summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTianon Gravi <admwiggin@gmail.com>2015-01-15 12:50:40 -0700
committerTianon Gravi <admwiggin@gmail.com>2015-01-15 12:50:40 -0700
commit2a0db60599fdd75b1bc3e297180fbe1282763759 (patch)
tree68d43c3e30d9ab961ddf6b7365201ca6b675b253
parentef33cba3c8de6c431df56503df51fcd3a473c89e (diff)
parentf154da9e12608589e8d5f0508f908a0c3e88a1bb (diff)
downloadgolang-2a0db60599fdd75b1bc3e297180fbe1282763759.tar.gz
Merge tag 'upstream/1.4' into debian-experimental
* tag 'upstream/1.4': Imported Upstream version 1.4
-rw-r--r--AUTHORS35
-rw-r--r--CONTRIBUTORS47
-rw-r--r--VERSION2
-rw-r--r--api/except.txt1
-rw-r--r--api/go1.4.txt604
-rw-r--r--api/next.txt24
-rw-r--r--doc/articles/go_command.html15
-rw-r--r--doc/articles/race_detector.html27
-rw-r--r--doc/asm.html157
-rw-r--r--doc/cmd.html8
-rw-r--r--doc/code.html187
-rw-r--r--doc/contrib.html33
-rw-r--r--doc/contribute.html674
-rw-r--r--doc/debugging_with_gdb.html50
-rw-r--r--doc/devel/release.html10
-rw-r--r--doc/devel/weekly.html2
-rw-r--r--doc/docs.html4
-rw-r--r--doc/effective_go.html4
-rw-r--r--doc/gccgo_contribute.html2
-rw-r--r--doc/gccgo_install.html4
-rw-r--r--doc/go1.3.html4
-rw-r--r--doc/go1.4.html896
-rw-r--r--doc/go1.html2
-rw-r--r--doc/go1compat.html35
-rw-r--r--doc/go_faq.html100
-rw-r--r--doc/go_mem.html23
-rw-r--r--doc/go_spec.html899
-rw-r--r--doc/gopher/biplane.jpgbin0 -> 203420 bytes
-rw-r--r--doc/gopher/fiveyears.jpgbin0 -> 220526 bytes
-rw-r--r--doc/help.html2
-rw-r--r--doc/install-source.html6
-rw-r--r--doc/install.html29
-rw-r--r--include/bio.h8
-rw-r--r--include/link.h35
-rwxr-xr-xlib/time/update.bash4
-rw-r--r--lib/time/zoneinfo.zipbin358933 -> 360713 bytes
-rw-r--r--misc/IntelliJIDEA/Go.xml99
-rw-r--r--misc/android/README11
-rw-r--r--misc/android/go_android_exec.go96
-rw-r--r--misc/bash/go237
-rw-r--r--misc/bbedit/Go.plist104
-rwxr-xr-xmisc/benchcmp2
-rw-r--r--misc/cgo/errors/issue7757.go14
-rw-r--r--misc/cgo/errors/issue8442.go17
-rwxr-xr-xmisc/cgo/errors/test.bash2
-rw-r--r--misc/cgo/test/backdoor/backdoor.go3
-rw-r--r--misc/cgo/test/backdoor/runtime.c32
-rw-r--r--misc/cgo/test/backdoor/thunk.s16
-rw-r--r--misc/cgo/test/basic.go5
-rw-r--r--misc/cgo/test/buildid_linux.go77
-rw-r--r--misc/cgo/test/callback.go67
-rw-r--r--misc/cgo/test/callback_c.c16
-rw-r--r--misc/cgo/test/callback_c_gc.c59
-rw-r--r--misc/cgo/test/callback_c_gccgo.c53
-rw-r--r--misc/cgo/test/cgo_linux_test.go5
-rw-r--r--misc/cgo/test/cgo_test.go97
-rw-r--r--misc/cgo/test/exports.go6
-rw-r--r--misc/cgo/test/issue5242.go31
-rw-r--r--misc/cgo/test/issue5548.go9
-rw-r--r--misc/cgo/test/issue6997_linux.go2
-rw-r--r--misc/cgo/test/issue7695_test.go27
-rw-r--r--misc/cgo/test/issue7978.go10
-rw-r--r--misc/cgo/test/issue8092.go36
-rw-r--r--misc/cgo/test/issue8428.go52
-rw-r--r--misc/cgo/test/issue8517.go13
-rw-r--r--misc/cgo/test/issue8517_windows.c24
-rw-r--r--misc/cgo/test/issue8517_windows.go45
-rw-r--r--misc/cgo/test/issue8694.go38
-rw-r--r--misc/cgo/test/issue8811.c8
-rw-r--r--misc/cgo/test/issue8811.go22
-rw-r--r--misc/cgo/test/issue8828.go16
-rw-r--r--misc/cgo/test/issue8828/issue8828.c7
-rw-r--r--misc/cgo/test/issue8828/trivial.go8
-rw-r--r--misc/cgo/test/issue9026.go9
-rw-r--r--misc/cgo/test/issue9026/issue9026.go36
-rw-r--r--misc/cgo/testcdefs/cdefstest.c1
-rw-r--r--misc/cgo/testcdefs/cdefstest.go19
-rw-r--r--misc/cgo/testcdefs/main.c28
-rw-r--r--misc/cgo/testgodefs/anonunion.go26
-rw-r--r--misc/cgo/testgodefs/issue8478.go20
-rw-r--r--misc/cgo/testgodefs/main.go15
-rwxr-xr-xmisc/cgo/testgodefs/test.bash20
-rw-r--r--misc/editors5
-rw-r--r--misc/emacs/go-mode-load.el96
-rw-r--r--misc/emacs/go-mode.el1196
-rw-r--r--misc/fraise/go.plist92
-rw-r--r--misc/fraise/readme.txt16
-rw-r--r--misc/kate/go.xml150
-rw-r--r--misc/makerelease/makerelease.go83
-rw-r--r--misc/makerelease/windows/installer.wxs11
-rw-r--r--misc/nacl/README97
-rwxr-xr-xmisc/nacl/go_nacl_arm_exec10
-rw-r--r--misc/nacl/mkzip.go10
-rw-r--r--misc/nacl/testzip.proto164
-rw-r--r--misc/notepadplus/README59
-rw-r--r--misc/notepadplus/functionList.xml50
-rw-r--r--misc/notepadplus/go.xml133
-rw-r--r--misc/notepadplus/userDefineLang.xml64
-rwxr-xr-xmisc/pprof5094
-rw-r--r--misc/vim/autoload/go/complete.vim103
-rw-r--r--misc/vim/compiler/go.vim30
-rw-r--r--misc/vim/ftdetect/gofiletype.vim23
-rw-r--r--misc/vim/ftplugin/go.vim19
-rw-r--r--misc/vim/ftplugin/go/fmt.vim69
-rw-r--r--misc/vim/ftplugin/go/import.vim250
-rwxr-xr-xmisc/vim/ftplugin/go/test.sh78
-rw-r--r--misc/vim/indent/go.vim77
-rw-r--r--misc/vim/plugin/godoc.vim130
-rw-r--r--misc/vim/readme.txt103
-rw-r--r--misc/vim/syntax/go.vim207
-rw-r--r--misc/vim/syntax/godoc.vim20
-rw-r--r--misc/xcode/3/README3
-rw-r--r--misc/xcode/3/go.pbfilespec31
-rw-r--r--misc/xcode/3/go.xclangspec293
-rw-r--r--misc/xcode/4/README2
-rw-r--r--misc/xcode/4/go.xclangspec290
-rwxr-xr-xmisc/xcode/4/go4xcode.sh112
-rw-r--r--misc/zsh/go161
-rwxr-xr-xsrc/androidtest.bash55
-rw-r--r--src/archive/tar/common.go (renamed from src/pkg/archive/tar/common.go)0
-rw-r--r--src/archive/tar/example_test.go (renamed from src/pkg/archive/tar/example_test.go)0
-rw-r--r--src/archive/tar/reader.go (renamed from src/pkg/archive/tar/reader.go)13
-rw-r--r--src/archive/tar/reader_test.go (renamed from src/pkg/archive/tar/reader_test.go)0
-rw-r--r--src/archive/tar/stat_atim.go (renamed from src/pkg/archive/tar/stat_atim.go)0
-rw-r--r--src/archive/tar/stat_atimespec.go (renamed from src/pkg/archive/tar/stat_atimespec.go)0
-rw-r--r--src/archive/tar/stat_unix.go (renamed from src/pkg/archive/tar/stat_unix.go)0
-rw-r--r--src/archive/tar/tar_test.go (renamed from src/pkg/archive/tar/tar_test.go)0
-rw-r--r--src/archive/tar/testdata/gnu.tar (renamed from src/pkg/archive/tar/testdata/gnu.tar)bin3072 -> 3072 bytes
-rw-r--r--src/archive/tar/testdata/nil-uid.tar (renamed from src/pkg/archive/tar/testdata/nil-uid.tar)bin1024 -> 1024 bytes
-rw-r--r--src/archive/tar/testdata/pax.tar (renamed from src/pkg/archive/tar/testdata/pax.tar)bin10240 -> 10240 bytes
-rw-r--r--src/archive/tar/testdata/small.txt (renamed from src/pkg/archive/tar/testdata/small.txt)0
-rw-r--r--src/archive/tar/testdata/small2.txt (renamed from src/pkg/archive/tar/testdata/small2.txt)0
-rw-r--r--src/archive/tar/testdata/sparse-formats.tar (renamed from src/pkg/archive/tar/testdata/sparse-formats.tar)bin17920 -> 17920 bytes
-rw-r--r--src/archive/tar/testdata/star.tar (renamed from src/pkg/archive/tar/testdata/star.tar)bin3072 -> 3072 bytes
-rw-r--r--src/archive/tar/testdata/ustar.tar (renamed from src/pkg/archive/tar/testdata/ustar.tar)bin2048 -> 2048 bytes
-rw-r--r--src/archive/tar/testdata/v7.tar (renamed from src/pkg/archive/tar/testdata/v7.tar)bin3584 -> 3584 bytes
-rw-r--r--src/archive/tar/testdata/writer-big-long.tar (renamed from src/pkg/archive/tar/testdata/writer-big-long.tar)bin4096 -> 4096 bytes
-rw-r--r--src/archive/tar/testdata/writer-big.tar (renamed from src/pkg/archive/tar/testdata/writer-big.tar)bin4096 -> 4096 bytes
-rw-r--r--src/archive/tar/testdata/writer.tar (renamed from src/pkg/archive/tar/testdata/writer.tar)bin3584 -> 3584 bytes
-rw-r--r--src/archive/tar/testdata/xattrs.tar (renamed from src/pkg/archive/tar/testdata/xattrs.tar)bin5120 -> 5120 bytes
-rw-r--r--src/archive/tar/writer.go (renamed from src/pkg/archive/tar/writer.go)19
-rw-r--r--src/archive/tar/writer_test.go (renamed from src/pkg/archive/tar/writer_test.go)35
-rw-r--r--src/archive/zip/example_test.go (renamed from src/pkg/archive/zip/example_test.go)0
-rw-r--r--src/archive/zip/reader.go (renamed from src/pkg/archive/zip/reader.go)9
-rw-r--r--src/archive/zip/reader_test.go (renamed from src/pkg/archive/zip/reader_test.go)23
-rw-r--r--src/archive/zip/register.go (renamed from src/pkg/archive/zip/register.go)0
-rw-r--r--src/archive/zip/struct.go (renamed from src/pkg/archive/zip/struct.go)0
-rw-r--r--src/archive/zip/testdata/crc32-not-streamed.zip (renamed from src/pkg/archive/zip/testdata/crc32-not-streamed.zip)bin314 -> 314 bytes
-rw-r--r--src/archive/zip/testdata/dd.zip (renamed from src/pkg/archive/zip/testdata/dd.zip)bin154 -> 154 bytes
-rw-r--r--src/archive/zip/testdata/go-no-datadesc-sig.zip (renamed from src/pkg/archive/zip/testdata/go-no-datadesc-sig.zip)bin330 -> 330 bytes
-rw-r--r--src/archive/zip/testdata/go-with-datadesc-sig.zip (renamed from src/pkg/archive/zip/testdata/go-with-datadesc-sig.zip)bin242 -> 242 bytes
-rw-r--r--src/archive/zip/testdata/gophercolor16x16.png (renamed from src/pkg/archive/zip/testdata/gophercolor16x16.png)bin785 -> 785 bytes
-rw-r--r--src/archive/zip/testdata/readme.notzip (renamed from src/pkg/archive/zip/testdata/readme.notzip)bin1905 -> 1905 bytes
-rw-r--r--src/archive/zip/testdata/readme.zip (renamed from src/pkg/archive/zip/testdata/readme.zip)bin1885 -> 1885 bytes
-rw-r--r--src/archive/zip/testdata/symlink.zip (renamed from src/pkg/archive/zip/testdata/symlink.zip)bin173 -> 173 bytes
-rw-r--r--src/archive/zip/testdata/test-trailing-junk.zip (renamed from src/pkg/archive/zip/testdata/test-trailing-junk.zip)bin1184 -> 1184 bytes
-rw-r--r--src/archive/zip/testdata/test.zip (renamed from src/pkg/archive/zip/testdata/test.zip)bin1170 -> 1170 bytes
-rw-r--r--src/archive/zip/testdata/unix.zip (renamed from src/pkg/archive/zip/testdata/unix.zip)bin620 -> 620 bytes
-rw-r--r--src/archive/zip/testdata/winxp.zip (renamed from src/pkg/archive/zip/testdata/winxp.zip)bin412 -> 412 bytes
-rw-r--r--src/archive/zip/testdata/zip64-2.zip (renamed from src/pkg/archive/zip/testdata/zip64-2.zip)bin266 -> 266 bytes
-rw-r--r--src/archive/zip/testdata/zip64.zip (renamed from src/pkg/archive/zip/testdata/zip64.zip)bin242 -> 242 bytes
-rw-r--r--src/archive/zip/writer.go (renamed from src/pkg/archive/zip/writer.go)6
-rw-r--r--src/archive/zip/writer_test.go (renamed from src/pkg/archive/zip/writer_test.go)19
-rw-r--r--src/archive/zip/zip_test.go (renamed from src/pkg/archive/zip/zip_test.go)0
-rw-r--r--src/bufio/bufio.go (renamed from src/pkg/bufio/bufio.go)32
-rw-r--r--src/bufio/bufio_test.go (renamed from src/pkg/bufio/bufio_test.go)19
-rw-r--r--src/bufio/example_test.go (renamed from src/pkg/bufio/example_test.go)0
-rw-r--r--src/bufio/export_test.go (renamed from src/pkg/bufio/export_test.go)0
-rw-r--r--src/bufio/scan.go (renamed from src/pkg/bufio/scan.go)27
-rw-r--r--src/bufio/scan_test.go (renamed from src/pkg/bufio/scan_test.go)120
-rw-r--r--src/builtin/builtin.go (renamed from src/pkg/builtin/builtin.go)0
-rw-r--r--src/bytes/buffer.go (renamed from src/pkg/bytes/buffer.go)0
-rw-r--r--src/bytes/buffer_test.go (renamed from src/pkg/bytes/buffer_test.go)0
-rw-r--r--src/bytes/bytes.go (renamed from src/pkg/bytes/bytes.go)12
-rw-r--r--src/bytes/bytes_decl.go (renamed from src/pkg/bytes/bytes_decl.go)0
-rw-r--r--src/bytes/bytes_test.go (renamed from src/pkg/bytes/bytes_test.go)6
-rw-r--r--src/bytes/compare_test.go (renamed from src/pkg/bytes/compare_test.go)0
-rw-r--r--src/bytes/equal_test.go (renamed from src/pkg/bytes/equal_test.go)0
-rw-r--r--src/bytes/example_test.go (renamed from src/pkg/bytes/example_test.go)0
-rw-r--r--src/bytes/export_test.go (renamed from src/pkg/bytes/export_test.go)0
-rw-r--r--src/bytes/reader.go (renamed from src/pkg/bytes/reader.go)0
-rw-r--r--src/bytes/reader_test.go (renamed from src/pkg/bytes/reader_test.go)0
-rw-r--r--src/cmd/5a/a.y2
-rw-r--r--src/cmd/5a/lex.c5
-rw-r--r--src/cmd/5a/y.tab.c2
-rw-r--r--src/cmd/5c/cgen.c38
-rw-r--r--src/cmd/5c/gc.h5
-rw-r--r--src/cmd/5c/peep.c4
-rw-r--r--src/cmd/5c/reg.c19
-rw-r--r--src/cmd/5c/sgen.c2
-rw-r--r--src/cmd/5c/swt.c11
-rw-r--r--src/cmd/5c/txt.c40
-rw-r--r--src/cmd/5g/cgen.c81
-rw-r--r--src/cmd/5g/galign.c8
-rw-r--r--src/cmd/5g/gg.h12
-rw-r--r--src/cmd/5g/ggen.c25
-rw-r--r--src/cmd/5g/gsubr.c27
-rw-r--r--src/cmd/5g/opt.h20
-rw-r--r--src/cmd/5g/peep.c6
-rw-r--r--src/cmd/5g/reg.c12
-rw-r--r--src/cmd/5l/5.out.h166
-rw-r--r--src/cmd/5l/asm.c75
-rw-r--r--src/cmd/5l/l.h76
-rw-r--r--src/cmd/5l/mkenam45
-rw-r--r--src/cmd/5l/noop.c43
-rw-r--r--src/cmd/5l/obj.c13
-rw-r--r--src/cmd/6a/a.y2
-rw-r--r--src/cmd/6a/lex.c35
-rw-r--r--src/cmd/6a/y.tab.c2
-rw-r--r--src/cmd/6c/cgen.c36
-rw-r--r--src/cmd/6c/gc.h5
-rw-r--r--src/cmd/6c/reg.c14
-rw-r--r--src/cmd/6c/sgen.c9
-rw-r--r--src/cmd/6c/swt.c9
-rw-r--r--src/cmd/6c/txt.c40
-rw-r--r--src/cmd/6g/cgen.c10
-rw-r--r--src/cmd/6g/galign.c8
-rw-r--r--src/cmd/6g/gg.h2
-rw-r--r--src/cmd/6g/ggen.c61
-rw-r--r--src/cmd/6g/gsubr.c29
-rw-r--r--src/cmd/6g/opt.h20
-rw-r--r--src/cmd/6g/reg.c8
-rw-r--r--src/cmd/6l/6.out.h2
-rw-r--r--src/cmd/6l/asm.c17
-rw-r--r--src/cmd/6l/l.h10
-rw-r--r--src/cmd/6l/mkenam45
-rw-r--r--src/cmd/8a/a.y2
-rw-r--r--src/cmd/8a/lex.c35
-rw-r--r--src/cmd/8a/y.tab.c2
-rw-r--r--src/cmd/8c/cgen.c38
-rw-r--r--src/cmd/8c/gc.h5
-rw-r--r--src/cmd/8c/reg.c9
-rw-r--r--src/cmd/8c/sgen.c2
-rw-r--r--src/cmd/8c/swt.c9
-rw-r--r--src/cmd/8c/txt.c40
-rw-r--r--src/cmd/8g/cgen.c88
-rw-r--r--src/cmd/8g/galign.c8
-rw-r--r--src/cmd/8g/gg.h1
-rw-r--r--src/cmd/8g/ggen.c49
-rw-r--r--src/cmd/8g/gsubr.c26
-rw-r--r--src/cmd/8g/opt.h20
-rw-r--r--src/cmd/8g/peep.c4
-rw-r--r--src/cmd/8g/reg.c6
-rw-r--r--src/cmd/8l/8.out.h2
-rw-r--r--src/cmd/8l/asm.c18
-rw-r--r--src/cmd/8l/l.h7
-rw-r--r--src/cmd/8l/mkenam45
-rw-r--r--src/cmd/addr2line/addr2line_test.go5
-rw-r--r--src/cmd/addr2line/main.go166
-rw-r--r--src/cmd/api/goapi.go158
-rw-r--r--src/cmd/api/goapi_test.go24
-rw-r--r--src/cmd/api/run.go9
-rw-r--r--src/cmd/cc/bv.c45
-rw-r--r--src/cmd/cc/cc.h8
-rw-r--r--src/cmd/cc/cc.y1
-rw-r--r--src/cmd/cc/dcl.c25
-rw-r--r--src/cmd/cc/godefs.c67
-rw-r--r--src/cmd/cc/lex.c3
-rw-r--r--src/cmd/cc/pgen.c202
-rw-r--r--src/cmd/cc/y.tab.c1147
-rw-r--r--src/cmd/cc/y.tab.h68
-rw-r--r--src/cmd/cgo/ast.go5
-rw-r--r--src/cmd/cgo/doc.go2
-rw-r--r--src/cmd/cgo/gcc.go187
-rw-r--r--src/cmd/cgo/out.go243
-rw-r--r--src/cmd/dist/a.h4
-rw-r--r--src/cmd/dist/arm.c3
-rw-r--r--src/cmd/dist/buf.c2
-rw-r--r--src/cmd/dist/build.c267
-rw-r--r--src/cmd/dist/buildgc.c38
-rw-r--r--src/cmd/dist/buildruntime.c84
-rw-r--r--src/cmd/dist/goc2c.c833
-rw-r--r--src/cmd/dist/plan9.c6
-rw-r--r--src/cmd/dist/unix.c16
-rw-r--r--src/cmd/dist/windows.c6
-rw-r--r--src/cmd/fix/doc.go2
-rw-r--r--src/cmd/fix/fix.go2
-rw-r--r--src/cmd/gc/align.c4
-rwxr-xr-xsrc/cmd/gc/bisonerrors18
-rw-r--r--src/cmd/gc/builtin.c33
-rw-r--r--src/cmd/gc/bv.c5
-rw-r--r--src/cmd/gc/const.c9
-rw-r--r--src/cmd/gc/dcl.c14
-rw-r--r--src/cmd/gc/esc.c3
-rw-r--r--src/cmd/gc/fmt.c36
-rw-r--r--src/cmd/gc/gen.c75
-rw-r--r--src/cmd/gc/go.h17
-rw-r--r--src/cmd/gc/go.y15
-rw-r--r--src/cmd/gc/lex.c363
-rw-r--r--src/cmd/gc/md5.c12
-rw-r--r--src/cmd/gc/mparith1.c2
-rw-r--r--src/cmd/gc/mparith2.c4
-rw-r--r--src/cmd/gc/mparith3.c4
-rw-r--r--src/cmd/gc/obj.c9
-rw-r--r--src/cmd/gc/order.c48
-rw-r--r--src/cmd/gc/pgen.c57
-rw-r--r--src/cmd/gc/plive.c34
-rw-r--r--src/cmd/gc/popt.c6
-rw-r--r--src/cmd/gc/racewalk.c26
-rw-r--r--src/cmd/gc/range.c48
-rw-r--r--src/cmd/gc/reflect.c591
-rw-r--r--src/cmd/gc/runtime.go40
-rw-r--r--src/cmd/gc/select.c65
-rw-r--r--src/cmd/gc/sinit.c32
-rw-r--r--src/cmd/gc/subr.c193
-rw-r--r--src/cmd/gc/swt.c1
-rw-r--r--src/cmd/gc/typecheck.c122
-rw-r--r--src/cmd/gc/walk.c543
-rw-r--r--src/cmd/gc/y.tab.c2566
-rw-r--r--src/cmd/gc/yerr.h84
-rw-r--r--src/cmd/go/build.go226
-rw-r--r--src/cmd/go/doc.go206
-rw-r--r--src/cmd/go/generate.go398
-rw-r--r--src/cmd/go/generate_test.go48
-rw-r--r--src/cmd/go/get.go35
-rw-r--r--src/cmd/go/go_windows_test.go55
-rw-r--r--src/cmd/go/help.go29
-rw-r--r--src/cmd/go/list.go39
-rw-r--r--src/cmd/go/main.go5
-rwxr-xr-xsrc/cmd/go/mkdoc.sh2
-rw-r--r--src/cmd/go/pkg.go180
-rwxr-xr-xsrc/cmd/go/test.bash405
-rw-r--r--src/cmd/go/test.go178
-rw-r--r--src/cmd/go/testdata/generate/test1.go (renamed from misc/cgo/test/backdoor/backdoor_gccgo.go)10
-rw-r--r--src/cmd/go/testdata/generate/test2.go10
-rw-r--r--src/cmd/go/testdata/generate/test3.go9
-rw-r--r--src/cmd/go/testdata/importcom/bad.go3
-rw-r--r--src/cmd/go/testdata/importcom/conflict.go3
-rw-r--r--src/cmd/go/testdata/importcom/src/bad/bad.go1
-rw-r--r--src/cmd/go/testdata/importcom/src/conflict/a.go1
-rw-r--r--src/cmd/go/testdata/importcom/src/conflict/b.go1
-rw-r--r--src/cmd/go/testdata/importcom/src/works/x/x.go1
-rw-r--r--src/cmd/go/testdata/importcom/src/works/x/x1.go1
-rw-r--r--src/cmd/go/testdata/importcom/src/wrongplace/x.go1
-rw-r--r--src/cmd/go/testdata/importcom/works.go3
-rw-r--r--src/cmd/go/testdata/importcom/wrongplace.go3
-rw-r--r--src/cmd/go/testdata/norunexample/example_test.go11
-rw-r--r--src/cmd/go/testdata/norunexample/test_test.go10
-rw-r--r--src/cmd/go/testdata/src/badc/x.c1
-rw-r--r--src/cmd/go/testdata/src/badc/x.go1
-rw-r--r--src/cmd/go/testdata/src/badtest/badexec/x_test.go5
-rw-r--r--src/cmd/go/testdata/src/badtest/badsyntax/x.go1
-rw-r--r--src/cmd/go/testdata/src/badtest/badsyntax/x_test.go3
-rw-r--r--src/cmd/go/testdata/src/badtest/badvar/x.go1
-rw-r--r--src/cmd/go/testdata/src/badtest/badvar/x_test.go5
-rw-r--r--src/cmd/go/testdata/src/vetpkg/a_test.go1
-rw-r--r--src/cmd/go/testdata/src/vetpkg/b.go7
-rw-r--r--src/cmd/go/testdata/testinternal/p.go3
-rw-r--r--src/cmd/go/testdata/testinternal2/p.go3
-rw-r--r--src/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go1
-rw-r--r--src/cmd/go/testflag.go7
-rw-r--r--src/cmd/go/testgo.go21
-rw-r--r--src/cmd/go/tool.go14
-rw-r--r--src/cmd/go/vcs.go149
-rw-r--r--src/cmd/go/vcs_test.go124
-rw-r--r--src/cmd/go/vet.go25
-rw-r--r--src/cmd/gofmt/doc.go2
-rw-r--r--src/cmd/gofmt/gofmt.go193
-rw-r--r--src/cmd/gofmt/gofmt_test.go121
-rw-r--r--src/cmd/gofmt/long_test.go4
-rw-r--r--src/cmd/gofmt/rewrite.go3
-rw-r--r--src/cmd/gofmt/simplify.go50
-rw-r--r--src/cmd/gofmt/testdata/composites.golden2
-rw-r--r--src/cmd/gofmt/testdata/composites.input2
-rw-r--r--src/cmd/gofmt/testdata/crlf.golden1
-rw-r--r--src/cmd/gofmt/testdata/crlf.input1
-rw-r--r--src/cmd/gofmt/testdata/emptydecl.golden14
-rw-r--r--src/cmd/gofmt/testdata/emptydecl.input16
-rw-r--r--src/cmd/gofmt/testdata/ranges.golden30
-rw-r--r--src/cmd/gofmt/testdata/ranges.input20
-rw-r--r--src/cmd/gofmt/testdata/rewrite1.golden2
-rw-r--r--src/cmd/gofmt/testdata/rewrite1.input2
-rw-r--r--src/cmd/gofmt/testdata/rewrite2.golden2
-rw-r--r--src/cmd/gofmt/testdata/rewrite2.input2
-rw-r--r--src/cmd/gofmt/testdata/rewrite3.golden2
-rw-r--r--src/cmd/gofmt/testdata/rewrite3.input2
-rw-r--r--src/cmd/gofmt/testdata/rewrite4.golden2
-rw-r--r--src/cmd/gofmt/testdata/rewrite4.input2
-rw-r--r--src/cmd/gofmt/testdata/rewrite5.golden2
-rw-r--r--src/cmd/gofmt/testdata/rewrite5.input2
-rw-r--r--src/cmd/gofmt/testdata/rewrite6.golden2
-rw-r--r--src/cmd/gofmt/testdata/rewrite6.input2
-rw-r--r--src/cmd/gofmt/testdata/rewrite7.golden2
-rw-r--r--src/cmd/gofmt/testdata/rewrite7.input2
-rw-r--r--src/cmd/gofmt/testdata/rewrite8.golden2
-rw-r--r--src/cmd/gofmt/testdata/rewrite8.input2
-rw-r--r--src/cmd/gofmt/testdata/slices1.golden8
-rw-r--r--src/cmd/gofmt/testdata/slices1.input8
-rw-r--r--src/cmd/gofmt/testdata/slices2.golden2
-rw-r--r--src/cmd/gofmt/testdata/slices2.input2
-rw-r--r--src/cmd/gofmt/testdata/stdin1.golden2
-rw-r--r--src/cmd/gofmt/testdata/stdin1.golden.gofmt3
-rw-r--r--src/cmd/gofmt/testdata/stdin1.input2
-rw-r--r--src/cmd/gofmt/testdata/stdin1.input.gofmt3
-rw-r--r--src/cmd/gofmt/testdata/stdin2.golden2
-rw-r--r--src/cmd/gofmt/testdata/stdin2.golden.gofmt10
-rw-r--r--src/cmd/gofmt/testdata/stdin2.input2
-rw-r--r--src/cmd/gofmt/testdata/stdin2.input.gofmt11
-rw-r--r--src/cmd/gofmt/testdata/stdin3.golden1
-rw-r--r--src/cmd/gofmt/testdata/stdin3.golden.gofmt7
-rw-r--r--src/cmd/gofmt/testdata/stdin3.input1
-rw-r--r--src/cmd/gofmt/testdata/stdin3.input.gofmt7
-rw-r--r--src/cmd/gofmt/testdata/stdin4.golden2
-rw-r--r--src/cmd/gofmt/testdata/stdin4.golden.gofmt3
-rw-r--r--src/cmd/gofmt/testdata/stdin4.input2
-rw-r--r--src/cmd/gofmt/testdata/stdin4.input.gofmt3
-rw-r--r--src/cmd/gofmt/testdata/stdin5.golden3
-rw-r--r--src/cmd/gofmt/testdata/stdin5.input3
-rw-r--r--src/cmd/gofmt/testdata/stdin6.golden19
-rw-r--r--src/cmd/gofmt/testdata/stdin6.input21
-rw-r--r--src/cmd/gofmt/testdata/stdin7.golden19
-rw-r--r--src/cmd/gofmt/testdata/stdin7.input21
-rw-r--r--src/cmd/internal/goobj/read.go (renamed from src/cmd/nm/debug_goobj.go)342
-rw-r--r--src/cmd/internal/goobj/read_test.go28
-rw-r--r--src/cmd/internal/objfile/disasm.go248
-rw-r--r--src/cmd/internal/objfile/elf.go104
-rw-r--r--src/cmd/internal/objfile/goobj.go93
-rw-r--r--src/cmd/internal/objfile/macho.go116
-rw-r--r--src/cmd/internal/objfile/objfile.go94
-rw-r--r--src/cmd/internal/objfile/pe.go201
-rw-r--r--src/cmd/internal/objfile/plan9obj.go146
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/Makefile2
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/decode.go567
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/decode_test.go69
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/ext_test.go614
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/gnu.go164
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/inst.go438
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/objdump_test.go258
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go260
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/plan9x.go211
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/tables.go9448
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/testdata/Makefile5
-rw-r--r--src/cmd/internal/rsc.io/arm/armasm/testdata/decode.txt306
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/Makefile3
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/decode.go1616
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/decode_test.go71
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/ext_test.go811
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/gnu.go926
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/inst.go641
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/inst_test.go20
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/intel.go518
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/objdump_test.go383
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/objdumpext_test.go314
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/plan9ext_test.go120
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/plan9x.go346
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/plan9x_test.go54
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/tables.go9760
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/testdata/Makefile12
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/testdata/decode.txt6731
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/xed_test.go211
-rw-r--r--src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go206
-rw-r--r--src/cmd/ld/data.c357
-rw-r--r--src/cmd/ld/decodesym.c38
-rw-r--r--src/cmd/ld/doc.go6
-rw-r--r--src/cmd/ld/dwarf.c156
-rw-r--r--src/cmd/ld/elf.c3
-rw-r--r--src/cmd/ld/ldelf.c8
-rw-r--r--src/cmd/ld/ldmacho.c4
-rw-r--r--src/cmd/ld/ldpe.c32
-rw-r--r--src/cmd/ld/lib.c91
-rw-r--r--src/cmd/ld/lib.h14
-rw-r--r--src/cmd/ld/macho.c3
-rw-r--r--src/cmd/ld/pass.c104
-rw-r--r--src/cmd/ld/pcln.c6
-rw-r--r--src/cmd/ld/pobj.c22
-rw-r--r--src/cmd/ld/symtab.c55
-rw-r--r--src/cmd/ld/textflag.h13
-rw-r--r--src/cmd/nm/elf.go57
-rw-r--r--src/cmd/nm/goobj.go67
-rw-r--r--src/cmd/nm/macho.go69
-rw-r--r--src/cmd/nm/nm.go57
-rw-r--r--src/cmd/nm/nm_test.go11
-rw-r--r--src/cmd/nm/pe.go98
-rw-r--r--src/cmd/nm/plan9obj.go48
-rw-r--r--src/cmd/objdump/Makefile10
-rw-r--r--src/cmd/objdump/armasm.go10821
-rw-r--r--src/cmd/objdump/elf.go65
-rw-r--r--src/cmd/objdump/macho.go77
-rw-r--r--src/cmd/objdump/main.go456
-rw-r--r--src/cmd/objdump/objdump_test.go122
-rw-r--r--src/cmd/objdump/pe.go99
-rw-r--r--src/cmd/objdump/plan9obj.go63
-rw-r--r--src/cmd/objdump/x86.go13800
-rw-r--r--src/cmd/pack/doc.go4
-rw-r--r--src/cmd/pack/pack.go50
-rw-r--r--src/cmd/pack/pack_test.go33
-rw-r--r--src/cmd/pprof/README8
-rw-r--r--src/cmd/pprof/doc.go12
-rw-r--r--src/cmd/pprof/internal/commands/commands.go215
-rw-r--r--src/cmd/pprof/internal/driver/driver.go1036
-rw-r--r--src/cmd/pprof/internal/driver/interactive.go492
-rw-r--r--src/cmd/pprof/internal/fetch/fetch.go82
-rw-r--r--src/cmd/pprof/internal/plugin/plugin.go213
-rw-r--r--src/cmd/pprof/internal/profile/encode.go470
-rw-r--r--src/cmd/pprof/internal/profile/filter.go157
-rw-r--r--src/cmd/pprof/internal/profile/legacy_profile.go1250
-rw-r--r--src/cmd/pprof/internal/profile/profile.go567
-rw-r--r--src/cmd/pprof/internal/profile/proto.go298
-rw-r--r--src/cmd/pprof/internal/profile/prune.go97
-rw-r--r--src/cmd/pprof/internal/report/report.go1718
-rw-r--r--src/cmd/pprof/internal/report/source.go450
-rw-r--r--src/cmd/pprof/internal/report/source_html.go77
-rw-r--r--src/cmd/pprof/internal/svg/svg.go75
-rw-r--r--src/cmd/pprof/internal/symbolizer/symbolizer.go195
-rw-r--r--src/cmd/pprof/internal/symbolz/symbolz.go111
-rw-r--r--src/cmd/pprof/internal/tempfile/tempfile.go45
-rw-r--r--src/cmd/pprof/pprof.go237
-rw-r--r--src/cmd/yacc/Makefile12
-rw-r--r--src/cmd/yacc/doc.go5
-rw-r--r--src/cmd/yacc/testdata/expr/README20
-rw-r--r--src/cmd/yacc/testdata/expr/expr.y (renamed from src/cmd/yacc/expr.y)7
-rw-r--r--src/cmd/yacc/testdata/expr/main.go15
-rw-r--r--src/cmd/yacc/yacc.go90
-rw-r--r--src/compress/bzip2/bit_reader.go (renamed from src/pkg/compress/bzip2/bit_reader.go)0
-rw-r--r--src/compress/bzip2/bzip2.go (renamed from src/pkg/compress/bzip2/bzip2.go)23
-rw-r--r--src/compress/bzip2/bzip2_test.go (renamed from src/pkg/compress/bzip2/bzip2_test.go)56
-rw-r--r--src/compress/bzip2/huffman.go (renamed from src/pkg/compress/bzip2/huffman.go)0
-rw-r--r--src/compress/bzip2/move_to_front.go53
-rw-r--r--src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 (renamed from src/pkg/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2)bin124744 -> 124744 bytes
-rw-r--r--src/compress/bzip2/testdata/e.txt.bz2 (renamed from src/pkg/compress/bzip2/testdata/e.txt.bz2)bin43149 -> 43149 bytes
-rw-r--r--src/compress/flate/copy.go (renamed from src/pkg/compress/flate/copy.go)0
-rw-r--r--src/compress/flate/copy_test.go (renamed from src/pkg/compress/flate/copy_test.go)0
-rw-r--r--src/compress/flate/deflate.go (renamed from src/pkg/compress/flate/deflate.go)0
-rw-r--r--src/compress/flate/deflate_test.go (renamed from src/pkg/compress/flate/deflate_test.go)0
-rw-r--r--src/compress/flate/fixedhuff.go (renamed from src/pkg/compress/flate/fixedhuff.go)2
-rw-r--r--src/compress/flate/flate_test.go (renamed from src/pkg/compress/flate/flate_test.go)0
-rw-r--r--src/compress/flate/gen.go (renamed from src/pkg/compress/flate/gen.go)55
-rw-r--r--src/compress/flate/huffman_bit_writer.go (renamed from src/pkg/compress/flate/huffman_bit_writer.go)0
-rw-r--r--src/compress/flate/huffman_code.go (renamed from src/pkg/compress/flate/huffman_code.go)0
-rw-r--r--src/compress/flate/inflate.go (renamed from src/pkg/compress/flate/inflate.go)37
-rw-r--r--src/compress/flate/inflate_test.go39
-rw-r--r--src/compress/flate/reader_test.go (renamed from src/pkg/compress/flate/reader_test.go)0
-rw-r--r--src/compress/flate/reverse_bits.go (renamed from src/pkg/compress/flate/reverse_bits.go)0
-rw-r--r--src/compress/flate/token.go (renamed from src/pkg/compress/flate/token.go)0
-rw-r--r--src/compress/flate/writer_test.go (renamed from src/pkg/compress/flate/writer_test.go)0
-rw-r--r--src/compress/gzip/gunzip.go (renamed from src/pkg/compress/gzip/gunzip.go)36
-rw-r--r--src/compress/gzip/gunzip_test.go (renamed from src/pkg/compress/gzip/gunzip_test.go)41
-rw-r--r--src/compress/gzip/gzip.go (renamed from src/pkg/compress/gzip/gzip.go)0
-rw-r--r--src/compress/gzip/gzip_test.go (renamed from src/pkg/compress/gzip/gzip_test.go)0
-rw-r--r--src/compress/gzip/testdata/issue6550.gz (renamed from src/pkg/compress/gzip/testdata/issue6550.gz)bin65536 -> 65536 bytes
-rw-r--r--src/compress/lzw/reader.go (renamed from src/pkg/compress/lzw/reader.go)10
-rw-r--r--src/compress/lzw/reader_test.go (renamed from src/pkg/compress/lzw/reader_test.go)0
-rw-r--r--src/compress/lzw/writer.go (renamed from src/pkg/compress/lzw/writer.go)0
-rw-r--r--src/compress/lzw/writer_test.go (renamed from src/pkg/compress/lzw/writer_test.go)0
-rw-r--r--src/compress/testdata/Mark.Twain-Tom.Sawyer.txt (renamed from src/pkg/compress/testdata/Mark.Twain-Tom.Sawyer.txt)0
-rw-r--r--src/compress/testdata/e.txt (renamed from src/pkg/compress/testdata/e.txt)0
-rw-r--r--src/compress/testdata/pi.txt (renamed from src/pkg/compress/testdata/pi.txt)0
-rw-r--r--src/compress/zlib/example_test.go (renamed from src/pkg/compress/zlib/example_test.go)0
-rw-r--r--src/compress/zlib/reader.go (renamed from src/pkg/compress/zlib/reader.go)81
-rw-r--r--src/compress/zlib/reader_test.go (renamed from src/pkg/compress/zlib/reader_test.go)0
-rw-r--r--src/compress/zlib/writer.go (renamed from src/pkg/compress/zlib/writer.go)0
-rw-r--r--src/compress/zlib/writer_test.go (renamed from src/pkg/compress/zlib/writer_test.go)0
-rw-r--r--src/container/heap/example_intheap_test.go (renamed from src/pkg/container/heap/example_intheap_test.go)0
-rw-r--r--src/container/heap/example_pq_test.go (renamed from src/pkg/container/heap/example_pq_test.go)0
-rw-r--r--src/container/heap/heap.go (renamed from src/pkg/container/heap/heap.go)0
-rw-r--r--src/container/heap/heap_test.go (renamed from src/pkg/container/heap/heap_test.go)0
-rw-r--r--src/container/list/example_test.go (renamed from src/pkg/container/list/example_test.go)0
-rw-r--r--src/container/list/list.go (renamed from src/pkg/container/list/list.go)0
-rw-r--r--src/container/list/list_test.go (renamed from src/pkg/container/list/list_test.go)0
-rw-r--r--src/container/ring/ring.go (renamed from src/pkg/container/ring/ring.go)0
-rw-r--r--src/container/ring/ring_test.go (renamed from src/pkg/container/ring/ring_test.go)0
-rw-r--r--src/crypto/aes/aes_test.go (renamed from src/pkg/crypto/aes/aes_test.go)0
-rw-r--r--src/crypto/aes/asm_amd64.s (renamed from src/pkg/crypto/aes/asm_amd64.s)2
-rw-r--r--src/crypto/aes/block.go (renamed from src/pkg/crypto/aes/block.go)0
-rw-r--r--src/crypto/aes/cipher.go (renamed from src/pkg/crypto/aes/cipher.go)0
-rw-r--r--src/crypto/aes/cipher_asm.go (renamed from src/pkg/crypto/aes/cipher_asm.go)0
-rw-r--r--src/crypto/aes/cipher_generic.go (renamed from src/pkg/crypto/aes/cipher_generic.go)0
-rw-r--r--src/crypto/aes/const.go (renamed from src/pkg/crypto/aes/const.go)0
-rw-r--r--src/crypto/cipher/benchmark_test.go (renamed from src/pkg/crypto/cipher/benchmark_test.go)0
-rw-r--r--src/crypto/cipher/cbc.go (renamed from src/pkg/crypto/cipher/cbc.go)0
-rw-r--r--src/crypto/cipher/cbc_aes_test.go (renamed from src/pkg/crypto/cipher/cbc_aes_test.go)0
-rw-r--r--src/crypto/cipher/cfb.go (renamed from src/pkg/crypto/cipher/cfb.go)0
-rw-r--r--src/crypto/cipher/cfb_test.go113
-rw-r--r--src/crypto/cipher/cipher.go (renamed from src/pkg/crypto/cipher/cipher.go)0
-rw-r--r--src/crypto/cipher/cipher_test.go (renamed from src/pkg/crypto/cipher/cipher_test.go)0
-rw-r--r--src/crypto/cipher/common_test.go (renamed from src/pkg/crypto/cipher/common_test.go)0
-rw-r--r--src/crypto/cipher/ctr.go (renamed from src/pkg/crypto/cipher/ctr.go)0
-rw-r--r--src/crypto/cipher/ctr_aes_test.go (renamed from src/pkg/crypto/cipher/ctr_aes_test.go)0
-rw-r--r--src/crypto/cipher/example_test.go (renamed from src/pkg/crypto/cipher/example_test.go)4
-rw-r--r--src/crypto/cipher/gcm.go (renamed from src/pkg/crypto/cipher/gcm.go)0
-rw-r--r--src/crypto/cipher/gcm_test.go (renamed from src/pkg/crypto/cipher/gcm_test.go)0
-rw-r--r--src/crypto/cipher/io.go (renamed from src/pkg/crypto/cipher/io.go)0
-rw-r--r--src/crypto/cipher/ofb.go (renamed from src/pkg/crypto/cipher/ofb.go)0
-rw-r--r--src/crypto/cipher/ofb_test.go (renamed from src/pkg/crypto/cipher/ofb_test.go)0
-rw-r--r--src/crypto/cipher/xor.go (renamed from src/pkg/crypto/cipher/xor.go)0
-rw-r--r--src/crypto/cipher/xor_test.go (renamed from src/pkg/crypto/cipher/xor_test.go)0
-rw-r--r--src/crypto/crypto.go (renamed from src/pkg/crypto/crypto.go)45
-rw-r--r--src/crypto/des/block.go (renamed from src/pkg/crypto/des/block.go)0
-rw-r--r--src/crypto/des/cipher.go (renamed from src/pkg/crypto/des/cipher.go)0
-rw-r--r--src/crypto/des/const.go (renamed from src/pkg/crypto/des/const.go)0
-rw-r--r--src/crypto/des/des_test.go (renamed from src/pkg/crypto/des/des_test.go)0
-rw-r--r--src/crypto/des/example_test.go (renamed from src/pkg/crypto/des/example_test.go)0
-rw-r--r--src/crypto/dsa/dsa.go (renamed from src/pkg/crypto/dsa/dsa.go)0
-rw-r--r--src/crypto/dsa/dsa_test.go (renamed from src/pkg/crypto/dsa/dsa_test.go)0
-rw-r--r--src/crypto/ecdsa/ecdsa.go (renamed from src/pkg/crypto/ecdsa/ecdsa.go)24
-rw-r--r--src/crypto/ecdsa/ecdsa_test.go (renamed from src/pkg/crypto/ecdsa/ecdsa_test.go)0
-rw-r--r--src/crypto/ecdsa/testdata/SigVer.rsp.bz2 (renamed from src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2)bin95485 -> 95485 bytes
-rw-r--r--src/crypto/elliptic/elliptic.go (renamed from src/pkg/crypto/elliptic/elliptic.go)0
-rw-r--r--src/crypto/elliptic/elliptic_test.go (renamed from src/pkg/crypto/elliptic/elliptic_test.go)0
-rw-r--r--src/crypto/elliptic/p224.go (renamed from src/pkg/crypto/elliptic/p224.go)0
-rw-r--r--src/crypto/elliptic/p224_test.go (renamed from src/pkg/crypto/elliptic/p224_test.go)0
-rw-r--r--src/crypto/elliptic/p256.go (renamed from src/pkg/crypto/elliptic/p256.go)0
-rw-r--r--src/crypto/hmac/hmac.go (renamed from src/pkg/crypto/hmac/hmac.go)0
-rw-r--r--src/crypto/hmac/hmac_test.go (renamed from src/pkg/crypto/hmac/hmac_test.go)0
-rw-r--r--src/crypto/md5/example_test.go (renamed from src/pkg/crypto/md5/example_test.go)0
-rw-r--r--src/crypto/md5/gen.go (renamed from src/pkg/crypto/md5/gen.go)23
-rw-r--r--src/crypto/md5/md5.go (renamed from src/pkg/crypto/md5/md5.go)2
-rw-r--r--src/crypto/md5/md5_test.go (renamed from src/pkg/crypto/md5/md5_test.go)0
-rw-r--r--src/crypto/md5/md5block.go (renamed from src/pkg/crypto/md5/md5block.go)2
-rw-r--r--src/crypto/md5/md5block_386.s (renamed from src/pkg/crypto/md5/md5block_386.s)2
-rw-r--r--src/crypto/md5/md5block_amd64.s (renamed from src/pkg/crypto/md5/md5block_amd64.s)2
-rw-r--r--src/crypto/md5/md5block_amd64p32.s (renamed from src/pkg/crypto/md5/md5block_amd64p32.s)2
-rw-r--r--src/crypto/md5/md5block_arm.s (renamed from src/pkg/crypto/md5/md5block_arm.s)2
-rw-r--r--src/crypto/md5/md5block_decl.go (renamed from src/pkg/crypto/md5/md5block_decl.go)0
-rw-r--r--src/crypto/md5/md5block_generic.go (renamed from src/pkg/crypto/md5/md5block_generic.go)0
-rw-r--r--src/crypto/rand/example_test.go (renamed from src/pkg/crypto/rand/example_test.go)0
-rw-r--r--src/crypto/rand/rand.go (renamed from src/pkg/crypto/rand/rand.go)0
-rw-r--r--src/crypto/rand/rand_linux.go39
-rw-r--r--src/crypto/rand/rand_test.go (renamed from src/pkg/crypto/rand/rand_test.go)0
-rw-r--r--src/crypto/rand/rand_unix.go (renamed from src/pkg/crypto/rand/rand_unix.go)11
-rw-r--r--src/crypto/rand/rand_windows.go (renamed from src/pkg/crypto/rand/rand_windows.go)0
-rw-r--r--src/crypto/rand/util.go (renamed from src/pkg/crypto/rand/util.go)0
-rw-r--r--src/crypto/rand/util_test.go (renamed from src/pkg/crypto/rand/util_test.go)0
-rw-r--r--src/crypto/rc4/rc4.go (renamed from src/pkg/crypto/rc4/rc4.go)0
-rw-r--r--src/crypto/rc4/rc4_386.s (renamed from src/pkg/crypto/rc4/rc4_386.s)2
-rw-r--r--src/crypto/rc4/rc4_amd64.s (renamed from src/pkg/crypto/rc4/rc4_amd64.s)2
-rw-r--r--src/crypto/rc4/rc4_amd64p32.s (renamed from src/pkg/crypto/rc4/rc4_amd64p32.s)2
-rw-r--r--src/crypto/rc4/rc4_arm.s (renamed from src/pkg/crypto/rc4/rc4_arm.s)4
-rw-r--r--src/crypto/rc4/rc4_asm.go (renamed from src/pkg/crypto/rc4/rc4_asm.go)2
-rw-r--r--src/crypto/rc4/rc4_ref.go (renamed from src/pkg/crypto/rc4/rc4_ref.go)2
-rw-r--r--src/crypto/rc4/rc4_test.go (renamed from src/pkg/crypto/rc4/rc4_test.go)0
-rw-r--r--src/crypto/rsa/pkcs1v15.go (renamed from src/pkg/crypto/rsa/pkcs1v15.go)0
-rw-r--r--src/crypto/rsa/pkcs1v15_test.go (renamed from src/pkg/crypto/rsa/pkcs1v15_test.go)0
-rw-r--r--src/crypto/rsa/pss.go (renamed from src/pkg/crypto/rsa/pss.go)15
-rw-r--r--src/crypto/rsa/pss_test.go (renamed from src/pkg/crypto/rsa/pss_test.go)0
-rw-r--r--src/crypto/rsa/rsa.go (renamed from src/pkg/crypto/rsa/rsa.go)19
-rw-r--r--src/crypto/rsa/rsa_test.go (renamed from src/pkg/crypto/rsa/rsa_test.go)0
-rw-r--r--src/crypto/rsa/testdata/pss-vect.txt.bz2 (renamed from src/pkg/crypto/rsa/testdata/pss-vect.txt.bz2)bin28526 -> 28526 bytes
-rw-r--r--src/crypto/sha1/example_test.go (renamed from src/pkg/crypto/sha1/example_test.go)0
-rw-r--r--src/crypto/sha1/sha1.go (renamed from src/pkg/crypto/sha1/sha1.go)0
-rw-r--r--src/crypto/sha1/sha1_test.go (renamed from src/pkg/crypto/sha1/sha1_test.go)0
-rw-r--r--src/crypto/sha1/sha1block.go (renamed from src/pkg/crypto/sha1/sha1block.go)0
-rw-r--r--src/crypto/sha1/sha1block_386.s (renamed from src/pkg/crypto/sha1/sha1block_386.s)2
-rw-r--r--src/crypto/sha1/sha1block_amd64.s (renamed from src/pkg/crypto/sha1/sha1block_amd64.s)2
-rw-r--r--src/crypto/sha1/sha1block_amd64p32.s (renamed from src/pkg/crypto/sha1/sha1block_amd64p32.s)2
-rw-r--r--src/crypto/sha1/sha1block_arm.s (renamed from src/pkg/crypto/sha1/sha1block_arm.s)2
-rw-r--r--src/crypto/sha1/sha1block_decl.go (renamed from src/pkg/crypto/sha1/sha1block_decl.go)0
-rw-r--r--src/crypto/sha1/sha1block_generic.go (renamed from src/pkg/crypto/sha1/sha1block_generic.go)0
-rw-r--r--src/crypto/sha256/sha256.go (renamed from src/pkg/crypto/sha256/sha256.go)0
-rw-r--r--src/crypto/sha256/sha256_test.go (renamed from src/pkg/crypto/sha256/sha256_test.go)0
-rw-r--r--src/crypto/sha256/sha256block.go (renamed from src/pkg/crypto/sha256/sha256block.go)0
-rw-r--r--src/crypto/sha256/sha256block_386.s (renamed from src/pkg/crypto/sha256/sha256block_386.s)0
-rw-r--r--src/crypto/sha256/sha256block_amd64.s (renamed from src/pkg/crypto/sha256/sha256block_amd64.s)2
-rw-r--r--src/crypto/sha256/sha256block_decl.go (renamed from src/pkg/crypto/sha256/sha256block_decl.go)0
-rw-r--r--src/crypto/sha512/sha512.go (renamed from src/pkg/crypto/sha512/sha512.go)0
-rw-r--r--src/crypto/sha512/sha512_test.go (renamed from src/pkg/crypto/sha512/sha512_test.go)0
-rw-r--r--src/crypto/sha512/sha512block.go (renamed from src/pkg/crypto/sha512/sha512block.go)0
-rw-r--r--src/crypto/sha512/sha512block_amd64.s (renamed from src/pkg/crypto/sha512/sha512block_amd64.s)2
-rw-r--r--src/crypto/sha512/sha512block_decl.go (renamed from src/pkg/crypto/sha512/sha512block_decl.go)0
-rw-r--r--src/crypto/subtle/constant_time.go (renamed from src/pkg/crypto/subtle/constant_time.go)5
-rw-r--r--src/crypto/subtle/constant_time_test.go (renamed from src/pkg/crypto/subtle/constant_time_test.go)2
-rw-r--r--src/crypto/tls/alert.go (renamed from src/pkg/crypto/tls/alert.go)2
-rw-r--r--src/crypto/tls/cipher_suites.go (renamed from src/pkg/crypto/tls/cipher_suites.go)5
-rw-r--r--src/crypto/tls/common.go (renamed from src/pkg/crypto/tls/common.go)73
-rw-r--r--src/crypto/tls/conn.go (renamed from src/pkg/crypto/tls/conn.go)6
-rw-r--r--src/crypto/tls/conn_test.go (renamed from src/pkg/crypto/tls/conn_test.go)22
-rw-r--r--src/crypto/tls/example_test.go (renamed from src/pkg/crypto/tls/example_test.go)0
-rw-r--r--src/crypto/tls/generate_cert.go (renamed from src/pkg/crypto/tls/generate_cert.go)62
-rw-r--r--src/crypto/tls/handshake_client.go (renamed from src/pkg/crypto/tls/handshake_client.go)93
-rw-r--r--src/crypto/tls/handshake_client_test.go (renamed from src/pkg/crypto/tls/handshake_client_test.go)53
-rw-r--r--src/crypto/tls/handshake_messages.go (renamed from src/pkg/crypto/tls/handshake_messages.go)98
-rw-r--r--src/crypto/tls/handshake_messages_test.go (renamed from src/pkg/crypto/tls/handshake_messages_test.go)5
-rw-r--r--src/crypto/tls/handshake_server.go (renamed from src/pkg/crypto/tls/handshake_server.go)59
-rw-r--r--src/crypto/tls/handshake_server_test.go (renamed from src/pkg/crypto/tls/handshake_server_test.go)168
-rw-r--r--src/crypto/tls/handshake_test.go (renamed from src/pkg/crypto/tls/handshake_test.go)0
-rw-r--r--src/crypto/tls/key_agreement.go (renamed from src/pkg/crypto/tls/key_agreement.go)6
-rw-r--r--src/crypto/tls/prf.go (renamed from src/pkg/crypto/tls/prf.go)0
-rw-r--r--src/crypto/tls/prf_test.go (renamed from src/pkg/crypto/tls/prf_test.go)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA (renamed from src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA (renamed from src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA (renamed from src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA (renamed from src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES (renamed from src/pkg/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES (renamed from src/pkg/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv10-RSA-RC4 (renamed from src/pkg/crypto/tls/testdata/Client-TLSv10-RSA-RC4)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES (renamed from src/pkg/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES (renamed from src/pkg/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv11-RSA-RC4 (renamed from src/pkg/crypto/tls/testdata/Client-TLSv11-RSA-RC4)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv12-ALPN97
-rw-r--r--src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch95
-rw-r--r--src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA (renamed from src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA (renamed from src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA (renamed from src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA (renamed from src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES (renamed from src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM (renamed from src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES (renamed from src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES)0
-rw-r--r--src/crypto/tls/testdata/Client-TLSv12-RSA-RC4 (renamed from src/pkg/crypto/tls/testdata/Client-TLSv12-RSA-RC4)0
-rw-r--r--src/crypto/tls/testdata/Server-SSLv3-RSA-3DES (renamed from src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-3DES)0
-rw-r--r--src/crypto/tls/testdata/Server-SSLv3-RSA-AES (renamed from src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-AES)0
-rw-r--r--src/crypto/tls/testdata/Server-SSLv3-RSA-RC4 (renamed from src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-RC4)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES (renamed from src/pkg/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv10-RSA-3DES (renamed from src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-3DES)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv10-RSA-AES (renamed from src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-AES)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv10-RSA-RC4 (renamed from src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-RC4)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV17
-rw-r--r--src/crypto/tls/testdata/Server-TLSv11-RSA-RC4 (renamed from src/pkg/crypto/tls/testdata/Server-TLSv11-RSA-RC4)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-ALPN122
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch121
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-IssueTicket (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-IssueTicket)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-RSA-3DES (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-3DES)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-RSA-AES (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-AES)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-RSA-RC4 (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-RC4)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-Resume (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-Resume)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-ResumeDisabled)0
-rw-r--r--src/crypto/tls/testdata/Server-TLSv12-SNI (renamed from src/pkg/crypto/tls/testdata/Server-TLSv12-SNI)0
-rw-r--r--src/crypto/tls/ticket.go (renamed from src/pkg/crypto/tls/ticket.go)0
-rw-r--r--src/crypto/tls/tls.go (renamed from src/pkg/crypto/tls/tls.go)0
-rw-r--r--src/crypto/tls/tls_test.go (renamed from src/pkg/crypto/tls/tls_test.go)45
-rw-r--r--src/crypto/x509/cert_pool.go (renamed from src/pkg/crypto/x509/cert_pool.go)0
-rw-r--r--src/crypto/x509/example_test.go (renamed from src/pkg/crypto/x509/example_test.go)0
-rw-r--r--src/crypto/x509/pem_decrypt.go (renamed from src/pkg/crypto/x509/pem_decrypt.go)0
-rw-r--r--src/crypto/x509/pem_decrypt_test.go (renamed from src/pkg/crypto/x509/pem_decrypt_test.go)4
-rw-r--r--src/crypto/x509/pkcs1.go (renamed from src/pkg/crypto/x509/pkcs1.go)0
-rw-r--r--src/crypto/x509/pkcs8.go (renamed from src/pkg/crypto/x509/pkcs8.go)0
-rw-r--r--src/crypto/x509/pkcs8_test.go (renamed from src/pkg/crypto/x509/pkcs8_test.go)0
-rw-r--r--src/crypto/x509/pkix/pkix.go (renamed from src/pkg/crypto/x509/pkix/pkix.go)2
-rw-r--r--src/crypto/x509/root.go (renamed from src/pkg/crypto/x509/root.go)0
-rw-r--r--src/crypto/x509/root_cgo_darwin.go (renamed from src/pkg/crypto/x509/root_cgo_darwin.go)0
-rw-r--r--src/crypto/x509/root_darwin.go (renamed from src/pkg/crypto/x509/root_darwin.go)0
-rw-r--r--src/crypto/x509/root_darwin_test.go (renamed from src/pkg/crypto/x509/root_darwin_test.go)0
-rw-r--r--src/crypto/x509/root_nocgo_darwin.go (renamed from src/pkg/crypto/x509/root_nocgo_darwin.go)0
-rw-r--r--src/crypto/x509/root_plan9.go (renamed from src/pkg/crypto/x509/root_plan9.go)0
-rw-r--r--src/crypto/x509/root_unix.go (renamed from src/pkg/crypto/x509/root_unix.go)27
-rw-r--r--src/crypto/x509/root_windows.go (renamed from src/pkg/crypto/x509/root_windows.go)0
-rw-r--r--src/crypto/x509/sec1.go (renamed from src/pkg/crypto/x509/sec1.go)0
-rw-r--r--src/crypto/x509/sec1_test.go (renamed from src/pkg/crypto/x509/sec1_test.go)0
-rw-r--r--src/crypto/x509/verify.go (renamed from src/pkg/crypto/x509/verify.go)8
-rw-r--r--src/crypto/x509/verify_test.go (renamed from src/pkg/crypto/x509/verify_test.go)0
-rw-r--r--src/crypto/x509/x509.go (renamed from src/pkg/crypto/x509/x509.go)19
-rw-r--r--src/crypto/x509/x509_test.go (renamed from src/pkg/crypto/x509/x509_test.go)87
-rw-r--r--src/crypto/x509/x509_test_import.go (renamed from src/pkg/crypto/x509/x509_test_import.go)0
-rw-r--r--src/database/sql/convert.go (renamed from src/pkg/database/sql/convert.go)0
-rw-r--r--src/database/sql/convert_test.go (renamed from src/pkg/database/sql/convert_test.go)37
-rw-r--r--src/database/sql/doc.txt (renamed from src/pkg/database/sql/doc.txt)0
-rw-r--r--src/database/sql/driver/driver.go (renamed from src/pkg/database/sql/driver/driver.go)0
-rw-r--r--src/database/sql/driver/types.go (renamed from src/pkg/database/sql/driver/types.go)0
-rw-r--r--src/database/sql/driver/types_test.go (renamed from src/pkg/database/sql/driver/types_test.go)0
-rw-r--r--src/database/sql/example_test.go (renamed from src/pkg/database/sql/example_test.go)0
-rw-r--r--src/database/sql/fakedb_test.go (renamed from src/pkg/database/sql/fakedb_test.go)24
-rw-r--r--src/database/sql/sql.go (renamed from src/pkg/database/sql/sql.go)220
-rw-r--r--src/database/sql/sql_test.go (renamed from src/pkg/database/sql/sql_test.go)84
-rw-r--r--src/debug/dwarf/buf.go (renamed from src/pkg/debug/dwarf/buf.go)0
-rw-r--r--src/debug/dwarf/const.go (renamed from src/pkg/debug/dwarf/const.go)0
-rw-r--r--src/debug/dwarf/entry.go (renamed from src/pkg/debug/dwarf/entry.go)0
-rw-r--r--src/debug/dwarf/open.go (renamed from src/pkg/debug/dwarf/open.go)0
-rw-r--r--src/debug/dwarf/testdata/typedef.c (renamed from src/pkg/debug/dwarf/testdata/typedef.c)0
-rwxr-xr-xsrc/debug/dwarf/testdata/typedef.elf (renamed from src/pkg/debug/dwarf/testdata/typedef.elf)bin12448 -> 12448 bytes
-rw-r--r--src/debug/dwarf/testdata/typedef.elf4 (renamed from src/pkg/debug/dwarf/testdata/typedef.elf4)bin9496 -> 9496 bytes
-rw-r--r--src/debug/dwarf/testdata/typedef.macho (renamed from src/pkg/debug/dwarf/testdata/typedef.macho)bin5024 -> 5024 bytes
-rw-r--r--src/debug/dwarf/type.go (renamed from src/pkg/debug/dwarf/type.go)85
-rw-r--r--src/debug/dwarf/type_test.go (renamed from src/pkg/debug/dwarf/type_test.go)0
-rw-r--r--src/debug/dwarf/typeunit.go (renamed from src/pkg/debug/dwarf/typeunit.go)0
-rw-r--r--src/debug/dwarf/unit.go (renamed from src/pkg/debug/dwarf/unit.go)0
-rw-r--r--src/debug/elf/elf.go (renamed from src/pkg/debug/elf/elf.go)338
-rw-r--r--src/debug/elf/elf_test.go (renamed from src/pkg/debug/elf/elf_test.go)0
-rw-r--r--src/debug/elf/file.go (renamed from src/pkg/debug/elf/file.go)80
-rw-r--r--src/debug/elf/file_test.go (renamed from src/pkg/debug/elf/file_test.go)8
-rw-r--r--src/debug/elf/symbols_test.go834
-rwxr-xr-xsrc/debug/elf/testdata/gcc-386-freebsd-exec (renamed from src/pkg/debug/elf/testdata/gcc-386-freebsd-exec)bin5742 -> 5742 bytes
-rwxr-xr-xsrc/debug/elf/testdata/gcc-amd64-linux-exec (renamed from src/pkg/debug/elf/testdata/gcc-amd64-linux-exec)bin8844 -> 8844 bytes
-rw-r--r--src/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj (renamed from src/pkg/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj)bin6544 -> 6544 bytes
-rw-r--r--src/debug/elf/testdata/go-relocation-test-clang-x86.obj (renamed from src/pkg/debug/elf/testdata/go-relocation-test-clang-x86.obj)bin1900 -> 1900 bytes
-rw-r--r--src/debug/elf/testdata/go-relocation-test-gcc424-x86-64.obj (renamed from src/pkg/debug/elf/testdata/go-relocation-test-gcc424-x86-64.obj)bin3088 -> 3088 bytes
-rw-r--r--src/debug/elf/testdata/go-relocation-test-gcc441-x86-64.obj (renamed from src/pkg/debug/elf/testdata/go-relocation-test-gcc441-x86-64.obj)bin2936 -> 2936 bytes
-rw-r--r--src/debug/elf/testdata/go-relocation-test-gcc441-x86.obj (renamed from src/pkg/debug/elf/testdata/go-relocation-test-gcc441-x86.obj)bin1884 -> 1884 bytes
-rw-r--r--src/debug/elf/testdata/go-relocation-test-gcc482-aarch64.objbin0 -> 3392 bytes
-rw-r--r--src/debug/elf/testdata/hello-world-core.gz (renamed from src/pkg/debug/elf/testdata/hello-world-core.gz)bin12678 -> 12678 bytes
-rw-r--r--src/debug/elf/testdata/hello.c (renamed from src/pkg/debug/elf/testdata/hello.c)0
-rw-r--r--src/debug/gosym/pclinetest.asm (renamed from src/pkg/debug/gosym/pclinetest.asm)0
-rw-r--r--src/debug/gosym/pclinetest.h (renamed from src/pkg/debug/gosym/pclinetest.h)0
-rw-r--r--src/debug/gosym/pclntab.go (renamed from src/pkg/debug/gosym/pclntab.go)0
-rw-r--r--src/debug/gosym/pclntab_test.go (renamed from src/pkg/debug/gosym/pclntab_test.go)0
-rw-r--r--src/debug/gosym/symtab.go (renamed from src/pkg/debug/gosym/symtab.go)2
-rw-r--r--src/debug/macho/fat.go (renamed from src/pkg/debug/macho/fat.go)0
-rw-r--r--src/debug/macho/file.go (renamed from src/pkg/debug/macho/file.go)0
-rw-r--r--src/debug/macho/file_test.go (renamed from src/pkg/debug/macho/file_test.go)0
-rw-r--r--src/debug/macho/macho.go (renamed from src/pkg/debug/macho/macho.go)0
-rw-r--r--src/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec (renamed from src/pkg/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec)bin28992 -> 28992 bytes
-rwxr-xr-xsrc/debug/macho/testdata/gcc-386-darwin-exec (renamed from src/pkg/debug/macho/testdata/gcc-386-darwin-exec)bin12588 -> 12588 bytes
-rwxr-xr-xsrc/debug/macho/testdata/gcc-amd64-darwin-exec (renamed from src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec)bin8512 -> 8512 bytes
-rw-r--r--src/debug/macho/testdata/gcc-amd64-darwin-exec-debug (renamed from src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec-debug)bin4540 -> 4540 bytes
-rw-r--r--src/debug/macho/testdata/hello.c (renamed from src/pkg/debug/macho/testdata/hello.c)0
-rw-r--r--src/debug/pe/file.go (renamed from src/pkg/debug/pe/file.go)12
-rw-r--r--src/debug/pe/file_test.go (renamed from src/pkg/debug/pe/file_test.go)31
-rw-r--r--src/debug/pe/pe.go (renamed from src/pkg/debug/pe/pe.go)0
-rw-r--r--src/debug/pe/testdata/gcc-386-mingw-exec (renamed from src/pkg/debug/pe/testdata/gcc-386-mingw-exec)bin29941 -> 29941 bytes
-rw-r--r--src/debug/pe/testdata/gcc-386-mingw-obj (renamed from src/pkg/debug/pe/testdata/gcc-386-mingw-obj)bin2372 -> 2372 bytes
-rw-r--r--src/debug/pe/testdata/gcc-amd64-mingw-execbin0 -> 273083 bytes
-rw-r--r--src/debug/pe/testdata/gcc-amd64-mingw-obj (renamed from src/pkg/debug/pe/testdata/gcc-amd64-mingw-obj)bin736 -> 736 bytes
-rw-r--r--src/debug/pe/testdata/hello.c (renamed from src/pkg/debug/pe/testdata/hello.c)0
-rw-r--r--src/debug/plan9obj/file.go (renamed from src/pkg/debug/plan9obj/file.go)27
-rw-r--r--src/debug/plan9obj/file_test.go (renamed from src/pkg/debug/plan9obj/file_test.go)4
-rw-r--r--src/debug/plan9obj/plan9obj.go (renamed from src/pkg/debug/plan9obj/plan9obj.go)0
-rwxr-xr-xsrc/debug/plan9obj/testdata/386-plan9-exec (renamed from src/pkg/debug/plan9obj/testdata/386-plan9-exec)bin37232 -> 37232 bytes
-rwxr-xr-xsrc/debug/plan9obj/testdata/amd64-plan9-exec (renamed from src/pkg/debug/plan9obj/testdata/amd64-plan9-exec)bin34279 -> 34279 bytes
-rw-r--r--src/debug/plan9obj/testdata/hello.c (renamed from src/pkg/debug/plan9obj/testdata/hello.c)0
-rw-r--r--src/encoding/ascii85/ascii85.go (renamed from src/pkg/encoding/ascii85/ascii85.go)1
-rw-r--r--src/encoding/ascii85/ascii85_test.go (renamed from src/pkg/encoding/ascii85/ascii85_test.go)0
-rw-r--r--src/encoding/asn1/asn1.go (renamed from src/pkg/encoding/asn1/asn1.go)30
-rw-r--r--src/encoding/asn1/asn1_test.go (renamed from src/pkg/encoding/asn1/asn1_test.go)53
-rw-r--r--src/encoding/asn1/common.go (renamed from src/pkg/encoding/asn1/common.go)0
-rw-r--r--src/encoding/asn1/marshal.go (renamed from src/pkg/encoding/asn1/marshal.go)18
-rw-r--r--src/encoding/asn1/marshal_test.go (renamed from src/pkg/encoding/asn1/marshal_test.go)7
-rw-r--r--src/encoding/base32/base32.go (renamed from src/pkg/encoding/base32/base32.go)46
-rw-r--r--src/encoding/base32/base32_test.go (renamed from src/pkg/encoding/base32/base32_test.go)16
-rw-r--r--src/encoding/base32/example_test.go (renamed from src/pkg/encoding/base32/example_test.go)0
-rw-r--r--src/encoding/base64/base64.go (renamed from src/pkg/encoding/base64/base64.go)26
-rw-r--r--src/encoding/base64/base64_test.go (renamed from src/pkg/encoding/base64/base64_test.go)16
-rw-r--r--src/encoding/base64/example_test.go (renamed from src/pkg/encoding/base64/example_test.go)0
-rw-r--r--src/encoding/binary/binary.go (renamed from src/pkg/encoding/binary/binary.go)77
-rw-r--r--src/encoding/binary/binary_test.go (renamed from src/pkg/encoding/binary/binary_test.go)23
-rw-r--r--src/encoding/binary/example_test.go (renamed from src/pkg/encoding/binary/example_test.go)0
-rw-r--r--src/encoding/binary/varint.go (renamed from src/pkg/encoding/binary/varint.go)0
-rw-r--r--src/encoding/binary/varint_test.go (renamed from src/pkg/encoding/binary/varint_test.go)0
-rw-r--r--src/encoding/csv/reader.go (renamed from src/pkg/encoding/csv/reader.go)0
-rw-r--r--src/encoding/csv/reader_test.go (renamed from src/pkg/encoding/csv/reader_test.go)0
-rw-r--r--src/encoding/csv/writer.go (renamed from src/pkg/encoding/csv/writer.go)16
-rw-r--r--src/encoding/csv/writer_test.go (renamed from src/pkg/encoding/csv/writer_test.go)11
-rw-r--r--src/encoding/encoding.go (renamed from src/pkg/encoding/encoding.go)0
-rw-r--r--src/encoding/gob/codec_test.go (renamed from src/pkg/encoding/gob/codec_test.go)333
-rw-r--r--src/encoding/gob/debug.go (renamed from src/pkg/encoding/gob/debug.go)6
-rw-r--r--src/encoding/gob/dec_helpers.go468
-rw-r--r--src/encoding/gob/decgen.go240
-rw-r--r--src/encoding/gob/decode.go (renamed from src/pkg/encoding/gob/decode.go)724
-rw-r--r--src/encoding/gob/decoder.go (renamed from src/pkg/encoding/gob/decoder.go)51
-rw-r--r--src/encoding/gob/doc.go (renamed from src/pkg/encoding/gob/doc.go)0
-rw-r--r--src/encoding/gob/dump.go (renamed from src/pkg/encoding/gob/dump.go)0
-rw-r--r--src/encoding/gob/enc_helpers.go414
-rw-r--r--src/encoding/gob/encgen.go218
-rw-r--r--src/encoding/gob/encode.go (renamed from src/pkg/encoding/gob/encode.go)482
-rw-r--r--src/encoding/gob/encoder.go (renamed from src/pkg/encoding/gob/encoder.go)11
-rw-r--r--src/encoding/gob/encoder_test.go (renamed from src/pkg/encoding/gob/encoder_test.go)98
-rw-r--r--src/encoding/gob/error.go (renamed from src/pkg/encoding/gob/error.go)0
-rw-r--r--src/encoding/gob/example_encdec_test.go (renamed from src/pkg/encoding/gob/example_encdec_test.go)0
-rw-r--r--src/encoding/gob/example_interface_test.go (renamed from src/pkg/encoding/gob/example_interface_test.go)0
-rw-r--r--src/encoding/gob/example_test.go (renamed from src/pkg/encoding/gob/example_test.go)0
-rw-r--r--src/encoding/gob/gobencdec_test.go (renamed from src/pkg/encoding/gob/gobencdec_test.go)7
-rw-r--r--src/encoding/gob/timing_test.go325
-rw-r--r--src/encoding/gob/type.go (renamed from src/pkg/encoding/gob/type.go)76
-rw-r--r--src/encoding/gob/type_test.go (renamed from src/pkg/encoding/gob/type_test.go)0
-rw-r--r--src/encoding/hex/hex.go (renamed from src/pkg/encoding/hex/hex.go)0
-rw-r--r--src/encoding/hex/hex_test.go (renamed from src/pkg/encoding/hex/hex_test.go)0
-rw-r--r--src/encoding/json/bench_test.go (renamed from src/pkg/encoding/json/bench_test.go)0
-rw-r--r--src/encoding/json/decode.go (renamed from src/pkg/encoding/json/decode.go)46
-rw-r--r--src/encoding/json/decode_test.go (renamed from src/pkg/encoding/json/decode_test.go)33
-rw-r--r--src/encoding/json/encode.go (renamed from src/pkg/encoding/json/encode.go)18
-rw-r--r--src/encoding/json/encode_test.go (renamed from src/pkg/encoding/json/encode_test.go)78
-rw-r--r--src/encoding/json/example_test.go (renamed from src/pkg/encoding/json/example_test.go)0
-rw-r--r--src/encoding/json/fold.go (renamed from src/pkg/encoding/json/fold.go)0
-rw-r--r--src/encoding/json/fold_test.go (renamed from src/pkg/encoding/json/fold_test.go)0
-rw-r--r--src/encoding/json/indent.go (renamed from src/pkg/encoding/json/indent.go)0
-rw-r--r--src/encoding/json/scanner.go (renamed from src/pkg/encoding/json/scanner.go)0
-rw-r--r--src/encoding/json/scanner_test.go (renamed from src/pkg/encoding/json/scanner_test.go)0
-rw-r--r--src/encoding/json/stream.go (renamed from src/pkg/encoding/json/stream.go)1
-rw-r--r--src/encoding/json/stream_test.go (renamed from src/pkg/encoding/json/stream_test.go)0
-rw-r--r--src/encoding/json/tagkey_test.go (renamed from src/pkg/encoding/json/tagkey_test.go)0
-rw-r--r--src/encoding/json/tags.go (renamed from src/pkg/encoding/json/tags.go)0
-rw-r--r--src/encoding/json/tags_test.go (renamed from src/pkg/encoding/json/tags_test.go)0
-rw-r--r--src/encoding/json/testdata/code.json.gz (renamed from src/pkg/encoding/json/testdata/code.json.gz)bin120432 -> 120432 bytes
-rw-r--r--src/encoding/pem/pem.go (renamed from src/pkg/encoding/pem/pem.go)0
-rw-r--r--src/encoding/pem/pem_test.go (renamed from src/pkg/encoding/pem/pem_test.go)0
-rw-r--r--src/encoding/xml/atom_test.go (renamed from src/pkg/encoding/xml/atom_test.go)0
-rw-r--r--src/encoding/xml/example_test.go (renamed from src/pkg/encoding/xml/example_test.go)0
-rw-r--r--src/encoding/xml/marshal.go (renamed from src/pkg/encoding/xml/marshal.go)0
-rw-r--r--src/encoding/xml/marshal_test.go (renamed from src/pkg/encoding/xml/marshal_test.go)0
-rw-r--r--src/encoding/xml/read.go (renamed from src/pkg/encoding/xml/read.go)0
-rw-r--r--src/encoding/xml/read_test.go (renamed from src/pkg/encoding/xml/read_test.go)0
-rw-r--r--src/encoding/xml/typeinfo.go (renamed from src/pkg/encoding/xml/typeinfo.go)0
-rw-r--r--src/encoding/xml/xml.go (renamed from src/pkg/encoding/xml/xml.go)10
-rw-r--r--src/encoding/xml/xml_test.go (renamed from src/pkg/encoding/xml/xml_test.go)31
-rw-r--r--src/errors/errors.go (renamed from src/pkg/errors/errors.go)0
-rw-r--r--src/errors/errors_test.go (renamed from src/pkg/errors/errors_test.go)0
-rw-r--r--src/errors/example_test.go (renamed from src/pkg/errors/example_test.go)0
-rw-r--r--src/expvar/expvar.go (renamed from src/pkg/expvar/expvar.go)0
-rw-r--r--src/expvar/expvar_test.go (renamed from src/pkg/expvar/expvar_test.go)0
-rw-r--r--src/flag/example_test.go (renamed from src/pkg/flag/example_test.go)0
-rw-r--r--src/flag/export_test.go (renamed from src/pkg/flag/export_test.go)0
-rw-r--r--src/flag/flag.go (renamed from src/pkg/flag/flag.go)27
-rw-r--r--src/flag/flag_test.go (renamed from src/pkg/flag/flag_test.go)10
-rw-r--r--src/fmt/doc.go (renamed from src/pkg/fmt/doc.go)47
-rw-r--r--src/fmt/export_test.go (renamed from src/pkg/fmt/export_test.go)0
-rw-r--r--src/fmt/fmt_test.go (renamed from src/pkg/fmt/fmt_test.go)201
-rw-r--r--src/fmt/format.go (renamed from src/pkg/fmt/format.go)84
-rw-r--r--src/fmt/print.go (renamed from src/pkg/fmt/print.go)226
-rw-r--r--src/fmt/scan.go (renamed from src/pkg/fmt/scan.go)1
-rw-r--r--src/fmt/scan_test.go (renamed from src/pkg/fmt/scan_test.go)32
-rw-r--r--src/fmt/stringer_test.go (renamed from src/pkg/fmt/stringer_test.go)0
-rw-r--r--src/go/ast/ast.go (renamed from src/pkg/go/ast/ast.go)6
-rw-r--r--src/go/ast/ast_test.go (renamed from src/pkg/go/ast/ast_test.go)0
-rw-r--r--src/go/ast/commentmap.go (renamed from src/pkg/go/ast/commentmap.go)0
-rw-r--r--src/go/ast/commentmap_test.go (renamed from src/pkg/go/ast/commentmap_test.go)0
-rw-r--r--src/go/ast/example_test.go (renamed from src/pkg/go/ast/example_test.go)0
-rw-r--r--src/go/ast/filter.go (renamed from src/pkg/go/ast/filter.go)0
-rw-r--r--src/go/ast/filter_test.go (renamed from src/pkg/go/ast/filter_test.go)0
-rw-r--r--src/go/ast/import.go (renamed from src/pkg/go/ast/import.go)0
-rw-r--r--src/go/ast/print.go (renamed from src/pkg/go/ast/print.go)0
-rw-r--r--src/go/ast/print_test.go (renamed from src/pkg/go/ast/print_test.go)0
-rw-r--r--src/go/ast/resolve.go (renamed from src/pkg/go/ast/resolve.go)0
-rw-r--r--src/go/ast/scope.go (renamed from src/pkg/go/ast/scope.go)2
-rw-r--r--src/go/ast/walk.go (renamed from src/pkg/go/ast/walk.go)4
-rw-r--r--src/go/build/build.go (renamed from src/pkg/go/build/build.go)232
-rw-r--r--src/go/build/build_test.go (renamed from src/pkg/go/build/build_test.go)52
-rw-r--r--src/go/build/deps_test.go (renamed from src/pkg/go/build/deps_test.go)11
-rw-r--r--src/go/build/doc.go (renamed from src/pkg/go/build/doc.go)14
-rw-r--r--src/go/build/read.go (renamed from src/pkg/go/build/read.go)0
-rw-r--r--src/go/build/read_test.go (renamed from src/pkg/go/build/read_test.go)0
-rw-r--r--src/go/build/syslist.go (renamed from src/pkg/go/build/syslist.go)2
-rw-r--r--src/go/build/syslist_test.go (renamed from src/pkg/go/build/syslist_test.go)0
-rw-r--r--src/go/build/testdata/empty/dummy0
-rw-r--r--src/go/build/testdata/multi/file.go5
-rw-r--r--src/go/build/testdata/multi/file_appengine.go5
-rw-r--r--src/go/build/testdata/other/file/file.go (renamed from src/pkg/go/build/testdata/other/file/file.go)0
-rw-r--r--src/go/build/testdata/other/main.go (renamed from src/pkg/go/build/testdata/other/main.go)0
-rw-r--r--src/go/doc/Makefile (renamed from src/pkg/go/doc/Makefile)0
-rw-r--r--src/go/doc/comment.go (renamed from src/pkg/go/doc/comment.go)0
-rw-r--r--src/go/doc/comment_test.go (renamed from src/pkg/go/doc/comment_test.go)0
-rw-r--r--src/go/doc/doc.go (renamed from src/pkg/go/doc/doc.go)0
-rw-r--r--src/go/doc/doc_test.go (renamed from src/pkg/go/doc/doc_test.go)0
-rw-r--r--src/go/doc/example.go (renamed from src/pkg/go/doc/example.go)0
-rw-r--r--src/go/doc/example_test.go (renamed from src/pkg/go/doc/example_test.go)0
-rw-r--r--src/go/doc/exports.go (renamed from src/pkg/go/doc/exports.go)26
-rw-r--r--src/go/doc/filter.go (renamed from src/pkg/go/doc/filter.go)0
-rw-r--r--src/go/doc/headscan.go (renamed from src/pkg/go/doc/headscan.go)15
-rw-r--r--src/go/doc/reader.go (renamed from src/pkg/go/doc/reader.go)0
-rw-r--r--src/go/doc/synopsis.go (renamed from src/pkg/go/doc/synopsis.go)0
-rw-r--r--src/go/doc/synopsis_test.go (renamed from src/pkg/go/doc/synopsis_test.go)0
-rw-r--r--src/go/doc/testdata/a.0.golden (renamed from src/pkg/go/doc/testdata/a.0.golden)0
-rw-r--r--src/go/doc/testdata/a.1.golden (renamed from src/pkg/go/doc/testdata/a.1.golden)0
-rw-r--r--src/go/doc/testdata/a.2.golden (renamed from src/pkg/go/doc/testdata/a.2.golden)0
-rw-r--r--src/go/doc/testdata/a0.go (renamed from src/pkg/go/doc/testdata/a0.go)0
-rw-r--r--src/go/doc/testdata/a1.go (renamed from src/pkg/go/doc/testdata/a1.go)0
-rw-r--r--src/go/doc/testdata/b.0.golden (renamed from src/pkg/go/doc/testdata/b.0.golden)0
-rw-r--r--src/go/doc/testdata/b.1.golden (renamed from src/pkg/go/doc/testdata/b.1.golden)0
-rw-r--r--src/go/doc/testdata/b.2.golden (renamed from src/pkg/go/doc/testdata/b.2.golden)0
-rw-r--r--src/go/doc/testdata/b.go (renamed from src/pkg/go/doc/testdata/b.go)0
-rw-r--r--src/go/doc/testdata/benchmark.go (renamed from src/pkg/go/doc/testdata/benchmark.go)0
-rw-r--r--src/go/doc/testdata/blank.0.golden37
-rw-r--r--src/go/doc/testdata/blank.1.golden46
-rw-r--r--src/go/doc/testdata/blank.2.golden37
-rw-r--r--src/go/doc/testdata/blank.go38
-rw-r--r--src/go/doc/testdata/bugpara.0.golden (renamed from src/pkg/go/doc/testdata/bugpara.0.golden)0
-rw-r--r--src/go/doc/testdata/bugpara.1.golden (renamed from src/pkg/go/doc/testdata/bugpara.1.golden)0
-rw-r--r--src/go/doc/testdata/bugpara.2.golden (renamed from src/pkg/go/doc/testdata/bugpara.2.golden)0
-rw-r--r--src/go/doc/testdata/bugpara.go (renamed from src/pkg/go/doc/testdata/bugpara.go)0
-rw-r--r--src/go/doc/testdata/c.0.golden (renamed from src/pkg/go/doc/testdata/c.0.golden)0
-rw-r--r--src/go/doc/testdata/c.1.golden (renamed from src/pkg/go/doc/testdata/c.1.golden)0
-rw-r--r--src/go/doc/testdata/c.2.golden (renamed from src/pkg/go/doc/testdata/c.2.golden)0
-rw-r--r--src/go/doc/testdata/c.go (renamed from src/pkg/go/doc/testdata/c.go)0
-rw-r--r--src/go/doc/testdata/d.0.golden (renamed from src/pkg/go/doc/testdata/d.0.golden)0
-rw-r--r--src/go/doc/testdata/d.1.golden (renamed from src/pkg/go/doc/testdata/d.1.golden)0
-rw-r--r--src/go/doc/testdata/d.2.golden (renamed from src/pkg/go/doc/testdata/d.2.golden)0
-rw-r--r--src/go/doc/testdata/d1.go (renamed from src/pkg/go/doc/testdata/d1.go)0
-rw-r--r--src/go/doc/testdata/d2.go (renamed from src/pkg/go/doc/testdata/d2.go)0
-rw-r--r--src/go/doc/testdata/e.0.golden (renamed from src/pkg/go/doc/testdata/e.0.golden)0
-rw-r--r--src/go/doc/testdata/e.1.golden (renamed from src/pkg/go/doc/testdata/e.1.golden)0
-rw-r--r--src/go/doc/testdata/e.2.golden (renamed from src/pkg/go/doc/testdata/e.2.golden)0
-rw-r--r--src/go/doc/testdata/e.go (renamed from src/pkg/go/doc/testdata/e.go)0
-rw-r--r--src/go/doc/testdata/error1.0.golden (renamed from src/pkg/go/doc/testdata/error1.0.golden)0
-rw-r--r--src/go/doc/testdata/error1.1.golden (renamed from src/pkg/go/doc/testdata/error1.1.golden)0
-rw-r--r--src/go/doc/testdata/error1.2.golden (renamed from src/pkg/go/doc/testdata/error1.2.golden)0
-rw-r--r--src/go/doc/testdata/error1.go (renamed from src/pkg/go/doc/testdata/error1.go)0
-rw-r--r--src/go/doc/testdata/error2.0.golden (renamed from src/pkg/go/doc/testdata/error2.0.golden)0
-rw-r--r--src/go/doc/testdata/error2.1.golden (renamed from src/pkg/go/doc/testdata/error2.1.golden)0
-rw-r--r--src/go/doc/testdata/error2.2.golden (renamed from src/pkg/go/doc/testdata/error2.2.golden)0
-rw-r--r--src/go/doc/testdata/error2.go (renamed from src/pkg/go/doc/testdata/error2.go)0
-rw-r--r--src/go/doc/testdata/example.go (renamed from src/pkg/go/doc/testdata/example.go)0
-rw-r--r--src/go/doc/testdata/f.0.golden (renamed from src/pkg/go/doc/testdata/f.0.golden)0
-rw-r--r--src/go/doc/testdata/f.1.golden (renamed from src/pkg/go/doc/testdata/f.1.golden)0
-rw-r--r--src/go/doc/testdata/f.2.golden (renamed from src/pkg/go/doc/testdata/f.2.golden)0
-rw-r--r--src/go/doc/testdata/f.go (renamed from src/pkg/go/doc/testdata/f.go)0
-rw-r--r--src/go/doc/testdata/template.txt (renamed from src/pkg/go/doc/testdata/template.txt)0
-rw-r--r--src/go/doc/testdata/testing.0.golden (renamed from src/pkg/go/doc/testdata/testing.0.golden)0
-rw-r--r--src/go/doc/testdata/testing.1.golden (renamed from src/pkg/go/doc/testdata/testing.1.golden)0
-rw-r--r--src/go/doc/testdata/testing.2.golden (renamed from src/pkg/go/doc/testdata/testing.2.golden)0
-rw-r--r--src/go/doc/testdata/testing.go (renamed from src/pkg/go/doc/testdata/testing.go)0
-rw-r--r--src/go/format/format.go266
-rw-r--r--src/go/format/format_test.go (renamed from src/pkg/go/format/format_test.go)6
-rw-r--r--src/go/parser/error_test.go (renamed from src/pkg/go/parser/error_test.go)3
-rw-r--r--src/go/parser/example_test.go (renamed from src/pkg/go/parser/example_test.go)0
-rw-r--r--src/go/parser/interface.go (renamed from src/pkg/go/parser/interface.go)2
-rw-r--r--src/go/parser/parser.go (renamed from src/pkg/go/parser/parser.go)72
-rw-r--r--src/go/parser/parser_test.go (renamed from src/pkg/go/parser/parser_test.go)38
-rw-r--r--src/go/parser/performance_test.go (renamed from src/pkg/go/parser/performance_test.go)0
-rw-r--r--src/go/parser/short_test.go (renamed from src/pkg/go/parser/short_test.go)6
-rw-r--r--src/go/parser/testdata/commas.src (renamed from src/pkg/go/parser/testdata/commas.src)0
-rw-r--r--src/go/parser/testdata/issue3106.src (renamed from src/pkg/go/parser/testdata/issue3106.src)0
-rw-r--r--src/go/printer/example_test.go (renamed from src/pkg/go/printer/example_test.go)0
-rw-r--r--src/go/printer/nodes.go (renamed from src/pkg/go/printer/nodes.go)37
-rw-r--r--src/go/printer/performance_test.go (renamed from src/pkg/go/printer/performance_test.go)0
-rw-r--r--src/go/printer/printer.go (renamed from src/pkg/go/printer/printer.go)0
-rw-r--r--src/go/printer/printer_test.go (renamed from src/pkg/go/printer/printer_test.go)13
-rw-r--r--src/go/printer/testdata/comments.golden (renamed from src/pkg/go/printer/testdata/comments.golden)0
-rw-r--r--src/go/printer/testdata/comments.input (renamed from src/pkg/go/printer/testdata/comments.input)0
-rw-r--r--src/go/printer/testdata/comments.x (renamed from src/pkg/go/printer/testdata/comments.x)0
-rw-r--r--src/go/printer/testdata/comments2.golden (renamed from src/pkg/go/printer/testdata/comments2.golden)0
-rw-r--r--src/go/printer/testdata/comments2.input (renamed from src/pkg/go/printer/testdata/comments2.input)0
-rw-r--r--src/go/printer/testdata/declarations.golden (renamed from src/pkg/go/printer/testdata/declarations.golden)25
-rw-r--r--src/go/printer/testdata/declarations.input (renamed from src/pkg/go/printer/testdata/declarations.input)25
-rw-r--r--src/go/printer/testdata/empty.golden (renamed from src/pkg/go/printer/testdata/empty.golden)0
-rw-r--r--src/go/printer/testdata/empty.input (renamed from src/pkg/go/printer/testdata/empty.input)0
-rw-r--r--src/go/printer/testdata/expressions.golden (renamed from src/pkg/go/printer/testdata/expressions.golden)5
-rw-r--r--src/go/printer/testdata/expressions.input (renamed from src/pkg/go/printer/testdata/expressions.input)5
-rw-r--r--src/go/printer/testdata/expressions.raw (renamed from src/pkg/go/printer/testdata/expressions.raw)5
-rw-r--r--src/go/printer/testdata/linebreaks.golden (renamed from src/pkg/go/printer/testdata/linebreaks.golden)0
-rw-r--r--src/go/printer/testdata/linebreaks.input (renamed from src/pkg/go/printer/testdata/linebreaks.input)0
-rw-r--r--src/go/printer/testdata/parser.go (renamed from src/pkg/go/printer/testdata/parser.go)0
-rw-r--r--src/go/printer/testdata/slow.golden (renamed from src/pkg/go/printer/testdata/slow.golden)0
-rw-r--r--src/go/printer/testdata/slow.input (renamed from src/pkg/go/printer/testdata/slow.input)0
-rw-r--r--src/go/printer/testdata/statements.golden (renamed from src/pkg/go/printer/testdata/statements.golden)11
-rw-r--r--src/go/printer/testdata/statements.input (renamed from src/pkg/go/printer/testdata/statements.input)5
-rw-r--r--src/go/scanner/errors.go (renamed from src/pkg/go/scanner/errors.go)0
-rw-r--r--src/go/scanner/example_test.go (renamed from src/pkg/go/scanner/example_test.go)0
-rw-r--r--src/go/scanner/scanner.go (renamed from src/pkg/go/scanner/scanner.go)0
-rw-r--r--src/go/scanner/scanner_test.go (renamed from src/pkg/go/scanner/scanner_test.go)0
-rw-r--r--src/go/token/position.go (renamed from src/pkg/go/token/position.go)51
-rw-r--r--src/go/token/position_test.go (renamed from src/pkg/go/token/position_test.go)101
-rw-r--r--src/go/token/serialize.go (renamed from src/pkg/go/token/serialize.go)0
-rw-r--r--src/go/token/serialize_test.go (renamed from src/pkg/go/token/serialize_test.go)0
-rw-r--r--src/go/token/token.go (renamed from src/pkg/go/token/token.go)0
-rw-r--r--src/hash/adler32/adler32.go (renamed from src/pkg/hash/adler32/adler32.go)0
-rw-r--r--src/hash/adler32/adler32_test.go (renamed from src/pkg/hash/adler32/adler32_test.go)0
-rw-r--r--src/hash/crc32/crc32.go (renamed from src/pkg/hash/crc32/crc32.go)4
-rw-r--r--src/hash/crc32/crc32_amd64.s (renamed from src/pkg/hash/crc32/crc32_amd64.s)2
-rw-r--r--src/hash/crc32/crc32_amd64p32.s (renamed from src/pkg/hash/crc32/crc32_amd64p32.s)2
-rw-r--r--src/hash/crc32/crc32_amd64x.go (renamed from src/pkg/hash/crc32/crc32_amd64x.go)0
-rw-r--r--src/hash/crc32/crc32_generic.go (renamed from src/pkg/hash/crc32/crc32_generic.go)0
-rw-r--r--src/hash/crc32/crc32_test.go (renamed from src/pkg/hash/crc32/crc32_test.go)0
-rw-r--r--src/hash/crc64/crc64.go (renamed from src/pkg/hash/crc64/crc64.go)0
-rw-r--r--src/hash/crc64/crc64_test.go (renamed from src/pkg/hash/crc64/crc64_test.go)0
-rw-r--r--src/hash/fnv/fnv.go (renamed from src/pkg/hash/fnv/fnv.go)0
-rw-r--r--src/hash/fnv/fnv_test.go (renamed from src/pkg/hash/fnv/fnv_test.go)0
-rw-r--r--src/hash/hash.go (renamed from src/pkg/hash/hash.go)0
-rw-r--r--src/hash/test_cases.txt (renamed from src/pkg/hash/test_cases.txt)0
-rw-r--r--src/hash/test_gen.awk (renamed from src/pkg/hash/test_gen.awk)0
-rw-r--r--src/html/entity.go (renamed from src/pkg/html/entity.go)0
-rw-r--r--src/html/entity_test.go (renamed from src/pkg/html/entity_test.go)0
-rw-r--r--src/html/escape.go (renamed from src/pkg/html/escape.go)0
-rw-r--r--src/html/escape_test.go (renamed from src/pkg/html/escape_test.go)0
-rw-r--r--src/html/template/attr.go (renamed from src/pkg/html/template/attr.go)0
-rw-r--r--src/html/template/clone_test.go (renamed from src/pkg/html/template/clone_test.go)0
-rw-r--r--src/html/template/content.go (renamed from src/pkg/html/template/content.go)0
-rw-r--r--src/html/template/content_test.go (renamed from src/pkg/html/template/content_test.go)0
-rw-r--r--src/html/template/context.go (renamed from src/pkg/html/template/context.go)0
-rw-r--r--src/html/template/css.go (renamed from src/pkg/html/template/css.go)0
-rw-r--r--src/html/template/css_test.go (renamed from src/pkg/html/template/css_test.go)0
-rw-r--r--src/html/template/doc.go (renamed from src/pkg/html/template/doc.go)0
-rw-r--r--src/html/template/error.go (renamed from src/pkg/html/template/error.go)16
-rw-r--r--src/html/template/escape.go (renamed from src/pkg/html/template/escape.go)74
-rw-r--r--src/html/template/escape_test.go (renamed from src/pkg/html/template/escape_test.go)23
-rw-r--r--src/html/template/html.go (renamed from src/pkg/html/template/html.go)0
-rw-r--r--src/html/template/html_test.go (renamed from src/pkg/html/template/html_test.go)0
-rw-r--r--src/html/template/js.go (renamed from src/pkg/html/template/js.go)0
-rw-r--r--src/html/template/js_test.go (renamed from src/pkg/html/template/js_test.go)2
-rw-r--r--src/html/template/template.go (renamed from src/pkg/html/template/template.go)40
-rw-r--r--src/html/template/transition.go (renamed from src/pkg/html/template/transition.go)12
-rw-r--r--src/html/template/url.go (renamed from src/pkg/html/template/url.go)0
-rw-r--r--src/html/template/url_test.go (renamed from src/pkg/html/template/url_test.go)0
-rw-r--r--src/image/color/color.go (renamed from src/pkg/image/color/color.go)0
-rw-r--r--src/image/color/palette/gen.go121
-rw-r--r--src/image/color/palette/generate.go8
-rw-r--r--src/image/color/palette/palette.go (renamed from src/pkg/image/color/palette/palette.go)3
-rw-r--r--src/image/color/ycbcr.go (renamed from src/pkg/image/color/ycbcr.go)0
-rw-r--r--src/image/color/ycbcr_test.go (renamed from src/pkg/image/color/ycbcr_test.go)0
-rw-r--r--src/image/decode_example_test.go (renamed from src/pkg/image/decode_example_test.go)0
-rw-r--r--src/image/decode_test.go (renamed from src/pkg/image/decode_test.go)0
-rw-r--r--src/image/draw/bench_test.go (renamed from src/pkg/image/draw/bench_test.go)0
-rw-r--r--src/image/draw/clip_test.go (renamed from src/pkg/image/draw/clip_test.go)0
-rw-r--r--src/image/draw/draw.go (renamed from src/pkg/image/draw/draw.go)0
-rw-r--r--src/image/draw/draw_test.go (renamed from src/pkg/image/draw/draw_test.go)0
-rw-r--r--src/image/format.go (renamed from src/pkg/image/format.go)0
-rw-r--r--src/image/geom.go (renamed from src/pkg/image/geom.go)0
-rw-r--r--src/image/gif/reader.go (renamed from src/pkg/image/gif/reader.go)7
-rw-r--r--src/image/gif/reader_test.go (renamed from src/pkg/image/gif/reader_test.go)64
-rw-r--r--src/image/gif/writer.go (renamed from src/pkg/image/gif/writer.go)18
-rw-r--r--src/image/gif/writer_test.go (renamed from src/pkg/image/gif/writer_test.go)25
-rw-r--r--src/image/image.go (renamed from src/pkg/image/image.go)32
-rw-r--r--src/image/image_test.go (renamed from src/pkg/image/image_test.go)0
-rw-r--r--src/image/jpeg/dct_test.go (renamed from src/pkg/image/jpeg/dct_test.go)0
-rw-r--r--src/image/jpeg/fdct.go (renamed from src/pkg/image/jpeg/fdct.go)0
-rw-r--r--src/image/jpeg/huffman.go244
-rw-r--r--src/image/jpeg/idct.go (renamed from src/pkg/image/jpeg/idct.go)0
-rw-r--r--src/image/jpeg/reader.go (renamed from src/pkg/image/jpeg/reader.go)210
-rw-r--r--src/image/jpeg/reader_test.go (renamed from src/pkg/image/jpeg/reader_test.go)45
-rw-r--r--src/image/jpeg/scan.go (renamed from src/pkg/image/jpeg/scan.go)57
-rw-r--r--src/image/jpeg/writer.go (renamed from src/pkg/image/jpeg/writer.go)133
-rw-r--r--src/image/jpeg/writer_test.go (renamed from src/pkg/image/jpeg/writer_test.go)28
-rw-r--r--src/image/names.go (renamed from src/pkg/image/names.go)0
-rw-r--r--src/image/png/paeth.go (renamed from src/pkg/image/png/paeth.go)41
-rw-r--r--src/image/png/paeth_test.go (renamed from src/pkg/image/png/paeth_test.go)8
-rw-r--r--src/image/png/reader.go (renamed from src/pkg/image/png/reader.go)219
-rw-r--r--src/image/png/reader_test.go (renamed from src/pkg/image/png/reader_test.go)16
-rw-r--r--src/image/png/testdata/benchGray.png (renamed from src/pkg/image/png/testdata/benchGray.png)bin14709 -> 14709 bytes
-rw-r--r--src/image/png/testdata/benchNRGBA-gradient.png (renamed from src/pkg/image/png/testdata/benchNRGBA-gradient.png)bin58831 -> 58831 bytes
-rw-r--r--src/image/png/testdata/benchNRGBA-opaque.png (renamed from src/pkg/image/png/testdata/benchNRGBA-opaque.png)bin44237 -> 44237 bytes
-rw-r--r--src/image/png/testdata/benchPaletted.png (renamed from src/pkg/image/png/testdata/benchPaletted.png)bin13397 -> 13397 bytes
-rw-r--r--src/image/png/testdata/benchRGB-interlace.pngbin0 -> 47483 bytes
-rw-r--r--src/image/png/testdata/benchRGB.png (renamed from src/pkg/image/png/testdata/benchRGB.png)bin39571 -> 39571 bytes
-rw-r--r--src/image/png/testdata/invalid-crc32.png (renamed from src/pkg/image/png/testdata/invalid-crc32.png)bin1289 -> 1289 bytes
-rw-r--r--src/image/png/testdata/invalid-noend.png (renamed from src/pkg/image/png/testdata/invalid-noend.png)bin1277 -> 1277 bytes
-rw-r--r--src/image/png/testdata/invalid-trunc.png (renamed from src/pkg/image/png/testdata/invalid-trunc.png)bin1288 -> 1288 bytes
-rw-r--r--src/image/png/testdata/invalid-zlib.png (renamed from src/pkg/image/png/testdata/invalid-zlib.png)bin1289 -> 1289 bytes
-rw-r--r--src/image/png/testdata/pngsuite/README (renamed from src/pkg/image/png/testdata/pngsuite/README)0
-rw-r--r--src/image/png/testdata/pngsuite/README.original (renamed from src/pkg/image/png/testdata/pngsuite/README.original)0
-rw-r--r--src/image/png/testdata/pngsuite/basn0g01-30.png (renamed from src/pkg/image/png/testdata/pngsuite/basn0g01-30.png)bin162 -> 162 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn0g01-30.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn0g01-30.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn0g01.png (renamed from src/pkg/image/png/testdata/pngsuite/basn0g01.png)bin164 -> 164 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn0g01.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn0g01.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn0g02-29.png (renamed from src/pkg/image/png/testdata/pngsuite/basn0g02-29.png)bin110 -> 110 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn0g02-29.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn0g02-29.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn0g02.png (renamed from src/pkg/image/png/testdata/pngsuite/basn0g02.png)bin104 -> 104 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn0g02.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn0g02.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn0g04-31.png (renamed from src/pkg/image/png/testdata/pngsuite/basn0g04-31.png)bin153 -> 153 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn0g04-31.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn0g04-31.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn0g04.png (renamed from src/pkg/image/png/testdata/pngsuite/basn0g04.png)bin145 -> 145 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn0g04.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn0g04.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn0g08.png (renamed from src/pkg/image/png/testdata/pngsuite/basn0g08.png)bin138 -> 138 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn0g08.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn0g08.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn0g16.png (renamed from src/pkg/image/png/testdata/pngsuite/basn0g16.png)bin167 -> 167 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn0g16.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn0g16.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn2c08.png (renamed from src/pkg/image/png/testdata/pngsuite/basn2c08.png)bin145 -> 145 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn2c08.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn2c08.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn2c16.png (renamed from src/pkg/image/png/testdata/pngsuite/basn2c16.png)bin302 -> 302 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn2c16.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn2c16.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn3p01.png (renamed from src/pkg/image/png/testdata/pngsuite/basn3p01.png)bin112 -> 112 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn3p01.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn3p01.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn3p02.png (renamed from src/pkg/image/png/testdata/pngsuite/basn3p02.png)bin146 -> 146 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn3p02.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn3p02.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn3p04-31i.pngbin0 -> 358 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn3p04-31i.sng57
-rw-r--r--src/image/png/testdata/pngsuite/basn3p04.png (renamed from src/pkg/image/png/testdata/pngsuite/basn3p04.png)bin216 -> 216 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn3p04.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn3p04.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn3p08-trns.png (renamed from src/pkg/image/png/testdata/pngsuite/basn3p08-trns.png)bin1538 -> 1538 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn3p08-trns.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn3p08-trns.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn3p08.png (renamed from src/pkg/image/png/testdata/pngsuite/basn3p08.png)bin1286 -> 1286 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn3p08.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn3p08.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn4a08.png (renamed from src/pkg/image/png/testdata/pngsuite/basn4a08.png)bin126 -> 126 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn4a08.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn4a08.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn4a16.png (renamed from src/pkg/image/png/testdata/pngsuite/basn4a16.png)bin2206 -> 2206 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn4a16.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn4a16.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn6a08.png (renamed from src/pkg/image/png/testdata/pngsuite/basn6a08.png)bin184 -> 184 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn6a08.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn6a08.sng)0
-rw-r--r--src/image/png/testdata/pngsuite/basn6a16.png (renamed from src/pkg/image/png/testdata/pngsuite/basn6a16.png)bin3435 -> 3435 bytes
-rw-r--r--src/image/png/testdata/pngsuite/basn6a16.sng (renamed from src/pkg/image/png/testdata/pngsuite/basn6a16.sng)0
-rw-r--r--src/image/png/writer.go (renamed from src/pkg/image/png/writer.go)62
-rw-r--r--src/image/png/writer_test.go (renamed from src/pkg/image/png/writer_test.go)29
-rw-r--r--src/image/testdata/video-001.5bpp.gif (renamed from src/pkg/image/testdata/video-001.5bpp.gif)bin6214 -> 6214 bytes
-rw-r--r--src/image/testdata/video-001.gif (renamed from src/pkg/image/testdata/video-001.gif)bin13106 -> 13106 bytes
-rw-r--r--src/image/testdata/video-001.interlaced.gif (renamed from src/pkg/image/testdata/video-001.interlaced.gif)bin14142 -> 14142 bytes
-rw-r--r--src/image/testdata/video-001.jpeg (renamed from src/pkg/image/testdata/video-001.jpeg)bin21459 -> 21459 bytes
-rw-r--r--src/image/testdata/video-001.png (renamed from src/pkg/image/testdata/video-001.png)bin29228 -> 29228 bytes
-rw-r--r--src/image/testdata/video-001.progressive.jpeg (renamed from src/pkg/image/testdata/video-001.progressive.jpeg)bin20732 -> 20732 bytes
-rw-r--r--src/image/testdata/video-001.q50.420.jpeg (renamed from src/pkg/image/testdata/video-001.q50.420.jpeg)bin3407 -> 3407 bytes
-rw-r--r--src/image/testdata/video-001.q50.420.progressive.jpeg (renamed from src/pkg/image/testdata/video-001.q50.420.progressive.jpeg)bin3279 -> 3279 bytes
-rw-r--r--src/image/testdata/video-001.q50.422.jpeg (renamed from src/pkg/image/testdata/video-001.q50.422.jpeg)bin3608 -> 3608 bytes
-rw-r--r--src/image/testdata/video-001.q50.422.progressive.jpeg (renamed from src/pkg/image/testdata/video-001.q50.422.progressive.jpeg)bin3506 -> 3506 bytes
-rw-r--r--src/image/testdata/video-001.q50.440.jpeg (renamed from src/pkg/image/testdata/video-001.q50.440.jpeg)bin3662 -> 3662 bytes
-rw-r--r--src/image/testdata/video-001.q50.440.progressive.jpeg (renamed from src/pkg/image/testdata/video-001.q50.440.progressive.jpeg)bin3529 -> 3529 bytes
-rw-r--r--src/image/testdata/video-001.q50.444.jpeg (renamed from src/pkg/image/testdata/video-001.q50.444.jpeg)bin4032 -> 4032 bytes
-rw-r--r--src/image/testdata/video-001.q50.444.progressive.jpeg (renamed from src/pkg/image/testdata/video-001.q50.444.progressive.jpeg)bin3935 -> 3935 bytes
-rw-r--r--src/image/testdata/video-001.separate.dc.progression.jpeg (renamed from src/pkg/image/testdata/video-001.separate.dc.progression.jpeg)bin14288 -> 14288 bytes
-rw-r--r--src/image/testdata/video-001.separate.dc.progression.progressive.jpeg (renamed from src/pkg/image/testdata/video-001.separate.dc.progression.progressive.jpeg)bin14312 -> 14312 bytes
-rw-r--r--src/image/testdata/video-005.gray.gif (renamed from src/pkg/image/testdata/video-005.gray.gif)bin14505 -> 14505 bytes
-rw-r--r--src/image/testdata/video-005.gray.jpeg (renamed from src/pkg/image/testdata/video-005.gray.jpeg)bin5618 -> 5618 bytes
-rw-r--r--src/image/testdata/video-005.gray.png (renamed from src/pkg/image/testdata/video-005.gray.png)bin14974 -> 14974 bytes
-rw-r--r--src/image/testdata/video-005.gray.q50.2x2.jpeg (renamed from src/pkg/image/testdata/video-005.gray.q50.2x2.jpeg)bin2782 -> 2782 bytes
-rw-r--r--src/image/testdata/video-005.gray.q50.2x2.progressive.jpeg (renamed from src/pkg/image/testdata/video-005.gray.q50.2x2.progressive.jpeg)bin2699 -> 2699 bytes
-rw-r--r--src/image/testdata/video-005.gray.q50.jpeg (renamed from src/pkg/image/testdata/video-005.gray.q50.jpeg)bin2782 -> 2782 bytes
-rw-r--r--src/image/testdata/video-005.gray.q50.progressive.jpeg (renamed from src/pkg/image/testdata/video-005.gray.q50.progressive.jpeg)bin2699 -> 2699 bytes
-rw-r--r--src/image/ycbcr.go (renamed from src/pkg/image/ycbcr.go)4
-rw-r--r--src/image/ycbcr_test.go (renamed from src/pkg/image/ycbcr_test.go)0
-rw-r--r--src/index/suffixarray/qsufsort.go (renamed from src/pkg/index/suffixarray/qsufsort.go)0
-rw-r--r--src/index/suffixarray/suffixarray.go (renamed from src/pkg/index/suffixarray/suffixarray.go)0
-rw-r--r--src/index/suffixarray/suffixarray_test.go (renamed from src/pkg/index/suffixarray/suffixarray_test.go)2
-rw-r--r--src/internal/syscall/getrandom_linux.go56
-rw-r--r--src/io/io.go (renamed from src/pkg/io/io.go)13
-rw-r--r--src/io/io_test.go (renamed from src/pkg/io/io_test.go)0
-rw-r--r--src/io/ioutil/ioutil.go (renamed from src/pkg/io/ioutil/ioutil.go)0
-rw-r--r--src/io/ioutil/ioutil_test.go (renamed from src/pkg/io/ioutil/ioutil_test.go)0
-rw-r--r--src/io/ioutil/tempfile.go (renamed from src/pkg/io/ioutil/tempfile.go)0
-rw-r--r--src/io/ioutil/tempfile_test.go (renamed from src/pkg/io/ioutil/tempfile_test.go)0
-rw-r--r--src/io/multi.go (renamed from src/pkg/io/multi.go)0
-rw-r--r--src/io/multi_test.go (renamed from src/pkg/io/multi_test.go)0
-rw-r--r--src/io/pipe.go (renamed from src/pkg/io/pipe.go)0
-rw-r--r--src/io/pipe_test.go (renamed from src/pkg/io/pipe_test.go)0
-rw-r--r--src/lib9/fmt/dofmt.c6
-rw-r--r--src/lib9/tempdir_windows.c19
-rw-r--r--src/liblink/asm5.c618
-rw-r--r--src/liblink/asm6.c1672
-rw-r--r--src/liblink/asm8.c1074
-rw-r--r--src/liblink/data.c2
-rw-r--r--src/liblink/ld.c36
-rw-r--r--src/liblink/list5.c17
-rw-r--r--src/liblink/list6.c2
-rw-r--r--src/liblink/list8.c2
-rw-r--r--src/liblink/obj5.c250
-rw-r--r--src/liblink/obj6.c263
-rw-r--r--src/liblink/obj8.c129
-rw-r--r--src/liblink/objfile.c78
-rw-r--r--src/liblink/pcln.c2
-rw-r--r--src/liblink/sym.c43
-rw-r--r--src/log/example_test.go (renamed from src/pkg/log/example_test.go)0
-rw-r--r--src/log/log.go (renamed from src/pkg/log/log.go)0
-rw-r--r--src/log/log_test.go (renamed from src/pkg/log/log_test.go)0
-rw-r--r--src/log/syslog/syslog.go (renamed from src/pkg/log/syslog/syslog.go)0
-rw-r--r--src/log/syslog/syslog_plan9.go (renamed from src/pkg/log/syslog/syslog_plan9.go)0
-rw-r--r--src/log/syslog/syslog_test.go (renamed from src/pkg/log/syslog/syslog_test.go)2
-rw-r--r--src/log/syslog/syslog_unix.go (renamed from src/pkg/log/syslog/syslog_unix.go)2
-rw-r--r--src/log/syslog/syslog_windows.go (renamed from src/pkg/log/syslog/syslog_windows.go)0
-rwxr-xr-xsrc/make.bash2
-rw-r--r--src/make.bat3
-rwxr-xr-xsrc/make.rc2
-rw-r--r--src/math/abs.go (renamed from src/pkg/math/abs.go)0
-rw-r--r--src/math/abs_386.s (renamed from src/pkg/math/abs_386.s)2
-rw-r--r--src/math/abs_amd64.s (renamed from src/pkg/math/abs_amd64.s)2
-rw-r--r--src/math/abs_amd64p32.s (renamed from src/pkg/math/abs_amd64p32.s)0
-rw-r--r--src/math/abs_arm.s (renamed from src/pkg/math/abs_arm.s)2
-rw-r--r--src/math/acosh.go (renamed from src/pkg/math/acosh.go)0
-rw-r--r--src/math/all_test.go (renamed from src/pkg/math/all_test.go)77
-rw-r--r--src/math/asin.go (renamed from src/pkg/math/asin.go)0
-rw-r--r--src/math/asin_386.s (renamed from src/pkg/math/asin_386.s)2
-rw-r--r--src/math/asin_amd64.s (renamed from src/pkg/math/asin_amd64.s)2
-rw-r--r--src/math/asin_amd64p32.s (renamed from src/pkg/math/asin_amd64p32.s)0
-rw-r--r--src/math/asin_arm.s (renamed from src/pkg/math/asin_arm.s)2
-rw-r--r--src/math/asinh.go (renamed from src/pkg/math/asinh.go)0
-rw-r--r--src/math/atan.go (renamed from src/pkg/math/atan.go)0
-rw-r--r--src/math/atan2.go (renamed from src/pkg/math/atan2.go)0
-rw-r--r--src/math/atan2_386.s (renamed from src/pkg/math/atan2_386.s)2
-rw-r--r--src/math/atan2_amd64.s (renamed from src/pkg/math/atan2_amd64.s)2
-rw-r--r--src/math/atan2_amd64p32.s (renamed from src/pkg/math/atan2_amd64p32.s)0
-rw-r--r--src/math/atan2_arm.s (renamed from src/pkg/math/atan2_arm.s)2
-rw-r--r--src/math/atan_386.s (renamed from src/pkg/math/atan_386.s)2
-rw-r--r--src/math/atan_amd64.s (renamed from src/pkg/math/atan_amd64.s)2
-rw-r--r--src/math/atan_amd64p32.s (renamed from src/pkg/math/atan_amd64p32.s)0
-rw-r--r--src/math/atan_arm.s (renamed from src/pkg/math/atan_arm.s)2
-rw-r--r--src/math/atanh.go (renamed from src/pkg/math/atanh.go)0
-rw-r--r--src/math/big/arith.go (renamed from src/pkg/math/big/arith.go)0
-rw-r--r--src/math/big/arith_386.s (renamed from src/pkg/math/big/arith_386.s)2
-rw-r--r--src/math/big/arith_amd64.s (renamed from src/pkg/math/big/arith_amd64.s)2
-rw-r--r--src/math/big/arith_amd64p32.s (renamed from src/pkg/math/big/arith_amd64p32.s)2
-rw-r--r--src/math/big/arith_arm.s (renamed from src/pkg/math/big/arith_arm.s)2
-rw-r--r--src/math/big/arith_decl.go (renamed from src/pkg/math/big/arith_decl.go)0
-rw-r--r--src/math/big/arith_test.go (renamed from src/pkg/math/big/arith_test.go)0
-rw-r--r--src/math/big/calibrate_test.go (renamed from src/pkg/math/big/calibrate_test.go)0
-rw-r--r--src/math/big/example_test.go (renamed from src/pkg/math/big/example_test.go)0
-rw-r--r--src/math/big/gcd_test.go (renamed from src/pkg/math/big/gcd_test.go)0
-rw-r--r--src/math/big/hilbert_test.go (renamed from src/pkg/math/big/hilbert_test.go)0
-rw-r--r--src/math/big/int.go (renamed from src/pkg/math/big/int.go)56
-rw-r--r--src/math/big/int_test.go (renamed from src/pkg/math/big/int_test.go)50
-rw-r--r--src/math/big/nat.go (renamed from src/pkg/math/big/nat.go)0
-rw-r--r--src/math/big/nat_test.go (renamed from src/pkg/math/big/nat_test.go)0
-rw-r--r--src/math/big/rat.go (renamed from src/pkg/math/big/rat.go)184
-rw-r--r--src/math/big/rat_test.go (renamed from src/pkg/math/big/rat_test.go)196
-rw-r--r--src/math/bits.go (renamed from src/pkg/math/bits.go)0
-rw-r--r--src/math/cbrt.go (renamed from src/pkg/math/cbrt.go)0
-rw-r--r--src/math/cmplx/abs.go (renamed from src/pkg/math/cmplx/abs.go)0
-rw-r--r--src/math/cmplx/asin.go (renamed from src/pkg/math/cmplx/asin.go)0
-rw-r--r--src/math/cmplx/cmath_test.go (renamed from src/pkg/math/cmplx/cmath_test.go)0
-rw-r--r--src/math/cmplx/conj.go (renamed from src/pkg/math/cmplx/conj.go)0
-rw-r--r--src/math/cmplx/exp.go (renamed from src/pkg/math/cmplx/exp.go)0
-rw-r--r--src/math/cmplx/isinf.go (renamed from src/pkg/math/cmplx/isinf.go)0
-rw-r--r--src/math/cmplx/isnan.go (renamed from src/pkg/math/cmplx/isnan.go)0
-rw-r--r--src/math/cmplx/log.go (renamed from src/pkg/math/cmplx/log.go)0
-rw-r--r--src/math/cmplx/phase.go (renamed from src/pkg/math/cmplx/phase.go)0
-rw-r--r--src/math/cmplx/polar.go (renamed from src/pkg/math/cmplx/polar.go)0
-rw-r--r--src/math/cmplx/pow.go (renamed from src/pkg/math/cmplx/pow.go)0
-rw-r--r--src/math/cmplx/rect.go (renamed from src/pkg/math/cmplx/rect.go)0
-rw-r--r--src/math/cmplx/sin.go (renamed from src/pkg/math/cmplx/sin.go)0
-rw-r--r--src/math/cmplx/sqrt.go (renamed from src/pkg/math/cmplx/sqrt.go)0
-rw-r--r--src/math/cmplx/tan.go (renamed from src/pkg/math/cmplx/tan.go)0
-rw-r--r--src/math/const.go (renamed from src/pkg/math/const.go)0
-rw-r--r--src/math/copysign.go (renamed from src/pkg/math/copysign.go)0
-rw-r--r--src/math/dim.go (renamed from src/pkg/math/dim.go)0
-rw-r--r--src/math/dim_386.s (renamed from src/pkg/math/dim_386.s)2
-rw-r--r--src/math/dim_amd64.s (renamed from src/pkg/math/dim_amd64.s)2
-rw-r--r--src/math/dim_amd64p32.s (renamed from src/pkg/math/dim_amd64p32.s)0
-rw-r--r--src/math/dim_arm.s (renamed from src/pkg/math/dim_arm.s)2
-rw-r--r--src/math/erf.go (renamed from src/pkg/math/erf.go)0
-rw-r--r--src/math/exp.go (renamed from src/pkg/math/exp.go)0
-rw-r--r--src/math/exp2_386.s (renamed from src/pkg/math/exp2_386.s)2
-rw-r--r--src/math/exp2_amd64.s (renamed from src/pkg/math/exp2_amd64.s)2
-rw-r--r--src/math/exp2_amd64p32.s (renamed from src/pkg/math/exp2_amd64p32.s)0
-rw-r--r--src/math/exp2_arm.s (renamed from src/pkg/math/exp2_arm.s)2
-rw-r--r--src/math/exp_386.s (renamed from src/pkg/math/exp_386.s)2
-rw-r--r--src/math/exp_amd64.s (renamed from src/pkg/math/exp_amd64.s)2
-rw-r--r--src/math/exp_amd64p32.s (renamed from src/pkg/math/exp_amd64p32.s)0
-rw-r--r--src/math/exp_arm.s (renamed from src/pkg/math/exp_arm.s)2
-rw-r--r--src/math/expm1.go (renamed from src/pkg/math/expm1.go)0
-rw-r--r--src/math/expm1_386.s (renamed from src/pkg/math/expm1_386.s)2
-rw-r--r--src/math/expm1_amd64.s (renamed from src/pkg/math/expm1_amd64.s)2
-rw-r--r--src/math/expm1_amd64p32.s (renamed from src/pkg/math/expm1_amd64p32.s)0
-rw-r--r--src/math/expm1_arm.s (renamed from src/pkg/math/expm1_arm.s)2
-rw-r--r--src/math/export_test.go (renamed from src/pkg/math/export_test.go)0
-rw-r--r--src/math/floor.go (renamed from src/pkg/math/floor.go)0
-rw-r--r--src/math/floor_386.s (renamed from src/pkg/math/floor_386.s)2
-rw-r--r--src/math/floor_amd64.s (renamed from src/pkg/math/floor_amd64.s)2
-rw-r--r--src/math/floor_amd64p32.s (renamed from src/pkg/math/floor_amd64p32.s)0
-rw-r--r--src/math/floor_arm.s (renamed from src/pkg/math/floor_arm.s)2
-rw-r--r--src/math/frexp.go (renamed from src/pkg/math/frexp.go)0
-rw-r--r--src/math/frexp_386.s (renamed from src/pkg/math/frexp_386.s)2
-rw-r--r--src/math/frexp_amd64.s (renamed from src/pkg/math/frexp_amd64.s)2
-rw-r--r--src/math/frexp_amd64p32.s (renamed from src/pkg/math/frexp_amd64p32.s)0
-rw-r--r--src/math/frexp_arm.s (renamed from src/pkg/math/frexp_arm.s)2
-rw-r--r--src/math/gamma.go (renamed from src/pkg/math/gamma.go)0
-rw-r--r--src/math/hypot.go (renamed from src/pkg/math/hypot.go)0
-rw-r--r--src/math/hypot_386.s (renamed from src/pkg/math/hypot_386.s)2
-rw-r--r--src/math/hypot_amd64.s (renamed from src/pkg/math/hypot_amd64.s)2
-rw-r--r--src/math/hypot_amd64p32.s (renamed from src/pkg/math/hypot_amd64p32.s)0
-rw-r--r--src/math/hypot_arm.s (renamed from src/pkg/math/hypot_arm.s)2
-rw-r--r--src/math/j0.go (renamed from src/pkg/math/j0.go)0
-rw-r--r--src/math/j1.go (renamed from src/pkg/math/j1.go)0
-rw-r--r--src/math/jn.go (renamed from src/pkg/math/jn.go)0
-rw-r--r--src/math/ldexp.go (renamed from src/pkg/math/ldexp.go)0
-rw-r--r--src/math/ldexp_386.s (renamed from src/pkg/math/ldexp_386.s)2
-rw-r--r--src/math/ldexp_amd64.s (renamed from src/pkg/math/ldexp_amd64.s)2
-rw-r--r--src/math/ldexp_amd64p32.s (renamed from src/pkg/math/ldexp_amd64p32.s)0
-rw-r--r--src/math/ldexp_arm.s (renamed from src/pkg/math/ldexp_arm.s)2
-rw-r--r--src/math/lgamma.go (renamed from src/pkg/math/lgamma.go)0
-rw-r--r--src/math/log.go (renamed from src/pkg/math/log.go)0
-rw-r--r--src/math/log10.go (renamed from src/pkg/math/log10.go)0
-rw-r--r--src/math/log10_386.s (renamed from src/pkg/math/log10_386.s)2
-rw-r--r--src/math/log10_amd64.s (renamed from src/pkg/math/log10_amd64.s)2
-rw-r--r--src/math/log10_amd64p32.s (renamed from src/pkg/math/log10_amd64p32.s)0
-rw-r--r--src/math/log10_arm.s (renamed from src/pkg/math/log10_arm.s)2
-rw-r--r--src/math/log1p.go (renamed from src/pkg/math/log1p.go)0
-rw-r--r--src/math/log1p_386.s (renamed from src/pkg/math/log1p_386.s)2
-rw-r--r--src/math/log1p_amd64.s (renamed from src/pkg/math/log1p_amd64.s)2
-rw-r--r--src/math/log1p_amd64p32.s (renamed from src/pkg/math/log1p_amd64p32.s)0
-rw-r--r--src/math/log1p_arm.s (renamed from src/pkg/math/log1p_arm.s)2
-rw-r--r--src/math/log_386.s (renamed from src/pkg/math/log_386.s)2
-rw-r--r--src/math/log_amd64.s (renamed from src/pkg/math/log_amd64.s)2
-rw-r--r--src/math/log_amd64p32.s (renamed from src/pkg/math/log_amd64p32.s)0
-rw-r--r--src/math/log_arm.s (renamed from src/pkg/math/log_arm.s)2
-rw-r--r--src/math/logb.go (renamed from src/pkg/math/logb.go)0
-rw-r--r--src/math/mod.go (renamed from src/pkg/math/mod.go)0
-rw-r--r--src/math/mod_386.s (renamed from src/pkg/math/mod_386.s)2
-rw-r--r--src/math/mod_amd64.s (renamed from src/pkg/math/mod_amd64.s)2
-rw-r--r--src/math/mod_amd64p32.s (renamed from src/pkg/math/mod_amd64p32.s)0
-rw-r--r--src/math/mod_arm.s (renamed from src/pkg/math/mod_arm.s)2
-rw-r--r--src/math/modf.go (renamed from src/pkg/math/modf.go)0
-rw-r--r--src/math/modf_386.s (renamed from src/pkg/math/modf_386.s)2
-rw-r--r--src/math/modf_amd64.s (renamed from src/pkg/math/modf_amd64.s)2
-rw-r--r--src/math/modf_amd64p32.s (renamed from src/pkg/math/modf_amd64p32.s)0
-rw-r--r--src/math/modf_arm.s (renamed from src/pkg/math/modf_arm.s)2
-rw-r--r--src/math/nextafter.go47
-rw-r--r--src/math/pow.go (renamed from src/pkg/math/pow.go)0
-rw-r--r--src/math/pow10.go (renamed from src/pkg/math/pow10.go)0
-rw-r--r--src/math/rand/example_test.go (renamed from src/pkg/math/rand/example_test.go)0
-rw-r--r--src/math/rand/exp.go (renamed from src/pkg/math/rand/exp.go)0
-rw-r--r--src/math/rand/normal.go (renamed from src/pkg/math/rand/normal.go)0
-rw-r--r--src/math/rand/rand.go (renamed from src/pkg/math/rand/rand.go)0
-rw-r--r--src/math/rand/rand_test.go (renamed from src/pkg/math/rand/rand_test.go)0
-rw-r--r--src/math/rand/regress_test.go (renamed from src/pkg/math/rand/regress_test.go)0
-rw-r--r--src/math/rand/rng.go (renamed from src/pkg/math/rand/rng.go)0
-rw-r--r--src/math/rand/zipf.go (renamed from src/pkg/math/rand/zipf.go)0
-rw-r--r--src/math/remainder.go (renamed from src/pkg/math/remainder.go)0
-rw-r--r--src/math/remainder_386.s (renamed from src/pkg/math/remainder_386.s)2
-rw-r--r--src/math/remainder_amd64.s (renamed from src/pkg/math/remainder_amd64.s)2
-rw-r--r--src/math/remainder_amd64p32.s (renamed from src/pkg/math/remainder_amd64p32.s)0
-rw-r--r--src/math/remainder_arm.s (renamed from src/pkg/math/remainder_arm.s)2
-rw-r--r--src/math/signbit.go (renamed from src/pkg/math/signbit.go)0
-rw-r--r--src/math/sin.go (renamed from src/pkg/math/sin.go)0
-rw-r--r--src/math/sin_386.s (renamed from src/pkg/math/sin_386.s)2
-rw-r--r--src/math/sin_amd64.s (renamed from src/pkg/math/sin_amd64.s)2
-rw-r--r--src/math/sin_amd64p32.s (renamed from src/pkg/math/sin_amd64p32.s)0
-rw-r--r--src/math/sin_arm.s (renamed from src/pkg/math/sin_arm.s)2
-rw-r--r--src/math/sincos.go (renamed from src/pkg/math/sincos.go)0
-rw-r--r--src/math/sincos_386.s (renamed from src/pkg/math/sincos_386.s)2
-rw-r--r--src/math/sincos_amd64.s (renamed from src/pkg/math/sincos_amd64.s)15
-rw-r--r--src/math/sincos_amd64p32.s (renamed from src/pkg/math/sincos_amd64p32.s)0
-rw-r--r--src/math/sincos_arm.s (renamed from src/pkg/math/sincos_arm.s)2
-rw-r--r--src/math/sinh.go (renamed from src/pkg/math/sinh.go)0
-rw-r--r--src/math/sqrt.go (renamed from src/pkg/math/sqrt.go)2
-rw-r--r--src/math/sqrt_386.s (renamed from src/pkg/math/sqrt_386.s)2
-rw-r--r--src/math/sqrt_amd64.s (renamed from src/pkg/math/sqrt_amd64.s)2
-rw-r--r--src/math/sqrt_amd64p32.s (renamed from src/pkg/math/sqrt_amd64p32.s)0
-rw-r--r--src/math/sqrt_arm.s (renamed from src/pkg/math/sqrt_arm.s)2
-rw-r--r--src/math/tan.go (renamed from src/pkg/math/tan.go)0
-rw-r--r--src/math/tan_386.s (renamed from src/pkg/math/tan_386.s)2
-rw-r--r--src/math/tan_amd64.s (renamed from src/pkg/math/tan_amd64.s)2
-rw-r--r--src/math/tan_amd64p32.s (renamed from src/pkg/math/tan_amd64p32.s)0
-rw-r--r--src/math/tan_arm.s (renamed from src/pkg/math/tan_arm.s)2
-rw-r--r--src/math/tanh.go (renamed from src/pkg/math/tanh.go)0
-rw-r--r--src/math/unsafe.go (renamed from src/pkg/math/unsafe.go)0
-rw-r--r--src/mime/grammar.go (renamed from src/pkg/mime/grammar.go)0
-rw-r--r--src/mime/mediatype.go (renamed from src/pkg/mime/mediatype.go)0
-rw-r--r--src/mime/mediatype_test.go (renamed from src/pkg/mime/mediatype_test.go)0
-rw-r--r--src/mime/multipart/example_test.go (renamed from src/pkg/mime/multipart/example_test.go)2
-rw-r--r--src/mime/multipart/formdata.go (renamed from src/pkg/mime/multipart/formdata.go)0
-rw-r--r--src/mime/multipart/formdata_test.go (renamed from src/pkg/mime/multipart/formdata_test.go)0
-rw-r--r--src/mime/multipart/multipart.go (renamed from src/pkg/mime/multipart/multipart.go)3
-rw-r--r--src/mime/multipart/multipart_test.go (renamed from src/pkg/mime/multipart/multipart_test.go)0
-rw-r--r--src/mime/multipart/quotedprintable.go (renamed from src/pkg/mime/multipart/quotedprintable.go)0
-rw-r--r--src/mime/multipart/quotedprintable_test.go (renamed from src/pkg/mime/multipart/quotedprintable_test.go)0
-rw-r--r--src/mime/multipart/testdata/nested-mime (renamed from src/pkg/mime/multipart/testdata/nested-mime)0
-rw-r--r--src/mime/multipart/writer.go (renamed from src/pkg/mime/multipart/writer.go)0
-rw-r--r--src/mime/multipart/writer_test.go (renamed from src/pkg/mime/multipart/writer_test.go)15
-rw-r--r--src/mime/testdata/test.types (renamed from src/pkg/mime/testdata/test.types)0
-rw-r--r--src/mime/testdata/test.types.plan9 (renamed from src/pkg/mime/testdata/test.types.plan9)0
-rw-r--r--src/mime/type.go121
-rw-r--r--src/mime/type_plan9.go (renamed from src/pkg/mime/type_plan9.go)2
-rw-r--r--src/mime/type_test.go54
-rw-r--r--src/mime/type_unix.go (renamed from src/pkg/mime/type_unix.go)2
-rw-r--r--src/mime/type_windows.go (renamed from src/pkg/mime/type_windows.go)2
-rwxr-xr-xsrc/nacltest.bash31
-rw-r--r--src/net/cgo_android.go14
-rw-r--r--src/net/cgo_bsd.go (renamed from src/pkg/net/cgo_bsd.go)0
-rw-r--r--src/net/cgo_linux.go (renamed from src/pkg/net/cgo_linux.go)2
-rw-r--r--src/net/cgo_netbsd.go (renamed from src/pkg/net/cgo_netbsd.go)0
-rw-r--r--src/net/cgo_openbsd.go (renamed from src/pkg/net/cgo_openbsd.go)0
-rw-r--r--src/net/cgo_stub.go (renamed from src/pkg/net/cgo_stub.go)0
-rw-r--r--src/net/cgo_unix.go (renamed from src/pkg/net/cgo_unix.go)0
-rw-r--r--src/net/cgo_unix_test.go (renamed from src/pkg/net/cgo_unix_test.go)0
-rw-r--r--src/net/conn_test.go (renamed from src/pkg/net/conn_test.go)2
-rw-r--r--src/net/dial.go (renamed from src/pkg/net/dial.go)17
-rw-r--r--src/net/dial_gen.go (renamed from src/pkg/net/dial_gen.go)0
-rw-r--r--src/net/dial_gen_test.go (renamed from src/pkg/net/dial_gen_test.go)0
-rw-r--r--src/net/dial_test.go (renamed from src/pkg/net/dial_test.go)16
-rw-r--r--src/net/dialgoogle_test.go (renamed from src/pkg/net/dialgoogle_test.go)0
-rw-r--r--src/net/dnsclient.go (renamed from src/pkg/net/dnsclient.go)4
-rw-r--r--src/net/dnsclient_test.go (renamed from src/pkg/net/dnsclient_test.go)0
-rw-r--r--src/net/dnsclient_unix.go (renamed from src/pkg/net/dnsclient_unix.go)293
-rw-r--r--src/net/dnsclient_unix_test.go (renamed from src/pkg/net/dnsclient_unix_test.go)109
-rw-r--r--src/net/dnsconfig_unix.go (renamed from src/pkg/net/dnsconfig_unix.go)39
-rw-r--r--src/net/dnsconfig_unix_test.go69
-rw-r--r--src/net/dnsmsg.go (renamed from src/pkg/net/dnsmsg.go)0
-rw-r--r--src/net/dnsmsg_test.go (renamed from src/pkg/net/dnsmsg_test.go)0
-rw-r--r--src/net/dnsname_test.go (renamed from src/pkg/net/dnsname_test.go)0
-rw-r--r--src/net/example_test.go (renamed from src/pkg/net/example_test.go)0
-rw-r--r--src/net/fd_mutex.go (renamed from src/pkg/net/fd_mutex.go)0
-rw-r--r--src/net/fd_mutex_test.go (renamed from src/pkg/net/fd_mutex_test.go)0
-rw-r--r--src/net/fd_plan9.go (renamed from src/pkg/net/fd_plan9.go)0
-rw-r--r--src/net/fd_poll_nacl.go (renamed from src/pkg/net/fd_poll_nacl.go)0
-rw-r--r--src/net/fd_poll_runtime.go (renamed from src/pkg/net/fd_poll_runtime.go)0
-rw-r--r--src/net/fd_unix.go (renamed from src/pkg/net/fd_unix.go)4
-rw-r--r--src/net/fd_unix_test.go (renamed from src/pkg/net/fd_unix_test.go)0
-rw-r--r--src/net/fd_windows.go (renamed from src/pkg/net/fd_windows.go)20
-rw-r--r--src/net/file_plan9.go (renamed from src/pkg/net/file_plan9.go)0
-rw-r--r--src/net/file_stub.go38
-rw-r--r--src/net/file_test.go (renamed from src/pkg/net/file_test.go)2
-rw-r--r--src/net/file_unix.go (renamed from src/pkg/net/file_unix.go)2
-rw-r--r--src/net/file_windows.go (renamed from src/pkg/net/file_windows.go)0
-rw-r--r--src/net/hosts.go (renamed from src/pkg/net/hosts.go)2
-rw-r--r--src/net/hosts_test.go (renamed from src/pkg/net/hosts_test.go)0
-rw-r--r--src/net/http/cgi/child.go (renamed from src/pkg/net/http/cgi/child.go)0
-rw-r--r--src/net/http/cgi/child_test.go (renamed from src/pkg/net/http/cgi/child_test.go)0
-rw-r--r--src/net/http/cgi/host.go (renamed from src/pkg/net/http/cgi/host.go)0
-rw-r--r--src/net/http/cgi/host_test.go (renamed from src/pkg/net/http/cgi/host_test.go)0
-rw-r--r--src/net/http/cgi/matryoshka_test.go (renamed from src/pkg/net/http/cgi/matryoshka_test.go)0
-rw-r--r--src/net/http/cgi/plan9_test.go (renamed from src/pkg/net/http/cgi/plan9_test.go)0
-rw-r--r--src/net/http/cgi/posix_test.go (renamed from src/pkg/net/http/cgi/posix_test.go)0
-rwxr-xr-xsrc/net/http/cgi/testdata/test.cgi (renamed from src/pkg/net/http/cgi/testdata/test.cgi)0
-rw-r--r--src/net/http/client.go (renamed from src/pkg/net/http/client.go)28
-rw-r--r--src/net/http/client_test.go (renamed from src/pkg/net/http/client_test.go)37
-rw-r--r--src/net/http/cookie.go (renamed from src/pkg/net/http/cookie.go)10
-rw-r--r--src/net/http/cookie_test.go (renamed from src/pkg/net/http/cookie_test.go)32
-rw-r--r--src/net/http/cookiejar/jar.go (renamed from src/pkg/net/http/cookiejar/jar.go)2
-rw-r--r--src/net/http/cookiejar/jar_test.go (renamed from src/pkg/net/http/cookiejar/jar_test.go)0
-rw-r--r--src/net/http/cookiejar/punycode.go (renamed from src/pkg/net/http/cookiejar/punycode.go)0
-rw-r--r--src/net/http/cookiejar/punycode_test.go (renamed from src/pkg/net/http/cookiejar/punycode_test.go)0
-rw-r--r--src/net/http/doc.go (renamed from src/pkg/net/http/doc.go)0
-rw-r--r--src/net/http/example_test.go (renamed from src/pkg/net/http/example_test.go)0
-rw-r--r--src/net/http/export_test.go (renamed from src/pkg/net/http/export_test.go)36
-rw-r--r--src/net/http/fcgi/child.go (renamed from src/pkg/net/http/fcgi/child.go)0
-rw-r--r--src/net/http/fcgi/fcgi.go (renamed from src/pkg/net/http/fcgi/fcgi.go)0
-rw-r--r--src/net/http/fcgi/fcgi_test.go (renamed from src/pkg/net/http/fcgi/fcgi_test.go)0
-rw-r--r--src/net/http/filetransport.go (renamed from src/pkg/net/http/filetransport.go)0
-rw-r--r--src/net/http/filetransport_test.go (renamed from src/pkg/net/http/filetransport_test.go)0
-rw-r--r--src/net/http/fs.go (renamed from src/pkg/net/http/fs.go)43
-rw-r--r--src/net/http/fs_test.go (renamed from src/pkg/net/http/fs_test.go)59
-rw-r--r--src/net/http/header.go (renamed from src/pkg/net/http/header.go)0
-rw-r--r--src/net/http/header_test.go (renamed from src/pkg/net/http/header_test.go)0
-rw-r--r--src/net/http/httptest/example_test.go (renamed from src/pkg/net/http/httptest/example_test.go)0
-rw-r--r--src/net/http/httptest/recorder.go (renamed from src/pkg/net/http/httptest/recorder.go)0
-rw-r--r--src/net/http/httptest/recorder_test.go (renamed from src/pkg/net/http/httptest/recorder_test.go)0
-rw-r--r--src/net/http/httptest/server.go (renamed from src/pkg/net/http/httptest/server.go)2
-rw-r--r--src/net/http/httptest/server_test.go (renamed from src/pkg/net/http/httptest/server_test.go)24
-rw-r--r--src/net/http/httputil/dump.go (renamed from src/pkg/net/http/httputil/dump.go)12
-rw-r--r--src/net/http/httputil/dump_test.go (renamed from src/pkg/net/http/httputil/dump_test.go)30
-rw-r--r--src/net/http/httputil/httputil.go (renamed from src/pkg/net/http/httputil/httputil.go)13
-rw-r--r--src/net/http/httputil/persist.go (renamed from src/pkg/net/http/httputil/persist.go)0
-rw-r--r--src/net/http/httputil/reverseproxy.go (renamed from src/pkg/net/http/httputil/reverseproxy.go)16
-rw-r--r--src/net/http/httputil/reverseproxy_test.go (renamed from src/pkg/net/http/httputil/reverseproxy_test.go)0
-rw-r--r--src/net/http/internal/chunked.go (renamed from src/pkg/net/http/chunked.go)19
-rw-r--r--src/net/http/internal/chunked_test.go (renamed from src/pkg/net/http/chunked_test.go)23
-rw-r--r--src/net/http/jar.go (renamed from src/pkg/net/http/jar.go)0
-rw-r--r--src/net/http/lex.go (renamed from src/pkg/net/http/lex.go)0
-rw-r--r--src/net/http/lex_test.go (renamed from src/pkg/net/http/lex_test.go)0
-rw-r--r--src/net/http/main_test.go (renamed from src/pkg/net/http/z_last_test.go)30
-rw-r--r--src/net/http/npn_test.go (renamed from src/pkg/net/http/npn_test.go)0
-rw-r--r--src/net/http/pprof/pprof.go (renamed from src/pkg/net/http/pprof/pprof.go)4
-rw-r--r--src/net/http/proxy_test.go (renamed from src/pkg/net/http/proxy_test.go)0
-rw-r--r--src/net/http/race.go (renamed from src/pkg/net/http/race.go)0
-rw-r--r--src/net/http/range_test.go (renamed from src/pkg/net/http/range_test.go)0
-rw-r--r--src/net/http/readrequest_test.go (renamed from src/pkg/net/http/readrequest_test.go)41
-rw-r--r--src/net/http/request.go (renamed from src/pkg/net/http/request.go)60
-rw-r--r--src/net/http/request_test.go (renamed from src/pkg/net/http/request_test.go)70
-rw-r--r--src/net/http/requestwrite_test.go (renamed from src/pkg/net/http/requestwrite_test.go)62
-rw-r--r--src/net/http/response.go (renamed from src/pkg/net/http/response.go)0
-rw-r--r--src/net/http/response_test.go (renamed from src/pkg/net/http/response_test.go)31
-rw-r--r--src/net/http/responsewrite_test.go (renamed from src/pkg/net/http/responsewrite_test.go)0
-rw-r--r--src/net/http/serve_test.go (renamed from src/pkg/net/http/serve_test.go)270
-rw-r--r--src/net/http/server.go (renamed from src/pkg/net/http/server.go)78
-rw-r--r--src/net/http/sniff.go (renamed from src/pkg/net/http/sniff.go)0
-rw-r--r--src/net/http/sniff_test.go (renamed from src/pkg/net/http/sniff_test.go)0
-rw-r--r--src/net/http/status.go (renamed from src/pkg/net/http/status.go)0
-rw-r--r--src/net/http/testdata/file (renamed from src/pkg/net/http/testdata/file)0
-rw-r--r--src/net/http/testdata/index.html (renamed from src/pkg/net/http/testdata/index.html)0
-rw-r--r--src/net/http/testdata/style.css (renamed from src/pkg/net/http/testdata/style.css)0
-rw-r--r--src/net/http/transfer.go (renamed from src/pkg/net/http/transfer.go)19
-rw-r--r--src/net/http/transfer_test.go (renamed from src/pkg/net/http/transfer_test.go)0
-rw-r--r--src/net/http/transport.go (renamed from src/pkg/net/http/transport.go)139
-rw-r--r--src/net/http/transport_test.go (renamed from src/pkg/net/http/transport_test.go)187
-rw-r--r--src/net/http/triv.go (renamed from src/pkg/net/http/triv.go)0
-rw-r--r--src/net/interface.go (renamed from src/pkg/net/interface.go)0
-rw-r--r--src/net/interface_bsd.go (renamed from src/pkg/net/interface_bsd.go)0
-rw-r--r--src/net/interface_bsd_test.go (renamed from src/pkg/net/interface_bsd_test.go)0
-rw-r--r--src/net/interface_darwin.go (renamed from src/pkg/net/interface_darwin.go)0
-rw-r--r--src/net/interface_dragonfly.go (renamed from src/pkg/net/interface_dragonfly.go)0
-rw-r--r--src/net/interface_freebsd.go (renamed from src/pkg/net/interface_freebsd.go)0
-rw-r--r--src/net/interface_linux.go (renamed from src/pkg/net/interface_linux.go)0
-rw-r--r--src/net/interface_linux_test.go (renamed from src/pkg/net/interface_linux_test.go)0
-rw-r--r--src/net/interface_netbsd.go (renamed from src/pkg/net/interface_netbsd.go)0
-rw-r--r--src/net/interface_openbsd.go (renamed from src/pkg/net/interface_openbsd.go)0
-rw-r--r--src/net/interface_stub.go (renamed from src/pkg/net/interface_stub.go)0
-rw-r--r--src/net/interface_test.go (renamed from src/pkg/net/interface_test.go)0
-rw-r--r--src/net/interface_unix_test.go (renamed from src/pkg/net/interface_unix_test.go)0
-rw-r--r--src/net/interface_windows.go (renamed from src/pkg/net/interface_windows.go)0
-rw-r--r--src/net/ip.go (renamed from src/pkg/net/ip.go)38
-rw-r--r--src/net/ip_test.go (renamed from src/pkg/net/ip_test.go)26
-rw-r--r--src/net/ipraw_test.go (renamed from src/pkg/net/ipraw_test.go)5
-rw-r--r--src/net/iprawsock.go (renamed from src/pkg/net/iprawsock.go)0
-rw-r--r--src/net/iprawsock_plan9.go (renamed from src/pkg/net/iprawsock_plan9.go)0
-rw-r--r--src/net/iprawsock_posix.go (renamed from src/pkg/net/iprawsock_posix.go)4
-rw-r--r--src/net/ipsock.go (renamed from src/pkg/net/ipsock.go)0
-rw-r--r--src/net/ipsock_plan9.go (renamed from src/pkg/net/ipsock_plan9.go)0
-rw-r--r--src/net/ipsock_posix.go (renamed from src/pkg/net/ipsock_posix.go)4
-rw-r--r--src/net/ipsock_test.go (renamed from src/pkg/net/ipsock_test.go)0
-rw-r--r--src/net/lookup.go (renamed from src/pkg/net/lookup.go)51
-rw-r--r--src/net/lookup_plan9.go (renamed from src/pkg/net/lookup_plan9.go)0
-rw-r--r--src/net/lookup_stub.go49
-rw-r--r--src/net/lookup_test.go231
-rw-r--r--src/net/lookup_unix.go (renamed from src/pkg/net/lookup_unix.go)2
-rw-r--r--src/net/lookup_windows.go (renamed from src/pkg/net/lookup_windows.go)79
-rw-r--r--src/net/lookup_windows_test.go243
-rw-r--r--src/net/mac.go (renamed from src/pkg/net/mac.go)0
-rw-r--r--src/net/mac_test.go (renamed from src/pkg/net/mac_test.go)0
-rw-r--r--src/net/mail/message.go (renamed from src/pkg/net/mail/message.go)13
-rw-r--r--src/net/mail/message_test.go (renamed from src/pkg/net/mail/message_test.go)10
-rw-r--r--src/net/mockicmp_test.go (renamed from src/pkg/net/mockicmp_test.go)0
-rw-r--r--src/net/mockserver_test.go (renamed from src/pkg/net/mockserver_test.go)0
-rw-r--r--src/net/multicast_test.go (renamed from src/pkg/net/multicast_test.go)2
-rw-r--r--src/net/net.go (renamed from src/pkg/net/net.go)1
-rw-r--r--src/net/net_test.go (renamed from src/pkg/net/net_test.go)0
-rw-r--r--src/net/net_windows_test.go (renamed from src/pkg/net/net_windows_test.go)0
-rw-r--r--src/net/netgo_unix_test.go (renamed from src/pkg/net/netgo_unix_test.go)0
-rw-r--r--src/net/packetconn_test.go (renamed from src/pkg/net/packetconn_test.go)0
-rw-r--r--src/net/parse.go (renamed from src/pkg/net/parse.go)22
-rw-r--r--src/net/parse_test.go (renamed from src/pkg/net/parse_test.go)4
-rw-r--r--src/net/pipe.go (renamed from src/pkg/net/pipe.go)0
-rw-r--r--src/net/pipe_test.go (renamed from src/pkg/net/pipe_test.go)0
-rw-r--r--src/net/port.go (renamed from src/pkg/net/port.go)0
-rw-r--r--src/net/port_test.go (renamed from src/pkg/net/port_test.go)6
-rw-r--r--src/net/port_unix.go (renamed from src/pkg/net/port_unix.go)2
-rw-r--r--src/net/protoconn_test.go (renamed from src/pkg/net/protoconn_test.go)0
-rw-r--r--src/net/race.go (renamed from src/pkg/net/race.go)0
-rw-r--r--src/net/race0.go (renamed from src/pkg/net/race0.go)0
-rw-r--r--src/net/rpc/client.go (renamed from src/pkg/net/rpc/client.go)12
-rw-r--r--src/net/rpc/client_test.go91
-rw-r--r--src/net/rpc/debug.go (renamed from src/pkg/net/rpc/debug.go)2
-rw-r--r--src/net/rpc/jsonrpc/all_test.go (renamed from src/pkg/net/rpc/jsonrpc/all_test.go)0
-rw-r--r--src/net/rpc/jsonrpc/client.go (renamed from src/pkg/net/rpc/jsonrpc/client.go)0
-rw-r--r--src/net/rpc/jsonrpc/server.go (renamed from src/pkg/net/rpc/jsonrpc/server.go)0
-rw-r--r--src/net/rpc/server.go (renamed from src/pkg/net/rpc/server.go)25
-rw-r--r--src/net/rpc/server_test.go (renamed from src/pkg/net/rpc/server_test.go)0
-rw-r--r--src/net/sendfile_dragonfly.go (renamed from src/pkg/net/sendfile_dragonfly.go)0
-rw-r--r--src/net/sendfile_freebsd.go (renamed from src/pkg/net/sendfile_freebsd.go)0
-rw-r--r--src/net/sendfile_linux.go (renamed from src/pkg/net/sendfile_linux.go)0
-rw-r--r--src/net/sendfile_stub.go (renamed from src/pkg/net/sendfile_stub.go)0
-rw-r--r--src/net/sendfile_windows.go (renamed from src/pkg/net/sendfile_windows.go)0
-rw-r--r--src/net/server_test.go (renamed from src/pkg/net/server_test.go)0
-rw-r--r--src/net/singleflight.go109
-rw-r--r--src/net/smtp/auth.go (renamed from src/pkg/net/smtp/auth.go)0
-rw-r--r--src/net/smtp/example_test.go (renamed from src/pkg/net/smtp/example_test.go)0
-rw-r--r--src/net/smtp/smtp.go (renamed from src/pkg/net/smtp/smtp.go)0
-rw-r--r--src/net/smtp/smtp_test.go (renamed from src/pkg/net/smtp/smtp_test.go)2
-rw-r--r--src/net/sock_bsd.go (renamed from src/pkg/net/sock_bsd.go)2
-rw-r--r--src/net/sock_cloexec.go (renamed from src/pkg/net/sock_cloexec.go)0
-rw-r--r--src/net/sock_linux.go (renamed from src/pkg/net/sock_linux.go)0
-rw-r--r--src/net/sock_plan9.go (renamed from src/pkg/net/sock_plan9.go)0
-rw-r--r--src/net/sock_posix.go (renamed from src/pkg/net/sock_posix.go)46
-rw-r--r--src/net/sock_stub.go (renamed from src/pkg/net/sock_solaris.go)2
-rw-r--r--src/net/sock_windows.go (renamed from src/pkg/net/sock_windows.go)0
-rw-r--r--src/net/sockopt_bsd.go (renamed from src/pkg/net/sockopt_bsd.go)4
-rw-r--r--src/net/sockopt_linux.go (renamed from src/pkg/net/sockopt_linux.go)0
-rw-r--r--src/net/sockopt_plan9.go (renamed from src/pkg/net/sockopt_plan9.go)0
-rw-r--r--src/net/sockopt_posix.go (renamed from src/pkg/net/sockopt_posix.go)2
-rw-r--r--src/net/sockopt_solaris.go (renamed from src/pkg/net/sockopt_solaris.go)0
-rw-r--r--src/net/sockopt_stub.go37
-rw-r--r--src/net/sockopt_windows.go (renamed from src/pkg/net/sockopt_windows.go)0
-rw-r--r--src/net/sockoptip_bsd.go (renamed from src/pkg/net/sockoptip_bsd.go)2
-rw-r--r--src/net/sockoptip_linux.go (renamed from src/pkg/net/sockoptip_linux.go)0
-rw-r--r--src/net/sockoptip_posix.go (renamed from src/pkg/net/sockoptip_posix.go)2
-rw-r--r--src/net/sockoptip_stub.go (renamed from src/pkg/net/sockoptip_stub.go)14
-rw-r--r--src/net/sockoptip_windows.go (renamed from src/pkg/net/sockoptip_windows.go)0
-rw-r--r--src/net/sys_cloexec.go (renamed from src/pkg/net/sys_cloexec.go)0
-rw-r--r--src/net/tcp_test.go (renamed from src/pkg/net/tcp_test.go)0
-rw-r--r--src/net/tcpsock.go (renamed from src/pkg/net/tcpsock.go)0
-rw-r--r--src/net/tcpsock_plan9.go (renamed from src/pkg/net/tcpsock_plan9.go)0
-rw-r--r--src/net/tcpsock_posix.go (renamed from src/pkg/net/tcpsock_posix.go)8
-rw-r--r--src/net/tcpsockopt_darwin.go (renamed from src/pkg/net/tcpsockopt_darwin.go)12
-rw-r--r--src/net/tcpsockopt_dragonfly.go (renamed from src/pkg/net/tcpsockopt_dragonfly.go)13
-rw-r--r--src/net/tcpsockopt_openbsd.go16
-rw-r--r--src/net/tcpsockopt_plan9.go (renamed from src/pkg/net/tcpsockopt_plan9.go)0
-rw-r--r--src/net/tcpsockopt_posix.go (renamed from src/pkg/net/tcpsockopt_posix.go)2
-rw-r--r--src/net/tcpsockopt_stub.go20
-rw-r--r--src/net/tcpsockopt_unix.go (renamed from src/pkg/net/tcpsockopt_unix.go)10
-rw-r--r--src/net/tcpsockopt_windows.go (renamed from src/pkg/net/tcpsockopt_windows.go)12
-rw-r--r--src/net/testdata/domain-resolv.conf5
-rw-r--r--src/net/testdata/empty-resolv.conf1
-rw-r--r--src/net/testdata/hosts (renamed from src/pkg/net/testdata/hosts)0
-rw-r--r--src/net/testdata/hosts_singleline (renamed from src/pkg/net/testdata/hosts_singleline)0
-rw-r--r--src/net/testdata/igmp (renamed from src/pkg/net/testdata/igmp)0
-rw-r--r--src/net/testdata/igmp6 (renamed from src/pkg/net/testdata/igmp6)0
-rw-r--r--src/net/testdata/resolv.conf8
-rw-r--r--src/net/testdata/search-resolv.conf5
-rw-r--r--src/net/textproto/header.go (renamed from src/pkg/net/textproto/header.go)0
-rw-r--r--src/net/textproto/pipeline.go (renamed from src/pkg/net/textproto/pipeline.go)0
-rw-r--r--src/net/textproto/reader.go (renamed from src/pkg/net/textproto/reader.go)0
-rw-r--r--src/net/textproto/reader_test.go (renamed from src/pkg/net/textproto/reader_test.go)0
-rw-r--r--src/net/textproto/textproto.go (renamed from src/pkg/net/textproto/textproto.go)0
-rw-r--r--src/net/textproto/writer.go (renamed from src/pkg/net/textproto/writer.go)0
-rw-r--r--src/net/textproto/writer_test.go (renamed from src/pkg/net/textproto/writer_test.go)0
-rw-r--r--src/net/timeout_test.go (renamed from src/pkg/net/timeout_test.go)0
-rw-r--r--src/net/udp_test.go (renamed from src/pkg/net/udp_test.go)41
-rw-r--r--src/net/udpsock.go (renamed from src/pkg/net/udpsock.go)0
-rw-r--r--src/net/udpsock_plan9.go (renamed from src/pkg/net/udpsock_plan9.go)0
-rw-r--r--src/net/udpsock_posix.go (renamed from src/pkg/net/udpsock_posix.go)6
-rw-r--r--src/net/unicast_posix_test.go (renamed from src/pkg/net/unicast_posix_test.go)3
-rw-r--r--src/net/unix_test.go (renamed from src/pkg/net/unix_test.go)15
-rw-r--r--src/net/unixsock.go (renamed from src/pkg/net/unixsock.go)0
-rw-r--r--src/net/unixsock_plan9.go (renamed from src/pkg/net/unixsock_plan9.go)0
-rw-r--r--src/net/unixsock_posix.go (renamed from src/pkg/net/unixsock_posix.go)15
-rw-r--r--src/net/url/example_test.go (renamed from src/pkg/net/url/example_test.go)30
-rw-r--r--src/net/url/url.go (renamed from src/pkg/net/url/url.go)29
-rw-r--r--src/net/url/url_test.go (renamed from src/pkg/net/url/url_test.go)56
-rw-r--r--src/net/z_last_test.go99
-rw-r--r--src/os/dir_plan9.go (renamed from src/pkg/os/dir_plan9.go)0
-rw-r--r--src/os/dir_unix.go (renamed from src/pkg/os/dir_unix.go)2
-rw-r--r--src/os/dir_windows.go (renamed from src/pkg/os/dir_windows.go)0
-rw-r--r--src/os/doc.go (renamed from src/pkg/os/doc.go)0
-rw-r--r--src/os/env.go (renamed from src/pkg/os/env.go)5
-rw-r--r--src/os/env_test.go (renamed from src/pkg/os/env_test.go)26
-rw-r--r--src/os/env_unix_test.go (renamed from src/pkg/os/env_unix_test.go)0
-rw-r--r--src/os/error.go (renamed from src/pkg/os/error.go)0
-rw-r--r--src/os/error_plan9.go (renamed from src/pkg/os/error_plan9.go)3
-rw-r--r--src/os/error_test.go (renamed from src/pkg/os/error_test.go)0
-rw-r--r--src/os/error_unix.go (renamed from src/pkg/os/error_unix.go)0
-rw-r--r--src/os/error_windows.go (renamed from src/pkg/os/error_windows.go)0
-rw-r--r--src/os/error_windows_test.go (renamed from src/pkg/os/error_windows_test.go)0
-rw-r--r--src/os/exec.go (renamed from src/pkg/os/exec.go)0
-rw-r--r--src/os/exec/example_test.go (renamed from src/pkg/os/exec/example_test.go)0
-rw-r--r--src/os/exec/exec.go (renamed from src/pkg/os/exec/exec.go)13
-rw-r--r--src/os/exec/exec_test.go (renamed from src/pkg/os/exec/exec_test.go)17
-rw-r--r--src/os/exec/lp_plan9.go (renamed from src/pkg/os/exec/lp_plan9.go)0
-rw-r--r--src/os/exec/lp_test.go (renamed from src/pkg/os/exec/lp_test.go)0
-rw-r--r--src/os/exec/lp_unix.go (renamed from src/pkg/os/exec/lp_unix.go)0
-rw-r--r--src/os/exec/lp_unix_test.go (renamed from src/pkg/os/exec/lp_unix_test.go)0
-rw-r--r--src/os/exec/lp_windows.go (renamed from src/pkg/os/exec/lp_windows.go)0
-rw-r--r--src/os/exec/lp_windows_test.go (renamed from src/pkg/os/exec/lp_windows_test.go)0
-rw-r--r--src/os/exec_plan9.go (renamed from src/pkg/os/exec_plan9.go)0
-rw-r--r--src/os/exec_posix.go (renamed from src/pkg/os/exec_posix.go)0
-rw-r--r--src/os/exec_unix.go (renamed from src/pkg/os/exec_unix.go)14
-rw-r--r--src/os/exec_windows.go (renamed from src/pkg/os/exec_windows.go)3
-rw-r--r--src/os/export_test.go (renamed from src/pkg/os/export_test.go)0
-rw-r--r--src/os/file.go (renamed from src/pkg/os/file.go)9
-rw-r--r--src/os/file_plan9.go (renamed from src/pkg/os/file_plan9.go)11
-rw-r--r--src/os/file_posix.go (renamed from src/pkg/os/file_posix.go)22
-rw-r--r--src/os/file_unix.go (renamed from src/pkg/os/file_unix.go)35
-rw-r--r--src/os/file_windows.go (renamed from src/pkg/os/file_windows.go)109
-rw-r--r--src/os/getwd.go (renamed from src/pkg/os/getwd.go)24
-rw-r--r--src/os/getwd_darwin.go (renamed from src/pkg/os/getwd_darwin.go)0
-rw-r--r--src/os/os_test.go (renamed from src/pkg/os/os_test.go)195
-rw-r--r--src/os/os_unix_test.go (renamed from src/pkg/os/os_unix_test.go)0
-rw-r--r--src/os/os_windows_test.go81
-rw-r--r--src/os/path.go (renamed from src/pkg/os/path.go)16
-rw-r--r--src/os/path_plan9.go (renamed from src/pkg/os/path_plan9.go)0
-rw-r--r--src/os/path_test.go (renamed from src/pkg/os/path_test.go)11
-rw-r--r--src/os/path_unix.go (renamed from src/pkg/os/path_unix.go)0
-rw-r--r--src/os/path_windows.go (renamed from src/pkg/os/path_windows.go)0
-rw-r--r--src/os/pipe_bsd.go (renamed from src/pkg/os/pipe_bsd.go)0
-rw-r--r--src/os/pipe_linux.go (renamed from src/pkg/os/pipe_linux.go)0
-rw-r--r--src/os/proc.go (renamed from src/pkg/os/proc.go)15
-rw-r--r--src/os/signal/example_test.go (renamed from src/pkg/os/signal/example_test.go)0
-rw-r--r--src/os/signal/sig.s (renamed from src/pkg/os/signal/sig.s)2
-rw-r--r--src/os/signal/signal.go (renamed from src/pkg/os/signal/signal.go)0
-rw-r--r--src/os/signal/signal_stub.go (renamed from src/pkg/os/signal/signal_stub.go)0
-rw-r--r--src/os/signal/signal_test.go (renamed from src/pkg/os/signal/signal_test.go)6
-rw-r--r--src/os/signal/signal_unix.go (renamed from src/pkg/os/signal/signal_unix.go)0
-rw-r--r--src/os/signal/signal_windows_test.go (renamed from src/pkg/os/signal/signal_windows_test.go)0
-rw-r--r--src/os/stat_darwin.go (renamed from src/pkg/os/stat_darwin.go)0
-rw-r--r--src/os/stat_dragonfly.go (renamed from src/pkg/os/stat_dragonfly.go)0
-rw-r--r--src/os/stat_freebsd.go (renamed from src/pkg/os/stat_freebsd.go)0
-rw-r--r--src/os/stat_linux.go (renamed from src/pkg/os/stat_linux.go)0
-rw-r--r--src/os/stat_nacl.go (renamed from src/pkg/os/stat_nacl.go)0
-rw-r--r--src/os/stat_netbsd.go (renamed from src/pkg/os/stat_netbsd.go)0
-rw-r--r--src/os/stat_openbsd.go (renamed from src/pkg/os/stat_openbsd.go)0
-rw-r--r--src/os/stat_plan9.go (renamed from src/pkg/os/stat_plan9.go)0
-rw-r--r--src/os/stat_solaris.go (renamed from src/pkg/os/stat_solaris.go)0
-rw-r--r--src/os/stat_windows.go (renamed from src/pkg/os/stat_windows.go)56
-rw-r--r--src/os/str.go (renamed from src/pkg/os/str.go)0
-rw-r--r--src/os/sys_bsd.go (renamed from src/pkg/os/sys_bsd.go)0
-rw-r--r--src/os/sys_darwin.go (renamed from src/pkg/os/sys_darwin.go)0
-rw-r--r--src/os/sys_freebsd.go (renamed from src/pkg/os/sys_freebsd.go)0
-rw-r--r--src/os/sys_linux.go (renamed from src/pkg/os/sys_linux.go)0
-rw-r--r--src/os/sys_nacl.go (renamed from src/pkg/os/sys_nacl.go)0
-rw-r--r--src/os/sys_plan9.go (renamed from src/pkg/os/sys_plan9.go)0
-rw-r--r--src/os/sys_solaris.go (renamed from src/pkg/os/sys_solaris.go)0
-rw-r--r--src/os/sys_unix.go (renamed from src/pkg/os/sys_unix.go)0
-rw-r--r--src/os/sys_windows.go (renamed from src/pkg/os/sys_windows.go)0
-rw-r--r--src/os/types.go (renamed from src/pkg/os/types.go)0
-rw-r--r--src/os/types_notwin.go (renamed from src/pkg/os/types_notwin.go)0
-rw-r--r--src/os/types_windows.go (renamed from src/pkg/os/types_windows.go)3
-rw-r--r--src/os/user/lookup.go (renamed from src/pkg/os/user/lookup.go)0
-rw-r--r--src/os/user/lookup_plan9.go (renamed from src/pkg/os/user/lookup_plan9.go)0
-rw-r--r--src/os/user/lookup_stubs.go (renamed from src/pkg/os/user/lookup_stubs.go)2
-rw-r--r--src/os/user/lookup_unix.go (renamed from src/pkg/os/user/lookup_unix.go)2
-rw-r--r--src/os/user/lookup_windows.go (renamed from src/pkg/os/user/lookup_windows.go)0
-rw-r--r--src/os/user/user.go (renamed from src/pkg/os/user/user.go)0
-rw-r--r--src/os/user/user_test.go (renamed from src/pkg/os/user/user_test.go)0
-rw-r--r--src/path/example_test.go (renamed from src/pkg/path/example_test.go)0
-rw-r--r--src/path/filepath/example_unix_test.go (renamed from src/pkg/path/filepath/example_unix_test.go)0
-rw-r--r--src/path/filepath/export_test.go (renamed from src/pkg/path/filepath/export_test.go)0
-rw-r--r--src/path/filepath/match.go (renamed from src/pkg/path/filepath/match.go)8
-rw-r--r--src/path/filepath/match_test.go (renamed from src/pkg/path/filepath/match_test.go)7
-rw-r--r--src/path/filepath/path.go (renamed from src/pkg/path/filepath/path.go)11
-rw-r--r--src/path/filepath/path_plan9.go (renamed from src/pkg/path/filepath/path_plan9.go)4
-rw-r--r--src/path/filepath/path_test.go (renamed from src/pkg/path/filepath/path_test.go)33
-rw-r--r--src/path/filepath/path_unix.go (renamed from src/pkg/path/filepath/path_unix.go)4
-rw-r--r--src/path/filepath/path_windows.go (renamed from src/pkg/path/filepath/path_windows.go)5
-rw-r--r--src/path/filepath/path_windows_test.go (renamed from src/pkg/path/filepath/path_windows_test.go)20
-rw-r--r--src/path/filepath/symlink.go (renamed from src/pkg/path/filepath/symlink.go)19
-rw-r--r--src/path/filepath/symlink_unix.go7
-rw-r--r--src/path/filepath/symlink_windows.go (renamed from src/pkg/path/filepath/symlink_windows.go)5
-rw-r--r--src/path/match.go (renamed from src/pkg/path/match.go)0
-rw-r--r--src/path/match_test.go (renamed from src/pkg/path/match_test.go)0
-rw-r--r--src/path/path.go (renamed from src/pkg/path/path.go)10
-rw-r--r--src/path/path_test.go (renamed from src/pkg/path/path_test.go)0
-rw-r--r--src/pkg/bytes/bytes.s5
-rw-r--r--src/pkg/compress/bzip2/move_to_front.go98
-rw-r--r--src/pkg/crypto/cipher/cfb_test.go38
-rw-r--r--src/pkg/debug/pe/testdata/gcc-amd64-mingw-execbin37376 -> 0 bytes
-rw-r--r--src/pkg/encoding/gob/timing_test.go109
-rw-r--r--src/pkg/go/format/format.go199
-rw-r--r--src/pkg/image/color/palette/gen.go101
-rw-r--r--src/pkg/image/jpeg/huffman.go219
-rw-r--r--src/pkg/math/nextafter.go27
-rw-r--r--src/pkg/mime/type.go77
-rw-r--r--src/pkg/mime/type_test.go29
-rw-r--r--src/pkg/net/dnsconfig_unix_test.go46
-rw-r--r--src/pkg/net/empty.c8
-rw-r--r--src/pkg/net/http/httputil/chunked.go203
-rw-r--r--src/pkg/net/http/httputil/chunked_test.go159
-rw-r--r--src/pkg/net/lookup_test.go137
-rw-r--r--src/pkg/net/rpc/client_test.go36
-rw-r--r--src/pkg/net/singleflight.go53
-rw-r--r--src/pkg/net/tcpsockopt_openbsd.go27
-rw-r--r--src/pkg/net/tcpsockopt_solaris.go27
-rw-r--r--src/pkg/net/testdata/resolv.conf6
-rw-r--r--src/pkg/net/z_last_test.go37
-rw-r--r--src/pkg/reflect/export_test.go19
-rw-r--r--src/pkg/runtime/alg.goc549
-rw-r--r--src/pkg/runtime/atomic_arm.c169
-rw-r--r--src/pkg/runtime/callback_windows.c77
-rw-r--r--src/pkg/runtime/chan.goc1155
-rw-r--r--src/pkg/runtime/complex.goc58
-rw-r--r--src/pkg/runtime/cpuprof.goc433
-rw-r--r--src/pkg/runtime/debug.go172
-rw-r--r--src/pkg/runtime/env_plan9.c42
-rw-r--r--src/pkg/runtime/env_posix.c73
-rw-r--r--src/pkg/runtime/export_test.go92
-rw-r--r--src/pkg/runtime/funcdata.h24
-rw-r--r--src/pkg/runtime/hashmap.goc1078
-rw-r--r--src/pkg/runtime/hashmap.h147
-rw-r--r--src/pkg/runtime/hashmap_fast.c233
-rw-r--r--src/pkg/runtime/iface.goc620
-rw-r--r--src/pkg/runtime/lock_futex.c201
-rw-r--r--src/pkg/runtime/lock_sema.c266
-rw-r--r--src/pkg/runtime/malloc.goc939
-rw-r--r--src/pkg/runtime/malloc1.go26
-rw-r--r--src/pkg/runtime/mallocrand.go93
-rw-r--r--src/pkg/runtime/mallocrep.go72
-rw-r--r--src/pkg/runtime/mallocrep1.go144
-rw-r--r--src/pkg/runtime/memclr_plan9_amd64.s48
-rw-r--r--src/pkg/runtime/mgc0.c2892
-rw-r--r--src/pkg/runtime/mgc0.go27
-rw-r--r--src/pkg/runtime/mgc0.h87
-rw-r--r--src/pkg/runtime/mprof.goc527
-rw-r--r--src/pkg/runtime/netpoll.goc467
-rw-r--r--src/pkg/runtime/netpoll_epoll.c102
-rw-r--r--src/pkg/runtime/netpoll_kqueue.c111
-rw-r--r--src/pkg/runtime/netpoll_nacl.c37
-rw-r--r--src/pkg/runtime/noasm_arm.goc74
-rw-r--r--src/pkg/runtime/os_solaris.h51
-rw-r--r--src/pkg/runtime/os_windows_386.c138
-rw-r--r--src/pkg/runtime/os_windows_amd64.c144
-rw-r--r--src/pkg/runtime/panic.c566
-rw-r--r--src/pkg/runtime/print.c393
-rw-r--r--src/pkg/runtime/race.go31
-rw-r--r--src/pkg/runtime/race/race_darwin_amd64.sysobin222964 -> 0 bytes
-rw-r--r--src/pkg/runtime/race/race_linux_amd64.sysobin243208 -> 0 bytes
-rw-r--r--src/pkg/runtime/race/race_windows_amd64.sysobin210859 -> 0 bytes
-rw-r--r--src/pkg/runtime/race0.c124
-rw-r--r--src/pkg/runtime/rdebug.goc27
-rw-r--r--src/pkg/runtime/rt0_plan9_386.s42
-rw-r--r--src/pkg/runtime/rt0_plan9_amd64.s14
-rw-r--r--src/pkg/runtime/rune.c231
-rw-r--r--src/pkg/runtime/runtime1.goc128
-rw-r--r--src/pkg/runtime/sema.goc294
-rw-r--r--src/pkg/runtime/sigqueue.goc165
-rw-r--r--src/pkg/runtime/slice.goc204
-rw-r--r--src/pkg/runtime/stack.c947
-rw-r--r--src/pkg/runtime/stack_gen_test.go1473
-rw-r--r--src/pkg/runtime/stack_test.go283
-rw-r--r--src/pkg/runtime/string.goc430
-rw-r--r--src/pkg/runtime/string_test.go77
-rw-r--r--src/pkg/runtime/symtab.goc332
-rw-r--r--src/pkg/runtime/syscall_solaris.goc374
-rw-r--r--src/pkg/runtime/syscall_windows.goc145
-rw-r--r--src/pkg/runtime/time.goc344
-rw-r--r--src/pkg/runtime/time_plan9_386.c36
-rw-r--r--src/pkg/runtime/traceback_arm.c357
-rw-r--r--src/pkg/runtime/traceback_x86.c430
-rw-r--r--src/pkg/runtime/type.go56
-rw-r--r--src/pkg/runtime/vlrt_arm.c807
-rw-r--r--src/pkg/sync/atomic/race.go276
-rw-r--r--src/pkg/syscall/asm_windows_386.s7
-rw-r--r--src/pkg/syscall/asm_windows_amd64.s7
-rw-r--r--src/pkg/syscall/mkall_windows.bat21
-rw-r--r--src/pkg/syscall/syscall_plan9_386.go32
-rw-r--r--src/pkg/syscall/syscall_plan9_amd64.go14
-rw-r--r--src/pkg/syscall/zsyscall_windows_386.go1760
-rw-r--r--src/pkg/syscall/zsysnum_plan9_386.go47
-rw-r--r--src/pkg/syscall/zsysnum_plan9_amd64.go48
-rw-r--r--src/pkg/time/Makefile9
-rw-r--r--src/pkg/time/internal_test.go92
-rw-r--r--src/pkg/unicode/Makefile16
-rwxr-xr-xsrc/race.bash7
-rw-r--r--src/reflect/all_test.go (renamed from src/pkg/reflect/all_test.go)337
-rw-r--r--src/reflect/asm_386.s (renamed from src/pkg/reflect/asm_386.s)5
-rw-r--r--src/reflect/asm_amd64.s (renamed from src/pkg/reflect/asm_amd64.s)9
-rw-r--r--src/reflect/asm_amd64p32.s (renamed from src/pkg/reflect/asm_amd64p32.s)5
-rw-r--r--src/reflect/asm_arm.s (renamed from src/pkg/reflect/asm_arm.s)5
-rw-r--r--src/reflect/deepequal.go (renamed from src/pkg/reflect/deepequal.go)0
-rw-r--r--src/reflect/example_test.go (renamed from src/pkg/reflect/example_test.go)0
-rw-r--r--src/reflect/export_test.go38
-rw-r--r--src/reflect/makefunc.go (renamed from src/pkg/reflect/makefunc.go)25
-rw-r--r--src/reflect/set_test.go (renamed from src/pkg/reflect/set_test.go)0
-rw-r--r--src/reflect/tostring_test.go (renamed from src/pkg/reflect/tostring_test.go)0
-rw-r--r--src/reflect/type.go (renamed from src/pkg/reflect/type.go)557
-rw-r--r--src/reflect/value.go (renamed from src/pkg/reflect/value.go)639
-rw-r--r--src/regexp/all_test.go (renamed from src/pkg/regexp/all_test.go)15
-rw-r--r--src/regexp/example_test.go (renamed from src/pkg/regexp/example_test.go)0
-rw-r--r--src/regexp/exec.go (renamed from src/pkg/regexp/exec.go)0
-rw-r--r--src/regexp/exec2_test.go (renamed from src/pkg/regexp/exec2_test.go)0
-rw-r--r--src/regexp/exec_test.go (renamed from src/pkg/regexp/exec_test.go)0
-rw-r--r--src/regexp/find_test.go (renamed from src/pkg/regexp/find_test.go)0
-rw-r--r--src/regexp/onepass.go (renamed from src/pkg/regexp/onepass.go)7
-rw-r--r--src/regexp/onepass_test.go (renamed from src/pkg/regexp/onepass_test.go)0
-rw-r--r--src/regexp/regexp.go (renamed from src/pkg/regexp/regexp.go)2
-rw-r--r--src/regexp/syntax/compile.go (renamed from src/pkg/regexp/syntax/compile.go)0
-rw-r--r--src/regexp/syntax/doc.go (renamed from src/pkg/regexp/syntax/doc.go)48
-rwxr-xr-xsrc/regexp/syntax/make_perl_groups.pl (renamed from src/pkg/regexp/syntax/make_perl_groups.pl)0
-rw-r--r--src/regexp/syntax/parse.go (renamed from src/pkg/regexp/syntax/parse.go)41
-rw-r--r--src/regexp/syntax/parse_test.go (renamed from src/pkg/regexp/syntax/parse_test.go)13
-rw-r--r--src/regexp/syntax/perl_groups.go (renamed from src/pkg/regexp/syntax/perl_groups.go)0
-rw-r--r--src/regexp/syntax/prog.go (renamed from src/pkg/regexp/syntax/prog.go)0
-rw-r--r--src/regexp/syntax/prog_test.go (renamed from src/pkg/regexp/syntax/prog_test.go)0
-rw-r--r--src/regexp/syntax/regexp.go (renamed from src/pkg/regexp/syntax/regexp.go)2
-rw-r--r--src/regexp/syntax/simplify.go (renamed from src/pkg/regexp/syntax/simplify.go)0
-rw-r--r--src/regexp/syntax/simplify_test.go (renamed from src/pkg/regexp/syntax/simplify_test.go)0
-rw-r--r--src/regexp/testdata/README (renamed from src/pkg/regexp/testdata/README)0
-rw-r--r--src/regexp/testdata/basic.dat (renamed from src/pkg/regexp/testdata/basic.dat)0
-rw-r--r--src/regexp/testdata/nullsubexpr.dat (renamed from src/pkg/regexp/testdata/nullsubexpr.dat)0
-rw-r--r--src/regexp/testdata/re2-exhaustive.txt.bz2 (renamed from src/pkg/regexp/testdata/re2-exhaustive.txt.bz2)bin394016 -> 394016 bytes
-rw-r--r--src/regexp/testdata/re2-search.txt (renamed from src/pkg/regexp/testdata/re2-search.txt)0
-rw-r--r--src/regexp/testdata/repetition.dat (renamed from src/pkg/regexp/testdata/repetition.dat)0
-rw-r--r--src/regexp/testdata/testregex.c (renamed from src/pkg/regexp/testdata/testregex.c)0
-rwxr-xr-xsrc/run.bash65
-rwxr-xr-xsrc/run.rc2
-rw-r--r--src/runtime/Makefile (renamed from src/pkg/runtime/Makefile)2
-rw-r--r--src/runtime/alg.go352
-rw-r--r--src/runtime/append_test.go (renamed from src/pkg/runtime/append_test.go)0
-rw-r--r--src/runtime/arch_386.go (renamed from src/pkg/syscall/asm_solaris_amd64.s)7
-rw-r--r--src/runtime/arch_386.h (renamed from src/pkg/runtime/arch_386.h)3
-rw-r--r--src/runtime/arch_amd64.go8
-rw-r--r--src/runtime/arch_amd64.h (renamed from src/pkg/runtime/arch_amd64.h)7
-rw-r--r--src/runtime/arch_amd64p32.go8
-rw-r--r--src/runtime/arch_amd64p32.h (renamed from src/pkg/runtime/arch_amd64p32.h)3
-rw-r--r--src/runtime/arch_arm.go8
-rw-r--r--src/runtime/arch_arm.h (renamed from src/pkg/runtime/arch_arm.h)9
-rw-r--r--src/runtime/asm.s14
-rw-r--r--src/runtime/asm_386.s (renamed from src/pkg/runtime/asm_386.s)698
-rw-r--r--src/runtime/asm_amd64.s (renamed from src/pkg/runtime/asm_amd64.s)817
-rw-r--r--src/runtime/asm_amd64p32.s (renamed from src/pkg/runtime/asm_amd64p32.s)644
-rw-r--r--src/runtime/asm_arm.s (renamed from src/pkg/runtime/asm_arm.s)653
-rw-r--r--src/runtime/atomic.go51
-rw-r--r--src/runtime/atomic_386.c (renamed from src/pkg/runtime/atomic_386.c)2
-rw-r--r--src/runtime/atomic_amd64x.c (renamed from src/pkg/runtime/atomic_amd64x.c)2
-rw-r--r--src/runtime/atomic_arm.go155
-rw-r--r--src/runtime/cgo/asm_386.s (renamed from src/pkg/runtime/cgo/asm_386.s)2
-rw-r--r--src/runtime/cgo/asm_amd64.s (renamed from src/pkg/runtime/cgo/asm_amd64.s)2
-rw-r--r--src/runtime/cgo/asm_arm.s (renamed from src/pkg/runtime/cgo/asm_arm.s)10
-rw-r--r--src/runtime/cgo/asm_nacl_amd64p32.s (renamed from src/pkg/runtime/cgo/asm_nacl_amd64p32.s)2
-rw-r--r--src/runtime/cgo/callbacks.c (renamed from src/pkg/runtime/cgo/callbacks.c)35
-rw-r--r--src/runtime/cgo/cgo.go (renamed from src/pkg/runtime/cgo/cgo.go)10
-rw-r--r--src/runtime/cgo/dragonfly.c (renamed from src/pkg/runtime/cgo/dragonfly.c)6
-rw-r--r--src/runtime/cgo/freebsd.c (renamed from src/pkg/runtime/cgo/freebsd.c)6
-rw-r--r--src/runtime/cgo/gcc_386.S (renamed from src/pkg/runtime/cgo/gcc_386.S)0
-rw-r--r--src/runtime/cgo/gcc_amd64.S (renamed from src/pkg/runtime/cgo/gcc_amd64.S)0
-rw-r--r--src/runtime/cgo/gcc_android.c31
-rw-r--r--src/runtime/cgo/gcc_android_arm.c43
-rw-r--r--src/runtime/cgo/gcc_arm.S (renamed from src/pkg/runtime/cgo/gcc_arm.S)22
-rw-r--r--src/runtime/cgo/gcc_darwin_386.c (renamed from src/pkg/runtime/cgo/gcc_darwin_386.c)73
-rw-r--r--src/runtime/cgo/gcc_darwin_amd64.c (renamed from src/pkg/runtime/cgo/gcc_darwin_amd64.c)62
-rw-r--r--src/runtime/cgo/gcc_dragonfly_386.c (renamed from src/pkg/runtime/cgo/gcc_dragonfly_386.c)21
-rw-r--r--src/runtime/cgo/gcc_dragonfly_amd64.c (renamed from src/pkg/runtime/cgo/gcc_dragonfly_amd64.c)21
-rw-r--r--src/runtime/cgo/gcc_fatalf.c23
-rw-r--r--src/runtime/cgo/gcc_freebsd_386.c (renamed from src/pkg/runtime/cgo/gcc_freebsd_386.c)21
-rw-r--r--src/runtime/cgo/gcc_freebsd_amd64.c (renamed from src/pkg/runtime/cgo/gcc_freebsd_amd64.c)21
-rw-r--r--src/runtime/cgo/gcc_freebsd_arm.c (renamed from src/pkg/runtime/cgo/gcc_freebsd_arm.c)23
-rw-r--r--src/runtime/cgo/gcc_linux_386.c (renamed from src/pkg/runtime/cgo/gcc_linux_386.c)24
-rw-r--r--src/runtime/cgo/gcc_linux_amd64.c (renamed from src/pkg/runtime/cgo/gcc_linux_amd64.c)24
-rw-r--r--src/runtime/cgo/gcc_linux_arm.c (renamed from src/pkg/runtime/cgo/gcc_linux_arm.c)50
-rw-r--r--src/runtime/cgo/gcc_netbsd_386.c (renamed from src/pkg/runtime/cgo/gcc_netbsd_386.c)21
-rw-r--r--src/runtime/cgo/gcc_netbsd_amd64.c (renamed from src/pkg/runtime/cgo/gcc_netbsd_amd64.c)21
-rw-r--r--src/runtime/cgo/gcc_netbsd_arm.c (renamed from src/pkg/runtime/cgo/gcc_netbsd_arm.c)23
-rw-r--r--src/runtime/cgo/gcc_openbsd_386.c (renamed from src/pkg/runtime/cgo/gcc_openbsd_386.c)21
-rw-r--r--src/runtime/cgo/gcc_openbsd_amd64.c (renamed from src/pkg/runtime/cgo/gcc_openbsd_amd64.c)21
-rw-r--r--src/runtime/cgo/gcc_setenv.c (renamed from src/pkg/runtime/cgo/gcc_setenv.c)7
-rw-r--r--src/runtime/cgo/gcc_util.c (renamed from src/pkg/runtime/cgo/gcc_util.c)0
-rw-r--r--src/runtime/cgo/gcc_windows_386.c (renamed from src/pkg/runtime/cgo/gcc_windows_386.c)9
-rw-r--r--src/runtime/cgo/gcc_windows_amd64.c (renamed from src/pkg/runtime/cgo/gcc_windows_amd64.c)9
-rw-r--r--src/runtime/cgo/iscgo.c (renamed from src/pkg/runtime/cgo/iscgo.c)0
-rw-r--r--src/runtime/cgo/libcgo.h (renamed from src/pkg/runtime/cgo/libcgo.h)10
-rw-r--r--src/runtime/cgo/netbsd.c (renamed from src/pkg/runtime/cgo/netbsd.c)6
-rw-r--r--src/runtime/cgo/openbsd.c (renamed from src/pkg/runtime/cgo/openbsd.c)6
-rw-r--r--src/runtime/cgo/setenv.c (renamed from src/pkg/runtime/cgo/setenv.c)5
-rw-r--r--src/runtime/cgocall.go (renamed from src/pkg/runtime/cgocall.c)311
-rw-r--r--src/runtime/cgocall.h (renamed from src/pkg/runtime/cgocall.h)1
-rw-r--r--src/runtime/cgocallback.go40
-rw-r--r--src/runtime/chan.go655
-rw-r--r--src/runtime/chan.h (renamed from src/pkg/runtime/chan.h)29
-rw-r--r--src/runtime/chan_test.go (renamed from src/pkg/runtime/chan_test.go)119
-rw-r--r--src/runtime/closure_test.go (renamed from src/pkg/runtime/closure_test.go)0
-rw-r--r--src/runtime/compiler.go (renamed from src/pkg/runtime/compiler.go)0
-rw-r--r--src/runtime/complex.go52
-rw-r--r--src/runtime/complex_test.go (renamed from src/pkg/runtime/complex_test.go)0
-rw-r--r--src/runtime/cpuprof.go425
-rw-r--r--src/runtime/crash_cgo_test.go (renamed from src/pkg/runtime/crash_cgo_test.go)77
-rw-r--r--src/runtime/crash_test.go (renamed from src/pkg/runtime/crash_test.go)157
-rw-r--r--src/runtime/debug.go70
-rw-r--r--src/runtime/debug/debug.s (renamed from src/pkg/runtime/debug/debug.c)0
-rw-r--r--src/runtime/debug/garbage.go (renamed from src/pkg/runtime/debug/garbage.go)46
-rw-r--r--src/runtime/debug/garbage_test.go (renamed from src/pkg/runtime/debug/garbage_test.go)13
-rw-r--r--src/runtime/debug/heapdump_test.go (renamed from src/pkg/runtime/debug/heapdump_test.go)0
-rw-r--r--src/runtime/debug/stack.go (renamed from src/pkg/runtime/debug/stack.go)0
-rw-r--r--src/runtime/debug/stack_test.go (renamed from src/pkg/runtime/debug/stack_test.go)18
-rw-r--r--src/runtime/debug/stubs.go20
-rw-r--r--src/runtime/debug/stubs.s21
-rw-r--r--src/runtime/defs.c (renamed from src/pkg/runtime/defs.c)3
-rw-r--r--src/runtime/defs1_linux.go (renamed from src/pkg/runtime/defs1_linux.go)2
-rw-r--r--src/runtime/defs2_linux.go (renamed from src/pkg/runtime/defs2_linux.go)2
-rw-r--r--src/runtime/defs_android_arm.h3
-rw-r--r--src/runtime/defs_arm_linux.go (renamed from src/pkg/runtime/defs_arm_linux.go)2
-rw-r--r--src/runtime/defs_darwin.go (renamed from src/pkg/runtime/defs_darwin.go)0
-rw-r--r--src/runtime/defs_darwin_386.h (renamed from src/pkg/runtime/defs_darwin_386.h)8
-rw-r--r--src/runtime/defs_darwin_amd64.h (renamed from src/pkg/runtime/defs_darwin_amd64.h)8
-rw-r--r--src/runtime/defs_dragonfly.go (renamed from src/pkg/runtime/defs_dragonfly.go)2
-rw-r--r--src/runtime/defs_dragonfly_386.h (renamed from src/pkg/runtime/defs_dragonfly_386.h)8
-rw-r--r--src/runtime/defs_dragonfly_amd64.h (renamed from src/pkg/runtime/defs_dragonfly_amd64.h)8
-rw-r--r--src/runtime/defs_freebsd.go (renamed from src/pkg/runtime/defs_freebsd.go)2
-rw-r--r--src/runtime/defs_freebsd_386.h (renamed from src/pkg/runtime/defs_freebsd_386.h)8
-rw-r--r--src/runtime/defs_freebsd_amd64.h (renamed from src/pkg/runtime/defs_freebsd_amd64.h)8
-rw-r--r--src/runtime/defs_freebsd_arm.h (renamed from src/pkg/runtime/defs_freebsd_arm.h)8
-rw-r--r--src/runtime/defs_linux.go (renamed from src/pkg/runtime/defs_linux.go)1
-rw-r--r--src/runtime/defs_linux_386.h (renamed from src/pkg/runtime/defs_linux_386.h)12
-rw-r--r--src/runtime/defs_linux_amd64.h (renamed from src/pkg/runtime/defs_linux_amd64.h)12
-rw-r--r--src/runtime/defs_linux_arm.h (renamed from src/pkg/runtime/defs_linux_arm.h)14
-rw-r--r--src/runtime/defs_nacl_386.h (renamed from src/pkg/runtime/defs_nacl_386.h)0
-rw-r--r--src/runtime/defs_nacl_amd64p32.h (renamed from src/pkg/runtime/defs_nacl_amd64p32.h)2
-rw-r--r--src/runtime/defs_nacl_arm.h70
-rw-r--r--src/runtime/defs_netbsd.go (renamed from src/pkg/runtime/defs_netbsd.go)2
-rw-r--r--src/runtime/defs_netbsd_386.go (renamed from src/pkg/runtime/defs_netbsd_386.go)0
-rw-r--r--src/runtime/defs_netbsd_386.h (renamed from src/pkg/runtime/defs_netbsd_386.h)10
-rw-r--r--src/runtime/defs_netbsd_amd64.go (renamed from src/pkg/runtime/defs_netbsd_amd64.go)0
-rw-r--r--src/runtime/defs_netbsd_amd64.h (renamed from src/pkg/runtime/defs_netbsd_amd64.h)10
-rw-r--r--src/runtime/defs_netbsd_arm.go (renamed from src/pkg/runtime/defs_netbsd_arm.go)0
-rw-r--r--src/runtime/defs_netbsd_arm.h (renamed from src/pkg/runtime/defs_netbsd_arm.h)10
-rw-r--r--src/runtime/defs_openbsd.go (renamed from src/pkg/runtime/defs_openbsd.go)6
-rw-r--r--src/runtime/defs_openbsd_386.h (renamed from src/pkg/runtime/defs_openbsd_386.h)12
-rw-r--r--src/runtime/defs_openbsd_amd64.h (renamed from src/pkg/runtime/defs_openbsd_amd64.h)12
-rw-r--r--src/runtime/defs_plan9_386.h (renamed from src/pkg/runtime/defs_plan9_386.h)5
-rw-r--r--src/runtime/defs_plan9_amd64.h (renamed from src/pkg/runtime/defs_plan9_amd64.h)2
-rw-r--r--src/runtime/defs_solaris.go (renamed from src/pkg/runtime/defs_solaris.go)2
-rw-r--r--src/runtime/defs_solaris_amd64.go (renamed from src/pkg/runtime/defs_solaris_amd64.go)0
-rw-r--r--src/runtime/defs_solaris_amd64.h (renamed from src/pkg/runtime/defs_solaris_amd64.h)8
-rw-r--r--src/runtime/defs_windows.go (renamed from src/pkg/runtime/defs_windows.go)3
-rw-r--r--src/runtime/defs_windows_386.h (renamed from src/pkg/runtime/defs_windows_386.h)3
-rw-r--r--src/runtime/defs_windows_amd64.h (renamed from src/pkg/runtime/defs_windows_amd64.h)3
-rw-r--r--src/runtime/env_plan9.go56
-rw-r--r--src/runtime/env_posix.go63
-rw-r--r--src/runtime/error.go (renamed from src/pkg/runtime/error.go)29
-rw-r--r--src/runtime/export_futex_test.go (renamed from src/pkg/runtime/export_futex_test.go)3
-rw-r--r--src/runtime/export_test.go165
-rw-r--r--src/runtime/extern.go (renamed from src/pkg/runtime/extern.go)149
-rw-r--r--src/runtime/float.c (renamed from src/pkg/runtime/float.c)0
-rw-r--r--src/runtime/funcdata.h60
-rw-r--r--src/runtime/futex_test.go (renamed from src/pkg/runtime/futex_test.go)0
-rw-r--r--src/runtime/gc_test.go (renamed from src/pkg/runtime/gc_test.go)56
-rw-r--r--src/runtime/gcinfo_test.go193
-rw-r--r--src/runtime/hash_test.go (renamed from src/pkg/runtime/hash_test.go)60
-rw-r--r--src/runtime/hashmap.go953
-rw-r--r--src/runtime/hashmap_fast.go379
-rw-r--r--src/runtime/heapdump.c (renamed from src/pkg/runtime/heapdump.c)431
-rw-r--r--src/runtime/iface.go439
-rw-r--r--src/runtime/iface_test.go (renamed from src/pkg/runtime/iface_test.go)0
-rw-r--r--src/runtime/lfstack.c (renamed from src/pkg/runtime/lfstack.goc)16
-rw-r--r--src/runtime/lfstack_test.go (renamed from src/pkg/runtime/lfstack_test.go)0
-rw-r--r--src/runtime/lock_futex.go205
-rw-r--r--src/runtime/lock_sema.go270
-rw-r--r--src/runtime/malloc.c396
-rw-r--r--src/runtime/malloc.go837
-rw-r--r--src/runtime/malloc.h (renamed from src/pkg/runtime/malloc.h)242
-rw-r--r--src/runtime/malloc_test.go (renamed from src/pkg/runtime/malloc_test.go)41
-rw-r--r--src/runtime/map_test.go (renamed from src/pkg/runtime/map_test.go)98
-rw-r--r--src/runtime/mapspeed_test.go (renamed from src/pkg/runtime/mapspeed_test.go)4
-rw-r--r--src/runtime/mcache.c (renamed from src/pkg/runtime/mcache.c)91
-rw-r--r--src/runtime/mcentral.c (renamed from src/pkg/runtime/mcentral.c)229
-rw-r--r--src/runtime/mem.go (renamed from src/pkg/runtime/mem.go)49
-rw-r--r--src/runtime/mem_darwin.c (renamed from src/pkg/runtime/mem_darwin.c)4
-rw-r--r--src/runtime/mem_dragonfly.c (renamed from src/pkg/runtime/mem_dragonfly.c)4
-rw-r--r--src/runtime/mem_freebsd.c (renamed from src/pkg/runtime/mem_freebsd.c)4
-rw-r--r--src/runtime/mem_linux.c (renamed from src/pkg/runtime/mem_linux.c)4
-rw-r--r--src/runtime/mem_nacl.c (renamed from src/pkg/runtime/mem_nacl.c)8
-rw-r--r--src/runtime/mem_netbsd.c (renamed from src/pkg/runtime/mem_netbsd.c)4
-rw-r--r--src/runtime/mem_openbsd.c (renamed from src/pkg/runtime/mem_openbsd.c)4
-rw-r--r--src/runtime/mem_plan9.c (renamed from src/pkg/runtime/mem_plan9.c)59
-rw-r--r--src/runtime/mem_solaris.c (renamed from src/pkg/runtime/mem_solaris.c)4
-rw-r--r--src/runtime/mem_windows.c (renamed from src/pkg/runtime/mem_windows.c)32
-rw-r--r--src/runtime/memclr_386.s (renamed from src/pkg/runtime/memclr_386.s)5
-rw-r--r--src/runtime/memclr_amd64.s (renamed from src/pkg/runtime/memclr_amd64.s)5
-rw-r--r--src/runtime/memclr_arm.s (renamed from src/pkg/runtime/memclr_arm.s)2
-rw-r--r--src/runtime/memclr_plan9_386.s (renamed from src/pkg/runtime/memclr_plan9_386.s)3
-rw-r--r--src/runtime/memclr_plan9_amd64.s21
-rw-r--r--src/runtime/memmove_386.s (renamed from src/pkg/runtime/memmove_386.s)5
-rw-r--r--src/runtime/memmove_amd64.s (renamed from src/pkg/runtime/memmove_amd64.s)57
-rw-r--r--src/runtime/memmove_arm.s (renamed from src/pkg/runtime/memmove_arm.s)2
-rw-r--r--src/runtime/memmove_linux_amd64_test.go (renamed from src/pkg/runtime/memmove_linux_amd64_test.go)0
-rw-r--r--src/runtime/memmove_nacl_amd64p32.s (renamed from src/pkg/runtime/memmove_nacl_amd64p32.s)4
-rw-r--r--src/runtime/memmove_plan9_386.s (renamed from src/pkg/runtime/memmove_plan9_386.s)5
-rw-r--r--src/runtime/memmove_plan9_amd64.s (renamed from src/pkg/runtime/memmove_plan9_amd64.s)5
-rw-r--r--src/runtime/memmove_test.go (renamed from src/pkg/runtime/memmove_test.go)64
-rw-r--r--src/runtime/mfinal_test.go (renamed from src/pkg/runtime/mfinal_test.go)13
-rw-r--r--src/runtime/mfixalloc.c (renamed from src/pkg/runtime/mfixalloc.c)0
-rw-r--r--src/runtime/mgc0.c2010
-rw-r--r--src/runtime/mgc0.go152
-rw-r--r--src/runtime/mgc0.h78
-rw-r--r--src/runtime/mheap.c (renamed from src/pkg/runtime/mheap.c)507
-rw-r--r--src/runtime/mknacl.sh (renamed from src/pkg/runtime/mknacl.sh)0
-rw-r--r--src/runtime/mprof.go672
-rw-r--r--src/runtime/msize.c (renamed from src/pkg/runtime/msize.c)2
-rw-r--r--src/runtime/netpoll.go455
-rw-r--r--src/runtime/netpoll_epoll.go97
-rw-r--r--src/runtime/netpoll_kqueue.go101
-rw-r--r--src/runtime/netpoll_nacl.go26
-rw-r--r--src/runtime/netpoll_solaris.c (renamed from src/pkg/runtime/netpoll_solaris.c)16
-rw-r--r--src/runtime/netpoll_stub.c (renamed from src/pkg/runtime/netpoll_stub.c)0
-rw-r--r--src/runtime/netpoll_windows.c (renamed from src/pkg/runtime/netpoll_windows.c)22
-rw-r--r--src/runtime/noasm_arm.go54
-rw-r--r--src/runtime/norace_test.go (renamed from src/pkg/runtime/norace_test.go)0
-rw-r--r--src/runtime/os_android.c16
-rw-r--r--src/runtime/os_android.h1
-rw-r--r--src/runtime/os_darwin.c (renamed from src/pkg/runtime/os_darwin.c)144
-rw-r--r--src/runtime/os_darwin.go24
-rw-r--r--src/runtime/os_darwin.h (renamed from src/pkg/runtime/os_darwin.h)19
-rw-r--r--src/runtime/os_dragonfly.c (renamed from src/pkg/runtime/os_dragonfly.c)106
-rw-r--r--src/runtime/os_dragonfly.go20
-rw-r--r--src/runtime/os_dragonfly.h (renamed from src/pkg/runtime/os_dragonfly.h)13
-rw-r--r--src/runtime/os_freebsd.c (renamed from src/pkg/runtime/os_freebsd.c)112
-rw-r--r--src/runtime/os_freebsd.go17
-rw-r--r--src/runtime/os_freebsd.h (renamed from src/pkg/runtime/os_freebsd.h)14
-rw-r--r--src/runtime/os_freebsd_arm.c (renamed from src/pkg/runtime/os_freebsd_arm.c)2
-rw-r--r--src/runtime/os_linux.c (renamed from src/pkg/runtime/os_linux.c)94
-rw-r--r--src/runtime/os_linux.go17
-rw-r--r--src/runtime/os_linux.h (renamed from src/pkg/runtime/os_linux.h)19
-rw-r--r--src/runtime/os_linux_386.c (renamed from src/pkg/runtime/os_linux_386.c)2
-rw-r--r--src/runtime/os_linux_arm.c (renamed from src/pkg/runtime/os_linux_arm.c)2
-rw-r--r--src/runtime/os_nacl.c (renamed from src/pkg/runtime/os_nacl.c)114
-rw-r--r--src/runtime/os_nacl.go39
-rw-r--r--src/runtime/os_nacl.h (renamed from src/pkg/runtime/os_nacl.h)0
-rw-r--r--src/runtime/os_nacl_arm.c24
-rw-r--r--src/runtime/os_netbsd.c (renamed from src/pkg/runtime/os_netbsd.c)148
-rw-r--r--src/runtime/os_netbsd.go20
-rw-r--r--src/runtime/os_netbsd.h (renamed from src/pkg/runtime/os_netbsd.h)25
-rw-r--r--src/runtime/os_netbsd_386.c (renamed from src/pkg/runtime/os_netbsd_386.c)0
-rw-r--r--src/runtime/os_netbsd_amd64.c (renamed from src/pkg/runtime/os_netbsd_amd64.c)0
-rw-r--r--src/runtime/os_netbsd_arm.c (renamed from src/pkg/runtime/os_netbsd_arm.c)2
-rw-r--r--src/runtime/os_openbsd.c (renamed from src/pkg/runtime/os_openbsd.c)159
-rw-r--r--src/runtime/os_openbsd.go17
-rw-r--r--src/runtime/os_openbsd.h (renamed from src/pkg/runtime/os_openbsd.h)17
-rw-r--r--src/runtime/os_plan9.c (renamed from src/pkg/runtime/os_plan9.c)154
-rw-r--r--src/runtime/os_plan9.go103
-rw-r--r--src/runtime/os_plan9.h (renamed from src/pkg/runtime/os_plan9.h)34
-rw-r--r--src/runtime/os_plan9_386.c (renamed from src/pkg/runtime/os_plan9_386.c)10
-rw-r--r--src/runtime/os_plan9_amd64.c (renamed from src/pkg/runtime/os_plan9_amd64.c)10
-rw-r--r--src/runtime/os_solaris.c (renamed from src/pkg/runtime/os_solaris.c)202
-rw-r--r--src/runtime/os_solaris.go100
-rw-r--r--src/runtime/os_solaris.h55
-rw-r--r--src/runtime/os_windows.c (renamed from src/pkg/runtime/os_windows.c)359
-rw-r--r--src/runtime/os_windows.go58
-rw-r--r--src/runtime/os_windows.h (renamed from src/pkg/runtime/os_windows.h)16
-rw-r--r--src/runtime/os_windows_386.c128
-rw-r--r--src/runtime/os_windows_386.go11
-rw-r--r--src/runtime/os_windows_amd64.c150
-rw-r--r--src/runtime/os_windows_amd64.go11
-rw-r--r--src/runtime/panic.c200
-rw-r--r--src/runtime/panic.go505
-rw-r--r--src/runtime/parfor.c (renamed from src/pkg/runtime/parfor.c)59
-rw-r--r--src/runtime/parfor_test.go (renamed from src/pkg/runtime/parfor_test.go)0
-rw-r--r--src/runtime/pprof/mprof_test.go99
-rw-r--r--src/runtime/pprof/pprof.go (renamed from src/pkg/runtime/pprof/pprof.go)6
-rw-r--r--src/runtime/pprof/pprof_test.go (renamed from src/pkg/runtime/pprof/pprof_test.go)129
-rw-r--r--src/runtime/print1.go323
-rw-r--r--src/runtime/proc.c (renamed from src/pkg/runtime/proc.c)2056
-rw-r--r--src/runtime/proc.go246
-rw-r--r--src/runtime/proc_test.go (renamed from src/pkg/runtime/proc_test.go)8
-rw-r--r--src/runtime/race.c (renamed from src/pkg/runtime/race.c)179
-rw-r--r--src/runtime/race.go127
-rw-r--r--src/runtime/race.h (renamed from src/pkg/runtime/race.h)0
-rw-r--r--src/runtime/race/README (renamed from src/pkg/runtime/race/README)2
-rw-r--r--src/runtime/race/doc.go (renamed from src/pkg/runtime/race/doc.go)0
-rw-r--r--src/runtime/race/output_test.go (renamed from src/pkg/runtime/race/output_test.go)0
-rw-r--r--src/runtime/race/race.go (renamed from src/pkg/runtime/race/race.go)4
-rw-r--r--src/runtime/race/race_darwin_amd64.sysobin0 -> 278328 bytes
-rw-r--r--src/runtime/race/race_freebsd_amd64.sysobin0 -> 294224 bytes
-rw-r--r--src/runtime/race/race_linux_amd64.sysobin0 -> 298064 bytes
-rw-r--r--src/runtime/race/race_test.go (renamed from src/pkg/runtime/race/race_test.go)0
-rw-r--r--src/runtime/race/race_unix_test.go30
-rw-r--r--src/runtime/race/race_windows_amd64.sysobin0 -> 292311 bytes
-rw-r--r--src/runtime/race/testdata/atomic_test.go (renamed from src/pkg/runtime/race/testdata/atomic_test.go)6
-rw-r--r--src/runtime/race/testdata/cgo_test.go (renamed from src/pkg/runtime/race/testdata/cgo_test.go)0
-rw-r--r--src/runtime/race/testdata/cgo_test_main.go (renamed from src/pkg/runtime/race/testdata/cgo_test_main.go)0
-rw-r--r--src/runtime/race/testdata/chan_test.go (renamed from src/pkg/runtime/race/testdata/chan_test.go)4
-rw-r--r--src/runtime/race/testdata/comp_test.go (renamed from src/pkg/runtime/race/testdata/comp_test.go)0
-rw-r--r--src/runtime/race/testdata/finalizer_test.go (renamed from src/pkg/runtime/race/testdata/finalizer_test.go)0
-rw-r--r--src/runtime/race/testdata/io_test.go (renamed from src/pkg/runtime/race/testdata/io_test.go)0
-rw-r--r--src/runtime/race/testdata/map_test.go (renamed from src/pkg/runtime/race/testdata/map_test.go)101
-rw-r--r--src/runtime/race/testdata/mop_test.go (renamed from src/pkg/runtime/race/testdata/mop_test.go)2
-rw-r--r--src/runtime/race/testdata/mutex_test.go (renamed from src/pkg/runtime/race/testdata/mutex_test.go)0
-rw-r--r--src/runtime/race/testdata/regression_test.go (renamed from src/pkg/runtime/race/testdata/regression_test.go)0
-rw-r--r--src/runtime/race/testdata/rwmutex_test.go (renamed from src/pkg/runtime/race/testdata/rwmutex_test.go)0
-rw-r--r--src/runtime/race/testdata/select_test.go (renamed from src/pkg/runtime/race/testdata/select_test.go)0
-rw-r--r--src/runtime/race/testdata/slice_test.go (renamed from src/pkg/runtime/race/testdata/slice_test.go)10
-rw-r--r--src/runtime/race/testdata/sync_test.go (renamed from src/pkg/runtime/race/testdata/sync_test.go)0
-rw-r--r--src/runtime/race/testdata/waitgroup_test.go (renamed from src/pkg/runtime/race/testdata/waitgroup_test.go)0
-rw-r--r--src/runtime/race0.go37
-rw-r--r--src/runtime/race_amd64.s (renamed from src/pkg/runtime/race_amd64.s)186
-rw-r--r--src/runtime/rdebug.go37
-rw-r--r--src/runtime/rt0_android_arm.s11
-rw-r--r--src/runtime/rt0_darwin_386.s (renamed from src/pkg/runtime/rt0_darwin_386.s)4
-rw-r--r--src/runtime/rt0_darwin_amd64.s (renamed from src/pkg/runtime/rt0_darwin_amd64.s)4
-rw-r--r--src/runtime/rt0_dragonfly_386.s (renamed from src/pkg/runtime/rt0_dragonfly_386.s)4
-rw-r--r--src/runtime/rt0_dragonfly_amd64.s (renamed from src/pkg/runtime/rt0_dragonfly_amd64.s)4
-rw-r--r--src/runtime/rt0_freebsd_386.s (renamed from src/pkg/runtime/rt0_freebsd_386.s)4
-rw-r--r--src/runtime/rt0_freebsd_amd64.s (renamed from src/pkg/runtime/rt0_freebsd_amd64.s)4
-rw-r--r--src/runtime/rt0_freebsd_arm.s (renamed from src/pkg/runtime/rt0_freebsd_arm.s)6
-rw-r--r--src/runtime/rt0_linux_386.s (renamed from src/pkg/runtime/rt0_linux_386.s)6
-rw-r--r--src/runtime/rt0_linux_amd64.s (renamed from src/pkg/runtime/rt0_linux_amd64.s)4
-rw-r--r--src/runtime/rt0_linux_arm.s (renamed from src/pkg/runtime/rt0_linux_arm.s)6
-rw-r--r--src/runtime/rt0_nacl_386.s (renamed from src/pkg/runtime/rt0_nacl_386.s)4
-rw-r--r--src/runtime/rt0_nacl_amd64p32.s (renamed from src/pkg/runtime/rt0_nacl_amd64p32.s)6
-rw-r--r--src/runtime/rt0_nacl_arm.s20
-rw-r--r--src/runtime/rt0_netbsd_386.s (renamed from src/pkg/runtime/rt0_netbsd_386.s)4
-rw-r--r--src/runtime/rt0_netbsd_amd64.s (renamed from src/pkg/runtime/rt0_netbsd_amd64.s)4
-rw-r--r--src/runtime/rt0_netbsd_arm.s (renamed from src/pkg/runtime/rt0_netbsd_arm.s)4
-rw-r--r--src/runtime/rt0_openbsd_386.s (renamed from src/pkg/runtime/rt0_openbsd_386.s)4
-rw-r--r--src/runtime/rt0_openbsd_amd64.s (renamed from src/pkg/runtime/rt0_openbsd_amd64.s)4
-rw-r--r--src/runtime/rt0_plan9_386.s23
-rw-r--r--src/runtime/rt0_plan9_amd64.s21
-rw-r--r--src/runtime/rt0_solaris_amd64.s (renamed from src/pkg/runtime/rt0_solaris_amd64.s)6
-rw-r--r--src/runtime/rt0_windows_386.s (renamed from src/pkg/runtime/rt0_windows_386.s)6
-rw-r--r--src/runtime/rt0_windows_amd64.s (renamed from src/pkg/runtime/rt0_windows_amd64.s)6
-rw-r--r--src/runtime/rune.go219
-rw-r--r--src/runtime/runtime-gdb.py (renamed from src/pkg/runtime/runtime-gdb.py)0
-rw-r--r--src/runtime/runtime.c (renamed from src/pkg/runtime/runtime.c)217
-rw-r--r--src/runtime/runtime.go60
-rw-r--r--src/runtime/runtime.h (renamed from src/pkg/runtime/runtime.h)463
-rw-r--r--src/runtime/runtime_linux_test.go (renamed from src/pkg/runtime/runtime_linux_test.go)0
-rw-r--r--src/runtime/runtime_test.go (renamed from src/pkg/runtime/runtime_test.go)71
-rw-r--r--src/runtime/runtime_unix_test.go (renamed from src/pkg/runtime/runtime_unix_test.go)0
-rw-r--r--src/runtime/select.go651
-rw-r--r--src/runtime/sema.go275
-rw-r--r--src/runtime/signal.c25
-rw-r--r--src/runtime/signal_386.c (renamed from src/pkg/runtime/signal_386.c)14
-rw-r--r--src/runtime/signal_amd64x.c (renamed from src/pkg/runtime/signal_amd64x.c)12
-rw-r--r--src/runtime/signal_android_386.h1
-rw-r--r--src/runtime/signal_android_arm.h1
-rw-r--r--src/runtime/signal_arm.c (renamed from src/pkg/runtime/signal_arm.c)15
-rw-r--r--src/runtime/signal_darwin_386.h (renamed from src/pkg/runtime/signal_darwin_386.h)0
-rw-r--r--src/runtime/signal_darwin_amd64.h (renamed from src/pkg/runtime/signal_darwin_amd64.h)0
-rw-r--r--src/runtime/signal_dragonfly_386.h (renamed from src/pkg/runtime/signal_dragonfly_386.h)0
-rw-r--r--src/runtime/signal_dragonfly_amd64.h (renamed from src/pkg/runtime/signal_dragonfly_amd64.h)0
-rw-r--r--src/runtime/signal_freebsd_386.h (renamed from src/pkg/runtime/signal_freebsd_386.h)0
-rw-r--r--src/runtime/signal_freebsd_amd64.h (renamed from src/pkg/runtime/signal_freebsd_amd64.h)0
-rw-r--r--src/runtime/signal_freebsd_arm.h (renamed from src/pkg/runtime/signal_freebsd_arm.h)0
-rw-r--r--src/runtime/signal_linux_386.h (renamed from src/pkg/runtime/signal_linux_386.h)0
-rw-r--r--src/runtime/signal_linux_amd64.h (renamed from src/pkg/runtime/signal_linux_amd64.h)0
-rw-r--r--src/runtime/signal_linux_arm.h (renamed from src/pkg/runtime/signal_linux_arm.h)0
-rw-r--r--src/runtime/signal_nacl_386.h (renamed from src/pkg/runtime/signal_nacl_386.h)0
-rw-r--r--src/runtime/signal_nacl_amd64p32.h (renamed from src/pkg/runtime/signal_nacl_amd64p32.h)2
-rw-r--r--src/runtime/signal_nacl_arm.h28
-rw-r--r--src/runtime/signal_netbsd_386.h (renamed from src/pkg/runtime/signal_netbsd_386.h)0
-rw-r--r--src/runtime/signal_netbsd_amd64.h (renamed from src/pkg/runtime/signal_netbsd_amd64.h)0
-rw-r--r--src/runtime/signal_netbsd_arm.h (renamed from src/pkg/runtime/signal_netbsd_arm.h)0
-rw-r--r--src/runtime/signal_openbsd_386.h (renamed from src/pkg/runtime/signal_openbsd_386.h)0
-rw-r--r--src/runtime/signal_openbsd_amd64.h (renamed from src/pkg/runtime/signal_openbsd_amd64.h)0
-rw-r--r--src/runtime/signal_solaris_amd64.h (renamed from src/pkg/runtime/signal_solaris_amd64.h)0
-rw-r--r--src/runtime/signal_unix.c (renamed from src/pkg/runtime/signal_unix.c)4
-rw-r--r--src/runtime/signal_unix.go13
-rw-r--r--src/runtime/signal_unix.h (renamed from src/pkg/runtime/signal_unix.h)0
-rw-r--r--src/runtime/signals_android.h1
-rw-r--r--src/runtime/signals_darwin.h (renamed from src/pkg/runtime/signals_darwin.h)3
-rw-r--r--src/runtime/signals_dragonfly.h (renamed from src/pkg/runtime/signals_dragonfly.h)3
-rw-r--r--src/runtime/signals_freebsd.h (renamed from src/pkg/runtime/signals_freebsd.h)3
-rw-r--r--src/runtime/signals_linux.h (renamed from src/pkg/runtime/signals_linux.h)3
-rw-r--r--src/runtime/signals_nacl.h (renamed from src/pkg/runtime/signals_nacl.h)3
-rw-r--r--src/runtime/signals_netbsd.h (renamed from src/pkg/runtime/signals_netbsd.h)3
-rw-r--r--src/runtime/signals_openbsd.h (renamed from src/pkg/runtime/signals_openbsd.h)3
-rw-r--r--src/runtime/signals_plan9.h (renamed from src/pkg/runtime/signals_plan9.h)3
-rw-r--r--src/runtime/signals_solaris.h (renamed from src/pkg/runtime/signals_solaris.h)3
-rw-r--r--src/runtime/signals_windows.h (renamed from src/pkg/runtime/signals_windows.h)0
-rw-r--r--src/runtime/sigpanic_unix.go40
-rw-r--r--src/runtime/sigqueue.go173
-rw-r--r--src/runtime/slice.go139
-rw-r--r--src/runtime/softfloat64.go (renamed from src/pkg/runtime/softfloat64.go)0
-rw-r--r--src/runtime/softfloat64_test.go (renamed from src/pkg/runtime/softfloat64_test.go)0
-rw-r--r--src/runtime/softfloat_arm.c (renamed from src/pkg/runtime/softfloat_arm.c)99
-rw-r--r--src/runtime/sqrt.go (renamed from src/pkg/runtime/sqrt.go)0
-rw-r--r--src/runtime/stack.c892
-rw-r--r--src/runtime/stack.go13
-rw-r--r--src/runtime/stack.h (renamed from src/pkg/runtime/stack.h)37
-rw-r--r--src/runtime/stack_test.go397
-rw-r--r--src/runtime/string.c226
-rw-r--r--src/runtime/string.go298
-rw-r--r--src/runtime/string_test.go160
-rw-r--r--src/runtime/stubs.go316
-rw-r--r--src/runtime/symtab.go288
-rw-r--r--src/runtime/symtab_test.go (renamed from src/pkg/runtime/symtab_test.go)0
-rw-r--r--src/runtime/sys_arm.c (renamed from src/pkg/runtime/sys_arm.c)0
-rw-r--r--src/runtime/sys_darwin_386.s (renamed from src/pkg/runtime/sys_darwin_386.s)45
-rw-r--r--src/runtime/sys_darwin_amd64.s (renamed from src/pkg/runtime/sys_darwin_amd64.s)171
-rw-r--r--src/runtime/sys_dragonfly_386.s (renamed from src/pkg/runtime/sys_dragonfly_386.s)42
-rw-r--r--src/runtime/sys_dragonfly_amd64.s (renamed from src/pkg/runtime/sys_dragonfly_amd64.s)132
-rw-r--r--src/runtime/sys_freebsd_386.s (renamed from src/pkg/runtime/sys_freebsd_386.s)40
-rw-r--r--src/runtime/sys_freebsd_amd64.s (renamed from src/pkg/runtime/sys_freebsd_amd64.s)132
-rw-r--r--src/runtime/sys_freebsd_arm.s (renamed from src/pkg/runtime/sys_freebsd_arm.s)33
-rw-r--r--src/runtime/sys_linux_386.s (renamed from src/pkg/runtime/sys_linux_386.s)166
-rw-r--r--src/runtime/sys_linux_amd64.s (renamed from src/pkg/runtime/sys_linux_amd64.s)174
-rw-r--r--src/runtime/sys_linux_arm.s (renamed from src/pkg/runtime/sys_linux_arm.s)69
-rw-r--r--src/runtime/sys_nacl_386.s (renamed from src/pkg/runtime/sys_nacl_386.s)252
-rw-r--r--src/runtime/sys_nacl_amd64p32.s (renamed from src/pkg/runtime/sys_nacl_amd64p32.s)218
-rw-r--r--src/runtime/sys_nacl_arm.s320
-rw-r--r--src/runtime/sys_netbsd_386.s (renamed from src/pkg/runtime/sys_netbsd_386.s)38
-rw-r--r--src/runtime/sys_netbsd_amd64.s (renamed from src/pkg/runtime/sys_netbsd_amd64.s)130
-rw-r--r--src/runtime/sys_netbsd_arm.s (renamed from src/pkg/runtime/sys_netbsd_arm.s)34
-rw-r--r--src/runtime/sys_openbsd_386.s (renamed from src/pkg/runtime/sys_openbsd_386.s)60
-rw-r--r--src/runtime/sys_openbsd_amd64.s (renamed from src/pkg/runtime/sys_openbsd_amd64.s)134
-rw-r--r--src/runtime/sys_plan9_386.s (renamed from src/pkg/runtime/sys_plan9_386.s)170
-rw-r--r--src/runtime/sys_plan9_amd64.s (renamed from src/pkg/runtime/sys_plan9_amd64.s)177
-rw-r--r--src/runtime/sys_solaris_amd64.s (renamed from src/pkg/runtime/sys_solaris_amd64.s)110
-rw-r--r--src/runtime/sys_windows_386.s (renamed from src/pkg/runtime/sys_windows_386.s)134
-rw-r--r--src/runtime/sys_windows_amd64.s (renamed from src/pkg/runtime/sys_windows_amd64.s)145
-rw-r--r--src/runtime/sys_x86.c (renamed from src/pkg/runtime/sys_x86.c)0
-rw-r--r--src/runtime/syscall_nacl.h (renamed from src/pkg/runtime/syscall_nacl.h)0
-rw-r--r--src/runtime/syscall_solaris.c23
-rw-r--r--src/runtime/syscall_solaris.go322
-rw-r--r--src/runtime/syscall_windows.go170
-rw-r--r--src/runtime/syscall_windows_test.go (renamed from src/pkg/runtime/syscall_windows_test.go)84
-rw-r--r--src/runtime/thunk.s183
-rw-r--r--src/runtime/thunk_solaris_amd64.s88
-rw-r--r--src/runtime/thunk_windows.s30
-rw-r--r--src/runtime/time.go289
-rw-r--r--src/runtime/tls_arm.s69
-rw-r--r--src/runtime/traceback.go659
-rw-r--r--src/runtime/type.h (renamed from src/pkg/runtime/type.h)43
-rw-r--r--src/runtime/typekind.go44
-rw-r--r--src/runtime/typekind.h (renamed from src/pkg/runtime/typekind.h)6
-rw-r--r--src/runtime/vdso_linux_amd64.c (renamed from src/pkg/runtime/vdso_linux_amd64.c)118
-rw-r--r--src/runtime/vlop_386.s (renamed from src/pkg/runtime/vlop_386.s)10
-rw-r--r--src/runtime/vlop_arm.s (renamed from src/pkg/runtime/vlop_arm.s)109
-rw-r--r--src/runtime/vlop_arm_test.go (renamed from src/pkg/runtime/vlop_arm_test.go)0
-rw-r--r--src/runtime/vlrt.c (renamed from src/pkg/runtime/vlrt_386.c)507
-rw-r--r--src/runtime/vlrt.go258
-rw-r--r--src/sort/example_interface_test.go (renamed from src/pkg/sort/example_interface_test.go)0
-rw-r--r--src/sort/example_keys_test.go (renamed from src/pkg/sort/example_keys_test.go)0
-rw-r--r--src/sort/example_multi_test.go (renamed from src/pkg/sort/example_multi_test.go)0
-rw-r--r--src/sort/example_test.go (renamed from src/pkg/sort/example_test.go)0
-rw-r--r--src/sort/example_wrapper_test.go (renamed from src/pkg/sort/example_wrapper_test.go)0
-rw-r--r--src/sort/export_test.go (renamed from src/pkg/sort/export_test.go)0
-rw-r--r--src/sort/search.go (renamed from src/pkg/sort/search.go)0
-rw-r--r--src/sort/search_test.go (renamed from src/pkg/sort/search_test.go)0
-rw-r--r--src/sort/sort.go (renamed from src/pkg/sort/sort.go)0
-rw-r--r--src/sort/sort_test.go (renamed from src/pkg/sort/sort_test.go)0
-rw-r--r--src/strconv/atob.go (renamed from src/pkg/strconv/atob.go)0
-rw-r--r--src/strconv/atob_test.go (renamed from src/pkg/strconv/atob_test.go)0
-rw-r--r--src/strconv/atof.go (renamed from src/pkg/strconv/atof.go)0
-rw-r--r--src/strconv/atof_test.go (renamed from src/pkg/strconv/atof_test.go)0
-rw-r--r--src/strconv/atoi.go (renamed from src/pkg/strconv/atoi.go)2
-rw-r--r--src/strconv/atoi_test.go (renamed from src/pkg/strconv/atoi_test.go)0
-rw-r--r--src/strconv/decimal.go (renamed from src/pkg/strconv/decimal.go)0
-rw-r--r--src/strconv/decimal_test.go (renamed from src/pkg/strconv/decimal_test.go)0
-rw-r--r--src/strconv/extfloat.go (renamed from src/pkg/strconv/extfloat.go)0
-rw-r--r--src/strconv/fp_test.go (renamed from src/pkg/strconv/fp_test.go)0
-rw-r--r--src/strconv/ftoa.go (renamed from src/pkg/strconv/ftoa.go)0
-rw-r--r--src/strconv/ftoa_test.go (renamed from src/pkg/strconv/ftoa_test.go)0
-rw-r--r--src/strconv/internal_test.go (renamed from src/pkg/strconv/internal_test.go)0
-rw-r--r--src/strconv/isprint.go (renamed from src/pkg/strconv/isprint.go)198
-rw-r--r--src/strconv/itoa.go (renamed from src/pkg/strconv/itoa.go)0
-rw-r--r--src/strconv/itoa_test.go (renamed from src/pkg/strconv/itoa_test.go)0
-rw-r--r--src/strconv/makeisprint.go (renamed from src/pkg/strconv/makeisprint.go)70
-rw-r--r--src/strconv/quote.go (renamed from src/pkg/strconv/quote.go)20
-rw-r--r--src/strconv/quote_example_test.go (renamed from src/pkg/strconv/quote_example_test.go)0
-rw-r--r--src/strconv/quote_test.go (renamed from src/pkg/strconv/quote_test.go)4
-rw-r--r--src/strconv/strconv_test.go (renamed from src/pkg/strconv/strconv_test.go)0
-rw-r--r--src/strconv/testdata/testfp.txt (renamed from src/pkg/strconv/testdata/testfp.txt)0
-rw-r--r--src/strings/example_test.go (renamed from src/pkg/strings/example_test.go)0
-rw-r--r--src/strings/export_test.go (renamed from src/pkg/strings/export_test.go)0
-rw-r--r--src/strings/reader.go (renamed from src/pkg/strings/reader.go)0
-rw-r--r--src/strings/reader_test.go (renamed from src/pkg/strings/reader_test.go)0
-rw-r--r--src/strings/replace.go (renamed from src/pkg/strings/replace.go)149
-rw-r--r--src/strings/replace_test.go (renamed from src/pkg/strings/replace_test.go)60
-rw-r--r--src/strings/search.go (renamed from src/pkg/strings/search.go)0
-rw-r--r--src/strings/search_test.go (renamed from src/pkg/strings/search_test.go)0
-rw-r--r--src/strings/strings.go (renamed from src/pkg/strings/strings.go)81
-rw-r--r--src/strings/strings.s (renamed from src/pkg/strings/strings.s)0
-rw-r--r--src/strings/strings_decl.go (renamed from src/pkg/strings/strings_decl.go)0
-rw-r--r--src/strings/strings_test.go (renamed from src/pkg/strings/strings_test.go)30
-rw-r--r--src/sync/atomic/64bit_arm.go (renamed from src/pkg/sync/atomic/64bit_arm.go)12
-rw-r--r--src/sync/atomic/asm_386.s (renamed from src/pkg/sync/atomic/asm_386.s)2
-rw-r--r--src/sync/atomic/asm_amd64.s (renamed from src/pkg/sync/atomic/asm_amd64.s)2
-rw-r--r--src/sync/atomic/asm_amd64p32.s (renamed from src/pkg/sync/atomic/asm_amd64p32.s)2
-rw-r--r--src/sync/atomic/asm_arm.s (renamed from src/pkg/sync/atomic/asm_arm.s)4
-rw-r--r--src/sync/atomic/asm_freebsd_arm.s (renamed from src/pkg/sync/atomic/asm_freebsd_arm.s)2
-rw-r--r--src/sync/atomic/asm_linux_arm.s (renamed from src/pkg/sync/atomic/asm_linux_arm.s)28
-rw-r--r--src/sync/atomic/asm_nacl_arm.s109
-rw-r--r--src/sync/atomic/asm_netbsd_arm.s (renamed from src/pkg/sync/atomic/asm_netbsd_arm.s)2
-rw-r--r--src/sync/atomic/atomic_linux_arm_test.go (renamed from src/pkg/sync/atomic/atomic_linux_arm_test.go)0
-rw-r--r--src/sync/atomic/atomic_test.go (renamed from src/pkg/sync/atomic/atomic_test.go)16
-rw-r--r--src/sync/atomic/doc.go (renamed from src/pkg/sync/atomic/doc.go)2
-rw-r--r--src/sync/atomic/export_linux_arm_test.go (renamed from src/pkg/sync/atomic/export_linux_arm_test.go)2
-rw-r--r--src/sync/atomic/race.s8
-rw-r--r--src/sync/atomic/value.go85
-rw-r--r--src/sync/atomic/value_test.go195
-rw-r--r--src/sync/cond.go (renamed from src/pkg/sync/cond.go)0
-rw-r--r--src/sync/cond_test.go (renamed from src/pkg/sync/cond_test.go)0
-rw-r--r--src/sync/example_test.go (renamed from src/pkg/sync/example_test.go)0
-rw-r--r--src/sync/export_test.go (renamed from src/pkg/sync/export_test.go)0
-rw-r--r--src/sync/mutex.go (renamed from src/pkg/sync/mutex.go)0
-rw-r--r--src/sync/mutex_test.go (renamed from src/pkg/sync/mutex_test.go)0
-rw-r--r--src/sync/once.go (renamed from src/pkg/sync/once.go)7
-rw-r--r--src/sync/once_test.go (renamed from src/pkg/sync/once_test.go)26
-rw-r--r--src/sync/pool.go (renamed from src/pkg/sync/pool.go)2
-rw-r--r--src/sync/pool_test.go (renamed from src/pkg/sync/pool_test.go)56
-rw-r--r--src/sync/race.go (renamed from src/pkg/sync/race.go)0
-rw-r--r--src/sync/race0.go (renamed from src/pkg/sync/race0.go)0
-rw-r--r--src/sync/runtime.go (renamed from src/pkg/sync/runtime.go)8
-rw-r--r--src/sync/runtime_sema_test.go (renamed from src/pkg/sync/runtime_sema_test.go)0
-rw-r--r--src/sync/rwmutex.go (renamed from src/pkg/sync/rwmutex.go)10
-rw-r--r--src/sync/rwmutex_test.go (renamed from src/pkg/sync/rwmutex_test.go)42
-rw-r--r--src/sync/waitgroup.go (renamed from src/pkg/sync/waitgroup.go)11
-rw-r--r--src/sync/waitgroup_test.go (renamed from src/pkg/sync/waitgroup_test.go)0
-rw-r--r--src/syscall/asm.s8
-rw-r--r--src/syscall/asm_darwin_386.s (renamed from src/pkg/syscall/asm_darwin_386.s)3
-rw-r--r--src/syscall/asm_darwin_amd64.s (renamed from src/pkg/syscall/asm_darwin_amd64.s)3
-rw-r--r--src/syscall/asm_dragonfly_386.s (renamed from src/pkg/syscall/asm_dragonfly_386.s)3
-rw-r--r--src/syscall/asm_dragonfly_amd64.s (renamed from src/pkg/syscall/asm_dragonfly_amd64.s)3
-rw-r--r--src/syscall/asm_freebsd_386.s (renamed from src/pkg/syscall/asm_freebsd_386.s)3
-rw-r--r--src/syscall/asm_freebsd_amd64.s (renamed from src/pkg/syscall/asm_freebsd_amd64.s)3
-rw-r--r--src/syscall/asm_freebsd_arm.s (renamed from src/pkg/syscall/asm_freebsd_arm.s)3
-rw-r--r--src/syscall/asm_linux_386.s (renamed from src/pkg/syscall/asm_linux_386.s)3
-rw-r--r--src/syscall/asm_linux_amd64.s (renamed from src/pkg/syscall/asm_linux_amd64.s)3
-rw-r--r--src/syscall/asm_linux_arm.s (renamed from src/pkg/syscall/asm_linux_arm.s)6
-rw-r--r--src/syscall/asm_nacl_386.s (renamed from src/pkg/syscall/asm_nacl_386.s)3
-rw-r--r--src/syscall/asm_nacl_amd64p32.s (renamed from src/pkg/syscall/asm_nacl_amd64p32.s)3
-rw-r--r--src/syscall/asm_nacl_arm.s44
-rw-r--r--src/syscall/asm_netbsd_386.s (renamed from src/pkg/syscall/asm_netbsd_386.s)3
-rw-r--r--src/syscall/asm_netbsd_amd64.s (renamed from src/pkg/syscall/asm_netbsd_amd64.s)3
-rw-r--r--src/syscall/asm_netbsd_arm.s (renamed from src/pkg/syscall/asm_netbsd_arm.s)3
-rw-r--r--src/syscall/asm_openbsd_386.s (renamed from src/pkg/syscall/asm_openbsd_386.s)3
-rw-r--r--src/syscall/asm_openbsd_amd64.s (renamed from src/pkg/syscall/asm_openbsd_amd64.s)3
-rw-r--r--src/syscall/asm_plan9_386.s (renamed from src/pkg/syscall/asm_plan9_386.s)4
-rw-r--r--src/syscall/asm_plan9_amd64.s (renamed from src/pkg/syscall/asm_plan9_amd64.s)12
-rw-r--r--src/syscall/asm_solaris_amd64.s81
-rw-r--r--src/syscall/bpf_bsd.go (renamed from src/pkg/syscall/bpf_bsd.go)0
-rw-r--r--src/syscall/creds_test.go (renamed from src/pkg/syscall/creds_test.go)0
-rw-r--r--src/syscall/dir_plan9.go (renamed from src/pkg/syscall/dir_plan9.go)0
-rw-r--r--src/syscall/dll_windows.go (renamed from src/pkg/syscall/dll_windows.go)3
-rw-r--r--src/syscall/env_plan9.go (renamed from src/pkg/syscall/env_plan9.go)86
-rw-r--r--src/syscall/env_unix.go (renamed from src/pkg/syscall/env_unix.go)48
-rw-r--r--src/syscall/env_windows.go (renamed from src/pkg/syscall/env_windows.go)8
-rw-r--r--src/syscall/exec_bsd.go (renamed from src/pkg/syscall/exec_bsd.go)0
-rw-r--r--src/syscall/exec_linux.go (renamed from src/pkg/syscall/exec_linux.go)123
-rw-r--r--src/syscall/exec_plan9.go (renamed from src/pkg/syscall/exec_plan9.go)0
-rw-r--r--src/syscall/exec_solaris.go (renamed from src/pkg/syscall/exec_solaris.go)0
-rw-r--r--src/syscall/exec_unix.go (renamed from src/pkg/syscall/exec_unix.go)0
-rw-r--r--src/syscall/exec_windows.go (renamed from src/pkg/syscall/exec_windows.go)15
-rw-r--r--src/syscall/export_test.go7
-rw-r--r--src/syscall/fd_nacl.go (renamed from src/pkg/syscall/fd_nacl.go)0
-rw-r--r--src/syscall/flock.go (renamed from src/pkg/syscall/flock.go)0
-rw-r--r--src/syscall/flock_linux_32bit.go (renamed from src/pkg/syscall/flock_linux_32bit.go)0
-rw-r--r--src/syscall/fs_nacl.go (renamed from src/pkg/syscall/fs_nacl.go)31
-rw-r--r--src/syscall/lsf_linux.go (renamed from src/pkg/syscall/lsf_linux.go)0
-rwxr-xr-xsrc/syscall/mkall.sh (renamed from src/pkg/syscall/mkall.sh)2
-rw-r--r--src/syscall/mkall_windows.bat15
-rwxr-xr-xsrc/syscall/mkerrors.sh (renamed from src/pkg/syscall/mkerrors.sh)0
-rwxr-xr-xsrc/syscall/mksyscall.pl (renamed from src/pkg/syscall/mksyscall.pl)6
-rwxr-xr-xsrc/syscall/mksyscall_solaris.pl (renamed from src/pkg/syscall/mksyscall_solaris.pl)8
-rw-r--r--src/syscall/mksyscall_windows.go (renamed from src/pkg/syscall/mksyscall_windows.go)143
-rwxr-xr-xsrc/syscall/mksysctl_openbsd.pl (renamed from src/pkg/syscall/mksysctl_openbsd.pl)0
-rwxr-xr-xsrc/syscall/mksysnum_darwin.pl (renamed from src/pkg/syscall/mksysnum_darwin.pl)0
-rwxr-xr-xsrc/syscall/mksysnum_dragonfly.pl (renamed from src/pkg/syscall/mksysnum_dragonfly.pl)0
-rwxr-xr-xsrc/syscall/mksysnum_freebsd.pl (renamed from src/pkg/syscall/mksysnum_freebsd.pl)0
-rwxr-xr-xsrc/syscall/mksysnum_linux.pl (renamed from src/pkg/syscall/mksysnum_linux.pl)0
-rwxr-xr-xsrc/syscall/mksysnum_netbsd.pl (renamed from src/pkg/syscall/mksysnum_netbsd.pl)0
-rwxr-xr-xsrc/syscall/mksysnum_openbsd.pl (renamed from src/pkg/syscall/mksysnum_openbsd.pl)0
-rwxr-xr-xsrc/syscall/mksysnum_plan9.sh (renamed from src/pkg/syscall/mksysnum_plan9.sh)0
-rw-r--r--src/syscall/mmap_unix_test.go (renamed from src/pkg/syscall/mmap_unix_test.go)0
-rw-r--r--src/syscall/net_nacl.go (renamed from src/pkg/syscall/net_nacl.go)7
-rw-r--r--src/syscall/netlink_linux.go (renamed from src/pkg/syscall/netlink_linux.go)3
-rw-r--r--src/syscall/race.go (renamed from src/pkg/syscall/race.go)0
-rw-r--r--src/syscall/race0.go (renamed from src/pkg/syscall/race0.go)0
-rw-r--r--src/syscall/route_bsd.go (renamed from src/pkg/syscall/route_bsd.go)2
-rw-r--r--src/syscall/route_darwin.go (renamed from src/pkg/syscall/route_darwin.go)0
-rw-r--r--src/syscall/route_dragonfly.go (renamed from src/pkg/syscall/route_dragonfly.go)0
-rw-r--r--src/syscall/route_freebsd.go (renamed from src/pkg/syscall/route_freebsd.go)0
-rw-r--r--src/syscall/route_freebsd_32bit.go (renamed from src/pkg/syscall/route_freebsd_32bit.go)0
-rw-r--r--src/syscall/route_freebsd_64bit.go (renamed from src/pkg/syscall/route_freebsd_64bit.go)0
-rw-r--r--src/syscall/route_netbsd.go (renamed from src/pkg/syscall/route_netbsd.go)0
-rw-r--r--src/syscall/route_openbsd.go (renamed from src/pkg/syscall/route_openbsd.go)0
-rw-r--r--src/syscall/security_windows.go (renamed from src/pkg/syscall/security_windows.go)0
-rw-r--r--src/syscall/so_solaris.go (renamed from src/pkg/syscall/so_solaris.go)4
-rw-r--r--src/syscall/sockcmsg_linux.go (renamed from src/pkg/syscall/sockcmsg_linux.go)0
-rw-r--r--src/syscall/sockcmsg_unix.go (renamed from src/pkg/syscall/sockcmsg_unix.go)0
-rw-r--r--src/syscall/srpc_nacl.go (renamed from src/pkg/syscall/srpc_nacl.go)0
-rw-r--r--src/syscall/str.go (renamed from src/pkg/syscall/str.go)6
-rw-r--r--src/syscall/syscall.go (renamed from src/pkg/syscall/syscall.go)14
-rw-r--r--src/syscall/syscall_bsd.go (renamed from src/pkg/syscall/syscall_bsd.go)37
-rw-r--r--src/syscall/syscall_bsd_test.go (renamed from src/pkg/syscall/syscall_bsd_test.go)0
-rw-r--r--src/syscall/syscall_darwin.go (renamed from src/pkg/syscall/syscall_darwin.go)1
-rw-r--r--src/syscall/syscall_darwin_386.go (renamed from src/pkg/syscall/syscall_darwin_386.go)0
-rw-r--r--src/syscall/syscall_darwin_amd64.go (renamed from src/pkg/syscall/syscall_darwin_amd64.go)0
-rw-r--r--src/syscall/syscall_dragonfly.go (renamed from src/pkg/syscall/syscall_dragonfly.go)0
-rw-r--r--src/syscall/syscall_dragonfly_386.go (renamed from src/pkg/syscall/syscall_dragonfly_386.go)0
-rw-r--r--src/syscall/syscall_dragonfly_amd64.go (renamed from src/pkg/syscall/syscall_dragonfly_amd64.go)0
-rw-r--r--src/syscall/syscall_freebsd.go (renamed from src/pkg/syscall/syscall_freebsd.go)0
-rw-r--r--src/syscall/syscall_freebsd_386.go (renamed from src/pkg/syscall/syscall_freebsd_386.go)0
-rw-r--r--src/syscall/syscall_freebsd_amd64.go (renamed from src/pkg/syscall/syscall_freebsd_amd64.go)0
-rw-r--r--src/syscall/syscall_freebsd_arm.go (renamed from src/pkg/syscall/syscall_freebsd_arm.go)0
-rw-r--r--src/syscall/syscall_linux.go (renamed from src/pkg/syscall/syscall_linux.go)23
-rw-r--r--src/syscall/syscall_linux_386.go (renamed from src/pkg/syscall/syscall_linux_386.go)2
-rw-r--r--src/syscall/syscall_linux_amd64.go (renamed from src/pkg/syscall/syscall_linux_amd64.go)1
-rw-r--r--src/syscall/syscall_linux_arm.go (renamed from src/pkg/syscall/syscall_linux_arm.go)2
-rw-r--r--src/syscall/syscall_nacl.go (renamed from src/pkg/syscall/syscall_nacl.go)0
-rw-r--r--src/syscall/syscall_nacl_386.go (renamed from src/pkg/syscall/syscall_nacl_386.go)0
-rw-r--r--src/syscall/syscall_nacl_amd64p32.go (renamed from src/pkg/syscall/syscall_nacl_amd64p32.go)0
-rw-r--r--src/syscall/syscall_nacl_arm.go32
-rw-r--r--src/syscall/syscall_netbsd.go (renamed from src/pkg/syscall/syscall_netbsd.go)0
-rw-r--r--src/syscall/syscall_netbsd_386.go (renamed from src/pkg/syscall/syscall_netbsd_386.go)0
-rw-r--r--src/syscall/syscall_netbsd_amd64.go (renamed from src/pkg/syscall/syscall_netbsd_amd64.go)0
-rw-r--r--src/syscall/syscall_netbsd_arm.go (renamed from src/pkg/syscall/syscall_netbsd_arm.go)0
-rw-r--r--src/syscall/syscall_no_getwd.go (renamed from src/pkg/syscall/syscall_no_getwd.go)0
-rw-r--r--src/syscall/syscall_openbsd.go (renamed from src/pkg/syscall/syscall_openbsd.go)0
-rw-r--r--src/syscall/syscall_openbsd_386.go (renamed from src/pkg/syscall/syscall_openbsd_386.go)0
-rw-r--r--src/syscall/syscall_openbsd_amd64.go (renamed from src/pkg/syscall/syscall_openbsd_amd64.go)0
-rw-r--r--src/syscall/syscall_plan9.go (renamed from src/pkg/syscall/syscall_plan9.go)31
-rw-r--r--src/syscall/syscall_solaris.go (renamed from src/pkg/syscall/syscall_solaris.go)0
-rw-r--r--src/syscall/syscall_solaris_amd64.go (renamed from src/pkg/syscall/syscall_solaris_amd64.go)0
-rw-r--r--src/syscall/syscall_test.go (renamed from src/pkg/syscall/syscall_test.go)17
-rw-r--r--src/syscall/syscall_unix.go (renamed from src/pkg/syscall/syscall_unix.go)4
-rw-r--r--src/syscall/syscall_unix_test.go (renamed from src/pkg/syscall/syscall_unix_test.go)0
-rw-r--r--src/syscall/syscall_windows.go (renamed from src/pkg/syscall/syscall_windows.go)101
-rw-r--r--src/syscall/syscall_windows_386.go (renamed from src/pkg/syscall/syscall_windows_386.go)0
-rw-r--r--src/syscall/syscall_windows_amd64.go (renamed from src/pkg/syscall/syscall_windows_amd64.go)0
-rw-r--r--src/syscall/syscall_windows_test.go (renamed from src/pkg/syscall/syscall_windows_test.go)0
-rw-r--r--src/syscall/tables_nacl.go (renamed from src/pkg/syscall/tables_nacl.go)0
-rw-r--r--src/syscall/time_nacl_386.s (renamed from src/pkg/syscall/time_nacl_386.s)2
-rw-r--r--src/syscall/time_nacl_amd64p32.s (renamed from src/pkg/syscall/time_nacl_amd64p32.s)2
-rw-r--r--src/syscall/time_nacl_arm.s11
-rw-r--r--src/syscall/types_darwin.go (renamed from src/pkg/syscall/types_darwin.go)0
-rw-r--r--src/syscall/types_dragonfly.go (renamed from src/pkg/syscall/types_dragonfly.go)0
-rw-r--r--src/syscall/types_freebsd.go (renamed from src/pkg/syscall/types_freebsd.go)0
-rw-r--r--src/syscall/types_linux.go (renamed from src/pkg/syscall/types_linux.go)0
-rw-r--r--src/syscall/types_netbsd.go (renamed from src/pkg/syscall/types_netbsd.go)0
-rw-r--r--src/syscall/types_openbsd.go (renamed from src/pkg/syscall/types_openbsd.go)0
-rw-r--r--src/syscall/types_plan9.c (renamed from src/pkg/syscall/types_plan9.c)0
-rw-r--r--src/syscall/types_solaris.go (renamed from src/pkg/syscall/types_solaris.go)0
-rw-r--r--src/syscall/unzip_nacl.go (renamed from src/pkg/syscall/unzip_nacl.go)0
-rw-r--r--src/syscall/zerrors_darwin_386.go (renamed from src/pkg/syscall/zerrors_darwin_386.go)0
-rw-r--r--src/syscall/zerrors_darwin_amd64.go (renamed from src/pkg/syscall/zerrors_darwin_amd64.go)0
-rw-r--r--src/syscall/zerrors_dragonfly_386.go (renamed from src/pkg/syscall/zerrors_dragonfly_386.go)0
-rw-r--r--src/syscall/zerrors_dragonfly_amd64.go (renamed from src/pkg/syscall/zerrors_dragonfly_amd64.go)0
-rw-r--r--src/syscall/zerrors_freebsd_386.go (renamed from src/pkg/syscall/zerrors_freebsd_386.go)0
-rw-r--r--src/syscall/zerrors_freebsd_amd64.go (renamed from src/pkg/syscall/zerrors_freebsd_amd64.go)0
-rw-r--r--src/syscall/zerrors_freebsd_arm.go (renamed from src/pkg/syscall/zerrors_freebsd_arm.go)0
-rw-r--r--src/syscall/zerrors_linux_386.go (renamed from src/pkg/syscall/zerrors_linux_386.go)0
-rw-r--r--src/syscall/zerrors_linux_amd64.go (renamed from src/pkg/syscall/zerrors_linux_amd64.go)0
-rw-r--r--src/syscall/zerrors_linux_arm.go (renamed from src/pkg/syscall/zerrors_linux_arm.go)0
-rw-r--r--src/syscall/zerrors_netbsd_386.go (renamed from src/pkg/syscall/zerrors_netbsd_386.go)0
-rw-r--r--src/syscall/zerrors_netbsd_amd64.go (renamed from src/pkg/syscall/zerrors_netbsd_amd64.go)0
-rw-r--r--src/syscall/zerrors_netbsd_arm.go (renamed from src/pkg/syscall/zerrors_netbsd_arm.go)0
-rw-r--r--src/syscall/zerrors_openbsd_386.go (renamed from src/pkg/syscall/zerrors_openbsd_386.go)0
-rw-r--r--src/syscall/zerrors_openbsd_amd64.go (renamed from src/pkg/syscall/zerrors_openbsd_amd64.go)0
-rw-r--r--src/syscall/zerrors_plan9_386.go (renamed from src/pkg/syscall/zerrors_plan9_386.go)0
-rw-r--r--src/syscall/zerrors_plan9_amd64.go (renamed from src/pkg/syscall/zerrors_plan9_amd64.go)0
-rw-r--r--src/syscall/zerrors_solaris_amd64.go (renamed from src/pkg/syscall/zerrors_solaris_amd64.go)0
-rw-r--r--src/syscall/zerrors_windows.go (renamed from src/pkg/syscall/zerrors_windows.go)0
-rw-r--r--src/syscall/zerrors_windows_386.go (renamed from src/pkg/syscall/zerrors_windows_386.go)0
-rw-r--r--src/syscall/zerrors_windows_amd64.go (renamed from src/pkg/syscall/zerrors_windows_amd64.go)0
-rw-r--r--src/syscall/zsyscall_darwin_386.go (renamed from src/pkg/syscall/zsyscall_darwin_386.go)32
-rw-r--r--src/syscall/zsyscall_darwin_amd64.go (renamed from src/pkg/syscall/zsyscall_darwin_amd64.go)32
-rw-r--r--src/syscall/zsyscall_dragonfly_386.go (renamed from src/pkg/syscall/zsyscall_dragonfly_386.go)30
-rw-r--r--src/syscall/zsyscall_dragonfly_amd64.go (renamed from src/pkg/syscall/zsyscall_dragonfly_amd64.go)30
-rw-r--r--src/syscall/zsyscall_freebsd_386.go (renamed from src/pkg/syscall/zsyscall_freebsd_386.go)30
-rw-r--r--src/syscall/zsyscall_freebsd_amd64.go (renamed from src/pkg/syscall/zsyscall_freebsd_amd64.go)30
-rw-r--r--src/syscall/zsyscall_freebsd_arm.go (renamed from src/pkg/syscall/zsyscall_freebsd_arm.go)30
-rw-r--r--src/syscall/zsyscall_linux_386.go (renamed from src/pkg/syscall/zsyscall_linux_386.go)70
-rw-r--r--src/syscall/zsyscall_linux_amd64.go (renamed from src/pkg/syscall/zsyscall_linux_amd64.go)71
-rw-r--r--src/syscall/zsyscall_linux_arm.go (renamed from src/pkg/syscall/zsyscall_linux_arm.go)70
-rw-r--r--src/syscall/zsyscall_nacl_386.go (renamed from src/pkg/syscall/zsyscall_nacl_386.go)0
-rw-r--r--src/syscall/zsyscall_nacl_amd64p32.go (renamed from src/pkg/syscall/zsyscall_nacl_amd64p32.go)0
-rw-r--r--src/syscall/zsyscall_nacl_arm.go63
-rw-r--r--src/syscall/zsyscall_netbsd_386.go (renamed from src/pkg/syscall/zsyscall_netbsd_386.go)27
-rw-r--r--src/syscall/zsyscall_netbsd_amd64.go (renamed from src/pkg/syscall/zsyscall_netbsd_amd64.go)27
-rw-r--r--src/syscall/zsyscall_netbsd_arm.go (renamed from src/pkg/syscall/zsyscall_netbsd_arm.go)27
-rw-r--r--src/syscall/zsyscall_openbsd_386.go (renamed from src/pkg/syscall/zsyscall_openbsd_386.go)29
-rw-r--r--src/syscall/zsyscall_openbsd_amd64.go (renamed from src/pkg/syscall/zsyscall_openbsd_amd64.go)29
-rw-r--r--src/syscall/zsyscall_plan9_386.go (renamed from src/pkg/syscall/zsyscall_plan9_386.go)46
-rw-r--r--src/syscall/zsyscall_plan9_amd64.go (renamed from src/pkg/syscall/zsyscall_plan9_amd64.go)12
-rw-r--r--src/syscall/zsyscall_solaris_amd64.go (renamed from src/pkg/syscall/zsyscall_solaris_amd64.go)23
-rw-r--r--src/syscall/zsyscall_windows.go (renamed from src/pkg/syscall/zsyscall_windows_amd64.go)124
-rw-r--r--src/syscall/zsysctl_openbsd.go (renamed from src/pkg/syscall/zsysctl_openbsd.go)0
-rw-r--r--src/syscall/zsysnum_darwin_386.go (renamed from src/pkg/syscall/zsysnum_darwin_386.go)0
-rw-r--r--src/syscall/zsysnum_darwin_amd64.go (renamed from src/pkg/syscall/zsysnum_darwin_amd64.go)0
-rw-r--r--src/syscall/zsysnum_dragonfly_386.go (renamed from src/pkg/syscall/zsysnum_dragonfly_386.go)0
-rw-r--r--src/syscall/zsysnum_dragonfly_amd64.go (renamed from src/pkg/syscall/zsysnum_dragonfly_amd64.go)0
-rw-r--r--src/syscall/zsysnum_freebsd_386.go (renamed from src/pkg/syscall/zsysnum_freebsd_386.go)0
-rw-r--r--src/syscall/zsysnum_freebsd_amd64.go (renamed from src/pkg/syscall/zsysnum_freebsd_amd64.go)0
-rw-r--r--src/syscall/zsysnum_freebsd_arm.go (renamed from src/pkg/syscall/zsysnum_freebsd_arm.go)0
-rw-r--r--src/syscall/zsysnum_linux_386.go (renamed from src/pkg/syscall/zsysnum_linux_386.go)0
-rw-r--r--src/syscall/zsysnum_linux_amd64.go (renamed from src/pkg/syscall/zsysnum_linux_amd64.go)0
-rw-r--r--src/syscall/zsysnum_linux_arm.go (renamed from src/pkg/syscall/zsysnum_linux_arm.go)0
-rw-r--r--src/syscall/zsysnum_netbsd_386.go (renamed from src/pkg/syscall/zsysnum_netbsd_386.go)0
-rw-r--r--src/syscall/zsysnum_netbsd_amd64.go (renamed from src/pkg/syscall/zsysnum_netbsd_amd64.go)0
-rw-r--r--src/syscall/zsysnum_netbsd_arm.go (renamed from src/pkg/syscall/zsysnum_netbsd_arm.go)0
-rw-r--r--src/syscall/zsysnum_openbsd_386.go (renamed from src/pkg/syscall/zsysnum_openbsd_386.go)0
-rw-r--r--src/syscall/zsysnum_openbsd_amd64.go (renamed from src/pkg/syscall/zsysnum_openbsd_amd64.go)0
-rw-r--r--src/syscall/zsysnum_plan9_386.go49
-rw-r--r--src/syscall/zsysnum_plan9_amd64.go49
-rw-r--r--src/syscall/zsysnum_solaris_amd64.go (renamed from src/pkg/syscall/zsysnum_solaris_amd64.go)0
-rw-r--r--src/syscall/zsysnum_windows_386.go (renamed from src/pkg/syscall/zsysnum_windows_386.go)0
-rw-r--r--src/syscall/zsysnum_windows_amd64.go (renamed from src/pkg/syscall/zsysnum_windows_amd64.go)0
-rw-r--r--src/syscall/ztypes_darwin_386.go (renamed from src/pkg/syscall/ztypes_darwin_386.go)0
-rw-r--r--src/syscall/ztypes_darwin_amd64.go (renamed from src/pkg/syscall/ztypes_darwin_amd64.go)0
-rw-r--r--src/syscall/ztypes_dragonfly_386.go (renamed from src/pkg/syscall/ztypes_dragonfly_386.go)0
-rw-r--r--src/syscall/ztypes_dragonfly_amd64.go (renamed from src/pkg/syscall/ztypes_dragonfly_amd64.go)0
-rw-r--r--src/syscall/ztypes_freebsd_386.go (renamed from src/pkg/syscall/ztypes_freebsd_386.go)0
-rw-r--r--src/syscall/ztypes_freebsd_amd64.go (renamed from src/pkg/syscall/ztypes_freebsd_amd64.go)0
-rw-r--r--src/syscall/ztypes_freebsd_arm.go (renamed from src/pkg/syscall/ztypes_freebsd_arm.go)0
-rw-r--r--src/syscall/ztypes_linux_386.go (renamed from src/pkg/syscall/ztypes_linux_386.go)0
-rw-r--r--src/syscall/ztypes_linux_amd64.go (renamed from src/pkg/syscall/ztypes_linux_amd64.go)0
-rw-r--r--src/syscall/ztypes_linux_arm.go (renamed from src/pkg/syscall/ztypes_linux_arm.go)0
-rw-r--r--src/syscall/ztypes_netbsd_386.go (renamed from src/pkg/syscall/ztypes_netbsd_386.go)0
-rw-r--r--src/syscall/ztypes_netbsd_amd64.go (renamed from src/pkg/syscall/ztypes_netbsd_amd64.go)0
-rw-r--r--src/syscall/ztypes_netbsd_arm.go (renamed from src/pkg/syscall/ztypes_netbsd_arm.go)0
-rw-r--r--src/syscall/ztypes_openbsd_386.go (renamed from src/pkg/syscall/ztypes_openbsd_386.go)0
-rw-r--r--src/syscall/ztypes_openbsd_amd64.go (renamed from src/pkg/syscall/ztypes_openbsd_amd64.go)0
-rw-r--r--src/syscall/ztypes_plan9_386.go (renamed from src/pkg/syscall/ztypes_plan9_386.go)0
-rw-r--r--src/syscall/ztypes_plan9_amd64.go (renamed from src/pkg/syscall/ztypes_plan9_amd64.go)0
-rw-r--r--src/syscall/ztypes_solaris_amd64.go (renamed from src/pkg/syscall/ztypes_solaris_amd64.go)0
-rw-r--r--src/syscall/ztypes_windows.go (renamed from src/pkg/syscall/ztypes_windows.go)83
-rw-r--r--src/syscall/ztypes_windows_386.go (renamed from src/pkg/syscall/ztypes_windows_386.go)0
-rw-r--r--src/syscall/ztypes_windows_amd64.go (renamed from src/pkg/syscall/ztypes_windows_amd64.go)0
-rw-r--r--src/testing/allocs.go (renamed from src/pkg/testing/allocs.go)0
-rw-r--r--src/testing/allocs_test.go29
-rw-r--r--src/testing/benchmark.go (renamed from src/pkg/testing/benchmark.go)16
-rw-r--r--src/testing/benchmark_test.go (renamed from src/pkg/testing/benchmark_test.go)2
-rw-r--r--src/testing/cover.go (renamed from src/pkg/testing/cover.go)28
-rw-r--r--src/testing/example.go (renamed from src/pkg/testing/example.go)6
-rw-r--r--src/testing/export_test.go (renamed from src/pkg/testing/export_test.go)0
-rw-r--r--src/testing/iotest/logger.go (renamed from src/pkg/testing/iotest/logger.go)0
-rw-r--r--src/testing/iotest/reader.go (renamed from src/pkg/testing/iotest/reader.go)0
-rw-r--r--src/testing/iotest/writer.go (renamed from src/pkg/testing/iotest/writer.go)0
-rw-r--r--src/testing/quick/quick.go (renamed from src/pkg/testing/quick/quick.go)6
-rw-r--r--src/testing/quick/quick_test.go (renamed from src/pkg/testing/quick/quick_test.go)0
-rw-r--r--src/testing/testing.go (renamed from src/pkg/testing/testing.go)74
-rw-r--r--src/testing/testing_test.go18
-rw-r--r--src/text/scanner/scanner.go (renamed from src/pkg/text/scanner/scanner.go)31
-rw-r--r--src/text/scanner/scanner_test.go (renamed from src/pkg/text/scanner/scanner_test.go)22
-rw-r--r--src/text/tabwriter/example_test.go (renamed from src/pkg/text/tabwriter/example_test.go)0
-rw-r--r--src/text/tabwriter/tabwriter.go (renamed from src/pkg/text/tabwriter/tabwriter.go)0
-rw-r--r--src/text/tabwriter/tabwriter_test.go (renamed from src/pkg/text/tabwriter/tabwriter_test.go)0
-rw-r--r--src/text/template/doc.go (renamed from src/pkg/text/template/doc.go)9
-rw-r--r--src/text/template/example_test.go (renamed from src/pkg/text/template/example_test.go)0
-rw-r--r--src/text/template/examplefiles_test.go (renamed from src/pkg/text/template/examplefiles_test.go)0
-rw-r--r--src/text/template/examplefunc_test.go (renamed from src/pkg/text/template/examplefunc_test.go)0
-rw-r--r--src/text/template/exec.go (renamed from src/pkg/text/template/exec.go)10
-rw-r--r--src/text/template/exec_test.go (renamed from src/pkg/text/template/exec_test.go)91
-rw-r--r--src/text/template/funcs.go (renamed from src/pkg/text/template/funcs.go)86
-rw-r--r--src/text/template/helper.go (renamed from src/pkg/text/template/helper.go)0
-rw-r--r--src/text/template/multi_test.go (renamed from src/pkg/text/template/multi_test.go)0
-rw-r--r--src/text/template/parse/lex.go (renamed from src/pkg/text/template/parse/lex.go)0
-rw-r--r--src/text/template/parse/lex_test.go (renamed from src/pkg/text/template/parse/lex_test.go)0
-rw-r--r--src/text/template/parse/node.go (renamed from src/pkg/text/template/parse/node.go)248
-rw-r--r--src/text/template/parse/parse.go (renamed from src/pkg/text/template/parse/parse.go)62
-rw-r--r--src/text/template/parse/parse_test.go (renamed from src/pkg/text/template/parse/parse_test.go)5
-rw-r--r--src/text/template/template.go (renamed from src/pkg/text/template/template.go)0
-rw-r--r--src/text/template/testdata/file1.tmpl (renamed from src/pkg/text/template/testdata/file1.tmpl)0
-rw-r--r--src/text/template/testdata/file2.tmpl (renamed from src/pkg/text/template/testdata/file2.tmpl)0
-rw-r--r--src/text/template/testdata/tmpl1.tmpl (renamed from src/pkg/text/template/testdata/tmpl1.tmpl)0
-rw-r--r--src/text/template/testdata/tmpl2.tmpl (renamed from src/pkg/text/template/testdata/tmpl2.tmpl)0
-rw-r--r--src/time/example_test.go (renamed from src/pkg/time/example_test.go)4
-rw-r--r--src/time/export_test.go (renamed from src/pkg/time/export_test.go)0
-rw-r--r--src/time/export_windows_test.go (renamed from src/pkg/time/export_windows_test.go)0
-rw-r--r--src/time/format.go (renamed from src/pkg/time/format.go)9
-rw-r--r--src/time/format_test.go (renamed from src/pkg/time/format_test.go)11
-rw-r--r--src/time/genzabbrs.go (renamed from src/pkg/time/genzabbrs.go)20
-rw-r--r--src/time/internal_test.go59
-rw-r--r--src/time/sleep.go (renamed from src/pkg/time/sleep.go)16
-rw-r--r--src/time/sleep_test.go (renamed from src/pkg/time/sleep_test.go)47
-rw-r--r--src/time/sys_plan9.go (renamed from src/pkg/time/sys_plan9.go)0
-rw-r--r--src/time/sys_unix.go (renamed from src/pkg/time/sys_unix.go)0
-rw-r--r--src/time/sys_windows.go (renamed from src/pkg/time/sys_windows.go)0
-rw-r--r--src/time/tick.go (renamed from src/pkg/time/tick.go)0
-rw-r--r--src/time/tick_test.go (renamed from src/pkg/time/tick_test.go)0
-rw-r--r--src/time/time.go (renamed from src/pkg/time/time.go)43
-rw-r--r--src/time/time_test.go (renamed from src/pkg/time/time_test.go)2
-rw-r--r--src/time/zoneinfo.go (renamed from src/pkg/time/zoneinfo.go)0
-rw-r--r--src/time/zoneinfo_abbrs_windows.go (renamed from src/pkg/time/zoneinfo_abbrs_windows.go)3
-rw-r--r--src/time/zoneinfo_plan9.go (renamed from src/pkg/time/zoneinfo_plan9.go)0
-rw-r--r--src/time/zoneinfo_read.go (renamed from src/pkg/time/zoneinfo_read.go)0
-rw-r--r--src/time/zoneinfo_test.go (renamed from src/pkg/time/zoneinfo_test.go)0
-rw-r--r--src/time/zoneinfo_unix.go (renamed from src/pkg/time/zoneinfo_unix.go)0
-rw-r--r--src/time/zoneinfo_windows.go (renamed from src/pkg/time/zoneinfo_windows.go)2
-rw-r--r--src/time/zoneinfo_windows_test.go (renamed from src/pkg/time/zoneinfo_windows_test.go)0
-rw-r--r--src/unicode/casetables.go (renamed from src/pkg/unicode/casetables.go)0
-rw-r--r--src/unicode/digit.go (renamed from src/pkg/unicode/digit.go)0
-rw-r--r--src/unicode/digit_test.go (renamed from src/pkg/unicode/digit_test.go)0
-rw-r--r--src/unicode/graphic.go (renamed from src/pkg/unicode/graphic.go)0
-rw-r--r--src/unicode/graphic_test.go (renamed from src/pkg/unicode/graphic_test.go)0
-rw-r--r--src/unicode/letter.go (renamed from src/pkg/unicode/letter.go)3
-rw-r--r--src/unicode/letter_test.go (renamed from src/pkg/unicode/letter_test.go)0
-rw-r--r--src/unicode/maketables.go (renamed from src/pkg/unicode/maketables.go)178
-rw-r--r--src/unicode/script_test.go (renamed from src/pkg/unicode/script_test.go)27
-rw-r--r--src/unicode/tables.go (renamed from src/pkg/unicode/tables.go)1248
-rw-r--r--src/unicode/utf16/export_test.go (renamed from src/pkg/unicode/utf16/export_test.go)0
-rw-r--r--src/unicode/utf16/utf16.go (renamed from src/pkg/unicode/utf16/utf16.go)0
-rw-r--r--src/unicode/utf16/utf16_test.go (renamed from src/pkg/unicode/utf16/utf16_test.go)0
-rw-r--r--src/unicode/utf8/example_test.go (renamed from src/pkg/unicode/utf8/example_test.go)0
-rw-r--r--src/unicode/utf8/utf8.go (renamed from src/pkg/unicode/utf8/utf8.go)28
-rw-r--r--src/unicode/utf8/utf8_test.go (renamed from src/pkg/unicode/utf8/utf8_test.go)0
-rw-r--r--src/unsafe/unsafe.go (renamed from src/pkg/unsafe/unsafe.go)3
-rw-r--r--test/assign.go12
-rw-r--r--test/bench/garbage/parser.go2
-rw-r--r--test/bench/shootout/chameneosredux.go2
-rw-r--r--test/chan/perm.go3
-rw-r--r--test/chan/select5.go6
-rw-r--r--test/escape2.go2
-rw-r--r--test/escape2n.go1494
-rw-r--r--test/fixedbugs/bug173.go2
-rw-r--r--test/fixedbugs/bug255.go19
-rw-r--r--test/fixedbugs/bug299.go10
-rw-r--r--test/fixedbugs/bug371.go6
-rw-r--r--test/fixedbugs/bug406.go2
-rw-r--r--test/fixedbugs/bug486.go14
-rw-r--r--test/fixedbugs/bug487.go24
-rw-r--r--test/fixedbugs/bug488.dir/a.go7
-rw-r--r--test/fixedbugs/bug488.dir/b.go9
-rw-r--r--test/fixedbugs/bug488.go12
-rw-r--r--test/fixedbugs/bug489.go22
-rw-r--r--test/fixedbugs/bug490.go16
-rw-r--r--test/fixedbugs/bug491.go110
-rw-r--r--test/fixedbugs/issue4232.go29
-rw-r--r--test/fixedbugs/issue4388.go6
-rw-r--r--test/fixedbugs/issue5856.go2
-rw-r--r--test/fixedbugs/issue6703a.go16
-rw-r--r--test/fixedbugs/issue6703b.go16
-rw-r--r--test/fixedbugs/issue6703c.go18
-rw-r--r--test/fixedbugs/issue6703d.go18
-rw-r--r--test/fixedbugs/issue6703e.go18
-rw-r--r--test/fixedbugs/issue6703f.go18
-rw-r--r--test/fixedbugs/issue6703g.go20
-rw-r--r--test/fixedbugs/issue6703h.go20
-rw-r--r--test/fixedbugs/issue6703i.go20
-rw-r--r--test/fixedbugs/issue6703j.go20
-rw-r--r--test/fixedbugs/issue6703k.go21
-rw-r--r--test/fixedbugs/issue6703l.go21
-rw-r--r--test/fixedbugs/issue6703m.go25
-rw-r--r--test/fixedbugs/issue6703n.go25
-rw-r--r--test/fixedbugs/issue6703o.go23
-rw-r--r--test/fixedbugs/issue6703p.go23
-rw-r--r--test/fixedbugs/issue6703q.go28
-rw-r--r--test/fixedbugs/issue6703r.go28
-rw-r--r--test/fixedbugs/issue6703s.go18
-rw-r--r--test/fixedbugs/issue6703t.go18
-rw-r--r--test/fixedbugs/issue6703u.go18
-rw-r--r--test/fixedbugs/issue6703v.go18
-rw-r--r--test/fixedbugs/issue6703w.go21
-rw-r--r--test/fixedbugs/issue6703x.go21
-rw-r--r--test/fixedbugs/issue6703y.go23
-rw-r--r--test/fixedbugs/issue6703z.go23
-rw-r--r--test/fixedbugs/issue7690.go49
-rw-r--r--test/fixedbugs/issue7760.go25
-rw-r--r--test/fixedbugs/issue8017.go26
-rw-r--r--test/fixedbugs/issue8060.dir/a.go7
-rw-r--r--test/fixedbugs/issue8060.dir/b.go13
-rw-r--r--test/fixedbugs/issue8060.go9
-rw-r--r--test/fixedbugs/issue8074.go16
-rw-r--r--test/fixedbugs/issue8079.go11
-rw-r--r--test/fixedbugs/issue8280.dir/a.go3
-rw-r--r--test/fixedbugs/issue8280.dir/b.go5
-rw-r--r--test/fixedbugs/issue8280.go9
-rw-r--r--test/fixedbugs/issue8311.go16
-rw-r--r--test/fixedbugs/issue8336.go29
-rw-r--r--test/fixedbugs/issue8347.go27
-rw-r--r--test/fixedbugs/issue8475.go25
-rw-r--r--test/fixedbugs/issue8507.go16
-rw-r--r--test/fixedbugs/issue8612.go34
-rw-r--r--test/fixedbugs/issue8761.go26
-rw-r--r--test/fixedbugs/issue8947.go53
-rw-r--r--test/fixedbugs/issue8961.go20
-rw-r--r--test/fixedbugs/issue9006.go37
-rw-r--r--test/fixedbugs/issue9110.go90
-rw-r--r--test/interface/explicit.go4
-rw-r--r--test/interface/fail.go14
-rw-r--r--test/linkx.go12
-rw-r--r--test/linkx_run.go33
-rw-r--r--test/live.go77
-rw-r--r--test/live2.go12
-rw-r--r--test/map.go2
-rw-r--r--test/maplinear.go172
-rw-r--r--test/mapnan.go56
-rw-r--r--test/named1.go8
-rw-r--r--test/nosplit.go23
-rw-r--r--test/print.go42
-rw-r--r--test/print.out24
-rw-r--r--test/range.go92
-rw-r--r--test/recover.go92
-rw-r--r--test/run.go49
-rw-r--r--test/shift1.go2
-rw-r--r--test/sinit.go77
-rw-r--r--test/sinit_run.go40
-rw-r--r--test/slice3.go18
-rw-r--r--test/slicecap.go90
-rw-r--r--test/stress/maps.go2
-rw-r--r--test/stress/parsego.go2
-rw-r--r--test/torture.go7
2785 files changed, 109936 insertions, 80446 deletions
diff --git a/AUTHORS b/AUTHORS
index d4fbbd143..46fd9fd29 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -13,8 +13,11 @@ Abhinav Gupta <abhinav.g90@gmail.com>
Adrian Nos <nos.adrian@gmail.com>
Adrian O'Grady <elpollouk@gmail.com>
Adrien Bustany <adrien-xx-google@bustany.org>
+Ahmed Waheed Moanes <oneofone@gmail.com>
Akshat Kumar <seed@mail.nanosouffle.net>
+Alan Shreve <alan@inconshreveable.com>
Albert Strasheim <fullung@gmail.com>
+Alberto Donizetti <alb.donizetti@gmail.com>
Alberto García Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
Aleksandar Dezelin <dezelin@gmail.com>
Alex A Skinner <alex@lx.lc>
@@ -34,6 +37,7 @@ Amrut Joshi <amrut.joshi@gmail.com>
Andrei Vieru <euvieru@gmail.com>
Andrew Balholm <andybalholm@gmail.com>
Andrew Bonventre <andybons@chromium.org>
+Andrew Bursavich <abursavich@gmail.com>
Andrew Harding <andrew@spacemonkey.com>
Andrew Lutomirski <andy@luto.us>
Andrew Pritchard <awpritchard@gmail.com>
@@ -61,6 +65,7 @@ Aulus Egnatius Varialus <varialus@gmail.com>
Ben Olive <sionide21@gmail.com>
Benjamin Black <b@b3k.us>
Benny Siegert <bsiegert@gmail.com>
+Benoit Sigoure <tsunanet@gmail.com>
Berengar Lehr <berengar.lehr@gmx.de>
Billie Harold Cleek <bhcleek@gmail.com>
Bjorn Tillenius <bjorn@tillenius.me>
@@ -87,6 +92,7 @@ Chris Farmiloe <chrisfarms@gmail.com>
Chris Howey <howeyc@gmail.com>
Chris Jones <chris@cjones.org>
Chris Lennert <calennert@gmail.com>
+Chris McGee <sirnewton_01@yahoo.ca> <newton688@gmail.com>
Christian Himpel <chressie@googlemail.com>
Christine Hansmann <chhansmann@gmail.com>
Christoffer Buchholz <christoffer.buchholz@gmail.com>
@@ -98,6 +104,7 @@ Christopher Wedgwood <cw@f00f.org>
Clement Skau <clementskau@gmail.com>
Conrad Meyer <cemeyer@cs.washington.edu>
Corey Thomasson <cthom.lists@gmail.com>
+Cristian Staretu <unclejacksons@gmail.com>
Damian Gryski <dgryski@gmail.com>
Dan Callahan <dan.callahan@gmail.com>
Dan Peterson <dpiddy@gmail.com>
@@ -115,10 +122,12 @@ David du Colombier <0intro@gmail.com>
David Forsythe <dforsythe@gmail.com>
David G. Andersen <dave.andersen@gmail.com>
David Jakob Fritz <david.jakob.fritz@gmail.com>
+David Leon Gil <coruus@gmail.com>
David Thomas <davidthomas426@gmail.com>
David Titarenco <david.titarenco@gmail.com>
Dean Prichard <dean.prichard@gmail.com>
Denis Brandolini <denis.brandolini@gmail.com>
+Derek Parker <parkerderek86@gmail.com>
Devon H. O'Dell <devon.odell@gmail.com>
Dhiru Kholia <dhiru.kholia@gmail.com>
Dimitri Tcaciuc <dtcaciuc@gmail.com>
@@ -136,7 +145,7 @@ Egon Elbre <egonelbre@gmail.com>
Ehren Kret <ehren.kret@gmail.com>
Eivind Uggedal <eivind@uggedal.com>
Elias Naur <elias.naur@gmail.com>
-Emil Hessman <c.emil.hessman@gmail.com>
+Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com>
Eric Milliken <emilliken@gmail.com>
@@ -148,6 +157,8 @@ Evan Shaw <chickencha@gmail.com>
Ewan Chou <coocood@gmail.com>
Fabrizio Milo <mistobaan@gmail.com>
Fan Hongjian <fan.howard@gmail.com>
+Fastly, Inc.
+Fatih Arslan <fatih@arslan.io>
Fazlul Shahriar <fshahriar@gmail.com>
Felix Geisendörfer <haimuiba@gmail.com>
Firmansyah Adiputra <frm.adiputra@gmail.com>
@@ -157,6 +168,7 @@ Francisco Souza <franciscossouza@gmail.com>
Frederick Kelly Mayle III <frederickmayle@gmail.com>
Fredrik Enestad <fredrik.enestad@soundtrackyourbrand.com>
Frithjof Schulze <schulze@math.uni-hannover.de> <sfrithjof@gmail.com>
+Gabriel Aszalos <gabriel.aszalos@gmail.com>
Gary Burd <gary@beagledreams.com>
Gautham Thambidorai <gautham.dorai@gmail.com>
Georg Reinke <guelfey@gmail.com>
@@ -174,6 +186,8 @@ Gustavo Niemeyer <gustavo@niemeyer.net>
Gwenael Treguier <gwenn.kahz@gmail.com>
Harley Laue <losinggeneration@gmail.com>
Hector Chu <hectorchu@gmail.com>
+Hector Martin Cantero <hector@marcansoft.com>
+Henning Schmiedehausen <henning@schmiedehausen.org>
Henrik Edwards <henrik.edwards@gmail.com>
Herbert Georg Fischer <herbert.fischer@gmail.com>
Hong Ruiqi <hongruiqi@gmail.com>
@@ -203,17 +217,21 @@ Jeff Hodges <jeff@somethingsimilar.com>
Jeff R. Allen <jra@nella.org>
Jeff Sickel <jas@corpus-callosum.com>
Jeff Wendling <jeff@spacemonkey.com>
+Jens Frederich <jfrederich@gmail.com>
Jeremy Jackins <jeremyjackins@gmail.com>
Jim McGrath <jimmc2@gmail.com>
Jimmy Zelinskie <jimmyzelinskie@gmail.com>
Jingcheng Zhang <diogin@gmail.com>
Joakim Sernbrant <serbaut@gmail.com>
Joe Poirier <jdpoirier@gmail.com>
+Joe Shaw <joe@joeshaw.org>
+Joel Stemmer <stemmertech@gmail.com>
John Asmuth <jasmuth@gmail.com>
John C Barstow <jbowtie@amathaine.com>
John Graham-Cumming <jgc@jgc.org> <jgrahamc@gmail.com>
John Howard Palevich <jack.palevich@gmail.com>
John Shahid <jvshahid@gmail.com>
+John Tuley <john@tuley.org>
Jonathan Gold <jgold.bg@gmail.com>
Jonathan Mark <jhmark@xenops.com>
Jonathan Rudenberg <jonathan@titanous.com>
@@ -225,6 +243,7 @@ Josh Bleecher Snyder <josharian@gmail.com>
Josh Goebel <dreamer3@gmail.com>
Josh Holland <jrh@joshh.co.uk>
Joshua Chase <jcjoshuachase@gmail.com>
+JT Olds <jtolds@xnet5.com>
Jukka-Pekka Kekkonen <karatepekka@gmail.com>
Julian Phillips <julian@quantumfyre.co.uk>
Julien Schmidt <google@julienschmidt.com>
@@ -250,10 +269,13 @@ Lucio De Re <lucio.dere@gmail.com>
Luit van Drongelen <luitvd@gmail.com>
Luka Zakrajšek <tr00.g33k@gmail.com>
Luke Curley <qpingu@gmail.com>
+Manuel Mendez <mmendez534@gmail.com>
Marc Weistroff <marc@weistroff.net>
Marco Hennings <marco.hennings@freiheit.com>
+Mark Theunissen <mark.theunissen@gmail.com>
Marko Juhani Silokunnas <marko.silokunnas@gmail.com>
Marko Tiikkaja <marko@joh.to>
+Markover Inc. DBA Poptip
Markus Duft <markus.duft@salomon.at>
Markus Sonderegger <marraison@gmail.com>
Markus Zimmermann <zimmski@gmail.com>
@@ -276,6 +298,7 @@ Michael Fraenkel <michael.fraenkel@gmail.com>
Michael Gehring <mg@ebfe.org> <gnirheg.leahcim@gmail.com>
Michael Hoisie <hoisie@gmail.com>
Michael Lewis <mikelikespie@gmail.com>
+Michael MacInnis <Michael.P.MacInnis@gmail.com>
Michael Pearson <mipearson@gmail.com>
Michael Stapelberg <michael@stapelberg.de>
Michael Teichgräber <mteichgraeber@gmx.de>
@@ -295,6 +318,7 @@ Moriyoshi Koizumi <mozo@mozo.jp>
Môshe van der Sterre <moshevds@gmail.com>
Nan Deng <monnand@gmail.com>
Nathan John Youngman <nj@nathany.com>
+Nathan P Finch <nate.finch@gmail.com>
ngmoco, LLC
Nicholas Katsaros <nick@nickkatsaros.com>
Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com>
@@ -325,6 +349,7 @@ Paul Lalonde <paul.a.lalonde@gmail.com>
Paul Sbarra <Sbarra.Paul@gmail.com>
Paul van Brouwershaven <paul@vanbrouwershaven.com>
Pavel Zinovkin <pavel.zinovkin@gmail.com>
+Percy Wegmann <ox.to.a.cart@gmail.com>
Petar Maymounkov <petarm@gmail.com>
Peter Armitage <peter.armitage@gmail.com>
Peter Froehlich <peter.hans.froehlich@gmail.com>
@@ -340,6 +365,7 @@ Pietro Gagliardi <pietro10@mac.com>
Preetam Jinka <pj@preet.am>
Quan Yong Zhai <qyzhai@gmail.com>
Raif S. Naffah <go@naffah-raif.name>
+Red Hat, Inc.
Rémy Oudompheng <oudomphe@phare.normalesup.org>
Richard Crowley <r@rcrowley.org>
Richard Eric Gavaletz <gavaletz@gmail.com>
@@ -356,6 +382,7 @@ Rodrigo Moraes de Oliveira <rodrigo.moraes@gmail.com>
Rodrigo Rafael Monti Kochenburger <divoxx@gmail.com>
Roger Pau Monné <royger@gmail.com>
Roger Peppe <rogpeppe@gmail.com>
+Ron Hashimoto <mail@h2so5.net>
Ron Minnich <rminnich@gmail.com>
Ross Light <rlight2@gmail.com>
Rowan Worth <sqweek@gmail.com>
@@ -374,6 +401,7 @@ Shane Hansen <shanemhansen@gmail.com>
Shawn Smith <shawn.p.smith@gmail.com>
Shenghou Ma <minux.ma@gmail.com>
Shivakumar GN <shivakumar.gn@gmail.com>
+Simon Whitehead <chemnova@gmail.com>
Sokolov Yura <funny.falcon@gmail.com>
Spring Mc <heresy.mc@gmail.com>
StalkR <stalkr@stalkr.net>
@@ -390,10 +418,14 @@ Tad Glines <tad.glines@gmail.com>
Taj Khattra <taj.khattra@gmail.com>
Tarmigan Casebolt <tarmigan@gmail.com>
Taru Karttunen <taruti@taruti.net>
+Tetsuo Kiso <tetsuokiso9@gmail.com>
+Thiago Fransosi Farina <thiago.farina@gmail.com>
Thomas Alan Copeland <talan.copeland@gmail.com>
Thomas Kappler <tkappler@gmail.com>
Timo Savola <timo.savola@gmail.com>
+Timo Truyts <alkaloid.btx@gmail.com>
Tobias Columbus <tobias.columbus@gmail.com>
+Tom Linford <tomlinford@gmail.com>
Tor Andersson <tor.andersson@gmail.com>
Travis Cline <travis.cline@gmail.com>
Tudor Golubenco <tudor.g@gmail.com>
@@ -412,6 +444,7 @@ Wei Guangjing <vcc.163@gmail.com>
Willem van der Schyff <willemvds@gmail.com>
William Josephson <wjosephson@gmail.com>
William Orr <will@worrbase.com> <ay1244@gmail.com>
+Xia Bin <snyh@snyh.org>
Xing Xing <mikespook@gmail.com>
Yasuhiro Matsumoto <mattn.jp@gmail.com>
Yissakhar Z. Beck <yissakhar.beck@gmail.com>
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 372229848..b5e709ed6 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -38,9 +38,12 @@ Adam Langley <agl@golang.org>
Adrian Nos <nos.adrian@gmail.com>
Adrian O'Grady <elpollouk@gmail.com>
Adrien Bustany <adrien-xx-google@bustany.org>
+Ahmed Waheed Moanes <oneofone@gmail.com>
Akshat Kumar <seed@mail.nanosouffle.net>
Alan Donovan <adonovan@google.com>
+Alan Shreve <alan@inconshreveable.com>
Albert Strasheim <fullung@gmail.com>
+Alberto Donizetti <alb.donizetti@gmail.com>
Alberto García Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
Aleksandar Dezelin <dezelin@gmail.com>
Alex A Skinner <alex@lx.lc>
@@ -63,8 +66,10 @@ Amrut Joshi <amrut.joshi@gmail.com>
Andrea Spadaccini <spadaccio@google.com>
Andreas Jellinghaus <andreas@ionisiert.de> <anj@google.com>
Andrei Vieru <euvieru@gmail.com>
+Andres Erbsen <andreser@google.com>
Andrew Balholm <andybalholm@gmail.com>
Andrew Bonventre <andybons@chromium.org>
+Andrew Bursavich <abursavich@gmail.com>
Andrew Gerrand <adg@golang.org>
Andrew Harding <andrew@spacemonkey.com>
Andrew Lutomirski <andy@luto.us>
@@ -91,7 +96,7 @@ Arvindh Rajesh Tamilmani <art@a-30.net>
Asim Shankar <asimshankar@gmail.com>
Ato Araki <ato.araki@gmail.com>
Aulus Egnatius Varialus <varialus@gmail.com>
-Austin Clements <aclements@csail.mit.edu>
+Austin Clements <austin@google.com> <aclements@csail.mit.edu>
Balazs Lecz <leczb@google.com>
Ben Eitzen <eitzenb@golang.org>
Ben Fried <ben.fried@gmail.com>
@@ -99,6 +104,7 @@ Ben Lynn <benlynn@gmail.com>
Ben Olive <sionide21@gmail.com>
Benjamin Black <b@b3k.us>
Benny Siegert <bsiegert@gmail.com>
+Benoit Sigoure <tsunanet@gmail.com>
Berengar Lehr <Berengar.Lehr@gmx.de>
Bill Neubauer <wcn@golang.org> <wcn@google.com> <bill.neubauer@gmail.com>
Bill Thiede <couchmoney@gmail.com>
@@ -138,6 +144,7 @@ Chris Hundt <hundt@google.com>
Chris Jones <chris@cjones.org> <chris.jones.yar@gmail.com>
Chris Lennert <calennert@gmail.com>
Chris Manghane <cmang@golang.org>
+Chris McGee <sirnewton_01@yahoo.ca> <newton688@gmail.com>
Christian Himpel <chressie@googlemail.com> <chressie@gmail.com>
Christine Hansmann <chhansmann@gmail.com>
Christoffer Buchholz <christoffer.buchholz@gmail.com>
@@ -152,7 +159,9 @@ Colby Ranger <cranger@google.com>
Conrad Meyer <cemeyer@cs.washington.edu>
Corey Thomasson <cthom.lists@gmail.com>
Cosmos Nicolaou <cnicolaou@google.com>
+Cristian Staretu <unclejacksons@gmail.com>
Damian Gryski <dgryski@gmail.com>
+Damien Neil <dneil@google.com>
Dan Callahan <dan.callahan@gmail.com>
Dan Peterson <dpiddy@gmail.com>
Dan Sinclair <dan.sinclair@gmail.com>
@@ -177,6 +186,7 @@ David du Colombier <0intro@gmail.com>
David Forsythe <dforsythe@gmail.com>
David G. Andersen <dave.andersen@gmail.com>
David Jakob Fritz <david.jakob.fritz@gmail.com>
+David Leon Gil <coruus@gmail.com>
David McLeish <davemc@google.com>
David Presotto <presotto@gmail.com>
David Symonds <dsymonds@golang.org>
@@ -184,6 +194,7 @@ David Thomas <davidthomas426@gmail.com>
David Titarenco <david.titarenco@gmail.com>
Dean Prichard <dean.prichard@gmail.com>
Denis Brandolini <denis.brandolini@gmail.com>
+Derek Parker <parkerderek86@gmail.com>
Devon H. O'Dell <devon.odell@gmail.com>
Dhiru Kholia <dhiru.kholia@gmail.com>
Dimitri Tcaciuc <dtcaciuc@gmail.com>
@@ -195,6 +206,7 @@ Dominik Honnef <dominik.honnef@gmail.com>
Donovan Hide <donovanhide@gmail.com>
Drew Hintz <adhintz@google.com>
Duncan Holm <mail@frou.org>
+Dustin Long <dustmop@gmail.com>
Dustin Sallings <dsallings@gmail.com>
Dustin Shields-Cloues <dcloues@gmail.com>
Eden Li <eden.li@gmail.com>
@@ -202,7 +214,7 @@ Egon Elbre <egonelbre@gmail.com>
Ehren Kret <ehren.kret@gmail.com>
Eivind Uggedal <eivind@uggedal.com>
Elias Naur <elias.naur@gmail.com>
-Emil Hessman <c.emil.hessman@gmail.com>
+Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com>
Eric Milliken <emilliken@gmail.com>
@@ -210,11 +222,13 @@ Eric Roshan-Eisner <eric.d.eisner@gmail.com>
Erik St. Martin <alakriti@gmail.com>
Erik Westrup <erik.westrup@gmail.com>
Esko Luontola <esko.luontola@gmail.com>
+Evan Kroske <evankroske@google.com>
Evan Martin <evan.martin@gmail.com>
Evan Shaw <chickencha@gmail.com>
Ewan Chou <coocood@gmail.com>
Fabrizio Milo <mistobaan@gmail.com>
Fan Hongjian <fan.howard@gmail.com>
+Fatih Arslan <fatih@arslan.io>
Fazlul Shahriar <fshahriar@gmail.com>
Felix Geisendörfer <haimuiba@gmail.com>
Firmansyah Adiputra <frm.adiputra@gmail.com>
@@ -228,12 +242,14 @@ Fredrik Enestad <fredrik.enestad@soundtrackyourbrand.com>
Frithjof Schulze <schulze@math.uni-hannover.de> <sfrithjof@gmail.com>
Fumitoshi Ukai <ukai@google.com>
Gaal Yahas <gaal@google.com>
+Gabriel Aszalos <gabriel.aszalos@gmail.com>
Gary Burd <gary@beagledreams.com> <gary.burd@gmail.com>
Gautham Thambidorai <gautham.dorai@gmail.com>
Georg Reinke <guelfey@gmail.com>
Gerasimos Dimitriadis <gedimitr@gmail.com>
Gideon Jan-Wessel Redelinghuys <gjredelinghuys@gmail.com>
Giles Lean <giles.lean@pobox.com>
+Glenn Lewis <gmlewis@google.com>
Gordon Klaus <gordon.klaus@gmail.com>
Graham King <graham4king@gmail.com>
Graham Miller <graham.miller@gmail.com>
@@ -243,9 +259,12 @@ Gustav Paul <gustav.paul@gmail.com>
Gustavo Franco <gustavorfranco@gmail.com>
Gustavo Niemeyer <gustavo@niemeyer.net> <n13m3y3r@gmail.com>
Gwenael Treguier <gwenn.kahz@gmail.com>
+Hana Kim <hyangah@gmail.com>
Han-Wen Nienhuys <hanwen@google.com>
Harley Laue <losinggeneration@gmail.com>
Hector Chu <hectorchu@gmail.com>
+Hector Martin Cantero <hector@marcansoft.com>
+Henning Schmiedehausen <henning@schmiedehausen.org>
Henrik Edwards <henrik.edwards@gmail.com>
Herbert Georg Fischer <herbert.fischer@gmail.com>
Hong Ruiqi <hongruiqi@gmail.com>
@@ -264,6 +283,7 @@ James Fysh <james.fysh@gmail.com>
James Gray <james@james4k.com>
James Meneghello <rawrz0r@gmail.com>
James P. Cooper <jamespcooper@gmail.com>
+James Robinson <jamesr@google.com> <jamesr.gatech@gmail.com>
James Toy <nil@opensesame.st>
James Tucker <raggi@google.com>
James Whitehead <jnwhiteh@gmail.com>
@@ -281,10 +301,12 @@ Jason Del Ponte <delpontej@gmail.com>
Jason Travis <infomaniac7@gmail.com>
Jay Weisskopf <jay@jayschwa.net>
Jean-Marc Eurin <jmeurin@google.com>
+Jed Denlea <jed@fastly.com>
Jeff Hodges <jeff@somethingsimilar.com>
Jeff R. Allen <jra@nella.org> <jeff.allen@gmail.com>
Jeff Sickel <jas@corpus-callosum.com>
Jeff Wendling <jeff@spacemonkey.com>
+Jens Frederich <jfrederich@gmail.com>
Jeremiah Harmsen <jeremiah@google.com>
Jeremy Jackins <jeremyjackins@gmail.com>
Jeremy Schlatter <jeremy.schlatter@gmail.com>
@@ -293,7 +315,9 @@ Jimmy Zelinskie <jimmyzelinskie@gmail.com>
Jingcheng Zhang <diogin@gmail.com>
Joakim Sernbrant <serbaut@gmail.com>
Joe Poirier <jdpoirier@gmail.com>
+Joe Shaw <joe@joeshaw.org>
Joel Sing <jsing@google.com>
+Joel Stemmer <stemmertech@gmail.com>
Johan Euphrosine <proppy@google.com>
John Asmuth <jasmuth@gmail.com>
John Beisley <huin@google.com>
@@ -303,6 +327,7 @@ John Graham-Cumming <jgc@jgc.org> <jgrahamc@gmail.com>
John Howard Palevich <jack.palevich@gmail.com>
John Newlin <jnewlin@google.com>
John Shahid <jvshahid@gmail.com>
+John Tuley <john@tuley.org>
Jonathan Allie <jonallie@google.com>
Jonathan Feinberg <feinberg@google.com>
Jonathan Gold <jgold.bg@gmail.com>
@@ -323,6 +348,7 @@ Josh Hoak <jhoak@google.com>
Josh Holland <jrh@joshh.co.uk>
Joshua Chase <jcjoshuachase@gmail.com>
JP Sugarbroad <jpsugar@google.com>
+JT Olds <jtolds@xnet5.com>
Jukka-Pekka Kekkonen <karatepekka@gmail.com>
Julian Phillips <julian@quantumfyre.co.uk>
Julien Schmidt <google@julienschmidt.com>
@@ -357,9 +383,11 @@ Luke Curley <qpingu@gmail.com>
Luuk van Dijk <lvd@golang.org> <lvd@google.com>
Manoj Dayaram <platform-dev@moovweb.com> <manoj.dayaram@moovweb.com>
Manu Garg <manugarg@google.com>
+Manuel Mendez <mmendez534@gmail.com>
Marc Weistroff <marc@weistroff.net>
Marcel van Lohuizen <mpvl@golang.org>
Marco Hennings <marco.hennings@freiheit.com>
+Mark Theunissen <mark.theunissen@gmail.com>
Mark Zavislak <zavislak@google.com>
Marko Juhani Silokunnas <marko.silokunnas@gmail.com>
Marko Mikulicic <mkm@google.com>
@@ -393,6 +421,7 @@ Michael Hoisie <hoisie@gmail.com>
Michael Hudson-Doyle <michael.hudson@linaro.org>
Michael Kelly <mjk@google.com>
Michael Lewis <mikelikespie@gmail.com>
+Michael MacInnis <Michael.P.MacInnis@gmail.com>
Michael Matloob <matloob@google.com>
Michael Pearson <mipearson@gmail.com>
Michael Piatek <piatek@google.com>
@@ -415,12 +444,15 @@ Mikkel Krautz <mikkel@krautz.dk> <krautz@gmail.com>
Miquel Sabaté Solà <mikisabate@gmail.com>
Moriyoshi Koizumi <mozo@mozo.jp>
Môshe van der Sterre <moshevds@gmail.com>
+Mrunal Patel <mrunalp@gmail.com>
Nan Deng <monnand@gmail.com>
Nathan John Youngman <nj@nathany.com>
+Nathan P Finch <nate.finch@gmail.com>
Nicholas Katsaros <nick@nickkatsaros.com>
Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com>
Nicholas Sullivan <nicholas.sullivan@gmail.com>
Nicholas Waples <nwaples@gmail.com>
+Nick Cooper <nmvc@google.com>
Nick Craig-Wood <nick@craig-wood.com> <nickcw@gmail.com>
Nicolas Kaiser <nikai@nikai.net>
Nicolas Owens <mischief@offblast.org>
@@ -447,10 +479,12 @@ Paul Borman <borman@google.com>
Paul Chang <paulchang@google.com>
Paul Hammond <paul@paulhammond.org>
Paul Lalonde <paul.a.lalonde@gmail.com>
+Paul Nasrat <pnasrat@google.com>
Paul Sbarra <Sbarra.Paul@gmail.com>
Paul van Brouwershaven <paul@vanbrouwershaven.com>
Pavel Zinovkin <pavel.zinovkin@gmail.com>
Pawel Szczur <filemon@google.com>
+Percy Wegmann <ox.to.a.cart@gmail.com>
Petar Maymounkov <petarm@gmail.com>
Peter Armitage <peter.armitage@gmail.com>
Peter Collingbourne <pcc@google.com>
@@ -472,11 +506,13 @@ Preetam Jinka <pj@preet.am>
Quan Yong Zhai <qyzhai@gmail.com>
Raif S. Naffah <go@naffah-raif.name>
Raph Levien <raph@google.com>
+Raul Silvera <rsilvera@google.com>
Rémy Oudompheng <oudomphe@phare.normalesup.org> <remyoudompheng@gmail.com>
Richard Crowley <r@rcrowley.org>
Richard Eric Gavaletz <gavaletz@gmail.com>
Richard Musiol <mail@richard-musiol.de> <neelance@gmail.com>
Rick Arnold <rickarnoldjr@gmail.com>
+Rick Hudson <rlh@golang.org>
Risto Jaakko Saarelma <rsaarelm@gmail.com>
Rob Pike <r@golang.org>
Robert Daniel Kortschak <dan.kortschak@adelaide.edu.au>
@@ -492,6 +528,7 @@ Rodrigo Moraes de Oliveira <rodrigo.moraes@gmail.com>
Rodrigo Rafael Monti Kochenburger <divoxx@gmail.com>
Roger Pau Monné <royger@gmail.com>
Roger Peppe <rogpeppe@gmail.com>
+Ron Hashimoto <mail@h2so5.net>
Ron Minnich <rminnich@gmail.com>
Ross Light <rlight2@gmail.com>
Rowan Worth <sqweek@gmail.com>
@@ -518,6 +555,7 @@ Shawn Ledbetter <sledbetter@google.com>
Shawn Smith <shawn.p.smith@gmail.com>
Shenghou Ma <minux@golang.org> <minux.ma@gmail.com>
Shivakumar GN <shivakumar.gn@gmail.com>
+Simon Whitehead <chemnova@gmail.com>
Sokolov Yura <funny.falcon@gmail.com>
Spring Mc <heresy.mc@gmail.com>
StalkR <stalkr@stalkr.net>
@@ -536,12 +574,16 @@ Tad Glines <tad.glines@gmail.com>
Taj Khattra <taj.khattra@gmail.com>
Tarmigan Casebolt <tarmigan@gmail.com>
Taru Karttunen <taruti@taruti.net>
+Tetsuo Kiso <tetsuokiso9@gmail.com>
+Thiago Fransosi Farina <thiago.farina@gmail.com> <tfarina@chromium.org>
Thomas Alan Copeland <talan.copeland@gmail.com>
Thomas Habets <habets@google.com>
Thomas Kappler <tkappler@gmail.com>
Timo Savola <timo.savola@gmail.com>
+Timo Truyts <alkaloid.btx@gmail.com>
Tobias Columbus <tobias.columbus@gmail.com> <tobias.columbus@googlemail.com>
Todd Wang <toddwang@gmail.com>
+Tom Linford <tomlinford@gmail.com>
Tom Szymanski <tgs@google.com>
Tor Andersson <tor.andersson@gmail.com>
Travis Cline <travis.cline@gmail.com>
@@ -566,6 +608,7 @@ Willem van der Schyff <willemvds@gmail.com>
William Chan <willchan@chromium.org>
William Josephson <wjosephson@gmail.com>
William Orr <will@worrbase.com> <ay1244@gmail.com>
+Xia Bin <snyh@snyh.org>
Xing Xing <mikespook@gmail.com>
Yan Zou <yzou@google.com>
Yasuhiro Matsumoto <mattn.jp@gmail.com>
diff --git a/VERSION b/VERSION
index 61592c338..40c8f5c53 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-go1.3.3 \ No newline at end of file
+go1.4 \ No newline at end of file
diff --git a/api/except.txt b/api/except.txt
index 1a8296635..6e40e1844 100644
--- a/api/except.txt
+++ b/api/except.txt
@@ -327,3 +327,4 @@ pkg syscall (netbsd-arm), const SizeofIfData = 132
pkg syscall (netbsd-arm), type IfMsghdr struct, Pad_cgo_1 [4]uint8
pkg syscall (netbsd-arm-cgo), const SizeofIfData = 132
pkg syscall (netbsd-arm-cgo), type IfMsghdr struct, Pad_cgo_1 [4]uint8
+pkg unicode, const Version = "6.3.0"
diff --git a/api/go1.4.txt b/api/go1.4.txt
new file mode 100644
index 000000000..08cb17f86
--- /dev/null
+++ b/api/go1.4.txt
@@ -0,0 +1,604 @@
+# CL 134210043 archive/zip: add Writer.Flush, Brad Fitzpatrick <bradfitz@golang.org>
+pkg archive/zip, method (*Writer) Flush() error
+
+# CL 97140043 compress/flate: add Reset() to allow reusing large buffers to compress multiple buffers, James Robinson <jamesr@google.com>
+pkg compress/flate, type Resetter interface { Reset }
+pkg compress/flate, type Resetter interface, Reset(io.Reader, []uint8) error
+pkg compress/zlib, type Resetter interface { Reset }
+pkg compress/zlib, type Resetter interface, Reset(io.Reader, []uint8) error
+
+# CL 159120044 compress/gzip: allow stopping at end of first stream, Russ Cox <rsc@golang.org>
+pkg compress/gzip, method (*Reader) Multistream(bool)
+
+# CL 138800043 crypto: Add SHA3 functions in go.crypto/sha3 to the Hash enum., David Leon Gil <coruus@gmail.com>
+pkg crypto, const SHA3_224 = 10
+pkg crypto, const SHA3_224 Hash
+pkg crypto, const SHA3_256 = 11
+pkg crypto, const SHA3_256 Hash
+pkg crypto, const SHA3_384 = 12
+pkg crypto, const SHA3_384 Hash
+pkg crypto, const SHA3_512 = 13
+pkg crypto, const SHA3_512 Hash
+
+# CL 114680043 crypto: add Signer, Adam Langley <agl@golang.org>
+pkg crypto, method (Hash) HashFunc() Hash
+pkg crypto, type Signer interface { Public, Sign }
+pkg crypto, type Signer interface, Public() PublicKey
+pkg crypto, type Signer interface, Sign(io.Reader, []uint8, SignerOpts) ([]uint8, error)
+pkg crypto, type SignerOpts interface { HashFunc }
+pkg crypto, type SignerOpts interface, HashFunc() Hash
+pkg crypto/ecdsa, method (*PrivateKey) Public() crypto.PublicKey
+pkg crypto/ecdsa, method (*PrivateKey) Sign(io.Reader, []uint8, crypto.SignerOpts) ([]uint8, error)
+pkg crypto/rsa, method (*PSSOptions) HashFunc() crypto.Hash
+pkg crypto/rsa, method (*PrivateKey) Public() crypto.PublicKey
+pkg crypto/rsa, method (*PrivateKey) Sign(io.Reader, []uint8, crypto.SignerOpts) ([]uint8, error)
+pkg crypto/rsa, type PSSOptions struct, Hash crypto.Hash
+
+# CL 157090043 crypto/tls: support TLS_FALLBACK_SCSV as a server., Adam Langley <agl@golang.org>
+pkg crypto/tls, const TLS_FALLBACK_SCSV = 22016
+pkg crypto/tls, const TLS_FALLBACK_SCSV uint16
+
+# CL 107400043 crypto/tls: Added dynamic alternative to NameToCertificate map for SNI, Percy Wegmann <ox.to.a.cart@gmail.com>
+pkg crypto/tls, type ClientHelloInfo struct
+pkg crypto/tls, type ClientHelloInfo struct, CipherSuites []uint16
+pkg crypto/tls, type ClientHelloInfo struct, ServerName string
+pkg crypto/tls, type ClientHelloInfo struct, SupportedCurves []CurveID
+pkg crypto/tls, type ClientHelloInfo struct, SupportedPoints []uint8
+pkg crypto/tls, type Config struct, GetCertificate func(*ClientHelloInfo) (*Certificate, error)
+pkg crypto/tls, type ConnectionState struct, TLSUnique []uint8
+
+# CL 153420045 crypto/x509: continue to recognise MaxPathLen of zero as "no value"., Adam Langley <agl@golang.org>
+pkg crypto/x509, type Certificate struct, MaxPathLenZero bool
+
+# CL 158950043 database/sql: add Drivers, returning list of registered drivers, Russ Cox <rsc@golang.org>
+pkg database/sql, func Drivers() []string
+
+# CL 117280043 debug/dwarf: fix Reader panic on DW_TAG_unspecified_type, Derek Parker <parkerderek86@gmail.com>
+pkg debug/dwarf, method (*UnspecifiedType) Basic() *BasicType
+pkg debug/dwarf, method (*UnspecifiedType) Common() *CommonType
+pkg debug/dwarf, method (*UnspecifiedType) Size() int64
+pkg debug/dwarf, method (*UnspecifiedType) String() string
+pkg debug/dwarf, type UnspecifiedType struct
+pkg debug/dwarf, type UnspecifiedType struct, embedded BasicType
+
+# CL 132000043 debug/elf: support arm64 relocations, Michael Hudson-Doyle <michael.hudson@linaro.org>
+pkg debug/elf, const EM_AARCH64 = 183
+pkg debug/elf, const EM_AARCH64 Machine
+pkg debug/elf, const R_AARCH64_ABS16 = 259
+pkg debug/elf, const R_AARCH64_ABS16 R_AARCH64
+pkg debug/elf, const R_AARCH64_ABS32 = 258
+pkg debug/elf, const R_AARCH64_ABS32 R_AARCH64
+pkg debug/elf, const R_AARCH64_ABS64 = 257
+pkg debug/elf, const R_AARCH64_ABS64 R_AARCH64
+pkg debug/elf, const R_AARCH64_ADD_ABS_LO12_NC = 277
+pkg debug/elf, const R_AARCH64_ADD_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_ADR_GOT_PAGE = 311
+pkg debug/elf, const R_AARCH64_ADR_GOT_PAGE R_AARCH64
+pkg debug/elf, const R_AARCH64_ADR_PREL_LO21 = 274
+pkg debug/elf, const R_AARCH64_ADR_PREL_LO21 R_AARCH64
+pkg debug/elf, const R_AARCH64_ADR_PREL_PG_HI21 = 275
+pkg debug/elf, const R_AARCH64_ADR_PREL_PG_HI21 R_AARCH64
+pkg debug/elf, const R_AARCH64_ADR_PREL_PG_HI21_NC = 276
+pkg debug/elf, const R_AARCH64_ADR_PREL_PG_HI21_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_CALL26 = 283
+pkg debug/elf, const R_AARCH64_CALL26 R_AARCH64
+pkg debug/elf, const R_AARCH64_CONDBR19 = 280
+pkg debug/elf, const R_AARCH64_CONDBR19 R_AARCH64
+pkg debug/elf, const R_AARCH64_COPY = 1024
+pkg debug/elf, const R_AARCH64_COPY R_AARCH64
+pkg debug/elf, const R_AARCH64_GLOB_DAT = 1025
+pkg debug/elf, const R_AARCH64_GLOB_DAT R_AARCH64
+pkg debug/elf, const R_AARCH64_GOT_LD_PREL19 = 309
+pkg debug/elf, const R_AARCH64_GOT_LD_PREL19 R_AARCH64
+pkg debug/elf, const R_AARCH64_IRELATIVE = 1032
+pkg debug/elf, const R_AARCH64_IRELATIVE R_AARCH64
+pkg debug/elf, const R_AARCH64_JUMP26 = 282
+pkg debug/elf, const R_AARCH64_JUMP26 R_AARCH64
+pkg debug/elf, const R_AARCH64_JUMP_SLOT = 1026
+pkg debug/elf, const R_AARCH64_JUMP_SLOT R_AARCH64
+pkg debug/elf, const R_AARCH64_LD64_GOT_LO12_NC = 312
+pkg debug/elf, const R_AARCH64_LD64_GOT_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_LDST128_ABS_LO12_NC = 299
+pkg debug/elf, const R_AARCH64_LDST128_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_LDST16_ABS_LO12_NC = 284
+pkg debug/elf, const R_AARCH64_LDST16_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_LDST32_ABS_LO12_NC = 285
+pkg debug/elf, const R_AARCH64_LDST32_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_LDST64_ABS_LO12_NC = 286
+pkg debug/elf, const R_AARCH64_LDST64_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_LDST8_ABS_LO12_NC = 278
+pkg debug/elf, const R_AARCH64_LDST8_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_LD_PREL_LO19 = 273
+pkg debug/elf, const R_AARCH64_LD_PREL_LO19 R_AARCH64
+pkg debug/elf, const R_AARCH64_MOVW_SABS_G0 = 270
+pkg debug/elf, const R_AARCH64_MOVW_SABS_G0 R_AARCH64
+pkg debug/elf, const R_AARCH64_MOVW_SABS_G1 = 271
+pkg debug/elf, const R_AARCH64_MOVW_SABS_G1 R_AARCH64
+pkg debug/elf, const R_AARCH64_MOVW_SABS_G2 = 272
+pkg debug/elf, const R_AARCH64_MOVW_SABS_G2 R_AARCH64
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G0 = 263
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G0 R_AARCH64
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G0_NC = 264
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G0_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G1 = 265
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G1 R_AARCH64
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G1_NC = 266
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G1_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G2 = 267
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G2 R_AARCH64
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G2_NC = 268
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G2_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G3 = 269
+pkg debug/elf, const R_AARCH64_MOVW_UABS_G3 R_AARCH64
+pkg debug/elf, const R_AARCH64_NONE = 0
+pkg debug/elf, const R_AARCH64_NONE R_AARCH64
+pkg debug/elf, const R_AARCH64_NULL = 256
+pkg debug/elf, const R_AARCH64_NULL R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_ABS16 = 2
+pkg debug/elf, const R_AARCH64_P32_ABS16 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_ABS32 = 1
+pkg debug/elf, const R_AARCH64_P32_ABS32 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_ADD_ABS_LO12_NC = 12
+pkg debug/elf, const R_AARCH64_P32_ADD_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_ADR_GOT_PAGE = 26
+pkg debug/elf, const R_AARCH64_P32_ADR_GOT_PAGE R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_ADR_PREL_LO21 = 10
+pkg debug/elf, const R_AARCH64_P32_ADR_PREL_LO21 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_ADR_PREL_PG_HI21 = 11
+pkg debug/elf, const R_AARCH64_P32_ADR_PREL_PG_HI21 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_CALL26 = 21
+pkg debug/elf, const R_AARCH64_P32_CALL26 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_CONDBR19 = 19
+pkg debug/elf, const R_AARCH64_P32_CONDBR19 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_COPY = 180
+pkg debug/elf, const R_AARCH64_P32_COPY R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_GLOB_DAT = 181
+pkg debug/elf, const R_AARCH64_P32_GLOB_DAT R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_GOT_LD_PREL19 = 25
+pkg debug/elf, const R_AARCH64_P32_GOT_LD_PREL19 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_IRELATIVE = 188
+pkg debug/elf, const R_AARCH64_P32_IRELATIVE R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_JUMP26 = 20
+pkg debug/elf, const R_AARCH64_P32_JUMP26 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_JUMP_SLOT = 182
+pkg debug/elf, const R_AARCH64_P32_JUMP_SLOT R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_LD32_GOT_LO12_NC = 27
+pkg debug/elf, const R_AARCH64_P32_LD32_GOT_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_LDST128_ABS_LO12_NC = 17
+pkg debug/elf, const R_AARCH64_P32_LDST128_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_LDST16_ABS_LO12_NC = 14
+pkg debug/elf, const R_AARCH64_P32_LDST16_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_LDST32_ABS_LO12_NC = 15
+pkg debug/elf, const R_AARCH64_P32_LDST32_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_LDST64_ABS_LO12_NC = 16
+pkg debug/elf, const R_AARCH64_P32_LDST64_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_LDST8_ABS_LO12_NC = 13
+pkg debug/elf, const R_AARCH64_P32_LDST8_ABS_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_LD_PREL_LO19 = 9
+pkg debug/elf, const R_AARCH64_P32_LD_PREL_LO19 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_MOVW_SABS_G0 = 8
+pkg debug/elf, const R_AARCH64_P32_MOVW_SABS_G0 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G0 = 5
+pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G0 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G0_NC = 6
+pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G0_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G1 = 7
+pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G1 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_PREL16 = 4
+pkg debug/elf, const R_AARCH64_P32_PREL16 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_PREL32 = 3
+pkg debug/elf, const R_AARCH64_P32_PREL32 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_RELATIVE = 183
+pkg debug/elf, const R_AARCH64_P32_RELATIVE R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSDESC = 187
+pkg debug/elf, const R_AARCH64_P32_TLSDESC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADD_LO12_NC = 126
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADD_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADR_PAGE21 = 124
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADR_PAGE21 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADR_PREL21 = 123
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADR_PREL21 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_CALL = 127
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_CALL R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_LD32_LO12_NC = 125
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_LD32_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_LD_PREL19 = 122
+pkg debug/elf, const R_AARCH64_P32_TLSDESC_LD_PREL19 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSGD_ADD_LO12_NC = 82
+pkg debug/elf, const R_AARCH64_P32_TLSGD_ADD_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSGD_ADR_PAGE21 = 81
+pkg debug/elf, const R_AARCH64_P32_TLSGD_ADR_PAGE21 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21 = 103
+pkg debug/elf, const R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC = 104
+pkg debug/elf, const R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19 = 105
+pkg debug/elf, const R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_HI12 = 109
+pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_HI12 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_LO12 = 110
+pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_LO12 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC = 111
+pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G0 = 107
+pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G0 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC = 108
+pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G1 = 106
+pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G1 R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLS_DTPMOD = 184
+pkg debug/elf, const R_AARCH64_P32_TLS_DTPMOD R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLS_DTPREL = 185
+pkg debug/elf, const R_AARCH64_P32_TLS_DTPREL R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TLS_TPREL = 186
+pkg debug/elf, const R_AARCH64_P32_TLS_TPREL R_AARCH64
+pkg debug/elf, const R_AARCH64_P32_TSTBR14 = 18
+pkg debug/elf, const R_AARCH64_P32_TSTBR14 R_AARCH64
+pkg debug/elf, const R_AARCH64_PREL16 = 262
+pkg debug/elf, const R_AARCH64_PREL16 R_AARCH64
+pkg debug/elf, const R_AARCH64_PREL32 = 261
+pkg debug/elf, const R_AARCH64_PREL32 R_AARCH64
+pkg debug/elf, const R_AARCH64_PREL64 = 260
+pkg debug/elf, const R_AARCH64_PREL64 R_AARCH64
+pkg debug/elf, const R_AARCH64_RELATIVE = 1027
+pkg debug/elf, const R_AARCH64_RELATIVE R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSDESC = 1031
+pkg debug/elf, const R_AARCH64_TLSDESC R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSDESC_ADD = 568
+pkg debug/elf, const R_AARCH64_TLSDESC_ADD R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSDESC_ADD_LO12_NC = 564
+pkg debug/elf, const R_AARCH64_TLSDESC_ADD_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSDESC_ADR_PAGE21 = 562
+pkg debug/elf, const R_AARCH64_TLSDESC_ADR_PAGE21 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSDESC_ADR_PREL21 = 561
+pkg debug/elf, const R_AARCH64_TLSDESC_ADR_PREL21 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSDESC_CALL = 569
+pkg debug/elf, const R_AARCH64_TLSDESC_CALL R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSDESC_LD64_LO12_NC = 563
+pkg debug/elf, const R_AARCH64_TLSDESC_LD64_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSDESC_LDR = 567
+pkg debug/elf, const R_AARCH64_TLSDESC_LDR R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSDESC_LD_PREL19 = 560
+pkg debug/elf, const R_AARCH64_TLSDESC_LD_PREL19 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSDESC_OFF_G0_NC = 566
+pkg debug/elf, const R_AARCH64_TLSDESC_OFF_G0_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSDESC_OFF_G1 = 565
+pkg debug/elf, const R_AARCH64_TLSDESC_OFF_G1 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSGD_ADD_LO12_NC = 514
+pkg debug/elf, const R_AARCH64_TLSGD_ADD_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSGD_ADR_PAGE21 = 513
+pkg debug/elf, const R_AARCH64_TLSGD_ADR_PAGE21 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 541
+pkg debug/elf, const R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542
+pkg debug/elf, const R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 543
+pkg debug/elf, const R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 540
+pkg debug/elf, const R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 539
+pkg debug/elf, const R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_HI12 = 549
+pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_HI12 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_LO12 = 550
+pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_LO12 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 551
+pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_LO12_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547
+pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G0 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 548
+pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G0_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G1 = 545
+pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G1 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 546
+pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G1_NC R_AARCH64
+pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G2 = 544
+pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G2 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLS_DTPMOD64 = 1028
+pkg debug/elf, const R_AARCH64_TLS_DTPMOD64 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLS_DTPREL64 = 1029
+pkg debug/elf, const R_AARCH64_TLS_DTPREL64 R_AARCH64
+pkg debug/elf, const R_AARCH64_TLS_TPREL64 = 1030
+pkg debug/elf, const R_AARCH64_TLS_TPREL64 R_AARCH64
+pkg debug/elf, const R_AARCH64_TSTBR14 = 279
+pkg debug/elf, const R_AARCH64_TSTBR14 R_AARCH64
+pkg debug/elf, method (R_AARCH64) GoString() string
+pkg debug/elf, method (R_AARCH64) String() string
+pkg debug/elf, type R_AARCH64 int
+
+# CL 107530043 debug/elf: add (*File).DynamicSymbols, ErrNoSymbols, and tests for (*File).Symbols and (*File).DynamicSymbols, and formalize symbol order., Pietro Gagliardi <pietro10@mac.com>
+pkg debug/elf, method (*File) DynamicSymbols() ([]Symbol, error)
+pkg debug/elf, var ErrNoSymbols error
+
+# CL 106460044 debug/plan9obj, cmd/addr2line: on Plan 9 use a.out header, Aram Hăvărneanu <aram@mgk.ro>
+pkg debug/plan9obj, type FileHeader struct, HdrSize uint64
+pkg debug/plan9obj, type FileHeader struct, LoadAddress uint64
+
+# CL 122960043 encoding/xml: add InputOffset method to Decoder, Russ Cox <rsc@golang.org>
+pkg encoding/xml, method (*Decoder) InputOffset() int64
+
+# CL 124940043 cmd/go, go/build: implement import comment checking, Russ Cox <rsc@golang.org>
+pkg go/build, const ImportComment = 4
+pkg go/build, const ImportComment ImportMode
+pkg go/build, type Package struct, ImportComment string
+
+# CL 155050043 go/build: Return MultiplePackageError on importing a dir containing multiple packages, Jens Frederich <jfrederich@gmail.com>
+pkg go/build, method (*MultiplePackageError) Error() string
+pkg go/build, type MultiplePackageError struct
+pkg go/build, type MultiplePackageError struct, Dir string
+pkg go/build, type MultiplePackageError struct, Files []string
+pkg go/build, type MultiplePackageError struct, Packages []string
+
+# CL 135110044 go/token: implement PositionFor accessors, Robert Griesemer <gri@golang.org>
+pkg go/token, method (*File) PositionFor(Pos, bool) Position
+pkg go/token, method (*FileSet) PositionFor(Pos, bool) Position
+
+# CL 109000049 image: add RGBAAt, Gray16At, etc., ChaiShushan <chaishushan@gmail.com>
+pkg image, method (*Alpha) AlphaAt(int, int) color.Alpha
+pkg image, method (*Alpha16) Alpha16At(int, int) color.Alpha16
+pkg image, method (*Gray) GrayAt(int, int) color.Gray
+pkg image, method (*Gray16) Gray16At(int, int) color.Gray16
+pkg image, method (*NRGBA) NRGBAAt(int, int) color.NRGBA
+pkg image, method (*NRGBA64) NRGBA64At(int, int) color.NRGBA64
+pkg image, method (*RGBA) RGBAAt(int, int) color.RGBA
+pkg image, method (*RGBA64) RGBA64At(int, int) color.RGBA64
+pkg image, method (*YCbCr) YCbCrAt(int, int) color.YCbCr
+
+# CL 129190043 png: make the encoder configurable, Jeff R. Allen <jra@nella.org>
+pkg image/png, const BestCompression = -3
+pkg image/png, const BestCompression CompressionLevel
+pkg image/png, const BestSpeed = -2
+pkg image/png, const BestSpeed CompressionLevel
+pkg image/png, const DefaultCompression = 0
+pkg image/png, const DefaultCompression CompressionLevel
+pkg image/png, const NoCompression = -1
+pkg image/png, const NoCompression CompressionLevel
+pkg image/png, method (*Encoder) Encode(io.Writer, image.Image) error
+pkg image/png, type CompressionLevel int
+pkg image/png, type Encoder struct
+pkg image/png, type Encoder struct, CompressionLevel CompressionLevel
+
+# CL 101750048 math: implement Nextafter32, Robert Griesemer <gri@golang.org>
+pkg math, func Nextafter32(float32, float32) float32
+
+# CL 93550043 math/big: implement Rat.Float32, Robert Griesemer <gri@golang.org>
+pkg math/big, method (*Rat) Float32() (float32, bool)
+
+# CL 76540043 net/http: add BasicAuth method to *http.Request, Kelsey Hightower <kelsey.hightower@gmail.com>
+pkg net/http, method (*Request) BasicAuth() (string, string, bool)
+
+# CL 137940043 net/http: add Transport.DialTLS hook, Brad Fitzpatrick <bradfitz@golang.org>
+pkg net/http, type Transport struct, DialTLS func(string, string) (net.Conn, error)
+
+# CL 132750043 net/http/httputil: Pass a Logger to ReverseProxy, allowing the user to control logging., Mark Theunissen <mark.theunissen@gmail.com>
+pkg net/http/httputil, type ReverseProxy struct, ErrorLog *log.Logger
+
+# CL 148370043 os, syscall: add Unsetenv, Brad Fitzpatrick <bradfitz@golang.org>
+pkg os, func Unsetenv(string) error
+pkg syscall, func Unsetenv(string) error
+
+# CL 144020043 reflect: add Type.Comparable, Russ Cox <rsc@golang.org>
+pkg reflect, type Type interface, Comparable() bool
+
+# CL 153670043 runtime: add PauseEnd array to MemStats and GCStats, Jens Frederich <jfrederich@gmail.com>
+pkg runtime, type MemStats struct, PauseEnd [256]uint64
+pkg runtime/debug, type GCStats struct, PauseEnd []time.Time
+
+# CL 136710045 sync/atomic: add Value, Dmitriy Vyukov <dvyukov@google.com>
+pkg sync/atomic, method (*Value) Load() interface{}
+pkg sync/atomic, method (*Value) Store(interface{})
+pkg sync/atomic, type Value struct
+
+# CL 126190043 syscall: support UID/GID map files for Linux user namespaces, Mrunal Patel <mrunalp@gmail.com>
+pkg syscall (linux-386), type SysProcAttr struct, GidMappings []SysProcIDMap
+pkg syscall (linux-386), type SysProcAttr struct, UidMappings []SysProcIDMap
+pkg syscall (linux-386), type SysProcIDMap struct
+pkg syscall (linux-386), type SysProcIDMap struct, ContainerID int
+pkg syscall (linux-386), type SysProcIDMap struct, HostID int
+pkg syscall (linux-386), type SysProcIDMap struct, Size int
+pkg syscall (linux-386-cgo), type SysProcAttr struct, GidMappings []SysProcIDMap
+pkg syscall (linux-386-cgo), type SysProcAttr struct, UidMappings []SysProcIDMap
+pkg syscall (linux-386-cgo), type SysProcIDMap struct
+pkg syscall (linux-386-cgo), type SysProcIDMap struct, ContainerID int
+pkg syscall (linux-386-cgo), type SysProcIDMap struct, HostID int
+pkg syscall (linux-386-cgo), type SysProcIDMap struct, Size int
+pkg syscall (linux-amd64), type SysProcAttr struct, GidMappings []SysProcIDMap
+pkg syscall (linux-amd64), type SysProcAttr struct, UidMappings []SysProcIDMap
+pkg syscall (linux-amd64), type SysProcIDMap struct
+pkg syscall (linux-amd64), type SysProcIDMap struct, ContainerID int
+pkg syscall (linux-amd64), type SysProcIDMap struct, HostID int
+pkg syscall (linux-amd64), type SysProcIDMap struct, Size int
+pkg syscall (linux-amd64-cgo), type SysProcAttr struct, GidMappings []SysProcIDMap
+pkg syscall (linux-amd64-cgo), type SysProcAttr struct, UidMappings []SysProcIDMap
+pkg syscall (linux-amd64-cgo), type SysProcIDMap struct
+pkg syscall (linux-amd64-cgo), type SysProcIDMap struct, ContainerID int
+pkg syscall (linux-amd64-cgo), type SysProcIDMap struct, HostID int
+pkg syscall (linux-amd64-cgo), type SysProcIDMap struct, Size int
+pkg syscall (linux-arm), type SysProcAttr struct, GidMappings []SysProcIDMap
+pkg syscall (linux-arm), type SysProcAttr struct, UidMappings []SysProcIDMap
+pkg syscall (linux-arm), type SysProcIDMap struct
+pkg syscall (linux-arm), type SysProcIDMap struct, ContainerID int
+pkg syscall (linux-arm), type SysProcIDMap struct, HostID int
+pkg syscall (linux-arm), type SysProcIDMap struct, Size int
+pkg syscall (linux-arm-cgo), type SysProcAttr struct, GidMappings []SysProcIDMap
+pkg syscall (linux-arm-cgo), type SysProcAttr struct, UidMappings []SysProcIDMap
+pkg syscall (linux-arm-cgo), type SysProcIDMap struct
+pkg syscall (linux-arm-cgo), type SysProcIDMap struct, ContainerID int
+pkg syscall (linux-arm-cgo), type SysProcIDMap struct, HostID int
+pkg syscall (linux-arm-cgo), type SysProcIDMap struct, Size int
+
+# CL 122200043 net: fix CNAME resolving on Windows, Egon Elbre <egonelbre@gmail.com>
+pkg syscall (windows-386), const DNS_INFO_NO_RECORDS = 9501
+pkg syscall (windows-386), const DNS_INFO_NO_RECORDS ideal-int
+pkg syscall (windows-386), const DnsSectionAdditional = 3
+pkg syscall (windows-386), const DnsSectionAdditional ideal-int
+pkg syscall (windows-386), const DnsSectionAnswer = 1
+pkg syscall (windows-386), const DnsSectionAnswer ideal-int
+pkg syscall (windows-386), const DnsSectionAuthority = 2
+pkg syscall (windows-386), const DnsSectionAuthority ideal-int
+pkg syscall (windows-386), const DnsSectionQuestion = 0
+pkg syscall (windows-386), const DnsSectionQuestion ideal-int
+pkg syscall (windows-386), func DnsNameCompare(*uint16, *uint16) bool
+pkg syscall (windows-amd64), const DNS_INFO_NO_RECORDS = 9501
+pkg syscall (windows-amd64), const DNS_INFO_NO_RECORDS ideal-int
+pkg syscall (windows-amd64), const DnsSectionAdditional = 3
+pkg syscall (windows-amd64), const DnsSectionAdditional ideal-int
+pkg syscall (windows-amd64), const DnsSectionAnswer = 1
+pkg syscall (windows-amd64), const DnsSectionAnswer ideal-int
+pkg syscall (windows-amd64), const DnsSectionAuthority = 2
+pkg syscall (windows-amd64), const DnsSectionAuthority ideal-int
+pkg syscall (windows-amd64), const DnsSectionQuestion = 0
+pkg syscall (windows-amd64), const DnsSectionQuestion ideal-int
+pkg syscall (windows-amd64), func DnsNameCompare(*uint16, *uint16) bool
+
+# CL 86160044 os: Implement symlink support for Windows, Michael Fraenkel <michael.fraenkel@gmail.com>
+pkg syscall (windows-386), const ERROR_PRIVILEGE_NOT_HELD = 1314
+pkg syscall (windows-386), const ERROR_PRIVILEGE_NOT_HELD Errno
+pkg syscall (windows-amd64), const ERROR_PRIVILEGE_NOT_HELD = 1314
+pkg syscall (windows-amd64), const ERROR_PRIVILEGE_NOT_HELD Errno
+
+# CL 86160044 os: Implement symlink support for Windows, Michael Fraenkel <michael.fraenkel@gmail.com>
+pkg syscall (windows-386), const FILE_ATTRIBUTE_REPARSE_POINT = 1024
+pkg syscall (windows-386), const FILE_ATTRIBUTE_REPARSE_POINT ideal-int
+pkg syscall (windows-386), const FILE_FLAG_OPEN_REPARSE_POINT = 2097152
+pkg syscall (windows-386), const FILE_FLAG_OPEN_REPARSE_POINT ideal-int
+pkg syscall (windows-386), const FSCTL_GET_REPARSE_POINT = 589992
+pkg syscall (windows-386), const FSCTL_GET_REPARSE_POINT ideal-int
+pkg syscall (windows-386), const IO_REPARSE_TAG_SYMLINK = 2684354572
+pkg syscall (windows-386), const IO_REPARSE_TAG_SYMLINK ideal-int
+pkg syscall (windows-386), const MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384
+pkg syscall (windows-386), const MAXIMUM_REPARSE_DATA_BUFFER_SIZE ideal-int
+pkg syscall (windows-386), const SYMBOLIC_LINK_FLAG_DIRECTORY = 1
+pkg syscall (windows-386), const SYMBOLIC_LINK_FLAG_DIRECTORY ideal-int
+pkg syscall (windows-386), func CreateHardLink(*uint16, *uint16, uintptr) error
+pkg syscall (windows-386), func CreateSymbolicLink(*uint16, *uint16, uint32) error
+pkg syscall (windows-386), func DeviceIoControl(Handle, uint32, *uint8, uint32, *uint8, uint32, *uint32, *Overlapped) error
+pkg syscall (windows-386), func LoadCreateSymbolicLink() error
+pkg syscall (windows-amd64), const FILE_ATTRIBUTE_REPARSE_POINT = 1024
+pkg syscall (windows-amd64), const FILE_ATTRIBUTE_REPARSE_POINT ideal-int
+pkg syscall (windows-amd64), const FILE_FLAG_OPEN_REPARSE_POINT = 2097152
+pkg syscall (windows-amd64), const FILE_FLAG_OPEN_REPARSE_POINT ideal-int
+pkg syscall (windows-amd64), const FSCTL_GET_REPARSE_POINT = 589992
+pkg syscall (windows-amd64), const FSCTL_GET_REPARSE_POINT ideal-int
+pkg syscall (windows-amd64), const IO_REPARSE_TAG_SYMLINK = 2684354572
+pkg syscall (windows-amd64), const IO_REPARSE_TAG_SYMLINK ideal-int
+pkg syscall (windows-amd64), const MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384
+pkg syscall (windows-amd64), const MAXIMUM_REPARSE_DATA_BUFFER_SIZE ideal-int
+pkg syscall (windows-amd64), const SYMBOLIC_LINK_FLAG_DIRECTORY = 1
+pkg syscall (windows-amd64), const SYMBOLIC_LINK_FLAG_DIRECTORY ideal-int
+pkg syscall (windows-amd64), func CreateHardLink(*uint16, *uint16, uintptr) error
+pkg syscall (windows-amd64), func CreateSymbolicLink(*uint16, *uint16, uint32) error
+pkg syscall (windows-amd64), func DeviceIoControl(Handle, uint32, *uint8, uint32, *uint8, uint32, *uint32, *Overlapped) error
+pkg syscall (windows-amd64), func LoadCreateSymbolicLink() error
+
+# CL 149510043 net: disable SIO_UDP_CONNRESET behavior on windows., Ron Hashimoto <mail@h2so5.net>
+pkg syscall (windows-386), const SIO_UDP_CONNRESET = 2550136844
+pkg syscall (windows-386), const SIO_UDP_CONNRESET ideal-int
+pkg syscall (windows-amd64), const SIO_UDP_CONNRESET = 2550136844
+pkg syscall (windows-amd64), const SIO_UDP_CONNRESET ideal-int
+
+# CL 102320044 syscall: implement syscall.Getppid() on Windows, Alan Shreve <alan@inconshreveable.com>
+pkg syscall (windows-386), const TH32CS_INHERIT = 2147483648
+pkg syscall (windows-386), const TH32CS_INHERIT ideal-int
+pkg syscall (windows-386), const TH32CS_SNAPALL = 15
+pkg syscall (windows-386), const TH32CS_SNAPALL ideal-int
+pkg syscall (windows-386), const TH32CS_SNAPHEAPLIST = 1
+pkg syscall (windows-386), const TH32CS_SNAPHEAPLIST ideal-int
+pkg syscall (windows-386), const TH32CS_SNAPMODULE = 8
+pkg syscall (windows-386), const TH32CS_SNAPMODULE ideal-int
+pkg syscall (windows-386), const TH32CS_SNAPMODULE32 = 16
+pkg syscall (windows-386), const TH32CS_SNAPMODULE32 ideal-int
+pkg syscall (windows-386), const TH32CS_SNAPPROCESS = 2
+pkg syscall (windows-386), const TH32CS_SNAPPROCESS ideal-int
+pkg syscall (windows-386), const TH32CS_SNAPTHREAD = 4
+pkg syscall (windows-386), const TH32CS_SNAPTHREAD ideal-int
+pkg syscall (windows-386), func CreateToolhelp32Snapshot(uint32, uint32) (Handle, error)
+pkg syscall (windows-386), func Process32First(Handle, *ProcessEntry32) error
+pkg syscall (windows-386), func Process32Next(Handle, *ProcessEntry32) error
+pkg syscall (windows-386), type ProcessEntry32 struct
+pkg syscall (windows-386), type ProcessEntry32 struct, DefaultHeapID uintptr
+pkg syscall (windows-386), type ProcessEntry32 struct, ExeFile [260]uint16
+pkg syscall (windows-386), type ProcessEntry32 struct, Flags uint32
+pkg syscall (windows-386), type ProcessEntry32 struct, ModuleID uint32
+pkg syscall (windows-386), type ProcessEntry32 struct, ParentProcessID uint32
+pkg syscall (windows-386), type ProcessEntry32 struct, PriClassBase int32
+pkg syscall (windows-386), type ProcessEntry32 struct, ProcessID uint32
+pkg syscall (windows-386), type ProcessEntry32 struct, Size uint32
+pkg syscall (windows-386), type ProcessEntry32 struct, Threads uint32
+pkg syscall (windows-386), type ProcessEntry32 struct, Usage uint32
+pkg syscall (windows-amd64), const TH32CS_INHERIT = 2147483648
+pkg syscall (windows-amd64), const TH32CS_INHERIT ideal-int
+pkg syscall (windows-amd64), const TH32CS_SNAPALL = 15
+pkg syscall (windows-amd64), const TH32CS_SNAPALL ideal-int
+pkg syscall (windows-amd64), const TH32CS_SNAPHEAPLIST = 1
+pkg syscall (windows-amd64), const TH32CS_SNAPHEAPLIST ideal-int
+pkg syscall (windows-amd64), const TH32CS_SNAPMODULE = 8
+pkg syscall (windows-amd64), const TH32CS_SNAPMODULE ideal-int
+pkg syscall (windows-amd64), const TH32CS_SNAPMODULE32 = 16
+pkg syscall (windows-amd64), const TH32CS_SNAPMODULE32 ideal-int
+pkg syscall (windows-amd64), const TH32CS_SNAPPROCESS = 2
+pkg syscall (windows-amd64), const TH32CS_SNAPPROCESS ideal-int
+pkg syscall (windows-amd64), const TH32CS_SNAPTHREAD = 4
+pkg syscall (windows-amd64), const TH32CS_SNAPTHREAD ideal-int
+pkg syscall (windows-amd64), func CreateToolhelp32Snapshot(uint32, uint32) (Handle, error)
+pkg syscall (windows-amd64), func Process32First(Handle, *ProcessEntry32) error
+pkg syscall (windows-amd64), func Process32Next(Handle, *ProcessEntry32) error
+pkg syscall (windows-amd64), type ProcessEntry32 struct
+pkg syscall (windows-amd64), type ProcessEntry32 struct, DefaultHeapID uintptr
+pkg syscall (windows-amd64), type ProcessEntry32 struct, ExeFile [260]uint16
+pkg syscall (windows-amd64), type ProcessEntry32 struct, Flags uint32
+pkg syscall (windows-amd64), type ProcessEntry32 struct, ModuleID uint32
+pkg syscall (windows-amd64), type ProcessEntry32 struct, ParentProcessID uint32
+pkg syscall (windows-amd64), type ProcessEntry32 struct, PriClassBase int32
+pkg syscall (windows-amd64), type ProcessEntry32 struct, ProcessID uint32
+pkg syscall (windows-amd64), type ProcessEntry32 struct, Size uint32
+pkg syscall (windows-amd64), type ProcessEntry32 struct, Threads uint32
+pkg syscall (windows-amd64), type ProcessEntry32 struct, Usage uint32
+
+# CL 127740043 os: make SameFile handle paths like c:a.txt properly, Alex Brainman <alex.brainman@gmail.com>
+pkg syscall (windows-386), func FullPath(string) (string, error)
+pkg syscall (windows-amd64), func FullPath(string) (string, error)
+
+# CL 98150043 testing: add Coverage function, Russ Cox <rsc@golang.org>
+pkg testing, func Coverage() float64
+
+# CL 148770043 cmd/go, testing: add TestMain support, Russ Cox <rsc@golang.org>
+pkg testing, func MainStart(func(string, string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample) *M
+pkg testing, method (*M) Run() int
+pkg testing, type M struct
+
+# CL 108030044 text/scanner: provide facility for custom identifiers, Robert Griesemer <gri@golang.org>
+pkg text/scanner, type Scanner struct, IsIdentRune func(int32, int) bool
+
+# CL 130620043 text/template: add back pointer to Nodes for better error generation, Rob Pike <r@golang.org>
+pkg text/template/parse, type DotNode struct, embedded NodeType
+pkg text/template/parse, type NilNode struct, embedded NodeType
+pkg text/template/parse, method (*BranchNode) Copy() Node
+pkg text/template/parse, method (*IdentifierNode) SetTree(*Tree) *IdentifierNode
+pkg html/template, type Error struct, Node parse.Node
+
+# CL 127470043 unicode: strconv: regexp: Upgrade to Unicode 7.0.0., Marcel van Lohuizen <mpvl@golang.org>
+pkg unicode, const Version = "7.0.0"
+pkg unicode, var Bassa_Vah *RangeTable
+pkg unicode, var Caucasian_Albanian *RangeTable
+pkg unicode, var Duployan *RangeTable
+pkg unicode, var Elbasan *RangeTable
+pkg unicode, var Grantha *RangeTable
+pkg unicode, var Khojki *RangeTable
+pkg unicode, var Khudawadi *RangeTable
+pkg unicode, var Linear_A *RangeTable
+pkg unicode, var Mahajani *RangeTable
+pkg unicode, var Manichaean *RangeTable
+pkg unicode, var Mende_Kikakui *RangeTable
+pkg unicode, var Modi *RangeTable
+pkg unicode, var Mro *RangeTable
+pkg unicode, var Nabataean *RangeTable
+pkg unicode, var Old_North_Arabian *RangeTable
+pkg unicode, var Old_Permic *RangeTable
+pkg unicode, var Pahawh_Hmong *RangeTable
+pkg unicode, var Palmyrene *RangeTable
+pkg unicode, var Pau_Cin_Hau *RangeTable
+pkg unicode, var Psalter_Pahlavi *RangeTable
+pkg unicode, var Siddham *RangeTable
+pkg unicode, var Tirhuta *RangeTable
+pkg unicode, var Warang_Citi *RangeTable
diff --git a/api/next.txt b/api/next.txt
index 5e49b3f94..e8570a6f2 100644
--- a/api/next.txt
+++ b/api/next.txt
@@ -115,3 +115,27 @@ pkg debug/goobj, type Var struct, Kind int
pkg debug/goobj, type Var struct, Name string
pkg debug/goobj, type Var struct, Offset int
pkg debug/goobj, type Var struct, Type SymID
+pkg unicode, const Version = "7.0.0"
+pkg unicode, var Bassa_Vah *RangeTable
+pkg unicode, var Caucasian_Albanian *RangeTable
+pkg unicode, var Duployan *RangeTable
+pkg unicode, var Elbasan *RangeTable
+pkg unicode, var Grantha *RangeTable
+pkg unicode, var Khojki *RangeTable
+pkg unicode, var Khudawadi *RangeTable
+pkg unicode, var Linear_A *RangeTable
+pkg unicode, var Mahajani *RangeTable
+pkg unicode, var Manichaean *RangeTable
+pkg unicode, var Mende_Kikakui *RangeTable
+pkg unicode, var Modi *RangeTable
+pkg unicode, var Mro *RangeTable
+pkg unicode, var Nabataean *RangeTable
+pkg unicode, var Old_North_Arabian *RangeTable
+pkg unicode, var Old_Permic *RangeTable
+pkg unicode, var Pahawh_Hmong *RangeTable
+pkg unicode, var Palmyrene *RangeTable
+pkg unicode, var Pau_Cin_Hau *RangeTable
+pkg unicode, var Psalter_Pahlavi *RangeTable
+pkg unicode, var Siddham *RangeTable
+pkg unicode, var Tirhuta *RangeTable
+pkg unicode, var Warang_Citi *RangeTable
diff --git a/doc/articles/go_command.html b/doc/articles/go_command.html
index fddca41e2..2978628cd 100644
--- a/doc/articles/go_command.html
+++ b/doc/articles/go_command.html
@@ -78,17 +78,18 @@ well-established conventions.</p>
source code. For Bitbucket, GitHub, Google Code, and Launchpad, the
root directory of the repository is identified by the repository's
main URL, without the <code>http://</code> prefix. Subdirectories are named by
-adding to that path. For example, the supplemental networking
-libraries for Go are obtained by running</p>
+adding to that path.
+For example, the Go example programs are obtained by running</p>
<pre>
-hg clone http://code.google.com/p/go.net
+git clone https://github.com/golang/example
</pre>
<p>and thus the import path for the root directory of that repository is
-"<code>code.google.com/p/go.net</code>". The websocket package is stored in a
-subdirectory, so its import path is
-"<code>code.google.com/p/go.net/websocket</code>".</p>
+"<code>github.com/golang/example</code>".
+The <a href="https://godoc.org/github.com/golang/example/stringutil">stringutil</a>
+package is stored in a subdirectory, so its import path is
+"<code>github.com/golang/example/stringutil</code>".</p>
<p>These paths are on the long side, but in exchange we get an
automatically managed name space for import paths and the ability for
@@ -99,7 +100,7 @@ deduce where to obtain the source code.</p>
in a known way from the import path. Specifically, the first choice
is <code>$GOPATH/src/&lt;import-path&gt;</code>. If <code>$GOPATH</code> is
unset, the go command will fall back to storing source code alongside the
-standard Go packages, in <code>$GOROOT/src/pkg/&lt;import-path&gt;</code>.
+standard Go packages, in <code>$GOROOT/src/&lt;import-path&gt;</code>.
If <code>$GOPATH</code> is set to a list of paths, the go command tries
<code>&lt;dir&gt;/src/&lt;import-path&gt;</code> for each of the directories in
that list.</p>
diff --git a/doc/articles/race_detector.html b/doc/articles/race_detector.html
index 282db8ba4..6defd98f9 100644
--- a/doc/articles/race_detector.html
+++ b/doc/articles/race_detector.html
@@ -57,35 +57,35 @@ Here is an example:
WARNING: DATA RACE
Read by goroutine 185:
net.(*pollServer).AddFD()
- src/pkg/net/fd_unix.go:89 +0x398
+ src/net/fd_unix.go:89 +0x398
net.(*pollServer).WaitWrite()
- src/pkg/net/fd_unix.go:247 +0x45
+ src/net/fd_unix.go:247 +0x45
net.(*netFD).Write()
- src/pkg/net/fd_unix.go:540 +0x4d4
+ src/net/fd_unix.go:540 +0x4d4
net.(*conn).Write()
- src/pkg/net/net.go:129 +0x101
+ src/net/net.go:129 +0x101
net.func·060()
- src/pkg/net/timeout_test.go:603 +0xaf
+ src/net/timeout_test.go:603 +0xaf
Previous write by goroutine 184:
net.setWriteDeadline()
- src/pkg/net/sockopt_posix.go:135 +0xdf
+ src/net/sockopt_posix.go:135 +0xdf
net.setDeadline()
- src/pkg/net/sockopt_posix.go:144 +0x9c
+ src/net/sockopt_posix.go:144 +0x9c
net.(*conn).SetDeadline()
- src/pkg/net/net.go:161 +0xe3
+ src/net/net.go:161 +0xe3
net.func·061()
- src/pkg/net/timeout_test.go:616 +0x3ed
+ src/net/timeout_test.go:616 +0x3ed
Goroutine 185 (running) created at:
net.func·061()
- src/pkg/net/timeout_test.go:609 +0x288
+ src/net/timeout_test.go:609 +0x288
Goroutine 184 (running) created at:
net.TestProlongTimeout()
- src/pkg/net/timeout_test.go:618 +0x298
+ src/net/timeout_test.go:618 +0x298
testing.tRunner()
- src/pkg/testing/testing.go:301 +0xe8
+ src/testing/testing.go:301 +0xe8
</pre>
<h2 id="Options">Options</h2>
@@ -377,7 +377,8 @@ func (w *Watchdog) Start() {
<h2 id="Supported_Systems">Supported Systems</h2>
<p>
-The race detector runs on <code>darwin/amd64</code>, <code>linux/amd64</code>, and <code>windows/amd64</code>.
+The race detector runs on <code>darwin/amd64</code>, <code>freebsd/amd64</code>,
+<code>linux/amd64</code>, and <code>windows/amd64</code>.
</p>
<h2 id="Runtime_Overheads">Runtime Overhead</h2>
diff --git a/doc/asm.html b/doc/asm.html
index d44cb799d..771c493cc 100644
--- a/doc/asm.html
+++ b/doc/asm.html
@@ -117,6 +117,9 @@ All user-defined symbols other than jump labels are written as offsets to these
<p>
The <code>SB</code> pseudo-register can be thought of as the origin of memory, so the symbol <code>foo(SB)</code>
is the name <code>foo</code> as an address in memory.
+This form is used to name global functions and data.
+Adding <code>&lt;&gt;</code> to the name, as in <code>foo&lt;&gt;(SB)</code>, makes the name
+visible only in the current source file, like a top-level <code>static</code> declaration in a C file.
</p>
<p>
@@ -128,8 +131,11 @@ Thus <code>0(FP)</code> is the first argument to the function,
When referring to a function argument this way, it is conventional to place the name
at the beginning, as in <code>first_arg+0(FP)</code> and <code>second_arg+8(FP)</code>.
Some of the assemblers enforce this convention, rejecting plain <code>0(FP)</code> and <code>8(FP)</code>.
-For assembly functions with Go prototypes, <code>go vet</code> will check that the argument names
+For assembly functions with Go prototypes, <code>go</code> <code>vet</code> will check that the argument names
and offsets match.
+On 32-bit systems, the low and high 32 bits of a 64-bit value are distinguished by adding
+a <code>_lo</code> or <code>_hi</code> suffix to the name, as in <code>arg_lo+0(FP)</code> or <code>arg_hi+4(FP)</code>.
+If a Go prototype does not name its result, the expected assembly name is <code>ret</code>.
</p>
<p>
@@ -149,7 +155,7 @@ hardware's <code>SP</code> register.
<p>
Instructions, registers, and assembler directives are always in UPPER CASE to remind you
that assembly programming is a fraught endeavor.
-(Exceptions: the <code>m</code> and <code>g</code> register renamings on ARM.)
+(Exception: the <code>g</code> register renaming on ARM.)
</p>
<p>
@@ -206,6 +212,8 @@ The frame size <code>$24-8</code> states that the function has a 24-byte frame
and is called with 8 bytes of argument, which live on the caller's frame.
If <code>NOSPLIT</code> is not specified for the <code>TEXT</code>,
the argument size must be provided.
+For assembly functions with Go prototypes, <code>go</code> <code>vet</code> will check that the
+argument size is correct.
</p>
<p>
@@ -216,19 +224,20 @@ simple name <code>profileloop</code>.
</p>
<p>
-For <code>DATA</code> directives, the symbol is followed by a slash and the number
-of bytes the memory associated with the symbol occupies.
-The arguments are optional flags and the data itself.
-For instance,
-</p>
+Global data symbols are defined by a sequence of initializing
+<code>DATA</code> directives followed by a <code>GLOBL</code> directive.
+Each <code>DATA</code> directive initializes a section of the
+corresponding memory.
+The memory not explicitly initialized is zeroed.
+The general form of the <code>DATA</code> directive is
<pre>
-DATA runtime·isplan9(SB)/4, $1
+DATA symbol+offset(SB)/width, value
</pre>
<p>
-declares the local symbol <code>runtime·isplan9</code> of size 4 and value 1.
-Again the symbol has the middle dot and is offset from <code>SB</code>.
+which initializes the symbol memory at the given offset and width with the given value.
+The <code>DATA</code> directives for a given symbol must be written with increasing offsets.
</p>
<p>
@@ -237,15 +246,26 @@ The arguments are optional flags and the size of the data being declared as a gl
which will have initial value all zeros unless a <code>DATA</code> directive
has initialized it.
The <code>GLOBL</code> directive must follow any corresponding <code>DATA</code> directives.
-This example
+</p>
+
+<p>
+For example,
</p>
<pre>
-GLOBL runtime·tlsoffset(SB),$4
+DATA divtab&lt;&gt;+0x00(SB)/4, $0xf4f8fcff
+DATA divtab&lt;&gt;+0x04(SB)/4, $0xe6eaedf0
+...
+DATA divtab&lt;&gt;+0x3c(SB)/4, $0x81828384
+GLOBL divtab&lt;&gt;(SB), RODATA, $64
+
+GLOBL runtime·tlsoffset(SB), NOPTR, $4
</pre>
<p>
-declares <code>runtime·tlsoffset</code> to have size 4.
+declares and initializes <code>divtab&lt;&gt;</code>, a read-only 64-byte table of 4-byte integer values,
+and declares <code>runtime·tlsoffset</code>, a 4-byte, implicitly zeroed variable that
+contains no pointers.
</p>
<p>
@@ -253,7 +273,7 @@ There may be one or two arguments to the directives.
If there are two, the first is a bit mask of flags,
which can be written as numeric expressions, added or or-ed together,
or can be set symbolically for easier absorption by a human.
-Their values, defined in the file <code>src/cmd/ld/textflag.h</code>, are:
+Their values, defined in the standard <code>#include</code> file <code>textflag.h</code>, are:
</p>
<ul>
@@ -299,6 +319,80 @@ This is a wrapper function and should not count as disabling <code>recover</code
</li>
</ul>
+<h3 id="runtime">Runtime Coordination</h3>
+
+<p>
+For garbage collection to run correctly, the runtime must know the
+location of pointers in all global data and in most stack frames.
+The Go compiler emits this information when compiling Go source files,
+but assembly programs must define it explicitly.
+</p>
+
+<p>
+A data symbol marked with the <code>NOPTR</code> flag (see above)
+is treated as containing no pointers to runtime-allocated data.
+A data symbol with the <code>RODATA</code> flag
+is allocated in read-only memory and is therefore treated
+as implicitly marked <code>NOPTR</code>.
+A data symbol with a total size smaller than a pointer
+is also treated as implicitly marked <code>NOPTR</code>.
+It is not possible to define a symbol containing pointers in an assembly source file;
+such a symbol must be defined in a Go source file instead.
+Assembly source can still refer to the symbol by name
+even without <code>DATA</code> and <code>GLOBL</code> directives.
+A good general rule of thumb is to define all non-<code>RODATA</code>
+symbols in Go instead of in assembly.
+</p>
+
+<p>
+Each function also needs annotations giving the location of
+live pointers in its arguments, results, and local stack frame.
+For an assembly function with no pointer results and
+either no local stack frame or no function calls,
+the only requirement is to define a Go prototype for the function
+in a Go source file in the same package.
+For more complex situations, explicit annotation is needed.
+These annotations use pseudo-instructions defined in the standard
+<code>#include</code> file <code>funcdata.h</code>.
+</p>
+
+<p>
+If a function has no arguments and no results,
+the pointer information can be omitted.
+This is indicated by an argument size annotation of <code>$<i>n</i>-0</code>
+on the <code>TEXT</code> instruction.
+Otherwise, pointer information must be provided by
+a Go prototype for the function in a Go source file,
+even for assembly functions not called directly from Go.
+(The prototype will also let <code>go</code> <code>vet</code> check the argument references.)
+At the start of the function, the arguments are assumed
+to be initialized but the results are assumed uninitialized.
+If the results will hold live pointers during a call instruction,
+the function should start by zeroing the results and then
+executing the pseudo-instruction <code>GO_RESULTS_INITIALIZED</code>.
+This instruction records that the results are now initialized
+and should be scanned during stack movement and garbage collection.
+It is typically easier to arrange that assembly functions do not
+return pointers or do not contain call instructions;
+no assembly functions in the standard library use
+<code>GO_RESULTS_INITIALIZED</code>.
+</p>
+
+<p>
+If a function has no local stack frame,
+the pointer information can be omitted.
+This is indicated by a local frame size annotation of <code>$0-<i>n</i></code>
+on the <code>TEXT</code> instruction.
+The pointer information can also be omitted if the
+function contains no call instructions.
+Otherwise, the local stack frame must not contain pointers,
+and the assembly must confirm this fact by executing the
+pseudo-instruction <code>NO_LOCAL_POINTERS</code>.
+Because stack resizing is implemented by moving the stack,
+the stack pointer may change during any function call:
+even pointers to stack data must not be kept in local variables.
+</p>
+
<h2 id="architectures">Architecture-specific details</h2>
<p>
@@ -344,7 +438,7 @@ Here follows some descriptions of key Go-specific details for the supported arch
<h3 id="x86">32-bit Intel 386</h3>
<p>
-The runtime pointers to the <code>m</code> and <code>g</code> structures are maintained
+The runtime pointer to the <code>g</code> structure is maintained
through the value of an otherwise unused (as far as Go is concerned) register in the MMU.
A OS-dependent macro <code>get_tls</code> is defined for the assembler if the source includes
an architecture-dependent header file, like this:
@@ -356,14 +450,15 @@ an architecture-dependent header file, like this:
<p>
Within the runtime, the <code>get_tls</code> macro loads its argument register
-with a pointer to a pair of words representing the <code>g</code> and <code>m</code> pointers.
+with a pointer to the <code>g</code> pointer, and the <code>g</code> struct
+contains the <code>m</code> pointer.
The sequence to load <code>g</code> and <code>m</code> using <code>CX</code> looks like this:
</p>
<pre>
get_tls(CX)
-MOVL g(CX), AX // Move g into AX.
-MOVL m(CX), BX // Move m into BX.
+MOVL g(CX), AX // Move g into AX.
+MOVL g_m(AX), BX // Move g->m into BX.
</pre>
<h3 id="amd64">64-bit Intel 386 (a.k.a. amd64)</h3>
@@ -376,22 +471,21 @@ pointers is the same as on the 386, except it uses <code>MOVQ</code> rather than
<pre>
get_tls(CX)
-MOVQ g(CX), AX // Move g into AX.
-MOVQ m(CX), BX // Move m into BX.
+MOVQ g(CX), AX // Move g into AX.
+MOVQ g_m(AX), BX // Move g->m into BX.
</pre>
<h3 id="arm">ARM</h3>
<p>
-The registers <code>R9</code>, <code>R10</code>, and <code>R11</code>
+The registers <code>R10</code> and <code>R11</code>
are reserved by the compiler and linker.
</p>
<p>
-<code>R9</code> and <code>R10</code> point to the <code>m</code> (machine) and <code>g</code>
-(goroutine) structures, respectively.
-Within assembler source code, these pointers must be referred to as <code>m</code> and <code>g</code>;
-the names <code>R9</code> and <code>R10</code> are not recognized.
+<code>R10</code> points to the <code>g</code> (goroutine) structure.
+Within assembler source code, this pointer must be referred to as <code>g</code>;
+the name <code>R10</code> is not recognized.
</p>
<p>
@@ -434,13 +528,10 @@ Here's how the 386 runtime defines the 64-bit atomic load function.
// so actually
// void atomicload64(uint64 *res, uint64 volatile *addr);
TEXT runtime·atomicload64(SB), NOSPLIT, $0-8
- MOVL 4(SP), BX
- MOVL 8(SP), AX
- // MOVQ (%EAX), %MM0
- BYTE $0x0f; BYTE $0x6f; BYTE $0x00
- // MOVQ %MM0, 0(%EBX)
- BYTE $0x0f; BYTE $0x7f; BYTE $0x03
- // EMMS
- BYTE $0x0F; BYTE $0x77
+ MOVL ptr+0(FP), AX
+ LEAL ret_lo+4(FP), BX
+ BYTE $0x0f; BYTE $0x6f; BYTE $0x00 // MOVQ (%EAX), %MM0
+ BYTE $0x0f; BYTE $0x7f; BYTE $0x03 // MOVQ %MM0, 0(%EBX)
+ BYTE $0x0F; BYTE $0x77 // EMMS
RET
</pre>
diff --git a/doc/cmd.html b/doc/cmd.html
index 725666f1d..5d20d3887 100644
--- a/doc/cmd.html
+++ b/doc/cmd.html
@@ -62,10 +62,10 @@ details.
</tr>
<tr>
-<td><a href="//godoc.org/code.google.com/p/go.tools/cmd/cover/">cover</a></td>
+<td><a href="//godoc.org/golang.org/x/tools/cmd/cover/">cover</a></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td>Cover is a program for creating and analyzing the coverage profiles
-generated by <code>"go test -coverprofile"</code>.
+generated by <code>"go test -coverprofile"</code>.</td>
</tr>
<tr>
@@ -83,13 +83,13 @@ gofmt</a> command with more general options.</td>
</tr>
<tr>
-<td><a href="//godoc.org/code.google.com/p/go.tools/cmd/godoc/">godoc</a></td>
+<td><a href="//godoc.org/golang.org/x/tools/cmd/godoc/">godoc</a></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td>Godoc extracts and generates documentation for Go packages.</td>
</tr>
<tr>
-<td><a href="//godoc.org/code.google.com/p/go.tools/cmd/vet/">vet</a></td>
+<td><a href="//godoc.org/golang.org/x/tools/cmd/vet/">vet</a></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td>Vet examines Go source code and reports suspicious constructs, such as Printf
calls whose arguments do not align with the format string.</td>
diff --git a/doc/code.html b/doc/code.html
index f019306fa..a4638f9ff 100644
--- a/doc/code.html
+++ b/doc/code.html
@@ -60,37 +60,35 @@ To give you an idea of how a workspace looks in practice, here's an example:
<pre>
bin/
- streak # command executable
- todo # command executable
+ hello # command executable
+ outyet # command executable
pkg/
linux_amd64/
- code.google.com/p/goauth2/
- oauth.a # package object
- github.com/nf/todo/
- task.a # package object
+ github.com/golang/example/
+ stringutil.a # package object
src/
- code.google.com/p/goauth2/
- .hg/ # mercurial repository metadata
- oauth/
- oauth.go # package source
- oauth_test.go # test source
- github.com/nf/
- streak/
- .git/ # git repository metadata
- oauth.go # command source
- streak.go # command source
- todo/
- .git/ # git repository metadata
- task/
- task.go # package source
- todo.go # command source
+ <a href="https://github.com/golang/example/">github.com/golang/example/</a>
+ .git/ # Git repository metadata
+ hello/
+ hello.go # command source
+ outyet/
+ main.go # command source
+ main_test.go # test source
+ stringutil/
+ reverse.go # package source
+ reverse_test.go # test source
</pre>
<p>
-This workspace contains three repositories (<code>goauth2</code>,
-<code>streak</code>, and <code>todo</code>) comprising two commands
-(<code>streak</code> and <code>todo</code>) and two libraries
-(<code>oauth</code> and <code>task</code>).
+This workspace contains one repository (<code>example</code>)
+comprising two commands (<code>hello</code> and <code>outyet</code>)
+and one library (<code>stringutil</code>).
+</p>
+
+<p>
+A typical workspace would contain 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>
<p>
@@ -277,29 +275,29 @@ Let's write a library and use it from the <code>hello</code> program.
<p>
Again, the first step is to choose a package path (we'll use
-<code>github.com/user/newmath</code>) and create the package directory:
+<code>github.com/user/stringutil</code>) and create the package directory:
</p>
<pre>
-$ <b>mkdir $GOPATH/src/github.com/user/newmath</b>
+$ <b>mkdir $GOPATH/src/github.com/user/stringutil</b>
</pre>
<p>
-Next, create a file named <code>sqrt.go</code> in that directory with the
+Next, create a file named <code>reverse.go</code> in that directory with the
following contents.
</p>
<pre>
-// Package newmath is a trivial example package.
-package newmath
-
-// Sqrt returns an approximation to the square root of x.
-func Sqrt(x float64) float64 {
- z := 1.0
- for i := 0; i &lt; 1000; i++ {
- z -= (z*z - x) / (2 * z)
+// Package stringutil contains utility functions for working with strings.
+package stringutil
+
+// Reverse returns its argument string reversed rune-wise left to right.
+func Reverse(s string) string {
+ r := []rune(s)
+ for i, j := 0, len(r)-1; i &lt; len(r)/2; i, j = i+1, j-1 {
+ r[i], r[j] = r[j], r[i]
}
- return z
+ return string(r)
}
</pre>
@@ -308,7 +306,7 @@ Now, test that the package compiles with <code>go build</code>:
</p>
<pre>
-$ <b>go build github.com/user/newmath</b>
+$ <b>go build github.com/user/stringutil</b>
</pre>
<p>
@@ -326,7 +324,7 @@ directory of the workspace.
</p>
<p>
-After confirming that the <code>newmath</code> package builds,
+After confirming that the <code>stringutil</code> package builds,
modify your original <code>hello.go</code> (which is in
<code>$GOPATH/src/github.com/user/hello</code>) to use it:
</p>
@@ -337,18 +335,18 @@ package main
import (
"fmt"
- <b>"github.com/user/newmath"</b>
+ <b>"github.com/user/stringutil"</b>
)
func main() {
- fmt.Printf("Hello, world. <b>Sqrt(2) = %v\n", newmath.Sqrt(2)</b>)
+ fmt.Printf(stringutil.Reverse("!oG ,olleH"))
}
</pre>
<p>
Whenever the <code>go</code> tool installs a package or binary, it also
-installs whatever dependencies it has. So when you install the <code>hello</code>
-program
+installs whatever dependencies it has.
+So when you install the <code>hello</code> program
</p>
<pre>
@@ -356,16 +354,16 @@ $ <b>go install github.com/user/hello</b>
</pre>
<p>
-the <code>newmath</code> package will be installed as well, automatically.
+the <code>stringutil</code> package will be installed as well, automatically.
</p>
<p>
-Running the new version of the program, you should see some numerical output:
+Running the new version of the program, you should see a new, reversed message:
</p>
<pre>
$ <b>hello</b>
-Hello, world. Sqrt(2) = 1.414213562373095
+Hello, Go!
</pre>
<p>
@@ -374,22 +372,22 @@ After the steps above, your workspace should look like this:
<pre>
bin/
- hello # command executable
+ hello # command executable
pkg/
- linux_amd64/ # this will reflect your OS and architecture
+ linux_amd64/ # this will reflect your OS and architecture
github.com/user/
- newmath.a # package object
+ stringutil.a # package object
src/
github.com/user/
hello/
- hello.go # command source
- newmath/
- sqrt.go # package source
+ hello.go # command source
+ stringutil/
+ reverse.go # package source
</pre>
<p>
-Note that <code>go install</code> placed the <code>newmath.a</code> object in a
-directory inside <code>pkg/linux_amd64</code> that mirrors its source
+Note that <code>go install</code> placed the <code>stringutil.a</code> object
+in a directory inside <code>pkg/linux_amd64</code> that mirrors its source
directory.
This is so that future invocations of the <code>go</code> tool can find the
package object and avoid recompiling the package unnecessarily.
@@ -457,20 +455,29 @@ if the function calls a failure function such as <code>t.Error</code> or
</p>
<p>
-Add a test to the <code>newmath</code> package by creating the file
-<code>$GOPATH/src/github.com/user/newmath/sqrt_test.go</code> containing the
-following Go code.
+Add a test to the <code>stringutil</code> package by creating the file
+<code>$GOPATH/src/github.com/user/stringutil/reverse_test.go</code> containing
+the following Go code.
</p>
<pre>
-package newmath
+package stringutil
import "testing"
-func TestSqrt(t *testing.T) {
- const in, out = 4, 2
- if x := Sqrt(in); x != out {
- t.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
+func TestReverse(t *testing.T) {
+ cases := []struct {
+ in, want string
+ }{
+ {"Hello, world", "dlrow ,olleH"},
+ {"Hello, 世界", "界世 ,olleH"},
+ {"", ""},
+ }
+ for _, c := range cases {
+ got := Reverse(c.in)
+ if got != c.want {
+ t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)
+ }
}
}
</pre>
@@ -480,8 +487,8 @@ Then run the test with <code>go test</code>:
</p>
<pre>
-$ <b>go test github.com/user/newmath</b>
-ok github.com/user/newmath 0.165s
+$ <b>go test github.com/user/stringutil</b>
+ok github.com/user/stringutil 0.165s
</pre>
<p>
@@ -491,7 +498,7 @@ directory, you can omit the package path:
<pre>
$ <b>go test</b>
-ok github.com/user/newmath 0.165s
+ok github.com/user/stringutil 0.165s
</pre>
<p>
@@ -507,16 +514,16 @@ An import path can describe how to obtain the package source code using a
revision control system such as Git or Mercurial. The <code>go</code> tool uses
this property to automatically fetch packages from remote repositories.
For instance, the examples described in this document are also kept in a
-Mercurial repository hosted at Google Code,
-<code><a href="//code.google.com/p/go.example">code.google.com/p/go.example</a></code>.
+Git repository hosted at GitHub
+<code><a href="https://github.com/golang/example">github.com/golang/example</a></code>.
If you include the repository URL in the package's import path,
<code>go get</code> will fetch, build, and install it automatically:
</p>
<pre>
-$ <b>go get code.google.com/p/go.example/hello</b>
+$ <b>go get github.com/golang/example/hello</b>
$ <b>$GOPATH/bin/hello</b>
-Hello, world. Sqrt(2) = 1.414213562373095
+Hello, Go examples!
</pre>
<p>
@@ -533,43 +540,45 @@ tree should now look like this:
<pre>
bin/
- hello # command executable
+ hello # command executable
pkg/
linux_amd64/
- code.google.com/p/go.example/
- newmath.a # package object
+ github.com/golang/example/
+ stringutil.a # package object
github.com/user/
- newmath.a # package object
+ stringutil.a # package object
src/
- code.google.com/p/go.example/
+ github.com/golang/example/
+ .git/ # Git repository metadata
hello/
- hello.go # command source
- newmath/
- sqrt.go # package source
- sqrt_test.go # test source
+ hello.go # command source
+ stringutil/
+ reverse.go # package source
+ reverse_test.go # test source
github.com/user/
hello/
- hello.go # command source
- newmath/
- sqrt.go # package source
- sqrt_test.go # test source
+ hello.go # command source
+ stringutil/
+ reverse.go # package source
+ reverse_test.go # test source
</pre>
<p>
-The <code>hello</code> command hosted at Google Code depends on the
-<code>newmath</code> package within the same repository. The imports in
-<code>hello.go</code> file use the same import path convention, so the <code>go
-get</code> command is able to locate and install the dependent package, too.
+The <code>hello</code> command hosted at GitHub depends on the
+<code>stringutil</code> package within the same repository. The imports in
+<code>hello.go</code> file use the same import path convention, so the
+<code>go get</code> command is able to locate and install the dependent
+package, too.
</p>
<pre>
-import "code.google.com/p/go.example/newmath"
+import "github.com/golang/example/stringutil"
</pre>
<p>
This convention is the easiest way to make your Go packages available for
others to use.
-The <a href="//code.google.com/p/go-wiki/wiki/Projects">Go Wiki</a>
+The <a href="//golang.org/wiki/Projects">Go Wiki</a>
and <a href="//godoc.org/">godoc.org</a>
provide lists of external Go projects.
</p>
@@ -618,5 +627,5 @@ The official mailing list for discussion of the Go language is
<p>
Report bugs using the
-<a href="//code.google.com/p/go/issues/list">Go issue tracker</a>.
+<a href="//golang.org/issue">Go issue tracker</a>.
</p>
diff --git a/doc/contrib.html b/doc/contrib.html
index a615fc67a..93a609fb2 100644
--- a/doc/contrib.html
+++ b/doc/contrib.html
@@ -30,21 +30,16 @@ We encourage all Go users to subscribe to
<h2 id="go1">Version history</h2>
<h3 id="release"><a href="/doc/devel/release.html">Release History</a></h3>
-<p>A summary of the changes between Go releases.</p>
-<h4 id="go1notes"><a href="/doc/go1">Go 1 Release Notes</a></h4>
-<p>
-A guide for updating your code to work with Go 1.
-</p>
+<p>A <a href="/doc/devel/release.html">summary</a> of the changes between Go releases. Notes for the major releases:</p>
-<h4 id="release notes"><a href="/doc/go1.1">Go 1.1 Release Notes</a></h4>
-<p>
-A list of significant changes in Go 1.1, with instructions for updating
-your code where necessary.
-Each point release includes a similar document appropriate for that
-release: <a href="/doc/go1.2">Go 1.2</a>, <a href="/doc/go1.3">Go 1.3</a>,
-and so on.
-</p>
+<ul>
+ <li><a href="/doc/go1.4">Go 1.4</a> <small>(December 2014)</small></li>
+ <li><a href="/doc/go1.3">Go 1.3</a> <small>(June 2014)</small></li>
+ <li><a href="/doc/go1.2">Go 1.2</a> <small>(December 2013)</small></li>
+ <li><a href="/doc/go1.1">Go 1.1</a> <small>(May 2013)</small></li>
+ <li><a href="/doc/go1">Go 1</a> <small>(March 2012)</small></li>
+</ul>
<h3 id="go1compat"><a href="/doc/go1compat">Go 1 and the Future of Go Programs</a></h3>
<p>
@@ -55,7 +50,7 @@ Go 1 matures.
<h2 id="resources">Developer Resources</h2>
-<h3 id="source"><a href="https://code.google.com/p/go/source">Source Code</a></h3>
+<h3 id="source"><a href="https://golang.org/change">Source Code</a></h3>
<p>Check out the Go source code.</p>
<h3 id="golang-dev"><a href="https://groups.google.com/group/golang-dev">Developer</a> and
@@ -81,13 +76,13 @@ systems and architectures.</p>
<h2 id="howto">How you can help</h2>
-<h3><a href="https://code.google.com/p/go/issues">Reporting issues</a></h3>
+<h3><a href="//golang.org/issue">Reporting issues</a></h3>
<p>
If you spot bugs, mistakes, or inconsistencies in the Go project's code or
documentation, please let us know by
-<a href="https://code.google.com/p/go/issues/entry">filing a ticket</a>
-on our <a href="https://code.google.com/p/go/issues">issue tracker</a>.
+<a href="//golang.org/issue/new">filing a ticket</a>
+on our <a href="//golang.org/issue">issue tracker</a>.
(Of course, you should check it's not an existing issue before creating
a new one.)
</p>
@@ -106,8 +101,8 @@ To get started, read these <a href="/doc/contribute.html">contribution
guidelines</a> for information on design, testing, and our code review process.
</p>
<p>
-Check <a href="https://code.google.com/p/go/issues">the tracker</a> for
+Check <a href="//golang.org/issue">the tracker</a> for
open issues that interest you. Those labeled
-<a href="https://code.google.com/p/go/issues/list?q=status=HelpWanted">HelpWanted</a>
+<a href="https://github.com/golang/go/issues?q=is%3Aopen+is%3Aissue+label%3Ahelpwanted">helpwanted</a>
are particularly in need of outside help.
</p>
diff --git a/doc/contribute.html b/doc/contribute.html
index 392734985..ba550d528 100644
--- a/doc/contribute.html
+++ b/doc/contribute.html
@@ -6,9 +6,21 @@
<p>
This document explains how to contribute changes to the Go project.
-It assumes you have installed Go using the
+It assumes you have installed Go from source:
+<p>
+
+<pre>
+$ git clone https://go.googlesource.com/go
+$ cd go/src
+$ ./all.bash
+</pre>
+<!--
+TODO(adg): delete the above, restore the below after we have updated install-source.html
<a href="/doc/install/source">installation instructions</a> and
have <a href="code.html">written and tested your code</a>.
+-->
+
+<p>
(Note that the <code>gccgo</code> frontend lives elsewhere;
see <a href="gccgo_contribute.html">Contributing to gccgo</a>.)
</p>
@@ -54,7 +66,8 @@ $ ./all.bash
</p>
<p>
-After running for a while, the command should print "<code>ALL TESTS PASSED</code>".
+After running for a while, the command should print
+"<code>ALL</code> <code>TESTS</code> <code>PASSED</code>".
</p>
<h2 id="Code_review">Code review</h2>
@@ -64,208 +77,229 @@ Changes to Go must be reviewed before they are submitted,
no matter who makes the change.
(In exceptional cases, such as fixing a build, the review can
follow shortly after submitting.)
-A Mercurial extension helps manage the code review process.
-The extension is included in the Go source tree but needs
-to be added to your Mercurial configuration.
+A custom git command called <code>git-review</code>,
+discussed below, helps manage the code review process through a Google-hosted
+<a href="https://go-review.googlesource.com/">instance</a> of the code review
+system called <a href="https://code.google.com/p/gerrit/">Gerrit</a>.
</p>
-<h3>Caveat for Mercurial aficionados</h3>
+<h3>Set up authentication for code review</h3>
<p>
-<i>Using Mercurial with the code review extension is not the same
-as using standard Mercurial.</i>
+The Git code hosting server and Gerrit code review server both use a Google
+Account to authenticate. You therefore need a Google Account to proceed.
+(If you can use the account to
+<a href="https://www.google.com/accounts/Login">sign in at google.com</a>,
+you can use it to sign in to the code review server.)
+The email address you use with the code review system
+will be recorded in the <a href="https://go.googlesource.com/go">change log</a>
+and in the <a href="/CONTRIBUTORS"><code>CONTRIBUTORS</code></a> file.
+You can <a href="https://www.google.com/accounts/NewAccount">create a Google Account</a>
+associated with any address where you receive email.
+</p>
+
+<p>
+Visit the site <a href="https://go.googlesource.com">go.googlesource.com</a>
+and log in using your Google Account.
+Click on the "Generate Password" link that appears at the top of the page.
</p>
<p>
-The Go repository is maintained as a single line of reviewed changes;
-we prefer to avoid the complexity of Mercurial's arbitrary change graph.
-The code review extension helps here: its <code>hg submit</code> command
-automatically checks for and warns about the local repository
-being out of date compared to the remote one.
-The <code>hg submit</code> command also verifies other
-properties about the Go repository.
-For example,
-it checks that Go code being checked in is formatted in the standard style,
-as defined by <a href="/cmd/gofmt">gofmt</a>,
-and it checks that the author of the code is properly recorded for
-<a href="#copyright">copyright purposes</a>.
+Click the radio button that says "Only <code>go.googlesource.com</code>"
+to use this authentication token only for the Go project.
</p>
<p>
-To help ensure changes are only created by <code>hg submit</code>,
-the code review extension disables the standard <code>hg commit</code>
-command.
+Further down the page is a box containing commands to install
+the authentication cookie in file called <code>.gitcookies</code> in your home
+directory.
+Copy the text for the commands into a Unix shell window to execute it.
+That will install the authentication token.
</p>
-<h3>Configure the extension</h3>
+<p>
+(If you are on a Windows computer, you should instead follow the instructions
+in the yellow box to run the command.)
+</p>
-<p>Edit <code>.hg/hgrc</code> in the root of your Go checkout to add:</p>
+<h3>Register with Gerrit</h3>
-<pre>
-[extensions]
-codereview = /path/to/go/lib/codereview/codereview.py
+<p>
+Now that you have a Google account and the authentication token,
+you need to register your account with Gerrit, the code review system.
+To do this, visit <a href="https://golang.org/cl">golang.org/cl</a>
+and log in using the same Google Account you used above.
+That is all that is required.
+</p>
-[ui]
-username = Your Name &lt;you@server.dom&gt;
+<h3>Install the git-review command</h3>
+
+<p>
+Now install the <code>git-review</code> command by running,
+</p>
+
+<pre>
+go get -u golang.org/x/review/git-review
</pre>
<p>
-The <code>username</code> information will not be used unless
-you are a committer (see below), but Mercurial complains if it is missing.
+Make sure <code>git-review</code> is installed in your shell path, so that the
+<code>git</code> command can find it. Check that
</p>
+<pre>
+$ git review help
+</pre>
+
<p>
-As the codereview extension is only enabled for your Go checkout, the remainder of this document assumes you
-are inside the go directory when issuing commands.
+prints help text, not an error.
</p>
-<p>To contribute to subrepositories, edit the <code>.hg/hgrc</code> for each
-subrepository in the same way. For example, add the codereview extension to
-<code>code.google.com/p/go.tools/.hg/hgrc</code>.
+<p>
+Note to Git aficionados: The <code>git-review</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-review command. If you do use plain
+Git, note that you still need the commit hooks that the git-review 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
+if you intend to use plain Git for daily work, install the hooks in a new Git
+checkout by running <code>git-review</code> <code>hooks</code>).
</p>
-<h3>Understanding the extension</h3>
+<h3>Set up git aliases</h3>
-<p>After adding the code review extension, you can run</p>
+<p>
+The <code>git-review</code> command can be run directly from the shell
+by typing, for instance,
+</p>
<pre>
-$ hg help codereview
+$ git review sync
</pre>
-<p>to learn more about its commands. To learn about a specific code-review-specific
-command such as <code>change</code>, run</p>
+<p>
+but it is more convenient to set up aliases for <code>git-review</code>'s own
+subcommands, so that the above becomes,
+</p>
<pre>
-$ hg help change
+$ git sync
</pre>
-<p>
-Windows users may need to perform extra steps to get the code review
-extension working. See the
-<a href="https://code.google.com/p/go-wiki/wiki/CodeReview">CodeReview page</a>
-on the <a href="https://code.google.com/p/go-wiki/wiki">Go Wiki</a> for details.
</p>
-
-<h3>Log in to the code review site.</h3>
+The <code>git-review</code> subcommands have been chosen to be distinct from
+Git's own, so it's safe to do so.
+</p>
<p>
-The code review server uses a Google Account to authenticate.
-(If you can use the account to
-<a href="https://www.google.com/accounts/Login?hl=en&amp;continue=http://www.google.com/">sign in at google.com</a>,
-you can use it to sign in to the code review server.)
-The email address you use on the Code Review site
-will be recorded in the <a href="https://code.google.com/p/go/source/list">Mercurial change log</a>
-and in the <a href="/CONTRIBUTORS"><code>CONTRIBUTORS</code></a> file.
-You can <a href="https://www.google.com/accounts/NewAccount">create a Google Account</a>
-associated with any address where you receive email.
-If you've enabled the two-step verification feature, don't forget to generate an
-application-specific password and use that when prompted for a password.
+The aliases are optional, but in the rest of this document we will assume
+they are installed.
+To install them, copy this text into your Git configuration file
+(usually <code>.gitconfig</code> in your home directory):
</p>
<pre>
-$ hg code-login
-Email (login for uploading to codereview.appspot.com): rsc@golang.org
-Password for rsc@golang.org:
-
-Saving authentication cookies to /Users/rsc/.codereview_upload_cookies_codereview.appspot.com
+[alias]
+ change = review change
+ gofmt = review gofmt
+ mail = review mail
+ pending = review pending
+ sync = review sync
</pre>
-<h3>Configure your account settings.</h3>
+<h3>Understanding the git-review command</h3>
-<p>Edit your <a href="https://codereview.appspot.com/settings">code review settings</a>.
-Grab a nickname.
-Many people prefer to set the Context option to
-&ldquo;Whole file&rdquo; to see more context when reviewing changes.
-</p>
+<p>After installing the <code>git-review</code> command, you can run</p>
+
+<pre>
+$ git review help
+</pre>
-<p>Once you have chosen a nickname in the settings page, others
-can use that nickname as a shorthand for naming reviewers and the CC list.
-For example, <code>rsc</code> is an alias for <code>rsc@golang.org</code>.
+<p>
+to learn more about its commands.
+You can also read the <a href="https://godoc.org/golang.org/x/review/git-review">command documentation</a>.
</p>
-<h3>Switch to the default branch</h3>
+<h3>Switch to the master branch</h3>
<p>
Most Go installations use a release branch, but new changes should
-only be made to the default branch. (They may be applied later to a release
-branch as part of the release process.)
-Before making a change, make sure you use the default branch:
+only be made based on the master branch.
+(They may be applied later to a release branch as part of the release process,
+but most contributors won't do this themselves.)
+Before making a change, make sure you start on the master branch:
</p>
<pre>
-$ hg update default
+$ git checkout master
+$ git sync
</pre>
+<p>
+(In Git terms, <code>git</code> <code>sync</code> runs
+<code>git</code> <code>pull</code> <code>-r</code>.)
+</p>
+
<h3>Make a change</h3>
<p>
The entire checked-out tree is writable.
-If you need to edit files, just edit them: Mercurial will figure out which ones changed.
-You do need to inform Mercurial of added, removed, copied, or renamed files,
-by running
-<code>hg add</code>,
-<code>hg rm</code>,
-<code>hg cp</code>,
-or
-<code>hg mv</code>.
+Once you have edited files, you must tell Git that they have been modified.
+You must also tell Git about any files that are added, removed, or renamed files.
+These operations are done with the usual Git commands,
+<code>git</code> <code>add</code>,
+<code>git</code> <code>rm</code>,
+and
+<code>git</code> <code>mv</code>.
</p>
-<p>When you are ready to send a change out for review, run</p>
+<p>
+If you wish to checkpoint your work, or are ready to send the code out for review, run</p>
<pre>
-$ hg change
+$ git change <i>&lt;branch&gt;</i>
</pre>
-<p>from any directory in your Go repository.
-Mercurial will open a change description file in your editor.
-(It uses the editor named by the <code>$EDITOR</code> environment variable, <code>vi</code> by default.)
-The file will look like:
+<p>
+from any directory in your Go repository to commit the changes so far.
+The name <i>&lt;branch&gt;</i> is an arbitrary one you choose to identify the
+local branch containing your changes.
</p>
-<pre>
-# Change list.
-# Lines beginning with # are ignored.
-# Multi-line values should be indented.
+<p>
+(In Git terms, <code>git</code> <code>change</code> <code>&lt;branch&gt;</code>
+runs <code>git</code> <code>checkout</code> <code>-b</code> <code>branch</code>,
+then <code>git</code> <code>branch</code> <code>--set-upstream-to</code> <code>origin/master</code>,
+then <code>git</code> <code>commit</code>.)
+</p>
-Reviewer:
-CC:
+<p>
+Git will open a change description file in your editor.
+(It uses the editor named by the <code>$EDITOR</code> environment variable,
+<code>vi</code> by default.)
+The file will look like:
+</p>
-Description:
- &lt;enter description here&gt;
+<pre>
-Files:
- src/pkg/math/sin.go
- src/pkg/math/tan.go
- src/pkg/regexp/regexp.go
+# Please enter the commit message for your changes. Lines starting
+# with '#' will be ignored, and an empty message aborts the commit.
+# On branch foo
+# Changes not staged for commit:
+# modified: editedfile.go
+#
</pre>
<p>
-The <code>Reviewer</code> line lists the reviewers assigned
-to this change, and the <code>CC</code> line lists people to
-notify about the change.
-These can be code review nicknames or arbitrary email addresses.
-Unless explicitly told otherwise, such as in the discussion leading
-up to sending in the change list, leave the reviewer field blank.
-This means that the
-<a href="https://groups.google.com/group/golang-codereviews">golang-codereviews@googlegroups.com</a>
-mailing list will be used as the reviewer.
-</p>
-
-<p>
-Replace &ldquo;<code>&lt;enter description here&gt;</code>&rdquo;
-with a description of your change.
+At the beginning of this file is a blank line; replace it
+with a thorough description of your change.
The first line of the change description is conventionally a one-line
summary of the change, prefixed by the primary affected package,
-and is used as the subject for code review mail; the rest of the
-description elaborates.
-</p>
-
-<p>
-The <code>Files</code> section lists all the modified files
-in your client.
-It is best to keep unrelated changes in different change lists.
-In this example, we can include just the changes to package <code>math</code>
-by deleting the line mentioning <code>regexp.go</code>.
+and is used as the subject for code review mail.
+The rest of the
+description elaborates and should provide context for the
+change and explain what it does.
+If there is a helpful reference, mention it here.
</p>
<p>
@@ -273,343 +307,314 @@ After editing, the template might now read:
</p>
<pre>
-# Change list.
-# Lines beginning with # are ignored.
-# Multi-line values should be indented.
+math: improved Sin, Cos and Tan precision for very large arguments
-Reviewer: golang-codereviews@googlegroups.com
-CC: math-nuts@swtch.com
+The existing implementation has poor numerical properties for
+large arguments, so use the McGillicutty algorithm to improve
+accuracy above 1e10.
-Description:
- math: improved Sin, Cos and Tan precision for very large arguments.
+The algorithm is described at http://wikipedia.org/wiki/McGillicutty_Algorithm
- See Bimmler and Shaney, ``Extreme sinusoids,'' J. Math 3(14).
- Fixes issue 159.
+Fixes #159
-Files:
- src/pkg/math/sin.go
- src/pkg/math/tan.go
+# Please enter the commit message for your changes. Lines starting
+# with '#' will be ignored, and an empty message aborts the commit.
+# On branch foo
+# Changes not staged for commit:
+# modified: editedfile.go
+#
</pre>
<p>
-The special sentence &ldquo;Fixes issue 159.&rdquo; associates
-the change with issue 159 in the <a href="https://code.google.com/p/go/issues/list">Go issue tracker</a>.
+The commented section of the file lists all the modified files in your client.
+It is best to keep unrelated changes in different change lists,
+so if you see a file listed that should not be included, abort
+the command and move that file to a different branch.
+</p>
+
+<p>
+The special notation "Fixes #159" associates the change with issue 159 in the
+<a href="https://golang.org/issue/159">Go issue tracker</a>.
When this change is eventually submitted, the issue
tracker will automatically mark the issue as fixed.
-(These conventions are described in detail by the
-<a href="https://code.google.com/p/support/wiki/IssueTracker#Integration_with_version_control">Google Project Hosting Issue Tracker documentation</a>.)
+(There are several such conventions, described in detail in the
+<a href="https://help.github.com/articles/closing-issues-via-commit-messages/">GitHub Issue Tracker documentation</a>.)
</p>
<p>
-Save the file and exit the editor.</p>
+Once you have finished writing the commit message,
+save the file and exit the editor.
+</p>
<p>
-The code review server assigns your change an issue number and URL,
-which <code>hg change</code> will print, something like:
+If you wish to do more editing, re-stage your changes using
+<code>git</code> <code>add</code>, and then run
</p>
<pre>
-CL created: https://codereview.appspot.com/99999
+$ git change
</pre>
-<h3>Adding or removing files from an existing change</h3>
-
<p>
-If you need to re-edit the change description, or change the files included in the CL,
-run <code>hg change 99999</code>.
+to update the change description and incorporate the staged changes. The
+change description contains a <code>Change-Id</code> line near the bottom,
+added by a Git commit hook during the initial
+<code>git</code> <code>change</code>.
+That line is used by Gerrit to match successive uploads of the same change.
+Do not edit or delete it.
</p>
<p>
-Alternatively, you can use
+(In Git terms, <code>git</code> <code>change</code> with no branch name
+runs <code>git</code> <code>commit</code> <code>--amend</code>.)
+</p>
+
+<h3>Mail the change for review</h3>
+
+<p>
+Once the change is ready, mail it out for review:
</p>
<pre>
-$ hg file 99999 somefile
+$ git mail
</pre>
<p>
-to add <code>somefile</code> to CL 99999, and
+You can specify a reviewer or CC interested parties
+using the <code>-r</code> or <code>-cc</code> options.
+Both accept a comma-separated list of email addresses:
</p>
<pre>
-$ hg file -d 99999 somefile
+$ git mail -r joe@golang.org -cc mabel@example.com,math-nuts@swtch.com
</pre>
<p>
-to remove <code>somefile</code> from the CL.
+Unless explicitly told otherwise, such as in the discussion leading
+up to sending in the change list, it's better not to specify a reviewer.
+All changes are automatically CC'ed to the
+<a href="https://groups.google.com/group/golang-codereviews">golang-codereviews@googlegroups.com</a>
+mailing list.
</p>
<p>
-A file may only belong to a single active CL at a time. <code>hg file</code>
-will issue a warning if a file is moved between changes.
+(In Git terms, <code>git</code> <code>mail</code> pushes the local committed
+changes to Gerrit using <code>git</code> <code>push</code> <code>origin</code>
+<code>HEAD:refs/for/master</code>.)
</p>
-<h3>Synchronize your client</h3>
-
-<p>While you were working, others might have submitted changes
-to the repository. To update your client, run</p>
-
-<pre>
-$ hg sync
-</pre>
-
-<p>(For Mercurial fans, <code>hg sync</code> runs <code>hg pull -u</code>
-but then also synchronizes the local change list state against the new data.)</p>
-
<p>
-If files you were editing have changed, Mercurial does its best to merge the
-remote changes into your local changes. It may leave some files to merge by hand.
+If your change relates to an open issue, please add a comment to the issue
+announcing your proposed fix, including a link to your CL.
</p>
<p>
-For example, suppose you have edited <code>flag_test.go</code> but
-someone else has committed an independent change.
-When you run <code>hg sync</code>, you will get the (scary-looking) output
-(emphasis added):
+The code review server assigns your change an issue number and URL,
+which <code>git</code> <code>mail</code> will print, something like:
+</p>
<pre>
-$ hg sync
-adding changesets
-adding manifests
-adding file changes
-added 1 changeset with 2 changes to 2 files
-getting src/pkg/flag/flag.go
-couldn't find merge tool hgmerge
-merging src/pkg/flag/flag_test.go
-warning: conflicts during merge.
-<i>merging src/pkg/flag/flag_test.go failed!</i>
-1 file updated, 0 files merged, 0 files removed, 1 file unresolved
-use 'hg resolve' to retry unresolved file merges
-$
+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>
+
<p>
-The only important part in that transcript is the italicized line:
-Mercurial failed to merge your changes with the independent change.
-When this happens, Mercurial leaves both edits in the file,
-marked by <code>&lt;&lt;&lt;&lt;&lt;&lt;&lt;</code> and
-<code>&gt;&gt;&gt;&gt;&gt;&gt;&gt;</code>.
-it is now your job to edit the file to combine them.
-Continuing the example, searching for those strings in <code>flag_test.go</code>
-might turn up:
+Running <code>git</code> <code>mail</code> will send an email to you and the
+reviewers asking them to visit the issue's URL and make comments on the change.
+When done, the reviewer adds comments through the Gerrit user interface
+and clicks "Reply" to send comments back.
+You will receive a mail notification when this happens.
+You must reply through the web interface.
+(Unlike with the old Rietveld review system, replying by mail has no effect.)
</p>
-<pre>
- VisitAll(visitor);
-&lt;&lt;&lt;&lt;&lt;&lt;&lt; local
- if len(m) != 7 {
-=======
- if len(m) != 8 {
-&gt;&gt;&gt;&gt;&gt;&gt;&gt; other
- t.Error("VisitAll misses some flags");
-</pre>
+<h3>Revise and upload</h3>
<p>
-Mercurial doesn't show it, but suppose the original text that both edits
-started with was 6; you added 1 and the other change added 2,
-so the correct answer might now be 9. First, edit the section
-to remove the markers and leave the correct code:
+You must respond to review comments through the web interface.
+(Unlike with the old Rietveld review system, responding by mail has no effect.)
</p>
-<pre>
- VisitAll(visitor);
- if len(m) != 9 {
- t.Error("VisitAll misses some flags");
-</pre>
-
<p>
-Then ask Mercurial to mark the conflict as resolved:
+When you have revised the code and are ready for another round of review,
+stage those changes and use <code>git</code> <code>change</code> to update the
+commit.
+To send the update change list for another round of review,
+run <code>git</code> <code>mail</code> again.
</p>
-<pre>
-$ hg resolve -m flag_test.go
-</pre>
-
<p>
-If you had been editing the file, say for debugging, but do not
-care to preserve your changes, you can run
-<code>hg revert flag_test.go</code> to abandon your
-changes, but you may still need to run
-<code>hg resolve -m</code> to mark the conflict resolved.
+The reviewer can comment on the new copy, and the process repeats.
+The reviewer approves the change by giving it a positive score
+(+1 or +2) and replying <code>LGTM</code>: looks good to me.
</p>
-<h3>Mail the change for review</h3>
-
<p>
-Creating or uploading the change uploads a copy of the diff to the code review server,
-but it does not notify anyone about it. To do that, you need to run <code>hg mail</code>
-(see below).
+You can see a list of your pending changes by running <code>git</code>
+<code>pending</code>, and switch between change branches with <code>git</code>
+<code>change</code> <code><i>&lt;branch&gt;</i></code>.
</p>
-<p>To send out a change for review, run <code>hg mail</code> using the change list number
-assigned during <code>hg change</code>:</p>
-
-<pre>
-$ hg mail 99999
-</pre>
+<h3>Synchronize your client</h3>
-<p>You can add to the <code>Reviewer:</code> and <code>CC:</code> lines
-using the <code>-r</code> or <code>--cc</code> options.
-In the above example, we could have left the <code>Reviewer</code> and <code>CC</code>
-lines blank and then run:
+<p>
+While you were working, others might have submitted changes to the repository.
+To update your local branch, run
</p>
<pre>
-$ hg mail -r golang-codereviews@googlegroups.com --cc math-nuts@swtch.com 99999
+$ git sync
</pre>
-<p>to achieve the same effect.</p>
-
-<p>Note that <code>-r</code> and <code>--cc</code> cannot be spelled <code>--r</code> or <code>-cc</code>.</p>
-
<p>
-If your change relates to an open issue, please add a comment to the issue
-announcing your proposed fix, including a link to your CL.
+(In git terms, git sync runs
+<code>git</code> <code>pull</code> <code>-r</code>.)
</p>
-<h3>Reviewing code</h3>
-
<p>
-Running <code>hg mail</code> will send an email to you and the reviewers
-asking them to visit the issue's URL and make comments on the change.
-When done, the reviewer clicks &ldquo;Publish and Mail comments&rdquo;
-to send comments back.
+If files you were editing have changed, Git does its best to merge the
+remote changes into your local changes.
+It may leave some files to merge by hand.
</p>
-
-<h3>Revise and upload</h3>
-
<p>
-When you have revised the code and are ready for another round of review,
-you can upload your change and send mail asking the reviewers to
-please take another look (<code>PTAL</code>). Use the change list number
-assigned during <code>hg change</code>
-</p>
+For example, suppose you have edited <code>sin.go</code> but
+someone else has committed an independent change.
+When you run <code>git</code> <code>sync</code>,
+you will get the (scary-looking) output:
<pre>
-$ hg mail 99999
+$ git sync
+Failed to merge in the changes.
+Patch failed at 0023 math: improved Sin, Cos and Tan precision for very large arguments
+The copy of the patch that failed is found in:
+   /home/you/repo/.git/rebase-apply/patch
+
+When you have resolved this problem, run "git rebase --continue".
+If you prefer to skip this patch, run "git rebase --skip" instead.
+To check out the original branch and stop rebasing, run "git rebase --abort".
</pre>
-
<p>
-Or to upload your change without sending a notification, run
+If this happens, run
</p>
<pre>
-$ hg upload 99999
+$ git status
</pre>
<p>
-You will probably revise your code in response to the reviewer comments.
-You might also visit the code review web page and reply to the comments,
-letting the reviewer know that you've addressed them or explain why you
-haven't. When you're done replying, click &ldquo;Publish and Mail comments&rdquo;
-to send the line-by-line replies and any other comments.
+to see which files failed to merge.
+The output will look something like this:
</p>
-<p>
-The reviewer can comment on the new copy, and the process repeats.
-The reviewer approves the change by replying with a mail that says
-<code>LGTM</code>: looks good to me.
-</p>
+<pre>
+rebase in progress; onto a24c3eb
+You are currently rebasing branch 'mcgillicutty' on 'a24c3eb'.
+  (fix conflicts and then run "git rebase --continue")
+  (use "git rebase --skip" to skip this patch)
+  (use "git rebase --abort" to check out the original branch)
-<p>
-You can see a list of your pending changes by running <code>hg pending</code> (<code>hg p</code> for short).
-</p>
+Unmerged paths:
+  (use "git reset HEAD &lt;file&gt;..." to unstage)
+  (use "git add &lt;file&gt;..." to mark resolution)
-<h3>Reviewing code by others</h3>
+ <i>both modified:   sin.go</i>
+</pre>
<p>
-You can import a CL proposed by someone else into your local Mercurial client
-by using the <code>hg clpatch</code> command. Running
+The only important part in that transcript is the italicized "both modified"
+line: Git failed to merge your changes with the conflicting change.
+When this happens, Git leaves both sets of edits in the file,
+with conflicts marked by <code>&lt;&lt;&lt;&lt;&lt;&lt;&lt;</code> and
+<code>&gt;&gt;&gt;&gt;&gt;&gt;&gt;</code>.
+It is now your job to edit the file to combine them.
+Continuing the example, searching for those strings in <code>sin.go</code>
+might turn up:
</p>
<pre>
-$ hg clpatch 99999
+ arg = scale(arg)
+&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD
+ if arg > 1e9 {
+=======
+ if arg > 1e10 {
+&gt;&gt;&gt;&gt;&gt;&gt;&gt; mcgillicutty
+ largeReduce(arg)
</pre>
<p>
-will apply the latest diff for CL 99999 to your working copy. If any of the
-files referenced in CL 99999 have local modifications, <code>clpatch</code>
-will refuse to apply the whole diff. Once applied, CL 99999 will show up in
-the output of <code>hg pending</code> and others.
-</p>
-
-<p>
-To revert a CL you have applied locally, use the <code>hg revert</code>
-command. Running
+Git doesn't show it, but suppose the original text that both edits
+started with was 1e8; you changed it to 1e10 and the other change to 1e9,
+so the correct answer might now be 1e10. First, edit the section
+to remove the markers and leave the correct code:
</p>
<pre>
-$ hg revert @99999
+ arg = scale(arg)
+ if arg > 1e10 {
+ largeReduce(arg)
</pre>
<p>
-will revert any files mentioned on CL 99999 to their original state. This can
-be an effective way of reverting one CL revision and applying another.
+Then tell Git that the conflict is resolved by running
</p>
-<p>
-Once the CL has been submitted, the next time you run <code>hg sync</code>
-it will be removed from your local pending list. Occasionally the pending list
-can get out of sync leaving stale references to closed or abandoned CLs.
-You can use <code>hg change -D 99999</code> to remove the reference to CL 99999.
-</p>
-
-<h3>Submit the change after the review</h3>
+<pre>
+$ git add sin.go
+</pre>
<p>
-After the code has been <code>LGTM</code>'ed, it is time to submit
-it to the Mercurial repository.
+If you had been editing the file, say for debugging, but do not
+care to preserve your changes, you can run
+<code>git</code> <code>reset</code> <code>HEAD</code> <code>sin.go</code>
+to abandon your changes.
+Then run <code>git</code> <code>rebase</code> <code>--continue</code> to
+restore the change commit.
</p>
+<h3>Reviewing code by others</h3>
+
<p>
-If you are not a committer, you cannot submit the change directly.
-Instead a committer, usually the reviewer who said <code>LGTM</code>,
-will run:
+You can import a change proposed by someone else into your local Git repository.
+On the Gerrit review page, click the "Download ▼" link in the upper right
+corner, copy the "Checkout" command and run it from your local Git repo.
+It should look something like this:
</p>
<pre>
-$ hg clpatch 99999
-$ hg submit 99999
+$ git fetch https://go.googlesource.com/review refs/changes/21/1221/1 && git checkout FETCH_HEAD
</pre>
<p>
-The <code>submit</code> command submits the code. You will be listed as the
-author, but the change message will also indicate who the committer was.
-Your local client will notice that the change has been submitted
-when you next run <code>hg sync</code>.
+To revert, change back to the branch you were working in.
</p>
+<h3>Submit the change after the review</h3>
+
<p>
-If you are a committer, you can run:
+After the code has been <code>LGTM</code>'ed, an approver may
+submit it to the master branch using the Gerrit UI.
+There is a "Submit" button on the web page for the change
+that appears once the change is approved (marked +2).
</p>
-<pre>
-$ hg submit 99999
-</pre>
-
<p>
This checks the change into the repository.
The change description will include a link to the code review,
and the code review will be updated with a link to the change
in the repository.
+Since the method used to integrate the changes is "Cherry Pick",
+the commit hashes in the repository will be changed by
+the submit operation.
</p>
-<p>
-If your local copy of the repository is out of date,
-<code>hg submit</code> will refuse the change:
-</p>
-
-<pre>
-$ hg submit 99999
-local repository out of date; must sync before submit
-</pre>
-
<h3>More information</h3>
<p>
-In addition to the information here, the Go community maintains a <a href="https://code.google.com/p/go-wiki/wiki/CodeReview">CodeReview</a> wiki page.
+In addition to the information here, the Go community maintains a <a href="https://golang.org/wiki/CodeReview">CodeReview</a> wiki page.
Feel free to contribute to this page as you learn the review process.
</p>
@@ -617,7 +622,8 @@ Feel free to contribute to this page as you learn the review process.
<p>Files in the Go repository don't list author names,
both to avoid clutter and to avoid having to keep the lists up to date.
-Instead, your name will appear in the <a href="https://code.google.com/p/go/source/list">Mercurial change log</a>
+Instead, your name will appear in the
+<a href="https://golang.org/change">change log</a>
and in the <a href="/CONTRIBUTORS"><code>CONTRIBUTORS</code></a> file
and perhaps the <a href="/AUTHORS"><code>AUTHORS</code></a> file.
</p>
diff --git a/doc/debugging_with_gdb.html b/doc/debugging_with_gdb.html
index afaedf74c..836816419 100644
--- a/doc/debugging_with_gdb.html
+++ b/doc/debugging_with_gdb.html
@@ -120,7 +120,7 @@ For example:
<p>
If you'd like to see how this works, or want to extend it, take a look at <a
-href="/src/pkg/runtime/runtime-gdb.py">src/pkg/runtime/runtime-gdb.py</a> in
+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&lt;T,U&gt;</code>) and variables (<code>runtime.m</code> and
<code>runtime.g</code>) that the linker
@@ -153,7 +153,7 @@ the form <code>pkg.(*MyType).Meth</code>.
<p>
In this tutorial we will inspect the binary of the
<a href="/pkg/regexp/">regexp</a> package's unit tests. To build the binary,
-change to <code>$GOROOT/src/pkg/regexp</code> and run <code>go test -c</code>.
+change to <code>$GOROOT/src/regexp</code> and run <code>go test -c</code>.
This should produce an executable file named <code>regexp.test</code>.
</p>
@@ -172,7 +172,7 @@ License GPLv 3+: GNU GPL version 3 or later &lt;http://gnu.org/licenses/gpl.htm
Type "show copying" and "show warranty" for licensing/warranty details.
This GDB was configured as "x86_64-linux".
-Reading symbols from /home/user/go/src/pkg/regexp/regexp.test...
+Reading symbols from /home/user/go/src/regexp/regexp.test...
done.
Loading Go Runtime support.
(gdb)
@@ -180,7 +180,7 @@ Loading Go Runtime support.
<p>
The message <code>"Loading Go Runtime support"</code> means that GDB loaded the
-extension from <code>$GOROOT/src/pkg/runtime/runtime-gdb.py</code>.
+extension from <code>$GOROOT/src/runtime/runtime-gdb.py</code>.
</p>
<p>
@@ -199,7 +199,7 @@ it by hand by telling gdb (assuming you have the go sources in
</p>
<pre>
-(gdb) <b>source ~/go/src/pkg/runtime/runtime-gdb.py</b>
+(gdb) <b>source ~/go/src/runtime/runtime-gdb.py</b>
Loading Go Runtime support.
</pre>
@@ -259,7 +259,7 @@ Set a breakpoint at the <code>TestFind</code> function:
<pre>
(gdb) <b>b 'regexp.TestFind'</b>
-Breakpoint 1 at 0x424908: file /home/user/go/src/pkg/regexp/find_test.go, line 148.
+Breakpoint 1 at 0x424908: file /home/user/go/src/regexp/find_test.go, line 148.
</pre>
<p>
@@ -268,9 +268,9 @@ Run the program:
<pre>
(gdb) <b>run</b>
-Starting program: /home/user/go/src/pkg/regexp/regexp.test
+Starting program: /home/user/go/src/regexp/regexp.test
-Breakpoint 1, regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
+Breakpoint 1, regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/regexp/find_test.go:148
148 func TestFind(t *testing.T) {
</pre>
@@ -297,9 +297,9 @@ Look at the stack trace for where we’ve paused the program:
<pre>
(gdb) <b>bt</b> <i># backtrace</i>
-#0 regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
-#1 0x000000000042f60b in testing.tRunner (t=0xf8404a89c0, test=0x573720) at /home/user/go/src/pkg/testing/testing.go:156
-#2 0x000000000040df64 in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:242
+#0 regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/regexp/find_test.go:148
+#1 0x000000000042f60b in testing.tRunner (t=0xf8404a89c0, test=0x573720) at /home/user/go/src/testing/testing.go:156
+#2 0x000000000040df64 in runtime.initdone () at /home/user/go/src/runtime/proc.c:242
#3 0x000000f8404a89c0 in ?? ()
#4 0x0000000000573720 in ?? ()
#5 0x0000000000000000 in ?? ()
@@ -311,18 +311,18 @@ The other goroutine, number 1, is stuck in <code>runtime.gosched</code>, blocked
<pre>
(gdb) <b>goroutine 1 bt</b>
-#0 0x000000000040facb in runtime.gosched () at /home/user/go/src/pkg/runtime/proc.c:873
+#0 0x000000000040facb in runtime.gosched () at /home/user/go/src/runtime/proc.c:873
#1 0x00000000004031c9 in runtime.chanrecv (c=void, ep=void, selected=void, received=void)
- at /home/user/go/src/pkg/runtime/chan.c:342
-#2 0x0000000000403299 in runtime.chanrecv1 (t=void, c=void) at/home/user/go/src/pkg/runtime/chan.c:423
+ at /home/user/go/src/runtime/chan.c:342
+#2 0x0000000000403299 in runtime.chanrecv1 (t=void, c=void) at/home/user/go/src/runtime/chan.c:423
#3 0x000000000043075b in testing.RunTests (matchString={void (struct string, struct string, bool *, error *)}
- 0x7ffff7f9ef60, tests= []testing.InternalTest = {...}) at /home/user/go/src/pkg/testing/testing.go:201
+ 0x7ffff7f9ef60, tests= []testing.InternalTest = {...}) at /home/user/go/src/testing/testing.go:201
#4 0x00000000004302b1 in testing.Main (matchString={void (struct string, struct string, bool *, error *)}
0x7ffff7f9ef80, tests= []testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark = {...})
-at /home/user/go/src/pkg/testing/testing.go:168
-#5 0x0000000000400dc1 in main.main () at /home/user/go/src/pkg/regexp/_testmain.go:98
-#6 0x00000000004022e7 in runtime.mainstart () at /home/user/go/src/pkg/runtime/amd64/asm.s:78
-#7 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:243
+at /home/user/go/src/testing/testing.go:168
+#5 0x0000000000400dc1 in main.main () at /home/user/go/src/regexp/_testmain.go:98
+#6 0x00000000004022e7 in runtime.mainstart () at /home/user/go/src/runtime/amd64/asm.s:78
+#7 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/runtime/proc.c:243
#8 0x0000000000000000 in ?? ()
</pre>
@@ -333,7 +333,7 @@ The stack frame shows we’re currently executing the <code>regexp.TestFind</cod
<pre>
(gdb) <b>info frame</b>
Stack level 0, frame at 0x7ffff7f9ff88:
- rip = 0x425530 in regexp.TestFind (/home/user/go/src/pkg/regexp/find_test.go:148);
+ rip = 0x425530 in regexp.TestFind (/home/user/go/src/regexp/find_test.go:148);
saved rip 0x430233
called by frame at 0x7ffff7f9ffa8
source language minimal.
@@ -410,7 +410,7 @@ We can step into the <code>String</code>function call with <code>"s"</code>:
<pre>
(gdb) <b>s</b>
-regexp.(*Regexp).String (re=0xf84068d070, noname=void) at /home/user/go/src/pkg/regexp/regexp.go:97
+regexp.(*Regexp).String (re=0xf84068d070, noname=void) at /home/user/go/src/regexp/regexp.go:97
97 func (re *Regexp) String() string {
</pre>
@@ -421,12 +421,12 @@ Get a stack trace to see where we are:
<pre>
(gdb) <b>bt</b>
#0 regexp.(*Regexp).String (re=0xf84068d070, noname=void)
- at /home/user/go/src/pkg/regexp/regexp.go:97
+ at /home/user/go/src/regexp/regexp.go:97
#1 0x0000000000425615 in regexp.TestFind (t=0xf840688b60)
- at /home/user/go/src/pkg/regexp/find_test.go:151
+ at /home/user/go/src/regexp/find_test.go:151
#2 0x0000000000430233 in testing.tRunner (t=0xf840688b60, test=0x5747b8)
- at /home/user/go/src/pkg/testing/testing.go:156
-#3 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:243
+ at /home/user/go/src/testing/testing.go:156
+#3 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/runtime/proc.c:243
....
</pre>
diff --git a/doc/devel/release.html b/doc/devel/release.html
index 1a8439134..5b5d6ab5e 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -3,8 +3,7 @@
}-->
<p>This page summarizes the changes between official stable releases of Go.
-The <a href="//code.google.com/p/go/source/list">Mercurial change log</a>
-has the full details.</p>
+The <a href="//golang.org/change">change log</a> has the full details.</p>
<p>To update to a specific release, use:</p>
@@ -13,6 +12,13 @@ hg pull
hg update <i>tag</i>
</pre>
+<h2 id="go1.4">go1.4 (released 2014/12/10)</h2>
+
+<p>
+Go 1.4 is a major release of Go.
+Read the <a href="/doc/go1.4">Go 1.4 Release Notes</a> for more information.
+</p>
+
<h2 id="go1.3">go1.3 (released 2014/06/18)</h2>
<p>
diff --git a/doc/devel/weekly.html b/doc/devel/weekly.html
index 34c87dc64..5a9c51ef1 100644
--- a/doc/devel/weekly.html
+++ b/doc/devel/weekly.html
@@ -5,7 +5,7 @@
<p>This page summarizes the changes between tagged weekly snapshots of Go.
Such snapshots are no longer created. This page remains as a historical reference only.</p>
-<p>For recent information, see the <a href="//code.google.com/p/go/source/list">Mercurial change log</a> and <a href="//groups.google.com/group/golang-dev/">development mailing list</a>.</p>
+<p>For recent information, see the <a href="//golang.org/change">change log</a> and <a href="//groups.google.com/group/golang-dev/">development mailing list</a>.</p>
<h2 id="2012-03-27">2012-03-27 (<a href="release.html#go1">Go 1</a>)</h2>
diff --git a/doc/docs.html b/doc/docs.html
index 642f36dd4..7eb3a3ad2 100644
--- a/doc/docs.html
+++ b/doc/docs.html
@@ -147,8 +147,8 @@ Guided tours of Go programs.
<li><a href="/blog/godoc-documenting-go-code">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li>
<li><a href="/blog/profiling-go-programs">Profiling Go Programs</a></li>
<li><a href="/doc/articles/race_detector.html">Data Race Detector</a> - a manual for the data race detector.</li>
-<li><a href="/blog/race-detector">Introducing the Go Race Detector</a> - an introduction to the race detector.
-<li><a href="/doc/asm">A Quick Guide to Go's Assembler</a> - an introduction to the assembler used by Go.
+<li><a href="/blog/race-detector">Introducing the Go Race Detector</a> - an introduction to the race detector.</li>
+<li><a href="/doc/asm">A Quick Guide to Go's Assembler</a> - an introduction to the assembler used by Go.</li>
</ul>
<h4 id="articles_more">More</h4>
diff --git a/doc/effective_go.html b/doc/effective_go.html
index c1e310796..4dd1a3e01 100644
--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -37,7 +37,7 @@ should read first.
<h3 id="examples">Examples</h3>
<p>
-The <a href="/src/pkg/">Go package sources</a>
+The <a href="/src/">Go package sources</a>
are intended to serve not
only as the core library but also as examples of how to
use the language.
@@ -344,7 +344,7 @@ determines just which package is being used.
<p>
Another convention is that the package name is the base name of
its source directory;
-the package in <code>src/pkg/encoding/base64</code>
+the package in <code>src/encoding/base64</code>
is imported as <code>"encoding/base64"</code> but has name <code>base64</code>,
not <code>encoding_base64</code> and not <code>encodingBase64</code>.
</p>
diff --git a/doc/gccgo_contribute.html b/doc/gccgo_contribute.html
index 9dd6ecb85..db7d1ab0e 100644
--- a/doc/gccgo_contribute.html
+++ b/doc/gccgo_contribute.html
@@ -73,7 +73,7 @@ script <code>libgo/merge.sh</code>. Accordingly, most library changes
should be made in the main Go repository. The files outside
of <code>libgo/go</code> are gccgo-specific; that said, some of the
files in <code>libgo/runtime</code> are based on files
-in <code>src/pkg/runtime</code> in the main Go repository.
+in <code>src/runtime</code> in the main Go repository.
</p>
<h2>Testing</h2>
diff --git a/doc/gccgo_install.html b/doc/gccgo_install.html
index 4c1a8c2f5..acb315a0a 100644
--- a/doc/gccgo_install.html
+++ b/doc/gccgo_install.html
@@ -42,6 +42,10 @@ identical to Go 1.1. The GCC 4.8.2 release includes a complete Go
1.1.2 implementation.
</p>
+<p>
+The GCC 4.9 releases include a complete Go 1.2 implementation.
+</p>
+
<h2 id="Source_code">Source code</h2>
<p>
diff --git a/doc/go1.3.html b/doc/go1.3.html
index 042de1bc7..d51052b2e 100644
--- a/doc/go1.3.html
+++ b/doc/go1.3.html
@@ -298,7 +298,7 @@ For example,
<h3 id="godoc">Changes to godoc</h3>
<p>
When invoked with the <code>-analysis</code> flag,
-<a href="//godoc.org/code.google.com/p/go.tools/cmd/godoc">godoc</a>
+<a href="//godoc.org/golang.org/x/tools/cmd/godoc">godoc</a>
now performs sophisticated <a href="/lib/godoc/analysis/help.html">static
analysis</a> of the code it indexes.
The results of analysis are presented in both the source view and the
@@ -318,7 +318,7 @@ call sites and their callees.
The program <code>misc/benchcmp</code> that compares
performance across benchmarking runs has been rewritten.
Once a shell and awk script in the main repository, it is now a Go program in the <code>go.tools</code> repo.
-Documentation is <a href="//godoc.org/code.google.com/p/go.tools/cmd/benchcmp">here</a>.
+Documentation is <a href="//godoc.org/golang.org/x/tools/cmd/benchcmp">here</a>.
</p>
<p>
diff --git a/doc/go1.4.html b/doc/go1.4.html
new file mode 100644
index 000000000..b4f9619bb
--- /dev/null
+++ b/doc/go1.4.html
@@ -0,0 +1,896 @@
+<!--{
+ "Title": "Go 1.4 Release Notes",
+ "Path": "/doc/go1.4",
+ "Template": true
+}-->
+
+<h2 id="introduction">Introduction to Go 1.4</h2>
+
+<p>
+The latest Go release, version 1.4, arrives as scheduled six months after 1.3.
+</p>
+
+<p>
+It contains only one tiny language change,
+in the form of a backwards-compatible simple variant of <code>for</code>-<code>range</code> loop,
+and a possibly breaking change to the compiler involving methods on pointers-to-pointers.
+</p>
+
+<p>
+The release focuses primarily on implementation work, improving the garbage collector
+and preparing the ground for a fully concurrent collector to be rolled out in the
+next few releases.
+Stacks are now contiguous, reallocated when necessary rather than linking on new
+"segments";
+this release therefore eliminates the notorious "hot stack split" problem.
+There are some new tools available including support in the <code>go</code> command
+for build-time source code generation.
+The release also adds support for ARM processors on Android and Native Client (NaCl)
+and for AMD64 on Plan 9.
+</p>
+
+<p>
+As always, Go 1.4 keeps the <a href="/doc/go1compat.html">promise
+of compatibility</a>,
+and almost everything
+will continue to compile and run without change when moved to 1.4.
+</p>
+
+<h2 id="language">Changes to the language</h2>
+
+<h3 id="forrange">For-range loops</h3>
+<p>
+Up until Go 1.3, <code>for</code>-<code>range</code> loop had two forms
+</p>
+
+<pre>
+for i, v := range x {
+ ...
+}
+</pre>
+
+<p>
+and
+</p>
+
+<pre>
+for i := range x {
+ ...
+}
+</pre>
+
+<p>
+If one was not interested in the loop values, only the iteration itself, it was still
+necessary to mention a variable (probably the <a href="/ref/spec#Blank_identifier">blank identifier</a>, as in
+<code>for</code> <code>_</code> <code>=</code> <code>range</code> <code>x</code>), because
+the form
+</p>
+
+<pre>
+for range x {
+ ...
+}
+</pre>
+
+<p>
+was not syntactically permitted.
+</p>
+
+<p>
+This situation seemed awkward, so as of Go 1.4 the variable-free form is now legal.
+The pattern arises rarely but the code can be cleaner when it does.
+</p>
+
+<p>
+<em>Updating</em>: The change is strictly backwards compatible to existing Go
+programs, but tools that analyze Go parse trees may need to be modified to accept
+this new form as the
+<code>Key</code> field of <a href="/pkg/go/ast/#RangeStmt"><code>RangeStmt</code></a>
+may now be <code>nil</code>.
+</p>
+
+<h3 id="methodonpointertopointer">Method calls on **T</h3>
+
+<p>
+Given these declarations,
+</p>
+
+<pre>
+type T int
+func (T) M() {}
+var x **T
+</pre>
+
+<p>
+both <code>gc</code> and <code>gccgo</code> accepted the method call
+</p>
+
+<pre>
+x.M()
+</pre>
+
+<p>
+which is a double dereference of the pointer-to-pointer <code>x</code>.
+The Go specification allows a single dereference to be inserted automatically,
+but not two, so this call is erroneous according to the language definition.
+It has therefore been disallowed in Go 1.4, which is a breaking change,
+although very few programs will be affected.
+</p>
+
+<p>
+<em>Updating</em>: Code that depends on the old, erroneous behavior will no longer
+compile but is easy to fix by adding an explicit dereference.
+</p>
+
+<h2 id="os">Changes to the supported operating systems and architectures</h2>
+
+<h3 id="android">Android</h3>
+
+<p>
+Go 1.4 can build binaries for ARM processors running the Android operating system.
+It can also build a <code>.so</code> library that can be loaded by an Android application
+using the supporting packages in the <a href="https://golang.org/x/mobile">mobile</a> subrepository.
+A brief description of the plans for this experimental port are available
+<a href="https://golang.org/s/go14android">here</a>.
+</p>
+
+<h3 id="naclarm">NaCl on ARM</h3>
+
+<p>
+The previous release introduced Native Client (NaCl) support for the 32-bit x86
+(<code>GOARCH=386</code>)
+and 64-bit x86 using 32-bit pointers (GOARCH=amd64p32).
+The 1.4 release adds NaCl support for ARM (GOARCH=arm).
+</p>
+
+<h3 id="plan9amd64">Plan9 on AMD64</h3>
+
+<p>
+This release adds support for the Plan 9 operating system on AMD64 processors,
+provided the kernel supports the <code>nsec</code> system call and uses 4K pages.
+</p>
+
+<h2 id="compatibility">Changes to the compatibility guidelines</h2>
+
+<p>
+The <a href="/pkg/unsafe/"><code>unsafe</code></a> package allows one
+to defeat Go's type system by exploiting internal details of the implementation
+or machine representation of data.
+It was never explicitly specified what use of <code>unsafe</code> meant
+with respect to compatibility as specified in the
+<a href="go1compat.html">Go compatibility guidelines</a>.
+The answer, of course, is that we can make no promise of compatibility
+for code that does unsafe things.
+</p>
+
+<p>
+We have clarified this situation in the documentation included in the release.
+The <a href="go1compat.html">Go compatibility guidelines</a> and the
+docs for the <a href="/pkg/unsafe/"><code>unsafe</code></a> package
+are now explicit that unsafe code is not guaranteed to remain compatible.
+</p>
+
+<p>
+<em>Updating</em>: Nothing technical has changed; this is just a clarification
+of the documentation.
+</p>
+
+
+<h2 id="impl">Changes to the implementations and tools</h2>
+
+<h3 id="runtime">Changes to the runtime</h3>
+
+<p>
+Prior to Go 1.4, the runtime (garbage collector, concurrency support, interface management,
+maps, slices, strings, ...) was mostly written in C, with some assembler support.
+In 1.4, much of the code has been translated to Go so that the garbage collector can scan
+the stacks of programs in the runtime and get accurate information about what variables
+are active.
+This change was large but should have no semantic effect on programs.
+</p>
+
+<p>
+This rewrite allows the garbage collector in 1.4 to be fully precise,
+meaning that it is aware of the location of all active pointers in the program.
+This means the heap will be smaller as there will be no false positives keeping non-pointers alive.
+Other related changes also reduce the heap size, which is smaller by 10%-30% overall
+relative to the previous release.
+</p>
+
+<p>
+A consequence is that stacks are no longer segmented, eliminating the "hot split" problem.
+When a stack limit is reached, a new, larger stack is allocated, all active frames for
+the goroutine are copied there, and any pointers into the stack are updated.
+Performance can be noticeably better in some cases and is always more predictable.
+Details are available in <a href="https://golang.org/s/contigstacks">the design document</a>.
+</p>
+
+<p>
+The use of contiguous stacks means that stacks can start smaller without triggering performance issues,
+so the default starting size for a goroutine's stack in 1.4 has been reduced from 8192 bytes to 2048 bytes.
+</p>
+
+<p>
+As preparation for the concurrent garbage collector scheduled for the 1.5 release,
+writes to pointer values in the heap are now done by a function call,
+called a write barrier, rather than directly from the function updating the value.
+In this next release, this will permit the garbage collector to mediate writes to the heap while it is running.
+This change has no semantic effect on programs in 1.4, but was
+included in the release to test the compiler and the resulting performance.
+</p>
+
+<p>
+The implementation of interface values has been modified.
+In earlier releases, the interface contained a word that was either a pointer or a one-word
+scalar value, depending on the type of the concrete object stored.
+This implementation was problematical for the garbage collector,
+so as of 1.4 interface values always hold a pointer.
+In running programs, most interface values were pointers anyway,
+so the effect is minimal, but programs that store integers (for example) in
+interfaces will see more allocations.
+</p>
+
+<p>
+As of Go 1.3, the runtime crashes if it finds a memory word that should contain
+a valid pointer but instead contains an obviously invalid pointer (for example, the value 3).
+Programs that store integers in pointer values may run afoul of this check and crash.
+In Go 1.4, setting the <a href="/pkg/runtime/"><code>GODEBUG</code></a> variable
+<code>invalidptr=0</code> disables
+the crash as a workaround, but we cannot guarantee that future releases will be
+able to avoid the crash; the correct fix is to rewrite code not to alias integers and pointers.
+</p>
+
+<h3 id="asm">Assembly</h3>
+
+<p>
+The language accepted by the assemblers <code>cmd/5a</code>, <code>cmd/6a</code>
+and <code>cmd/8a</code> has had several changes,
+mostly to make it easier to deliver type information to the runtime.
+</p>
+
+<p>
+First, the <code>textflag.h</code> file that defines flags for <code>TEXT</code> directives
+has been copied from the linker source directory to a standard location so it can be
+included with the simple directive
+</p>
+
+<pre>
+#include "textflag.h"
+</pre>
+
+<p>
+The more important changes are in how assembler source can define the necessary
+type information.
+For most programs it will suffice to move data
+definitions (<code>DATA</code> and <code>GLOBL</code> directives)
+out of assembly into Go files
+and to write a Go declaration for each assembly function.
+The <a href="/doc/asm#runtime">assembly document</a> describes what to do.
+</p>
+
+<p>
+<em>Updating</em>:
+Assembly files that include <code>textflag.h</code> from its old
+location will still work, but should be updated.
+For the type information, most assembly routines will need no change,
+but all should be examined.
+Assembly source files that define data,
+functions with non-empty stack frames, or functions that return pointers
+need particular attention.
+A description of the necessary (but simple) changes
+is in the <a href="/doc/asm#runtime">assembly document</a>.
+</p>
+
+<p>
+More information about these changes is in the <a href="/doc/asm">assembly document</a>.
+</p>
+
+<h3 id="gccgo">Status of gccgo</h3>
+
+<p>
+The release schedules for the GCC and Go projects do not coincide.
+GCC release 4.9 contains the Go 1.2 version of gccgo.
+The next release, GCC 5, will likely have the Go 1.4 version of gccgo.
+</p>
+
+<h3 id="internalpackages">Internal packages</h3>
+
+<p>
+Go's package system makes it easy to structure programs into components with clean boundaries,
+but there are only two forms of access: local (unexported) and global (exported).
+Sometimes one wishes to have components that are not exported,
+for instance to avoid acquiring clients of interfaces to code that is part of a public repository
+but not intended for use outside the program to which it belongs.
+</p>
+
+<p>
+The Go language does not have the power to enforce this distinction, but as of Go 1.4 the
+<a href="/cmd/go/"><code>go</code></a> command introduces
+a mechanism to define "internal" packages that may not be imported by packages outside
+the source subtree in which they reside.
+</p>
+
+<p>
+To create such a package, place it in a directory named <code>internal</code> or in a subdirectory of a directory
+named internal.
+When the <code>go</code> command sees an import of a package with <code>internal</code> in its path,
+it verifies that the package doing the import
+is within the tree rooted at the parent of the <code>internal</code> directory.
+For example, a package <code>.../a/b/c/internal/d/e/f</code>
+can be imported only by code in the directory tree rooted at <code>.../a/b/c</code>.
+It cannot be imported by code in <code>.../a/b/g</code> or in any other repository.
+</p>
+
+<p>
+For Go 1.4, the internal package mechanism is enforced for the main Go repository;
+from 1.5 and onward it will be enforced for any repository.
+</p>
+
+<p>
+Full details of the mechanism are in
+<a href="https://golang.org/s/go14internal">the design document</a>.
+</p>
+
+<h3 id="canonicalimports">Canonical import paths</h3>
+
+<p>
+Code often lives in repositories hosted by public services such as <code>github.com</code>,
+meaning that the import paths for packages begin with the name of the hosting service,
+<code>github.com/rsc/pdf</code> for example.
+One can use
+<a href="/cmd/go/#hdr-Remote_import_paths">an existing mechanism</a>
+to provide a "custom" or "vanity" import path such as
+<code>rsc.io/pdf</code>, but
+that creates two valid import paths for the package.
+That is a problem: one may inadvertently import the package through the two
+distinct paths in a single program, which is wasteful;
+miss an update to a package because the path being used is not recognized to be
+out of date;
+or break clients using the old path by moving the package to a different hosting service.
+</p>
+
+<p>
+Go 1.4 introduces an annotation for package clauses in Go source that identify a canonical
+import path for the package.
+If an import is attempted using a path that is not canonical,
+the <a href="/cmd/go/"><code>go</code></a> command
+will refuse to compile the importing package.
+</p>
+
+<p>
+The syntax is simple: put an identifying comment on the package line.
+For our example, the package clause would read:
+</p>
+
+<pre>
+package pdf // import "rsc.io/pdf"
+</pre>
+
+<p>
+With this in place,
+the <code>go</code> command will
+refuse to compile a package that imports <code>github.com/rsc/pdf</code>,
+ensuring that the code can be moved without breaking users.
+</p>
+
+<p>
+The check is at build time, not download time, so if <code>go</code> <code>get</code>
+fails because of this check, the mis-imported package has been copied to the local machine
+and should be removed manually.
+</p>
+
+<p>
+To complement this new feature, a check has been added at update time to verify
+that the local package's remote repository matches that of its custom import.
+The <code>go</code> <code>get</code> <code>-u</code> command will fail to
+update a package if its remote repository has changed since it was first
+downloaded.
+The new <code>-f</code> flag overrides this check.
+</p>
+
+<p>
+Further information is in
+<a href="https://golang.org/s/go14customimport">the design document</a>.
+</p>
+
+<h3 id="subrepo">Import paths for the subrepositories</h3>
+
+<p>
+The Go project subrepositories (<code>code.google.com/p/go.tools</code> and so on)
+are now available under custom import paths replacing <code>code.google.com/p/go.</code> with <code>golang.org/x/</code>,
+as in <code>golang.org/x/tools</code>.
+We will add canonical import comments to the code around June 1, 2015,
+at which point Go 1.4 and later will stop accepting the old <code>code.google.com</code> paths.
+</p>
+
+<p>
+<em>Updating</em>: All code that imports from subrepositories should change
+to use the new <code>golang.org</code> paths.
+Go 1.0 and later can resolve and import the new paths, so updating will not break
+compatibility with older releases.
+Code that has not updated will stop compiling with Go 1.4 around June 1, 2015.
+</p>
+
+<h3 id="gogenerate">The go generate subcommand</h3>
+
+<p>
+The <a href="/cmd/go/"><code>go</code></a> command has a new subcommand,
+<a href="/cmd/go/#hdr-Generate_Go_files_by_processing_source"><code>go generate</code></a>,
+to automate the running of tools to generate source code before compilation.
+For example, it can be used to run the <a href="/cmd/yacc"><code>yacc</code></a>
+compiler-compiler on a <code>.y</code> file to produce the Go source file implementing the grammar,
+or to automate the generation of <code>String</code> methods for typed constants using the new
+<a href="http://godoc.org/golang.org/x/tools/cmd/stringer">stringer</a>
+tool in the <code>golang.org/x/tools</code> subrepository.
+</p>
+
+<p>
+For more information, see the
+<a href="https://golang.org/s/go1.4-generate">design document</a>.
+</p>
+
+<h3 id="filenames">Change to file name handling</h3>
+
+<p>
+Build constraints, also known as build tags, control compilation by including or excluding files
+(see the documentation <a href="/pkg/go/build/"><code>/go/build</code></a>).
+Compilation can also be controlled by the name of the file itself by "tagging" the file with
+a suffix (before the <code>.go</code> or <code>.s</code> extension) with an underscore
+and the name of the architecture or operating system.
+For instance, the file <code>gopher_arm.go</code> will only be compiled if the target
+processor is an ARM.
+</p>
+
+<p>
+Before Go 1.4, a file called just <code>arm.go</code> was similarly tagged, but this behavior
+can break sources when new architectures are added, causing files to suddenly become tagged.
+In 1.4, therefore, a file will be tagged in this manner only if the tag (architecture or operating
+system name) is preceded by an underscore.
+</p>
+
+<p>
+<em>Updating</em>: Packages that depend on the old behavior will no longer compile correctly.
+Files with names like <code>windows.go</code> or <code>amd64.go</code> should either
+have explicit build tags added to the source or be renamed to something like
+<code>os_windows.go</code> or <code>support_amd64.go</code>.
+</p>
+
+<h3 id="gocmd">Other changes to the go command</h3>
+
+<p>
+There were a number of minor changes to the
+<a href="/cmd/go/"><code>cmd/go</code></a>
+command worth noting.
+</p>
+
+<ul>
+
+<li>
+Unless <a href="/cmd/cgo/"><code>cgo</code></a> is being used to build the package,
+the <code>go</code> command now refuses to compile C source files,
+since the relevant C compilers
+(<a href="/cmd/6c/"><code>6c</code></a> etc.)
+are intended to be removed from the installation in some future release.
+(They are used today only to build part of the runtime.)
+It is difficult to use them correctly in any case, so any extant uses are likely incorrect,
+so we have disabled them.
+</li>
+
+<li>
+The <a href="/cmd/go/#hdr-Test_packages"><code>go</code> <code>test</code></a>
+subcommand has a new flag, <code>-o</code>, to set the name of the resulting binary,
+corresponding to the same flag in other subcommands.
+The non-functional <code>-file</code> flag has been removed.
+</li>
+
+<li>
+The <a href="/cmd/go/#hdr-Test_packages"><code>go</code> <code>test</code></a>
+subcommand will compile and link all <code>*_test.go</code> files in the package,
+even when there are no <code>Test</code> functions in them.
+It previously ignored such files.
+</li>
+
+<li>
+The behavior of the
+<a href="/cmd/go/#hdr-Test_packages"><code>go</code> <code>build</code></a>
+subcommand's
+<code>-a</code> flag has been changed for non-development installations.
+For installations running a released distribution, the <code>-a</code> flag will no longer
+rebuild the standard library and commands, to avoid overwriting the installation's files.
+</li>
+
+</ul>
+
+<h3 id="pkg">Changes to package source layout</h3>
+
+<p>
+In the main Go source repository, the source code for the packages was kept in
+the directory <code>src/pkg</code>, which made sense but differed from
+other repositories, including the Go subrepositories.
+In Go 1.4, the<code> pkg</code> level of the source tree is now gone, so for example
+the <a href="/pkg/fmt/"><code>fmt</code></a> package's source, once kept in
+directory <code>src/pkg/fmt</code>, now lives one level higher in <code>src/fmt</code>.
+</p>
+
+<p>
+<em>Updating</em>: Tools like <code>godoc</code> that discover source code
+need to know about the new location. All tools and services maintained by the Go team
+have been updated.
+</p>
+
+
+<h3 id="swig">SWIG</h3>
+
+<p>
+Due to runtime changes in this release, Go 1.4 requires SWIG 3.0.3.
+</p>
+
+<h3 id="misc">Miscellany</h3>
+
+<p>
+The standard repository's top-level <code>misc</code> directory used to contain
+Go support for editors and IDEs: plugins, initialization scripts and so on.
+Maintaining these was becoming time-consuming
+and needed external help because many of the editors listed were not used by
+members of the core team.
+It also required us to make decisions about which plugin was best for a given
+editor, even for editors we do not use.
+</p>
+
+<p>
+The Go community at large is much better suited to managing this information.
+In Go 1.4, therefore, this support has been removed from the repository.
+Instead, there is a curated, informative list of what's available on
+a <a href="//golang.org/wiki/IDEsAndTextEditorPlugins">wiki page</a>.
+</p>
+
+<h2 id="performance">Performance</h2>
+
+<p>
+Most programs will run about the same speed or slightly faster in 1.4 than in 1.3;
+some will be slightly slower.
+There are many changes, making it hard to be precise about what to expect.
+</p>
+
+<p>
+As mentioned above, much of the runtime was translated to Go from C,
+which led to some reduction in heap sizes.
+It also improved performance slightly because the Go compiler is better
+at optimization, due to things like inlining, than the C compiler used to build
+the runtime.
+</p>
+
+<p>
+The garbage collector was sped up, leading to measurable improvements for
+garbage-heavy programs.
+On the other hand, the new write barriers slow things down again, typically
+by about the same amount but, depending on their behavior, some programs
+may be somewhat slower or faster.
+</p>
+
+<p>
+Library changes that affect performance are documented below.
+</p>
+
+<h2 id="library">Changes to the standard library</h2>
+
+<h3 id="new_packages">New packages</h3>
+
+<p>
+There are no new packages in this release.
+</p>
+
+<h3 id="major_library_changes">Major changes to the library</h3>
+
+<h4 id="scanner">bufio.Scanner</h4>
+
+<p>
+The <a href="/pkg/bufio/#Scanner"><code>Scanner</code></a> type in the
+<a href="/pkg/bufio/"><code>bufio</code></a> package
+has had a bug fixed that may require changes to custom
+<a href="/pkg/bufio/#SplitFunc"><code>split functions</code></a>.
+The bug made it impossible to generate an empty token at EOF; the fix
+changes the end conditions seen by the split function.
+Previously, scanning stopped at EOF if there was no more data.
+As of 1.4, the split function will be called once at EOF after input is exhausted,
+so the split function can generate a final empty token
+as the documentation already promised.
+</p>
+
+<p>
+<em>Updating</em>: Custom split functions may need to be modified to
+handle empty tokens at EOF as desired.
+</p>
+
+<h4 id="syscall">syscall</h4>
+
+<p>
+The <a href="/pkg/syscall/"><code>syscall</code></a> package is now frozen except
+for changes needed to maintain the core repository.
+In particular, it will no longer be extended to support new or different system calls
+that are not used by the core.
+The reasons are described at length in <a href="https://golang.org/s/go1.4-syscall">a
+separate document</a>.
+</p>
+
+<p>
+A new subrepository, <a href="https://golang.org/x/sys">golang.org/x/sys</a>,
+has been created to serve as the location for new developments to support system
+calls on all kernels.
+It has a nicer structure, with three packages that each hold the implementation of
+system calls for one of
+<a href="http://godoc.org/golang.org/x/sys/unix">Unix</a>,
+<a href="http://godoc.org/golang.org/x/sys/windows">Windows</a> and
+<a href="http://godoc.org/golang.org/x/sys/plan9">Plan 9</a>.
+These packages will be curated more generously, accepting all reasonable changes
+that reflect kernel interfaces in those operating systems.
+See the documentation and the article mentioned above for more information.
+</p>
+
+<p>
+<em>Updating</em>: Existing programs are not affected as the <code>syscall</code>
+package is largely unchanged from the 1.3 release.
+Future development that requires system calls not in the <code>syscall</code> package
+should build on <code>golang.org/x/sys</code> instead.
+</p>
+
+<h3 id="minor_library_changes">Minor changes to the library</h3>
+
+<p>
+The following list summarizes a number of minor changes to the library, mostly additions.
+See the relevant package documentation for more information about each change.
+</p>
+
+<ul>
+
+<li>
+The <a href="/pkg/archive/zip/"><code>archive/zip</code></a> package's
+<a href="/pkg/archive/zip/#Writer"><code>Writer</code></a> now supports a
+<a href="/pkg/archive/zip/#Writer.Flush"><code>Flush</code></a> method.
+</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 support a <code>Reset</code> method
+for the decompressors, allowing them to reuse buffers and improve performance.
+The <a href="/pkg/compress/gzip/"><code>compress/gzip</code></a> package also has a
+<a href="/pkg/compress/gzip/#Reader.Multistream"><code>Multistream</code></a> method to control support
+for multistream files.
+</li>
+
+<li>
+The <a href="/pkg/crypto/"><code>crypto</code></a> package now has a
+<a href="/pkg/crypto/#Signer"><code>Signer</code></a> interface, implemented by the
+<code>PrivateKey</code> types in
+<a href="/pkg/crypto/ecdsa"><code>crypto/ecdsa</code></a> and
+<a href="/pkg/crypto/rsa"><code>crypto/rsa</code></a>.
+</li>
+
+<li>
+The <a href="/pkg/crypto/tls/"><code>crypto/tls</code></a> package
+now supports ALPN as defined in <a href="http://tools.ietf.org/html/rfc7301">RFC 7301</a>.
+</li>
+
+<li>
+The <a href="/pkg/crypto/tls/"><code>crypto/tls</code></a> package
+now supports programmatic selection of server certificates
+through the new <a href="/pkg/crypto/tls/#Config.CertificateForName"><code>CertificateForName</code></a> function
+of the <a href="/pkg/crypo/tls/#Config"><code>Config</code></a> struct.
+</li>
+
+<li>
+Also in the crypto/tls package, the server now supports
+<a href="https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00">TLS_FALLBACK_SCSV</a>
+to help clients detect fallback attacks.
+(The Go client does not support fallback at all, so it is not vulnerable to
+those attacks.)
+</li>
+
+<li>
+The <a href="/pkg/database/sql/"><code>database/sql</code></a> package can now list all registered
+<a href="/pkg/database/sql/#Drivers"><code>Drivers</code></a>.
+</li>
+
+<li>
+The <a href="/pkg/debug/dwarf/"><code>debug/dwarf</code></a> package now supports
+<a href="/pkg/debug/dwarf/#UnspecifiedType"><code>UnspecifiedType</code></a>s.
+</li>
+
+<li>
+In the <a href="/pkg/encoding/asn1/"><code>encoding/asn1</code></a> package,
+optional elements with a default value will now only be omitted if they have that value.
+</li>
+
+<li>
+The <a href="/pkg/encoding/csv/"><code>encoding/csv</code></a> package no longer
+quotes empty strings but does quote the end-of-data marker <code>\.</code> (backslash dot).
+This is permitted by the definition of CSV and allows it to work better with Postgres.
+</li>
+
+<li>
+The <a href="/pkg/encoding/gob/"><code>encoding/gob</code></a> package has been rewritten to eliminate
+the use of unsafe operations, allowing it to be used in environments that do not permit use of the
+<a href="/pkg/unsafe/"><code>unsafe</code></a> package.
+For typical uses it will be 10-30% slower, but the delta is dependent on the type of the data and
+in some cases, especially involving arrays, it can be faster.
+There is no functional change.
+</li>
+
+<li>
+The <a href="/pkg/encoding/xml/"><code>encoding/xml</code></a> package's
+<a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> can now report its input offset.
+</li>
+
+<li>
+In the <a href="/pkg/fmt/"><code>fmt</code></a> package,
+formatting of pointers to maps has changed to be consistent with that of pointers
+to structs, arrays, and so on.
+For instance, <code>&amp;map[string]int{"one":</code> <code>1}</code> now prints by default as
+<code>&amp;map[one:</code> <code>1]</code> rather than as a hexadecimal pointer value.
+</li>
+
+<li>
+The <a href="/pkg/image/"><code>image</code></a> package's
+<a href="/pkg/image/#Image"><code>Image</code></a>
+implementations like
+<a href="/pkg/image/#RGBA"><code>RGBA</code></a> and
+<a href="/pkg/image/#Gray"><code>Gray</code></a> have specialized
+<a href="/pkg/image/#RGBA.RGBAAt"><code>RGBAAt</code></a> and
+<a href="/pkg/image/#Gray.GrayAt"><code>GrayAt</code></a> methods alongside the general
+<a href="/pkg/image/#Image.At"><code>At</code></a> method.
+</li>
+
+<li>
+The <a href="/pkg/image/png/"><code>image/png</code></a> package now has an
+<a href="/pkg/image/png/#Encoder"><code>Encoder</code></a>
+type to control the compression level used for encoding.
+</li>
+
+<li>
+The <a href="/pkg/math/"><code>math</code></a> package now has a
+<a href="/pkg/math/#Nextafter32"><code>Nextafter32</code><a/> function.
+</li>
+
+<li>
+The <a href="/pkg/net/http/"><code>net/http</code></a> package's
+<a href="/pkg/net/http/#Request"><code>Request</code></a> type
+has a new <a href="/pkg/net/http/#Request.BasicAuth"><code>BasicAuth</code></a> method
+that returns the username and password from authenticated requests using the
+HTTP Basic Authentication
+Scheme.
+</li>
+
+<li>The <a href="/pkg/net/http/"><code>net/http</code></a> package's
+<a href="/pkg/net/http/#Request"><code>Transport</code></a> type
+has a new <a href="/pkg/net/http/#Transport.DialTLS"><code>DialTLS</code></a> hook
+that allows customizing the behavior of outbound TLS connections.
+</li>
+
+<li>
+The <a href="/pkg/net/http/httputil/"><code>net/http/httputil</code></a> package's
+<a href="/pkg/net/http/httputil/#ReverseProxy"><code>ReverseProxy</code></a> type
+has a new field,
+<a href="/pkg/net/http/#ReverseProxy.ErrorLog"><code>ErrorLog</code></a>, that
+provides user control of logging.
+</li>
+
+<li>
+The <a href="/pkg/os/"><code>os</code></a> package
+now implements symbolic links on the Windows operating system
+through the <a href="/pkg/os/#Symlink"><code>Symlink</code></a> function.
+Other operating systems already have this functionality.
+There is also a new <a href="/pkg/os/#Unsetenv"><code>Unsetenv</code></a> function.
+</li>
+
+<li>
+The <a href="/pkg/reflect/"><code>reflect</code></a> package's
+<a href="/pkg/reflect/#Type"><code>Type</code></a> interface
+has a new method, <a href="/pkg/reflect/#type.Comparable"><code>Comparable</code></a>,
+that reports whether the type implements general comparisons.
+</li>
+
+<li>
+Also in the <a href="/pkg/reflect/"><code>reflect</code></a> package, the
+<a href="/pkg/reflect/#Value"><code>Value</code></a> interface is now three instead of four words
+because of changes to the implementation of interfaces in the runtime.
+This saves memory but has no semantic effect.
+</li>
+
+<li>
+The <a href="/pkg/runtime/"><code>runtime</code></a> package
+now implements monotonic clocks on Windows,
+as it already did for the other systems.
+</li>
+
+<li>
+The <a href="/pkg/runtime/"><code>runtime</code></a> package's
+<a href="/pkg/runtime/#MemStats.Mallocs"><code>Mallocs</code></a> counter
+now counts very small allocations that were missed in Go 1.3.
+This may break tests using <a href="/pkg/runtime/#ReadMemStats"><code>ReadMemStats</code></a>
+or <a href="/pkg/testing/#AllocsPerRun"><code>AllocsPerRun</code></a>
+due to the more accurate answer.
+</li>
+
+<li>
+In the <a href="/pkg/runtime/"><code>runtime</code></a> package,
+an array <a href="/pkg/runtime/#MemStats.PauseEnd"><code>PauseEnd</code></a>
+has been added to the
+<a href="/pkg/runtime/#MemStats"><code>MemStats</code></a>
+and <a href="/pkg/runtime/#GCStats"><code>GCStats</code></a> structs.
+This array is a circular buffer of times when garbage collection pauses ended.
+The corresponding pause durations are already recorded in
+<a href="/pkg/runtime/#MemStats.PauseNs"><code>PauseNs</code></a>
+</li>
+
+<li>
+The <a href="/pkg/runtime/race/"><code>runtime/race</code></a> package
+now supports FreeBSD, which means the
+<a href="/pkg/cmd/go/"><code>go</code></a> command's <code>-race</code>
+flag now works on FreeBSD.
+</li>
+
+<li>
+The <a href="/pkg/sync/atomic/"><code>sync/atomic</code></a> package
+has a new type, <a href="/pkg/sync/atomic/#Value"><code>Value</code></a>.
+<code>Value</code> provides an efficient mechanism for atomic loads and
+stores of values of arbitrary type.
+</li>
+
+<li>
+In the <a href="/pkg/syscall/"><code>syscall</code></a> package's
+implementation on Linux, the
+<a href="/pkg/syscall/#Setuid"><code>Setuid</code></a>
+and <a href="/pkg/syscall/#Setgid"><code>Setgid</code></a> have been disabled
+because those system calls operate on the calling thread, not the whole process, which is
+different from other platforms and not the expected result.
+</li>
+
+<li>
+The <a href="/pkg/testing/"><code>testing</code></a> package
+has a new facility to provide more control over running a set of tests.
+If the test code contains a function
+<pre>
+func TestMain(m *<a href="/pkg/testing/#M"><code>testing.M</code></a>)
+</pre>
+
+that function will be called instead of running the tests directly.
+The <code>M</code> struct contains methods to access and run the tests.
+</li>
+
+<li>
+Also in the <a href="/pkg/testing/"><code>testing</code></a> package,
+a new <a href="/pkg/testing/#Coverage"><code>Coverage</code></a>
+function reports the current test coverage fraction,
+enabling individual tests to report how much they are contributing to the
+overall coverage.
+</li>
+
+<li>
+The <a href="/pkg/text/scanner/"><code>text/scanner</code></a> package's
+<a href="/pkg/text/scanner/#Scanner"><code>Scanner</code></a> type
+has a new function,
+<a href="/pkg/text/scanner/#Scanner.IsIdentRune"><code>IsIdentRune</code></a>,
+allowing one to control the definition of an identifier when scanning.
+</li>
+
+<li>
+The <a href="/pkg/text/template/"><code>text/template</code></a> package's boolean
+functions <code>eq</code>, <code>lt</code>, and so on have been generalized to allow comparison
+of signed and unsigned integers, simplifying their use in practice.
+(Previously one could only compare values of the same signedness.)
+All negative values compare less than all unsigned values.
+</li>
+
+<li>
+The <code>time</code> package now uses the standard symbol for the micro prefix,
+the micro symbol (U+00B5 'µ'), to print microsecond durations.
+<a href="/pkg/time/#ParseDuration"><code>ParseDuration</code></a> still accepts <code>us</code>
+but the package no longer prints microseconds as <code>us</code>.
+<br>
+<em>Updating</em>: Code that depends on the output format of durations
+but does not use ParseDuration will need to be updated.
+</li>
+
+</ul>
diff --git a/doc/go1.html b/doc/go1.html
index 5cf5df929..1665d74e9 100644
--- a/doc/go1.html
+++ b/doc/go1.html
@@ -2035,4 +2035,4 @@ They are available for many combinations of architecture and operating system
Installation details are described on the
<a href="/doc/install">Getting Started</a> page, while
the distributions themselves are listed on the
-<a href="/dl/">downloads page</a>.
+<a href="https://golang.org/dl/">downloads page</a>.
diff --git a/doc/go1compat.html b/doc/go1compat.html
index d10b9af29..d800dec0c 100644
--- a/doc/go1compat.html
+++ b/doc/go1compat.html
@@ -83,16 +83,16 @@ break if the bug is fixed. We reserve the right to fix such bugs.
<li>
Struct literals. For the addition of features in later point
releases, it may be necessary to add fields to exported structs in
-the API. Code that uses untagged struct literals (such as pkg.T{3,
+the API. Code that uses unkeyed struct literals (such as pkg.T{3,
"x"}) to create values of these types would fail to compile after
-such a change. However, code that uses tagged literals (pkg.T{A:
+such a change. However, code that uses keyed literals (pkg.T{A:
3, B: "x"}) will continue to compile after such a change. We will
-update such data structures in a way that allows tagged struct
-literals to remain compatible, although untagged literals may fail
+update such data structures in a way that allows keyed struct
+literals to remain compatible, although unkeyed literals may fail
to compile. (There are also more intricate cases involving nested
data structures or interfaces, but they have the same resolution.)
We therefore recommend that composite literals whose type is defined
-in a separate package should use the tagged notation.
+in a separate package should use the keyed notation.
</li>
<li>
@@ -104,6 +104,14 @@ outside of tests, and using it may cause a program to fail
to compile in future releases.
</li>
+<li>
+Use of package <code>unsafe</code>. Packages that import
+<a href="/pkg/unsafe/"><code>unsafe</code></a>
+may depend on internal properties of the Go implementation.
+We reserve the right to make changes to the implementation
+that may break such programs.
+</li>
+
</ul>
<p>
@@ -145,13 +153,28 @@ developed software based on Go 1.
<p>
Code in sub-repositories of the main go tree, such as
-<a href="//code.google.com/p/go.net">code.google.com/p/go.net</a>,
+<a href="//golang.org/x/net">golang.org/x/net</a>,
may be developed under
looser compatibility requirements. However, the sub-repositories
will be tagged as appropriate to identify versions that are compatible
with the Go 1 point releases.
</p>
+<h2 id="operating_systems">Operating systems</h2>
+
+<p>
+It is impossible to guarantee long-term compatibility with operating
+system interfaces, which are changed by outside parties.
+The <a href="/pkg/syscall/"><code>syscall</code></a> package
+is therefore outside the purview of the guarantees made here.
+As of Go version 1.4, the <code>syscall</code> package is frozen.
+Any evolution of the system call interface must be supported elsewhere,
+such as in the
+<a href="//golang.org/x/sys">go.sys</a> subrepository.
+For details and background, see
+<a href="//golang.org/s/go1.4-syscall">this document</a>.
+</p>
+
<h2 id="tools">Tools</h2>
<p>
diff --git a/doc/go_faq.html b/doc/go_faq.html
index f2082ef5b..6b77f1c1e 100644
--- a/doc/go_faq.html
+++ b/doc/go_faq.html
@@ -228,7 +228,7 @@ document server running in a production configuration on
</p>
<p>
-Other examples include the <a href="https://code.google.com/p/vitess/">Vitess</a>
+Other examples include the <a href="//code.google.com/p/vitess/">Vitess</a>
system for large-scale SQL installations and Google's download server, <code>dl.google.com</code>,
which delivers Chrome binaries and other large installables such as <code>apt-get</code>
packages.
@@ -889,6 +889,11 @@ type is generic; if you care about how many bits an integer holds, Go
encourages you to be explicit.
</p>
+<p>
+A blog post, title <a href="http://blog.golang.org/constants">Constants</a>,
+explores this topic in more detail.
+</p>
+
<h3 id="builtin_maps">
Why are maps built in?</h3>
<p>
@@ -971,7 +976,7 @@ It is a handy reference for people doing code reviews for Go projects.
How do I submit patches to the Go libraries?</h3>
<p>
-The library sources are in <code>go/src/pkg</code>.
+The library sources are in the <code>src</code> directory of the repository.
If you want to make a significant change, please discuss on the mailing list before embarking.
</p>
@@ -981,32 +986,6 @@ See the document
for more information about how to proceed.
</p>
-<h3 id="Why_does_the_project_use_Mercurial_and_not_git">
-Why does the project use Mercurial and not git?</h3>
-
-<p>
-The Go project, hosted by Google Code at
-<a href="//code.google.com/p/go">code.google.com/p/go</a>,
-uses Mercurial as its version control system.
-When the project launched,
-Google Code supported only Subversion and Mercurial.
-Mercurial was a better choice because of its plugin mechanism
-that allowed us to create the "codereview" plugin to connect
-the project to the excellent code review tools at
-<a href="//codereview.appspot.com">codereview.appspot.com</a>.
-</p>
-
-<p>
-Programmers who work
-with the Go project's source rather than release downloads sometimes
-ask for the project to switch to git.
-That would be possible, but it would be a lot of work and
-would also require reimplementing the codereview plugin.
-Given that Mercurial works today, with code review support,
-combined with the Go project's mostly linear, non-branching use of
-version control, a switch to git doesn't seem worthwhile.
-</p>
-
<h3 id="git_https">
Why does "go get" use HTTPS when cloning a repository?</h3>
@@ -1110,7 +1089,7 @@ error but the situation can still be confusing, because sometimes a
<a href="#different_method_sets">pointer
is necessary to satisfy an interface</a>.
The insight is that although a pointer to a concrete type can satisfy
-an interface, with one exception <em>a pointer to an interface can never satisfy a interface</em>.
+an interface, with one exception <em>a pointer to an interface can never satisfy an interface</em>.
</p>
<p>
@@ -1351,7 +1330,7 @@ to speed it up.
</p>
<p>
-Go's goroutine scheduler is not as good as it needs to be. In future, it
+Go's goroutine scheduler is not as good as it needs to be. In the future, it
should recognize such cases and optimize its use of OS threads. For now,
<code>GOMAXPROCS</code> should be set on a per-application basis.
</p>
@@ -1571,7 +1550,7 @@ table-driven, iterating over a list of inputs and outputs defined
in a data structure (Go has excellent support for data structure literals).
The work to write a good test and good error messages will then be amortized over many
test cases. The standard Go library is full of illustrative examples, such as in
-<a href="/src/pkg/fmt/fmt_test.go">the formatting tests for the <code>fmt</code> package</a>.
+<a href="/src/fmt/fmt_test.go">the formatting tests for the <code>fmt</code> package</a>.
</p>
@@ -1590,30 +1569,40 @@ and uses a variant of the Plan 9 loader to generate ELF/Mach-O/PE binaries.
</p>
<p>
-We considered writing <code>gc</code>, the original Go compiler, in Go itself but
+We considered using LLVM for <code>gc</code> but we felt it was too large and
+slow to meet our performance goals.
+</p>
+
+<p>
+We also considered writing <code>gc</code>, the original Go compiler, in Go itself but
elected not to do so because of the difficulties of bootstrapping and
especially of open source distribution&mdash;you'd need a Go compiler to
set up a Go environment. <code>Gccgo</code>, which came later, makes it possible to
-consider writing a compiler in Go, which might well happen.
-(Go would be a
-fine language in which to implement a compiler; a native lexer and
-parser are already available in the <a href="/pkg/go/"><code>go</code></a> package
-and a type checker is in the works.)
+consider writing a compiler in Go.
+A plan to do that by machine translation of the existing compiler is under development.
+<a href="http://golang.org/s/go13compiler">A separate document</a>
+explains the reason for this approach.
</p>
<p>
-We also considered using LLVM for <code>gc</code> but we felt it was too large and
-slow to meet our performance goals.
+That plan aside,
+Go is a
+fine language in which to implement a self-hosting compiler: a native lexer and
+parser are already available in the <a href="/pkg/go/"><code>go</code></a> package
+and a separate type checking
+<a href="http://godoc.org/golang.org/x/tools/go/types">package</a>
+has also been written.
</p>
<h3 id="How_is_the_run_time_support_implemented">
How is the run-time support implemented?</h3>
<p>
-Again due to bootstrapping issues, the run-time code is mostly in C (with a
-tiny bit of assembler) although Go is capable of implementing most of
-it now. <code>Gccgo</code>'s run-time support uses <code>glibc</code>.
-<code>Gc</code> uses a custom library to keep the footprint under
+Again due to bootstrapping issues, the run-time code was originally written mostly in C (with a
+tiny bit of assembler) although much of it has been translated to Go since then
+and one day all of it might be (except for the assembler bits).
+<code>Gccgo</code>'s run-time support uses <code>glibc</code>.
+<code>Gc</code> uses a custom C library to keep the footprint under
control; it is
compiled with a version of the Plan 9 C compiler that supports
resizable stacks for goroutines.
@@ -1637,8 +1626,8 @@ A simple C "hello, world" program compiled and linked statically using gcc
on Linux is around 750 kB,
including an implementation of <code>printf</code>.
An equivalent Go program using <code>fmt.Printf</code>
-is around 1.2 MB, but
-that includes more powerful run-time support.
+is around 1.9 MB, but
+that includes more powerful run-time support and type information.
</p>
<h3 id="unused_variables_and_imports">
@@ -1646,14 +1635,17 @@ Can I stop these complaints about my unused variable/import?</h3>
<p>
The presence of an unused variable may indicate a bug, while
-unused imports just slow down compilation.
-Accumulate enough unused imports in your code tree and
-things can get very slow.
-For these reasons, Go allows neither.
+unused imports just slow down compilation,
+an effect that can become substantial as a program accumulates
+code and programmers over time.
+For these reasons, Go refuses to compile programs with unused
+variables or imports,
+trading short-term convenience for long-term build speed and
+program clarity.
</p>
<p>
-When developing code, it's common to create these situations
+Still, when developing code, it's common to create these situations
temporarily and it can be annoying to have to edit them out before the
program will compile.
</p>
@@ -1695,6 +1687,14 @@ func main() {
}
</pre>
+<p>
+Nowadays, most Go programmers use a tool,
+<a href="http://godoc.org/golang.org/x/tools/cmd/goimports">goimports</a>,
+which automatically rewrites a Go source file to have the correct imports,
+eliminating the unused imports issue in practice.
+This program is easily connected to most editors to run automatically when a Go source file is written.
+</p>
+
<h2 id="Performance">Performance</h2>
<h3 id="Why_does_Go_perform_badly_on_benchmark_x">
diff --git a/doc/go_mem.html b/doc/go_mem.html
index 2ea1ded7a..5dd48ff7f 100644
--- a/doc/go_mem.html
+++ b/doc/go_mem.html
@@ -21,6 +21,29 @@ reads of a variable in one goroutine can be guaranteed to
observe values produced by writes to the same variable in a different goroutine.
</p>
+
+<h2>Advice</h2>
+
+<p>
+Programs that modify data being simultaneously accessed by multiple goroutines
+must serialize such access.
+</p>
+
+<p>
+To serialize access, protect the data with channel operations or other synchronization primitives
+such as those in the <a href="/pkg/sync/"><code>sync</code></a>
+and <a href="/pkg/sync/atomic/"><code>sync/atomic</code></a> packages.
+</p>
+
+<p>
+If you must read the rest of this document to understand the behavior of your program,
+you are being too clever.
+</p>
+
+<p>
+Don't be clever.
+</p>
+
<h2>Happens Before</h2>
<p>
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 660c8535e..ca0deb56a 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
- "Subtitle": "Version of May 28, 2014",
+ "Subtitle": "Version of November 11, 2014",
"Path": "/ref/spec"
}-->
@@ -479,7 +479,7 @@ Interpreted string literals are character sequences between double
quotes <code>&quot;&quot;</code>. The text between the quotes,
which may not contain newlines, forms the
value of the literal, with backslash escapes interpreted as they
-are in rune literals (except that <code>\'</code> is illegal and
+are in <a href="#Rune_literals">rune literals</a> (except that <code>\'</code> is illegal and
<code>\"</code> is legal), with the same restrictions.
The three-digit octal (<code>\</code><i>nnn</i>)
and two-digit hexadecimal (<code>\x</code><i>nn</i>) escapes represent individual
@@ -577,7 +577,7 @@ Numeric constants represent values of arbitrary precision and do not overflow.
</p>
<p>
-Constants may be <a href="#Types">typed</a> or untyped.
+Constants may be <a href="#Types">typed</a> or <i>untyped</i>.
Literal constants, <code>true</code>, <code>false</code>, <code>iota</code>,
and certain <a href="#Constant_expressions">constant expressions</a>
containing only untyped constant operands are untyped.
@@ -598,6 +598,17 @@ not <code>int32</code> or <code>string</code>.
</p>
<p>
+An untyped constant has a <i>default type</i> which is the type to which the
+constant is implicitly converted in contexts where a typed value is required,
+for instance, in a <a href="#Short_variable_declarations">short variable declaration</a>
+such as <code>i := 0</code> where there is no explicit type.
+The default type of an untyped constant is <code>bool</code>, <code>rune</code>,
+<code>int</code>, <code>float64</code>, <code>complex128</code> or <code>string</code>
+respectively, depending on whether it is a boolean, rune, integer, floating-point,
+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>,
@@ -636,6 +647,65 @@ of evaluating <a href="#Constant_expressions">constant
expressions</a>.
</p>
+<h2 id="Variables">Variables</h2>
+
+<p>
+A variable is a storage location for holding a <i>value</i>.
+The set of permissible values is determined by the
+variable's <i><a href="#Types">type</a></i>.
+</p>
+
+<p>
+A <a href="#Variable_declarations">variable declaration</a>
+or, for function parameters and results, the signature
+of a <a href="#Function_declarations">function declaration</a>
+or <a href="#Function_literals">function literal</a> reserves
+storage for a named variable.
+
+Calling the built-in function <a href="#Allocation"><code>new</code></a>
+or taking the address of a <a href="#Composite_literals">composite literal</a>
+allocates storage for a variable at run time.
+Such an anonymous variable is referred to via a (possibly implicit)
+<a href="#Address_operators">pointer indirection</a>.
+</p>
+
+<p>
+<i>Structured</i> variables of <a href="#Array_types">array</a>, <a href="#Slice_types">slice</a>,
+and <a href="#Struct_types">struct</a> types have elements and fields that may
+be <a href="#Address_operators">addressed</a> individually. Each such element
+acts like a variable.
+</p>
+
+<p>
+The <i>static type</i> (or just <i>type</i>) of a variable is the
+type given in its declaration, the type provided in the
+<code>new</code> call or composite literal, or the type of
+an element of a structured variable.
+Variables of interface type also have a distinct <i>dynamic type</i>,
+which is the concrete type of the value assigned to the variable at run time
+(unless the value is the predeclared identifier <code>nil</code>,
+which has no type).
+The dynamic type may vary during execution but values stored in interface
+variables are always <a href="#Assignability">assignable</a>
+to the static type of the variable.
+</p>
+
+<pre>
+var x interface{} // x is nil and has static type interface{}
+var v *T // v has value nil, static type *T
+x = 42 // x has value 42 and dynamic type int
+x = v // x has value (*T)(nil) and dynamic type *T
+</pre>
+
+<p>
+A variable's value is retrieved by referring to the variable in an
+<a href="#Expressions">expression</a>; it is the most recent value
+<a href="#Assignments">assigned</a> to the variable.
+If a variable has not yet been assigned a value, its value is the
+<a href="#The_zero_value">zero value</a> for its type.
+</p>
+
+
<h2 id="Types">Types</h2>
<p>
@@ -662,17 +732,6 @@ type literals.
</p>
<p>
-The <i>static type</i> (or just <i>type</i>) of a variable is the
-type defined by its declaration. Variables of interface type
-also have a distinct <i>dynamic type</i>, which
-is the actual type of the value stored in the variable at run time.
-The dynamic type may vary during execution but is always
-<a href="#Assignability">assignable</a>
-to the static type of the interface variable. For non-interface
-types, the dynamic type is always the static type.
-</p>
-
-<p>
Each type <code>T</code> has an <i>underlying type</i>: If <code>T</code>
is one of the predeclared boolean, numeric, or string types, or a type literal,
the corresponding underlying
@@ -1027,14 +1086,14 @@ struct {
<h3 id="Pointer_types">Pointer types</h3>
<p>
-A pointer type denotes the set of all pointers to variables of a given
+A pointer type denotes the set of all pointers to <a href="#Variables">variables</a> of a given
type, called the <i>base type</i> of the pointer.
The value of an uninitialized pointer is <code>nil</code>.
</p>
<pre class="ebnf">
PointerType = "*" BaseType .
-BaseType = Type .
+BaseType = Type .
</pre>
<pre>
@@ -1154,11 +1213,11 @@ interface{}
<p>
Similarly, consider this interface specification,
which appears within a <a href="#Type_declarations">type declaration</a>
-to define an interface called <code>Lock</code>:
+to define an interface called <code>Locker</code>:
</p>
<pre>
-type Lock interface {
+type Locker interface {
Lock()
Unlock()
}
@@ -1174,28 +1233,35 @@ func (p T) Unlock() { … }
</pre>
<p>
-they implement the <code>Lock</code> interface as well
+they implement the <code>Locker</code> interface as well
as the <code>File</code> interface.
</p>
+
<p>
-An interface may use an interface type name <code>T</code>
-in place of a method specification.
-The effect, called embedding an interface,
-is equivalent to enumerating the methods of <code>T</code> explicitly
-in the interface.
+An interface <code>T</code> may use a (possibly qualified) interface type
+name <code>E</code> in place of a method specification. This is called
+<i>embedding</i> interface <code>E</code> in <code>T</code>; it adds
+all (exported and non-exported) methods of <code>E</code> to the interface
+<code>T</code>.
</p>
<pre>
-type ReadWrite interface {
+type ReadWriter interface {
Read(b Buffer) bool
Write(b Buffer) bool
}
type File interface {
- ReadWrite // same as enumerating the methods in ReadWrite
- Lock // same as enumerating the methods in Lock
+ ReadWriter // same as adding the methods of ReadWriter
+ Locker // same as adding the methods of Locker
Close()
}
+
+type LockedFile interface {
+ Locker
+ File // illegal: Lock, Unlock not unique
+ Lock() // illegal: Lock not unique
+}
</pre>
<p>
@@ -1443,7 +1509,7 @@ is different from <code>[]string</code>.
<h3 id="Assignability">Assignability</h3>
<p>
-A value <code>x</code> is <i>assignable</i> to a variable of type <code>T</code>
+A value <code>x</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
("<code>x</code> is assignable to <code>T</code>") in any of these cases:
</p>
@@ -1875,9 +1941,10 @@ func (tz TimeZone) String() string {
<h3 id="Variable_declarations">Variable declarations</h3>
<p>
-A variable declaration creates a variable, binds an identifier to it and
-gives it a type and optionally an initial value.
+A variable declaration creates one or more variables, binds corresponding
+identifiers to them, and gives each a type and an initial value.
</p>
+
<pre class="ebnf">
VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
@@ -1898,22 +1965,27 @@ var _, found = entries[name] // map lookup; only interested in "found"
<p>
If a list of expressions is given, the variables are initialized
-by <a href="#Assignments">assigning</a> the expressions to the variables
-in order; all expressions must be consumed and all variables initialized from them.
+with the expressions following the rules for <a href="#Assignments">assignments</a>.
Otherwise, each variable is initialized to its <a href="#The_zero_value">zero value</a>.
</p>
<p>
-If the type is present, each variable is given that type.
-Otherwise, the types are deduced from the assignment
-of the expression list.
+If a type is present, each variable is given that type.
+Otherwise, each variable is given the type of the corresponding
+initialization value in the assignment.
+If that value is an untyped constant, it is first
+<a href="#Conversions">converted</a> to its <a href="#Constants">default type</a>;
+if it is an untyped boolean value, it is first converted to type <code>bool</code>.
+The predeclared value <code>nil</code> cannot be used to initialize a variable
+with no explicit type.
</p>
-<p>
-If the type is absent and the corresponding expression evaluates to an
-untyped <a href="#Constants">constant</a>, the type of the declared variable
-is as described in §<a href="#Assignments">Assignments</a>.
-</p>
+<pre>
+var d = math.Sin(0.5) // d is int64
+var i = 42 // i is int
+var t, ok = x.(T) // t is T, ok is bool
+var n = nil // illegal
+</pre>
<p>
Implementation restriction: A compiler may make it illegal to declare a variable
@@ -2029,13 +2101,14 @@ and associates the method with the receiver's <i>base type</i>.
<pre class="ebnf">
MethodDecl = "func" Receiver MethodName ( Function | Signature ) .
-Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" .
-BaseTypeName = identifier .
+Receiver = Parameters .
</pre>
<p>
-The receiver type must be of the form <code>T</code> or <code>*T</code> where
-<code>T</code> is a type name. The type denoted by <code>T</code> is called
+The receiver is specified via an extra parameter section preceeding the method
+name. That parameter section must declare a single 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
it must be declared in the same package as the method.
The method is said to be <i>bound</i> to the base type and the method name
@@ -2117,9 +2190,9 @@ operand only on the left-hand side of an <a href="#Assignments">assignment</a>.
</p>
<pre class="ebnf">
-Operand = Literal | OperandName | MethodExpr | "(" Expression ")" .
-Literal = BasicLit | CompositeLit | FunctionLit .
-BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
+Operand = Literal | OperandName | MethodExpr | "(" Expression ")" .
+Literal = BasicLit | CompositeLit | FunctionLit .
+BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
OperandName = identifier | QualifiedIdent.
</pre>
@@ -2241,7 +2314,8 @@ For array and slice literals the following rules apply:
<p>
<a href="#Address_operators">Taking the address</a> of a composite literal
-generates a pointer to a unique instance of the literal's value.
+generates a pointer to a unique <a href="#Variables">variable</a> initialized
+with the literal's value.
</p>
<pre>
var pointer *Point3D = &amp;Point3D{y: 1000}
@@ -2375,12 +2449,11 @@ Primary expressions are the operands for unary and binary expressions.
PrimaryExpr =
Operand |
Conversion |
- BuiltinCall |
PrimaryExpr Selector |
PrimaryExpr Index |
PrimaryExpr Slice |
PrimaryExpr TypeAssertion |
- PrimaryExpr Call .
+ PrimaryExpr Arguments .
Selector = "." identifier .
Index = "[" Expression "]" .
@@ -2388,8 +2461,7 @@ Slice = "[" ( [ Expression ] ":" [ Expression ] ) |
( [ Expression ] ":" Expression ":" Expression )
"]" .
TypeAssertion = "." "(" Type ")" .
-Call = "(" [ ArgumentList [ "," ] ] ")" .
-ArgumentList = ExpressionList [ "..." ] .
+Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .
</pre>
@@ -2449,30 +2521,40 @@ The following rules apply to selectors:
<ol>
<li>
For a value <code>x</code> of type <code>T</code> or <code>*T</code>
-where <code>T</code> is not an interface type,
+where <code>T</code> is not a pointer or interface type,
<code>x.f</code> denotes the field or method at the shallowest depth
in <code>T</code> where there
is such an <code>f</code>.
If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code></a>
with shallowest depth, the selector expression is illegal.
</li>
+
<li>
-For a variable <code>x</code> of type <code>I</code> where <code>I</code>
+For a value <code>x</code> of type <code>I</code> where <code>I</code>
is an interface type, <code>x.f</code> denotes the actual method with name
-<code>f</code> of the value assigned to <code>x</code>.
+<code>f</code> of the dynamic value of <code>x</code>.
If there is no method with name <code>f</code> in the
<a href="#Method_sets">method set</a> of <code>I</code>, the selector
expression is illegal.
</li>
+
+<li>
+As an exception, if the type of <code>x</code> is a named pointer type
+and <code>(*x).f</code> is a valid selector expression denoting a field
+(but not a method), <code>x.f</code> is shorthand for <code>(*x).f</code>.
+</li>
+
<li>
In all other cases, <code>x.f</code> is illegal.
</li>
+
<li>
If <code>x</code> is of pointer type and has the value
<code>nil</code> and <code>x.f</code> denotes a struct field,
assigning to or evaluating <code>x.f</code>
causes a <a href="#Run_time_panics">run-time panic</a>.
</li>
+
<li>
If <code>x</code> is of interface type and has the value
<code>nil</code>, <a href="#Calls">calling</a> or
@@ -2482,18 +2564,6 @@ causes a <a href="#Run_time_panics">run-time panic</a>.
</ol>
<p>
-Selectors automatically <a href="#Address_operators">dereference</a>
-pointers to structs.
-If <code>x</code> is a pointer to a struct, <code>x.y</code>
-is shorthand for <code>(*x).y</code>; if the field <code>y</code>
-is also a pointer to a struct, <code>x.y.z</code> is shorthand
-for <code>(*(*x).y).z</code>, and so on.
-If <code>x</code> contains an anonymous field of type <code>*A</code>,
-where <code>A</code> is also a struct type,
-<code>x.f</code> is shorthand for <code>(*x.A).f</code>.
-</p>
-
-<p>
For example, given the declarations:
</p>
@@ -2502,13 +2572,13 @@ type T0 struct {
x int
}
-func (recv *T0) M0()
+func (*T0) M0()
type T1 struct {
y int
}
-func (recv T1) M1()
+func (T1) M1()
type T2 struct {
z int
@@ -2516,9 +2586,13 @@ type T2 struct {
*T0
}
-func (recv *T2) M2()
+func (*T2) M2()
+
+type Q *T2
-var p *T2 // with p != nil and p.T0 != nil
+var t T2 // with t.T0 != nil
+var p *T2 // with p != nil and (*p).T0 != nil
+var q Q = p
</pre>
<p>
@@ -2526,13 +2600,254 @@ one may write:
</p>
<pre>
-p.z // (*p).z
-p.y // ((*p).T1).y
-p.x // (*(*p).T0).x
+t.z // t.z
+t.y // t.T1.y
+t.x // (*t.TO).x
+
+p.z // (*p).z
+p.y // (*p).T1.y
+p.x // (*(*p).T0).x
+
+q.x // (*(*q).T0).x (*q).x is a valid field selector
+
+p.M2() // p.M2() M2 expects *T2 receiver
+p.M1() // ((*p).T1).M1() M1 expects T1 receiver
+p.M0() // ((&(*p).T0)).M0() M0 expects *T0 receiver, see section on Calls
+</pre>
+
+<p>
+but the following is invalid:
+</p>
+
+<pre>
+q.M0() // (*q).M0 is valid but not a field selector
+</pre>
+
+
+<h3 id="Method_expressions">Method expressions</h3>
+
+<p>
+If <code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
+<code>T.M</code> is a function that is callable as a regular function
+with the same arguments as <code>M</code> prefixed by an additional
+argument that is the receiver of the method.
+</p>
+
+<pre class="ebnf">
+MethodExpr = ReceiverType "." MethodName .
+ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
+</pre>
+
+<p>
+Consider a struct type <code>T</code> with two methods,
+<code>Mv</code>, whose receiver is of type <code>T</code>, and
+<code>Mp</code>, whose receiver is of type <code>*T</code>.
+</p>
+
+<pre>
+type T struct {
+ a int
+}
+func (tv T) Mv(a int) int { return 0 } // value receiver
+func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
+
+var t T
+</pre>
+
+<p>
+The expression
+</p>
+
+<pre>
+T.Mv
+</pre>
+
+<p>
+yields a function equivalent to <code>Mv</code> but
+with an explicit receiver as its first argument; it has signature
+</p>
+
+<pre>
+func(tv T, a int) int
+</pre>
+
+<p>
+That function may be called normally with an explicit receiver, so
+these five invocations are equivalent:
+</p>
+
+<pre>
+t.Mv(7)
+T.Mv(t, 7)
+(T).Mv(t, 7)
+f1 := T.Mv; f1(t, 7)
+f2 := (T).Mv; f2(t, 7)
+</pre>
+
+<p>
+Similarly, the expression
+</p>
+
+<pre>
+(*T).Mp
+</pre>
+
+<p>
+yields a function value representing <code>Mp</code> with signature
+</p>
+
+<pre>
+func(tp *T, f float32) float32
+</pre>
+
+<p>
+For a method with a value receiver, one can derive a function
+with an explicit pointer receiver, so
+</p>
+
+<pre>
+(*T).Mv
+</pre>
+
+<p>
+yields a function value representing <code>Mv</code> with signature
+</p>
+
+<pre>
+func(tv *T, a int) int
+</pre>
+
+<p>
+Such a function indirects through the receiver to create a value
+to pass as the receiver to the underlying method;
+the method does not overwrite the value whose address is passed in
+the function call.
+</p>
+
+<p>
+The final case, a value-receiver function for a pointer-receiver method,
+is illegal because pointer-receiver methods are not in the method set
+of the value type.
+</p>
+
+<p>
+Function values derived from methods are called with function call syntax;
+the receiver is provided as the first argument to the call.
+That is, given <code>f := T.Mv</code>, <code>f</code> is invoked
+as <code>f(t, 7)</code> not <code>t.f(7)</code>.
+To construct a function that binds the receiver, use a
+<a href="#Function_literals">function literal</a> or
+<a href="#Method_values">method value</a>.
+</p>
+
+<p>
+It is legal to derive a function value from a method of an interface type.
+The resulting function takes an explicit receiver of that interface type.
+</p>
+
+<h3 id="Method_values">Method values</h3>
+
+<p>
+If the expression <code>x</code> has static type <code>T</code> and
+<code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
+<code>x.M</code> is called a <i>method value</i>.
+The method value <code>x.M</code> is a function value that is callable
+with the same arguments as a method call of <code>x.M</code>.
+The expression <code>x</code> is evaluated and saved during the evaluation of the
+method value; the saved copy is then used as the receiver in any calls,
+which may be executed later.
+</p>
+
+<p>
+The type <code>T</code> may be an interface or non-interface type.
+</p>
+
+<p>
+As in the discussion of <a href="#Method_expressions">method expressions</a> above,
+consider a struct type <code>T</code> with two methods,
+<code>Mv</code>, whose receiver is of type <code>T</code>, and
+<code>Mp</code>, whose receiver is of type <code>*T</code>.
+</p>
+
+<pre>
+type T struct {
+ a int
+}
+func (tv T) Mv(a int) int { return 0 } // value receiver
+func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
+
+var t T
+var pt *T
+func makeT() T
+</pre>
+
+<p>
+The expression
+</p>
+
+<pre>
+t.Mv
+</pre>
+
+<p>
+yields a function value of type
+</p>
+
+<pre>
+func(int) int
+</pre>
+
+<p>
+These two invocations are equivalent:
+</p>
+
+<pre>
+t.Mv(7)
+f := t.Mv; f(7)
+</pre>
+
+<p>
+Similarly, the expression
+</p>
+
+<pre>
+pt.Mp
+</pre>
+
+<p>
+yields a function value of type
+</p>
+
+<pre>
+func(float32) float32
+</pre>
+
+<p>
+As with <a href="#Selectors">selectors</a>, a reference to a non-interface method with a value receiver
+using a pointer will automatically dereference that pointer: <code>pt.Mv</code> is equivalent to <code>(*pt).Mv</code>.
+</p>
+
+<p>
+As with <a href="#Calls">method calls</a>, a reference to a non-interface method with a pointer receiver
+using an addressable value will automatically take the address of that value: <code>t.Mp</code> is equivalent to <code>(&amp;t).Mp</code>.
+</p>
+
+<pre>
+f := t.Mv; f(7) // like t.Mv(7)
+f := pt.Mp; f(7) // like pt.Mp(7)
+f := pt.Mv; f(7) // like (*pt).Mv(7)
+f := t.Mp; f(7) // like (&amp;t).Mp(7)
+f := makeT().Mp // invalid: result of makeT() is not addressable
+</pre>
+
+<p>
+Although the examples above use non-interface types, it is also legal to create a method value
+from a value of interface type.
+</p>
-p.M2() // (*p).M2()
-p.M1() // ((*p).T1).M1()
-p.M0() // ((*p).T0).M0()
+<pre>
+var i interface { M(int) } = myVal
+f := i.M; f(7) // like i.M(7)
</pre>
@@ -2625,7 +2940,7 @@ Otherwise <code>a[x]</code> is illegal.
<p>
An index expression on a map <code>a</code> of type <code>map[K]V</code>
-may be used in an assignment or initialization of the special form
+used in an <a href="#Assignments">assignment</a> or initialization of the special form
</p>
<pre>
@@ -2635,11 +2950,9 @@ var v, ok = a[x]
</pre>
<p>
-where the result of the index expression is a pair of values with types
-<code>(V, bool)</code>. In this form, the value of <code>ok</code> is
+yields an additional untyped boolean value. The value of <code>ok</code> is
<code>true</code> if the key <code>x</code> is present in the map, and
-<code>false</code> otherwise. The value of <code>v</code> is the value
-<code>a[x]</code> as in the single-result form.
+<code>false</code> otherwise.
</p>
<p>
@@ -2824,7 +3137,7 @@ r := y.(io.Reader) // r has type io.Reader and y must implement both I and i
</pre>
<p>
-If a type assertion is used in an <a href="#Assignments">assignment</a> or initialization of the form
+A type assertion used in an <a href="#Assignments">assignment</a> or initialization of the special form
</p>
<pre>
@@ -2834,13 +3147,10 @@ var v, ok = x.(T)
</pre>
<p>
-the result of the assertion is a pair of values with types <code>(T, bool)</code>.
-If the assertion holds, the expression returns the pair <code>(x.(T), true)</code>;
-otherwise, the expression returns <code>(Z, false)</code> where <code>Z</code>
-is the <a href="#The_zero_value">zero value</a> for type <code>T</code>.
+yields an additional untyped boolean value. The value of <code>ok</code> is <code>true</code>
+if the assertion holds. Otherwise it is <code>false</code> and the value of <code>v</code> is
+the <a href="#The_zero_value">zero value</a> for type <code>T</code>.
No run-time panic occurs in this case.
-The type assertion in this construct thus acts like a function call
-returning a value and a boolean indicating success.
</p>
@@ -2870,7 +3180,7 @@ the method.
<pre>
math.Atan2(x, y) // function call
var pt *Point
-pt.Scale(3.5) // method call with receiver pt
+pt.Scale(3.5) // method call with receiver pt
</pre>
<p>
@@ -3375,13 +3685,13 @@ or an array indexing operation of an addressable array.
As an exception to the addressability requirement, <code>x</code> may also be a
(possibly parenthesized)
<a href="#Composite_literals">composite literal</a>.
-If the evaluation of <code>x</code> would cause a <a href="#Run_time_panics">run-time panic</a>,
+If the evaluation of <code>x</code> would cause a <a href="#Run_time_panics">run-time panic</a>,
then the evaluation of <code>&amp;x</code> does too.
</p>
<p>
For an operand <code>x</code> of pointer type <code>*T</code>, the pointer
-indirection <code>*x</code> denotes the value of type <code>T</code> pointed
+indirection <code>*x</code> denotes the <a href="#Variables">variable</a> of type <code>T</code> pointed
to by <code>x</code>.
If <code>x</code> is <code>nil</code>, an attempt to evaluate <code>*x</code>
will cause a <a href="#Run_time_panics">run-time panic</a>.
@@ -3422,7 +3732,7 @@ f(&lt;-ch)
</pre>
<p>
-A receive expression used in an assignment or initialization of the form
+A receive expression used in an <a href="#Assignments">assignment</a> or initialization of the special form
</p>
<pre>
@@ -3432,7 +3742,7 @@ var x, ok = &lt;-ch
</pre>
<p>
-yields an additional result of type <code>bool</code> reporting whether the
+yields an additional untyped boolean result reporting whether the
communication succeeded. The value of <code>ok</code> is <code>true</code>
if the value received was delivered by a successful send operation to the
channel, or <code>false</code> if it is a zero value generated because the
@@ -3440,232 +3750,6 @@ channel is closed and empty.
</p>
-<h3 id="Method_expressions">Method expressions</h3>
-
-<p>
-If <code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
-<code>T.M</code> is a function that is callable as a regular function
-with the same arguments as <code>M</code> prefixed by an additional
-argument that is the receiver of the method.
-</p>
-
-<pre class="ebnf">
-MethodExpr = ReceiverType "." MethodName .
-ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
-</pre>
-
-<p>
-Consider a struct type <code>T</code> with two methods,
-<code>Mv</code>, whose receiver is of type <code>T</code>, and
-<code>Mp</code>, whose receiver is of type <code>*T</code>.
-</p>
-
-<pre>
-type T struct {
- a int
-}
-func (tv T) Mv(a int) int { return 0 } // value receiver
-func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
-
-var t T
-</pre>
-
-<p>
-The expression
-</p>
-
-<pre>
-T.Mv
-</pre>
-
-<p>
-yields a function equivalent to <code>Mv</code> but
-with an explicit receiver as its first argument; it has signature
-</p>
-
-<pre>
-func(tv T, a int) int
-</pre>
-
-<p>
-That function may be called normally with an explicit receiver, so
-these five invocations are equivalent:
-</p>
-
-<pre>
-t.Mv(7)
-T.Mv(t, 7)
-(T).Mv(t, 7)
-f1 := T.Mv; f1(t, 7)
-f2 := (T).Mv; f2(t, 7)
-</pre>
-
-<p>
-Similarly, the expression
-</p>
-
-<pre>
-(*T).Mp
-</pre>
-
-<p>
-yields a function value representing <code>Mp</code> with signature
-</p>
-
-<pre>
-func(tp *T, f float32) float32
-</pre>
-
-<p>
-For a method with a value receiver, one can derive a function
-with an explicit pointer receiver, so
-</p>
-
-<pre>
-(*T).Mv
-</pre>
-
-<p>
-yields a function value representing <code>Mv</code> with signature
-</p>
-
-<pre>
-func(tv *T, a int) int
-</pre>
-
-<p>
-Such a function indirects through the receiver to create a value
-to pass as the receiver to the underlying method;
-the method does not overwrite the value whose address is passed in
-the function call.
-</p>
-
-<p>
-The final case, a value-receiver function for a pointer-receiver method,
-is illegal because pointer-receiver methods are not in the method set
-of the value type.
-</p>
-
-<p>
-Function values derived from methods are called with function call syntax;
-the receiver is provided as the first argument to the call.
-That is, given <code>f := T.Mv</code>, <code>f</code> is invoked
-as <code>f(t, 7)</code> not <code>t.f(7)</code>.
-To construct a function that binds the receiver, use a
-<a href="#Function_literals">function literal</a> or
-<a href="#Method_values">method value</a>.
-</p>
-
-<p>
-It is legal to derive a function value from a method of an interface type.
-The resulting function takes an explicit receiver of that interface type.
-</p>
-
-<h3 id="Method_values">Method values</h3>
-
-<p>
-If the expression <code>x</code> has static type <code>T</code> and
-<code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
-<code>x.M</code> is called a <i>method value</i>.
-The method value <code>x.M</code> is a function value that is callable
-with the same arguments as a method call of <code>x.M</code>.
-The expression <code>x</code> is evaluated and saved during the evaluation of the
-method value; the saved copy is then used as the receiver in any calls,
-which may be executed later.
-</p>
-
-<p>
-The type <code>T</code> may be an interface or non-interface type.
-</p>
-
-<p>
-As in the discussion of <a href="#Method_expressions">method expressions</a> above,
-consider a struct type <code>T</code> with two methods,
-<code>Mv</code>, whose receiver is of type <code>T</code>, and
-<code>Mp</code>, whose receiver is of type <code>*T</code>.
-</p>
-
-<pre>
-type T struct {
- a int
-}
-func (tv T) Mv(a int) int { return 0 } // value receiver
-func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
-
-var t T
-var pt *T
-func makeT() T
-</pre>
-
-<p>
-The expression
-</p>
-
-<pre>
-t.Mv
-</pre>
-
-<p>
-yields a function value of type
-</p>
-
-<pre>
-func(int) int
-</pre>
-
-<p>
-These two invocations are equivalent:
-</p>
-
-<pre>
-t.Mv(7)
-f := t.Mv; f(7)
-</pre>
-
-<p>
-Similarly, the expression
-</p>
-
-<pre>
-pt.Mp
-</pre>
-
-<p>
-yields a function value of type
-</p>
-
-<pre>
-func(float32) float32
-</pre>
-
-<p>
-As with <a href="#Selectors">selectors</a>, a reference to a non-interface method with a value receiver
-using a pointer will automatically dereference that pointer: <code>pt.Mv</code> is equivalent to <code>(*pt).Mv</code>.
-</p>
-
-<p>
-As with <a href="#Calls">method calls</a>, a reference to a non-interface method with a pointer receiver
-using an addressable value will automatically take the address of that value: <code>t.Mp</code> is equivalent to <code>(&amp;t).Mp</code>.
-</p>
-
-<pre>
-f := t.Mv; f(7) // like t.Mv(7)
-f := pt.Mp; f(7) // like pt.Mp(7)
-f := pt.Mv; f(7) // like (*pt).Mv(7)
-f := t.Mp; f(7) // like (&amp;t).Mp(7)
-f := makeT().Mp // invalid: result of makeT() is not addressable
-</pre>
-
-<p>
-Although the examples above use non-interface types, it is also legal to create a method value
-from a value of interface type.
-</p>
-
-<pre>
-var i interface { M(int) } = myVal
-f := i.M; f(7) // like i.M(7)
-</pre>
-
<h3 id="Conversions">Conversions</h3>
<p>
@@ -4055,7 +4139,7 @@ n := map[int]int{a: f()} // n may be {2: 3} or {3: 3}: evaluation order bet
<p>
At package level, initialization dependencies override the left-to-right rule
for individual initialization expressions, but not for operands within each
-expression:
+expression:
</p>
<pre>
@@ -4314,7 +4398,7 @@ a[i] = 23
<p>
An <i>assignment operation</i> <code>x</code> <i>op</i><code>=</code>
-<code>y</code> where <i>op</i> is a binary arithmetic operation equivalent
+<code>y</code> where <i>op</i> is a binary arithmetic operation is equivalent
to <code>x</code> <code>=</code> <code>x</code> <i>op</i>
<code>y</code> but evaluates <code>x</code>
only once. The <i>op</i><code>=</code> construct is a single token.
@@ -4332,8 +4416,8 @@ i &amp;^= 1&lt;&lt;n
A tuple assignment assigns the individual elements of a multi-valued
operation to a list of variables. There are two forms. In the
first, the right hand operand is a single multi-valued expression
-such as a function evaluation or <a href="#Channel_types">channel</a> or
-<a href="#Map_types">map</a> operation or a <a href="#Type_assertions">type assertion</a>.
+such as a function call, a <a href="#Channel_types">channel</a> or
+<a href="#Map_types">map</a> operation, or a <a href="#Type_assertions">type assertion</a>.
The number of operands on the left
hand side must match the number of values. For instance, if
<code>f</code> is a function returning two values,
@@ -4407,23 +4491,21 @@ to the type of the operand to which it is assigned, with the following special c
</p>
<ol>
-<li><p>
- If an untyped <a href="#Constants">constant</a>
+<li>
+ Any typed value may be assigned to the blank identifier.
+</li>
+
+<li>
+ If an untyped constant
is assigned to a variable of interface type or the blank identifier,
- the constant is first <a href="#Conversions">converted</a> to type
- <code>bool</code>, <code>rune</code>, <code>int</code>, <code>float64</code>,
- <code>complex128</code> or <code>string</code> respectively, depending on
- whether the value is a boolean, rune, integer, floating-point, complex, or
- string constant.
-</p></li>
-
-<li><p>
- <!-- Note that the result of a comparison is an untyped bool that may not be constant. -->
- If a left-hand side is the blank identifier, any typed or non-constant
- value except for the predeclared identifier
- <a href="#Predeclared_identifiers"><code>nil</code></a>
- may be assigned to it.
-</p></li>
+ the constant is first <a href="#Conversions">converted</a> to its
+ <a href="#Constants">default type</a>.
+</li>
+
+<li>
+ If an untyped boolean value is assigned to a variable of interface type or
+ the blank identifier, it is first converted to type <code>bool</code>.
+</li>
</ol>
<h3 id="If_statements">If statements</h3>
@@ -4678,6 +4760,7 @@ additionally it may specify an <i>init</i>
and a <i>post</i> statement, such as an assignment,
an increment or decrement statement. The init statement may be a
<a href="#Short_variable_declarations">short variable declaration</a>, but the post statement must not.
+Variables declared by the init statement are re-used in each iteration.
</p>
<pre class="ebnf">
@@ -4713,41 +4796,42 @@ for { S() } is the same as for true { S() }
A "for" statement with a "range" clause
iterates through all entries of an array, slice, string or map,
or values received on a channel. For each entry it assigns <i>iteration values</i>
-to corresponding <i>iteration variables</i> and then executes the block.
+to corresponding <i>iteration variables</i> if present and then executes the block.
</p>
<pre class="ebnf">
-RangeClause = ( ExpressionList "=" | IdentifierList ":=" ) "range" Expression .
+RangeClause = [ ExpressionList "=" | IdentifierList ":=" ] "range" Expression .
</pre>
<p>
The expression on the right in the "range" clause is called the <i>range expression</i>,
which may be an array, pointer to an array, slice, string, map, or channel permitting
<a href="#Receive_operator">receive operations</a>.
-As with an assignment, the operands on the left must be
+As with an assignment, if present the operands on the left must be
<a href="#Address_operators">addressable</a> or map index expressions; they
-denote the iteration variables. If the range expression is a channel, only
-one iteration variable is permitted, otherwise there may be one or two. In the latter case,
-if the second iteration variable is the <a href="#Blank_identifier">blank identifier</a>,
-the range clause is equivalent to the same clause with only the first variable present.
+denote the iteration variables. If the range expression is a channel, at most
+one iteration variable is permitted, otherwise there may be up to two.
+If the last iteration variable is the <a href="#Blank_identifier">blank identifier</a>,
+the range clause is equivalent to the same clause without that identifier.
</p>
<p>
The range expression is evaluated once before beginning the loop,
-with one exception. If the range expression is an array or a pointer to an array
-and only the first iteration value is present, only the range expression's
-length is evaluated; if that length is constant
-<a href="#Length_and_capacity">by definition</a>,
+with one exception: if the range expression is an array or a pointer to an array
+and at most one iteration variable is present, only the range expression's
+length is evaluated; if that length is constant,
+<a href="#Length_and_capacity">by definition</a>
the range expression itself will not be evaluated.
</p>
<p>
Function calls on the left are evaluated once per iteration.
-For each iteration, iteration values are produced as follows:
+For each iteration, iteration values are produced as follows
+if the respective iteration variables are present:
</p>
<pre class="grammar">
-Range expression 1st value 2nd value (if 2nd variable is present)
+Range expression 1st value 2nd value
array or slice a [n]E, *[n]E, or []E index i int a[i] E
string s string type index i int see below rune
@@ -4759,7 +4843,7 @@ channel c chan E, &lt;-chan E element e E
<li>
For an array, pointer to array, or slice value <code>a</code>, the index iteration
values are produced in increasing order, starting at element index 0.
-If only the first iteration variable is present, the range loop produces
+If at most one iteration variable is present, the range loop produces
iteration values from 0 up to <code>len(a)-1</code> and does not index into the array
or slice itself. For a <code>nil</code> slice, the number of iterations is 0.
</li>
@@ -4803,7 +4887,7 @@ The iteration variables may be declared by the "range" clause using a form of
<a href="#Short_variable_declarations">short variable declaration</a>
(<code>:=</code>).
In this case their types are set to the types of the respective iteration values
-and their <a href="#Declarations_and_scope">scope</a> ends at the end of the "for"
+and their <a href="#Declarations_and_scope">scope</a> is the block of the "for"
statement; they are re-used in each iteration.
If the iteration variables are declared outside the "for" statement,
after execution their values will be those of the last iteration.
@@ -4840,6 +4924,9 @@ var ch chan Work = producer()
for w := range ch {
doWork(w)
}
+
+// empty a channel
+for range ch {}
</pre>
@@ -5242,13 +5329,16 @@ Calls of built-in functions are restricted as for
</p>
<p>
-Each time the "defer" statement
+Each time a "defer" statement
executes, the function value and parameters to the call are
<a href="#Calls">evaluated as usual</a>
-and saved anew but the actual function body is not executed.
-Instead, deferred functions are executed immediately before
+and saved anew but the actual function is not invoked.
+Instead, deferred functions are invoked immediately before
the surrounding function returns, in the reverse order
they were deferred.
+If a deferred function value evaluates
+to <code>nil</code>, execution <a href="#Handling_panics">panics</a>
+when the function is invoked, not when the "defer" statement is executed.
</p>
<p>
@@ -5295,11 +5385,6 @@ so they can only appear in <a href="#Calls">call expressions</a>;
they cannot be used as function values.
</p>
-<pre class="ebnf">
-BuiltinCall = identifier "(" [ BuiltinArgs [ "," ] ] ")" .
-BuiltinArgs = Type [ "," ArgumentList ] | ArgumentList .
-</pre>
-
<h3 id="Close">Close</h3>
<p>
@@ -5378,9 +5463,11 @@ var z complex128
<h3 id="Allocation">Allocation</h3>
<p>
-The built-in function <code>new</code> takes a type <code>T</code> and
-returns a value of type <code>*T</code>.
-The memory is initialized as described in the section on
+The built-in function <code>new</code> takes a type <code>T</code>,
+allocates storage for a <a href="#Variables">variable</a> of that type
+at run time, and returns a value of type <code>*T</code>
+<a href="#Pointer_types">pointing</a> to it.
+The variable is initialized as described in the section on
<a href="#The_zero_value">initial values</a>.
</p>
@@ -5398,10 +5485,10 @@ new(S)
</pre>
<p>
-dynamically allocates memory for a variable of type <code>S</code>,
+allocates storage for a variable of type <code>S</code>,
initializes it (<code>a=0</code>, <code>b=0.0</code>),
and returns a value of type <code>*S</code> containing the address
-of the memory.
+of the location.
</p>
<h3 id="Making_slices_maps_and_channels">Making slices, maps and channels</h3>
@@ -5868,10 +5955,12 @@ func main() {
<h3 id="The_zero_value">The zero value</h3>
<p>
-When memory is allocated to store a value, either through a declaration
-or a call of <code>make</code> or <code>new</code>,
-and no explicit initialization is provided, the memory is
-given a default initialization. Each element of such a value is
+When storage is allocated for a <a href="#Variables">variable</a>,
+either through a declaration or a call of <code>new</code>, or when
+a new value is created, either through a composite literal or a call
+of <code>make</code>,
+and no explicit initialization is provided, the variable or value is
+given a default value. Each element of such a variable or value is
set to the <i>zero value</i> for its type: <code>false</code> for booleans,
<code>0</code> for integers, <code>0.0</code> for floats, <code>""</code>
for strings, and <code>nil</code> for pointers, functions, interfaces, slices, channels, and maps.
@@ -5915,20 +6004,42 @@ var t T
</pre>
<h3 id="Package_initialization">Package initialization</h3>
+
<p>
-Within a package, package-level variables are initialized according
-to their <i>dependencies</i>: if a variable <code>x</code> depends on
-a variable <code>y</code>, <code>x</code> will be initialized after
-<code>y</code>.
+Within a package, package-level variables are initialized in
+<i>declaration order</i> but after any of the variables
+they <i>depend</i> on.
+</p>
+
+<p>
+More precisely, a package-level variable is considered <i>ready for
+initialization</i> if it is not yet initialized and either has
+no <a href="#Variable_declarations">initialization expression</a> or
+its initialization expression has no dependencies on uninitialized variables.
+Initialization proceeds by repeatedly initializing the next package-level
+variable that is earliest in declaration order and ready for initialization,
+until there are no variables ready for initialization.
+</p>
+
+<p>
+If any variables are still uninitialized when this
+process ends, those variables are part of one or more initialization cycles,
+and the program is not valid.
+</p>
+
+<p>
+The declaration order of variables declared in multiple files is determined
+by the order in which the files are presented to the compiler: Variables
+declared in the first file are declared before any of the variables declared
+in the second file, and so on.
</p>
<p>
Dependency analysis does not rely on the actual values of the
variables, only on lexical <i>references</i> to them in the source,
-analyzed transitively. For instance, a variable <code>x</code>'s
-<a href="#Variable_declarations">initialization expression</a>
-may refer to a function whose body refers to variable <code>y</code>;
-if so, <code>x</code> depends on <code>y</code>.
+analyzed transitively. For instance, if a variable <code>x</code>'s
+initialization expression refers to a function whose body refers to
+variable <code>y</code> then <code>x</code> depends on <code>y</code>.
Specifically:
</p>
@@ -5941,7 +6052,7 @@ variable or function.
<li>
A reference to a method <code>m</code> is a
<a href="#Method_values">method value</a> or
-<a href="#Method_expressions">method expression</a> of the form
+<a href="#Method_expressions">method expression</a> of the form
<code>t.m</code>, where the (static) type of <code>t</code> is
not an interface type, and the method <code>m</code> is in the
<a href="#Method_sets">method set</a> of <code>t</code>.
@@ -5950,7 +6061,7 @@ It is immaterial whether the resulting function value
</li>
<li>
-A variable, function, or method <code>x</code> depends on a variable
+A variable, function, or method <code>x</code> depends on a variable
<code>y</code> if <code>x</code>'s initialization expression or body
(for functions and methods) contains a reference to <code>y</code>
or to a function or method that depends on <code>y</code>.
@@ -5961,11 +6072,6 @@ or to a function or method that depends on <code>y</code>.
Dependency analysis is performed per package; only references referring
to variables, functions, and methods declared in the current package
are considered.
-It is an error if variable dependencies form a cycle
-(but dependency cycles containing no variables are permitted).
-If two variables are independent of each other,
-they are initialized in the order they are declared
-in the source, possibly in multiple files, as presented to the compiler.
</p>
<p>
@@ -5988,8 +6094,6 @@ func f() int {
<p>
the initialization order is <code>d</code>, <code>b</code>, <code>c</code>, <code>a</code>.
-Since <code>b</code> and <code>c</code> are independent of each other, they are
-initialized in declaration order (<code>b</code> before <code>c</code>).
</p>
<p>
@@ -6002,7 +6106,7 @@ func init() { … }
</pre>
<p>
-Multiple such functions may be defined, even within a single
+Multiple such functions may be defined, even within a single
source file. The <code>init</code> identifier is not
<a href="#Declarations_and_scope">declared</a> and thus
<code>init</code> functions cannot be referred to from anywhere
@@ -6032,6 +6136,12 @@ the <code>init</code> functions: it will not invoke the next one
until the previous one has returned.
</p>
+<p>
+To ensure reproducible initialization behavior, build systems are encouraged
+to present multiple files belonging to the same package in lexical file name
+order to a compiler.
+</p>
+
<h3 id="Program_execution">Program execution</h3>
<p>
@@ -6106,8 +6216,8 @@ type Error interface {
The built-in package <code>unsafe</code>, known to the compiler,
provides facilities for low-level programming including operations
that violate the type system. A package using <code>unsafe</code>
-must be vetted manually for type safety. The package provides the
-following interface:
+must be vetted manually for type safety and may not be portable.
+The package provides the following interface:
</p>
<pre class="grammar">
@@ -6122,10 +6232,11 @@ func Sizeof(variable ArbitraryType) uintptr
</pre>
<p>
-Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted to
-a <code>Pointer</code> type and vice versa.
A <code>Pointer</code> is a <a href="#Pointer_types">pointer type</a> but a <code>Pointer</code>
value may not be <a href="#Address_operators">dereferenced</a>.
+Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted to
+a <code>Pointer</code> type and vice versa.
+The effect of converting between <code>Pointer</code> and <code>uintptr</code> is implementation-defined.
</p>
<pre>
diff --git a/doc/gopher/biplane.jpg b/doc/gopher/biplane.jpg
new file mode 100644
index 000000000..d5e666f96
--- /dev/null
+++ b/doc/gopher/biplane.jpg
Binary files differ
diff --git a/doc/gopher/fiveyears.jpg b/doc/gopher/fiveyears.jpg
new file mode 100644
index 000000000..df1064868
--- /dev/null
+++ b/doc/gopher/fiveyears.jpg
Binary files differ
diff --git a/doc/help.html b/doc/help.html
index a307b2aad..2cc47806c 100644
--- a/doc/help.html
+++ b/doc/help.html
@@ -24,7 +24,7 @@ Need help with Go? Try these resources.
<p>
Search the <a href="//groups.google.com/group/golang-nuts">golang-nuts</a>
archives and consult the <a href="/doc/go_faq.html">FAQ</a> and
-<a href="//code.google.com/p/go-wiki/wiki">wiki</a> before posting.
+<a href="//golang.org/wiki">wiki</a> before posting.
</p>
<h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
diff --git a/doc/install-source.html b/doc/install-source.html
index 82859b50f..f53deb404 100644
--- a/doc/install-source.html
+++ b/doc/install-source.html
@@ -241,12 +241,12 @@ provides <b>essential setup instructions</b> for using the Go tools.
<p>
The source code for several Go tools (including <a href="/cmd/godoc/">godoc</a>)
-is kept in <a href="https://code.google.com/p/go.tools">the go.tools repository</a>.
+is kept in <a href="https://golang.org/x/tools">the go.tools repository</a>.
To install all of them, run the <code>go</code> <code>get</code> command:
</p>
<pre>
-$ go get code.google.com/p/go.tools/cmd/...
+$ go get golang.org/x/tools/cmd/...
</pre>
<p>
@@ -254,7 +254,7 @@ Or if you just want to install a specific command (<code>godoc</code> in this ca
</p>
<pre>
-$ go get code.google.com/p/go.tools/cmd/godoc
+$ go get golang.org/x/tools/cmd/godoc
</pre>
<p>
diff --git a/doc/install.html b/doc/install.html
index 2de04471c..9561fdde2 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -6,14 +6,14 @@
<h2 id="download">Download the Go distribution</h2>
<p>
-<a href="/dl/" id="start" class="download" target="_blank">
+<a href="https://golang.org/dl/" id="start" class="download" target="_blank">
<span class="big">Download Go</span>
<span class="desc">Click here to visit the downloads page</span>
</a>
</p>
<p>
-<a href="https://code.google.com/p/go/wiki/Downloads?tm=2" target="_blank">Official binary
+<a href="https://golang.org/dl/" target="_blank">Official binary
distributions</a> are available for the FreeBSD (release 8 and above), Linux, Mac OS X (Snow Leopard
and above), and Windows operating systems and the 32-bit (<code>386</code>) and
64-bit (<code>amd64</code>) x86 processor architectures.
@@ -47,7 +47,7 @@ proceeding. If your OS or architecture is not on the list, it's possible that
<tr><td>FreeBSD 8 or later</td> <td>amd64, 386, arm</td> <td>Debian GNU/kFreeBSD not supported; FreeBSD/ARM needs FreeBSD 10 or later</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; no binary distribution for ARM yet</td></tr>
<tr><td>Mac OS X 10.6 or later</td> <td>amd64, 386</td> <td>use the gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup></td></tr>
-<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>&#8224;</sup>. No need for cgywin or msys.</td></tr>
+<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>&#8224;</sup>. No need for cygwin or msys.</td></tr>
</table>
<p>
@@ -70,7 +70,7 @@ first <a href="#uninstall">remove the existing version</a>.
<h3 id="tarball">Linux, Mac OS X, and FreeBSD tarballs</h3>
<p>
-<a href="https://code.google.com/p/go/wiki/Downloads?tm=2">Download the archive</a>
+<a href="https://golang.org/dl/">Download the archive</a>
and extract it into <code>/usr/local</code>, creating a Go tree in
<code>/usr/local/go</code>. For example:
</p>
@@ -127,7 +127,7 @@ location.
<h3 id="osx">Mac OS X package installer</h3>
<p>
-<a href="https://code.google.com/p/go/wiki/Downloads?tm=2">Download the package file</a>,
+<a href="https://golang.org/dl/">Download the package file</a>,
open it, and follow the prompts to install the Go tools.
The package installs the Go distribution to <code>/usr/local/go</code>.
</p>
@@ -150,7 +150,7 @@ MSI installer that configures your installation automatically.
<h4 id="windows_msi">MSI installer</h4>
<p>
-Open the <a href="https://code.google.com/p/go/wiki/Downloads?tm=2">MSI file</a>
+Open the <a href="https://golang.org/dl/">MSI file</a>
and follow the prompts to install the Go tools.
By default, the installer puts the Go distribution in <code>c:\Go</code>.
</p>
@@ -164,7 +164,7 @@ command prompts for the change to take effect.
<h4 id="windows_zip">Zip archive</h4>
<p>
-<a href="https://code.google.com/p/go/wiki/Downloads?tm=2">Download the zip file</a> and extract it into the directory of your choice (we suggest <code>c:\Go</code>).
+<a href="https://golang.org/dl/">Download the zip file</a> and extract it into the directory of your choice (we suggest <code>c:\Go</code>).
</p>
<p>
@@ -224,19 +224,12 @@ If you see the "hello, world" message then your Go installation is working.
<p>
You're almost done.
-You just need to do a little more setup.
+You just need to set up your environment.
</p>
<p>
-<a href="/doc/code.html" class="download" id="writing">
-<span class="big">How to Write Go Code</span>
-<span class="desc">Learn how to set up and use the Go tools</span>
-</a>
-</p>
-
-<p>
-The <a href="/doc/code.html">How to Write Go Code</a> document
-provides <b>essential setup instructions</b> for using the Go tools.
+Read the <a href="/doc/code.html">How to Write Go Code</a> document,
+which provides <b>essential setup instructions</b> for using the Go tools.
</p>
@@ -277,5 +270,3 @@ The official mailing list for discussion of the Go language is
Report bugs using the
<a href="//golang.org/issue">Go issue tracker</a>.
</p>
-
-
diff --git a/include/bio.h b/include/bio.h
index f61409b8a..982b881f1 100644
--- a/include/bio.h
+++ b/include/bio.h
@@ -129,6 +129,14 @@ int Bungetc(Biobuf*);
int Bungetrune(Biobuf*);
long Bwrite(Biobuf*, void*, long);
int Bvprint(Biobuf*, char*, va_list);
+/*c2go
+int BGETC(Biobuf*);
+int BGETLE2(Biobuf*);
+int BGETLE4(Biobuf*);
+int BPUTC(Biobuf*, int);
+int BPUTLE2(Biobuf*, int);
+int BPUTLE4(Biobuf*, int);
+*/
#if defined(__cplusplus)
}
diff --git a/include/link.h b/include/link.h
index 248497888..05e117c87 100644
--- a/include/link.h
+++ b/include/link.h
@@ -105,13 +105,15 @@ struct Prog
int32 spadj;
uchar mark;
uchar back; // 6l, 8l
- char ft; /* 6l, 8l oclass cache */
- char tt; // 6l, 8l
- uchar optab; // 5l
+ uchar ft; /* 6l, 8l oclass cache */
+ uchar tt; // 6l, 8l
+ uint16 optab; // 5l
uchar isize; // 6l, 8l
char width; /* fake for DATA */
char mode; /* 16, 32, or 64 in 6l, 8l; internal use in 5g, 6g, 8g */
+
+ /*c2go uchar TEXTFLAG; */
};
// prevent incompatible type signatures between liblink and 8l on Plan 9
@@ -124,6 +126,7 @@ struct LSym
short type;
short version;
uchar dupok;
+ uchar cfunc;
uchar external;
uchar nosplit;
uchar reachable;
@@ -167,7 +170,7 @@ struct LSym
// SDATA, SBSS
uchar* p;
- int32 np;
+ int np;
int32 maxp;
Reloc* r;
int32 nr;
@@ -201,10 +204,10 @@ enum
SELFSECT,
SMACHO, /* Mach-O __nl_symbol_ptr */
SMACHOGOT,
+ SWINDOWS,
SNOPTRDATA,
SINITARR,
SDATA,
- SWINDOWS,
SBSS,
SNOPTRBSS,
STLSBSS,
@@ -370,6 +373,7 @@ struct Link
char* trimpath;
char* goroot;
char* goroot_final;
+ int32 enforce_data_order; // for use by assembler
// hash table of all symbols
LSym* hash[LINKHASH];
@@ -389,9 +393,9 @@ struct Link
LSym* sym_divu;
LSym* sym_mod;
LSym* sym_modu;
- LSym* symmorestack[20];
- LSym* gmsym;
- LSym* plan9tos;
+ LSym* symmorestack[2];
+ LSym* tlsg;
+ LSym* plan9privates;
Prog* curp;
Prog* printp;
Prog* blitrl;
@@ -403,7 +407,7 @@ struct Link
int asmode;
uchar* andptr;
uchar and[100];
- int32 instoffset;
+ int64 instoffset;
int32 autosize;
int32 armsize;
@@ -429,11 +433,17 @@ struct Link
LSym* filesyms;
};
+enum {
+ LittleEndian = 0x04030201,
+ BigEndian = 0x01020304,
+};
+
// LinkArch is the definition of a single architecture.
struct LinkArch
{
char* name; // "arm", "amd64", and so on
int thechar; // '5', '6', and so on
+ int32 endian; // LittleEndian or BigEndian
void (*addstacksplit)(Link*, LSym*);
void (*assemble)(Link*, LSym*);
@@ -462,6 +472,7 @@ struct LinkArch
int D_PARAM;
int D_SCONST;
int D_STATIC;
+ int D_OREG;
int ACALL;
int ADATA;
@@ -532,6 +543,7 @@ vlong adduint8(Link *ctxt, LSym *s, uint8 v);
vlong adduintxx(Link *ctxt, LSym *s, uint64 v, int wid);
void mangle(char *file);
void savedata(Link *ctxt, LSym *s, Prog *p, char *pn);
+void savedata1(Link *ctxt, LSym *s, Prog *p, char *pn, int enforce_order);
vlong setaddr(Link *ctxt, LSym *s, vlong off, LSym *t);
vlong setaddrplus(Link *ctxt, LSym *s, vlong off, LSym *t, vlong add);
vlong setuint16(Link *ctxt, LSym *s, vlong r, uint16 v);
@@ -558,7 +570,7 @@ int find1(int32 l, int c);
void linkgetline(Link *ctxt, int32 line, LSym **f, int32 *l);
void histtoauto(Link *ctxt);
void mkfwd(LSym*);
-void nuxiinit(void);
+void nuxiinit(LinkArch*);
void savehist(Link *ctxt, int32 line, int32 off);
Prog* copyp(Link*, Prog*);
Prog* appendp(Link*, Prog*);
@@ -600,6 +612,8 @@ extern char* anames5[];
extern char* anames6[];
extern char* anames8[];
+extern char* cnames5[];
+
extern LinkArch link386;
extern LinkArch linkamd64;
extern LinkArch linkamd64p32;
@@ -610,6 +624,7 @@ extern LinkArch linkarm;
#pragma varargck type "lD" Addr*
#pragma varargck type "P" Prog*
#pragma varargck type "R" int
+#pragma varargck type "^" int
// TODO(ality): remove this workaround.
// It's here because Pconv in liblink/list?.c references %L.
diff --git a/lib/time/update.bash b/lib/time/update.bash
index 8e1662afd..caa8450fa 100755
--- a/lib/time/update.bash
+++ b/lib/time/update.bash
@@ -7,8 +7,8 @@
# downloaded from the ICANN/IANA distribution.
# Versions to use.
-CODE=2014d
-DATA=2014d
+CODE=2014j
+DATA=2014j
set -e
rm -rf work
diff --git a/lib/time/zoneinfo.zip b/lib/time/zoneinfo.zip
index e0d3afe07..425d7c98f 100644
--- a/lib/time/zoneinfo.zip
+++ b/lib/time/zoneinfo.zip
Binary files differ
diff --git a/misc/IntelliJIDEA/Go.xml b/misc/IntelliJIDEA/Go.xml
deleted file mode 100644
index 51abdf412..000000000
--- a/misc/IntelliJIDEA/Go.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- 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.
-
-Copy this custom language definition & configuration file to
- * Mac : ~/Library/Preferences/IntelliJIdea10/filetypes/
- * Linux & Windows : ~/.IntelliJIdea10/config/filetypes/
--->
-
-<filetype binary="false" default_extension="" description="Go" name="Go">
- <highlighting>
- <options>
- <option name="LINE_COMMENT" value="//"/>
- <option name="COMMENT_START" value="/*"/>
- <option name="COMMENT_END" value="*/"/>
- <option name="HEX_PREFIX" value="0x"/>
- <option name="NUM_POSTFIXES" value=""/>
- <option name="HAS_BRACKETS" value="true"/>
- <option name="HAS_BRACES" value="true"/>
- <option name="HAS_PARENS" value="true"/>
- <option name="HAS_STRING_ESCAPES" value="true"/>
- </options>
- <keywords ignore_case="false">
- <keyword name="break"/>
- <keyword name="case"/>
- <keyword name="chan"/>
- <keyword name="const"/>
- <keyword name="continue"/>
- <keyword name="default"/>
- <keyword name="defer"/>
- <keyword name="else"/>
- <keyword name="fallthrough"/>
- <keyword name="for"/>
- <keyword name="func"/>
- <keyword name="go"/>
- <keyword name="goto"/>
- <keyword name="if"/>
- <keyword name="import"/>
- <keyword name="interface"/>
- <keyword name="map"/>
- <keyword name="package"/>
- <keyword name="range"/>
- <keyword name="return"/>
- <keyword name="select"/>
- <keyword name="struct"/>
- <keyword name="switch"/>
- <keyword name="type"/>
- <keyword name="var"/>
- </keywords>
- <keywords2>
- <keyword name="bool"/>
- <keyword name="byte"/>
- <keyword name="complex64"/>
- <keyword name="complex128"/>
- <keyword name="float32"/>
- <keyword name="float64"/>
- <keyword name="int"/>
- <keyword name="int8"/>
- <keyword name="int16"/>
- <keyword name="int32"/>
- <keyword name="int64"/>
- <keyword name="string"/>
- <keyword name="uint"/>
- <keyword name="uint8"/>
- <keyword name="uint16"/>
- <keyword name="uint32"/>
- <keyword name="uint64"/>
- <keyword name="uintptr"/>
- </keywords2>
- <keywords3>
- <keyword name="append"/>
- <keyword name="cap"/>
- <keyword name="close"/>
- <keyword name="complex"/>
- <keyword name="copy"/>
- <keyword name="delete"/>
- <keyword name="imag"/>
- <keyword name="len"/>
- <keyword name="make"/>
- <keyword name="new"/>
- <keyword name="panic"/>
- <keyword name="print"/>
- <keyword name="println"/>
- <keyword name="real"/>
- <keyword name="recover"/>
- </keywords3>
- <keywords4>
- <keyword name="false"/>
- <keyword name="iota"/>
- <keyword name="nil"/>
- <keyword name="true"/>
- </keywords4>
- </highlighting>
- <extensionMap>
- <mapping ext="go"/>
- </extensionMap>
-</filetype>
diff --git a/misc/android/README b/misc/android/README
new file mode 100644
index 000000000..5f24fafc7
--- /dev/null
+++ b/misc/android/README
@@ -0,0 +1,11 @@
+Android
+=======
+
+For details on developing Go for Android, see the documentation in the
+go.mobile subrepository:
+
+ https://code.google.com/p/go/source/browse/README?repo=mobile
+
+To run the standard library tests, see androidtest.bash. Run it as
+
+ CC_FOR_TARGET=.../ndk-gcc GOARCH=arm GOARM=7 ./androidtest.bash
diff --git a/misc/android/go_android_exec.go b/misc/android/go_android_exec.go
new file mode 100644
index 000000000..e32a805a8
--- /dev/null
+++ b/misc/android/go_android_exec.go
@@ -0,0 +1,96 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This program can be used as go_android_GOARCH_exec by the Go tool.
+// It executes binaries on an android device using adb.
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strconv"
+ "strings"
+)
+
+func run(args ...string) string {
+ buf := new(bytes.Buffer)
+ cmd := exec.Command("adb", args...)
+ cmd.Stdout = io.MultiWriter(os.Stdout, buf)
+ cmd.Stderr = os.Stderr
+ log.Printf("adb %s", strings.Join(args, " "))
+ err := cmd.Run()
+ if err != nil {
+ log.Fatalf("adb %s: %v", strings.Join(args, " "), err)
+ }
+ return buf.String()
+}
+
+func main() {
+ log.SetFlags(0)
+ log.SetPrefix("go_android_exec: ")
+
+ // Determine thepackage by examining the current working
+ // directory, which will look something like
+ // "$GOROOT/src/mime/multipart". We extract everything
+ // after the $GOROOT to run on the same relative directory
+ // on the target device.
+ //
+ // TODO(crawshaw): Pick useful subdir when we are not
+ // inside a GOROOT, e.g. we are in a GOPATH.
+ cwd, err := os.Getwd()
+ if err != nil {
+ log.Fatal(err)
+ }
+ subdir, err := filepath.Rel(runtime.GOROOT(), cwd)
+ if err != nil {
+ log.Fatal(err)
+ }
+ subdir = filepath.ToSlash(subdir)
+
+ // Binary names can conflict.
+ // E.g. template.test from the {html,text}/template packages.
+ binName := filepath.Base(os.Args[1])
+ deviceGoroot := "/data/local/tmp/goroot"
+ deviceBin := fmt.Sprintf("%s/%s-%d", deviceGoroot, binName, os.Getpid())
+
+ // The push of the binary happens in parallel with other tests.
+ // Unfortunately, a simultaneous call to adb shell hold open
+ // file descriptors, so it is necessary to push then move to
+ // avoid a "text file busy" error on execution.
+ // https://code.google.com/p/android/issues/detail?id=65857
+ run("push", os.Args[1], deviceBin+"-tmp")
+ run("shell", "cp '"+deviceBin+"-tmp' '"+deviceBin+"'")
+ run("shell", "rm '"+deviceBin+"-tmp'")
+
+ // The adb shell command will return an exit code of 0 regardless
+ // of the command run. E.g.
+ // $ adb shell false
+ // $ echo $?
+ // 0
+ // https://code.google.com/p/android/issues/detail?id=3254
+ // So we append the exitcode to the output and parse it from there.
+ const exitstr = "exitcode="
+ cmd := `export TMPDIR="/data/local/tmp"` +
+ `; export GOROOT="` + deviceGoroot + `"` +
+ `; cd "$GOROOT/` + subdir + `"` +
+ "; '" + deviceBin + "' " + strings.Join(os.Args[2:], " ") +
+ "; echo -n " + exitstr + "$?"
+ output := run("shell", cmd)
+ run("shell", "rm '"+deviceBin+"'") // cleanup
+ output = output[strings.LastIndex(output, "\n")+1:]
+ if !strings.HasPrefix(output, exitstr) {
+ log.Fatalf("no exit code: %q", output)
+ }
+ code, err := strconv.Atoi(output[len(exitstr):])
+ if err != nil {
+ log.Fatalf("bad exit code: %v", err)
+ }
+ os.Exit(code)
+}
diff --git a/misc/bash/go b/misc/bash/go
deleted file mode 100644
index 50f4f720b..000000000
--- a/misc/bash/go
+++ /dev/null
@@ -1,237 +0,0 @@
-# install in /etc/bash_completion.d/ or your personal directory
-
-complete -f -X '!*.8' 8l
-complete -f -X '!*.6' 6l
-complete -f -X '!*.5' 5l
-complete -f -X '!*.go' 8g 6g 5g gofmt gccgo
-
-_go_importpath()
-{
- echo "$(compgen -W "$(go list all) all std" -- "$1")"
-}
-
-_go()
-{
- # TODO: Only allow flags before other arguments. run already does
- # this.
-
- local cur=`_get_cword`
- local prev="${COMP_WORDS[COMP_CWORD-1]}"
-
- local cmd="${COMP_WORDS[1]}"
-
- local cmds="build clean env fix fmt get
- install list run test tool version vet"
- local addhelp="c gopath importpath packages testflag testfunc"
- local other="help"
-
- if [ "$COMP_CWORD" == 1 ]; then
- for opt in $cmds; do
- if [[ "$opt" == "$cmd" ]]; then
- COMPREPLY=("$opt")
- return
- fi
- done
- fi
-
- case "$cmd" in
- 'build')
- case "$prev" in
- '-o')
- _filedir
- ;;
- '-p')
- ;;
- *)
- if [[ "$cur" == -* ]]; then
- COMPREPLY=($(compgen -W "-a -n -o -p -v -x" -- "$cur"))
- else
- local found=0
- for ((i=0; i < ${#COMP_WORDS[@]}; i++)); do
- case "$i" in
- 0|1|"$COMP_CWORD")
- continue
- ;;
- esac
- local opt="${COMP_WORDS[i]}"
- if [[ "$opt" != -* ]]; then
- if [[ "$opt" == *.go && -f "$opt" ]]; then
- found=1
- break
- else
- found=2
- break
- fi
- fi
- done
- case "$found" in
- 0)
- _filedir go
- COMPREPLY+=(`_go_importpath "$cur"`)
- ;;
- 1)
- _filedir go
- ;;
- 2)
- COMPREPLY=(`_go_importpath "$cur"`)
- ;;
- esac
- fi
- ;;
- esac
- ;;
- 'clean')
- if [[ "$cur" == -* ]]; then
- COMPREPLY=($(compgen -W "-i -r -n -x" -- "$cur"))
- else
- COMPREPLY=(`_go_importpath "$cur"`)
- fi
- ;;
- 'fix')
- COMPREPLY=(`_go_importpath "$cur"`)
- ;;
- 'fmt')
- COMPREPLY=(`_go_importpath "$cur"`)
- ;;
- 'get')
- case "$prev" in
- '-p')
- ;;
- *)
- if [[ "$cur" == -* ]]; then
- COMPREPLY=($(compgen -W "-a -d -fix -n -p -u -v -x" -- "$cur"))
- else
- COMPREPLY=(`_go_importpath "$cur"`)
- fi
- ;;
- esac
- ;;
- 'install')
- case "$prev" in
- '-p')
- ;;
- *)
- if [[ "$cur" == -* ]]; then
- COMPREPLY=($(compgen -W "-a -n -p -v -x" -- "$cur"))
- else
- COMPREPLY=(`_go_importpath "$cur"`)
- fi
- ;;
- esac
- ;;
- 'list')
- case "$prev" in
- '-f')
- ;;
- *)
- if [[ "$cur" == -* ]]; then
- COMPREPLY=($(compgen -W "-e -f -json" -- "$cur"))
- else
- COMPREPLY=(`_go_importpath "$cur"`)
- fi
- ;;
- esac
- ;;
- 'run')
- if [[ "$cur" == -* && "$prev" != *.go ]]; then
- COMPREPLY=($(compgen -W "-a -n -x" -- "$cur"))
- else
- _filedir
- fi
- ;;
- 'test') # TODO: Support for testflags.
- case "$prev" in
- '-file')
- _filedir go
- ;;
- '-p')
- ;;
- *)
- if [[ "$cur" == -* ]]; then
- COMPREPLY=($(compgen -W "-c -file -i -p -x" -- "$cur"))
- else
- COMPREPLY=(`_go_importpath "$cur"`)
- fi
- ;;
- esac
- ;;
- 'tool')
- if [ "$COMP_CWORD" == 2 ]; then
- COMPREPLY=($(compgen -W "$(go tool)" -- "$cur"))
- else
- case "${COMP_WORDS[2]}" in
- [568]a) # TODO: Implement something.
- #_go_tool_568a
- ;;
- [568]c) # TODO: Implement something.
- #_go_tool_568c
- ;;
- [568]g) # TODO: Implement something.
- #_go_tool_568g
- ;;
- [568]l) # TODO: Implement something.
- #_go_tool_568l
- ;;
- 'api') # TODO: Implement something.
- #_go_tool_api
- ;;
- 'cgo') # TODO: Implement something.
- #_go_tool_cgo
- ;;
- 'cov') # TODO: Implement something.
- #_go_tool_cov
- ;;
- 'dist') # TODO: Implement something.
- #_go_tool_dist
- ;;
- 'fix') # TODO: Implement something.
- #_go_tool_fix
- ;;
- 'nm') # TODO: Implement something.
- #_go_tool_nm
- ;;
- 'pack') # TODO: Implement something.
- #_go_tool_pack
- ;;
- 'pprof') # TODO: Implement something.
- #_go_tool_pprof
- ;;
- 'vet') # TODO: Implement something.
- #_go_tool_vet
- ;;
- 'yacc') # TODO: Implement something.
- #_go_tool_yacc
- ;;
- esac
- if [[ "$cur" == -* ]]; then
- COMPREPLY=($(compgen -W "${COMPREPLY[*]} -h" -- "$cur"))
- fi
- fi
- ;;
- 'version')
- ;;
- 'vet')
- if [[ "$cur" == -* ]]; then
- :
- else
- COMPREPLY=(`_go_importpath "$cur"`)
- fi
- ;;
- 'help')
- if [ "$COMP_CWORD" == 2 ]; then
- COMPREPLY=($(compgen -W "$cmds $addhelp" -- "$cur"))
- fi
- ;;
- *)
- if [ "$COMP_CWORD" == 1 ]; then
- COMPREPLY=($(compgen -W "$cmds $other" -- "$cur"))
- else
- _filedir
- fi
- ;;
- esac
-}
-
-complete $filenames -F _go go
-
-# vim:ts=2 sw=2 et syn=sh
diff --git a/misc/bbedit/Go.plist b/misc/bbedit/Go.plist
deleted file mode 100644
index 1220d6efb..000000000
--- a/misc/bbedit/Go.plist
+++ /dev/null
@@ -1,104 +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.
-{
- BBEditDocumentType = "CodelessLanguageModule";
- BBLMColorsSyntax = YES;
- BBLMIsCaseSensitive = YES;
- BBLMKeywordList = (
- append,
- bool,
- break,
- byte,
- cap,
- case,
- chan,
- close,
- complex,
- complex128,
- complex64,
- const,
- continue,
- copy,
- default,
- defer,
- delete,
- else,
- error,
- fallthrough,
- false,
- float32,
- float64,
- for,
- func,
- go,
- goto,
- if,
- iota,
- imag,
- import,
- int,
- int16,
- int32,
- int64,
- int8,
- interface,
- len,
- make,
- map,
- new,
- nil,
- package,
- panic,
- print,
- println,
- range,
- real,
- recover,
- return,
- rune,
- select,
- string,
- struct,
- switch,
- true,
- type,
- uint,
- uint16,
- uint32,
- uint64,
- uint8,
- uintptr,
- var,
- );
- BBLMLanguageCode = go;
- "BBLMLanguageDisplayName" = "Go";
- BBLMScansFunctions = YES;
- BBLMSuffixMap = (
- {
- BBLMLanguageSuffix = ".go";
- },
- );
- "Language Features" = {
- "Close Block Comments" = "*/";
- "Close Parameter Lists" = ")";
- "Close Statement Blocks" = "}";
- "Close Strings 1" = "`";
- "Close Strings 2" = "\"";
- "End-of-line Ends Strings 1" = YES;
- "End-of-line Ends Strings 2" = YES;
- "Escape Char in Strings 1" = "\\";
- "Escape Char in Strings 2" = "\\";
- "Identifier and Keyword Characters" = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
- "Open Block Comments" = "/*";
- "Open Line Comments" = "//";
- "Open Parameter Lists" = "(";
- "Open Statement Blocks" = "{";
- "Open Strings 1" = "`";
- "Open Strings 2" = "\"";
- "Prefix for Functions" = "func";
- "Prefix for Procedures" = "func";
- "Terminator for Prototypes 1" = ";";
- "Terminator for Prototypes 2" = "";
- };
-}
diff --git a/misc/benchcmp b/misc/benchcmp
index 28a37392d..84d92eefd 100755
--- a/misc/benchcmp
+++ b/misc/benchcmp
@@ -1,5 +1,5 @@
#!/bin/bash
echo 'misc/benchcmp has moved:' >&2
-echo ' go get -u code.google.com/p/go.tools/cmd/benchcmp' >&2
+echo ' go get -u golang.org/x/tools/cmd/benchcmp' >&2
exit 2
diff --git a/misc/cgo/errors/issue7757.go b/misc/cgo/errors/issue7757.go
new file mode 100644
index 000000000..5eafd22e8
--- /dev/null
+++ b/misc/cgo/errors/issue7757.go
@@ -0,0 +1,14 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+/*
+void foo() {}
+*/
+import "C"
+
+func main() {
+ C.foo = C.foo // ERROR HERE
+}
diff --git a/misc/cgo/errors/issue8442.go b/misc/cgo/errors/issue8442.go
new file mode 100644
index 000000000..45daf8e59
--- /dev/null
+++ b/misc/cgo/errors/issue8442.go
@@ -0,0 +1,17 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Issue 8442. Cgo output unhelpful error messages for
+// invalid C preambles.
+
+/*
+void issue8442foo(UNDEF*); // ERROR HERE
+*/
+import "C"
+
+func main() {
+ C.issue8442foo(nil)
+}
diff --git a/misc/cgo/errors/test.bash b/misc/cgo/errors/test.bash
index f0f60c844..c96264389 100755
--- a/misc/cgo/errors/test.bash
+++ b/misc/cgo/errors/test.bash
@@ -27,6 +27,8 @@ check() {
check err1.go
check err2.go
check err3.go
+check issue7757.go
+check issue8442.go
rm -rf errs _obj
exit 0
diff --git a/misc/cgo/test/backdoor/backdoor.go b/misc/cgo/test/backdoor/backdoor.go
index 7398772bd..3a973494b 100644
--- a/misc/cgo/test/backdoor/backdoor.go
+++ b/misc/cgo/test/backdoor/backdoor.go
@@ -4,5 +4,4 @@
package backdoor
-func LockedOSThread() bool // in runtime.c
-func Issue7695(x1, x2, x3, x4, x5, x6, x7, x8 uintptr)
+func LockedOSThread() bool // in thunk.s
diff --git a/misc/cgo/test/backdoor/runtime.c b/misc/cgo/test/backdoor/runtime.c
deleted file mode 100644
index 7e6b44872..000000000
--- a/misc/cgo/test/backdoor/runtime.c
+++ /dev/null
@@ -1,32 +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.
-
-// Expose some runtime functions for testing.
-// Must be in a non-cgo-using package so that
-// the go command compiles this file with 6c, not gcc.
-
-// +build gc
-
-typedef char bool;
-
-bool runtime·lockedOSThread(void);
-
-static void
-FLUSH(void*)
-{
-}
-
-void
-·LockedOSThread(bool b)
-{
- b = runtime·lockedOSThread();
- FLUSH(&b);
-}
-
-// This is what a cgo-compiled stub declaration looks like.
-void
-·Issue7695(struct{void *y[8*sizeof(void*)];}p)
-{
- USED(p);
-}
diff --git a/misc/cgo/test/backdoor/thunk.s b/misc/cgo/test/backdoor/thunk.s
new file mode 100644
index 000000000..ae735c8a3
--- /dev/null
+++ b/misc/cgo/test/backdoor/thunk.s
@@ -0,0 +1,16 @@
+// 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.
+
+// Assembly to get into package runtime without using exported symbols.
+
+// +build amd64 amd64p32 arm 386
+
+#include "textflag.h"
+
+#ifdef GOARCH_arm
+#define JMP B
+#endif
+
+TEXT ·LockedOSThread(SB),NOSPLIT,$0-0
+ JMP runtime·lockedOSThread(SB)
diff --git a/misc/cgo/test/basic.go b/misc/cgo/test/basic.go
index 79cbf2b9c..019139d01 100644
--- a/misc/cgo/test/basic.go
+++ b/misc/cgo/test/basic.go
@@ -157,3 +157,8 @@ func testUnsignedInt(t *testing.T) {
t.Errorf("Incorrect unsigned int - got %x, want %x", a, b)
}
}
+
+// Static (build-time) test that syntax traversal visits all operands of s[i:j:k].
+func sliceOperands(array [2000]int) {
+ _ = array[C.KILO:C.KILO:C.KILO] // no type error
+}
diff --git a/misc/cgo/test/buildid_linux.go b/misc/cgo/test/buildid_linux.go
new file mode 100644
index 000000000..a3a86edfc
--- /dev/null
+++ b/misc/cgo/test/buildid_linux.go
@@ -0,0 +1,77 @@
+// 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 cgotest
+
+// Test that we have no more than one build ID. In the past we used
+// to generate a separate build ID for each package using cgo, and the
+// linker concatenated them all. We don't want that--we only want
+// one.
+
+import (
+ "bytes"
+ "debug/elf"
+ "os"
+ "testing"
+)
+
+func testBuildID(t *testing.T) {
+ f, err := elf.Open("/proc/self/exe")
+ if err != nil {
+ if os.IsNotExist(err) {
+ t.Skip("no /proc/self/exe")
+ }
+ t.Fatalf("opening /proc/self/exe: ", err)
+ }
+ defer f.Close()
+
+ c := 0
+ for i, s := range f.Sections {
+ if s.Type != elf.SHT_NOTE {
+ continue
+ }
+
+ d, err := s.Data()
+ if err != nil {
+ t.Logf("reading data of note section %d: %v", i, err)
+ continue
+ }
+
+ for len(d) > 0 {
+
+ // ELF standards differ as to the sizes in
+ // note sections. Both the GNU linker and
+ // gold always generate 32-bit sizes, so that
+ // is what we assume here.
+
+ if len(d) < 12 {
+ t.Logf("note section %d too short (%d < 12)", i, len(d))
+ continue
+ }
+
+ namesz := f.ByteOrder.Uint32(d)
+ descsz := f.ByteOrder.Uint32(d[4:])
+ typ := f.ByteOrder.Uint32(d[8:])
+
+ an := (namesz + 3) &^ 3
+ ad := (descsz + 3) &^ 3
+
+ if int(12+an+ad) > len(d) {
+ t.Logf("note section %d too short for header (%d < 12 + align(%d,4) + align(%d,4))", i, len(d), namesz, descsz)
+ continue
+ }
+
+ // 3 == NT_GNU_BUILD_ID
+ if typ == 3 && namesz == 4 && bytes.Equal(d[12:16], []byte("GNU\000")) {
+ c++
+ }
+
+ d = d[12+an+ad:]
+ }
+ }
+
+ if c > 1 {
+ t.Errorf("found %d build ID notes", c)
+ }
+}
diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go
index 82ed015bd..44167e6e9 100644
--- a/misc/cgo/test/callback.go
+++ b/misc/cgo/test/callback.go
@@ -9,16 +9,21 @@ void callback(void *f);
void callGoFoo(void);
void callGoStackCheck(void);
void callPanic(void);
+void callCgoAllocate(void);
+int callGoReturnVal(void);
+int returnAfterGrow(void);
+int returnAfterGrowFromGo(void);
*/
import "C"
import (
- "./backdoor"
"path"
"runtime"
"strings"
"testing"
"unsafe"
+
+ "./backdoor"
)
// nestedCall calls into C, back into Go, and finally to f.
@@ -152,11 +157,13 @@ func testCallbackCallers(t *testing.T) {
n := 0
name := []string{
"test.goCallback",
+ "runtime.call16",
"runtime.cgocallbackg1",
"runtime.cgocallbackg",
"runtime.cgocallback_gofunc",
- "runtime.asmcgocall",
- "runtime.cgocall",
+ "asmcgocall",
+ "runtime.asmcgocall_errno",
+ "runtime.cgocall_errno",
"test._Cfunc_callback",
"test.nestedCall",
"test.testCallbackCallers",
@@ -181,8 +188,12 @@ func testCallbackCallers(t *testing.T) {
if strings.HasPrefix(fname, "_") {
fname = path.Base(f.Name()[1:])
}
- if fname != name[i] {
- t.Errorf("expected function name %s, got %s", name[i], fname)
+ namei := ""
+ if i < len(name) {
+ namei = name[i]
+ }
+ if fname != namei {
+ t.Errorf("stk[%d] = %q, want %q", i, fname, namei)
}
}
}
@@ -200,6 +211,52 @@ func testPanicFromC(t *testing.T) {
C.callPanic()
}
+func testAllocateFromC(t *testing.T) {
+ C.callCgoAllocate() // crashes or exits on failure
+}
+
+// Test that C code can return a value if it calls a Go function that
+// causes a stack copy.
+func testReturnAfterGrow(t *testing.T) {
+ // Use a new goroutine so that we get a small stack.
+ c := make(chan int)
+ go func() {
+ c <- int(C.returnAfterGrow())
+ }()
+ if got, want := <-c, 123456; got != want {
+ t.Errorf("got %d want %d", got, want)
+ }
+}
+
+// Test that we can return a value from Go->C->Go if the Go code
+// causes a stack copy.
+func testReturnAfterGrowFromGo(t *testing.T) {
+ // Use a new goroutine so that we get a small stack.
+ c := make(chan int)
+ go func() {
+ c <- int(C.returnAfterGrowFromGo())
+ }()
+ if got, want := <-c, 129*128/2; got != want {
+ t.Errorf("got %d want %d", got, want)
+ }
+}
+
+//export goReturnVal
+func goReturnVal() (r C.int) {
+ // Force a stack copy.
+ var f func(int) int
+ f = func(i int) int {
+ var buf [256]byte
+ use(buf[:])
+ if i == 0 {
+ return 0
+ }
+ return i + f(i-1)
+ }
+ r = C.int(f(128))
+ return
+}
+
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 dcd4ddd4e..5bb642534 100644
--- a/misc/cgo/test/callback_c.c
+++ b/misc/cgo/test/callback_c.c
@@ -64,3 +64,19 @@ callGoStackCheck(void)
extern void goStackCheck(void);
goStackCheck();
}
+
+int
+returnAfterGrow(void)
+{
+ extern int goReturnVal(void);
+ goReturnVal();
+ return 123456;
+}
+
+int
+returnAfterGrowFromGo(void)
+{
+ extern int goReturnVal(void);
+ return goReturnVal();
+}
+
diff --git a/misc/cgo/test/callback_c_gc.c b/misc/cgo/test/callback_c_gc.c
index 8953b74a6..28a62c6db 100644
--- a/misc/cgo/test/callback_c_gc.c
+++ b/misc/cgo/test/callback_c_gc.c
@@ -5,11 +5,15 @@
// +build gc
#include "_cgo_export.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
/* Test calling panic from C. This is what SWIG does. */
extern void crosscall2(void (*fn)(void *, int), void *, int);
extern void _cgo_panic(void *, int);
+extern void _cgo_allocate(void *, int);
void
callPanic(void)
@@ -19,3 +23,58 @@ callPanic(void)
crosscall2(_cgo_panic, &a, sizeof a);
*(int*)1 = 1;
}
+
+/* Test calling cgo_allocate from C. This is what SWIG does. */
+
+typedef struct List List;
+struct List
+{
+ List *next;
+ int x;
+};
+
+void
+callCgoAllocate(void)
+{
+ int i;
+ struct { size_t n; void *ret; } a;
+ List *l, *head, **tail;
+
+ // Make sure this doesn't crash.
+ // And make sure it returns non-nil.
+ a.n = 0;
+ a.ret = 0;
+ crosscall2(_cgo_allocate, &a, sizeof a);
+ if(a.ret == 0) {
+ fprintf(stderr, "callCgoAllocate: alloc 0 returned nil\n");
+ exit(2);
+ }
+
+ head = 0;
+ tail = &head;
+ for(i=0; i<100; i++) {
+ a.n = sizeof *l;
+ crosscall2(_cgo_allocate, &a, sizeof a);
+ l = a.ret;
+ l->x = i;
+ l->next = 0;
+ *tail = l;
+ tail = &l->next;
+ }
+
+ gc();
+
+ l = head;
+ for(i=0; i<100; i++) {
+ if(l->x != i) {
+ fprintf(stderr, "callCgoAllocate: lost memory\n");
+ exit(2);
+ }
+ l = l->next;
+ }
+ if(l != 0) {
+ fprintf(stderr, "callCgoAllocate: lost memory\n");
+ exit(2);
+ }
+}
+
diff --git a/misc/cgo/test/callback_c_gccgo.c b/misc/cgo/test/callback_c_gccgo.c
index 0ea7296c6..d367b7b68 100644
--- a/misc/cgo/test/callback_c_gccgo.c
+++ b/misc/cgo/test/callback_c_gccgo.c
@@ -5,13 +5,66 @@
// +build gccgo
#include "_cgo_export.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
/* Test calling panic from C. This is what SWIG does. */
extern void _cgo_panic(const char *);
+extern void *_cgo_allocate(size_t);
void
callPanic(void)
{
_cgo_panic("panic from C");
}
+
+/* Test calling cgo_allocate from C. This is what SWIG does. */
+
+typedef struct List List;
+struct List
+{
+ List *next;
+ int x;
+};
+
+void
+callCgoAllocate(void)
+{
+ int i;
+ List *l, *head, **tail;
+
+ // Make sure this doesn't crash.
+ // And make sure it returns non-nil.
+ if(_cgo_allocate(0) == 0) {
+ fprintf(stderr, "callCgoAllocate: alloc 0 returned nil\n");
+ exit(2);
+ }
+
+ head = 0;
+ tail = &head;
+ for(i=0; i<100; i++) {
+ l = _cgo_allocate(sizeof *l);
+ l->x = i;
+ l->next = 0;
+ *tail = l;
+ tail = &l->next;
+ }
+
+ gc();
+
+ l = head;
+ for(i=0; i<100; i++) {
+ if(l->x != i) {
+ fprintf(stderr, "callCgoAllocate: lost memory\n");
+ exit(2);
+ }
+ l = l->next;
+ }
+ if(l != 0) {
+ fprintf(stderr, "callCgoAllocate: lost memory\n");
+ exit(2);
+ }
+}
+
diff --git a/misc/cgo/test/cgo_linux_test.go b/misc/cgo/test/cgo_linux_test.go
index 0a405c7a3..4fe0db1b2 100644
--- a/misc/cgo/test/cgo_linux_test.go
+++ b/misc/cgo/test/cgo_linux_test.go
@@ -6,5 +6,6 @@ package cgotest
import "testing"
-func TestSetgid(t *testing.T) { testSetgid(t) }
-func Test6997(t *testing.T) { test6997(t) }
+func TestSetgid(t *testing.T) { testSetgid(t) }
+func Test6997(t *testing.T) { test6997(t) }
+func TestBuildID(t *testing.T) { testBuildID(t) }
diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go
index e2e5a2bc1..fbdfac87a 100644
--- a/misc/cgo/test/cgo_test.go
+++ b/misc/cgo/test/cgo_test.go
@@ -10,49 +10,58 @@ import "testing"
// so that they can use cgo (import "C").
// These wrappers are here for gotest to find.
-func TestAlign(t *testing.T) { testAlign(t) }
-func TestConst(t *testing.T) { testConst(t) }
-func TestEnum(t *testing.T) { testEnum(t) }
-func TestAtol(t *testing.T) { testAtol(t) }
-func TestErrno(t *testing.T) { testErrno(t) }
-func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) }
-func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) }
-func TestCallback(t *testing.T) { testCallback(t) }
-func TestCallbackGC(t *testing.T) { testCallbackGC(t) }
-func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) }
-func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) }
-func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) }
-func TestPanicFromC(t *testing.T) { testPanicFromC(t) }
-func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
-func TestBlocking(t *testing.T) { testBlocking(t) }
-func Test1328(t *testing.T) { test1328(t) }
-func TestParallelSleep(t *testing.T) { testParallelSleep(t) }
-func TestSetEnv(t *testing.T) { testSetEnv(t) }
-func TestHelpers(t *testing.T) { testHelpers(t) }
-func TestLibgcc(t *testing.T) { testLibgcc(t) }
-func Test1635(t *testing.T) { test1635(t) }
-func TestPrintf(t *testing.T) { testPrintf(t) }
-func Test4029(t *testing.T) { test4029(t) }
-func TestBoolAlign(t *testing.T) { testBoolAlign(t) }
-func Test3729(t *testing.T) { test3729(t) }
-func Test3775(t *testing.T) { test3775(t) }
-func TestCthread(t *testing.T) { testCthread(t) }
-func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) }
-func Test5227(t *testing.T) { test5227(t) }
-func TestCflags(t *testing.T) { testCflags(t) }
-func Test5337(t *testing.T) { test5337(t) }
-func Test5548(t *testing.T) { test5548(t) }
-func Test5603(t *testing.T) { test5603(t) }
-func Test6833(t *testing.T) { test6833(t) }
-func Test3250(t *testing.T) { test3250(t) }
-func TestCallbackStack(t *testing.T) { testCallbackStack(t) }
-func TestFpVar(t *testing.T) { testFpVar(t) }
-func Test4339(t *testing.T) { test4339(t) }
-func Test6390(t *testing.T) { test6390(t) }
-func Test5986(t *testing.T) { test5986(t) }
-func Test7665(t *testing.T) { test7665(t) }
-func TestNaming(t *testing.T) { testNaming(t) }
-func Test7560(t *testing.T) { test7560(t) }
-func Test7978(t *testing.T) { test7978(t) }
+func TestAlign(t *testing.T) { testAlign(t) }
+func TestConst(t *testing.T) { testConst(t) }
+func TestEnum(t *testing.T) { testEnum(t) }
+func TestAtol(t *testing.T) { testAtol(t) }
+func TestErrno(t *testing.T) { testErrno(t) }
+func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) }
+func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) }
+func TestCallback(t *testing.T) { testCallback(t) }
+func TestCallbackGC(t *testing.T) { testCallbackGC(t) }
+func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) }
+func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) }
+func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) }
+func TestPanicFromC(t *testing.T) { testPanicFromC(t) }
+func TestAllocateFromC(t *testing.T) { testAllocateFromC(t) }
+func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
+func TestBlocking(t *testing.T) { testBlocking(t) }
+func Test1328(t *testing.T) { test1328(t) }
+func TestParallelSleep(t *testing.T) { testParallelSleep(t) }
+func TestSetEnv(t *testing.T) { testSetEnv(t) }
+func TestHelpers(t *testing.T) { testHelpers(t) }
+func TestLibgcc(t *testing.T) { testLibgcc(t) }
+func Test1635(t *testing.T) { test1635(t) }
+func TestPrintf(t *testing.T) { testPrintf(t) }
+func Test4029(t *testing.T) { test4029(t) }
+func TestBoolAlign(t *testing.T) { testBoolAlign(t) }
+func Test3729(t *testing.T) { test3729(t) }
+func Test3775(t *testing.T) { test3775(t) }
+func TestCthread(t *testing.T) { testCthread(t) }
+func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) }
+func Test5227(t *testing.T) { test5227(t) }
+func TestCflags(t *testing.T) { testCflags(t) }
+func Test5337(t *testing.T) { test5337(t) }
+func Test5548(t *testing.T) { test5548(t) }
+func Test5603(t *testing.T) { test5603(t) }
+func Test6833(t *testing.T) { test6833(t) }
+func Test3250(t *testing.T) { test3250(t) }
+func TestCallbackStack(t *testing.T) { testCallbackStack(t) }
+func TestFpVar(t *testing.T) { testFpVar(t) }
+func Test4339(t *testing.T) { test4339(t) }
+func Test6390(t *testing.T) { test6390(t) }
+func Test5986(t *testing.T) { test5986(t) }
+func Test7665(t *testing.T) { test7665(t) }
+func TestNaming(t *testing.T) { testNaming(t) }
+func Test7560(t *testing.T) { test7560(t) }
+func Test5242(t *testing.T) { test5242(t) }
+func Test8092(t *testing.T) { test8092(t) }
+func Test7978(t *testing.T) { test7978(t) }
+func Test8694(t *testing.T) { test8694(t) }
+func Test8517(t *testing.T) { test8517(t) }
+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 BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/misc/cgo/test/exports.go b/misc/cgo/test/exports.go
index f96c60b00..4fe1703a6 100644
--- a/misc/cgo/test/exports.go
+++ b/misc/cgo/test/exports.go
@@ -5,8 +5,14 @@
package cgotest
import "C"
+import "runtime"
//export ReturnIntLong
func ReturnIntLong() (int, C.long) {
return 1, 2
}
+
+//export gc
+func gc() {
+ runtime.GC()
+}
diff --git a/misc/cgo/test/issue5242.go b/misc/cgo/test/issue5242.go
new file mode 100644
index 000000000..fe0a6321c
--- /dev/null
+++ b/misc/cgo/test/issue5242.go
@@ -0,0 +1,31 @@
+// 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.
+
+// Issue 5242. Cgo incorrectly computed the alignment of structs
+// with no Go accessible fields as 0, and then panicked on
+// modulo-by-zero computations.
+
+package cgotest
+
+/*
+typedef struct {
+} foo;
+
+typedef struct {
+ int x : 1;
+} bar;
+
+int issue5242(foo f, bar b) {
+ return 5242;
+}
+*/
+import "C"
+
+import "testing"
+
+func test5242(t *testing.T) {
+ if got := C.issue5242(C.foo{}, C.bar{}); got != 5242 {
+ t.Errorf("got %v", got)
+ }
+}
diff --git a/misc/cgo/test/issue5548.go b/misc/cgo/test/issue5548.go
index b41f46562..c879f2ae9 100644
--- a/misc/cgo/test/issue5548.go
+++ b/misc/cgo/test/issue5548.go
@@ -14,13 +14,14 @@ import "C"
//export issue5548FromC
func issue5548FromC(s string, i int) int {
if len(s) == 4 && s == "test" && i == 42 {
- return 1
+ return 12345
}
- return 0
+ println("got", len(s), i)
+ return 9876
}
func test5548(t *testing.T) {
- if C.issue5548_in_c() == 0 {
- t.Fail()
+ if x := C.issue5548_in_c(); x != 12345 {
+ t.Errorf("issue5548_in_c = %d, want %d", x, 12345)
}
}
diff --git a/misc/cgo/test/issue6997_linux.go b/misc/cgo/test/issue6997_linux.go
index 871bd517a..5455f0c53 100644
--- a/misc/cgo/test/issue6997_linux.go
+++ b/misc/cgo/test/issue6997_linux.go
@@ -34,7 +34,7 @@ func test6997(t *testing.T) {
if r == 0 {
t.Error("pthread finished but wasn't cancelled??")
}
- case <-time.After(5 * time.Second):
+ case <-time.After(30 * time.Second):
t.Error("hung in pthread_cancel/pthread_join")
}
}
diff --git a/misc/cgo/test/issue7695_test.go b/misc/cgo/test/issue7695_test.go
deleted file mode 100644
index 4bd6f8e73..000000000
--- a/misc/cgo/test/issue7695_test.go
+++ /dev/null
@@ -1,27 +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.
-
-// Demo of deferred C function with untrue prototype
-// breaking stack copying. See golang.org/issue/7695.
-
-package cgotest
-
-import (
- "testing"
-
- "./backdoor"
-)
-
-func TestIssue7695(t *testing.T) {
- defer backdoor.Issue7695(1, 0, 2, 0, 0, 3, 0, 4)
- recurse(100)
-}
-
-func recurse(n int) {
- var x [128]int
- n += x[0]
- if n > 0 {
- recurse(n - 1)
- }
-}
diff --git a/misc/cgo/test/issue7978.go b/misc/cgo/test/issue7978.go
index 432e006eb..5feed07b9 100644
--- a/misc/cgo/test/issue7978.go
+++ b/misc/cgo/test/issue7978.go
@@ -83,21 +83,21 @@ func issue7978go() {
func test7978(t *testing.T) {
if os.Getenv("GOTRACEBACK") != "2" {
- t.Fatal("GOTRACEBACK must be 2")
+ t.Fatalf("GOTRACEBACK must be 2")
}
issue7978sync = 0
go issue7978go()
// test in c code, before callback
issue7978wait(0, 1)
- issue7978check(t, "runtime.cgocall(", "", 1)
+ issue7978check(t, "runtime.cgocall_errno(", "", 1)
// test in go code, during callback
issue7978wait(2, 3)
- issue7978check(t, "test.issue7978cb(", "test.issue7978go", 4)
+ 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, "runtime.cgocall_errno(", "runtime.cgocallback", 1)
// test in go code, after return from cgo
issue7978wait(6, 7)
- issue7978check(t, "test.issue7978go(", "", 4)
+ issue7978check(t, "test.issue7978go(", "", 3)
atomic.StoreUint32(&issue7978sync, 8)
}
diff --git a/misc/cgo/test/issue8092.go b/misc/cgo/test/issue8092.go
new file mode 100644
index 000000000..8a14ce6d7
--- /dev/null
+++ b/misc/cgo/test/issue8092.go
@@ -0,0 +1,36 @@
+// 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.
+
+// Issue 8092. Test that linker defined symbols (e.g., text, data) don't
+// conflict with C symbols.
+
+package cgotest
+
+/*
+char text[] = "text";
+char data[] = "data";
+char *ctext(void) { return text; }
+char *cdata(void) { return data; }
+*/
+import "C"
+
+import "testing"
+
+func test8092(t *testing.T) {
+ tests := []struct {
+ s string
+ a, b *C.char
+ }{
+ {"text", &C.text[0], C.ctext()},
+ {"data", &C.data[0], C.cdata()},
+ }
+ for _, test := range tests {
+ if test.a != test.b {
+ t.Errorf("%s: pointer mismatch: %v != %v", test.s, test.a, test.b)
+ }
+ if got := C.GoString(test.a); got != test.s {
+ t.Errorf("%s: points at %#v, want %#v", test.s, got, test.s)
+ }
+ }
+}
diff --git a/misc/cgo/test/issue8428.go b/misc/cgo/test/issue8428.go
new file mode 100644
index 000000000..a3dc5755c
--- /dev/null
+++ b/misc/cgo/test/issue8428.go
@@ -0,0 +1,52 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test fails on older versions of OS X because they use older buggy
+// versions of Clang that emit ambiguous DWARF info. See issue 8611.
+// +build !darwin
+
+package cgotest
+
+// Issue 8428. Cgo inconsistently translated zero size arrays.
+
+/*
+struct issue8428one {
+ char b;
+ char rest[];
+};
+
+struct issue8428two {
+ void *p;
+ char b;
+ char rest[0];
+};
+
+struct issue8428three {
+ char w[1][2][3][0];
+ char x[2][3][0][1];
+ char y[3][0][1][2];
+ char z[0][1][2][3];
+};
+*/
+import "C"
+
+import "unsafe"
+
+var _ = C.struct_issue8428one{
+ b: C.char(0),
+ rest: [0]C.char{},
+}
+
+var _ = C.struct_issue8428two{
+ p: unsafe.Pointer(nil),
+ b: C.char(0),
+ rest: [0]C.char{},
+}
+
+var _ = C.struct_issue8428three{
+ w: [1][2][3][0]C.char{},
+ x: [2][3][0][1]C.char{},
+ y: [3][0][1][2]C.char{},
+ z: [0][1][2][3]C.char{},
+}
diff --git a/misc/cgo/test/issue8517.go b/misc/cgo/test/issue8517.go
new file mode 100644
index 000000000..4e431df92
--- /dev/null
+++ b/misc/cgo/test/issue8517.go
@@ -0,0 +1,13 @@
+// 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 !windows
+
+package cgotest
+
+import "testing"
+
+func test8517(t *testing.T) {
+ t.Skip("skipping windows only test")
+}
diff --git a/misc/cgo/test/issue8517_windows.c b/misc/cgo/test/issue8517_windows.c
new file mode 100644
index 000000000..a0b94c126
--- /dev/null
+++ b/misc/cgo/test/issue8517_windows.c
@@ -0,0 +1,24 @@
+// 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 "windows.h"
+
+extern void testHandleLeaksCallback();
+
+DWORD WINAPI testHandleLeaksFunc(LPVOID lpThreadParameter)
+{
+ int i;
+ for(i = 0; i < 100; i++) {
+ testHandleLeaksCallback();
+ }
+ return 0;
+}
+
+void testHandleLeaks()
+{
+ HANDLE h;
+ h = CreateThread(NULL, 0, &testHandleLeaksFunc, 0, 0, NULL);
+ WaitForSingleObject(h, INFINITE);
+ CloseHandle(h);
+}
diff --git a/misc/cgo/test/issue8517_windows.go b/misc/cgo/test/issue8517_windows.go
new file mode 100644
index 000000000..3782631e9
--- /dev/null
+++ b/misc/cgo/test/issue8517_windows.go
@@ -0,0 +1,45 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cgotest
+
+//void testHandleLeaks();
+import "C"
+
+import (
+ "syscall"
+ "testing"
+ "unsafe"
+)
+
+var issue8517counter int
+
+var (
+ kernel32 = syscall.MustLoadDLL("kernel32.dll")
+ getProcessHandleCount = kernel32.MustFindProc("GetProcessHandleCount")
+)
+
+func processHandleCount(t *testing.T) int {
+ const current_process = ^uintptr(0)
+ var c uint32
+ r, _, err := getProcessHandleCount.Call(current_process, uintptr(unsafe.Pointer(&c)))
+ if r == 0 {
+ t.Fatal(err)
+ }
+ return int(c)
+}
+
+func test8517(t *testing.T) {
+ c1 := processHandleCount(t)
+ C.testHandleLeaks()
+ c2 := processHandleCount(t)
+ if c1+issue8517counter <= c2 {
+ t.Fatalf("too many handles leaked: issue8517counter=%v c1=%v c2=%v", issue8517counter, c1, c2)
+ }
+}
+
+//export testHandleLeaksCallback
+func testHandleLeaksCallback() {
+ issue8517counter++
+}
diff --git a/misc/cgo/test/issue8694.go b/misc/cgo/test/issue8694.go
new file mode 100644
index 000000000..1876f782d
--- /dev/null
+++ b/misc/cgo/test/issue8694.go
@@ -0,0 +1,38 @@
+// 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 cgotest
+
+/*
+#include <complex.h>
+
+complex float complexFloatSquared(complex float a) { return a*a; }
+complex double complexDoubleSquared(complex double a) { return a*a; }
+*/
+import "C"
+
+import (
+ "runtime"
+ "testing"
+)
+
+func test8694(t *testing.T) {
+ if runtime.GOARCH == "arm" {
+ 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)
+ 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)
+ y2 := y * y
+ cy2 := C.complexDoubleSquared(y)
+ if cy2 != y2 {
+ t.Errorf("C.complexDoubleSquared(%v) = %v, want %v", y, cy2, y2)
+ }
+}
diff --git a/misc/cgo/test/issue8811.c b/misc/cgo/test/issue8811.c
new file mode 100644
index 000000000..584bb3934
--- /dev/null
+++ b/misc/cgo/test/issue8811.c
@@ -0,0 +1,8 @@
+// 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.
+
+int issue8811Initialized = 0;
+
+void issue8811Init() {
+}
diff --git a/misc/cgo/test/issue8811.go b/misc/cgo/test/issue8811.go
new file mode 100644
index 000000000..2e217d935
--- /dev/null
+++ b/misc/cgo/test/issue8811.go
@@ -0,0 +1,22 @@
+// 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 cgotest
+
+/*
+extern int issue8811Initialized;
+extern void issue8811Init();
+
+void issue8811Execute() {
+ if(!issue8811Initialized)
+ issue8811Init();
+}
+*/
+import "C"
+
+import "testing"
+
+func test8811(t *testing.T) {
+ C.issue8811Execute()
+}
diff --git a/misc/cgo/test/issue8828.go b/misc/cgo/test/issue8828.go
new file mode 100644
index 000000000..304797c92
--- /dev/null
+++ b/misc/cgo/test/issue8828.go
@@ -0,0 +1,16 @@
+// compile
+
+// 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.
+
+// Issue 8828: compiling a file with -compiler=gccgo fails if a .c file
+// has the same name as compiled directory.
+
+package cgotest
+
+import "./issue8828"
+
+func p() {
+ issue8828.Bar()
+}
diff --git a/misc/cgo/test/issue8828/issue8828.c b/misc/cgo/test/issue8828/issue8828.c
new file mode 100644
index 000000000..2950f87cf
--- /dev/null
+++ b/misc/cgo/test/issue8828/issue8828.c
@@ -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.
+
+void foo()
+{
+}
diff --git a/misc/cgo/test/issue8828/trivial.go b/misc/cgo/test/issue8828/trivial.go
new file mode 100644
index 000000000..e7b9a4e57
--- /dev/null
+++ b/misc/cgo/test/issue8828/trivial.go
@@ -0,0 +1,8 @@
+package issue8828
+
+//void foo();
+import "C"
+
+func Bar() {
+ C.foo()
+}
diff --git a/misc/cgo/test/issue9026.go b/misc/cgo/test/issue9026.go
new file mode 100644
index 000000000..8848d0e81
--- /dev/null
+++ b/misc/cgo/test/issue9026.go
@@ -0,0 +1,9 @@
+package cgotest
+
+import (
+ "testing"
+
+ "./issue9026"
+)
+
+func test9026(t *testing.T) { issue9026.Test(t) }
diff --git a/misc/cgo/test/issue9026/issue9026.go b/misc/cgo/test/issue9026/issue9026.go
new file mode 100644
index 000000000..0af86e64d
--- /dev/null
+++ b/misc/cgo/test/issue9026/issue9026.go
@@ -0,0 +1,36 @@
+package issue9026
+
+// This file appears in its own package since the assertion tests the
+// per-package counter used to create fresh identifiers.
+
+/*
+typedef struct {} git_merge_file_input;
+
+typedef struct {} git_merge_file_options;
+
+void git_merge_file(
+ git_merge_file_input *in,
+ git_merge_file_options *opts) {}
+*/
+import "C"
+import (
+ "fmt"
+ "testing"
+)
+
+func Test(t *testing.T) {
+ var in C.git_merge_file_input
+ var opts *C.git_merge_file_options
+ C.git_merge_file(&in, opts)
+
+ // Test that the generated type names are deterministic.
+ // (Previously this would fail about 10% of the time.)
+ //
+ // Brittle: the assertion may fail spuriously when the algorithm
+ // changes, but should remain stable otherwise.
+ got := fmt.Sprintf("%T %T", in, opts)
+ want := "issue9026._Ctype_struct___0 *issue9026._Ctype_struct___1"
+ if got != want {
+ t.Errorf("Non-deterministic type names: got %s, want %s", got, want)
+ }
+}
diff --git a/misc/cgo/testcdefs/cdefstest.c b/misc/cgo/testcdefs/cdefstest.c
index 10cdd66b6..ce670e729 100644
--- a/misc/cgo/testcdefs/cdefstest.c
+++ b/misc/cgo/testcdefs/cdefstest.c
@@ -6,3 +6,4 @@
#include "cdefstest.h"
struct CdefsTest test;
+struct PackedTest packed;
diff --git a/misc/cgo/testcdefs/cdefstest.go b/misc/cgo/testcdefs/cdefstest.go
index e6305b77d..5e613c79e 100644
--- a/misc/cgo/testcdefs/cdefstest.go
+++ b/misc/cgo/testcdefs/cdefstest.go
@@ -35,7 +35,26 @@ struct cdefsTest {
// Correct: -> Array [20][20]**int8 -> int8 **array[20][20]
char **array5[20][20];
};
+
+// Test that packed structures can be translated to C correctly too.
+// See issue 8477.
+
+struct packedTest {
+ char first;
+ int second;
+ long long third;
+} __attribute__((packed));
+
+// Test that conflicting type definitions don't cause problems with cgo.
+// See issue 8477.
+
+typedef struct timespec {
+ double bogus;
+} pid_t;
+
*/
import "C"
type CdefsTest C.struct_cdefsTest
+
+//type PackedTest C.struct_packedTest
diff --git a/misc/cgo/testcdefs/main.c b/misc/cgo/testcdefs/main.c
index 2d3ee4dbe..594a43167 100644
--- a/misc/cgo/testcdefs/main.c
+++ b/misc/cgo/testcdefs/main.c
@@ -17,11 +17,25 @@ struct CdefsOrig {
int8 **array5[20][20];
};
+// Packed structs are no longer supported for -cdefs.
+/*
+typedef struct PackedOrig PackedOrig;
+#pragma pack on
+struct PackedOrig {
+ int8 first;
+ int32 second;
+ int64 third;
+};
+#pragma pack off
+*/
+
void
main·test(int32 ret)
{
CdefsOrig o;
CdefsTest t;
+ // PackedOrig po;
+ // PackedTest pt;
ret = 0;
if(sizeof(t.array1) != sizeof(o.array1) || offsetof(CdefsTest, array1[0]) != offsetof(CdefsOrig, array1[0])) {
@@ -44,5 +58,19 @@ main·test(int32 ret)
runtime·printf("array5: size, offset = %d, %d, want %d, %d\n", sizeof(t.array5), offsetof(CdefsTest, array5[0][0]), sizeof(o.array5), offsetof(CdefsOrig, array5[0][0]));
ret = 1;
}
+/*
+ if(sizeof(pt.first) != sizeof(po.first) || offsetof(PackedTest, first) != offsetof(PackedOrig, first)) {
+ runtime·printf("first: size, offset = %d, %d, want %d, %d\n", sizeof(pt.first), offsetof(PackedTest, first), sizeof(po.first), offsetof(PackedOrig, first));
+ ret = 1;
+ }
+ if(sizeof(pt.second) != sizeof(po.second) || offsetof(PackedTest, second) != offsetof(PackedOrig, second)) {
+ runtime·printf("second: size, offset = %d, %d, want %d, %d\n", sizeof(pt.second), offsetof(PackedTest, second), sizeof(po.second), offsetof(PackedOrig, second));
+ ret = 1;
+ }
+ if(sizeof(pt.third) != sizeof(po.third) || offsetof(PackedTest, third) != offsetof(PackedOrig, third)) {
+ runtime·printf("third: size, offset = %d, %d, want %d, %d\n", sizeof(pt.third), offsetof(PackedTest, third), sizeof(po.third), offsetof(PackedOrig, third));
+ ret = 1;
+ }
+*/
FLUSH(&ret); // flush return value
}
diff --git a/misc/cgo/testgodefs/anonunion.go b/misc/cgo/testgodefs/anonunion.go
new file mode 100644
index 000000000..7bc736b9d
--- /dev/null
+++ b/misc/cgo/testgodefs/anonunion.go
@@ -0,0 +1,26 @@
+// 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
+
+// This file tests that when cgo -godefs sees a struct with a field
+// that is an anonymous union, the first field in the union is
+// promoted to become a field of the struct. See issue 6677 for
+// background.
+
+/*
+typedef struct {
+ union {
+ long l;
+ int c;
+ };
+} t;
+*/
+import "C"
+
+// Input for cgo -godefs.
+
+type T C.t
diff --git a/misc/cgo/testgodefs/issue8478.go b/misc/cgo/testgodefs/issue8478.go
new file mode 100644
index 000000000..92258fde7
--- /dev/null
+++ b/misc/cgo/testgodefs/issue8478.go
@@ -0,0 +1,20 @@
+// 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
+
+// Issue 8478. Test that void* is consistently mapped to *byte.
+
+/*
+typedef struct {
+ void *p;
+ void **q;
+ void ***r;
+} s;
+*/
+import "C"
+
+type Issue8478 C.s
diff --git a/misc/cgo/testgodefs/main.go b/misc/cgo/testgodefs/main.go
new file mode 100644
index 000000000..7faccf265
--- /dev/null
+++ b/misc/cgo/testgodefs/main.go
@@ -0,0 +1,15 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Test that the struct field in anonunion.go was promoted.
+var v1 T
+var v2 = v1.L
+
+// Test that P, Q, and R all point to byte.
+var v3 = Issue8478{P: (*byte)(nil), Q: (**byte)(nil), R: (***byte)(nil)}
+
+func main() {
+}
diff --git a/misc/cgo/testgodefs/test.bash b/misc/cgo/testgodefs/test.bash
new file mode 100755
index 000000000..5281b1056
--- /dev/null
+++ b/misc/cgo/testgodefs/test.bash
@@ -0,0 +1,20 @@
+# 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.
+
+# We are testing cgo -godefs, which translates Go files that use
+# import "C" into Go files with Go definitions of types defined in the
+# import "C" block. Add more tests here.
+FILE_PREFIXES="anonunion issue8478"
+
+RM=
+for FP in $FILE_PREFIXES
+do
+ go tool cgo -godefs ${FP}.go > ${FP}_defs.go
+ RM="${RM} ${FP}_defs.go"
+done
+
+go build . && ./testgodefs
+EXIT=$?
+rm -rf _obj testgodefs ${RM}
+exit $EXIT
diff --git a/misc/editors b/misc/editors
new file mode 100644
index 000000000..850ec3401
--- /dev/null
+++ b/misc/editors
@@ -0,0 +1,5 @@
+For information about plugins and other support for Go in editors and shells,
+see this page on the Go Wiki:
+
+https://code.google.com/p/go-wiki/wiki/IDEsAndTextEditorPlugins
+
diff --git a/misc/emacs/go-mode-load.el b/misc/emacs/go-mode-load.el
deleted file mode 100644
index 3fc35c116..000000000
--- a/misc/emacs/go-mode-load.el
+++ /dev/null
@@ -1,96 +0,0 @@
-;;; go-mode-load.el --- automatically extracted autoloads
-;;; Commentary:
-
-;; To install go-mode, add the following lines to your .emacs file:
-;; (add-to-list 'load-path "PATH CONTAINING go-mode-load.el" t)
-;; (require 'go-mode-load)
-;;
-;; After this, go-mode will be used for files ending in '.go'.
-;;
-;; To compile go-mode from the command line, run the following
-;; emacs -batch -f batch-byte-compile go-mode.el
-;;
-;; See go-mode.el for documentation.
-;;
-;; To update this file, evaluate the following form
-;; (let ((generated-autoload-file buffer-file-name)) (update-file-autoloads "go-mode.el"))
-
-;;; Code:
-
-
-;;;### (autoloads (go-download-play godoc gofmt-before-save go-mode)
-;;;;;; "go-mode" "go-mode.el" (20767 50749))
-;;; Generated autoloads from go-mode.el
-
-(autoload 'go-mode "go-mode" "\
-Major mode for editing Go source text.
-
-This mode provides (not just) basic editing capabilities for
-working with Go code. It offers almost complete syntax
-highlighting, indentation that is almost identical to gofmt,
-proper parsing of the buffer content to allow features such as
-navigation by function, manipulation of comments or detection of
-strings.
-
-Additionally to these core features, it offers various features to
-help with writing Go code. You can directly run buffer content
-through gofmt, read godoc documentation from within Emacs, modify
-and clean up the list of package imports or interact with the
-Playground (uploading and downloading pastes).
-
-The following extra functions are defined:
-
-- `gofmt'
-- `godoc'
-- `go-import-add'
-- `go-remove-unused-imports'
-- `go-goto-imports'
-- `go-play-buffer' and `go-play-region'
-- `go-download-play'
-
-If you want to automatically run `gofmt' before saving a file,
-add the following hook to your emacs configuration:
-
-\(add-hook 'before-save-hook 'gofmt-before-save)
-
-If you're looking for even more integration with Go, namely
-on-the-fly syntax checking, auto-completion and snippets, it is
-recommended to look at goflymake
-\(https://github.com/dougm/goflymake), gocode
-\(https://github.com/nsf/gocode) and yasnippet-go
-\(https://github.com/dominikh/yasnippet-go)
-
-\(fn)" t nil)
-
-(add-to-list 'auto-mode-alist (cons "\\.go\\'" 'go-mode))
-
-(autoload 'gofmt-before-save "go-mode" "\
-Add this to .emacs to run gofmt on the current buffer when saving:
- (add-hook 'before-save-hook 'gofmt-before-save).
-
-Note that this will cause go-mode to get loaded the first time
-you save any file, kind of defeating the point of autoloading.
-
-\(fn)" t nil)
-
-(autoload 'godoc "go-mode" "\
-Show go documentation for a query, much like M-x man.
-
-\(fn QUERY)" t nil)
-
-(autoload 'go-download-play "go-mode" "\
-Downloads a paste from the playground and inserts it in a Go
-buffer. Tries to look for a URL at point.
-
-\(fn URL)" t nil)
-
-;;;***
-
-(provide 'go-mode-load)
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; coding: utf-8
-;; End:
-;;; go-mode-load.el ends here
diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el
deleted file mode 100644
index 6333ff966..000000000
--- a/misc/emacs/go-mode.el
+++ /dev/null
@@ -1,1196 +0,0 @@
-;;; go-mode.el --- Major mode for the Go programming language
-
-;; 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.
-
-(require 'cl)
-(require 'etags)
-(require 'ffap)
-(require 'find-file)
-(require 'ring)
-(require 'url)
-
-;; XEmacs compatibility guidelines
-;; - Minimum required version of XEmacs: 21.5.32
-;; - Feature that cannot be backported: POSIX character classes in
-;; regular expressions
-;; - Functions that could be backported but won't because 21.5.32
-;; covers them: plenty.
-;; - Features that are still partly broken:
-;; - godef will not work correctly if multibyte characters are
-;; being used
-;; - Fontification will not handle unicode correctly
-;;
-;; - Do not use \_< and \_> regexp delimiters directly; use
-;; go--regexp-enclose-in-symbol
-;;
-;; - The character `_` must not be a symbol constituent but a
-;; character constituent
-;;
-;; - Do not use process-lines
-;;
-;; - Use go--old-completion-list-style when using a plain list as the
-;; collection for completing-read
-;;
-;; - Use go--kill-whole-line instead of kill-whole-line (called
-;; kill-entire-line in XEmacs)
-;;
-;; - Use go--position-bytes instead of position-bytes
-(defmacro go--xemacs-p ()
- `(featurep 'xemacs))
-
-(defalias 'go--kill-whole-line
- (if (fboundp 'kill-whole-line)
- #'kill-whole-line
- #'kill-entire-line))
-
-;; Delete the current line without putting it in the kill-ring.
-(defun go--delete-whole-line (&optional arg)
- ;; Emacs uses both kill-region and kill-new, Xemacs only uses
- ;; kill-region. In both cases we turn them into operations that do
- ;; not modify the kill ring. This solution does depend on the
- ;; implementation of kill-line, but it's the only viable solution
- ;; that does not require to write kill-line from scratch.
- (flet ((kill-region (beg end)
- (delete-region beg end))
- (kill-new (s) ()))
- (go--kill-whole-line arg)))
-
-;; declare-function is an empty macro that only byte-compile cares
-;; about. Wrap in always false if to satisfy Emacsen without that
-;; macro.
-(if nil
- (declare-function go--position-bytes "go-mode" (point)))
-
-;; XEmacs unfortunately does not offer position-bytes. We can fall
-;; back to just using (point), but it will be incorrect as soon as
-;; multibyte characters are being used.
-(if (fboundp 'position-bytes)
- (defalias 'go--position-bytes #'position-bytes)
- (defun go--position-bytes (point) point))
-
-(defun go--old-completion-list-style (list)
- (mapcar (lambda (x) (cons x nil)) list))
-
-;; GNU Emacs 24 has prog-mode, older GNU Emacs and XEmacs do not, so
-;; copy its definition for those.
-(if (not (fboundp 'prog-mode))
- (define-derived-mode prog-mode fundamental-mode "Prog"
- "Major mode for editing source code."
- (set (make-local-variable 'require-final-newline) mode-require-final-newline)
- (set (make-local-variable 'parse-sexp-ignore-comments) t)
- (setq bidi-paragraph-direction 'left-to-right)))
-
-(defun go--regexp-enclose-in-symbol (s)
- ;; XEmacs does not support \_<, GNU Emacs does. In GNU Emacs we make
- ;; extensive use of \_< to support unicode in identifiers. Until we
- ;; come up with a better solution for XEmacs, this solution will
- ;; break fontification in XEmacs for identifiers such as "typeµ".
- ;; XEmacs will consider "type" a keyword, GNU Emacs won't.
-
- (if (go--xemacs-p)
- (concat "\\<" s "\\>")
- (concat "\\_<" s "\\_>")))
-
-;; Move up one level of parentheses.
-(defun go-goto-opening-parenthesis (&optional legacy-unused)
- ;; The old implementation of go-goto-opening-parenthesis had an
- ;; optional argument to speed up the function. It didn't change the
- ;; function's outcome.
-
- ;; Silently fail if there's no matching opening parenthesis.
- (condition-case nil
- (backward-up-list)
- (scan-error nil)))
-
-
-(defconst go-dangling-operators-regexp "[^-]-\\|[^+]\\+\\|[/*&><.=|^]")
-(defconst go-identifier-regexp "[[:word:][:multibyte:]]+")
-(defconst go-label-regexp go-identifier-regexp)
-(defconst go-type-regexp "[[:word:][:multibyte:]*]+")
-(defconst go-func-regexp (concat (go--regexp-enclose-in-symbol "func") "\\s *\\(" go-identifier-regexp "\\)"))
-(defconst go-func-meth-regexp (concat
- (go--regexp-enclose-in-symbol "func") "\\s *\\(?:(\\s *"
- "\\(" go-identifier-regexp "\\s +\\)?" go-type-regexp
- "\\s *)\\s *\\)?\\("
- go-identifier-regexp
- "\\)("))
-(defconst go-builtins
- '("append" "cap" "close" "complex" "copy"
- "delete" "imag" "len" "make" "new"
- "panic" "print" "println" "real" "recover")
- "All built-in functions in the Go language. Used for font locking.")
-
-(defconst go-mode-keywords
- '("break" "default" "func" "interface" "select"
- "case" "defer" "go" "map" "struct"
- "chan" "else" "goto" "package" "switch"
- "const" "fallthrough" "if" "range" "type"
- "continue" "for" "import" "return" "var")
- "All keywords in the Go language. Used for font locking.")
-
-(defconst go-constants '("nil" "true" "false" "iota"))
-(defconst go-type-name-regexp (concat "\\(?:[*(]\\)*\\(?:" go-identifier-regexp "\\.\\)?\\(" go-identifier-regexp "\\)"))
-
-(defvar go-dangling-cache)
-(defvar go-godoc-history nil)
-(defvar go--coverage-current-file-name)
-
-(defgroup go nil
- "Major mode for editing Go code"
- :group 'languages)
-
-(defgroup go-cover nil
- "Options specific to `cover`"
- :group 'go)
-
-(defcustom go-fontify-function-calls t
- "Fontify function and method calls if this is non-nil."
- :type 'boolean
- :group 'go)
-
-(defcustom go-mode-hook nil
- "Hook called by `go-mode'."
- :type 'hook
- :group 'go)
-
-(defcustom go-command "go"
- "The 'go' command. Some users have multiple Go development
-trees and invoke the 'go' tool via a wrapper that sets GOROOT and
-GOPATH based on the current directory. Such users should
-customize this variable to point to the wrapper script."
- :type 'string
- :group 'go)
-
-(defcustom gofmt-command "gofmt"
- "The 'gofmt' command. Some users may replace this with 'goimports'
-from https://github.com/bradfitz/goimports."
- :type 'string
- :group 'go)
-
-(defcustom go-other-file-alist
- '(("_test\\.go\\'" (".go"))
- ("\\.go\\'" ("_test.go")))
- "See the documentation of `ff-other-file-alist' for details."
- :type '(repeat (list regexp (choice (repeat string) function)))
- :group 'go)
-
-(defface go-coverage-untracked
- '((t (:foreground "#505050")))
- "Coverage color of untracked code."
- :group 'go-cover)
-
-(defface go-coverage-0
- '((t (:foreground "#c00000")))
- "Coverage color for uncovered code."
- :group 'go-cover)
-(defface go-coverage-1
- '((t (:foreground "#808080")))
- "Coverage color for covered code with weight 1."
- :group 'go-cover)
-(defface go-coverage-2
- '((t (:foreground "#748c83")))
- "Coverage color for covered code with weight 2."
- :group 'go-cover)
-(defface go-coverage-3
- '((t (:foreground "#689886")))
- "Coverage color for covered code with weight 3."
- :group 'go-cover)
-(defface go-coverage-4
- '((t (:foreground "#5ca489")))
- "Coverage color for covered code with weight 4."
- :group 'go-cover)
-(defface go-coverage-5
- '((t (:foreground "#50b08c")))
- "Coverage color for covered code with weight 5."
- :group 'go-cover)
-(defface go-coverage-6
- '((t (:foreground "#44bc8f")))
- "Coverage color for covered code with weight 6."
- :group 'go-cover)
-(defface go-coverage-7
- '((t (:foreground "#38c892")))
- "Coverage color for covered code with weight 7."
- :group 'go-cover)
-(defface go-coverage-8
- '((t (:foreground "#2cd495")))
- "Coverage color for covered code with weight 8.
-For mode=set, all covered lines will have this weight."
- :group 'go-cover)
-(defface go-coverage-9
- '((t (:foreground "#20e098")))
- "Coverage color for covered code with weight 9."
- :group 'go-cover)
-(defface go-coverage-10
- '((t (:foreground "#14ec9b")))
- "Coverage color for covered code with weight 10."
- :group 'go-cover)
-(defface go-coverage-covered
- '((t (:foreground "#2cd495")))
- "Coverage color of covered code."
- :group 'go-cover)
-
-(defvar go-mode-syntax-table
- (let ((st (make-syntax-table)))
- (modify-syntax-entry ?+ "." st)
- (modify-syntax-entry ?- "." st)
- (modify-syntax-entry ?% "." st)
- (modify-syntax-entry ?& "." st)
- (modify-syntax-entry ?| "." st)
- (modify-syntax-entry ?^ "." st)
- (modify-syntax-entry ?! "." st)
- (modify-syntax-entry ?= "." st)
- (modify-syntax-entry ?< "." st)
- (modify-syntax-entry ?> "." st)
- (modify-syntax-entry ?/ (if (go--xemacs-p) ". 1456" ". 124b") st)
- (modify-syntax-entry ?* ". 23" st)
- (modify-syntax-entry ?\n "> b" st)
- (modify-syntax-entry ?\" "\"" st)
- (modify-syntax-entry ?\' "\"" st)
- (modify-syntax-entry ?` "\"" st)
- (modify-syntax-entry ?\\ "\\" st)
- ;; It would be nicer to have _ as a symbol constituent, but that
- ;; would trip up XEmacs, which does not support the \_< anchor
- (modify-syntax-entry ?_ "w" st)
-
- st)
- "Syntax table for Go mode.")
-
-(defun go--build-font-lock-keywords ()
- ;; we cannot use 'symbols in regexp-opt because GNU Emacs <24
- ;; doesn't understand that
- (append
- `((,(go--regexp-enclose-in-symbol (regexp-opt go-mode-keywords t)) . font-lock-keyword-face)
- (,(concat "\\(" (go--regexp-enclose-in-symbol (regexp-opt go-builtins t)) "\\)[[:space:]]*(") 1 font-lock-builtin-face)
- (,(go--regexp-enclose-in-symbol (regexp-opt go-constants t)) . font-lock-constant-face)
- (,go-func-regexp 1 font-lock-function-name-face)) ;; function (not method) name
-
- (if go-fontify-function-calls
- `((,(concat "\\(" go-identifier-regexp "\\)[[:space:]]*(") 1 font-lock-function-name-face) ;; function call/method name
- (,(concat "[^[:word:][:multibyte:]](\\(" go-identifier-regexp "\\))[[:space:]]*(") 1 font-lock-function-name-face)) ;; bracketed function call
- `((,go-func-meth-regexp 2 font-lock-function-name-face))) ;; method name
-
- `(
- ("\\(`[^`]*`\\)" 1 font-lock-multiline) ;; raw string literal, needed for font-lock-syntactic-keywords
- (,(concat (go--regexp-enclose-in-symbol "type") "[[:space:]]+\\([^[:space:]]+\\)") 1 font-lock-type-face) ;; types
- (,(concat (go--regexp-enclose-in-symbol "type") "[[:space:]]+" go-identifier-regexp "[[:space:]]*" go-type-name-regexp) 1 font-lock-type-face) ;; types
- (,(concat "[^[:word:][:multibyte:]]\\[\\([[:digit:]]+\\|\\.\\.\\.\\)?\\]" go-type-name-regexp) 2 font-lock-type-face) ;; Arrays/slices
- (,(concat "\\(" go-identifier-regexp "\\)" "{") 1 font-lock-type-face)
- (,(concat (go--regexp-enclose-in-symbol "map") "\\[[^]]+\\]" go-type-name-regexp) 1 font-lock-type-face) ;; map value type
- (,(concat (go--regexp-enclose-in-symbol "map") "\\[" go-type-name-regexp) 1 font-lock-type-face) ;; map key type
- (,(concat (go--regexp-enclose-in-symbol "chan") "[[:space:]]*\\(?:<-\\)?" go-type-name-regexp) 1 font-lock-type-face) ;; channel type
- (,(concat (go--regexp-enclose-in-symbol "\\(?:new\\|make\\)") "\\(?:[[:space:]]\\|)\\)*(" go-type-name-regexp) 1 font-lock-type-face) ;; new/make type
- ;; TODO do we actually need this one or isn't it just a function call?
- (,(concat "\\.\\s *(" go-type-name-regexp) 1 font-lock-type-face) ;; Type conversion
- (,(concat (go--regexp-enclose-in-symbol "func") "[[:space:]]+(" go-identifier-regexp "[[:space:]]+" go-type-name-regexp ")") 1 font-lock-type-face) ;; Method receiver
- (,(concat (go--regexp-enclose-in-symbol "func") "[[:space:]]+(" go-type-name-regexp ")") 1 font-lock-type-face) ;; Method receiver without variable name
- ;; Like the original go-mode this also marks compound literal
- ;; fields. There, it was marked as to fix, but I grew quite
- ;; accustomed to it, so it'll stay for now.
- (,(concat "^[[:space:]]*\\(" go-label-regexp "\\)[[:space:]]*:\\(\\S.\\|$\\)") 1 font-lock-constant-face) ;; Labels and compound literal fields
- (,(concat (go--regexp-enclose-in-symbol "\\(goto\\|break\\|continue\\)") "[[:space:]]*\\(" go-label-regexp "\\)") 2 font-lock-constant-face)))) ;; labels in goto/break/continue
-
-(defconst go--font-lock-syntactic-keywords
- ;; Override syntax property of raw string literal contents, so that
- ;; backslashes have no special meaning in ``. Used in Emacs 23 or older.
- '((go--match-raw-string-literal
- (1 (7 . ?`))
- (2 (15 . nil)) ;; 15 = "generic string"
- (3 (7 . ?`)))))
-
-(defvar go-mode-map
- (let ((m (make-sparse-keymap)))
- (define-key m "}" #'go-mode-insert-and-indent)
- (define-key m ")" #'go-mode-insert-and-indent)
- (define-key m "," #'go-mode-insert-and-indent)
- (define-key m ":" #'go-mode-insert-and-indent)
- (define-key m "=" #'go-mode-insert-and-indent)
- (define-key m (kbd "C-c C-a") #'go-import-add)
- (define-key m (kbd "C-c C-j") #'godef-jump)
- (define-key m (kbd "C-x 4 C-c C-j") #'godef-jump-other-window)
- (define-key m (kbd "C-c C-d") #'godef-describe)
- m)
- "Keymap used by Go mode to implement electric keys.")
-
-(defun go-mode-insert-and-indent (key)
- "Invoke the global binding of KEY, then reindent the line."
-
- (interactive (list (this-command-keys)))
- (call-interactively (lookup-key (current-global-map) key))
- (indent-according-to-mode))
-
-(defmacro go-paren-level ()
- `(car (syntax-ppss)))
-
-(defmacro go-in-string-or-comment-p ()
- `(nth 8 (syntax-ppss)))
-
-(defmacro go-in-string-p ()
- `(nth 3 (syntax-ppss)))
-
-(defmacro go-in-comment-p ()
- `(nth 4 (syntax-ppss)))
-
-(defmacro go-goto-beginning-of-string-or-comment ()
- `(goto-char (nth 8 (syntax-ppss))))
-
-(defun go--backward-irrelevant (&optional stop-at-string)
- "Skips backwards over any characters that are irrelevant for
-indentation and related tasks.
-
-It skips over whitespace, comments, cases and labels and, if
-STOP-AT-STRING is not true, over strings."
-
- (let (pos (start-pos (point)))
- (skip-chars-backward "\n\s\t")
- (if (and (save-excursion (beginning-of-line) (go-in-string-p)) (looking-back "`") (not stop-at-string))
- (backward-char))
- (if (and (go-in-string-p) (not stop-at-string))
- (go-goto-beginning-of-string-or-comment))
- (if (looking-back "\\*/")
- (backward-char))
- (if (go-in-comment-p)
- (go-goto-beginning-of-string-or-comment))
- (setq pos (point))
- (beginning-of-line)
- (if (or (looking-at (concat "^" go-label-regexp ":")) (looking-at "^[[:space:]]*\\(case .+\\|default\\):"))
- (end-of-line 0)
- (goto-char pos))
- (if (/= start-pos (point))
- (go--backward-irrelevant stop-at-string))
- (/= start-pos (point))))
-
-(defun go--buffer-narrowed-p ()
- "Return non-nil if the current buffer is narrowed."
- (/= (buffer-size)
- (- (point-max)
- (point-min))))
-
-(defun go--match-raw-string-literal (end)
- "Search for a raw string literal. Set point to the end of the
-occurence found on success. Returns nil on failure."
- (when (search-forward "`" end t)
- (goto-char (match-beginning 0))
- (if (go-in-string-or-comment-p)
- (progn (goto-char (match-end 0))
- (go--match-raw-string-literal end))
- (when (looking-at "\\(`\\)\\([^`]*\\)\\(`\\)")
- (goto-char (match-end 0))
- t))))
-
-(defun go-previous-line-has-dangling-op-p ()
- "Returns non-nil if the current line is a continuation line."
- (let* ((cur-line (line-number-at-pos))
- (val (gethash cur-line go-dangling-cache 'nope)))
- (if (or (go--buffer-narrowed-p) (equal val 'nope))
- (save-excursion
- (beginning-of-line)
- (go--backward-irrelevant t)
- (setq val (looking-back go-dangling-operators-regexp))
- (if (not (go--buffer-narrowed-p))
- (puthash cur-line val go-dangling-cache))))
- val))
-
-(defun go--at-function-definition ()
- "Return non-nil if point is on the opening curly brace of a
-function definition.
-
-We do this by first calling (beginning-of-defun), which will take
-us to the start of *some* function. We then look for the opening
-curly brace of that function and compare its position against the
-curly brace we are checking. If they match, we return non-nil."
- (if (= (char-after) ?\{)
- (save-excursion
- (let ((old-point (point))
- start-nesting)
- (beginning-of-defun)
- (when (looking-at "func ")
- (setq start-nesting (go-paren-level))
- (skip-chars-forward "^{")
- (while (> (go-paren-level) start-nesting)
- (forward-char)
- (skip-chars-forward "^{") 0)
- (if (and (= (go-paren-level) start-nesting) (= old-point (point)))
- t))))))
-
-(defun go--indentation-for-opening-parenthesis ()
- "Return the semantic indentation for the current opening parenthesis.
-
-If point is on an opening curly brace and said curly brace
-belongs to a function declaration, the indentation of the func
-keyword will be returned. Otherwise the indentation of the
-current line will be returned."
- (save-excursion
- (if (go--at-function-definition)
- (progn
- (beginning-of-defun)
- (current-indentation))
- (current-indentation))))
-
-(defun go-indentation-at-point ()
- (save-excursion
- (let (start-nesting)
- (back-to-indentation)
- (setq start-nesting (go-paren-level))
-
- (cond
- ((go-in-string-p)
- (current-indentation))
- ((looking-at "[])}]")
- (go-goto-opening-parenthesis)
- (if (go-previous-line-has-dangling-op-p)
- (- (current-indentation) tab-width)
- (go--indentation-for-opening-parenthesis)))
- ((progn (go--backward-irrelevant t) (looking-back go-dangling-operators-regexp))
- ;; only one nesting for all dangling operators in one operation
- (if (go-previous-line-has-dangling-op-p)
- (current-indentation)
- (+ (current-indentation) tab-width)))
- ((zerop (go-paren-level))
- 0)
- ((progn (go-goto-opening-parenthesis) (< (go-paren-level) start-nesting))
- (if (go-previous-line-has-dangling-op-p)
- (current-indentation)
- (+ (go--indentation-for-opening-parenthesis) tab-width)))
- (t
- (current-indentation))))))
-
-(defun go-mode-indent-line ()
- (interactive)
- (let (indent
- shift-amt
- (pos (- (point-max) (point)))
- (point (point))
- (beg (line-beginning-position)))
- (back-to-indentation)
- (if (go-in-string-or-comment-p)
- (goto-char point)
- (setq indent (go-indentation-at-point))
- (if (looking-at (concat go-label-regexp ":\\([[:space:]]*/.+\\)?$\\|case .+:\\|default:"))
- (decf indent tab-width))
- (setq shift-amt (- indent (current-column)))
- (if (zerop shift-amt)
- nil
- (delete-region beg (point))
- (indent-to indent))
- ;; If initial point was within line's indentation,
- ;; position after the indentation. Else stay at same point in text.
- (if (> (- (point-max) pos) (point))
- (goto-char (- (point-max) pos))))))
-
-(defun go-beginning-of-defun (&optional count)
- (setq count (or count 1))
- (let ((first t)
- failure)
- (dotimes (i (abs count))
- (while (and (not failure)
- (or first (go-in-string-or-comment-p)))
- (if (>= count 0)
- (progn
- (go--backward-irrelevant)
- (if (not (re-search-backward go-func-meth-regexp nil t))
- (setq failure t)))
- (if (looking-at go-func-meth-regexp)
- (forward-char))
- (if (not (re-search-forward go-func-meth-regexp nil t))
- (setq failure t)))
- (setq first nil)))
- (if (< count 0)
- (beginning-of-line))
- (not failure)))
-
-(defun go-end-of-defun ()
- (let (orig-level)
- ;; It can happen that we're not placed before a function by emacs
- (if (not (looking-at "func"))
- (go-beginning-of-defun -1))
- (skip-chars-forward "^{")
- (forward-char)
- (setq orig-level (go-paren-level))
- (while (>= (go-paren-level) orig-level)
- (skip-chars-forward "^}")
- (forward-char))))
-
-;;;###autoload
-(define-derived-mode go-mode prog-mode "Go"
- "Major mode for editing Go source text.
-
-This mode provides (not just) basic editing capabilities for
-working with Go code. It offers almost complete syntax
-highlighting, indentation that is almost identical to gofmt and
-proper parsing of the buffer content to allow features such as
-navigation by function, manipulation of comments or detection of
-strings.
-
-In addition to these core features, it offers various features to
-help with writing Go code. You can directly run buffer content
-through gofmt, read godoc documentation from within Emacs, modify
-and clean up the list of package imports or interact with the
-Playground (uploading and downloading pastes).
-
-The following extra functions are defined:
-
-- `gofmt'
-- `godoc'
-- `go-import-add'
-- `go-remove-unused-imports'
-- `go-goto-imports'
-- `go-play-buffer' and `go-play-region'
-- `go-download-play'
-- `godef-describe' and `godef-jump'
-- `go-coverage'
-
-If you want to automatically run `gofmt' before saving a file,
-add the following hook to your emacs configuration:
-
-\(add-hook 'before-save-hook #'gofmt-before-save)
-
-If you want to use `godef-jump' instead of etags (or similar),
-consider binding godef-jump to `M-.', which is the default key
-for `find-tag':
-
-\(add-hook 'go-mode-hook (lambda ()
- (local-set-key (kbd \"M-.\") #'godef-jump)))
-
-Please note that godef is an external dependency. You can install
-it with
-
-go get code.google.com/p/rog-go/exp/cmd/godef
-
-
-If you're looking for even more integration with Go, namely
-on-the-fly syntax checking, auto-completion and snippets, it is
-recommended that you look at goflymake
-\(https://github.com/dougm/goflymake), gocode
-\(https://github.com/nsf/gocode), go-eldoc
-\(github.com/syohex/emacs-go-eldoc) and yasnippet-go
-\(https://github.com/dominikh/yasnippet-go)"
-
- ;; Font lock
- (set (make-local-variable 'font-lock-defaults)
- '(go--build-font-lock-keywords))
-
- ;; Indentation
- (set (make-local-variable 'indent-line-function) #'go-mode-indent-line)
-
- ;; Comments
- (set (make-local-variable 'comment-start) "// ")
- (set (make-local-variable 'comment-end) "")
- (set (make-local-variable 'comment-use-syntax) t)
- (set (make-local-variable 'comment-start-skip) "\\(//+\\|/\\*+\\)\\s *")
-
- (set (make-local-variable 'beginning-of-defun-function) #'go-beginning-of-defun)
- (set (make-local-variable 'end-of-defun-function) #'go-end-of-defun)
-
- (set (make-local-variable 'parse-sexp-lookup-properties) t)
- (if (boundp 'syntax-propertize-function)
- (set (make-local-variable 'syntax-propertize-function) #'go-propertize-syntax)
- (set (make-local-variable 'font-lock-syntactic-keywords)
- go--font-lock-syntactic-keywords)
- (set (make-local-variable 'font-lock-multiline) t))
-
- (set (make-local-variable 'go-dangling-cache) (make-hash-table :test 'eql))
- (add-hook 'before-change-functions (lambda (x y) (setq go-dangling-cache (make-hash-table :test 'eql))) t t)
-
- ;; ff-find-other-file
- (setq ff-other-file-alist 'go-other-file-alist)
-
- (setq imenu-generic-expression
- '(("type" "^type *\\([^ \t\n\r\f]*\\)" 1)
- ("func" "^func *\\(.*\\) {" 1)))
- (imenu-add-to-menubar "Index")
-
- ;; Go style
- (setq indent-tabs-mode t)
-
- ;; Handle unit test failure output in compilation-mode
- ;;
- ;; Note the final t argument to add-to-list for append, ie put these at the
- ;; *ends* of compilation-error-regexp-alist[-alist]. We want go-test to be
- ;; handled first, otherwise other elements will match that don't work, and
- ;; those alists are traversed in *reverse* order:
- ;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2001-12/msg00674.html
- (when (and (boundp 'compilation-error-regexp-alist)
- (boundp 'compilation-error-regexp-alist-alist))
- (add-to-list 'compilation-error-regexp-alist 'go-test t)
- (add-to-list 'compilation-error-regexp-alist-alist
- '(go-test . ("^\t+\\([^()\t\n]+\\):\\([0-9]+\\):? .*$" 1 2)) t)))
-
-;;;###autoload
-(add-to-list 'auto-mode-alist (cons "\\.go\\'" 'go-mode))
-
-(defun go--apply-rcs-patch (patch-buffer)
- "Apply an RCS-formatted diff from PATCH-BUFFER to the current
-buffer."
- (let ((target-buffer (current-buffer))
- ;; Relative offset between buffer line numbers and line numbers
- ;; in patch.
- ;;
- ;; Line numbers in the patch are based on the source file, so
- ;; we have to keep an offset when making changes to the
- ;; buffer.
- ;;
- ;; Appending lines decrements the offset (possibly making it
- ;; negative), deleting lines increments it. This order
- ;; simplifies the forward-line invocations.
- (line-offset 0))
- (save-excursion
- (with-current-buffer patch-buffer
- (goto-char (point-min))
- (while (not (eobp))
- (unless (looking-at "^\\([ad]\\)\\([0-9]+\\) \\([0-9]+\\)")
- (error "invalid rcs patch or internal error in go--apply-rcs-patch"))
- (forward-line)
- (let ((action (match-string 1))
- (from (string-to-number (match-string 2)))
- (len (string-to-number (match-string 3))))
- (cond
- ((equal action "a")
- (let ((start (point)))
- (forward-line len)
- (let ((text (buffer-substring start (point))))
- (with-current-buffer target-buffer
- (decf line-offset len)
- (goto-char (point-min))
- (forward-line (- from len line-offset))
- (insert text)))))
- ((equal action "d")
- (with-current-buffer target-buffer
- (go--goto-line (- from line-offset))
- (incf line-offset len)
- (go--delete-whole-line len)))
- (t
- (error "invalid rcs patch or internal error in go--apply-rcs-patch")))))))))
-
-(defun gofmt ()
- "Formats the current buffer according to the gofmt tool."
-
- (interactive)
- (let ((tmpfile (make-temp-file "gofmt" nil ".go"))
- (patchbuf (get-buffer-create "*Gofmt patch*"))
- (errbuf (get-buffer-create "*Gofmt Errors*"))
- (coding-system-for-read 'utf-8)
- (coding-system-for-write 'utf-8))
-
- (with-current-buffer errbuf
- (setq buffer-read-only nil)
- (erase-buffer))
- (with-current-buffer patchbuf
- (erase-buffer))
-
- (write-region nil nil tmpfile)
-
- ;; We're using errbuf for the mixed stdout and stderr output. This
- ;; is not an issue because gofmt -w does not produce any stdout
- ;; output in case of success.
- (if (zerop (call-process gofmt-command nil errbuf nil "-w" tmpfile))
- (if (zerop (call-process-region (point-min) (point-max) "diff" nil patchbuf nil "-n" "-" tmpfile))
- (progn
- (kill-buffer errbuf)
- (message "Buffer is already gofmted"))
- (go--apply-rcs-patch patchbuf)
- (kill-buffer errbuf)
- (message "Applied gofmt"))
- (message "Could not apply gofmt. Check errors for details")
- (gofmt--process-errors (buffer-file-name) tmpfile errbuf))
-
- (kill-buffer patchbuf)
- (delete-file tmpfile)))
-
-
-(defun gofmt--process-errors (filename tmpfile errbuf)
- ;; Convert the gofmt stderr to something understood by the compilation mode.
- (with-current-buffer errbuf
- (goto-char (point-min))
- (insert "gofmt errors:\n")
- (while (search-forward-regexp (concat "^\\(" (regexp-quote tmpfile) "\\):") nil t)
- (replace-match (file-name-nondirectory filename) t t nil 1))
- (compilation-mode)
- (display-buffer errbuf)))
-
-;;;###autoload
-(defun gofmt-before-save ()
- "Add this to .emacs to run gofmt on the current buffer when saving:
- (add-hook 'before-save-hook 'gofmt-before-save).
-
-Note that this will cause go-mode to get loaded the first time
-you save any file, kind of defeating the point of autoloading."
-
- (interactive)
- (when (eq major-mode 'go-mode) (gofmt)))
-
-(defun godoc--read-query ()
- "Read a godoc query from the minibuffer."
- ;; Compute the default query as the symbol under the cursor.
- ;; TODO: This does the wrong thing for e.g. multipart.NewReader (it only grabs
- ;; half) but I see no way to disambiguate that from e.g. foobar.SomeMethod.
- (let* ((bounds (bounds-of-thing-at-point 'symbol))
- (symbol (if bounds
- (buffer-substring-no-properties (car bounds)
- (cdr bounds)))))
- (completing-read (if symbol
- (format "godoc (default %s): " symbol)
- "godoc: ")
- (go--old-completion-list-style (go-packages)) nil nil nil 'go-godoc-history symbol)))
-
-(defun godoc--get-buffer (query)
- "Get an empty buffer for a godoc query."
- (let* ((buffer-name (concat "*godoc " query "*"))
- (buffer (get-buffer buffer-name)))
- ;; Kill the existing buffer if it already exists.
- (when buffer (kill-buffer buffer))
- (get-buffer-create buffer-name)))
-
-(defun godoc--buffer-sentinel (proc event)
- "Sentinel function run when godoc command completes."
- (with-current-buffer (process-buffer proc)
- (cond ((string= event "finished\n") ;; Successful exit.
- (goto-char (point-min))
- (view-mode 1)
- (display-buffer (current-buffer) t))
- ((/= (process-exit-status proc) 0) ;; Error exit.
- (let ((output (buffer-string)))
- (kill-buffer (current-buffer))
- (message (concat "godoc: " output)))))))
-
-;;;###autoload
-(defun godoc (query)
- "Show go documentation for a query, much like M-x man."
- (interactive (list (godoc--read-query)))
- (unless (string= query "")
- (set-process-sentinel
- (start-process-shell-command "godoc" (godoc--get-buffer query)
- (concat "godoc " query))
- 'godoc--buffer-sentinel)
- nil))
-
-(defun go-goto-imports ()
- "Move point to the block of imports.
-
-If using
-
- import (
- \"foo\"
- \"bar\"
- )
-
-it will move point directly behind the last import.
-
-If using
-
- import \"foo\"
- import \"bar\"
-
-it will move point to the next line after the last import.
-
-If no imports can be found, point will be moved after the package
-declaration."
- (interactive)
- ;; FIXME if there's a block-commented import before the real
- ;; imports, we'll jump to that one.
-
- ;; Generally, this function isn't very forgiving. it'll bark on
- ;; extra whitespace. It works well for clean code.
- (let ((old-point (point)))
- (goto-char (point-min))
- (cond
- ((re-search-forward "^import ()" nil t)
- (backward-char 1)
- 'block-empty)
- ((re-search-forward "^import ([^)]+)" nil t)
- (backward-char 2)
- 'block)
- ((re-search-forward "\\(^import \\([^\"]+ \\)?\"[^\"]+\"\n?\\)+" nil t)
- 'single)
- ((re-search-forward "^[[:space:]\n]*package .+?\n" nil t)
- (message "No imports found, moving point after package declaration")
- 'none)
- (t
- (goto-char old-point)
- (message "No imports or package declaration found. Is this really a Go file?")
- 'fail))))
-
-(defun go-play-buffer ()
- "Like `go-play-region', but acts on the entire buffer."
- (interactive)
- (go-play-region (point-min) (point-max)))
-
-(defun go-play-region (start end)
- "Send the region to the Playground and stores the resulting
-link in the kill ring."
- (interactive "r")
- (let* ((url-request-method "POST")
- (url-request-extra-headers
- '(("Content-Type" . "application/x-www-form-urlencoded")))
- (url-request-data
- (encode-coding-string
- (buffer-substring-no-properties start end)
- 'utf-8))
- (content-buf (url-retrieve
- "http://play.golang.org/share"
- (lambda (arg)
- (cond
- ((equal :error (car arg))
- (signal 'go-play-error (cdr arg)))
- (t
- (re-search-forward "\n\n")
- (kill-new (format "http://play.golang.org/p/%s" (buffer-substring (point) (point-max))))
- (message "http://play.golang.org/p/%s" (buffer-substring (point) (point-max)))))))))))
-
-;;;###autoload
-(defun go-download-play (url)
- "Downloads a paste from the playground and inserts it in a Go
-buffer. Tries to look for a URL at point."
- (interactive (list (read-from-minibuffer "Playground URL: " (ffap-url-p (ffap-string-at-point 'url)))))
- (with-current-buffer
- (let ((url-request-method "GET") url-request-data url-request-extra-headers)
- (url-retrieve-synchronously (concat url ".go")))
- (let ((buffer (generate-new-buffer (concat (car (last (split-string url "/"))) ".go"))))
- (goto-char (point-min))
- (re-search-forward "\n\n")
- (copy-to-buffer buffer (point) (point-max))
- (kill-buffer)
- (with-current-buffer buffer
- (go-mode)
- (switch-to-buffer buffer)))))
-
-(defun go-propertize-syntax (start end)
- (save-excursion
- (goto-char start)
- (while (search-forward "\\" end t)
- (put-text-property (1- (point)) (point) 'syntax-table (if (= (char-after) ?`) '(1) '(9))))))
-
-(defun go-import-add (arg import)
- "Add a new import to the list of imports.
-
-When called with a prefix argument asks for an alternative name
-to import the package as.
-
-If no list exists yet, one will be created if possible.
-
-If an identical import has been commented, it will be
-uncommented, otherwise a new import will be added."
-
- ;; - If there's a matching `// import "foo"`, uncomment it
- ;; - If we're in an import() block and there's a matching `"foo"`, uncomment it
- ;; - Otherwise add a new import, with the appropriate syntax
- (interactive
- (list
- current-prefix-arg
- (replace-regexp-in-string "^[\"']\\|[\"']$" "" (completing-read "Package: " (go--old-completion-list-style (go-packages))))))
- (save-excursion
- (let (as line import-start)
- (if arg
- (setq as (read-from-minibuffer "Import as: ")))
- (if as
- (setq line (format "%s \"%s\"" as import))
- (setq line (format "\"%s\"" import)))
-
- (goto-char (point-min))
- (if (re-search-forward (concat "^[[:space:]]*//[[:space:]]*import " line "$") nil t)
- (uncomment-region (line-beginning-position) (line-end-position))
- (case (go-goto-imports)
- ('fail (message "Could not find a place to add import."))
- ('block-empty
- (insert "\n\t" line "\n"))
- ('block
- (save-excursion
- (re-search-backward "^import (")
- (setq import-start (point)))
- (if (re-search-backward (concat "^[[:space:]]*//[[:space:]]*" line "$") import-start t)
- (uncomment-region (line-beginning-position) (line-end-position))
- (insert "\n\t" line)))
- ('single (insert "import " line "\n"))
- ('none (insert "\nimport (\n\t" line "\n)\n")))))))
-
-(defun go-root-and-paths ()
- (let* ((output (split-string (shell-command-to-string (concat go-command " env GOROOT GOPATH"))
- "\n"))
- (root (car output))
- (paths (split-string (cadr output) ":")))
- (append (list root) paths)))
-
-(defun go--string-prefix-p (s1 s2 &optional ignore-case)
- "Return non-nil if S1 is a prefix of S2.
-If IGNORE-CASE is non-nil, the comparison is case-insensitive."
- (eq t (compare-strings s1 nil nil
- s2 0 (length s1) ignore-case)))
-
-(defun go--directory-dirs (dir)
- "Recursively return all subdirectories in DIR."
- (if (file-directory-p dir)
- (let ((dir (directory-file-name dir))
- (dirs '())
- (files (directory-files dir nil nil t)))
- (dolist (file files)
- (unless (member file '("." ".."))
- (let ((file (concat dir "/" file)))
- (if (file-directory-p file)
- (setq dirs (append (cons file
- (go--directory-dirs file))
- dirs))))))
- dirs)
- '()))
-
-
-(defun go-packages ()
- (sort
- (delete-dups
- (mapcan
- (lambda (topdir)
- (let ((pkgdir (concat topdir "/pkg/")))
- (mapcan (lambda (dir)
- (mapcar (lambda (file)
- (let ((sub (substring file (length pkgdir) -2)))
- (unless (or (go--string-prefix-p "obj/" sub) (go--string-prefix-p "tool/" sub))
- (mapconcat #'identity (cdr (split-string sub "/")) "/"))))
- (if (file-directory-p dir)
- (directory-files dir t "\\.a$"))))
- (if (file-directory-p pkgdir)
- (go--directory-dirs pkgdir)))))
- (go-root-and-paths)))
- #'string<))
-
-(defun go-unused-imports-lines ()
- ;; FIXME Technically, -o /dev/null fails in quite some cases (on
- ;; Windows, when compiling from within GOPATH). Practically,
- ;; however, it has the same end result: There won't be a
- ;; compiled binary/archive, and we'll get our import errors when
- ;; there are any.
- (reverse (remove nil
- (mapcar
- (lambda (line)
- (if (string-match "^\\(.+\\):\\([[:digit:]]+\\): imported and not used: \".+\".*$" line)
- (if (string= (file-truename (match-string 1 line)) (file-truename buffer-file-name))
- (string-to-number (match-string 2 line)))))
- (split-string (shell-command-to-string
- (concat go-command
- (if (string-match "_test\.go$" buffer-file-truename)
- " test -c"
- " build -o /dev/null"))) "\n")))))
-
-(defun go-remove-unused-imports (arg)
- "Removes all unused imports. If ARG is non-nil, unused imports
-will be commented, otherwise they will be removed completely."
- (interactive "P")
- (save-excursion
- (let ((cur-buffer (current-buffer)) flymake-state lines)
- (when (boundp 'flymake-mode)
- (setq flymake-state flymake-mode)
- (flymake-mode-off))
- (save-some-buffers nil (lambda () (equal cur-buffer (current-buffer))))
- (if (buffer-modified-p)
- (message "Cannot operate on unsaved buffer")
- (setq lines (go-unused-imports-lines))
- (dolist (import lines)
- (go--goto-line import)
- (beginning-of-line)
- (if arg
- (comment-region (line-beginning-position) (line-end-position))
- (go--delete-whole-line)))
- (message "Removed %d imports" (length lines)))
- (if flymake-state (flymake-mode-on)))))
-
-(defun godef--find-file-line-column (specifier other-window)
- "Given a file name in the format of `filename:line:column',
-visit FILENAME and go to line LINE and column COLUMN."
- (if (not (string-match "\\(.+\\):\\([0-9]+\\):\\([0-9]+\\)" specifier))
- ;; We've only been given a directory name
- (funcall (if other-window #'find-file-other-window #'find-file) specifier)
- (let ((filename (match-string 1 specifier))
- (line (string-to-number (match-string 2 specifier)))
- (column (string-to-number (match-string 3 specifier))))
- (with-current-buffer (funcall (if other-window #'find-file-other-window #'find-file) filename)
- (go--goto-line line)
- (beginning-of-line)
- (forward-char (1- column))
- (if (buffer-modified-p)
- (message "Buffer is modified, file position might not have been correct"))))))
-
-(defun godef--call (point)
- "Call godef, acquiring definition position and expression
-description at POINT."
- (if (go--xemacs-p)
- (error "godef does not reliably work in XEmacs, expect bad results"))
- (if (not (buffer-file-name (go--coverage-origin-buffer)))
- (error "Cannot use godef on a buffer without a file name")
- (let ((outbuf (get-buffer-create "*godef*")))
- (with-current-buffer outbuf
- (erase-buffer))
- (call-process-region (point-min)
- (point-max)
- "godef"
- nil
- outbuf
- nil
- "-i"
- "-t"
- "-f"
- (file-truename (buffer-file-name (go--coverage-origin-buffer)))
- "-o"
- (number-to-string (go--position-bytes point)))
- (with-current-buffer outbuf
- (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n")))))
-
-(defun godef-describe (point)
- "Describe the expression at POINT."
- (interactive "d")
- (condition-case nil
- (let ((description (cdr (butlast (godef--call point) 1))))
- (if (not description)
- (message "No description found for expression at point")
- (message "%s" (mapconcat #'identity description "\n"))))
- (file-error (message "Could not run godef binary"))))
-
-(defun godef-jump (point &optional other-window)
- "Jump to the definition of the expression at POINT."
- (interactive "d")
- (condition-case nil
- (let ((file (car (godef--call point))))
- (cond
- ((string= "-" file)
- (message "godef: expression is not defined anywhere"))
- ((string= "godef: no identifier found" file)
- (message "%s" file))
- ((go--string-prefix-p "godef: no declaration found for " file)
- (message "%s" file))
- ((go--string-prefix-p "error finding import path for " file)
- (message "%s" file))
- (t
- (push-mark)
- (ring-insert find-tag-marker-ring (point-marker))
- (godef--find-file-line-column file other-window))))
- (file-error (message "Could not run godef binary"))))
-
-(defun godef-jump-other-window (point)
- (interactive "d")
- (godef-jump point t))
-
-(defun go--goto-line (line)
- (goto-char (point-min))
- (forward-line (1- line)))
-
-(defun go--line-column-to-point (line column)
- (save-excursion
- (go--goto-line line)
- (forward-char (1- column))
- (point)))
-
-(defstruct go--covered
- start-line start-column end-line end-column covered count)
-
-(defun go--coverage-file ()
- "Return the coverage file to use, either by reading it from the
-current coverage buffer or by prompting for it."
- (if (boundp 'go--coverage-current-file-name)
- go--coverage-current-file-name
- (read-file-name "Coverage file: " nil nil t)))
-
-(defun go--coverage-origin-buffer ()
- "Return the buffer to base the coverage on."
- (or (buffer-base-buffer) (current-buffer)))
-
-(defun go--coverage-face (count divisor)
- "Return the intensity face for COUNT when using DIVISOR
-to scale it to a range [0,10].
-
-DIVISOR scales the absolute cover count to values from 0 to 10.
-For DIVISOR = 0 the count will always translate to 8."
- (let* ((norm (cond
- ((= count 0)
- -0.1) ;; Uncovered code, set to -0.1 so n becomes 0.
- ((= divisor 0)
- 0.8) ;; covermode=set, set to 0.8 so n becomes 8.
- (t
- (/ (log count) divisor))))
- (n (1+ (floor (* norm 9))))) ;; Convert normalized count [0,1] to intensity [0,10]
- (concat "go-coverage-" (number-to-string n))))
-
-(defun go--coverage-make-overlay (range divisor)
- "Create a coverage overlay for a RANGE of covered/uncovered
-code. Uses DIVISOR to scale absolute counts to a [0,10] scale."
- (let* ((count (go--covered-count range))
- (face (go--coverage-face count divisor))
- (ov (make-overlay (go--line-column-to-point (go--covered-start-line range)
- (go--covered-start-column range))
- (go--line-column-to-point (go--covered-end-line range)
- (go--covered-end-column range)))))
-
- (overlay-put ov 'face face)
- (overlay-put ov 'help-echo (format "Count: %d" count))))
-
-(defun go--coverage-clear-overlays ()
- "Remove existing overlays and put a single untracked overlay
-over the entire buffer."
- (remove-overlays)
- (overlay-put (make-overlay (point-min) (point-max))
- 'face
- 'go-coverage-untracked))
-
-(defun go--coverage-parse-file (coverage-file file-name)
- "Parse COVERAGE-FILE and extract coverage information and
-divisor for FILE-NAME."
- (let (ranges
- (max-count 0))
- (with-temp-buffer
- (insert-file-contents coverage-file)
- (go--goto-line 2) ;; Skip over mode
- (while (not (eobp))
- (let* ((parts (split-string (buffer-substring (point-at-bol) (point-at-eol)) ":"))
- (file (car parts))
- (rest (split-string (nth 1 parts) "[., ]")))
-
- (destructuring-bind
- (start-line start-column end-line end-column num count)
- (mapcar #'string-to-number rest)
-
- (when (string= (file-name-nondirectory file) file-name)
- (if (> count max-count)
- (setq max-count count))
- (push (make-go--covered :start-line start-line
- :start-column start-column
- :end-line end-line
- :end-column end-column
- :covered (/= count 0)
- :count count)
- ranges)))
-
- (forward-line)))
-
- (list ranges (if (> max-count 0) (log max-count) 0)))))
-
-(defun go-coverage (&optional coverage-file)
- "Open a clone of the current buffer and overlay it with
-coverage information gathered via go test -coverprofile=COVERAGE-FILE.
-
-If COVERAGE-FILE is nil, it will either be inferred from the
-current buffer if it's already a coverage buffer, or be prompted
-for."
- (interactive)
- (let* ((cur-buffer (current-buffer))
- (origin-buffer (go--coverage-origin-buffer))
- (gocov-buffer-name (concat (buffer-name origin-buffer) "<gocov>"))
- (coverage-file (or coverage-file (go--coverage-file)))
- (ranges-and-divisor (go--coverage-parse-file
- coverage-file
- (file-name-nondirectory (buffer-file-name origin-buffer))))
- (cov-mtime (nth 5 (file-attributes coverage-file)))
- (cur-mtime (nth 5 (file-attributes (buffer-file-name origin-buffer)))))
-
- (if (< (float-time cov-mtime) (float-time cur-mtime))
- (message "Coverage file is older than the source file."))
-
- (with-current-buffer (or (get-buffer gocov-buffer-name)
- (make-indirect-buffer origin-buffer gocov-buffer-name t))
- (set (make-local-variable 'go--coverage-current-file-name) coverage-file)
-
- (save-excursion
- (go--coverage-clear-overlays)
- (dolist (range (car ranges-and-divisor))
- (go--coverage-make-overlay range (cadr ranges-and-divisor))))
-
- (if (not (eq cur-buffer (current-buffer)))
- (display-buffer (current-buffer) #'display-buffer-reuse-window)))))
-
-(provide 'go-mode)
diff --git a/misc/fraise/go.plist b/misc/fraise/go.plist
deleted file mode 100644
index 17f416221..000000000
--- a/misc/fraise/go.plist
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>beginCommand</key>
- <string></string>
- <key>endCommand</key>
- <string></string>
- <key>beginInstruction</key>
- <string></string>
- <key>endInstruction</key>
- <string></string>
- <key>beginVariable</key>
- <string></string>
- <key>endVariable</key>
- <string></string>
- <key>firstString</key>
- <string>&quot;</string>
- <key>secondString</key>
- <string>&apos;</string>
- <key>firstSingleLineComment</key>
- <string>//</string>
- <key>secondSingleLineComment</key>
- <string></string>
- <key>beginFirstMultiLineComment</key>
- <string>/*</string>
- <key>endFirstMultiLineComment</key>
- <string>*/</string>
- <key>beginSecondMultiLineComment</key>
- <string></string>
- <key>endSecondMultiLineComment</key>
- <string></string>
- <key>functionDefinition</key>
- <string>^func\s*.*\(.*\)\s?\{</string>
- <key>removeFromFunction</key>
- <string></string>
- <key>keywordsCaseSensitive</key>
- <true/>
- <key>recolourKeywordIfAlreadyColoured</key>
- <true/>
- <key>keywords</key>
- <array>
- <string>break</string>
- <string>case</string>
- <string>chan</string>
- <string>const</string>
- <string>continue</string>
- <string>default</string>
- <string>defer</string>
- <string>else</string>
- <string>fallthrough</string>
- <string>for</string>
- <string>func</string>
- <string>go</string>
- <string>goto</string>
- <string>if</string>
- <string>import</string>
- <string>interface</string>
- <string>map</string>
- <string>package</string>
- <string>range</string>
- <string>return</string>
- <string>select</string>
- <string>struct</string>
- <string>switch</string>
- <string>type</string>
- <string>var</string>
- <string>bool</string>
- <string>byte</string>
- <string>chan</string>
- <string>complex64</string>
- <string>complex128</string>
- <string>float32</string>
- <string>float64</string>
- <string>int</string>
- <string>int8</string>
- <string>int16</string>
- <string>int32</string>
- <string>int64</string>
- <string>map</string>
- <string>string</string>
- <string>uint</string>
- <string>uintptr</string>
- <string>uint8</string>
- <string>uint16</string>
- <string>uint32</string>
- <string>uint64</string>
- </array>
- <key>autocompleteWords</key>
- <array/>
-</dict>
-</plist>
diff --git a/misc/fraise/readme.txt b/misc/fraise/readme.txt
deleted file mode 100644
index fb0f2c8c1..000000000
--- a/misc/fraise/readme.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-##Instructions for enabling Go syntax highlighting in Fraise.app##
-1. Move go.plist to /Applications/Fraise.app/Contents/Resources/Syntax\ Definitions/
-2. Open /Applications/Fraise.app/Contents/Resources/SyntaxDefinitions.plist and add
-
- <dict>
- <key>name</key>
- <string>GoogleGo</string>
- <key>file</key>
- <string>go</string>
- <key>extensions</key>
- <string>go</string>
- </dict>
-
-before </array>
-
-3. Restart Fraise and you're good to Go! \ No newline at end of file
diff --git a/misc/kate/go.xml b/misc/kate/go.xml
deleted file mode 100644
index 03f4f2a0c..000000000
--- a/misc/kate/go.xml
+++ /dev/null
@@ -1,150 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Go" section="Sources"
- version="1.00" kateversion="2.4"
- indenter="cstyle"
- extensions="*.go"
- mimetype=""
- priority="5"
- author="The Go Authors"
- license="BSD">
- <highlighting>
- <list name="keywords">
- <item> break </item>
- <item> case </item>
- <item> chan </item>
- <item> const </item>
- <item> continue </item>
- <item> default </item>
- <item> defer </item>
- <item> else </item>
- <item> fallthrough </item>
- <item> for </item>
- <item> func </item>
- <item> go </item>
- <item> goto </item>
- <item> if </item>
- <item> import </item>
- <item> interface </item>
- <item> map </item>
- <item> package </item>
- <item> range </item>
- <item> return </item>
- <item> select </item>
- <item> struct </item>
- <item> switch </item>
- <item> type </item>
- <item> var </item>
- </list>
- <list name="predeclared">
- <item> false </item>
- <item> iota </item>
- <item> nil </item>
- <item> true </item>
- </list>
- <list name="types">
- <item> bool </item>
- <item> byte </item>
- <item> complex64 </item>
- <item> complex128 </item>
- <item> error </item>
- <item> float32 </item>
- <item> float64 </item>
- <item> int </item>
- <item> int8 </item>
- <item> int16 </item>
- <item> int32 </item>
- <item> int64 </item>
- <item> rune </item>
- <item> string </item>
- <item> uint </item>
- <item> uintptr </item>
- <item> uint8 </item>
- <item> uint16 </item>
- <item> uint32 </item>
- <item> uint64 </item>
- </list>
- <list name="functions">
- <item> append </item>
- <item> cap </item>
- <item> close </item>
- <item> complex </item>
- <item> copy </item>
- <item> delete </item>
- <item> imag </item>
- <item> len </item>
- <item> make </item>
- <item> new </item>
- <item> panic </item>
- <item> print </item>
- <item> println </item>
- <item> real </item>
- <item> recover </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <DetectSpaces />
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Predeclared Identifier" context="#stay"
- String="predeclared"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <keyword attribute="Builtin Function" context="#stay" String="functions"/>
- <DetectIdentifier />
- <DetectChar attribute="Symbol" context="#stay" char="{" beginRegion="Brace1" />
- <DetectChar attribute="Symbol" context="#stay" char="}" endRegion="Brace1" />
- <HlCOct attribute="Octal" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <HlCChar attribute="Char" context="#stay"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <DetectChar attribute="String" context="Multiline String" char="`"/>
- <Detect2Chars attribute="Comment" context="Comment 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Comment 2" char="/" char1="*" beginRegion="Comment"/>
- <AnyChar attribute="Symbol" context="#stay" String=":!%&amp;()+,-/.*&lt;=&gt;?[]|~^&#59;"/>
- </context>
-
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
-
- <context attribute="String" lineEndContext="#stay" name="Multiline String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="`"/>
- </context>
-
- <context attribute="Comment" lineEndContext="#pop" name="Comment 1">
- <LineContinue attribute="Comment" context="#stay"/>
- </context>
-
- <context attribute="Comment" lineEndContext="#stay" name="Comment 2">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" spellChecking="false"/>
- <itemData name="Keyword" defStyleNum="dsKeyword" spellChecking="false"/>
- <itemData name="Predeclared Identifier" defStyleNum="dsOthers" spellChecking="false"/>
- <itemData name="Builtin Function" defStyleNum="dsFunction" spellChecking="false"/>
- <itemData name="Data Type" defStyleNum="dsDataType" spellChecking="false"/>
- <itemData name="Decimal" defStyleNum="dsDecVal" spellChecking="false"/>
- <itemData name="Octal" defStyleNum="dsBaseN" spellChecking="false"/>
- <itemData name="Hex" defStyleNum="dsBaseN" spellChecking="false"/>
- <itemData name="Float" defStyleNum="dsFloat" spellChecking="false"/>
- <itemData name="Char" defStyleNum="dsChar" spellChecking="false"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal" spellChecking="false"/>
- <itemData name="Error" defStyleNum="dsError" spellChecking="false"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" additionalDeliminator="'&quot;" />
- </general>
-</language>
diff --git a/misc/makerelease/makerelease.go b/misc/makerelease/makerelease.go
index 2496a865a..3b511b1db 100644
--- a/misc/makerelease/makerelease.go
+++ b/misc/makerelease/makerelease.go
@@ -14,6 +14,7 @@ import (
"compress/gzip"
"crypto/sha1"
"encoding/json"
+ "errors"
"flag"
"fmt"
"io"
@@ -30,7 +31,7 @@ import (
"strings"
"code.google.com/p/goauth2/oauth"
- "code.google.com/p/google-api-go-client/storage/v1beta2"
+ storage "code.google.com/p/google-api-go-client/storage/v1"
)
var (
@@ -53,20 +54,20 @@ var (
)
const (
- blogPath = "code.google.com/p/go.blog"
- toolPath = "code.google.com/p/go.tools"
+ blogPath = "golang.org/x/blog"
+ toolPath = "golang.org/x/tools"
tourPath = "code.google.com/p/go-tour"
- defaultToolTag = "release-branch.go1.2"
- defaultTourTag = "release-branch.go1.2"
+ defaultToolTag = "release-branch.go1.4"
+ defaultTourTag = "release-branch.go1.4"
)
// Import paths for tool commands.
// These must be the command that cmd/go knows to install to $GOROOT/bin
// or $GOROOT/pkg/tool.
var toolPaths = []string{
- "code.google.com/p/go.tools/cmd/cover",
- "code.google.com/p/go.tools/cmd/godoc",
- "code.google.com/p/go.tools/cmd/vet",
+ "golang.org/x/tools/cmd/cover",
+ "golang.org/x/tools/cmd/godoc",
+ "golang.org/x/tools/cmd/vet",
}
var preBuildCleanFiles = []string{
@@ -74,8 +75,8 @@ var preBuildCleanFiles = []string{
"misc/dashboard/godashboard",
"src/cmd/cov",
"src/cmd/prof",
- "src/pkg/exp",
- "src/pkg/old",
+ "src/exp",
+ "src/old",
}
var cleanFiles = []string{
@@ -154,6 +155,7 @@ func main() {
log.Fatalln("setupOAuthClient:", err)
}
}
+ ok := true
for _, targ := range flag.Args() {
var b Build
if m := fileRe.FindStringSubmatch(targ); m != nil {
@@ -205,8 +207,12 @@ func main() {
}
if err := b.Do(); err != nil {
log.Printf("%s: %v", targ, err)
+ ok = false
}
}
+ if !ok {
+ os.Exit(1)
+ }
}
type Build struct {
@@ -432,7 +438,8 @@ func (b *Build) Do() error {
// Build package.
_, err = b.run(work, "candle",
"-nologo",
- "-dVersion="+version,
+ "-dGoVersion="+version,
+ "-dWixGoVersion="+wixVersion(version),
"-dArch="+b.Arch,
"-dSourceDir=go",
installer, appfiles)
@@ -466,6 +473,22 @@ func (b *Build) Do() error {
return err
}
+var versionRe = regexp.MustCompile(`^go([0-9]+(\.[0-9]+)*)`)
+
+// The Microsoft installer requires version format major.minor.build
+// (http://msdn.microsoft.com/en-us/library/aa370859%28v=vs.85%29.aspx).
+// Where the major and minor field has a maximum value of 255 and build 65535.
+// The offical Go version format is goMAJOR.MINOR.PATCH at $GOROOT/VERSION.
+// It's based on the Mercurial tag. Remove prefix and suffix to make the
+// installer happy.
+func wixVersion(v string) string {
+ m := versionRe.FindStringSubmatch(v)
+ if m == nil {
+ return "0.0.0"
+ }
+ return m[1]
+}
+
// extras fetches the go.tools, go.blog, and go-tour repositories,
// builds them and copies the resulting binaries and static assets
// to the new GOROOT.
@@ -482,16 +505,38 @@ func (b *Build) extras() error {
}
func (b *Build) get(repoPath, revision string) error {
- // Fetch the packages (without building/installing).
- _, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"),
- "get", "-d", repoPath+"/...")
- if err != nil {
- return err
+ dest := filepath.Join(b.gopath, "src", filepath.FromSlash(repoPath))
+
+ if strings.HasPrefix(repoPath, "golang.org/x/") {
+ // For sub-repos, fetch the old Mercurial repo; bypass "go get".
+ // DO NOT import this special case into the git tree.
+
+ if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil {
+ return err
+ }
+ repo := strings.Replace(repoPath, "golang.org/x/", "https://code.google.com/p/go.", 1)
+ if _, err := b.run(b.gopath, "hg", "clone", repo, dest); err != nil {
+ return err
+ }
+ } else {
+ // Fetch the packages (without building/installing).
+ _, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"),
+ "get", "-d", repoPath+"/...")
+ if err != nil {
+ return err
+ }
}
// Update the repo to the specified revision.
- p := filepath.Join(b.gopath, "src", filepath.FromSlash(repoPath))
- _, err = b.run(p, "hg", "update", revision)
+ var err error
+ switch {
+ case exists(filepath.Join(dest, ".git")):
+ _, err = b.run(dest, "git", "checkout", revision)
+ case exists(filepath.Join(dest, ".hg")):
+ _, err = b.run(dest, "hg", "update", revision)
+ default:
+ err = errors.New("unknown version control system")
+ }
return err
}
@@ -721,7 +766,7 @@ type File struct {
func setupOAuthClient() error {
config := &oauth.Config{
ClientId: "999119582588-h7kpj5pcm6d9solh5lgrbusmvvk4m9dn.apps.googleusercontent.com",
- ClientSecret: "8YLFgOhXIELWbO",
+ ClientSecret: "8YLFgOhXIELWbO-NtF3iqIQz",
Scope: storage.DevstorageRead_writeScope,
AuthURL: "https://accounts.google.com/o/oauth2/auth",
TokenURL: "https://accounts.google.com/o/oauth2/token",
diff --git a/misc/makerelease/windows/installer.wxs b/misc/makerelease/windows/installer.wxs
index b170b98dc..01178e265 100644
--- a/misc/makerelease/windows/installer.wxs
+++ b/misc/makerelease/windows/installer.wxs
@@ -18,13 +18,12 @@
<Product
Id="FF5B30B2-08C2-11E1-85A2-6ACA4824019B"
- Name="Go Programming Language $(var.Arch) $(var.Version)"
+ Name="Go Programming Language $(var.Arch) $(var.GoVersion)"
Language="1033"
Codepage="1252"
- Version="0.0.0.0"
+ Version="$(var.WixGoVersion)"
Manufacturer="http://golang.org"
UpgradeCode="$(var.UpgradeCode)" >
- <!-- Version="$(var.Version)" TODO: Version requires X.X.X.X format -->
<Package
Id='*'
@@ -40,9 +39,9 @@
<Property Id="ARPCOMMENTS" Value="The Go programming language is a fast, statically typed, compiled language that feels like a dynamically typed, interpreted language." />
<Property Id="ARPCONTACT" Value="golang-nuts@googlegroups.com" />
-<Property Id="ARPHELPLINK" Value="golang.org/doc/community.html" />
-<Property Id="ARPREADME" Value="golang.org" />
-<Property Id="ARPURLINFOABOUT" Value="golang.org" />
+<Property Id="ARPHELPLINK" Value="https://golang.org/help/" />
+<Property Id="ARPREADME" Value="https://golang.org" />
+<Property Id="ARPURLINFOABOUT" Value="https://golang.org" />
<Property Id="LicenseAccepted">1</Property>
<Icon Id="gopher.ico" SourceFile="images\gopher.ico"/>
<Property Id="ARPPRODUCTICON" Value="gopher.ico" />
diff --git a/misc/nacl/README b/misc/nacl/README
index 9cc2bda60..72d0e08ad 100644
--- a/misc/nacl/README
+++ b/misc/nacl/README
@@ -1,63 +1,122 @@
Native Client
=============
-This document outlines the basics of building and developing the Go runtime and programs in the Native Client (NaCl) environment.
+This document outlines the basics of building and developing the Go runtime and
+programs in the Native Client (NaCl) environment.
-Go 1.3 supports two architectures
+Go 1.3 supports three architectures
* nacl/386 which is standard 386.
- * nacl/amd64p32 which is a 64 bit architecture, where the address space is limited to a 4gb window.
+ * nacl/amd64p32 which is a 64 bit architecture, where the address space is
+ limited to a 4gb window.
+ * nacl/arm which is 32-bit ARMv7A architecture with 1GB address space.
For background it is recommended that you read http://golang.org/s/go13nacl.
Prerequisites
-------------
-Native Client programs are executed inside a sandbox, the NaCl runtime. This runtime must be installed before you can use NaCl programs.
+Native Client programs are executed inside a sandbox, the NaCl runtime. This
+runtime must be installed before you can use NaCl programs.
-The NaCl distribution comes with an installer which ensures you have access to the latest version of the runtime. The version tracks the Chrome numbering scheme.
+The NaCl distribution comes with an installer which ensures you have access to
+the latest version of the runtime. The version tracks the Chrome numbering
+scheme.
# Download NaCl
-Download nacl_sdk.zip file from https://developers.google.com/native-client/dev/sdk/download, and unpack it. I chose /opt/nacl_sdk
+Download nacl_sdk.zip file from
+ https://developers.google.com/native-client/dev/sdk/download
+and unpack it. I chose /opt/nacl_sdk.
# Update
-The zip file contains a small skeleton that can be used to download the correct sdk. These are released every 6-8 weeks, in line with Chrome releases.
+The zip file contains a small skeleton that can be used to download the correct
+sdk. These are released every 6-8 weeks, in line with Chrome releases.
% cd /opt/nacl_sdk
% ./naclsdk update
-At this time pepper_33 is the stable version. If naclsdk downloads a later version, please adjust accordingly.
+At this time pepper_34 is the stable version. If naclsdk downloads a later
+version, please adjust accordingly. As of June 2014, only the canary sdk
+provides support for nacl/arm.
-The cmd/go helper scripts expect that the runtime loaders, sel_ldr_x86_{32,64} are in your path. I find it easiest to make a symlink from the NaCl distribution to my $GOPATH/bin directory.
+The cmd/go helper scripts expect that the loaders sel_ldr_{x86_{32,64},arm} and
+nacl_helper_bootstrap_arm are in your path. I find it easiest to make a symlink
+from the NaCl distribution to my $GOPATH/bin directory.
- % ln -nfs /opt/nacl_sdk/pepper_33/tools/sel_ldr_x86_32 $GOPATH/bin/sel_ldr_x86_32
- % ln -nfs /opt/nacl_sdk/pepper_33/tools/sel_ldr_x86_64 $GOPATH/bin/sel_ldr_x86_64
+ % ln -nfs /opt/nacl_sdk/pepper_34/tools/sel_ldr_x86_32 $GOPATH/bin/sel_ldr_x86_32
+ % ln -nfs /opt/nacl_sdk/pepper_34/tools/sel_ldr_x86_64 $GOPATH/bin/sel_ldr_x86_64
+ % ln -nfs /opt/nacl_sdk/pepper_canary/tools/sel_ldr_arm $GOPATH/bin/sel_ldr_arm
+
+Additionally, for NaCl/ARM only:
+
+ % ln -nfs /opt/nacl_sdk/pepper_canary/tools/nacl_helper_bootstrap_arm $GOPATH/bin/nacl_helper_bootstrap_arm
Support scripts
---------------
-Symlink the two scripts in this directory into your $PATH, just as you did with NaCl sdk above.
+Symlink the two scripts in this directory into your $PATH, just as you did with
+NaCl sdk above.
- % ln -nfs $GOROOT/go/misc/nacl/go_nacl_amd64p32_exec $GOPATH/bin/go_nacl_amd64p32_exec
- % ln -nfs $GOROOT/go/misc/nacl/go_nacl_386_exec $GOPATH/bin/go_nacl_386_exec
+ % ln -nfs $GOROOT/misc/nacl/go_nacl_amd64p32_exec $GOPATH/bin/go_nacl_amd64p32_exec
+ % ln -nfs $GOROOT/misc/nacl/go_nacl_386_exec $GOPATH/bin/go_nacl_386_exec
+ % ln -nfs $GOROOT/misc/nacl/go_nacl_arm_exec $GOPATH/bin/go_nacl_arm_exec
Building and testing
--------------------
-Building for NaCl is similar to cross compiling for other platforms. However, as it is not possible to ever build in a `native` NaCl environment, the cmd/go tool has been enhanced to allow the full build, all.bash, to be executed, rather than just the compile stage, make.bash.
+Building for NaCl is similar to cross compiling for other platforms. However,
+as it is not possible to ever build in a `native` NaCl environment, the cmd/go
+tool has been enhanced to allow the full build, all.bash, to be executed,
+rather than just the compile stage, make.bash.
-The cmd/go tool knows that if GOOS is set to `nacl` it should not try to execute any binaries itself. Instead it passes their execution to a support script which sets up a Native Client environment and invokes the NaCl sandbox.
+The cmd/go tool knows that if GOOS is set to `nacl` it should not try to
+execute any binaries itself. Instead it passes their execution to a support
+script which sets up a Native Client environment and invokes the NaCl sandbox.
-The script's name has a special format, go_$GOOS_$GOARCH_exec, so cmd/go can find it.
+The script's name has a special format, go_$GOOS_$GOARCH_exec, so cmd/go can
+find it.
-In short, if the support scripts are in place, the cmd/go tool can be used as per normal.
+In short, if the support scripts are in place, the cmd/go tool can be used as
+per normal.
# Build and test Go for NaCl
-NaCl does not permit direct file system access. Instead, package syscall provides a simulated file system served by in-memory data. The script nacltest.bash is the NaCl equivalent of all.bash. It builds NaCl with an in-memory file system containing files needed for tests, and then it runs the tests.
+NaCl does not permit direct file system access. Instead, package syscall
+provides a simulated file system served by in-memory data. The script
+nacltest.bash is the NaCl equivalent of all.bash. It builds NaCl with an
+in-memory file system containing files needed for tests, and then it runs the
+tests.
% cd go/src
% env GOARCH=amd64p32 ./nacltest.bash
+Debugging
+---------
+
+Assuming that you have built nacl/amd64p32 binary ./mybin and can run as:
+
+ % sel_ldr_x86_64 -l /dev/null -S -e ./mybin
+
+Create the nacl manifest file mybin.manifest with the following contents:
+
+ { "program": { "x86-64": { "url": "mybin" } } }
+
+url is the path to the binary relative to the manifest file.
+Then, run the program as:
+
+ % sel_ldr_x86_64 -g -l /dev/null -S -e ./mybin
+
+The -g flag instructs the loader to stop at startup. Then, in another console:
+
+ % /opt/nacl_sdk/pepper_34/toolchain/linux_x86_glibc/bin/x86_64-nacl-gdb
+ % nacl-manifest mybin.manifest
+ % target remote :4014
+
+If you see that the program is stopped in _rt0_amd64p32_nacl, then symbols are
+loaded successfully and you can type 'c' to start the program.
+Next time you can automate it as:
+
+ % /opt/nacl_sdk/pepper_34/toolchain/linux_x86_glibc/bin/x86_64-nacl-gdb \
+ -ex 'nacl-manifest mybin.manifest' -ex 'target remote :4014'
diff --git a/misc/nacl/go_nacl_arm_exec b/misc/nacl/go_nacl_arm_exec
new file mode 100755
index 000000000..4275cb111
--- /dev/null
+++ b/misc/nacl/go_nacl_arm_exec
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+eval $(go env)
+
+export NACLENV_GOARCH=$GOARCH
+export NACLENV_GOOS=$GOOS
+export NACLENV_GOROOT=/go
+export NACLENV_NACLPWD=$(pwd | sed "s;$GOROOT;/go;")
+
+exec nacl_helper_bootstrap_arm $(which sel_ldr_arm) --reserved_at_zero=0xXXXXXXXXXXXXXXXX -l /dev/null -S -e "$@"
diff --git a/misc/nacl/mkzip.go b/misc/nacl/mkzip.go
index 7b2de7d47..aaf37f120 100644
--- a/misc/nacl/mkzip.go
+++ b/misc/nacl/mkzip.go
@@ -71,7 +71,13 @@ func main() {
var w io.Writer = zf
if *gopackage != "" {
- fmt.Fprintf(zf, "package %s\n\nfunc init() {\n\tunzip(\"", *gopackage)
+ fmt.Fprintf(zf, `package %s
+import "sync"
+func init() {
+ var once sync.Once
+ fsinit = func() {
+ once.Do(func() {
+ unzip("`, *gopackage)
gw := &goWriter{b: bufio.NewWriter(w)}
defer func() {
if err := gw.Close(); err != nil {
@@ -214,7 +220,7 @@ func (w *goWriter) Write(b []byte) (int, error) {
}
func (w *goWriter) Close() error {
- fmt.Fprintf(w.b, "\")\n}\n")
+ fmt.Fprintf(w.b, "\")\n\t\t})\n\t}\n}")
w.b.Flush()
return nil
}
diff --git a/misc/nacl/testzip.proto b/misc/nacl/testzip.proto
index 2701ff463..07d4a1db0 100644
--- a/misc/nacl/testzip.proto
+++ b/misc/nacl/testzip.proto
@@ -10,101 +10,105 @@ usr src=../misc/nacl/testdata
go src=..
src
cmd
+ internal
+ objfile
+ objfile.go
gofmt
+ gofmt.go
+ gofmt_test.go
testdata
+
- pkg
- archive
- tar
- testdata
- +
- zip
- testdata
- +
- compress
- bzip2
- testdata
- +
- flate
- gzip
- testdata
- +
- lzw
- testdata
- +
- zlib
- crypto
- rsa
- testdata
- +
- tls
- testdata
- +
- debug
- dwarf
- testdata
- +
- elf
- testdata
- +
- macho
- testdata
- +
- pe
- testdata
- +
- plan9obj
- testdata
- +
- go
- build
- +
- doc
- testdata
- +
- format
- +
- parser
- +
- printer
- +
- image
- testdata
- +
- draw
- gif
- jpeg
- png
- testdata
- +
- io
+ archive
+ tar
+ testdata
+ +
+ zip
+ testdata
+ +
+ compress
+ bzip2
+ testdata
+ +
+ flate
+ gzip
+ testdata
+ +
+ lzw
+ testdata
+
- mime
+ zlib
+ crypto
+ rsa
+ testdata
+ +
+ tls
+ testdata
+ +
+ debug
+ dwarf
+ testdata
+ +
+ elf
+ testdata
+ +
+ macho
testdata
+
- multipart
- testdata
- +
- net
- http
+ pe
+ testdata
+
+ plan9obj
testdata
+
- os
+ go
+ build
+
- path
- filepath
+ doc
+ testdata
+
- regexp
+ format
+ +
+ parser
+ +
+ printer
+ +
+ image
+ testdata
+ +
+ draw
+ gif
+ jpeg
+ png
testdata
+
- strconv
+ io
+ +
+ mime
+ testdata
+ +
+ multipart
+ testdata
+ +
+ net
+ http
+ +
+ testdata
+ +
+ os
+ +
+ path
+ filepath
+ +
+ regexp
+ testdata
+ +
+ strconv
+ testdata
+ +
+ text
+ template
testdata
+
- text
- template
- testdata
- +
lib
time
zoneinfo.zip
diff --git a/misc/notepadplus/README b/misc/notepadplus/README
deleted file mode 100644
index fca4f5f09..000000000
--- a/misc/notepadplus/README
+++ /dev/null
@@ -1,59 +0,0 @@
-Notepad++ syntax highlighting
------------------------------
-
-The userDefineLang.xml uses the new User Defined Language system (UDL2),
-which needs Notepad++ v6.2 or higher.
-
-Installing from Notepad++ Installer
-
- 1. Add the contents of userDefineLang.xml at %APPDATA%\Notepad++\userDefineLang.xml
- between <NotepadPlus> ... </NotepadPlus>
- 2. Restart Notepad++
-
-Installing from Notepad++ zip/7z package
-
- 1. Given a Notepad++ installation at <DIR>.
- 2. Add the contents of userDefineLang.xml at <DIR>\userDefineLang.xml
- between <NotepadPlus> ... </NotepadPlus>
- 3. Restart Notepad++
-
-Reference
-
- 1. http://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=User_Defined_Languages
- 2. http://notepad-plus-plus.org/news/notepad-6.2-release-udl2.html
- 3. http://udl20.weebly.com/index.html
-
-
-Notepad++ keyword auto-completion
----------------------------------
-
- 1. Given a Notepad++ installation at <DIR>.
- 2. Copy go.xml to <DIR>\plugins\APIs
- 3. Restart Notepad++
-
-Reference
-
- 1. http://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=Auto_Completion
-
-Notepad++ Function List
------------------------
-
-The functionList.xml uses the Function List Pane new feature,
-which needs Notepad++ v6.4 or higher.
-
-Installing from Notepad++ Installer
-
- 1. Add the contents of userDefineLang.xml at %APPDATA%\Notepad++\functionList.xml
- between <associationMap> ... </associationMap> and <parsers> ... </parsers>
- 2. Restart Notepad++
-
-Installing from Notepad++ zip/7z package
-
- 1. Given a Notepad++ installation at <DIR>.
- 2. Add the contents of functionList.xml at <DIR>\functionList.xml
- between <associationMap> ... </associationMap> and <parsers> ... </parsers>
- 3. Restart Notepad++
-
-Reference
-
- 1. http://notepad-plus-plus.org/features/function-list.html
diff --git a/misc/notepadplus/functionList.xml b/misc/notepadplus/functionList.xml
deleted file mode 100644
index 7c605db4f..000000000
--- a/misc/notepadplus/functionList.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<!-- <NotepadPlus> -->
- <!-- <functionList> -->
- <!-- <associationMap> -->
-
- <!--
- if npp version == 6.4:
- <association ext=".go" id="go"/>
-
- if npp version >= 6.5:
- <association userDefinedLangName="go" id="go"/>
- -->
-
- <!-- </associationMap> -->
- <!-- <parsers> -->
- <parser id="go" displayName="Go" commentExpr="((/\*.*?\*)/|(//.*?$))">
- <classRange
- mainExpr="^type\s+\w+\s+interface\s*\{"
- openSymbole = "\{"
- closeSymbole = "\}"
- displayMode="node">
- <className>
- <nameExpr expr="type\s+\w+"/>
- <nameExpr expr="\s+\w+"/>
- <nameExpr expr="\w+"/>
- </className>
- <function
- mainExpr="^\s+\w+\s*\(">
- <functionName>
- <funcNameExpr expr="\w+"/>
- </functionName>
- </function>
- </classRange>
- <function
- mainExpr="(^func\s+\w+)|(^func\s*\(\s*\w*\s*\*?\s*\w+\s*\)\s*\w+)"
- displayMode="$className->$functionName">
- <functionName>
- <nameExpr expr="((func\s+\w+)|(\)\s*\w+))"/>
- <nameExpr expr="((\s+\w+)|(\)\s*\w+))"/>
- <nameExpr expr="\w+"/>
- </functionName>
- <className>
- <nameExpr expr="\w+\s*\)"/>
- <nameExpr expr="\w+"/>
- </className>
- </function>
- </parser>
-
- <!-- </parsers> -->
- <!-- </functionList> -->
-<!-- </NotepadPlus> -->
diff --git a/misc/notepadplus/go.xml b/misc/notepadplus/go.xml
deleted file mode 100644
index 59e4116d6..000000000
--- a/misc/notepadplus/go.xml
+++ /dev/null
@@ -1,133 +0,0 @@
-<NotepadPlus>
- <!-- Go Programming Language builtins and keywords -->
- <AutoComplete>
- <KeyWord name="append" func="yes">
- <Overload retVal="[]Type">
- <Param name="slice []Type" />
- <Param name="elems ...Type" />
- </Overload>
- </KeyWord>
- <KeyWord name="bool" />
- <KeyWord name="break" />
- <KeyWord name="byte" />
- <KeyWord name="cap" func="yes">
- <Overload retVal="int">
- <Param name="v Type" />
- </Overload>
- </KeyWord>
- <KeyWord name="case" />
- <KeyWord name="chan" />
- <KeyWord name="close" func="yes">
- <Overload retVal="">
- <Param name="c chan<- Type" />
- </Overload>
- </KeyWord>
- <KeyWord name="complex" func="yes">
- <Overload retVal="ComplexType">
- <Param name="r" />
- <Param name="i FloatType" />
- </Overload>
- </KeyWord>
- <KeyWord name="complex128" />
- <KeyWord name="complex64" />
- <KeyWord name="const" />
- <KeyWord name="continue" />
- <KeyWord name="copy" func="yes">
- <Overload retVal="int">
- <Param name="dst" />
- <Param name="src []Type" />
- </Overload>
- </KeyWord>
- <KeyWord name="default" />
- <KeyWord name="defer" />
- <KeyWord name="delete" func="yes">
- <Overload retVal="">
- <Param name="m map[Type]Type1" />
- <Param name="key Type" />
- </Overload>
- </KeyWord>
- <KeyWord name="else" />
- <KeyWord name="error" />
- <KeyWord name="fallthrough" />
- <KeyWord name="false" />
- <KeyWord name="float32" />
- <KeyWord name="float64" />
- <KeyWord name="for" />
- <KeyWord name="func" />
- <KeyWord name="go" />
- <KeyWord name="goto" />
- <KeyWord name="if" />
- <KeyWord name="iota" />
- <KeyWord name="imag" func="yes">
- <Overload retVal="FloatType">
- <Param name="c ComplexType" />
- </Overload>
- </KeyWord>
- <KeyWord name="import" />
- <KeyWord name="int" />
- <KeyWord name="int16" />
- <KeyWord name="int32" />
- <KeyWord name="int64" />
- <KeyWord name="int8" />
- <KeyWord name="interface" />
- <KeyWord name="len" func="yes">
- <Overload retVal="int">
- <Param name="v Type" />
- </Overload>
- </KeyWord>
- <KeyWord name="make" func="yes">
- <Overload retVal="Type">
- <Param name="Type" />
- <Param name="size IntegerType" />
- </Overload>
- </KeyWord>
- <KeyWord name="map" />
- <KeyWord name="new" func="yes">
- <Overload retVal="*Type">
- <Param name="Type" />
- </Overload>
- </KeyWord>
- <KeyWord name="nil" />
- <KeyWord name="package" />
- <KeyWord name="panic" func="yes">
- <Overload retVal="">
- <Param name="v interface{}" />
- </Overload>
- </KeyWord>
- <KeyWord name="print" func="yes">
- <Overload retVal="">
- <Param name="args ...Type" />
- </Overload>
- </KeyWord>
- <KeyWord name="println" func="yes">
- <Overload retVal="" >
- <Param name="args ...Type" />
- </Overload>
- </KeyWord>
- <KeyWord name="range" />
- <KeyWord name="real" func="yes">
- <Overload retVal="FloatType">
- <Param name="c ComplexType" />
- </Overload>
- </KeyWord>
- <KeyWord name="recover" func="yes">
- <Overload retVal="interface{}">
- </Overload>
- </KeyWord>
- <KeyWord name="return" />
- <KeyWord name="rune" />
- <KeyWord name="select" />
- <KeyWord name="string" />
- <KeyWord name="struct" />
- <KeyWord name="switch" />
- <KeyWord name="true" />
- <KeyWord name="type" />
- <KeyWord name="uint" />
- <KeyWord name="uint16" />
- <KeyWord name="uint32" />
- <KeyWord name="uint64" />
- <KeyWord name="uint8" />
- <KeyWord name="uintptr" />
- <KeyWord name="var" />
- </AutoComplete>
-</NotepadPlus>
diff --git a/misc/notepadplus/userDefineLang.xml b/misc/notepadplus/userDefineLang.xml
deleted file mode 100644
index 9751f7901..000000000
--- a/misc/notepadplus/userDefineLang.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<!-- <NotepadPlus> -->
- <UserLang name="go" ext="go" udlVersion="2.1">
- <Settings>
- <Global caseIgnored="no" allowFoldOfComments="yes" foldCompact="no" forcePureLC="0" decimalSeparator="0" />
- <Prefix Keywords1="no" Keywords2="no" Keywords3="no" Keywords4="no" Keywords5="no" Keywords6="no" Keywords7="no" Keywords8="no" />
- </Settings>
- <KeywordLists>
- <Keywords name="Comments">00// 01 02 03/* 04*/</Keywords>
- <Keywords name="Numbers, prefix1"></Keywords>
- <Keywords name="Numbers, prefix2">0x 0X</Keywords>
- <Keywords name="Numbers, extras1">a b c d e f A B C D E F</Keywords>
- <Keywords name="Numbers, extras2"></Keywords>
- <Keywords name="Numbers, suffix1"></Keywords>
- <Keywords name="Numbers, suffix2">i</Keywords>
- <Keywords name="Numbers, range"></Keywords>
- <Keywords name="Operators1">( ) [ ] { } ... , ; &amp; ^ % &gt; &lt; ! = + - * / | :</Keywords>
- <Keywords name="Operators2"></Keywords>
- <Keywords name="Folders in code1, open"></Keywords>
- <Keywords name="Folders in code1, middle"></Keywords>
- <Keywords name="Folders in code1, close"></Keywords>
- <Keywords name="Folders in code2, open"></Keywords>
- <Keywords name="Folders in code2, middle"></Keywords>
- <Keywords name="Folders in code2, close"></Keywords>
- <Keywords name="Folders in comment, open"></Keywords>
- <Keywords name="Folders in comment, middle"></Keywords>
- <Keywords name="Folders in comment, close"></Keywords>
- <Keywords name="Keywords1">break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var</Keywords>
- <Keywords name="Keywords2">bool byte complex64 complex128 error float32 float64 int int8 int16 int32 int64 rune string uint uint8 uint16 uint32 uint64 uintptr true false iota nil</Keywords>
- <Keywords name="Keywords3">append cap close complex copy delete imag len make new panic print println real recover _</Keywords>
- <Keywords name="Keywords4"></Keywords>
- <Keywords name="Keywords5"></Keywords>
- <Keywords name="Keywords6"></Keywords>
- <Keywords name="Keywords7"></Keywords>
- <Keywords name="Keywords8"></Keywords>
- <Keywords name="Delimiters">00&quot; 01\ 02&quot; 03&apos; 04\ 05&apos; 06` 07 08` 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23</Keywords>
- </KeywordLists>
- <Styles>
- <WordsStyle name="DEFAULT" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="COMMENTS" fgColor="008000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="LINE COMMENTS" fgColor="008000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="NUMBERS" fgColor="A52A2A" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="KEYWORDS1" fgColor="AA0000" bgColor="FFFFFF" fontName="" fontStyle="1" nesting="0" />
- <WordsStyle name="KEYWORDS2" fgColor="AA0000" bgColor="FFFFFF" fontName="" fontStyle="1" nesting="0" />
- <WordsStyle name="KEYWORDS3" fgColor="AA0000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="KEYWORDS4" fgColor="A00000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="KEYWORDS5" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="KEYWORDS6" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="KEYWORDS7" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="KEYWORDS8" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="OPERATORS" fgColor="8000FF" bgColor="FFFFFF" fontName="" fontStyle="1" nesting="0" />
- <WordsStyle name="FOLDER IN CODE1" fgColor="8000FF" bgColor="FFFFFF" fontName="" fontStyle="1" nesting="0" />
- <WordsStyle name="FOLDER IN CODE2" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="FOLDER IN COMMENT" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="DELIMITERS1" fgColor="0000FF" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="DELIMITERS2" fgColor="0000FF" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="DELIMITERS3" fgColor="0000FF" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="DELIMITERS4" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="DELIMITERS5" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="DELIMITERS6" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="DELIMITERS7" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- <WordsStyle name="DELIMITERS8" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
- </Styles>
- </UserLang>
-<!-- </NotepadPlus> -->
diff --git a/misc/pprof b/misc/pprof
deleted file mode 100755
index ad3f1ebe1..000000000
--- a/misc/pprof
+++ /dev/null
@@ -1,5094 +0,0 @@
-#! /usr/bin/env perl
-
-# This is a copy of http://google-perftools.googlecode.com/svn/trunk/src/pprof
-# with local modifications to handle generation of SVG images and
-# the Go-style pprof paths. These modifications will probably filter
-# back into the official source before long.
-# It's convenient to have a copy here because we need just the one
-# Perl script, not all the C++ libraries that surround it.
-
-# Copyright (c) 1998-2007, Google Inc.
-# All rights reserved.
-#
-# 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 Google Inc. 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.
-
-# ---
-# Program for printing the profile generated by common/profiler.cc,
-# or by the heap profiler (common/debugallocation.cc)
-#
-# The profile contains a sequence of entries of the form:
-# <count> <stack trace>
-# This program parses the profile, and generates user-readable
-# output.
-#
-# Examples:
-#
-# % tools/pprof "program" "profile"
-# Enters "interactive" mode
-#
-# % tools/pprof --text "program" "profile"
-# Generates one line per procedure
-#
-# % tools/pprof --gv "program" "profile"
-# Generates annotated call-graph and displays via "gv"
-#
-# % tools/pprof --gv --focus=Mutex "program" "profile"
-# Restrict to code paths that involve an entry that matches "Mutex"
-#
-# % tools/pprof --gv --focus=Mutex --ignore=string "program" "profile"
-# Restrict to code paths that involve an entry that matches "Mutex"
-# and does not match "string"
-#
-# % tools/pprof --list=IBF_CheckDocid "program" "profile"
-# Generates disassembly listing of all routines with at least one
-# sample that match the --list=<regexp> pattern. The listing is
-# annotated with the flat and cumulative sample counts at each line.
-#
-# % tools/pprof --disasm=IBF_CheckDocid "program" "profile"
-# Generates disassembly listing of all routines with at least one
-# sample that match the --disasm=<regexp> pattern. The listing is
-# annotated with the flat and cumulative sample counts at each PC value.
-#
-# TODO: Use color to indicate files?
-
-use strict;
-use warnings;
-use Getopt::Long;
-use File::Temp;
-use File::Copy;
-
-my $PPROF_VERSION = "1.5";
-
-# NOTE: All mentions of c++filt have been expunged from this script
-# because (1) we don't use C++, and (2) the copy of c++filt that ships
-# on OS X is from 2007 and destroys nm output by "demangling" the
-# first two columns (address and symbol type).
-
-# These are the object tools we use which can come from a
-# user-specified location using --tools, from the PPROF_TOOLS
-# environment variable, or from the environment.
-my %obj_tool_map = (
- "objdump" => "objdump",
- "nm" => "nm",
- "addr2line" => "addr2line",
- ## ConfigureObjTools may add architecture-specific entries:
- #"nm_pdb" => "nm-pdb", # for reading windows (PDB-format) executables
- #"addr2line_pdb" => "addr2line-pdb", # ditto
- #"otool" => "otool", # equivalent of objdump on OS X
-);
-my $DOT = "dot"; # leave non-absolute, since it may be in /usr/local
-my $GV = "gv";
-my $KCACHEGRIND = "kcachegrind";
-my $PS2PDF = "ps2pdf";
-# These are used for dynamic profiles
-
-# These are the web pages that servers need to support for dynamic profiles
-my $HEAP_PAGE = "/pprof/heap";
-my $THREAD_PAGE = "/pprof/thread";
-my $PROFILE_PAGE = "/pprof/profile"; # must support cgi-param "?seconds=#"
-my $BLOCK_PAGE = "/pprof/block";
-my $PMUPROFILE_PAGE = "/pprof/pmuprofile(?:\\?.*)?"; # must support cgi-param
- # ?seconds=#&event=x&period=n
-my $GROWTH_PAGE = "/pprof/growth";
-my $CONTENTION_PAGE = "/pprof/contention";
-my $WALL_PAGE = "/pprof/wall(?:\\?.*)?"; # accepts options like namefilter
-my $FILTEREDPROFILE_PAGE = "/pprof/filteredprofile(?:\\?.*)?";
-my $SYMBOL_PAGE = "/pprof/symbol"; # must support symbol lookup via POST
-my $PROGRAM_NAME_PAGE = "/pprof/cmdline";
-
-# default binary name
-my $UNKNOWN_BINARY = "(unknown)";
-
-# There is a pervasive dependency on the length (in hex characters,
-# i.e., nibbles) of an address, distinguishing between 32-bit and
-# 64-bit profiles. To err on the safe size, default to 64-bit here:
-my $address_length = 16;
-
-# A list of paths to search for shared object files
-my @prefix_list = ();
-
-# Special routine name that should not have any symbols.
-# Used as separator to parse "addr2line -i" output.
-my $sep_symbol = '_fini';
-my $sep_address = undef;
-
-my $OS = $^O;
-my $DEVNULL = "/dev/null";
-if ($^O =~ /MSWin32|cygwin|msys/) {
- $OS = "windows";
- $DEVNULL = "NUL";
-}
-
-##### Argument parsing #####
-
-sub usage_string {
- return <<EOF;
-Usage:
-pprof [options] <program> <profiles>
- <profiles> is a space separated list of profile names.
-pprof [options] <symbolized-profiles>
- <symbolized-profiles> is a list of profile files where each file contains
- the necessary symbol mappings as well as profile data (likely generated
- with --raw).
-pprof [options] <profile>
- <profile> is a remote form. Symbols are obtained from host:port$SYMBOL_PAGE
-
- Each name can be:
- /path/to/profile - a path to a profile file
- host:port[/<service>] - a location of a service to get profile from
-
- The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile,
- $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall,
- $THREAD_PAGE, $BLOCK_PAGE or /pprof/filteredprofile.
- For instance:
- pprof http://myserver.com:80$HEAP_PAGE
- If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profiling).
-pprof --symbols <program>
- Maps addresses to symbol names. In this mode, stdin should be a
- list of library mappings, in the same format as is found in the heap-
- and cpu-profile files (this loosely matches that of /proc/self/maps
- on linux), followed by a list of hex addresses to map, one per line.
-
- For more help with querying remote servers, including how to add the
- necessary server-side support code, see this filename (or one like it):
-
- /usr/doc/google-perftools-$PPROF_VERSION/pprof_remote_servers.html
-
-Options:
- --cum Sort by cumulative data
- --base=<base> Subtract <base> from <profile> before display
- --interactive Run in interactive mode (interactive "help" gives help) [default]
- --seconds=<n> Length of time for dynamic profiles [default=30 secs]
- --add_lib=<file> Read additional symbols and line info from the given library
- --lib_prefix=<dir> Comma separated list of library path prefixes
-
-Reporting Granularity:
- --addresses Report at address level
- --lines Report at source line level
- --functions Report at function level [default]
- --files Report at source file level
-
-Output type:
- --text Generate text report
- --callgrind Generate callgrind format to stdout
- --gv Generate Postscript and display
- --web Generate SVG and display
- --list=<regexp> Generate source listing of matching routines
- --disasm=<regexp> Generate disassembly of matching routines
- --symbols Print demangled symbol names found at given addresses
- --dot Generate DOT file to stdout
- --ps Generate Postcript to stdout
- --pdf Generate PDF to stdout
- --svg Generate SVG to stdout
- --gif Generate GIF to stdout
- --raw Generate symbolized pprof data (useful with remote fetch)
-
-Heap-Profile Options:
- --inuse_space Display in-use (mega)bytes [default]
- --inuse_objects Display in-use objects
- --alloc_space Display allocated (mega)bytes
- --alloc_objects Display allocated objects
- --show_bytes Display space in bytes
- --drop_negative Ignore negative differences
-
-Contention-profile options:
- --total_delay Display total delay at each region [default]
- --contentions Display number of delays at each region
- --mean_delay Display mean delay at each region
-
-Call-graph Options:
- --nodecount=<n> Show at most so many nodes [default=80]
- --nodefraction=<f> Hide nodes below <f>*total [default=.005]
- --edgefraction=<f> Hide edges below <f>*total [default=.001]
- --focus=<regexp> Focus on nodes matching <regexp>
- --ignore=<regexp> Ignore nodes matching <regexp>
- --scale=<n> Set GV scaling [default=0]
- --heapcheck Make nodes with non-0 object counts
- (i.e. direct leak generators) more visible
-
-Miscellaneous:
- --tools=<prefix> Prefix for object tool pathnames
- --test Run unit tests
- --help This message
- --version Version information
-
-Environment Variables:
- PPROF_TMPDIR Profiles directory. Defaults to \$HOME/pprof
- PPROF_TOOLS Prefix for object tools pathnames
-
-Examples:
-
-pprof /bin/ls ls.prof
- Enters "interactive" mode
-pprof --text /bin/ls ls.prof
- Outputs one line per procedure
-pprof --web /bin/ls ls.prof
- Displays annotated call-graph in web browser
-pprof --gv /bin/ls ls.prof
- Displays annotated call-graph via 'gv'
-pprof --gv --focus=Mutex /bin/ls ls.prof
- Restricts to code paths including a .*Mutex.* entry
-pprof --gv --focus=Mutex --ignore=string /bin/ls ls.prof
- Code paths including Mutex but not string
-pprof --list=getdir /bin/ls ls.prof
- (Per-line) annotated source listing for getdir()
-pprof --disasm=getdir /bin/ls ls.prof
- (Per-PC) annotated disassembly for getdir()
-
-pprof http://localhost:1234/
- Enters "interactive" mode
-pprof --text localhost:1234
- Outputs one line per procedure for localhost:1234
-pprof --raw localhost:1234 > ./local.raw
-pprof --text ./local.raw
- Fetches a remote profile for later analysis and then
- analyzes it in text mode.
-EOF
-}
-
-sub version_string {
- return <<EOF
-pprof (part of google-perftools $PPROF_VERSION)
-
-Copyright 1998-2007 Google Inc.
-
-This is BSD licensed software; see the source for copying conditions
-and license information.
-There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE.
-EOF
-}
-
-sub usage {
- my $msg = shift;
- print STDERR "$msg\n\n";
- print STDERR usage_string();
- print STDERR "\nFATAL ERROR: $msg\n"; # just as a reminder
- exit(1);
-}
-
-sub Init() {
- # Setup tmp-file name and handler to clean it up.
- # We do this in the very beginning so that we can use
- # error() and cleanup() function anytime here after.
- $main::tmpfile_sym = File::Temp->new()->filename;
- $main::tmpfile_ps = File::Temp->new()->filename;
-
- $main::next_tmpfile = 0;
- $SIG{'INT'} = \&sighandler;
-
- # Cache from filename/linenumber to source code
- $main::source_cache = ();
-
- $main::opt_help = 0;
- $main::opt_version = 0;
-
- $main::opt_cum = 0;
- $main::opt_base = '';
- $main::opt_addresses = 0;
- $main::opt_lines = 0;
- $main::opt_functions = 0;
- $main::opt_files = 0;
- $main::opt_lib_prefix = "";
-
- $main::opt_text = 0;
- $main::opt_callgrind = 0;
- $main::opt_list = "";
- $main::opt_disasm = "";
- $main::opt_symbols = 0;
- $main::opt_gv = 0;
- $main::opt_web = 0;
- $main::opt_dot = 0;
- $main::opt_ps = 0;
- $main::opt_pdf = 0;
- $main::opt_gif = 0;
- $main::opt_svg = 0;
- $main::opt_raw = 0;
-
- $main::opt_nodecount = 80;
- $main::opt_nodefraction = 0.005;
- $main::opt_edgefraction = 0.001;
- $main::opt_focus = '';
- $main::opt_ignore = '';
- $main::opt_scale = 0;
- $main::opt_heapcheck = 0;
- $main::opt_seconds = 30;
- $main::opt_lib = "";
-
- $main::opt_inuse_space = 0;
- $main::opt_inuse_objects = 0;
- $main::opt_alloc_space = 0;
- $main::opt_alloc_objects = 0;
- $main::opt_show_bytes = 0;
- $main::opt_drop_negative = 0;
- $main::opt_interactive = 0;
-
- $main::opt_total_delay = 0;
- $main::opt_contentions = 0;
- $main::opt_mean_delay = 0;
-
- $main::opt_tools = "";
- $main::opt_debug = 0;
- $main::opt_test = 0;
-
- # These are undocumented flags used only by unittests.
- $main::opt_test_stride = 0;
-
- # Are we using $SYMBOL_PAGE?
- $main::use_symbol_page = 0;
-
- # Files returned by TempName.
- %main::tempnames = ();
-
- # Type of profile we are dealing with
- # Supported types:
- # cpu
- # heap
- # growth
- # contention
- $main::profile_type = ''; # Empty type means "unknown"
-
- GetOptions("help!" => \$main::opt_help,
- "version!" => \$main::opt_version,
- "cum!" => \$main::opt_cum,
- "base=s" => \$main::opt_base,
- "seconds=i" => \$main::opt_seconds,
- "add_lib=s" => \$main::opt_lib,
- "lib_prefix=s" => \$main::opt_lib_prefix,
- "functions!" => \$main::opt_functions,
- "lines!" => \$main::opt_lines,
- "addresses!" => \$main::opt_addresses,
- "files!" => \$main::opt_files,
- "text!" => \$main::opt_text,
- "callgrind!" => \$main::opt_callgrind,
- "list=s" => \$main::opt_list,
- "disasm=s" => \$main::opt_disasm,
- "symbols!" => \$main::opt_symbols,
- "gv!" => \$main::opt_gv,
- "web!" => \$main::opt_web,
- "dot!" => \$main::opt_dot,
- "ps!" => \$main::opt_ps,
- "pdf!" => \$main::opt_pdf,
- "svg!" => \$main::opt_svg,
- "gif!" => \$main::opt_gif,
- "raw!" => \$main::opt_raw,
- "interactive!" => \$main::opt_interactive,
- "nodecount=i" => \$main::opt_nodecount,
- "nodefraction=f" => \$main::opt_nodefraction,
- "edgefraction=f" => \$main::opt_edgefraction,
- "focus=s" => \$main::opt_focus,
- "ignore=s" => \$main::opt_ignore,
- "scale=i" => \$main::opt_scale,
- "heapcheck" => \$main::opt_heapcheck,
- "inuse_space!" => \$main::opt_inuse_space,
- "inuse_objects!" => \$main::opt_inuse_objects,
- "alloc_space!" => \$main::opt_alloc_space,
- "alloc_objects!" => \$main::opt_alloc_objects,
- "show_bytes!" => \$main::opt_show_bytes,
- "drop_negative!" => \$main::opt_drop_negative,
- "total_delay!" => \$main::opt_total_delay,
- "contentions!" => \$main::opt_contentions,
- "mean_delay!" => \$main::opt_mean_delay,
- "tools=s" => \$main::opt_tools,
- "test!" => \$main::opt_test,
- "debug!" => \$main::opt_debug,
- # Undocumented flags used only by unittests:
- "test_stride=i" => \$main::opt_test_stride,
- ) || usage("Invalid option(s)");
-
- # Deal with the standard --help and --version
- if ($main::opt_help) {
- print usage_string();
- exit(0);
- }
-
- if ($main::opt_version) {
- print version_string();
- exit(0);
- }
-
- # Disassembly/listing/symbols mode requires address-level info
- if ($main::opt_disasm || $main::opt_list || $main::opt_symbols) {
- $main::opt_functions = 0;
- $main::opt_lines = 0;
- $main::opt_addresses = 1;
- $main::opt_files = 0;
- }
-
- # Check heap-profiling flags
- if ($main::opt_inuse_space +
- $main::opt_inuse_objects +
- $main::opt_alloc_space +
- $main::opt_alloc_objects > 1) {
- usage("Specify at most on of --inuse/--alloc options");
- }
-
- # Check output granularities
- my $grains =
- $main::opt_functions +
- $main::opt_lines +
- $main::opt_addresses +
- $main::opt_files +
- 0;
- if ($grains > 1) {
- usage("Only specify one output granularity option");
- }
- if ($grains == 0) {
- $main::opt_functions = 1;
- }
-
- # Check output modes
- my $modes =
- $main::opt_text +
- $main::opt_callgrind +
- ($main::opt_list eq '' ? 0 : 1) +
- ($main::opt_disasm eq '' ? 0 : 1) +
- ($main::opt_symbols == 0 ? 0 : 1) +
- $main::opt_gv +
- $main::opt_web +
- $main::opt_dot +
- $main::opt_ps +
- $main::opt_pdf +
- $main::opt_svg +
- $main::opt_gif +
- $main::opt_raw +
- $main::opt_interactive +
- 0;
- if ($modes > 1) {
- usage("Only specify one output mode");
- }
- if ($modes == 0) {
- if (-t STDOUT) { # If STDOUT is a tty, activate interactive mode
- $main::opt_interactive = 1;
- } else {
- $main::opt_text = 1;
- }
- }
-
- if ($main::opt_test) {
- RunUnitTests();
- # Should not return
- exit(1);
- }
-
- # Binary name and profile arguments list
- $main::prog = "";
- @main::pfile_args = ();
-
- # Remote profiling without a binary (using $SYMBOL_PAGE instead)
- if (IsProfileURL($ARGV[0])) {
- $main::use_symbol_page = 1;
- } elsif ($ARGV[0] && IsSymbolizedProfileFile($ARGV[0])) {
- $main::use_symbolized_profile = 1;
- $main::prog = $UNKNOWN_BINARY; # will be set later from the profile file
- }
-
- if ($main::use_symbol_page || $main::use_symbolized_profile) {
- # We don't need a binary!
- my %disabled = ('--lines' => $main::opt_lines,
- '--disasm' => $main::opt_disasm);
- for my $option (keys %disabled) {
- usage("$option cannot be used without a binary") if $disabled{$option};
- }
- # Set $main::prog later...
- scalar(@ARGV) || usage("Did not specify profile file");
- } elsif ($main::opt_symbols) {
- # --symbols needs a binary-name (to run nm on, etc) but not profiles
- $main::prog = shift(@ARGV) || usage("Did not specify program");
- } else {
- $main::prog = shift(@ARGV) || usage("Did not specify program");
- scalar(@ARGV) || usage("Did not specify profile file");
- }
-
- # Parse profile file/location arguments
- foreach my $farg (@ARGV) {
- if ($farg =~ m/(.*)\@([0-9]+)(|\/.*)$/ ) {
- my $machine = $1;
- my $num_machines = $2;
- my $path = $3;
- for (my $i = 0; $i < $num_machines; $i++) {
- unshift(@main::pfile_args, "$i.$machine$path");
- }
- } else {
- unshift(@main::pfile_args, $farg);
- }
- }
-
- if ($main::use_symbol_page) {
- unless (IsProfileURL($main::pfile_args[0])) {
- error("The first profile should be a remote form to use $SYMBOL_PAGE\n");
- }
- CheckSymbolPage();
- $main::prog = FetchProgramName();
- } elsif (!$main::use_symbolized_profile) { # may not need objtools!
- ConfigureObjTools($main::prog)
- }
-
- # Break the opt_lib_prefix into the prefix_list array
- @prefix_list = split (',', $main::opt_lib_prefix);
-
- # Remove trailing / from the prefixes, in the list to prevent
- # searching things like /my/path//lib/mylib.so
- foreach (@prefix_list) {
- s|/+$||;
- }
-}
-
-sub Main() {
- Init();
- $main::collected_profile = undef;
- @main::profile_files = ();
- $main::op_time = time();
-
- # Printing symbols is special and requires a lot less info that most.
- if ($main::opt_symbols) {
- PrintSymbols(*STDIN); # Get /proc/maps and symbols output from stdin
- return;
- }
-
- # Fetch all profile data
- FetchDynamicProfiles();
-
- # this will hold symbols that we read from the profile files
- my $symbol_map = {};
-
- # Read one profile, pick the last item on the list
- my $data = ReadProfile($main::prog, pop(@main::profile_files));
- my $profile = $data->{profile};
- my $pcs = $data->{pcs};
- my $libs = $data->{libs}; # Info about main program and shared libraries
- $symbol_map = MergeSymbols($symbol_map, $data->{symbols});
-
- # Add additional profiles, if available.
- if (scalar(@main::profile_files) > 0) {
- foreach my $pname (@main::profile_files) {
- my $data2 = ReadProfile($main::prog, $pname);
- $profile = AddProfile($profile, $data2->{profile});
- $pcs = AddPcs($pcs, $data2->{pcs});
- $symbol_map = MergeSymbols($symbol_map, $data2->{symbols});
- }
- }
-
- # Subtract base from profile, if specified
- if ($main::opt_base ne '') {
- my $base = ReadProfile($main::prog, $main::opt_base);
- $profile = SubtractProfile($profile, $base->{profile});
- $pcs = AddPcs($pcs, $base->{pcs});
- $symbol_map = MergeSymbols($symbol_map, $base->{symbols});
- }
-
- # Get total data in profile
- my $total = TotalProfile($profile);
-
- # Collect symbols
- my $symbols;
- if ($main::use_symbolized_profile) {
- $symbols = FetchSymbols($pcs, $symbol_map);
- } elsif ($main::use_symbol_page) {
- $symbols = FetchSymbols($pcs);
- } else {
- $symbols = ExtractSymbols($libs, $pcs);
- }
-
- # Remove uniniteresting stack items
- $profile = RemoveUninterestingFrames($symbols, $profile);
-
- # Focus?
- if ($main::opt_focus ne '') {
- $profile = FocusProfile($symbols, $profile, $main::opt_focus);
- }
-
- # Ignore?
- if ($main::opt_ignore ne '') {
- $profile = IgnoreProfile($symbols, $profile, $main::opt_ignore);
- }
-
- my $calls = ExtractCalls($symbols, $profile);
-
- # Reduce profiles to required output granularity, and also clean
- # each stack trace so a given entry exists at most once.
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- # Print
- if (!$main::opt_interactive) {
- if ($main::opt_disasm) {
- PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm, $total);
- } elsif ($main::opt_list) {
- PrintListing($total, $libs, $flat, $cumulative, $main::opt_list, 0);
- } elsif ($main::opt_text) {
- # Make sure the output is empty when have nothing to report
- # (only matters when --heapcheck is given but we must be
- # compatible with old branches that did not pass --heapcheck always):
- if ($total != 0) {
- Infof("Total: %s %s\n", Unparse($total), Units());
- }
- PrintText($symbols, $flat, $cumulative, $total, -1);
- } elsif ($main::opt_raw) {
- PrintSymbolizedProfile($symbols, $profile, $main::prog);
- } elsif ($main::opt_callgrind) {
- PrintCallgrind($calls);
- } else {
- if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {
- if ($main::opt_gv) {
- RunGV(TempName($main::next_tmpfile, "ps"), "");
- } elsif ($main::opt_web) {
- my $tmp = TempName($main::next_tmpfile, "svg");
- RunWeb($tmp);
- # The command we run might hand the file name off
- # to an already running browser instance and then exit.
- # Normally, we'd remove $tmp on exit (right now),
- # but fork a child to remove $tmp a little later, so that the
- # browser has time to load it first.
- delete $main::tempnames{$tmp};
- if (fork() == 0) {
- sleep 5;
- unlink($tmp);
- exit(0);
- }
- }
- } else {
- exit(1);
- }
- }
- } else {
- InteractiveMode($profile, $symbols, $libs, $total);
- }
-
- cleanup();
- exit(0);
-}
-
-##### Entry Point #####
-
-Main();
-
-# Temporary code to detect if we're running on a Goobuntu system.
-# These systems don't have the right stuff installed for the special
-# Readline libraries to work, so as a temporary workaround, we default
-# to using the normal stdio code, rather than the fancier readline-based
-# code
-sub ReadlineMightFail {
- if (-e '/lib/libtermcap.so.2') {
- return 0; # libtermcap exists, so readline should be okay
- } else {
- return 1;
- }
-}
-
-sub RunGV {
- my $fname = shift;
- my $bg = shift; # "" or " &" if we should run in background
- if (!system("$GV --version >$DEVNULL 2>&1")) {
- # Options using double dash are supported by this gv version.
- # Also, turn on noantialias to better handle bug in gv for
- # postscript files with large dimensions.
- # TODO: Maybe we should not pass the --noantialias flag
- # if the gv version is known to work properly without the flag.
- system("$GV --scale=$main::opt_scale --noantialias " . $fname . $bg);
- } else {
- # Old gv version - only supports options that use single dash.
- print STDERR "$GV -scale $main::opt_scale\n";
- system("$GV -scale $main::opt_scale " . $fname . $bg);
- }
-}
-
-sub RunWeb {
- my $fname = shift;
- print STDERR "Loading web page file:///$fname\n";
-
- if (`uname` =~ /Darwin/) {
- # OS X: open will use standard preference for SVG files.
- system("/usr/bin/open", $fname);
- return;
- }
-
- if (`uname` =~ /CYGWIN/) {
- # Windows(cygwin): open will use standard preference for SVG files.
- my $winname = `cygpath -wa $fname`;
- system("explorer.exe", $winname);
- return;
- }
-
- # Some kind of Unix; try generic symlinks, then specific browsers.
- # (Stop once we find one.)
- # Works best if the browser is already running.
- my @alt = (
- "/etc/alternatives/gnome-www-browser",
- "/etc/alternatives/x-www-browser",
- "google-chrome",
- "firefox",
- );
- foreach my $b (@alt) {
- if (system($b, $fname) == 0) {
- return;
- }
- }
-
- print STDERR "Could not load web browser.\n";
-}
-
-sub RunKcachegrind {
- my $fname = shift;
- my $bg = shift; # "" or " &" if we should run in background
- print STDERR "Starting '$KCACHEGRIND " . $fname . $bg . "'\n";
- system("$KCACHEGRIND " . $fname . $bg);
-}
-
-
-##### Interactive helper routines #####
-
-sub InteractiveMode {
- $| = 1; # Make output unbuffered for interactive mode
- my ($orig_profile, $symbols, $libs, $total) = @_;
-
- print STDERR "Welcome to pprof! For help, type 'help'.\n";
-
- # Use ReadLine if it's installed and input comes from a console.
- if ( -t STDIN &&
- !ReadlineMightFail() &&
- defined(eval {require Term::ReadLine}) ) {
- my $term = new Term::ReadLine 'pprof';
- while ( defined ($_ = $term->readline('(pprof) '))) {
- $term->addhistory($_) if /\S/;
- if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {
- last; # exit when we get an interactive command to quit
- }
- }
- } else { # don't have readline
- while (1) {
- print STDERR "(pprof) ";
- $_ = <STDIN>;
- last if ! defined $_ ;
- s/\r//g; # turn windows-looking lines into unix-looking lines
-
- # Save some flags that might be reset by InteractiveCommand()
- my $save_opt_lines = $main::opt_lines;
-
- if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {
- last; # exit when we get an interactive command to quit
- }
-
- # Restore flags
- $main::opt_lines = $save_opt_lines;
- }
- }
-}
-
-# Takes two args: orig profile, and command to run.
-# Returns 1 if we should keep going, or 0 if we were asked to quit
-sub InteractiveCommand {
- my($orig_profile, $symbols, $libs, $total, $command) = @_;
- $_ = $command; # just to make future m//'s easier
- if (!defined($_)) {
- print STDERR "\n";
- return 0;
- }
- if (m/^\s*quit/) {
- return 0;
- }
- if (m/^\s*help/) {
- InteractiveHelpMessage();
- return 1;
- }
- # Clear all the mode options -- mode is controlled by "$command"
- $main::opt_text = 0;
- $main::opt_callgrind = 0;
- $main::opt_disasm = 0;
- $main::opt_list = 0;
- $main::opt_gv = 0;
- $main::opt_cum = 0;
-
- if (m/^\s*(text|top)(\d*)\s*(.*)/) {
- $main::opt_text = 1;
-
- my $line_limit = ($2 ne "") ? int($2) : 10;
-
- my $routine;
- my $ignore;
- ($routine, $ignore) = ParseInteractiveArgs($3);
-
- my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore);
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- PrintText($symbols, $flat, $cumulative, $total, $line_limit);
- return 1;
- }
- if (m/^\s*callgrind\s*([^ \n]*)/) {
- $main::opt_callgrind = 1;
-
- # Get derived profiles
- my $calls = ExtractCalls($symbols, $orig_profile);
- my $filename = $1;
- if ( $1 eq '' ) {
- $filename = TempName($main::next_tmpfile, "callgrind");
- }
- PrintCallgrind($calls, $filename);
- if ( $1 eq '' ) {
- RunKcachegrind($filename, " & ");
- $main::next_tmpfile++;
- }
-
- return 1;
- }
- if (m/^\s*(web)?list\s*(.+)/) {
- my $html = (defined($1) && ($1 eq "web"));
- $main::opt_list = 1;
-
- my $routine;
- my $ignore;
- ($routine, $ignore) = ParseInteractiveArgs($2);
-
- my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore);
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- PrintListing($total, $libs, $flat, $cumulative, $routine, $html);
- return 1;
- }
- if (m/^\s*disasm\s*(.+)/) {
- $main::opt_disasm = 1;
-
- my $routine;
- my $ignore;
- ($routine, $ignore) = ParseInteractiveArgs($1);
-
- # Process current profile to account for various settings
- my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore);
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- PrintDisassembly($libs, $flat, $cumulative, $routine, $total);
- return 1;
- }
- if (m/^\s*(gv|web)\s*(.*)/) {
- $main::opt_gv = 0;
- $main::opt_web = 0;
- if ($1 eq "gv") {
- $main::opt_gv = 1;
- } elsif ($1 eq "web") {
- $main::opt_web = 1;
- }
-
- my $focus;
- my $ignore;
- ($focus, $ignore) = ParseInteractiveArgs($2);
-
- # Process current profile to account for various settings
- my $profile = ProcessProfile($total, $orig_profile, $symbols, $focus, $ignore);
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {
- if ($main::opt_gv) {
- RunGV(TempName($main::next_tmpfile, "ps"), " &");
- } elsif ($main::opt_web) {
- RunWeb(TempName($main::next_tmpfile, "svg"));
- }
- $main::next_tmpfile++;
- }
- return 1;
- }
- if (m/^\s*$/) {
- return 1;
- }
- print STDERR "Unknown command: try 'help'.\n";
- return 1;
-}
-
-
-sub ProcessProfile {
- my $total_count = shift;
- my $orig_profile = shift;
- my $symbols = shift;
- my $focus = shift;
- my $ignore = shift;
-
- # Process current profile to account for various settings
- my $profile = $orig_profile;
- printf("Total: %s %s\n", Unparse($total_count), Units());
- if ($focus ne '') {
- $profile = FocusProfile($symbols, $profile, $focus);
- my $focus_count = TotalProfile($profile);
- Infof("After focusing on '%s': %s %s of %s (%0.1f%%)\n",
- $focus,
- Unparse($focus_count), Units(),
- Unparse($total_count), ($focus_count*100.0) / $total_count);
- }
- if ($ignore ne '') {
- $profile = IgnoreProfile($symbols, $profile, $ignore);
- my $ignore_count = TotalProfile($profile);
- Infof("After ignoring '%s': %s %s of %s (%0.1f%%)\n",
- $ignore,
- Unparse($ignore_count), Units(),
- Unparse($total_count),
- ($ignore_count*100.0) / $total_count);
- }
-
- return $profile;
-}
-
-sub InteractiveHelpMessage {
- print STDERR <<ENDOFHELP;
-Interactive pprof mode
-
-Commands:
- gv
- gv [focus] [-ignore1] [-ignore2]
- Show graphical hierarchical display of current profile. Without
- any arguments, shows all samples in the profile. With the optional
- "focus" argument, restricts the samples shown to just those where
- the "focus" regular expression matches a routine name on the stack
- trace.
-
- web
- web [focus] [-ignore1] [-ignore2]
- Like GV, but displays profile in your web browser instead of using
- Ghostview. Works best if your web browser is already running.
- To change the browser that gets used:
- On Linux, set the /etc/alternatives/gnome-www-browser symlink.
- On OS X, change the Finder association for SVG files.
-
- list [routine_regexp] [-ignore1] [-ignore2]
- Show source listing of routines whose names match "routine_regexp"
-
- weblist [routine_regexp] [-ignore1] [-ignore2]
- Displays a source listing of routines whose names match "routine_regexp"
- in a web browser. You can click on source lines to view the
- corresponding disassembly.
-
- top [--cum] [-ignore1] [-ignore2]
- top20 [--cum] [-ignore1] [-ignore2]
- top37 [--cum] [-ignore1] [-ignore2]
- Show top lines ordered by flat profile count, or cumulative count
- if --cum is specified. If a number is present after 'top', the
- top K routines will be shown (defaults to showing the top 10)
-
- disasm [routine_regexp] [-ignore1] [-ignore2]
- Show disassembly of routines whose names match "routine_regexp",
- annotated with sample counts.
-
- callgrind
- callgrind [filename]
- Generates callgrind file. If no filename is given, kcachegrind is called.
-
- help - This listing
- quit or ^D - End pprof
-
-For commands that accept optional -ignore tags, samples where any routine in
-the stack trace matches the regular expression in any of the -ignore
-parameters will be ignored.
-
-Further pprof details are available at this location (or one similar):
-
- /usr/doc/google-perftools-$PPROF_VERSION/cpu_profiler.html
- /usr/doc/google-perftools-$PPROF_VERSION/heap_profiler.html
-
-ENDOFHELP
-}
-sub ParseInteractiveArgs {
- my $args = shift;
- my $focus = "";
- my $ignore = "";
- my @x = split(/ +/, $args);
- foreach $a (@x) {
- if ($a =~ m/^(--|-)lines$/) {
- $main::opt_lines = 1;
- } elsif ($a =~ m/^(--|-)cum$/) {
- $main::opt_cum = 1;
- } elsif ($a =~ m/^-(.*)/) {
- $ignore .= (($ignore ne "") ? "|" : "" ) . $1;
- } else {
- $focus .= (($focus ne "") ? "|" : "" ) . $a;
- }
- }
- if ($ignore ne "") {
- print STDERR "Ignoring samples in call stacks that match '$ignore'\n";
- }
- return ($focus, $ignore);
-}
-
-##### Output code #####
-
-sub TempName {
- my $fnum = shift;
- my $ext = shift;
- my $file = "$main::tmpfile_ps.$fnum.$ext";
- $main::tempnames{$file} = 1;
- return $file;
-}
-
-# Print profile data in packed binary format (64-bit) to standard out
-sub PrintProfileData {
- my $profile = shift;
-
- # print header (64-bit style)
- # (zero) (header-size) (version) (sample-period) (zero)
- print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0);
-
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- if ($#addrs >= 0) {
- my $depth = $#addrs + 1;
- # int(foo / 2**32) is the only reliable way to get rid of bottom
- # 32 bits on both 32- and 64-bit systems.
- print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32));
- print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32));
-
- foreach my $full_addr (@addrs) {
- my $addr = $full_addr;
- $addr =~ s/0x0*//; # strip off leading 0x, zeroes
- if (length($addr) > 16) {
- print STDERR "Invalid address in profile: $full_addr\n";
- next;
- }
- my $low_addr = substr($addr, -8); # get last 8 hex chars
- my $high_addr = substr($addr, -16, 8); # get up to 8 more hex chars
- print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr));
- }
- }
- }
-}
-
-# Print symbols and profile data
-sub PrintSymbolizedProfile {
- my $symbols = shift;
- my $profile = shift;
- my $prog = shift;
-
- $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $symbol_marker = $&;
-
- print '--- ', $symbol_marker, "\n";
- if (defined($prog)) {
- print 'binary=', $prog, "\n";
- }
- while (my ($pc, $name) = each(%{$symbols})) {
- my $sep = ' ';
- print '0x', $pc;
- # We have a list of function names, which include the inlined
- # calls. They are separated (and terminated) by --, which is
- # illegal in function names.
- for (my $j = 2; $j <= $#{$name}; $j += 3) {
- print $sep, $name->[$j];
- $sep = '--';
- }
- print "\n";
- }
- print '---', "\n";
-
- $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $profile_marker = $&;
- print '--- ', $profile_marker, "\n";
- if (defined($main::collected_profile)) {
- # if used with remote fetch, simply dump the collected profile to output.
- open(SRC, "<$main::collected_profile");
- while (<SRC>) {
- print $_;
- }
- close(SRC);
- } else {
- # dump a cpu-format profile to standard out
- PrintProfileData($profile);
- }
-}
-
-# Print information conditionally filtered out depending on the output
-# format.
-sub Infof {
- my $format = shift;
- my @args = @_;
- return if $main::opt_svg;
- printf($format, @args);
-}
-
-# Print text output
-sub PrintText {
- my $symbols = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $total = shift;
- my $line_limit = shift;
-
- # Which profile to sort by?
- my $s = $main::opt_cum ? $cumulative : $flat;
-
- my $running_sum = 0;
- my $lines = 0;
- foreach my $k (sort { GetEntry($s, $b) <=> GetEntry($s, $a) || $a cmp $b }
- keys(%{$cumulative})) {
- my $f = GetEntry($flat, $k);
- my $c = GetEntry($cumulative, $k);
- $running_sum += $f;
-
- my $sym = $k;
- if (exists($symbols->{$k})) {
- $sym = $symbols->{$k}->[0] . " " . $symbols->{$k}->[1];
- if ($main::opt_addresses) {
- $sym = $k . " " . $sym;
- }
- }
-
- if ($f != 0 || $c != 0) {
- printf("%8s %6s %6s %8s %6s %s\n",
- Unparse($f),
- Percent($f, $total),
- Percent($running_sum, $total),
- Unparse($c),
- Percent($c, $total),
- $sym);
- }
- $lines++;
- last if ($line_limit >= 0 && $lines >= $line_limit);
- }
-}
-
-# Print the call graph in a way that's suiteable for callgrind.
-sub PrintCallgrind {
- my $calls = shift;
- my $filename;
- if ($main::opt_interactive) {
- $filename = shift;
- print STDERR "Writing callgrind file to '$filename'.\n"
- } else {
- $filename = "&STDOUT";
- }
- open(CG, ">".$filename );
- printf CG ("events: Hits\n\n");
- foreach my $call ( map { $_->[0] }
- sort { $a->[1] cmp $b ->[1] ||
- $a->[2] <=> $b->[2] }
- map { /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/;
- [$_, $1, $2] }
- keys %$calls ) {
- my $count = int($calls->{$call});
- $call =~ /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/;
- my ( $caller_file, $caller_line, $caller_function,
- $callee_file, $callee_line, $callee_function ) =
- ( $1, $2, $3, $5, $6, $7 );
-
- printf CG ("fl=$caller_file\nfn=$caller_function\n");
- if (defined $6) {
- printf CG ("cfl=$callee_file\n");
- printf CG ("cfn=$callee_function\n");
- printf CG ("calls=$count $callee_line\n");
- }
- printf CG ("$caller_line $count\n\n");
- }
-}
-
-# Print disassembly for all all routines that match $main::opt_disasm
-sub PrintDisassembly {
- my $libs = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $disasm_opts = shift;
- my $total = shift;
-
- foreach my $lib (@{$libs}) {
- my $symbol_table = GetProcedureBoundaries($lib->[0], $disasm_opts);
- my $offset = AddressSub($lib->[1], $lib->[3]);
- foreach my $routine (sort ByName keys(%{$symbol_table})) {
- my $start_addr = $symbol_table->{$routine}->[0];
- my $end_addr = $symbol_table->{$routine}->[1];
- # See if there are any samples in this routine
- my $length = hex(AddressSub($end_addr, $start_addr));
- my $addr = AddressAdd($start_addr, $offset);
- for (my $i = 0; $i < $length; $i++) {
- if (defined($cumulative->{$addr})) {
- PrintDisassembledFunction($lib->[0], $offset,
- $routine, $flat, $cumulative,
- $start_addr, $end_addr, $total);
- last;
- }
- $addr = AddressInc($addr);
- }
- }
- }
-}
-
-# Return reference to array of tuples of the form:
-# [start_address, filename, linenumber, instruction, limit_address]
-# E.g.,
-# ["0x806c43d", "/foo/bar.cc", 131, "ret", "0x806c440"]
-sub Disassemble {
- my $prog = shift;
- my $offset = shift;
- my $start_addr = shift;
- my $end_addr = shift;
-
- my $objdump = $obj_tool_map{"objdump"};
- my $cmd = sprintf("$objdump -C -d -l --no-show-raw-insn " .
- "--start-address=0x$start_addr " .
- "--stop-address=0x$end_addr $prog");
-
- if (system("$objdump --help >$DEVNULL 2>&1") != 0) {
- # objdump must not exist. Fall back to go tool objdump.
- $objdump = "go tool objdump";
- $cmd = "$objdump $prog 0x$start_addr 0x$end_addr";
- }
-
- open(OBJDUMP, "$cmd |") || error("$objdump: $!\n");
- my @result = ();
- my $filename = "";
- my $linenumber = -1;
- my $last = ["", "", "", ""];
- while (<OBJDUMP>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- chop;
- if (m|\s*(.+):(\d+)\s*$|) {
- # Location line of the form:
- # <filename>:<linenumber>
- $filename = $1;
- $linenumber = $2;
- } elsif (m/^ +([0-9a-f]+):\s*(.*)/) {
- # Disassembly line -- zero-extend address to full length
- my $addr = HexExtend($1);
- my $k = AddressAdd($addr, $offset);
- $last->[4] = $k; # Store ending address for previous instruction
- $last = [$k, $filename, $linenumber, $2, $end_addr];
- push(@result, $last);
- }
- }
- close(OBJDUMP);
- return @result;
-}
-
-# The input file should contain lines of the form /proc/maps-like
-# output (same format as expected from the profiles) or that looks
-# like hex addresses (like "0xDEADBEEF"). We will parse all
-# /proc/maps output, and for all the hex addresses, we will output
-# "short" symbol names, one per line, in the same order as the input.
-sub PrintSymbols {
- my $maps_and_symbols_file = shift;
-
- # ParseLibraries expects pcs to be in a set. Fine by us...
- my @pclist = (); # pcs in sorted order
- my $pcs = {};
- my $map = "";
- foreach my $line (<$maps_and_symbols_file>) {
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- if ($line =~ /\b(0x[0-9a-f]+)\b/i) {
- push(@pclist, HexExtend($1));
- $pcs->{$pclist[-1]} = 1;
- } else {
- $map .= $line;
- }
- }
-
- my $libs = ParseLibraries($main::prog, $map, $pcs);
- my $symbols = ExtractSymbols($libs, $pcs);
-
- foreach my $pc (@pclist) {
- # ->[0] is the shortname, ->[2] is the full name
- print(($symbols->{$pc}->[0] || "??") . "\n");
- }
-}
-
-
-# For sorting functions by name
-sub ByName {
- return ShortFunctionName($a) cmp ShortFunctionName($b);
-}
-
-# Print source-listing for all all routines that match $main::opt_list
-sub PrintListing {
- my $total = shift;
- my $libs = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $list_opts = shift;
- my $html = shift;
-
- my $output = \*STDOUT;
- my $fname = "";
-
-
- if ($html) {
- # Arrange to write the output to a temporary file
- $fname = TempName($main::next_tmpfile, "html");
- $main::next_tmpfile++;
- if (!open(TEMP, ">$fname")) {
- print STDERR "$fname: $!\n";
- return;
- }
- $output = \*TEMP;
- print $output HtmlListingHeader();
- printf $output ("<div class=\"legend\">%s<br>Total: %s %s</div>\n",
- $main::prog, Unparse($total), Units());
- }
-
- my $listed = 0;
- foreach my $lib (@{$libs}) {
- my $symbol_table = GetProcedureBoundaries($lib->[0], $list_opts);
- my $offset = AddressSub($lib->[1], $lib->[3]);
- foreach my $routine (sort ByName keys(%{$symbol_table})) {
- # Print if there are any samples in this routine
- my $start_addr = $symbol_table->{$routine}->[0];
- my $end_addr = $symbol_table->{$routine}->[1];
- my $length = hex(AddressSub($end_addr, $start_addr));
- my $addr = AddressAdd($start_addr, $offset);
- for (my $i = 0; $i < $length; $i++) {
- if (defined($cumulative->{$addr})) {
- $listed += PrintSource(
- $lib->[0], $offset,
- $routine, $flat, $cumulative,
- $start_addr, $end_addr,
- $html,
- $output);
- last;
- }
- $addr = AddressInc($addr);
- }
- }
- }
-
- if ($html) {
- if ($listed > 0) {
- print $output HtmlListingFooter();
- close($output);
- RunWeb($fname);
- } else {
- close($output);
- unlink($fname);
- }
- }
-}
-
-sub HtmlListingHeader {
- return <<'EOF';
-<!DOCTYPE html>
-<html>
-<head>
-<title>Pprof listing</title>
-<style type="text/css">
-body {
- font-family: sans-serif;
-}
-h1 {
- font-size: 1.5em;
- margin-bottom: 4px;
-}
-.legend {
- font-size: 1.25em;
-}
-.line {
- color: #aaaaaa;
-}
-.livesrc {
- color: #0000ff;
- cursor: pointer;
-}
-.livesrc:hover {
- background-color: #cccccc;
-}
-.asm {
- color: #888888;
- display: none;
-}
-</style>
-<script type="text/javascript">
-function pprof_toggle_asm(e) {
- var target;
- if (!e) e = window.event;
- if (e.target) target = e.target;
- else if (e.srcElement) target = e.srcElement;
-
- if (target && target.className == "livesrc") {
- var asm = target.nextSibling;
- if (asm && asm.className == "asm") {
- asm.style.display = (asm.style.display == "block" ? "none" : "block");
- e.preventDefault();
- return false;
- }
- }
-}
-</script>
-</head>
-<body>
-EOF
-}
-
-sub HtmlListingFooter {
- return <<'EOF';
-</body>
-</html>
-EOF
-}
-
-sub HtmlEscape {
- my $text = shift;
- $text =~ s/&/&amp;/g;
- $text =~ s/</&lt;/g;
- $text =~ s/>/&gt;/g;
- return $text;
-}
-
-# Returns the indentation of the line, if it has any non-whitespace
-# characters. Otherwise, returns -1.
-sub Indentation {
- my $line = shift;
- if (m/^(\s*)\S/) {
- return length($1);
- } else {
- return -1;
- }
-}
-
-# Print source-listing for one routine
-sub PrintSource {
- my $prog = shift;
- my $offset = shift;
- my $routine = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $start_addr = shift;
- my $end_addr = shift;
- my $html = shift;
- my $output = shift;
-
- # Disassemble all instructions (just to get line numbers)
- my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);
-
- # Hack 1: assume that the first source file encountered in the
- # disassembly contains the routine
- my $filename = undef;
- for (my $i = 0; $i <= $#instructions; $i++) {
- if ($instructions[$i]->[2] >= 0) {
- $filename = $instructions[$i]->[1];
- last;
- }
- }
- if (!defined($filename)) {
- print STDERR "no filename found in $routine\n";
- return 0;
- }
-
- # Hack 2: assume that the largest line number from $filename is the
- # end of the procedure. This is typically safe since if P1 contains
- # an inlined call to P2, then P2 usually occurs earlier in the
- # source file. If this does not work, we might have to compute a
- # density profile or just print all regions we find.
- my $lastline = 0;
- for (my $i = 0; $i <= $#instructions; $i++) {
- my $f = $instructions[$i]->[1];
- my $l = $instructions[$i]->[2];
- if (($f eq $filename) && ($l > $lastline)) {
- $lastline = $l;
- }
- }
-
- # Hack 3: assume the first source location from "filename" is the start of
- # the source code.
- my $firstline = 1;
- for (my $i = 0; $i <= $#instructions; $i++) {
- if ($instructions[$i]->[1] eq $filename) {
- $firstline = $instructions[$i]->[2];
- last;
- }
- }
-
- # Hack 4: Extend last line forward until its indentation is less than
- # the indentation we saw on $firstline
- my $oldlastline = $lastline;
- {
- if (!open(FILE, "<$filename")) {
- print STDERR "$filename: $!\n";
- return 0;
- }
- my $l = 0;
- my $first_indentation = -1;
- while (<FILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- $l++;
- my $indent = Indentation($_);
- if ($l >= $firstline) {
- if ($first_indentation < 0 && $indent >= 0) {
- $first_indentation = $indent;
- last if ($first_indentation == 0);
- }
- }
- if ($l >= $lastline && $indent >= 0) {
- if ($indent >= $first_indentation) {
- $lastline = $l+1;
- } else {
- last;
- }
- }
- }
- close(FILE);
- }
-
- # Assign all samples to the range $firstline,$lastline,
- # Hack 4: If an instruction does not occur in the range, its samples
- # are moved to the next instruction that occurs in the range.
- my $samples1 = {}; # Map from line number to flat count
- my $samples2 = {}; # Map from line number to cumulative count
- my $running1 = 0; # Unassigned flat counts
- my $running2 = 0; # Unassigned cumulative counts
- my $total1 = 0; # Total flat counts
- my $total2 = 0; # Total cumulative counts
- my %disasm = (); # Map from line number to disassembly
- my $running_disasm = ""; # Unassigned disassembly
- my $skip_marker = "---\n";
- if ($html) {
- $skip_marker = "";
- for (my $l = $firstline; $l <= $lastline; $l++) {
- $disasm{$l} = "";
- }
- }
- foreach my $e (@instructions) {
- # Add up counts for all address that fall inside this instruction
- my $c1 = 0;
- my $c2 = 0;
- for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {
- $c1 += GetEntry($flat, $a);
- $c2 += GetEntry($cumulative, $a);
- }
-
- if ($html) {
- $running_disasm .= sprintf(" %6s %6s \t\t%8s: %s\n",
- HtmlPrintNumber($c1),
- HtmlPrintNumber($c2),
- $e->[0],
- CleanDisassembly($e->[3]));
- }
-
- $running1 += $c1;
- $running2 += $c2;
- $total1 += $c1;
- $total2 += $c2;
- my $file = $e->[1];
- my $line = $e->[2];
- if (($file eq $filename) &&
- ($line >= $firstline) &&
- ($line <= $lastline)) {
- # Assign all accumulated samples to this line
- AddEntry($samples1, $line, $running1);
- AddEntry($samples2, $line, $running2);
- $running1 = 0;
- $running2 = 0;
- if ($html) {
- $disasm{$line} .= $running_disasm;
- $running_disasm = '';
- }
- }
- }
-
- # Assign any leftover samples to $lastline
- AddEntry($samples1, $lastline, $running1);
- AddEntry($samples2, $lastline, $running2);
-
- if ($html) {
- printf $output (
- "<h1>%s</h1>%s\n<pre onClick=\"pprof_toggle_asm()\">\n" .
- "Total:%6s %6s (flat / cumulative %s)\n",
- HtmlEscape(ShortFunctionName($routine)),
- HtmlEscape($filename),
- Unparse($total1),
- Unparse($total2),
- Units());
- } else {
- printf $output (
- "ROUTINE ====================== %s in %s\n" .
- "%6s %6s Total %s (flat / cumulative)\n",
- ShortFunctionName($routine),
- $filename,
- Unparse($total1),
- Unparse($total2),
- Units());
- }
- if (!open(FILE, "<$filename")) {
- print STDERR "$filename: $!\n";
- return 0;
- }
- my $l = 0;
- while (<FILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- $l++;
- if ($l >= $firstline - 5 &&
- (($l <= $oldlastline + 5) || ($l <= $lastline))) {
- chop;
- my $text = $_;
- if ($l == $firstline) { print $output $skip_marker; }
- my $n1 = GetEntry($samples1, $l);
- my $n2 = GetEntry($samples2, $l);
- if ($html) {
- my $dis = $disasm{$l};
- if (!defined($dis) || $n1 + $n2 == 0) {
- # No samples/disassembly for this source line
- printf $output (
- "<span class=\"line\">%5d</span> " .
- "<span class=\"deadsrc\">%6s %6s %s</span>\n",
- $l,
- HtmlPrintNumber($n1),
- HtmlPrintNumber($n2),
- HtmlEscape($text));
- } else {
- printf $output (
- "<span class=\"line\">%5d</span> " .
- "<span class=\"livesrc\">%6s %6s %s</span>" .
- "<span class=\"asm\">%s</span>\n",
- $l,
- HtmlPrintNumber($n1),
- HtmlPrintNumber($n2),
- HtmlEscape($text),
- HtmlEscape($dis));
- }
- } else {
- printf $output(
- "%6s %6s %4d: %s\n",
- UnparseAlt($n1),
- UnparseAlt($n2),
- $l,
- $text);
- }
- if ($l == $lastline) { print $output $skip_marker; }
- };
- }
- close(FILE);
- if ($html) {
- print $output "</pre>\n";
- }
- return 1;
-}
-
-# Return the source line for the specified file/linenumber.
-# Returns undef if not found.
-sub SourceLine {
- my $file = shift;
- my $line = shift;
-
- # Look in cache
- if (!defined($main::source_cache{$file})) {
- if (100 < scalar keys(%main::source_cache)) {
- # Clear the cache when it gets too big
- $main::source_cache = ();
- }
-
- # Read all lines from the file
- if (!open(FILE, "<$file")) {
- print STDERR "$file: $!\n";
- $main::source_cache{$file} = []; # Cache the negative result
- return undef;
- }
- my $lines = [];
- push(@{$lines}, ""); # So we can use 1-based line numbers as indices
- while (<FILE>) {
- push(@{$lines}, $_);
- }
- close(FILE);
-
- # Save the lines in the cache
- $main::source_cache{$file} = $lines;
- }
-
- my $lines = $main::source_cache{$file};
- if (($line < 0) || ($line > $#{$lines})) {
- return undef;
- } else {
- return $lines->[$line];
- }
-}
-
-# Print disassembly for one routine with interspersed source if available
-sub PrintDisassembledFunction {
- my $prog = shift;
- my $offset = shift;
- my $routine = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $start_addr = shift;
- my $end_addr = shift;
- my $total = shift;
-
- # Disassemble all instructions
- my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);
-
- # Make array of counts per instruction
- my @flat_count = ();
- my @cum_count = ();
- my $flat_total = 0;
- my $cum_total = 0;
- foreach my $e (@instructions) {
- # Add up counts for all address that fall inside this instruction
- my $c1 = 0;
- my $c2 = 0;
- for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {
- $c1 += GetEntry($flat, $a);
- $c2 += GetEntry($cumulative, $a);
- }
- push(@flat_count, $c1);
- push(@cum_count, $c2);
- $flat_total += $c1;
- $cum_total += $c2;
- }
-
- # Print header with total counts
- printf("ROUTINE ====================== %s\n" .
- "%6s %6s %s (flat, cumulative) %.1f%% of total\n",
- ShortFunctionName($routine),
- Unparse($flat_total),
- Unparse($cum_total),
- Units(),
- ($cum_total * 100.0) / $total);
-
- # Process instructions in order
- my $current_file = "";
- for (my $i = 0; $i <= $#instructions; ) {
- my $e = $instructions[$i];
-
- # Print the new file name whenever we switch files
- if ($e->[1] ne $current_file) {
- $current_file = $e->[1];
- my $fname = $current_file;
- $fname =~ s|^\./||; # Trim leading "./"
-
- # Shorten long file names
- if (length($fname) >= 58) {
- $fname = "..." . substr($fname, -55);
- }
- printf("-------------------- %s\n", $fname);
- }
-
- # TODO: Compute range of lines to print together to deal with
- # small reorderings.
- my $first_line = $e->[2];
- my $last_line = $first_line;
- my %flat_sum = ();
- my %cum_sum = ();
- for (my $l = $first_line; $l <= $last_line; $l++) {
- $flat_sum{$l} = 0;
- $cum_sum{$l} = 0;
- }
-
- # Find run of instructions for this range of source lines
- my $first_inst = $i;
- while (($i <= $#instructions) &&
- ($instructions[$i]->[2] >= $first_line) &&
- ($instructions[$i]->[2] <= $last_line)) {
- $e = $instructions[$i];
- $flat_sum{$e->[2]} += $flat_count[$i];
- $cum_sum{$e->[2]} += $cum_count[$i];
- $i++;
- }
- my $last_inst = $i - 1;
-
- # Print source lines
- for (my $l = $first_line; $l <= $last_line; $l++) {
- my $line = SourceLine($current_file, $l);
- if (!defined($line)) {
- $line = "?\n";
- next;
- } else {
- $line =~ s/^\s+//;
- }
- printf("%6s %6s %5d: %s",
- UnparseAlt($flat_sum{$l}),
- UnparseAlt($cum_sum{$l}),
- $l,
- $line);
- }
-
- # Print disassembly
- for (my $x = $first_inst; $x <= $last_inst; $x++) {
- my $e = $instructions[$x];
- my $address = $e->[0];
- $address = AddressSub($address, $offset); # Make relative to section
- $address =~ s/^0x//;
- $address =~ s/^0*//;
-
- printf("%6s %6s %8s: %6s\n",
- UnparseAlt($flat_count[$x]),
- UnparseAlt($cum_count[$x]),
- $address,
- CleanDisassembly($e->[3]));
- }
- }
-}
-
-# Print DOT graph
-sub PrintDot {
- my $prog = shift;
- my $symbols = shift;
- my $raw = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $overall_total = shift;
-
- # Get total
- my $local_total = TotalProfile($flat);
- my $nodelimit = int($main::opt_nodefraction * $local_total);
- my $edgelimit = int($main::opt_edgefraction * $local_total);
- my $nodecount = $main::opt_nodecount;
-
- # Find nodes to include
- my @list = (sort { abs(GetEntry($cumulative, $b)) <=>
- abs(GetEntry($cumulative, $a))
- || $a cmp $b }
- keys(%{$cumulative}));
- my $last = $nodecount - 1;
- if ($last > $#list) {
- $last = $#list;
- }
- while (($last >= 0) &&
- (abs(GetEntry($cumulative, $list[$last])) <= $nodelimit)) {
- $last--;
- }
- if ($last < 0) {
- print STDERR "No nodes to print\n";
- cleanup();
- return 0;
- }
-
- if ($nodelimit > 0 || $edgelimit > 0) {
- printf STDERR ("Dropping nodes with <= %s %s; edges with <= %s abs(%s)\n",
- Unparse($nodelimit), Units(),
- Unparse($edgelimit), Units());
- }
-
- # Open DOT output file
- my $output;
- if ($main::opt_gv) {
- $output = "| $DOT -Tps2 >" . TempName($main::next_tmpfile, "ps");
- } elsif ($main::opt_ps) {
- $output = "| $DOT -Tps2";
- } elsif ($main::opt_pdf) {
- $output = "| $DOT -Tps2 | $PS2PDF - -";
- } elsif ($main::opt_web || $main::opt_svg) {
- # We need to post-process the SVG, so write to a temporary file always.
- $output = "| $DOT -Tsvg >" . TempName($main::next_tmpfile, "svg");
- } elsif ($main::opt_gif) {
- $output = "| $DOT -Tgif";
- } else {
- $output = ">&STDOUT";
- }
- open(DOT, $output) || error("$output: $!\n");
-
- # Title
- printf DOT ("digraph \"%s; %s %s\" {\n",
- $prog,
- Unparse($overall_total),
- Units());
- if ($main::opt_pdf) {
- # The output is more printable if we set the page size for dot.
- printf DOT ("size=\"8,11\"\n");
- }
- printf DOT ("node [width=0.375,height=0.25];\n");
-
- # Print legend
- printf DOT ("Legend [shape=box,fontsize=24,shape=plaintext," .
- "label=\"%s\\l%s\\l%s\\l%s\\l%s\\l\"];\n",
- $prog,
- sprintf("Total %s: %s", Units(), Unparse($overall_total)),
- sprintf("Focusing on: %s", Unparse($local_total)),
- sprintf("Dropped nodes with <= %s abs(%s)",
- Unparse($nodelimit), Units()),
- sprintf("Dropped edges with <= %s %s",
- Unparse($edgelimit), Units())
- );
-
- # Print nodes
- my %node = ();
- my $nextnode = 1;
- foreach my $a (@list[0..$last]) {
- # Pick font size
- my $f = GetEntry($flat, $a);
- my $c = GetEntry($cumulative, $a);
-
- my $fs = 8;
- if ($local_total > 0) {
- $fs = 8 + (50.0 * sqrt(abs($f * 1.0 / $local_total)));
- }
-
- $node{$a} = $nextnode++;
- my $sym = $a;
- $sym =~ s/\s+/\\n/g;
- $sym =~ s/::/\\n/g;
-
- # Extra cumulative info to print for non-leaves
- my $extra = "";
- if ($f != $c) {
- $extra = sprintf("\\rof %s (%s)",
- Unparse($c),
- Percent($c, $overall_total));
- }
- my $style = "";
- if ($main::opt_heapcheck) {
- if ($f > 0) {
- # make leak-causing nodes more visible (add a background)
- $style = ",style=filled,fillcolor=gray"
- } elsif ($f < 0) {
- # make anti-leak-causing nodes (which almost never occur)
- # stand out as well (triple border)
- $style = ",peripheries=3"
- }
- }
-
- printf DOT ("N%d [label=\"%s\\n%s (%s)%s\\r" .
- "\",shape=box,fontsize=%.1f%s];\n",
- $node{$a},
- $sym,
- Unparse($f),
- Percent($f, $overall_total),
- $extra,
- $fs,
- $style,
- );
- }
-
- # Get edges and counts per edge
- my %edge = ();
- my $n;
- foreach my $k (keys(%{$raw})) {
- # TODO: omit low %age edges
- $n = $raw->{$k};
- my @translated = TranslateStack($symbols, $k);
- for (my $i = 1; $i <= $#translated; $i++) {
- my $src = $translated[$i];
- my $dst = $translated[$i-1];
- #next if ($src eq $dst); # Avoid self-edges?
- if (exists($node{$src}) && exists($node{$dst})) {
- my $edge_label = "$src\001$dst";
- if (!exists($edge{$edge_label})) {
- $edge{$edge_label} = 0;
- }
- $edge{$edge_label} += $n;
- }
- }
- }
-
- # Print edges
- foreach my $e (keys(%edge)) {
- my @x = split(/\001/, $e);
- $n = $edge{$e};
-
- if (abs($n) > $edgelimit) {
- # Compute line width based on edge count
- my $fraction = abs($local_total ? (3 * ($n / $local_total)) : 0);
- if ($fraction > 1) { $fraction = 1; }
- my $w = $fraction * 2;
- if ($w < 1 && ($main::opt_web || $main::opt_svg)) {
- # SVG output treats line widths < 1 poorly.
- $w = 1;
- }
-
- # Dot sometimes segfaults if given edge weights that are too large, so
- # we cap the weights at a large value
- my $edgeweight = abs($n) ** 0.7;
- if ($edgeweight > 100000) { $edgeweight = 100000; }
- $edgeweight = int($edgeweight);
-
- my $style = sprintf("setlinewidth(%f)", $w);
- if ($x[1] =~ m/\(inline\)/) {
- $style .= ",dashed";
- }
-
- # Use a slightly squashed function of the edge count as the weight
- printf DOT ("N%s -> N%s [label=%s, weight=%d, style=\"%s\"];\n",
- $node{$x[0]},
- $node{$x[1]},
- Unparse($n),
- $edgeweight,
- $style);
- }
- }
-
- print DOT ("}\n");
- close(DOT);
-
- if ($main::opt_web || $main::opt_svg) {
- # Rewrite SVG to be more usable inside web browser.
- RewriteSvg(TempName($main::next_tmpfile, "svg"));
- }
-
- return 1;
-}
-
-sub RewriteSvg {
- my $svgfile = shift;
-
- open(SVG, $svgfile) || die "open temp svg: $!";
- my @svg = <SVG>;
- close(SVG);
- unlink $svgfile;
- my $svg = join('', @svg);
-
- # Dot's SVG output is
- #
- # <svg width="___" height="___"
- # viewBox="___" xmlns=...>
- # <g id="graph0" transform="...">
- # ...
- # </g>
- # </svg>
- #
- # Change it to
- #
- # <svg width="100%" height="100%"
- # xmlns=...>
- # $svg_javascript
- # <g id="viewport" transform="translate(0,0)">
- # <g id="graph0" transform="...">
- # ...
- # </g>
- # </g>
- # </svg>
-
- # Fix width, height; drop viewBox.
- $svg =~ s/(?s)<svg width="[^"]+" height="[^"]+"(.*?)viewBox="[^"]+"/<svg width="100%" height="100%"$1/;
-
- # Insert script, viewport <g> above first <g>
- my $svg_javascript = SvgJavascript();
- my $viewport = "<g id=\"viewport\" transform=\"translate(0,0)\">\n";
- $svg =~ s/<g id="graph\d"/$svg_javascript$viewport$&/;
-
- # Insert final </g> above </svg>.
- $svg =~ s/(.*)(<\/svg>)/$1<\/g>$2/;
- $svg =~ s/<g id="graph\d"(.*?)/<g id="viewport"$1/;
-
- if ($main::opt_svg) {
- # --svg: write to standard output.
- print $svg;
- } else {
- # Write back to temporary file.
- open(SVG, ">$svgfile") || die "open $svgfile: $!";
- print SVG $svg;
- close(SVG);
- }
-}
-
-sub SvgJavascript {
- return <<'EOF';
-<script type="text/ecmascript"><![CDATA[
-// SVGPan
-// http://www.cyberz.org/blog/2009/12/08/svgpan-a-javascript-svg-panzoomdrag-library/
-// Local modification: if(true || ...) below to force panning, never moving.
-// Local modification: add clamping to fix bug in handleMouseWheel.
-
-/**
- * SVGPan library 1.2
- * ====================
- *
- * Given an unique existing element with id "viewport", including the
- * the library into any SVG adds the following capabilities:
- *
- * - Mouse panning
- * - Mouse zooming (using the wheel)
- * - Object dargging
- *
- * Known issues:
- *
- * - Zooming (while panning) on Safari has still some issues
- *
- * Releases:
- *
- * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui
- * Fixed a bug with browser mouse handler interaction
- *
- * 1.1, Wed Feb 3 17:39:33 GMT 2010, Zeng Xiaohui
- * Updated the zoom code to support the mouse wheel on Safari/Chrome
- *
- * 1.0, Andrea Leofreddi
- * First release
- *
- * This code is licensed under the following BSD license:
- *
- * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``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 Andrea Leofreddi 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 views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of Andrea Leofreddi.
- */
-
-var root = document.documentElement;
-
-var state = 'none', stateTarget, stateOrigin, stateTf;
-
-setupHandlers(root);
-
-/**
- * Register handlers
- */
-function setupHandlers(root){
- setAttributes(root, {
- "onmouseup" : "add(evt)",
- "onmousedown" : "handleMouseDown(evt)",
- "onmousemove" : "handleMouseMove(evt)",
- "onmouseup" : "handleMouseUp(evt)",
- //"onmouseout" : "handleMouseUp(evt)", // Decomment this to stop the pan functionality when dragging out of the SVG element
- });
-
- if(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)
- window.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari
- else
- window.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others
-
- var g = svgDoc.getElementById("svg");
- g.width = "100%";
- g.height = "100%";
-}
-
-/**
- * Instance an SVGPoint object with given event coordinates.
- */
-function getEventPoint(evt) {
- var p = root.createSVGPoint();
-
- p.x = evt.clientX;
- p.y = evt.clientY;
-
- return p;
-}
-
-/**
- * Sets the current transform matrix of an element.
- */
-function setCTM(element, matrix) {
- var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")";
-
- element.setAttribute("transform", s);
-}
-
-/**
- * Dumps a matrix to a string (useful for debug).
- */
-function dumpMatrix(matrix) {
- var s = "[ " + matrix.a + ", " + matrix.c + ", " + matrix.e + "\n " + matrix.b + ", " + matrix.d + ", " + matrix.f + "\n 0, 0, 1 ]";
-
- return s;
-}
-
-/**
- * Sets attributes of an element.
- */
-function setAttributes(element, attributes){
- for (i in attributes)
- element.setAttributeNS(null, i, attributes[i]);
-}
-
-/**
- * Handle mouse move event.
- */
-function handleMouseWheel(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- var delta;
-
- if(evt.wheelDelta)
- delta = evt.wheelDelta / 3600; // Chrome/Safari
- else
- delta = evt.detail / -90; // Mozilla
-
- var z = 1 + delta; // Zoom factor: 0.9/1.1
-
- // Clamp to reasonable values.
- // The 0.1 check is important because
- // a very large scroll can turn into a
- // negative z, which rotates the image 180 degrees.
- if(z < 0.1)
- z = 0.1;
- if(z > 10.0)
- z = 10.0;
-
- var g = svgDoc.getElementById("viewport");
-
- var p = getEventPoint(evt);
-
- p = p.matrixTransform(g.getCTM().inverse());
-
- // Compute new scale matrix in current mouse position
- var k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);
-
- setCTM(g, g.getCTM().multiply(k));
-
- stateTf = stateTf.multiply(k.inverse());
-}
-
-/**
- * Handle mouse move event.
- */
-function handleMouseMove(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- var g = svgDoc.getElementById("viewport");
-
- if(state == 'pan') {
- // Pan mode
- var p = getEventPoint(evt).matrixTransform(stateTf);
-
- setCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y));
- } else if(state == 'move') {
- // Move mode
- var p = getEventPoint(evt).matrixTransform(g.getCTM().inverse());
-
- setCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM()));
-
- stateOrigin = p;
- }
-}
-
-/**
- * Handle click event.
- */
-function handleMouseDown(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- var g = svgDoc.getElementById("viewport");
-
- if(true || evt.target.tagName == "svg") {
- // Pan mode
- state = 'pan';
-
- stateTf = g.getCTM().inverse();
-
- stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
- } else {
- // Move mode
- state = 'move';
-
- stateTarget = evt.target;
-
- stateTf = g.getCTM().inverse();
-
- stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
- }
-}
-
-/**
- * Handle mouse button release event.
- */
-function handleMouseUp(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- if(state == 'pan' || state == 'move') {
- // Quit pan mode
- state = '';
- }
-}
-
-]]></script>
-EOF
-}
-
-# Translate a stack of addresses into a stack of symbols
-sub TranslateStack {
- my $symbols = shift;
- my $k = shift;
-
- my @addrs = split(/\n/, $k);
- my @result = ();
- for (my $i = 0; $i <= $#addrs; $i++) {
- my $a = $addrs[$i];
-
- # Skip large addresses since they sometimes show up as fake entries on RH9
- if (length($a) > 8 && $a gt "7fffffffffffffff") {
- next;
- }
-
- if ($main::opt_disasm || $main::opt_list) {
- # We want just the address for the key
- push(@result, $a);
- next;
- }
-
- my $symlist = $symbols->{$a};
- if (!defined($symlist)) {
- $symlist = [$a, "", $a];
- }
-
- # We can have a sequence of symbols for a particular entry
- # (more than one symbol in the case of inlining). Callers
- # come before callees in symlist, so walk backwards since
- # the translated stack should contain callees before callers.
- for (my $j = $#{$symlist}; $j >= 2; $j -= 3) {
- my $func = $symlist->[$j-2];
- my $fileline = $symlist->[$j-1];
- my $fullfunc = $symlist->[$j];
- if ($j > 2) {
- $func = "$func (inline)";
- }
- if ($main::opt_addresses) {
- push(@result, "$a $func $fileline");
- } elsif ($main::opt_lines) {
- if ($func eq '??' && $fileline eq '??:0') {
- push(@result, "$a");
- } else {
- push(@result, "$func $fileline");
- }
- } elsif ($main::opt_functions) {
- if ($func eq '??') {
- push(@result, "$a");
- } else {
- push(@result, $func);
- }
- } elsif ($main::opt_files) {
- if ($fileline eq '??:0' || $fileline eq '') {
- push(@result, "$a");
- } else {
- my $f = $fileline;
- $f =~ s/:\d+$//;
- push(@result, $f);
- }
- } else {
- push(@result, $a);
- last; # Do not print inlined info
- }
- }
- }
-
- # print join(",", @addrs), " => ", join(",", @result), "\n";
- return @result;
-}
-
-# Generate percent string for a number and a total
-sub Percent {
- my $num = shift;
- my $tot = shift;
- if ($tot != 0) {
- return sprintf("%.1f%%", $num * 100.0 / $tot);
- } else {
- return ($num == 0) ? "nan" : (($num > 0) ? "+inf" : "-inf");
- }
-}
-
-# Generate pretty-printed form of number
-sub Unparse {
- my $num = shift;
- if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {
- if ($main::opt_inuse_objects || $main::opt_alloc_objects) {
- return sprintf("%d", $num);
- } else {
- if ($main::opt_show_bytes) {
- return sprintf("%d", $num);
- } else {
- return sprintf("%.1f", $num / 1048576.0);
- }
- }
- } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {
- return sprintf("%.3f", $num / 1e9); # Convert nanoseconds to seconds
- } else {
- return sprintf("%d", $num);
- }
-}
-
-# Alternate pretty-printed form: 0 maps to "."
-sub UnparseAlt {
- my $num = shift;
- if ($num == 0) {
- return ".";
- } else {
- return Unparse($num);
- }
-}
-
-# Alternate pretty-printed form: 0 maps to ""
-sub HtmlPrintNumber {
- my $num = shift;
- if ($num == 0) {
- return "";
- } else {
- return Unparse($num);
- }
-}
-
-# Return output units
-sub Units {
- if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {
- if ($main::opt_inuse_objects || $main::opt_alloc_objects) {
- return "objects";
- } else {
- if ($main::opt_show_bytes) {
- return "B";
- } else {
- return "MB";
- }
- }
- } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {
- return "seconds";
- } elsif ($main::profile_type eq 'thread') {
- return "threads";
- } else {
- return "samples";
- }
-}
-
-##### Profile manipulation code #####
-
-# Generate flattened profile:
-# If count is charged to stack [a,b,c,d], in generated profile,
-# it will be charged to [a]
-sub FlatProfile {
- my $profile = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- if ($#addrs >= 0) {
- AddEntry($result, $addrs[0], $count);
- }
- }
- return $result;
-}
-
-# Generate cumulative profile:
-# If count is charged to stack [a,b,c,d], in generated profile,
-# it will be charged to [a], [b], [c], [d]
-sub CumulativeProfile {
- my $profile = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- foreach my $a (@addrs) {
- AddEntry($result, $a, $count);
- }
- }
- return $result;
-}
-
-# If the second-youngest PC on the stack is always the same, returns
-# that pc. Otherwise, returns undef.
-sub IsSecondPcAlwaysTheSame {
- my $profile = shift;
-
- my $second_pc = undef;
- foreach my $k (keys(%{$profile})) {
- my @addrs = split(/\n/, $k);
- if ($#addrs < 1) {
- return undef;
- }
- if (not defined $second_pc) {
- $second_pc = $addrs[1];
- } else {
- if ($second_pc ne $addrs[1]) {
- return undef;
- }
- }
- }
- return $second_pc;
-}
-
-sub ExtractSymbolLocation {
- my $symbols = shift;
- my $address = shift;
- # 'addr2line' outputs "??:0" for unknown locations; we do the
- # same to be consistent.
- my $location = "??:0:unknown";
- if (exists $symbols->{$address}) {
- my $file = $symbols->{$address}->[1];
- if ($file eq "?") {
- $file = "??:0"
- }
- $location = $file . ":" . $symbols->{$address}->[0];
- }
- return $location;
-}
-
-# Extracts a graph of calls.
-sub ExtractCalls {
- my $symbols = shift;
- my $profile = shift;
-
- my $calls = {};
- while( my ($stack_trace, $count) = each %$profile ) {
- my @address = split(/\n/, $stack_trace);
- my $destination = ExtractSymbolLocation($symbols, $address[0]);
- AddEntry($calls, $destination, $count);
- for (my $i = 1; $i <= $#address; $i++) {
- my $source = ExtractSymbolLocation($symbols, $address[$i]);
- my $call = "$source -> $destination";
- AddEntry($calls, $call, $count);
- $destination = $source;
- }
- }
-
- return $calls;
-}
-
-sub RemoveUninterestingFrames {
- my $symbols = shift;
- my $profile = shift;
-
- # List of function names to skip
- my %skip = ();
- my $skip_regexp = 'NOMATCH';
- if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {
- foreach my $name ('calloc',
- 'cfree',
- 'malloc',
- 'free',
- 'memalign',
- 'posix_memalign',
- 'pvalloc',
- 'valloc',
- 'realloc',
- 'tc_calloc',
- 'tc_cfree',
- 'tc_malloc',
- 'tc_free',
- 'tc_memalign',
- 'tc_posix_memalign',
- 'tc_pvalloc',
- 'tc_valloc',
- 'tc_realloc',
- 'tc_new',
- 'tc_delete',
- 'tc_newarray',
- 'tc_deletearray',
- 'tc_new_nothrow',
- 'tc_newarray_nothrow',
- 'do_malloc',
- '::do_malloc', # new name -- got moved to an unnamed ns
- '::do_malloc_or_cpp_alloc',
- 'DoSampledAllocation',
- 'simple_alloc::allocate',
- '__malloc_alloc_template::allocate',
- '__builtin_delete',
- '__builtin_new',
- '__builtin_vec_delete',
- '__builtin_vec_new',
- 'operator new',
- 'operator new[]',
- # Go
- 'catstring',
- 'cnew',
- 'copyin',
- 'gostring',
- 'gostringsize',
- 'growslice1',
- 'appendslice1',
- 'hash_init',
- 'hash_subtable_new',
- 'hash_conv',
- 'hash_grow',
- 'hash_insert_internal',
- 'hash_insert',
- 'mapassign',
- 'runtime.mapassign',
- 'runtime.appendslice',
- 'runtime.mapassign1',
- 'makechan',
- 'makemap',
- 'mal',
- 'profilealloc',
- 'runtime.new',
- 'makeslice1',
- 'runtime.malloc',
- 'unsafe.New',
- 'runtime.mallocgc',
- 'runtime.catstring',
- 'runtime.cnew',
- 'runtime.cnewarray',
- 'runtime.growslice',
- 'runtime.ifaceT2E',
- 'runtime.ifaceT2I',
- 'runtime.makechan',
- 'runtime.makechan_c',
- 'runtime.makemap',
- 'runtime.makemap_c',
- 'runtime.makeslice',
- 'runtime.mal',
- 'runtime.settype',
- 'runtime.settype_flush',
- 'runtime.slicebytetostring',
- 'runtime.sliceinttostring',
- 'runtime.stringtoslicebyte',
- 'runtime.stringtosliceint',
- # These mark the beginning/end of our custom sections
- '__start_google_malloc',
- '__stop_google_malloc',
- '__start_malloc_hook',
- '__stop_malloc_hook') {
- $skip{$name} = 1;
- $skip{"_" . $name} = 1; # Mach (OS X) adds a _ prefix to everything
- }
- # TODO: Remove TCMalloc once everything has been
- # moved into the tcmalloc:: namespace and we have flushed
- # old code out of the system.
- $skip_regexp = "TCMalloc|^tcmalloc::";
- } elsif ($main::profile_type eq 'contention') {
- foreach my $vname ('Mutex::Unlock', 'Mutex::UnlockSlow') {
- $skip{$vname} = 1;
- }
- } elsif ($main::profile_type eq 'cpu') {
- # Drop signal handlers used for CPU profile collection
- # TODO(dpeng): this should not be necessary; it's taken
- # care of by the general 2nd-pc mechanism below.
- foreach my $name ('ProfileData::Add', # historical
- 'ProfileData::prof_handler', # historical
- 'CpuProfiler::prof_handler',
- '__FRAME_END__',
- '__pthread_sighandler',
- '__restore') {
- $skip{$name} = 1;
- }
- } else {
- # Nothing skipped for unknown types
- }
-
- # Go doesn't have the problem that this heuristic tries to fix. Disable.
- if (0 && $main::profile_type eq 'cpu') {
- # If all the second-youngest program counters are the same,
- # this STRONGLY suggests that it is an artifact of measurement,
- # i.e., stack frames pushed by the CPU profiler signal handler.
- # Hence, we delete them.
- # (The topmost PC is read from the signal structure, not from
- # the stack, so it does not get involved.)
- while (my $second_pc = IsSecondPcAlwaysTheSame($profile)) {
- my $result = {};
- my $func = '';
- if (exists($symbols->{$second_pc})) {
- $second_pc = $symbols->{$second_pc}->[0];
- }
- print STDERR "Removing $second_pc from all stack traces.\n";
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- splice @addrs, 1, 1;
- my $reduced_path = join("\n", @addrs);
- AddEntry($result, $reduced_path, $count);
- }
- $profile = $result;
- }
- }
-
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- my @path = ();
- foreach my $a (@addrs) {
- if (exists($symbols->{$a})) {
- my $func = $symbols->{$a}->[0];
- if ($skip{$func} || ($func =~ m/$skip_regexp/)) {
- next;
- }
- }
- push(@path, $a);
- }
- my $reduced_path = join("\n", @path);
- AddEntry($result, $reduced_path, $count);
- }
- return $result;
-}
-
-# Reduce profile to granularity given by user
-sub ReduceProfile {
- my $symbols = shift;
- my $profile = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @translated = TranslateStack($symbols, $k);
- my @path = ();
- my %seen = ();
- $seen{''} = 1; # So that empty keys are skipped
- foreach my $e (@translated) {
- # To avoid double-counting due to recursion, skip a stack-trace
- # entry if it has already been seen
- if (!$seen{$e}) {
- $seen{$e} = 1;
- push(@path, $e);
- }
- }
- my $reduced_path = join("\n", @path);
- AddEntry($result, $reduced_path, $count);
- }
- return $result;
-}
-
-# Does the specified symbol array match the regexp?
-sub SymbolMatches {
- my $sym = shift;
- my $re = shift;
- if (defined($sym)) {
- for (my $i = 0; $i < $#{$sym}; $i += 3) {
- if ($sym->[$i] =~ m/$re/ || $sym->[$i+1] =~ m/$re/) {
- return 1;
- }
- }
- }
- return 0;
-}
-
-# Focus only on paths involving specified regexps
-sub FocusProfile {
- my $symbols = shift;
- my $profile = shift;
- my $focus = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- foreach my $a (@addrs) {
- # Reply if it matches either the address/shortname/fileline
- if (($a =~ m/$focus/) || SymbolMatches($symbols->{$a}, $focus)) {
- AddEntry($result, $k, $count);
- last;
- }
- }
- }
- return $result;
-}
-
-# Focus only on paths not involving specified regexps
-sub IgnoreProfile {
- my $symbols = shift;
- my $profile = shift;
- my $ignore = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- my $matched = 0;
- foreach my $a (@addrs) {
- # Reply if it matches either the address/shortname/fileline
- if (($a =~ m/$ignore/) || SymbolMatches($symbols->{$a}, $ignore)) {
- $matched = 1;
- last;
- }
- }
- if (!$matched) {
- AddEntry($result, $k, $count);
- }
- }
- return $result;
-}
-
-# Get total count in profile
-sub TotalProfile {
- my $profile = shift;
- my $result = 0;
- foreach my $k (keys(%{$profile})) {
- $result += $profile->{$k};
- }
- return $result;
-}
-
-# Add A to B
-sub AddProfile {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- # add all keys in A
- foreach my $k (keys(%{$A})) {
- my $v = $A->{$k};
- AddEntry($R, $k, $v);
- }
- # add all keys in B
- foreach my $k (keys(%{$B})) {
- my $v = $B->{$k};
- AddEntry($R, $k, $v);
- }
- return $R;
-}
-
-# Merges symbol maps
-sub MergeSymbols {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- foreach my $k (keys(%{$A})) {
- $R->{$k} = $A->{$k};
- }
- if (defined($B)) {
- foreach my $k (keys(%{$B})) {
- $R->{$k} = $B->{$k};
- }
- }
- return $R;
-}
-
-
-# Add A to B
-sub AddPcs {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- # add all keys in A
- foreach my $k (keys(%{$A})) {
- $R->{$k} = 1
- }
- # add all keys in B
- foreach my $k (keys(%{$B})) {
- $R->{$k} = 1
- }
- return $R;
-}
-
-# Subtract B from A
-sub SubtractProfile {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- foreach my $k (keys(%{$A})) {
- my $v = $A->{$k} - GetEntry($B, $k);
- if ($v < 0 && $main::opt_drop_negative) {
- $v = 0;
- }
- AddEntry($R, $k, $v);
- }
- if (!$main::opt_drop_negative) {
- # Take care of when subtracted profile has more entries
- foreach my $k (keys(%{$B})) {
- if (!exists($A->{$k})) {
- AddEntry($R, $k, 0 - $B->{$k});
- }
- }
- }
- return $R;
-}
-
-# Get entry from profile; zero if not present
-sub GetEntry {
- my $profile = shift;
- my $k = shift;
- if (exists($profile->{$k})) {
- return $profile->{$k};
- } else {
- return 0;
- }
-}
-
-# Add entry to specified profile
-sub AddEntry {
- my $profile = shift;
- my $k = shift;
- my $n = shift;
- if (!exists($profile->{$k})) {
- $profile->{$k} = 0;
- }
- $profile->{$k} += $n;
-}
-
-# Add a stack of entries to specified profile, and add them to the $pcs
-# list.
-sub AddEntries {
- my $profile = shift;
- my $pcs = shift;
- my $stack = shift;
- my $count = shift;
- my @k = ();
-
- foreach my $e (split(/\s+/, $stack)) {
- my $pc = HexExtend($e);
- $pcs->{$pc} = 1;
- push @k, $pc;
- }
- AddEntry($profile, (join "\n", @k), $count);
-}
-
-sub IsSymbolizedProfileFile {
- my $file_name = shift;
-
- if (!(-e $file_name) || !(-r $file_name)) {
- return 0;
- }
-
- $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $symbol_marker = $&;
- # Check if the file contains a symbol-section marker.
- open(TFILE, "<$file_name");
- my @lines = <TFILE>;
- my $result = grep(/^--- *$symbol_marker/, @lines);
- close(TFILE);
- return $result > 0;
-}
-
-##### Code to profile a server dynamically #####
-
-sub CheckSymbolPage {
- my $url = SymbolPageURL();
-print STDERR "Read $url\n";
-
- my $line = FetchHTTP($url);
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- unless (defined($line)) {
- error("$url doesn't exist\n");
- }
-
- if ($line =~ /^num_symbols:\s+(\d+)$/) {
- if ($1 == 0) {
- error("Stripped binary. No symbols available.\n");
- }
- } else {
- error("Failed to get the number of symbols from $url\n");
- }
-}
-
-sub IsProfileURL {
- my $profile_name = shift;
- my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($profile_name);
- return defined($host) and defined($port) and defined($path);
-}
-
-sub ParseProfileURL {
- my $profile_name = shift;
- if (defined($profile_name) &&
- $profile_name =~ m,^(?:(https?)://|)([^/:]+):(\d+)(|\@\d+)(|/|(.*?)($PROFILE_PAGE|$PMUPROFILE_PAGE|$HEAP_PAGE|$GROWTH_PAGE|$THREAD_PAGE|$BLOCK_PAGE|$CONTENTION_PAGE|$WALL_PAGE|$FILTEREDPROFILE_PAGE))$,o) {
- # $7 is $PROFILE_PAGE/$HEAP_PAGE/etc. $5 is *everything* after
- # the hostname, as long as that everything is the empty string,
- # a slash, or something ending in $PROFILE_PAGE/$HEAP_PAGE/etc.
- # So "$7 || $5" is $PROFILE_PAGE/etc if there, or else it's "/" or "".
- return ($1 || "http", $2, $3, $6, $7 || $5);
- }
- return ();
-}
-
-# We fetch symbols from the first profile argument.
-sub SymbolPageURL {
- my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($main::pfile_args[0]);
- return "$scheme://$host:$port$prefix$SYMBOL_PAGE";
-}
-
-sub FetchProgramName() {
- my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($main::pfile_args[0]);
- my $url = "$scheme://$host:$port$prefix$PROGRAM_NAME_PAGE";
-
- my $cmdline = FetchHTTP($url);
- $cmdline =~ s/\n.*//s; # first line only
- $cmdline =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- error("Failed to get program name from $url\n") unless defined($cmdline);
- $cmdline =~ s/\x00.+//; # Remove argv[1] and latters.
- $cmdline =~ s!\n!!g; # Remove LFs.
- return $cmdline;
-}
-
-# Reads a symbol map from the file handle name given as $1, returning
-# the resulting symbol map. Also processes variables relating to symbols.
-# Currently, the only variable processed is 'binary=<value>' which updates
-# $main::prog to have the correct program name.
-sub ReadSymbols {
- my $in = shift;
- my $map = shift;
- while (<$in>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- # Removes all the leading zeroes from the symbols, see comment below.
- if (m/^0x0*([0-9a-f]+)\s+(.+)/) {
- $map->{$1} = $2;
- } elsif (m/^---/) {
- last;
- } elsif (m/^([a-z][^=]*)=(.*)$/ ) {
- my ($variable, $value) = ($1, $2);
- for ($variable, $value) {
- s/^\s+//;
- s/\s+$//;
- }
- if ($variable eq "binary") {
- if ($main::prog ne $UNKNOWN_BINARY && $main::prog ne $value) {
- printf STDERR ("Warning: Mismatched binary name '%s', using '%s'.\n",
- $main::prog, $value);
- }
- $main::prog = $value;
- } else {
- printf STDERR ("Ignoring unknown variable in symbols list: " .
- "'%s' = '%s'\n", $variable, $value);
- }
- }
- }
- return $map;
-}
-
-# Fetches and processes symbols to prepare them for use in the profile output
-# code. If the optional 'symbol_map' arg is not given, fetches symbols from
-# $SYMBOL_PAGE for all PC values found in profile. Otherwise, the raw symbols
-# are assumed to have already been fetched into 'symbol_map' and are simply
-# extracted and processed.
-sub FetchSymbols {
- my $pcset = shift;
- my $symbol_map = shift;
-
- my %seen = ();
- my @pcs = grep { !$seen{$_}++ } keys(%$pcset); # uniq
-
- if (!defined($symbol_map)) {
- $symbol_map = {};
-
- my $post_data = join("+", sort((map {"0x" . "$_"} @pcs)));
- my $url = SymbolPageURL();
- my $content = PostHTTP($url, $post_data);
-
- my $tmp_symbol = File::Temp->new()->filename;
- open(SYMBOL, ">$tmp_symbol");
- print SYMBOL $content;
- close(SYMBOL);
-
- open(SYMBOL, "<$tmp_symbol") || error("$tmp_symbol");
- ReadSymbols(*SYMBOL{IO}, $symbol_map);
- close(SYMBOL);
- }
-
- my $symbols = {};
- foreach my $pc (@pcs) {
- my $fullname;
- # For 64 bits binaries, symbols are extracted with 8 leading zeroes.
- # Then /symbol reads the long symbols in as uint64, and outputs
- # the result with a "0x%08llx" format which get rid of the zeroes.
- # By removing all the leading zeroes in both $pc and the symbols from
- # /symbol, the symbols match and are retrievable from the map.
- my $shortpc = $pc;
- $shortpc =~ s/^0*//;
- # Each line may have a list of names, which includes the function
- # and also other functions it has inlined. They are separated
- # (in PrintSymbolizedFile), by --, which is illegal in function names.
- my $fullnames;
- if (defined($symbol_map->{$shortpc})) {
- $fullnames = $symbol_map->{$shortpc};
- } else {
- $fullnames = "0x" . $pc; # Just use addresses
- }
- my $sym = [];
- $symbols->{$pc} = $sym;
- foreach my $fullname (split("--", $fullnames)) {
- my $name = ShortFunctionName($fullname);
- push(@{$sym}, $name, "?", $fullname);
- }
- }
- return $symbols;
-}
-
-sub BaseName {
- my $file_name = shift;
- $file_name =~ s!^.*/!!; # Remove directory name
- return $file_name;
-}
-
-sub MakeProfileBaseName {
- my ($binary_name, $profile_name) = @_;
- my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($profile_name);
- my $binary_shortname = BaseName($binary_name);
- return sprintf("%s.%s.%s-port%s",
- $binary_shortname, $main::op_time, $host, $port);
-}
-
-sub FetchDynamicProfile {
- my $binary_name = shift;
- my $profile_name = shift;
- my $fetch_name_only = shift;
- my $encourage_patience = shift;
-
- if (!IsProfileURL($profile_name)) {
- return $profile_name;
- } else {
- my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($profile_name);
- if ($path eq "" || $path eq "/") {
- # Missing type specifier defaults to cpu-profile
- $path = $PROFILE_PAGE;
- }
-
- my $profile_file = MakeProfileBaseName($binary_name, $profile_name);
-
- my $url;
- my $timeout;
- if (($path =~ m/$PROFILE_PAGE/) || ($path =~ m/$PMUPROFILE_PAGE/)) {
- if ($path =~ m/$PROFILE_PAGE/) {
- $url = sprintf("$scheme://$host:$port$prefix$path?seconds=%d",
- $main::opt_seconds);
- } else {
- if ($profile_name =~ m/[?]/) {
- $profile_name .= "&"
- } else {
- $profile_name .= "?"
- }
- $url = sprintf("$scheme://$profile_name" . "seconds=%d",
- $main::opt_seconds);
- }
- $timeout = int($main::opt_seconds * 1.01 + 60);
- } else {
- # For non-CPU profiles, we add a type-extension to
- # the target profile file name.
- my $suffix = $path;
- $suffix =~ s,/,.,g;
- $profile_file .= "$suffix";
- $url = "$scheme://$host:$port$prefix$path";
- }
-
- my $tmp_profile = File::Temp->new()->filename;
- my $real_profile = File::Temp->new()->filename;
-
- if ($fetch_name_only > 0) {
- return $real_profile;
- }
-
- if (($path =~ m/$PROFILE_PAGE/) || ($path =~ m/$PMUPROFILE_PAGE/)){
- print STDERR "Gathering CPU profile from $url for $main::opt_seconds seconds to\n ${real_profile}\n";
- if ($encourage_patience) {
- print STDERR "Be patient...\n";
- }
- } else {
- print STDERR "Fetching $path profile from $host:$port to\n ${real_profile}\n";
- }
-
- my $content = FetchHTTP($url, $timeout);
-
- open(OUTFILE, ">$tmp_profile");
- binmode(OUTFILE);
- print OUTFILE $content;
- close(OUTFILE);
-
- my $line = $content;
- $line !~ /^Could not enable CPU profiling/ || error($line);
-
- copy($tmp_profile, $real_profile) || error("Unable to copy profile\n");
- print STDERR "Wrote profile to $real_profile\n";
- $main::collected_profile = $real_profile;
- return $main::collected_profile;
- }
-}
-
-# Collect profiles in parallel
-sub FetchDynamicProfiles {
- my $items = scalar(@main::pfile_args);
- my $levels = log($items) / log(2);
-
- if ($items == 1) {
- $main::profile_files[0] = FetchDynamicProfile($main::prog, $main::pfile_args[0], 0, 1);
- } else {
- # math rounding issues
- if ((2 ** $levels) < $items) {
- $levels++;
- }
- my $count = scalar(@main::pfile_args);
- for (my $i = 0; $i < $count; $i++) {
- $main::profile_files[$i] = FetchDynamicProfile($main::prog, $main::pfile_args[$i], 1, 0);
- }
- print STDERR "Fetching $count profiles, Be patient...\n";
- FetchDynamicProfilesRecurse($levels, 0, 0);
- $main::collected_profile = join(" \\\n ", @main::profile_files);
- }
-}
-
-# Recursively fork a process to get enough processes
-# collecting profiles
-sub FetchDynamicProfilesRecurse {
- my $maxlevel = shift;
- my $level = shift;
- my $position = shift;
-
- if (my $pid = fork()) {
- $position = 0 | ($position << 1);
- TryCollectProfile($maxlevel, $level, $position);
- wait;
- } else {
- $position = 1 | ($position << 1);
- TryCollectProfile($maxlevel, $level, $position);
- exit(0);
- }
-}
-
-# Collect a single profile
-sub TryCollectProfile {
- my $maxlevel = shift;
- my $level = shift;
- my $position = shift;
-
- if ($level >= ($maxlevel - 1)) {
- if ($position < scalar(@main::pfile_args)) {
- FetchDynamicProfile($main::prog, $main::pfile_args[$position], 0, 0);
- }
- } else {
- FetchDynamicProfilesRecurse($maxlevel, $level+1, $position);
- }
-}
-
-##### Parsing code #####
-
-# Provide a small streaming-read module to handle very large
-# cpu-profile files. Stream in chunks along a sliding window.
-# Provides an interface to get one 'slot', correctly handling
-# endian-ness differences. A slot is one 32-bit or 64-bit word
-# (depending on the input profile). We tell endianness and bit-size
-# for the profile by looking at the first 8 bytes: in cpu profiles,
-# the second slot is always 3 (we'll accept anything that's not 0).
-BEGIN {
- package CpuProfileStream;
-
- sub new {
- my ($class, $file, $fname) = @_;
- my $self = { file => $file,
- base => 0,
- stride => 512 * 1024, # must be a multiple of bitsize/8
- slots => [],
- unpack_code => "", # N for big-endian, V for little
- };
- bless $self, $class;
- # Let unittests adjust the stride
- if ($main::opt_test_stride > 0) {
- $self->{stride} = $main::opt_test_stride;
- }
- # Read the first two slots to figure out bitsize and endianness.
- my $slots = $self->{slots};
- my $str;
- read($self->{file}, $str, 8);
- # Set the global $address_length based on what we see here.
- # 8 is 32-bit (8 hexadecimal chars); 16 is 64-bit (16 hexadecimal chars).
- $address_length = ($str eq (chr(0)x8)) ? 16 : 8;
- if ($address_length == 8) {
- if (substr($str, 6, 2) eq chr(0)x2) {
- $self->{unpack_code} = 'V'; # Little-endian.
- } elsif (substr($str, 4, 2) eq chr(0)x2) {
- $self->{unpack_code} = 'N'; # Big-endian
- } else {
- ::error("$fname: header size >= 2**16\n");
- }
- @$slots = unpack($self->{unpack_code} . "*", $str);
- } else {
- # If we're a 64-bit profile, make sure we're a 64-bit-capable
- # perl. Otherwise, each slot will be represented as a float
- # instead of an int64, losing precision and making all the
- # 64-bit addresses right. We *could* try to handle this with
- # software emulation of 64-bit ints, but that's added complexity
- # for no clear benefit (yet). We use 'Q' to test for 64-bit-ness;
- # perl docs say it's only available on 64-bit perl systems.
- my $has_q = 0;
- eval { $has_q = pack("Q", "1") ? 1 : 1; };
- if (!$has_q) {
- ::error("$fname: need a 64-bit perl to process this 64-bit profile.\n");
- }
- read($self->{file}, $str, 8);
- if (substr($str, 4, 4) eq chr(0)x4) {
- # We'd love to use 'Q', but it's a) not universal, b) not endian-proof.
- $self->{unpack_code} = 'V'; # Little-endian.
- } elsif (substr($str, 0, 4) eq chr(0)x4) {
- $self->{unpack_code} = 'N'; # Big-endian
- } else {
- ::error("$fname: header size >= 2**32\n");
- }
- my @pair = unpack($self->{unpack_code} . "*", $str);
- # Since we know one of the pair is 0, it's fine to just add them.
- @$slots = (0, $pair[0] + $pair[1]);
- }
- return $self;
- }
-
- # Load more data when we access slots->get(X) which is not yet in memory.
- sub overflow {
- my ($self) = @_;
- my $slots = $self->{slots};
- $self->{base} += $#$slots + 1; # skip over data we're replacing
- my $str;
- read($self->{file}, $str, $self->{stride});
- if ($address_length == 8) { # the 32-bit case
- # This is the easy case: unpack provides 32-bit unpacking primitives.
- @$slots = unpack($self->{unpack_code} . "*", $str);
- } else {
- # We need to unpack 32 bits at a time and combine.
- my @b32_values = unpack($self->{unpack_code} . "*", $str);
- my @b64_values = ();
- for (my $i = 0; $i < $#b32_values; $i += 2) {
- # TODO(csilvers): if this is a 32-bit perl, the math below
- # could end up in a too-large int, which perl will promote
- # to a double, losing necessary precision. Deal with that.
- if ($self->{unpack_code} eq 'V') { # little-endian
- push(@b64_values, $b32_values[$i] + $b32_values[$i+1] * (2**32));
- } else {
- push(@b64_values, $b32_values[$i] * (2**32) + $b32_values[$i+1]);
- }
- }
- @$slots = @b64_values;
- }
- }
-
- # Access the i-th long in the file (logically), or -1 at EOF.
- sub get {
- my ($self, $idx) = @_;
- my $slots = $self->{slots};
- while ($#$slots >= 0) {
- if ($idx < $self->{base}) {
- # The only time we expect a reference to $slots[$i - something]
- # after referencing $slots[$i] is reading the very first header.
- # Since $stride > |header|, that shouldn't cause any lookback
- # errors. And everything after the header is sequential.
- print STDERR "Unexpected look-back reading CPU profile";
- return -1; # shrug, don't know what better to return
- } elsif ($idx > $self->{base} + $#$slots) {
- $self->overflow();
- } else {
- return $slots->[$idx - $self->{base}];
- }
- }
- # If we get here, $slots is [], which means we've reached EOF
- return -1; # unique since slots is supposed to hold unsigned numbers
- }
-}
-
-# Parse profile generated by common/profiler.cc and return a reference
-# to a map:
-# $result->{version} Version number of profile file
-# $result->{period} Sampling period (in microseconds)
-# $result->{profile} Profile object
-# $result->{map} Memory map info from profile
-# $result->{pcs} Hash of all PC values seen, key is hex address
-sub ReadProfile {
- my $prog = shift;
- my $fname = shift;
-
- if (IsSymbolizedProfileFile($fname) && !$main::use_symbolized_profile) {
- # we have both a binary and symbolized profiles, abort
- usage("Symbolized profile '$fname' cannot be used with a binary arg. " .
- "Try again without passing '$prog'.");
- }
-
- $main::profile_type = '';
-
- $CONTENTION_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $contention_marker = $&;
- $GROWTH_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $growth_marker = $&;
- $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $symbol_marker = $&;
- $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $profile_marker = $&;
-
- # Look at first line to see if it is a heap or a CPU profile.
- # CPU profile may start with no header at all, and just binary data
- # (starting with \0\0\0\0) -- in that case, don't try to read the
- # whole firstline, since it may be gigabytes(!) of data.
- open(PROFILE, "<$fname") || error("$fname: $!\n");
- binmode PROFILE; # New perls do UTF-8 processing
- my $firstchar = "";
- my $header = "";
- read(PROFILE, $firstchar, 1);
- seek(PROFILE, -1, 1); # unread the firstchar
- if ($firstchar ne "\0") {
- $header = <PROFILE>;
- if (!defined($header)) {
- error("Profile is empty.\n");
- }
- $header =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- }
-
- my $symbols;
- if ($header =~ m/^--- *$symbol_marker/o) {
- # read the symbol section of the symbolized profile file
- $symbols = ReadSymbols(*PROFILE{IO});
-
- # read the next line to get the header for the remaining profile
- $header = "";
- read(PROFILE, $firstchar, 1);
- seek(PROFILE, -1, 1); # unread the firstchar
- if ($firstchar ne "\0") {
- $header = <PROFILE>;
- $header =~ s/\r//g;
- }
- }
-
- my $result;
-
- if ($header =~ m/^heap profile:.*$growth_marker/o) {
- $main::profile_type = 'growth';
- $result = ReadHeapProfile($prog, $fname, $header);
- } elsif ($header =~ m/^heap profile:/) {
- $main::profile_type = 'heap';
- $result = ReadHeapProfile($prog, $fname, $header);
- } elsif ($header =~ m/^--- *$contention_marker/o) {
- $main::profile_type = 'contention';
- $result = ReadSynchProfile($prog, $fname);
- } elsif ($header =~ m/^--- *Stacks:/) {
- print STDERR
- "Old format contention profile: mistakenly reports " .
- "condition variable signals as lock contentions.\n";
- $main::profile_type = 'contention';
- $result = ReadSynchProfile($prog, $fname);
- } elsif ($header =~ m/^thread creation profile:/) {
- $main::profile_type = 'thread';
- $result = ReadThreadProfile($prog, $fname);
- } elsif ($header =~ m/^--- *$profile_marker/) {
- # the binary cpu profile data starts immediately after this line
- $main::profile_type = 'cpu';
- $result = ReadCPUProfile($prog, $fname);
- } else {
- if (defined($symbols)) {
- # a symbolized profile contains a format we don't recognize, bail out
- error("$fname: Cannot recognize profile section after symbols.\n");
- }
- # no ascii header present -- must be a CPU profile
- $main::profile_type = 'cpu';
- $result = ReadCPUProfile($prog, $fname);
- }
-
- # if we got symbols along with the profile, return those as well
- if (defined($symbols)) {
- $result->{symbols} = $symbols;
- }
-
- return $result;
-}
-
-# Subtract one from caller pc so we map back to call instr.
-# However, don't do this if we're reading a symbolized profile
-# file, in which case the subtract-one was done when the file
-# was written.
-#
-# We apply the same logic to all readers, though ReadCPUProfile uses an
-# independent implementation.
-sub FixCallerAddresses {
- my $stack = shift;
- if ($main::use_symbolized_profile) {
- return $stack;
- } else {
- $stack =~ /(\s)/;
- my $delimiter = $1;
- my @addrs = split(' ', $stack);
- my @fixedaddrs;
- $#fixedaddrs = $#addrs;
- if ($#addrs >= 0) {
- $fixedaddrs[0] = $addrs[0];
- }
- for (my $i = 1; $i <= $#addrs; $i++) {
- $fixedaddrs[$i] = AddressSub($addrs[$i], "0x1");
- }
- return join $delimiter, @fixedaddrs;
- }
-}
-
-# CPU profile reader
-sub ReadCPUProfile {
- my $prog = shift;
- my $fname = shift;
- my $version;
- my $period;
- my $i;
- my $profile = {};
- my $pcs = {};
-
- # Parse string into array of slots.
- my $slots = CpuProfileStream->new(*PROFILE, $fname);
-
- # Read header. The current header version is a 5-element structure
- # containing:
- # 0: header count (always 0)
- # 1: header "words" (after this one: 3)
- # 2: format version (0)
- # 3: sampling period (usec)
- # 4: unused padding (always 0)
- if ($slots->get(0) != 0 ) {
- error("$fname: not a profile file, or old format profile file\n");
- }
- $i = 2 + $slots->get(1);
- $version = $slots->get(2);
- $period = $slots->get(3);
- # Do some sanity checking on these header values.
- if ($version > (2**32) || $period > (2**32) || $i > (2**32) || $i < 5) {
- error("$fname: not a profile file, or corrupted profile file\n");
- }
-
- # Parse profile
- while ($slots->get($i) != -1) {
- my $n = $slots->get($i++);
- my $d = $slots->get($i++);
- if ($d > (2**16)) { # TODO(csilvers): what's a reasonable max-stack-depth?
- my $addr = sprintf("0%o", $i * ($address_length == 8 ? 4 : 8));
- print STDERR "At index $i (address $addr):\n";
- error("$fname: stack trace depth >= 2**32\n");
- }
- if ($slots->get($i) == 0) {
- # End of profile data marker
- $i += $d;
- last;
- }
-
- # Make key out of the stack entries
- my @k = ();
- for (my $j = 0; $j < $d; $j++) {
- my $pc = $slots->get($i+$j);
- # Subtract one from caller pc so we map back to call instr.
- # However, don't do this if we're reading a symbolized profile
- # file, in which case the subtract-one was done when the file
- # was written.
- if ($j > 0 && !$main::use_symbolized_profile) {
- $pc--;
- }
- $pc = sprintf("%0*x", $address_length, $pc);
- $pcs->{$pc} = 1;
- push @k, $pc;
- }
-
- AddEntry($profile, (join "\n", @k), $n);
- $i += $d;
- }
-
- # Parse map
- my $map = '';
- seek(PROFILE, $i * 4, 0);
- read(PROFILE, $map, (stat PROFILE)[7]);
- close(PROFILE);
-
- my $r = {};
- $r->{version} = $version;
- $r->{period} = $period;
- $r->{profile} = $profile;
- $r->{libs} = ParseLibraries($prog, $map, $pcs);
- $r->{pcs} = $pcs;
-
- return $r;
-}
-
-sub ReadHeapProfile {
- my $prog = shift;
- my $fname = shift;
- my $header = shift;
-
- my $index = 1;
- if ($main::opt_inuse_space) {
- $index = 1;
- } elsif ($main::opt_inuse_objects) {
- $index = 0;
- } elsif ($main::opt_alloc_space) {
- $index = 3;
- } elsif ($main::opt_alloc_objects) {
- $index = 2;
- }
-
- # Find the type of this profile. The header line looks like:
- # heap profile: 1246: 8800744 [ 1246: 8800744] @ <heap-url>/266053
- # There are two pairs <count: size>, the first inuse objects/space, and the
- # second allocated objects/space. This is followed optionally by a profile
- # type, and if that is present, optionally by a sampling frequency.
- # For remote heap profiles (v1):
- # The interpretation of the sampling frequency is that the profiler, for
- # each sample, calculates a uniformly distributed random integer less than
- # the given value, and records the next sample after that many bytes have
- # been allocated. Therefore, the expected sample interval is half of the
- # given frequency. By default, if not specified, the expected sample
- # interval is 128KB. Only remote-heap-page profiles are adjusted for
- # sample size.
- # For remote heap profiles (v2):
- # The sampling frequency is the rate of a Poisson process. This means that
- # the probability of sampling an allocation of size X with sampling rate Y
- # is 1 - exp(-X/Y)
- # For version 2, a typical header line might look like this:
- # heap profile: 1922: 127792360 [ 1922: 127792360] @ <heap-url>_v2/524288
- # the trailing number (524288) is the sampling rate. (Version 1 showed
- # double the 'rate' here)
- my $sampling_algorithm = 0;
- my $sample_adjustment = 0;
- chomp($header);
- my $type = "unknown";
- if ($header =~ m"^heap profile:\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\](\s*@\s*([^/]*)(/(\d+))?)?") {
- if (defined($6) && ($6 ne '')) {
- $type = $6;
- my $sample_period = $8;
- # $type is "heapprofile" for profiles generated by the
- # heap-profiler, and either "heap" or "heap_v2" for profiles
- # generated by sampling directly within tcmalloc. It can also
- # be "growth" for heap-growth profiles. The first is typically
- # found for profiles generated locally, and the others for
- # remote profiles.
- if (($type eq "heapprofile") || ($type !~ /heap/) ) {
- # No need to adjust for the sampling rate with heap-profiler-derived data
- $sampling_algorithm = 0;
- } elsif ($type =~ /_v2/) {
- $sampling_algorithm = 2; # version 2 sampling
- if (defined($sample_period) && ($sample_period ne '')) {
- $sample_adjustment = int($sample_period);
- }
- } else {
- $sampling_algorithm = 1; # version 1 sampling
- if (defined($sample_period) && ($sample_period ne '')) {
- $sample_adjustment = int($sample_period)/2;
- }
- }
- } else {
- # We detect whether or not this is a remote-heap profile by checking
- # that the total-allocated stats ($n2,$s2) are exactly the
- # same as the in-use stats ($n1,$s1). It is remotely conceivable
- # that a non-remote-heap profile may pass this check, but it is hard
- # to imagine how that could happen.
- # In this case it's so old it's guaranteed to be remote-heap version 1.
- my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);
- if (($n1 == $n2) && ($s1 == $s2)) {
- # This is likely to be a remote-heap based sample profile
- $sampling_algorithm = 1;
- }
- }
- }
-
- if ($sampling_algorithm > 0) {
- # For remote-heap generated profiles, adjust the counts and sizes to
- # account for the sample rate (we sample once every 128KB by default).
- if ($sample_adjustment == 0) {
- # Turn on profile adjustment.
- $sample_adjustment = 128*1024;
- print STDERR "Adjusting heap profiles for 1-in-128KB sampling rate\n";
- } else {
- printf STDERR ("Adjusting heap profiles for 1-in-%d sampling rate\n",
- $sample_adjustment);
- }
- if ($sampling_algorithm > 1) {
- # We don't bother printing anything for the original version (version 1)
- printf STDERR "Heap version $sampling_algorithm\n";
- }
- }
-
- my $profile = {};
- my $pcs = {};
- my $map = "";
-
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- if (/^MAPPED_LIBRARIES:/) {
- # Read the /proc/self/maps data
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- $map .= $_;
- }
- last;
- }
-
- if (/^--- Memory map:/) {
- # Read /proc/self/maps data as formatted by DumpAddressMap()
- my $buildvar = "";
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- # Parse "build=<dir>" specification if supplied
- if (m/^\s*build=(.*)\n/) {
- $buildvar = $1;
- }
-
- # Expand "$build" variable if available
- $_ =~ s/\$build\b/$buildvar/g;
-
- $map .= $_;
- }
- last;
- }
-
- # Read entry of the form:
- # <count1>: <bytes1> [<count2>: <bytes2>] @ a1 a2 a3 ... an
- s/^\s*//;
- s/\s*$//;
- if (m/^\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\]\s+@\s+(.*)$/) {
- my $stack = $5;
- my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);
-
- if ($sample_adjustment) {
- if ($sampling_algorithm == 2) {
- # Remote-heap version 2
- # The sampling frequency is the rate of a Poisson process.
- # This means that the probability of sampling an allocation of
- # size X with sampling rate Y is 1 - exp(-X/Y)
- my $ratio;
- $ratio = (($s1*1.0)/$n1)/($sample_adjustment);
- my $scale_factor;
- $scale_factor = 1/(1 - exp(-$ratio));
- $n1 *= $scale_factor;
- $s1 *= $scale_factor;
- $ratio = (($s2*1.0)/$n2)/($sample_adjustment);
- $scale_factor = 1/(1 - exp(-$ratio));
- $n2 *= $scale_factor;
- $s2 *= $scale_factor;
- } else {
- # Remote-heap version 1
- my $ratio;
- if ($n1 > 0) {
- $ratio = (($s1*1.0)/$n1)/($sample_adjustment);
- if ($ratio < 1) {
- $n1 /= $ratio;
- $s1 /= $ratio;
- }
- }
- if ($n2 > 0) {
- $ratio = (($s2*1.0)/$n2)/($sample_adjustment);
- if ($ratio < 1) {
- $n2 /= $ratio;
- $s2 /= $ratio;
- }
- }
- }
- }
-
- my @counts = ($n1, $s1, $n2, $s2);
- AddEntries($profile, $pcs, FixCallerAddresses($stack), $counts[$index]);
- }
- }
-
- my $r = {};
- $r->{version} = "heap";
- $r->{period} = 1;
- $r->{profile} = $profile;
- $r->{libs} = ParseLibraries($prog, $map, $pcs);
- $r->{pcs} = $pcs;
- return $r;
-}
-
-sub ReadThreadProfile {
- my $prog = shift;
- my $fname = shift;
-
- my $profile = {};
- my $pcs = {};
- my $map = "";
-
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- if (/^MAPPED_LIBRARIES:/) {
- # Read the /proc/self/maps data
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- $map .= $_;
- }
- last;
- }
-
- if (/^--- Memory map:/) {
- # Read /proc/self/maps data as formatted by DumpAddressMap()
- my $buildvar = "";
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- # Parse "build=<dir>" specification if supplied
- if (m/^\s*build=(.*)\n/) {
- $buildvar = $1;
- }
-
- # Expand "$build" variable if available
- $_ =~ s/\$build\b/$buildvar/g;
-
- $map .= $_;
- }
- last;
- }
-
- # Read entry of the form:
- # @ a1 a2 a3 ... an
- s/^\s*//;
- s/\s*$//;
- if (m/^@\s+(.*)$/) {
- AddEntries($profile, $pcs, FixCallerAddresses($1), 1);
- }
- }
-
- my $r = {};
- $r->{version} = "thread";
- $r->{period} = 1;
- $r->{profile} = $profile;
- $r->{libs} = ParseLibraries($prog, $map, $pcs);
- $r->{pcs} = $pcs;
- return $r;
-}
-
-sub ReadSynchProfile {
- my ($prog, $fname, $header) = @_;
-
- my $map = '';
- my $profile = {};
- my $pcs = {};
- my $sampling_period = 1;
- my $cyclespernanosec = 2.8; # Default assumption for old binaries
- my $seen_clockrate = 0;
- my $line;
-
- my $index = 0;
- if ($main::opt_total_delay) {
- $index = 0;
- } elsif ($main::opt_contentions) {
- $index = 1;
- } elsif ($main::opt_mean_delay) {
- $index = 2;
- }
-
- while ( $line = <PROFILE> ) {
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- if ( $line =~ /^\s*(\d+)\s+(\d+) \@\s*(.*?)\s*$/ ) {
- my ($cycles, $count, $stack) = ($1, $2, $3);
-
- # Convert cycles to nanoseconds
- $cycles /= $cyclespernanosec;
-
- # Adjust for sampling done by application
- $cycles *= $sampling_period;
- $count *= $sampling_period;
-
- my @values = ($cycles, $count, $cycles / $count);
- AddEntries($profile, $pcs, FixCallerAddresses($stack), $values[$index]);
-
- } elsif ( $line =~ /^(slow release).*thread \d+ \@\s*(.*?)\s*$/ ||
- $line =~ /^\s*(\d+) \@\s*(.*?)\s*$/ ) {
- my ($cycles, $stack) = ($1, $2);
- if ($cycles !~ /^\d+$/) {
- next;
- }
-
- # Convert cycles to nanoseconds
- $cycles /= $cyclespernanosec;
-
- # Adjust for sampling done by application
- $cycles *= $sampling_period;
-
- AddEntries($profile, $pcs, FixCallerAddresses($stack), $cycles);
-
- } elsif ( $line =~ m/^([a-z][^=]*)=(.*)$/ ) {
- my ($variable, $value) = ($1,$2);
- for ($variable, $value) {
- s/^\s+//;
- s/\s+$//;
- }
- if ($variable eq "cycles/second") {
- $cyclespernanosec = $value / 1e9;
- $seen_clockrate = 1;
- } elsif ($variable eq "sampling period") {
- $sampling_period = $value;
- } elsif ($variable eq "ms since reset") {
- # Currently nothing is done with this value in pprof
- # So we just silently ignore it for now
- } elsif ($variable eq "discarded samples") {
- # Currently nothing is done with this value in pprof
- # So we just silently ignore it for now
- } else {
- printf STDERR ("Ignoring unnknown variable in /contention output: " .
- "'%s' = '%s'\n",$variable,$value);
- }
- } else {
- # Memory map entry
- $map .= $line;
- }
- }
- close PROFILE;
-
- if (!$seen_clockrate) {
- printf STDERR ("No cycles/second entry in profile; Guessing %.1f GHz\n",
- $cyclespernanosec);
- }
-
- my $r = {};
- $r->{version} = 0;
- $r->{period} = $sampling_period;
- $r->{profile} = $profile;
- $r->{libs} = ParseLibraries($prog, $map, $pcs);
- $r->{pcs} = $pcs;
- return $r;
-}
-
-# Given a hex value in the form "0x1abcd" return "0001abcd" or
-# "000000000001abcd", depending on the current address length.
-# There's probably a more idiomatic (or faster) way to do this...
-sub HexExtend {
- my $addr = shift;
-
- $addr =~ s/^0x//;
-
- if (length $addr > $address_length) {
- printf STDERR "Warning: address $addr is longer than address length $address_length\n";
- }
-
- return substr("000000000000000".$addr, -$address_length);
-}
-
-##### Symbol extraction #####
-
-# Aggressively search the lib_prefix values for the given library
-# If all else fails, just return the name of the library unmodified.
-# If the lib_prefix is "/my/path,/other/path" and $file is "/lib/dir/mylib.so"
-# it will search the following locations in this order, until it finds a file:
-# /my/path/lib/dir/mylib.so
-# /other/path/lib/dir/mylib.so
-# /my/path/dir/mylib.so
-# /other/path/dir/mylib.so
-# /my/path/mylib.so
-# /other/path/mylib.so
-# /lib/dir/mylib.so (returned as last resort)
-sub FindLibrary {
- my $file = shift;
- my $suffix = $file;
-
- # Search for the library as described above
- do {
- foreach my $prefix (@prefix_list) {
- my $fullpath = $prefix . $suffix;
- if (-e $fullpath) {
- return $fullpath;
- }
- }
- } while ($suffix =~ s|^/[^/]+/|/|);
- return $file;
-}
-
-# Return path to library with debugging symbols.
-# For libc libraries, the copy in /usr/lib/debug contains debugging symbols
-sub DebuggingLibrary {
- my $file = shift;
- if ($file =~ m|^/| && -f "/usr/lib/debug$file") {
- return "/usr/lib/debug$file";
- }
- return undef;
-}
-
-# Parse text section header of a library using objdump
-sub ParseTextSectionHeaderFromObjdump {
- my $lib = shift;
-
- my $size = undef;
- my $vma;
- my $file_offset;
- # Get objdump output from the library file to figure out how to
- # map between mapped addresses and addresses in the library.
- my $objdump = $obj_tool_map{"objdump"};
- open(OBJDUMP, "$objdump -h $lib |")
- || error("$objdump $lib: $!\n");
- while (<OBJDUMP>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- # Idx Name Size VMA LMA File off Algn
- # 10 .text 00104b2c 420156f0 420156f0 000156f0 2**4
- # For 64-bit objects, VMA and LMA will be 16 hex digits, size and file
- # offset may still be 8. But AddressSub below will still handle that.
- my @x = split;
- if (($#x >= 6) && ($x[1] eq '.text')) {
- $size = $x[2];
- $vma = $x[3];
- $file_offset = $x[5];
- last;
- }
- }
- close(OBJDUMP);
-
- if (!defined($size)) {
- return undef;
- }
-
- my $r = {};
- $r->{size} = $size;
- $r->{vma} = $vma;
- $r->{file_offset} = $file_offset;
-
- return $r;
-}
-
-# Parse text section header of a library using otool (on OS X)
-sub ParseTextSectionHeaderFromOtool {
- my $lib = shift;
-
- my $size = undef;
- my $vma = undef;
- my $file_offset = undef;
- # Get otool output from the library file to figure out how to
- # map between mapped addresses and addresses in the library.
- my $otool = $obj_tool_map{"otool"};
- open(OTOOL, "$otool -l $lib |")
- || error("$otool $lib: $!\n");
- my $cmd = "";
- my $sectname = "";
- my $segname = "";
- foreach my $line (<OTOOL>) {
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- # Load command <#>
- # cmd LC_SEGMENT
- # [...]
- # Section
- # sectname __text
- # segname __TEXT
- # addr 0x000009f8
- # size 0x00018b9e
- # offset 2552
- # align 2^2 (4)
- # We will need to strip off the leading 0x from the hex addresses,
- # and convert the offset into hex.
- if ($line =~ /Load command/) {
- $cmd = "";
- $sectname = "";
- $segname = "";
- } elsif ($line =~ /Section/) {
- $sectname = "";
- $segname = "";
- } elsif ($line =~ /cmd (\w+)/) {
- $cmd = $1;
- } elsif ($line =~ /sectname (\w+)/) {
- $sectname = $1;
- } elsif ($line =~ /segname (\w+)/) {
- $segname = $1;
- } elsif (!(($cmd eq "LC_SEGMENT" || $cmd eq "LC_SEGMENT_64") &&
- $sectname eq "__text" &&
- $segname eq "__TEXT")) {
- next;
- } elsif ($line =~ /\baddr 0x([0-9a-fA-F]+)/) {
- $vma = $1;
- } elsif ($line =~ /\bsize 0x([0-9a-fA-F]+)/) {
- $size = $1;
- } elsif ($line =~ /\boffset ([0-9]+)/) {
- $file_offset = sprintf("%016x", $1);
- }
- if (defined($vma) && defined($size) && defined($file_offset)) {
- last;
- }
- }
- close(OTOOL);
-
- if (!defined($vma) || !defined($size) || !defined($file_offset)) {
- return undef;
- }
-
- my $r = {};
- $r->{size} = $size;
- $r->{vma} = $vma;
- $r->{file_offset} = $file_offset;
-
- return $r;
-}
-
-sub ParseTextSectionHeader {
- # obj_tool_map("otool") is only defined if we're in a Mach-O environment
- if (defined($obj_tool_map{"otool"})) {
- my $r = ParseTextSectionHeaderFromOtool(@_);
- if (defined($r)){
- return $r;
- }
- }
- # If otool doesn't work, or we don't have it, fall back to objdump
- return ParseTextSectionHeaderFromObjdump(@_);
-}
-
-# Split /proc/pid/maps dump into a list of libraries
-sub ParseLibraries {
- return if $main::use_symbol_page; # We don't need libraries info.
- my $prog = shift;
- my $map = shift;
- my $pcs = shift;
-
- my $result = [];
- my $h = "[a-f0-9]+";
- my $zero_offset = HexExtend("0");
-
- my $buildvar = "";
- foreach my $l (split("\n", $map)) {
- if ($l =~ m/^\s*build=(.*)$/) {
- $buildvar = $1;
- }
-
- my $start;
- my $finish;
- my $offset;
- my $lib;
- if ($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+\.(so|dll|dylib|bundle)((\.\d+)+\w*(\.\d+){0,3})?)$/i) {
- # Full line from /proc/self/maps. Example:
- # 40000000-40015000 r-xp 00000000 03:01 12845071 /lib/ld-2.3.2.so
- $start = HexExtend($1);
- $finish = HexExtend($2);
- $offset = HexExtend($3);
- $lib = $4;
- $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths
- } elsif ($l =~ /^\s*($h)-($h):\s*(\S+\.so(\.\d+)*)/) {
- # Cooked line from DumpAddressMap. Example:
- # 40000000-40015000: /lib/ld-2.3.2.so
- $start = HexExtend($1);
- $finish = HexExtend($2);
- $offset = $zero_offset;
- $lib = $3;
- } else {
- next;
- }
-
- # Expand "$build" variable if available
- $lib =~ s/\$build\b/$buildvar/g;
-
- $lib = FindLibrary($lib);
-
- # Check for pre-relocated libraries, which use pre-relocated symbol tables
- # and thus require adjusting the offset that we'll use to translate
- # VM addresses into symbol table addresses.
- # Only do this if we're not going to fetch the symbol table from a
- # debugging copy of the library.
- if (!DebuggingLibrary($lib)) {
- my $text = ParseTextSectionHeader($lib);
- if (defined($text)) {
- my $vma_offset = AddressSub($text->{vma}, $text->{file_offset});
- $offset = AddressAdd($offset, $vma_offset);
- }
- }
-
- push(@{$result}, [$lib, $start, $finish, $offset]);
- }
-
- # Append special entry for additional library (not relocated)
- if ($main::opt_lib ne "") {
- my $text = ParseTextSectionHeader($main::opt_lib);
- if (defined($text)) {
- my $start = $text->{vma};
- my $finish = AddressAdd($start, $text->{size});
-
- push(@{$result}, [$main::opt_lib, $start, $finish, $start]);
- }
- }
-
- # Append special entry for the main program. This covers
- # 0..max_pc_value_seen, so that we assume pc values not found in one
- # of the library ranges will be treated as coming from the main
- # program binary.
- my $min_pc = HexExtend("0");
- my $max_pc = $min_pc; # find the maximal PC value in any sample
- foreach my $pc (keys(%{$pcs})) {
- if (HexExtend($pc) gt $max_pc) { $max_pc = HexExtend($pc); }
- }
- push(@{$result}, [$prog, $min_pc, $max_pc, $zero_offset]);
-
- return $result;
-}
-
-# Add two hex addresses of length $address_length.
-# Run pprof --test for unit test if this is changed.
-sub AddressAdd {
- my $addr1 = shift;
- my $addr2 = shift;
- my $sum;
-
- if ($address_length == 8) {
- # Perl doesn't cope with wraparound arithmetic, so do it explicitly:
- $sum = (hex($addr1)+hex($addr2)) % (0x10000000 * 16);
- return sprintf("%08x", $sum);
-
- } else {
- # Do the addition in 7-nibble chunks to trivialize carry handling.
-
- if ($main::opt_debug and $main::opt_test) {
- print STDERR "AddressAdd $addr1 + $addr2 = ";
- }
-
- my $a1 = substr($addr1,-7);
- $addr1 = substr($addr1,0,-7);
- my $a2 = substr($addr2,-7);
- $addr2 = substr($addr2,0,-7);
- $sum = hex($a1) + hex($a2);
- my $c = 0;
- if ($sum > 0xfffffff) {
- $c = 1;
- $sum -= 0x10000000;
- }
- my $r = sprintf("%07x", $sum);
-
- $a1 = substr($addr1,-7);
- $addr1 = substr($addr1,0,-7);
- $a2 = substr($addr2,-7);
- $addr2 = substr($addr2,0,-7);
- $sum = hex($a1) + hex($a2) + $c;
- $c = 0;
- if ($sum > 0xfffffff) {
- $c = 1;
- $sum -= 0x10000000;
- }
- $r = sprintf("%07x", $sum) . $r;
-
- $sum = hex($addr1) + hex($addr2) + $c;
- if ($sum > 0xff) { $sum -= 0x100; }
- $r = sprintf("%02x", $sum) . $r;
-
- if ($main::opt_debug and $main::opt_test) { print STDERR "$r\n"; }
-
- return $r;
- }
-}
-
-
-# Subtract two hex addresses of length $address_length.
-# Run pprof --test for unit test if this is changed.
-sub AddressSub {
- my $addr1 = shift;
- my $addr2 = shift;
- my $diff;
-
- if ($address_length == 8) {
- # Perl doesn't cope with wraparound arithmetic, so do it explicitly:
- $diff = (hex($addr1)-hex($addr2)) % (0x10000000 * 16);
- return sprintf("%08x", $diff);
-
- } else {
- # Do the addition in 7-nibble chunks to trivialize borrow handling.
- # if ($main::opt_debug) { print STDERR "AddressSub $addr1 - $addr2 = "; }
-
- my $a1 = hex(substr($addr1,-7));
- $addr1 = substr($addr1,0,-7);
- my $a2 = hex(substr($addr2,-7));
- $addr2 = substr($addr2,0,-7);
- my $b = 0;
- if ($a2 > $a1) {
- $b = 1;
- $a1 += 0x10000000;
- }
- $diff = $a1 - $a2;
- my $r = sprintf("%07x", $diff);
-
- $a1 = hex(substr($addr1,-7));
- $addr1 = substr($addr1,0,-7);
- $a2 = hex(substr($addr2,-7)) + $b;
- $addr2 = substr($addr2,0,-7);
- $b = 0;
- if ($a2 > $a1) {
- $b = 1;
- $a1 += 0x10000000;
- }
- $diff = $a1 - $a2;
- $r = sprintf("%07x", $diff) . $r;
-
- $a1 = hex($addr1);
- $a2 = hex($addr2) + $b;
- if ($a2 > $a1) { $a1 += 0x100; }
- $diff = $a1 - $a2;
- $r = sprintf("%02x", $diff) . $r;
-
- # if ($main::opt_debug) { print STDERR "$r\n"; }
-
- return $r;
- }
-}
-
-# Increment a hex addresses of length $address_length.
-# Run pprof --test for unit test if this is changed.
-sub AddressInc {
- my $addr = shift;
- my $sum;
-
- if ($address_length == 8) {
- # Perl doesn't cope with wraparound arithmetic, so do it explicitly:
- $sum = (hex($addr)+1) % (0x10000000 * 16);
- return sprintf("%08x", $sum);
-
- } else {
- # Do the addition in 7-nibble chunks to trivialize carry handling.
- # We are always doing this to step through the addresses in a function,
- # and will almost never overflow the first chunk, so we check for this
- # case and exit early.
-
- # if ($main::opt_debug) { print STDERR "AddressInc $addr1 = "; }
-
- my $a1 = substr($addr,-7);
- $addr = substr($addr,0,-7);
- $sum = hex($a1) + 1;
- my $r = sprintf("%07x", $sum);
- if ($sum <= 0xfffffff) {
- $r = $addr . $r;
- # if ($main::opt_debug) { print STDERR "$r\n"; }
- return HexExtend($r);
- } else {
- $r = "0000000";
- }
-
- $a1 = substr($addr,-7);
- $addr = substr($addr,0,-7);
- $sum = hex($a1) + 1;
- $r = sprintf("%07x", $sum) . $r;
- if ($sum <= 0xfffffff) {
- $r = $addr . $r;
- # if ($main::opt_debug) { print STDERR "$r\n"; }
- return HexExtend($r);
- } else {
- $r = "00000000000000";
- }
-
- $sum = hex($addr) + 1;
- if ($sum > 0xff) { $sum -= 0x100; }
- $r = sprintf("%02x", $sum) . $r;
-
- # if ($main::opt_debug) { print STDERR "$r\n"; }
- return $r;
- }
-}
-
-# Extract symbols for all PC values found in profile
-sub ExtractSymbols {
- my $libs = shift;
- my $pcset = shift;
-
- my $symbols = {};
-
- # Map each PC value to the containing library
- my %seen = ();
- foreach my $lib (@{$libs}) {
- my $libname = $lib->[0];
- my $start = $lib->[1];
- my $finish = $lib->[2];
- my $offset = $lib->[3];
-
- # Get list of pcs that belong in this library.
- my $contained = [];
- foreach my $pc (keys(%{$pcset})) {
- if (!$seen{$pc} && ($pc ge $start) && ($pc le $finish)) {
- $seen{$pc} = 1;
- push(@{$contained}, $pc);
- }
- }
- # Map to symbols
- MapToSymbols($libname, AddressSub($start, $offset), $contained, $symbols);
- }
-
- return $symbols;
-}
-
-# Map list of PC values to symbols for a given image
-sub MapToSymbols {
- my $image = shift;
- my $offset = shift;
- my $pclist = shift;
- my $symbols = shift;
-
- my $debug = 0;
-
- # Ignore empty binaries
- if ($#{$pclist} < 0) { return; }
-
- # Figure out the addr2line command to use
- my $addr2line = $obj_tool_map{"addr2line"};
- my $cmd = "$addr2line -f -C -e $image";
- if (exists $obj_tool_map{"addr2line_pdb"}) {
- $addr2line = $obj_tool_map{"addr2line_pdb"};
- $cmd = "$addr2line --demangle -f -C -e $image";
- }
-
- # Use the go version because we know it works on all platforms
- $addr2line = "go tool addr2line";
- $cmd = "$addr2line $image";
-
- # If "addr2line" isn't installed on the system at all, just use
- # nm to get what info we can (function names, but not line numbers).
- if (system("$addr2line --help >$DEVNULL 2>&1") != 0) {
- MapSymbolsWithNM($image, $offset, $pclist, $symbols);
- return;
- }
-
- # "addr2line -i" can produce a variable number of lines per input
- # address, with no separator that allows us to tell when data for
- # the next address starts. So we find the address for a special
- # symbol (_fini) and interleave this address between all real
- # addresses passed to addr2line. The name of this special symbol
- # can then be used as a separator.
- $sep_address = undef; # May be filled in by MapSymbolsWithNM()
- my $nm_symbols = {};
- MapSymbolsWithNM($image, $offset, $pclist, $nm_symbols);
- # TODO(csilvers): only add '-i' if addr2line supports it.
- if (defined($sep_address)) {
- # Only add " -i" to addr2line if the binary supports it.
- # addr2line --help returns 0, but not if it sees an unknown flag first.
- if (system("$cmd -i --help >$DEVNULL 2>&1") == 0) {
- $cmd .= " -i";
- } else {
- $sep_address = undef; # no need for sep_address if we don't support -i
- }
- }
-
- # Make file with all PC values with intervening 'sep_address' so
- # that we can reliably detect the end of inlined function list
- open(ADDRESSES, ">$main::tmpfile_sym") || error("$main::tmpfile_sym: $!\n");
- if ($debug) { print("---- $image ---\n"); }
- for (my $i = 0; $i <= $#{$pclist}; $i++) {
- # addr2line always reads hex addresses, and does not need '0x' prefix.
- if ($debug) { printf STDERR ("%s\n", $pclist->[$i]); }
- printf ADDRESSES ("%s\n", AddressSub($pclist->[$i], $offset));
- if (defined($sep_address)) {
- printf ADDRESSES ("%s\n", $sep_address);
- }
- }
- close(ADDRESSES);
- if ($debug) {
- print("----\n");
- system("cat $main::tmpfile_sym");
- print("---- $cmd\n");
- system("$cmd <$main::tmpfile_sym");
- print("----\n");
- }
-
- open(SYMBOLS, "$cmd <$main::tmpfile_sym |") || error("$cmd: $!\n");
- my $count = 0; # Index in pclist
- while (<SYMBOLS>) {
- # Read fullfunction and filelineinfo from next pair of lines
- s/\r?\n$//g;
- my $fullfunction = $_;
- $_ = <SYMBOLS>;
- s/\r?\n$//g;
- my $filelinenum = $_;
-
- if (defined($sep_address) && $fullfunction eq $sep_symbol) {
- # Terminating marker for data for this address
- $count++;
- next;
- }
-
- $filelinenum =~ s|\\|/|g; # turn windows-style paths into unix-style paths
-
- my $pcstr = $pclist->[$count];
- my $function = ShortFunctionName($fullfunction);
- if ($fullfunction eq '??') {
- # See if nm found a symbol
- my $nms = $nm_symbols->{$pcstr};
- if (defined($nms)) {
- $function = $nms->[0];
- $fullfunction = $nms->[2];
- }
- }
-
- # Prepend to accumulated symbols for pcstr
- # (so that caller comes before callee)
- my $sym = $symbols->{$pcstr};
- if (!defined($sym)) {
- $sym = [];
- $symbols->{$pcstr} = $sym;
- }
- unshift(@{$sym}, $function, $filelinenum, $fullfunction);
- if ($debug) { printf STDERR ("%s => [%s]\n", $pcstr, join(" ", @{$sym})); }
- if (!defined($sep_address)) {
- # Inlining is off, se this entry ends immediately
- $count++;
- }
- }
- close(SYMBOLS);
-}
-
-# Use nm to map the list of referenced PCs to symbols. Return true iff we
-# are able to read procedure information via nm.
-sub MapSymbolsWithNM {
- my $image = shift;
- my $offset = shift;
- my $pclist = shift;
- my $symbols = shift;
-
- # Get nm output sorted by increasing address
- my $symbol_table = GetProcedureBoundaries($image, ".");
- if (!%{$symbol_table}) {
- return 0;
- }
- # Start addresses are already the right length (8 or 16 hex digits).
- my @names = sort { $symbol_table->{$a}->[0] cmp $symbol_table->{$b}->[0] }
- keys(%{$symbol_table});
-
- if ($#names < 0) {
- # No symbols: just use addresses
- foreach my $pc (@{$pclist}) {
- my $pcstr = "0x" . $pc;
- $symbols->{$pc} = [$pcstr, "?", $pcstr];
- }
- return 0;
- }
-
- # Sort addresses so we can do a join against nm output
- my $index = 0;
- my $fullname = $names[0];
- my $name = ShortFunctionName($fullname);
- foreach my $pc (sort { $a cmp $b } @{$pclist}) {
- # Adjust for mapped offset
- my $mpc = AddressSub($pc, $offset);
- while (($index < $#names) && ($mpc ge $symbol_table->{$fullname}->[1])){
- $index++;
- $fullname = $names[$index];
- $name = ShortFunctionName($fullname);
- }
- if ($mpc lt $symbol_table->{$fullname}->[1]) {
- $symbols->{$pc} = [$name, "?", $fullname];
- } else {
- my $pcstr = "0x" . $pc;
- $symbols->{$pc} = [$pcstr, "?", $pcstr];
- }
- }
- return 1;
-}
-
-sub ShortFunctionName {
- my $function = shift;
- while ($function =~ s/(?<!\.)\([^()]*\)(\s*const)?//g) { } # Argument types
- while ($function =~ s/<[^<>]*>//g) { } # Remove template arguments
- $function =~ s/^.*\s+(\w+::)/$1/; # Remove leading type
- return $function;
-}
-
-# Trim overly long symbols found in disassembler output
-sub CleanDisassembly {
- my $d = shift;
- while ($d =~ s/(?<!\.)\([^()%A-Z]*\)(\s*const)?//g) { } # Argument types, not (%rax)
- while ($d =~ s/(\w+)<[^<>]*>/$1/g) { } # Remove template arguments
- return $d;
-}
-
-##### Miscellaneous #####
-
-# Find the right versions of the above object tools to use. The
-# argument is the program file being analyzed, and should be an ELF
-# 32-bit or ELF 64-bit executable file. The location of the tools
-# is determined by considering the following options in this order:
-# 1) --tools option, if set
-# 2) PPROF_TOOLS environment variable, if set
-# 3) the environment
-sub ConfigureObjTools {
- my $prog_file = shift;
-
- # Check for the existence of $prog_file because /usr/bin/file does not
- # predictably return error status in prod.
- (-e $prog_file) || error("$prog_file does not exist.\n");
-
- # Follow symlinks (at least for systems where "file" supports that)
- my $file_cmd = "/usr/bin/file -L $prog_file 2>$DEVNULL || /usr/bin/file $prog_file 2>$DEVNULL";
- if ($^O eq "MSWin32") {
- $file_cmd = "file -L $prog_file 2>NUL || file $prog_file 2>NUL";
- }
- my $file_type = `$file_cmd`;
-
- if ($file_type =~ /64-bit/) {
- # Change $address_length to 16 if the program file is ELF 64-bit.
- # We can't detect this from many (most?) heap or lock contention
- # profiles, since the actual addresses referenced are generally in low
- # memory even for 64-bit programs.
- $address_length = 16;
- }
-
- if (($file_type =~ /MS Windows/) || ($OS eq "windows")) {
- # For windows, we provide a version of nm and addr2line as part of
- # the opensource release, which is capable of parsing
- # Windows-style PDB executables. It should live in the path, or
- # in the same directory as pprof.
- $obj_tool_map{"nm_pdb"} = "nm-pdb";
- $obj_tool_map{"addr2line_pdb"} = "addr2line-pdb";
- $obj_tool_map{"objdump"} = "false"; # no objdump
- }
-
- if ($file_type =~ /Mach-O/) {
- # OS X uses otool to examine Mach-O files, rather than objdump.
- $obj_tool_map{"otool"} = "otool";
- $obj_tool_map{"addr2line"} = "false"; # no addr2line
- $obj_tool_map{"objdump"} = "false"; # no objdump
- }
-
- # Go fill in %obj_tool_map with the pathnames to use:
- foreach my $tool (keys %obj_tool_map) {
- $obj_tool_map{$tool} = ConfigureTool($obj_tool_map{$tool});
- }
-}
-
-# Returns the path of a caller-specified object tool. If --tools or
-# PPROF_TOOLS are specified, then returns the full path to the tool
-# with that prefix. Otherwise, returns the path unmodified (which
-# means we will look for it on PATH).
-sub ConfigureTool {
- my $tool = shift;
- my $path;
-
- if ($main::opt_tools ne "") {
- # Use a prefix specified by the --tools option...
- $path = $main::opt_tools . $tool;
- if (!-x $path) {
- error("No '$tool' found with prefix specified by --tools $main::opt_tools\n");
- }
- } elsif (exists $ENV{"PPROF_TOOLS"} &&
- $ENV{"PPROF_TOOLS"} ne "") {
- #... or specified with the PPROF_TOOLS environment variable...
- $path = $ENV{"PPROF_TOOLS"} . $tool;
- if (!-x $path) {
- error("No '$tool' found with prefix specified by PPROF_TOOLS=$ENV{PPROF_TOOLS}\n");
- }
- } else {
- # ... otherwise use the version that exists in the same directory as
- # pprof. If there's nothing there, use $PATH.
- $0 =~ m,[^/]*$,; # this is everything after the last slash
- my $dirname = $`; # this is everything up to and including the last slash
- if (-x "$dirname$tool") {
- $path = "$dirname$tool";
- } else {
- $path = $tool;
- }
- }
- if ($main::opt_debug) { print STDERR "Using '$path' for '$tool'.\n"; }
- return $path;
-}
-
-# FetchHTTP retrieves a URL using either curl or LWP::UserAgent.
-# It returns the entire body of the page on success, or exits the program
-# with an error message on any failure.
-sub FetchHTTP {
- my $url = shift;
- my $timeout = shift; # optional, in seconds
- eval "use LWP::UserAgent ();";
- if ($@) {
- my @max;
- push @max, "--max-time", $timeout if $timeout;
- open(my $fh, "-|", "curl", @max, "-s", $url) or error("Neither LWP::UserAgent nor curl is installed: $!\n");
- my $slurp = do { local $/; <$fh> };
- close($fh);
- if ($? != 0) {
- error("Error fetching $url with curl: exit $?")
- }
- return $slurp;
- }
- my $ua = LWP::UserAgent->new;
- $ua->timeout($timeout) if $timeout;
- my $res = $ua->get($url);
- error("Failed to fetch $url\n") unless $res->is_success();
- return $res->content();
-}
-
-sub PostHTTP {
- my ($url, $post_data) = @_;
- eval "use LWP::UserAgent ();";
- if ($@) {
- open(POSTFILE, ">$main::tmpfile_sym");
- print POSTFILE $post_data;
- close(POSTFILE);
-
- open(my $fh, "-|", "curl", "-s", "-d", "\@$main::tmpfile_sym", $url) or error("Neither LWP::UserAgent nor curl is installed: $!\n");
- my $slurp = do { local $/; <$fh> };
- close($fh);
- if ($? != 0) {
- error("Error fetching $url with curl: exit $?")
- }
- return $slurp;
- }
- my $req = HTTP::Request->new(POST => $url);
- $req->content($post_data);
- my $ua = LWP::UserAgent->new;
- my $res = $ua->request($req);
- error("Failed to POST to $url\n") unless $res->is_success();
- return $res->content();
-}
-
-sub cleanup {
- unlink($main::tmpfile_sym) if defined $main::tmpfile_sym;
- unlink(keys %main::tempnames) if %main::tempnames;
- unlink($main::collected_profile) if defined $main::collected_profile;
-
- # We leave any collected profiles in $HOME/pprof in case the user wants
- # to look at them later. We print a message informing them of this.
- if ((scalar(@main::profile_files) > 0) &&
- defined($main::collected_profile)) {
- if (scalar(@main::profile_files) == 1) {
- print STDERR "Dynamically gathered profile is in $main::collected_profile\n";
- }
- print STDERR "If you want to investigate this profile further, you can do:\n";
- print STDERR "\n";
- print STDERR " pprof \\\n";
- print STDERR " $main::prog \\\n";
- print STDERR " $main::collected_profile\n";
- print STDERR "\n";
- }
-}
-
-sub sighandler {
- cleanup();
- exit(1);
-}
-
-sub error {
- my $msg = shift;
- print STDERR $msg;
- cleanup();
- exit(1);
-}
-
-
-# Run $nm_command and get all the resulting procedure boundaries whose
-# names match "$regexp" and returns them in a hashtable mapping from
-# procedure name to a two-element vector of [start address, end address]
-sub GetProcedureBoundariesViaNm {
- my $nm_command = shift;
- my $regexp = shift;
-
- my $symbol_table = {};
- open(NM, "$nm_command |") || error("$nm_command: $!\n");
- my $last_start = "0";
- my $routine = "";
- while (<NM>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- if (m/^\s*([0-9a-f]+) (.) (..*)/) {
- my $start_val = $1;
- my $type = $2;
- my $this_routine = $3;
-
- # It's possible for two symbols to share the same address, if
- # one is a zero-length variable (like __start_google_malloc) or
- # one symbol is a weak alias to another (like __libc_malloc).
- # In such cases, we want to ignore all values except for the
- # actual symbol, which in nm-speak has type "T". The logic
- # below does this, though it's a bit tricky: what happens when
- # we have a series of lines with the same address, is the first
- # one gets queued up to be processed. However, it won't
- # *actually* be processed until later, when we read a line with
- # a different address. That means that as long as we're reading
- # lines with the same address, we have a chance to replace that
- # item in the queue, which we do whenever we see a 'T' entry --
- # that is, a line with type 'T'. If we never see a 'T' entry,
- # we'll just go ahead and process the first entry (which never
- # got touched in the queue), and ignore the others.
- if ($start_val eq $last_start && $type =~ /t/i) {
- # We are the 'T' symbol at this address, replace previous symbol.
- $routine = $this_routine;
- next;
- } elsif ($start_val eq $last_start) {
- # We're not the 'T' symbol at this address, so ignore us.
- next;
- }
-
- if ($this_routine eq $sep_symbol) {
- $sep_address = HexExtend($start_val);
- }
-
- # Tag this routine with the starting address in case the image
- # has multiple occurrences of this routine. We use a syntax
- # that resembles template paramters that are automatically
- # stripped out by ShortFunctionName()
- $this_routine .= "<$start_val>";
-
- if (defined($routine) && $routine =~ m/$regexp/) {
- $symbol_table->{$routine} = [HexExtend($last_start),
- HexExtend($start_val)];
- }
- $last_start = $start_val;
- $routine = $this_routine;
- } elsif (m/^Loaded image name: (.+)/) {
- # The win32 nm workalike emits information about the binary it is using.
- if ($main::opt_debug) { print STDERR "Using Image $1\n"; }
- } elsif (m/^PDB file name: (.+)/) {
- # The win32 nm workalike emits information about the pdb it is using.
- if ($main::opt_debug) { print STDERR "Using PDB $1\n"; }
- }
- }
- close(NM);
- # Handle the last line in the nm output. Unfortunately, we don't know
- # how big this last symbol is, because we don't know how big the file
- # is. For now, we just give it a size of 0.
- # TODO(csilvers): do better here.
- if (defined($routine) && $routine =~ m/$regexp/) {
- $symbol_table->{$routine} = [HexExtend($last_start),
- HexExtend($last_start)];
- }
- return $symbol_table;
-}
-
-# Gets the procedure boundaries for all routines in "$image" whose names
-# match "$regexp" and returns them in a hashtable mapping from procedure
-# name to a two-element vector of [start address, end address].
-# Will return an empty map if nm is not installed or not working properly.
-sub GetProcedureBoundaries {
- my $image = shift;
- my $regexp = shift;
-
- # For libc libraries, the copy in /usr/lib/debug contains debugging symbols
- my $debugging = DebuggingLibrary($image);
- if ($debugging) {
- $image = $debugging;
- }
-
- my $nm = $obj_tool_map{"nm"};
-
- # nm can fail for two reasons: 1) $image isn't a debug library; 2) nm
- # binary doesn't support --demangle. In addition, for OS X we need
- # to use the -f flag to get 'flat' nm output (otherwise we don't sort
- # properly and get incorrect results). Unfortunately, GNU nm uses -f
- # in an incompatible way. So first we test whether our nm supports
- # --demangle and -f.
- my $demangle_flag = "";
- if (system("$nm --demangle $image >$DEVNULL 2>&1") == 0) {
- # In this mode, we do "nm --demangle <foo>"
- $demangle_flag = "--demangle";
- }
- my $flatten_flag = "";
- if (system("$nm -f $image >$DEVNULL 2>&1") == 0) {
- $flatten_flag = "-f";
- }
-
- # Finally, in the case $image isn't a debug library, we try again with
- # -D to at least get *exported* symbols. If we can't use --demangle, too bad.
- my @nm_commands = ("$nm -n $flatten_flag $demangle_flag" .
- " $image 2>$DEVNULL",
- "$nm -D -n $flatten_flag $demangle_flag" .
- " $image 2>$DEVNULL",
- # go tool nm is for Go binaries
- "go tool nm $image 2>$DEVNULL | sort");
-
- foreach my $nm_command (@nm_commands) {
- my $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp);
- return $symbol_table if (%{$symbol_table});
- }
- my $symbol_table = {};
- return $symbol_table;
-}
-
-
-# The test vectors for AddressAdd/Sub/Inc are 8-16-nibble hex strings.
-# To make them more readable, we add underscores at interesting places.
-# This routine removes the underscores, producing the canonical representation
-# used by pprof to represent addresses, particularly in the tested routines.
-sub CanonicalHex {
- my $arg = shift;
- return join '', (split '_',$arg);
-}
-
-
-# Unit test for AddressAdd:
-sub AddressAddUnitTest {
- my $test_data_8 = shift;
- my $test_data_16 = shift;
- my $error_count = 0;
- my $fail_count = 0;
- my $pass_count = 0;
- # print STDERR "AddressAddUnitTest: ", 1+$#{$test_data_8}, " tests\n";
-
- # First a few 8-nibble addresses. Note that this implementation uses
- # plain old arithmetic, so a quick sanity check along with verifying what
- # happens to overflow (we want it to wrap):
- $address_length = 8;
- foreach my $row (@{$test_data_8}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressAdd ($row->[0], $row->[1]);
- if ($sum ne $row->[2]) {
- printf STDERR "ERROR: %s != %s + %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[2];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressAdd 32-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count = $fail_count;
- $fail_count = 0;
- $pass_count = 0;
-
- # Now 16-nibble addresses.
- $address_length = 16;
- foreach my $row (@{$test_data_16}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressAdd (CanonicalHex($row->[0]), CanonicalHex($row->[1]));
- my $expected = join '', (split '_',$row->[2]);
- if ($sum ne CanonicalHex($row->[2])) {
- printf STDERR "ERROR: %s != %s + %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[2];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressAdd 64-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count += $fail_count;
-
- return $error_count;
-}
-
-
-# Unit test for AddressSub:
-sub AddressSubUnitTest {
- my $test_data_8 = shift;
- my $test_data_16 = shift;
- my $error_count = 0;
- my $fail_count = 0;
- my $pass_count = 0;
- # print STDERR "AddressSubUnitTest: ", 1+$#{$test_data_8}, " tests\n";
-
- # First a few 8-nibble addresses. Note that this implementation uses
- # plain old arithmetic, so a quick sanity check along with verifying what
- # happens to overflow (we want it to wrap):
- $address_length = 8;
- foreach my $row (@{$test_data_8}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressSub ($row->[0], $row->[1]);
- if ($sum ne $row->[3]) {
- printf STDERR "ERROR: %s != %s - %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[3];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressSub 32-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count = $fail_count;
- $fail_count = 0;
- $pass_count = 0;
-
- # Now 16-nibble addresses.
- $address_length = 16;
- foreach my $row (@{$test_data_16}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressSub (CanonicalHex($row->[0]), CanonicalHex($row->[1]));
- if ($sum ne CanonicalHex($row->[3])) {
- printf STDERR "ERROR: %s != %s - %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[3];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressSub 64-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count += $fail_count;
-
- return $error_count;
-}
-
-
-# Unit test for AddressInc:
-sub AddressIncUnitTest {
- my $test_data_8 = shift;
- my $test_data_16 = shift;
- my $error_count = 0;
- my $fail_count = 0;
- my $pass_count = 0;
- # print STDERR "AddressIncUnitTest: ", 1+$#{$test_data_8}, " tests\n";
-
- # First a few 8-nibble addresses. Note that this implementation uses
- # plain old arithmetic, so a quick sanity check along with verifying what
- # happens to overflow (we want it to wrap):
- $address_length = 8;
- foreach my $row (@{$test_data_8}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressInc ($row->[0]);
- if ($sum ne $row->[4]) {
- printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum,
- $row->[0], $row->[4];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressInc 32-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count = $fail_count;
- $fail_count = 0;
- $pass_count = 0;
-
- # Now 16-nibble addresses.
- $address_length = 16;
- foreach my $row (@{$test_data_16}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressInc (CanonicalHex($row->[0]));
- if ($sum ne CanonicalHex($row->[4])) {
- printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum,
- $row->[0], $row->[4];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressInc 64-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count += $fail_count;
-
- return $error_count;
-}
-
-
-# Driver for unit tests.
-# Currently just the address add/subtract/increment routines for 64-bit.
-sub RunUnitTests {
- my $error_count = 0;
-
- # This is a list of tuples [a, b, a+b, a-b, a+1]
- my $unit_test_data_8 = [
- [qw(aaaaaaaa 50505050 fafafafa 5a5a5a5a aaaaaaab)],
- [qw(50505050 aaaaaaaa fafafafa a5a5a5a6 50505051)],
- [qw(ffffffff aaaaaaaa aaaaaaa9 55555555 00000000)],
- [qw(00000001 ffffffff 00000000 00000002 00000002)],
- [qw(00000001 fffffff0 fffffff1 00000011 00000002)],
- ];
- my $unit_test_data_16 = [
- # The implementation handles data in 7-nibble chunks, so those are the
- # interesting boundaries.
- [qw(aaaaaaaa 50505050
- 00_000000f_afafafa 00_0000005_a5a5a5a 00_000000a_aaaaaab)],
- [qw(50505050 aaaaaaaa
- 00_000000f_afafafa ff_ffffffa_5a5a5a6 00_0000005_0505051)],
- [qw(ffffffff aaaaaaaa
- 00_000001a_aaaaaa9 00_0000005_5555555 00_0000010_0000000)],
- [qw(00000001 ffffffff
- 00_0000010_0000000 ff_ffffff0_0000002 00_0000000_0000002)],
- [qw(00000001 fffffff0
- 00_000000f_ffffff1 ff_ffffff0_0000011 00_0000000_0000002)],
-
- [qw(00_a00000a_aaaaaaa 50505050
- 00_a00000f_afafafa 00_a000005_a5a5a5a 00_a00000a_aaaaaab)],
- [qw(0f_fff0005_0505050 aaaaaaaa
- 0f_fff000f_afafafa 0f_ffefffa_5a5a5a6 0f_fff0005_0505051)],
- [qw(00_000000f_fffffff 01_800000a_aaaaaaa
- 01_800001a_aaaaaa9 fe_8000005_5555555 00_0000010_0000000)],
- [qw(00_0000000_0000001 ff_fffffff_fffffff
- 00_0000000_0000000 00_0000000_0000002 00_0000000_0000002)],
- [qw(00_0000000_0000001 ff_fffffff_ffffff0
- ff_fffffff_ffffff1 00_0000000_0000011 00_0000000_0000002)],
- ];
-
- $error_count += AddressAddUnitTest($unit_test_data_8, $unit_test_data_16);
- $error_count += AddressSubUnitTest($unit_test_data_8, $unit_test_data_16);
- $error_count += AddressIncUnitTest($unit_test_data_8, $unit_test_data_16);
- if ($error_count > 0) {
- print STDERR $error_count, " errors: FAILED\n";
- } else {
- print STDERR "PASS\n";
- }
- exit ($error_count);
-}
diff --git a/misc/vim/autoload/go/complete.vim b/misc/vim/autoload/go/complete.vim
deleted file mode 100644
index a4fa6b668..000000000
--- a/misc/vim/autoload/go/complete.vim
+++ /dev/null
@@ -1,103 +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.
-"
-" This file provides a utility function that performs auto-completion of
-" package names, for use by other commands.
-
-let s:goos = $GOOS
-let s:goarch = $GOARCH
-
-if len(s:goos) == 0
- if exists('g:golang_goos')
- let s:goos = g:golang_goos
- elseif has('win32') || has('win64')
- let s:goos = 'windows'
- elseif has('macunix')
- let s:goos = 'darwin'
- else
- let s:goos = '*'
- endif
-endif
-
-if len(s:goarch) == 0
- if exists('g:golang_goarch')
- let s:goarch = g:golang_goarch
- else
- let s:goarch = '*'
- endif
-endif
-
-function! go#complete#PackageMembers(package, member)
- silent! let content = system('godoc ' . a:package)
- if v:shell_error || !len(content)
- return []
- endif
- let lines = filter(split(content, "\n"),"v:val !~ '^\\s\\+$'")
- try
- let mx1 = '^\s\+\(\S+\)\s\+=\s\+.*'
- let mx2 = '^\%(const\|var\|type\|func\) \([A-Z][^ (]\+\).*'
- let candidates =
- \ map(filter(copy(lines), 'v:val =~ mx1'), 'substitute(v:val, mx1, "\\1", "")')
- \ + map(filter(copy(lines), 'v:val =~ mx2'), 'substitute(v:val, mx2, "\\1", "")')
- return filter(candidates, '!stridx(v:val, a:member)')
- catch
- return []
- endtry
-endfunction
-
-function! go#complete#Package(ArgLead, CmdLine, CursorPos)
- let dirs = []
-
- let words = split(a:CmdLine, '\s\+', 1)
- if len(words) > 2
- " Complete package members
- return go#complete#PackageMembers(words[1], words[2])
- endif
-
- if executable('go')
- let goroot = substitute(system('go env GOROOT'), '\n', '', 'g')
- if v:shell_error
- echomsg '''go env GOROOT'' failed'
- endif
- else
- let goroot = $GOROOT
- endif
-
- if len(goroot) != 0 && isdirectory(goroot)
- let dirs += [goroot]
- endif
-
- let pathsep = ':'
- if s:goos == 'windows'
- let pathsep = ';'
- endif
- let workspaces = split($GOPATH, pathsep)
- if workspaces != []
- let dirs += workspaces
- endif
-
- if len(dirs) == 0
- " should not happen
- return []
- endif
-
- let ret = {}
- for dir in dirs
- " this may expand to multiple lines
- let root = split(expand(dir . '/pkg/' . s:goos . '_' . s:goarch), "\n")
- call add(root, expand(dir . '/src'))
- for r in root
- for i in split(globpath(r, a:ArgLead.'*'), "\n")
- if isdirectory(i)
- let i .= '/'
- elseif i !~ '\.a$'
- continue
- endif
- let i = substitute(substitute(i[len(r)+1:], '[\\]', '/', 'g'), '\.a$', '', 'g')
- let ret[i] = i
- endfor
- endfor
- endfor
- return sort(keys(ret))
-endfunction
diff --git a/misc/vim/compiler/go.vim b/misc/vim/compiler/go.vim
deleted file mode 100644
index 2c8cce497..000000000
--- a/misc/vim/compiler/go.vim
+++ /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.
-"
-" compiler/go.vim: Vim compiler file for Go.
-
-if exists("current_compiler")
- finish
-endif
-let current_compiler = "go"
-
-if exists(":CompilerSet") != 2
- command -nargs=* CompilerSet setlocal <args>
-endif
-
-let s:save_cpo = &cpo
-set cpo-=C
-
-CompilerSet makeprg=go\ build
-CompilerSet errorformat=
- \%-G#\ %.%#,
- \%A%f:%l:%c:\ %m,
- \%A%f:%l:\ %m,
- \%C%*\\s%m,
- \%-G%.%#
-
-let &cpo = s:save_cpo
-unlet s:save_cpo
-
-" vim:ts=4:sw=4:et
diff --git a/misc/vim/ftdetect/gofiletype.vim b/misc/vim/ftdetect/gofiletype.vim
deleted file mode 100644
index b658f6b0e..000000000
--- a/misc/vim/ftdetect/gofiletype.vim
+++ /dev/null
@@ -1,23 +0,0 @@
-" We take care to preserve the user's fileencodings and fileformats,
-" because those settings are global (not buffer local), yet we want
-" to override them for loading Go files, which are defined to be UTF-8.
-let s:current_fileformats = ''
-let s:current_fileencodings = ''
-
-" define fileencodings to open as utf-8 encoding even if it's ascii.
-function! s:gofiletype_pre()
- let s:current_fileformats = &g:fileformats
- let s:current_fileencodings = &g:fileencodings
- set fileencodings=utf-8 fileformats=unix
- setlocal filetype=go
-endfunction
-
-" restore fileencodings as others
-function! s:gofiletype_post()
- let &g:fileformats = s:current_fileformats
- let &g:fileencodings = s:current_fileencodings
-endfunction
-
-au BufNewFile *.go setlocal filetype=go fileencoding=utf-8 fileformat=unix
-au BufRead *.go call s:gofiletype_pre()
-au BufReadPost *.go call s:gofiletype_post()
diff --git a/misc/vim/ftplugin/go.vim b/misc/vim/ftplugin/go.vim
deleted file mode 100644
index 532fb1723..000000000
--- a/misc/vim/ftplugin/go.vim
+++ /dev/null
@@ -1,19 +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.
-"
-" go.vim: Vim filetype plugin for Go.
-
-if exists("b:did_ftplugin")
- finish
-endif
-let b:did_ftplugin = 1
-
-setlocal formatoptions-=t
-
-setlocal comments=s1:/*,mb:*,ex:*/,://
-setlocal commentstring=//\ %s
-
-let b:undo_ftplugin = "setl fo< com< cms<"
-
-" vim:ts=4:sw=4:et
diff --git a/misc/vim/ftplugin/go/fmt.vim b/misc/vim/ftplugin/go/fmt.vim
deleted file mode 100644
index 359545bd4..000000000
--- a/misc/vim/ftplugin/go/fmt.vim
+++ /dev/null
@@ -1,69 +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.
-"
-" fmt.vim: Vim command to format Go files with gofmt.
-"
-" This filetype plugin add a new commands for go buffers:
-"
-" :Fmt
-"
-" Filter the current Go buffer through gofmt.
-" It tries to preserve cursor position and avoids
-" replacing the buffer with stderr output.
-"
-" Options:
-"
-" g:go_fmt_commands [default=1]
-"
-" Flag to indicate whether to enable the commands listed above.
-"
-" g:gofmt_command [default="gofmt"]
-"
-" Flag naming the gofmt executable to use.
-"
-if exists("b:did_ftplugin_go_fmt")
- finish
-endif
-
-if !exists("g:go_fmt_commands")
- let g:go_fmt_commands = 1
-endif
-
-if !exists("g:gofmt_command")
- let g:gofmt_command = "gofmt"
-endif
-
-if g:go_fmt_commands
- command! -buffer Fmt call s:GoFormat()
-endif
-
-function! s:GoFormat()
- let view = winsaveview()
- silent execute "%!" . g:gofmt_command
- if v:shell_error
- let errors = []
- for line in getline(1, line('$'))
- let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)')
- if !empty(tokens)
- call add(errors, {"filename": @%,
- \"lnum": tokens[2],
- \"col": tokens[3],
- \"text": tokens[4]})
- endif
- endfor
- if empty(errors)
- % | " Couldn't detect gofmt error format, output errors
- endif
- undo
- if !empty(errors)
- call setqflist(errors, 'r')
- endif
- echohl Error | echomsg "Gofmt returned error" | echohl None
- endif
- call winrestview(view)
-endfunction
-
-let b:did_ftplugin_go_fmt = 1
-
-" vim:ts=4:sw=4:et
diff --git a/misc/vim/ftplugin/go/import.vim b/misc/vim/ftplugin/go/import.vim
deleted file mode 100644
index 91c8697a4..000000000
--- a/misc/vim/ftplugin/go/import.vim
+++ /dev/null
@@ -1,250 +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.
-"
-" import.vim: Vim commands to import/drop Go packages.
-"
-" This filetype plugin adds three new commands for go buffers:
-"
-" :Import {path}
-"
-" Import ensures that the provided package {path} is imported
-" in the current Go buffer, using proper style and ordering.
-" If {path} is already being imported, an error will be
-" displayed and the buffer will be untouched.
-"
-" :ImportAs {localname} {path}
-"
-" Same as Import, but uses a custom local name for the package.
-"
-" :Drop {path}
-"
-" Remove the import line for the provided package {path}, if
-" present in the current Go buffer. If {path} is not being
-" imported, an error will be displayed and the buffer will be
-" untouched.
-"
-" If you would like to add shortcuts, you can do so by doing the following:
-"
-" Import fmt
-" au Filetype go nnoremap <buffer> <LocalLeader>f :Import fmt<CR>
-"
-" Drop fmt
-" au Filetype go nnoremap <buffer> <LocalLeader>F :Drop fmt<CR>
-"
-" Import the word under your cursor
-" au Filetype go nnoremap <buffer> <LocalLeader>k
-" \ :exe 'Import ' . expand('<cword>')<CR>
-"
-" The backslash '\' is the default maplocalleader, so it is possible that
-" your vim is set to use a different character (:help maplocalleader).
-"
-" Options:
-"
-" g:go_import_commands [default=1]
-"
-" Flag to indicate whether to enable the commands listed above.
-"
-if exists("b:did_ftplugin_go_import")
- finish
-endif
-
-if !exists("g:go_import_commands")
- let g:go_import_commands = 1
-endif
-
-if g:go_import_commands
- command! -buffer -nargs=? -complete=customlist,go#complete#Package Drop call s:SwitchImport(0, '', <f-args>)
- command! -buffer -nargs=1 -complete=customlist,go#complete#Package Import call s:SwitchImport(1, '', <f-args>)
- command! -buffer -nargs=* -complete=customlist,go#complete#Package ImportAs call s:SwitchImport(1, <f-args>)
-endif
-
-function! s:SwitchImport(enabled, localname, path)
- let view = winsaveview()
- let path = a:path
-
- " Quotes are not necessary, so remove them if provided.
- if path[0] == '"'
- let path = strpart(path, 1)
- endif
- if path[len(path)-1] == '"'
- let path = strpart(path, 0, len(path) - 1)
- endif
- if path == ''
- call s:Error('Import path not provided')
- return
- endif
-
- " Extract any site prefix (e.g. github.com/).
- " If other imports with the same prefix are grouped separately,
- " we will add this new import with them.
- " Only up to and including the first slash is used.
- let siteprefix = matchstr(path, "^[^/]*/")
-
- let qpath = '"' . path . '"'
- if a:localname != ''
- let qlocalpath = a:localname . ' ' . qpath
- else
- let qlocalpath = qpath
- endif
- let indentstr = 0
- let packageline = -1 " Position of package name statement
- let appendline = -1 " Position to introduce new import
- let deleteline = -1 " Position of line with existing import
- let linesdelta = 0 " Lines added/removed
-
- " Find proper place to add/remove import.
- let line = 0
- while line <= line('$')
- let linestr = getline(line)
-
- if linestr =~# '^package\s'
- let packageline = line
- let appendline = line
-
- elseif linestr =~# '^import\s\+('
- let appendstr = qlocalpath
- let indentstr = 1
- let appendline = line
- let firstblank = -1
- let lastprefix = ""
- while line <= line("$")
- let line = line + 1
- let linestr = getline(line)
- let m = matchlist(getline(line), '^\()\|\(\s\+\)\(\S*\s*\)"\(.\+\)"\)')
- if empty(m)
- if siteprefix == "" && a:enabled
- " must be in the first group
- break
- endif
- " record this position, but keep looking
- if firstblank < 0
- let firstblank = line
- endif
- continue
- endif
- if m[1] == ')'
- " if there's no match, add it to the first group
- if appendline < 0 && firstblank >= 0
- let appendline = firstblank
- endif
- break
- endif
- let lastprefix = matchstr(m[4], "^[^/]*/")
- if a:localname != '' && m[3] != ''
- let qlocalpath = printf('%-' . (len(m[3])-1) . 's %s', a:localname, qpath)
- endif
- let appendstr = m[2] . qlocalpath
- let indentstr = 0
- if m[4] == path
- let appendline = -1
- let deleteline = line
- break
- elseif m[4] < path
- " don't set candidate position if we have a site prefix,
- " we've passed a blank line, and this doesn't share the same
- " site prefix.
- if siteprefix == "" || firstblank < 0 || match(m[4], "^" . siteprefix) >= 0
- let appendline = line
- endif
- elseif siteprefix != "" && match(m[4], "^" . siteprefix) >= 0
- " first entry of site group
- let appendline = line - 1
- break
- endif
- endwhile
- break
-
- elseif linestr =~# '^import '
- if appendline == packageline
- let appendstr = 'import ' . qlocalpath
- let appendline = line - 1
- endif
- let m = matchlist(linestr, '^import\(\s\+\)\(\S*\s*\)"\(.\+\)"')
- if !empty(m)
- if m[3] == path
- let appendline = -1
- let deleteline = line
- break
- endif
- if m[3] < path
- let appendline = line
- endif
- if a:localname != '' && m[2] != ''
- let qlocalpath = printf("%s %" . len(m[2])-1 . "s", a:localname, qpath)
- endif
- let appendstr = 'import' . m[1] . qlocalpath
- endif
-
- elseif linestr =~# '^\(var\|const\|type\|func\)\>'
- break
-
- endif
- let line = line + 1
- endwhile
-
- " Append or remove the package import, as requested.
- if a:enabled
- if deleteline != -1
- call s:Error(qpath . ' already being imported')
- elseif appendline == -1
- call s:Error('No package line found')
- else
- if appendline == packageline
- call append(appendline + 0, '')
- call append(appendline + 1, 'import (')
- call append(appendline + 2, ')')
- let appendline += 2
- let linesdelta += 3
- let appendstr = qlocalpath
- let indentstr = 1
- endif
- call append(appendline, appendstr)
- execute appendline + 1
- if indentstr
- execute 'normal >>'
- endif
- let linesdelta += 1
- endif
- else
- if deleteline == -1
- call s:Error(qpath . ' not being imported')
- else
- execute deleteline . 'd'
- let linesdelta -= 1
-
- if getline(deleteline-1) =~# '^import\s\+(' && getline(deleteline) =~# '^)'
- " Delete empty import block
- let deleteline -= 1
- execute deleteline . "d"
- execute deleteline . "d"
- let linesdelta -= 2
- endif
-
- if getline(deleteline) == '' && getline(deleteline - 1) == ''
- " Delete spacing for removed line too.
- execute deleteline . "d"
- let linesdelta -= 1
- endif
- endif
- endif
-
- " Adjust view for any changes.
- let view.lnum += linesdelta
- let view.topline += linesdelta
- if view.topline < 0
- let view.topline = 0
- endif
-
- " Put buffer back where it was.
- call winrestview(view)
-
-endfunction
-
-function! s:Error(s)
- echohl Error | echo a:s | echohl None
-endfunction
-
-let b:did_ftplugin_go_import = 1
-
-" vim:ts=4:sw=4:et
diff --git a/misc/vim/ftplugin/go/test.sh b/misc/vim/ftplugin/go/test.sh
deleted file mode 100755
index d8a5b8951..000000000
--- a/misc/vim/ftplugin/go/test.sh
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/bin/bash -e
-#
-# 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.
-#
-# Tests for import.vim.
-
-cd $(dirname $0)
-
-cat > base.go <<EOF
-package test
-
-import (
- "bytes"
- "io"
- "net"
-
- "mycorp/foo"
-)
-EOF
-
-fail=0
-
-# usage: test_one command pattern
-# Pattern is a PCRE expression that will match across lines.
-test_one() {
- echo 2>&1 -n "$1: "
- vim -e -s -u /dev/null -U /dev/null --noplugin -c "source import.vim" \
- -c "$1" -c 'wq! test.go' base.go
- # ensure blank lines are treated correctly
- if ! gofmt test.go | cmp test.go -; then
- echo 2>&1 "gofmt conflict"
- gofmt test.go | diff -u test.go - | sed "s/^/ /" 2>&1
- fail=1
- return
- fi
- if ! [[ $(cat test.go) =~ $2 ]]; then
- echo 2>&1 "$2 did not match"
- cat test.go | sed "s/^/ /" 2>&1
- fail=1
- return
- fi
- echo 2>&1 "ok"
-}
-
-# Tests for Import
-
-test_one "Import baz" '"baz".*"bytes"'
-test_one "Import io/ioutil" '"io".*"io/ioutil".*"net"'
-test_one "Import myc" '"io".*"myc".*"net"' # prefix of a site prefix
-test_one "Import nat" '"io".*"nat".*"net"'
-test_one "Import net/http" '"net".*"net/http".*"mycorp/foo"'
-test_one "Import zoo" '"net".*"zoo".*"mycorp/foo"'
-test_one "Import mycorp/bar" '"net".*"mycorp/bar".*"mycorp/foo"'
-test_one "Import mycorp/goo" '"net".*"mycorp/foo".*"mycorp/goo"'
-
-# Tests for Drop
-
-cat > base.go <<EOF
-package test
-
-import (
- "foo"
-
- "something"
- "zoo"
-)
-EOF
-
-test_one "Drop something" '\([^"]*"foo"[^"]*"zoo"[^"]*\)'
-
-rm -f base.go test.go
-if [ $fail -gt 0 ]; then
- echo 2>&1 "FAIL"
- exit 1
-fi
-echo 2>&1 "PASS"
diff --git a/misc/vim/indent/go.vim b/misc/vim/indent/go.vim
deleted file mode 100644
index e3d6e8416..000000000
--- a/misc/vim/indent/go.vim
+++ /dev/null
@@ -1,77 +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.
-"
-" indent/go.vim: Vim indent file for Go.
-"
-" TODO:
-" - function invocations split across lines
-" - general line splits (line ends in an operator)
-
-if exists("b:did_indent")
- finish
-endif
-let b:did_indent = 1
-
-" C indentation is too far off useful, mainly due to Go's := operator.
-" Let's just define our own.
-setlocal nolisp
-setlocal autoindent
-setlocal indentexpr=GoIndent(v:lnum)
-setlocal indentkeys+=<:>,0=},0=)
-
-if exists("*GoIndent")
- finish
-endif
-
-" The shiftwidth() function is relatively new.
-" Don't require it to exist.
-if exists('*shiftwidth')
- func s:sw()
- return shiftwidth()
- endfunc
-else
- func s:sw()
- return &shiftwidth
- endfunc
-endif
-
-function! GoIndent(lnum)
- let prevlnum = prevnonblank(a:lnum-1)
- if prevlnum == 0
- " top of file
- return 0
- endif
-
- " grab the previous and current line, stripping comments.
- let prevl = substitute(getline(prevlnum), '//.*$', '', '')
- let thisl = substitute(getline(a:lnum), '//.*$', '', '')
- let previ = indent(prevlnum)
-
- let ind = previ
-
- if prevl =~ '[({]\s*$'
- " previous line opened a block
- let ind += s:sw()
- endif
- if prevl =~# '^\s*\(case .*\|default\):$'
- " previous line is part of a switch statement
- let ind += s:sw()
- endif
- " TODO: handle if the previous line is a label.
-
- if thisl =~ '^\s*[)}]'
- " this line closed a block
- let ind -= s:sw()
- endif
-
- " Colons are tricky.
- " We want to outdent if it's part of a switch ("case foo:" or "default:").
- " We ignore trying to deal with jump labels because (a) they're rare, and
- " (b) they're hard to disambiguate from a composite literal key.
- if thisl =~# '^\s*\(case .*\|default\):$'
- let ind -= s:sw()
- endif
-
- return ind
-endfunction
diff --git a/misc/vim/plugin/godoc.vim b/misc/vim/plugin/godoc.vim
deleted file mode 100644
index a145d313f..000000000
--- a/misc/vim/plugin/godoc.vim
+++ /dev/null
@@ -1,130 +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.
-"
-" godoc.vim: Vim command to see godoc.
-"
-"
-" Commands:
-"
-" :Godoc
-"
-" Open the relevant Godoc for either the word[s] passed to the command or
-" the, by default, the word under the cursor.
-"
-" Options:
-"
-" g:go_godoc_commands [default=1]
-"
-" Flag to indicate whether to enable the commands listed above.
-
-if exists("g:loaded_godoc")
- finish
-endif
-let g:loaded_godoc = 1
-
-let s:buf_nr = -1
-let s:last_word = ''
-
-if !exists('g:go_godoc_commands')
- let g:go_godoc_commands = 1
-endif
-
-if g:go_godoc_commands
- command! -nargs=* -range -complete=customlist,go#complete#Package Godoc :call s:Godoc(<f-args>)
-endif
-
-nnoremap <silent> <Plug>(godoc-keyword) :<C-u>call <SID>Godoc('')<CR>
-
-function! s:GodocView()
- if !bufexists(s:buf_nr)
- leftabove new
- file `="[Godoc]"`
- let s:buf_nr = bufnr('%')
- elseif bufwinnr(s:buf_nr) == -1
- leftabove split
- execute s:buf_nr . 'buffer'
- delete _
- elseif bufwinnr(s:buf_nr) != bufwinnr('%')
- execute bufwinnr(s:buf_nr) . 'wincmd w'
- endif
-
- setlocal filetype=godoc
- setlocal bufhidden=delete
- setlocal buftype=nofile
- setlocal noswapfile
- setlocal nobuflisted
- setlocal modifiable
- setlocal nocursorline
- setlocal nocursorcolumn
- setlocal iskeyword+=:
- setlocal iskeyword-=-
-
- nnoremap <buffer> <silent> K :Godoc<cr>
-
- au BufHidden <buffer> call let <SID>buf_nr = -1
-endfunction
-
-function! s:GodocWord(word)
- if !executable('godoc')
- echohl WarningMsg
- echo "godoc command not found."
- echo " install with: go get code.google.com/p/go.tools/cmd/godoc"
- echohl None
- return 0
- endif
- let word = a:word
- silent! let content = system('godoc ' . word)
- if v:shell_error || !len(content)
- if len(s:last_word)
- silent! let content = system('godoc ' . s:last_word.'/'.word)
- if v:shell_error || !len(content)
- echo 'No documentation found for "' . word . '".'
- return 0
- endif
- let word = s:last_word.'/'.word
- else
- echo 'No documentation found for "' . word . '".'
- return 0
- endif
- endif
- let s:last_word = word
- silent! call s:GodocView()
- setlocal modifiable
- silent! %d _
- silent! put! =content
- silent! normal gg
- setlocal nomodifiable
- setfiletype godoc
- return 1
-endfunction
-
-function! s:Godoc(...)
- if !len(a:000)
- let oldiskeyword = &iskeyword
- setlocal iskeyword+=.
- let word = expand('<cword>')
- let &iskeyword = oldiskeyword
- let word = substitute(word, '[^a-zA-Z0-9\\/._~-]', '', 'g')
- let words = split(word, '\.\ze[^./]\+$')
- else
- let words = a:000
- endif
- if !len(words)
- return
- endif
- if s:GodocWord(words[0])
- if len(words) > 1
- if search('^\%(const\|var\|type\|\s\+\) ' . words[1] . '\s\+=\s')
- return
- endif
- if search('^func ' . words[1] . '(')
- silent! normal zt
- return
- endif
- echo 'No documentation found for "' . words[1] . '".'
- endif
- endif
-endfunction
-
-" vim:ts=4:sw=4:et
diff --git a/misc/vim/readme.txt b/misc/vim/readme.txt
deleted file mode 100644
index 9a9e22870..000000000
--- a/misc/vim/readme.txt
+++ /dev/null
@@ -1,103 +0,0 @@
-Vim plugins for Go (http://golang.org)
-======================================
-
-To use all the Vim plugins, add these lines to your $HOME/.vimrc.
-
- " Some Linux distributions set filetype in /etc/vimrc.
- " Clear filetype flags before changing runtimepath to force Vim to reload them.
- if exists("g:did_load_filetypes")
- filetype off
- filetype plugin indent off
- endif
- set runtimepath+=$GOROOT/misc/vim " replace $GOROOT with the output of: go env GOROOT
- filetype plugin indent on
- syntax on
-
-If you want to select fewer plugins, use the instructions in the rest of
-this file.
-
-A popular configuration is to gofmt Go source files when they are saved.
-To do that, add this line to the end of your $HOME/.vimrc.
-
- autocmd FileType go autocmd BufWritePre <buffer> Fmt
-
-
-Vim syntax highlighting
------------------------
-
-To install automatic syntax highlighting for GO programs:
-
- 1. Copy or link the filetype detection script to the ftdetect directory
- underneath your vim runtime directory (normally $HOME/.vim/ftdetect)
- 2. Copy or link syntax/go.vim to the syntax directory underneath your vim
- runtime directory (normally $HOME/.vim/syntax). Linking this file rather
- than just copying it will ensure any changes are automatically reflected
- in your syntax highlighting.
- 3. Add the following line to your .vimrc file (normally $HOME/.vimrc):
-
- syntax on
-
-In a typical unix environment you might accomplish this using the following
-commands:
-
- mkdir -p $HOME/.vim/ftdetect
- mkdir -p $HOME/.vim/syntax
- mkdir -p $HOME/.vim/autoload/go
- ln -s $GOROOT/misc/vim/ftdetect/gofiletype.vim $HOME/.vim/ftdetect/
- ln -s $GOROOT/misc/vim/syntax/go.vim $HOME/.vim/syntax
- ln -s $GOROOT/misc/vim/autoload/go/complete.vim $HOME/.vim/autoload/go
- echo "syntax on" >> $HOME/.vimrc
-
-
-Vim filetype plugins
---------------------
-
-To install one of the available filetype plugins:
-
- 1. Same as 1 above.
- 2. Copy or link ftplugin/go.vim to the ftplugin directory underneath your vim
- runtime directory (normally $HOME/.vim/ftplugin). Copy or link one or more
- additional plugins from ftplugin/go/*.vim to the Go-specific subdirectory
- in the same place ($HOME/.vim/ftplugin/go/*.vim).
- 3. Add the following line to your .vimrc file (normally $HOME/.vimrc):
-
- filetype plugin on
-
-
-Vim indentation plugin
-----------------------
-
-To install automatic indentation:
-
- 1. Same as 1 above.
- 2. Copy or link indent/go.vim to the indent directory underneath your vim
- runtime directory (normally $HOME/.vim/indent).
- 3. Add the following line to your .vimrc file (normally $HOME/.vimrc):
-
- filetype indent on
-
-
-Vim compiler plugin
--------------------
-
-To install the compiler plugin:
-
- 1. Same as 1 above.
- 2. Copy or link compiler/go.vim to the compiler directory underneath your vim
- runtime directory (normally $HOME/.vim/compiler).
- 3. Activate the compiler plugin with ":compiler go". To always enable the
- compiler plugin in Go source files add an autocommand to your .vimrc file
- (normally $HOME/.vimrc):
-
- autocmd FileType go compiler go
-
-
-Godoc plugin
-------------
-
-To install godoc plugin:
-
- 1. Same as 1 above.
- 2. Copy or link plugin/godoc.vim to $HOME/.vim/plugin/godoc,
- syntax/godoc.vim to $HOME/.vim/syntax/godoc.vim,
- and autoload/go/complete.vim to $HOME/.vim/autoload/go/complete.vim.
diff --git a/misc/vim/syntax/go.vim b/misc/vim/syntax/go.vim
deleted file mode 100644
index 1ce6cb27f..000000000
--- a/misc/vim/syntax/go.vim
+++ /dev/null
@@ -1,207 +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.vim: Vim syntax file for Go.
-"
-" Options:
-" There are some options for customizing the highlighting; the recommended
-" settings are the default values, but you can write:
-" let OPTION_NAME = 0
-" in your ~/.vimrc file to disable particular options. You can also write:
-" let OPTION_NAME = 1
-" to enable particular options. At present, all options default to on.
-"
-" - go_highlight_array_whitespace_error
-" Highlights white space after "[]".
-" - go_highlight_chan_whitespace_error
-" Highlights white space around the communications operator that don't follow
-" the standard style.
-" - go_highlight_extra_types
-" Highlights commonly used library types (io.Reader, etc.).
-" - go_highlight_space_tab_error
-" Highlights instances of tabs following spaces.
-" - go_highlight_trailing_whitespace_error
-" Highlights trailing white space.
-
-" Quit when a (custom) syntax file was already loaded
-if exists("b:current_syntax")
- finish
-endif
-
-if !exists("go_highlight_array_whitespace_error")
- let go_highlight_array_whitespace_error = 1
-endif
-if !exists("go_highlight_chan_whitespace_error")
- let go_highlight_chan_whitespace_error = 1
-endif
-if !exists("go_highlight_extra_types")
- let go_highlight_extra_types = 1
-endif
-if !exists("go_highlight_space_tab_error")
- let go_highlight_space_tab_error = 1
-endif
-if !exists("go_highlight_trailing_whitespace_error")
- let go_highlight_trailing_whitespace_error = 1
-endif
-
-syn case match
-
-syn keyword goDirective package import
-syn keyword goDeclaration var const type
-syn keyword goDeclType struct interface
-
-hi def link goDirective Statement
-hi def link goDeclaration Keyword
-hi def link goDeclType Keyword
-
-" Keywords within functions
-syn keyword goStatement defer go goto return break continue fallthrough
-syn keyword goConditional if else switch select
-syn keyword goLabel case default
-syn keyword goRepeat for range
-
-hi def link goStatement Statement
-hi def link goConditional Conditional
-hi def link goLabel Label
-hi def link goRepeat Repeat
-
-" Predefined types
-syn keyword goType chan map bool string error
-syn keyword goSignedInts int int8 int16 int32 int64 rune
-syn keyword goUnsignedInts byte uint uint8 uint16 uint32 uint64 uintptr
-syn keyword goFloats float32 float64
-syn keyword goComplexes complex64 complex128
-
-hi def link goType Type
-hi def link goSignedInts Type
-hi def link goUnsignedInts Type
-hi def link goFloats Type
-hi def link goComplexes Type
-
-" Treat func specially: it's a declaration at the start of a line, but a type
-" elsewhere. Order matters here.
-syn match goType /\<func\>/
-syn match goDeclaration /^func\>/
-
-" Predefined functions and values
-syn keyword goBuiltins append cap close complex copy delete imag len
-syn keyword goBuiltins make new panic print println real recover
-syn keyword goConstants iota true false nil
-
-hi def link goBuiltins Keyword
-hi def link goConstants Keyword
-
-" Comments; their contents
-syn keyword goTodo contained TODO FIXME XXX BUG
-syn cluster goCommentGroup contains=goTodo
-syn region goComment start="/\*" end="\*/" contains=@goCommentGroup,@Spell
-syn region goComment start="//" end="$" contains=@goCommentGroup,@Spell
-
-hi def link goComment Comment
-hi def link goTodo Todo
-
-" Go escapes
-syn match goEscapeOctal display contained "\\[0-7]\{3}"
-syn match goEscapeC display contained +\\[abfnrtv\\'"]+
-syn match goEscapeX display contained "\\x\x\{2}"
-syn match goEscapeU display contained "\\u\x\{4}"
-syn match goEscapeBigU display contained "\\U\x\{8}"
-syn match goEscapeError display contained +\\[^0-7xuUabfnrtv\\'"]+
-
-hi def link goEscapeOctal goSpecialString
-hi def link goEscapeC goSpecialString
-hi def link goEscapeX goSpecialString
-hi def link goEscapeU goSpecialString
-hi def link goEscapeBigU goSpecialString
-hi def link goSpecialString Special
-hi def link goEscapeError Error
-
-" Strings and their contents
-syn cluster goStringGroup contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU,goEscapeError
-syn region goString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@goStringGroup
-syn region goRawString start=+`+ end=+`+
-
-hi def link goString String
-hi def link goRawString String
-
-" Characters; their contents
-syn cluster goCharacterGroup contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU
-syn region goCharacter start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=@goCharacterGroup
-
-hi def link goCharacter Character
-
-" Regions
-syn region goBlock start="{" end="}" transparent fold
-syn region goParen start='(' end=')' transparent
-
-" Integers
-syn match goDecimalInt "\<\d\+\([Ee]\d\+\)\?\>"
-syn match goHexadecimalInt "\<0x\x\+\>"
-syn match goOctalInt "\<0\o\+\>"
-syn match goOctalError "\<0\o*[89]\d*\>"
-
-hi def link goDecimalInt Integer
-hi def link goHexadecimalInt Integer
-hi def link goOctalInt Integer
-hi def link Integer Number
-
-" Floating point
-syn match goFloat "\<\d\+\.\d*\([Ee][-+]\d\+\)\?\>"
-syn match goFloat "\<\.\d\+\([Ee][-+]\d\+\)\?\>"
-syn match goFloat "\<\d\+[Ee][-+]\d\+\>"
-
-hi def link goFloat Float
-
-" Imaginary literals
-syn match goImaginary "\<\d\+i\>"
-syn match goImaginary "\<\d\+\.\d*\([Ee][-+]\d\+\)\?i\>"
-syn match goImaginary "\<\.\d\+\([Ee][-+]\d\+\)\?i\>"
-syn match goImaginary "\<\d\+[Ee][-+]\d\+i\>"
-
-hi def link goImaginary Number
-
-" Spaces after "[]"
-if go_highlight_array_whitespace_error != 0
- syn match goSpaceError display "\(\[\]\)\@<=\s\+"
-endif
-
-" Spacing errors around the 'chan' keyword
-if go_highlight_chan_whitespace_error != 0
- " receive-only annotation on chan type
- syn match goSpaceError display "\(<-\)\@<=\s\+\(chan\>\)\@="
- " send-only annotation on chan type
- syn match goSpaceError display "\(\<chan\)\@<=\s\+\(<-\)\@="
- " value-ignoring receives in a few contexts
- syn match goSpaceError display "\(\(^\|[={(,;]\)\s*<-\)\@<=\s\+"
-endif
-
-" Extra types commonly seen
-if go_highlight_extra_types != 0
- syn match goExtraType /\<bytes\.\(Buffer\)\>/
- syn match goExtraType /\<io\.\(Reader\|Writer\|ReadWriter\|ReadWriteCloser\)\>/
- syn match goExtraType /\<reflect\.\(Kind\|Type\|Value\)\>/
- syn match goExtraType /\<unsafe\.Pointer\>/
-endif
-
-" Space-tab error
-if go_highlight_space_tab_error != 0
- syn match goSpaceError display " \+\t"me=e-1
-endif
-
-" Trailing white space error
-if go_highlight_trailing_whitespace_error != 0
- syn match goSpaceError display excludenl "\s\+$"
-endif
-
-hi def link goExtraType Type
-hi def link goSpaceError Error
-
-" Search backwards for a global declaration to start processing the syntax.
-"syn sync match goSync grouphere NONE /^\(const\|var\|type\|func\)\>/
-
-" There's a bug in the implementation of grouphere. For now, use the
-" following as a more expensive/less precise workaround.
-syn sync minlines=500
-
-let b:current_syntax = "go"
diff --git a/misc/vim/syntax/godoc.vim b/misc/vim/syntax/godoc.vim
deleted file mode 100644
index bd4443f7c..000000000
--- a/misc/vim/syntax/godoc.vim
+++ /dev/null
@@ -1,20 +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.
-
-if exists("b:current_syntax")
- finish
-endif
-
-syn case match
-syn match godocTitle "^\([A-Z][A-Z ]*\)$"
-
-command -nargs=+ HiLink hi def link <args>
-
-HiLink godocTitle Title
-
-delcommand HiLink
-
-let b:current_syntax = "godoc"
-
-" vim:ts=4 sts=2 sw=2:
diff --git a/misc/xcode/3/README b/misc/xcode/3/README
deleted file mode 100644
index 69f371c2c..000000000
--- a/misc/xcode/3/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory contains files for Go syntax highlighting in Xcode 3.x.
-See the comments in go.pbfilespec and go.xclangspec for installation
-instructions.
diff --git a/misc/xcode/3/go.pbfilespec b/misc/xcode/3/go.pbfilespec
deleted file mode 100644
index 1034778f5..000000000
--- a/misc/xcode/3/go.pbfilespec
+++ /dev/null
@@ -1,31 +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.pbfilespec
- Go source file spec for Xcode 3
-
- There is not much documentation available regarding the format
- of .pbfilespec files. As a starting point, see for instance the
- outdated documentation at:
- http://maxao.free.fr/xcode-plugin-interface/specifications.html
- and the files in:
- /Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/
-
- Place this file in directory:
- ~/Library/Application Support/Developer/Shared/Xcode/Specifications/
-*/
-
-(
- {
- Identifier = sourcecode.go;
- BasedOn = sourcecode;
- Name = "Go Files";
- Extensions = ("go");
- MIMETypes = ("text/go");
- Language = "xcode.lang.go";
- IsTextFile = YES;
- IsSourceFile = YES;
- }
-)
diff --git a/misc/xcode/3/go.xclangspec b/misc/xcode/3/go.xclangspec
deleted file mode 100644
index 4a8c94d5b..000000000
--- a/misc/xcode/3/go.xclangspec
+++ /dev/null
@@ -1,293 +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.xclangspec
- Go language specification for Xcode 3
-
- This is a preliminary version that supports basic syntax high-lighting
- (such as keywords, literals, and comments) and an attempt to provide
- some structure information (incomplete).
-
- There is not much documentation available regarding the format
- of .xclangspec files. As a starting point, see for instance the
- outdated documentation at:
- http://maxao.free.fr/xcode-plugin-interface/specifications.html
- and the files in:
- /Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/
-
- Place this file in directory:
- ~/Library/Application Support/Developer/Shared/Xcode/Specifications/
-*/
-
-(
-
-// ----------------------------------------------------------------------------
-// Keywords
-
-// TODO How do we get general Unicode identifiers?
-
- {
- Identifier = "xcode.lang.go.identifier";
- Syntax = {
- StartChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
- Chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
- Words = (
- "break",
- "case",
- "chan",
- "const",
- "continue",
-
- "default",
- "defer",
- "else",
- "fallthrough",
- "for",
-
- "func",
- "go",
- "goto",
- "if",
- "import",
-
- "interface",
- "map",
- "package",
- "range",
- "return",
-
- "select",
- "struct",
- "switch",
- "type",
- "var",
- );
- Type = "xcode.syntax.keyword";
- AltType = "xcode.syntax.identifier"; // non-keywords are identifiers
- };
- },
-
-// TODO decide what should go here, if anything
- {
- Identifier = "xcode.lang.go.interestingOperators";
- Syntax = {
- Words = (
- "...",
- ".",
- "*",
- ",",
- ":",
- );
- Type = "xcode.syntax.plain";
- };
- },
-
- {
- Identifier = "xcode.lang.go.rawstring";
- Syntax = {
- Start = "`";
- End = "`";
- Type = "xcode.syntax.string";
- };
- },
-
-// ----------------------------------------------------------------------------
-// Syntax Coloring
-
- {
- Identifier = "xcode.lang.go";
- Description = "Go Coloring";
- BasedOn = "xcode.lang.simpleColoring";
- IncludeInMenu = YES;
- Name = "Go";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer.toplevel";
- IncludeRules = (
- "xcode.lang.go.block",
- "xcode.lang.go.bracketexpr",
- "xcode.lang.go.parenexpr",
- );
- Type = "xcode.syntax.plain";
- };
- },
-
- // The following rule returns tokens to the other rules
- {
- Identifier = "xcode.lang.go.lexer";
- Syntax = {
- IncludeRules = (
- "xcode.lang.go.comment",
- "xcode.lang.go.comment.singleline",
- "xcode.lang.string",
- "xcode.lang.character",
- "xcode.lang.go.rawstring",
- "xcode.lang.go.identifier",
- "xcode.lang.number",
- "xcode.lang.go.interestingOperators",
- );
- };
- },
-
- {
- Identifier = "xcode.lang.go.lexer.toplevel";
- Syntax = {
- IncludeRules = (
- "xcode.lang.go.comment",
- "xcode.lang.go.comment.singleline",
- "xcode.lang.string",
- "xcode.lang.character",
- "xcode.lang.go.rawstring",
- "xcode.lang.go.type.declaration",
- "xcode.lang.go.method.declaration",
- "xcode.lang.go.function.declaration",
- "xcode.lang.go.identifier",
- "xcode.lang.number",
- );
- };
- },
-
- {
- Identifier = "xcode.lang.go.method.declaration";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Rules = (
- "func",
- "xcode.lang.go.parenexpr",
- "xcode.lang.go.identifier",
- "xcode.lang.go.parenexpr",
- );
- Type = "xcode.syntax.declaration.method";
- };
- },
-
- {
- Identifier = "xcode.lang.go.type.declaration";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Rules = (
- "type",
- "xcode.lang.go.identifier",
- );
- Type = "xcode.syntax.typedef";
- };
- },
-
- {
- Identifier = "xcode.lang.go.function.declaration";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Rules = (
- "func",
- "xcode.lang.go.identifier",
- "xcode.lang.go.parenexpr",
- );
- Type = "xcode.syntax.declaration.function";
- };
- },
-
-// ----------------------------------------------------------------------------
-// Blocks
-
- {
- Identifier = "xcode.lang.go.block";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Start = "{";
- End = "}";
- Foldable = YES;
- Recursive = YES;
- IncludeRules = (
- "xcode.lang.go.bracketexpr",
- "xcode.lang.go.parenexpr",
- );
- };
- },
-
- {
- Identifier = "xcode.lang.go.parenexpr";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Start = "(";
- End = ")";
- Recursive = YES;
- IncludeRules = (
- "xcode.lang.go.bracketexpr",
- "xcode.lang.go.block",
- );
- };
- },
-
- {
- Identifier = "xcode.lang.go.bracketexpr";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Start = "[";
- End = "]";
- Recursive = YES;
- IncludeRules = (
- "xcode.lang.go.parenexpr",
- );
- };
- },
-
- {
- Identifier = "xcode.lang.go.comment";
- Syntax = {
- Start = "/*";
- End = "*/";
- Foldable = YES;
- IncludeRules = (
- "xcode.lang.url",
- "xcode.lang.url.mail",
- "xcode.lang.comment.mark",
- );
- Type = "xcode.syntax.comment";
- };
- },
-
- {
- Identifier = "xcode.lang.go.comment.singleline";
- Syntax = {
- Start = "//";
- End = "\n";
- IncludeRules = (
- "xcode.lang.url",
- "xcode.lang.url.mail",
- "xcode.lang.comment.mark",
- );
- Type = "xcode.syntax.comment";
- };
- },
-
- // This rule recognizes special comments markers and adds them
- // to the list of file markers at the top of the editor window.
- // This overrides the markers specified in
- // /Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/BaseSupport.xclangspec
- // and appears to apply them to all languages. Thus, for now
- // "inherit" the existing markers here for backward-compatibility.
- {
- Identifier = "xcode.lang.comment.mark";
- Syntax = {
- StartChars = "BMTF!?";
- Match = (
- // Go-specific markers
- "^\(BUG.*$\)$", // include "BUG" in the markers list
- "^\(TODO.*$\)$", // include "TODO" in the markers list
- // inherited markers
- "^MARK:[ \t]+\(.*\)$",
- "^\(TODO:[ \t]+.*\)$", // include "TODO: " in the markers list
- "^\(FIXME:[ \t]+.*\)$", // include "FIXME: " in the markers list
- "^\(!!!:.*\)$", // include "!!!:" in the markers list
- "^\(\\?\\?\\?:.*\)$" // include "???:" in the markers list
- );
- // This is the order of captures. All of the match strings above need the same order.
- CaptureTypes = (
- "xcode.syntax.mark"
- );
- Type = "xcode.syntax.comment";
- };
- },
-
-)
diff --git a/misc/xcode/4/README b/misc/xcode/4/README
deleted file mode 100644
index 09576d6d5..000000000
--- a/misc/xcode/4/README
+++ /dev/null
@@ -1,2 +0,0 @@
-This directory contains files for Go syntax highlighting in Xcode 4.x.
-For installation, read, edit, and run go4xcode.sh . \ No newline at end of file
diff --git a/misc/xcode/4/go.xclangspec b/misc/xcode/4/go.xclangspec
deleted file mode 100644
index 96edc8000..000000000
--- a/misc/xcode/4/go.xclangspec
+++ /dev/null
@@ -1,290 +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.
-
- go.xclangspec
- Go language specification for Xcode 4.x.
-
- This is a preliminary version that supports basic syntax coloring
- (such as keywords, literals, and comments) and an attempt to provide
- some structure information (incomplete).
-
- There is not much documentation available regarding the format
- of .xclangspec files. As a starting point, see for instance the
- outdated documentation at:
-
- http://maxao.free.fr/xcode-plugin-interface/specifications.html
-
-*/
-
-(
-
-// ----------------------------------------------------------------------------
-// Keywords
-
-// TODO How do we get general Unicode identifiers?
-
- {
- Identifier = "xcode.lang.go.identifier";
- Syntax = {
- StartChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
- Chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
- Words = (
- "break",
- "case",
- "chan",
- "const",
- "continue",
-
- "default",
- "defer",
- "else",
- "fallthrough",
- "for",
-
- "func",
- "go",
- "goto",
- "if",
- "import",
-
- "interface",
- "map",
- "package",
- "range",
- "return",
-
- "select",
- "struct",
- "switch",
- "type",
- "var",
- );
- Type = "xcode.syntax.keyword";
- AltType = "xcode.syntax.identifier"; // non-keywords are identifiers
- };
- },
-
-// TODO decide what should go here, if anything
- {
- Identifier = "xcode.lang.go.interestingOperators";
- Syntax = {
- Words = (
- "...",
- ".",
- "*",
- ",",
- ":",
- );
- Type = "xcode.syntax.plain";
- };
- },
-
- {
- Identifier = "xcode.lang.go.rawstring";
- Syntax = {
- Start = "`";
- End = "`";
- Type = "xcode.syntax.string";
- };
- },
-
-// ----------------------------------------------------------------------------
-// Syntax Coloring
-
- {
- Identifier = "xcode.lang.go";
- Description = "Go Coloring";
- BasedOn = "xcode.lang.simpleColoring";
- IncludeInMenu = YES;
- Name = "Go";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer.toplevel";
- IncludeRules = (
- "xcode.lang.go.block",
- "xcode.lang.go.bracketexpr",
- "xcode.lang.go.parenexpr",
- );
- Type = "xcode.syntax.plain";
- };
- },
-
- // The following rule returns tokens to the other rules
- {
- Identifier = "xcode.lang.go.lexer";
- Syntax = {
- IncludeRules = (
- "xcode.lang.go.comment",
- "xcode.lang.go.comment.singleline",
- "xcode.lang.string",
- "xcode.lang.character",
- "xcode.lang.go.rawstring",
- "xcode.lang.go.identifier",
- "xcode.lang.number",
- "xcode.lang.go.interestingOperators",
- );
- };
- },
-
- {
- Identifier = "xcode.lang.go.lexer.toplevel";
- Syntax = {
- IncludeRules = (
- "xcode.lang.go.comment",
- "xcode.lang.go.comment.singleline",
- "xcode.lang.string",
- "xcode.lang.character",
- "xcode.lang.go.rawstring",
- "xcode.lang.go.type.declaration",
- "xcode.lang.go.method.declaration",
- "xcode.lang.go.function.declaration",
- "xcode.lang.go.identifier",
- "xcode.lang.number",
- );
- };
- },
-
- {
- Identifier = "xcode.lang.go.method.declaration";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Rules = (
- "func",
- "xcode.lang.go.parenexpr",
- "xcode.lang.go.identifier",
- "xcode.lang.go.parenexpr",
- );
- Type = "xcode.syntax.declaration.method";
- };
- },
-
- {
- Identifier = "xcode.lang.go.type.declaration";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Rules = (
- "type",
- "xcode.lang.go.identifier",
- );
- Type = "xcode.syntax.typedef";
- };
- },
-
- {
- Identifier = "xcode.lang.go.function.declaration";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Rules = (
- "func",
- "xcode.lang.go.identifier",
- "xcode.lang.go.parenexpr",
- );
- Type = "xcode.syntax.declaration.function";
- };
- },
-
-// ----------------------------------------------------------------------------
-// Blocks
-
- {
- Identifier = "xcode.lang.go.block";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Start = "{";
- End = "}";
- Foldable = YES;
- Recursive = YES;
- IncludeRules = (
- "xcode.lang.go.bracketexpr",
- "xcode.lang.go.parenexpr",
- );
- };
- },
-
- {
- Identifier = "xcode.lang.go.parenexpr";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Start = "(";
- End = ")";
- Recursive = YES;
- IncludeRules = (
- "xcode.lang.go.bracketexpr",
- "xcode.lang.go.block",
- );
- };
- },
-
- {
- Identifier = "xcode.lang.go.bracketexpr";
- Syntax = {
- Tokenizer = "xcode.lang.go.lexer";
- Start = "[";
- End = "]";
- Recursive = YES;
- IncludeRules = (
- "xcode.lang.go.parenexpr",
- );
- };
- },
-
- {
- Identifier = "xcode.lang.go.comment";
- Syntax = {
- Start = "/*";
- End = "*/";
- Foldable = YES;
- IncludeRules = (
- "xcode.lang.url",
- "xcode.lang.url.mail",
- "xcode.lang.comment.mark",
- );
- Type = "xcode.syntax.comment";
- };
- },
-
- {
- Identifier = "xcode.lang.go.comment.singleline";
- Syntax = {
- Start = "//";
- End = "\n";
- IncludeRules = (
- "xcode.lang.url",
- "xcode.lang.url.mail",
- "xcode.lang.comment.mark",
- );
- Type = "xcode.syntax.comment";
- };
- },
-
- // This rule recognizes special comments markers and adds them
- // to the list of file markers at the top of the editor window.
- // This overrides the markers specified in
- // /Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/BaseSupport.xclangspec
- // and appears to apply them to all languages. Thus, for now
- // "inherit" the existing markers here for backward-compatibility.
- {
- Identifier = "xcode.lang.comment.mark";
- Syntax = {
- StartChars = "BMTF!?";
- Match = (
- // Go-specific markers
- "^\(BUG.*$\)$", // include "BUG" in the markers list
- "^\(TODO.*$\)$", // include "TODO" in the markers list
- // inherited markers
- "^MARK:[ \t]+\(.*\)$",
- "^\(TODO:[ \t]+.*\)$", // include "TODO: " in the markers list
- "^\(FIXME:[ \t]+.*\)$", // include "FIXME: " in the markers list
- "^\(!!!:.*\)$", // include "!!!:" in the markers list
- "^\(\\?\\?\\?:.*\)$" // include "???:" in the markers list
- );
- // This is the order of captures. All of the match strings above need the same order.
- CaptureTypes = (
- "xcode.syntax.mark"
- );
- Type = "xcode.syntax.comment";
- };
- },
-
-)
diff --git a/misc/xcode/4/go4xcode.sh b/misc/xcode/4/go4xcode.sh
deleted file mode 100755
index 4b0125e46..000000000
--- a/misc/xcode/4/go4xcode.sh
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env bash
-# 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.
-
-# Illustrates how a Go language specification can be installed for Xcode 4+,
-# to enable syntax coloring, by adding an entry to a plugindata file.
-#
-# FIXME: Write a decent Xcode plugin to handle the file type association and
-# language specification properly instead of altering Xcode library files.
-
-set -e
-
-# Assumes Xcode 4+.
-XCODE_MAJOR_VERSION=`xcodebuild -version | awk 'NR == 1 {print substr($2,1,1)}'`
-if [ "$XCODE_MAJOR_VERSION" -lt "4" ]; then
- echo "Xcode 4+ not found."
- exit 1
-fi
-
-# DVTFOUNDATION_DIR may vary depending on Xcode setup. If Xcode has installed
-# the `xcode-select` command, it will be determined automatically. Otherwise,
-# change it to reflect your current Xcode setup. Find suitable path with e.g.:
-#
-# find / -type f -name 'DVTFoundation.xcplugindata' 2> /dev/null
-#
-# Example of DVTFOUNDATION_DIR's from "default" Xcode 4+ setups;
-#
-# Xcode 4.1: /Developer/Library/PrivateFrameworks/DVTFoundation.framework/Versions/A/Resources/
-# Xcode 4.3: /Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/
-
-# Defaults to Xcode 4.3's DVTFOUNDATION_DIR. Path is modified automatically if
-# `xcode-select` command is available, as mentioned above.
-DVTFOUNDATION_DIR="/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/"
-
-if type "xcode-select" > /dev/null; then
- DVTFOUNDATION_DIR=`xcode-select --print-path`
- DVTFOUNDATION_DIR+="/.."
- FRAMEWORK_NAME="DVTFoundation.framework"
- DVTFOUNDATION_DIR=`find $DVTFOUNDATION_DIR -name $FRAMEWORK_NAME -print`
- DVTFOUNDATION_DIR+="/Versions/A/Resources"
-fi
-
-PLUGINDATA_FILE="DVTFoundation.xcplugindata"
-
-PLISTBUDDY=/usr/libexec/PlistBuddy
-PLIST_FILE=tmp.plist
-
-# Provide means of deleting the Go entry from the plugindata file.
-if [ "$1" = "--delete-entry" ]; then
- echo "Removing Go language specification entry."
- $PLISTBUDDY -c "Delete :plug-in:extensions:Xcode.SourceCodeLanguage.Go" $DVTFOUNDATION_DIR/$PLUGINDATA_FILE
- echo "Run 'sudo rm -rf /var/folders/*' and restart Xcode to update change immediately."
- exit 0
-fi
-
-GO_VERSION="`go version`"
-
-GO_LANG_ENTRY="
- <?xml version=\"1.0\" encoding=\"UTF-8\"?>
- <!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
- <plist version=\"1.0\">
- <dict>
- <key>Xcode.SourceCodeLanguage.Go</key>
- <dict>
- <key>conformsTo</key>
- <array>
- <dict>
- <key>identifier</key>
- <string>Xcode.SourceCodeLanguage.Generic</string>
- </dict>
- </array>
- <key>documentationAbbreviation</key>
- <string>go</string>
- <key>fileDataType</key>
- <array>
- <dict>
- <key>identifier</key>
- <string>com.apple.xcode.go-source</string>
- </dict>
- </array>
- <key>id</key>
- <string>Xcode.SourceCodeLanguage.Go</string>
- <key>languageName</key>
- <string>Go</string>
- <key>languageSpecification</key>
- <string>xcode.lang.go</string>
- <key>name</key>
- <string>The Go Programming Language</string>
- <key>point</key>
- <string>Xcode.SourceCodeLanguage</string>
- <key>version</key>
- <string>$GO_VERSION</string>
- </dict>
- </dict>
- </plist>
-"
-
-echo "Backing up plugindata file (copied to $PLUGINDATA_FILE.bak)."
-cp $DVTFOUNDATION_DIR/$PLUGINDATA_FILE $DVTFOUNDATION_DIR/$PLUGINDATA_FILE.bak
-
-echo "Adding Go language specification entry."
-echo $GO_LANG_ENTRY > $PLIST_FILE
-$PLISTBUDDY -c "Merge $PLIST_FILE plug-in:extensions" $DVTFOUNDATION_DIR/$PLUGINDATA_FILE
-
-rm -f $PLIST_FILE
-
-echo "Installing Go language specification file for Xcode."
-cp $GOROOT/misc/xcode/4/go.xclangspec $DVTFOUNDATION_DIR
-
-echo "Run 'sudo rm -rf /var/folders/*' and restart Xcode to update change immediately."
-echo "Syntax coloring must be manually selected from the Editor - Syntax Coloring menu in Xcode."
diff --git a/misc/zsh/go b/misc/zsh/go
deleted file mode 100644
index 066cf4065..000000000
--- a/misc/zsh/go
+++ /dev/null
@@ -1,161 +0,0 @@
-# install in /etc/zsh/zshrc or your personal .zshrc
-
-# gc
-prefixes=(5 6 8)
-for p in $prefixes; do
- compctl -g "*.${p}" ${p}l
- compctl -g "*.go" ${p}g
-done
-
-# standard go tools
-compctl -g "*.go" gofmt
-
-# gccgo
-compctl -g "*.go" gccgo
-
-# go tool
-__go_tool_complete() {
- typeset -a commands build_flags
- commands+=(
- 'build[compile packages and dependencies]'
- 'clean[remove object files]'
- 'env[print Go environment information]'
- 'fix[run go tool fix on packages]'
- 'fmt[run gofmt on package sources]'
- 'get[download and install packages and dependencies]'
- 'help[display help]'
- 'install[compile and install packages and dependencies]'
- 'list[list packages]'
- 'run[compile and run Go program]'
- 'test[test packages]'
- 'tool[run specified go tool]'
- 'version[print Go version]'
- 'vet[run go tool vet on packages]'
- )
- if (( CURRENT == 2 )); then
- # explain go commands
- _values 'go tool commands' ${commands[@]}
- return
- fi
- build_flags=(
- '-a[force reinstallation of packages that are already up-to-date]'
- '-n[print the commands but do not run them]'
- '-p[number of parallel builds]:number'
- '-race[enable data race detection]'
- '-x[print the commands]'
- '-work[print temporary directory name and keep it]'
- '-ccflags[flags for 5c/6c/8c]:flags'
- '-gcflags[flags for 5g/6g/8g]:flags'
- '-ldflags[flags for 5l/6l/8l]:flags'
- '-gccgoflags[flags for gccgo]:flags'
- '-compiler[name of compiler to use]:name'
- '-installsuffix[suffix to add to package directory]:suffix'
- '-tags[list of build tags to consider satisfied]:tags'
- )
- __go_list() {
- local expl importpaths
- declare -a importpaths
- importpaths=($(go list ${words[$CURRENT]}... 2>/dev/null))
- _wanted importpaths expl 'import paths' compadd "$@" - "${importpaths[@]}"
- }
- case ${words[2]} in
- clean|doc)
- _arguments -s -w : '*:importpaths:__go_list'
- ;;
- fix|fmt|list|vet)
- _alternative ':importpaths:__go_list' ':files:_path_files -g "*.go"'
- ;;
- install)
- _arguments -s -w : ${build_flags[@]} \
- "-v[show package names]" \
- '*:importpaths:__go_list'
- ;;
- get)
- _arguments -s -w : \
- ${build_flags[@]}
- ;;
- build)
- _arguments -s -w : \
- ${build_flags[@]} \
- "-v[show package names]" \
- "-o[output file]:file:_files" \
- "*:args:{ _alternative ':importpaths:__go_list' ':files:_path_files -g \"*.go\"' }"
- ;;
- test)
- _arguments -s -w : \
- ${build_flags[@]} \
- "-c[do not run, compile the test binary]" \
- "-i[do not run, install dependencies]" \
- "-v[print test output]" \
- "-x[print the commands]" \
- "-short[use short mode]" \
- "-parallel[number of parallel tests]:number" \
- "-cpu[values of GOMAXPROCS to use]:number list" \
- "-cover[enable coverage analysis]" \
- "-run[run tests and examples matching regexp]:regexp" \
- "-bench[run benchmarks matching regexp]:regexp" \
- "-benchmem[print memory allocation stats]" \
- "-benchtime[run each benchmark until taking this long]:duration" \
- "-blockprofile[write goroutine blocking profile to file]:file" \
- "-blockprofilerate[set sampling rate of goroutine blocking profile]:number" \
- "-timeout[kill test after that duration]:duration" \
- "-cpuprofile[write CPU profile to file]:file:_files" \
- "-memprofile[write heap profile to file]:file:_files" \
- "-memprofilerate[set heap profiling rate]:number" \
- "*:args:{ _alternative ':importpaths:__go_list' ':files:_path_files -g \"*.go\"' }"
- ;;
- help)
- _values "${commands[@]}" \
- 'c[how to call C code]' \
- 'importpath[description of import path]' \
- 'gopath[GOPATH environment variable]' \
- 'packages[description of package lists]' \
- 'testflag[description of testing flags]' \
- 'testfunc[description of testing functions]'
- ;;
- run)
- _arguments -s -w : \
- ${build_flags[@]} \
- '*:file:_path_files -g "*.go"'
- ;;
- tool)
- if (( CURRENT == 3 )); then
- _values "go tool" $(go tool)
- return
- fi
- case ${words[3]} in
- [568]g)
- _arguments -s -w : \
- '-I[search for packages in DIR]:includes:_path_files -/' \
- '-L[show full path in file:line prints]' \
- '-S[print the assembly language]' \
- '-V[print the compiler version]' \
- '-e[no limit on number of errors printed]' \
- '-h[panic on an error]' \
- '-l[disable inlining]' \
- '-m[print optimization decisions]' \
- '-o[file specify output file]:file' \
- '-p[assumed import path for this code]:importpath' \
- '-u[disable package unsafe]' \
- "*:file:_files -g '*.go'"
- ;;
- [568]l)
- local O=${words[3]%l}
- _arguments -s -w : \
- '-o[file specify output file]:file' \
- '-L[search for packages in DIR]:includes:_path_files -/' \
- "*:file:_files -g '*.[ao$O]'"
- ;;
- dist)
- _values "dist tool" banner bootstrap clean env install version
- ;;
- *)
- # use files by default
- _files
- ;;
- esac
- ;;
- esac
-}
-
-compdef __go_tool_complete go
diff --git a/src/androidtest.bash b/src/androidtest.bash
new file mode 100755
index 000000000..504d276c4
--- /dev/null
+++ b/src/androidtest.bash
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+# 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.
+
+# For testing Android.
+# The compiler runs locally, then a copy of the GOROOT is pushed to a
+# target device using adb, and the tests are run there.
+
+set -e
+ulimit -c 0 # no core files
+
+if [ ! -f make.bash ]; then
+ echo 'nacl.bash must be run from $GOROOT/src' 1>&2
+ exit 1
+fi
+
+if [ -z $GOOS ]; then
+ export GOOS=android
+fi
+if [ "$GOOS" != "android" ]; then
+ echo "androidtest.bash requires GOOS=android, got GOOS=$GOOS" 1>&2
+ exit 1
+fi
+
+export CGO_ENABLED=1
+
+# Run the build for the host bootstrap, so we can build go_android_exec.
+# Also lets us fail early before the (slow) adb push if the build is broken.
+./make.bash
+export GOROOT=$(dirname $(pwd))
+export PATH=$GOROOT/bin:$PATH
+GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH go build \
+ -o ../bin/go_android_${GOARCH}_exec \
+ ../misc/android/go_android_exec.go
+
+# Push GOROOT to target device.
+#
+# The adb sync command will sync either the /system or /data
+# directories of an android device from a similar directory
+# on the host. So we fake one with symlinks to push the GOROOT
+# into a subdirectory of /data.
+export ANDROID_PRODUCT_OUT=/tmp/androidtest-$$
+FAKE_GOROOT=$ANDROID_PRODUCT_OUT/data/local/tmp/goroot
+mkdir -p $FAKE_GOROOT
+ln -s $GOROOT/src $FAKE_GOROOT/src
+ln -s $GOROOT/test $FAKE_GOROOT/test
+ln -s $GOROOT/lib $FAKE_GOROOT/lib
+echo '# Syncing test files to android device'
+time adb sync data &> /dev/null
+echo ''
+rm -rf "$ANDROID_PRODUCT_OUT"
+
+# Run standard build and tests.
+./all.bash --no-clean
diff --git a/src/pkg/archive/tar/common.go b/src/archive/tar/common.go
index e363aa793..e363aa793 100644
--- a/src/pkg/archive/tar/common.go
+++ b/src/archive/tar/common.go
diff --git a/src/pkg/archive/tar/example_test.go b/src/archive/tar/example_test.go
index 351eaa0e6..351eaa0e6 100644
--- a/src/pkg/archive/tar/example_test.go
+++ b/src/archive/tar/example_test.go
diff --git a/src/pkg/archive/tar/reader.go b/src/archive/tar/reader.go
index 920a9b08f..a27559d0f 100644
--- a/src/pkg/archive/tar/reader.go
+++ b/src/archive/tar/reader.go
@@ -29,10 +29,11 @@ const maxNanoSecondIntSize = 9
// The Next method advances to the next file in the archive (including the first),
// and then it can be treated as an io.Reader to access the file's data.
type Reader struct {
- r io.Reader
- err error
- pad int64 // amount of padding (ignored) after current file entry
- curr numBytesReader // reader for current file entry
+ r io.Reader
+ err error
+ pad int64 // amount of padding (ignored) after current file entry
+ curr numBytesReader // reader for current file entry
+ hdrBuff [blockSize]byte // buffer to use in readHeader
}
// A numBytesReader is an io.Reader with a numBytes method, returning the number
@@ -426,7 +427,9 @@ func (tr *Reader) verifyChecksum(header []byte) bool {
}
func (tr *Reader) readHeader() *Header {
- header := make([]byte, blockSize)
+ header := tr.hdrBuff[:]
+ copy(header, zeroBlock)
+
if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
return nil
}
diff --git a/src/pkg/archive/tar/reader_test.go b/src/archive/tar/reader_test.go
index 9601ffe45..9601ffe45 100644
--- a/src/pkg/archive/tar/reader_test.go
+++ b/src/archive/tar/reader_test.go
diff --git a/src/pkg/archive/tar/stat_atim.go b/src/archive/tar/stat_atim.go
index cf9cc79c5..cf9cc79c5 100644
--- a/src/pkg/archive/tar/stat_atim.go
+++ b/src/archive/tar/stat_atim.go
diff --git a/src/pkg/archive/tar/stat_atimespec.go b/src/archive/tar/stat_atimespec.go
index 6f17dbe30..6f17dbe30 100644
--- a/src/pkg/archive/tar/stat_atimespec.go
+++ b/src/archive/tar/stat_atimespec.go
diff --git a/src/pkg/archive/tar/stat_unix.go b/src/archive/tar/stat_unix.go
index cb843db4c..cb843db4c 100644
--- a/src/pkg/archive/tar/stat_unix.go
+++ b/src/archive/tar/stat_unix.go
diff --git a/src/pkg/archive/tar/tar_test.go b/src/archive/tar/tar_test.go
index ed333f3ea..ed333f3ea 100644
--- a/src/pkg/archive/tar/tar_test.go
+++ b/src/archive/tar/tar_test.go
diff --git a/src/pkg/archive/tar/testdata/gnu.tar b/src/archive/tar/testdata/gnu.tar
index fc899dc8d..fc899dc8d 100644
--- a/src/pkg/archive/tar/testdata/gnu.tar
+++ b/src/archive/tar/testdata/gnu.tar
Binary files differ
diff --git a/src/pkg/archive/tar/testdata/nil-uid.tar b/src/archive/tar/testdata/nil-uid.tar
index cc9cfaa33..cc9cfaa33 100644
--- a/src/pkg/archive/tar/testdata/nil-uid.tar
+++ b/src/archive/tar/testdata/nil-uid.tar
Binary files differ
diff --git a/src/pkg/archive/tar/testdata/pax.tar b/src/archive/tar/testdata/pax.tar
index 9bc24b658..9bc24b658 100644
--- a/src/pkg/archive/tar/testdata/pax.tar
+++ b/src/archive/tar/testdata/pax.tar
Binary files differ
diff --git a/src/pkg/archive/tar/testdata/small.txt b/src/archive/tar/testdata/small.txt
index b249bfc51..b249bfc51 100644
--- a/src/pkg/archive/tar/testdata/small.txt
+++ b/src/archive/tar/testdata/small.txt
diff --git a/src/pkg/archive/tar/testdata/small2.txt b/src/archive/tar/testdata/small2.txt
index 394ee3ecd..394ee3ecd 100644
--- a/src/pkg/archive/tar/testdata/small2.txt
+++ b/src/archive/tar/testdata/small2.txt
diff --git a/src/pkg/archive/tar/testdata/sparse-formats.tar b/src/archive/tar/testdata/sparse-formats.tar
index 8bd4e74d5..8bd4e74d5 100644
--- a/src/pkg/archive/tar/testdata/sparse-formats.tar
+++ b/src/archive/tar/testdata/sparse-formats.tar
Binary files differ
diff --git a/src/pkg/archive/tar/testdata/star.tar b/src/archive/tar/testdata/star.tar
index 59e2d4e60..59e2d4e60 100644
--- a/src/pkg/archive/tar/testdata/star.tar
+++ b/src/archive/tar/testdata/star.tar
Binary files differ
diff --git a/src/pkg/archive/tar/testdata/ustar.tar b/src/archive/tar/testdata/ustar.tar
index 29679d9a3..29679d9a3 100644
--- a/src/pkg/archive/tar/testdata/ustar.tar
+++ b/src/archive/tar/testdata/ustar.tar
Binary files differ
diff --git a/src/pkg/archive/tar/testdata/v7.tar b/src/archive/tar/testdata/v7.tar
index eb65fc941..eb65fc941 100644
--- a/src/pkg/archive/tar/testdata/v7.tar
+++ b/src/archive/tar/testdata/v7.tar
Binary files differ
diff --git a/src/pkg/archive/tar/testdata/writer-big-long.tar b/src/archive/tar/testdata/writer-big-long.tar
index 5960ee824..5960ee824 100644
--- a/src/pkg/archive/tar/testdata/writer-big-long.tar
+++ b/src/archive/tar/testdata/writer-big-long.tar
Binary files differ
diff --git a/src/pkg/archive/tar/testdata/writer-big.tar b/src/archive/tar/testdata/writer-big.tar
index 753e883ce..753e883ce 100644
--- a/src/pkg/archive/tar/testdata/writer-big.tar
+++ b/src/archive/tar/testdata/writer-big.tar
Binary files differ
diff --git a/src/pkg/archive/tar/testdata/writer.tar b/src/archive/tar/testdata/writer.tar
index e6d816ad0..e6d816ad0 100644
--- a/src/pkg/archive/tar/testdata/writer.tar
+++ b/src/archive/tar/testdata/writer.tar
Binary files differ
diff --git a/src/pkg/archive/tar/testdata/xattrs.tar b/src/archive/tar/testdata/xattrs.tar
index 9701950ed..9701950ed 100644
--- a/src/pkg/archive/tar/testdata/xattrs.tar
+++ b/src/archive/tar/testdata/xattrs.tar
Binary files differ
diff --git a/src/pkg/archive/tar/writer.go b/src/archive/tar/writer.go
index 6eff6f6f8..dafb2cabf 100644
--- a/src/pkg/archive/tar/writer.go
+++ b/src/archive/tar/writer.go
@@ -37,8 +37,10 @@ type Writer struct {
nb int64 // number of unwritten bytes for current file entry
pad int64 // amount of padding to write after current file entry
closed bool
- usedBinary bool // whether the binary numeric field extension was used
- preferPax bool // use pax header instead of binary numeric header
+ usedBinary bool // whether the binary numeric field extension was used
+ preferPax bool // use pax header instead of binary numeric header
+ hdrBuff [blockSize]byte // buffer to use in writeHeader when writing a regular header
+ paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header
}
// NewWriter creates a new Writer writing to w.
@@ -160,7 +162,18 @@ 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
- header := make([]byte, blockSize)
+ var header []byte
+
+ // We need to select which scratch buffer to use carefully,
+ // since this method is called recursively to write PAX headers.
+ // If allowPax is true, this is the non-recursive call, and we will use hdrBuff.
+ // If allowPax is false, we are being called by writePAXHeader, and hdrBuff is
+ // already being used by the non-recursive call, so we must use paxHdrBuff.
+ header = tw.hdrBuff[:]
+ if !allowPax {
+ header = tw.paxHdrBuff[:]
+ }
+ copy(header, zeroBlock)
s := slicer(header)
// keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
diff --git a/src/pkg/archive/tar/writer_test.go b/src/archive/tar/writer_test.go
index 512fab1a6..5e42e322f 100644
--- a/src/pkg/archive/tar/writer_test.go
+++ b/src/archive/tar/writer_test.go
@@ -454,3 +454,38 @@ func TestUSTARLongName(t *testing.T) {
t.Fatal("Couldn't recover long name")
}
}
+
+func TestValidTypeflagWithPAXHeader(t *testing.T) {
+ var buffer bytes.Buffer
+ tw := NewWriter(&buffer)
+
+ fileName := strings.Repeat("ab", 100)
+
+ hdr := &Header{
+ Name: fileName,
+ Size: 4,
+ Typeflag: 0,
+ }
+ if err := tw.WriteHeader(hdr); err != nil {
+ t.Fatalf("Failed to write header: %s", err)
+ }
+ if _, err := tw.Write([]byte("fooo")); err != nil {
+ t.Fatalf("Failed to write the file's data: %s", err)
+ }
+ tw.Close()
+
+ tr := NewReader(&buffer)
+
+ for {
+ header, err := tr.Next()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ t.Fatalf("Failed to read header: %s", err)
+ }
+ if header.Typeflag != 0 {
+ t.Fatalf("Typeflag should've been 0, found %d", header.Typeflag)
+ }
+ }
+}
diff --git a/src/pkg/archive/zip/example_test.go b/src/archive/zip/example_test.go
index c2ed9e79c..c2ed9e79c 100644
--- a/src/pkg/archive/zip/example_test.go
+++ b/src/archive/zip/example_test.go
diff --git a/src/pkg/archive/zip/reader.go b/src/archive/zip/reader.go
index 80ee03006..8136b840d 100644
--- a/src/pkg/archive/zip/reader.go
+++ b/src/archive/zip/reader.go
@@ -267,8 +267,13 @@ func readDirectoryHeader(f *File, r io.Reader) error {
b = b[size:]
}
// Should have consumed the whole header.
- if len(b) != 0 {
- return ErrFormat
+ // 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
+ }
}
}
return nil
diff --git a/src/pkg/archive/zip/reader_test.go b/src/archive/zip/reader_test.go
index 5652f3a50..29d0652dc 100644
--- a/src/pkg/archive/zip/reader_test.go
+++ b/src/archive/zip/reader_test.go
@@ -13,6 +13,7 @@ import (
"os"
"path/filepath"
"regexp"
+ "strings"
"testing"
"time"
)
@@ -508,3 +509,25 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) {
b := rZipBytes()
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{
+ "PK\x01\x02\n\x00\n\x00\x00\b\x00\x004\x9d3?\xaa\x1b\x06\xf0\x81\x02\x00\x00\x81\x02\x00\x00-\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00res/drawable-xhdpi-v4/ic_actionbar_accept.png\xfe\xca\x00\x00\x00",
+ "PK\x01\x02\n\x00\n\x00\x00\b\x00\x004\x9d3?\x90K\x89\xc7t\n\x00\x00t\n\x00\x00\x0e\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x02\x00\x00resources.arsc\x00\x00\x00",
+ "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xff$\x18\xed3\x03\x00\x00\xb4\b\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00t\r\x00\x00AndroidManifest.xml",
+ "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\x14\xc5K\xab\x192\x02\x00\xc8\xcd\x04\x00\v\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x10\x00\x00classes.dex",
+ "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?E\x96\nD\xac\x01\x00\x00P\x03\x00\x00&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:C\x02\x00res/layout/actionbar_set_wallpaper.xml",
+ "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?Ļ\x14\xe3\xd8\x01\x00\x00\xd8\x03\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:E\x02\x00res/layout/wallpaper_cropper.xml",
+ "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?}\xc1\x15\x9eZ\x01\x00\x00!\x02\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`G\x02\x00META-INF/MANIFEST.MF",
+ "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xe6\x98Ьo\x01\x00\x00\x84\x02\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfcH\x02\x00META-INF/CERT.SF",
+ "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xbfP\x96b\x86\x04\x00\x00\xb2\x06\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa9J\x02\x00META-INF/CERT.RSA",
+ }
+ for i, s := range dirEnts {
+ var f File
+ err := readDirectoryHeader(&f, strings.NewReader(s))
+ if err != nil {
+ t.Errorf("error reading #%d: %v", i, err)
+ }
+ }
+}
diff --git a/src/pkg/archive/zip/register.go b/src/archive/zip/register.go
index 4211ec7af..4211ec7af 100644
--- a/src/pkg/archive/zip/register.go
+++ b/src/archive/zip/register.go
diff --git a/src/pkg/archive/zip/struct.go b/src/archive/zip/struct.go
index cb28e8324..cb28e8324 100644
--- a/src/pkg/archive/zip/struct.go
+++ b/src/archive/zip/struct.go
diff --git a/src/pkg/archive/zip/testdata/crc32-not-streamed.zip b/src/archive/zip/testdata/crc32-not-streamed.zip
index f268d8873..f268d8873 100644
--- a/src/pkg/archive/zip/testdata/crc32-not-streamed.zip
+++ b/src/archive/zip/testdata/crc32-not-streamed.zip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/dd.zip b/src/archive/zip/testdata/dd.zip
index e53378b0b..e53378b0b 100644
--- a/src/pkg/archive/zip/testdata/dd.zip
+++ b/src/archive/zip/testdata/dd.zip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/go-no-datadesc-sig.zip b/src/archive/zip/testdata/go-no-datadesc-sig.zip
index c3d593f44..c3d593f44 100644
--- a/src/pkg/archive/zip/testdata/go-no-datadesc-sig.zip
+++ b/src/archive/zip/testdata/go-no-datadesc-sig.zip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/go-with-datadesc-sig.zip b/src/archive/zip/testdata/go-with-datadesc-sig.zip
index bcfe121bb..bcfe121bb 100644
--- a/src/pkg/archive/zip/testdata/go-with-datadesc-sig.zip
+++ b/src/archive/zip/testdata/go-with-datadesc-sig.zip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/gophercolor16x16.png b/src/archive/zip/testdata/gophercolor16x16.png
index 48854ff3b..48854ff3b 100644
--- a/src/pkg/archive/zip/testdata/gophercolor16x16.png
+++ b/src/archive/zip/testdata/gophercolor16x16.png
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/readme.notzip b/src/archive/zip/testdata/readme.notzip
index 06668c4c1..06668c4c1 100644
--- a/src/pkg/archive/zip/testdata/readme.notzip
+++ b/src/archive/zip/testdata/readme.notzip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/readme.zip b/src/archive/zip/testdata/readme.zip
index db3bb900e..db3bb900e 100644
--- a/src/pkg/archive/zip/testdata/readme.zip
+++ b/src/archive/zip/testdata/readme.zip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/symlink.zip b/src/archive/zip/testdata/symlink.zip
index af846938c..af846938c 100644
--- a/src/pkg/archive/zip/testdata/symlink.zip
+++ b/src/archive/zip/testdata/symlink.zip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/test-trailing-junk.zip b/src/archive/zip/testdata/test-trailing-junk.zip
index 42281b4e3..42281b4e3 100644
--- a/src/pkg/archive/zip/testdata/test-trailing-junk.zip
+++ b/src/archive/zip/testdata/test-trailing-junk.zip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/test.zip b/src/archive/zip/testdata/test.zip
index 03890c05d..03890c05d 100644
--- a/src/pkg/archive/zip/testdata/test.zip
+++ b/src/archive/zip/testdata/test.zip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/unix.zip b/src/archive/zip/testdata/unix.zip
index ce1a981b2..ce1a981b2 100644
--- a/src/pkg/archive/zip/testdata/unix.zip
+++ b/src/archive/zip/testdata/unix.zip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/winxp.zip b/src/archive/zip/testdata/winxp.zip
index 3919322f0..3919322f0 100644
--- a/src/pkg/archive/zip/testdata/winxp.zip
+++ b/src/archive/zip/testdata/winxp.zip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/zip64-2.zip b/src/archive/zip/testdata/zip64-2.zip
index f844e3537..f844e3537 100644
--- a/src/pkg/archive/zip/testdata/zip64-2.zip
+++ b/src/archive/zip/testdata/zip64-2.zip
Binary files differ
diff --git a/src/pkg/archive/zip/testdata/zip64.zip b/src/archive/zip/testdata/zip64.zip
index a2ee1fa33..a2ee1fa33 100644
--- a/src/pkg/archive/zip/testdata/zip64.zip
+++ b/src/archive/zip/testdata/zip64.zip
Binary files differ
diff --git a/src/pkg/archive/zip/writer.go b/src/archive/zip/writer.go
index 6c9800a78..170beec0e 100644
--- a/src/pkg/archive/zip/writer.go
+++ b/src/archive/zip/writer.go
@@ -34,6 +34,12 @@ func NewWriter(w io.Writer) *Writer {
return &Writer{cw: &countWriter{w: bufio.NewWriter(w)}}
}
+// Flush flushes any buffered data to the underlying writer.
+// Calling Flush is not normally necessary; calling Close is sufficient.
+func (w *Writer) Flush() error {
+ return w.cw.w.(*bufio.Writer).Flush()
+}
+
// Close finishes writing the zip file by writing the central directory.
// It does not (and can not) close the underlying writer.
func (w *Writer) Close() error {
diff --git a/src/pkg/archive/zip/writer_test.go b/src/archive/zip/writer_test.go
index 4bfa87080..184a7d96a 100644
--- a/src/pkg/archive/zip/writer_test.go
+++ b/src/archive/zip/writer_test.go
@@ -6,6 +6,7 @@ package zip
import (
"bytes"
+ "io"
"io/ioutil"
"math/rand"
"os"
@@ -86,6 +87,24 @@ func TestWriter(t *testing.T) {
}
}
+func TestWriterFlush(t *testing.T) {
+ var buf bytes.Buffer
+ w := NewWriter(struct{ io.Writer }{&buf})
+ _, err := w.Create("foo")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if buf.Len() > 0 {
+ t.Fatalf("Unexpected %d bytes already in buffer", buf.Len())
+ }
+ if err := w.Flush(); err != nil {
+ t.Fatal(err)
+ }
+ if buf.Len() == 0 {
+ t.Fatal("No bytes written after Flush")
+ }
+}
+
func testCreate(t *testing.T, w *Writer, wt *WriteTest) {
header := &FileHeader{
Name: wt.Name,
diff --git a/src/pkg/archive/zip/zip_test.go b/src/archive/zip/zip_test.go
index 32a16a79e..32a16a79e 100644
--- a/src/pkg/archive/zip/zip_test.go
+++ b/src/archive/zip/zip_test.go
diff --git a/src/pkg/bufio/bufio.go b/src/bufio/bufio.go
index 61ef26191..d3c68fe6f 100644
--- a/src/pkg/bufio/bufio.go
+++ b/src/bufio/bufio.go
@@ -30,8 +30,8 @@ var (
// Reader implements buffering for an io.Reader object.
type Reader struct {
buf []byte
- rd io.Reader
- r, w int
+ rd io.Reader // reader provided by the client
+ r, w int // buf read and write positions
err error
lastByte int
lastRuneSize int
@@ -131,18 +131,17 @@ func (b *Reader) Peek(n int) ([]byte, error) {
for b.w-b.r < n && b.err == nil {
b.fill() // b.w-b.r < len(b.buf) => buffer is not full
}
- m := b.w - b.r
- if m > n {
- m = n
- }
+
var err error
- if m < n {
+ if avail := b.w - b.r; avail < n {
+ // not enough data in buffer
+ n = avail
err = b.readErr()
if err == nil {
err = ErrBufferFull
}
}
- return b.buf[b.r : b.r+m], err
+ return b.buf[b.r : b.r+n], err
}
// Read reads data into p.
@@ -173,15 +172,13 @@ func (b *Reader) Read(p []byte) (n int, err error) {
return n, b.readErr()
}
b.fill() // buffer is empty
- if b.w == b.r {
+ if b.r == b.w {
return 0, b.readErr()
}
}
- if n > b.w-b.r {
- n = b.w - b.r
- }
- copy(p[0:n], b.buf[b.r:])
+ // copy as much as we can
+ n = copy(p, b.buf[b.r:b.w])
b.r += n
b.lastByte = int(b.buf[b.r-1])
b.lastRuneSize = -1
@@ -288,7 +285,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
}
// Buffer full?
- if n := b.Buffered(); n >= len(b.buf) {
+ if b.Buffered() >= len(b.buf) {
b.r = b.w
line = b.buf
err = ErrBufferFull
@@ -301,6 +298,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
// Handle last byte, if any.
if i := len(line) - 1; i >= 0 {
b.lastByte = int(line[i])
+ b.lastRuneSize = -1
}
return
@@ -458,11 +456,13 @@ func (b *Reader) WriteTo(w io.Writer) (n int64, err error) {
return n, b.readErr()
}
+var errNegativeWrite = errors.New("bufio: writer returned negative count from Write")
+
// writeBuf writes the Reader's buffer to the writer.
func (b *Reader) writeBuf(w io.Writer) (int64, error) {
n, err := w.Write(b.buf[b.r:b.w])
- if n < b.r-b.w {
- panic(errors.New("bufio: writer did not write all data"))
+ if n < 0 {
+ panic(errNegativeWrite)
}
b.r += n
return int64(n), err
diff --git a/src/pkg/bufio/bufio_test.go b/src/bufio/bufio_test.go
index 76d3c8ead..550dac917 100644
--- a/src/pkg/bufio/bufio_test.go
+++ b/src/bufio/bufio_test.go
@@ -31,9 +31,6 @@ func newRot13Reader(r io.Reader) *rot13Reader {
func (r13 *rot13Reader) Read(p []byte) (int, error) {
n, err := r13.r.Read(p)
- if err != nil {
- return n, err
- }
for i := 0; i < n; i++ {
c := p[i] | 0x20 // lowercase byte
if 'a' <= c && c <= 'm' {
@@ -42,7 +39,7 @@ func (r13 *rot13Reader) Read(p []byte) (int, error) {
p[i] -= 13
}
}
- return n, nil
+ return n, err
}
// Call ReadByte to accumulate the text of a file
@@ -438,7 +435,7 @@ func TestUnreadRuneError(t *testing.T) {
if err != nil {
t.Error("unexpected error on ReadRune (2):", err)
}
- for _ = range buf {
+ for range buf {
_, err = r.ReadByte()
if err != nil {
t.Error("unexpected error on ReadByte (2):", err)
@@ -463,6 +460,18 @@ func TestUnreadRuneError(t *testing.T) {
if r.UnreadRune() == nil {
t.Error("expected error after UnreadByte (3)")
}
+ // Test error after ReadSlice.
+ _, _, err = r.ReadRune() // reset state
+ if err != nil {
+ t.Error("unexpected error on ReadRune (4):", err)
+ }
+ _, err = r.ReadSlice(0)
+ if err != io.EOF {
+ t.Error("unexpected error on ReadSlice (4):", err)
+ }
+ if r.UnreadRune() == nil {
+ t.Error("expected error after ReadSlice (4)")
+ }
}
func TestUnreadRuneAtEOF(t *testing.T) {
diff --git a/src/pkg/bufio/example_test.go b/src/bufio/example_test.go
index 3da914142..3da914142 100644
--- a/src/pkg/bufio/example_test.go
+++ b/src/bufio/example_test.go
diff --git a/src/pkg/bufio/export_test.go b/src/bufio/export_test.go
index 3d3bb27d8..3d3bb27d8 100644
--- a/src/pkg/bufio/export_test.go
+++ b/src/bufio/export_test.go
diff --git a/src/pkg/bufio/scan.go b/src/bufio/scan.go
index 715ce071e..364d15961 100644
--- a/src/pkg/bufio/scan.go
+++ b/src/bufio/scan.go
@@ -36,6 +36,7 @@ type Scanner struct {
start int // First non-processed byte in buf.
end int // End of data in buf.
err error // Sticky error.
+ empties int // Count of successive empty tokens.
}
// SplitFunc is the signature of the split function used to tokenize the
@@ -64,8 +65,9 @@ var (
)
const (
- // Maximum size used to buffer a token. The actual maximum token size
- // may be smaller as the buffer may need to include, for instance, a newline.
+ // MaxScanTokenSize is the maximum size used to buffer a token.
+ // The actual maximum token size may be smaller as the buffer
+ // may need to include, for instance, a newline.
MaxScanTokenSize = 64 * 1024
)
@@ -107,11 +109,15 @@ func (s *Scanner) Text() string {
// After Scan returns false, the Err method will return any error that
// occurred during scanning, except that if it was io.EOF, Err
// will return nil.
+// Split 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 {
// Loop until we have a token.
for {
// See if we can get a token with what we already have.
- if s.end > s.start {
+ // If we've run out of data but have an error, give the split function
+ // a chance to recover any remaining, possibly empty token.
+ 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 {
s.setErr(err)
@@ -122,6 +128,15 @@ func (s *Scanner) Scan() bool {
}
s.token = token
if token != nil {
+ if s.err == nil || advance > 0 {
+ s.empties = 0
+ } else {
+ // Returning tokens not advancing input at EOF.
+ s.empties++
+ if s.empties > 100 {
+ panic("bufio.Scan: 100 empty tokens without progressing")
+ }
+ }
return true
}
}
@@ -169,6 +184,7 @@ func (s *Scanner) Scan() bool {
break
}
if n > 0 {
+ s.empties = 0
break
}
loop++
@@ -326,9 +342,6 @@ func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) {
break
}
}
- if atEOF && len(data) == 0 {
- return 0, nil, nil
- }
// Scan until space, marking end of word.
for width, i := 0, start; i < len(data); i += width {
var r rune
@@ -342,5 +355,5 @@ func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) {
return len(data), data[start:], nil
}
// Request more data.
- return 0, nil, nil
+ return start, nil, nil
}
diff --git a/src/pkg/bufio/scan_test.go b/src/bufio/scan_test.go
index 0db7cad20..eea87cbf7 100644
--- a/src/pkg/bufio/scan_test.go
+++ b/src/bufio/scan_test.go
@@ -15,6 +15,8 @@ import (
"unicode/utf8"
)
+const smallMaxTokenSize = 256 // Much smaller for more efficient testing.
+
// Test white space table matches the Unicode definition.
func TestSpace(t *testing.T) {
for r := rune(0); r <= utf8.MaxRune; r++ {
@@ -172,7 +174,6 @@ func genLine(buf *bytes.Buffer, lineNum, n int, addNewline bool) {
// Test the line splitter, including some carriage returns but no long lines.
func TestScanLongLines(t *testing.T) {
- const smallMaxTokenSize = 256 // Much smaller for more efficient testing.
// Build a buffer of lots of line lengths up to but not exceeding smallMaxTokenSize.
tmp := new(bytes.Buffer)
buf := new(bytes.Buffer)
@@ -404,3 +405,120 @@ func TestBadReader(t *testing.T) {
t.Errorf("unexpected error: %v", err)
}
}
+
+func TestScanWordsExcessiveWhiteSpace(t *testing.T) {
+ const word = "ipsum"
+ s := strings.Repeat(" ", 4*smallMaxTokenSize) + word
+ scanner := NewScanner(strings.NewReader(s))
+ scanner.MaxTokenSize(smallMaxTokenSize)
+ scanner.Split(ScanWords)
+ if !scanner.Scan() {
+ t.Fatalf("scan failed: %v", scanner.Err())
+ }
+ if token := scanner.Text(); token != word {
+ t.Fatalf("unexpected token: %v", token)
+ }
+}
+
+// Test that empty tokens, including at end of line or end of file, are found by the scanner.
+// Issue 8672: Could miss final empty token.
+
+func commaSplit(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
+ }
+ }
+ if !atEOF {
+ return 0, nil, nil
+ }
+ return 0, data, nil
+}
+
+func TestEmptyTokens(t *testing.T) {
+ s := NewScanner(strings.NewReader("1,2,3,"))
+ values := []string{"1", "2", "3", ""}
+ s.Split(commaSplit)
+ var i int
+ for i = 0; i < len(values); i++ {
+ if !s.Scan() {
+ break
+ }
+ 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))
+ }
+ if err := s.Err(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func loopAtEOFSplit(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if len(data) > 0 {
+ return 1, data[:1], nil
+ }
+ return 0, data, nil
+}
+
+func TestDontLoopForever(t *testing.T) {
+ s := NewScanner(strings.NewReader("abc"))
+ s.Split(loopAtEOFSplit)
+ // Expect a panic
+ defer func() {
+ err := recover()
+ if err == nil {
+ t.Fatal("should have panicked")
+ }
+ if msg, ok := err.(string); !ok || !strings.Contains(msg, "empty tokens") {
+ panic(err)
+ }
+ }()
+ for count := 0; s.Scan(); count++ {
+ if count > 1000 {
+ t.Fatal("looping")
+ }
+ }
+ if s.Err() != nil {
+ t.Fatal("after scan:", s.Err())
+ }
+}
+
+func TestBlankLines(t *testing.T) {
+ s := NewScanner(strings.NewReader(strings.Repeat("\n", 1000)))
+ for count := 0; s.Scan(); count++ {
+ if count > 2000 {
+ t.Fatal("looping")
+ }
+ }
+ if s.Err() != nil {
+ t.Fatal("after scan:", s.Err())
+ }
+}
+
+type countdown int
+
+func (c *countdown) split(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if *c > 0 {
+ *c--
+ return 1, data[:1], nil
+ }
+ return 0, nil, nil
+}
+
+// Check that the looping-at-EOF check doesn't trigger for merely empty tokens.
+func TestEmptyLinesOK(t *testing.T) {
+ c := countdown(10000)
+ s := NewScanner(strings.NewReader(strings.Repeat("\n", 10000)))
+ s.Split(c.split)
+ for s.Scan() {
+ }
+ if s.Err() != nil {
+ t.Fatal("after scan:", s.Err())
+ }
+ if c != 0 {
+ t.Fatalf("stopped with %d left to process", c)
+ }
+}
diff --git a/src/pkg/builtin/builtin.go b/src/builtin/builtin.go
index 51550a459..51550a459 100644
--- a/src/pkg/builtin/builtin.go
+++ b/src/builtin/builtin.go
diff --git a/src/pkg/bytes/buffer.go b/src/bytes/buffer.go
index 46ca1d5ad..46ca1d5ad 100644
--- a/src/pkg/bytes/buffer.go
+++ b/src/bytes/buffer.go
diff --git a/src/pkg/bytes/buffer_test.go b/src/bytes/buffer_test.go
index 75145b05e..75145b05e 100644
--- a/src/pkg/bytes/buffer_test.go
+++ b/src/bytes/buffer_test.go
diff --git a/src/pkg/bytes/bytes.go b/src/bytes/bytes.go
index 0c53e4c0b..7634707b3 100644
--- a/src/pkg/bytes/bytes.go
+++ b/src/bytes/bytes.go
@@ -267,6 +267,8 @@ func Fields(s []byte) [][]byte {
// It splits the slice s at each run of code points c satisfying f(c) and
// returns a slice of subslices of s. If all code points in s satisfy f(c), or
// len(s) == 0, an empty slice is returned.
+// FieldsFunc makes no guarantees about the order in which it calls f(c).
+// If f does not return consistent results for a given c, FieldsFunc may crash.
func FieldsFunc(s []byte, f func(rune) bool) [][]byte {
n := 0
inField := false
@@ -377,9 +379,10 @@ func Map(mapping func(r rune) rune, s []byte) []byte {
// Repeat returns a new byte slice consisting of count copies of b.
func Repeat(b []byte, count int) []byte {
nb := make([]byte, len(b)*count)
- bp := 0
- for i := 0; i < count; i++ {
- bp += copy(nb[bp:], b)
+ bp := copy(nb, b)
+ for bp < len(nb) {
+ copy(nb[bp:], nb[:bp])
+ bp *= 2
}
return nb
}
@@ -604,6 +607,9 @@ func Runes(s []byte) []rune {
// Replace returns a copy of the slice s with the first n
// non-overlapping instances of old replaced by new.
+// If old is empty, it matches at the beginning of the slice
+// and after each UTF-8 sequence, yielding up to k+1 replacements
+// for a k-rune slice.
// If n < 0, there is no limit on the number of replacements.
func Replace(s, old, new []byte, n int) []byte {
m := 0
diff --git a/src/pkg/bytes/bytes_decl.go b/src/bytes/bytes_decl.go
index 617d7489a..617d7489a 100644
--- a/src/pkg/bytes/bytes_decl.go
+++ b/src/bytes/bytes_decl.go
diff --git a/src/pkg/bytes/bytes_test.go b/src/bytes/bytes_test.go
index 394dd7a44..980c41d75 100644
--- a/src/pkg/bytes/bytes_test.go
+++ b/src/bytes/bytes_test.go
@@ -1232,3 +1232,9 @@ func BenchmarkTrimSpace(b *testing.B) {
TrimSpace(s)
}
}
+
+func BenchmarkRepeat(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Repeat([]byte("-"), 80)
+ }
+}
diff --git a/src/pkg/bytes/compare_test.go b/src/bytes/compare_test.go
index 63522374e..63522374e 100644
--- a/src/pkg/bytes/compare_test.go
+++ b/src/bytes/compare_test.go
diff --git a/src/pkg/bytes/equal_test.go b/src/bytes/equal_test.go
index 1bf19a74b..1bf19a74b 100644
--- a/src/pkg/bytes/equal_test.go
+++ b/src/bytes/equal_test.go
diff --git a/src/pkg/bytes/example_test.go b/src/bytes/example_test.go
index ad2dbc69b..ad2dbc69b 100644
--- a/src/pkg/bytes/example_test.go
+++ b/src/bytes/example_test.go
diff --git a/src/pkg/bytes/export_test.go b/src/bytes/export_test.go
index 3b915d5ea..3b915d5ea 100644
--- a/src/pkg/bytes/export_test.go
+++ b/src/bytes/export_test.go
diff --git a/src/pkg/bytes/reader.go b/src/bytes/reader.go
index d2d40fa7c..d2d40fa7c 100644
--- a/src/pkg/bytes/reader.go
+++ b/src/bytes/reader.go
diff --git a/src/pkg/bytes/reader_test.go b/src/bytes/reader_test.go
index d3dce5349..d3dce5349 100644
--- a/src/pkg/bytes/reader_test.go
+++ b/src/bytes/reader_test.go
diff --git a/src/cmd/5a/a.y b/src/cmd/5a/a.y
index 56d0c563d..ad647606e 100644
--- a/src/cmd/5a/a.y
+++ b/src/cmd/5a/a.y
@@ -33,7 +33,7 @@
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
#include <libc.h>
#include "a.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
%}
%union
{
diff --git a/src/cmd/5a/lex.c b/src/cmd/5a/lex.c
index 571fdf7f2..9c6970947 100644
--- a/src/cmd/5a/lex.c
+++ b/src/cmd/5a/lex.c
@@ -85,6 +85,7 @@ main(int argc, char *argv[])
ctxt = linknew(&linkarm);
ctxt->diag = yyerror;
ctxt->bso = &bstdout;
+ ctxt->enforce_data_order = 1;
Binit(&bstdout, 1, OWRITE);
listinit5();
fmtinstall('L', Lconv);
@@ -199,8 +200,8 @@ struct
"R6", LREG, 6,
"R7", LREG, 7,
"R8", LREG, 8,
- "m", LREG, 9, // avoid unintentionally clobber m/g using R9/R10
- "g", LREG, 10,
+ "R9", LREG, 9,
+ "g", LREG, 10, // avoid unintentionally clobber g using R10
"R11", LREG, 11,
"R12", LREG, 12,
"R13", LREG, 13,
diff --git a/src/cmd/5a/y.tab.c b/src/cmd/5a/y.tab.c
index 0bc8c34e1..a6251b835 100644
--- a/src/cmd/5a/y.tab.c
+++ b/src/cmd/5a/y.tab.c
@@ -69,7 +69,7 @@
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
#include <libc.h>
#include "a.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
/* Line 371 of yacc.c */
#line 76 "y.tab.c"
diff --git a/src/cmd/5c/cgen.c b/src/cmd/5c/cgen.c
index 08ed36055..5a049ae62 100644
--- a/src/cmd/5c/cgen.c
+++ b/src/cmd/5c/cgen.c
@@ -29,7 +29,7 @@
// THE SOFTWARE.
#include "gc.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
void
_cgen(Node *n, Node *nn, int inrel)
@@ -46,7 +46,7 @@ _cgen(Node *n, Node *nn, int inrel)
}
if(n == Z || n->type == T)
return;
- if(typesuv[n->type->etype]) {
+ if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) {
sugen(n, nn, n->type->width);
return;
}
@@ -75,7 +75,7 @@ _cgen(Node *n, Node *nn, int inrel)
if(r != Z && r->complex >= FNX)
switch(o) {
default:
- regret(&nod, r);
+ regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
@@ -107,7 +107,7 @@ _cgen(Node *n, Node *nn, int inrel)
if(l->addable >= INDEXED && l->complex < FNX) {
if(nn != Z || r->addable < INDEXED) {
if(r->complex >= FNX && nn == Z)
- regret(&nod, r);
+ regret(&nod, r, 0, 0);
else
regalloc(&nod, r, nn);
cgen(r, &nod);
@@ -348,7 +348,7 @@ _cgen(Node *n, Node *nn, int inrel)
if(l->op != OIND)
diag(n, "bad function call");
- regret(&nod, l->left);
+ regret(&nod, l->left, 0, 0);
cgen(l->left, &nod);
regsalloc(&nod1, l->left);
gopcode(OAS, &nod, Z, &nod1);
@@ -366,22 +366,20 @@ _cgen(Node *n, Node *nn, int inrel)
if(REGARG >= 0)
o = reg[REGARG];
gargs(r, &nod, &nod1);
- gpcdata(PCDATA_ArgSize, curarg);
if(l->addable < INDEXED) {
reglcgen(&nod, l, Z);
gopcode(OFUNC, Z, Z, &nod);
regfree(&nod);
} else
gopcode(OFUNC, Z, Z, l);
- gpcdata(PCDATA_ArgSize, -1);
if(REGARG >= 0)
if(o != reg[REGARG])
reg[REGARG]--;
- if(nn != Z) {
- regret(&nod, n);
- gopcode(OAS, &nod, Z, nn);
+ regret(&nod, n, l->type, 1);
+ if(nn != Z)
+ gmove(&nod, nn);
+ if(nod.op == OREGISTER)
regfree(&nod);
- }
break;
case OIND:
@@ -823,7 +821,7 @@ boolgen(Node *n, int true, Node *nn)
if(true)
o = comrel[relindex(o)];
if(l->complex >= FNX && r->complex >= FNX) {
- regret(&nod, r);
+ regret(&nod, r, 0, 0);
cgenrel(r, &nod);
regsalloc(&nod1, r);
gopcode(OAS, &nod, Z, &nod1);
@@ -957,7 +955,7 @@ sugen(Node *n, Node *nn, int32 w)
if(nn != Z && side(nn)) {
nod1 = *n;
nod1.type = typ(TIND, n->type);
- regret(&nod2, &nod1);
+ regret(&nod2, &nod1, 0, 0);
lcgen(nn, &nod2);
regsalloc(&nod0, &nod1);
gopcode(OAS, &nod2, Z, &nod0);
@@ -1036,6 +1034,20 @@ sugen(Node *n, Node *nn, int32 w)
break;
case OFUNC:
+ if(!hasdotdotdot(n->left->type)) {
+ cgen(n, Z);
+ if(nn != Z) {
+ curarg -= n->type->width;
+ regret(&nod1, n, n->left->type, 1);
+ if(nn->complex >= FNX) {
+ regsalloc(&nod2, n);
+ cgen(&nod1, &nod2);
+ nod1 = nod2;
+ }
+ cgen(&nod1, nn);
+ }
+ break;
+ }
if(nn == Z) {
sugen(n, nodrat, w);
break;
diff --git a/src/cmd/5c/gc.h b/src/cmd/5c/gc.h
index 40d3a2b07..7417b7dbe 100644
--- a/src/cmd/5c/gc.h
+++ b/src/cmd/5c/gc.h
@@ -144,7 +144,6 @@ EXTERN Prog* lastp;
EXTERN int32 maxargsafe;
EXTERN int mnstring;
EXTERN Multab multab[20];
-EXTERN int retok;
extern int hintabsize;
EXTERN Node* nodrat;
EXTERN Node* nodret;
@@ -211,7 +210,7 @@ void usedset(Node*, int);
void xcom(Node*);
int bcomplex(Node*, Node*);
Prog* gtext(Sym*, int32);
-vlong argsize(void);
+vlong argsize(int);
/*
* cgen.c
@@ -237,7 +236,7 @@ Node* nodconst(int32);
Node* nod32const(vlong);
Node* nodfconst(double);
void nodreg(Node*, Node*, int);
-void regret(Node*, Node*);
+void regret(Node*, Node*, Type*, int);
int tmpreg(void);
void regalloc(Node*, Node*, Node*);
void regfree(Node*);
diff --git a/src/cmd/5c/peep.c b/src/cmd/5c/peep.c
index 143400a63..1de56b594 100644
--- a/src/cmd/5c/peep.c
+++ b/src/cmd/5c/peep.c
@@ -853,11 +853,15 @@ xtramodes(Reg *r, Addr *a)
switch (p1->from.type) {
case D_REG:
/* register offset */
+ if(nacl)
+ return 0;
a->type = D_SHIFT;
a->offset = p1->from.reg;
break;
case D_SHIFT:
/* scaled register offset */
+ if(nacl)
+ return 0;
a->type = D_SHIFT;
case D_CONST:
/* immediate offset */
diff --git a/src/cmd/5c/reg.c b/src/cmd/5c/reg.c
index b9ac21abd..9024d5f49 100644
--- a/src/cmd/5c/reg.c
+++ b/src/cmd/5c/reg.c
@@ -204,6 +204,16 @@ regopt(Prog *p)
break;
}
+ /* the mod/div runtime routines smash R12 */
+ switch(p->as) {
+ case AMOD:
+ case AMODU:
+ case ADIV:
+ case ADIVU:
+ regbits |= RtoB(12);
+ break;
+ }
+
if(p->as == AMOVM) {
if(p->from.type == D_CONST)
z = p->from.offset;
@@ -396,7 +406,7 @@ loop2:
rgp->cost = change;
nregion++;
if(nregion >= NRGN) {
- warn(Z, "too many regions");
+ fatal(Z, "too many regions");
goto brk;
}
rgp++;
@@ -632,11 +642,8 @@ mkvar(Addr *a, int docon)
if(s)
if(s->name[0] == '.')
goto none;
- if(nvar >= NVAR) {
- if(debug['w'] > 1 && s)
- warn(Z, "variable not optimized: %s", s->name);
- goto none;
- }
+ if(nvar >= NVAR)
+ fatal(Z, "variable not optimized: %s", s->name);
i = nvar;
nvar++;
v = &var[i];
diff --git a/src/cmd/5c/sgen.c b/src/cmd/5c/sgen.c
index efcc0437b..a36612caa 100644
--- a/src/cmd/5c/sgen.c
+++ b/src/cmd/5c/sgen.c
@@ -36,7 +36,7 @@ gtext(Sym *s, int32 stkoff)
{
int32 a;
- a = argsize();
+ a = argsize(1);
if((textflag & NOSPLIT) != 0 && stkoff >= 128)
yyerror("stack frame too large for NOSPLIT function");
diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c
index fd81a4e68..f39963b8f 100644
--- a/src/cmd/5c/swt.c
+++ b/src/cmd/5c/swt.c
@@ -60,7 +60,7 @@ swit2(C1 *q, int nc, int32 def, Node *n)
if(nc >= 3) {
i = (q+nc-1)->val - (q+0)->val;
- if(i > 0 && i < nc*2)
+ if(!nacl && i > 0 && i < nc*2)
goto direct;
}
if(nc < 5) {
@@ -374,10 +374,11 @@ align(int32 i, Type *t, int op, int32 *maxalign)
{
int32 o;
Type *v;
- int w;
+ int w, packw;
o = i;
w = 1;
+ packw = 0;
switch(op) {
default:
diag(Z, "unknown align opcode %d", op);
@@ -388,7 +389,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1)
w = 1;
if(packflg)
- w = packflg;
+ packw = packflg;
break;
case Ael1: /* initial align of struct element */
@@ -404,7 +405,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1 || w > SZ_LONG)
fatal(Z, "align");
if(packflg)
- w = packflg;
+ packw = packflg;
break;
case Ael2: /* width of a struct element */
@@ -440,6 +441,8 @@ align(int32 i, Type *t, int op, int32 *maxalign)
w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */
break;
}
+ if(packw != 0 && xround(o, w) != xround(o, packw))
+ diag(Z, "#pragma pack changes offset of %T", t);
o = xround(o, w);
if(maxalign != nil && *maxalign < w)
*maxalign = w;
diff --git a/src/cmd/5c/txt.c b/src/cmd/5c/txt.c
index a753510ca..af40220cc 100644
--- a/src/cmd/5c/txt.c
+++ b/src/cmd/5c/txt.c
@@ -274,15 +274,43 @@ nodreg(Node *n, Node *nn, int reg)
}
void
-regret(Node *n, Node *nn)
+regret(Node *n, Node *nn, Type *t, int mode)
{
int r;
- r = REGRET;
- if(typefd[nn->type->etype])
- r = FREGRET+NREG;
- nodreg(n, nn, r);
- reg[r]++;
+ if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
+ r = REGRET;
+ if(typefd[nn->type->etype])
+ r = FREGRET+NREG;
+ nodreg(n, nn, r);
+ reg[r]++;
+ return;
+ }
+
+ if(mode == 1) {
+ // fetch returned value after call.
+ // already called gargs, so curarg is set.
+ curarg = (curarg+3) & ~3;
+ regaalloc(n, nn);
+ return;
+ }
+
+ if(mode == 2) {
+ // store value to be returned.
+ // must compute arg offset.
+ if(t->etype != TFUNC)
+ fatal(Z, "bad regret func %T", t);
+ *n = *nn;
+ n->op = ONAME;
+ n->class = CPARAM;
+ n->sym = slookup(".ret");
+ n->complex = nodret->complex;
+ n->xoffset = argsize(0);
+ n->addable = 20;
+ return;
+ }
+
+ fatal(Z, "bad regret");
}
int
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 9011b2022..c535cfbef 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -254,7 +254,6 @@ cgen(Node *n, Node *res)
case OOR:
case OXOR:
case OADD:
- case OADDPTR:
case OMUL:
a = optoas(n->op, nl->type);
goto sbop;
@@ -1107,11 +1106,10 @@ bgen(Node *n, int true, int likely, Prog *to)
{
int et, a;
Node *nl, *nr, *r;
- Node n1, n2, n3, n4, tmp;
+ Node n1, n2, n3, tmp;
NodeList *ll;
Prog *p1, *p2;
- USED(n4); // in unreachable code below
if(debug['g']) {
dump("\nbgen", n);
}
@@ -1497,7 +1495,7 @@ sgen(Node *n, Node *res, int64 w)
if(osrc < odst && odst < osrc+w)
dir = -dir;
- if(op == AMOVW && dir > 0 && c >= 4 && c <= 128) {
+ if(op == AMOVW && !nacl && dir > 0 && c >= 4 && c <= 128) {
r0.op = OREGISTER;
r0.val.u.reg = REGALLOC_R0;
r1.op = OREGISTER;
@@ -1524,7 +1522,7 @@ sgen(Node *n, Node *res, int64 w)
f = sysfunc("duffcopy");
p = gins(ADUFFCOPY, N, f);
afunclit(&p->to, f);
- // 8 and 128 = magic constants: see ../../pkg/runtime/asm_arm.s
+ // 8 and 128 = magic constants: see ../../runtime/asm_arm.s
p->to.offset = 8*(128-c);
regfree(&tmp);
@@ -1636,7 +1634,10 @@ int
componentgen(Node *nr, Node *nl)
{
Node nodl, nodr, tmp;
+ Type *t;
int freel, freer;
+ vlong fldcount;
+ vlong loffset, roffset;
freel = 0;
freer = 0;
@@ -1646,8 +1647,33 @@ componentgen(Node *nr, Node *nl)
goto no;
case TARRAY:
- if(!isslice(nl->type))
+ t = nl->type;
+
+ // Slices are ok.
+ if(isslice(t))
+ break;
+ // Small arrays are ok.
+ if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
+ break;
+
+ goto no;
+
+ case TSTRUCT:
+ // Small structs with non-fat types are ok.
+ // Zero-sized structs are treated separately elsewhere.
+ fldcount = 0;
+ for(t=nl->type->type; t; t=t->down) {
+ if(isfat(t->type))
+ goto no;
+ if(t->etype != TFIELD)
+ fatal("componentgen: not a TFIELD: %lT", t);
+ fldcount++;
+ }
+ if(fldcount == 0 || fldcount > 4)
goto no;
+
+ break;
+
case TSTRING:
case TINTER:
break;
@@ -1675,6 +1701,7 @@ componentgen(Node *nr, Node *nl)
freer = 1;
}
+
// nl and nr are 'cadable' which basically means they are names (variables) now.
// If they are the same variable, don't generate any code, because the
// VARDEF we generate will mark the old value as dead incorrectly.
@@ -1684,8 +1711,25 @@ componentgen(Node *nr, Node *nl)
switch(nl->type->etype) {
case TARRAY:
+ // componentgen for arrays.
if(nl->op == ONAME)
gvardef(nl);
+ t = nl->type;
+ if(!isslice(t)) {
+ nodl.type = t->type;
+ nodr.type = nodl.type;
+ for(fldcount=0; fldcount < t->bound; fldcount++) {
+ if(nr == N)
+ clearslim(&nodl);
+ else
+ gmove(&nodr, &nodl);
+ nodl.xoffset += t->type->width;
+ nodr.xoffset += t->type->width;
+ }
+ goto yes;
+ }
+
+ // componentgen for slices.
nodl.xoffset += Array_array;
nodl.type = ptrto(nl->type->type);
@@ -1760,6 +1804,31 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl);
goto yes;
+
+ case TSTRUCT:
+ if(nl->op == ONAME)
+ gvardef(nl);
+ loffset = nodl.xoffset;
+ roffset = nodr.xoffset;
+ // funarg structs may not begin at offset zero.
+ if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type)
+ loffset -= nl->type->type->width;
+ if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type)
+ roffset -= nr->type->type->width;
+
+ for(t=nl->type->type; t; t=t->down) {
+ nodl.xoffset = loffset + t->width;
+ nodl.type = t->type;
+
+ if(nr == N)
+ clearslim(&nodl);
+ else {
+ nodr.xoffset = roffset + t->width;
+ nodr.type = nodl.type;
+ gmove(&nodr, &nodl);
+ }
+ }
+ goto yes;
}
no:
diff --git a/src/cmd/5g/galign.c b/src/cmd/5g/galign.c
index a62102ef8..b4c45da69 100644
--- a/src/cmd/5g/galign.c
+++ b/src/cmd/5g/galign.c
@@ -23,10 +23,10 @@ vlong MAXWIDTH = (1LL<<32) - 1;
*/
Typedef typedefs[] =
{
- "int", TINT, TINT32,
- "uint", TUINT, TUINT32,
- "uintptr", TUINTPTR, TUINT32,
- 0
+ {"int", TINT, TINT32},
+ {"uint", TUINT, TUINT32},
+ {"uintptr", TUINTPTR, TUINT32},
+ {0}
};
void
diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h
index 413e93c24..00914bfa3 100644
--- a/src/cmd/5g/gg.h
+++ b/src/cmd/5g/gg.h
@@ -11,10 +11,13 @@
#define TEXTFLAG reg
-#define REGALLOC_R0 0
-#define REGALLOC_RMAX REGEXT
-#define REGALLOC_F0 NREG
-#define REGALLOC_FMAX (REGALLOC_F0 + FREGEXT)
+enum
+{
+ REGALLOC_R0 = 0,
+ REGALLOC_RMAX = REGEXT,
+ REGALLOC_F0 = NREG,
+ REGALLOC_FMAX = REGALLOC_F0 + FREGEXT,
+};
EXTERN int32 dynloc;
EXTERN uchar reg[REGALLOC_FMAX+1];
@@ -106,7 +109,6 @@ void split64(Node*, Node*, Node*);
void splitclean(void);
Node* ncon(uint32 i);
void gtrack(Sym*);
-void gargsize(int32);
/*
* obj.c
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index fb32c2f36..53cddb760 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -76,7 +76,7 @@ zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0)
if(cnt < 4*widthptr) {
for(i = 0; i < cnt; i += widthptr)
p = appendpp(p, AMOVW, D_REG, 0, 0, D_OREG, REGSP, 4+frame+lo+i);
- } else if(cnt <= 128*widthptr) {
+ } else if(!nacl && (cnt <= 128*widthptr)) {
p = appendpp(p, AADD, D_CONST, NREG, 4+frame+lo, D_REG, 1, 0);
p->reg = REGSP;
p = appendpp(p, ADUFFZERO, D_NONE, NREG, 0, D_OREG, NREG, 0);
@@ -179,28 +179,12 @@ fixautoused(Prog* p)
void
ginscall(Node *f, int proc)
{
- int32 arg;
Prog *p;
Node n1, r, r1, con;
if(f->type != T)
setmaxarg(f->type);
- arg = -1;
- // Most functions have a fixed-size argument block, so traceback uses that during unwind.
- // Not all, though: there are some variadic functions in package runtime,
- // and for those we emit call-specific metadata recorded by caller.
- // Reflect generates functions with variable argsize (see reflect.methodValueCall/makeFuncStub),
- // so we do this for all indirect calls as well.
- if(f->type != T && (f->sym == S || (f->sym != S && f->sym->pkg == runtimepkg) || proc == 1 || proc == 2)) {
- arg = f->type->argwid;
- if(proc == 1 || proc == 2)
- arg += 3*widthptr;
- }
-
- if(arg != -1)
- gargsize(arg);
-
switch(proc) {
default:
fatal("ginscall: bad proc %d", proc);
@@ -297,9 +281,6 @@ ginscall(Node *f, int proc)
}
break;
}
-
- if(arg != -1)
- gargsize(-1);
}
/*
@@ -906,11 +887,11 @@ clearfat(Node *nl)
patch(gbranch(ABNE, T, 0), pl);
regfree(&end);
- } else if(q >= 4) {
+ } else if(q >= 4 && !nacl) {
f = sysfunc("duffzero");
p = gins(ADUFFZERO, N, f);
afunclit(&p->to, f);
- // 4 and 128 = magic constants: see ../../pkg/runtime/asm_arm.s
+ // 4 and 128 = magic constants: see ../../runtime/asm_arm.s
p->to.offset = 4*(128-q);
} else
while(q > 0) {
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index f66c87b5a..06e274e14 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -31,11 +31,11 @@
#include <u.h>
#include <libc.h>
#include "gg.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
// TODO(rsc): Can make this bigger if we move
// the text segment up higher in 5l for all GOOS.
-// At the same time, can raise StackBig in ../../pkg/runtime/stack.h.
+// At the same time, can raise StackBig in ../../runtime/stack.h.
long unmappedzero = 4096;
void
@@ -206,17 +206,7 @@ ggloblnod(Node *nam)
}
void
-gargsize(int32 size)
-{
- Node n1, n2;
-
- nodconst(&n1, types[TINT32], PCDATA_ArgSize);
- nodconst(&n2, types[TINT32], size);
- gins(APCDATA, &n1, &n2);
-}
-
-void
-ggloblsym(Sym *s, int32 width, int dupok, int rodata)
+ggloblsym(Sym *s, int32 width, int8 flags)
{
Prog *p;
@@ -227,10 +217,7 @@ ggloblsym(Sym *s, int32 width, int dupok, int rodata)
p->to.type = D_CONST;
p->to.name = D_NONE;
p->to.offset = width;
- if(dupok)
- p->reg |= DUPOK;
- if(rodata)
- p->reg |= RODATA;
+ p->reg = flags;
}
void
@@ -374,7 +361,7 @@ regalloc(Node *n, Type *t, Node *o)
print("registers allocated at\n");
for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
print("%d %p\n", i, regpc[i]);
- yyerror("out of fixed registers");
+ fatal("out of fixed registers");
goto err;
case TFLOAT32:
@@ -387,7 +374,7 @@ regalloc(Node *n, Type *t, Node *o)
for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++)
if(reg[i] == 0)
goto out;
- yyerror("out of floating point registers");
+ fatal("out of floating point registers");
goto err;
case TCOMPLEX64:
@@ -636,6 +623,7 @@ splitclean(void)
}
#define CASE(a,b) (((a)<<16)|((b)<<0))
+/*c2go int CASE(int, int); */
void
gmove(Node *f, Node *t)
@@ -1601,7 +1589,6 @@ optoas(int op, Type *t)
case CASE(OADD, TINT32):
case CASE(OADD, TUINT32):
case CASE(OADD, TPTR32):
- case CASE(OADDPTR, TPTR32):
a = AADD;
break;
diff --git a/src/cmd/5g/opt.h b/src/cmd/5g/opt.h
index e3e3f78ed..1946c1d33 100644
--- a/src/cmd/5g/opt.h
+++ b/src/cmd/5g/opt.h
@@ -49,6 +49,24 @@
typedef struct Reg Reg;
typedef struct Rgn Rgn;
+/*c2go
+extern Node *Z;
+enum
+{
+ D_HI = D_NONE,
+ D_LO = D_NONE,
+ CLOAD = 5,
+ CREF = 5,
+ CINF = 1000,
+ LOOP = 3,
+};
+
+uint32 BLOAD(Reg*);
+uint32 BSTORE(Reg*);
+uint32 LOAD(Reg*);
+uint32 STORE(Reg*);
+*/
+
// A Reg is a wrapper around a single Prog (one instruction) that holds
// register optimization information while the optimizer runs.
// r->prog is the instruction.
@@ -71,8 +89,10 @@ struct Reg
int32 regu; // register used bitmap
};
#define R ((Reg*)0)
+/*c2go extern Reg *R; */
#define NRGN 600
+/*c2go enum { NRGN = 600 }; */
struct Rgn
{
Reg* enter;
diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c
index 4aa645206..639f4c5f6 100644
--- a/src/cmd/5g/peep.c
+++ b/src/cmd/5g/peep.c
@@ -564,6 +564,8 @@ gotit:
* ..
*/
#define FAIL(msg) { if(debug['P']) print("\t%s; FAILURE\n", msg); return 0; }
+/*c2go void FAIL(char*); */
+
int
shiftprop(Flow *r)
{
@@ -875,11 +877,15 @@ xtramodes(Graph *g, Flow *r, Adr *a)
switch (p1->from.type) {
case D_REG:
/* register offset */
+ if(nacl)
+ return 0;
a->type = D_SHIFT;
a->offset = p1->from.reg;
break;
case D_SHIFT:
/* scaled register offset */
+ if(nacl)
+ return 0;
a->type = D_SHIFT;
case D_CONST:
/* immediate offset */
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index 4762df506..b78c268df 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -36,6 +36,11 @@
#define NREGVAR 32
#define REGBITS ((uint32)0xffffffff)
+/*c2go enum {
+ NREGVAR = 32,
+ REGBITS = 0xffffffff,
+};
+*/
void addsplits(void);
static Reg* firstr;
@@ -194,7 +199,7 @@ regopt(Prog *firstp)
proginfo(&info, p);
// Avoid making variables for direct-called functions.
- if(p->as == ABL && p->to.type == D_EXTERN)
+ if(p->as == ABL && p->to.name == D_EXTERN)
continue;
bit = mkvar(r, &p->from);
@@ -222,6 +227,10 @@ regopt(Prog *firstp)
for(z=0; z<BITS; z++)
r->set.b[z] |= bit.b[z];
}
+
+ /* the mod/div runtime routines smash R12 */
+ if(p->as == ADIV || p->as == ADIVU || p->as == AMOD || p->as == AMODU)
+ r->set.b[0] |= RtoB(12);
}
if(firstr == R)
return;
@@ -1306,6 +1315,7 @@ void
addreg(Adr *a, int rn)
{
a->sym = nil;
+ a->node = nil;
a->name = D_NONE;
a->type = D_REG;
a->reg = rn;
diff --git a/src/cmd/5l/5.out.h b/src/cmd/5l/5.out.h
index 9e8aceecb..7b16ac446 100644
--- a/src/cmd/5l/5.out.h
+++ b/src/cmd/5l/5.out.h
@@ -28,34 +28,94 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#define NSNAME 8
-#define NSYM 50
-#define NREG 16
+enum
+{
+ NSNAME = 8,
+ NSYM = 50,
+ NREG = 16,
+};
#include "../ld/textflag.h"
-#define REGRET 0
/* -1 disables use of REGARG */
#define REGARG -1
-/* compiler allocates R1 up as temps */
-/* compiler allocates register variables R3 up */
-#define REGEXT 10
-/* these two registers are declared in runtime.h */
-#define REGG (REGEXT-0)
-#define REGM (REGEXT-1)
-/* compiler allocates external registers R10 down */
-#define REGTMP 11
-#define REGSP 13
-#define REGLINK 14
-#define REGPC 15
-
-#define NFREG 16
-#define FREGRET 0
-#define FREGEXT 7
-#define FREGTMP 15
+/*c2go enum { REGARG = -1 }; */
+
+enum
+{
+ REGRET = 0,
+ /* compiler allocates R1 up as temps */
+ /* compiler allocates register variables R3 up */
+ /* compiler allocates external registers R10 down */
+ REGEXT = 10,
+ /* these two registers are declared in runtime.h */
+ REGG = REGEXT-0,
+ REGM = REGEXT-1,
+
+ REGTMP = 11,
+ REGSP = 13,
+ REGLINK = 14,
+ REGPC = 15,
+
+ NFREG = 16,
+ FREGRET = 0,
+ FREGEXT = 7,
+ FREGTMP = 15,
+};
/* compiler allocates register variables F0 up */
/* compiler allocates external registers F7 down */
-enum as
+enum
+{
+ C_NONE,
+ C_REG,
+ C_REGREG,
+ C_REGREG2,
+ C_SHIFT,
+ C_FREG,
+ C_PSR,
+ C_FCR,
+
+ C_RCON, /* 0xff rotated */
+ C_NCON, /* ~RCON */
+ C_SCON, /* 0xffff */
+ C_LCON,
+ C_LCONADDR,
+ C_ZFCON,
+ C_SFCON,
+ C_LFCON,
+
+ C_RACON,
+ C_LACON,
+
+ C_SBRA,
+ C_LBRA,
+
+ C_HAUTO, /* halfword insn offset (-0xff to 0xff) */
+ C_FAUTO, /* float insn offset (0 to 0x3fc, word aligned) */
+ C_HFAUTO, /* both H and F */
+ C_SAUTO, /* -0xfff to 0xfff */
+ C_LAUTO,
+
+ C_HOREG,
+ C_FOREG,
+ C_HFOREG,
+ C_SOREG,
+ C_ROREG,
+ C_SROREG, /* both nil and R */
+ C_LOREG,
+
+ C_PC,
+ C_SP,
+ C_HREG,
+
+ C_ADDR, /* reference to relocatable address */
+
+ C_GOK,
+
+ C_NCLASS, /* must be the last */
+};
+
+enum
{
AXXX,
@@ -202,6 +262,8 @@ enum as
AVARKILL,
ADUFFCOPY,
ADUFFZERO,
+ ADATABUNDLE,
+ ADATABUNDLEEND,
AMRC, // MRC/MCR
@@ -209,35 +271,38 @@ enum as
};
/* scond byte */
-#define C_SCOND ((1<<4)-1)
-#define C_SBIT (1<<4)
-#define C_PBIT (1<<5)
-#define C_WBIT (1<<6)
-#define C_FBIT (1<<7) /* psr flags-only */
-#define C_UBIT (1<<7) /* up bit, unsigned bit */
-
-#define C_SCOND_EQ 0
-#define C_SCOND_NE 1
-#define C_SCOND_HS 2
-#define C_SCOND_LO 3
-#define C_SCOND_MI 4
-#define C_SCOND_PL 5
-#define C_SCOND_VS 6
-#define C_SCOND_VC 7
-#define C_SCOND_HI 8
-#define C_SCOND_LS 9
-#define C_SCOND_GE 10
-#define C_SCOND_LT 11
-#define C_SCOND_GT 12
-#define C_SCOND_LE 13
-#define C_SCOND_NONE 14
-#define C_SCOND_NV 15
-
-/* D_SHIFT type */
-#define SHIFT_LL 0<<5
-#define SHIFT_LR 1<<5
-#define SHIFT_AR 2<<5
-#define SHIFT_RR 3<<5
+enum
+{
+ C_SCOND = (1<<4)-1,
+ C_SBIT = 1<<4,
+ C_PBIT = 1<<5,
+ C_WBIT = 1<<6,
+ C_FBIT = 1<<7, /* psr flags-only */
+ C_UBIT = 1<<7, /* up bit, unsigned bit */
+
+ C_SCOND_EQ = 0,
+ C_SCOND_NE = 1,
+ C_SCOND_HS = 2,
+ C_SCOND_LO = 3,
+ C_SCOND_MI = 4,
+ C_SCOND_PL = 5,
+ C_SCOND_VS = 6,
+ C_SCOND_VC = 7,
+ C_SCOND_HI = 8,
+ C_SCOND_LS = 9,
+ C_SCOND_GE = 10,
+ C_SCOND_LT = 11,
+ C_SCOND_GT = 12,
+ C_SCOND_LE = 13,
+ C_SCOND_NONE = 14,
+ C_SCOND_NV = 15,
+
+ /* D_SHIFT type */
+ SHIFT_LL = 0<<5,
+ SHIFT_LR = 1<<5,
+ SHIFT_AR = 2<<5,
+ SHIFT_RR = 3<<5,
+};
enum
{
@@ -279,3 +344,4 @@ enum
* this is the ranlib header
*/
#define SYMDEF "__.GOSYMDEF"
+/*c2go extern char SYMDEF[]; */
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index e87921218..9c1c04e2d 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -648,19 +648,20 @@ asmb(void)
switch(HEADTYPE) {
default:
case Hplan9: /* plan 9 */
- lput(0x647); /* magic */
- lput(segtext.filelen); /* sizes */
- lput(segdata.filelen);
- lput(segdata.len - segdata.filelen);
- lput(symsize); /* nsyms */
- lput(entryvalue()); /* va of entry */
- lput(0L);
- lput(lcsize);
+ LPUT(0x647); /* magic */
+ LPUT(segtext.filelen); /* sizes */
+ LPUT(segdata.filelen);
+ LPUT(segdata.len - segdata.filelen);
+ LPUT(symsize); /* nsyms */
+ LPUT(entryvalue()); /* va of entry */
+ LPUT(0L);
+ LPUT(lcsize);
break;
case Hlinux:
case Hfreebsd:
case Hnetbsd:
case Hopenbsd:
+ case Hnacl:
asmbelf(symo);
break;
}
@@ -675,64 +676,6 @@ asmb(void)
}
}
-/*
-void
-cput(int32 c)
-{
- *cbp++ = c;
- if(--cbc <= 0)
- cflush();
-}
-*/
-
-void
-wput(int32 l)
-{
-
- cbp[0] = l>>8;
- cbp[1] = l;
- cbp += 2;
- cbc -= 2;
- if(cbc <= 0)
- cflush();
-}
-
-
-void
-hput(int32 l)
-{
-
- cbp[0] = l>>8;
- cbp[1] = l;
- cbp += 2;
- cbc -= 2;
- if(cbc <= 0)
- cflush();
-}
-
-void
-lput(int32 l)
-{
-
- cbp[0] = l>>24;
- cbp[1] = l>>16;
- cbp[2] = l>>8;
- cbp[3] = l;
- cbp += 4;
- cbc -= 4;
- if(cbc <= 0)
- cflush();
-}
-
-void
-nopstat(char *f, Count *c)
-{
- if(c->outof)
- Bprint(&bso, "%s delay %d/%d (%.2f)\n", f,
- c->outof - c->count, c->outof,
- (double)(c->outof - c->count)/c->outof);
-}
-
int32
rnd(int32 v, int32 r)
{
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index 761bc861a..c881a544a 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -48,23 +48,8 @@ enum
#define EXTERN extern
#endif
-/* do not undefine this - code will be removed eventually */
-#define CALLEEBX
-
-#define dynptrsize 0
-
#define P ((Prog*)0)
#define S ((LSym*)0)
-#define TNAME (ctxt->cursym?ctxt->cursym->name:noname)
-
-#define SIGNINTERN (1729*325*1729)
-
-typedef struct Count Count;
-struct Count
-{
- int32 count;
- int32 outof;
-};
enum
{
@@ -73,62 +58,9 @@ enum
LABEL = 1<<1,
LEAF = 1<<2,
- STRINGSZ = 200,
- MINSIZ = 64,
- NENT = 100,
- MAXIO = 8192,
- MAXHIST = 40, /* limit of path elements for history symbols */
MINLC = 4,
-
- C_NONE = 0,
- C_REG,
- C_REGREG,
- C_REGREG2,
- C_SHIFT,
- C_FREG,
- C_PSR,
- C_FCR,
-
- C_RCON, /* 0xff rotated */
- C_NCON, /* ~RCON */
- C_SCON, /* 0xffff */
- C_LCON,
- C_LCONADDR,
- C_ZFCON,
- C_SFCON,
- C_LFCON,
-
- C_RACON,
- C_LACON,
-
- C_SBRA,
- C_LBRA,
-
- C_HAUTO, /* halfword insn offset (-0xff to 0xff) */
- C_FAUTO, /* float insn offset (0 to 0x3fc, word aligned) */
- C_HFAUTO, /* both H and F */
- C_SAUTO, /* -0xfff to 0xfff */
- C_LAUTO,
-
- C_HOREG,
- C_FOREG,
- C_HFOREG,
- C_SOREG,
- C_ROREG,
- C_SROREG, /* both nil and R */
- C_LOREG,
-
- C_PC,
- C_SP,
- C_HREG,
-
- C_ADDR, /* reference to relocatable address */
-
- C_GOK,
};
-#ifndef COFFCVT
-
EXTERN int32 autosize;
EXTERN LSym* datap;
EXTERN int debug[128];
@@ -152,26 +84,18 @@ void adddynrela(LSym *rel, LSym *s, Reloc *r);
void adddynsym(Link *ctxt, LSym *s);
int archreloc(Reloc *r, LSym *s, vlong *val);
void asmb(void);
-void cput(int32 c);
int elfreloc1(Reloc *r, vlong sectoff);
void elfsetupplt(void);
-void hput(int32 l);
void listinit(void);
-void lput(int32 l);
int machoreloc1(Reloc *r, vlong sectoff);
void main(int argc, char *argv[]);
-void noops(void);
-void nopstat(char *f, Count *c);
int32 rnd(int32 v, int32 r);
-void wput(int32 l);
/* Native is little-endian */
#define LPUT(a) lputl(a)
#define WPUT(a) wputl(a)
#define VPUT(a) abort()
-#endif
-
/* Used by ../ld/dwarf.c */
enum
{
diff --git a/src/cmd/5l/mkenam b/src/cmd/5l/mkenam
deleted file mode 100644
index 6cccb0263..000000000
--- a/src/cmd/5l/mkenam
+++ /dev/null
@@ -1,45 +0,0 @@
-# Inferno utils/5c/mkenam
-# http://code.google.com/p/inferno-os/source/browse/utils/5c/mkenam
-#
-# Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-# Portions Copyright © 1995-1997 C H Forsyth (forsyth@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@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.
-
-awk '
-BEGIN {
- print "char* anames[] ="
- print "{"
-}
-
-/^ A/ {
- name=$1
- sub(/,/, "", name)
- sub(/^A/, "", name)
- print "\t\"" name "\","
-}
-
-END { print "};" }
-' ../5l/5.out.h >enam.c
diff --git a/src/cmd/5l/noop.c b/src/cmd/5l/noop.c
deleted file mode 100644
index d42c86289..000000000
--- a/src/cmd/5l/noop.c
+++ /dev/null
@@ -1,43 +0,0 @@
-// Inferno utils/5l/noop.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5l/noop.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@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@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.
-
-// Code transformations.
-
-#include "l.h"
-#include "../ld/lib.h"
-
-void
-noops(void)
-{
- LSym *s;
-
- for(s = ctxt->textp; s != nil; s = s->next)
- ctxt->arch->addstacksplit(ctxt, s);
-}
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index 86a0ece2e..c6f60ee7c 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -63,6 +63,7 @@ archinit(void)
break;
case Hlinux:
case Hfreebsd:
+ case Hnacl:
break;
}
@@ -82,7 +83,6 @@ archinit(void)
case Hlinux: /* arm elf */
case Hfreebsd:
case Hnetbsd:
- case Hnacl:
debug['d'] = 0; // with dynamic linking
elfinit();
HEADR = ELFRESERVE;
@@ -93,6 +93,17 @@ archinit(void)
if(INITRND == -1)
INITRND = 4096;
break;
+ case Hnacl:
+ elfinit();
+ HEADR = 0x10000;
+ funcalign = 16;
+ if(INITTEXT == -1)
+ INITTEXT = 0x20000;
+ if(INITDAT == -1)
+ INITDAT = 0;
+ if(INITRND == -1)
+ INITRND = 0x10000;
+ break;
}
if(INITDAT != 0 && INITRND != 0)
print("warning: -D0x%ux is ignored because of -R0x%ux\n",
diff --git a/src/cmd/6a/a.y b/src/cmd/6a/a.y
index 6fd491067..1089d4061 100644
--- a/src/cmd/6a/a.y
+++ b/src/cmd/6a/a.y
@@ -33,7 +33,7 @@
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
#include <libc.h>
#include "a.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
%}
%union {
Sym *sym;
diff --git a/src/cmd/6a/lex.c b/src/cmd/6a/lex.c
index 167e6b6c1..8973d6974 100644
--- a/src/cmd/6a/lex.c
+++ b/src/cmd/6a/lex.c
@@ -101,6 +101,7 @@ main(int argc, char *argv[])
ctxt = linknew(thelinkarch);
ctxt->diag = yyerror;
ctxt->bso = &bstdout;
+ ctxt->enforce_data_order = 1;
Binit(&bstdout, 1, OWRITE);
listinit6();
fmtinstall('L', Lconv);
@@ -435,49 +436,49 @@ struct
"IRETQ", LTYPE0, AIRETQ,
"IRETW", LTYPE0, AIRETW,
- "JOS", LTYPER, AJOS,
+ "JOS", LTYPER, AJOS, /* overflow set (OF = 1) */
"JO", LTYPER, AJOS, /* alternate */
- "JOC", LTYPER, AJOC,
+ "JOC", LTYPER, AJOC, /* overflow clear (OF = 0) */
"JNO", LTYPER, AJOC, /* alternate */
- "JCS", LTYPER, AJCS,
+ "JCS", LTYPER, AJCS, /* carry set (CF = 1) */
"JB", LTYPER, AJCS, /* alternate */
"JC", LTYPER, AJCS, /* alternate */
"JNAE", LTYPER, AJCS, /* alternate */
"JLO", LTYPER, AJCS, /* alternate */
- "JCC", LTYPER, AJCC,
+ "JCC", LTYPER, AJCC, /* carry clear (CF = 0) */
"JAE", LTYPER, AJCC, /* alternate */
"JNB", LTYPER, AJCC, /* alternate */
"JNC", LTYPER, AJCC, /* alternate */
"JHS", LTYPER, AJCC, /* alternate */
- "JEQ", LTYPER, AJEQ,
+ "JEQ", LTYPER, AJEQ, /* equal (ZF = 1) */
"JE", LTYPER, AJEQ, /* alternate */
"JZ", LTYPER, AJEQ, /* alternate */
- "JNE", LTYPER, AJNE,
+ "JNE", LTYPER, AJNE, /* not equal (ZF = 0) */
"JNZ", LTYPER, AJNE, /* alternate */
- "JLS", LTYPER, AJLS,
+ "JLS", LTYPER, AJLS, /* lower or same (unsigned) (CF = 1 || ZF = 1) */
"JBE", LTYPER, AJLS, /* alternate */
"JNA", LTYPER, AJLS, /* alternate */
- "JHI", LTYPER, AJHI,
+ "JHI", LTYPER, AJHI, /* higher (unsigned) (CF = 0 && ZF = 0) */
"JA", LTYPER, AJHI, /* alternate */
"JNBE", LTYPER, AJHI, /* alternate */
- "JMI", LTYPER, AJMI,
+ "JMI", LTYPER, AJMI, /* negative (minus) (SF = 1) */
"JS", LTYPER, AJMI, /* alternate */
- "JPL", LTYPER, AJPL,
+ "JPL", LTYPER, AJPL, /* non-negative (plus) (SF = 0) */
"JNS", LTYPER, AJPL, /* alternate */
- "JPS", LTYPER, AJPS,
+ "JPS", LTYPER, AJPS, /* parity set (PF = 1) */
"JP", LTYPER, AJPS, /* alternate */
"JPE", LTYPER, AJPS, /* alternate */
- "JPC", LTYPER, AJPC,
+ "JPC", LTYPER, AJPC, /* parity clear (PF = 0) */
"JNP", LTYPER, AJPC, /* alternate */
"JPO", LTYPER, AJPC, /* alternate */
- "JLT", LTYPER, AJLT,
+ "JLT", LTYPER, AJLT, /* less than (signed) (SF != OF) */
"JL", LTYPER, AJLT, /* alternate */
"JNGE", LTYPER, AJLT, /* alternate */
- "JGE", LTYPER, AJGE,
+ "JGE", LTYPER, AJGE, /* greater than or equal (signed) (SF = OF) */
"JNL", LTYPER, AJGE, /* alternate */
- "JLE", LTYPER, AJLE,
+ "JLE", LTYPER, AJLE, /* less than or equal (signed) (ZF = 1 || SF != OF) */
"JNG", LTYPER, AJLE, /* alternate */
- "JGT", LTYPER, AJGT,
+ "JGT", LTYPER, AJGT, /* greater than (signed) (ZF = 0 && SF = OF) */
"JG", LTYPER, AJGT, /* alternate */
"JNLE", LTYPER, AJGT, /* alternate */
"JCXZL", LTYPER, AJCXZL,
@@ -612,7 +613,7 @@ struct
"SCASL", LTYPE0, ASCASL,
"SCASQ", LTYPE0, ASCASQ,
"SCASW", LTYPE0, ASCASW,
- "SETCC", LTYPE1, ASETCC,
+ "SETCC", LTYPE1, ASETCC, /* see JCC etc above for condition codes */
"SETCS", LTYPE1, ASETCS,
"SETEQ", LTYPE1, ASETEQ,
"SETGE", LTYPE1, ASETGE,
diff --git a/src/cmd/6a/y.tab.c b/src/cmd/6a/y.tab.c
index a4f0f74cc..b69fd95b5 100644
--- a/src/cmd/6a/y.tab.c
+++ b/src/cmd/6a/y.tab.c
@@ -150,7 +150,7 @@
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
#include <libc.h>
#include "a.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
/* Enabling traces. */
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c
index bdef76ff0..68dd7bb5f 100644
--- a/src/cmd/6c/cgen.c
+++ b/src/cmd/6c/cgen.c
@@ -29,7 +29,7 @@
// THE SOFTWARE.
#include "gc.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
/* ,x/^(print|prtree)\(/i/\/\/ */
int castup(Type*, Type*);
@@ -51,7 +51,7 @@ cgen(Node *n, Node *nn)
}
if(n == Z || n->type == T)
return;
- if(typesu[n->type->etype]) {
+ if(typesu[n->type->etype] && (n->op != OFUNC || nn != Z)) {
sugen(n, nn, n->type->width);
return;
}
@@ -88,7 +88,7 @@ cgen(Node *n, Node *nn)
if(cond(o) && typesu[l->type->etype])
break;
- regret(&nod, r);
+ regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
@@ -135,7 +135,7 @@ cgen(Node *n, Node *nn)
if(!hardleft) {
if(nn != Z || r->addable < INDEXED || hardconst(r)) {
if(r->complex >= FNX && nn == Z)
- regret(&nod, r);
+ regret(&nod, r, 0, 0);
else
regalloc(&nod, r, nn);
cgen(r, &nod);
@@ -929,7 +929,7 @@ cgen(Node *n, Node *nn)
if(l->op != OIND)
diag(n, "bad function call");
- regret(&nod, l->left);
+ regret(&nod, l->left, 0, 0);
cgen(l->left, &nod);
regsalloc(&nod1, l->left);
gmove(&nod, &nod1);
@@ -945,7 +945,6 @@ cgen(Node *n, Node *nn)
return;
}
gargs(r, &nod, &nod1);
- gpcdata(PCDATA_ArgSize, curarg);
if(l->addable < INDEXED) {
reglcgen(&nod, l, nn);
nod.op = OREGISTER;
@@ -953,14 +952,13 @@ cgen(Node *n, Node *nn)
regfree(&nod);
} else
gopcode(OFUNC, n->type, Z, l);
- gpcdata(PCDATA_ArgSize, -1);
if(REGARG >= 0 && reg[REGARG])
reg[REGARG]--;
- if(nn != Z) {
- regret(&nod, n);
+ regret(&nod, n, l->type, 1); // update maxarg if nothing else
+ if(nn != Z)
gmove(&nod, nn);
+ if(nod.op == OREGISTER)
regfree(&nod);
- }
break;
case OIND:
@@ -1382,7 +1380,7 @@ boolgen(Node *n, int true, Node *nn)
if(true)
o = comrel[relindex(o)];
if(l->complex >= FNX && r->complex >= FNX) {
- regret(&nod, r);
+ regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
gmove(&nod, &nod1);
@@ -1535,7 +1533,7 @@ sugen(Node *n, Node *nn, int32 w)
if(nn != Z && side(nn)) {
nod1 = *n;
nod1.type = typ(TIND, n->type);
- regret(&nod2, &nod1);
+ regret(&nod2, &nod1, 0, 0);
lcgen(nn, &nod2);
regsalloc(&nod0, &nod1);
cgen(&nod2, &nod0);
@@ -1617,6 +1615,20 @@ sugen(Node *n, Node *nn, int32 w)
break;
case OFUNC:
+ if(!hasdotdotdot(n->left->type)) {
+ cgen(n, Z);
+ if(nn != Z) {
+ curarg -= n->type->width;
+ regret(&nod1, n, n->left->type, 1);
+ if(nn->complex >= FNX) {
+ regsalloc(&nod2, n);
+ cgen(&nod1, &nod2);
+ nod1 = nod2;
+ }
+ cgen(&nod1, nn);
+ }
+ break;
+ }
if(nn == Z) {
sugen(n, nodrat, w);
break;
diff --git a/src/cmd/6c/gc.h b/src/cmd/6c/gc.h
index a196e55a8..aa9d95d21 100644
--- a/src/cmd/6c/gc.h
+++ b/src/cmd/6c/gc.h
@@ -143,7 +143,6 @@ EXTERN int32 cursafe;
EXTERN Prog* lastp;
EXTERN int32 maxargsafe;
EXTERN int mnstring;
-EXTERN int retok;
EXTERN Node* nodrat;
EXTERN Node* nodret;
EXTERN Node* nodsafe;
@@ -211,7 +210,7 @@ void xcom(Node*);
void indx(Node*);
int bcomplex(Node*, Node*);
Prog* gtext(Sym*, int32);
-vlong argsize(void);
+vlong argsize(int);
/*
* cgen.c
@@ -240,7 +239,7 @@ Node* nodfconst(double);
Node* nodgconst(vlong, Type*);
int nodreg(Node*, Node*, int);
int isreg(Node*, int);
-void regret(Node*, Node*);
+void regret(Node*, Node*, Type*, int);
void regalloc(Node*, Node*, Node*);
void regfree(Node*);
void regialloc(Node*, Node*, Node*);
diff --git a/src/cmd/6c/reg.c b/src/cmd/6c/reg.c
index 348d747b7..6f8d3ce14 100644
--- a/src/cmd/6c/reg.c
+++ b/src/cmd/6c/reg.c
@@ -585,14 +585,11 @@ loop2:
}
rgp->cost = change;
nregion++;
- if(nregion >= NRGN) {
- warn(Z, "too many regions");
- goto brk;
- }
+ if(nregion >= NRGN)
+ fatal(Z, "too many regions");
rgp++;
}
}
-brk:
qsort(region, nregion, sizeof(region[0]), rcmp);
/*
@@ -808,11 +805,8 @@ mkvar(Reg *r, Addr *a)
goto out;
v++;
}
- if(nvar >= NVAR) {
- if(debug['w'] > 1 && s)
- warn(Z, "variable not optimized: %s", s->name);
- goto none;
- }
+ if(nvar >= NVAR)
+ fatal(Z, "variable not optimized: %s", s->name);
i = nvar;
nvar++;
v = &var[i];
diff --git a/src/cmd/6c/sgen.c b/src/cmd/6c/sgen.c
index ba1c1f652..fceb332b2 100644
--- a/src/cmd/6c/sgen.c
+++ b/src/cmd/6c/sgen.c
@@ -29,14 +29,14 @@
// THE SOFTWARE.
#include "gc.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
Prog*
gtext(Sym *s, int32 stkoff)
{
vlong v;
- v = ((uvlong)argsize() << 32) | (stkoff & 0xffffffff);
+ v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
if((textflag & NOSPLIT) && stkoff >= 128)
yyerror("stack frame too large for NOSPLIT function");
@@ -124,10 +124,7 @@ xcom(Node *n)
break;
case ONAME:
- if(flag_largemodel)
- n->addable = 9;
- else
- n->addable = 10;
+ n->addable = 9;
if(n->class == CPARAM || n->class == CAUTO)
n->addable = 11;
break;
diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c
index d7713648d..6e918eb10 100644
--- a/src/cmd/6c/swt.c
+++ b/src/cmd/6c/swt.c
@@ -250,10 +250,11 @@ align(int32 i, Type *t, int op, int32 *maxalign)
{
int32 o;
Type *v;
- int w;
+ int w, packw;
o = i;
w = 1;
+ packw = 0;
switch(op) {
default:
diag(Z, "unknown align opcode %d", op);
@@ -264,7 +265,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1)
w = 1;
if(packflg)
- w = packflg;
+ packw = packflg;
break;
case Ael1: /* initial align of struct element */
@@ -277,7 +278,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1 || w > SZ_VLONG)
fatal(Z, "align");
if(packflg)
- w = packflg;
+ packw = packflg;
break;
case Ael2: /* width of a struct element */
@@ -331,6 +332,8 @@ align(int32 i, Type *t, int op, int32 *maxalign)
o = align(o, t, Ael2, nil);
break;
}
+ if(packw != 0 && xround(o, w) != xround(o, packw))
+ diag(Z, "#pragma pack changes offset of %T", t);
o = xround(o, w);
if(maxalign && *maxalign < w)
*maxalign = w;
diff --git a/src/cmd/6c/txt.c b/src/cmd/6c/txt.c
index 4d07436c3..3bdbf410e 100644
--- a/src/cmd/6c/txt.c
+++ b/src/cmd/6c/txt.c
@@ -351,15 +351,43 @@ nodreg(Node *n, Node *nn, int r)
}
void
-regret(Node *n, Node *nn)
+regret(Node *n, Node *nn, Type *t, int mode)
{
int r;
+
+ if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
+ r = REGRET;
+ if(typefd[nn->type->etype])
+ r = FREGRET;
+ nodreg(n, nn, r);
+ reg[r]++;
+ return;
+ }
+
+ if(mode == 1) {
+ // fetch returned value after call.
+ // already called gargs, so curarg is set.
+ curarg = (curarg+7) & ~7;
+ regaalloc(n, nn);
+ return;
+ }
- r = REGRET;
- if(typefd[nn->type->etype])
- r = FREGRET;
- nodreg(n, nn, r);
- reg[r]++;
+ if(mode == 2) {
+ // store value to be returned.
+ // must compute arg offset.
+ if(t->etype != TFUNC)
+ fatal(Z, "bad regret func %T", t);
+ *n = *nn;
+ n->op = ONAME;
+ n->class = CPARAM;
+ n->sym = slookup(".ret");
+ n->complex = nodret->complex;
+ n->addable = 20;
+ n->xoffset = argsize(0);
+ return;
+ }
+
+ fatal(Z, "bad regret");
}
void
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
index 4dd505b08..d13c98dad 100644
--- a/src/cmd/6g/cgen.c
+++ b/src/cmd/6g/cgen.c
@@ -247,7 +247,6 @@ cgen(Node *n, Node *res)
case OOR:
case OXOR:
case OADD:
- case OADDPTR:
case OMUL:
a = optoas(n->op, nl->type);
if(a == AIMULB) {
@@ -752,12 +751,7 @@ agenr(Node *n, Node *a, Node *res)
regalloc(&n3, types[tptr], res);
p1 = gins(ALEAQ, N, &n3);
datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
- if(flag_largemodel) {
- gins(AADDQ, &n2, &n3);
- } else {
- p1->from.scale = 1;
- p1->from.index = n2.val.u.reg;
- }
+ gins(AADDQ, &n2, &n3);
goto indexdone;
}
@@ -1457,7 +1451,7 @@ sgen(Node *n, Node *ns, int64 w)
p = gins(ADUFFCOPY, N, N);
p->to.type = D_ADDR;
p->to.sym = linksym(pkglookup("duffcopy", runtimepkg));
- // 14 and 128 = magic constants: see ../../pkg/runtime/asm_amd64.s
+ // 14 and 128 = magic constants: see ../../runtime/asm_amd64.s
p->to.offset = 14*(128-q);
} else
while(q > 0) {
diff --git a/src/cmd/6g/galign.c b/src/cmd/6g/galign.c
index 1d32c5a61..5670e6fac 100644
--- a/src/cmd/6g/galign.c
+++ b/src/cmd/6g/galign.c
@@ -30,10 +30,10 @@ int cmpptr = ACMPQ;
*/
Typedef typedefs[] =
{
- "int", TINT, TINT64,
- "uint", TUINT, TUINT64,
- "uintptr", TUINTPTR, TUINT64,
- 0
+ {"int", TINT, TINT64},
+ {"uint", TUINT, TUINT64},
+ {"uintptr", TUINTPTR, TUINT64},
+ {0}
};
void
diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h
index a5da17d61..fe69d5c96 100644
--- a/src/cmd/6g/gg.h
+++ b/src/cmd/6g/gg.h
@@ -51,7 +51,6 @@ void allocparams(void);
void checklabels(void);
void ginscall(Node*, int);
int gen_as_init(Node*);
-void clearslim(Node*);
/*
* cgen.c
@@ -100,7 +99,6 @@ int sudoaddable(int, Node*, Addr*);
void afunclit(Addr*, Node*);
void nodfconst(Node*, Type*, Mpflt*);
void gtrack(Sym*);
-void gargsize(vlong);
void fixlargeoffset(Node *n);
/*
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index 9665d831b..363620769 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -175,7 +175,6 @@ fixautoused(Prog *p)
void
ginscall(Node *f, int proc)
{
- int32 arg;
Prog *p;
Node reg, con;
Node r1;
@@ -183,21 +182,6 @@ ginscall(Node *f, int proc)
if(f->type != T)
setmaxarg(f->type);
- arg = -1;
- // Most functions have a fixed-size argument block, so traceback uses that during unwind.
- // Not all, though: there are some variadic functions in package runtime,
- // and for those we emit call-specific metadata recorded by caller.
- // Reflect generates functions with variable argsize (see reflect.methodValueCall/makeFuncStub),
- // so we do this for all indirect calls as well.
- if(f->type != T && (f->sym == S || (f->sym != S && f->sym->pkg == runtimepkg) || proc == 1 || proc == 2)) {
- arg = f->type->argwid;
- if(proc == 1 || proc == 2)
- arg += 2*widthptr;
- }
-
- if(arg != -1)
- gargsize(arg);
-
switch(proc) {
default:
fatal("ginscall: bad proc %d", proc);
@@ -275,9 +259,6 @@ ginscall(Node *f, int proc)
}
break;
}
-
- if(arg != -1)
- gargsize(-1);
}
/*
@@ -1121,26 +1102,54 @@ clearfat(Node *nl)
c = w % 8; // bytes
q = w / 8; // quads
+ 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.
+ agenr(nl, &n1, N);
+ n1.op = OINDREG;
+ nodconst(&z, types[TUINT64], 0);
+ while(q-- > 0) {
+ n1.type = z.type;
+ gins(AMOVQ, &z, &n1);
+ n1.xoffset += 8;
+ }
+ if(c >= 4) {
+ nodconst(&z, types[TUINT32], 0);
+ n1.type = z.type;
+ gins(AMOVL, &z, &n1);
+ n1.xoffset += 4;
+ c -= 4;
+ }
+ nodconst(&z, types[TUINT8], 0);
+ while(c-- > 0) {
+ n1.type = z.type;
+ gins(AMOVB, &z, &n1);
+ n1.xoffset++;
+ }
+ regfree(&n1);
+ return;
+ }
+
savex(D_DI, &n1, &oldn1, N, types[tptr]);
agen(nl, &n1);
savex(D_AX, &ax, &oldax, N, types[tptr]);
gconreg(AMOVL, 0, D_AX);
- if(q > 128 || (q >= 4 && nacl)) {
+ if(q > 128 || nacl) {
gconreg(movptr, q, D_CX);
gins(AREP, N, N); // repeat
gins(ASTOSQ, N, N); // STOQ AL,*(DI)+
- } else if(q >= 4) {
+ } else {
p = gins(ADUFFZERO, N, N);
p->to.type = D_ADDR;
p->to.sym = linksym(pkglookup("duffzero", runtimepkg));
- // 2 and 128 = magic constants: see ../../pkg/runtime/asm_amd64.s
+ // 2 and 128 = magic constants: see ../../runtime/asm_amd64.s
p->to.offset = 2*(128-q);
- } else
- while(q > 0) {
- gins(ASTOSQ, N, N); // STOQ AL,*(DI)+
- q--;
}
z = ax;
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index e4d00bf41..5bd924660 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -31,11 +31,11 @@
#include <u.h>
#include <libc.h>
#include "gg.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
// TODO(rsc): Can make this bigger if we move
// the text segment up higher in 6l for all GOOS.
-// At the same time, can raise StackBig in ../../pkg/runtime/stack.h.
+// At the same time, can raise StackBig in ../../runtime/stack.h.
vlong unmappedzero = 4096;
void
@@ -215,17 +215,7 @@ gtrack(Sym *s)
}
void
-gargsize(vlong size)
-{
- Node n1, n2;
-
- nodconst(&n1, types[TINT32], PCDATA_ArgSize);
- nodconst(&n2, types[TINT32], size);
- gins(APCDATA, &n1, &n2);
-}
-
-void
-ggloblsym(Sym *s, int32 width, int dupok, int rodata)
+ggloblsym(Sym *s, int32 width, int8 flags)
{
Prog *p;
@@ -236,10 +226,7 @@ ggloblsym(Sym *s, int32 width, int dupok, int rodata)
p->to.type = D_CONST;
p->to.index = D_NONE;
p->to.offset = width;
- if(dupok)
- p->from.scale |= DUPOK;
- if(rodata)
- p->from.scale |= RODATA;
+ p->from.scale = flags;
}
int
@@ -584,6 +571,7 @@ ginscon(int as, vlong c, Node *n2)
}
#define CASE(a,b) (((a)<<16)|((b)<<0))
+/*c2go int CASE(int, int); */
/*
* Is this node a memory operand?
@@ -600,11 +588,8 @@ ismem(Node *n)
case ONAME:
case OPARAM:
case OCLOSUREVAR:
- return 1;
case OADDR:
- if(flag_largemodel)
- return 1;
- break;
+ return 1;
}
return 0;
}
@@ -1542,14 +1527,12 @@ optoas(int op, Type *t)
case CASE(OADD, TINT32):
case CASE(OADD, TUINT32):
case CASE(OADD, TPTR32):
- case CASE(OADDPTR, TPTR32):
a = AADDL;
break;
case CASE(OADD, TINT64):
case CASE(OADD, TUINT64):
case CASE(OADD, TPTR64):
- case CASE(OADDPTR, TPTR64):
a = AADDQ;
break;
diff --git a/src/cmd/6g/opt.h b/src/cmd/6g/opt.h
index bf356af0c..dbd039d89 100644
--- a/src/cmd/6g/opt.h
+++ b/src/cmd/6g/opt.h
@@ -49,6 +49,24 @@
typedef struct Reg Reg;
typedef struct Rgn Rgn;
+/*c2go
+extern Node *Z;
+enum
+{
+ D_HI = D_NONE,
+ D_LO = D_NONE,
+ CLOAD = 5,
+ CREF = 5,
+ CINF = 1000,
+ LOOP = 3,
+};
+
+uint32 BLOAD(Reg*);
+uint32 BSTORE(Reg*);
+uint32 LOAD(Reg*);
+uint32 STORE(Reg*);
+*/
+
// A Reg is a wrapper around a single Prog (one instruction) that holds
// register optimization information while the optimizer runs.
// r->prog is the instruction.
@@ -71,8 +89,10 @@ struct Reg
int32 regu; // register used bitmap
};
#define R ((Reg*)0)
+/*c2go extern Reg *R; */
#define NRGN 600
+/*c2go enum { NRGN = 600 }; */
struct Rgn
{
Reg* enter;
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
index f3b1e55de..1f757e197 100644
--- a/src/cmd/6g/reg.c
+++ b/src/cmd/6g/reg.c
@@ -35,6 +35,11 @@
#define NREGVAR 32 /* 16 general + 16 floating */
#define REGBITS ((uint32)0xffffffff)
+/*c2go enum {
+ NREGVAR = 32,
+ REGBITS = 0xffffffff,
+};
+*/
static Reg* firstr;
static int first = 1;
@@ -839,7 +844,7 @@ prop(Reg *r, Bits ref, Bits cal)
if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
for(; v1 != nil; v1 = v1->nextinnode) {
j = v1 - var;
- cal.b[j/32] |= 1<<(j&31);
+ cal.b[j/32] |= 1UL<<(j&31);
}
}
}
@@ -1186,6 +1191,7 @@ void
addreg(Adr *a, int rn)
{
a->sym = nil;
+ a->node = nil;
a->offset = 0;
a->type = rn;
diff --git a/src/cmd/6l/6.out.h b/src/cmd/6l/6.out.h
index 1e2a1488f..af72784e8 100644
--- a/src/cmd/6l/6.out.h
+++ b/src/cmd/6l/6.out.h
@@ -36,7 +36,7 @@
* amd64
*/
-enum as
+enum
{
AXXX,
AAAA,
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 7828e2892..18b5aa311 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -290,7 +290,6 @@ elfreloc1(Reloc *r, vlong sectoff)
break;
case R_CALL:
- case R_PCREL:
if(r->siz == 4) {
if(r->xsym->type == SDYNIMPORT)
VPUT(R_X86_64_GOTPCREL | (uint64)elfsym<<32);
@@ -299,7 +298,14 @@ elfreloc1(Reloc *r, vlong sectoff)
} else
return -1;
break;
-
+
+ case R_PCREL:
+ if(r->siz == 4) {
+ VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
+ } else
+ return -1;
+ break;
+
case R_TLS:
if(r->siz == 4) {
if(flag_shared)
@@ -323,7 +329,7 @@ machoreloc1(Reloc *r, vlong sectoff)
rs = r->xsym;
- if(rs->type == SHOSTOBJ) {
+ if(rs->type == SHOSTOBJ || r->type == R_PCREL) {
if(rs->dynid < 0) {
diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type);
return -1;
@@ -345,10 +351,13 @@ machoreloc1(Reloc *r, vlong sectoff)
v |= MACHO_X86_64_RELOC_UNSIGNED<<28;
break;
case R_CALL:
- case R_PCREL:
v |= 1<<24; // pc-relative bit
v |= MACHO_X86_64_RELOC_BRANCH<<28;
break;
+ case R_PCREL:
+ // NOTE: Only works with 'external' relocation. Forced above.
+ v |= 1<<24; // pc-relative bit
+ v |= MACHO_X86_64_RELOC_SIGNED<<28;
}
switch(r->siz) {
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index 7303910a6..ff2e69452 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -68,14 +68,9 @@ EXTERN int RegSize;
#define P ((Prog*)0)
#define S ((LSym*)0)
-#define TNAME (ctxt->cursym?ctxt->cursym->name:noname)
enum
{
- MINSIZ = 8,
- STRINGSZ = 200,
MINLC = 1,
- MAXIO = 8192,
- MAXHIST = 40, /* limit of path elements for history symbols */
};
#pragma varargck type "I" uchar*
@@ -89,9 +84,6 @@ EXTERN int32 spsize;
EXTERN LSym* symlist;
EXTERN int32 symsize;
-EXTERN vlong textstksiz;
-EXTERN vlong textarg;
-
int Iconv(Fmt *fp);
void adddynlib(char *lib);
void adddynrel(LSym *s, Reloc *r);
@@ -103,8 +95,6 @@ int elfreloc1(Reloc *r, vlong sectoff);
void elfsetupplt(void);
void listinit(void);
int machoreloc1(Reloc *r, vlong sectoff);
-void main(int argc, char *argv[]);
-void parsetextconst(vlong arg);
vlong rnd(vlong v, vlong r);
/* Native is little-endian */
diff --git a/src/cmd/6l/mkenam b/src/cmd/6l/mkenam
deleted file mode 100644
index 3001dbe93..000000000
--- a/src/cmd/6l/mkenam
+++ /dev/null
@@ -1,45 +0,0 @@
-# Inferno utils/6c/mkenam
-# http://code.google.com/p/inferno-os/source/browse/utils/6c/mkenam
-#
-# Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-# Portions Copyright © 1995-1997 C H Forsyth (forsyth@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@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.
-
-awk '
-BEGIN {
- print "char* anames[] ="
- print "{"
-}
-
-/^ A/ {
- name=$1
- sub(/,/, "", name)
- sub(/^A/, "", name)
- print "\t\"" name "\","
-}
-
-END { print "};" }
-' ../6l/6.out.h >enam.c
diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y
index d7ff623da..6bcf1313b 100644
--- a/src/cmd/8a/a.y
+++ b/src/cmd/8a/a.y
@@ -33,7 +33,7 @@
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
#include <libc.h>
#include "a.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
%}
%union {
Sym *sym;
diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c
index 32c099b75..6ce6a18ab 100644
--- a/src/cmd/8a/lex.c
+++ b/src/cmd/8a/lex.c
@@ -90,6 +90,7 @@ main(int argc, char *argv[])
ctxt = linknew(&link386);
ctxt->diag = yyerror;
ctxt->bso = &bstdout;
+ ctxt->enforce_data_order = 1;
Binit(&bstdout, 1, OWRITE);
listinit8();
fmtinstall('L', Lconv);
@@ -352,49 +353,49 @@ struct
"IRETL", LTYPE0, AIRETL,
"IRETW", LTYPE0, AIRETW,
- "JOS", LTYPER, AJOS,
+ "JOS", LTYPER, AJOS, /* overflow set (OF = 1) */
"JO", LTYPER, AJOS, /* alternate */
- "JOC", LTYPER, AJOC,
+ "JOC", LTYPER, AJOC, /* overflow clear (OF = 0) */
"JNO", LTYPER, AJOC, /* alternate */
- "JCS", LTYPER, AJCS,
+ "JCS", LTYPER, AJCS, /* carry set (CF = 1) */
"JB", LTYPER, AJCS, /* alternate */
"JC", LTYPER, AJCS, /* alternate */
"JNAE", LTYPER, AJCS, /* alternate */
"JLO", LTYPER, AJCS, /* alternate */
- "JCC", LTYPER, AJCC,
+ "JCC", LTYPER, AJCC, /* carry clear (CF = 0) */
"JAE", LTYPER, AJCC, /* alternate */
"JNB", LTYPER, AJCC, /* alternate */
"JNC", LTYPER, AJCC, /* alternate */
"JHS", LTYPER, AJCC, /* alternate */
- "JEQ", LTYPER, AJEQ,
+ "JEQ", LTYPER, AJEQ, /* equal (ZF = 1) */
"JE", LTYPER, AJEQ, /* alternate */
"JZ", LTYPER, AJEQ, /* alternate */
- "JNE", LTYPER, AJNE,
+ "JNE", LTYPER, AJNE, /* not equal (ZF = 0) */
"JNZ", LTYPER, AJNE, /* alternate */
- "JLS", LTYPER, AJLS,
+ "JLS", LTYPER, AJLS, /* lower or same (unsigned) (CF = 1 || ZF = 1) */
"JBE", LTYPER, AJLS, /* alternate */
"JNA", LTYPER, AJLS, /* alternate */
- "JHI", LTYPER, AJHI,
+ "JHI", LTYPER, AJHI, /* higher (unsigned) (CF = 0 && ZF = 0) */
"JA", LTYPER, AJHI, /* alternate */
"JNBE", LTYPER, AJHI, /* alternate */
- "JMI", LTYPER, AJMI,
+ "JMI", LTYPER, AJMI, /* negative (minus) (SF = 1) */
"JS", LTYPER, AJMI, /* alternate */
- "JPL", LTYPER, AJPL,
+ "JPL", LTYPER, AJPL, /* non-negative (plus) (SF = 0) */
"JNS", LTYPER, AJPL, /* alternate */
- "JPS", LTYPER, AJPS,
+ "JPS", LTYPER, AJPS, /* parity set (PF = 1) */
"JP", LTYPER, AJPS, /* alternate */
"JPE", LTYPER, AJPS, /* alternate */
- "JPC", LTYPER, AJPC,
+ "JPC", LTYPER, AJPC, /* parity clear (PF = 0) */
"JNP", LTYPER, AJPC, /* alternate */
"JPO", LTYPER, AJPC, /* alternate */
- "JLT", LTYPER, AJLT,
+ "JLT", LTYPER, AJLT, /* less than (signed) (SF != OF) */
"JL", LTYPER, AJLT, /* alternate */
"JNGE", LTYPER, AJLT, /* alternate */
- "JGE", LTYPER, AJGE,
+ "JGE", LTYPER, AJGE, /* greater than or equal (signed) (SF = OF) */
"JNL", LTYPER, AJGE, /* alternate */
- "JLE", LTYPER, AJLE,
+ "JLE", LTYPER, AJLE, /* less than or equal (signed) (ZF = 1 || SF != OF) */
"JNG", LTYPER, AJLE, /* alternate */
- "JGT", LTYPER, AJGT,
+ "JGT", LTYPER, AJGT, /* greater than (signed) (ZF = 0 && SF = OF) */
"JG", LTYPER, AJGT, /* alternate */
"JNLE", LTYPER, AJGT, /* alternate */
@@ -493,7 +494,7 @@ struct
"SCASB", LTYPE0, ASCASB,
"SCASL", LTYPE0, ASCASL,
"SCASW", LTYPE0, ASCASW,
- "SETCC", LTYPE1, ASETCC,
+ "SETCC", LTYPE1, ASETCC, /* see JCC etc above for condition codes */
"SETCS", LTYPE1, ASETCS,
"SETEQ", LTYPE1, ASETEQ,
"SETGE", LTYPE1, ASETGE,
diff --git a/src/cmd/8a/y.tab.c b/src/cmd/8a/y.tab.c
index f48c9fe1f..85279c21f 100644
--- a/src/cmd/8a/y.tab.c
+++ b/src/cmd/8a/y.tab.c
@@ -146,7 +146,7 @@
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
#include <libc.h>
#include "a.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
/* Enabling traces. */
diff --git a/src/cmd/8c/cgen.c b/src/cmd/8c/cgen.c
index f54102245..87e8fdad8 100644
--- a/src/cmd/8c/cgen.c
+++ b/src/cmd/8c/cgen.c
@@ -29,7 +29,7 @@
// THE SOFTWARE.
#include "gc.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
/* ,x/^(print|prtree)\(/i/\/\/ */
@@ -49,7 +49,7 @@ cgen(Node *n, Node *nn)
}
if(n == Z || n->type == T)
return;
- if(typesuv[n->type->etype]) {
+ if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) {
sugen(n, nn, n->type->width);
return;
}
@@ -86,7 +86,7 @@ cgen(Node *n, Node *nn)
if(cond(o) && typesuv[l->type->etype])
break;
- regret(&nod, r);
+ regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
@@ -147,7 +147,7 @@ cgen(Node *n, Node *nn)
if(!hardleft) {
if(nn != Z || r->addable < INDEXED) {
if(r->complex >= FNX && nn == Z)
- regret(&nod, r);
+ regret(&nod, r, 0, 0);
else
regalloc(&nod, r, nn);
cgen(r, &nod);
@@ -922,7 +922,7 @@ cgen(Node *n, Node *nn)
if(l->op != OIND)
diag(n, "bad function call");
- regret(&nod, l->left);
+ regret(&nod, l->left, 0, 0);
cgen(l->left, &nod);
regsalloc(&nod1, l->left);
gmove(&nod, &nod1);
@@ -938,7 +938,6 @@ cgen(Node *n, Node *nn)
return;
}
gargs(r, &nod, &nod1);
- gpcdata(PCDATA_ArgSize, curarg);
if(l->addable < INDEXED) {
reglcgen(&nod, l, nn);
nod.op = OREGISTER;
@@ -946,15 +945,14 @@ cgen(Node *n, Node *nn)
regfree(&nod);
} else
gopcode(OFUNC, n->type, Z, l);
- gpcdata(PCDATA_ArgSize, -1);
if(REGARG >= 0 && reg[REGARG])
reg[REGARG]--;
- if(nn != Z) {
- regret(&nod, n);
+ regret(&nod, n, l->type, 1); // update maxarg if nothing else
+ if(nn != Z)
gmove(&nod, nn);
+ if(nod.op == OREGISTER)
regfree(&nod);
- } else
- if(typefd[n->type->etype])
+ if(nn == Z && hasdotdotdot(l->type) && typefd[n->type->etype])
gins(AFMOVDP, &fregnode0, &fregnode0);
break;
@@ -1374,7 +1372,7 @@ boolgen(Node *n, int true, Node *nn)
if(true)
o = comrel[relindex(o)];
if(l->complex >= FNX && r->complex >= FNX) {
- regret(&nod, r);
+ regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
gmove(&nod, &nod1);
@@ -1567,7 +1565,7 @@ sugen(Node *n, Node *nn, int32 w)
if(nn != Z && side(nn)) {
nod1 = *n;
nod1.type = typ(TIND, n->type);
- regret(&nod2, &nod1);
+ regret(&nod2, &nod1, 0, 0);
lcgen(nn, &nod2);
regsalloc(&nod0, &nod1);
cgen(&nod2, &nod0);
@@ -1649,6 +1647,20 @@ sugen(Node *n, Node *nn, int32 w)
break;
case OFUNC:
+ if(!hasdotdotdot(n->left->type)) {
+ cgen(n, Z);
+ if(nn != Z) {
+ curarg -= n->type->width;
+ regret(&nod1, n, n->left->type, 1);
+ if(nn->complex >= FNX) {
+ regsalloc(&nod2, n);
+ cgen(&nod1, &nod2);
+ nod1 = nod2;
+ }
+ cgen(&nod1, nn);
+ }
+ break;
+ }
if(nn == Z) {
sugen(n, nodrat, w);
break;
diff --git a/src/cmd/8c/gc.h b/src/cmd/8c/gc.h
index 87b8e22bc..aa3888d73 100644
--- a/src/cmd/8c/gc.h
+++ b/src/cmd/8c/gc.h
@@ -143,7 +143,6 @@ EXTERN int32 cursafe;
EXTERN Prog* lastp;
EXTERN int32 maxargsafe;
EXTERN int mnstring;
-EXTERN int retok;
EXTERN Node* nodrat;
EXTERN Node* nodret;
EXTERN Node* nodsafe;
@@ -211,7 +210,7 @@ void xcom(Node*);
void indx(Node*);
int bcomplex(Node*, Node*);
Prog* gtext(Sym*, int32);
-vlong argsize(void);
+vlong argsize(int);
/*
* cgen.c
@@ -245,7 +244,7 @@ Node* nodconst(int32);
Node* nodfconst(double);
int nodreg(Node*, Node*, int);
int isreg(Node*, int);
-void regret(Node*, Node*);
+void regret(Node*, Node*, Type*, int);
void regalloc(Node*, Node*, Node*);
void regfree(Node*);
void regialloc(Node*, Node*, Node*);
diff --git a/src/cmd/8c/reg.c b/src/cmd/8c/reg.c
index e6ba8bcb3..ea862f388 100644
--- a/src/cmd/8c/reg.c
+++ b/src/cmd/8c/reg.c
@@ -518,7 +518,7 @@ loop2:
rgp->cost = change;
nregion++;
if(nregion >= NRGN) {
- warn(Z, "too many regions");
+ fatal(Z, "too many regions");
goto brk;
}
rgp++;
@@ -746,11 +746,8 @@ mkvar(Reg *r, Addr *a)
goto out;
v++;
}
- if(nvar >= NVAR) {
- if(debug['w'] > 1 && s)
- warn(Z, "variable not optimized: %s", s->name);
- goto none;
- }
+ if(nvar >= NVAR)
+ fatal(Z, "variable not optimized: %s", s->name);
i = nvar;
nvar++;
v = &var[i];
diff --git a/src/cmd/8c/sgen.c b/src/cmd/8c/sgen.c
index 069bbc1fc..d647010ef 100644
--- a/src/cmd/8c/sgen.c
+++ b/src/cmd/8c/sgen.c
@@ -35,7 +35,7 @@ gtext(Sym *s, int32 stkoff)
{
int32 a;
- a = argsize();
+ a = argsize(1);
if((textflag & NOSPLIT) != 0 && stkoff >= 128)
yyerror("stack frame too large for NOSPLIT function");
diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c
index ae36f84ea..d960519e3 100644
--- a/src/cmd/8c/swt.c
+++ b/src/cmd/8c/swt.c
@@ -255,10 +255,11 @@ align(int32 i, Type *t, int op, int32 *maxalign)
{
int32 o;
Type *v;
- int w;
+ int w, packw;
o = i;
w = 1;
+ packw = 0;
switch(op) {
default:
diag(Z, "unknown align opcode %d", op);
@@ -269,7 +270,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1)
w = 1;
if(packflg)
- w = packflg;
+ packw = packflg;
break;
case Ael1: /* initial align of struct element */
@@ -285,7 +286,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1 || w > SZ_LONG)
fatal(Z, "align");
if(packflg)
- w = packflg;
+ packw = packflg;
break;
case Ael2: /* width of a struct element */
@@ -320,6 +321,8 @@ align(int32 i, Type *t, int op, int32 *maxalign)
o = align(o, t, Ael2, nil);
break;
}
+ if(packw != 0 && xround(o, w) != xround(o, packw))
+ diag(Z, "#pragma pack changes offset of %T", t);
o = xround(o, w);
if(maxalign && *maxalign < w)
*maxalign = w;
diff --git a/src/cmd/8c/txt.c b/src/cmd/8c/txt.c
index 25082de05..7f87a0a0d 100644
--- a/src/cmd/8c/txt.c
+++ b/src/cmd/8c/txt.c
@@ -311,15 +311,43 @@ nodreg(Node *n, Node *nn, int r)
}
void
-regret(Node *n, Node *nn)
+regret(Node *n, Node *nn, Type *t, int mode)
{
int r;
- r = REGRET;
- if(typefd[nn->type->etype])
- r = FREGRET;
- nodreg(n, nn, r);
- reg[r]++;
+ if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
+ r = REGRET;
+ if(typefd[nn->type->etype])
+ r = FREGRET;
+ nodreg(n, nn, r);
+ reg[r]++;
+ return;
+ }
+
+ if(mode == 1) {
+ // fetch returned value after call.
+ // already called gargs, so curarg is set.
+ curarg = (curarg+3) & ~3;
+ regaalloc(n, nn);
+ return;
+ }
+
+ if(mode == 2) {
+ // store value to be returned.
+ // must compute arg offset.
+ if(t->etype != TFUNC)
+ fatal(Z, "bad regret func %T", t);
+ *n = *nn;
+ n->op = ONAME;
+ n->class = CPARAM;
+ n->sym = slookup(".retx");
+ n->complex = 0;
+ n->addable = 20;
+ n->xoffset = argsize(0);
+ return;
+ }
+
+ fatal(Z, "bad regret");
}
void
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index d626c2eb0..2735fb6a5 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -242,7 +242,6 @@ cgen(Node *n, Node *res)
case OOR:
case OXOR:
case OADD:
- case OADDPTR:
case OMUL:
a = optoas(n->op, nl->type);
if(a == AIMULB) {
@@ -347,8 +346,11 @@ cgen(Node *n, Node *res)
if(istype(nl->type, TCHAN)) {
// chan has cap in the second 32-bit word.
// a zero pointer means zero length
- regalloc(&n1, types[tptr], res);
+ tempname(&n1, types[tptr]);
cgen(nl, &n1);
+ regalloc(&n2, types[tptr], N);
+ gmove(&n1, &n2);
+ n1 = n2;
nodconst(&n2, types[tptr], 0);
gins(optoas(OCMP, types[tptr]), &n1, &n2);
@@ -1324,7 +1326,7 @@ sgen(Node *n, Node *res, int64 w)
p = gins(ADUFFCOPY, N, N);
p->to.type = D_ADDR;
p->to.sym = linksym(pkglookup("duffcopy", runtimepkg));
- // 10 and 128 = magic constants: see ../../pkg/runtime/asm_386.s
+ // 10 and 128 = magic constants: see ../../runtime/asm_386.s
p->to.offset = 10*(128-q);
} else
while(q > 0) {
@@ -1364,7 +1366,10 @@ int
componentgen(Node *nr, Node *nl)
{
Node nodl, nodr;
+ Type *t;
int freel, freer;
+ vlong fldcount;
+ vlong loffset, roffset;
freel = 0;
freer = 0;
@@ -1374,8 +1379,33 @@ componentgen(Node *nr, Node *nl)
goto no;
case TARRAY:
- if(!isslice(nl->type))
+ t = nl->type;
+
+ // Slices are ok.
+ if(isslice(t))
+ break;
+ // Small arrays are ok.
+ if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
+ break;
+
+ goto no;
+
+ case TSTRUCT:
+ // Small structs with non-fat types are ok.
+ // Zero-sized structs are treated separately elsewhere.
+ fldcount = 0;
+ for(t=nl->type->type; t; t=t->down) {
+ if(isfat(t->type))
+ goto no;
+ if(t->etype != TFIELD)
+ fatal("componentgen: not a TFIELD: %lT", t);
+ fldcount++;
+ }
+ if(fldcount == 0 || fldcount > 4)
goto no;
+
+ break;
+
case TSTRING:
case TINTER:
break;
@@ -1396,7 +1426,7 @@ componentgen(Node *nr, Node *nl)
freer = 1;
}
}
-
+
// nl and nr are 'cadable' which basically means they are names (variables) now.
// If they are the same variable, don't generate any code, because the
// VARDEF we generate will mark the old value as dead incorrectly.
@@ -1406,8 +1436,25 @@ componentgen(Node *nr, Node *nl)
switch(nl->type->etype) {
case TARRAY:
+ // componentgen for arrays.
if(nl->op == ONAME)
gvardef(nl);
+ t = nl->type;
+ if(!isslice(t)) {
+ nodl.type = t->type;
+ nodr.type = nodl.type;
+ for(fldcount=0; fldcount < t->bound; fldcount++) {
+ if(nr == N)
+ clearslim(&nodl);
+ else
+ gmove(&nodr, &nodl);
+ nodl.xoffset += t->type->width;
+ nodr.xoffset += t->type->width;
+ }
+ goto yes;
+ }
+
+ // componentgen for slices.
nodl.xoffset += Array_array;
nodl.type = ptrto(nl->type->type);
@@ -1419,7 +1466,7 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl);
nodl.xoffset += Array_nel-Array_array;
- nodl.type = types[TUINT32];
+ nodl.type = types[simtype[TUINT]];
if(nr != N) {
nodr.xoffset += Array_nel-Array_array;
@@ -1429,7 +1476,7 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl);
nodl.xoffset += Array_cap-Array_nel;
- nodl.type = types[TUINT32];
+ nodl.type = types[simtype[TUINT]];
if(nr != N) {
nodr.xoffset += Array_cap-Array_nel;
@@ -1454,7 +1501,7 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl);
nodl.xoffset += Array_nel-Array_array;
- nodl.type = types[TUINT32];
+ nodl.type = types[simtype[TUINT]];
if(nr != N) {
nodr.xoffset += Array_nel-Array_array;
@@ -1489,6 +1536,31 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl);
goto yes;
+
+ case TSTRUCT:
+ if(nl->op == ONAME)
+ gvardef(nl);
+ loffset = nodl.xoffset;
+ roffset = nodr.xoffset;
+ // funarg structs may not begin at offset zero.
+ if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type)
+ loffset -= nl->type->type->width;
+ if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type)
+ roffset -= nr->type->type->width;
+
+ for(t=nl->type->type; t; t=t->down) {
+ nodl.xoffset = loffset + t->width;
+ nodl.type = t->type;
+
+ if(nr == N)
+ clearslim(&nodl);
+ else {
+ nodr.xoffset = roffset + t->width;
+ nodr.type = nodl.type;
+ gmove(&nodr, &nodl);
+ }
+ }
+ goto yes;
}
no:
diff --git a/src/cmd/8g/galign.c b/src/cmd/8g/galign.c
index fbd2e9ad3..a0eb34937 100644
--- a/src/cmd/8g/galign.c
+++ b/src/cmd/8g/galign.c
@@ -23,10 +23,10 @@ vlong MAXWIDTH = (1LL<<32) - 1;
*/
Typedef typedefs[] =
{
- "int", TINT, TINT32,
- "uint", TUINT, TUINT32,
- "uintptr", TUINTPTR, TUINT32,
- 0
+ {"int", TINT, TINT32},
+ {"uint", TUINT, TUINT32},
+ {"uintptr", TUINTPTR, TUINT32},
+ {0}
};
void
diff --git a/src/cmd/8g/gg.h b/src/cmd/8g/gg.h
index bdefa93b5..238f92765 100644
--- a/src/cmd/8g/gg.h
+++ b/src/cmd/8g/gg.h
@@ -114,7 +114,6 @@ void split64(Node*, Node*, Node*);
void splitclean(void);
void nswap(Node*, Node*);
void gtrack(Sym*);
-void gargsize(int32);
/*
* cplx.c
*/
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 5e3140480..6333a60bb 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -157,7 +157,7 @@ void
clearfat(Node *nl)
{
uint32 w, c, q;
- Node n1;
+ Node n1, z;
Prog *p;
/* clear a fat object */
@@ -172,6 +172,32 @@ clearfat(Node *nl)
c = w % 4; // bytes
q = w / 4; // quads
+ if(q < 4) {
+ // Write sequence of MOV 0, off(base) instead of using STOSL.
+ // The hope is that although the code will be slightly longer,
+ // the MOVs will have no dependencies and pipeline better
+ // than the unrolled STOSL loop.
+ // NOTE: Must use agen, not igen, so that optimizer sees address
+ // being taken. We are not writing on field boundaries.
+ regalloc(&n1, types[tptr], N);
+ agen(nl, &n1);
+ n1.op = OINDREG;
+ nodconst(&z, types[TUINT64], 0);
+ while(q-- > 0) {
+ n1.type = z.type;
+ gins(AMOVL, &z, &n1);
+ n1.xoffset += 4;
+ }
+ nodconst(&z, types[TUINT8], 0);
+ while(c-- > 0) {
+ n1.type = z.type;
+ gins(AMOVB, &z, &n1);
+ n1.xoffset++;
+ }
+ regfree(&n1);
+ return;
+ }
+
nodreg(&n1, types[tptr], D_DI);
agen(nl, &n1);
gconreg(AMOVL, 0, D_AX);
@@ -184,7 +210,7 @@ clearfat(Node *nl)
p = gins(ADUFFZERO, N, N);
p->to.type = D_ADDR;
p->to.sym = linksym(pkglookup("duffzero", runtimepkg));
- // 1 and 128 = magic constants: see ../../pkg/runtime/asm_386.s
+ // 1 and 128 = magic constants: see ../../runtime/asm_386.s
p->to.offset = 1*(128-q);
} else
while(q > 0) {
@@ -210,28 +236,12 @@ clearfat(Node *nl)
void
ginscall(Node *f, int proc)
{
- int32 arg;
Prog *p;
Node reg, r1, con;
if(f->type != T)
setmaxarg(f->type);
- arg = -1;
- // Most functions have a fixed-size argument block, so traceback uses that during unwind.
- // Not all, though: there are some variadic functions in package runtime,
- // and for those we emit call-specific metadata recorded by caller.
- // Reflect generates functions with variable argsize (see reflect.methodValueCall/makeFuncStub),
- // so we do this for all indirect calls as well.
- if(f->type != T && (f->sym == S || (f->sym != S && f->sym->pkg == runtimepkg) || proc == 1 || proc == 2)) {
- arg = f->type->argwid;
- if(proc == 1 || proc == 2)
- arg += 2*widthptr;
- }
-
- if(arg != -1)
- gargsize(arg);
-
switch(proc) {
default:
fatal("ginscall: bad proc %d", proc);
@@ -293,9 +303,6 @@ ginscall(Node *f, int proc)
}
break;
}
-
- if(arg != -1)
- gargsize(-1);
}
/*
diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c
index 2f3cb28c8..3077e0ad9 100644
--- a/src/cmd/8g/gsubr.c
+++ b/src/cmd/8g/gsubr.c
@@ -31,14 +31,15 @@
#include <u.h>
#include <libc.h>
#include "gg.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
// TODO(rsc): Can make this bigger if we move
// the text segment up higher in 8l for all GOOS.
-// At the same time, can raise StackBig in ../../pkg/runtime/stack.h.
+// At the same time, can raise StackBig in ../../runtime/stack.h.
uint32 unmappedzero = 4096;
#define CASE(a,b) (((a)<<16)|((b)<<0))
+/*c2go int CASE(int, int);*/
void
clearp(Prog *p)
@@ -205,17 +206,7 @@ ggloblnod(Node *nam)
}
void
-gargsize(int32 size)
-{
- Node n1, n2;
-
- nodconst(&n1, types[TINT32], PCDATA_ArgSize);
- nodconst(&n2, types[TINT32], size);
- gins(APCDATA, &n1, &n2);
-}
-
-void
-ggloblsym(Sym *s, int32 width, int dupok, int rodata)
+ggloblsym(Sym *s, int32 width, int8 flags)
{
Prog *p;
@@ -226,10 +217,7 @@ ggloblsym(Sym *s, int32 width, int dupok, int rodata)
p->to.type = D_CONST;
p->to.index = D_NONE;
p->to.offset = width;
- if(dupok)
- p->from.scale |= DUPOK;
- if(rodata)
- p->from.scale |= RODATA;
+ p->from.scale = flags;
}
void
@@ -432,7 +420,6 @@ optoas(int op, Type *t)
case CASE(OADD, TINT32):
case CASE(OADD, TUINT32):
case CASE(OADD, TPTR32):
- case CASE(OADDPTR, TPTR32):
a = AADDL;
break;
@@ -697,6 +684,7 @@ optoas(int op, Type *t)
}
#define FCASE(a, b, c) (((a)<<16)|((b)<<8)|(c))
+/*c2go int FCASE(int, int, int); */
int
foptoas(int op, Type *t, int flg)
{
@@ -950,7 +938,7 @@ regalloc(Node *n, Type *t, Node *o)
fprint(2, "registers allocated at\n");
for(i=D_AX; i<=D_DI; i++)
fprint(2, "\t%R\t%#lux\n", i, regpc[i]);
- yyerror("out of fixed registers");
+ fatal("out of fixed registers");
goto err;
case TFLOAT32:
diff --git a/src/cmd/8g/opt.h b/src/cmd/8g/opt.h
index 77a69e13a..09f58c40a 100644
--- a/src/cmd/8g/opt.h
+++ b/src/cmd/8g/opt.h
@@ -49,6 +49,24 @@
typedef struct Reg Reg;
typedef struct Rgn Rgn;
+/*c2go
+extern Node *Z;
+enum
+{
+ D_HI = D_NONE,
+ D_LO = D_NONE,
+ CLOAD = 5,
+ CREF = 5,
+ CINF = 1000,
+ LOOP = 3,
+};
+
+uint32 BLOAD(Reg*);
+uint32 BSTORE(Reg*);
+uint32 LOAD(Reg*);
+uint32 STORE(Reg*);
+*/
+
// A Reg is a wrapper around a single Prog (one instruction) that holds
// register optimization information while the optimizer runs.
// r->prog is the instruction.
@@ -84,8 +102,10 @@ struct Reg
Prog* prog; // actual instruction
};
#define R ((Reg*)0)
+/*c2go extern Reg *R; */
#define NRGN 600
+/*c2go enum { NRGN = 600 }; */
struct Rgn
{
Reg* enter;
diff --git a/src/cmd/8g/peep.c b/src/cmd/8g/peep.c
index e2f3a003d..91a91d20d 100644
--- a/src/cmd/8g/peep.c
+++ b/src/cmd/8g/peep.c
@@ -33,7 +33,9 @@
#include "gg.h"
#include "opt.h"
-#define REGEXT 0
+enum {
+ REGEXT = 0,
+};
static void conprop(Flow *r);
static void elimshortmov(Graph*);
diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c
index fd610f87a..302b273a1 100644
--- a/src/cmd/8g/reg.c
+++ b/src/cmd/8g/reg.c
@@ -35,6 +35,11 @@
#define NREGVAR 16 /* 8 integer + 8 floating */
#define REGBITS ((uint32)0xffff)
+/*c2go enum {
+ NREGVAR = 16,
+ REGBITS = (1<<NREGVAR) - 1,
+};
+*/
static Reg* firstr;
static int first = 1;
@@ -1163,6 +1168,7 @@ void
addreg(Adr *a, int rn)
{
a->sym = nil;
+ a->node = nil;
a->offset = 0;
a->type = rn;
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h
index 8e642d390..ed54f6744 100644
--- a/src/cmd/8l/8.out.h
+++ b/src/cmd/8l/8.out.h
@@ -32,7 +32,7 @@
#define NSNAME 8
#include "../ld/textflag.h"
-enum as
+enum
{
AXXX,
AAAA,
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index c135dce70..98c042403 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -117,13 +117,21 @@ adddynrel(LSym *s, Reloc *r)
case 256 + R_386_GOT32:
if(targ->type != SDYNIMPORT) {
// have symbol
- // turn MOVL of GOT entry into LEAL of symbol itself
- if(r->off < 2 || s->p[r->off-2] != 0x8b) {
- diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
+ if(r->off >= 2 && s->p[r->off-2] == 0x8b) {
+ // turn MOVL of GOT entry into LEAL of symbol address, relative to GOT.
+ s->p[r->off-2] = 0x8d;
+ r->type = R_GOTOFF;
return;
}
- s->p[r->off-2] = 0x8d;
- r->type = R_GOTOFF;
+ if(r->off >= 2 && s->p[r->off-2] == 0xff && s->p[r->off-1] == 0xb3) {
+ // turn PUSHL of GOT entry into PUSHL of symbol itself.
+ // use unnecessary SS prefix to keep instruction same length.
+ s->p[r->off-2] = 0x36;
+ s->p[r->off-1] = 0x68;
+ r->type = R_ADDR;
+ return;
+ }
+ diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
return;
}
addgotsym(ctxt, targ);
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index c9695ade0..70d3a4bb4 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -50,15 +50,10 @@ enum
#define P ((Prog*)0)
#define S ((LSym*)0)
-#define TNAME (ctxt->cursym?ctxt->cursym->name:noname)
enum
{
- MINSIZ = 4,
- STRINGSZ = 200,
MINLC = 1,
- MAXIO = 8192,
- MAXHIST = 40, /* limit of path elements for history symbols */
};
#pragma varargck type "I" uchar*
@@ -72,7 +67,6 @@ EXTERN char* rpath;
EXTERN int32 spsize;
EXTERN LSym* symlist;
EXTERN int32 symsize;
-EXTERN int32 textsize;
int Iconv(Fmt *fp);
void adddynlib(char *lib);
@@ -85,7 +79,6 @@ int elfreloc1(Reloc *r, vlong sectoff);
void elfsetupplt(void);
void listinit(void);
int machoreloc1(Reloc *r, vlong sectoff);
-void main(int argc, char *argv[]);
int32 rnd(int32 v, int32 r);
void s8put(char *n);
char* xsymname(LSym *s);
diff --git a/src/cmd/8l/mkenam b/src/cmd/8l/mkenam
deleted file mode 100644
index 992aa3160..000000000
--- a/src/cmd/8l/mkenam
+++ /dev/null
@@ -1,45 +0,0 @@
-# Inferno utils/8c/mkenam
-# http://code.google.com/p/inferno-os/source/browse/utils/8c/mkenam
-#
-# Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-# Portions Copyright © 1995-1997 C H Forsyth (forsyth@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@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.
-
-awk '
-BEGIN {
- print "char* anames[] ="
- print "{"
-}
-
-/^ A/ {
- name=$1
- sub(/,/, "", name)
- sub(/^A/, "", name)
- print "\t\"" name "\","
-}
-
-END { print "};" }
-' ../8l/8.out.h >enam.c
diff --git a/src/cmd/addr2line/addr2line_test.go b/src/cmd/addr2line/addr2line_test.go
index b278d08ce..10d1dc922 100644
--- a/src/cmd/addr2line/addr2line_test.go
+++ b/src/cmd/addr2line/addr2line_test.go
@@ -92,8 +92,9 @@ func testAddr2Line(t *testing.T, exepath, addr string) {
// This is line 93. The test depends on that.
func TestAddr2Line(t *testing.T) {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
+ switch runtime.GOOS {
+ case "nacl", "android":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
syms := loadSyms(t)
diff --git a/src/cmd/addr2line/main.go b/src/cmd/addr2line/main.go
index b94ba12ef..267f4170a 100644
--- a/src/cmd/addr2line/main.go
+++ b/src/cmd/addr2line/main.go
@@ -19,17 +19,14 @@ package main
import (
"bufio"
- "debug/elf"
- "debug/gosym"
- "debug/macho"
- "debug/pe"
- "debug/plan9obj"
"flag"
"fmt"
"log"
"os"
"strconv"
"strings"
+
+ "cmd/internal/objfile"
)
func printUsage(w *os.File) {
@@ -60,18 +57,12 @@ func main() {
usage()
}
- f, err := os.Open(flag.Arg(0))
+ f, err := objfile.Open(flag.Arg(0))
if err != nil {
log.Fatal(err)
}
- textStart, symtab, pclntab, err := loadTables(f)
- if err != nil {
- log.Fatalf("reading %s: %v", flag.Arg(0), err)
- }
-
- pcln := gosym.NewLineTable(pclntab, textStart)
- tab, err := gosym.NewTable(symtab, pcln)
+ tab, err := f.PCLineTable()
if err != nil {
log.Fatalf("reading %s: %v", flag.Arg(0), err)
}
@@ -102,152 +93,3 @@ func main() {
}
stdout.Flush()
}
-
-func loadTables(f *os.File) (textStart uint64, symtab, pclntab []byte, err error) {
- if obj, err := elf.NewFile(f); err == nil {
- if sect := obj.Section(".text"); sect != nil {
- textStart = sect.Addr
- }
- if sect := obj.Section(".gosymtab"); sect != nil {
- if symtab, err = sect.Data(); err != nil {
- return 0, nil, nil, err
- }
- }
- if sect := obj.Section(".gopclntab"); sect != nil {
- if pclntab, err = sect.Data(); err != nil {
- return 0, nil, nil, err
- }
- }
- return textStart, symtab, pclntab, nil
- }
-
- if obj, err := macho.NewFile(f); err == nil {
- if sect := obj.Section("__text"); sect != nil {
- textStart = sect.Addr
- }
- if sect := obj.Section("__gosymtab"); sect != nil {
- if symtab, err = sect.Data(); err != nil {
- return 0, nil, nil, err
- }
- }
- if sect := obj.Section("__gopclntab"); sect != nil {
- if pclntab, err = sect.Data(); err != nil {
- return 0, nil, nil, err
- }
- }
- return textStart, symtab, pclntab, nil
- }
-
- if obj, err := pe.NewFile(f); err == nil {
- var imageBase uint64
- switch oh := obj.OptionalHeader.(type) {
- case *pe.OptionalHeader32:
- imageBase = uint64(oh.ImageBase)
- case *pe.OptionalHeader64:
- imageBase = oh.ImageBase
- default:
- return 0, nil, nil, fmt.Errorf("pe file format not recognized")
- }
- if sect := obj.Section(".text"); sect != nil {
- textStart = imageBase + uint64(sect.VirtualAddress)
- }
- if pclntab, err = loadPETable(obj, "pclntab", "epclntab"); err != nil {
- return 0, nil, nil, err
- }
- if symtab, err = loadPETable(obj, "symtab", "esymtab"); err != nil {
- return 0, nil, nil, err
- }
- return textStart, symtab, pclntab, nil
- }
-
- if obj, err := plan9obj.NewFile(f); err == nil {
- sym, err := findPlan9Symbol(obj, "text")
- if err != nil {
- return 0, nil, nil, err
- }
- textStart = sym.Value
- if pclntab, err = loadPlan9Table(obj, "pclntab", "epclntab"); err != nil {
- return 0, nil, nil, err
- }
- if symtab, err = loadPlan9Table(obj, "symtab", "esymtab"); err != nil {
- return 0, nil, nil, err
- }
- return textStart, symtab, pclntab, nil
- }
-
- return 0, nil, nil, fmt.Errorf("unrecognized binary format")
-}
-
-func findPESymbol(f *pe.File, name string) (*pe.Symbol, error) {
- for _, s := range f.Symbols {
- if s.Name != name {
- continue
- }
- if s.SectionNumber <= 0 {
- return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber)
- }
- if len(f.Sections) < int(s.SectionNumber) {
- return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections))
- }
- return s, nil
- }
- return nil, fmt.Errorf("no %s symbol found", name)
-}
-
-func loadPETable(f *pe.File, sname, ename string) ([]byte, error) {
- ssym, err := findPESymbol(f, sname)
- if err != nil {
- return nil, err
- }
- esym, err := findPESymbol(f, ename)
- if err != nil {
- return nil, err
- }
- if ssym.SectionNumber != esym.SectionNumber {
- return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename)
- }
- sect := f.Sections[ssym.SectionNumber-1]
- data, err := sect.Data()
- if err != nil {
- return nil, err
- }
- return data[ssym.Value:esym.Value], nil
-}
-
-func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) {
- syms, err := f.Symbols()
- if err != nil {
- return nil, err
- }
- for _, s := range syms {
- if s.Name != name {
- continue
- }
- return &s, nil
- }
- return nil, fmt.Errorf("no %s symbol found", name)
-}
-
-func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) {
- ssym, err := findPlan9Symbol(f, sname)
- if err != nil {
- return nil, err
- }
- esym, err := findPlan9Symbol(f, ename)
- if err != nil {
- return nil, err
- }
- text, err := findPlan9Symbol(f, "text")
- if err != nil {
- return nil, err
- }
- sect := f.Section("text")
- if sect == nil {
- return nil, err
- }
- data, err := sect.Data()
- if err != nil {
- return nil, err
- }
- return data[ssym.Value-text.Value : esym.Value-text.Value], nil
-}
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index 4bde794a1..4a63eac71 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -107,6 +107,8 @@ func setContexts() {
}
}
+var internalPkg = regexp.MustCompile(`(^|/)internal($|/)`)
+
func main() {
flag.Parse()
@@ -132,12 +134,16 @@ func main() {
if err != nil {
log.Fatal(err)
}
- pkgNames = strings.Fields(string(stds))
+ for _, pkg := range strings.Fields(string(stds)) {
+ if !internalPkg.MatchString(pkg) {
+ pkgNames = append(pkgNames, pkg)
+ }
+ }
}
var featureCtx = make(map[string]map[string]bool) // feature -> context name -> true
for _, context := range contexts {
- w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src/pkg"))
+ w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src"))
for _, name := range pkgNames {
// - Package "unsafe" contains special signatures requiring
@@ -277,7 +283,7 @@ func compareAPI(w io.Writer, features, required, optional, exception []string) (
delete(optionalSet, newFeature)
} else {
fmt.Fprintf(w, "+%s\n", newFeature)
- if !*allowNew {
+ if !*allowNew || !strings.Contains(runtime.Version(), "devel") {
ok = false // we're in lock-down mode for next release
}
}
@@ -307,11 +313,15 @@ func fileFeatures(filename string) []string {
if err != nil {
log.Fatalf("Error reading file %s: %v", filename, err)
}
- text := strings.TrimSpace(string(bs))
- if text == "" {
- return nil
+ lines := strings.Split(string(bs), "\n")
+ var nonblank []string
+ for _, line := range lines {
+ line = strings.TrimSpace(line)
+ if line != "" && !strings.HasPrefix(line, "#") {
+ nonblank = append(nonblank, line)
+ }
}
- return strings.Split(text, "\n")
+ return nonblank
}
var fset = token.NewFileSet()
@@ -370,6 +380,106 @@ func (w *Walker) parseFile(dir, file string) (*ast.File, error) {
log.Fatalf("incorrect generated file: %s", err)
}
}
+ if w.context != nil && file == fmt.Sprintf("zruntime_defs_%s_%s.go", w.context.GOOS, w.context.GOARCH) {
+ // Just enough to keep the api checker happy. Keep sorted.
+ src := "package runtime; type (" +
+ " _defer struct{};" +
+ " _func struct{};" +
+ " _panic struct{};" +
+ " _select struct{}; " +
+ " _type struct{};" +
+ " alg struct{};" +
+ " chantype struct{};" +
+ " context struct{};" + // windows
+ " eface struct{};" +
+ " epollevent struct{};" +
+ " funcval struct{};" +
+ " g struct{};" +
+ " gobuf struct{};" +
+ " hchan struct{};" +
+ " iface struct{};" +
+ " interfacetype struct{};" +
+ " itab struct{};" +
+ " keventt struct{};" +
+ " m struct{};" +
+ " maptype struct{};" +
+ " mcache struct{};" +
+ " mspan struct{};" +
+ " mutex struct{};" +
+ " note struct{};" +
+ " p struct{};" +
+ " parfor struct{};" +
+ " slicetype struct{};" +
+ " stkframe struct{};" +
+ " sudog struct{};" +
+ " timespec struct{};" +
+ " waitq struct{};" +
+ " wincallbackcontext struct{};" +
+ "); " +
+ "const (" +
+ " cb_max = 2000;" +
+ " _CacheLineSize = 64;" +
+ " _Gidle = 1;" +
+ " _Grunnable = 2;" +
+ " _Grunning = 3;" +
+ " _Gsyscall = 4;" +
+ " _Gwaiting = 5;" +
+ " _Gdead = 6;" +
+ " _Genqueue = 7;" +
+ " _Gcopystack = 8;" +
+ " _NSIG = 32;" +
+ " _FlagNoScan = iota;" +
+ " _FlagNoZero;" +
+ " _TinySize;" +
+ " _TinySizeClass;" +
+ " _MaxSmallSize;" +
+ " _PageShift;" +
+ " _PageSize;" +
+ " _PageMask;" +
+ " _BitsPerPointer;" +
+ " _BitsMask;" +
+ " _PointersPerByte;" +
+ " _MaxGCMask;" +
+ " _BitsDead;" +
+ " _BitsPointer;" +
+ " _MSpanInUse;" +
+ " _ConcurrentSweep;" +
+ " _KindBool;" +
+ " _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;" +
+ " _KindGCProg;" +
+ " _KindNoPointers;" +
+ " _KindMask;" +
+ ")"
+ f, err = parser.ParseFile(fset, filename, src, 0)
+ if err != nil {
+ log.Fatalf("incorrect generated file: %s", err)
+ }
+ }
if f == nil {
f, err = parser.ParseFile(fset, filename, nil, 0)
@@ -391,6 +501,11 @@ func contains(list []string, s string) bool {
return false
}
+// The package cache doesn't operate correctly in rare (so far artificial)
+// circumstances (issue 8425). Disable before debugging non-obvious errors
+// from the type-checker.
+const usePkgCache = true
+
var (
pkgCache = map[string]*types.Package{} // map tagKey to package
pkgTags = map[string][]string{} // map import dir to list of relevant tags
@@ -452,11 +567,13 @@ func (w *Walker) Import(name string) (pkg *types.Package) {
// If we've already done an import with the same set
// of relevant tags, reuse the result.
var key string
- if tags, ok := pkgTags[dir]; ok {
- key = tagKey(dir, context, tags)
- if pkg := pkgCache[key]; pkg != nil {
- w.imported[name] = pkg
- return pkg
+ if usePkgCache {
+ if tags, ok := pkgTags[dir]; ok {
+ key = tagKey(dir, context, tags)
+ if pkg := pkgCache[key]; pkg != nil {
+ w.imported[name] = pkg
+ return pkg
+ }
}
}
@@ -469,9 +586,11 @@ func (w *Walker) Import(name string) (pkg *types.Package) {
}
// Save tags list first time we see a directory.
- if _, ok := pkgTags[dir]; !ok {
- pkgTags[dir] = info.AllTags
- key = tagKey(dir, context, info.AllTags)
+ if usePkgCache {
+ if _, ok := pkgTags[dir]; !ok {
+ pkgTags[dir] = info.AllTags
+ key = tagKey(dir, context, info.AllTags)
+ }
}
filenames := append(append([]string{}, info.GoFiles...), info.CgoFiles...)
@@ -488,6 +607,11 @@ func (w *Walker) Import(name string) (pkg *types.Package) {
if !contains(filenames, n) {
filenames = append(filenames, n)
}
+
+ n = fmt.Sprintf("zruntime_defs_%s_%s.go", w.context.GOOS, w.context.GOARCH)
+ if !contains(filenames, n) {
+ filenames = append(filenames, n)
+ }
}
// Parse package files.
@@ -519,7 +643,9 @@ func (w *Walker) Import(name string) (pkg *types.Package) {
log.Fatalf("error typechecking package %s: %s (%s)", name, err, ctxt)
}
- pkgCache[key] = pkg
+ if usePkgCache {
+ pkgCache[key] = pkg
+ }
w.imported[name] = pkg
return
diff --git a/src/cmd/api/goapi_test.go b/src/cmd/api/goapi_test.go
index b909c32b3..f4fb7d319 100644
--- a/src/cmd/api/goapi_test.go
+++ b/src/cmd/api/goapi_test.go
@@ -38,7 +38,7 @@ func TestGolden(t *testing.T) {
continue
}
- goldenFile := filepath.Join("testdata", "src", "pkg", fi.Name(), "golden.txt")
+ goldenFile := filepath.Join("testdata", "src", fi.Name(), "golden.txt")
w := NewWalker(nil, "testdata/src/pkg")
w.export(w.Import(fi.Name()))
@@ -142,6 +142,26 @@ func TestCompareAPI(t *testing.T) {
}
}
+func TestSkipInternal(t *testing.T) {
+ tests := []struct {
+ pkg string
+ want bool
+ }{
+ {"net/http", true},
+ {"net/http/internal-foo", true},
+ {"net/http/internal", false},
+ {"net/http/internal/bar", false},
+ {"internal/foo", false},
+ {"internal", false},
+ }
+ for _, tt := range tests {
+ got := !internalPkg.MatchString(tt.pkg)
+ if got != tt.want {
+ t.Errorf("%s is internal = %v; want %v", tt.pkg, got, tt.want)
+ }
+ }
+}
+
func BenchmarkAll(b *testing.B) {
stds, err := exec.Command("go", "list", "std").Output()
if err != nil {
@@ -156,7 +176,7 @@ func BenchmarkAll(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, context := range contexts {
- w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src/pkg"))
+ w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src"))
for _, name := range pkgNames {
if name != "unsafe" && !strings.HasPrefix(name, "cmd/") {
w.export(w.Import(name))
diff --git a/src/cmd/api/run.go b/src/cmd/api/run.go
index 896b2b4a1..ed5613edd 100644
--- a/src/cmd/api/run.go
+++ b/src/cmd/api/run.go
@@ -21,6 +21,7 @@ import (
"os/exec"
"os/user"
"path/filepath"
+ "runtime"
"strings"
)
@@ -53,7 +54,7 @@ func main() {
}
out, err = exec.Command("go", "tool", "api",
- "-c", file("go1", "go1.1", "go1.2", "go1.3"),
+ "-c", file("go1", "go1.1", "go1.2", "go1.3", "go1.4"),
"-next", file("next"),
"-except", file("except")).CombinedOutput()
if err != nil {
@@ -98,16 +99,14 @@ func prepGoPath() string {
if err == nil {
username = u.Username
} else {
- // Only need to handle Unix here, as Windows's os/user uses
- // native syscall and should work fine without cgo.
username = os.Getenv("USER")
if username == "" {
- log.Fatalf("Error getting current user: %v", err)
+ username = "nobody"
}
}
// The GOPATH we'll return
- gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(username), goToolsVersion)
+ gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(username)+"-"+cleanUsername(strings.Fields(runtime.Version())[0]), goToolsVersion)
// cloneDir is where we run "hg clone".
cloneDir := filepath.Join(gopath, "src", "code.google.com", "p")
diff --git a/src/cmd/cc/bv.c b/src/cmd/cc/bv.c
deleted file mode 100644
index 51b7f4076..000000000
--- a/src/cmd/cc/bv.c
+++ /dev/null
@@ -1,45 +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 <u.h>
-#include "cc.h"
-
-enum {
- WORDSIZE = sizeof(uint32),
- WORDBITS = 32,
-};
-
-uintptr
-bvsize(uintptr n)
-{
- return ((n + WORDBITS - 1) / WORDBITS) * WORDSIZE;
-}
-
-Bvec*
-bvalloc(int32 n)
-{
- Bvec *bv;
- uintptr nbytes;
-
- if(n < 0)
- fatal(Z, "bvalloc: initial size is negative\n");
- nbytes = sizeof(Bvec) + bvsize(n);
- bv = malloc(nbytes);
- if(bv == nil)
- fatal(Z, "bvalloc: malloc failed\n");
- memset(bv, 0, nbytes);
- bv->n = n;
- return bv;
-}
-
-void
-bvset(Bvec *bv, int32 i)
-{
- uint32 mask;
-
- if(i < 0 || i >= bv->n)
- fatal(Z, "bvset: index %d is out of bounds with length %d\n", i, bv->n);
- mask = 1 << (i % WORDBITS);
- bv->b[i / WORDBITS] |= mask;
-}
diff --git a/src/cmd/cc/cc.h b/src/cmd/cc/cc.h
index c8aac1253..9530f5cf6 100644
--- a/src/cmd/cc/cc.h
+++ b/src/cmd/cc/cc.h
@@ -762,12 +762,6 @@ int beq(Bits, Bits);
int bset(Bits, uint);
/*
- * bv.c
- */
-Bvec* bvalloc(int32 n);
-void bvset(Bvec *bv, int32 i);
-
-/*
* dpchk.c
*/
void dpcheck(Node*);
@@ -794,7 +788,7 @@ void xcom(Node*);
int32 exreg(Type*);
int32 align(int32, Type*, int, int32*);
int32 maxround(int32, int32);
-int hasdotdotdot(void);
+int hasdotdotdot(Type*);
void linkarchinit(void);
extern schar ewidth[];
diff --git a/src/cmd/cc/cc.y b/src/cmd/cc/cc.y
index 11ee444b7..8d7cb1472 100644
--- a/src/cmd/cc/cc.y
+++ b/src/cmd/cc/cc.y
@@ -1043,6 +1043,7 @@ complex:
}
| LSTRUCT sbody
{
+ diag(Z, "struct must have tag");
taggen++;
sprint(symb, "_%d_", taggen);
$$ = dotag(lookup(), TSTRUCT, autobn);
diff --git a/src/cmd/cc/dcl.c b/src/cmd/cc/dcl.c
index a7a942686..117508fd6 100644
--- a/src/cmd/cc/dcl.c
+++ b/src/cmd/cc/dcl.c
@@ -30,6 +30,9 @@
#include <u.h>
#include "cc.h"
+#include "../ld/textflag.h"
+
+static int haspointers(Type*);
Node*
dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n)
@@ -123,7 +126,8 @@ loop:
if(dataflag) {
s->dataflag = dataflag;
dataflag = 0;
- }
+ } else if(s->type != T && !haspointers(s->type))
+ s->dataflag = NOPTR;
firstbit = 0;
n->sym = s;
n->type = s->type;
@@ -568,9 +572,8 @@ haspointers(Type *t)
return 0;
case TARRAY:
return haspointers(t->link);
- case TFUNC:
case TIND:
- return 1;
+ return t->link->etype != TFUNC;
default:
return 0;
}
@@ -697,7 +700,8 @@ argmark(Node *n, int pass)
{
Type *t;
- autoffset = align(0, thisfn->link, Aarg0, nil);
+ if(hasdotdotdot(thisfn->link))
+ autoffset = align(0, thisfn->link, Aarg0, nil);
stkoff = 0;
for(; n->left != Z; n = n->left) {
if(n->op != OFUNC || n->left->op != ONAME)
@@ -1401,6 +1405,10 @@ xdecl(int c, Type *t, Sym *s)
}
tmerge(t, s);
s->type = t;
+ if(c == CTYPEDEF && (typechlv[t->etype] || typefd[t->etype])) {
+ s->type = copytyp(t);
+ s->type->tag = s;
+ }
s->class = c;
s->block = 0;
s->offset = o;
@@ -1481,12 +1489,9 @@ edecl(int c, Type *t, Sym *s)
{
Type *t1;
- if(s == S) {
- if(!typesu[t->etype])
- diag(Z, "unnamed structure element must be struct/union");
- if(c != CXXX)
- diag(Z, "unnamed structure element cannot have class");
- } else
+ if(s == S)
+ diag(Z, "unnamed structure elements not supported");
+ else
if(c != CXXX)
diag(Z, "structure element cannot have class: %s", s->name);
t1 = t;
diff --git a/src/cmd/cc/godefs.c b/src/cmd/cc/godefs.c
index 7457bd000..d9f67f0ae 100644
--- a/src/cmd/cc/godefs.c
+++ b/src/cmd/cc/godefs.c
@@ -154,7 +154,6 @@ static void
printtypename(Type *t)
{
Sym *s;
- Type *t1;
int w;
char *n;
@@ -188,40 +187,27 @@ printtypename(Type *t)
switch(t->etype) {
case TINT:
- Bprint(&outbuf, "int32");
- break;
case TUINT:
- Bprint(&outbuf, "uint32");
- break;
case TCHAR:
- Bprint(&outbuf, "int8");
- break;
case TUCHAR:
- Bprint(&outbuf, "uint8");
- break;
case TSHORT:
- Bprint(&outbuf, "int16");
- break;
case TUSHORT:
- Bprint(&outbuf, "uint16");
- break;
case TLONG:
- Bprint(&outbuf, "int32");
- break;
case TULONG:
- Bprint(&outbuf, "uint32");
- break;
case TVLONG:
- Bprint(&outbuf, "int64");
- break;
case TUVLONG:
- Bprint(&outbuf, "uint64");
- break;
case TFLOAT:
- Bprint(&outbuf, "float32");
- break;
case TDOUBLE:
- Bprint(&outbuf, "float64");
+ // All names used in the runtime code should be typedefs.
+ if(t->tag != nil) {
+ if(strcmp(t->tag->name, "intgo") == 0)
+ Bprint(&outbuf, "int");
+ else if(strcmp(t->tag->name, "uintgo") == 0)
+ Bprint(&outbuf, "uint");
+ else
+ Bprint(&outbuf, "%s", t->tag->name);
+ } else
+ Bprint(&outbuf, "C.%T", t);
break;
case TUNION:
case TSTRUCT:
@@ -231,27 +217,18 @@ printtypename(Type *t)
n = s->name;
else if(t->tag)
n = t->tag->name;
- if(strcmp(n, "String") == 0){
+ if(strcmp(n, "String") == 0)
Bprint(&outbuf, "string");
- } else if(strcmp(n, "Slice") == 0){
+ else if(strcmp(n, "Slice") == 0)
Bprint(&outbuf, "[]byte");
- } else
+ else if(strcmp(n, "Eface") == 0)
+ Bprint(&outbuf, "interface{}");
+ else
Bprint(&outbuf, "%U", n);
break;
case TFUNC:
- Bprint(&outbuf, "func(");
- for(t1 = t->down; t1 != T; t1 = t1->down) {
- if(t1->etype == TVOID)
- break;
- if(t1 != t->down)
- Bprint(&outbuf, ", ");
- printtypename(t1);
- }
- Bprint(&outbuf, ")");
- if(t->link && t->link->etype != TVOID) {
- Bprint(&outbuf, " ");
- printtypename(t->link);
- }
+ // There's no equivalent to a C function in the Go world.
+ Bprint(&outbuf, "unsafe.Pointer");
break;
case TDOT:
Bprint(&outbuf, "...interface{}");
@@ -340,9 +317,9 @@ godefvar(Sym *s)
switch(t->etype) {
case TENUM:
if(!typefd[t->etype])
- Bprint(&outbuf, "const %U = %lld\n", s->name, s->vconst);
+ Bprint(&outbuf, "const %s = %lld\n", s->name, s->vconst);
else
- Bprint(&outbuf, "const %U = %f\n;", s->name, s->fconst);
+ Bprint(&outbuf, "const %s = %f\n;", s->name, s->fconst);
break;
case TFUNC:
@@ -376,8 +353,10 @@ godefvar(Sym *s)
case CSTATIC:
case CEXTERN:
case CGLOBL:
- if(strchr(s->name, '$') != nil) // TODO(lvd)
- break;
+ if(strchr(s->name, '$') != nil)
+ break;
+ if(strncmp(s->name, "go.weak.", 8) == 0)
+ break;
Bprint(&outbuf, "var %U\t", s->name);
printtypename(t);
Bprint(&outbuf, "\n");
diff --git a/src/cmd/cc/lex.c b/src/cmd/cc/lex.c
index 424843764..7c9f718c0 100644
--- a/src/cmd/cc/lex.c
+++ b/src/cmd/cc/lex.c
@@ -31,6 +31,7 @@
#include <u.h>
#include "cc.h"
#include "y.tab.h"
+#include "../ld/textflag.h"
#ifndef CPP
#define CPP "cpp"
@@ -203,6 +204,7 @@ main(int argc, char *argv[])
flagparse(&argc, &argv, usage);
ctxt->debugasm = debug['S'];
+ ctxt->debugvlog = debug['v'];
if(argc < 1 && outfile == 0)
usage();
@@ -1316,6 +1318,7 @@ cinit(void)
t->width = 0;
symstring = slookup(".string");
symstring->class = CSTATIC;
+ symstring->dataflag = NOPTR;
symstring->type = t;
t = typ(TARRAY, types[TCHAR]);
diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c
index 10bebc196..db9aae916 100644
--- a/src/cmd/cc/pgen.c
+++ b/src/cmd/cc/pgen.c
@@ -29,51 +29,27 @@
// THE SOFTWARE.
#include "gc.h"
-#include "../../pkg/runtime/funcdata.h"
-
-enum { BitsPerPointer = 2 };
-
-static void dumpgcargs(Type *fn, Sym *sym);
-
-static Sym*
-makefuncdatasym(char *namefmt, int64 funcdatakind)
-{
- Node nod;
- Sym *sym;
- static int32 nsym;
- static char namebuf[40];
-
- snprint(namebuf, sizeof(namebuf), namefmt, nsym++);
- sym = slookup(namebuf);
- sym->class = CSTATIC;
- memset(&nod, 0, sizeof nod);
- nod.op = ONAME;
- nod.sym = sym;
- nod.class = CSTATIC;
- gins(AFUNCDATA, nodconst(funcdatakind), &nod);
- linksym(sym)->type = SRODATA;
- return sym;
-}
+#include "../../runtime/funcdata.h"
int
-hasdotdotdot(void)
+hasdotdotdot(Type *t)
{
- Type *t;
-
- for(t=thisfn->down; t!=T; t=t->down)
+ for(t=t->down; t!=T; t=t->down)
if(t->etype == TDOT)
return 1;
return 0;
}
vlong
-argsize(void)
+argsize(int doret)
{
Type *t;
int32 s;
//print("t=%T\n", thisfn);
- s = align(0, thisfn->link, Aarg0, nil);
+ s = 0;
+ if(hasdotdotdot(thisfn))
+ s = align(s, thisfn->link, Aarg0, nil);
for(t=thisfn->down; t!=T; t=t->down) {
switch(t->etype) {
case TVOID:
@@ -93,6 +69,14 @@ argsize(void)
s = (s+7) & ~7;
else
s = (s+3) & ~3;
+ if(doret && thisfn->link->etype != TVOID) {
+ s = align(s, thisfn->link, Aarg1, nil);
+ s = align(s, thisfn->link, Aarg2, nil);
+ if(thechar == '6')
+ s = (s+7) & ~7;
+ else
+ s = (s+3) & ~3;
+ }
return s;
}
@@ -101,9 +85,6 @@ codgen(Node *n, Node *nn)
{
Prog *sp;
Node *n1, nod, nod1;
- Sym *gcargs;
- Sym *gclocals;
- int isvarargs;
cursafe = 0;
curarg = 0;
@@ -123,19 +104,10 @@ codgen(Node *n, Node *nn)
nearln = nn->lineno;
p = gtext(n1->sym, stkoff);
+ p->from.sym->cfunc = 1;
sp = p;
/*
- * generate funcdata symbol for this function.
- * data is filled in at the end of codgen().
- */
- isvarargs = hasdotdotdot();
- gcargs = nil;
- if(!isvarargs)
- gcargs = makefuncdatasym("gcargs·%d", FUNCDATA_ArgsPointerMaps);
- gclocals = makefuncdatasym("gclocals·%d", FUNCDATA_LocalsPointerMaps);
-
- /*
* isolate first argument
*/
if(REGARG >= 0) {
@@ -155,8 +127,6 @@ codgen(Node *n, Node *nn)
}
}
- retok = 0;
-
canreach = 1;
warnreach = 1;
gen(n);
@@ -171,22 +141,6 @@ codgen(Node *n, Node *nn)
if(thechar=='6' || thechar=='7') /* [sic] */
maxargsafe = xround(maxargsafe, 8);
sp->to.offset += maxargsafe;
-
- if(!isvarargs)
- dumpgcargs(thisfn, gcargs);
-
- // TODO(rsc): "stkoff" is not right. It does not account for
- // the possibility of data stored in .safe variables.
- // Unfortunately those move up and down just like
- // the argument frame (and in fact dovetail with it)
- // so the number we need is not available or even
- // well-defined. Probably we need to make the safe
- // area its own section.
- // That said, we've been using stkoff for months
- // and nothing too terrible has happened.
- gextern(gclocals, nodconst(-stkoff), 0, 4); // locals
- gclocals->type = typ(0, T);
- gclocals->type->width = 4;
}
void
@@ -214,7 +168,7 @@ supgen(Node *n)
void
gen(Node *n)
{
- Node *l, nod;
+ Node *l, nod, nod1;
Prog *sp, *spc, *spb;
Case *cn;
long sbc, scc;
@@ -275,14 +229,26 @@ loop:
gbranch(ORETURN);
break;
}
+ if(typecmplx[n->type->etype] && !hasdotdotdot(thisfn)) {
+ regret(&nod, n, thisfn, 2);
+ sugen(l, &nod, n->type->width);
+ noretval(3);
+ gbranch(ORETURN);
+ break;
+ }
if(typecmplx[n->type->etype]) {
sugen(l, nodret, n->type->width);
noretval(3);
gbranch(ORETURN);
break;
}
- regret(&nod, n);
+ regret(&nod1, n, thisfn, 2);
+ nod = nod1;
+ if(nod.op != OREGISTER)
+ regalloc(&nod, n, Z);
cgen(l, &nod);
+ if(nod1.op != OREGISTER)
+ gmove(&nod, &nod1);
regfree(&nod);
if(typefd[n->type->etype])
noretval(1);
@@ -654,111 +620,3 @@ bcomplex(Node *n, Node *c)
boolgen(n, 1, Z);
return 0;
}
-
-// Updates the bitvector with a set bit for each pointer containing
-// value in the type description starting at offset.
-static void
-walktype1(Type *t, int32 offset, Bvec *bv, int param)
-{
- Type *t1;
- int32 o;
- int32 widthptr;
-
- widthptr = ewidth[TIND];
- switch(t->etype) {
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TFLOAT:
- case TDOUBLE:
- // non-pointer types
- for(o = 0; o < t->width; o++)
- bvset(bv, ((offset + t->offset + o) / widthptr) * BitsPerPointer); // 1 = live scalar
- break;
-
- case TIND:
- pointer:
- // pointer types
- if((offset + t->offset) % widthptr != 0)
- yyerror("unaligned pointer");
- bvset(bv, ((offset + t->offset) / widthptr)*BitsPerPointer + 1); // 2 = live ptr
- break;
-
- case TARRAY:
- if(param) // unlike Go, C passes arrays by reference
- goto pointer;
- // array in struct or union is an actual array
- for(o = 0; o < t->width; o += t->link->width)
- walktype1(t->link, offset+o, bv, 0);
- break;
-
- case TSTRUCT:
- // build map recursively
- for(t1 = t->link; t1 != T; t1 = t1->down)
- walktype1(t1, offset, bv, 0);
- break;
-
- case TUNION:
- walktype1(t->link, offset, bv, 0);
- break;
-
- default:
- yyerror("can't handle arg type %s\n", tnames[t->etype]);
- }
-}
-
-// Compute a bit vector to describe the pointer containing locations
-// in the argument list. Adds the data to gcsym and returns the offset
-// of end of the bit vector.
-static void
-dumpgcargs(Type *fn, Sym *sym)
-{
- Bvec *bv;
- Type *t;
- int32 i;
- int32 argbytes;
- int32 symoffset, argoffset;
-
- // Dump the length of the bitmap array. This value is always one for
- // functions written in C.
- symoffset = 0;
- gextern(sym, nodconst(1), symoffset, 4);
- symoffset += 4;
- argbytes = (argsize() + ewidth[TIND] - 1);
- bv = bvalloc((argbytes / ewidth[TIND]) * BitsPerPointer);
- argoffset = align(0, fn->link, Aarg0, nil);
- if(argoffset > 0) {
- // The C calling convention returns structs by copying them to a
- // location pointed to by a hidden first argument. This first
- // argument is a pointer.
- if(argoffset != ewidth[TIND])
- yyerror("passbyptr arg not the right size");
- bvset(bv, 1); // 2 = live ptr
- }
- for(t = fn->down; t != T; t = t->down) {
- if(t->etype == TVOID)
- continue;
- argoffset = align(argoffset, t, Aarg1, nil);
- walktype1(t, argoffset, bv, 1);
- argoffset = align(argoffset, t, Aarg2, nil);
- }
- // Dump the length of the bitmap.
- gextern(sym, nodconst(bv->n), symoffset, 4);
- symoffset += 4;
- // Dump the words of the bitmap.
- for(i = 0; i < bv->n; i += 32) {
- gextern(sym, nodconst(bv->b[i/32]), symoffset, 4);
- symoffset += 4;
- }
- free(bv);
- // Finalize the gc symbol.
- sym->type = typ(0, T);
- sym->type->width = symoffset;
-}
diff --git a/src/cmd/cc/y.tab.c b/src/cmd/cc/y.tab.c
index 8588515ab..94932efe5 100644
--- a/src/cmd/cc/y.tab.c
+++ b/src/cmd/cc/y.tab.c
@@ -1,21 +1,24 @@
-/* A Bison parser, made by GNU Bison 2.7.12-4996. */
+/* A Bison parser, made by GNU Bison 2.3. */
-/* Bison implementation for Yacc-like parsers in C
-
- Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -26,7 +29,7 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
@@ -44,7 +47,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.7.12-4996"
+#define YYBISON_VERSION "2.3"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -52,53 +55,10 @@
/* Pure parsers. */
#define YYPURE 0
-/* Push parsers. */
-#define YYPUSH 0
-
-/* Pull parsers. */
-#define YYPULL 1
-
-
-
-
-/* Copy the first part of user declarations. */
-/* Line 371 of yacc.c */
-#line 31 "cc.y"
-
-#include <u.h>
-#include <stdio.h> /* if we don't, bison will, and cc.h re-#defines getc */
-#include "cc.h"
+/* Using locations. */
+#define YYLSP_NEEDED 0
-/* Line 371 of yacc.c */
-#line 74 "y.tab.c"
-# ifndef YY_NULL
-# if defined __cplusplus && 201103L <= __cplusplus
-# define YY_NULL nullptr
-# else
-# define YY_NULL 0
-# endif
-# endif
-
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* In a future release of Bison, this section will be replaced
- by #include "y.tab.h". */
-#ifndef YY_YY_Y_TAB_H_INCLUDED
-# define YY_YY_Y_TAB_H_INCLUDED
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
/* Tokens. */
#ifndef YYTOKENTYPE
@@ -256,12 +216,37 @@ extern int yydebug;
+
+/* Copy the first part of user declarations. */
+#line 31 "cc.y"
+
+#include <u.h>
+#include <stdio.h> /* if we don't, bison will, and cc.h re-#defines getc */
+#include "cc.h"
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-{
-/* Line 387 of yacc.c */
#line 36 "cc.y"
-
+{
Node* node;
Sym* sym;
Type* type;
@@ -285,38 +270,22 @@ typedef union YYSTYPE
int32 lval;
double dval;
vlong vval;
-
-
-/* Line 387 of yacc.c */
-#line 292 "y.tab.c"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
+}
+/* Line 193 of yacc.c. */
+#line 276 "y.tab.c"
+ YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
#endif
-extern YYSTYPE yylval;
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !YY_YY_Y_TAB_H_INCLUDED */
/* Copy the second part of user declarations. */
-/* Line 390 of yacc.c */
-#line 320 "y.tab.c"
+
+/* Line 216 of yacc.c. */
+#line 289 "y.tab.c"
#ifdef short
# undef short
@@ -369,45 +338,36 @@ typedef short int yytype_int16;
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
# endif
# endif
# ifndef YY_
-# define YY_(Msgid) Msgid
-# endif
-#endif
-
-#ifndef __attribute__
-/* This feature is available in gcc versions 2.5 and later. */
-# if (! defined __GNUC__ || __GNUC__ < 2 \
- || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
-# define __attribute__(Spec) /* empty */
+# define YY_(msgid) msgid
# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
+# define YYUSE(e) ((void) (e))
#else
-# define YYUSE(E) /* empty */
+# define YYUSE(e) /* empty */
#endif
-
/* Identity function, used to suppress warnings about constant conditions. */
#ifndef lint
-# define YYID(N) (N)
+# define YYID(n) (n)
#else
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static int
-YYID (int yyi)
+YYID (int i)
#else
static int
-YYID (yyi)
- int yyi;
+YYID (i)
+ int i;
#endif
{
- return yyi;
+ return i;
}
#endif
@@ -428,12 +388,11 @@ YYID (yyi)
# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
- /* Use EXIT_SUCCESS as a witness for stdlib.h. */
-# ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
# endif
# endif
# endif
@@ -456,24 +415,24 @@ YYID (yyi)
# ifndef YYSTACK_ALLOC_MAXIMUM
# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
# endif
-# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+# if (defined __cplusplus && ! defined _STDLIB_H \
&& ! ((defined YYMALLOC || defined malloc) \
&& (defined YYFREE || defined free)))
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
# endif
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
-# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
-# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
@@ -489,9 +448,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- yytype_int16 yyss_alloc;
- YYSTYPE yyvs_alloc;
-};
+ yytype_int16 yyss;
+ YYSTYPE yyvs;
+ };
/* The size of the maximum gap between one aligned stack and the next. */
# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
@@ -502,19 +461,35 @@ union yyalloc
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
-# define YYCOPY_NEEDED 1
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
/* Relocate STACK from its old location to the new one. The
local variables YYSIZE and YYSTACKSIZE give the old and new number of
elements in the stack, and YYPTR gives the new location of the
stack. Advance YYPTR to a properly aligned location for the next
stack. */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+# define YYSTACK_RELOCATE(Stack) \
do \
{ \
YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
- Stack = &yyptr->Stack_alloc; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
@@ -522,26 +497,6 @@ union yyalloc
#endif
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from SRC to DST. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(Dst, Src, Count) \
- __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
-# else
-# define YYCOPY(Dst, Src, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (Dst)[yyi] = (Src)[yyi]; \
- } \
- while (YYID (0))
-# endif
-# endif
-#endif /* !YYCOPY_NEEDED */
-
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
@@ -737,16 +692,16 @@ static const yytype_uint16 yyrline[] =
794, 798, 802, 803, 810, 817, 824, 831, 838, 845,
852, 859, 860, 863, 873, 891, 901, 919, 922, 925,
926, 933, 932, 955, 959, 962, 967, 972, 978, 986,
- 992, 998, 1004, 1012, 1020, 1027, 1033, 1032, 1044, 1052,
- 1058, 1057, 1069, 1077, 1086, 1090, 1085, 1107, 1106, 1115,
- 1121, 1122, 1128, 1131, 1137, 1138, 1139, 1142, 1143, 1149,
- 1150, 1153, 1157, 1161, 1162, 1165, 1166, 1167, 1168, 1169,
- 1170, 1171, 1172, 1173, 1176, 1177, 1178, 1179, 1180, 1181,
- 1182, 1185, 1186, 1187, 1190, 1205, 1217, 1218
+ 992, 998, 1004, 1012, 1020, 1027, 1033, 1032, 1044, 1053,
+ 1059, 1058, 1070, 1078, 1087, 1091, 1086, 1108, 1107, 1116,
+ 1122, 1123, 1129, 1132, 1138, 1139, 1140, 1143, 1144, 1150,
+ 1151, 1154, 1158, 1162, 1163, 1166, 1167, 1168, 1169, 1170,
+ 1171, 1172, 1173, 1174, 1177, 1178, 1179, 1180, 1181, 1182,
+ 1183, 1186, 1187, 1188, 1191, 1206, 1218, 1219
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || 0
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
@@ -764,16 +719,16 @@ static const char *const yytname[] =
"LTYPEDEF", "LTYPESTR", "LUNION", "LUNSIGNED", "LWHILE", "LVOID",
"LENUM", "LSIGNED", "LCONSTNT", "LVOLATILE", "LSET", "LSIGNOF",
"LRESTRICT", "LINLINE", "')'", "']'", "'{'", "'}'", "'!'", "'~'",
- "$accept", "prog", "xdecl", "$@1", "$@2", "xdlist", "$@3", "xdecor",
- "xdecor2", "adecl", "adlist", "$@4", "pdecl", "pdlist", "edecl", "$@5",
- "$@6", "zedlist", "edlist", "edecor", "abdecor", "abdecor1", "abdecor2",
+ "$accept", "prog", "xdecl", "@1", "@2", "xdlist", "@3", "xdecor",
+ "xdecor2", "adecl", "adlist", "@4", "pdecl", "pdlist", "edecl", "@5",
+ "@6", "zedlist", "edlist", "edecor", "abdecor", "abdecor1", "abdecor2",
"abdecor3", "init", "qual", "qlist", "ilist", "zarglist", "arglist",
- "block", "slist", "labels", "label", "stmnt", "forexpr", "ulstmnt",
- "$@7", "$@8", "zcexpr", "zexpr", "lexpr", "cexpr", "expr", "xuexpr",
- "uexpr", "pexpr", "string", "lstring", "zelist", "elist", "sbody", "@9",
- "zctlist", "types", "tlist", "ctlist", "complex", "$@10", "$@11", "$@12",
- "$@13", "$@14", "gctnlist", "zgnlist", "gctname", "gcnlist", "gcname",
- "enum", "tname", "cname", "gname", "name", "tag", "ltag", YY_NULL
+ "block", "slist", "labels", "label", "stmnt", "forexpr", "ulstmnt", "@7",
+ "@8", "zcexpr", "zexpr", "lexpr", "cexpr", "expr", "xuexpr", "uexpr",
+ "pexpr", "string", "lstring", "zelist", "elist", "sbody", "@9",
+ "zctlist", "types", "tlist", "ctlist", "complex", "@10", "@11", "@12",
+ "@13", "@14", "gctnlist", "zgnlist", "gctname", "gcnlist", "gcname",
+ "enum", "tname", "cname", "gname", "name", "tag", "ltag", 0
};
#endif
@@ -855,8 +810,8 @@ static const yytype_uint8 yyr2[] =
1, 1, 1, 1, 1, 1, 1, 1
};
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE doesn't specify something else to do. Zero
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
@@ -981,7 +936,8 @@ static const yytype_int16 yypgoto[] =
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
- number is the opposite. If YYTABLE_NINF, syntax error. */
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -205
static const yytype_int16 yytable[] =
{
@@ -1106,12 +1062,6 @@ static const yytype_int16 yytable[] =
178, 179, 180, 181, 182, 183, 184, 185, 186
};
-#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-331)))
-
-#define yytable_value_is_error(Yytable_value) \
- YYID (0)
-
static const yytype_int16 yycheck[] =
{
1, 27, 14, 91, 131, 17, 30, 58, 20, 33,
@@ -1295,50 +1245,78 @@ static const yytype_uint8 yystos[] =
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. However,
- YYFAIL appears to be in use. Nevertheless, it is formally deprecated
- in Bison 2.4.2's NEWS entry, where a plan to phase it out is
- discussed. */
+ Once GCC version 2 has supplanted version 1, this can go. */
#define YYFAIL goto yyerrlab
-#if defined YYFAIL
- /* This is here to suppress warnings from the GCC cpp's
- -Wunused-macros. Normally we don't worry about that warning, but
- some users do, and we want to make it easy for users to remove
- YYFAIL uses, which will produce warnings from Bison 2.5. */
-#endif
#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- YYPOPSTACK (yylen); \
- yystate = *yyssp; \
- goto yybackup; \
- } \
- else \
- { \
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
yyerror (YY_("syntax error: cannot back up")); \
YYERROR; \
} \
while (YYID (0))
-/* Error token number */
+
#define YYTERROR 1
#define YYERRCODE 256
-/* This macro is provided for backward compatibility. */
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
#endif
/* YYLEX -- calling `yylex' with the right arguments. */
+
#ifdef YYLEX_PARAM
# define YYLEX yylex (YYLEX_PARAM)
#else
@@ -1388,8 +1366,6 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
YYSTYPE const * const yyvaluep;
#endif
{
- FILE *yyo = yyoutput;
- YYUSE (yyo);
if (!yyvaluep)
return;
# ifdef YYPRINT
@@ -1398,7 +1374,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
# else
YYUSE (yyoutput);
# endif
- YYUSE (yytype);
+ switch (yytype)
+ {
+ default:
+ break;
+ }
}
@@ -1435,20 +1415,17 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
#else
static void
-yy_stack_print (yybottom, yytop)
- yytype_int16 *yybottom;
- yytype_int16 *yytop;
+yy_stack_print (bottom, top)
+ yytype_int16 *bottom;
+ yytype_int16 *top;
#endif
{
YYFPRINTF (stderr, "Stack now");
- for (; yybottom <= yytop; yybottom++)
- {
- int yybot = *yybottom;
- YYFPRINTF (stderr, " %d", yybot);
- }
+ for (; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
YYFPRINTF (stderr, "\n");
}
@@ -1482,11 +1459,11 @@ yy_reduce_print (yyvsp, yyrule)
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
- YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ fprintf (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
&(yyvsp[(yyi + 1) - (yynrhs)])
);
- YYFPRINTF (stderr, "\n");
+ fprintf (stderr, "\n");
}
}
@@ -1523,6 +1500,7 @@ int yydebug;
# define YYMAXDEPTH 10000
#endif
+
#if YYERROR_VERBOSE
@@ -1625,145 +1603,115 @@ yytnamerr (char *yyres, const char *yystr)
}
# endif
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
- about the unexpected token YYTOKEN for the state stack whose top is
- YYSSP.
-
- Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
- not large enough to hold the message. In that case, also set
- *YYMSG_ALLOC to the required number of bytes. Return 2 if the
- required number of bytes is too large to store. */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
- yytype_int16 *yyssp, int yytoken)
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
{
- YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
- YYSIZE_T yysize = yysize0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- /* Internationalized format string. */
- const char *yyformat = YY_NULL;
- /* Arguments of yyformat. */
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- /* Number of reported tokens (one for the "unexpected", one per
- "expected"). */
- int yycount = 0;
-
- /* There are many possibilities here to consider:
- - Assume YYFAIL is not used. It's too flawed to consider. See
- <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
- for details. YYERROR is fine as it does not invoke this
- function.
- - If this state is a consistent state with a default action, then
- the only way this function was invoked is if the default action
- is an error action. In that case, don't check for expected
- tokens because there are none.
- - The only way there can be no lookahead present (in yychar) is if
- this state is a consistent state with a default action. Thus,
- detecting the absence of a lookahead is sufficient to determine
- that there is no unexpected or expected token to report. In that
- case, just report a simple "syntax error".
- - Don't assume there isn't a lookahead just because this state is a
- consistent state with a default action. There might have been a
- previous inconsistent state, consistent state with a non-default
- action, or user semantic action that manipulated yychar.
- - Of course, the expected token list depends on states to have
- correct lookahead information, and it depends on the parser not
- to perform extra reductions after fetching a lookahead from the
- scanner and before detecting a syntax error. Thus, state merging
- (from LALR or IELR) and default reductions corrupt the expected
- token list. However, the list is correct for canonical LR with
- one exception: it will still contain any token that will not be
- accepted due to an error action in a later state.
- */
- if (yytoken != YYEMPTY)
- {
- int yyn = yypact[*yyssp];
- yyarg[yycount++] = yytname[yytoken];
- if (!yypact_value_is_default (yyn))
- {
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. In other words, skip the first -YYN actions for
- this state because they are default actions. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yyx;
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
- && !yytable_value_is_error (yytable[yyx + yyn]))
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- {
- YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
- if (! (yysize <= yysize1
- && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
- }
- }
- }
- }
+ int yyn = yypact[yystate];
- switch (yycount)
- {
-# define YYCASE_(N, S) \
- case N: \
- yyformat = S; \
- break
- YYCASE_(0, YY_("syntax error"));
- YYCASE_(1, YY_("syntax error, unexpected %s"));
- YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
- YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
- YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
- YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
- }
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
- {
- YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
- }
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
- if (*yymsg_alloc < yysize)
- {
- *yymsg_alloc = 2 * yysize;
- if (! (yysize <= *yymsg_alloc
- && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
- *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
- return 1;
- }
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- {
- char *yyp = *yymsg;
- int yyi = 0;
- while ((*yyp = *yyformat) != '\0')
- if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyformat += 2;
- }
- else
- {
- yyp++;
- yyformat++;
- }
- }
- return 0;
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
}
#endif /* YYERROR_VERBOSE */
+
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
@@ -1788,31 +1736,44 @@ yydestruct (yymsg, yytype, yyvaluep)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
- YYUSE (yytype);
-}
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
-/* The lookahead symbol. */
-int yychar;
-#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END
-#endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
+/* The look-ahead symbol. */
+int yychar;
-/* The semantic value of the lookahead symbol. */
-YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
+/* The semantic value of the look-ahead symbol. */
+YYSTYPE yylval;
/* Number of syntax errors so far. */
int yynerrs;
+
/*----------.
| yyparse. |
`----------*/
@@ -1839,37 +1800,14 @@ yyparse ()
#endif
#endif
{
- int yystate;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
-
- /* The stacks and their tools:
- `yyss': related to states.
- `yyvs': related to semantic values.
-
- Refer to the stacks through separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
-
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss;
- yytype_int16 *yyssp;
-
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs;
- YYSTYPE *yyvsp;
-
- YYSIZE_T yystacksize;
-
+
+ int yystate;
int yyn;
int yyresult;
- /* Lookahead token as an internal (translated) token number. */
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
int yytoken = 0;
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
-
#if YYERROR_VERBOSE
/* Buffer for error messages, and its allocated size. */
char yymsgbuf[128];
@@ -1877,22 +1815,54 @@ yyparse ()
YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
#endif
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp;
+
+
+
#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
/* The number of symbols on the RHS of the reduced rule.
Keep to zero when no symbol should be popped. */
int yylen = 0;
- yyssp = yyss = yyssa;
- yyvsp = yyvs = yyvsa;
- yystacksize = YYINITDEPTH;
-
YYDPRINTF ((stderr, "Starting parse\n"));
yystate = 0;
yyerrstatus = 0;
yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
goto yysetstate;
/*------------------------------------------------------------.
@@ -1919,6 +1889,7 @@ yyparse ()
YYSTYPE *yyvs1 = yyvs;
yytype_int16 *yyss1 = yyss;
+
/* Each stack pointer address is followed by the size of the
data in use in that stack, in bytes. This used to be a
conditional around just the two extra args, but that might
@@ -1926,6 +1897,7 @@ yyparse ()
yyoverflow (YY_("memory exhausted"),
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),
+
&yystacksize);
yyss = yyss1;
@@ -1948,8 +1920,9 @@ yyparse ()
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
if (! yyptr)
goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss_alloc, yyss);
- YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
@@ -1960,6 +1933,7 @@ yyparse ()
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
+
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
(unsigned long int) yystacksize));
@@ -1969,9 +1943,6 @@ yyparse ()
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
- if (yystate == YYFINAL)
- YYACCEPT;
-
goto yybackup;
/*-----------.
@@ -1980,16 +1951,16 @@ yyparse ()
yybackup:
/* Do appropriate processing given the current state. Read a
- lookahead token if we need one and don't already have one. */
+ look-ahead token if we need one and don't already have one. */
- /* First try to decide what to do without reference to lookahead token. */
+ /* First try to decide what to do without reference to look-ahead token. */
yyn = yypact[yystate];
- if (yypact_value_is_default (yyn))
+ if (yyn == YYPACT_NINF)
goto yydefault;
- /* Not known => get a lookahead token if don't already have one. */
+ /* Not known => get a look-ahead token if don't already have one. */
- /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
@@ -2015,27 +1986,29 @@ yybackup:
yyn = yytable[yyn];
if (yyn <= 0)
{
- if (yytable_value_is_error (yyn))
- goto yyerrlab;
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
/* Count tokens shifted since error; after three, turn off error
status. */
if (yyerrstatus)
yyerrstatus--;
- /* Shift the lookahead token. */
+ /* Shift the look-ahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
- /* Discard the shifted token. */
- yychar = YYEMPTY;
+ /* Discard the shifted token unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
yystate = yyn;
- YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
- YY_IGNORE_MAYBE_UNINITIALIZED_END
goto yynewstate;
@@ -2072,7 +2045,6 @@ yyreduce:
switch (yyn)
{
case 4:
-/* Line 1787 of yacc.c */
#line 109 "cc.y"
{
dodecl(xdecl, lastclass, lasttype, Z);
@@ -2080,7 +2052,6 @@ yyreduce:
break;
case 6:
-/* Line 1787 of yacc.c */
#line 114 "cc.y"
{
lastdcl = T;
@@ -2098,7 +2069,6 @@ yyreduce:
break;
case 7:
-/* Line 1787 of yacc.c */
#line 128 "cc.y"
{
argmark((yyvsp[(2) - (4)].node), 1);
@@ -2106,7 +2076,6 @@ yyreduce:
break;
case 8:
-/* Line 1787 of yacc.c */
#line 132 "cc.y"
{
Node *n;
@@ -2120,7 +2089,6 @@ yyreduce:
break;
case 9:
-/* Line 1787 of yacc.c */
#line 144 "cc.y"
{
dodecl(xdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
@@ -2128,7 +2096,6 @@ yyreduce:
break;
case 10:
-/* Line 1787 of yacc.c */
#line 148 "cc.y"
{
(yyvsp[(1) - (1)].node) = dodecl(xdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
@@ -2136,7 +2103,6 @@ yyreduce:
break;
case 11:
-/* Line 1787 of yacc.c */
#line 152 "cc.y"
{
doinit((yyvsp[(1) - (4)].node)->sym, (yyvsp[(1) - (4)].node)->type, 0L, (yyvsp[(4) - (4)].node));
@@ -2144,7 +2110,6 @@ yyreduce:
break;
case 14:
-/* Line 1787 of yacc.c */
#line 160 "cc.y"
{
(yyval.node) = new(OIND, (yyvsp[(3) - (3)].node), Z);
@@ -2153,7 +2118,6 @@ yyreduce:
break;
case 16:
-/* Line 1787 of yacc.c */
#line 168 "cc.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
@@ -2161,7 +2125,6 @@ yyreduce:
break;
case 17:
-/* Line 1787 of yacc.c */
#line 172 "cc.y"
{
(yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
@@ -2169,7 +2132,6 @@ yyreduce:
break;
case 18:
-/* Line 1787 of yacc.c */
#line 176 "cc.y"
{
(yyval.node) = new(OARRAY, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
@@ -2177,7 +2139,6 @@ yyreduce:
break;
case 19:
-/* Line 1787 of yacc.c */
#line 185 "cc.y"
{
(yyval.node) = dodecl(adecl, lastclass, lasttype, Z);
@@ -2185,7 +2146,6 @@ yyreduce:
break;
case 20:
-/* Line 1787 of yacc.c */
#line 189 "cc.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
@@ -2193,7 +2153,6 @@ yyreduce:
break;
case 21:
-/* Line 1787 of yacc.c */
#line 195 "cc.y"
{
dodecl(adecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
@@ -2202,7 +2161,6 @@ yyreduce:
break;
case 22:
-/* Line 1787 of yacc.c */
#line 200 "cc.y"
{
(yyvsp[(1) - (1)].node) = dodecl(adecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
@@ -2210,7 +2168,6 @@ yyreduce:
break;
case 23:
-/* Line 1787 of yacc.c */
#line 204 "cc.y"
{
int32 w;
@@ -2222,7 +2179,6 @@ yyreduce:
break;
case 24:
-/* Line 1787 of yacc.c */
#line 212 "cc.y"
{
(yyval.node) = (yyvsp[(1) - (3)].node);
@@ -2235,7 +2191,6 @@ yyreduce:
break;
case 27:
-/* Line 1787 of yacc.c */
#line 229 "cc.y"
{
dodecl(pdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
@@ -2243,7 +2198,6 @@ yyreduce:
break;
case 29:
-/* Line 1787 of yacc.c */
#line 239 "cc.y"
{
lasttype = (yyvsp[(1) - (1)].type);
@@ -2251,7 +2205,6 @@ yyreduce:
break;
case 31:
-/* Line 1787 of yacc.c */
#line 244 "cc.y"
{
lasttype = (yyvsp[(2) - (2)].type);
@@ -2259,7 +2212,6 @@ yyreduce:
break;
case 33:
-/* Line 1787 of yacc.c */
#line 250 "cc.y"
{
lastfield = 0;
@@ -2268,7 +2220,6 @@ yyreduce:
break;
case 35:
-/* Line 1787 of yacc.c */
#line 258 "cc.y"
{
dodecl(edecl, CXXX, lasttype, (yyvsp[(1) - (1)].node));
@@ -2276,7 +2227,6 @@ yyreduce:
break;
case 37:
-/* Line 1787 of yacc.c */
#line 265 "cc.y"
{
lastbit = 0;
@@ -2285,7 +2235,6 @@ yyreduce:
break;
case 38:
-/* Line 1787 of yacc.c */
#line 270 "cc.y"
{
(yyval.node) = new(OBIT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2293,7 +2242,6 @@ yyreduce:
break;
case 39:
-/* Line 1787 of yacc.c */
#line 274 "cc.y"
{
(yyval.node) = new(OBIT, Z, (yyvsp[(2) - (2)].node));
@@ -2301,7 +2249,6 @@ yyreduce:
break;
case 40:
-/* Line 1787 of yacc.c */
#line 282 "cc.y"
{
(yyval.node) = (Z);
@@ -2309,7 +2256,6 @@ yyreduce:
break;
case 42:
-/* Line 1787 of yacc.c */
#line 289 "cc.y"
{
(yyval.node) = new(OIND, (Z), Z);
@@ -2318,7 +2264,6 @@ yyreduce:
break;
case 43:
-/* Line 1787 of yacc.c */
#line 294 "cc.y"
{
(yyval.node) = new(OIND, (yyvsp[(3) - (3)].node), Z);
@@ -2327,7 +2272,6 @@ yyreduce:
break;
case 46:
-/* Line 1787 of yacc.c */
#line 303 "cc.y"
{
(yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
@@ -2335,7 +2279,6 @@ yyreduce:
break;
case 47:
-/* Line 1787 of yacc.c */
#line 307 "cc.y"
{
(yyval.node) = new(OARRAY, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
@@ -2343,7 +2286,6 @@ yyreduce:
break;
case 48:
-/* Line 1787 of yacc.c */
#line 313 "cc.y"
{
(yyval.node) = new(OFUNC, (Z), Z);
@@ -2351,7 +2293,6 @@ yyreduce:
break;
case 49:
-/* Line 1787 of yacc.c */
#line 317 "cc.y"
{
(yyval.node) = new(OARRAY, (Z), (yyvsp[(2) - (3)].node));
@@ -2359,7 +2300,6 @@ yyreduce:
break;
case 50:
-/* Line 1787 of yacc.c */
#line 321 "cc.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
@@ -2367,7 +2307,6 @@ yyreduce:
break;
case 52:
-/* Line 1787 of yacc.c */
#line 328 "cc.y"
{
(yyval.node) = new(OINIT, invert((yyvsp[(2) - (3)].node)), Z);
@@ -2375,7 +2314,6 @@ yyreduce:
break;
case 53:
-/* Line 1787 of yacc.c */
#line 334 "cc.y"
{
(yyval.node) = new(OARRAY, (yyvsp[(2) - (3)].node), Z);
@@ -2383,7 +2321,6 @@ yyreduce:
break;
case 54:
-/* Line 1787 of yacc.c */
#line 338 "cc.y"
{
(yyval.node) = new(OELEM, Z, Z);
@@ -2392,7 +2329,6 @@ yyreduce:
break;
case 57:
-/* Line 1787 of yacc.c */
#line 347 "cc.y"
{
(yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].node));
@@ -2400,7 +2336,6 @@ yyreduce:
break;
case 59:
-/* Line 1787 of yacc.c */
#line 352 "cc.y"
{
(yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
@@ -2408,7 +2343,6 @@ yyreduce:
break;
case 62:
-/* Line 1787 of yacc.c */
#line 360 "cc.y"
{
(yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
@@ -2416,7 +2350,6 @@ yyreduce:
break;
case 63:
-/* Line 1787 of yacc.c */
#line 365 "cc.y"
{
(yyval.node) = Z;
@@ -2424,7 +2357,6 @@ yyreduce:
break;
case 64:
-/* Line 1787 of yacc.c */
#line 369 "cc.y"
{
(yyval.node) = invert((yyvsp[(1) - (1)].node));
@@ -2432,7 +2364,6 @@ yyreduce:
break;
case 66:
-/* Line 1787 of yacc.c */
#line 377 "cc.y"
{
(yyval.node) = new(OPROTO, (yyvsp[(2) - (2)].node), Z);
@@ -2441,7 +2372,6 @@ yyreduce:
break;
case 67:
-/* Line 1787 of yacc.c */
#line 382 "cc.y"
{
(yyval.node) = new(OPROTO, (yyvsp[(2) - (2)].node), Z);
@@ -2450,7 +2380,6 @@ yyreduce:
break;
case 68:
-/* Line 1787 of yacc.c */
#line 387 "cc.y"
{
(yyval.node) = new(ODOTDOT, Z, Z);
@@ -2458,7 +2387,6 @@ yyreduce:
break;
case 69:
-/* Line 1787 of yacc.c */
#line 391 "cc.y"
{
(yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2466,7 +2394,6 @@ yyreduce:
break;
case 70:
-/* Line 1787 of yacc.c */
#line 397 "cc.y"
{
(yyval.node) = invert((yyvsp[(2) - (3)].node));
@@ -2478,7 +2405,6 @@ yyreduce:
break;
case 71:
-/* Line 1787 of yacc.c */
#line 406 "cc.y"
{
(yyval.node) = Z;
@@ -2486,7 +2412,6 @@ yyreduce:
break;
case 72:
-/* Line 1787 of yacc.c */
#line 410 "cc.y"
{
(yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
@@ -2494,7 +2419,6 @@ yyreduce:
break;
case 73:
-/* Line 1787 of yacc.c */
#line 414 "cc.y"
{
(yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
@@ -2502,7 +2426,6 @@ yyreduce:
break;
case 75:
-/* Line 1787 of yacc.c */
#line 421 "cc.y"
{
(yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
@@ -2510,7 +2433,6 @@ yyreduce:
break;
case 76:
-/* Line 1787 of yacc.c */
#line 427 "cc.y"
{
(yyval.node) = new(OCASE, (yyvsp[(2) - (3)].node), Z);
@@ -2518,7 +2440,6 @@ yyreduce:
break;
case 77:
-/* Line 1787 of yacc.c */
#line 431 "cc.y"
{
(yyval.node) = new(OCASE, Z, Z);
@@ -2526,7 +2447,6 @@ yyreduce:
break;
case 78:
-/* Line 1787 of yacc.c */
#line 435 "cc.y"
{
(yyval.node) = new(OLABEL, dcllabel((yyvsp[(1) - (2)].sym), 1), Z);
@@ -2534,7 +2454,6 @@ yyreduce:
break;
case 79:
-/* Line 1787 of yacc.c */
#line 441 "cc.y"
{
(yyval.node) = Z;
@@ -2542,7 +2461,6 @@ yyreduce:
break;
case 81:
-/* Line 1787 of yacc.c */
#line 446 "cc.y"
{
(yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
@@ -2550,7 +2468,6 @@ yyreduce:
break;
case 83:
-/* Line 1787 of yacc.c */
#line 453 "cc.y"
{
(yyval.node) = (yyvsp[(2) - (2)].node);
@@ -2558,7 +2475,6 @@ yyreduce:
break;
case 85:
-/* Line 1787 of yacc.c */
#line 459 "cc.y"
{
markdcl();
@@ -2566,7 +2482,6 @@ yyreduce:
break;
case 86:
-/* Line 1787 of yacc.c */
#line 463 "cc.y"
{
(yyval.node) = revertdcl();
@@ -2578,7 +2493,6 @@ yyreduce:
break;
case 87:
-/* Line 1787 of yacc.c */
#line 471 "cc.y"
{
(yyval.node) = new(OIF, (yyvsp[(3) - (5)].node), new(OLIST, (yyvsp[(5) - (5)].node), Z));
@@ -2588,7 +2502,6 @@ yyreduce:
break;
case 88:
-/* Line 1787 of yacc.c */
#line 477 "cc.y"
{
(yyval.node) = new(OIF, (yyvsp[(3) - (7)].node), new(OLIST, (yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)));
@@ -2600,13 +2513,11 @@ yyreduce:
break;
case 89:
-/* Line 1787 of yacc.c */
#line 484 "cc.y"
{ markdcl(); }
break;
case 90:
-/* Line 1787 of yacc.c */
#line 485 "cc.y"
{
(yyval.node) = revertdcl();
@@ -2621,7 +2532,6 @@ yyreduce:
break;
case 91:
-/* Line 1787 of yacc.c */
#line 496 "cc.y"
{
(yyval.node) = new(OWHILE, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
@@ -2629,7 +2539,6 @@ yyreduce:
break;
case 92:
-/* Line 1787 of yacc.c */
#line 500 "cc.y"
{
(yyval.node) = new(ODWHILE, (yyvsp[(5) - (7)].node), (yyvsp[(2) - (7)].node));
@@ -2637,7 +2546,6 @@ yyreduce:
break;
case 93:
-/* Line 1787 of yacc.c */
#line 504 "cc.y"
{
(yyval.node) = new(ORETURN, (yyvsp[(2) - (3)].node), Z);
@@ -2646,7 +2554,6 @@ yyreduce:
break;
case 94:
-/* Line 1787 of yacc.c */
#line 509 "cc.y"
{
(yyval.node) = new(OCONST, Z, Z);
@@ -2664,7 +2571,6 @@ yyreduce:
break;
case 95:
-/* Line 1787 of yacc.c */
#line 523 "cc.y"
{
(yyval.node) = new(OBREAK, Z, Z);
@@ -2672,7 +2578,6 @@ yyreduce:
break;
case 96:
-/* Line 1787 of yacc.c */
#line 527 "cc.y"
{
(yyval.node) = new(OCONTINUE, Z, Z);
@@ -2680,7 +2585,6 @@ yyreduce:
break;
case 97:
-/* Line 1787 of yacc.c */
#line 531 "cc.y"
{
(yyval.node) = new(OGOTO, dcllabel((yyvsp[(2) - (3)].sym), 0), Z);
@@ -2688,7 +2592,6 @@ yyreduce:
break;
case 98:
-/* Line 1787 of yacc.c */
#line 535 "cc.y"
{
(yyval.node) = new(OUSED, (yyvsp[(3) - (5)].node), Z);
@@ -2696,7 +2599,6 @@ yyreduce:
break;
case 99:
-/* Line 1787 of yacc.c */
#line 539 "cc.y"
{
(yyval.node) = new(OPREFETCH, (yyvsp[(3) - (5)].node), Z);
@@ -2704,7 +2606,6 @@ yyreduce:
break;
case 100:
-/* Line 1787 of yacc.c */
#line 543 "cc.y"
{
(yyval.node) = new(OSET, (yyvsp[(3) - (5)].node), Z);
@@ -2712,7 +2613,6 @@ yyreduce:
break;
case 101:
-/* Line 1787 of yacc.c */
#line 548 "cc.y"
{
(yyval.node) = Z;
@@ -2720,7 +2620,6 @@ yyreduce:
break;
case 103:
-/* Line 1787 of yacc.c */
#line 554 "cc.y"
{
(yyval.node) = Z;
@@ -2728,7 +2627,6 @@ yyreduce:
break;
case 105:
-/* Line 1787 of yacc.c */
#line 561 "cc.y"
{
(yyval.node) = new(OCAST, (yyvsp[(1) - (1)].node), Z);
@@ -2737,7 +2635,6 @@ yyreduce:
break;
case 107:
-/* Line 1787 of yacc.c */
#line 569 "cc.y"
{
(yyval.node) = new(OCOMMA, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2745,7 +2642,6 @@ yyreduce:
break;
case 109:
-/* Line 1787 of yacc.c */
#line 576 "cc.y"
{
(yyval.node) = new(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2753,7 +2649,6 @@ yyreduce:
break;
case 110:
-/* Line 1787 of yacc.c */
#line 580 "cc.y"
{
(yyval.node) = new(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2761,7 +2656,6 @@ yyreduce:
break;
case 111:
-/* Line 1787 of yacc.c */
#line 584 "cc.y"
{
(yyval.node) = new(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2769,7 +2663,6 @@ yyreduce:
break;
case 112:
-/* Line 1787 of yacc.c */
#line 588 "cc.y"
{
(yyval.node) = new(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2777,7 +2670,6 @@ yyreduce:
break;
case 113:
-/* Line 1787 of yacc.c */
#line 592 "cc.y"
{
(yyval.node) = new(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2785,7 +2677,6 @@ yyreduce:
break;
case 114:
-/* Line 1787 of yacc.c */
#line 596 "cc.y"
{
(yyval.node) = new(OASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2793,7 +2684,6 @@ yyreduce:
break;
case 115:
-/* Line 1787 of yacc.c */
#line 600 "cc.y"
{
(yyval.node) = new(OASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2801,7 +2691,6 @@ yyreduce:
break;
case 116:
-/* Line 1787 of yacc.c */
#line 604 "cc.y"
{
(yyval.node) = new(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2809,7 +2698,6 @@ yyreduce:
break;
case 117:
-/* Line 1787 of yacc.c */
#line 608 "cc.y"
{
(yyval.node) = new(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2817,7 +2705,6 @@ yyreduce:
break;
case 118:
-/* Line 1787 of yacc.c */
#line 612 "cc.y"
{
(yyval.node) = new(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2825,7 +2712,6 @@ yyreduce:
break;
case 119:
-/* Line 1787 of yacc.c */
#line 616 "cc.y"
{
(yyval.node) = new(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2833,7 +2719,6 @@ yyreduce:
break;
case 120:
-/* Line 1787 of yacc.c */
#line 620 "cc.y"
{
(yyval.node) = new(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2841,7 +2726,6 @@ yyreduce:
break;
case 121:
-/* Line 1787 of yacc.c */
#line 624 "cc.y"
{
(yyval.node) = new(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2849,7 +2733,6 @@ yyreduce:
break;
case 122:
-/* Line 1787 of yacc.c */
#line 628 "cc.y"
{
(yyval.node) = new(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2857,7 +2740,6 @@ yyreduce:
break;
case 123:
-/* Line 1787 of yacc.c */
#line 632 "cc.y"
{
(yyval.node) = new(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2865,7 +2747,6 @@ yyreduce:
break;
case 124:
-/* Line 1787 of yacc.c */
#line 636 "cc.y"
{
(yyval.node) = new(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2873,7 +2754,6 @@ yyreduce:
break;
case 125:
-/* Line 1787 of yacc.c */
#line 640 "cc.y"
{
(yyval.node) = new(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2881,7 +2761,6 @@ yyreduce:
break;
case 126:
-/* Line 1787 of yacc.c */
#line 644 "cc.y"
{
(yyval.node) = new(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2889,7 +2768,6 @@ yyreduce:
break;
case 127:
-/* Line 1787 of yacc.c */
#line 648 "cc.y"
{
(yyval.node) = new(OCOND, (yyvsp[(1) - (5)].node), new(OLIST, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)));
@@ -2897,7 +2775,6 @@ yyreduce:
break;
case 128:
-/* Line 1787 of yacc.c */
#line 652 "cc.y"
{
(yyval.node) = new(OAS, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2905,7 +2782,6 @@ yyreduce:
break;
case 129:
-/* Line 1787 of yacc.c */
#line 656 "cc.y"
{
(yyval.node) = new(OASADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2913,7 +2789,6 @@ yyreduce:
break;
case 130:
-/* Line 1787 of yacc.c */
#line 660 "cc.y"
{
(yyval.node) = new(OASSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2921,7 +2796,6 @@ yyreduce:
break;
case 131:
-/* Line 1787 of yacc.c */
#line 664 "cc.y"
{
(yyval.node) = new(OASMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2929,7 +2803,6 @@ yyreduce:
break;
case 132:
-/* Line 1787 of yacc.c */
#line 668 "cc.y"
{
(yyval.node) = new(OASDIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2937,7 +2810,6 @@ yyreduce:
break;
case 133:
-/* Line 1787 of yacc.c */
#line 672 "cc.y"
{
(yyval.node) = new(OASMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2945,7 +2817,6 @@ yyreduce:
break;
case 134:
-/* Line 1787 of yacc.c */
#line 676 "cc.y"
{
(yyval.node) = new(OASASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2953,7 +2824,6 @@ yyreduce:
break;
case 135:
-/* Line 1787 of yacc.c */
#line 680 "cc.y"
{
(yyval.node) = new(OASASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2961,7 +2831,6 @@ yyreduce:
break;
case 136:
-/* Line 1787 of yacc.c */
#line 684 "cc.y"
{
(yyval.node) = new(OASAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2969,7 +2838,6 @@ yyreduce:
break;
case 137:
-/* Line 1787 of yacc.c */
#line 688 "cc.y"
{
(yyval.node) = new(OASXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2977,7 +2845,6 @@ yyreduce:
break;
case 138:
-/* Line 1787 of yacc.c */
#line 692 "cc.y"
{
(yyval.node) = new(OASOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -2985,7 +2852,6 @@ yyreduce:
break;
case 140:
-/* Line 1787 of yacc.c */
#line 699 "cc.y"
{
(yyval.node) = new(OCAST, (yyvsp[(5) - (5)].node), Z);
@@ -2996,7 +2862,6 @@ yyreduce:
break;
case 141:
-/* Line 1787 of yacc.c */
#line 706 "cc.y"
{
(yyval.node) = new(OSTRUCT, (yyvsp[(6) - (7)].node), Z);
@@ -3006,7 +2871,6 @@ yyreduce:
break;
case 143:
-/* Line 1787 of yacc.c */
#line 715 "cc.y"
{
(yyval.node) = new(OIND, (yyvsp[(2) - (2)].node), Z);
@@ -3014,7 +2878,6 @@ yyreduce:
break;
case 144:
-/* Line 1787 of yacc.c */
#line 719 "cc.y"
{
(yyval.node) = new(OADDR, (yyvsp[(2) - (2)].node), Z);
@@ -3022,7 +2885,6 @@ yyreduce:
break;
case 145:
-/* Line 1787 of yacc.c */
#line 723 "cc.y"
{
(yyval.node) = new(OPOS, (yyvsp[(2) - (2)].node), Z);
@@ -3030,7 +2892,6 @@ yyreduce:
break;
case 146:
-/* Line 1787 of yacc.c */
#line 727 "cc.y"
{
(yyval.node) = new(ONEG, (yyvsp[(2) - (2)].node), Z);
@@ -3038,7 +2899,6 @@ yyreduce:
break;
case 147:
-/* Line 1787 of yacc.c */
#line 731 "cc.y"
{
(yyval.node) = new(ONOT, (yyvsp[(2) - (2)].node), Z);
@@ -3046,7 +2906,6 @@ yyreduce:
break;
case 148:
-/* Line 1787 of yacc.c */
#line 735 "cc.y"
{
(yyval.node) = new(OCOM, (yyvsp[(2) - (2)].node), Z);
@@ -3054,7 +2913,6 @@ yyreduce:
break;
case 149:
-/* Line 1787 of yacc.c */
#line 739 "cc.y"
{
(yyval.node) = new(OPREINC, (yyvsp[(2) - (2)].node), Z);
@@ -3062,7 +2920,6 @@ yyreduce:
break;
case 150:
-/* Line 1787 of yacc.c */
#line 743 "cc.y"
{
(yyval.node) = new(OPREDEC, (yyvsp[(2) - (2)].node), Z);
@@ -3070,7 +2927,6 @@ yyreduce:
break;
case 151:
-/* Line 1787 of yacc.c */
#line 747 "cc.y"
{
(yyval.node) = new(OSIZE, (yyvsp[(2) - (2)].node), Z);
@@ -3078,7 +2934,6 @@ yyreduce:
break;
case 152:
-/* Line 1787 of yacc.c */
#line 751 "cc.y"
{
(yyval.node) = new(OSIGN, (yyvsp[(2) - (2)].node), Z);
@@ -3086,7 +2941,6 @@ yyreduce:
break;
case 153:
-/* Line 1787 of yacc.c */
#line 757 "cc.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
@@ -3094,7 +2948,6 @@ yyreduce:
break;
case 154:
-/* Line 1787 of yacc.c */
#line 761 "cc.y"
{
(yyval.node) = new(OSIZE, Z, Z);
@@ -3104,7 +2957,6 @@ yyreduce:
break;
case 155:
-/* Line 1787 of yacc.c */
#line 767 "cc.y"
{
(yyval.node) = new(OSIGN, Z, Z);
@@ -3114,7 +2966,6 @@ yyreduce:
break;
case 156:
-/* Line 1787 of yacc.c */
#line 773 "cc.y"
{
(yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), Z);
@@ -3126,7 +2977,6 @@ yyreduce:
break;
case 157:
-/* Line 1787 of yacc.c */
#line 781 "cc.y"
{
(yyval.node) = new(OIND, new(OADD, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node)), Z);
@@ -3134,7 +2984,6 @@ yyreduce:
break;
case 158:
-/* Line 1787 of yacc.c */
#line 785 "cc.y"
{
(yyval.node) = new(ODOT, new(OIND, (yyvsp[(1) - (3)].node), Z), Z);
@@ -3143,7 +2992,6 @@ yyreduce:
break;
case 159:
-/* Line 1787 of yacc.c */
#line 790 "cc.y"
{
(yyval.node) = new(ODOT, (yyvsp[(1) - (3)].node), Z);
@@ -3152,7 +3000,6 @@ yyreduce:
break;
case 160:
-/* Line 1787 of yacc.c */
#line 795 "cc.y"
{
(yyval.node) = new(OPOSTINC, (yyvsp[(1) - (2)].node), Z);
@@ -3160,7 +3007,6 @@ yyreduce:
break;
case 161:
-/* Line 1787 of yacc.c */
#line 799 "cc.y"
{
(yyval.node) = new(OPOSTDEC, (yyvsp[(1) - (2)].node), Z);
@@ -3168,7 +3014,6 @@ yyreduce:
break;
case 163:
-/* Line 1787 of yacc.c */
#line 804 "cc.y"
{
(yyval.node) = new(OCONST, Z, Z);
@@ -3179,7 +3024,6 @@ yyreduce:
break;
case 164:
-/* Line 1787 of yacc.c */
#line 811 "cc.y"
{
(yyval.node) = new(OCONST, Z, Z);
@@ -3190,7 +3034,6 @@ yyreduce:
break;
case 165:
-/* Line 1787 of yacc.c */
#line 818 "cc.y"
{
(yyval.node) = new(OCONST, Z, Z);
@@ -3201,7 +3044,6 @@ yyreduce:
break;
case 166:
-/* Line 1787 of yacc.c */
#line 825 "cc.y"
{
(yyval.node) = new(OCONST, Z, Z);
@@ -3212,7 +3054,6 @@ yyreduce:
break;
case 167:
-/* Line 1787 of yacc.c */
#line 832 "cc.y"
{
(yyval.node) = new(OCONST, Z, Z);
@@ -3223,7 +3064,6 @@ yyreduce:
break;
case 168:
-/* Line 1787 of yacc.c */
#line 839 "cc.y"
{
(yyval.node) = new(OCONST, Z, Z);
@@ -3234,7 +3074,6 @@ yyreduce:
break;
case 169:
-/* Line 1787 of yacc.c */
#line 846 "cc.y"
{
(yyval.node) = new(OCONST, Z, Z);
@@ -3245,7 +3084,6 @@ yyreduce:
break;
case 170:
-/* Line 1787 of yacc.c */
#line 853 "cc.y"
{
(yyval.node) = new(OCONST, Z, Z);
@@ -3256,7 +3094,6 @@ yyreduce:
break;
case 173:
-/* Line 1787 of yacc.c */
#line 864 "cc.y"
{
(yyval.node) = new(OSTRING, Z, Z);
@@ -3270,7 +3107,6 @@ yyreduce:
break;
case 174:
-/* Line 1787 of yacc.c */
#line 874 "cc.y"
{
char *s;
@@ -3290,7 +3126,6 @@ yyreduce:
break;
case 175:
-/* Line 1787 of yacc.c */
#line 892 "cc.y"
{
(yyval.node) = new(OLSTRING, Z, Z);
@@ -3304,7 +3139,6 @@ yyreduce:
break;
case 176:
-/* Line 1787 of yacc.c */
#line 902 "cc.y"
{
char *s;
@@ -3324,7 +3158,6 @@ yyreduce:
break;
case 177:
-/* Line 1787 of yacc.c */
#line 919 "cc.y"
{
(yyval.node) = Z;
@@ -3332,7 +3165,6 @@ yyreduce:
break;
case 180:
-/* Line 1787 of yacc.c */
#line 927 "cc.y"
{
(yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
@@ -3340,7 +3172,6 @@ yyreduce:
break;
case 181:
-/* Line 1787 of yacc.c */
#line 933 "cc.y"
{
(yyval.tyty).t1 = strf;
@@ -3357,7 +3188,6 @@ yyreduce:
break;
case 182:
-/* Line 1787 of yacc.c */
#line 946 "cc.y"
{
(yyval.type) = strf;
@@ -3369,7 +3199,6 @@ yyreduce:
break;
case 183:
-/* Line 1787 of yacc.c */
#line 955 "cc.y"
{
lastclass = CXXX;
@@ -3378,7 +3207,6 @@ yyreduce:
break;
case 185:
-/* Line 1787 of yacc.c */
#line 963 "cc.y"
{
(yyval.tycl).t = (yyvsp[(1) - (1)].type);
@@ -3387,7 +3215,6 @@ yyreduce:
break;
case 186:
-/* Line 1787 of yacc.c */
#line 968 "cc.y"
{
(yyval.tycl).t = simplet((yyvsp[(1) - (1)].lval));
@@ -3396,7 +3223,6 @@ yyreduce:
break;
case 187:
-/* Line 1787 of yacc.c */
#line 973 "cc.y"
{
(yyval.tycl).t = simplet((yyvsp[(1) - (1)].lval));
@@ -3406,7 +3232,6 @@ yyreduce:
break;
case 188:
-/* Line 1787 of yacc.c */
#line 979 "cc.y"
{
(yyval.tycl).t = (yyvsp[(1) - (2)].type);
@@ -3418,7 +3243,6 @@ yyreduce:
break;
case 189:
-/* Line 1787 of yacc.c */
#line 987 "cc.y"
{
(yyval.tycl).t = simplet(typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval)));
@@ -3428,7 +3252,6 @@ yyreduce:
break;
case 190:
-/* Line 1787 of yacc.c */
#line 993 "cc.y"
{
(yyval.tycl).t = (yyvsp[(2) - (3)].type);
@@ -3438,7 +3261,6 @@ yyreduce:
break;
case 191:
-/* Line 1787 of yacc.c */
#line 999 "cc.y"
{
(yyval.tycl).t = simplet((yyvsp[(2) - (2)].lval));
@@ -3448,7 +3270,6 @@ yyreduce:
break;
case 192:
-/* Line 1787 of yacc.c */
#line 1005 "cc.y"
{
(yyval.tycl).t = simplet(typebitor((yyvsp[(2) - (3)].lval), (yyvsp[(3) - (3)].lval)));
@@ -3458,7 +3279,6 @@ yyreduce:
break;
case 193:
-/* Line 1787 of yacc.c */
#line 1013 "cc.y"
{
(yyval.type) = (yyvsp[(1) - (1)].tycl).t;
@@ -3468,7 +3288,6 @@ yyreduce:
break;
case 194:
-/* Line 1787 of yacc.c */
#line 1021 "cc.y"
{
lasttype = (yyvsp[(1) - (1)].tycl).t;
@@ -3477,7 +3296,6 @@ yyreduce:
break;
case 195:
-/* Line 1787 of yacc.c */
#line 1028 "cc.y"
{
dotag((yyvsp[(2) - (2)].sym), TSTRUCT, 0);
@@ -3486,7 +3304,6 @@ yyreduce:
break;
case 196:
-/* Line 1787 of yacc.c */
#line 1033 "cc.y"
{
dotag((yyvsp[(2) - (2)].sym), TSTRUCT, autobn);
@@ -3494,7 +3311,6 @@ yyreduce:
break;
case 197:
-/* Line 1787 of yacc.c */
#line 1037 "cc.y"
{
(yyval.type) = (yyvsp[(2) - (4)].sym)->suetag;
@@ -3506,9 +3322,9 @@ yyreduce:
break;
case 198:
-/* Line 1787 of yacc.c */
#line 1045 "cc.y"
{
+ diag(Z, "struct must have tag");
taggen++;
sprint(symb, "_%d_", taggen);
(yyval.type) = dotag(lookup(), TSTRUCT, autobn);
@@ -3518,8 +3334,7 @@ yyreduce:
break;
case 199:
-/* Line 1787 of yacc.c */
-#line 1053 "cc.y"
+#line 1054 "cc.y"
{
dotag((yyvsp[(2) - (2)].sym), TUNION, 0);
(yyval.type) = (yyvsp[(2) - (2)].sym)->suetag;
@@ -3527,16 +3342,14 @@ yyreduce:
break;
case 200:
-/* Line 1787 of yacc.c */
-#line 1058 "cc.y"
+#line 1059 "cc.y"
{
dotag((yyvsp[(2) - (2)].sym), TUNION, autobn);
}
break;
case 201:
-/* Line 1787 of yacc.c */
-#line 1062 "cc.y"
+#line 1063 "cc.y"
{
(yyval.type) = (yyvsp[(2) - (4)].sym)->suetag;
if((yyval.type)->link != T)
@@ -3547,8 +3360,7 @@ yyreduce:
break;
case 202:
-/* Line 1787 of yacc.c */
-#line 1070 "cc.y"
+#line 1071 "cc.y"
{
taggen++;
sprint(symb, "_%d_", taggen);
@@ -3559,8 +3371,7 @@ yyreduce:
break;
case 203:
-/* Line 1787 of yacc.c */
-#line 1078 "cc.y"
+#line 1079 "cc.y"
{
dotag((yyvsp[(2) - (2)].sym), TENUM, 0);
(yyval.type) = (yyvsp[(2) - (2)].sym)->suetag;
@@ -3571,16 +3382,14 @@ yyreduce:
break;
case 204:
-/* Line 1787 of yacc.c */
-#line 1086 "cc.y"
+#line 1087 "cc.y"
{
dotag((yyvsp[(2) - (2)].sym), TENUM, autobn);
}
break;
case 205:
-/* Line 1787 of yacc.c */
-#line 1090 "cc.y"
+#line 1091 "cc.y"
{
en.tenum = T;
en.cenum = T;
@@ -3588,8 +3397,7 @@ yyreduce:
break;
case 206:
-/* Line 1787 of yacc.c */
-#line 1095 "cc.y"
+#line 1096 "cc.y"
{
(yyval.type) = (yyvsp[(2) - (7)].sym)->suetag;
if((yyval.type)->link != T)
@@ -3604,8 +3412,7 @@ yyreduce:
break;
case 207:
-/* Line 1787 of yacc.c */
-#line 1107 "cc.y"
+#line 1108 "cc.y"
{
en.tenum = T;
en.cenum = T;
@@ -3613,186 +3420,158 @@ yyreduce:
break;
case 208:
-/* Line 1787 of yacc.c */
-#line 1112 "cc.y"
+#line 1113 "cc.y"
{
(yyval.type) = en.tenum;
}
break;
case 209:
-/* Line 1787 of yacc.c */
-#line 1116 "cc.y"
+#line 1117 "cc.y"
{
(yyval.type) = tcopy((yyvsp[(1) - (1)].sym)->type);
}
break;
case 211:
-/* Line 1787 of yacc.c */
-#line 1123 "cc.y"
+#line 1124 "cc.y"
{
(yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
}
break;
case 212:
-/* Line 1787 of yacc.c */
-#line 1128 "cc.y"
+#line 1129 "cc.y"
{
(yyval.lval) = 0;
}
break;
case 213:
-/* Line 1787 of yacc.c */
-#line 1132 "cc.y"
+#line 1133 "cc.y"
{
(yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
}
break;
case 218:
-/* Line 1787 of yacc.c */
-#line 1144 "cc.y"
+#line 1145 "cc.y"
{
(yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
}
break;
case 221:
-/* Line 1787 of yacc.c */
-#line 1154 "cc.y"
+#line 1155 "cc.y"
{
doenum((yyvsp[(1) - (1)].sym), Z);
}
break;
case 222:
-/* Line 1787 of yacc.c */
-#line 1158 "cc.y"
+#line 1159 "cc.y"
{
doenum((yyvsp[(1) - (3)].sym), (yyvsp[(3) - (3)].node));
}
break;
case 225:
-/* Line 1787 of yacc.c */
-#line 1165 "cc.y"
+#line 1166 "cc.y"
{ (yyval.lval) = BCHAR; }
break;
case 226:
-/* Line 1787 of yacc.c */
-#line 1166 "cc.y"
+#line 1167 "cc.y"
{ (yyval.lval) = BSHORT; }
break;
case 227:
-/* Line 1787 of yacc.c */
-#line 1167 "cc.y"
+#line 1168 "cc.y"
{ (yyval.lval) = BINT; }
break;
case 228:
-/* Line 1787 of yacc.c */
-#line 1168 "cc.y"
+#line 1169 "cc.y"
{ (yyval.lval) = BLONG; }
break;
case 229:
-/* Line 1787 of yacc.c */
-#line 1169 "cc.y"
+#line 1170 "cc.y"
{ (yyval.lval) = BSIGNED; }
break;
case 230:
-/* Line 1787 of yacc.c */
-#line 1170 "cc.y"
+#line 1171 "cc.y"
{ (yyval.lval) = BUNSIGNED; }
break;
case 231:
-/* Line 1787 of yacc.c */
-#line 1171 "cc.y"
+#line 1172 "cc.y"
{ (yyval.lval) = BFLOAT; }
break;
case 232:
-/* Line 1787 of yacc.c */
-#line 1172 "cc.y"
+#line 1173 "cc.y"
{ (yyval.lval) = BDOUBLE; }
break;
case 233:
-/* Line 1787 of yacc.c */
-#line 1173 "cc.y"
+#line 1174 "cc.y"
{ (yyval.lval) = BVOID; }
break;
case 234:
-/* Line 1787 of yacc.c */
-#line 1176 "cc.y"
+#line 1177 "cc.y"
{ (yyval.lval) = BAUTO; }
break;
case 235:
-/* Line 1787 of yacc.c */
-#line 1177 "cc.y"
+#line 1178 "cc.y"
{ (yyval.lval) = BSTATIC; }
break;
case 236:
-/* Line 1787 of yacc.c */
-#line 1178 "cc.y"
+#line 1179 "cc.y"
{ (yyval.lval) = BEXTERN; }
break;
case 237:
-/* Line 1787 of yacc.c */
-#line 1179 "cc.y"
+#line 1180 "cc.y"
{ (yyval.lval) = BTYPEDEF; }
break;
case 238:
-/* Line 1787 of yacc.c */
-#line 1180 "cc.y"
+#line 1181 "cc.y"
{ (yyval.lval) = BTYPESTR; }
break;
case 239:
-/* Line 1787 of yacc.c */
-#line 1181 "cc.y"
+#line 1182 "cc.y"
{ (yyval.lval) = BREGISTER; }
break;
case 240:
-/* Line 1787 of yacc.c */
-#line 1182 "cc.y"
+#line 1183 "cc.y"
{ (yyval.lval) = 0; }
break;
case 241:
-/* Line 1787 of yacc.c */
-#line 1185 "cc.y"
+#line 1186 "cc.y"
{ (yyval.lval) = BCONSTNT; }
break;
case 242:
-/* Line 1787 of yacc.c */
-#line 1186 "cc.y"
+#line 1187 "cc.y"
{ (yyval.lval) = BVOLATILE; }
break;
case 243:
-/* Line 1787 of yacc.c */
-#line 1187 "cc.y"
+#line 1188 "cc.y"
{ (yyval.lval) = 0; }
break;
case 244:
-/* Line 1787 of yacc.c */
-#line 1191 "cc.y"
+#line 1192 "cc.y"
{
(yyval.node) = new(ONAME, Z, Z);
if((yyvsp[(1) - (1)].sym)->class == CLOCAL)
@@ -3809,8 +3588,7 @@ yyreduce:
break;
case 245:
-/* Line 1787 of yacc.c */
-#line 1206 "cc.y"
+#line 1207 "cc.y"
{
(yyval.node) = new(ONAME, Z, Z);
(yyval.node)->sym = (yyvsp[(1) - (1)].sym);
@@ -3824,21 +3602,10 @@ yyreduce:
break;
-/* Line 1787 of yacc.c */
-#line 3829 "y.tab.c"
+/* Line 1267 of yacc.c. */
+#line 3607 "y.tab.c"
default: break;
}
- /* User semantic actions sometimes alter yychar, and that requires
- that yytoken be updated with the new translation. We take the
- approach of translating immediately before every use of yytoken.
- One alternative is translating here after every semantic action,
- but that translation would be missed if the semantic action invokes
- YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
- if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
- incorrect destructor might then be invoked immediately. In the
- case of YYERROR or YYBACKUP, subsequent parser actions might lead
- to an incorrect destructor call or verbose syntax error message
- before the lookahead is translated. */
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
YYPOPSTACK (yylen);
@@ -3847,6 +3614,7 @@ yyreduce:
*++yyvsp = yyval;
+
/* Now `shift' the result of the reduction. Determine what state
that goes to, based on the state we popped back to and the rule
number reduced by. */
@@ -3866,10 +3634,6 @@ yyreduce:
| yyerrlab -- here on detecting error |
`------------------------------------*/
yyerrlab:
- /* Make sure we have latest lookahead translation. See comments at
- user semantic actions for why this is necessary. */
- yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
@@ -3877,36 +3641,37 @@ yyerrlab:
#if ! YYERROR_VERBOSE
yyerror (YY_("syntax error"));
#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
- yyssp, yytoken)
{
- char const *yymsgp = YY_("syntax error");
- int yysyntax_error_status;
- yysyntax_error_status = YYSYNTAX_ERROR;
- if (yysyntax_error_status == 0)
- yymsgp = yymsg;
- else if (yysyntax_error_status == 1)
- {
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
- if (!yymsg)
- {
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- yysyntax_error_status = 2;
- }
- else
- {
- yysyntax_error_status = YYSYNTAX_ERROR;
- yymsgp = yymsg;
- }
- }
- yyerror (yymsgp);
- if (yysyntax_error_status == 2)
- goto yyexhaustedlab;
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
}
-# undef YYSYNTAX_ERROR
#endif
}
@@ -3914,7 +3679,7 @@ yyerrlab:
if (yyerrstatus == 3)
{
- /* If just tried and failed to reuse lookahead token after an
+ /* If just tried and failed to reuse look-ahead token after an
error, discard it. */
if (yychar <= YYEOF)
@@ -3931,7 +3696,7 @@ yyerrlab:
}
}
- /* Else will try to reuse lookahead token after shifting the error
+ /* Else will try to reuse look-ahead token after shifting the error
token. */
goto yyerrlab1;
@@ -3965,7 +3730,7 @@ yyerrlab1:
for (;;)
{
yyn = yypact[yystate];
- if (!yypact_value_is_default (yyn))
+ if (yyn != YYPACT_NINF)
{
yyn += YYTERROR;
if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
@@ -3988,9 +3753,10 @@ yyerrlab1:
YY_STACK_PRINT (yyss, yyssp);
}
- YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
*++yyvsp = yylval;
- YY_IGNORE_MAYBE_UNINITIALIZED_END
/* Shift the error token. */
@@ -4014,7 +3780,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
-#if !defined yyoverflow || YYERROR_VERBOSE
+#ifndef yyoverflow
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
@@ -4025,14 +3791,9 @@ yyexhaustedlab:
#endif
yyreturn:
- if (yychar != YYEMPTY)
- {
- /* Make sure we have latest lookahead translation. See comments at
- user semantic actions for why this is necessary. */
- yytoken = YYTRANSLATE (yychar);
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval);
- }
+ if (yychar != YYEOF && yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
/* Do not reclaim the symbols of the rule which action triggered
this YYABORT or YYACCEPT. */
YYPOPSTACK (yylen);
@@ -4056,6 +3817,6 @@ yyreturn:
}
-/* Line 2050 of yacc.c */
-#line 1219 "cc.y"
+#line 1220 "cc.y"
+
diff --git a/src/cmd/cc/y.tab.h b/src/cmd/cc/y.tab.h
index b26d659ef..32daca9b6 100644
--- a/src/cmd/cc/y.tab.h
+++ b/src/cmd/cc/y.tab.h
@@ -1,21 +1,24 @@
-/* A Bison parser, made by GNU Bison 2.7.12-4996. */
+/* A Bison parser, made by GNU Bison 2.3. */
-/* Bison interface for Yacc-like parsers in C
-
- Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -26,20 +29,10 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
-#ifndef YY_YY_Y_TAB_H_INCLUDED
-# define YY_YY_Y_TAB_H_INCLUDED
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -196,12 +189,11 @@ extern int yydebug;
+
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-{
-/* Line 2053 of yacc.c */
#line 36 "cc.y"
-
+{
Node* node;
Sym* sym;
Type* type;
@@ -225,30 +217,14 @@ typedef union YYSTYPE
int32 lval;
double dval;
vlong vval;
-
-
-/* Line 2053 of yacc.c */
-#line 232 "y.tab.h"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
+}
+/* Line 1529 of yacc.c. */
+#line 223 "y.tab.h"
+ YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !YY_YY_Y_TAB_H_INCLUDED */
diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go
index 7757efa1b..10e2278a1 100644
--- a/src/cmd/cgo/ast.go
+++ b/src/cmd/cgo/ast.go
@@ -272,7 +272,7 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
case nil:
- // These are ordered and grouped to match ../../pkg/go/ast/ast.go
+ // These are ordered and grouped to match ../../go/ast/ast.go
case *ast.Field:
if len(n.Names) == 0 && context == "field" {
f.walk(&n.Type, "embed-type", visit)
@@ -308,6 +308,9 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
if n.High != nil {
f.walk(&n.High, "expr", visit)
}
+ if n.Max != nil {
+ f.walk(&n.Max, "expr", visit)
+ }
case *ast.TypeAssertExpr:
f.walk(&n.X, "expr", visit)
f.walk(&n.Type, "type", visit)
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index 69c7ce893..6179c7afd 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -152,7 +152,7 @@ In C, a function argument written as a fixed size array
actually requires a pointer to the first element of the array.
C compilers are aware of this calling convention and adjust
the call accordingly, but Go cannot. In Go, you must pass
-the pointer to the first element explicitly: C.f(&x[0]).
+the pointer to the first element explicitly: C.f(&C.x[0]).
A few special functions convert between Go and C types
by making copies of the data. In pseudo-Go definitions:
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index f55cfbac4..abdd369d7 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -229,7 +229,8 @@ func (p *Package) guessKinds(f *File) []*Name {
// Determine kinds for names we already know about,
// like #defines or 'struct foo', before bothering with gcc.
var names, needType []*Name
- for _, n := range f.Name {
+ for _, key := range nameKeys(f.Name) {
+ n := f.Name[key]
// If we've already found this name as a #define
// and we can translate it as a constant value, do so.
if n.Define != "" {
@@ -331,6 +332,7 @@ func (p *Package) guessKinds(f *File) []*Name {
const (
notType = 1 << iota
notConst
+ notDeclared
)
for _, line := range strings.Split(stderr, "\n") {
if !strings.Contains(line, ": error:") {
@@ -365,7 +367,7 @@ func (p *Package) guessKinds(f *File) []*Name {
completed = true
case "not-declared":
- error_(token.NoPos, "%s", strings.TrimSpace(line[c2+1:]))
+ sniff[i] |= notDeclared
case "not-type":
sniff[i] |= notType
case "not-const":
@@ -374,12 +376,12 @@ func (p *Package) guessKinds(f *File) []*Name {
}
if !completed {
- fatalf("%s did not produce error at completed:1\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
+ fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", p.gccBaseCmd()[0], b.Bytes(), stderr)
}
for i, n := range names {
switch sniff[i] {
- case 0:
+ default:
error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
case notType:
n.Kind = "const"
@@ -390,6 +392,14 @@ func (p *Package) guessKinds(f *File) []*Name {
}
}
if nerrors > 0 {
+ // Check if compiling the preamble by itself causes any errors,
+ // because the messages we've printed out so far aren't helpful
+ // to users debugging preamble mistakes. See issue 8442.
+ preambleErrors := p.gccErrors([]byte(f.Preamble))
+ if len(preambleErrors) > 0 {
+ error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors)
+ }
+
fatalf("unresolved names")
}
@@ -649,7 +659,13 @@ func (p *Package) rewriteRef(f *File) {
f.Name[fpName] = name
}
r.Name = name
- expr = ast.NewIdent(name.Mangle)
+ // Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr
+ // function is defined in out.go and simply returns its argument. See
+ // issue 7757.
+ expr = &ast.CallExpr{
+ Fun: &ast.Ident{NamePos: (*r.Expr).Pos(), Name: "_Cgo_ptr"},
+ Args: []ast.Expr{ast.NewIdent(name.Mangle)},
+ }
} else if r.Name.Kind == "type" {
// Okay - might be new(T)
expr = r.Name.Type.Go
@@ -928,9 +944,8 @@ type typeConv struct {
// Map from types to incomplete pointers to those types.
ptrs map[dwarf.Type][]*Type
-
- // Fields to be processed by godefsField after completing pointers.
- todoFlds [][]*ast.Field
+ // Keys of ptrs in insertion order (deterministic worklist)
+ ptrKeys []dwarf.Type
// Predeclared types.
bool ast.Expr
@@ -940,9 +955,9 @@ type typeConv struct {
float32, float64 ast.Expr
complex64, complex128 ast.Expr
void ast.Expr
- unsafePointer ast.Expr
string ast.Expr
goVoid ast.Expr // _Ctype_void, denotes C's void
+ goVoidPtr ast.Expr // unsafe.Pointer or *byte
ptrSize int64
intSize int64
@@ -972,10 +987,17 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
c.float64 = c.Ident("float64")
c.complex64 = c.Ident("complex64")
c.complex128 = c.Ident("complex128")
- c.unsafePointer = c.Ident("unsafe.Pointer")
c.void = c.Ident("void")
c.string = c.Ident("string")
c.goVoid = c.Ident("_Ctype_void")
+
+ // Normally cgo translates void* to unsafe.Pointer,
+ // but for historical reasons -cdefs and -godefs use *byte instead.
+ if *cdefs || *godefs {
+ c.goVoidPtr = &ast.StarExpr{X: c.byte}
+ } else {
+ c.goVoidPtr = c.Ident("unsafe.Pointer")
+ }
}
// base strips away qualifiers and typedefs to get the underlying type
@@ -1037,29 +1059,22 @@ func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
}
// FinishType completes any outstanding type mapping work.
-// In particular, it resolves incomplete pointer types and also runs
-// godefsFields on any new struct types.
+// In particular, it resolves incomplete pointer types.
func (c *typeConv) FinishType(pos token.Pos) {
// Completing one pointer type might produce more to complete.
// Keep looping until they're all done.
- for len(c.ptrs) > 0 {
- for dtype := range c.ptrs {
- // Note Type might invalidate c.ptrs[dtype].
- t := c.Type(dtype, pos)
- for _, ptr := range c.ptrs[dtype] {
- ptr.Go.(*ast.StarExpr).X = t.Go
- ptr.C.Set("%s*", t.C)
- }
- delete(c.ptrs, dtype)
- }
- }
+ for len(c.ptrKeys) > 0 {
+ dtype := c.ptrKeys[0]
+ c.ptrKeys = c.ptrKeys[1:]
- // Now that pointer types are completed, we can invoke godefsFields
- // to rewrite struct definitions.
- for _, fld := range c.todoFlds {
- godefsFields(fld)
+ // Note Type might invalidate c.ptrs[dtype].
+ t := c.Type(dtype, pos)
+ for _, ptr := range c.ptrs[dtype] {
+ ptr.Go.(*ast.StarExpr).X = t.Go
+ ptr.C.Set("%s*", t.C)
+ }
+ c.ptrs[dtype] = nil // retain the map key
}
- c.todoFlds = nil
}
// Type returns a *Type with the same memory layout as
@@ -1072,12 +1087,6 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
return t
}
- // clang won't generate DW_AT_byte_size for pointer types,
- // so we have to fix it here.
- if dt, ok := base(dtype).(*dwarf.PtrType); ok && dt.ByteSize == -1 {
- dt.ByteSize = c.ptrSize
- }
-
t := new(Type)
t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
t.Align = -1
@@ -1101,12 +1110,20 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
t.Go = c.Opaque(t.Size)
break
}
+ count := dt.Count
+ if count == -1 {
+ // Indicates flexible array member, which Go doesn't support.
+ // Translate to zero-length array instead.
+ count = 0
+ }
sub := c.Type(dt.Type, pos)
t.Align = sub.Align
t.Go = &ast.ArrayType{
- Len: c.intExpr(dt.Count),
+ Len: c.intExpr(count),
Elt: sub.Go,
}
+ // Recalculate t.Size now that we know sub.Size.
+ t.Size = count * sub.Size
t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
case *dwarf.BoolType:
@@ -1207,11 +1224,15 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
}
case *dwarf.PtrType:
+ // Clang doesn't emit DW_AT_byte_size for pointer types.
+ if t.Size != c.ptrSize && t.Size != -1 {
+ fatalf("%s: unexpected: %d-byte pointer type - %s", lineno(pos), t.Size, dtype)
+ }
+ t.Size = c.ptrSize
t.Align = c.ptrSize
- // Translate void* as unsafe.Pointer
if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
- t.Go = c.unsafePointer
+ t.Go = c.goVoidPtr
t.C.Set("void*")
break
}
@@ -1219,6 +1240,9 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
// Placeholder initialization; completed in FinishType.
t.Go = &ast.StarExpr{}
t.C.Set("<incomplete>*")
+ if _, ok := c.ptrs[dt.Type]; !ok {
+ c.ptrKeys = append(c.ptrKeys, dt.Type)
+ }
c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t)
case *dwarf.QualType:
@@ -1379,34 +1403,24 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
}
}
- if t.Size <= 0 {
- // Clang does not record the size of a pointer in its DWARF entry,
- // so if dtype is an array, the call to dtype.Size at the top of the function
- // computed the size as the array length * 0 = 0.
- // The type switch called Type (this function) recursively on the pointer
- // entry, and the code near the top of the function updated the size to
- // be correct, so calling dtype.Size again will produce the correct value.
- t.Size = dtype.Size()
- if t.Size < 0 {
- // Unsized types are [0]byte, unless they're typedefs of other types
- // or structs with tags.
- // if so, use the name we've already defined.
- t.Size = 0
- switch dt := dtype.(type) {
- case *dwarf.TypedefType:
- // ok
- case *dwarf.StructType:
- if dt.StructName != "" {
- break
- }
- t.Go = c.Opaque(0)
- default:
- t.Go = c.Opaque(0)
- }
- if t.C.Empty() {
- t.C.Set("void")
+ if t.Size < 0 {
+ // Unsized types are [0]byte, unless they're typedefs of other types
+ // or structs with tags.
+ // if so, use the name we've already defined.
+ t.Size = 0
+ switch dt := dtype.(type) {
+ case *dwarf.TypedefType:
+ // ok
+ case *dwarf.StructType:
+ if dt.StructName != "" {
+ break
}
- return t
+ t.Go = c.Opaque(0)
+ default:
+ t.Go = c.Opaque(0)
+ }
+ if t.C.Empty() {
+ t.C.Set("void")
}
}
@@ -1538,6 +1552,9 @@ func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field {
// Struct conversion: return Go and (6g) C syntax for type.
func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
+ // Minimum alignment for a struct is 1 byte.
+ align = 1
+
var buf bytes.Buffer
buf.WriteString("struct {")
fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
@@ -1579,7 +1596,27 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
fld = c.pad(fld, f.ByteOffset-off)
off = f.ByteOffset
}
- t := c.Type(f.Type, pos)
+
+ name := f.Name
+ ft := f.Type
+
+ // In godefs or cdefs mode, if this field is a C11
+ // anonymous union then treat the first field in the
+ // union as the field in the struct. This handles
+ // cases like the glibc <sys/resource.h> file; see
+ // issue 6677.
+ if *godefs || *cdefs {
+ if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] {
+ name = st.Field[0].Name
+ ident[name] = name
+ ft = st.Field[0].Type
+ }
+ }
+
+ // TODO: Handle fields that are anonymous structs by
+ // promoting the fields of the inner struct.
+
+ t := c.Type(ft, pos)
tgo := t.Go
size := t.Size
talign := t.Align
@@ -1598,17 +1635,18 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
talign = size
}
- if talign > 0 && f.ByteOffset%talign != 0 {
+ if talign > 0 && f.ByteOffset%talign != 0 && !*cdefs {
// Drop misaligned fields, the same way we drop integer bit fields.
// The goal is to make available what can be made available.
// Otherwise one bad and unneeded field in an otherwise okay struct
// makes the whole program not compile. Much of the time these
// structs are in system headers that cannot be corrected.
+ // Exception: In -cdefs mode, we use #pragma pack, so misaligned
+ // fields should still work.
continue
}
n := len(fld)
fld = fld[0 : n+1]
- name := f.Name
if name == "" {
name = fmt.Sprintf("anon%d", anon)
anon++
@@ -1635,7 +1673,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
csyntax = buf.String()
if *godefs || *cdefs {
- c.todoFlds = append(c.todoFlds, fld)
+ godefsFields(fld)
}
expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
return
@@ -1673,19 +1711,6 @@ func godefsFields(fld []*ast.Field) {
n.Name = upper(n.Name)
}
}
- p := &f.Type
- t := *p
- if star, ok := t.(*ast.StarExpr); ok {
- star = &ast.StarExpr{X: star.X}
- *p = star
- p = &star.X
- t = *p
- }
- if id, ok := t.(*ast.Ident); ok {
- if id.Name == "unsafe.Pointer" {
- *p = ast.NewIdent("*byte")
- }
- }
}
}
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 76c7247af..d92bed9bf 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -44,6 +44,7 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fm, "int main() { return 0; }\n")
if *importRuntimeCgo {
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
+ fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
} else {
// If we're not importing runtime/cgo, we *are* runtime/cgo,
// which provides crosscall2. We just need a prototype.
@@ -58,16 +59,14 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n")
fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
- if *importSyscall {
- fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
- }
if !*gccgo && *importRuntimeCgo {
fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
}
- fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n")
if *importSyscall {
- fmt.Fprintf(fgo2, "func _Cerrno(dst *error, x int32) { *dst = syscall.Errno(x) }\n")
+ fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
+ fmt.Fprintf(fgo2, "var _ syscall.Errno\n")
}
+ fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n")
typedefNames := make([]string, 0, len(typedef))
for name := range typedef {
@@ -87,9 +86,10 @@ func (p *Package) writeDefs() {
}
if *gccgo {
- fmt.Fprintf(fc, p.cPrologGccgo())
+ fmt.Fprint(fc, p.cPrologGccgo())
} else {
- fmt.Fprintf(fc, cProlog)
+ fmt.Fprint(fc, cProlog)
+ fmt.Fprint(fgo2, goProlog)
}
gccgoSymbolPrefix := p.gccgoSymbolPrefix()
@@ -130,6 +130,7 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C)
} else {
+ fmt.Fprintf(fc, "#pragma dataflag NOPTR /* C pointer, not heap pointer */ \n")
fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n.C)
}
fmt.Fprintf(fc, "\n")
@@ -296,10 +297,6 @@ func (p *Package) structType(n *Name) (string, int64) {
fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
off += pad
}
- if n.AddError {
- fmt.Fprint(&buf, "\t\tint e[2*sizeof(void *)/sizeof(int)]; /* error */\n")
- off += 2 * p.PtrSize
- }
if off == 0 {
fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct
}
@@ -334,19 +331,18 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
}
// Builtins defined in the C prolog.
- inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" || name == "_CMalloc"
+ inProlog := builtinDefs[name] != ""
+ cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
+ paramnames := []string(nil)
+ for i, param := range d.Type.Params.List {
+ paramName := fmt.Sprintf("p%d", i)
+ param.Names = []*ast.Ident{ast.NewIdent(paramName)}
+ paramnames = append(paramnames, paramName)
+ }
if *gccgo {
// Gccgo style hooks.
fmt.Fprint(fgo2, "\n")
- cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
- paramnames := []string(nil)
- for i, param := range d.Type.Params.List {
- paramName := fmt.Sprintf("p%d", i)
- param.Names = []*ast.Ident{ast.NewIdent(paramName)}
- paramnames = append(paramnames, paramName)
- }
-
conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, " {\n")
if !inProlog {
@@ -383,7 +379,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
fmt.Fprint(fgo2, "}\n")
// declare the C function.
- fmt.Fprintf(fgo2, "//extern _cgo%s%s\n", cPrefix, n.Mangle)
+ fmt.Fprintf(fgo2, "//extern %s\n", cname)
d.Name = ast.NewIdent(cname)
if n.AddError {
l := d.Type.Results.List
@@ -394,61 +390,50 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
return
}
- conf.Fprint(fgo2, fset, d)
- fmt.Fprint(fgo2, "\n")
if inProlog {
+ fmt.Fprint(fgo2, builtinDefs[name])
return
}
- var argSize int64
- _, argSize = p.structType(n)
-
// C wrapper calls into gcc, passing a pointer to the argument frame.
- fmt.Fprintf(fc, "#pragma cgo_import_static _cgo%s%s\n", cPrefix, n.Mangle)
- fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle)
- fmt.Fprintf(fc, "\n")
- fmt.Fprintf(fc, "void\n")
- if argSize == 0 {
- argSize++
+ fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", cname)
+ fmt.Fprintf(fc, "void %s(void*);\n", cname)
+ fmt.Fprintf(fc, "#pragma dataflag NOPTR\n")
+ fmt.Fprintf(fc, "void *·%s = %s;\n", cname, cname)
+
+ nret := 0
+ if !void {
+ d.Type.Results.List[0].Names = []*ast.Ident{ast.NewIdent("r1")}
+ nret = 1
}
- // TODO(rsc): The struct here should declare pointers only where
- // there are pointers in the actual argument frame.
- // This is a workaround for golang.org/issue/6397.
- fmt.Fprintf(fc, "·%s(struct{", n.Mangle)
- if n := argSize / p.PtrSize; n > 0 {
- fmt.Fprintf(fc, "void *y[%d];", n)
+ if n.AddError {
+ d.Type.Results.List[nret].Names = []*ast.Ident{ast.NewIdent("r2")}
}
- if n := argSize % p.PtrSize; n > 0 {
- fmt.Fprintf(fc, "uint8 x[%d];", n)
+
+ fmt.Fprint(fgo2, "\n")
+ fmt.Fprintf(fgo2, "var %s unsafe.Pointer\n", cname)
+ conf.Fprint(fgo2, fset, d)
+ fmt.Fprint(fgo2, " {\n")
+
+ // NOTE: Using uintptr to hide from escape analysis.
+ arg := "0"
+ if len(paramnames) > 0 {
+ arg = "uintptr(unsafe.Pointer(&p0))"
+ } else if !void {
+ arg = "uintptr(unsafe.Pointer(&r1))"
}
- fmt.Fprintf(fc, "}p)\n")
- fmt.Fprintf(fc, "{\n")
- fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle)
+
+ prefix := ""
if n.AddError {
- // gcc leaves errno in first word of interface at end of p.
- // check whether it is zero; if so, turn interface into nil.
- // if not, turn interface into errno.
- // Go init function initializes ·_Cerrno with an os.Errno
- // for us to copy.
- fmt.Fprintln(fc, ` {
- int32 e;
- void **v;
- v = (void**)(&p+1) - 2; /* v = final two void* of p */
- e = *(int32*)v;
- v[0] = (void*)0xdeadbeef;
- v[1] = (void*)0xdeadbeef;
- if(e == 0) {
- /* nil interface */
- v[0] = 0;
- v[1] = 0;
- } else {
- ·_Cerrno(v, e); /* fill in v as error for errno e */
- }
- }`)
+ prefix = "errno := "
}
- fmt.Fprintf(fc, "}\n")
- fmt.Fprintf(fc, "\n")
+ fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall_errno(%s, %s)\n", prefix, cname, arg)
+ if n.AddError {
+ fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n")
+ }
+ fmt.Fprintf(fgo2, "\treturn\n")
+ fmt.Fprintf(fgo2, "}\n")
}
// writeOutput creates stubs for a specific source file to be compiled by 6g
@@ -521,7 +506,11 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
// Gcc wrapper unpacks the C argument struct
// and calls the actual C function.
- fmt.Fprintf(fgcc, "void\n")
+ if n.AddError {
+ fmt.Fprintf(fgcc, "int\n")
+ } else {
+ fmt.Fprintf(fgcc, "void\n")
+ }
fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
fmt.Fprintf(fgcc, "{\n")
if n.AddError {
@@ -531,9 +520,13 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
// Use packed attribute to force no padding in this struct in case
// gcc has different packing requirements.
fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute())
+ if n.FuncType.Result != nil {
+ // Save the stack top for use below.
+ fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n")
+ }
fmt.Fprintf(fgcc, "\t")
if t := n.FuncType.Result; t != nil {
- fmt.Fprintf(fgcc, "a->r = ")
+ fmt.Fprintf(fgcc, "__typeof__(a->r) r = ")
if c := t.C.String(); c[len(c)-1] == '*' {
fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
}
@@ -556,8 +549,15 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
fmt.Fprintf(fgcc, "a->p%d", i)
}
fmt.Fprintf(fgcc, ");\n")
+ if n.FuncType.Result != nil {
+ // The cgo call may have caused a stack copy (via a callback).
+ // Adjust the return value pointer appropriately.
+ fmt.Fprintf(fgcc, "\ta = (void*)((char*)a + (_cgo_topofstack() - stktop));\n")
+ // Save the return value.
+ fmt.Fprintf(fgcc, "\ta->r = r;\n")
+ }
if n.AddError {
- fmt.Fprintf(fgcc, "\t*(int*)(a->e) = errno;\n")
+ fmt.Fprintf(fgcc, "\treturn errno;\n")
}
fmt.Fprintf(fgcc, "}\n")
fmt.Fprintf(fgcc, "\n")
@@ -1016,7 +1016,7 @@ func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) {
fn(i, r.Type)
i++
} else {
- for _ = range r.Names {
+ for range r.Names {
fn(i, r.Type)
i++
}
@@ -1143,21 +1143,17 @@ __cgo_size_assert(__cgo_long_long, 8)
__cgo_size_assert(float, 4)
__cgo_size_assert(double, 8)
+extern char* _cgo_topofstack(void);
+
#include <errno.h>
#include <string.h>
`
const builtinProlog = `
-#include <sys/types.h> /* for size_t below */
+#include <stddef.h> /* for ptrdiff_t and size_t below */
/* Define intgo when compiling with GCC. */
-#ifdef __PTRDIFF_TYPE__
-typedef __PTRDIFF_TYPE__ intgo;
-#elif defined(_LP64)
-typedef long long intgo;
-#else
-typedef int intgo;
-#endif
+typedef ptrdiff_t intgo;
typedef struct { char *p; intgo n; } _GoString_;
typedef struct { char *p; intgo n; intgo c; } _GoBytes_;
@@ -1171,47 +1167,86 @@ void *_CMalloc(size_t);
const cProlog = `
#include "runtime.h"
#include "cgocall.h"
+#include "textflag.h"
+
+#pragma dataflag NOPTR
+static void *cgocall_errno = runtime·cgocall_errno;
+#pragma dataflag NOPTR
+void *·_cgo_runtime_cgocall_errno = &cgocall_errno;
+
+#pragma dataflag NOPTR
+static void *runtime_gostring = runtime·gostring;
+#pragma dataflag NOPTR
+void *·_cgo_runtime_gostring = &runtime_gostring;
+
+#pragma dataflag NOPTR
+static void *runtime_gostringn = runtime·gostringn;
+#pragma dataflag NOPTR
+void *·_cgo_runtime_gostringn = &runtime_gostringn;
+
+#pragma dataflag NOPTR
+static void *runtime_gobytes = runtime·gobytes;
+#pragma dataflag NOPTR
+void *·_cgo_runtime_gobytes = &runtime_gobytes;
+
+#pragma dataflag NOPTR
+static void *runtime_cmalloc = runtime·cmalloc;
+#pragma dataflag NOPTR
+void *·_cgo_runtime_cmalloc = &runtime_cmalloc;
void ·_Cerrno(void*, int32);
+`
-void
-·_Cfunc_GoString(int8 *p, String s)
-{
- s = runtime·gostring((byte*)p);
- FLUSH(&s);
+const goProlog = `
+var _cgo_runtime_cgocall_errno func(unsafe.Pointer, uintptr) int32
+var _cgo_runtime_cmalloc func(uintptr) unsafe.Pointer
+`
+
+const goStringDef = `
+var _cgo_runtime_gostring func(*_Ctype_char) string
+func _Cfunc_GoString(p *_Ctype_char) string {
+ return _cgo_runtime_gostring(p)
}
+`
-void
-·_Cfunc_GoStringN(int8 *p, int32 l, String s)
-{
- s = runtime·gostringn((byte*)p, l);
- FLUSH(&s);
+const goStringNDef = `
+var _cgo_runtime_gostringn func(*_Ctype_char, int) string
+func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
+ return _cgo_runtime_gostringn(p, int(l))
}
+`
-void
-·_Cfunc_GoBytes(int8 *p, int32 l, Slice s)
-{
- s = runtime·gobytes((byte*)p, l);
- FLUSH(&s);
+const goBytesDef = `
+var _cgo_runtime_gobytes func(unsafe.Pointer, int) []byte
+func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
+ return _cgo_runtime_gobytes(p, int(l))
}
+`
-void
-·_Cfunc_CString(String s, int8 *p)
-{
- p = runtime·cmalloc(s.len+1);
- runtime·memmove((byte*)p, s.str, s.len);
- p[s.len] = 0;
- FLUSH(&p);
+const cStringDef = `
+func _Cfunc_CString(s string) *_Ctype_char {
+ p := _cgo_runtime_cmalloc(uintptr(len(s)+1))
+ pp := (*[1<<30]byte)(p)
+ copy(pp[:], s)
+ pp[len(s)] = 0
+ return (*_Ctype_char)(p)
}
+`
-void
-·_Cfunc__CMalloc(uintptr n, int8 *p)
-{
- p = runtime·cmalloc(n);
- FLUSH(&p);
+const cMallocDef = `
+func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer {
+ return _cgo_runtime_cmalloc(uintptr(n))
}
`
+var builtinDefs = map[string]string{
+ "GoString": goStringDef,
+ "GoStringN": goStringNDef,
+ "GoBytes": goBytesDef,
+ "CString": cStringDef,
+ "_CMalloc": cMallocDef,
+}
+
func (p *Package) cPrologGccgo() string {
return strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1)
}
diff --git a/src/cmd/dist/a.h b/src/cmd/dist/a.h
index 6222e5060..288063b94 100644
--- a/src/cmd/dist/a.h
+++ b/src/cmd/dist/a.h
@@ -108,9 +108,6 @@ void mkzexperiment(char*, char*);
// buildgo.c
void mkzdefaultcc(char*, char*);
-// goc2c.c
-void goc2c(char*, char*);
-
// main.c
extern int vflag;
extern int sflag;
@@ -129,6 +126,7 @@ bool isfile(char *p);
char* lastelem(char*);
Time mtime(char*);
void readfile(Buf*, char*);
+void copyfile(char*, char*, int);
void run(Buf *b, char *dir, int mode, char *cmd, ...);
void runv(Buf *b, char *dir, int mode, Vec *argv);
void bgrunv(char *dir, int mode, Vec *argv);
diff --git a/src/cmd/dist/arm.c b/src/cmd/dist/arm.c
index 52a621c5d..1ce7b7710 100644
--- a/src/cmd/dist/arm.c
+++ b/src/cmd/dist/arm.c
@@ -21,7 +21,8 @@ xgetgoarm(void)
// FreeBSD has broken VFP support
return "5";
#endif
- if(xtryexecfunc(useVFPv3))
+ // NaCl always has VFP support.
+ if(streq(goos, "nacl") || xtryexecfunc(useVFPv3))
return "7";
else if(xtryexecfunc(useVFPv1))
return "6";
diff --git a/src/cmd/dist/buf.c b/src/cmd/dist/buf.c
index 45fb1954d..2ddc6be75 100644
--- a/src/cmd/dist/buf.c
+++ b/src/cmd/dist/buf.c
@@ -202,7 +202,7 @@ vadd(Vec *v, char *p)
}
// vaddn adds a string consisting of the n bytes at p to the vector.
-void
+static void
vaddn(Vec *v, char *p, int n)
{
char *q;
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index 6884e0aae..d638ae4eb 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -35,7 +35,6 @@ bool rebuildall;
bool defaultclang;
static bool shouldbuild(char*, char*);
-static void copy(char*, char*, int);
static void dopack(char*, char*, char**, int);
static char *findgoversion(void);
@@ -56,6 +55,7 @@ static char *okgoos[] = {
"darwin",
"dragonfly",
"linux",
+ "android",
"solaris",
"freebsd",
"nacl",
@@ -366,8 +366,8 @@ static char *oldtool[] = {
// not be in release branches.
static char *unreleased[] = {
"src/cmd/link",
- "src/pkg/debug/goobj",
- "src/pkg/old",
+ "src/debug/goobj",
+ "src/old",
};
// setup sets up the tree for the initial build.
@@ -590,7 +590,7 @@ static struct {
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libbio.a",
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/lib9.a",
}},
- {"pkg/runtime", {
+ {"runtime", {
"zaexperiment.h", // must sort above zasm
"zasm_$GOOS_$GOARCH.h",
"zsys_$GOOS_$GOARCH.s",
@@ -607,7 +607,6 @@ char *depsuffix[] = {
".h",
".s",
".go",
- ".goc",
};
// gentab records how to generate some trivial files.
@@ -639,7 +638,7 @@ install(char *dir)
{
char *name, *p, *elem, *prefix, *exe;
bool islib, ispkg, isgo, stale, ispackcmd;
- Buf b, b1, path;
+ Buf b, b1, path, final_path, final_name;
Vec compile, files, link, go, missing, clean, lib, extra;
Time ttarg, t;
int i, j, k, n, doclean, targ;
@@ -654,6 +653,8 @@ install(char *dir)
binit(&b);
binit(&b1);
binit(&path);
+ binit(&final_path);
+ binit(&final_name);
vinit(&compile);
vinit(&files);
vinit(&link);
@@ -666,15 +667,9 @@ install(char *dir)
// path = full path to dir.
bpathf(&path, "%s/src/%s", goroot, dir);
+ bpathf(&final_path, "%s/src/%s", goroot_final, dir);
name = lastelem(dir);
- // For misc/prof, copy into the tool directory and we're done.
- if(hasprefix(dir, "misc/")) {
- copy(bpathf(&b, "%s/%s", tooldir, name),
- bpathf(&b1, "%s/misc/%s", goroot, name), 1);
- goto out;
- }
-
// set up gcc command line on first run.
if(gccargs.len == 0) {
bprintf(&b, "%s %s", defaultcc, defaultcflags);
@@ -704,7 +699,7 @@ install(char *dir)
}
islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc");
- ispkg = hasprefix(dir, "pkg");
+ ispkg = !islib && !hasprefix(dir, "cmd/");
isgo = ispkg || streq(dir, "cmd/go") || streq(dir, "cmd/cgo");
exe = "";
@@ -730,11 +725,11 @@ install(char *dir)
// Go library (package).
ispackcmd = 1;
vadd(&link, "pack"); // program name - unused here, but all the other cases record one
- p = bprintf(&b, "%s/pkg/%s_%s/%s", goroot, goos, goarch, dir+4);
+ p = bprintf(&b, "%s/pkg/%s_%s/%s", goroot, goos, goarch, dir);
*xstrrchr(p, '/') = '\0';
xmkdirall(p);
targ = link.len;
- vadd(&link, bpathf(&b, "%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir+4));
+ vadd(&link, bpathf(&b, "%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir));
} else if(streq(dir, "cmd/go") || streq(dir, "cmd/cgo")) {
// Go command.
vadd(&link, bpathf(&b, "%s/%sl", tooldir, gochar));
@@ -881,18 +876,22 @@ install(char *dir)
goto out;
// For package runtime, copy some files into the work space.
- if(streq(dir, "pkg/runtime")) {
- copy(bpathf(&b, "%s/arch_GOARCH.h", workdir),
+ if(streq(dir, "runtime")) {
+ copyfile(bpathf(&b, "%s/arch_GOARCH.h", workdir),
bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0);
- copy(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
+ copyfile(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0);
p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch);
if(isfile(p))
- copy(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
- copy(bpathf(&b, "%s/os_GOOS.h", workdir),
+ copyfile(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
+ copyfile(bpathf(&b, "%s/os_GOOS.h", workdir),
bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0);
- copy(bpathf(&b, "%s/signals_GOOS.h", workdir),
+ copyfile(bpathf(&b, "%s/signals_GOOS.h", workdir),
bpathf(&b1, "%s/signals_%s.h", bstr(&path), goos), 0);
+ copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
+ bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0);
+ copyfile(bpathf(&b, "%s/pkg/%s_%s/funcdata.h", goroot, goos, goarch),
+ bpathf(&b1, "%s/src/runtime/funcdata.h", goroot), 0);
}
// Generate any missing files; regenerate existing ones.
@@ -907,7 +906,7 @@ install(char *dir)
errprintf("generate %s\n", p);
gentab[j].gen(bstr(&path), p);
// Do not add generated file to clean list.
- // In pkg/runtime, we want to be able to
+ // In runtime, we want to be able to
// build the package with the go tool,
// and it assumes these generated files already
// exist (it does not know how to build them).
@@ -925,27 +924,11 @@ install(char *dir)
// One more copy for package runtime.
// The last batch was required for the generators.
// This one is generated.
- if(streq(dir, "pkg/runtime")) {
- copy(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir),
+ if(streq(dir, "runtime")) {
+ copyfile(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir),
bpathf(&b1, "%s/zasm_%s_%s.h", bstr(&path), goos, goarch), 0);
}
- // Generate .c files from .goc files.
- if(streq(dir, "pkg/runtime")) {
- for(i=0; i<files.len; i++) {
- p = files.p[i];
- if(!hassuffix(p, ".goc"))
- continue;
- // b = path/zp but with _goos_goarch.c instead of .goc
- bprintf(&b, "%s%sz%s", bstr(&path), slash, lastelem(p));
- b.len -= 4;
- bwritef(&b, "_%s_%s.c", goos, goarch);
- goc2c(p, bstr(&b));
- vadd(&files, bstr(&b));
- }
- vuniq(&files);
- }
-
if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
// We've generated the right files; the go command can do the build.
if(vflag > 1)
@@ -1086,7 +1069,7 @@ install(char *dir)
else
vadd(&compile, "main");
- if(streq(dir, "pkg/runtime"))
+ if(streq(dir, "runtime"))
vadd(&compile, "-+");
vcopy(&compile, go.p, go.len);
@@ -1115,11 +1098,11 @@ install(char *dir)
nobuild:
// In package runtime, we install runtime.h and cgocall.h too,
// for use by cgo compilation.
- if(streq(dir, "pkg/runtime")) {
- copy(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch),
- bpathf(&b1, "%s/src/pkg/runtime/cgocall.h", goroot), 0);
- copy(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch),
- bpathf(&b1, "%s/src/pkg/runtime/runtime.h", goroot), 0);
+ if(streq(dir, "runtime")) {
+ copyfile(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch),
+ bpathf(&b1, "%s/src/runtime/cgocall.h", goroot), 0);
+ copyfile(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch),
+ bpathf(&b1, "%s/src/runtime/runtime.h", goroot), 0);
}
@@ -1149,7 +1132,7 @@ matchfield(char *f)
p = xstrrchr(f, ',');
if(p == nil)
- return streq(f, goos) || streq(f, goarch) || streq(f, "cmd_go_bootstrap") || streq(f, "go1.1");
+ return streq(f, goos) || streq(f, goarch) || streq(f, "cmd_go_bootstrap") || streq(f, "go1.1") || (streq(goos, "android") && streq(f, "linux"));
*p = 0;
res = matchfield(f) && matchfield(p+1);
*p = ',';
@@ -1241,8 +1224,8 @@ out:
}
// copy copies the file src to dst, via memory (so only good for small files).
-static void
-copy(char *dst, char *src, int exec)
+void
+copyfile(char *dst, char *src, int exec)
{
Buf b;
@@ -1303,8 +1286,6 @@ static char *buildorder[] = {
"libbio",
"liblink",
- "misc/pprof",
-
"cmd/cc", // must be before c
"cmd/gc", // must be before g
"cmd/%sl", // must be before a, c, g
@@ -1316,47 +1297,47 @@ static char *buildorder[] = {
// back when there were build scripts. Will have to
// be maintained by hand, but shouldn't change very
// often.
- "pkg/runtime",
- "pkg/errors",
- "pkg/sync/atomic",
- "pkg/sync",
- "pkg/io",
- "pkg/unicode",
- "pkg/unicode/utf8",
- "pkg/unicode/utf16",
- "pkg/bytes",
- "pkg/math",
- "pkg/strings",
- "pkg/strconv",
- "pkg/bufio",
- "pkg/sort",
- "pkg/container/heap",
- "pkg/encoding/base64",
- "pkg/syscall",
- "pkg/time",
- "pkg/os",
- "pkg/reflect",
- "pkg/fmt",
- "pkg/encoding",
- "pkg/encoding/json",
- "pkg/flag",
- "pkg/path/filepath",
- "pkg/path",
- "pkg/io/ioutil",
- "pkg/log",
- "pkg/regexp/syntax",
- "pkg/regexp",
- "pkg/go/token",
- "pkg/go/scanner",
- "pkg/go/ast",
- "pkg/go/parser",
- "pkg/os/exec",
- "pkg/os/signal",
- "pkg/net/url",
- "pkg/text/template/parse",
- "pkg/text/template",
- "pkg/go/doc",
- "pkg/go/build",
+ "runtime",
+ "errors",
+ "sync/atomic",
+ "sync",
+ "io",
+ "unicode",
+ "unicode/utf8",
+ "unicode/utf16",
+ "bytes",
+ "math",
+ "strings",
+ "strconv",
+ "bufio",
+ "sort",
+ "container/heap",
+ "encoding/base64",
+ "syscall",
+ "time",
+ "os",
+ "reflect",
+ "fmt",
+ "encoding",
+ "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",
"cmd/go",
};
@@ -1364,6 +1345,7 @@ static char *buildorder[] = {
// It is bigger than the buildorder because we clean all the
// compilers but build only the $GOARCH ones.
static char *cleantab[] = {
+ // Commands and C libraries.
"cmd/5a",
"cmd/5c",
"cmd/5g",
@@ -1382,46 +1364,48 @@ static char *cleantab[] = {
"lib9",
"libbio",
"liblink",
- "pkg/bufio",
- "pkg/bytes",
- "pkg/container/heap",
- "pkg/encoding",
- "pkg/encoding/base64",
- "pkg/encoding/json",
- "pkg/errors",
- "pkg/flag",
- "pkg/fmt",
- "pkg/go/ast",
- "pkg/go/build",
- "pkg/go/doc",
- "pkg/go/parser",
- "pkg/go/scanner",
- "pkg/go/token",
- "pkg/io",
- "pkg/io/ioutil",
- "pkg/log",
- "pkg/math",
- "pkg/net/url",
- "pkg/os",
- "pkg/os/exec",
- "pkg/path",
- "pkg/path/filepath",
- "pkg/reflect",
- "pkg/regexp",
- "pkg/regexp/syntax",
- "pkg/runtime",
- "pkg/sort",
- "pkg/strconv",
- "pkg/strings",
- "pkg/sync",
- "pkg/sync/atomic",
- "pkg/syscall",
- "pkg/text/template",
- "pkg/text/template/parse",
- "pkg/time",
- "pkg/unicode",
- "pkg/unicode/utf16",
- "pkg/unicode/utf8",
+
+ // Go packages.
+ "bufio",
+ "bytes",
+ "container/heap",
+ "encoding",
+ "encoding/base64",
+ "encoding/json",
+ "errors",
+ "flag",
+ "fmt",
+ "go/ast",
+ "go/build",
+ "go/doc",
+ "go/parser",
+ "go/scanner",
+ "go/token",
+ "io",
+ "io/ioutil",
+ "log",
+ "math",
+ "net/url",
+ "os",
+ "os/exec",
+ "path",
+ "path/filepath",
+ "reflect",
+ "regexp",
+ "regexp/syntax",
+ "runtime",
+ "sort",
+ "strconv",
+ "strings",
+ "sync",
+ "sync/atomic",
+ "syscall",
+ "text/template",
+ "text/template/parse",
+ "time",
+ "unicode",
+ "unicode/utf16",
+ "unicode/utf8",
};
static void
@@ -1450,9 +1434,9 @@ clean(void)
xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4));
}
- // remove src/pkg/runtime/z* unconditionally
+ // remove src/runtime/z* unconditionally
vreset(&dir);
- bpathf(&path, "%s/src/pkg/runtime", goroot);
+ bpathf(&path, "%s/src/runtime", goroot);
xreaddir(&dir, bstr(&path));
for(j=0; j<dir.len; j++) {
if(hasprefix(dir.p[j], "z"))
@@ -1589,6 +1573,15 @@ cmdbootstrap(int argc, char **argv)
if(argc > 0)
usage();
+ if(isdir(bpathf(&b, "%s/src/pkg", goroot))) {
+ fatal("\n\n"
+ "The Go package sources have moved to $GOROOT/src.\n"
+ "*** %s still exists. ***\n"
+ "It probably contains stale files that may confuse the build.\n"
+ "Please (check what's there and) remove it and try again.\n"
+ "See http://golang.org/s/go14nopkg\n", bpathf(&b, "%s/src/pkg", goroot));
+ }
+
if(rebuildall)
clean();
goversion = findgoversion();
@@ -1619,9 +1612,9 @@ cmdbootstrap(int argc, char **argv)
xsetenv("GOARCH", goarch);
xsetenv("GOOS", goos);
- // Build pkg/runtime for actual goos/goarch too.
+ // Build runtime for actual goos/goarch too.
if(!streq(goos, gohostos) || !streq(goarch, gohostarch))
- install("pkg/runtime");
+ install("runtime");
bfree(&b);
}
diff --git a/src/cmd/dist/buildgc.c b/src/cmd/dist/buildgc.c
index 1f0625daa..66adf6857 100644
--- a/src/cmd/dist/buildgc.c
+++ b/src/cmd/dist/buildgc.c
@@ -65,24 +65,35 @@ gcopnames(char *dir, char *file)
// mkanames reads [568].out.h and writes anames[568].c
// The format is much the same as the Go opcodes above.
+// it also writes out cnames array for C_* constants.
void
mkanames(char *dir, char *file)
{
- int i, ch;
- Buf in, b, out;
+ int i, j, ch;
+ Buf in, b, out, out2;
Vec lines;
char *p;
binit(&b);
binit(&in);
binit(&out);
+ binit(&out2);
vinit(&lines);
ch = file[xstrlen(file)-3];
bprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch);
readfile(&in, bstr(&b));
splitlines(&lines, bstr(&in));
- bprintf(&out, "char* anames%c[] = {\n", ch);
+
+ // Include link.h so that the extern declaration there is
+ // checked against the non-extern declaration we are generating.
+ bwritestr(&out, bprintf(&b, "#include <u.h>\n"));
+ bwritestr(&out, bprintf(&b, "#include <libc.h>\n"));
+ bwritestr(&out, bprintf(&b, "#include <bio.h>\n"));
+ bwritestr(&out, bprintf(&b, "#include <link.h>\n"));
+ bwritestr(&out, bprintf(&b, "\n"));
+
+ bwritestr(&out, bprintf(&b, "char* anames%c[] = {\n", ch));
for(i=0; i<lines.len; i++) {
if(hasprefix(lines.p[i], "\tA")) {
p = xstrstr(lines.p[i], ",");
@@ -96,10 +107,31 @@ mkanames(char *dir, char *file)
}
}
bwritestr(&out, "};\n");
+
+ j=0;
+ bprintf(&out2, "char* cnames%c[] = {\n", ch);
+ for(i=0; i<lines.len; i++) {
+ if(hasprefix(lines.p[i], "\tC_")) {
+ p = xstrstr(lines.p[i], ",");
+ if(p)
+ *p = '\0';
+ p = xstrstr(lines.p[i], "\n");
+ if(p)
+ *p = '\0';
+ p = lines.p[i] + 3;
+ bwritestr(&out2, bprintf(&b, "\t\"%s\",\n", p));
+ j++;
+ }
+ }
+ bwritestr(&out2, "};\n");
+ if(j>0)
+ bwriteb(&out, &out2);
+
writefile(&out, file, 0);
bfree(&b);
bfree(&in);
bfree(&out);
+ bfree(&out2);
vfree(&lines);
}
diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c
index ba5993b2f..bb774e05f 100644
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -5,7 +5,7 @@
#include "a.h"
/*
- * Helpers for building pkg/runtime.
+ * Helpers for building runtime.
*/
// mkzversion writes zversion.go:
@@ -30,7 +30,8 @@ mkzversion(char *dir, char *file)
"package runtime\n"
"\n"
"const defaultGoroot = `%s`\n"
- "const theVersion = `%s`\n", goroot_final, goversion));
+ "const theVersion = `%s`\n"
+ "var buildVersion = theVersion\n", goroot_final, goversion));
writefile(&out, file, 0);
@@ -108,10 +109,14 @@ mkzgoos(char *dir, char *file)
binit(&b);
binit(&out);
+
+ bwritestr(&out, "// auto generated by go tool dist\n\n");
+
+ if(streq(goos, "linux")) {
+ bwritestr(&out, "// +build !android\n\n");
+ }
bwritestr(&out, bprintf(&b,
- "// auto generated by go tool dist\n"
- "\n"
"package runtime\n"
"\n"
"const theGoos = `%s`\n", goos));
@@ -130,17 +135,14 @@ static struct {
{"386", "",
"#define get_tls(r) MOVL TLS, r\n"
"#define g(r) 0(r)(TLS*1)\n"
- "#define m(r) 4(r)(TLS*1)\n"
},
{"amd64p32", "",
"#define get_tls(r) MOVL TLS, r\n"
"#define g(r) 0(r)(TLS*1)\n"
- "#define m(r) 4(r)(TLS*1)\n"
},
{"amd64", "",
"#define get_tls(r) MOVQ TLS, r\n"
"#define g(r) 0(r)(TLS*1)\n"
- "#define m(r) 8(r)(TLS*1)\n"
},
{"arm", "",
@@ -160,11 +162,12 @@ mkzasm(char *dir, char *file)
{
int i, n;
char *aggr, *p;
- Buf in, b, out, exp;
+ Buf in, b, b1, out, exp;
Vec argv, lines, fields;
binit(&in);
binit(&b);
+ binit(&b1);
binit(&out);
binit(&exp);
vinit(&argv);
@@ -172,6 +175,10 @@ mkzasm(char *dir, char *file)
vinit(&fields);
bwritestr(&out, "// auto generated by go tool dist\n\n");
+ if(streq(goos, "linux")) {
+ bwritestr(&out, "// +build !android\n\n");
+ }
+
for(i=0; i<nelem(zasmhdr); i++) {
if(hasprefix(goarch, zasmhdr[i].goarch) && hasprefix(goos, zasmhdr[i].goos)) {
bwritestr(&out, zasmhdr[i].hdr);
@@ -181,6 +188,9 @@ mkzasm(char *dir, char *file)
fatal("unknown $GOOS/$GOARCH in mkzasm");
ok:
+ copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
+ bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0);
+
// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -a -n -o workdir/proc.acid proc.c
// to get acid [sic] output. Run once without the -a -o workdir/proc.acid in order to
// report compilation failures (the -o redirects all messages, unfortunately).
@@ -192,6 +202,8 @@ ok:
vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
vadd(&argv, "-I");
vadd(&argv, bprintf(&b, "%s", workdir));
+ vadd(&argv, "-I");
+ vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
vadd(&argv, "-n");
vadd(&argv, "-a");
vadd(&argv, "-o");
@@ -230,6 +242,12 @@ ok:
aggr = "cbctxt";
else if(streq(fields.p[1], "SEH"))
aggr = "seh";
+ else if(streq(fields.p[1], "Alg"))
+ aggr = "alg";
+ else if(streq(fields.p[1], "Panic"))
+ aggr = "panic";
+ else if(streq(fields.p[1], "Stack"))
+ aggr = "stack";
}
if(hasprefix(lines.p[i], "}"))
aggr = nil;
@@ -262,6 +280,7 @@ ok:
bfree(&in);
bfree(&b);
+ bfree(&b1);
bfree(&out);
bfree(&exp);
vfree(&argv);
@@ -283,6 +302,10 @@ mkzsys(char *dir, char *file)
binit(&out);
bwritestr(&out, "// auto generated by go tool dist\n\n");
+ if(streq(goos, "linux")) {
+ bwritestr(&out, "// +build !android\n\n");
+ }
+
if(streq(goos, "windows")) {
bwritef(&out,
"// runtime·callbackasm is called by external code to\n"
@@ -306,16 +329,20 @@ mkzsys(char *dir, char *file)
static char *runtimedefs[] = {
"defs.c",
+ "malloc.c",
+ "mcache.c",
+ "mgc0.c",
"proc.c",
"parfor.c",
+ "stack.c",
};
// mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h,
// which contains Go struct definitions equivalent to the C ones.
// Mostly we just write the output of 6c -q to the file.
// However, we run it on multiple files, so we have to delete
-// the duplicated definitions, and we don't care about the funcs
-// and consts, so we delete those too.
+// the duplicated definitions, and we don't care about the funcs,
+// so we delete those too.
//
void
mkzruntimedefs(char *dir, char *file)
@@ -335,13 +362,24 @@ mkzruntimedefs(char *dir, char *file)
vinit(&seen);
bwritestr(&out, "// auto generated by go tool dist\n"
- "\n"
+ "\n");
+
+ if(streq(goos, "linux")) {
+ bwritestr(&out, "// +build !android\n\n");
+ }
+
+ bwritestr(&out,
"package runtime\n"
"import \"unsafe\"\n"
"var _ unsafe.Pointer\n"
"\n"
);
+ // Do not emit definitions for these.
+ vadd(&seen, "true");
+ vadd(&seen, "false");
+ vadd(&seen, "raceenabled");
+ vadd(&seen, "allgs");
// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -q -n -o workdir/runtimedefs
// on each of the runtimedefs C files.
@@ -352,6 +390,8 @@ mkzruntimedefs(char *dir, char *file)
vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
vadd(&argv, "-I");
vadd(&argv, bprintf(&b, "%s", workdir));
+ vadd(&argv, "-I");
+ vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
vadd(&argv, "-q");
vadd(&argv, "-n");
vadd(&argv, "-o");
@@ -371,15 +411,15 @@ mkzruntimedefs(char *dir, char *file)
splitlines(&lines, bstr(&in));
for(i=0; i<lines.len; i++) {
p = lines.p[i];
- // Drop comment, func, and const lines.
- if(hasprefix(p, "//") || hasprefix(p, "const") || hasprefix(p, "func"))
+ // Drop comment and func lines.
+ if(hasprefix(p, "//") || hasprefix(p, "func"))
continue;
// Note beginning of type or var decl, which can be multiline.
// Remove duplicates. The linear check of seen here makes the
// whole processing quadratic in aggregate, but there are only
// about 100 declarations, so this is okay (and simple).
- if(hasprefix(p, "type ") || hasprefix(p, "var ")) {
+ if(hasprefix(p, "type ") || hasprefix(p, "var ") || hasprefix(p, "const ")) {
splitfields(&fields, p);
if(fields.len < 2)
continue;
@@ -390,6 +430,17 @@ mkzruntimedefs(char *dir, char *file)
}
vadd(&seen, fields.p[1]);
}
+
+ // Const lines are printed in original case (usually upper). Add a leading _ as needed.
+ if(hasprefix(p, "const ")) {
+ if('A' <= p[6] && p[6] <= 'Z')
+ bwritestr(&out, "const _");
+ else
+ bwritestr(&out, "const ");
+ bwritestr(&out, p+6);
+ continue;
+ }
+
if(skip) {
if(hasprefix(p, "}"))
skip = 0;
@@ -398,6 +449,11 @@ mkzruntimedefs(char *dir, char *file)
bwritestr(&out, p);
}
+
+ // Some windows specific const.
+ if(streq(goos, "windows")) {
+ bwritestr(&out, bprintf(&b, "const cb_max = %d\n", MAXWINCB));
+ }
writefile(&out, file, 0);
diff --git a/src/cmd/dist/goc2c.c b/src/cmd/dist/goc2c.c
deleted file mode 100644
index 38627657e..000000000
--- a/src/cmd/dist/goc2c.c
+++ /dev/null
@@ -1,833 +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.
-
-#include "a.h"
-
-/*
- * Translate a .goc file into a .c file. A .goc file is a combination
- * of a limited form of Go with C.
- */
-
-/*
- package PACKAGENAME
- {# line}
- func NAME([NAME TYPE { , NAME TYPE }]) [(NAME TYPE { , NAME TYPE })] \{
- C code with proper brace nesting
- \}
-*/
-
-/*
- * We generate C code which implements the function such that it can
- * be called from Go and executes the C code.
- */
-
-static char *input;
-static Buf *output;
-#define EOF -1
-
-enum
-{
- use64bitint = 1,
-};
-
-static int
-xgetchar(void)
-{
- int c;
-
- c = *input;
- if(c == 0)
- return EOF;
- input++;
- return c;
-}
-
-static void
-xungetc(void)
-{
- input--;
-}
-
-static void
-xputchar(char c)
-{
- bwrite(output, &c, 1);
-}
-
-static int
-xisspace(int c)
-{
- return c == ' ' || c == '\t' || c == '\r' || c == '\n';
-}
-
-/* Whether we're emitting for gcc */
-static int gcc;
-
-/* File and line number */
-static const char *file;
-static unsigned int lineno;
-
-/* List of names and types. */
-struct params {
- struct params *next;
- char *name;
- char *type;
-};
-
-/* index into type_table */
-enum {
- Bool,
- Float,
- Int,
- Uint,
- Uintptr,
- String,
- Slice,
- Eface,
- Complex128,
- Float32,
- Float64,
-};
-
-static struct {
- char *name;
- int size;
- int rnd; // alignment
-} type_table[] = {
- /*
- * variable sized first, for easy replacement.
- * order matches enum above.
- * default is 32-bit architecture sizes.
- * spelling as in package runtime, so intgo/uintgo not int/uint.
- */
- {"bool", 1},
- {"float", 4},
- {"intgo", 4},
- {"uintgo", 4},
- {"uintptr", 4},
- {"String", 8},
- {"Slice", 12},
- {"Eface", 8},
- {"Complex128", 16},
-
- /* fixed size */
- {"float32", 4},
- {"float64", 8},
- {"byte", 1},
- {"int8", 1},
- {"uint8", 1},
- {"int16", 2},
- {"uint16", 2},
- {"int32", 4},
- {"rune", 4},
- {"uint32", 4},
- {"int64", 8},
- {"uint64", 8},
-
- {nil, 0},
-};
-
-/* Fixed structure alignment (non-gcc only) */
-int structround = 4;
-
-/* Unexpected EOF. */
-static void
-bad_eof(void)
-{
- fatal("%s:%d: unexpected EOF\n", file, lineno);
-}
-
-/* Free a list of parameters. */
-static void
-free_params(struct params *p)
-{
- while (p != nil) {
- struct params *next;
-
- next = p->next;
- xfree(p->name);
- xfree(p->type);
- xfree(p);
- p = next;
- }
-}
-
-/* Read a character, tracking lineno. */
-static int
-getchar_update_lineno(void)
-{
- int c;
-
- c = xgetchar();
- if (c == '\n')
- ++lineno;
- return c;
-}
-
-/* Read a character, giving an error on EOF, tracking lineno. */
-static int
-getchar_no_eof(void)
-{
- int c;
-
- c = getchar_update_lineno();
- if (c == EOF)
- bad_eof();
- return c;
-}
-
-/* Read a character, skipping comments. */
-static int
-getchar_skipping_comments(void)
-{
- int c;
-
- while (1) {
- c = getchar_update_lineno();
- if (c != '/')
- return c;
-
- c = xgetchar();
- if (c == '/') {
- do {
- c = getchar_update_lineno();
- } while (c != EOF && c != '\n');
- return c;
- } else if (c == '*') {
- while (1) {
- c = getchar_update_lineno();
- if (c == EOF)
- return EOF;
- if (c == '*') {
- do {
- c = getchar_update_lineno();
- } while (c == '*');
- if (c == '/')
- break;
- }
- }
- } else {
- xungetc();
- return '/';
- }
- }
-}
-
-/*
- * Read and return a token. Tokens are string or character literals
- * or else delimited by whitespace or by [(),{}].
- * The latter are all returned as single characters.
- */
-static char *
-read_token(void)
-{
- int c, q;
- char *buf;
- unsigned int alc, off;
- char* delims = "(),{}";
-
- while (1) {
- c = getchar_skipping_comments();
- if (c == EOF)
- return nil;
- if (!xisspace(c))
- break;
- }
- alc = 16;
- buf = xmalloc(alc + 1);
- off = 0;
- if(c == '"' || c == '\'') {
- q = c;
- buf[off] = c;
- ++off;
- while (1) {
- if (off+2 >= alc) { // room for c and maybe next char
- alc *= 2;
- buf = xrealloc(buf, alc + 1);
- }
- c = getchar_no_eof();
- buf[off] = c;
- ++off;
- if(c == q)
- break;
- if(c == '\\') {
- buf[off] = getchar_no_eof();
- ++off;
- }
- }
- } else if (xstrrchr(delims, c) != nil) {
- buf[off] = c;
- ++off;
- } else {
- while (1) {
- if (off >= alc) {
- alc *= 2;
- buf = xrealloc(buf, alc + 1);
- }
- buf[off] = c;
- ++off;
- c = getchar_skipping_comments();
- if (c == EOF)
- break;
- if (xisspace(c) || xstrrchr(delims, c) != nil) {
- if (c == '\n')
- lineno--;
- xungetc();
- break;
- }
- }
- }
- buf[off] = '\0';
- return buf;
-}
-
-/* Read a token, giving an error on EOF. */
-static char *
-read_token_no_eof(void)
-{
- char *token = read_token();
- if (token == nil)
- bad_eof();
- return token;
-}
-
-/* Read the package clause, and return the package name. */
-static char *
-read_package(void)
-{
- char *token;
-
- token = read_token_no_eof();
- if (token == nil)
- fatal("%s:%d: no token\n", file, lineno);
- if (!streq(token, "package")) {
- fatal("%s:%d: expected \"package\", got \"%s\"\n",
- file, lineno, token);
- }
- return read_token_no_eof();
-}
-
-/* Read and copy preprocessor lines. */
-static void
-read_preprocessor_lines(void)
-{
- int first;
-
- first = 1;
- while (1) {
- int c;
-
- do {
- c = getchar_skipping_comments();
- } while (xisspace(c));
- if (c != '#') {
- xungetc();
- break;
- }
- if(first) {
- first = 0;
- xputchar('\n');
- }
- xputchar(c);
- do {
- c = getchar_update_lineno();
- xputchar(c);
- } while (c != '\n');
- }
-}
-
-/*
- * Read a type in Go syntax and return a type in C syntax. We only
- * permit basic types and pointers.
- */
-static char *
-read_type(void)
-{
- char *p, *op, *q;
- int pointer_count;
- unsigned int len;
-
- p = read_token_no_eof();
- if (*p != '*' && !streq(p, "int") && !streq(p, "uint"))
- return p;
- op = p;
- pointer_count = 0;
- while (*p == '*') {
- ++pointer_count;
- ++p;
- }
- len = xstrlen(p);
- q = xmalloc(len + 2 + pointer_count + 1);
- xmemmove(q, p, len);
-
- // Turn int/uint into intgo/uintgo.
- if((len == 3 && xmemcmp(q, "int", 3) == 0) || (len == 4 && xmemcmp(q, "uint", 4) == 0)) {
- q[len++] = 'g';
- q[len++] = 'o';
- }
-
- while (pointer_count-- > 0)
- q[len++] = '*';
-
- q[len] = '\0';
- xfree(op);
- return q;
-}
-
-/* Return the size of the given type. */
-static int
-type_size(char *p, int *rnd)
-{
- int i;
-
- if(p[xstrlen(p)-1] == '*') {
- *rnd = type_table[Uintptr].rnd;
- return type_table[Uintptr].size;
- }
-
- if(streq(p, "Iface"))
- p = "Eface";
-
- for(i=0; type_table[i].name; i++)
- if(streq(type_table[i].name, p)) {
- *rnd = type_table[i].rnd;
- return type_table[i].size;
- }
- fatal("%s:%d: unknown type %s\n", file, lineno, p);
- return 0;
-}
-
-/*
- * Read a list of parameters. Each parameter is a name and a type.
- * The list ends with a ')'. We have already read the '('.
- */
-static struct params *
-read_params(int *poffset)
-{
- char *token;
- struct params *ret, **pp, *p;
- int offset, size, rnd;
-
- ret = nil;
- pp = &ret;
- token = read_token_no_eof();
- offset = 0;
- if (!streq(token, ")")) {
- while (1) {
- p = xmalloc(sizeof(struct params));
- p->name = token;
- p->next = nil;
- *pp = p;
- pp = &p->next;
-
- if(streq(token, "...")) {
- p->type = xstrdup("");
- } else {
- p->type = read_type();
- rnd = 0;
- size = type_size(p->type, &rnd);
- if(rnd > structround)
- rnd = structround;
- if(offset%rnd)
- offset += rnd - offset%rnd;
- offset += size;
- }
-
- token = read_token_no_eof();
- if (!streq(token, ","))
- break;
- token = read_token_no_eof();
- }
- }
- if (!streq(token, ")")) {
- fatal("%s:%d: expected '('\n",
- file, lineno);
- }
- if (poffset != nil)
- *poffset = offset;
- return ret;
-}
-
-/*
- * Read a function header. This reads up to and including the initial
- * '{' character. Returns 1 if it read a header, 0 at EOF.
- */
-static int
-read_func_header(char **name, struct params **params, int *paramwid, struct params **rets)
-{
- int lastline;
- char *token;
-
- lastline = -1;
- while (1) {
- read_preprocessor_lines();
- token = read_token();
- if (token == nil)
- return 0;
- if (streq(token, "func")) {
- if(lastline != -1)
- bwritef(output, "\n");
- break;
- }
- if (lastline != lineno) {
- if (lastline == lineno-1)
- bwritef(output, "\n");
- else
- bwritef(output, "\n#line %d \"%s\"\n", lineno, file);
- lastline = lineno;
- }
- bwritef(output, "%s ", token);
- }
-
- *name = read_token_no_eof();
-
- token = read_token();
- if (token == nil || !streq(token, "(")) {
- fatal("%s:%d: expected \"(\"\n",
- file, lineno);
- }
- *params = read_params(paramwid);
-
- token = read_token();
- if (token == nil || !streq(token, "("))
- *rets = nil;
- else {
- *rets = read_params(nil);
- token = read_token();
- }
- if (token == nil || !streq(token, "{")) {
- fatal("%s:%d: expected \"{\"\n",
- file, lineno);
- }
- return 1;
-}
-
-/* Write out parameters. */
-static void
-write_params(struct params *params, int *first)
-{
- struct params *p;
-
- for (p = params; p != nil; p = p->next) {
- if (*first)
- *first = 0;
- else
- bwritef(output, ", ");
- bwritef(output, "%s %s", p->type, p->name);
- }
-}
-
-/* Write a 6g function header. */
-static void
-write_6g_func_header(char *package, char *name, struct params *params,
- int paramwid, struct params *rets)
-{
- int first, n;
- struct params *p;
-
- bwritef(output, "void\n");
- if(!contains(name, "·"))
- bwritef(output, "%s·", package);
- bwritef(output, "%s(", name);
-
- first = 1;
- write_params(params, &first);
-
- /* insert padding to align output struct */
- if(rets != nil && paramwid%structround != 0) {
- n = structround - paramwid%structround;
- if(n & 1)
- bwritef(output, ", uint8");
- if(n & 2)
- bwritef(output, ", uint16");
- if(n & 4)
- bwritef(output, ", uint32");
- }
-
- write_params(rets, &first);
- bwritef(output, ")\n{\n");
-
- for (p = rets; p != nil; p = p->next) {
- if(streq(p->name, "..."))
- continue;
- if(streq(p->type, "Slice"))
- bwritef(output, "\t%s.array = 0;\n\t%s.len = 0;\n\t%s.cap = 0;\n", p->name, p->name, p->name);
- else if(streq(p->type, "String"))
- bwritef(output, "\t%s.str = 0;\n\t%s.len = 0;\n", p->name, p->name);
- else if(streq(p->type, "Eface"))
- bwritef(output, "\t%s.type = 0;\n\t%s.data = 0;\n", p->name, p->name);
- else if(streq(p->type, "Iface"))
- bwritef(output, "\t%s.tab = 0;\n\t%s.data = 0;\n", p->name, p->name);
- else if(streq(p->type, "Complex128"))
- bwritef(output, "\t%s.real = 0;\n\t%s.imag = 0;\n", p->name, p->name);
- else
- bwritef(output, "\t%s = 0;\n", p->name);
- bwritef(output, "\tFLUSH(&%s);\n", p->name);
- }
-}
-
-/* Write a 6g function trailer. */
-static void
-write_6g_func_trailer(struct params *rets)
-{
- struct params *p;
-
- for (p = rets; p != nil; p = p->next)
- if(!streq(p->name, "..."))
- bwritef(output, "\tFLUSH(&%s);\n", p->name);
- bwritef(output, "}\n");
-}
-
-/* Define the gcc function return type if necessary. */
-static void
-define_gcc_return_type(char *package, char *name, struct params *rets)
-{
- struct params *p;
-
- if (rets == nil || rets->next == nil)
- return;
- bwritef(output, "struct %s_%s_ret {\n", package, name);
- for (p = rets; p != nil; p = p->next)
- bwritef(output, " %s %s;\n", p->type, p->name);
- bwritef(output, "};\n");
-}
-
-/* Write out the gcc function return type. */
-static void
-write_gcc_return_type(char *package, char *name, struct params *rets)
-{
- if (rets == nil)
- bwritef(output, "void");
- else if (rets->next == nil)
- bwritef(output, "%s", rets->type);
- else
- bwritef(output, "struct %s_%s_ret", package, name);
-}
-
-/* Write out a gcc function header. */
-static void
-write_gcc_func_header(char *package, char *name, struct params *params,
- struct params *rets)
-{
- int first;
- struct params *p;
-
- define_gcc_return_type(package, name, rets);
- write_gcc_return_type(package, name, rets);
- bwritef(output, " %s_%s(", package, name);
- first = 1;
- write_params(params, &first);
- bwritef(output, ") asm (\"%s.%s\");\n", package, name);
- write_gcc_return_type(package, name, rets);
- bwritef(output, " %s_%s(", package, name);
- first = 1;
- write_params(params, &first);
- bwritef(output, ")\n{\n");
- for (p = rets; p != nil; p = p->next)
- bwritef(output, " %s %s;\n", p->type, p->name);
-}
-
-/* Write out a gcc function trailer. */
-static void
-write_gcc_func_trailer(char *package, char *name, struct params *rets)
-{
- if (rets == nil) {
- // nothing to do
- }
- else if (rets->next == nil)
- bwritef(output, "return %s;\n", rets->name);
- else {
- struct params *p;
-
- bwritef(output, " {\n struct %s_%s_ret __ret;\n", package, name);
- for (p = rets; p != nil; p = p->next)
- bwritef(output, " __ret.%s = %s;\n", p->name, p->name);
- bwritef(output, " return __ret;\n }\n");
- }
- bwritef(output, "}\n");
-}
-
-/* Write out a function header. */
-static void
-write_func_header(char *package, char *name,
- struct params *params, int paramwid,
- struct params *rets)
-{
- if (gcc)
- write_gcc_func_header(package, name, params, rets);
- else
- write_6g_func_header(package, name, params, paramwid, rets);
- bwritef(output, "#line %d \"%s\"\n", lineno, file);
-}
-
-/* Write out a function trailer. */
-static void
-write_func_trailer(char *package, char *name,
- struct params *rets)
-{
- if (gcc)
- write_gcc_func_trailer(package, name, rets);
- else
- write_6g_func_trailer(rets);
-}
-
-/*
- * Read and write the body of the function, ending in an unnested }
- * (which is read but not written).
- */
-static void
-copy_body(void)
-{
- int nesting = 0;
- while (1) {
- int c;
-
- c = getchar_no_eof();
- if (c == '}' && nesting == 0)
- return;
- xputchar(c);
- switch (c) {
- default:
- break;
- case '{':
- ++nesting;
- break;
- case '}':
- --nesting;
- break;
- case '/':
- c = getchar_update_lineno();
- xputchar(c);
- if (c == '/') {
- do {
- c = getchar_no_eof();
- xputchar(c);
- } while (c != '\n');
- } else if (c == '*') {
- while (1) {
- c = getchar_no_eof();
- xputchar(c);
- if (c == '*') {
- do {
- c = getchar_no_eof();
- xputchar(c);
- } while (c == '*');
- if (c == '/')
- break;
- }
- }
- }
- break;
- case '"':
- case '\'':
- {
- int delim = c;
- do {
- c = getchar_no_eof();
- xputchar(c);
- if (c == '\\') {
- c = getchar_no_eof();
- xputchar(c);
- c = '\0';
- }
- } while (c != delim);
- }
- break;
- }
- }
-}
-
-/* Process the entire file. */
-static void
-process_file(void)
-{
- char *package, *name, *p, *n;
- struct params *params, *rets;
- int paramwid;
-
- package = read_package();
- read_preprocessor_lines();
- while (read_func_header(&name, &params, &paramwid, &rets)) {
- // name may have a package override already
- n = xstrstr(name, "·");
- if(n != nil) {
- p = xmalloc(n - name + 1);
- xmemmove(p, name, n - name);
- p[n - name] = 0;
- n += xstrlen("·");
- } else {
- p = package;
- n = name;
- }
- write_func_header(p, n, params, paramwid, rets);
- copy_body();
- write_func_trailer(p, n, rets);
- xfree(name);
- if(p != package) xfree(p);
- free_params(params);
- free_params(rets);
- }
- xfree(package);
-}
-
-void
-goc2c(char *goc, char *c)
-{
- int i;
- Buf in, out;
-
- binit(&in);
- binit(&out);
-
- file = goc;
- readfile(&in, goc);
-
- // TODO: set gcc=1 when using gcc
-
- if(!gcc) {
- if(streq(goarch, "amd64")) {
- type_table[Uintptr].size = 8;
- if(use64bitint) {
- type_table[Int].size = 8;
- } else {
- type_table[Int].size = 4;
- }
- structround = 8;
- } else if(streq(goarch, "amd64p32")) {
- type_table[Uintptr].size = 4;
- type_table[Int].size = 4;
- structround = 8;
- } else {
- // NOTE: These are set in the initializer,
- // but they might have been changed by a
- // previous invocation of goc2c, so we have
- // to restore them.
- type_table[Uintptr].size = 4;
- type_table[Int].size = 4;
- structround = 4;
- }
-
- type_table[Uint].size = type_table[Int].size;
- type_table[Slice].size = type_table[Uintptr].size+2*type_table[Int].size;
- type_table[Eface].size = 2*type_table[Uintptr].size;
- type_table[String].size = 2*type_table[Uintptr].size;
-
- for(i=0; i<nelem(type_table); i++)
- type_table[i].rnd = type_table[i].size;
-
- type_table[String].rnd = type_table[Uintptr].rnd;
- type_table[Slice].rnd = type_table[Uintptr].rnd;
- type_table[Eface].rnd = type_table[Uintptr].rnd;
- type_table[Complex128].rnd = type_table[Float64].rnd;
- }
-
- bprintf(&out, "// auto generated by go tool dist\n// goos=%s goarch=%s\n\n", goos, goarch);
- input = bstr(&in);
- output = &out;
-
- lineno = 1;
- process_file();
-
- writefile(&out, c, 0);
-}
diff --git a/src/cmd/dist/plan9.c b/src/cmd/dist/plan9.c
index 8d492ebc6..e4bf25147 100644
--- a/src/cmd/dist/plan9.c
+++ b/src/cmd/dist/plan9.c
@@ -23,7 +23,7 @@ bprintf(Buf *b, char *fmt, ...)
{
va_list arg;
char buf[4096];
-
+
breset(b);
va_start(arg, fmt);
vsnprintf(buf, sizeof buf, fmt, arg);
@@ -572,10 +572,10 @@ bool
hassuffix(char *p, char *suffix)
{
int np, ns;
-
+
np = strlen(p);
ns = strlen(suffix);
- return np >= ns && strcmp(p+np-ns, suffix) == 0;
+ return np >= ns && streq(p+np-ns, suffix);
}
// hasprefix reports whether p begins with prefix.
diff --git a/src/cmd/dist/unix.c b/src/cmd/dist/unix.c
index 8b943a2d9..4a78684b4 100644
--- a/src/cmd/dist/unix.c
+++ b/src/cmd/dist/unix.c
@@ -431,7 +431,7 @@ xremoveall(char *p)
}
bfree(&b);
- vfree(&dir);
+ vfree(&dir);
}
// xreaddir replaces dst with a list of the names of the files in dir.
@@ -441,13 +441,13 @@ xreaddir(Vec *dst, char *dir)
{
DIR *d;
struct dirent *dp;
-
+
vreset(dst);
d = opendir(dir);
if(d == nil)
fatal("opendir %s: %s", dir, strerror(errno));
while((dp = readdir(d)) != nil) {
- if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
+ if(streq(dp->d_name, ".") || streq(dp->d_name, ".."))
continue;
vadd(dst, dp->d_name);
}
@@ -461,7 +461,7 @@ xworkdir(void)
{
Buf b;
char *p;
-
+
binit(&b);
xgetenv(&b, "TMPDIR");
@@ -546,10 +546,10 @@ bool
hassuffix(char *p, char *suffix)
{
int np, ns;
-
+
np = strlen(p);
ns = strlen(suffix);
- return np >= ns && strcmp(p+np-ns, suffix) == 0;
+ return np >= ns && streq(p+np-ns, suffix);
}
// hasprefix reports whether p begins with prefix.
@@ -712,7 +712,7 @@ main(int argc, char **argv)
fatal("unknown architecture: %s", u.machine);
}
- if(strcmp(gohostarch, "arm") == 0)
+ if(streq(gohostarch, "arm"))
maxnbg = 1;
// The OS X 10.6 linker does not support external linking mode.
@@ -724,7 +724,7 @@ main(int argc, char **argv)
//
// Roughly, OS X 10.N shows up as uname release (N+4),
// so OS X 10.6 is uname version 10 and OS X 10.8 is uname version 12.
- if(strcmp(gohostos, "darwin") == 0) {
+ if(streq(gohostos, "darwin")) {
if(uname(&u) < 0)
fatal("uname: %s", strerror(errno));
osx = atoi(u.release) - 4;
diff --git a/src/cmd/dist/windows.c b/src/cmd/dist/windows.c
index 2839c4bc5..ff1a27351 100644
--- a/src/cmd/dist/windows.c
+++ b/src/cmd/dist/windows.c
@@ -770,10 +770,10 @@ bool
hassuffix(char *p, char *suffix)
{
int np, ns;
-
+
np = strlen(p);
ns = strlen(suffix);
- return np >= ns && strcmp(p+np-ns, suffix) == 0;
+ return np >= ns && streq(p+np-ns, suffix);
}
bool
@@ -929,7 +929,7 @@ xsamefile(char *f1, char *f2)
return 1;
torune(&ru, f1);
- // refer to ../../pkg/os/stat_windows.go:/sameFile
+ // refer to ../../os/stat_windows.go:/sameFile
fd1 = CreateFileW(ru, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
xfree(ru);
if(fd1 == INVALID_HANDLE_VALUE)
diff --git a/src/cmd/fix/doc.go b/src/cmd/fix/doc.go
index 5de3e08c5..057016957 100644
--- a/src/cmd/fix/doc.go
+++ b/src/cmd/fix/doc.go
@@ -27,7 +27,7 @@ rewrites are idempotent, so that it is safe to apply fix to updated
or partially updated code even without using the -r flag.
Fix prints the full list of fixes it can apply in its help output;
-to see them, run go tool fix -?.
+to see them, run go tool fix -help.
Fix does not make backup copies of the files that it edits.
Instead, use a version control system's ``diff'' functionality to inspect
diff --git a/src/cmd/fix/fix.go b/src/cmd/fix/fix.go
index a100be794..a07bbac79 100644
--- a/src/cmd/fix/fix.go
+++ b/src/cmd/fix/fix.go
@@ -101,7 +101,7 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) {
case *[]ast.Stmt:
walkBeforeAfter(*n, before, after)
- // These are ordered and grouped to match ../../pkg/go/ast/ast.go
+ // These are ordered and grouped to match ../../go/ast/ast.go
case *ast.Field:
walkBeforeAfter(&n.Names, before, after)
walkBeforeAfter(&n.Type, before, after)
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index b809640e4..6e5d149c7 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -119,8 +119,10 @@ dowidth(Type *t)
if(t->width == -2) {
lno = lineno;
lineno = t->lineno;
- if(!t->broke)
+ if(!t->broke) {
+ t->broke = 1;
yyerror("invalid recursive type %T", t);
+ }
t->width = 0;
lineno = lno;
return;
diff --git a/src/cmd/gc/bisonerrors b/src/cmd/gc/bisonerrors
index 1f97fc8ce..fa74c67c3 100755
--- a/src/cmd/gc/bisonerrors
+++ b/src/cmd/gc/bisonerrors
@@ -22,6 +22,7 @@ BEGIN{
bison = 1
grammar = 0
states = 0
+ open = 0
}
# In Grammar section of y.output,
@@ -130,11 +131,26 @@ $1 == "%" {
continue
# No shift or reduce applied - found the error.
- printf("\t%s, %s,\n", state, tok);
+ printf("\t{%s, %s,\n", state, tok);
+ open = 1;
break
}
next
}
# Print other lines verbatim.
+open && /,$/ {
+ s = $0;
+ sub(",", "},", s)
+ print s
+ open = 0
+ next
+}
+
+open && /"$/ {
+ print $0 "}"
+ open = 0
+ next
+}
+
{print}
diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c
index 5ca5aeb77..fbca4ee5f 100644
--- a/src/cmd/gc/builtin.c
+++ b/src/cmd/gc/builtin.c
@@ -2,18 +2,19 @@
char *runtimeimport =
"package runtime\n"
"import runtime \"runtime\"\n"
- "func @\"\".new (@\"\".typ·2 *byte) (? *any)\n"
+ "func @\"\".newobject (@\"\".typ·2 *byte) (? *any)\n"
"func @\"\".panicindex ()\n"
"func @\"\".panicslice ()\n"
"func @\"\".panicdivide ()\n"
"func @\"\".throwreturn ()\n"
"func @\"\".throwinit ()\n"
"func @\"\".panicwrap (? string, ? string, ? string)\n"
- "func @\"\".panic (? interface {})\n"
- "func @\"\".recover (? *int32) (? interface {})\n"
+ "func @\"\".gopanic (? interface {})\n"
+ "func @\"\".gorecover (? *int32) (? interface {})\n"
"func @\"\".printbool (? bool)\n"
"func @\"\".printfloat (? float64)\n"
"func @\"\".printint (? int64)\n"
+ "func @\"\".printhex (? uint64)\n"
"func @\"\".printuint (? uint64)\n"
"func @\"\".printcomplex (? complex128)\n"
"func @\"\".printstring (? string)\n"
@@ -23,7 +24,6 @@ char *runtimeimport =
"func @\"\".printslice (? any)\n"
"func @\"\".printnl ()\n"
"func @\"\".printsp ()\n"
- "func @\"\".goprintf ()\n"
"func @\"\".concatstring2 (? string, ? string) (? string)\n"
"func @\"\".concatstring3 (? string, ? string, ? string) (? string)\n"
"func @\"\".concatstring4 (? string, ? string, ? string, ? string) (? string)\n"
@@ -39,7 +39,7 @@ char *runtimeimport =
"func @\"\".stringtoslicerune (? string) (? []rune)\n"
"func @\"\".stringiter (? string, ? int) (? int)\n"
"func @\"\".stringiter2 (? string, ? int) (@\"\".retk·1 int, @\"\".retv·2 rune)\n"
- "func @\"\".copy (@\"\".to·2 any, @\"\".fr·3 any, @\"\".wid·4 uintptr) (? int)\n"
+ "func @\"\".slicecopy (@\"\".to·2 any, @\"\".fr·3 any, @\"\".wid·4 uintptr) (? int)\n"
"func @\"\".slicestringcopy (@\"\".to·2 any, @\"\".fr·3 any) (? int)\n"
"func @\"\".typ2Itab (@\"\".typ·2 *byte, @\"\".typ2·3 *byte, @\"\".cache·4 **byte) (@\"\".ret·1 *byte)\n"
"func @\"\".convI2E (@\"\".elem·2 any) (@\"\".ret·1 any)\n"
@@ -64,7 +64,6 @@ char *runtimeimport =
"func @\"\".efaceeq (@\"\".i1·2 any, @\"\".i2·3 any) (@\"\".ret·1 bool)\n"
"func @\"\".ifacethash (@\"\".i1·2 any) (@\"\".ret·1 uint32)\n"
"func @\"\".efacethash (@\"\".i1·2 any) (@\"\".ret·1 uint32)\n"
- "func @\"\".equal (@\"\".typ·2 *byte, @\"\".x1·3 any, @\"\".x2·4 any) (@\"\".ret·1 bool)\n"
"func @\"\".makemap (@\"\".mapType·2 *byte, @\"\".hint·3 int64) (@\"\".hmap·1 map[any]any)\n"
"func @\"\".mapaccess1 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 *any) (@\"\".val·1 *any)\n"
"func @\"\".mapaccess1_fast32 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
@@ -83,10 +82,18 @@ char *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"
+ "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"
+ "func @\"\".writebarrieriface (@\"\".dst·1 *any, @\"\".src·2 any)\n"
+ "func @\"\".writebarrierfat2 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat3 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat4 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat (@\"\".typ·1 *byte, @\"\".dst·2 *any, @\"\".src·3 *any)\n"
"func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (? bool)\n"
"func @\"\".selectnbrecv (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".hchan·4 <-chan any) (? bool)\n"
"func @\"\".selectnbrecv2 (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".received·4 *bool, @\"\".hchan·5 <-chan any) (? bool)\n"
- "func @\"\".newselect (@\"\".size·2 int32) (@\"\".sel·1 *byte)\n"
+ "func @\"\".newselect (@\"\".sel·1 *byte, @\"\".selsize·2 int64, @\"\".size·3 int32)\n"
"func @\"\".selectsend (@\"\".sel·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (@\"\".selected·1 bool)\n"
"func @\"\".selectrecv (@\"\".sel·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any) (@\"\".selected·1 bool)\n"
"func @\"\".selectrecv2 (@\"\".sel·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any, @\"\".received·5 *bool) (@\"\".selected·1 bool)\n"
@@ -96,12 +103,12 @@ char *runtimeimport =
"func @\"\".makeslice (@\"\".typ·2 *byte, @\"\".nel·3 int64, @\"\".cap·4 int64) (@\"\".ary·1 []any)\n"
"func @\"\".growslice (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".n·4 int64) (@\"\".ary·1 []any)\n"
"func @\"\".memmove (@\"\".to·1 *any, @\"\".frm·2 *any, @\"\".length·3 uintptr)\n"
- "func @\"\".memequal (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
- "func @\"\".memequal8 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
- "func @\"\".memequal16 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
- "func @\"\".memequal32 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
- "func @\"\".memequal64 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
- "func @\"\".memequal128 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
+ "func @\"\".memequal (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
+ "func @\"\".memequal8 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
+ "func @\"\".memequal16 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
+ "func @\"\".memequal32 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
+ "func @\"\".memequal64 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
+ "func @\"\".memequal128 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
"func @\"\".int64div (? int64, ? int64) (? int64)\n"
"func @\"\".uint64div (? uint64, ? uint64) (? uint64)\n"
"func @\"\".int64mod (? int64, ? int64) (? int64)\n"
diff --git a/src/cmd/gc/bv.c b/src/cmd/gc/bv.c
index 0e8f8d473..cfd1cd281 100644
--- a/src/cmd/gc/bv.c
+++ b/src/cmd/gc/bv.c
@@ -108,6 +108,9 @@ bvnext(Bvec *bv, int32 i)
{
uint32 w;
+ if(i >= bv->n)
+ return -1;
+
// Jump i ahead to next word with bits.
if((bv->b[i>>WORDSHIFT]>>(i&WORDMASK)) == 0) {
i &= ~WORDMASK;
@@ -117,7 +120,7 @@ bvnext(Bvec *bv, int32 i)
}
if(i >= bv->n)
return -1;
-
+
// Find 1 bit.
w = bv->b[i>>WORDSHIFT]>>(i&WORDMASK);
while((w&1) == 0) {
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index 143c1730d..e418b9c56 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -6,6 +6,7 @@
#include <libc.h>
#include "go.h"
#define TUP(x,y) (((x)<<16)|(y))
+/*c2go int TUP(int, int); */
static Val tocplx(Val);
static Val toflt(Val);
@@ -1565,7 +1566,6 @@ isgoconst(Node *n)
case ORSH:
case OSUB:
case OXOR:
- case OCONV:
case OIOTA:
case OCOMPLEX:
case OREAL:
@@ -1573,7 +1573,12 @@ isgoconst(Node *n)
if(isgoconst(n->left) && (n->right == N || isgoconst(n->right)))
return 1;
break;
-
+
+ case OCONV:
+ if(okforconst[n->type->etype] && isgoconst(n->left))
+ return 1;
+ break;
+
case OLEN:
case OCAP:
l = n->left;
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 73c2581be..dfcf47520 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -488,6 +488,10 @@ colasdefn(NodeList *left, Node *defn)
NodeList *l;
Node *n;
+ for(l=left; l; l=l->next)
+ if(l->n->sym != S)
+ l->n->sym->flags |= SymUniq;
+
nnew = 0;
nerr = 0;
for(l=left; l; l=l->next) {
@@ -499,6 +503,13 @@ colasdefn(NodeList *left, Node *defn)
nerr++;
continue;
}
+ if((n->sym->flags & SymUniq) == 0) {
+ yyerrorl(defn->lineno, "%S repeated on left side of :=", n->sym);
+ n->diag++;
+ nerr++;
+ continue;
+ }
+ n->sym->flags &= ~SymUniq;
if(n->sym->block == block)
continue;
@@ -547,6 +558,9 @@ ifacedcl(Node *n)
if(n->op != ODCLFIELD || n->right == N)
fatal("ifacedcl");
+ if(isblank(n->left))
+ yyerror("methods must have a unique non-blank name");
+
dclcontext = PPARAM;
markdcl();
funcdepth++;
diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c
index 78624d7cb..324f24fcf 100644
--- a/src/cmd/gc/esc.c
+++ b/src/cmd/gc/esc.c
@@ -495,7 +495,7 @@ esc(EscState *e, Node *n, Node *up)
case ORANGE:
// Everything but fixed array is a dereference.
- if(isfixedarray(n->type) && n->list->next)
+ if(isfixedarray(n->type) && n->list && n->list->next)
escassign(e, n->list->next->n, n->right);
break;
@@ -1110,6 +1110,7 @@ escflood(EscState *e, Node *dst)
// pass all the tests we have written so far, which we assume matches
// the level of complexity we want the escape analysis code to handle.
#define MinLevel (-2)
+/*c2go enum { MinLevel = -2 };*/
static void
escwalk(EscState *e, int level, Node *dst, Node *src)
diff --git a/src/cmd/gc/fmt.c b/src/cmd/gc/fmt.c
index b5f8a834f..89d2a1404 100644
--- a/src/cmd/gc/fmt.c
+++ b/src/cmd/gc/fmt.c
@@ -649,7 +649,7 @@ typefmt(Fmt *fp, Type *t)
if(t->funarg) {
fmtstrcpy(fp, "(");
- if(fmtmode == FTypeId || fmtmode == FErr) { // no argument names on function signature, and no "noescape" tags
+ if(fmtmode == FTypeId || fmtmode == FErr) { // no argument names on function signature, and no "noescape"/"nosplit" tags
for(t1=t->type; t1!=T; t1=t1->down)
if(t1->down)
fmtprint(fp, "%hT, ", t1);
@@ -810,6 +810,13 @@ stmtfmt(Fmt *f, Node *n)
break;
case OASOP:
+ if(n->implicit) {
+ if(n->etype == OADD)
+ fmtprint(f, "%N++", n->left);
+ else
+ fmtprint(f, "%N--", n->left);
+ break;
+ }
fmtprint(f, "%N %#O= %N", n->left, n->etype, n->right);
break;
@@ -880,7 +887,11 @@ stmtfmt(Fmt *f, Node *n)
fmtstrcpy(f, "for loop");
break;
}
-
+
+ if(n->list == nil) {
+ fmtprint(f, "for range %N { %H }", n->right, n->nbody);
+ break;
+ }
fmtprint(f, "for %,H = range %N { %H }", n->list, n->right, n->nbody);
break;
@@ -974,7 +985,6 @@ static int opprec[] = {
[OTFUNC] = 8,
[OTINTER] = 8,
[OTMAP] = 8,
- [OTPAREN] = 8,
[OTSTRUCT] = 8,
[OINDEXMAP] = 8,
@@ -1105,16 +1115,11 @@ exprfmt(Fmt *f, Node *n, int prec)
case ONAME:
// Special case: name used as local variable in export.
- switch(n->class&~PHEAP){
- case PAUTO:
- case PPARAM:
- case PPARAMOUT:
- // _ becomes ~b%d internally; print as _ for export
- if(fmtmode == FExp && n->sym && n->sym->name[0] == '~' && n->sym->name[1] == 'b')
- return fmtprint(f, "_");
- if(fmtmode == FExp && n->sym && !isblank(n) && n->vargen > 0)
- return fmtprint(f, "%S·%d", n->sym, n->vargen);
- }
+ // _ becomes ~b%d internally; print as _ for export
+ if(fmtmode == FExp && n->sym && n->sym->name[0] == '~' && n->sym->name[1] == 'b')
+ return fmtprint(f, "_");
+ if(fmtmode == FExp && n->sym && !isblank(n) && n->vargen > 0)
+ return fmtprint(f, "%S·%d", n->sym, n->vargen);
// Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
// but for export, this should be rendered as (*pkg.T).meth.
@@ -1140,9 +1145,6 @@ exprfmt(Fmt *f, Node *n, int prec)
return fmtprint(f, "[]%N", n->left);
return fmtprint(f, "[]%N", n->right); // happens before typecheck
- case OTPAREN:
- return fmtprint(f, "(%N)", n->left);
-
case OTMAP:
return fmtprint(f, "map[%N]%N", n->left, n->right);
@@ -1153,7 +1155,7 @@ exprfmt(Fmt *f, Node *n, int prec)
case Csend:
return fmtprint(f, "chan<- %N", n->left);
default:
- if(n->left != N && n->left->op == TCHAN && n->left->sym == S && n->left->etype == Crecv)
+ if(n->left != N && n->left->op == OTCHAN && n->left->sym == S && n->left->etype == Crecv)
return fmtprint(f, "chan (%N)", n->left);
else
return fmtprint(f, "chan %N", n->left);
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index cf630f348..c7c9fcdaf 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -54,9 +54,6 @@ addrescapes(Node *n)
if(n->class == PAUTO && n->esc == EscNever)
break;
- if(debug['N'] && n->esc != EscUnknown)
- fatal("without escape analysis, only PAUTO's should have esc: %N", n);
-
switch(n->class) {
case PPARAMREF:
addrescapes(n->defn);
@@ -91,8 +88,7 @@ addrescapes(Node *n)
snprint(buf, sizeof buf, "&%S", n->sym);
n->heapaddr->sym = lookup(buf);
n->heapaddr->orig->sym = n->heapaddr->sym;
- if(!debug['N'])
- n->esc = EscHeap;
+ n->esc = EscHeap;
if(debug['m'])
print("%L: moved to heap: %N\n", n->lineno, n);
curfn = oldfn;
@@ -584,6 +580,8 @@ cgen_dcl(Node *n)
}
if(!(n->class & PHEAP))
return;
+ if(compiling_runtime)
+ yyerror("%N escapes to heap, not allowed in runtime.", n);
if(n->alloc == nil)
n->alloc = callnew(n->type);
cgen_as(n->heapaddr, n->alloc);
@@ -733,14 +731,10 @@ cgen_as(Node *nl, Node *nr)
return;
}
- if(nr == N || isnil(nr)) {
- // externals and heaps should already be clear
- if(nr == N) {
- if(nl->class == PEXTERN)
- return;
- if(nl->class & PHEAP)
- return;
- }
+ if(nr == N || iszero(nr)) {
+ // heaps should already be clear
+ if(nr == N && (nl->class & PHEAP))
+ return;
tl = nl->type;
if(tl == T)
@@ -804,7 +798,8 @@ cgen_eface(Node *n, Node *res)
void
cgen_slice(Node *n, Node *res)
{
- Node src, dst, *cap, *len, *offs, *add, *base;
+ Node src, dst, *cap, *len, *offs, *add, *base, *tmpcap, *tmplen, *cmp, con;
+ Prog *p1, *p2;
cap = n->list->n;
len = n->list->next->n;
@@ -821,6 +816,11 @@ cgen_slice(Node *n, Node *res)
// garbage collector can see.
base = temp(types[TUINTPTR]);
+ tmplen = temp(types[TINT]);
+ if(n->op != OSLICESTR)
+ tmpcap = temp(types[TINT]);
+ else
+ tmpcap = tmplen;
if(isnil(n->left)) {
tempname(&src, n->left->type);
@@ -835,43 +835,62 @@ cgen_slice(Node *n, Node *res)
fatal("slicearr is supposed to work on pointer: %+N\n", n);
cgen(&src, base);
cgen_checknil(base);
- if(offs != N) {
- add = nod(OADD, base, offs);
- typecheck(&add, Erv);
- cgen(add, base);
- }
- } else if(offs == N) {
- src.type = types[tptr];
- cgen(&src, base);
} else {
src.type = types[tptr];
- add = nod(OADDPTR, &src, offs);
- typecheck(&add, Erv);
- cgen(add, base);
+ cgen(&src, base);
}
// committed to the update
gvardef(res);
+ // compute len and cap.
+ // len = n-i, cap = m-i, and offs = i*width.
+ // computing offs last lets the multiply overwrite i.
+ cgen(len, tmplen);
+ if(n->op != OSLICESTR)
+ cgen(cap, tmpcap);
+
+ // if new cap != 0 { base += add }
+ // This avoids advancing base past the end of the underlying array/string,
+ // so that it cannot point at the next object in memory.
+ // If cap == 0, the base doesn't matter except insofar as it is 0 or non-zero.
+ // In essence we are replacing x[i:j:k] where i == j == k
+ // or x[i:j] where i == j == cap(x) with x[0:0:0].
+ if(offs != N) {
+ p1 = gjmp(P);
+ p2 = gjmp(P);
+ patch(p1, pc);
+
+ nodconst(&con, tmpcap->type, 0);
+ cmp = nod(OEQ, tmpcap, &con);
+ typecheck(&cmp, Erv);
+ bgen(cmp, 1, -1, p2);
+
+ add = nod(OADD, base, offs);
+ typecheck(&add, Erv);
+ cgen(add, base);
+
+ patch(p2, pc);
+ }
+
// dst.array = src.array [ + lo *width ]
dst = *res;
dst.xoffset += Array_array;
dst.type = types[tptr];
-
cgen(base, &dst);
// dst.len = hi [ - lo ]
dst = *res;
dst.xoffset += Array_nel;
dst.type = types[simtype[TUINT]];
- cgen(len, &dst);
+ cgen(tmplen, &dst);
if(n->op != OSLICESTR) {
// dst.cap = cap [ - lo ]
dst = *res;
dst.xoffset += Array_cap;
dst.type = types[simtype[TUINT]];
- cgen(cap, &dst);
+ cgen(tmpcap, &dst);
}
}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index ee879f67f..965a0550d 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -269,6 +269,7 @@ struct Node
uchar colas; // OAS resulting from :=
uchar diag; // already printed error about this
uchar noescape; // func arguments do not escape
+ uchar nosplit; // func should not execute on separate stack
uchar builtin; // built-in name, like len or close
uchar walkdef;
uchar typecheck;
@@ -282,6 +283,7 @@ struct Node
uchar addrtaken; // address taken, even if not moved to heap
uchar dupok; // duplicate definitions ok (for func)
uchar wrapper; // is method wrapper (for func)
+ uchar reslice; // this is a reslice x = x[0:y] or x = append(x, ...)
schar likely; // likeliness of if statement
uchar hasbreak; // has break statement
uchar needzero; // if it contains pointers, needs to be zeroed on function entry
@@ -380,7 +382,6 @@ enum
SymExported = 1<<2, // already written out by export
SymUniq = 1<<3,
SymSiggen = 1<<4,
- SymGcgen = 1<<5,
};
struct Sym
@@ -447,7 +448,6 @@ enum
OSUB, // x - y
OOR, // x | y
OXOR, // x ^ y
- OADDPTR, // ptr + uintptr, inserted by compiler only, used to avoid unsafe type changes during codegen
OADDSTR, // s + "foo"
OADDR, // &x
OANDAND, // b0 && b1
@@ -573,7 +573,6 @@ enum
OTINTER, // interface{}
OTFUNC, // func()
OTARRAY, // []int, [8]int, [N]int or [...]int
- OTPAREN, // (T)
// misc
ODDD, // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}.
@@ -975,11 +974,13 @@ EXTERN int funcdepth;
EXTERN int typecheckok;
EXTERN int compiling_runtime;
EXTERN int compiling_wrappers;
+EXTERN int use_writebarrier;
EXTERN int pure_go;
EXTERN char* flag_installsuffix;
EXTERN int flag_race;
EXTERN int flag_largemodel;
EXTERN int noescape;
+EXTERN int nosplit;
EXTERN int debuglive;
EXTERN Link* ctxt;
@@ -1169,6 +1170,7 @@ void cgen_callmeth(Node *n, int proc);
void cgen_eface(Node* n, Node* res);
void cgen_slice(Node* n, Node* res);
void clearlabels(void);
+void clearslim(Node*);
void checklabels(void);
int dotoffset(Node *n, int64 *oary, Node **nn);
void gen(Node *n);
@@ -1284,6 +1286,7 @@ LSym* linksym(Sym*);
* order.c
*/
void order(Node *fn);
+void orderstmtinplace(Node **stmt);
/*
* range.c
@@ -1302,7 +1305,6 @@ Sym* typenamesym(Type *t);
Sym* tracksym(Type *t);
Sym* typesymprefix(char *prefix, Type *t);
int haspointers(Type *t);
-void usefield(Node*);
Type* hiter(Type* t);
/*
@@ -1364,6 +1366,7 @@ int is64(Type *t);
int isbadimport(Strlit *s);
int isblank(Node *n);
int isblanksym(Sym *s);
+int isdirectiface(Type*);
int isfixedarray(Type *t);
int isideal(Type *t);
int isinter(Type *t);
@@ -1372,6 +1375,7 @@ int isnilinter(Type *t);
int isptrto(Type *t, int et);
int isslice(Type *t);
int istype(Type *t, int et);
+int iszero(Node *n);
void linehist(char *file, int32 off, int relative);
NodeList* list(NodeList *l, Node *n);
NodeList* list1(Node *n);
@@ -1464,7 +1468,9 @@ void walkstmt(Node **np);
void walkstmtlist(NodeList *l);
Node* conv(Node*, Type*);
int candiscard(Node*);
+int needwritebarrier(Node*, Node*);
Node* outervalue(Node*);
+void usefield(Node*);
/*
* arch-specific ggen.c/gsubr.c/gobj.c/pgen.c/plive.c
@@ -1505,7 +1511,7 @@ void gdata(Node*, Node*, int);
void gdatacomplex(Node*, Mpcplx*);
void gdatastring(Node*, Strlit*);
void ggloblnod(Node *nam);
-void ggloblsym(Sym *s, int32 width, int dupok, int rodata);
+void ggloblsym(Sym *s, int32 width, int8 flags);
void gvardef(Node*);
void gvarkill(Node*);
Prog* gjmp(Prog*);
@@ -1514,6 +1520,7 @@ void movelarge(NodeList*);
int isfat(Type*);
void linkarchinit(void);
void liveness(Node*, Prog*, Sym*, Sym*);
+void twobitwalktype1(Type*, vlong*, Bvec*);
void markautoused(Prog*);
Plist* newplist(void);
Node* nodarg(Type*, int);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 2f354f723..68fccc1ad 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -460,11 +460,13 @@ simple_stmt:
| expr LINC
{
$$ = nod(OASOP, $1, nodintconst(1));
+ $$->implicit = 1;
$$->etype = OADD;
}
| expr LDEC
{
$$ = nod(OASOP, $1, nodintconst(1));
+ $$->implicit = 1;
$$->etype = OSUB;
}
@@ -613,6 +615,11 @@ range_stmt:
$$->colas = 1;
colasdefn($1, $$);
}
+| LRANGE expr
+ {
+ $$ = nod(ORANGE, N, $2);
+ $$->etype = 0; // := flag
+ }
for_header:
osimple_stmt ';' osimple_stmt ';' osimple_stmt
@@ -1180,7 +1187,7 @@ ntype:
| dotname
| '(' ntype ')'
{
- $$ = nod(OTPAREN, $2, N);
+ $$ = $2;
}
non_expr_type:
@@ -1199,7 +1206,7 @@ non_recvchantype:
| dotname
| '(' ntype ')'
{
- $$ = nod(OTPAREN, $2, N);
+ $$ = $2;
}
convtype:
@@ -1311,6 +1318,7 @@ xfndcl:
$$->nbody = $3;
$$->endlineno = lineno;
$$->noescape = noescape;
+ $$->nosplit = nosplit;
funcbody($$);
}
@@ -1365,8 +1373,6 @@ fndcl:
yyerror("bad receiver in method");
break;
}
- if(rcvr->right->op == OTPAREN || (rcvr->right->op == OIND && rcvr->right->left->op == OTPAREN))
- yyerror("cannot parenthesize receiver type");
t = nod(OTFUNC, rcvr, N);
t->list = $6;
@@ -1495,6 +1501,7 @@ xdcl_list:
testdclstack();
nointerface = 0;
noescape = 0;
+ nosplit = 0;
}
vardcl_list:
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index a50101c42..523ba37aa 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -45,7 +45,7 @@ static struct {
};
// Debug arguments.
-// These can be specified with the -d flag, as in "-d checknil"
+// These can be specified with the -d flag, as in "-d nil"
// to set the debug_checknil variable. In general the list passed
// to -d can be comma-separated.
static struct {
@@ -139,6 +139,8 @@ yy_isalnum(int c)
#define isalnum use_yy_isalnum_instead_of_isalnum
#define DBG if(!debug['x']){}else print
+/*c2go void DBG(char*, ...); */
+
enum
{
EOF = -1,
@@ -310,6 +312,8 @@ main(int argc, char *argv[])
flagcount("u", "reject unsafe code", &safemode);
flagcount("v", "increase debug verbosity", &debug['v']);
flagcount("w", "debug type checking", &debug['w']);
+ use_writebarrier = 1;
+ flagcount("wb", "enable write barrier", &use_writebarrier);
flagcount("x", "debug lexer", &debug['x']);
flagcount("y", "debug declarations in canned imports (with -d)", &debug['y']);
if(thechar == '6')
@@ -317,6 +321,7 @@ main(int argc, char *argv[])
flagparse(&argc, &argv, usage);
ctxt->debugasm = debug['S'];
+ ctxt->debugvlog = debug['v'];
if(argc < 1)
usage();
@@ -339,8 +344,8 @@ main(int argc, char *argv[])
break;
}
}
- if(j == nelem(debugtab))
- fatal("unknown debug information -d '%s'\n", f[i]);
+ if(debugtab[j].name == nil)
+ sysfatal("unknown debug information -d '%s'\n", f[i]);
}
}
@@ -476,8 +481,12 @@ main(int argc, char *argv[])
}
// Phase 5: Escape analysis.
- if(!debug['N'])
- escapes(xtop);
+ // Required for moving heap allocations onto stack,
+ // which in turn is required by the closure implementation,
+ // which stores the addresses of stack variables into the closure.
+ // If the closure does not escape, it needs to be on the stack
+ // or else the stack copier will not update it.
+ escapes(xtop);
// Escape analysis moved escaped values off stack.
// Move large values off stack too.
@@ -516,24 +525,18 @@ saveerrors(void)
nerrors = 0;
}
-/*
- * macro to portably read/write archive header.
- * 'cmd' is read/write/Bread/Bwrite, etc.
- */
-#define HEADER_IO(cmd, f, h) cmd(f, h.name, sizeof(h.name)) != sizeof(h.name)\
- || cmd(f, h.date, sizeof(h.date)) != sizeof(h.date)\
- || cmd(f, h.uid, sizeof(h.uid)) != sizeof(h.uid)\
- || cmd(f, h.gid, sizeof(h.gid)) != sizeof(h.gid)\
- || cmd(f, h.mode, sizeof(h.mode)) != sizeof(h.mode)\
- || cmd(f, h.size, sizeof(h.size)) != sizeof(h.size)\
- || cmd(f, h.fmag, sizeof(h.fmag)) != sizeof(h.fmag)
-
static int
arsize(Biobuf *b, char *name)
{
struct ar_hdr a;
- if (HEADER_IO(Bread, b, a))
+ if(Bread(b, a.name, sizeof(a.name)) != sizeof(a.name) ||
+ Bread(b, a.date, sizeof(a.date)) != sizeof(a.date) ||
+ Bread(b, a.uid, sizeof(a.uid)) != sizeof(a.uid) ||
+ Bread(b, a.gid, sizeof(a.gid)) != sizeof(a.gid) ||
+ Bread(b, a.mode, sizeof(a.mode)) != sizeof(a.mode) ||
+ Bread(b, a.size, sizeof(a.size)) != sizeof(a.size) ||
+ Bread(b, a.fmag, sizeof(a.fmag)) != sizeof(a.fmag))
return -1;
if(strncmp(a.name, name, strlen(name)) != 0)
@@ -1592,6 +1595,10 @@ go:
noescape = 1;
goto out;
}
+ if(strcmp(lexbuf, "go:nosplit") == 0) {
+ nosplit = 1;
+ goto out;
+ }
out:
return c;
@@ -1854,74 +1861,74 @@ static struct
/* name lexical etype op
*/
/* basic types */
- "int8", LNAME, TINT8, OXXX,
- "int16", LNAME, TINT16, OXXX,
- "int32", LNAME, TINT32, OXXX,
- "int64", LNAME, TINT64, OXXX,
-
- "uint8", LNAME, TUINT8, OXXX,
- "uint16", LNAME, TUINT16, OXXX,
- "uint32", LNAME, TUINT32, OXXX,
- "uint64", LNAME, TUINT64, OXXX,
-
- "float32", LNAME, TFLOAT32, OXXX,
- "float64", LNAME, TFLOAT64, OXXX,
-
- "complex64", LNAME, TCOMPLEX64, OXXX,
- "complex128", LNAME, TCOMPLEX128, OXXX,
-
- "bool", LNAME, TBOOL, OXXX,
- "string", LNAME, TSTRING, OXXX,
-
- "any", LNAME, TANY, OXXX,
-
- "break", LBREAK, Txxx, OXXX,
- "case", LCASE, Txxx, OXXX,
- "chan", LCHAN, Txxx, OXXX,
- "const", LCONST, Txxx, OXXX,
- "continue", LCONTINUE, Txxx, OXXX,
- "default", LDEFAULT, Txxx, OXXX,
- "else", LELSE, Txxx, OXXX,
- "defer", LDEFER, Txxx, OXXX,
- "fallthrough", LFALL, Txxx, OXXX,
- "for", LFOR, Txxx, OXXX,
- "func", LFUNC, Txxx, OXXX,
- "go", LGO, Txxx, OXXX,
- "goto", LGOTO, Txxx, OXXX,
- "if", LIF, Txxx, OXXX,
- "import", LIMPORT, Txxx, OXXX,
- "interface", LINTERFACE, Txxx, OXXX,
- "map", LMAP, Txxx, OXXX,
- "package", LPACKAGE, Txxx, OXXX,
- "range", LRANGE, Txxx, OXXX,
- "return", LRETURN, Txxx, OXXX,
- "select", LSELECT, Txxx, OXXX,
- "struct", LSTRUCT, Txxx, OXXX,
- "switch", LSWITCH, Txxx, OXXX,
- "type", LTYPE, Txxx, OXXX,
- "var", LVAR, Txxx, OXXX,
-
- "append", LNAME, Txxx, OAPPEND,
- "cap", LNAME, Txxx, OCAP,
- "close", LNAME, Txxx, OCLOSE,
- "complex", LNAME, Txxx, OCOMPLEX,
- "copy", LNAME, Txxx, OCOPY,
- "delete", LNAME, Txxx, ODELETE,
- "imag", LNAME, Txxx, OIMAG,
- "len", LNAME, Txxx, OLEN,
- "make", LNAME, Txxx, OMAKE,
- "new", LNAME, Txxx, ONEW,
- "panic", LNAME, Txxx, OPANIC,
- "print", LNAME, Txxx, OPRINT,
- "println", LNAME, Txxx, OPRINTN,
- "real", LNAME, Txxx, OREAL,
- "recover", LNAME, Txxx, ORECOVER,
-
- "notwithstanding", LIGNORE, Txxx, OXXX,
- "thetruthofthematter", LIGNORE, Txxx, OXXX,
- "despiteallobjections", LIGNORE, Txxx, OXXX,
- "whereas", LIGNORE, Txxx, OXXX,
- "insofaras", LIGNORE, Txxx, OXXX,
+ {"int8", LNAME, TINT8, OXXX},
+ {"int16", LNAME, TINT16, OXXX},
+ {"int32", LNAME, TINT32, OXXX},
+ {"int64", LNAME, TINT64, OXXX},
+
+ {"uint8", LNAME, TUINT8, OXXX},
+ {"uint16", LNAME, TUINT16, OXXX},
+ {"uint32", LNAME, TUINT32, OXXX},
+ {"uint64", LNAME, TUINT64, OXXX},
+
+ {"float32", LNAME, TFLOAT32, OXXX},
+ {"float64", LNAME, TFLOAT64, OXXX},
+
+ {"complex64", LNAME, TCOMPLEX64, OXXX},
+ {"complex128", LNAME, TCOMPLEX128, OXXX},
+
+ {"bool", LNAME, TBOOL, OXXX},
+ {"string", LNAME, TSTRING, OXXX},
+
+ {"any", LNAME, TANY, OXXX},
+
+ {"break", LBREAK, Txxx, OXXX},
+ {"case", LCASE, Txxx, OXXX},
+ {"chan", LCHAN, Txxx, OXXX},
+ {"const", LCONST, Txxx, OXXX},
+ {"continue", LCONTINUE, Txxx, OXXX},
+ {"default", LDEFAULT, Txxx, OXXX},
+ {"else", LELSE, Txxx, OXXX},
+ {"defer", LDEFER, Txxx, OXXX},
+ {"fallthrough", LFALL, Txxx, OXXX},
+ {"for", LFOR, Txxx, OXXX},
+ {"func", LFUNC, Txxx, OXXX},
+ {"go", LGO, Txxx, OXXX},
+ {"goto", LGOTO, Txxx, OXXX},
+ {"if", LIF, Txxx, OXXX},
+ {"import", LIMPORT, Txxx, OXXX},
+ {"interface", LINTERFACE, Txxx, OXXX},
+ {"map", LMAP, Txxx, OXXX},
+ {"package", LPACKAGE, Txxx, OXXX},
+ {"range", LRANGE, Txxx, OXXX},
+ {"return", LRETURN, Txxx, OXXX},
+ {"select", LSELECT, Txxx, OXXX},
+ {"struct", LSTRUCT, Txxx, OXXX},
+ {"switch", LSWITCH, Txxx, OXXX},
+ {"type", LTYPE, Txxx, OXXX},
+ {"var", LVAR, Txxx, OXXX},
+
+ {"append", LNAME, Txxx, OAPPEND},
+ {"cap", LNAME, Txxx, OCAP},
+ {"close", LNAME, Txxx, OCLOSE},
+ {"complex", LNAME, Txxx, OCOMPLEX},
+ {"copy", LNAME, Txxx, OCOPY},
+ {"delete", LNAME, Txxx, ODELETE},
+ {"imag", LNAME, Txxx, OIMAG},
+ {"len", LNAME, Txxx, OLEN},
+ {"make", LNAME, Txxx, OMAKE},
+ {"new", LNAME, Txxx, ONEW},
+ {"panic", LNAME, Txxx, OPANIC},
+ {"print", LNAME, Txxx, OPRINT},
+ {"println", LNAME, Txxx, OPRINTN},
+ {"real", LNAME, Txxx, OREAL},
+ {"recover", LNAME, Txxx, ORECOVER},
+
+ {"notwithstanding", LIGNORE, Txxx, OXXX},
+ {"thetruthofthematter", LIGNORE, Txxx, OXXX},
+ {"despiteallobjections", LIGNORE, Txxx, OXXX},
+ {"whereas", LIGNORE, Txxx, OXXX},
+ {"insofaras", LIGNORE, Txxx, OXXX},
};
static void
@@ -2171,50 +2178,50 @@ struct
char* name;
} lexn[] =
{
- 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",
+ {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"},
};
char*
@@ -2236,56 +2243,56 @@ struct
char *want;
} yytfix[] =
{
- "$end", "EOF",
- "LLITERAL", "literal",
- "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", "!=",
+ {"$end", "EOF"},
+ {"LLITERAL", "literal"},
+ {"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",
+ {"';'", "semicolon or newline"},
+ {"','", "comma"},
};
static void
diff --git a/src/cmd/gc/md5.c b/src/cmd/gc/md5.c
index 0051ac964..46cb6b712 100644
--- a/src/cmd/gc/md5.c
+++ b/src/cmd/gc/md5.c
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// 64-bit MD5 (does full MD5 but returns 64 bits only).
-// Translation of ../../pkg/crypto/md5/md5*.go.
+// Translation of ../../crypto/md5/md5*.go.
#include <u.h>
#include <libc.h>
@@ -20,7 +20,15 @@ enum {
#define _Init1 0xEFCDAB89
#define _Init2 0x98BADCFE
#define _Init3 0x10325476
-
+/*c2go
+enum {
+ _Init0 = 0x67452301,
+ _Init1 = 0xEFCDAB89,
+ _Init2 = 0x98BADCFE,
+ _Init3 = 0x10325476
+};
+*/
+
void
md5reset(MD5 *d)
{
diff --git a/src/cmd/gc/mparith1.c b/src/cmd/gc/mparith1.c
index 1519caec7..d33a81e09 100644
--- a/src/cmd/gc/mparith1.c
+++ b/src/cmd/gc/mparith1.c
@@ -591,7 +591,7 @@ Fconv(Fmt *fp)
d = mpgetflt(fvp);
if(d >= 0 && (fp->flags & FmtSign))
fmtprint(fp, "+");
- return fmtprint(fp, "%g", d, exp, fvp);
+ return fmtprint(fp, "%g", d);
}
// very out of range. compute decimal approximation by hand.
diff --git a/src/cmd/gc/mparith2.c b/src/cmd/gc/mparith2.c
index 5cf98c62c..fd9f591ce 100644
--- a/src/cmd/gc/mparith2.c
+++ b/src/cmd/gc/mparith2.c
@@ -656,7 +656,7 @@ mpdivmodfixfix(Mpint *q, Mpint *r, Mpint *n, Mpint *d)
}
static int
-iszero(Mpint *a)
+mpiszero(Mpint *a)
{
long *a1;
int i;
@@ -687,7 +687,7 @@ mpdivfract(Mpint *a, Mpint *b)
for(j=0; j<Mpscale; j++) {
x <<= 1;
if(mpcmp(&d, &n) <= 0) {
- if(!iszero(&d))
+ if(!mpiszero(&d))
x |= 1;
mpsubfixfix(&n, &d);
}
diff --git a/src/cmd/gc/mparith3.c b/src/cmd/gc/mparith3.c
index 95618f1c6..6afd75c02 100644
--- a/src/cmd/gc/mparith3.c
+++ b/src/cmd/gc/mparith3.c
@@ -251,8 +251,8 @@ mpgetfltN(Mpflt *a, int prec, int bias)
s = minexp - e;
if(s > prec+1)
s = prec+1;
- if((v & ((1<<s)-1)) != 0)
- v |= 1<<s;
+ if((v & ((1ULL<<s)-1)) != 0)
+ v |= 1ULL<<s;
v >>= s;
e = minexp;
}
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index 4eeb03aa8..b752a13ce 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -5,6 +5,7 @@
#include <u.h>
#include <libc.h>
#include "go.h"
+#include "../ld/textflag.h"
/*
* architecture-independent object file output
@@ -84,7 +85,7 @@ dumpobj(void)
externdcl = tmp;
zero = pkglookup("zerovalue", runtimepkg);
- ggloblsym(zero, zerosize, 1, 1);
+ ggloblsym(zero, zerosize, DUPOK|RODATA);
dumpdata();
writeobj(ctxt, bout);
@@ -128,7 +129,7 @@ dumpglobls(void)
for(l=funcsyms; l; l=l->next) {
n = l->n;
dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0);
- ggloblsym(n->sym, widthptr, 1, 1);
+ ggloblsym(n->sym, widthptr, DUPOK|RODATA);
}
// Do not reprocess funcsyms on next dumpglobls call.
@@ -249,7 +250,7 @@ stringsym(char *s, int len)
}
off = duint8(sym, off, 0); // terminating NUL for runtime
off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment
- ggloblsym(sym, off, 1, 1);
+ ggloblsym(sym, off, DUPOK|RODATA);
return sym;
}
@@ -272,7 +273,7 @@ slicebytes(Node *nam, char *s, int len)
m = len-n;
off = dsname(sym, off, s+n, m);
}
- ggloblsym(sym, off, 0, 0);
+ ggloblsym(sym, off, NOPTR);
if(nam->op != ONAME)
fatal("slicebytes %N", nam);
diff --git a/src/cmd/gc/order.c b/src/cmd/gc/order.c
index 30dbc7dac..76820fde7 100644
--- a/src/cmd/gc/order.c
+++ b/src/cmd/gc/order.c
@@ -317,7 +317,7 @@ orderexprinplace(Node **np, Order *outer)
// Orderstmtinplace orders the side effects of the single statement *np
// and replaces it with the resulting statement list.
-static void
+void
orderstmtinplace(Node **np)
{
Node *n;
@@ -438,6 +438,9 @@ ordercall(Node *n, Order *order)
// 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.
+//
+// Ordermapassign also inserts these temporaries if needed for
+// calling writebarrierfat with a pointer to n->right.
static void
ordermapassign(Node *n, Order *order)
{
@@ -451,7 +454,8 @@ ordermapassign(Node *n, Order *order)
case OAS:
order->out = list(order->out, n);
- if(n->left->op == OINDEXMAP && !isaddrokay(n->right)) {
+ // We call writebarrierfat only for values > 4 pointers long. See walk.c.
+ if((n->left->op == OINDEXMAP || (needwritebarrier(n->left, n->right) && n->left->type->width > 4*widthptr)) && !isaddrokay(n->right)) {
m = n->left;
n->left = ordertemp(m->type, order, 0);
a = nod(OAS, m, n->left);
@@ -593,7 +597,10 @@ orderstmt(Node *n, Order *order)
orderexpr(&n->rlist->n->left, order); // arg to recv
ch = n->rlist->n->left->type;
tmp1 = ordertemp(ch->type, order, haspointers(ch->type));
- tmp2 = ordertemp(types[TBOOL], order, 0);
+ if(!isblank(n->list->next->n))
+ tmp2 = ordertemp(n->list->next->n->type, order, 0);
+ else
+ tmp2 = ordertemp(types[TBOOL], order, 0);
order->out = list(order->out, n);
r = nod(OAS, n->list->n, tmp1);
typecheck(&r, Etop);
@@ -768,6 +775,12 @@ orderstmt(Node *n, Order *order)
// 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
+ // than ordinary expressions. Even something like p.c
+ // has to be hoisted into a temporary, so that it cannot be
+ // reordered after the channel evaluation for a different
+ // case (if p were nil, then the timing of the fault would
+ // give this away).
t = marktemp(order);
for(l=n->list; l; l=l->next) {
if(l->n->op != OXCASE)
@@ -810,6 +823,8 @@ orderstmt(Node *n, Order *order)
// r->left == N means 'case <-c'.
// c is always evaluated; x and ok are only evaluated when assigned.
orderexpr(&r->right->left, order);
+ if(r->right->left->op != ONAME)
+ r->right->left = ordercopyexpr(r->right->left, r->right->left->type, order, 0);
// Introduce temporary for receive and move actual copy into case body.
// avoids problems with target being addressed, as usual.
@@ -1017,11 +1032,21 @@ orderexpr(Node **np, Order *order)
orderexprinplace(&n->right, order);
break;
+ case OAPPEND:
case OCALLFUNC:
- case OCALLMETH:
case OCALLINTER:
- case OAPPEND:
+ case OCALLMETH:
+ case OCAP:
case OCOMPLEX:
+ case OCOPY:
+ case OIMAG:
+ case OLEN:
+ case OMAKECHAN:
+ case OMAKEMAP:
+ case OMAKESLICE:
+ case ONEW:
+ case OREAL:
+ case ORECOVER:
ordercall(n, order);
n = ordercopyexpr(n, n->type, order, 0);
break;
@@ -1055,6 +1080,19 @@ orderexpr(Node **np, Order *order)
orderexpr(&n->left, order);
n = ordercopyexpr(n, n->type, order, 1);
break;
+
+ case OEQ:
+ case ONE:
+ orderexpr(&n->left, order);
+ orderexpr(&n->right, order);
+ t = n->left->type;
+ if(t->etype == TSTRUCT || isfixedarray(t)) {
+ // for complex comparisons, we need both args to be
+ // addressable so we can pass them to the runtime.
+ orderaddrtemp(&n->left, order);
+ orderaddrtemp(&n->right, order);
+ }
+ break;
}
lineno = lno;
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
index 40620c3da..39028e3f8 100644
--- a/src/cmd/gc/pgen.c
+++ b/src/cmd/gc/pgen.c
@@ -11,9 +11,10 @@
#include "md5.h"
#include "gg.h"
#include "opt.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
static void allocauto(Prog* p);
+static void emitptrargsmap(void);
static Sym*
makefuncdatasym(char *namefmt, int64 funcdatakind)
@@ -173,9 +174,17 @@ compile(Node *fn)
lno = setlineno(fn);
+ curfn = fn;
+ dowidth(curfn->type);
+
if(fn->nbody == nil) {
- if(pure_go || strncmp(fn->nname->sym->name, "init·", 6) == 0)
+ if(pure_go || strncmp(fn->nname->sym->name, "init·", 6) == 0) {
yyerror("missing function body", fn);
+ goto ret;
+ }
+ if(debug['A'])
+ goto ret;
+ emitptrargsmap();
goto ret;
}
@@ -184,9 +193,6 @@ compile(Node *fn)
// set up domain for labels
clearlabels();
- curfn = fn;
- dowidth(curfn->type);
-
if(curfn->type->outnamed) {
// add clearing of the output parameters
t = structfirst(&save, getoutarg(curfn->type));
@@ -229,9 +235,11 @@ compile(Node *fn)
ptxt->TEXTFLAG |= WRAPPER;
if(fn->needctxt)
ptxt->TEXTFLAG |= NEEDCTXT;
+ if(fn->nosplit)
+ ptxt->TEXTFLAG |= NOSPLIT;
// Clumsy but important.
- // See test/recover.go for test cases and src/pkg/reflect/value.go
+ // See test/recover.go for test cases and src/reflect/value.go
// for the actual functions being considered.
if(myimportpath != nil && strcmp(myimportpath, "reflect") == 0) {
if(strcmp(curfn->nname->sym->name, "callReflect") == 0 || strcmp(curfn->nname->sym->name, "callMethod") == 0)
@@ -327,6 +335,43 @@ ret:
lineno = lno;
}
+static void
+emitptrargsmap(void)
+{
+ int nptr, nbitmap, j, off;
+ vlong xoffset;
+ Bvec *bv;
+ Sym *sym;
+
+ sym = lookup(smprint("%s.args_stackmap", curfn->nname->sym->name));
+
+ nptr = curfn->type->argwid / widthptr;
+ bv = bvalloc(nptr*2);
+ nbitmap = 1;
+ if(curfn->type->outtuple > 0)
+ nbitmap = 2;
+ off = duint32(sym, 0, nbitmap);
+ off = duint32(sym, off, bv->n);
+ if(curfn->type->thistuple > 0) {
+ xoffset = 0;
+ twobitwalktype1(getthisx(curfn->type), &xoffset, bv);
+ }
+ if(curfn->type->intuple > 0) {
+ xoffset = 0;
+ twobitwalktype1(getinargx(curfn->type), &xoffset, bv);
+ }
+ for(j = 0; j < bv->n; j += 32)
+ off = duint32(sym, off, bv->b[j/32]);
+ if(curfn->type->outtuple > 0) {
+ xoffset = 0;
+ twobitwalktype1(getoutargx(curfn->type), &xoffset, bv);
+ for(j = 0; j < bv->n; j += 32)
+ off = duint32(sym, off, bv->b[j/32]);
+ }
+ ggloblsym(sym, off, RODATA);
+ free(bv);
+}
+
// 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.
diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c
index 7a40ab559..0feb2c710 100644
--- a/src/cmd/gc/plive.c
+++ b/src/cmd/gc/plive.c
@@ -17,9 +17,9 @@
#include <libc.h>
#include "gg.h"
#include "opt.h"
-#include "../../pkg/runtime/funcdata.h"
-
-enum { BitsPerPointer = 2 };
+#include "../ld/textflag.h"
+#include "../../runtime/funcdata.h"
+#include "../../runtime/mgc0.h"
enum {
UNVISITED = 0,
@@ -674,8 +674,8 @@ static void
progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
{
ProgInfo info;
- Adr *from;
- Adr *to;
+ Addr *from;
+ Addr *to;
Node *node;
int32 i;
int32 pos;
@@ -1063,7 +1063,7 @@ checkptxt(Node *fn, Prog *firstp)
// and then simply copied into bv at the correct offset on future calls with
// the same type t. On https://rsc.googlecode.com/hg/testdata/slow.go, twobitwalktype1
// accounts for 40% of the 6g execution time.
-static void
+void
twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
{
vlong fieldoffset;
@@ -1113,8 +1113,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { byte *str; intgo len; }
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid alignment, %T", t);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 0);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 3:0 = multiword:string
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot
*xoffset += t->width;
break;
@@ -1145,9 +1144,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { byte *array; uintgo len; uintgo cap; }
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid TARRAY alignment, %T", t);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 0);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 2); // 3:1 = multiword/slice
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot
*xoffset += t->width;
} else
for(i = 0; i < t->bound; i++)
@@ -1683,6 +1680,13 @@ livenessepilogue(Liveness *lv)
// FNV-1 hash function constants.
#define H0 2166136261UL
#define Hp 16777619UL
+/*c2go
+enum
+{
+ H0 = 2166136261,
+ Hp = 16777619,
+};
+*/
static uint32
hashbitmap(uint32 h, Bvec *bv)
@@ -1932,11 +1936,15 @@ twobitwritesymbol(Array *arr, Sym *sym)
break;
for(j = 0; j < bv->n; j += 32) {
word = bv->b[j/32];
- off = duint32(sym, off, word);
+ // Runtime reads the bitmaps as byte arrays. Oblige.
+ off = duint8(sym, off, word);
+ off = duint8(sym, off, word>>8);
+ off = duint8(sym, off, word>>16);
+ off = duint8(sym, off, word>>24);
}
}
duint32(sym, 0, i); // number of bitmaps
- ggloblsym(sym, off, 0, 1);
+ ggloblsym(sym, off, RODATA);
}
static void
diff --git a/src/cmd/gc/popt.c b/src/cmd/gc/popt.c
index ea88b94db..993bb2482 100644
--- a/src/cmd/gc/popt.c
+++ b/src/cmd/gc/popt.c
@@ -49,7 +49,7 @@ noreturn(Prog *p)
symlist[0] = pkglookup("panicindex", runtimepkg);
symlist[1] = pkglookup("panicslice", runtimepkg);
symlist[2] = pkglookup("throwinit", runtimepkg);
- symlist[3] = pkglookup("panic", runtimepkg);
+ symlist[3] = pkglookup("gopanic", runtimepkg);
symlist[4] = pkglookup("panicwrap", runtimepkg);
symlist[5] = pkglookup("throwreturn", runtimepkg);
symlist[6] = pkglookup("selectgo", runtimepkg);
@@ -98,6 +98,10 @@ chasejmp(Prog *p, int *jmploop)
*/
#define alive ((void*)0)
#define dead ((void*)1)
+/*c2go
+extern void *alive;
+extern void *dead;
+*/
/* mark all code reachable from firstp as alive */
static void
diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c
index 285bd78a2..c9e27fe56 100644
--- a/src/cmd/gc/racewalk.c
+++ b/src/cmd/gc/racewalk.c
@@ -208,6 +208,26 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
goto ret;
case OCALLFUNC:
+ // Instrument dst argument of runtime.writebarrier* calls
+ // as we do not instrument runtime code.
+ if(n->left->sym != S && n->left->sym->pkg == runtimepkg && strncmp(n->left->sym->name, "writebarrier", 12) == 0) {
+ // Find the dst argument.
+ // The list can be reordered, so it's not necessary just the first or the second element.
+ for(l = n->list; l; l = l->next) {
+ if(strcmp(n->left->sym->name, "writebarrierfat") == 0) {
+ if(l->n->left->xoffset == widthptr)
+ break;
+ } else {
+ if(l->n->left->xoffset == 0)
+ break;
+ }
+ }
+ if(l == nil)
+ fatal("racewalk: writebarrier no arg");
+ if(l->n->right->op != OADDR)
+ fatal("racewalk: writebarrier bad arg");
+ callinstr(&l->n->right->left, init, 1, 0);
+ }
racewalknode(&n->left, init, 0, 0);
goto ret;
@@ -419,8 +439,10 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
ret:
if(n->op != OBLOCK) // OBLOCK is handled above in a special way.
racewalklist(n->list, init);
- racewalknode(&n->ntest, &n->ntest->ninit, 0, 0);
- racewalknode(&n->nincr, &n->nincr->ninit, 0, 0);
+ if(n->ntest != N)
+ racewalknode(&n->ntest, &n->ntest->ninit, 0, 0);
+ if(n->nincr != N)
+ racewalknode(&n->nincr, &n->nincr->ninit, 0, 0);
racewalklist(n->nbody, nil);
racewalklist(n->nelse, nil);
racewalklist(n->rlist, nil);
diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c
index 45aa521b3..4ed452832 100644
--- a/src/cmd/gc/range.c
+++ b/src/cmd/gc/range.c
@@ -67,9 +67,11 @@ typecheckrange(Node *n)
yyerror("too many variables in range");
}
- v1 = n->list->n;
+ v1 = N;
+ if(n->list)
+ v1 = n->list->n;
v2 = N;
- if(n->list->next)
+ if(n->list && n->list->next)
v2 = n->list->next->n;
// this is not only a optimization but also a requirement in the spec.
@@ -77,14 +79,17 @@ typecheckrange(Node *n)
// clause is equivalent to the same clause with only the first variable
// present."
if(isblank(v2)) {
- n->list = list1(v1);
+ if(v1 != N)
+ n->list = list1(v1);
v2 = N;
}
- if(v1->defn == n)
- v1->type = t1;
- else if(v1->type != T && assignop(t1, v1->type, &why) == 0)
- yyerror("cannot assign type %T to %lN in range%s", t1, v1, why);
+ if(v1) {
+ if(v1->defn == n)
+ v1->type = t1;
+ else if(v1->type != T && assignop(t1, v1->type, &why) == 0)
+ yyerror("cannot assign type %T to %lN in range%s", t1, v1, why);
+ }
if(v2) {
if(v2->defn == n)
v2->type = t2;
@@ -123,9 +128,11 @@ walkrange(Node *n)
a = n->right;
lno = setlineno(a);
- v1 = n->list->n;
+ v1 = N;
+ if(n->list)
+ v1 = n->list->n;
v2 = N;
- if(n->list->next && !isblank(n->list->next->n))
+ if(n->list && n->list->next && !isblank(n->list->next->n))
v2 = n->list->next->n;
// n->list has no meaning anymore, clear it
// to avoid erroneous processing by racewalk.
@@ -154,7 +161,9 @@ walkrange(Node *n)
n->ntest = nod(OLT, hv1, hn);
n->nincr = nod(OAS, hv1, nod(OADD, hv1, nodintconst(1)));
- if(v2 == N)
+ if(v1 == N)
+ body = nil;
+ else if(v2 == N)
body = list1(nod(OAS, v1, hv1));
else {
a = nod(OAS2, N, N);
@@ -205,16 +214,18 @@ walkrange(Node *n)
key = nod(ODOT, hit, keyname);
key = nod(OIND, key, N);
- if(v2 == N) {
- a = nod(OAS, v1, key);
+ if(v1 == N)
+ body = nil;
+ else if(v2 == N) {
+ body = list1(nod(OAS, v1, key));
} else {
val = nod(ODOT, hit, valname);
val = nod(OIND, val, N);
a = nod(OAS2, N, N);
a->list = list(list1(v1), v2);
a->rlist = list(list1(key), val);
+ body = list1(a);
}
- body = list1(a);
break;
case TCHAN:
@@ -223,6 +234,7 @@ walkrange(Node *n)
n->ntest = N;
hv1 = temp(t->type);
+ hv1->typecheck = 1;
if(haspointers(t->type))
init = list(init, nod(OAS, hv1, N));
hb = temp(types[TBOOL]);
@@ -233,7 +245,10 @@ walkrange(Node *n)
a->list = list(list1(hv1), hb);
a->rlist = list1(nod(ORECV, ha, N));
n->ntest->ninit = list1(a);
- body = list1(nod(OAS, v1, hv1));
+ if(v1 == N)
+ body = nil;
+ else
+ body = list1(nod(OAS, v1, hv1));
break;
case TSTRING:
@@ -257,7 +272,10 @@ walkrange(Node *n)
n->ntest = nod(ONE, hv1, nodintconst(0));
n->ntest->ninit = list(list1(nod(OAS, ohv1, hv1)), a);
- body = list1(nod(OAS, v1, ohv1));
+
+ body = nil;
+ if(v1 != N)
+ body = list1(nod(OAS, v1, ohv1));
if(v2 != N)
body = list(body, nod(OAS, v2, hv2));
break;
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index dbb447e4e..b2ff2fbc5 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -5,7 +5,9 @@
#include <u.h>
#include <libc.h>
#include "go.h"
-#include "../../pkg/runtime/mgc0.h"
+#include "../ld/textflag.h"
+#include "../../runtime/mgc0.h"
+#include "../../runtime/typekind.h"
/*
* runtime interface and reflection data structures
@@ -15,7 +17,9 @@ static NodeList* signatlist;
static Sym* dtypesym(Type*);
static Sym* weaktypesym(Type*);
static Sym* dalgsym(Type*);
-static Sym* dgcsym(Type*);
+static int usegcprog(Type*);
+static void gengcprog(Type*, Sym**, Sym**);
+static void gengcmask(Type*, uint8[16]);
static int
sigcmp(Sig *a, Sig *b)
@@ -105,7 +109,7 @@ lsort(Sig *l, int(*f)(Sig*, Sig*))
// the given map type. This type is not visible to users -
// we include only enough information to generate a correct GC
// program for it.
-// Make sure this stays in sync with ../../pkg/runtime/hashmap.c!
+// Make sure this stays in sync with ../../runtime/hashmap.c!
enum {
BUCKETSIZE = 8,
MAXKEYSIZE = 128,
@@ -188,7 +192,7 @@ mapbucket(Type *t)
// the given map type. This type is not visible to users -
// we include only enough information to generate a correct GC
// program for it.
-// Make sure this stays in sync with ../../pkg/runtime/hashmap.c!
+// Make sure this stays in sync with ../../runtime/hashmap.go!
static Type*
hmap(Type *t)
{
@@ -207,10 +211,6 @@ hmap(Type *t)
offset += 4; // flags
offset += 4; // hash0
offset += 1; // B
- offset += 1; // keysize
- offset += 1; // valuesize
- offset = (offset + 1) / 2 * 2;
- offset += 2; // bucketsize
offset = (offset + widthptr - 1) / widthptr * widthptr;
bucketsfield = typ(TFIELD);
@@ -261,7 +261,7 @@ hiter(Type *t)
// bptr *Bucket
// other [4]uintptr
// }
- // must match ../../pkg/runtime/hashmap.c:hash_iter.
+ // must match ../../runtime/hashmap.c:hash_iter.
field[0] = typ(TFIELD);
field[0]->type = ptrto(t->down);
field[0]->sym = mal(sizeof(Sym));
@@ -378,7 +378,7 @@ methods(Type *t)
// type stored in interface word
it = t;
- if(it->width > widthptr)
+ if(!isdirectiface(it))
it = ptrto(t);
// make list of methods for t,
@@ -524,7 +524,7 @@ dimportpath(Pkg *p)
p->pathsym = n->sym;
gdatastring(n, p->path);
- ggloblsym(n->sym, types[TSTRING]->width, 1, 1);
+ ggloblsym(n->sym, types[TSTRING]->width, DUPOK|RODATA);
}
static int
@@ -550,7 +550,7 @@ dgopkgpath(Sym *s, int ot, Pkg *pkg)
/*
* uncommonType
- * ../../pkg/runtime/type.go:/uncommonType
+ * ../../runtime/type.go:/uncommonType
*/
static int
dextratype(Sym *sym, int off, Type *t, int ptroff)
@@ -564,6 +564,7 @@ dextratype(Sym *sym, int off, Type *t, int ptroff)
return off;
// fill in *extraType pointer in header
+ off = rnd(off, widthptr);
dsymptr(sym, ptroff, sym, off);
n = 0;
@@ -593,7 +594,7 @@ dextratype(Sym *sym, int off, Type *t, int ptroff)
// methods
for(a=m; a; a=a->link) {
// method
- // ../../pkg/runtime/type.go:/method
+ // ../../runtime/type.go:/method
ot = dgostringptr(s, ot, a->name);
ot = dgopkgpath(s, ot, a->pkg);
ot = dsymptr(s, ot, dtypesym(a->mtype), 0);
@@ -611,37 +612,6 @@ dextratype(Sym *sym, int off, Type *t, int ptroff)
return ot;
}
-enum {
- KindBool = 1,
- 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,
-
- KindNoPointers = 1<<7,
-};
-
static int
kinds[] =
{
@@ -740,28 +710,30 @@ haspointers(Type *t)
/*
* commonType
- * ../../pkg/runtime/type.go:/commonType
+ * ../../runtime/type.go:/commonType
*/
static int
dcommontype(Sym *s, int ot, Type *t)
{
- int i, alg, sizeofAlg;
- Sym *sptr, *algsym, *zero;
+ int i, alg, sizeofAlg, gcprog;
+ Sym *sptr, *algsym, *zero, *gcprog0, *gcprog1, *sbits;
+ uint8 gcmask[16];
static Sym *algarray;
+ uint64 x1, x2;
char *p;
if(ot != 0)
fatal("dcommontype %d", ot);
- sizeofAlg = 4*widthptr;
+ sizeofAlg = 2*widthptr;
if(algarray == nil)
algarray = pkglookup("algarray", runtimepkg);
+ dowidth(t);
alg = algtype(t);
algsym = S;
if(alg < 0)
algsym = dalgsym(t);
- dowidth(t);
if(t->sym != nil && !isptr[t->etype])
sptr = dtypesym(ptrto(t));
else
@@ -808,17 +780,52 @@ dcommontype(Sym *s, int ot, Type *t)
ot = duint8(s, ot, t->align); // align
ot = duint8(s, ot, t->align); // fieldAlign
+ gcprog = usegcprog(t);
i = kinds[t->etype];
if(t->etype == TARRAY && t->bound < 0)
i = KindSlice;
if(!haspointers(t))
i |= KindNoPointers;
+ if(isdirectiface(t))
+ i |= KindDirectIface;
+ if(gcprog)
+ i |= KindGCProg;
ot = duint8(s, ot, i); // kind
if(alg >= 0)
ot = dsymptr(s, ot, algarray, alg*sizeofAlg);
else
ot = dsymptr(s, ot, algsym, 0);
- ot = dsymptr(s, ot, dgcsym(t), 0); // gc
+ // gc
+ if(gcprog) {
+ gengcprog(t, &gcprog0, &gcprog1);
+ if(gcprog0 != S)
+ ot = dsymptr(s, ot, gcprog0, 0);
+ else
+ ot = duintptr(s, ot, 0);
+ ot = dsymptr(s, ot, gcprog1, 0);
+ } else {
+ gengcmask(t, gcmask);
+ x1 = 0;
+ for(i=0; i<8; i++)
+ x1 = x1<<8 | gcmask[i];
+ if(widthptr == 4) {
+ p = smprint("gcbits.%#016llux", x1);
+ } else {
+ x2 = 0;
+ for(i=0; i<8; i++)
+ x2 = x2<<8 | gcmask[i+8];
+ p = smprint("gcbits.%#016llux%016llux", x1, x2);
+ }
+ sbits = pkglookup(p, runtimepkg);
+ if((sbits->flags & SymUniq) == 0) {
+ sbits->flags |= SymUniq;
+ for(i = 0; i < 2*widthptr; i++)
+ duint8(sbits, i, gcmask[i]);
+ ggloblsym(sbits, 2*widthptr, DUPOK|RODATA);
+ }
+ ot = dsymptr(s, ot, sbits, 0);
+ ot = duintptr(s, ot, 0);
+ }
p = smprint("%-uT", t);
//print("dcommontype: %s\n", p);
ot = dgostringptr(s, ot, p); // string
@@ -975,7 +982,9 @@ dtypesym(Type *t)
tbase = t;
if(isptr[t->etype] && t->sym == S && t->type->sym != S)
tbase = t->type;
- dupok = tbase->sym == S;
+ dupok = 0;
+ if(tbase->sym == S)
+ dupok = DUPOK;
if(compiling_runtime &&
(tbase == types[tbase->etype] ||
@@ -1002,7 +1011,7 @@ ok:
case TARRAY:
if(t->bound >= 0) {
- // ../../pkg/runtime/type.go:/ArrayType
+ // ../../runtime/type.go:/ArrayType
s1 = dtypesym(t->type);
t2 = typ(TARRAY);
t2->type = t->type;
@@ -1014,7 +1023,7 @@ ok:
ot = dsymptr(s, ot, s2, 0);
ot = duintptr(s, ot, t->bound);
} else {
- // ../../pkg/runtime/type.go:/SliceType
+ // ../../runtime/type.go:/SliceType
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
@@ -1023,7 +1032,7 @@ ok:
break;
case TCHAN:
- // ../../pkg/runtime/type.go:/ChanType
+ // ../../runtime/type.go:/ChanType
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
@@ -1073,14 +1082,14 @@ ok:
n++;
}
- // ../../pkg/runtime/type.go:/InterfaceType
+ // ../../runtime/type.go:/InterfaceType
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
ot = duintxx(s, ot, n, widthint);
ot = duintxx(s, ot, n, widthint);
for(a=m; a; a=a->link) {
- // ../../pkg/runtime/type.go:/imethod
+ // ../../runtime/type.go:/imethod
ot = dgostringptr(s, ot, a->name);
ot = dgopkgpath(s, ot, a->pkg);
ot = dsymptr(s, ot, dtypesym(a->type), 0);
@@ -1088,7 +1097,7 @@ ok:
break;
case TMAP:
- // ../../pkg/runtime/type.go:/MapType
+ // ../../runtime/type.go:/MapType
s1 = dtypesym(t->down);
s2 = dtypesym(t->type);
s3 = dtypesym(mapbucket(t));
@@ -1099,16 +1108,31 @@ ok:
ot = dsymptr(s, ot, s2, 0);
ot = dsymptr(s, ot, s3, 0);
ot = dsymptr(s, ot, s4, 0);
+ if(t->down->width > MAXKEYSIZE) {
+ ot = duint8(s, ot, widthptr);
+ ot = duint8(s, ot, 1); // indirect
+ } else {
+ ot = duint8(s, ot, t->down->width);
+ ot = duint8(s, ot, 0); // not indirect
+ }
+ if(t->type->width > MAXVALSIZE) {
+ ot = duint8(s, ot, widthptr);
+ ot = duint8(s, ot, 1); // indirect
+ } else {
+ ot = duint8(s, ot, t->type->width);
+ ot = duint8(s, ot, 0); // not indirect
+ }
+ ot = duint16(s, ot, mapbucket(t)->width);
break;
case TPTR32:
case TPTR64:
if(t->type->etype == TANY) {
- // ../../pkg/runtime/type.go:/UnsafePointerType
+ // ../../runtime/type.go:/UnsafePointerType
ot = dcommontype(s, ot, t);
break;
}
- // ../../pkg/runtime/type.go:/PtrType
+ // ../../runtime/type.go:/PtrType
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
@@ -1116,7 +1140,7 @@ ok:
break;
case TSTRUCT:
- // ../../pkg/runtime/type.go:/StructType
+ // ../../runtime/type.go:/StructType
// for security, only the exported fields.
n = 0;
for(t1=t->type; t1!=T; t1=t1->down) {
@@ -1129,7 +1153,7 @@ ok:
ot = duintxx(s, ot, n, widthint);
ot = duintxx(s, ot, n, widthint);
for(t1=t->type; t1!=T; t1=t1->down) {
- // ../../pkg/runtime/type.go:/structField
+ // ../../runtime/type.go:/structField
if(t1->sym && !t1->embedded) {
ot = dgostringptr(s, ot, t1->sym->name);
if(exportname(t1->sym->name))
@@ -1150,7 +1174,7 @@ ok:
break;
}
ot = dextratype(s, ot, t, xt);
- ggloblsym(s, ot, dupok, 1);
+ ggloblsym(s, ot, dupok|RODATA);
// generate typelink.foo pointing at s = type.foo.
// The linker will leave a table of all the typelinks for
@@ -1164,7 +1188,7 @@ ok:
case TMAP:
slink = typelinksym(t);
dsymptr(slink, 0, s, 0);
- ggloblsym(slink, widthptr, dupok, 1);
+ ggloblsym(slink, widthptr, dupok|RODATA);
}
}
@@ -1236,8 +1260,7 @@ static Sym*
dalgsym(Type *t)
{
int ot;
- Sym *s, *hash, *eq;
- char buf[100];
+ Sym *s, *hash, *hashfunc, *eq, *eqfunc;
// dalgsym is only called for a type that needs an algorithm table,
// which implies that the type is comparable (or else it would use ANOEQ).
@@ -1248,55 +1271,225 @@ dalgsym(Type *t)
eq = typesymprefix(".eq", t);
geneq(eq, t);
- // ../../pkg/runtime/runtime.h:/Alg
+ // make Go funcs (closures) for calling hash and equal from Go
+ hashfunc = typesymprefix(".hashfunc", t);
+ dsymptr(hashfunc, 0, hash, 0);
+ ggloblsym(hashfunc, widthptr, DUPOK|RODATA);
+ eqfunc = typesymprefix(".eqfunc", t);
+ dsymptr(eqfunc, 0, eq, 0);
+ ggloblsym(eqfunc, widthptr, DUPOK|RODATA);
+
+ // ../../runtime/alg.go:/typeAlg
ot = 0;
- ot = dsymptr(s, ot, hash, 0);
- ot = dsymptr(s, ot, eq, 0);
- ot = dsymptr(s, ot, pkglookup("memprint", runtimepkg), 0);
- switch(t->width) {
- default:
- ot = dsymptr(s, ot, pkglookup("memcopy", runtimepkg), 0);
- break;
- case 1:
- case 2:
- case 4:
- case 8:
- case 16:
- snprint(buf, sizeof buf, "memcopy%d", (int)t->width*8);
- ot = dsymptr(s, ot, pkglookup(buf, runtimepkg), 0);
- break;
- }
+ ot = dsymptr(s, ot, hashfunc, 0);
+ ot = dsymptr(s, ot, eqfunc, 0);
- ggloblsym(s, ot, 1, 1);
+ ggloblsym(s, ot, DUPOK|RODATA);
return s;
}
static int
-gcinline(Type *t)
+usegcprog(Type *t)
{
- switch(t->etype) {
- case TARRAY:
- if(t->bound == 1)
- return 1;
- if(t->width <= 4*widthptr)
- return 1;
- break;
+ vlong size, nptr;
+
+ if(!haspointers(t))
+ return 0;
+ if(t->width == BADWIDTH)
+ dowidth(t);
+ // Calculate size of the unrolled GC mask.
+ nptr = (t->width+widthptr-1)/widthptr;
+ size = nptr;
+ if(size%2)
+ size *= 2; // repeated
+ size = size*gcBits/8; // 4 bits per word
+ // Decide whether to use unrolled GC mask or GC program.
+ // We could use a more elaborate condition, but this seems to work well in practice.
+ // For small objects GC program can't give significant reduction.
+ // While large objects usually contain arrays; and even if it don't
+ // the program uses 2-bits per word while mask uses 4-bits per word,
+ // so the program is still smaller.
+ return size > 2*widthptr;
+}
+
+// Generates sparse GC bitmask (4 bits per word).
+static void
+gengcmask(Type *t, uint8 gcmask[16])
+{
+ Bvec *vec;
+ vlong xoffset, nptr, i, j;
+ int half, mw;
+ uint8 bits, *pos;
+
+ memset(gcmask, 0, 16);
+ if(!haspointers(t))
+ return;
+
+ // Generate compact mask as stacks use.
+ xoffset = 0;
+ vec = bvalloc(2*widthptr*8);
+ twobitwalktype1(t, &xoffset, vec);
+
+ // Unfold the mask for the GC bitmap format:
+ // 4 bits per word, 2 high bits encode pointer info.
+ pos = (uint8*)gcmask;
+ nptr = (t->width+widthptr-1)/widthptr;
+ half = 0;
+ mw = 0;
+ // If number of words is odd, repeat the mask.
+ // This makes simpler handling of arrays in runtime.
+ for(j=0; j<=(nptr%2); j++) {
+ for(i=0; i<nptr; i++) {
+ bits = bvget(vec, i*BitsPerPointer) | bvget(vec, i*BitsPerPointer+1)<<1;
+ // Some fake types (e.g. Hmap) has missing fileds.
+ // twobitwalktype1 generates BitsDead for that holes,
+ // replace BitsDead with BitsScalar.
+ if(!mw && bits == BitsDead)
+ bits = BitsScalar;
+ mw = !mw && bits == BitsMultiWord;
+ bits <<= 2;
+ if(half)
+ bits <<= 4;
+ *pos |= bits;
+ half = !half;
+ if(!half)
+ pos++;
+ }
}
- return 0;
}
-static int
-dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
+// Helper object for generation of GC programs.
+typedef struct ProgGen ProgGen;
+struct ProgGen
{
- Type *t1;
- vlong o, off2, fieldoffset, i;
+ Sym* s;
+ int32 datasize;
+ uint8 data[256/PointersPerByte];
+ vlong ot;
+};
- if(t->align > 0 && (*off % t->align) != 0)
- fatal("dgcsym1: invalid initial alignment, %T", t);
+static void
+proggeninit(ProgGen *g, Sym *s)
+{
+ g->s = s;
+ g->datasize = 0;
+ g->ot = 0;
+ memset(g->data, 0, sizeof(g->data));
+}
+
+static void
+proggenemit(ProgGen *g, uint8 v)
+{
+ g->ot = duint8(g->s, g->ot, v);
+}
+
+// Emits insData block from g->data.
+static void
+proggendataflush(ProgGen *g)
+{
+ int32 i, s;
+
+ if(g->datasize == 0)
+ return;
+ proggenemit(g, insData);
+ proggenemit(g, g->datasize);
+ s = (g->datasize + PointersPerByte - 1)/PointersPerByte;
+ for(i = 0; i < s; i++)
+ proggenemit(g, g->data[i]);
+ g->datasize = 0;
+ memset(g->data, 0, sizeof(g->data));
+}
+
+static void
+proggendata(ProgGen *g, uint8 d)
+{
+ g->data[g->datasize/PointersPerByte] |= d << ((g->datasize%PointersPerByte)*BitsPerPointer);
+ g->datasize++;
+ if(g->datasize == 255)
+ proggendataflush(g);
+}
+
+// Skip v bytes due to alignment, etc.
+static void
+proggenskip(ProgGen *g, vlong off, vlong v)
+{
+ vlong i;
+
+ for(i = off; i < off+v; i++) {
+ if((i%widthptr) == 0)
+ proggendata(g, BitsScalar);
+ }
+}
+
+// Emit insArray instruction.
+static void
+proggenarray(ProgGen *g, vlong len)
+{
+ int32 i;
+
+ proggendataflush(g);
+ proggenemit(g, insArray);
+ for(i = 0; i < widthptr; i++, len >>= 8)
+ proggenemit(g, len);
+}
+
+static void
+proggenarrayend(ProgGen *g)
+{
+ proggendataflush(g);
+ proggenemit(g, insArrayEnd);
+}
+
+static vlong
+proggenfini(ProgGen *g)
+{
+ proggendataflush(g);
+ proggenemit(g, insEnd);
+ return g->ot;
+}
+
+static void gengcprog1(ProgGen *g, Type *t, vlong *xoffset);
+
+// Generates GC program for large types.
+static void
+gengcprog(Type *t, Sym **pgc0, Sym **pgc1)
+{
+ Sym *gc0, *gc1;
+ vlong nptr, size, ot, xoffset;
+ ProgGen g;
+
+ nptr = (t->width+widthptr-1)/widthptr;
+ size = nptr;
+ if(size%2)
+ size *= 2; // repeated twice
+ size = size*PointersPerByte/8; // 4 bits per word
+ size++; // unroll flag in the beginning, used by runtime (see runtime.markallocated)
+ // emity space in BSS for unrolled program
+ *pgc0 = S;
+ // Don't generate it if it's too large, runtime will unroll directly into GC bitmap.
+ if(size <= MaxGCMask) {
+ gc0 = typesymprefix(".gc", t);
+ ggloblsym(gc0, size, DUPOK|NOPTR);
+ *pgc0 = gc0;
+ }
+
+ // program in RODATA
+ gc1 = typesymprefix(".gcprog", t);
+ proggeninit(&g, gc1);
+ xoffset = 0;
+ gengcprog1(&g, t, &xoffset);
+ ot = proggenfini(&g);
+ ggloblsym(gc1, ot, DUPOK|RODATA);
+ *pgc1 = gc1;
+}
+
+// Recursively walks type t and writes GC program into g.
+static void
+gengcprog1(ProgGen *g, Type *t, vlong *xoffset)
+{
+ vlong fieldoffset, i, o, n;
+ Type *t1;
- if(t->width == BADWIDTH)
- dowidth(t);
-
switch(t->etype) {
case TINT8:
case TUINT8:
@@ -1314,187 +1507,71 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
case TFLOAT64:
case TCOMPLEX64:
case TCOMPLEX128:
- *off += t->width;
+ proggenskip(g, *xoffset, t->width);
+ *xoffset += t->width;
break;
-
case TPTR32:
case TPTR64:
- // NOTE: Any changes here need to be made to reflect.PtrTo as well.
- if(*off % widthptr != 0)
- fatal("dgcsym1: invalid alignment, %T", t);
-
- // NOTE(rsc): Emitting GC_APTR here for *nonptrtype
- // (pointer to non-pointer-containing type) means that
- // we do not record 'nonptrtype' and instead tell the
- // garbage collector to look up the type of the memory in
- // type information stored in the heap. In effect we are telling
- // the collector "we don't trust our information - use yours".
- // It's not completely clear why we want to do this.
- // It does have the effect that if you have a *SliceHeader and a *[]int
- // pointing at the same actual slice header, *SliceHeader will not be
- // used as an authoritative type for the memory, which is good:
- // if the collector scanned the memory as type *SliceHeader, it would
- // see no pointers inside but mark the block as scanned, preventing
- // the seeing of pointers when we followed the *[]int pointer.
- // Perhaps that kind of situation is the rationale.
- if(!haspointers(t->type)) {
- ot = duintptr(s, ot, GC_APTR);
- ot = duintptr(s, ot, *off);
- } else {
- ot = duintptr(s, ot, GC_PTR);
- ot = duintptr(s, ot, *off);
- ot = dsymptr(s, ot, dgcsym(t->type), 0);
- }
- *off += t->width;
- break;
-
case TUNSAFEPTR:
case TFUNC:
- if(*off % widthptr != 0)
- fatal("dgcsym1: invalid alignment, %T", t);
- ot = duintptr(s, ot, GC_APTR);
- ot = duintptr(s, ot, *off);
- *off += t->width;
- break;
-
- // struct Hchan*
case TCHAN:
- // NOTE: Any changes here need to be made to reflect.ChanOf as well.
- if(*off % widthptr != 0)
- fatal("dgcsym1: invalid alignment, %T", t);
- ot = duintptr(s, ot, GC_CHAN_PTR);
- ot = duintptr(s, ot, *off);
- ot = dsymptr(s, ot, dtypesym(t), 0);
- *off += t->width;
- break;
-
- // struct Hmap*
case TMAP:
- // NOTE: Any changes here need to be made to reflect.MapOf as well.
- if(*off % widthptr != 0)
- fatal("dgcsym1: invalid alignment, %T", t);
- ot = duintptr(s, ot, GC_PTR);
- ot = duintptr(s, ot, *off);
- ot = dsymptr(s, ot, dgcsym(hmap(t)), 0);
- *off += t->width;
+ proggendata(g, BitsPointer);
+ *xoffset += t->width;
break;
-
- // struct { byte *str; int32 len; }
case TSTRING:
- if(*off % widthptr != 0)
- fatal("dgcsym1: invalid alignment, %T", t);
- ot = duintptr(s, ot, GC_STRING);
- ot = duintptr(s, ot, *off);
- *off += t->width;
+ proggendata(g, BitsPointer);
+ proggendata(g, BitsScalar);
+ *xoffset += t->width;
break;
-
- // struct { Itab* tab; void* data; }
- // struct { Type* type; void* data; } // When isnilinter(t)==true
case TINTER:
- if(*off % widthptr != 0)
- fatal("dgcsym1: invalid alignment, %T", t);
- if(isnilinter(t)) {
- ot = duintptr(s, ot, GC_EFACE);
- ot = duintptr(s, ot, *off);
- } else {
- ot = duintptr(s, ot, GC_IFACE);
- ot = duintptr(s, ot, *off);
- }
- *off += t->width;
+ proggendata(g, BitsMultiWord);
+ if(isnilinter(t))
+ proggendata(g, BitsEface);
+ else
+ proggendata(g, BitsIface);
+ *xoffset += t->width;
break;
-
case TARRAY:
- if(t->bound < -1)
- fatal("dgcsym1: invalid bound, %T", t);
- if(t->type->width == BADWIDTH)
- dowidth(t->type);
if(isslice(t)) {
- // NOTE: Any changes here need to be made to reflect.SliceOf as well.
- // struct { byte* array; uint32 len; uint32 cap; }
- if(*off % widthptr != 0)
- fatal("dgcsym1: invalid alignment, %T", t);
- if(t->type->width != 0) {
- ot = duintptr(s, ot, GC_SLICE);
- ot = duintptr(s, ot, *off);
- ot = dsymptr(s, ot, dgcsym(t->type), 0);
- } else {
- ot = duintptr(s, ot, GC_APTR);
- ot = duintptr(s, ot, *off);
- }
- *off += t->width;
+ proggendata(g, BitsPointer);
+ proggendata(g, BitsScalar);
+ proggendata(g, BitsScalar);
} else {
- // NOTE: Any changes here need to be made to reflect.ArrayOf as well,
- // at least once ArrayOf's gc info is implemented and ArrayOf is exported.
- // struct { byte* array; uint32 len; uint32 cap; }
- if(t->bound < 1 || !haspointers(t->type)) {
- *off += t->width;
- } else if(gcinline(t)) {
- for(i=0; i<t->bound; i++)
- ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1
+ t1 = t->type;
+ if(t1->width == 0) {
+ // ignore
+ } if(t->bound <= 1 || t->bound*t1->width < 32*widthptr) {
+ for(i = 0; i < t->bound; i++)
+ gengcprog1(g, t1, xoffset);
+ } else if(!haspointers(t1)) {
+ n = t->width;
+ n -= -*xoffset&(widthptr-1); // skip to next ptr boundary
+ proggenarray(g, (n+widthptr-1)/widthptr);
+ proggendata(g, BitsScalar);
+ proggenarrayend(g);
+ *xoffset -= (n+widthptr-1)/widthptr*widthptr - t->width;
} else {
- if(stack_size < GC_STACK_CAPACITY) {
- ot = duintptr(s, ot, GC_ARRAY_START); // a stack push during GC
- ot = duintptr(s, ot, *off);
- ot = duintptr(s, ot, t->bound);
- ot = duintptr(s, ot, t->type->width);
- off2 = 0;
- ot = dgcsym1(s, ot, t->type, &off2, stack_size+1); // recursive call of dgcsym1
- ot = duintptr(s, ot, GC_ARRAY_NEXT); // a stack pop during GC
- } else {
- ot = duintptr(s, ot, GC_REGION);
- ot = duintptr(s, ot, *off);
- ot = duintptr(s, ot, t->width);
- ot = dsymptr(s, ot, dgcsym(t), 0);
- }
- *off += t->width;
+ proggenarray(g, t->bound);
+ gengcprog1(g, t1, xoffset);
+ *xoffset += (t->bound-1)*t1->width;
+ proggenarrayend(g);
}
}
break;
-
case TSTRUCT:
o = 0;
- for(t1=t->type; t1!=T; t1=t1->down) {
+ for(t1 = t->type; t1 != T; t1 = t1->down) {
fieldoffset = t1->width;
- *off += fieldoffset - o;
- ot = dgcsym1(s, ot, t1->type, off, stack_size); // recursive call of dgcsym1
+ proggenskip(g, *xoffset, fieldoffset - o);
+ *xoffset += fieldoffset - o;
+ gengcprog1(g, t1->type, xoffset);
o = fieldoffset + t1->type->width;
}
- *off += t->width - o;
+ proggenskip(g, *xoffset, t->width - o);
+ *xoffset += t->width - o;
break;
-
default:
- fatal("dgcsym1: unexpected type %T", t);
+ fatal("gengcprog1: unexpected type, %T", t);
}
-
- return ot;
-}
-
-static Sym*
-dgcsym(Type *t)
-{
- int ot;
- vlong off;
- Sym *s;
-
- s = typesymprefix(".gc", t);
- if(s->flags & SymGcgen)
- return s;
- s->flags |= SymGcgen;
-
- if(t->width == BADWIDTH)
- dowidth(t);
-
- ot = 0;
- off = 0;
- ot = duintptr(s, ot, t->width);
- ot = dgcsym1(s, ot, t, &off, 0);
- ot = duintptr(s, ot, GC_END);
- ggloblsym(s, ot, 1, 1);
-
- if(t->align > 0)
- off = rnd(off, t->align);
- if(off != t->width)
- fatal("dgcsym: off=%lld, size=%lld, type %T", off, t->width, t);
-
- return s;
}
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index fb5c2a150..0fb15c265 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -12,7 +12,7 @@ package PACKAGE
// emitted by compiler, not referred to by go programs
-func new(typ *byte) *any
+func newobject(typ *byte) *any
func panicindex()
func panicslice()
func panicdivide()
@@ -20,12 +20,13 @@ func throwreturn()
func throwinit()
func panicwrap(string, string, string)
-func panic(interface{})
-func recover(*int32) interface{}
+func gopanic(interface{})
+func gorecover(*int32) interface{}
func printbool(bool)
func printfloat(float64)
func printint(int64)
+func printhex(uint64)
func printuint(uint64)
func printcomplex(complex128)
func printstring(string)
@@ -35,7 +36,6 @@ func printeface(any)
func printslice(any)
func printnl()
func printsp()
-func goprintf()
func concatstring2(string, string) string
func concatstring3(string, string, string) string
@@ -53,7 +53,7 @@ func stringtoslicebyte(string) []byte
func stringtoslicerune(string) []rune
func stringiter(string, int) int
func stringiter2(string, int) (retk int, retv rune)
-func copy(to any, fr any, wid uintptr) int
+func slicecopy(to any, fr any, wid uintptr) int
func slicestringcopy(to any, fr any) int
// interface conversions
@@ -84,8 +84,6 @@ func efaceeq(i1 any, i2 any) (ret bool)
func ifacethash(i1 any) (ret uint32)
func efacethash(i1 any) (ret uint32)
-func equal(typ *byte, x1, x2 any) (ret bool)
-
// *byte is really *runtime.Type
func makemap(mapType *byte, hint int64) (hmap map[any]any)
func mapaccess1(mapType *byte, hmap map[any]any, key *any) (val *any)
@@ -108,11 +106,25 @@ func chanrecv2(chanType *byte, hchan <-chan any, elem *any) bool
func chansend1(chanType *byte, hchan chan<- any, elem *any)
func closechan(hchan any)
+// *byte is really *runtime.Type
+func writebarrierptr(dst *any, src any)
+func writebarrierstring(dst *any, src any)
+func writebarrierslice(dst *any, src any)
+func writebarrieriface(dst *any, src any)
+
+// The unused *byte argument makes sure that src is 2-pointer-aligned,
+// which is the maximum alignment on NaCl amd64p32
+// (and possibly on 32-bit systems if we start 64-bit aligning uint64s).
+func writebarrierfat2(dst *any, _ *byte, src any)
+func writebarrierfat3(dst *any, _ *byte, src any)
+func writebarrierfat4(dst *any, _ *byte, src any)
+func writebarrierfat(typ *byte, dst *any, src *any)
+
func selectnbsend(chanType *byte, hchan chan<- any, elem *any) bool
func selectnbrecv(chanType *byte, elem *any, hchan <-chan any) bool
func selectnbrecv2(chanType *byte, elem *any, received *bool, hchan <-chan any) bool
-func newselect(size int32) (sel *byte)
+func newselect(sel *byte, selsize int64, size int32)
func selectsend(sel *byte, hchan chan<- any, elem *any) (selected bool)
func selectrecv(sel *byte, hchan <-chan any, elem *any) (selected bool)
func selectrecv2(sel *byte, hchan <-chan any, elem *any, received *bool) (selected bool)
@@ -124,12 +136,12 @@ func makeslice(typ *byte, nel int64, cap int64) (ary []any)
func growslice(typ *byte, old []any, n int64) (ary []any)
func memmove(to *any, frm *any, length uintptr)
-func memequal(eq *bool, size uintptr, x, y *any)
-func memequal8(eq *bool, size uintptr, x, y *any)
-func memequal16(eq *bool, size uintptr, x, y *any)
-func memequal32(eq *bool, size uintptr, x, y *any)
-func memequal64(eq *bool, size uintptr, x, y *any)
-func memequal128(eq *bool, size uintptr, x, y *any)
+func memequal(x, y *any, size uintptr) bool
+func memequal8(x, y *any, size uintptr) bool
+func memequal16(x, y *any, size uintptr) bool
+func memequal32(x, y *any, size uintptr) bool
+func memequal64(x, y *any, size uintptr) bool
+func memequal128(x, y *any, size uintptr) bool
// only used on 32-bit
func int64div(int64, int64) int64
diff --git a/src/cmd/gc/select.c b/src/cmd/gc/select.c
index 58a120674..965ad277f 100644
--- a/src/cmd/gc/select.c
+++ b/src/cmd/gc/select.c
@@ -10,6 +10,8 @@
#include <libc.h>
#include "go.h"
+static Type* selecttype(int32 size);
+
void
typecheckselect(Node *sel)
{
@@ -95,7 +97,7 @@ void
walkselect(Node *sel)
{
int lno, i;
- Node *n, *r, *a, *var, *cas, *dflt, *ch;
+ Node *n, *r, *a, *var, *selv, *cas, *dflt, *ch;
NodeList *l, *init;
if(sel->list == nil && sel->xoffset != 0)
@@ -257,8 +259,12 @@ walkselect(Node *sel)
// generate sel-struct
setlineno(sel);
- var = temp(ptrto(types[TUINT8]));
- r = nod(OAS, var, mkcall("newselect", var->type, nil, nodintconst(sel->xoffset)));
+ selv = temp(selecttype(sel->xoffset));
+ r = nod(OAS, selv, N);
+ typecheck(&r, Etop);
+ init = list(init, r);
+ var = conv(conv(nod(OADDR, selv, N), types[TUNSAFEPTR]), ptrto(types[TUINT8]));
+ r = mkcall("newselect", T, nil, var, nodintconst(selv->type->width), nodintconst(sel->xoffset));
typecheck(&r, Etop);
init = list(init, r);
@@ -301,6 +307,8 @@ walkselect(Node *sel)
break;
}
}
+ // selv is no longer alive after use.
+ r->nbody = list(r->nbody, nod(OVARKILL, selv, N));
r->nbody = concat(r->nbody, cas->nbody);
r->nbody = list(r->nbody, nod(OBREAK, N, N));
init = list(init, r);
@@ -316,3 +324,54 @@ out:
walkstmtlist(sel->nbody);
lineno = lno;
}
+
+// Keep in sync with src/runtime/chan.h.
+static Type*
+selecttype(int32 size)
+{
+ Node *sel, *sudog, *scase, *arr;
+
+ // TODO(dvyukov): it's possible to generate SudoG and Scase only once
+ // and then cache; and also cache Select per size.
+ sudog = nod(OTSTRUCT, N, N);
+ sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("g")), typenod(ptrto(types[TUINT8]))));
+ sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("selectdone")), typenod(ptrto(types[TUINT8]))));
+ sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("link")), typenod(ptrto(types[TUINT8]))));
+ sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("prev")), typenod(ptrto(types[TUINT8]))));
+ sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("elem")), typenod(ptrto(types[TUINT8]))));
+ sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("releasetime")), typenod(types[TUINT64])));
+ 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->local = 1;
+
+ scase = nod(OTSTRUCT, N, N);
+ scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("elem")), typenod(ptrto(types[TUINT8]))));
+ scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("chan")), typenod(ptrto(types[TUINT8]))));
+ scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("pc")), typenod(types[TUINTPTR])));
+ scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("kind")), typenod(types[TUINT16])));
+ scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("so")), typenod(types[TUINT16])));
+ 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->local = 1;
+
+ sel = nod(OTSTRUCT, N, N);
+ sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("tcase")), typenod(types[TUINT16])));
+ sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("ncase")), typenod(types[TUINT16])));
+ sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("pollorder")), typenod(ptrto(types[TUINT8]))));
+ sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("lockorder")), typenod(ptrto(types[TUINT8]))));
+ arr = nod(OTARRAY, nodintconst(size), scase);
+ sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("scase")), arr));
+ arr = nod(OTARRAY, nodintconst(size), typenod(ptrto(types[TUINT8])));
+ sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("lockorderarr")), arr));
+ arr = nod(OTARRAY, nodintconst(size), typenod(types[TUINT16]));
+ sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("pollorderarr")), arr));
+ typecheck(&sel, Etype);
+ sel->type->noalg = 1;
+ sel->type->local = 1;
+
+ return sel->type;
+}
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index 59804cd8d..8ad7ae7ab 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -17,7 +17,6 @@ enum
InitPending = 2,
};
-static int iszero(Node*);
static void initplan(Node*);
static NodeList *initlist;
static void init2(Node*, NodeList**);
@@ -207,7 +206,7 @@ init2(Node *n, NodeList **out)
if(n->op == OCLOSURE)
init2list(n->closure->nbody, out);
- if(n->op == ODOTMETH)
+ if(n->op == ODOTMETH || n->op == OCALLPART)
init2(n->type->nname, out);
}
@@ -633,11 +632,14 @@ structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
a = nod(ODOT, var, newname(index->sym));
a = nod(OAS, a, value);
typecheck(&a, Etop);
- walkexpr(&a, init);
if(pass == 1) {
+ walkexpr(&a, init); // add any assignments in r to top
if(a->op != OAS)
fatal("structlit: not as");
a->dodata = 2;
+ } else {
+ orderstmtinplace(&a);
+ walkstmt(&a);
}
*init = list(*init, a);
}
@@ -693,11 +695,14 @@ arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
a = nod(OINDEX, var, index);
a = nod(OAS, a, value);
typecheck(&a, Etop);
- walkexpr(&a, init); // add any assignments in r to top
if(pass == 1) {
+ walkexpr(&a, init);
if(a->op != OAS)
- fatal("structlit: not as");
+ fatal("arraylit: not as");
a->dodata = 2;
+ } else {
+ orderstmtinplace(&a);
+ walkstmt(&a);
}
*init = list(*init, a);
}
@@ -807,7 +812,8 @@ slicelit(int ctxt, Node *n, Node *var, NodeList **init)
// make slice out of heap (5)
a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N)));
typecheck(&a, Etop);
- walkexpr(&a, init);
+ orderstmtinplace(&a);
+ walkstmt(&a);
*init = list(*init, a);
// put dynamics into slice (6)
@@ -839,7 +845,8 @@ slicelit(int ctxt, Node *n, Node *var, NodeList **init)
// build list of var[c] = expr
a = nod(OAS, a, value);
typecheck(&a, Etop);
- walkexpr(&a, init);
+ orderstmtinplace(&a);
+ walkstmt(&a);
*init = list(*init, a);
}
}
@@ -1060,7 +1067,7 @@ anylit(int ctxt, Node *n, Node *var, NodeList **init)
if(t->etype != TSTRUCT)
fatal("anylit: not struct");
- if(simplename(var)) {
+ if(simplename(var) && count(n->list) > 4) {
if(ctxt == 0) {
// lay out static data
@@ -1083,7 +1090,7 @@ anylit(int ctxt, Node *n, Node *var, NodeList **init)
}
// initialize of not completely specified
- if(count(n->list) < structcount(t)) {
+ if(simplename(var) || count(n->list) < structcount(t)) {
a = nod(OAS, var, N);
typecheck(&a, Etop);
walkexpr(&a, init);
@@ -1100,7 +1107,7 @@ anylit(int ctxt, Node *n, Node *var, NodeList **init)
break;
}
- if(simplename(var)) {
+ if(simplename(var) && count(n->list) > 4) {
if(ctxt == 0) {
// lay out static data
@@ -1123,7 +1130,7 @@ anylit(int ctxt, Node *n, Node *var, NodeList **init)
}
// initialize of not completely specified
- if(count(n->list) < t->bound) {
+ if(simplename(var) || count(n->list) < t->bound) {
a = nod(OAS, var, N);
typecheck(&a, Etop);
walkexpr(&a, init);
@@ -1348,7 +1355,6 @@ no:
return 0;
}
-static int iszero(Node*);
static int isvaluelit(Node*);
static InitEntry* entry(InitPlan*);
static void addvalue(InitPlan*, vlong, Node*, Node*);
@@ -1432,7 +1438,7 @@ addvalue(InitPlan *p, vlong xoffset, Node *key, Node *n)
e->expr = n;
}
-static int
+int
iszero(Node *n)
{
NodeList *l;
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 72a9ac20c..c3bc5af3b 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -529,7 +529,8 @@ algtype1(Type *t, Type **bad)
if(bad)
*bad = T;
-
+ if(t->broke)
+ return AMEM;
if(t->noalg)
return ANOEQ;
@@ -656,11 +657,15 @@ maptype(Type *key, Type *val)
{
Type *t;
Type *bad;
- int atype;
+ int atype, mtype;
if(key != nil) {
atype = algtype1(key, &bad);
- switch(bad == T ? key->etype : bad->etype) {
+ if(bad == T)
+ mtype = key->etype;
+ else
+ mtype = bad->etype;
+ switch(mtype) {
default:
if(atype == ANOEQ)
yyerror("invalid map key type %T", key);
@@ -2625,9 +2630,10 @@ hashmem(Type *t)
n = newname(sym);
n->class = PFUNC;
tfn = nod(OTFUNC, N, N);
- tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(types[TUINTPTR]))));
- tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
+ tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
+ tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
+ tfn->rlist = list(tfn->rlist, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
typecheck(&tfn, Etype);
n->type = tfn->type;
return n;
@@ -2673,9 +2679,10 @@ hashfor(Type *t)
n = newname(sym);
n->class = PFUNC;
tfn = nod(OTFUNC, N, N);
- tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(types[TUINTPTR]))));
- tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
+ tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
+ tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
+ tfn->rlist = list(tfn->rlist, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
typecheck(&tfn, Etype);
n->type = tfn->type;
return n;
@@ -2687,7 +2694,7 @@ hashfor(Type *t)
void
genhash(Sym *sym, Type *t)
{
- Node *n, *fn, *np, *nh, *ni, *call, *nx, *na, *tfn;
+ Node *n, *fn, *np, *nh, *ni, *call, *nx, *na, *tfn, *r;
Node *hashel;
Type *first, *t1;
int old_safemode;
@@ -2700,21 +2707,23 @@ genhash(Sym *sym, Type *t)
dclcontext = PEXTERN;
markdcl();
- // func sym(h *uintptr, s uintptr, p *T)
+ // func sym(p *T, s uintptr, h uintptr) uintptr
fn = nod(ODCLFUNC, N, N);
fn->nname = newname(sym);
fn->nname->class = PFUNC;
tfn = nod(OTFUNC, N, N);
fn->nname->ntype = tfn;
- n = nod(ODCLFIELD, newname(lookup("h")), typenod(ptrto(types[TUINTPTR])));
+ n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t)));
tfn->list = list(tfn->list, n);
- nh = n->left;
+ np = n->left;
n = nod(ODCLFIELD, newname(lookup("s")), typenod(types[TUINTPTR]));
tfn->list = list(tfn->list, n);
- n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t)));
+ n = nod(ODCLFIELD, newname(lookup("h")), typenod(types[TUINTPTR]));
tfn->list = list(tfn->list, n);
- np = n->left;
+ nh = n->left;
+ n = nod(ODCLFIELD, N, typenod(types[TUINTPTR])); // return value
+ tfn->rlist = list(tfn->rlist, n);
funchdr(fn);
typecheck(&fn->nname->ntype, Etype);
@@ -2740,15 +2749,17 @@ genhash(Sym *sym, Type *t)
colasdefn(n->list, n);
ni = n->list->n;
- // *h = *h<<3 | *h>>61
+ // TODO: with aeshash we don't need these shift/mul parts
+
+ // h = h<<3 | h>>61
n->nbody = list(n->nbody,
nod(OAS,
- nod(OIND, nh, N),
+ nh,
nod(OOR,
- nod(OLSH, nod(OIND, nh, N), nodintconst(3)),
- nod(ORSH, nod(OIND, nh, N), nodintconst(widthptr*8-3)))));
+ nod(OLSH, nh, nodintconst(3)),
+ nod(ORSH, nh, nodintconst(widthptr*8-3)))));
- // *h *= mul
+ // h *= mul
// Same multipliers as in runtime.memhash.
if(widthptr == 4)
mul = 3267000013LL;
@@ -2756,19 +2767,19 @@ genhash(Sym *sym, Type *t)
mul = 23344194077549503LL;
n->nbody = list(n->nbody,
nod(OAS,
- nod(OIND, nh, N),
- nod(OMUL, nod(OIND, nh, N), nodintconst(mul))));
+ nh,
+ nod(OMUL, nh, nodintconst(mul))));
- // hashel(h, sizeof(p[i]), &p[i])
+ // h = hashel(&p[i], sizeof(p[i]), h)
call = nod(OCALL, hashel, N);
- call->list = list(call->list, nh);
- call->list = list(call->list, nodintconst(t->type->width));
nx = nod(OINDEX, np, ni);
nx->bounded = 1;
na = nod(OADDR, nx, N);
na->etype = 1; // no escape to heap
call->list = list(call->list, na);
- n->nbody = list(n->nbody, call);
+ call->list = list(call->list, nodintconst(t->type->width));
+ call->list = list(call->list, nh);
+ n->nbody = list(n->nbody, nod(OAS, nh, call));
fn->nbody = list(fn->nbody, n);
break;
@@ -2793,15 +2804,15 @@ genhash(Sym *sym, Type *t)
if(first != T) {
size = offend - first->width; // first->width is offset
hashel = hashmem(first->type);
- // hashel(h, size, &p.first)
+ // h = hashel(&p.first, size, h)
call = nod(OCALL, hashel, N);
- call->list = list(call->list, nh);
- call->list = list(call->list, nodintconst(size));
nx = nod(OXDOT, np, newname(first->sym)); // TODO: fields from other packages?
na = nod(OADDR, nx, N);
na->etype = 1; // no escape to heap
call->list = list(call->list, na);
- fn->nbody = list(fn->nbody, call);
+ call->list = list(call->list, nodintconst(size));
+ call->list = list(call->list, nh);
+ fn->nbody = list(fn->nbody, nod(OAS, nh, call));
first = T;
}
@@ -2812,20 +2823,21 @@ genhash(Sym *sym, Type *t)
// Run hash for this field.
hashel = hashfor(t1->type);
- // hashel(h, size, &p.t1)
+ // h = hashel(&p.t1, size, h)
call = nod(OCALL, hashel, N);
- call->list = list(call->list, nh);
- call->list = list(call->list, nodintconst(t1->type->width));
nx = nod(OXDOT, np, newname(t1->sym)); // TODO: fields from other packages?
na = nod(OADDR, nx, N);
na->etype = 1; // no escape to heap
call->list = list(call->list, na);
- fn->nbody = list(fn->nbody, call);
+ call->list = list(call->list, nodintconst(t1->type->width));
+ call->list = list(call->list, nh);
+ fn->nbody = list(fn->nbody, nod(OAS, nh, call));
}
- // make sure body is not empty.
- fn->nbody = list(fn->nbody, nod(ORETURN, N, N));
break;
}
+ r = nod(ORETURN, N, N);
+ r->list = list(r->list, nh);
+ fn->nbody = list(fn->nbody, r);
if(debug['r'])
dumplist("genhash body", fn->nbody);
@@ -2849,18 +2861,19 @@ genhash(Sym *sym, Type *t)
}
// Return node for
-// if p.field != q.field { *eq = false; return }
+// if p.field != q.field { return false }
static Node*
-eqfield(Node *p, Node *q, Node *field, Node *eq)
+eqfield(Node *p, Node *q, Node *field)
{
- Node *nif, *nx, *ny;
+ Node *nif, *nx, *ny, *r;
nx = nod(OXDOT, p, field);
ny = nod(OXDOT, q, field);
nif = nod(OIF, N, N);
nif->ntest = nod(ONE, nx, ny);
- nif->nbody = list(nif->nbody, nod(OAS, nod(OIND, eq, N), nodbool(0)));
- nif->nbody = list(nif->nbody, nod(ORETURN, N, N));
+ r = nod(ORETURN, N, N);
+ r->list = list(r->list, nodbool(0));
+ nif->nbody = list(nif->nbody, r);
return nif;
}
@@ -2889,11 +2902,11 @@ eqmemfunc(vlong size, Type *type)
}
// Return node for
-// if memequal(size, &p.field, &q.field, eq); !*eq { return }
+// if !memequal(&p.field, &q.field, size) { return false }
static Node*
-eqmem(Node *p, Node *q, Node *field, vlong size, Node *eq)
+eqmem(Node *p, Node *q, Node *field, vlong size)
{
- Node *nif, *nx, *ny, *call;
+ Node *nif, *nx, *ny, *call, *r;
nx = nod(OADDR, nod(OXDOT, p, field), N);
nx->etype = 1; // does not escape
@@ -2903,15 +2916,16 @@ eqmem(Node *p, Node *q, Node *field, vlong size, Node *eq)
typecheck(&ny, Erv);
call = nod(OCALL, eqmemfunc(size, nx->type->type), N);
- call->list = list(call->list, eq);
- call->list = list(call->list, nodintconst(size));
call->list = list(call->list, nx);
call->list = list(call->list, ny);
+ call->list = list(call->list, nodintconst(size));
nif = nod(OIF, N, N);
nif->ninit = list(nif->ninit, call);
- nif->ntest = nod(ONOT, nod(OIND, eq, N), N);
- nif->nbody = list(nif->nbody, nod(ORETURN, N, N));
+ nif->ntest = nod(ONOT, call, N);
+ r = nod(ORETURN, N, N);
+ r->list = list(r->list, nodbool(0));
+ nif->nbody = list(nif->nbody, r);
return nif;
}
@@ -2921,7 +2935,7 @@ eqmem(Node *p, Node *q, Node *field, vlong size, Node *eq)
void
geneq(Sym *sym, Type *t)
{
- Node *n, *fn, *np, *neq, *nq, *tfn, *nif, *ni, *nx, *ny, *nrange;
+ Node *n, *fn, *np, *nq, *tfn, *nif, *ni, *nx, *ny, *nrange, *r;
Type *t1, *first;
int old_safemode;
int64 size;
@@ -2934,24 +2948,23 @@ geneq(Sym *sym, Type *t)
dclcontext = PEXTERN;
markdcl();
- // func sym(eq *bool, s uintptr, p, q *T)
+ // func sym(p, q *T, s uintptr) bool
fn = nod(ODCLFUNC, N, N);
fn->nname = newname(sym);
fn->nname->class = PFUNC;
tfn = nod(OTFUNC, N, N);
fn->nname->ntype = tfn;
- n = nod(ODCLFIELD, newname(lookup("eq")), typenod(ptrto(types[TBOOL])));
- tfn->list = list(tfn->list, n);
- neq = n->left;
- n = nod(ODCLFIELD, newname(lookup("s")), typenod(types[TUINTPTR]));
- tfn->list = list(tfn->list, n);
n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t)));
tfn->list = list(tfn->list, n);
np = n->left;
n = nod(ODCLFIELD, newname(lookup("q")), typenod(ptrto(t)));
tfn->list = list(tfn->list, n);
nq = n->left;
+ n = nod(ODCLFIELD, newname(lookup("s")), typenod(types[TUINTPTR]));
+ tfn->list = list(tfn->list, n);
+ n = nod(ODCLFIELD, N, typenod(types[TBOOL]));
+ tfn->rlist = list(tfn->rlist, n);
funchdr(fn);
@@ -2977,7 +2990,7 @@ geneq(Sym *sym, Type *t)
colasdefn(nrange->list, nrange);
ni = nrange->list->n;
- // if p[i] != q[i] { *eq = false; return }
+ // if p[i] != q[i] { return false }
nx = nod(OINDEX, np, ni);
nx->bounded = 1;
ny = nod(OINDEX, nq, ni);
@@ -2985,13 +2998,11 @@ geneq(Sym *sym, Type *t)
nif = nod(OIF, N, N);
nif->ntest = nod(ONE, nx, ny);
- nif->nbody = list(nif->nbody, nod(OAS, nod(OIND, neq, N), nodbool(0)));
- nif->nbody = list(nif->nbody, nod(ORETURN, N, N));
+ r = nod(ORETURN, N, N);
+ r->list = list(r->list, nodbool(0));
+ nif->nbody = list(nif->nbody, r);
nrange->nbody = list(nrange->nbody, nif);
fn->nbody = list(fn->nbody, nrange);
-
- // *eq = true;
- fn->nbody = list(fn->nbody, nod(OAS, nod(OIND, neq, N), nodbool(1)));
break;
case TSTRUCT:
@@ -3016,16 +3027,16 @@ geneq(Sym *sym, Type *t)
// cross-package unexported fields.
if(first != T) {
if(first->down == t1) {
- fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
+ fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym)));
} else if(first->down->down == t1) {
- fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
+ fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym)));
first = first->down;
if(!isblanksym(first->sym))
- fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
+ fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym)));
} else {
// More than two fields: use memequal.
size = offend - first->width; // first->width is offset
- fn->nbody = list(fn->nbody, eqmem(np, nq, newname(first->sym), size, neq));
+ fn->nbody = list(fn->nbody, eqmem(np, nq, newname(first->sym), size));
}
first = T;
}
@@ -3035,14 +3046,17 @@ geneq(Sym *sym, Type *t)
continue;
// Check this field, which is not just memory.
- fn->nbody = list(fn->nbody, eqfield(np, nq, newname(t1->sym), neq));
+ fn->nbody = list(fn->nbody, eqfield(np, nq, newname(t1->sym)));
}
- // *eq = true;
- fn->nbody = list(fn->nbody, nod(OAS, nod(OIND, neq, N), nodbool(1)));
break;
}
+ // return true
+ r = nod(ORETURN, N, N);
+ r->list = list(r->list, nodbool(1));
+ fn->nbody = list(fn->nbody, r);
+
if(debug['r'])
dumplist("geneq body", fn->nbody);
@@ -3445,7 +3459,7 @@ smagic(Magic *m)
mask = 0xffffffffLL;
break;
case 64:
- mask = 0xffffffffffffffffLL;
+ mask = 0xffffffffffffffffULL;
break;
}
two31 = mask ^ (mask>>1);
@@ -3453,7 +3467,7 @@ smagic(Magic *m)
p = m->w-1;
ad = m->sd;
if(m->sd < 0)
- ad = -m->sd;
+ ad = -(uvlong)m->sd;
// bad denominators
if(ad == 0 || ad == 1 || ad == two31) {
@@ -3543,7 +3557,7 @@ umagic(Magic *m)
mask = 0xffffffffLL;
break;
case 64:
- mask = 0xffffffffffffffffLL;
+ mask = 0xffffffffffffffffULL;
break;
}
two31 = mask ^ (mask>>1);
@@ -3628,7 +3642,7 @@ ngotype(Node *n)
* users if we escape that as little as possible.
*
* If you edit this, edit ../ld/lib.c:/^pathtoprefix too.
- * If you edit this, edit ../../pkg/debug/goobj/read.go:/importPathToPrefix too.
+ * If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
*/
static char*
pathtoprefix(char *s)
@@ -3785,3 +3799,42 @@ checknil(Node *x, NodeList **init)
n->typecheck = 1;
*init = list(*init, n);
}
+
+/*
+ * Can this type be stored directly in an interface word?
+ */
+int
+isdirectiface(Type *t)
+{
+ // Setting IfacePointerOnly = 1 changes the
+ // interface representation so that the data word
+ // in an interface value must always be a pointer.
+ // Setting it to 0 uses the original representation,
+ // where the data word can hold a pointer or any
+ // non-pointer value no bigger than a pointer.
+ enum {
+ IfacePointerOnly = 1,
+ };
+
+ if(IfacePointerOnly) {
+ switch(t->etype) {
+ case TPTR32:
+ case TPTR64:
+ case TCHAN:
+ case TMAP:
+ case TFUNC:
+ case TUNSAFEPTR:
+ return 1;
+ case TARRAY:
+ // Array of 1 direct iface type can be direct.
+ return t->bound == 1 && isdirectiface(t->type);
+ case TSTRUCT:
+ // Struct with 1 field of direct iface type can be direct.
+ return t->type != T && t->type->down == T && isdirectiface(t->type->type);
+ }
+ return 0;
+ }
+
+ dowidth(t);
+ return t->width <= widthptr;
+}
diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c
index ce0190507..e1d8af878 100644
--- a/src/cmd/gc/swt.c
+++ b/src/cmd/gc/swt.c
@@ -34,6 +34,7 @@ struct Case
Case* link; // linked list to link
};
#define C ((Case*)nil)
+/*c2go Case *C; */
void
dumpcase(Case *c0)
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index c50b2285b..714c66268 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -33,7 +33,7 @@ static void stringtoarraylit(Node**);
static Node* resolve(Node*);
static void checkdefergo(Node*);
static int checkmake(Type*, char*, Node*);
-static int checksliceindex(Node*, Type*);
+static int checksliceindex(Node*, Node*, Type*);
static int checksliceconst(Node*, Node*);
static NodeList* typecheckdefstack;
@@ -311,6 +311,7 @@ typecheck1(Node **np, int top)
Type *t, *tp, *missing, *have, *badtype;
Val v;
char *why, *desc, descbuf[64];
+ vlong x;
n = *np;
@@ -382,16 +383,6 @@ reswitch:
if(n->type == T)
goto error;
break;
-
- case OTPAREN:
- ok |= Etype;
- l = typecheck(&n->left, Etype);
- if(l->type == T)
- goto error;
- n->op = OTYPE;
- n->type = l->type;
- n->left = N;
- break;
case OTARRAY:
ok |= Etype;
@@ -418,7 +409,10 @@ reswitch:
v = toint(l->val);
break;
default:
- yyerror("invalid array bound %N", l);
+ if(l->type != T && isint[l->type->etype] && l->op != OLITERAL)
+ yyerror("non-constant array bound %N", l);
+ else
+ yyerror("invalid array bound %N", l);
goto error;
}
t->bound = mpgetfix(v.u.xval);
@@ -535,19 +529,6 @@ reswitch:
op = n->etype;
goto arith;
- case OADDPTR:
- ok |= Erv;
- l = typecheck(&n->left, Erv);
- r = typecheck(&n->right, Erv);
- if(l->type == T || r->type == T)
- goto error;
- if(l->type->etype != tptr)
- fatal("bad OADDPTR left type %E for %N", l->type->etype, n->left);
- if(r->type->etype != TUINTPTR)
- fatal("bad OADDPTR right type %E for %N", r->type->etype, n->right);
- n->type = types[tptr];
- goto ret;
-
case OADD:
case OAND:
case OANDAND:
@@ -620,6 +601,10 @@ reswitch:
}
if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
defaultlit2(&l, &r, 1);
+ if(n->op == OASOP && n->implicit) {
+ yyerror("invalid operation: %N (non-numeric type %T)", n, l->type);
+ goto error;
+ }
yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
goto error;
}
@@ -756,10 +741,6 @@ reswitch:
l = n->left;
if((t = l->type) == T)
goto error;
- // top&Eindir means this is &x in *&x. (or the arg to built-in print)
- // n->etype means code generator flagged it as non-escaping.
- if(debug['N'] && !(top & Eindir) && !n->etype)
- addrescapes(n->left);
n->type = ptrto(t);
goto ret;
@@ -915,11 +896,12 @@ reswitch:
break;
}
if(isconst(n->right, CTINT)) {
- if(mpgetfix(n->right->val.u.xval) < 0)
+ x = mpgetfix(n->right->val.u.xval);
+ if(x < 0)
yyerror("invalid %s index %N (index must be non-negative)", why, n->right);
- else if(isfixedarray(t) && t->bound > 0 && mpgetfix(n->right->val.u.xval) >= t->bound)
+ else if(isfixedarray(t) && t->bound > 0 && x >= t->bound)
yyerror("invalid array index %N (out of bounds for %d-element array)", n->right, t->bound);
- else if(isconst(n->left, CTSTR) && mpgetfix(n->right->val.u.xval) >= n->left->val.u.sval->len)
+ else if(isconst(n->left, CTSTR) && x >= n->left->val.u.sval->len)
yyerror("invalid string index %N (out of bounds for %d-byte string)", n->right, n->left->val.u.sval->len);
else if(mpcmpfixfix(n->right->val.u.xval, maxintval[TINT]) > 0)
yyerror("invalid %s index %N (index too large)", why, n->right);
@@ -1019,9 +1001,9 @@ reswitch:
yyerror("cannot slice %N (type %T)", l, t);
goto error;
}
- if((lo = n->right->left) != N && checksliceindex(lo, tp) < 0)
+ if((lo = n->right->left) != N && checksliceindex(l, lo, tp) < 0)
goto error;
- if((hi = n->right->right) != N && checksliceindex(hi, tp) < 0)
+ if((hi = n->right->right) != N && checksliceindex(l, hi, tp) < 0)
goto error;
if(checksliceconst(lo, hi) < 0)
goto error;
@@ -1068,11 +1050,11 @@ reswitch:
yyerror("cannot slice %N (type %T)", l, t);
goto error;
}
- if((lo = n->right->left) != N && checksliceindex(lo, tp) < 0)
+ if((lo = n->right->left) != N && checksliceindex(l, lo, tp) < 0)
goto error;
- if((mid = n->right->right->left) != N && checksliceindex(mid, tp) < 0)
+ if((mid = n->right->right->left) != N && checksliceindex(l, mid, tp) < 0)
goto error;
- if((hi = n->right->right->right) != N && checksliceindex(hi, tp) < 0)
+ if((hi = n->right->right->right) != N && checksliceindex(l, hi, tp) < 0)
goto error;
if(checksliceconst(lo, hi) < 0 || checksliceconst(lo, mid) < 0 || checksliceconst(mid, hi) < 0)
goto error;
@@ -1842,7 +1824,7 @@ out:
}
static int
-checksliceindex(Node *r, Type *tp)
+checksliceindex(Node *l, Node *r, Type *tp)
{
Type *t;
@@ -1859,6 +1841,9 @@ checksliceindex(Node *r, Type *tp)
} else if(tp != nil && tp->bound > 0 && mpgetfix(r->val.u.xval) > tp->bound) {
yyerror("invalid slice index %N (out of bounds for %d-element array)", r, tp->bound);
return -1;
+ } else if(isconst(l, CTSTR) && mpgetfix(r->val.u.xval) > l->val.u.sval->len) {
+ yyerror("invalid slice index %N (out of bounds for %d-byte string)", r, l->val.u.sval->len);
+ return -1;
} else if(mpcmpfixfix(r->val.u.xval, maxintval[TINT]) > 0) {
yyerror("invalid slice index %N (index too large)", r);
return -1;
@@ -2139,18 +2124,19 @@ lookdot(Node *n, Type *t, int dostrcmp)
if(!eqtype(rcvr, tt)) {
if(rcvr->etype == tptr && eqtype(rcvr->type, tt)) {
checklvalue(n->left, "call pointer method on");
- if(debug['N'])
- addrescapes(n->left);
n->left = nod(OADDR, n->left, N);
n->left->implicit = 1;
typecheck(&n->left, Etype|Erv);
- } else if(tt->etype == tptr && eqtype(tt->type, rcvr)) {
+ } else if(tt->etype == tptr && rcvr->etype != tptr && eqtype(tt->type, rcvr)) {
n->left = nod(OIND, n->left, N);
n->left->implicit = 1;
typecheck(&n->left, Etype|Erv);
- } else if(tt->etype == tptr && tt->type->etype == tptr && eqtype(derefall(tt), rcvr)) {
+ } else if(tt->etype == tptr && tt->type->etype == tptr && eqtype(derefall(tt), derefall(rcvr))) {
yyerror("calling method %N with receiver %lN requires explicit dereference", n->right, n->left);
while(tt->etype == tptr) {
+ // Stop one level early for method with pointer receiver.
+ if(rcvr->etype == tptr && tt->type->etype != tptr)
+ break;
n->left = nod(OIND, n->left, N);
n->left->implicit = 1;
typecheck(&n->left, Etype|Erv);
@@ -2831,6 +2817,33 @@ checkassignlist(NodeList *l)
checkassign(l->n);
}
+// Check whether l and r are the same side effect-free expression,
+// so that it is safe to reuse one instead of computing both.
+static int
+samesafeexpr(Node *l, Node *r)
+{
+ if(l->op != r->op || !eqtype(l->type, r->type))
+ return 0;
+
+ switch(l->op) {
+ case ONAME:
+ case OCLOSUREVAR:
+ return l == r;
+
+ case ODOT:
+ case ODOTPTR:
+ return l->right != nil && r->right != nil && l->right->sym == r->right->sym && samesafeexpr(l->left, r->left);
+
+ case OIND:
+ return samesafeexpr(l->left, r->left);
+
+ case OINDEX:
+ return samesafeexpr(l->left, r->left) && samesafeexpr(l->right, r->right);
+ }
+
+ return 0;
+}
+
/*
* type check assignment.
* if this assignment is the definition of a var on the left side,
@@ -2868,6 +2881,29 @@ typecheckas(Node *n)
n->typecheck = 1;
if(n->left->typecheck == 0)
typecheck(&n->left, Erv | Easgn);
+
+ // Recognize slices being updated in place, for better code generation later.
+ // Don't rewrite if using race detector, to avoid needing to teach race detector
+ // about this optimization.
+ if(n->left && n->left->op != OINDEXMAP && n->right && !flag_race) {
+ switch(n->right->op) {
+ case OSLICE:
+ case OSLICE3:
+ case OSLICESTR:
+ // For x = x[0:y], x can be updated in place, without touching pointer.
+ if(samesafeexpr(n->left, n->right->left) && (n->right->right->left == N || iszero(n->right->right->left)))
+ n->right->reslice = 1;
+ break;
+
+ case OAPPEND:
+ // For x = append(x, ...), x can be updated in place when there is capacity,
+ // without touching the pointer; otherwise the emitted code to growslice
+ // can take care of updating the pointer, and only in that case.
+ if(n->right->list != nil && samesafeexpr(n->left, n->right->list->n))
+ n->right->reslice = 1;
+ break;
+ }
+ }
}
static void
@@ -2975,7 +3011,7 @@ typecheckas2(Node *n)
if(l->defn == n)
l->type = r->type;
l = n->list->next->n;
- if(l->type != T)
+ if(l->type != T && l->type->etype != TBOOL)
checkassignto(types[TBOOL], l);
if(l->defn == n && l->ntype == N)
l->type = types[TBOOL];
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 1cb25512e..ff9b36208 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -5,8 +5,11 @@
#include <u.h>
#include <libc.h>
#include "go.h"
+#include "../ld/textflag.h"
-static Node* walkprint(Node*, NodeList**, int);
+static Node* walkprint(Node*, NodeList**);
+static Node* writebarrierfn(char*, Type*, Type*);
+static Node* applywritebarrier(Node*, NodeList**);
static Node* mapfn(char*, Type*);
static Node* mapfndel(char*, Type*);
static Node* ascompatee1(int, Node*, Node*, NodeList**);
@@ -29,6 +32,7 @@ static void walkmul(Node**, NodeList**);
static void walkdiv(Node**, NodeList**);
static int bounded(Node*, int64);
static Mpint mpzero;
+static void walkprintfunc(Node**, NodeList**);
void
walk(Node *fn)
@@ -134,6 +138,8 @@ walkstmt(Node **np)
n = *np;
if(n == N)
return;
+ if(n->dodata == 2) // don't walk, generated by anylit.
+ return;
setlineno(n);
@@ -221,8 +227,7 @@ walkstmt(Node **np)
switch(n->left->op) {
case OPRINT:
case OPRINTN:
- walkexprlist(n->left->list, &n->ninit);
- n->left = walkprint(n->left, &n->ninit, 1);
+ walkprintfunc(&n->left, &n->ninit);
break;
case OCOPY:
n->left = copyany(n->left, &n->ninit, 1);
@@ -255,8 +260,7 @@ walkstmt(Node **np)
switch(n->left->op) {
case OPRINT:
case OPRINTN:
- walkexprlist(n->left->list, &n->ninit);
- n->left = walkprint(n->left, &n->ninit, 1);
+ walkprintfunc(&n->left, &n->ninit);
break;
case OCOPY:
n->left = copyany(n->left, &n->ninit, 1);
@@ -538,15 +542,15 @@ walkexpr(Node **np, NodeList **init)
case OPRINT:
case OPRINTN:
walkexprlist(n->list, init);
- n = walkprint(n, init, 0);
+ n = walkprint(n, init);
goto ret;
case OPANIC:
- n = mkcall("panic", T, init, n->left);
+ n = mkcall("gopanic", T, init, n->left);
goto ret;
case ORECOVER:
- n = mkcall("recover", n->type, init, nod(OADDR, nodfp, N));
+ n = mkcall("gorecover", n->type, init, nod(OADDR, nodfp, N));
goto ret;
case OLITERAL:
@@ -609,7 +613,7 @@ walkexpr(Node **np, NodeList **init)
if(oaslit(n, init))
goto ret;
- if(n->right == N)
+ if(n->right == N || iszero(n->right) && !flag_race)
goto ret;
switch(n->right->op) {
@@ -632,6 +636,7 @@ walkexpr(Node **np, NodeList **init)
r = convas(nod(OAS, n->left, n->right), init);
r->dodata = n->dodata;
n = r;
+ n = applywritebarrier(n, init);
}
goto ret;
@@ -643,6 +648,8 @@ walkexpr(Node **np, NodeList **init)
walkexprlistsafe(n->rlist, init);
ll = ascompatee(OAS, n->list, n->rlist, init);
ll = reorder3(ll);
+ for(lr = ll; lr != nil; lr = lr->next)
+ lr->n = applywritebarrier(lr->n, init);
n = liststmt(ll);
goto ret;
@@ -655,6 +662,8 @@ walkexpr(Node **np, NodeList **init)
walkexpr(&r, 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;
@@ -672,7 +681,7 @@ walkexpr(Node **np, NodeList **init)
n1 = nod(OADDR, n->list->n, N);
n1->etype = 1; // addr does not escape
fn = chanfn("chanrecv2", 2, r->left->type);
- r = mkcall1(fn, types[TBOOL], init, typename(r->left->type), r->left, n1);
+ 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;
@@ -687,7 +696,7 @@ walkexpr(Node **np, NodeList **init)
walkexpr(&r->right, init);
t = r->left->type;
p = nil;
- if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing.
+ if(t->type->width <= 128) { // Check ../../runtime/hashmap.c:MAXVALUESIZE before changing.
switch(simsimtype(t->down)) {
case TINT32:
case TUINT32:
@@ -722,6 +731,12 @@ walkexpr(Node **np, NodeList **init)
var->typecheck = 1;
fn = mapfn(p, t);
r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, key);
+
+ // mapaccess2* returns a typed bool, but due to spec changes,
+ // the boolean result of i.(T) is now untyped so we make it the
+ // same type as the variable on the lhs.
+ if(!isblank(n->list->next->n))
+ r->type->type->down->type = n->list->next->n->type;
n->rlist = list1(r);
n->op = OAS2FUNC;
n->list->n = var;
@@ -769,6 +784,12 @@ walkexpr(Node **np, NodeList **init)
*p = '\0';
fn = syslook(buf, 1);
+
+ // runtime.assert(E|I)2TOK returns a typed bool, but due
+ // to spec changes, the boolean result of i.(T) is now untyped
+ // so we make it the same type as the variable on the lhs.
+ if(!isblank(n->list->next->n))
+ fn->type->type->down->type->type = n->list->next->n->type;
ll = list1(typename(r->type));
ll = list(ll, r->left);
argtype(fn, r->left->type);
@@ -821,9 +842,7 @@ walkexpr(Node **np, NodeList **init)
walkexpr(&n->left, init);
// Optimize convT2E as a two-word copy when T is uintptr-shaped.
- if(!isinter(n->left->type) && isnilinter(n->type) &&
- (n->left->type->width == widthptr) &&
- isint[simsimtype(n->left->type)]) {
+ if(isnilinter(n->type) && isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) {
l = nod(OEFACE, typename(n->left->type), n->left);
l->type = n->type;
l->typecheck = n->typecheck;
@@ -865,14 +884,13 @@ walkexpr(Node **np, NodeList **init)
l->class = PEXTERN;
l->xoffset = 0;
sym->def = l;
- ggloblsym(sym, widthptr, 1, 0);
+ ggloblsym(sym, widthptr, DUPOK|NOPTR);
}
l = nod(OADDR, sym->def, N);
l->addable = 1;
ll = list(ll, l);
- if(n->left->type->width == widthptr &&
- isint[simsimtype(n->left->type)]) {
+ if(isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) {
/* For pointer types, we can make a special form of optimization
*
* These statements are put onto the expression init list:
@@ -1073,7 +1091,7 @@ walkexpr(Node **np, NodeList **init)
t = n->left->type;
p = nil;
- if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing.
+ if(t->type->width <= 128) { // Check ../../runtime/hashmap.c:MAXVALUESIZE before changing.
switch(simsimtype(t->down)) {
case TINT32:
case TUINT32:
@@ -1371,7 +1389,6 @@ walkexpr(Node **np, NodeList **init)
case OMAPLIT:
case OSTRUCTLIT:
case OPTRLIT:
- // XXX TODO do we need to clear var?
var = temp(n->type);
anylit(0, n, var, init);
n = var;
@@ -1471,8 +1488,13 @@ ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
static int
fncall(Node *l, Type *rt)
{
+ Node r;
+
if(l->ullman >= UINF || l->op == OINDEXMAP)
return 1;
+ memset(&r, 0, sizeof r);
+ if(needwritebarrier(l, &r))
+ return 1;
if(eqtype(l->type, rt))
return 0;
return 1;
@@ -1523,8 +1545,10 @@ ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init)
a = nod(OAS, l, nodarg(r, fp));
a = convas(a, init);
ullmancalc(a);
- if(a->ullman >= UINF)
+ if(a->ullman >= UINF) {
+ dump("ascompatet ucount", a);
ucount++;
+ }
nn = list(nn, a);
r = structnext(&saver);
}
@@ -1732,7 +1756,7 @@ ret:
// generate code for print
static Node*
-walkprint(Node *nn, NodeList **init, int defer)
+walkprint(Node *nn, NodeList **init)
{
Node *r;
Node *n;
@@ -1740,31 +1764,17 @@ walkprint(Node *nn, NodeList **init, int defer)
Node *on;
Type *t;
int notfirst, et, op;
- NodeList *calls, *intypes, *args;
- Fmt fmt;
+ NodeList *calls;
on = nil;
op = nn->op;
all = nn->list;
calls = nil;
notfirst = 0;
- intypes = nil;
- args = nil;
-
- memset(&fmt, 0, sizeof fmt);
- if(defer) {
- // defer print turns into defer printf with format string
- fmtstrinit(&fmt);
- intypes = list(intypes, nod(ODCLFIELD, N, typenod(types[TSTRING])));
- args = list1(nod(OXXX, N, N));
- }
for(l=all; l; l=l->next) {
if(notfirst) {
- if(defer)
- fmtprint(&fmt, " ");
- else
- calls = list(calls, mkcall("printsp", T, init));
+ calls = list(calls, mkcall("printsp", T, init));
}
notfirst = op == OPRINTN;
@@ -1792,119 +1802,63 @@ walkprint(Node *nn, NodeList **init, int defer)
t = n->type;
et = n->type->etype;
if(isinter(n->type)) {
- if(defer) {
- if(isnilinter(n->type))
- fmtprint(&fmt, "%%e");
- else
- fmtprint(&fmt, "%%i");
- } else {
- if(isnilinter(n->type))
- on = syslook("printeface", 1);
- else
- on = syslook("printiface", 1);
- argtype(on, n->type); // any-1
- }
+ if(isnilinter(n->type))
+ on = syslook("printeface", 1);
+ else
+ on = syslook("printiface", 1);
+ argtype(on, n->type); // any-1
} else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR) {
- if(defer) {
- fmtprint(&fmt, "%%p");
- } else {
- on = syslook("printpointer", 1);
- argtype(on, n->type); // any-1
- }
+ on = syslook("printpointer", 1);
+ argtype(on, n->type); // any-1
} else if(isslice(n->type)) {
- if(defer) {
- fmtprint(&fmt, "%%a");
- } else {
- on = syslook("printslice", 1);
- argtype(on, n->type); // any-1
- }
+ on = syslook("printslice", 1);
+ argtype(on, n->type); // any-1
} else if(isint[et]) {
- if(defer) {
- if(et == TUINT64)
- fmtprint(&fmt, "%%U");
- else {
- fmtprint(&fmt, "%%D");
- t = types[TINT64];
- }
- } else {
- if(et == TUINT64)
- on = syslook("printuint", 0);
+ if(et == TUINT64) {
+ if((t->sym->pkg == runtimepkg || compiling_runtime) && strcmp(t->sym->name, "hex") == 0)
+ on = syslook("printhex", 0);
else
- on = syslook("printint", 0);
- }
- } else if(isfloat[et]) {
- if(defer) {
- fmtprint(&fmt, "%%f");
- t = types[TFLOAT64];
+ on = syslook("printuint", 0);
} else
- on = syslook("printfloat", 0);
+ on = syslook("printint", 0);
+ } else if(isfloat[et]) {
+ on = syslook("printfloat", 0);
} else if(iscomplex[et]) {
- if(defer) {
- fmtprint(&fmt, "%%C");
- t = types[TCOMPLEX128];
- } else
- on = syslook("printcomplex", 0);
+ on = syslook("printcomplex", 0);
} else if(et == TBOOL) {
- if(defer)
- fmtprint(&fmt, "%%t");
- else
- on = syslook("printbool", 0);
+ on = syslook("printbool", 0);
} else if(et == TSTRING) {
- if(defer)
- fmtprint(&fmt, "%%S");
- else
- on = syslook("printstring", 0);
+ on = syslook("printstring", 0);
} else {
badtype(OPRINT, n->type, T);
continue;
}
- if(!defer) {
- t = *getinarg(on->type);
- if(t != nil)
- t = t->type;
- if(t != nil)
- t = t->type;
- }
+ t = *getinarg(on->type);
+ if(t != nil)
+ t = t->type;
+ if(t != nil)
+ t = t->type;
if(!eqtype(t, n->type)) {
n = nod(OCONV, n, N);
n->type = t;
}
- if(defer) {
- intypes = list(intypes, nod(ODCLFIELD, N, typenod(t)));
- args = list(args, n);
- } else {
- r = nod(OCALL, on, N);
- r->list = list1(n);
- calls = list(calls, r);
- }
+ r = nod(OCALL, on, N);
+ r->list = list1(n);
+ calls = list(calls, r);
}
- if(defer) {
- if(op == OPRINTN)
- fmtprint(&fmt, "\n");
- on = syslook("goprintf", 1);
- on->type = functype(nil, intypes, nil);
- args->n = nod(OLITERAL, N, N);
- args->n->val.ctype = CTSTR;
- args->n->val.u.sval = strlit(fmtstrflush(&fmt));
- r = nod(OCALL, on, N);
- r->list = args;
- typecheck(&r, Etop);
- walkexpr(&r, init);
- } else {
- if(op == OPRINTN)
- calls = list(calls, mkcall("printnl", T, nil));
- typechecklist(calls, Etop);
- walkexprlist(calls, init);
+ if(op == OPRINTN)
+ calls = list(calls, mkcall("printnl", T, nil));
+ typechecklist(calls, Etop);
+ walkexprlist(calls, init);
- r = nod(OEMPTY, N, N);
- typecheck(&r, Etop);
- walkexpr(&r, init);
- r->ninit = calls;
- }
+ r = nod(OEMPTY, N, N);
+ typecheck(&r, Etop);
+ walkexpr(&r, init);
+ r->ninit = calls;
return r;
}
@@ -1914,11 +1868,166 @@ callnew(Type *t)
Node *fn;
dowidth(t);
- fn = syslook("new", 1);
+ fn = syslook("newobject", 1);
argtype(fn, t);
return mkcall1(fn, ptrto(t), nil, typename(t));
}
+static int
+isstack(Node *n)
+{
+ while(n->op == ODOT || n->op == OPAREN || n->op == OCONVNOP || n->op == OINDEX && isfixedarray(n->left->type))
+ n = n->left;
+
+ switch(n->op) {
+ case OINDREG:
+ // OINDREG only ends up in walk if it's indirect of SP.
+ return 1;
+
+ case ONAME:
+ switch(n->class) {
+ case PAUTO:
+ case PPARAM:
+ case PPARAMOUT:
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int
+isglobal(Node *n)
+{
+ while(n->op == ODOT || n->op == OPAREN || n->op == OCONVNOP || n->op == OINDEX && isfixedarray(n->left->type))
+ n = n->left;
+
+ switch(n->op) {
+ case ONAME:
+ switch(n->class) {
+ case PEXTERN:
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+// Do we need a write barrier for the assignment l = r?
+int
+needwritebarrier(Node *l, Node *r)
+{
+ if(!use_writebarrier)
+ return 0;
+
+ if(l == N || isblank(l))
+ return 0;
+
+ // No write barrier for write of non-pointers.
+ dowidth(l->type);
+ if(!haspointers(l->type))
+ return 0;
+
+ // No write barrier for write to stack.
+ if(isstack(l))
+ return 0;
+
+ // No write barrier for implicit or explicit zeroing.
+ if(r == N || iszero(r))
+ return 0;
+
+ // No write barrier for initialization to constant.
+ if(r->op == OLITERAL)
+ return 0;
+
+ // No write barrier for storing static (read-only) data.
+ if(r->op == ONAME && strncmp(r->sym->name, "statictmp_", 10) == 0)
+ return 0;
+
+ // No write barrier for storing address of stack values,
+ // which are guaranteed only to be written to the stack.
+ if(r->op == OADDR && isstack(r->left))
+ return 0;
+
+ // No write barrier for storing address of global, which
+ // is live no matter what.
+ if(r->op == OADDR && isglobal(r->left))
+ return 0;
+
+ // No write barrier for reslice: x = x[0:y] or x = append(x, ...).
+ // Both are compiled to modify x directly.
+ // In the case of append, a write barrier may still be needed
+ // if the underlying array grows, but the append code can
+ // generate the write barrier directly in that case.
+ // (It does not yet, but the cost of the write barrier will be
+ // small compared to the cost of the allocation.)
+ if(r->reslice) {
+ switch(r->op) {
+ case OSLICE:
+ case OSLICE3:
+ case OSLICESTR:
+ case OAPPEND:
+ break;
+ default:
+ dump("bad reslice-l", l);
+ dump("bad reslice-r", r);
+ break;
+ }
+ return 0;
+ }
+
+ // Otherwise, be conservative and use write barrier.
+ return 1;
+}
+
+// TODO(rsc): Perhaps componentgen should run before this.
+static Node*
+applywritebarrier(Node *n, NodeList **init)
+{
+ Node *l, *r;
+ Type *t;
+
+ if(n->left && n->right && needwritebarrier(n->left, n->right)) {
+ t = n->left->type;
+ l = nod(OADDR, n->left, N);
+ l->etype = 1; // addr does not escape
+ if(t->width == widthptr) {
+ n = mkcall1(writebarrierfn("writebarrierptr", t, n->right->type), T, init,
+ l, n->right);
+ } else if(t->etype == TSTRING) {
+ n = mkcall1(writebarrierfn("writebarrierstring", t, n->right->type), T, init,
+ l, n->right);
+ } else if(isslice(t)) {
+ n = mkcall1(writebarrierfn("writebarrierslice", t, n->right->type), T, init,
+ l, n->right);
+ } else if(isinter(t)) {
+ n = mkcall1(writebarrierfn("writebarrieriface", t, n->right->type), T, init,
+ l, n->right);
+ } else if(t->width == 2*widthptr) {
+ n = mkcall1(writebarrierfn("writebarrierfat2", t, n->right->type), T, init,
+ l, nodnil(), n->right);
+ } else if(t->width == 3*widthptr) {
+ n = mkcall1(writebarrierfn("writebarrierfat3", t, n->right->type), T, init,
+ l, nodnil(), n->right);
+ } else if(t->width == 4*widthptr) {
+ n = mkcall1(writebarrierfn("writebarrierfat4", t, n->right->type), T, init,
+ l, nodnil(), n->right);
+ } else {
+ r = n->right;
+ while(r->op == OCONVNOP)
+ r = r->left;
+ r = nod(OADDR, r, N);
+ r->etype = 1; // addr does not escape
+ //warnl(n->lineno, "writebarrierfat %T %N", t, r);
+ n = mkcall1(writebarrierfn("writebarrierfat", t, r->left->type), T, init,
+ typename(t), l, r);
+ }
+ }
+ return n;
+}
+
static Node*
convas(Node *n, NodeList **init)
{
@@ -1958,11 +2067,10 @@ convas(Node *n, NodeList **init)
goto out;
}
- if(eqtype(lt, rt))
- goto out;
-
- n->right = assignconv(n->right, lt, "assignment");
- walkexpr(&n->right, init);
+ if(!eqtype(lt, rt)) {
+ n->right = assignconv(n->right, lt, "assignment");
+ walkexpr(&n->right, init);
+ }
out:
ullmancalc(n);
@@ -2355,6 +2463,8 @@ paramstoheap(Type **argin, int out)
continue;
// generate allocation & copying code
+ if(compiling_runtime)
+ yyerror("%N escapes to heap, not allowed in runtime.", v);
if(v->alloc == nil)
v->alloc = callnew(v->type);
nn = list(nn, nod(OAS, v->heapaddr, v->alloc));
@@ -2512,6 +2622,17 @@ mapfndel(char *name, Type *t)
}
static Node*
+writebarrierfn(char *name, Type *l, Type *r)
+{
+ Node *fn;
+
+ fn = syslook(name, 1);
+ argtype(fn, l);
+ argtype(fn, r);
+ return fn;
+}
+
+static Node*
addstr(Node *n, NodeList **init)
{
Node *r, *cat, *slice;
@@ -2620,7 +2741,7 @@ appendslice(Node *n, NodeList **init)
if(l2->type->etype == TSTRING)
fn = syslook("slicestringcopy", 1);
else
- fn = syslook("copy", 1);
+ fn = syslook("slicecopy", 1);
argtype(fn, l1->type);
argtype(fn, l2->type);
nt = mkcall1(fn, types[TINT], &l,
@@ -2758,7 +2879,7 @@ copyany(Node *n, NodeList **init, int runtimecall)
if(n->right->type->etype == TSTRING)
fn = syslook("slicestringcopy", 1);
else
- fn = syslook("copy", 1);
+ fn = syslook("slicecopy", 1);
argtype(fn, n->left->type);
argtype(fn, n->right->type);
return mkcall1(fn, n->type, init,
@@ -2863,14 +2984,14 @@ sliceany(Node* n, NodeList **init)
lb = N;
}
- // dynamic checks convert all bounds to unsigned to save us the bound < 0 comparison
- // generate
- // if hb > bound || lb > hb { panicslice() }
+ // Checking src[lb:hb:cb] or src[lb:hb].
+ // if chk0 || chk1 || chk2 { panicslice() }
chk = N;
- chk0 = N;
- chk1 = N;
- chk2 = N;
+ chk0 = N; // cap(src) < cb
+ chk1 = N; // cb < hb for src[lb:hb:cb]; cap(src) < hb for src[lb:hb]
+ chk2 = N; // hb < lb
+ // All comparisons are unsigned to avoid testing < 0.
bt = types[simtype[TUINT]];
if(cb != N && cb->type->width > 4)
bt = types[TUINT64];
@@ -3010,10 +3131,10 @@ eqfor(Type *t)
n = newname(sym);
n->class = PFUNC;
ntype = nod(OTFUNC, N, N);
- ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(types[TBOOL]))));
- ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
+ ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
+ ntype->rlist = list(ntype->rlist, nod(ODCLFIELD, N, typenod(types[TBOOL])));
typecheck(&ntype, Etype);
n->type = ntype->type;
return n;
@@ -3034,10 +3155,9 @@ countfield(Type *t)
static void
walkcompare(Node **np, NodeList **init)
{
- Node *n, *l, *r, *fn, *call, *a, *li, *ri, *expr;
+ Node *n, *l, *r, *call, *a, *li, *ri, *expr, *cmpl, *cmpr;
int andor, i;
Type *t, *t1;
- static Node *tempbool;
n = *np;
@@ -3055,17 +3175,25 @@ walkcompare(Node **np, NodeList **init)
break;
}
- if(!islvalue(n->left) || !islvalue(n->right))
- goto hard;
+ cmpl = n->left;
+ while(cmpl != N && cmpl->op == OCONVNOP)
+ cmpl = cmpl->left;
+ cmpr = n->right;
+ while(cmpr != N && cmpr->op == OCONVNOP)
+ cmpr = cmpr->left;
+
+ if(!islvalue(cmpl) || !islvalue(cmpr)) {
+ fatal("arguments of comparison must be lvalues - %N %N", cmpl, cmpr);
+ }
l = temp(ptrto(t));
- a = nod(OAS, l, nod(OADDR, n->left, N));
+ a = nod(OAS, l, nod(OADDR, cmpl, N));
a->right->etype = 1; // addr does not escape
typecheck(&a, Etop);
*init = list(*init, a);
r = temp(ptrto(t));
- a = nod(OAS, r, nod(OADDR, n->right, N));
+ a = nod(OAS, r, nod(OADDR, cmpr, N));
a->right->etype = 1; // addr does not escape
typecheck(&a, Etop);
*init = list(*init, a);
@@ -3115,57 +3243,16 @@ walkcompare(Node **np, NodeList **init)
goto ret;
}
- // Chose not to inline, but still have addresses.
- // Call equality function directly.
- // The equality function requires a bool pointer for
- // storing its address, because it has to be callable
- // from C, and C can't access an ordinary Go return value.
- // To avoid creating many temporaries, cache one per function.
- if(tempbool == N || tempbool->curfn != curfn)
- tempbool = temp(types[TBOOL]);
-
+ // Chose not to inline. Call equality function directly.
call = nod(OCALL, eqfor(t), N);
- a = nod(OADDR, tempbool, N);
- a->etype = 1; // does not escape
- call->list = list(call->list, a);
- call->list = list(call->list, nodintconst(t->width));
call->list = list(call->list, l);
call->list = list(call->list, r);
- typecheck(&call, Etop);
- walkstmt(&call);
- *init = list(*init, call);
-
- // tempbool cannot be used directly as multiple comparison
- // expressions may exist in the same statement. Create another
- // temporary to hold the value (its address is not taken so it can
- // be optimized away).
- r = temp(types[TBOOL]);
- a = nod(OAS, r, tempbool);
- typecheck(&a, Etop);
- walkstmt(&a);
- *init = list(*init, a);
-
+ call->list = list(call->list, nodintconst(t->width));
+ r = call;
if(n->op != OEQ)
r = nod(ONOT, r, N);
goto ret;
-hard:
- // Cannot take address of one or both of the operands.
- // Instead, pass directly to runtime helper function.
- // Easier on the stack than passing the address
- // of temporary variables, because we are better at reusing
- // the argument space than temporary variable space.
- fn = syslook("equal", 1);
- l = n->left;
- r = n->right;
- argtype(fn, n->left->type);
- argtype(fn, n->left->type);
- r = mkcall1(fn, n->type, init, typename(n->left->type), l, r);
- if(n->op == ONE) {
- r = nod(ONOT, r, N);
- }
- goto ret;
-
ret:
typecheck(&r, Erv);
walkexpr(&r, init);
@@ -3780,3 +3867,71 @@ candiscard(Node *n)
return 1;
}
+
+// rewrite
+// print(x, y, z)
+// into
+// func(a1, a2, a3) {
+// print(a1, a2, a3)
+// }(x, y, z)
+// and same for println.
+static void
+walkprintfunc(Node **np, NodeList **init)
+{
+ Node *n;
+ Node *a, *fn, *t, *oldfn;
+ NodeList *l, *printargs;
+ int num;
+ char buf[100];
+ static int prgen;
+
+ n = *np;
+
+ if(n->ninit != nil) {
+ walkstmtlist(n->ninit);
+ *init = concat(*init, n->ninit);
+ n->ninit = nil;
+ }
+
+ t = nod(OTFUNC, N, N);
+ num = 0;
+ printargs = nil;
+ for(l=n->list; l != nil; l=l->next) {
+ snprint(buf, sizeof buf, "a%d", num++);
+ a = nod(ODCLFIELD, newname(lookup(buf)), typenod(l->n->type));
+ t->list = list(t->list, a);
+ printargs = list(printargs, a->left);
+ }
+
+ fn = nod(ODCLFUNC, N, N);
+ snprint(buf, sizeof buf, "print·%d", ++prgen);
+ fn->nname = newname(lookup(buf));
+ fn->nname->defn = fn;
+ fn->nname->ntype = t;
+ declare(fn->nname, PFUNC);
+
+ oldfn = curfn;
+ curfn = nil;
+ funchdr(fn);
+
+ a = nod(n->op, N, N);
+ a->list = printargs;
+ typecheck(&a, Etop);
+ walkstmt(&a);
+
+ fn->nbody = list1(a);
+
+ funcbody(fn);
+
+ typecheck(&fn, Etop);
+ typechecklist(fn->nbody, Etop);
+ xtop = list(xtop, fn);
+ curfn = oldfn;
+
+ a = nod(OCALL, N, N);
+ a->left = fn->nname;
+ a->list = n->list;
+ typecheck(&a, Etop);
+ walkexpr(&a, init);
+ *np = a;
+}
diff --git a/src/cmd/gc/y.tab.c b/src/cmd/gc/y.tab.c
index 08d8ecff2..f464126ac 100644
--- a/src/cmd/gc/y.tab.c
+++ b/src/cmd/gc/y.tab.c
@@ -440,16 +440,16 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 4
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 2270
+#define YYLAST 2201
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 76
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 142
/* YYNRULES -- Number of rules. */
-#define YYNRULES 351
+#define YYNRULES 352
/* YYNRULES -- Number of states. */
-#define YYNSTATES 667
+#define YYNSTATES 669
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
@@ -506,35 +506,35 @@ static const yytype_uint16 yyprhs[] =
129, 132, 137, 141, 146, 150, 152, 155, 157, 159,
162, 164, 168, 172, 176, 179, 182, 186, 192, 198,
201, 202, 207, 208, 212, 213, 216, 217, 222, 227,
- 232, 238, 240, 242, 245, 246, 250, 252, 256, 257,
- 258, 259, 268, 269, 275, 276, 279, 280, 283, 284,
- 285, 293, 294, 300, 302, 306, 310, 314, 318, 322,
- 326, 330, 334, 338, 342, 346, 350, 354, 358, 362,
- 366, 370, 374, 378, 382, 384, 387, 390, 393, 396,
- 399, 402, 405, 408, 412, 418, 425, 427, 429, 433,
- 439, 445, 450, 457, 466, 468, 474, 480, 486, 494,
- 496, 497, 501, 503, 508, 510, 515, 517, 521, 523,
- 525, 527, 529, 531, 533, 535, 536, 538, 540, 542,
- 544, 549, 554, 556, 558, 560, 563, 565, 567, 569,
- 571, 573, 577, 579, 581, 583, 586, 588, 590, 592,
- 594, 598, 600, 602, 604, 606, 608, 610, 612, 614,
- 616, 620, 625, 630, 633, 637, 643, 645, 647, 650,
- 654, 660, 664, 670, 674, 678, 684, 693, 699, 708,
- 714, 715, 719, 720, 722, 726, 728, 733, 736, 737,
- 741, 743, 747, 749, 753, 755, 759, 761, 765, 767,
- 771, 775, 778, 783, 787, 793, 799, 801, 805, 807,
- 810, 812, 816, 821, 823, 826, 829, 831, 833, 837,
- 838, 841, 842, 844, 846, 848, 850, 852, 854, 856,
- 858, 860, 861, 866, 868, 871, 874, 877, 880, 883,
- 886, 888, 892, 894, 898, 900, 904, 906, 910, 912,
- 916, 918, 920, 924, 928, 929, 932, 933, 935, 936,
- 938, 939, 941, 942, 944, 945, 947, 948, 950, 951,
- 953, 954, 956, 957, 959, 964, 969, 975, 982, 987,
- 992, 994, 996, 998, 1000, 1002, 1004, 1006, 1008, 1010,
- 1014, 1019, 1025, 1030, 1035, 1038, 1041, 1046, 1050, 1054,
- 1060, 1064, 1069, 1073, 1079, 1081, 1082, 1084, 1088, 1090,
- 1092, 1095, 1097, 1099, 1105, 1106, 1109, 1111, 1115, 1117,
- 1121, 1123
+ 232, 235, 241, 243, 245, 248, 249, 253, 255, 259,
+ 260, 261, 262, 271, 272, 278, 279, 282, 283, 286,
+ 287, 288, 296, 297, 303, 305, 309, 313, 317, 321,
+ 325, 329, 333, 337, 341, 345, 349, 353, 357, 361,
+ 365, 369, 373, 377, 381, 385, 387, 390, 393, 396,
+ 399, 402, 405, 408, 411, 415, 421, 428, 430, 432,
+ 436, 442, 448, 453, 460, 469, 471, 477, 483, 489,
+ 497, 499, 500, 504, 506, 511, 513, 518, 520, 524,
+ 526, 528, 530, 532, 534, 536, 538, 539, 541, 543,
+ 545, 547, 552, 557, 559, 561, 563, 566, 568, 570,
+ 572, 574, 576, 580, 582, 584, 586, 589, 591, 593,
+ 595, 597, 601, 603, 605, 607, 609, 611, 613, 615,
+ 617, 619, 623, 628, 633, 636, 640, 646, 648, 650,
+ 653, 657, 663, 667, 673, 677, 681, 687, 696, 702,
+ 711, 717, 718, 722, 723, 725, 729, 731, 736, 739,
+ 740, 744, 746, 750, 752, 756, 758, 762, 764, 768,
+ 770, 774, 778, 781, 786, 790, 796, 802, 804, 808,
+ 810, 813, 815, 819, 824, 826, 829, 832, 834, 836,
+ 840, 841, 844, 845, 847, 849, 851, 853, 855, 857,
+ 859, 861, 863, 864, 869, 871, 874, 877, 880, 883,
+ 886, 889, 891, 895, 897, 901, 903, 907, 909, 913,
+ 915, 919, 921, 923, 927, 931, 932, 935, 936, 938,
+ 939, 941, 942, 944, 945, 947, 948, 950, 951, 953,
+ 954, 956, 957, 959, 960, 962, 967, 972, 978, 985,
+ 990, 995, 997, 999, 1001, 1003, 1005, 1007, 1009, 1011,
+ 1013, 1017, 1022, 1028, 1033, 1038, 1041, 1044, 1049, 1053,
+ 1057, 1063, 1067, 1072, 1076, 1082, 1084, 1085, 1087, 1091,
+ 1093, 1095, 1098, 1100, 1102, 1108, 1109, 1112, 1114, 1118,
+ 1120, 1124, 1126
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
@@ -563,96 +563,96 @@ static const yytype_int16 yyrhs[] =
-1, -1, 67, 101, 183, 68, -1, -1, 99, 103,
183, -1, -1, 104, 102, -1, -1, 35, 106, 183,
68, -1, 186, 65, 26, 126, -1, 186, 5, 26,
- 126, -1, 194, 62, 194, 62, 194, -1, 194, -1,
- 107, -1, 108, 105, -1, -1, 16, 111, 109, -1,
- 194, -1, 194, 62, 194, -1, -1, -1, -1, 20,
- 114, 112, 115, 105, 116, 119, 120, -1, -1, 14,
- 20, 118, 112, 105, -1, -1, 119, 117, -1, -1,
- 14, 100, -1, -1, -1, 30, 122, 112, 123, 35,
- 104, 68, -1, -1, 28, 125, 35, 104, 68, -1,
- 127, -1, 126, 47, 126, -1, 126, 33, 126, -1,
- 126, 38, 126, -1, 126, 46, 126, -1, 126, 45,
- 126, -1, 126, 43, 126, -1, 126, 39, 126, -1,
- 126, 40, 126, -1, 126, 49, 126, -1, 126, 50,
- 126, -1, 126, 51, 126, -1, 126, 52, 126, -1,
- 126, 53, 126, -1, 126, 54, 126, -1, 126, 55,
- 126, -1, 126, 56, 126, -1, 126, 34, 126, -1,
- 126, 44, 126, -1, 126, 48, 126, -1, 126, 36,
- 126, -1, 134, -1, 53, 127, -1, 56, 127, -1,
- 49, 127, -1, 50, 127, -1, 69, 127, -1, 70,
- 127, -1, 52, 127, -1, 36, 127, -1, 134, 59,
- 60, -1, 134, 59, 187, 191, 60, -1, 134, 59,
- 187, 11, 191, 60, -1, 3, -1, 143, -1, 134,
- 63, 141, -1, 134, 63, 59, 135, 60, -1, 134,
- 63, 59, 31, 60, -1, 134, 71, 126, 72, -1,
- 134, 71, 192, 66, 192, 72, -1, 134, 71, 192,
- 66, 192, 66, 192, 72, -1, 128, -1, 149, 59,
- 126, 191, 60, -1, 150, 137, 130, 189, 68, -1,
- 129, 67, 130, 189, 68, -1, 59, 135, 60, 67,
- 130, 189, 68, -1, 165, -1, -1, 126, 66, 133,
- -1, 126, -1, 67, 130, 189, 68, -1, 126, -1,
- 67, 130, 189, 68, -1, 129, -1, 59, 135, 60,
- -1, 126, -1, 147, -1, 146, -1, 35, -1, 67,
- -1, 141, -1, 141, -1, -1, 138, -1, 24, -1,
- 142, -1, 73, -1, 74, 3, 63, 24, -1, 74,
- 3, 63, 73, -1, 141, -1, 138, -1, 11, -1,
- 11, 146, -1, 155, -1, 161, -1, 153, -1, 154,
- -1, 152, -1, 59, 146, 60, -1, 155, -1, 161,
- -1, 153, -1, 53, 147, -1, 161, -1, 153, -1,
- 154, -1, 152, -1, 59, 146, 60, -1, 161, -1,
- 153, -1, 153, -1, 155, -1, 161, -1, 153, -1,
- 154, -1, 152, -1, 143, -1, 143, 63, 141, -1,
- 71, 192, 72, 146, -1, 71, 11, 72, 146, -1,
- 8, 148, -1, 8, 36, 146, -1, 23, 71, 146,
- 72, 146, -1, 156, -1, 157, -1, 53, 146, -1,
- 36, 8, 146, -1, 29, 137, 170, 190, 68, -1,
- 29, 137, 68, -1, 22, 137, 171, 190, 68, -1,
- 22, 137, 68, -1, 17, 159, 162, -1, 141, 59,
- 179, 60, 163, -1, 59, 179, 60, 141, 59, 179,
- 60, 163, -1, 200, 59, 195, 60, 210, -1, 59,
- 215, 60, 141, 59, 195, 60, 210, -1, 17, 59,
- 179, 60, 163, -1, -1, 67, 183, 68, -1, -1,
- 151, -1, 59, 179, 60, -1, 161, -1, 164, 137,
- 183, 68, -1, 164, 1, -1, -1, 166, 90, 62,
- -1, 93, -1, 167, 62, 93, -1, 95, -1, 168,
- 62, 95, -1, 97, -1, 169, 62, 97, -1, 172,
- -1, 170, 62, 172, -1, 175, -1, 171, 62, 175,
- -1, 184, 146, 198, -1, 174, 198, -1, 59, 174,
- 60, 198, -1, 53, 174, 198, -1, 59, 53, 174,
- 60, 198, -1, 53, 59, 174, 60, 198, -1, 24,
- -1, 24, 63, 141, -1, 173, -1, 138, 176, -1,
- 173, -1, 59, 173, 60, -1, 59, 179, 60, 163,
- -1, 136, -1, 141, 136, -1, 141, 145, -1, 145,
- -1, 177, -1, 178, 75, 177, -1, -1, 178, 191,
- -1, -1, 100, -1, 91, -1, 181, -1, 1, -1,
- 98, -1, 110, -1, 121, -1, 124, -1, 113, -1,
- -1, 144, 66, 182, 180, -1, 15, -1, 6, 140,
- -1, 10, 140, -1, 18, 128, -1, 13, 128, -1,
- 19, 138, -1, 27, 193, -1, 180, -1, 183, 62,
- 180, -1, 138, -1, 184, 75, 138, -1, 139, -1,
- 185, 75, 139, -1, 126, -1, 186, 75, 126, -1,
- 135, -1, 187, 75, 135, -1, 131, -1, 132, -1,
- 188, 75, 131, -1, 188, 75, 132, -1, -1, 188,
- 191, -1, -1, 62, -1, -1, 75, -1, -1, 126,
- -1, -1, 186, -1, -1, 98, -1, -1, 215, -1,
- -1, 216, -1, -1, 217, -1, -1, 3, -1, 21,
- 24, 3, 62, -1, 32, 200, 202, 62, -1, 9,
- 200, 65, 213, 62, -1, 9, 200, 202, 65, 213,
- 62, -1, 31, 201, 202, 62, -1, 17, 160, 162,
- 62, -1, 142, -1, 200, -1, 204, -1, 205, -1,
- 206, -1, 204, -1, 206, -1, 142, -1, 24, -1,
- 71, 72, 202, -1, 71, 3, 72, 202, -1, 23,
- 71, 202, 72, 202, -1, 29, 67, 196, 68, -1,
- 22, 67, 197, 68, -1, 53, 202, -1, 8, 203,
- -1, 8, 59, 205, 60, -1, 8, 36, 202, -1,
- 36, 8, 202, -1, 17, 59, 195, 60, 210, -1,
- 141, 202, 198, -1, 141, 11, 202, 198, -1, 141,
- 202, 198, -1, 141, 59, 195, 60, 210, -1, 202,
- -1, -1, 211, -1, 59, 195, 60, -1, 202, -1,
- 3, -1, 50, 3, -1, 141, -1, 212, -1, 59,
- 212, 49, 212, 60, -1, -1, 214, 199, -1, 207,
- -1, 215, 75, 207, -1, 208, -1, 216, 62, 208,
- -1, 209, -1, 217, 62, 209, -1
+ 126, -1, 26, 126, -1, 194, 62, 194, 62, 194,
+ -1, 194, -1, 107, -1, 108, 105, -1, -1, 16,
+ 111, 109, -1, 194, -1, 194, 62, 194, -1, -1,
+ -1, -1, 20, 114, 112, 115, 105, 116, 119, 120,
+ -1, -1, 14, 20, 118, 112, 105, -1, -1, 119,
+ 117, -1, -1, 14, 100, -1, -1, -1, 30, 122,
+ 112, 123, 35, 104, 68, -1, -1, 28, 125, 35,
+ 104, 68, -1, 127, -1, 126, 47, 126, -1, 126,
+ 33, 126, -1, 126, 38, 126, -1, 126, 46, 126,
+ -1, 126, 45, 126, -1, 126, 43, 126, -1, 126,
+ 39, 126, -1, 126, 40, 126, -1, 126, 49, 126,
+ -1, 126, 50, 126, -1, 126, 51, 126, -1, 126,
+ 52, 126, -1, 126, 53, 126, -1, 126, 54, 126,
+ -1, 126, 55, 126, -1, 126, 56, 126, -1, 126,
+ 34, 126, -1, 126, 44, 126, -1, 126, 48, 126,
+ -1, 126, 36, 126, -1, 134, -1, 53, 127, -1,
+ 56, 127, -1, 49, 127, -1, 50, 127, -1, 69,
+ 127, -1, 70, 127, -1, 52, 127, -1, 36, 127,
+ -1, 134, 59, 60, -1, 134, 59, 187, 191, 60,
+ -1, 134, 59, 187, 11, 191, 60, -1, 3, -1,
+ 143, -1, 134, 63, 141, -1, 134, 63, 59, 135,
+ 60, -1, 134, 63, 59, 31, 60, -1, 134, 71,
+ 126, 72, -1, 134, 71, 192, 66, 192, 72, -1,
+ 134, 71, 192, 66, 192, 66, 192, 72, -1, 128,
+ -1, 149, 59, 126, 191, 60, -1, 150, 137, 130,
+ 189, 68, -1, 129, 67, 130, 189, 68, -1, 59,
+ 135, 60, 67, 130, 189, 68, -1, 165, -1, -1,
+ 126, 66, 133, -1, 126, -1, 67, 130, 189, 68,
+ -1, 126, -1, 67, 130, 189, 68, -1, 129, -1,
+ 59, 135, 60, -1, 126, -1, 147, -1, 146, -1,
+ 35, -1, 67, -1, 141, -1, 141, -1, -1, 138,
+ -1, 24, -1, 142, -1, 73, -1, 74, 3, 63,
+ 24, -1, 74, 3, 63, 73, -1, 141, -1, 138,
+ -1, 11, -1, 11, 146, -1, 155, -1, 161, -1,
+ 153, -1, 154, -1, 152, -1, 59, 146, 60, -1,
+ 155, -1, 161, -1, 153, -1, 53, 147, -1, 161,
+ -1, 153, -1, 154, -1, 152, -1, 59, 146, 60,
+ -1, 161, -1, 153, -1, 153, -1, 155, -1, 161,
+ -1, 153, -1, 154, -1, 152, -1, 143, -1, 143,
+ 63, 141, -1, 71, 192, 72, 146, -1, 71, 11,
+ 72, 146, -1, 8, 148, -1, 8, 36, 146, -1,
+ 23, 71, 146, 72, 146, -1, 156, -1, 157, -1,
+ 53, 146, -1, 36, 8, 146, -1, 29, 137, 170,
+ 190, 68, -1, 29, 137, 68, -1, 22, 137, 171,
+ 190, 68, -1, 22, 137, 68, -1, 17, 159, 162,
+ -1, 141, 59, 179, 60, 163, -1, 59, 179, 60,
+ 141, 59, 179, 60, 163, -1, 200, 59, 195, 60,
+ 210, -1, 59, 215, 60, 141, 59, 195, 60, 210,
+ -1, 17, 59, 179, 60, 163, -1, -1, 67, 183,
+ 68, -1, -1, 151, -1, 59, 179, 60, -1, 161,
+ -1, 164, 137, 183, 68, -1, 164, 1, -1, -1,
+ 166, 90, 62, -1, 93, -1, 167, 62, 93, -1,
+ 95, -1, 168, 62, 95, -1, 97, -1, 169, 62,
+ 97, -1, 172, -1, 170, 62, 172, -1, 175, -1,
+ 171, 62, 175, -1, 184, 146, 198, -1, 174, 198,
+ -1, 59, 174, 60, 198, -1, 53, 174, 198, -1,
+ 59, 53, 174, 60, 198, -1, 53, 59, 174, 60,
+ 198, -1, 24, -1, 24, 63, 141, -1, 173, -1,
+ 138, 176, -1, 173, -1, 59, 173, 60, -1, 59,
+ 179, 60, 163, -1, 136, -1, 141, 136, -1, 141,
+ 145, -1, 145, -1, 177, -1, 178, 75, 177, -1,
+ -1, 178, 191, -1, -1, 100, -1, 91, -1, 181,
+ -1, 1, -1, 98, -1, 110, -1, 121, -1, 124,
+ -1, 113, -1, -1, 144, 66, 182, 180, -1, 15,
+ -1, 6, 140, -1, 10, 140, -1, 18, 128, -1,
+ 13, 128, -1, 19, 138, -1, 27, 193, -1, 180,
+ -1, 183, 62, 180, -1, 138, -1, 184, 75, 138,
+ -1, 139, -1, 185, 75, 139, -1, 126, -1, 186,
+ 75, 126, -1, 135, -1, 187, 75, 135, -1, 131,
+ -1, 132, -1, 188, 75, 131, -1, 188, 75, 132,
+ -1, -1, 188, 191, -1, -1, 62, -1, -1, 75,
+ -1, -1, 126, -1, -1, 186, -1, -1, 98, -1,
+ -1, 215, -1, -1, 216, -1, -1, 217, -1, -1,
+ 3, -1, 21, 24, 3, 62, -1, 32, 200, 202,
+ 62, -1, 9, 200, 65, 213, 62, -1, 9, 200,
+ 202, 65, 213, 62, -1, 31, 201, 202, 62, -1,
+ 17, 160, 162, 62, -1, 142, -1, 200, -1, 204,
+ -1, 205, -1, 206, -1, 204, -1, 206, -1, 142,
+ -1, 24, -1, 71, 72, 202, -1, 71, 3, 72,
+ 202, -1, 23, 71, 202, 72, 202, -1, 29, 67,
+ 196, 68, -1, 22, 67, 197, 68, -1, 53, 202,
+ -1, 8, 203, -1, 8, 59, 205, 60, -1, 8,
+ 36, 202, -1, 36, 8, 202, -1, 17, 59, 195,
+ 60, 210, -1, 141, 202, 198, -1, 141, 11, 202,
+ 198, -1, 141, 202, 198, -1, 141, 59, 195, 60,
+ 210, -1, 202, -1, -1, 211, -1, 59, 195, 60,
+ -1, 202, -1, 3, -1, 50, 3, -1, 141, -1,
+ 212, -1, 59, 212, 49, 212, 60, -1, -1, 214,
+ 199, -1, 207, -1, 215, 75, 207, -1, 208, -1,
+ 216, 62, 208, -1, 209, -1, 217, 62, 209, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
@@ -663,37 +663,37 @@ static const yytype_uint16 yyrline[] =
263, 264, 271, 271, 284, 288, 289, 293, 298, 304,
308, 312, 316, 322, 328, 334, 339, 343, 347, 353,
359, 363, 367, 373, 377, 383, 384, 388, 394, 403,
- 409, 427, 432, 444, 460, 465, 472, 492, 510, 519,
- 538, 537, 552, 551, 583, 586, 593, 592, 603, 609,
- 618, 629, 635, 638, 646, 645, 656, 662, 674, 678,
- 683, 673, 704, 703, 716, 719, 725, 728, 740, 744,
- 739, 762, 761, 777, 778, 782, 786, 790, 794, 798,
- 802, 806, 810, 814, 818, 822, 826, 830, 834, 838,
- 842, 846, 850, 855, 861, 862, 866, 877, 881, 885,
- 889, 894, 898, 908, 912, 917, 925, 929, 930, 941,
- 945, 949, 953, 957, 965, 966, 972, 979, 985, 992,
- 995, 1002, 1008, 1025, 1032, 1033, 1040, 1041, 1060, 1061,
- 1064, 1067, 1071, 1082, 1091, 1097, 1100, 1103, 1110, 1111,
- 1117, 1130, 1145, 1153, 1165, 1170, 1176, 1177, 1178, 1179,
- 1180, 1181, 1187, 1188, 1189, 1190, 1196, 1197, 1198, 1199,
- 1200, 1206, 1207, 1210, 1213, 1214, 1215, 1216, 1217, 1220,
- 1221, 1234, 1238, 1243, 1248, 1253, 1257, 1258, 1261, 1267,
- 1274, 1280, 1287, 1293, 1304, 1318, 1347, 1387, 1412, 1430,
- 1439, 1442, 1450, 1454, 1458, 1465, 1471, 1476, 1488, 1491,
- 1501, 1502, 1508, 1509, 1515, 1519, 1525, 1526, 1532, 1536,
- 1542, 1565, 1570, 1576, 1582, 1589, 1598, 1607, 1622, 1628,
- 1633, 1637, 1644, 1657, 1658, 1664, 1670, 1673, 1677, 1683,
- 1686, 1695, 1698, 1699, 1703, 1704, 1710, 1711, 1712, 1713,
- 1714, 1716, 1715, 1730, 1736, 1740, 1744, 1748, 1752, 1757,
- 1776, 1782, 1790, 1794, 1800, 1804, 1810, 1814, 1820, 1824,
- 1833, 1837, 1841, 1845, 1851, 1854, 1862, 1863, 1865, 1866,
- 1869, 1872, 1875, 1878, 1881, 1884, 1887, 1890, 1893, 1896,
- 1899, 1902, 1905, 1908, 1914, 1918, 1922, 1926, 1930, 1934,
- 1954, 1961, 1972, 1973, 1974, 1977, 1978, 1981, 1985, 1995,
- 1999, 2003, 2007, 2011, 2015, 2019, 2025, 2031, 2039, 2047,
- 2053, 2060, 2076, 2098, 2102, 2108, 2111, 2114, 2118, 2128,
- 2132, 2151, 2159, 2160, 2172, 2173, 2176, 2180, 2186, 2190,
- 2196, 2200
+ 409, 427, 432, 444, 460, 466, 474, 494, 512, 521,
+ 540, 539, 554, 553, 585, 588, 595, 594, 605, 611,
+ 618, 625, 636, 642, 645, 653, 652, 663, 669, 681,
+ 685, 690, 680, 711, 710, 723, 726, 732, 735, 747,
+ 751, 746, 769, 768, 784, 785, 789, 793, 797, 801,
+ 805, 809, 813, 817, 821, 825, 829, 833, 837, 841,
+ 845, 849, 853, 857, 862, 868, 869, 873, 884, 888,
+ 892, 896, 901, 905, 915, 919, 924, 932, 936, 937,
+ 948, 952, 956, 960, 964, 972, 973, 979, 986, 992,
+ 999, 1002, 1009, 1015, 1032, 1039, 1040, 1047, 1048, 1067,
+ 1068, 1071, 1074, 1078, 1089, 1098, 1104, 1107, 1110, 1117,
+ 1118, 1124, 1137, 1152, 1160, 1172, 1177, 1183, 1184, 1185,
+ 1186, 1187, 1188, 1194, 1195, 1196, 1197, 1203, 1204, 1205,
+ 1206, 1207, 1213, 1214, 1217, 1220, 1221, 1222, 1223, 1224,
+ 1227, 1228, 1241, 1245, 1250, 1255, 1260, 1264, 1265, 1268,
+ 1274, 1281, 1287, 1294, 1300, 1311, 1326, 1355, 1393, 1418,
+ 1436, 1445, 1448, 1456, 1460, 1464, 1471, 1477, 1482, 1494,
+ 1497, 1508, 1509, 1515, 1516, 1522, 1526, 1532, 1533, 1539,
+ 1543, 1549, 1572, 1577, 1583, 1589, 1596, 1605, 1614, 1629,
+ 1635, 1640, 1644, 1651, 1664, 1665, 1671, 1677, 1680, 1684,
+ 1690, 1693, 1702, 1705, 1706, 1710, 1711, 1717, 1718, 1719,
+ 1720, 1721, 1723, 1722, 1737, 1743, 1747, 1751, 1755, 1759,
+ 1764, 1783, 1789, 1797, 1801, 1807, 1811, 1817, 1821, 1827,
+ 1831, 1840, 1844, 1848, 1852, 1858, 1861, 1869, 1870, 1872,
+ 1873, 1876, 1879, 1882, 1885, 1888, 1891, 1894, 1897, 1900,
+ 1903, 1906, 1909, 1912, 1915, 1921, 1925, 1929, 1933, 1937,
+ 1941, 1961, 1968, 1979, 1980, 1981, 1984, 1985, 1988, 1992,
+ 2002, 2006, 2010, 2014, 2018, 2022, 2026, 2032, 2038, 2046,
+ 2054, 2060, 2067, 2083, 2105, 2109, 2115, 2118, 2121, 2125,
+ 2135, 2139, 2158, 2166, 2167, 2179, 2180, 2183, 2187, 2193,
+ 2197, 2203, 2207
};
#endif
@@ -772,35 +772,35 @@ static const yytype_uint8 yyr1[] =
93, 93, 93, 94, 94, 95, 95, 95, 96, 97,
98, 98, 98, 98, 98, 98, 99, 99, 99, 99,
101, 100, 103, 102, 104, 104, 106, 105, 107, 107,
- 108, 108, 108, 109, 111, 110, 112, 112, 114, 115,
- 116, 113, 118, 117, 119, 119, 120, 120, 122, 123,
- 121, 125, 124, 126, 126, 126, 126, 126, 126, 126,
+ 107, 108, 108, 108, 109, 111, 110, 112, 112, 114,
+ 115, 116, 113, 118, 117, 119, 119, 120, 120, 122,
+ 123, 121, 125, 124, 126, 126, 126, 126, 126, 126,
126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
- 126, 126, 126, 126, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 128, 128, 128, 129, 129, 129, 129,
+ 126, 126, 126, 126, 126, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 128, 128, 128, 129, 129, 129,
129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
- 130, 131, 132, 132, 133, 133, 134, 134, 135, 135,
- 136, 137, 137, 138, 139, 140, 140, 141, 141, 141,
- 142, 142, 143, 144, 145, 145, 146, 146, 146, 146,
- 146, 146, 147, 147, 147, 147, 148, 148, 148, 148,
- 148, 149, 149, 150, 151, 151, 151, 151, 151, 152,
- 152, 153, 153, 153, 153, 153, 153, 153, 154, 155,
- 156, 156, 157, 157, 158, 159, 159, 160, 160, 161,
- 162, 162, 163, 163, 163, 164, 165, 165, 166, 166,
- 167, 167, 168, 168, 169, 169, 170, 170, 171, 171,
- 172, 172, 172, 172, 172, 172, 173, 173, 174, 175,
- 175, 175, 176, 177, 177, 177, 177, 178, 178, 179,
- 179, 180, 180, 180, 180, 180, 181, 181, 181, 181,
- 181, 182, 181, 181, 181, 181, 181, 181, 181, 181,
- 183, 183, 184, 184, 185, 185, 186, 186, 187, 187,
- 188, 188, 188, 188, 189, 189, 190, 190, 191, 191,
- 192, 192, 193, 193, 194, 194, 195, 195, 196, 196,
- 197, 197, 198, 198, 199, 199, 199, 199, 199, 199,
- 200, 201, 202, 202, 202, 203, 203, 204, 204, 204,
- 204, 204, 204, 204, 204, 204, 204, 204, 205, 206,
- 207, 207, 208, 209, 209, 210, 210, 211, 211, 212,
- 212, 212, 213, 213, 214, 214, 215, 215, 216, 216,
- 217, 217
+ 129, 130, 131, 132, 132, 133, 133, 134, 134, 135,
+ 135, 136, 137, 137, 138, 139, 140, 140, 141, 141,
+ 141, 142, 142, 143, 144, 145, 145, 146, 146, 146,
+ 146, 146, 146, 147, 147, 147, 147, 148, 148, 148,
+ 148, 148, 149, 149, 150, 151, 151, 151, 151, 151,
+ 152, 152, 153, 153, 153, 153, 153, 153, 153, 154,
+ 155, 156, 156, 157, 157, 158, 159, 159, 160, 160,
+ 161, 162, 162, 163, 163, 163, 164, 165, 165, 166,
+ 166, 167, 167, 168, 168, 169, 169, 170, 170, 171,
+ 171, 172, 172, 172, 172, 172, 172, 173, 173, 174,
+ 175, 175, 175, 176, 177, 177, 177, 177, 178, 178,
+ 179, 179, 180, 180, 180, 180, 180, 181, 181, 181,
+ 181, 181, 182, 181, 181, 181, 181, 181, 181, 181,
+ 181, 183, 183, 184, 184, 185, 185, 186, 186, 187,
+ 187, 188, 188, 188, 188, 189, 189, 190, 190, 191,
+ 191, 192, 192, 193, 193, 194, 194, 195, 195, 196,
+ 196, 197, 197, 198, 198, 199, 199, 199, 199, 199,
+ 199, 200, 201, 202, 202, 202, 203, 203, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 205,
+ 206, 207, 207, 208, 209, 209, 210, 210, 211, 211,
+ 212, 212, 212, 213, 213, 214, 214, 215, 215, 216,
+ 216, 217, 217
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
@@ -813,35 +813,35 @@ static const yytype_uint8 yyr2[] =
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,
- 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,
+ 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, 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
+ 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
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -849,656 +849,642 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint16 yydefact[] =
{
- 5, 0, 3, 0, 1, 0, 7, 0, 22, 157,
- 159, 0, 0, 158, 218, 20, 6, 344, 0, 4,
+ 5, 0, 3, 0, 1, 0, 7, 0, 22, 158,
+ 160, 0, 0, 159, 219, 20, 6, 345, 0, 4,
0, 0, 0, 21, 0, 0, 0, 16, 0, 0,
- 9, 22, 0, 8, 28, 126, 155, 0, 39, 155,
- 0, 263, 74, 0, 0, 0, 78, 0, 0, 292,
- 91, 0, 88, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 290, 0, 25, 0, 256, 257,
- 260, 258, 259, 50, 93, 134, 146, 114, 163, 162,
- 127, 0, 0, 0, 183, 196, 197, 26, 215, 0,
- 139, 27, 0, 19, 0, 0, 0, 0, 0, 0,
- 345, 160, 161, 11, 14, 286, 18, 22, 13, 17,
- 156, 264, 153, 0, 0, 0, 0, 162, 189, 193,
- 179, 177, 178, 176, 265, 134, 0, 294, 249, 0,
- 210, 134, 268, 294, 151, 152, 0, 0, 276, 293,
- 269, 0, 0, 294, 0, 0, 36, 48, 0, 29,
- 274, 154, 0, 122, 117, 118, 121, 115, 116, 0,
- 0, 148, 0, 149, 174, 172, 173, 119, 120, 0,
- 291, 0, 219, 0, 32, 0, 0, 0, 0, 0,
+ 9, 22, 0, 8, 28, 127, 156, 0, 39, 156,
+ 0, 264, 75, 0, 0, 0, 79, 0, 0, 293,
+ 92, 0, 89, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 291, 0, 25, 0, 257, 258,
+ 261, 259, 260, 50, 94, 135, 147, 115, 164, 163,
+ 128, 0, 0, 0, 184, 197, 198, 26, 216, 0,
+ 140, 27, 0, 19, 0, 0, 0, 0, 0, 0,
+ 346, 161, 162, 11, 14, 287, 18, 22, 13, 17,
+ 157, 265, 154, 0, 0, 0, 0, 163, 190, 194,
+ 180, 178, 179, 177, 266, 135, 0, 295, 250, 0,
+ 211, 135, 269, 295, 152, 153, 0, 0, 277, 294,
+ 270, 0, 0, 295, 0, 0, 36, 48, 0, 29,
+ 275, 155, 0, 123, 118, 119, 122, 116, 117, 0,
+ 0, 149, 0, 150, 175, 173, 174, 120, 121, 0,
+ 292, 0, 220, 0, 32, 0, 0, 0, 0, 0,
55, 0, 0, 0, 54, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 140,
- 0, 0, 290, 261, 0, 140, 217, 0, 0, 0,
- 0, 310, 0, 0, 210, 0, 0, 311, 0, 0,
- 23, 287, 0, 12, 249, 0, 0, 194, 170, 168,
- 169, 166, 167, 198, 0, 0, 295, 72, 0, 75,
- 0, 71, 164, 243, 162, 246, 150, 247, 288, 0,
- 249, 0, 204, 79, 76, 157, 0, 203, 0, 286,
- 240, 228, 0, 64, 0, 0, 201, 272, 286, 226,
- 238, 302, 0, 89, 38, 224, 286, 49, 31, 220,
- 286, 0, 0, 40, 0, 175, 147, 0, 0, 35,
- 286, 0, 0, 51, 95, 110, 113, 96, 100, 101,
- 99, 111, 98, 97, 94, 112, 102, 103, 104, 105,
- 106, 107, 108, 109, 284, 123, 278, 288, 0, 128,
- 291, 0, 0, 288, 284, 255, 60, 253, 252, 270,
- 254, 0, 53, 52, 277, 0, 0, 0, 0, 318,
- 0, 0, 0, 0, 0, 317, 0, 312, 313, 314,
- 0, 346, 0, 0, 296, 0, 0, 0, 15, 10,
- 0, 0, 0, 180, 190, 66, 73, 0, 0, 294,
- 165, 244, 245, 289, 250, 212, 0, 0, 0, 294,
- 0, 236, 0, 249, 239, 287, 0, 0, 0, 0,
- 302, 0, 0, 287, 0, 303, 231, 0, 302, 0,
- 287, 0, 287, 0, 42, 275, 0, 0, 0, 199,
- 170, 168, 169, 167, 140, 192, 191, 287, 0, 44,
- 0, 140, 142, 280, 281, 288, 0, 288, 289, 0,
- 0, 0, 131, 290, 262, 289, 0, 0, 0, 0,
- 216, 0, 0, 325, 315, 316, 296, 300, 0, 298,
- 0, 324, 339, 0, 0, 341, 342, 0, 0, 0,
- 0, 0, 302, 0, 0, 309, 0, 297, 304, 308,
- 305, 212, 171, 0, 0, 0, 0, 248, 249, 162,
- 213, 188, 186, 187, 184, 185, 209, 212, 211, 80,
- 77, 237, 241, 0, 229, 202, 195, 0, 0, 92,
- 62, 65, 0, 233, 0, 302, 227, 200, 273, 230,
- 64, 225, 37, 221, 30, 41, 0, 284, 45, 222,
- 286, 47, 33, 43, 284, 0, 289, 285, 137, 0,
- 279, 124, 130, 129, 0, 135, 136, 0, 271, 327,
- 0, 0, 318, 0, 317, 0, 334, 350, 301, 0,
- 0, 0, 348, 299, 328, 340, 0, 306, 0, 319,
- 0, 302, 330, 0, 347, 335, 0, 69, 68, 294,
- 0, 249, 205, 84, 212, 0, 59, 0, 302, 302,
- 232, 0, 171, 0, 287, 0, 46, 0, 140, 144,
- 141, 282, 283, 125, 290, 132, 61, 326, 335, 296,
- 323, 0, 0, 302, 322, 0, 0, 320, 307, 331,
- 296, 296, 338, 207, 336, 67, 70, 214, 0, 86,
- 242, 0, 0, 56, 0, 63, 235, 234, 90, 138,
- 223, 34, 143, 284, 0, 329, 0, 351, 321, 332,
- 349, 0, 0, 0, 212, 0, 85, 81, 0, 0,
- 0, 133, 335, 343, 335, 337, 206, 82, 87, 58,
- 57, 145, 333, 208, 294, 0, 83
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 141,
+ 0, 0, 291, 262, 0, 141, 218, 0, 0, 0,
+ 0, 311, 0, 0, 211, 0, 0, 312, 0, 0,
+ 23, 288, 0, 12, 250, 0, 0, 195, 171, 169,
+ 170, 167, 168, 199, 0, 0, 0, 296, 73, 0,
+ 76, 0, 72, 165, 244, 163, 247, 151, 248, 289,
+ 0, 250, 0, 205, 80, 77, 158, 0, 204, 0,
+ 287, 241, 229, 0, 64, 0, 0, 202, 273, 287,
+ 227, 239, 303, 0, 90, 38, 225, 287, 49, 31,
+ 221, 287, 0, 0, 40, 0, 176, 148, 0, 0,
+ 35, 287, 0, 0, 51, 96, 111, 114, 97, 101,
+ 102, 100, 112, 99, 98, 95, 113, 103, 104, 105,
+ 106, 107, 108, 109, 110, 285, 124, 279, 289, 0,
+ 129, 292, 0, 0, 289, 285, 256, 60, 254, 253,
+ 271, 255, 0, 53, 52, 278, 0, 0, 0, 0,
+ 319, 0, 0, 0, 0, 0, 318, 0, 313, 314,
+ 315, 0, 347, 0, 0, 297, 0, 0, 0, 15,
+ 10, 0, 0, 0, 181, 191, 70, 66, 74, 0,
+ 0, 295, 166, 245, 246, 290, 251, 213, 0, 0,
+ 0, 295, 0, 237, 0, 250, 240, 288, 0, 0,
+ 0, 0, 303, 0, 0, 288, 0, 304, 232, 0,
+ 303, 0, 288, 0, 288, 0, 42, 276, 0, 0,
+ 0, 200, 171, 169, 170, 168, 141, 193, 192, 288,
+ 0, 44, 0, 141, 143, 281, 282, 289, 0, 289,
+ 290, 0, 0, 0, 132, 291, 263, 290, 0, 0,
+ 0, 0, 217, 0, 0, 326, 316, 317, 297, 301,
+ 0, 299, 0, 325, 340, 0, 0, 342, 343, 0,
+ 0, 0, 0, 0, 303, 0, 0, 310, 0, 298,
+ 305, 309, 306, 213, 172, 0, 0, 0, 0, 249,
+ 250, 163, 214, 189, 187, 188, 185, 186, 210, 213,
+ 212, 81, 78, 238, 242, 0, 230, 203, 196, 0,
+ 0, 93, 62, 65, 0, 234, 0, 303, 228, 201,
+ 274, 231, 64, 226, 37, 222, 30, 41, 0, 285,
+ 45, 223, 287, 47, 33, 43, 285, 0, 290, 286,
+ 138, 0, 280, 125, 131, 130, 0, 136, 137, 0,
+ 272, 328, 0, 0, 319, 0, 318, 0, 335, 351,
+ 302, 0, 0, 0, 349, 300, 329, 341, 0, 307,
+ 0, 320, 0, 303, 331, 0, 348, 336, 0, 69,
+ 68, 295, 0, 250, 206, 85, 213, 0, 59, 0,
+ 303, 303, 233, 0, 172, 0, 288, 0, 46, 0,
+ 141, 145, 142, 283, 284, 126, 291, 133, 61, 327,
+ 336, 297, 324, 0, 0, 303, 323, 0, 0, 321,
+ 308, 332, 297, 297, 339, 208, 337, 67, 71, 215,
+ 0, 87, 243, 0, 0, 56, 0, 63, 236, 235,
+ 91, 139, 224, 34, 144, 285, 0, 330, 0, 352,
+ 322, 333, 350, 0, 0, 0, 213, 0, 86, 82,
+ 0, 0, 0, 134, 336, 344, 336, 338, 207, 83,
+ 88, 58, 57, 146, 334, 209, 295, 0, 84
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
-1, 1, 6, 2, 3, 14, 21, 30, 105, 31,
- 8, 24, 16, 17, 65, 327, 67, 149, 518, 519,
- 145, 146, 68, 500, 328, 438, 501, 577, 388, 366,
- 473, 237, 238, 239, 69, 127, 253, 70, 133, 378,
- 573, 646, 664, 619, 647, 71, 143, 399, 72, 141,
- 73, 74, 75, 76, 314, 423, 424, 590, 77, 316,
- 243, 136, 78, 150, 111, 117, 13, 80, 81, 245,
- 246, 163, 119, 82, 83, 480, 228, 84, 230, 231,
- 85, 86, 87, 130, 214, 88, 252, 486, 89, 90,
- 22, 280, 520, 276, 268, 259, 269, 270, 271, 261,
- 384, 247, 248, 249, 329, 330, 322, 331, 272, 152,
- 92, 317, 425, 426, 222, 374, 171, 140, 254, 466,
- 551, 545, 396, 100, 212, 218, 612, 443, 347, 348,
- 349, 351, 552, 547, 613, 614, 456, 457, 25, 467,
- 553, 548
+ 8, 24, 16, 17, 65, 328, 67, 149, 520, 521,
+ 145, 146, 68, 502, 329, 440, 503, 579, 390, 368,
+ 475, 238, 239, 240, 69, 127, 254, 70, 133, 380,
+ 575, 648, 666, 621, 649, 71, 143, 401, 72, 141,
+ 73, 74, 75, 76, 315, 425, 426, 592, 77, 317,
+ 244, 136, 78, 150, 111, 117, 13, 80, 81, 246,
+ 247, 163, 119, 82, 83, 482, 228, 84, 230, 231,
+ 85, 86, 87, 130, 214, 88, 253, 488, 89, 90,
+ 22, 281, 522, 277, 269, 260, 270, 271, 272, 262,
+ 386, 248, 249, 250, 330, 331, 323, 332, 273, 152,
+ 92, 318, 427, 428, 222, 376, 171, 140, 255, 468,
+ 553, 547, 398, 100, 212, 218, 614, 445, 348, 349,
+ 350, 352, 554, 549, 615, 616, 458, 459, 25, 469,
+ 555, 550
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -474
+#define YYPACT_NINF -473
static const yytype_int16 yypact[] =
{
- -474, 48, 28, 35, -474, 258, -474, 37, -474, -474,
- -474, 61, 12, -474, 85, 107, -474, -474, 70, -474,
- 156, 82, 1059, -474, 122, 328, 22, -474, 56, 199,
- -474, 35, 211, -474, -474, -474, 258, 767, -474, 258,
- 459, -474, -474, 152, 459, 258, -474, 23, 145, 1650,
- -474, 23, -474, 294, 359, 1650, 1650, 1650, 1650, 1650,
- 1650, 1693, 1650, 1650, 1289, 159, -474, 412, -474, -474,
- -474, -474, -474, 939, -474, -474, 157, 302, -474, 168,
- -474, 175, 184, 23, 204, -474, -474, -474, 219, 54,
- -474, -474, 47, -474, 227, -12, 269, 227, 227, 239,
- -474, -474, -474, -474, -474, 240, -474, -474, -474, -474,
- -474, -474, -474, 250, 1813, 1813, 1813, -474, 259, -474,
- -474, -474, -474, -474, -474, 64, 302, 1650, 1805, 262,
- 260, 174, -474, 1650, -474, -474, 221, 1813, 2166, 255,
- -474, 290, 237, 1650, 304, 1813, -474, -474, 420, -474,
- -474, -474, 580, -474, -474, -474, -474, -474, -474, 1736,
- 1693, 2166, 280, -474, 253, -474, 50, -474, -474, 275,
- 2166, 285, -474, 430, -474, 612, 1650, 1650, 1650, 1650,
- -474, 1650, 1650, 1650, -474, 1650, 1650, 1650, 1650, 1650,
- 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, -474,
- 1332, 428, 1650, -474, 1650, -474, -474, 1234, 1650, 1650,
- 1650, -474, 763, 258, 260, 293, 369, -474, 1992, 1992,
- -474, 51, 326, -474, 1805, 392, 1813, -474, -474, -474,
- -474, -474, -474, -474, 341, 258, -474, -474, 371, -474,
- 89, 342, 1813, -474, 1805, -474, -474, -474, 335, 360,
- 1805, 1234, -474, -474, 357, 99, 399, -474, 365, 380,
- -474, -474, 377, -474, 173, 151, -474, -474, 381, -474,
- -474, 456, 1779, -474, -474, -474, 401, -474, -474, -474,
- 404, 1650, 258, 366, 1838, -474, 405, 1813, 1813, -474,
- 407, 1650, 410, 2166, 650, -474, 2190, 877, 877, 877,
- 877, -474, 877, 877, 2214, -474, 461, 461, 461, 461,
- -474, -474, -474, -474, 1387, -474, -474, 52, 1442, -474,
- 2064, 411, 1160, 2031, 1387, -474, -474, -474, -474, -474,
- -474, 19, 255, 255, 2166, 1905, 447, 441, 439, -474,
- 444, 505, 1992, 225, 27, -474, 454, -474, -474, -474,
- 1931, -474, 125, 458, 258, 460, 465, 466, -474, -474,
- 463, 1813, 480, -474, -474, -474, -474, 1497, 1552, 1650,
- -474, -474, -474, 1805, -474, 1872, 484, 24, 371, 1650,
- 258, 485, 487, 1805, -474, 472, 481, 1813, 81, 399,
- 456, 399, 490, 289, 483, -474, -474, 258, 456, 519,
- 258, 495, 258, 496, 255, -474, 1650, 1897, 1813, -474,
- 321, 349, 350, 354, -474, -474, -474, 258, 497, 255,
- 1650, -474, 2094, -474, -474, 488, 491, 489, 1693, 498,
- 500, 502, -474, 1650, -474, -474, 506, 503, 1234, 1160,
- -474, 1992, 534, -474, -474, -474, 258, 1958, 1992, 258,
- 1992, -474, -474, 565, 149, -474, -474, 510, 504, 1992,
- 225, 1992, 456, 258, 258, -474, 514, 507, -474, -474,
- -474, 1872, -474, 1234, 1650, 1650, 515, -474, 1805, 520,
- -474, -474, -474, -474, -474, -474, -474, 1872, -474, -474,
- -474, -474, -474, 518, -474, -474, -474, 1693, 517, -474,
- -474, -474, 524, -474, 525, 456, -474, -474, -474, -474,
- -474, -474, -474, -474, -474, 255, 526, 1387, -474, -474,
- 527, 612, -474, 255, 1387, 1595, 1387, -474, -474, 530,
- -474, -474, -474, -474, 116, -474, -474, 141, -474, -474,
- 539, 540, 521, 542, 546, 538, -474, -474, 548, 543,
- 1992, 549, -474, 552, -474, -474, 562, -474, 1992, -474,
- 556, 456, -474, 560, -474, 1984, 238, 2166, 2166, 1650,
- 561, 1805, -474, -474, 1872, 32, -474, 1160, 456, 456,
- -474, 186, 370, 554, 258, 563, 410, 557, -474, 2166,
- -474, -474, -474, -474, 1650, -474, -474, -474, 1984, 258,
- -474, 1958, 1992, 456, -474, 258, 149, -474, -474, -474,
- 258, 258, -474, -474, -474, -474, -474, -474, 564, 613,
- -474, 1650, 1650, -474, 1693, 566, -474, -474, -474, -474,
- -474, -474, -474, 1387, 558, -474, 571, -474, -474, -474,
- -474, 577, 582, 583, 1872, 36, -474, -474, 2118, 2142,
- 572, -474, 1984, -474, 1984, -474, -474, -474, -474, -474,
- -474, -474, -474, -474, 1650, 371, -474
+ -473, 65, 22, 49, -473, 261, -473, 64, -473, -473,
+ -473, 95, 52, -473, 143, 145, -473, -473, 104, -473,
+ 68, 128, 1049, -473, 142, 305, 16, -473, 56, 204,
+ -473, 49, 220, -473, -473, -473, 261, 974, -473, 261,
+ 562, -473, -473, 288, 562, 261, -473, 14, 147, 1615,
+ -473, 14, -473, 395, 401, 1615, 1615, 1615, 1615, 1615,
+ 1615, 1658, 1615, 1615, 737, 168, -473, 414, -473, -473,
+ -473, -473, -473, 649, -473, -473, 165, 122, -473, 169,
+ -473, 177, 218, 14, 219, -473, -473, -473, 235, 89,
+ -473, -473, 34, -473, 206, 124, 286, 206, 206, 260,
+ -473, -473, -473, -473, -473, 265, -473, -473, -473, -473,
+ -473, -473, -473, 270, 1803, 1803, 1803, -473, 269, -473,
+ -473, -473, -473, -473, -473, 39, 122, 882, 1777, 283,
+ 277, 230, -473, 1615, -473, -473, 292, 1803, 2097, 280,
+ -473, 332, 315, 1615, 215, 1803, -473, -473, 244, -473,
+ -473, -473, 949, -473, -473, -473, -473, -473, -473, 1701,
+ 1658, 2097, 298, -473, 9, -473, 59, -473, -473, 303,
+ 2097, 319, -473, 330, -473, 1744, 1615, 1615, 1615, 1615,
+ -473, 1615, 1615, 1615, -473, 1615, 1615, 1615, 1615, 1615,
+ 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, -473,
+ 1297, 455, 1615, -473, 1615, -473, -473, 1225, 1615, 1615,
+ 1615, -473, 594, 261, 277, 328, 403, -473, 1308, 1308,
+ -473, 152, 352, -473, 1777, 405, 1803, -473, -473, -473,
+ -473, -473, -473, -473, 354, 261, 1615, -473, -473, 382,
+ -473, 47, 360, 1803, -473, 1777, -473, -473, -473, 351,
+ 367, 1777, 1225, -473, -473, 366, 84, 407, -473, 374,
+ 373, -473, -473, 372, -473, 138, 42, -473, -473, 377,
+ -473, -473, 442, 1769, -473, -473, -473, 384, -473, -473,
+ -473, 389, 1615, 261, 391, 1830, -473, 394, 1803, 1803,
+ -473, 409, 1615, 411, 2097, 1935, -473, 2121, 1080, 1080,
+ 1080, 1080, -473, 1080, 1080, 2145, -473, 503, 503, 503,
+ 503, -473, -473, -473, -473, 1352, -473, -473, 27, 1407,
+ -473, 1995, 412, 1147, 1962, 1352, -473, -473, -473, -473,
+ -473, -473, 7, 280, 280, 2097, 698, 418, 415, 413,
+ -473, 416, 477, 1308, 188, 31, -473, 425, -473, -473,
+ -473, 1897, -473, 221, 433, 261, 434, 436, 439, -473,
+ -473, 432, 1803, 452, -473, -473, 2097, -473, -473, 1462,
+ 1517, 1615, -473, -473, -473, 1777, -473, 1856, 453, 91,
+ 382, 1615, 261, 454, 456, 1777, -473, 475, 451, 1803,
+ 133, 407, 442, 407, 460, 326, 462, -473, -473, 261,
+ 442, 467, 261, 478, 261, 486, 280, -473, 1615, 1864,
+ 1803, -473, 26, 248, 264, 430, -473, -473, -473, 261,
+ 492, 280, 1615, -473, 2025, -473, -473, 485, 493, 487,
+ 1658, 504, 506, 508, -473, 1615, -473, -473, 512, 505,
+ 1225, 1147, -473, 1308, 517, -473, -473, -473, 261, 1889,
+ 1308, 261, 1308, -473, -473, 571, 155, -473, -473, 514,
+ 509, 1308, 188, 1308, 442, 261, 261, -473, 518, 507,
+ -473, -473, -473, 1856, -473, 1225, 1615, 1615, 521, -473,
+ 1777, 528, -473, -473, -473, -473, -473, -473, -473, 1856,
+ -473, -473, -473, -473, -473, 520, -473, -473, -473, 1658,
+ 522, -473, -473, -473, 530, -473, 532, 442, -473, -473,
+ -473, -473, -473, -473, -473, -473, -473, 280, 535, 1352,
+ -473, -473, 536, 1744, -473, 280, 1352, 1560, 1352, -473,
+ -473, 539, -473, -473, -473, -473, 247, -473, -473, 308,
+ -473, -473, 541, 543, 545, 546, 547, 544, -473, -473,
+ 551, 548, 1308, 554, -473, 557, -473, -473, 576, -473,
+ 1308, -473, 564, 442, -473, 568, -473, 1923, 318, 2097,
+ 2097, 1615, 569, 1777, -473, -473, 1856, 156, -473, 1147,
+ 442, 442, -473, 243, 483, 563, 261, 577, 411, 570,
+ -473, 2097, -473, -473, -473, -473, 1615, -473, -473, -473,
+ 1923, 261, -473, 1889, 1308, 442, -473, 261, 155, -473,
+ -473, -473, 261, 261, -473, -473, -473, -473, -473, -473,
+ 579, 627, -473, 1615, 1615, -473, 1658, 580, -473, -473,
+ -473, -473, -473, -473, -473, 1352, 572, -473, 583, -473,
+ -473, -473, -473, 585, 586, 590, 1856, 77, -473, -473,
+ 2049, 2073, 584, -473, 1923, -473, 1923, -473, -473, -473,
+ -473, -473, -473, -473, -473, -473, 1615, 382, -473
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -474, -474, -474, -474, -474, -474, -474, -15, -474, -474,
- 616, -474, -3, -474, -474, 622, -474, -125, -27, 66,
- -474, -124, -112, -474, 11, -474, -474, -474, 147, -368,
- -474, -474, -474, -474, -474, -474, -140, -474, -474, -474,
- -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
- 532, 10, 247, -474, -194, 132, 135, -474, 279, -59,
- 418, 67, 5, 384, 624, 425, 317, 20, -474, 424,
- 636, 509, -474, -474, -474, -474, -36, -37, -31, -49,
- -474, -474, -474, -474, -474, -32, 464, -473, -474, -474,
- -474, -474, -474, -474, -474, -474, 277, -119, -231, 287,
- -474, 300, -474, -205, -300, 652, -474, -242, -474, -63,
- 106, 182, -474, -316, -241, -285, -195, -474, -111, -420,
- -474, -474, -245, -474, 402, -474, -176, -474, 345, 249,
- 346, 218, 87, 96, -415, -474, -429, 252, -474, 522,
- -474, -474
+ -473, -473, -473, -473, -473, -473, -473, -12, -473, -473,
+ 624, -473, -1, -473, -473, 635, -473, -137, -48, 74,
+ -473, -130, -112, -473, 11, -473, -473, -473, 149, -372,
+ -473, -473, -473, -473, -473, -473, -140, -473, -473, -473,
+ -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+ 662, 448, 257, -473, -196, 135, 139, -473, 262, -59,
+ 424, -16, -3, 387, 632, 427, 313, 20, -473, 428,
+ -89, 524, -473, -473, -473, -473, -36, -37, -31, -49,
+ -473, -473, -473, -473, -473, -32, 458, -472, -473, -473,
+ -473, -473, -473, -473, -473, -473, 279, -108, -211, 290,
+ -473, 306, -473, -214, -291, 658, -473, -230, -473, -63,
+ -6, 191, -473, -302, -219, -254, -195, -473, -107, -435,
+ -473, -473, -347, -473, 323, -473, 72, -473, 371, 268,
+ 380, 242, 102, 110, -468, -473, -438, 255, -473, 515,
+ -473, -473
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says.
If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -277
+#define YYTABLE_NINF -278
static const yytype_int16 yytable[] =
{
- 121, 120, 162, 273, 175, 123, 122, 321, 437, 377,
- 489, 324, 165, 104, 572, 236, 241, 260, 386, 360,
- 275, 236, 434, 279, 164, 556, 541, 394, 108, 166,
- 458, 236, 429, 390, 392, 401, 346, 621, 436, 403,
- 174, 110, 356, 357, 110, 376, 101, 213, 4, 418,
- 132, -215, 208, 5, 27, 206, 657, 118, 134, 27,
- 7, 15, 11, 427, 18, 153, 154, 155, 156, 157,
- 158, -267, 167, 168, 19, 9, -267, 229, 229, 229,
- 9, 439, 232, 232, 232, -215, 439, 440, 497, 134,
- 135, 229, 488, 498, 367, 102, 232, 622, 623, 459,
- 229, 620, -236, 326, 223, 232, 20, 624, 229, -181,
- 175, 165, 209, 232, 29, 229, 103, -215, 142, 29,
- 232, 135, 210, 164, 10, 11, -267, 428, 166, 10,
- 11, 23, -267, 26, 118, 118, 118, 382, 229, 538,
- 527, 258, 529, 232, 33, 503, 290, 267, 118, 499,
- 205, 165, 452, 509, 368, 139, 207, 118, 502, 27,
- 504, -236, 380, 164, 210, 118, 451, -236, 166, 153,
- 157, 656, 118, 9, 462, 381, 9, 641, 493, 636,
- 9, -266, 594, 635, 93, 463, -266, 229, 595, 229,
- 642, 643, 232, 497, 232, 118, 537, 381, 498, 453,
- 464, 583, 106, 439, 391, 229, 358, 229, 587, 596,
- 232, 128, 232, 229, 109, 28, 137, 562, 232, 29,
- 517, 172, 10, 11, 199, 10, 11, 524, 452, 10,
- 11, 566, 389, 240, -153, 229, -266, 662, 534, 663,
- 232, 203, -266, 204, 118, 255, 118, 411, 410, 9,
- 229, 229, 413, 412, 628, 232, 232, 236, 476, 431,
- 580, 255, 118, -182, 118, 539, 260, 236, 490, 165,
- 118, 546, 549, 570, 554, 453, 511, 513, -181, 585,
- 256, 164, 9, 559, 454, 561, 166, 125, -183, 257,
- 264, 131, 118, 216, 10, 11, 265, 666, 10, 11,
- 439, 11, 221, 220, 118, 266, 615, 118, 118, 224,
- 10, 11, -182, 255, 332, 333, 609, 650, 9, 126,
- -183, 250, 235, 126, 229, 263, 484, 251, 9, 232,
- 210, 10, 11, 626, 627, 625, 229, 94, 482, 481,
- 286, 232, 264, 485, 483, 95, 229, 287, 265, 96,
- 229, 232, 354, 144, 521, 232, -179, 288, 639, 97,
- 98, 200, 10, 11, 274, 201, 618, 10, 11, 530,
- 229, 229, 355, 202, 603, 232, 232, 10, 11, 165,
- -179, 118, 607, 9, -177, -178, 359, 404, -179, -176,
- 258, 164, 99, 118, 633, 118, 166, 419, 267, 634,
- 361, 363, 508, 118, 369, -180, 365, 118, -177, -178,
- 373, 211, 211, -176, 211, 211, -177, -178, 148, 379,
- 375, -176, 484, 381, 383, 546, 638, 118, 118, -180,
- 12, 406, 10, 11, 482, 481, 9, -180, 484, 485,
- 483, 229, 385, 393, 9, 32, 232, 79, 165, 387,
- 482, 481, 9, 32, 9, 485, 483, 236, 616, 395,
- 164, 112, 35, 400, 112, 166, 402, 37, 129, 417,
- 112, 173, 414, 332, 333, 420, 113, 433, 147, 151,
- 278, 47, 48, 9, 229, 10, 11, 318, 51, 232,
- 289, 118, 151, 10, 11, 178, 255, 215, 118, 217,
- 219, 10, 11, 10, 11, 186, 446, 118, 447, 190,
- 448, 449, 515, 450, 195, 196, 197, 198, 61, 460,
- 465, 521, 468, 471, 665, 484, 523, 469, 470, 345,
- 64, 256, 10, 11, 229, 345, 345, 482, 481, 232,
- 472, 118, 485, 483, 487, 10, 11, 492, 380, 495,
- 505, 507, 236, 244, 510, 512, 514, 522, 531, 528,
- 532, 112, 533, 526, 435, 530, 535, 112, 555, 147,
- 341, 536, 557, 151, 565, 165, 558, 569, 574, 571,
- -157, 138, 464, 576, 578, 579, 582, 164, 37, 584,
- 593, 118, 166, 161, 118, 484, 170, 113, 151, 597,
- 598, 599, 47, 48, 9, -158, 600, 482, 481, 51,
- 601, 606, 485, 483, 605, 602, 225, 604, 608, 610,
- 37, 617, 629, 631, 644, 632, 319, 645, 439, 113,
- 651, 652, 79, 115, 47, 48, 9, 653, 350, 226,
- 661, 51, 654, 655, 66, 281, 32, 107, 225, 244,
- 630, 64, 345, 10, 11, 282, 658, 581, 591, 345,
- 364, 592, 371, 124, 118, 115, 405, 345, 372, 285,
- 506, 226, 494, 477, 91, 244, 79, 291, 353, 575,
- 444, 445, 564, 64, 178, 10, 11, 282, 181, 182,
- 183, 540, 640, 185, 186, 187, 188, 637, 190, 191,
- 192, 193, 194, 195, 196, 197, 198, 151, 293, 294,
- 295, 296, 560, 297, 298, 299, 0, 300, 301, 302,
- 303, 304, 305, 306, 307, 308, 309, 310, 311, 312,
- 313, 0, 161, 0, 320, 352, 323, 0, 0, 0,
- 138, 138, 334, 0, 0, 0, 0, 79, 0, 0,
- 227, 233, 234, 0, 0, 0, 0, 0, 345, 0,
- 0, 0, 0, 0, 544, 345, 0, 345, 455, 0,
- 0, 335, 0, 262, 0, 37, 345, 0, 345, 350,
- 336, 277, 0, 0, 113, 337, 338, 339, 283, 47,
- 48, 9, 340, 0, 0, 0, 51, 0, 244, 341,
- 479, 0, 0, 114, 0, 491, 0, 0, 244, 0,
- 112, 292, 0, 138, 0, 0, 342, 0, 112, 0,
- 115, 0, 112, 138, 0, 147, 116, 151, 343, 0,
- 0, 0, 0, 0, 344, 0, 0, 11, 64, 0,
- 10, 11, 151, 0, 0, 0, 422, 0, 0, 0,
- 161, 0, 0, 0, 0, 0, 422, 0, 0, 0,
- 0, 0, 362, 79, 79, 0, 0, 345, 0, 0,
- 0, 350, 543, 0, 550, 345, 0, 0, 370, 455,
- 0, 0, 345, 0, 0, 455, 0, 0, 563, 350,
- 0, 0, 0, 0, 0, 0, 0, 0, 79, 138,
- 138, 0, 0, 244, 0, 0, 0, 0, 398, 0,
- 0, 178, 0, 0, 0, 345, 0, 0, 544, 345,
- 409, 186, 0, 415, 416, 190, 191, 192, 193, 194,
- 195, 196, 197, 198, 0, 0, 0, 0, 138, 0,
- 0, 0, 0, 176, -276, 0, 0, 0, 0, 0,
- 0, 0, 138, 0, 0, 0, 0, 0, 0, 0,
- 161, 0, 0, 0, 0, 170, 0, 0, 0, 345,
- 0, 345, 177, 178, 0, 179, 180, 181, 182, 183,
- 0, 184, 185, 186, 187, 188, 189, 190, 191, 192,
- 193, 194, 195, 196, 197, 198, 244, 409, 0, 0,
- 0, 0, 79, 0, -276, 0, 567, 568, 0, 151,
- 0, 0, 0, 0, -276, 0, 0, 0, 0, 0,
- 0, 0, 0, 496, 350, 0, 543, 0, 0, 161,
- 550, 455, 0, 0, 0, 350, 350, 0, 0, 0,
- 0, 0, 0, 227, 516, 0, 0, 0, 0, 422,
- 0, 0, 0, 0, 0, 0, 422, 589, 422, -2,
+ 121, 120, 162, 274, 175, 123, 122, 322, 491, 325,
+ 361, 280, 165, 543, 276, 237, 104, 574, 558, 174,
+ 242, 237, 379, 439, 164, 227, 233, 234, 261, 166,
+ 108, 237, 436, 110, 460, 142, 110, 378, 429, 208,
+ 101, 388, 132, 139, -184, 505, -268, 5, 263, 134,
+ 396, -268, 369, 511, 392, 394, 278, 118, 403, 27,
+ -216, -180, 405, 284, 431, 4, 383, 205, -183, 441,
+ 438, 27, 420, 207, 7, 442, -184, 229, 229, 229,
+ 9, 135, 232, 232, 232, -180, 293, -237, 15, 102,
+ 206, 229, 9, -180, -216, 393, 232, 659, 18, 209,
+ 229, -268, 430, 461, 622, 232, 223, -268, 229, 210,
+ 175, 165, 370, 232, 19, 229, 103, 564, -182, 29,
+ 232, 241, 210, 164, 134, 291, -216, 28, 166, 10,
+ 11, 29, 637, 259, 118, 118, 118, 363, 229, 268,
+ 499, 10, 11, 232, 327, 500, -237, 382, 118, 384,
+ 540, 165, -237, 441, 372, 27, 135, 118, 454, 490,
+ 582, 623, 383, 164, 20, 118, 638, 26, 166, 23,
+ 643, 495, 118, 529, 658, 531, 9, 644, 645, 9,
+ 504, 200, 506, 213, 400, 201, 664, 229, 665, 229,
+ 33, 454, 232, 202, 232, 118, 411, 391, 11, 417,
+ 418, 501, 333, 334, 93, 455, 229, 106, 229, 359,
+ 539, 232, 9, 232, 229, 29, 611, 585, 137, 232,
+ 519, 624, 625, 109, 589, 10, 11, 526, 10, 11,
+ 172, 626, 199, 628, 629, -154, 229, -267, 455, 9,
+ 536, 232, -267, 203, 118, 568, 118, 456, 413, 412,
+ 499, 229, 229, 415, 414, 500, 232, 232, 641, 237,
+ 433, 10, 11, 118, 478, 118, 572, 515, 9, 237,
+ 165, 118, 513, 411, 492, 275, 406, 204, -183, 261,
+ 11, 465, 164, -178, 347, 9, 421, 166, 10, 11,
+ 357, 358, -267, 118, -182, 668, 466, 125, -267, -179,
+ 498, 131, 126, 587, 279, 118, 126, -178, 118, 118,
+ 216, 630, 9, 596, 94, -178, 256, 10, 11, 597,
+ 227, 518, 95, -179, 220, 229, 96, 221, 486, 224,
+ 232, -179, 235, 652, 10, 11, 97, 98, 229, 256,
+ 484, 483, 251, 232, 252, 487, 485, 128, 229, 627,
+ 256, 257, 229, 232, 9, 210, 523, 232, 287, 620,
+ 258, 10, 11, 333, 334, 10, 11, 264, 265, 99,
+ 441, 532, 229, 229, 266, 288, 598, 232, 232, 265,
+ 441, 165, 118, 267, 259, 266, 617, 355, 10, 11,
+ 290, 289, 268, 164, 635, 118, 510, 118, 166, 10,
+ 11, 636, 517, 10, 11, 118, 356, 211, 211, 118,
+ 211, 211, 360, 362, 364, 453, 525, 367, 215, 9,
+ 217, 219, 371, 464, 486, 9, 375, 377, 381, 118,
+ 118, 383, 12, 385, 588, 387, 484, 483, 9, 395,
+ 486, 487, 485, 229, 389, 397, 402, 32, 232, 79,
+ 165, 404, 484, 483, 144, 32, 408, 487, 485, 237,
+ 148, 416, 164, 112, 618, -177, 112, 166, 10, 11,
+ 129, 419, 112, 173, 10, 11, 422, 448, 435, 9,
+ 147, 151, 449, 451, 450, 452, 229, 10, 11, -177,
+ 462, 232, 473, 118, 151, 467, 470, -177, 471, 256,
+ 118, 472, 512, 153, 154, 155, 156, 157, 158, 118,
+ 167, 168, 474, 489, 319, 541, 494, 382, -181, 497,
+ 507, 548, 551, 523, 556, 346, 667, 486, 10, 11,
+ 509, 346, 346, 561, 257, 563, 229, 178, 514, 484,
+ 483, 232, -181, 118, 487, 485, 516, 186, 10, 11,
+ -181, 190, 524, 342, 237, 245, 195, 196, 197, 198,
+ 528, 530, 437, 112, 533, 35, 534, 532, 535, 112,
+ 37, 147, 537, 538, 557, 151, 559, 165, 567, 113,
+ 576, 560, 466, 571, 47, 48, 9, 573, 578, 164,
+ 580, 51, 581, 118, 166, 584, 118, 486, 586, 595,
+ 151, 599, 336, 600, -158, 601, -159, 153, 157, 484,
+ 483, 337, 602, 603, 487, 485, 338, 339, 340, 607,
+ 604, 61, 606, 341, 605, 608, 610, 612, 320, 619,
+ 342, 631, 609, 64, 79, 10, 11, 633, 634, 646,
+ 351, 647, 441, 654, 653, 655, 656, 343, 32, 346,
+ 657, 245, 663, 176, -277, 107, 346, 66, 660, 344,
+ 632, 583, 365, 593, 346, 345, 118, 594, 11, 373,
+ 407, 124, 354, 374, 508, 548, 640, 496, 245, 79,
+ 91, 479, 177, 178, 286, 179, 180, 181, 182, 183,
+ 577, 184, 185, 186, 187, 188, 189, 190, 191, 192,
+ 193, 194, 195, 196, 197, 198, 336, 446, 566, 642,
+ 151, 138, 542, 639, -277, 337, 447, 562, 0, 0,
+ 338, 339, 340, 161, -277, 0, 170, 341, 353, 0,
+ 0, 0, 0, 0, 443, 0, 0, 0, 0, 0,
+ 35, 0, 0, 0, 0, 37, 0, 0, 169, 0,
+ 79, 343, 0, 0, 113, 0, 346, 444, 0, 47,
+ 48, 9, 546, 346, 0, 346, 51, 0, 0, 345,
+ 0, 457, 11, 55, 346, 0, 346, 0, 0, 0,
+ 0, 0, 351, 0, 0, 0, 56, 57, 0, 58,
+ 59, 0, 0, 60, 0, 0, 61, 0, 0, 0,
+ 0, 0, 245, 0, 481, 0, 62, 63, 64, 493,
+ 10, 11, 245, 0, 112, 0, 0, 0, 0, 0,
+ 0, 0, 112, 0, 0, 0, 112, 0, 0, 147,
+ 0, 151, 0, 0, 0, 0, 0, 0, 294, 295,
+ 296, 297, 0, 298, 299, 300, 151, 301, 302, 303,
+ 304, 305, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 0, 161, 0, 321, 346, 324, 79, 79, 0,
+ 138, 138, 335, 346, 0, 351, 545, 0, 552, 0,
+ 346, 0, 0, 457, 0, 35, 0, 0, 0, 457,
+ 37, 0, 565, 351, 0, 0, 0, 0, 366, 113,
+ 0, 0, 79, 0, 47, 48, 9, 245, 236, 0,
+ 0, 51, 0, 346, 0, 0, 546, 346, 55, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 56, 57, 0, 58, 59, 0, 0, 60, 0,
+ 0, 61, 0, 0, 138, 0, 0, 0, 0, 0,
+ 0, 62, 63, 64, 138, 10, 11, 37, 0, 0,
+ 0, 0, 0, 0, 0, 0, 113, 346, 0, 346,
+ 0, 47, 48, 9, 0, 0, 0, 424, 51, 0,
+ 0, 161, 37, 0, 0, 225, 0, 424, 0, 0,
+ 0, 113, 0, 0, 0, 0, 47, 48, 9, 0,
+ 245, 0, 115, 51, 0, 0, 79, 0, 226, 0,
+ 114, 0, 0, 151, 282, 0, 0, 0, 0, 0,
+ 64, 0, 10, 11, 283, 0, 0, 115, 351, 0,
+ 545, 138, 138, 116, 552, 457, 0, 0, 0, 351,
+ 351, 0, 0, 0, 0, 64, 0, 10, 11, -2,
34, 0, 35, 0, 0, 36, 0, 37, 38, 39,
0, 0, 40, 0, 41, 42, 43, 44, 45, 46,
- 0, 47, 48, 9, 0, 0, 49, 50, 51, 52,
- 53, 54, 0, 0, 0, 55, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 56, 57,
+ 138, 47, 48, 9, 0, 0, 49, 50, 51, 52,
+ 53, 54, 0, 0, 138, 55, 0, 0, 0, 0,
+ 0, 0, 161, 0, 0, 0, 0, 170, 56, 57,
0, 58, 59, 0, 0, 60, 0, 0, 61, 0,
- 0, -24, 0, 0, 0, 0, 170, 0, 62, 63,
- 64, 0, 10, 11, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 648, 649, 0, 161, 586, 0, 0,
- 0, 325, 0, 35, 0, 422, 36, -251, 37, 38,
- 39, 0, -251, 40, 0, 41, 42, 113, 44, 45,
- 46, 0, 47, 48, 9, 0, 0, 49, 50, 51,
- 52, 53, 54, 0, 0, 0, 55, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,
- 57, 0, 58, 59, 0, 0, 60, 0, 0, 61,
- 0, 0, -251, 0, 0, 0, 0, 326, -251, 62,
- 63, 64, 0, 10, 11, 325, 0, 35, 0, 0,
- 36, 0, 37, 38, 39, 0, 0, 40, 0, 41,
- 42, 113, 44, 45, 46, 0, 47, 48, 9, 0,
- 0, 49, 50, 51, 52, 53, 54, 0, 0, 0,
- 55, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 56, 57, 0, 58, 59, 0, 0,
- 60, 0, 35, 61, 0, 0, -251, 37, 0, 0,
- 169, 326, -251, 62, 63, 64, 113, 10, 11, 0,
- 0, 47, 48, 9, 0, 0, 0, 0, 51, 0,
- 0, 0, 0, 0, 0, 55, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 35, 0, 0, 56, 57,
- 37, 58, 59, 0, 0, 60, 0, 0, 61, 113,
- 0, 0, 0, 0, 47, 48, 9, 0, 62, 63,
- 64, 51, 10, 11, 0, 0, 0, 0, 159, 0,
+ 0, -24, 0, 0, 178, 0, 0, 0, 62, 63,
+ 64, 0, 10, 11, 186, 0, 0, 0, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 0, 569, 570,
+ 0, 0, 0, 0, 0, 0, 0, 0, 326, 0,
+ 35, 0, 0, 36, -252, 37, 38, 39, 0, -252,
+ 40, 161, 41, 42, 113, 44, 45, 46, 0, 47,
+ 48, 9, 0, 0, 49, 50, 51, 52, 53, 54,
+ 0, 424, 0, 55, 0, 0, 0, 0, 424, 591,
+ 424, 0, 0, 0, 0, 0, 56, 57, 0, 58,
+ 59, 0, 0, 60, 0, 0, 61, 0, 0, -252,
+ 0, 0, 0, 0, 327, -252, 62, 63, 64, 0,
+ 10, 11, 0, 0, 0, 0, 326, 0, 35, 0,
+ 0, 36, 0, 37, 38, 39, 0, 0, 40, 0,
+ 41, 42, 113, 44, 45, 46, 0, 47, 48, 9,
+ 0, 0, 49, 50, 51, 52, 53, 54, 170, 0,
+ 0, 55, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 56, 57, 0, 58, 59, 0,
+ 0, 60, 0, 0, 61, 650, 651, -252, 161, 0,
+ 0, 0, 327, -252, 62, 63, 64, 424, 10, 11,
+ 35, 0, 0, 0, 0, 37, 0, 0, 0, 0,
+ 0, 0, 0, 0, 113, 0, 336, 0, 0, 47,
+ 48, 9, 0, 0, 0, 337, 51, 0, 0, 0,
+ 338, 339, 340, 159, 0, 0, 0, 341, 0, 0,
+ 0, 0, 0, 0, 342, 0, 56, 57, 0, 58,
+ 160, 0, 0, 60, 0, 35, 61, 316, 0, 0,
+ 37, 343, 0, 0, 0, 0, 62, 63, 64, 113,
+ 10, 11, 0, 0, 47, 48, 9, 0, 0, 345,
+ 0, 51, 11, 0, 0, 0, 0, 0, 55, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 56, 57, 0, 58, 160, 0, 0, 60, 0,
- 35, 61, 315, 0, 0, 37, 0, 0, 0, 0,
+ 0, 56, 57, 0, 58, 59, 0, 0, 60, 0,
+ 35, 61, 0, 0, 0, 37, 0, 0, 0, 423,
0, 62, 63, 64, 113, 10, 11, 0, 0, 47,
- 48, 9, 0, 0, 0, 0, 51, 0, 0, 0,
- 0, 0, 0, 55, 0, 0, 0, 0, 0, 0,
+ 48, 9, 0, 0, 0, 0, 51, 0, 432, 0,
+ 0, 0, 0, 159, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 56, 57, 0, 58,
- 59, 0, 0, 60, 0, 35, 61, 0, 0, 0,
- 37, 0, 0, 0, 421, 0, 62, 63, 64, 113,
- 10, 11, 0, 0, 47, 48, 9, 0, 0, 0,
- 0, 51, 0, 430, 0, 0, 0, 0, 159, 0,
+ 160, 0, 0, 60, 0, 35, 61, 0, 0, 0,
+ 37, 0, 0, 0, 0, 0, 62, 63, 64, 113,
+ 10, 11, 0, 0, 47, 48, 9, 0, 476, 0,
+ 0, 51, 0, 0, 0, 0, 0, 0, 55, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 56, 57, 0, 58, 160, 0, 0, 60, 0,
+ 0, 56, 57, 0, 58, 59, 0, 0, 60, 0,
35, 61, 0, 0, 0, 37, 0, 0, 0, 0,
0, 62, 63, 64, 113, 10, 11, 0, 0, 47,
- 48, 9, 0, 474, 0, 0, 51, 0, 0, 0,
+ 48, 9, 0, 477, 0, 0, 51, 0, 0, 0,
0, 0, 0, 55, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 56, 57, 0, 58,
- 59, 0, 0, 60, 0, 35, 61, 0, 0, 0,
- 37, 0, 0, 0, 0, 0, 62, 63, 64, 113,
- 10, 11, 0, 0, 47, 48, 9, 0, 475, 0,
- 0, 51, 0, 0, 0, 0, 0, 0, 55, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 35, 0,
- 0, 56, 57, 37, 58, 59, 0, 0, 60, 0,
- 0, 61, 113, 0, 0, 0, 0, 47, 48, 9,
- 0, 62, 63, 64, 51, 10, 11, 0, 0, 0,
+ 0, 0, 0, 35, 0, 0, 56, 57, 37, 58,
+ 59, 0, 0, 60, 0, 0, 61, 113, 0, 0,
+ 0, 0, 47, 48, 9, 0, 62, 63, 64, 51,
+ 10, 11, 0, 0, 0, 0, 55, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,
+ 57, 0, 58, 59, 0, 0, 60, 0, 35, 61,
+ 0, 0, 0, 37, 0, 0, 0, 590, 0, 62,
+ 63, 64, 113, 10, 11, 0, 0, 47, 48, 9,
+ 0, 0, 0, 0, 51, 0, 0, 0, 0, 0,
0, 55, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 56, 57, 0, 58, 59, 0,
- 0, 60, 0, 35, 61, 0, 0, 0, 37, 0,
- 0, 0, 588, 0, 62, 63, 64, 113, 10, 11,
- 0, 0, 47, 48, 9, 0, 0, 0, 0, 51,
- 0, 0, 0, 0, 0, 0, 55, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 35, 0, 0, 56,
- 57, 37, 58, 59, 0, 0, 60, 0, 0, 61,
- 113, 0, 0, 0, 0, 47, 48, 9, 0, 62,
- 63, 64, 51, 10, 11, 0, 0, 0, 0, 159,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 35,
- 0, 0, 56, 57, 284, 58, 160, 0, 0, 60,
- 0, 0, 61, 113, 0, 0, 0, 0, 47, 48,
- 9, 0, 62, 63, 64, 51, 10, 11, 0, 0,
- 0, 0, 55, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 56, 57, 37, 58, 59,
- 0, 0, 60, 0, 0, 61, 113, 0, 0, 0,
- 0, 47, 48, 9, 0, 62, 63, 64, 51, 10,
- 11, 0, 0, 37, 0, 225, 242, 0, 0, 0,
- 0, 37, 113, 0, 0, 0, 0, 47, 48, 9,
- 113, 0, 115, 0, 51, 47, 48, 9, 226, 0,
- 0, 225, 51, 0, 0, 0, 37, 0, 0, 225,
- 64, 0, 10, 11, 397, 113, 0, 0, 115, 0,
- 47, 48, 9, 0, 226, 0, 115, 51, 0, 0,
- 0, 0, 226, 0, 407, 0, 64, 0, 10, 11,
- 37, 0, 0, 0, 64, 0, 10, 11, 0, 113,
- 0, 115, 0, 0, 47, 48, 9, 408, 0, 0,
- 0, 51, 0, 0, 0, 284, 0, 0, 225, 64,
- 0, 10, 11, 335, 113, 0, 0, 0, 0, 47,
- 48, 9, 336, 0, 0, 115, 51, 337, 338, 339,
- 0, 478, 0, 225, 340, 0, 0, 0, 0, 335,
- 0, 441, 461, 64, 0, 10, 11, 0, 336, 0,
- 115, 0, 0, 337, 338, 339, 226, 0, 342, 0,
- 340, 0, 0, 0, 442, 0, 335, 341, 64, 0,
- 10, 11, 0, 0, 0, 336, 344, 0, 0, 11,
- 337, 338, 542, 0, 342, 0, 0, 340, 0, 0,
- 0, 0, 335, 0, 341, 0, 0, 0, 0, 0,
- 335, 336, 344, 0, 0, 11, 337, 338, 339, 336,
- 0, 342, 0, 340, 337, 338, 339, 0, 0, 0,
- 341, 340, 0, 0, 0, 0, 0, 0, 341, 344,
- 0, 10, 11, 0, 0, 0, 0, 342, 0, 0,
- 0, 0, 0, 611, 0, 342, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 344, 0, 0, 11, 0,
- 0, 0, 0, 344, 177, 178, 11, 179, 0, 181,
+ 0, 35, 0, 0, 56, 57, 37, 58, 59, 0,
+ 0, 60, 0, 0, 61, 113, 0, 0, 0, 0,
+ 47, 48, 9, 0, 62, 63, 64, 51, 10, 11,
+ 0, 0, 0, 0, 159, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 35, 0, 0, 56, 57, 285,
+ 58, 160, 0, 0, 60, 0, 0, 61, 113, 0,
+ 0, 0, 0, 47, 48, 9, 0, 62, 63, 64,
+ 51, 10, 11, 0, 0, 0, 0, 55, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 56, 57, 37, 58, 59, 0, 0, 60, 0, 0,
+ 61, 113, 0, 0, 0, 0, 47, 48, 9, 0,
+ 62, 63, 64, 51, 10, 11, 0, 37, 0, 0,
+ 225, 0, 0, 0, 0, 37, 113, 0, 243, 0,
+ 0, 47, 48, 9, 113, 0, 0, 115, 51, 47,
+ 48, 9, 0, 226, 0, 225, 51, 0, 0, 292,
+ 0, 37, 0, 225, 0, 64, 0, 10, 11, 283,
+ 113, 0, 115, 0, 0, 47, 48, 9, 226, 0,
+ 115, 0, 51, 0, 0, 0, 226, 0, 37, 225,
+ 64, 0, 10, 11, 399, 0, 0, 113, 64, 0,
+ 10, 11, 47, 48, 9, 0, 115, 0, 0, 51,
+ 0, 0, 226, 0, 37, 0, 409, 0, 0, 0,
+ 0, 0, 285, 113, 64, 0, 10, 11, 47, 48,
+ 9, 113, 0, 115, 0, 51, 47, 48, 9, 410,
+ 0, 0, 225, 51, 0, 0, 0, 336, 0, 0,
+ 225, 64, 0, 10, 11, 336, 337, 0, 463, 115,
+ 0, 338, 339, 544, 337, 480, 0, 115, 341, 338,
+ 339, 340, 0, 226, 0, 342, 341, 64, 0, 10,
+ 11, 336, 0, 342, 0, 64, 0, 10, 11, 0,
+ 337, 0, 343, 0, 0, 338, 339, 340, 0, 0,
+ 343, 0, 341, 0, 0, 0, 0, 0, 0, 342,
+ 345, 0, 10, 11, 0, 0, 0, 0, 345, 178,
+ 0, 11, 0, 181, 182, 183, 343, 0, 185, 186,
+ 187, 188, 613, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 0, 0, 345, 177, 178, 11, 179, 0,
+ 181, 182, 183, 0, 0, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 177, 178,
+ 0, 179, 0, 181, 182, 183, 0, 437, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 0, 0, 0, 0, 0, 0, 177, 178,
+ 0, 179, 0, 181, 182, 183, 0, 434, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 177, 178, 0, 179, 0, 181, 182, 183,
+ 0, 527, 185, 186, 187, 188, 189, 190, 191, 192,
+ 193, 194, 195, 196, 197, 198, 177, 178, 0, 179,
+ 0, 181, 182, 183, 0, 661, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 177, 178, 0, 179, 0, 181, 182, 183, 0, 662,
+ 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+ 195, 196, 197, 198, 177, 178, 0, 0, 0, 181,
182, 183, 0, 0, 185, 186, 187, 188, 189, 190,
- 191, 192, 193, 194, 195, 196, 197, 198, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 177, 178, 0,
- 179, 0, 181, 182, 183, 0, 435, 185, 186, 187,
- 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
- 198, 0, 0, 0, 0, 0, 0, 177, 178, 0,
- 179, 0, 181, 182, 183, 0, 432, 185, 186, 187,
- 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
- 198, 177, 178, 0, 179, 0, 181, 182, 183, 0,
- 525, 185, 186, 187, 188, 189, 190, 191, 192, 193,
- 194, 195, 196, 197, 198, 177, 178, 0, 179, 0,
- 181, 182, 183, 0, 659, 185, 186, 187, 188, 189,
- 190, 191, 192, 193, 194, 195, 196, 197, 198, 177,
- 178, 0, 179, 0, 181, 182, 183, 0, 660, 185,
- 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
- 196, 197, 198, 177, 178, 0, 0, 0, 181, 182,
- 183, 0, 0, 185, 186, 187, 188, 189, 190, 191,
- 192, 193, 194, 195, 196, 197, 198, 177, 178, 0,
- 0, 0, 181, 182, 183, 0, 0, 185, 186, 187,
- 188, 0, 190, 191, 192, 193, 194, 195, 196, 197,
- 198
+ 191, 192, 193, 194, 195, 196, 197, 198, 177, 178,
+ 0, 0, 0, 181, 182, 183, 0, 0, 185, 186,
+ 187, 188, 0, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198
};
static const yytype_int16 yycheck[] =
{
- 37, 37, 61, 143, 67, 37, 37, 202, 324, 251,
- 378, 205, 61, 28, 487, 127, 127, 136, 259, 224,
- 144, 133, 322, 148, 61, 454, 446, 268, 31, 61,
- 3, 143, 317, 264, 265, 276, 212, 5, 323, 280,
- 67, 36, 218, 219, 39, 250, 24, 59, 0, 290,
- 45, 1, 5, 25, 3, 1, 20, 37, 35, 3,
- 25, 24, 74, 11, 3, 55, 56, 57, 58, 59,
- 60, 7, 62, 63, 62, 24, 12, 114, 115, 116,
- 24, 62, 114, 115, 116, 35, 62, 68, 7, 35,
- 67, 128, 68, 12, 5, 73, 128, 65, 66, 72,
- 137, 574, 3, 67, 107, 137, 21, 75, 145, 59,
- 173, 160, 65, 145, 63, 152, 60, 67, 51, 63,
- 152, 67, 75, 160, 73, 74, 62, 75, 160, 73,
- 74, 24, 68, 63, 114, 115, 116, 256, 175, 439,
- 425, 136, 427, 175, 62, 390, 173, 142, 128, 68,
- 83, 200, 3, 398, 65, 49, 89, 137, 389, 3,
- 391, 62, 63, 200, 75, 145, 342, 68, 200, 159,
- 160, 644, 152, 24, 350, 24, 24, 606, 383, 599,
- 24, 7, 66, 598, 62, 60, 12, 224, 72, 226,
- 610, 611, 224, 7, 226, 175, 438, 24, 12, 50,
- 75, 517, 3, 62, 53, 242, 221, 244, 524, 68,
- 242, 59, 244, 250, 3, 59, 71, 462, 250, 63,
- 414, 62, 73, 74, 67, 73, 74, 421, 3, 73,
- 74, 473, 59, 127, 66, 272, 62, 652, 433, 654,
- 272, 66, 68, 59, 224, 24, 226, 284, 284, 24,
- 287, 288, 284, 284, 68, 287, 288, 369, 369, 318,
- 505, 24, 242, 59, 244, 441, 385, 379, 379, 318,
- 250, 447, 448, 478, 450, 50, 400, 402, 59, 520,
- 59, 318, 24, 459, 59, 461, 318, 40, 35, 68,
- 53, 44, 272, 24, 73, 74, 59, 665, 73, 74,
- 62, 74, 62, 64, 284, 68, 68, 287, 288, 59,
- 73, 74, 59, 24, 208, 209, 561, 633, 24, 40,
- 67, 59, 63, 44, 361, 35, 375, 67, 24, 361,
- 75, 73, 74, 578, 579, 577, 373, 9, 375, 375,
- 60, 373, 53, 375, 375, 17, 383, 72, 59, 21,
- 387, 383, 59, 59, 417, 387, 35, 72, 603, 31,
- 32, 59, 73, 74, 60, 63, 571, 73, 74, 428,
- 407, 408, 3, 71, 550, 407, 408, 73, 74, 428,
- 59, 361, 558, 24, 35, 35, 60, 281, 67, 35,
- 385, 428, 64, 373, 588, 375, 428, 291, 393, 594,
- 8, 60, 397, 383, 62, 35, 35, 387, 59, 59,
- 75, 94, 95, 59, 97, 98, 67, 67, 59, 62,
- 60, 67, 471, 24, 59, 601, 602, 407, 408, 59,
- 5, 65, 73, 74, 471, 471, 24, 67, 487, 471,
- 471, 478, 62, 62, 24, 20, 478, 22, 497, 72,
- 487, 487, 24, 28, 24, 487, 487, 569, 569, 3,
- 497, 36, 3, 62, 39, 497, 62, 8, 43, 62,
- 45, 59, 67, 367, 368, 65, 17, 66, 53, 54,
- 60, 22, 23, 24, 521, 73, 74, 59, 29, 521,
- 60, 471, 67, 73, 74, 34, 24, 95, 478, 97,
- 98, 73, 74, 73, 74, 44, 59, 487, 67, 48,
- 71, 67, 406, 8, 53, 54, 55, 56, 59, 65,
- 62, 584, 62, 60, 664, 574, 420, 62, 62, 212,
- 71, 59, 73, 74, 571, 218, 219, 574, 574, 571,
- 60, 521, 574, 574, 60, 73, 74, 60, 63, 68,
- 60, 68, 664, 128, 35, 60, 60, 60, 60, 68,
- 60, 136, 60, 75, 75, 624, 60, 142, 3, 144,
- 36, 68, 62, 148, 60, 624, 72, 62, 60, 59,
- 59, 49, 75, 66, 60, 60, 60, 624, 8, 62,
- 60, 571, 624, 61, 574, 644, 64, 17, 173, 60,
- 60, 59, 22, 23, 24, 59, 68, 644, 644, 29,
- 62, 49, 644, 644, 62, 72, 36, 68, 62, 59,
- 8, 60, 68, 60, 60, 68, 201, 14, 62, 17,
- 72, 60, 207, 53, 22, 23, 24, 60, 213, 59,
- 68, 29, 60, 60, 22, 65, 221, 31, 36, 224,
- 584, 71, 335, 73, 74, 75, 645, 510, 526, 342,
- 235, 526, 244, 39, 644, 53, 282, 350, 244, 160,
- 393, 59, 385, 373, 22, 250, 251, 65, 214, 497,
- 335, 335, 464, 71, 34, 73, 74, 75, 38, 39,
- 40, 442, 605, 43, 44, 45, 46, 601, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, 282, 176, 177,
- 178, 179, 460, 181, 182, 183, -1, 185, 186, 187,
+ 37, 37, 61, 143, 67, 37, 37, 202, 380, 205,
+ 224, 148, 61, 448, 144, 127, 28, 489, 456, 67,
+ 127, 133, 252, 325, 61, 114, 115, 116, 136, 61,
+ 31, 143, 323, 36, 3, 51, 39, 251, 11, 5,
+ 24, 260, 45, 49, 35, 392, 7, 25, 137, 35,
+ 269, 12, 5, 400, 265, 266, 145, 37, 277, 3,
+ 1, 35, 281, 152, 318, 0, 24, 83, 59, 62,
+ 324, 3, 291, 89, 25, 68, 67, 114, 115, 116,
+ 24, 67, 114, 115, 116, 59, 175, 3, 24, 73,
+ 1, 128, 24, 67, 35, 53, 128, 20, 3, 65,
+ 137, 62, 75, 72, 576, 137, 107, 68, 145, 75,
+ 173, 160, 65, 145, 62, 152, 60, 464, 59, 63,
+ 152, 127, 75, 160, 35, 173, 67, 59, 160, 73,
+ 74, 63, 600, 136, 114, 115, 116, 226, 175, 142,
+ 7, 73, 74, 175, 67, 12, 62, 63, 128, 257,
+ 441, 200, 68, 62, 243, 3, 67, 137, 3, 68,
+ 507, 5, 24, 200, 21, 145, 601, 63, 200, 24,
+ 608, 385, 152, 427, 646, 429, 24, 612, 613, 24,
+ 391, 59, 393, 59, 273, 63, 654, 224, 656, 226,
+ 62, 3, 224, 71, 226, 175, 285, 59, 74, 288,
+ 289, 68, 208, 209, 62, 50, 243, 3, 245, 221,
+ 440, 243, 24, 245, 251, 63, 563, 519, 71, 251,
+ 416, 65, 66, 3, 526, 73, 74, 423, 73, 74,
+ 62, 75, 67, 580, 581, 66, 273, 7, 50, 24,
+ 435, 273, 12, 66, 224, 475, 226, 59, 285, 285,
+ 7, 288, 289, 285, 285, 12, 288, 289, 605, 371,
+ 319, 73, 74, 243, 371, 245, 480, 404, 24, 381,
+ 319, 251, 402, 362, 381, 60, 282, 59, 59, 387,
+ 74, 60, 319, 35, 212, 24, 292, 319, 73, 74,
+ 218, 219, 62, 273, 59, 667, 75, 40, 68, 35,
+ 389, 44, 40, 522, 60, 285, 44, 59, 288, 289,
+ 24, 68, 24, 66, 9, 67, 24, 73, 74, 72,
+ 409, 410, 17, 59, 64, 362, 21, 62, 377, 59,
+ 362, 67, 63, 635, 73, 74, 31, 32, 375, 24,
+ 377, 377, 59, 375, 67, 377, 377, 59, 385, 579,
+ 24, 59, 389, 385, 24, 75, 419, 389, 60, 573,
+ 68, 73, 74, 369, 370, 73, 74, 35, 53, 64,
+ 62, 430, 409, 410, 59, 72, 68, 409, 410, 53,
+ 62, 430, 362, 68, 387, 59, 68, 59, 73, 74,
+ 60, 72, 395, 430, 590, 375, 399, 377, 430, 73,
+ 74, 596, 408, 73, 74, 385, 3, 94, 95, 389,
+ 97, 98, 60, 8, 60, 343, 422, 35, 95, 24,
+ 97, 98, 62, 351, 473, 24, 75, 60, 62, 409,
+ 410, 24, 5, 59, 523, 62, 473, 473, 24, 62,
+ 489, 473, 473, 480, 72, 3, 62, 20, 480, 22,
+ 499, 62, 489, 489, 59, 28, 65, 489, 489, 571,
+ 59, 67, 499, 36, 571, 35, 39, 499, 73, 74,
+ 43, 62, 45, 59, 73, 74, 65, 59, 66, 24,
+ 53, 54, 67, 67, 71, 8, 523, 73, 74, 59,
+ 65, 523, 60, 473, 67, 62, 62, 67, 62, 24,
+ 480, 62, 35, 55, 56, 57, 58, 59, 60, 489,
+ 62, 63, 60, 60, 59, 443, 60, 63, 35, 68,
+ 60, 449, 450, 586, 452, 212, 666, 576, 73, 74,
+ 68, 218, 219, 461, 59, 463, 573, 34, 60, 576,
+ 576, 573, 59, 523, 576, 576, 60, 44, 73, 74,
+ 67, 48, 60, 36, 666, 128, 53, 54, 55, 56,
+ 75, 68, 75, 136, 60, 3, 60, 626, 60, 142,
+ 8, 144, 60, 68, 3, 148, 62, 626, 60, 17,
+ 60, 72, 75, 62, 22, 23, 24, 59, 66, 626,
+ 60, 29, 60, 573, 626, 60, 576, 646, 62, 60,
+ 173, 60, 8, 60, 59, 59, 59, 159, 160, 646,
+ 646, 17, 68, 62, 646, 646, 22, 23, 24, 62,
+ 72, 59, 68, 29, 552, 49, 62, 59, 201, 60,
+ 36, 68, 560, 71, 207, 73, 74, 60, 68, 60,
+ 213, 14, 62, 60, 72, 60, 60, 53, 221, 336,
+ 60, 224, 68, 4, 5, 31, 343, 22, 647, 65,
+ 586, 512, 235, 528, 351, 71, 646, 528, 74, 245,
+ 283, 39, 214, 245, 395, 603, 604, 387, 251, 252,
+ 22, 375, 33, 34, 160, 36, 37, 38, 39, 40,
+ 499, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 8, 336, 466, 607,
+ 283, 49, 444, 603, 65, 17, 336, 462, -1, -1,
+ 22, 23, 24, 61, 75, -1, 64, 29, 213, -1,
+ -1, -1, -1, -1, 36, -1, -1, -1, -1, -1,
+ 3, -1, -1, -1, -1, 8, -1, -1, 11, -1,
+ 323, 53, -1, -1, 17, -1, 443, 59, -1, 22,
+ 23, 24, 449, 450, -1, 452, 29, -1, -1, 71,
+ -1, 344, 74, 36, 461, -1, 463, -1, -1, -1,
+ -1, -1, 355, -1, -1, -1, 49, 50, -1, 52,
+ 53, -1, -1, 56, -1, -1, 59, -1, -1, -1,
+ -1, -1, 375, -1, 377, -1, 69, 70, 71, 382,
+ 73, 74, 385, -1, 387, -1, -1, -1, -1, -1,
+ -1, -1, 395, -1, -1, -1, 399, -1, -1, 402,
+ -1, 404, -1, -1, -1, -1, -1, -1, 176, 177,
+ 178, 179, -1, 181, 182, 183, 419, 185, 186, 187,
188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
- 198, -1, 200, -1, 202, 213, 204, -1, -1, -1,
- 208, 209, 210, -1, -1, -1, -1, 322, -1, -1,
- 114, 115, 116, -1, -1, -1, -1, -1, 441, -1,
- -1, -1, -1, -1, 447, 448, -1, 450, 343, -1,
- -1, 8, -1, 137, -1, 8, 459, -1, 461, 354,
- 17, 145, -1, -1, 17, 22, 23, 24, 152, 22,
- 23, 24, 29, -1, -1, -1, 29, -1, 373, 36,
- 375, -1, -1, 36, -1, 380, -1, -1, 383, -1,
- 385, 175, -1, 281, -1, -1, 53, -1, 393, -1,
- 53, -1, 397, 291, -1, 400, 59, 402, 65, -1,
- -1, -1, -1, -1, 71, -1, -1, 74, 71, -1,
- 73, 74, 417, -1, -1, -1, 314, -1, -1, -1,
- 318, -1, -1, -1, -1, -1, 324, -1, -1, -1,
- -1, -1, 226, 438, 439, -1, -1, 550, -1, -1,
- -1, 446, 447, -1, 449, 558, -1, -1, 242, 454,
- -1, -1, 565, -1, -1, 460, -1, -1, 463, 464,
- -1, -1, -1, -1, -1, -1, -1, -1, 473, 367,
- 368, -1, -1, 478, -1, -1, -1, -1, 272, -1,
- -1, 34, -1, -1, -1, 598, -1, -1, 601, 602,
- 284, 44, -1, 287, 288, 48, 49, 50, 51, 52,
- 53, 54, 55, 56, -1, -1, -1, -1, 406, -1,
- -1, -1, -1, 4, 5, -1, -1, -1, -1, -1,
- -1, -1, 420, -1, -1, -1, -1, -1, -1, -1,
- 428, -1, -1, -1, -1, 433, -1, -1, -1, 652,
- -1, 654, 33, 34, -1, 36, 37, 38, 39, 40,
- -1, 42, 43, 44, 45, 46, 47, 48, 49, 50,
- 51, 52, 53, 54, 55, 56, 571, 361, -1, -1,
- -1, -1, 577, -1, 65, -1, 474, 475, -1, 584,
- -1, -1, -1, -1, 75, -1, -1, -1, -1, -1,
- -1, -1, -1, 387, 599, -1, 601, -1, -1, 497,
- 605, 606, -1, -1, -1, 610, 611, -1, -1, -1,
- -1, -1, -1, 407, 408, -1, -1, -1, -1, 517,
- -1, -1, -1, -1, -1, -1, 524, 525, 526, 0,
+ 198, -1, 200, -1, 202, 552, 204, 440, 441, -1,
+ 208, 209, 210, 560, -1, 448, 449, -1, 451, -1,
+ 567, -1, -1, 456, -1, 3, -1, -1, -1, 462,
+ 8, -1, 465, 466, -1, -1, -1, -1, 236, 17,
+ -1, -1, 475, -1, 22, 23, 24, 480, 26, -1,
+ -1, 29, -1, 600, -1, -1, 603, 604, 36, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 49, 50, -1, 52, 53, -1, -1, 56, -1,
+ -1, 59, -1, -1, 282, -1, -1, -1, -1, -1,
+ -1, 69, 70, 71, 292, 73, 74, 8, -1, -1,
+ -1, -1, -1, -1, -1, -1, 17, 654, -1, 656,
+ -1, 22, 23, 24, -1, -1, -1, 315, 29, -1,
+ -1, 319, 8, -1, -1, 36, -1, 325, -1, -1,
+ -1, 17, -1, -1, -1, -1, 22, 23, 24, -1,
+ 573, -1, 53, 29, -1, -1, 579, -1, 59, -1,
+ 36, -1, -1, 586, 65, -1, -1, -1, -1, -1,
+ 71, -1, 73, 74, 75, -1, -1, 53, 601, -1,
+ 603, 369, 370, 59, 607, 608, -1, -1, -1, 612,
+ 613, -1, -1, -1, -1, 71, -1, 73, 74, 0,
1, -1, 3, -1, -1, 6, -1, 8, 9, 10,
-1, -1, 13, -1, 15, 16, 17, 18, 19, 20,
- -1, 22, 23, 24, -1, -1, 27, 28, 29, 30,
- 31, 32, -1, -1, -1, 36, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 49, 50,
+ 408, 22, 23, 24, -1, -1, 27, 28, 29, 30,
+ 31, 32, -1, -1, 422, 36, -1, -1, -1, -1,
+ -1, -1, 430, -1, -1, -1, -1, 435, 49, 50,
-1, 52, 53, -1, -1, 56, -1, -1, 59, -1,
- -1, 62, -1, -1, -1, -1, 594, -1, 69, 70,
- 71, -1, 73, 74, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 621, 622, -1, 624, 521, -1, -1,
- -1, 1, -1, 3, -1, 633, 6, 7, 8, 9,
- 10, -1, 12, 13, -1, 15, 16, 17, 18, 19,
- 20, -1, 22, 23, 24, -1, -1, 27, 28, 29,
- 30, 31, 32, -1, -1, -1, 36, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 49,
- 50, -1, 52, 53, -1, -1, 56, -1, -1, 59,
- -1, -1, 62, -1, -1, -1, -1, 67, 68, 69,
- 70, 71, -1, 73, 74, 1, -1, 3, -1, -1,
- 6, -1, 8, 9, 10, -1, -1, 13, -1, 15,
- 16, 17, 18, 19, 20, -1, 22, 23, 24, -1,
- -1, 27, 28, 29, 30, 31, 32, -1, -1, -1,
- 36, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 49, 50, -1, 52, 53, -1, -1,
- 56, -1, 3, 59, -1, -1, 62, 8, -1, -1,
- 11, 67, 68, 69, 70, 71, 17, 73, 74, -1,
- -1, 22, 23, 24, -1, -1, -1, -1, 29, -1,
- -1, -1, -1, -1, -1, 36, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3, -1, -1, 49, 50,
- 8, 52, 53, -1, -1, 56, -1, -1, 59, 17,
- -1, -1, -1, -1, 22, 23, 24, -1, 69, 70,
- 71, 29, 73, 74, -1, -1, -1, -1, 36, -1,
+ -1, 62, -1, -1, 34, -1, -1, -1, 69, 70,
+ 71, -1, 73, 74, 44, -1, -1, -1, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, -1, 476, 477,
+ -1, -1, -1, -1, -1, -1, -1, -1, 1, -1,
+ 3, -1, -1, 6, 7, 8, 9, 10, -1, 12,
+ 13, 499, 15, 16, 17, 18, 19, 20, -1, 22,
+ 23, 24, -1, -1, 27, 28, 29, 30, 31, 32,
+ -1, 519, -1, 36, -1, -1, -1, -1, 526, 527,
+ 528, -1, -1, -1, -1, -1, 49, 50, -1, 52,
+ 53, -1, -1, 56, -1, -1, 59, -1, -1, 62,
+ -1, -1, -1, -1, 67, 68, 69, 70, 71, -1,
+ 73, 74, -1, -1, -1, -1, 1, -1, 3, -1,
+ -1, 6, -1, 8, 9, 10, -1, -1, 13, -1,
+ 15, 16, 17, 18, 19, 20, -1, 22, 23, 24,
+ -1, -1, 27, 28, 29, 30, 31, 32, 596, -1,
+ -1, 36, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 49, 50, -1, 52, 53, -1,
+ -1, 56, -1, -1, 59, 623, 624, 62, 626, -1,
+ -1, -1, 67, 68, 69, 70, 71, 635, 73, 74,
+ 3, -1, -1, -1, -1, 8, -1, -1, -1, -1,
+ -1, -1, -1, -1, 17, -1, 8, -1, -1, 22,
+ 23, 24, -1, -1, -1, 17, 29, -1, -1, -1,
+ 22, 23, 24, 36, -1, -1, -1, 29, -1, -1,
+ -1, -1, -1, -1, 36, -1, 49, 50, -1, 52,
+ 53, -1, -1, 56, -1, 3, 59, 60, -1, -1,
+ 8, 53, -1, -1, -1, -1, 69, 70, 71, 17,
+ 73, 74, -1, -1, 22, 23, 24, -1, -1, 71,
+ -1, 29, 74, -1, -1, -1, -1, -1, 36, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 49, 50, -1, 52, 53, -1, -1, 56, -1,
- 3, 59, 60, -1, -1, 8, -1, -1, -1, -1,
+ 3, 59, -1, -1, -1, 8, -1, -1, -1, 67,
-1, 69, 70, 71, 17, 73, 74, -1, -1, 22,
- 23, 24, -1, -1, -1, -1, 29, -1, -1, -1,
+ 23, 24, -1, -1, -1, -1, 29, -1, 31, -1,
-1, -1, -1, 36, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 49, 50, -1, 52,
53, -1, -1, 56, -1, 3, 59, -1, -1, -1,
- 8, -1, -1, -1, 67, -1, 69, 70, 71, 17,
- 73, 74, -1, -1, 22, 23, 24, -1, -1, -1,
- -1, 29, -1, 31, -1, -1, -1, -1, 36, -1,
+ 8, -1, -1, -1, -1, -1, 69, 70, 71, 17,
+ 73, 74, -1, -1, 22, 23, 24, -1, 26, -1,
+ -1, 29, -1, -1, -1, -1, -1, -1, 36, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 49, 50, -1, 52, 53, -1, -1, 56, -1,
3, 59, -1, -1, -1, 8, -1, -1, -1, -1,
-1, 69, 70, 71, 17, 73, 74, -1, -1, 22,
23, 24, -1, 26, -1, -1, 29, -1, -1, -1,
-1, -1, -1, 36, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 49, 50, -1, 52,
- 53, -1, -1, 56, -1, 3, 59, -1, -1, -1,
- 8, -1, -1, -1, -1, -1, 69, 70, 71, 17,
- 73, 74, -1, -1, 22, 23, 24, -1, 26, -1,
- -1, 29, -1, -1, -1, -1, -1, -1, 36, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 3, -1,
- -1, 49, 50, 8, 52, 53, -1, -1, 56, -1,
- -1, 59, 17, -1, -1, -1, -1, 22, 23, 24,
- -1, 69, 70, 71, 29, 73, 74, -1, -1, -1,
+ -1, -1, -1, 3, -1, -1, 49, 50, 8, 52,
+ 53, -1, -1, 56, -1, -1, 59, 17, -1, -1,
+ -1, -1, 22, 23, 24, -1, 69, 70, 71, 29,
+ 73, 74, -1, -1, -1, -1, 36, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 49,
+ 50, -1, 52, 53, -1, -1, 56, -1, 3, 59,
+ -1, -1, -1, 8, -1, -1, -1, 67, -1, 69,
+ 70, 71, 17, 73, 74, -1, -1, 22, 23, 24,
+ -1, -1, -1, -1, 29, -1, -1, -1, -1, -1,
-1, 36, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 49, 50, -1, 52, 53, -1,
- -1, 56, -1, 3, 59, -1, -1, -1, 8, -1,
- -1, -1, 67, -1, 69, 70, 71, 17, 73, 74,
- -1, -1, 22, 23, 24, -1, -1, -1, -1, 29,
- -1, -1, -1, -1, -1, -1, 36, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3, -1, -1, 49,
- 50, 8, 52, 53, -1, -1, 56, -1, -1, 59,
- 17, -1, -1, -1, -1, 22, 23, 24, -1, 69,
- 70, 71, 29, 73, 74, -1, -1, -1, -1, 36,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 3,
- -1, -1, 49, 50, 8, 52, 53, -1, -1, 56,
- -1, -1, 59, 17, -1, -1, -1, -1, 22, 23,
- 24, -1, 69, 70, 71, 29, 73, 74, -1, -1,
- -1, -1, 36, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 49, 50, 8, 52, 53,
- -1, -1, 56, -1, -1, 59, 17, -1, -1, -1,
- -1, 22, 23, 24, -1, 69, 70, 71, 29, 73,
- 74, -1, -1, 8, -1, 36, 11, -1, -1, -1,
- -1, 8, 17, -1, -1, -1, -1, 22, 23, 24,
- 17, -1, 53, -1, 29, 22, 23, 24, 59, -1,
- -1, 36, 29, -1, -1, -1, 8, -1, -1, 36,
- 71, -1, 73, 74, 75, 17, -1, -1, 53, -1,
- 22, 23, 24, -1, 59, -1, 53, 29, -1, -1,
- -1, -1, 59, -1, 36, -1, 71, -1, 73, 74,
- 8, -1, -1, -1, 71, -1, 73, 74, -1, 17,
- -1, 53, -1, -1, 22, 23, 24, 59, -1, -1,
- -1, 29, -1, -1, -1, 8, -1, -1, 36, 71,
- -1, 73, 74, 8, 17, -1, -1, -1, -1, 22,
- 23, 24, 17, -1, -1, 53, 29, 22, 23, 24,
- -1, 59, -1, 36, 29, -1, -1, -1, -1, 8,
- -1, 36, 11, 71, -1, 73, 74, -1, 17, -1,
- 53, -1, -1, 22, 23, 24, 59, -1, 53, -1,
- 29, -1, -1, -1, 59, -1, 8, 36, 71, -1,
- 73, 74, -1, -1, -1, 17, 71, -1, -1, 74,
- 22, 23, 24, -1, 53, -1, -1, 29, -1, -1,
- -1, -1, 8, -1, 36, -1, -1, -1, -1, -1,
- 8, 17, 71, -1, -1, 74, 22, 23, 24, 17,
- -1, 53, -1, 29, 22, 23, 24, -1, -1, -1,
- 36, 29, -1, -1, -1, -1, -1, -1, 36, 71,
- -1, 73, 74, -1, -1, -1, -1, 53, -1, -1,
- -1, -1, -1, 59, -1, 53, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 71, -1, -1, 74, -1,
- -1, -1, -1, 71, 33, 34, 74, 36, -1, 38,
+ -1, 3, -1, -1, 49, 50, 8, 52, 53, -1,
+ -1, 56, -1, -1, 59, 17, -1, -1, -1, -1,
+ 22, 23, 24, -1, 69, 70, 71, 29, 73, 74,
+ -1, -1, -1, -1, 36, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3, -1, -1, 49, 50, 8,
+ 52, 53, -1, -1, 56, -1, -1, 59, 17, -1,
+ -1, -1, -1, 22, 23, 24, -1, 69, 70, 71,
+ 29, 73, 74, -1, -1, -1, -1, 36, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 49, 50, 8, 52, 53, -1, -1, 56, -1, -1,
+ 59, 17, -1, -1, -1, -1, 22, 23, 24, -1,
+ 69, 70, 71, 29, 73, 74, -1, 8, -1, -1,
+ 36, -1, -1, -1, -1, 8, 17, -1, 11, -1,
+ -1, 22, 23, 24, 17, -1, -1, 53, 29, 22,
+ 23, 24, -1, 59, -1, 36, 29, -1, -1, 65,
+ -1, 8, -1, 36, -1, 71, -1, 73, 74, 75,
+ 17, -1, 53, -1, -1, 22, 23, 24, 59, -1,
+ 53, -1, 29, -1, -1, -1, 59, -1, 8, 36,
+ 71, -1, 73, 74, 75, -1, -1, 17, 71, -1,
+ 73, 74, 22, 23, 24, -1, 53, -1, -1, 29,
+ -1, -1, 59, -1, 8, -1, 36, -1, -1, -1,
+ -1, -1, 8, 17, 71, -1, 73, 74, 22, 23,
+ 24, 17, -1, 53, -1, 29, 22, 23, 24, 59,
+ -1, -1, 36, 29, -1, -1, -1, 8, -1, -1,
+ 36, 71, -1, 73, 74, 8, 17, -1, 11, 53,
+ -1, 22, 23, 24, 17, 59, -1, 53, 29, 22,
+ 23, 24, -1, 59, -1, 36, 29, 71, -1, 73,
+ 74, 8, -1, 36, -1, 71, -1, 73, 74, -1,
+ 17, -1, 53, -1, -1, 22, 23, 24, -1, -1,
+ 53, -1, 29, -1, -1, -1, -1, -1, -1, 36,
+ 71, -1, 73, 74, -1, -1, -1, -1, 71, 34,
+ -1, 74, -1, 38, 39, 40, 53, -1, 43, 44,
+ 45, 46, 59, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, -1, -1, 71, 33, 34, 74, 36, -1,
+ 38, 39, 40, -1, -1, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 33, 34,
+ -1, 36, -1, 38, 39, 40, -1, 75, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, -1, -1, -1, -1, -1, -1, 33, 34,
+ -1, 36, -1, 38, 39, 40, -1, 72, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 33, 34, -1, 36, -1, 38, 39, 40,
+ -1, 66, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 33, 34, -1, 36,
+ -1, 38, 39, 40, -1, 66, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 33, 34, -1, 36, -1, 38, 39, 40, -1, 66,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 33, 34, -1, -1, -1, 38,
39, 40, -1, -1, 43, 44, 45, 46, 47, 48,
- 49, 50, 51, 52, 53, 54, 55, 56, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 33, 34, -1,
- 36, -1, 38, 39, 40, -1, 75, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 56, -1, -1, -1, -1, -1, -1, 33, 34, -1,
- 36, -1, 38, 39, 40, -1, 72, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 33, 34, -1, 36, -1, 38, 39, 40, -1,
- 66, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 33, 34, -1, 36, -1,
- 38, 39, 40, -1, 66, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 33,
- 34, -1, 36, -1, 38, 39, 40, -1, 66, 43,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 33, 34, -1, -1, -1, 38, 39,
- 40, -1, -1, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, 33, 34, -1,
- -1, -1, 38, 39, 40, -1, -1, 43, 44, 45,
- 46, -1, 48, 49, 50, 51, 52, 53, 54, 55,
- 56
+ 49, 50, 51, 52, 53, 54, 55, 56, 33, 34,
+ -1, -1, -1, 38, 39, 40, -1, -1, 43, 44,
+ 45, 46, -1, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -1528,50 +1514,50 @@ static const yytype_uint8 yystos[] =
59, 63, 71, 66, 59, 137, 1, 137, 5, 65,
75, 142, 200, 59, 160, 200, 24, 200, 201, 200,
64, 62, 190, 88, 59, 36, 59, 146, 152, 153,
- 154, 155, 161, 146, 146, 63, 98, 107, 108, 109,
- 186, 194, 11, 136, 141, 145, 146, 177, 178, 179,
- 59, 67, 162, 112, 194, 24, 59, 68, 138, 171,
- 173, 175, 146, 35, 53, 59, 68, 138, 170, 172,
- 173, 174, 184, 112, 60, 97, 169, 146, 60, 93,
- 167, 65, 75, 146, 8, 147, 60, 72, 72, 60,
- 94, 65, 146, 126, 126, 126, 126, 126, 126, 126,
+ 154, 155, 161, 146, 146, 63, 26, 98, 107, 108,
+ 109, 186, 194, 11, 136, 141, 145, 146, 177, 178,
+ 179, 59, 67, 162, 112, 194, 24, 59, 68, 138,
+ 171, 173, 175, 146, 35, 53, 59, 68, 138, 170,
+ 172, 173, 174, 184, 112, 60, 97, 169, 146, 60,
+ 93, 167, 65, 75, 146, 8, 147, 60, 72, 72,
+ 60, 94, 65, 146, 126, 126, 126, 126, 126, 126,
126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
- 126, 126, 126, 126, 130, 60, 135, 187, 59, 141,
- 126, 192, 182, 126, 130, 1, 67, 91, 100, 180,
- 181, 183, 186, 186, 126, 8, 17, 22, 23, 24,
- 29, 36, 53, 65, 71, 142, 202, 204, 205, 206,
- 141, 207, 215, 162, 59, 3, 202, 202, 83, 60,
- 179, 8, 146, 60, 141, 35, 105, 5, 65, 62,
- 146, 136, 145, 75, 191, 60, 179, 183, 115, 62,
- 63, 24, 173, 59, 176, 62, 190, 72, 104, 59,
- 174, 53, 174, 62, 190, 3, 198, 75, 146, 123,
- 62, 190, 62, 190, 186, 139, 65, 36, 59, 146,
- 152, 153, 154, 161, 67, 146, 146, 62, 190, 186,
- 65, 67, 126, 131, 132, 188, 189, 11, 75, 191,
- 31, 135, 72, 66, 180, 75, 191, 189, 101, 62,
- 68, 36, 59, 203, 204, 206, 59, 67, 71, 67,
- 8, 202, 3, 50, 59, 141, 212, 213, 3, 72,
- 65, 11, 202, 60, 75, 62, 195, 215, 62, 62,
- 62, 60, 60, 106, 26, 26, 194, 177, 59, 141,
- 151, 152, 153, 154, 155, 161, 163, 60, 68, 105,
- 194, 141, 60, 179, 175, 68, 146, 7, 12, 68,
- 99, 102, 174, 198, 174, 60, 172, 68, 138, 198,
- 35, 97, 60, 93, 60, 186, 146, 130, 94, 95,
- 168, 185, 60, 186, 130, 66, 75, 191, 68, 191,
- 135, 60, 60, 60, 192, 60, 68, 183, 180, 202,
- 205, 195, 24, 141, 142, 197, 202, 209, 217, 202,
- 141, 196, 208, 216, 202, 3, 212, 62, 72, 202,
- 213, 202, 198, 141, 207, 60, 183, 126, 126, 62,
- 179, 59, 163, 116, 60, 187, 66, 103, 60, 60,
- 198, 104, 60, 189, 62, 190, 146, 189, 67, 126,
- 133, 131, 132, 60, 66, 72, 68, 60, 60, 59,
- 68, 62, 72, 202, 68, 62, 49, 202, 62, 198,
- 59, 59, 202, 210, 211, 68, 194, 60, 179, 119,
- 163, 5, 65, 66, 75, 183, 198, 198, 68, 68,
- 95, 60, 68, 130, 192, 210, 195, 209, 202, 198,
- 208, 212, 195, 195, 60, 14, 117, 120, 126, 126,
- 189, 72, 60, 60, 60, 60, 163, 20, 100, 66,
- 66, 68, 210, 210, 118, 112, 105
+ 126, 126, 126, 126, 126, 130, 60, 135, 187, 59,
+ 141, 126, 192, 182, 126, 130, 1, 67, 91, 100,
+ 180, 181, 183, 186, 186, 126, 8, 17, 22, 23,
+ 24, 29, 36, 53, 65, 71, 142, 202, 204, 205,
+ 206, 141, 207, 215, 162, 59, 3, 202, 202, 83,
+ 60, 179, 8, 146, 60, 141, 126, 35, 105, 5,
+ 65, 62, 146, 136, 145, 75, 191, 60, 179, 183,
+ 115, 62, 63, 24, 173, 59, 176, 62, 190, 72,
+ 104, 59, 174, 53, 174, 62, 190, 3, 198, 75,
+ 146, 123, 62, 190, 62, 190, 186, 139, 65, 36,
+ 59, 146, 152, 153, 154, 161, 67, 146, 146, 62,
+ 190, 186, 65, 67, 126, 131, 132, 188, 189, 11,
+ 75, 191, 31, 135, 72, 66, 180, 75, 191, 189,
+ 101, 62, 68, 36, 59, 203, 204, 206, 59, 67,
+ 71, 67, 8, 202, 3, 50, 59, 141, 212, 213,
+ 3, 72, 65, 11, 202, 60, 75, 62, 195, 215,
+ 62, 62, 62, 60, 60, 106, 26, 26, 194, 177,
+ 59, 141, 151, 152, 153, 154, 155, 161, 163, 60,
+ 68, 105, 194, 141, 60, 179, 175, 68, 146, 7,
+ 12, 68, 99, 102, 174, 198, 174, 60, 172, 68,
+ 138, 198, 35, 97, 60, 93, 60, 186, 146, 130,
+ 94, 95, 168, 185, 60, 186, 130, 66, 75, 191,
+ 68, 191, 135, 60, 60, 60, 192, 60, 68, 183,
+ 180, 202, 205, 195, 24, 141, 142, 197, 202, 209,
+ 217, 202, 141, 196, 208, 216, 202, 3, 212, 62,
+ 72, 202, 213, 202, 198, 141, 207, 60, 183, 126,
+ 126, 62, 179, 59, 163, 116, 60, 187, 66, 103,
+ 60, 60, 198, 104, 60, 189, 62, 190, 146, 189,
+ 67, 126, 133, 131, 132, 60, 66, 72, 68, 60,
+ 60, 59, 68, 62, 72, 202, 68, 62, 49, 202,
+ 62, 198, 59, 59, 202, 210, 211, 68, 194, 60,
+ 179, 119, 163, 5, 65, 66, 75, 183, 198, 198,
+ 68, 68, 95, 60, 68, 130, 192, 210, 195, 209,
+ 202, 198, 208, 212, 195, 195, 60, 14, 117, 120,
+ 126, 126, 189, 72, 60, 60, 60, 60, 163, 20,
+ 100, 66, 66, 68, 210, 210, 118, 112, 105
};
#define yyerrok (yyerrstatus = 0)
@@ -2795,20 +2781,22 @@ yyreduce:
#line 461 "go.y"
{
(yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1));
+ (yyval.node)->implicit = 1;
(yyval.node)->etype = OADD;
}
break;
case 55:
-#line 466 "go.y"
+#line 467 "go.y"
{
(yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1));
+ (yyval.node)->implicit = 1;
(yyval.node)->etype = OSUB;
}
break;
case 56:
-#line 473 "go.y"
+#line 475 "go.y"
{
Node *n, *nn;
@@ -2831,7 +2819,7 @@ yyreduce:
break;
case 57:
-#line 493 "go.y"
+#line 495 "go.y"
{
Node *n;
@@ -2852,7 +2840,7 @@ yyreduce:
break;
case 58:
-#line 511 "go.y"
+#line 513 "go.y"
{
// will be converted to OCASE
// right will point to next case
@@ -2864,7 +2852,7 @@ yyreduce:
break;
case 59:
-#line 520 "go.y"
+#line 522 "go.y"
{
Node *n, *nn;
@@ -2883,14 +2871,14 @@ yyreduce:
break;
case 60:
-#line 538 "go.y"
+#line 540 "go.y"
{
markdcl();
}
break;
case 61:
-#line 542 "go.y"
+#line 544 "go.y"
{
if((yyvsp[(3) - (4)].list) == nil)
(yyval.node) = nod(OEMPTY, N, N);
@@ -2901,7 +2889,7 @@ yyreduce:
break;
case 62:
-#line 552 "go.y"
+#line 554 "go.y"
{
// If the last token read by the lexer was consumed
// as part of the case, clear it (parser has cleared yychar).
@@ -2915,7 +2903,7 @@ yyreduce:
break;
case 63:
-#line 563 "go.y"
+#line 565 "go.y"
{
int last;
@@ -2937,28 +2925,28 @@ yyreduce:
break;
case 64:
-#line 583 "go.y"
+#line 585 "go.y"
{
(yyval.list) = nil;
}
break;
case 65:
-#line 587 "go.y"
+#line 589 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node));
}
break;
case 66:
-#line 593 "go.y"
+#line 595 "go.y"
{
markdcl();
}
break;
case 67:
-#line 597 "go.y"
+#line 599 "go.y"
{
(yyval.list) = (yyvsp[(3) - (4)].list);
popdcl();
@@ -2966,7 +2954,7 @@ yyreduce:
break;
case 68:
-#line 604 "go.y"
+#line 606 "go.y"
{
(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2975,7 +2963,7 @@ yyreduce:
break;
case 69:
-#line 610 "go.y"
+#line 612 "go.y"
{
(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2987,6 +2975,14 @@ yyreduce:
case 70:
#line 619 "go.y"
{
+ (yyval.node) = nod(ORANGE, N, (yyvsp[(2) - (2)].node));
+ (yyval.node)->etype = 0; // := flag
+ }
+ break;
+
+ case 71:
+#line 626 "go.y"
+ {
// init ; test ; incr
if((yyvsp[(5) - (5)].node) != N && (yyvsp[(5) - (5)].node)->colas != 0)
yyerror("cannot declare in the for-increment");
@@ -2998,8 +2994,8 @@ yyreduce:
}
break;
- case 71:
-#line 630 "go.y"
+ case 72:
+#line 637 "go.y"
{
// normal test
(yyval.node) = nod(OFOR, N, N);
@@ -3007,31 +3003,31 @@ yyreduce:
}
break;
- case 73:
-#line 639 "go.y"
+ case 74:
+#line 646 "go.y"
{
(yyval.node) = (yyvsp[(1) - (2)].node);
(yyval.node)->nbody = concat((yyval.node)->nbody, (yyvsp[(2) - (2)].list));
}
break;
- case 74:
-#line 646 "go.y"
+ case 75:
+#line 653 "go.y"
{
markdcl();
}
break;
- case 75:
-#line 650 "go.y"
+ case 76:
+#line 657 "go.y"
{
(yyval.node) = (yyvsp[(3) - (3)].node);
popdcl();
}
break;
- case 76:
-#line 657 "go.y"
+ case 77:
+#line 664 "go.y"
{
// test
(yyval.node) = nod(OIF, N, N);
@@ -3039,8 +3035,8 @@ yyreduce:
}
break;
- case 77:
-#line 663 "go.y"
+ case 78:
+#line 670 "go.y"
{
// init ; test
(yyval.node) = nod(OIF, N, N);
@@ -3050,30 +3046,30 @@ yyreduce:
}
break;
- case 78:
-#line 674 "go.y"
+ case 79:
+#line 681 "go.y"
{
markdcl();
}
break;
- case 79:
-#line 678 "go.y"
+ case 80:
+#line 685 "go.y"
{
if((yyvsp[(3) - (3)].node)->ntest == N)
yyerror("missing condition in if statement");
}
break;
- case 80:
-#line 683 "go.y"
+ case 81:
+#line 690 "go.y"
{
(yyvsp[(3) - (5)].node)->nbody = (yyvsp[(5) - (5)].list);
}
break;
- case 81:
-#line 687 "go.y"
+ case 82:
+#line 694 "go.y"
{
Node *n;
NodeList *nn;
@@ -3090,15 +3086,15 @@ yyreduce:
}
break;
- case 82:
-#line 704 "go.y"
+ case 83:
+#line 711 "go.y"
{
markdcl();
}
break;
- case 83:
-#line 708 "go.y"
+ case 84:
+#line 715 "go.y"
{
if((yyvsp[(4) - (5)].node)->ntest == N)
yyerror("missing condition in if statement");
@@ -3107,29 +3103,29 @@ yyreduce:
}
break;
- case 84:
-#line 716 "go.y"
+ case 85:
+#line 723 "go.y"
{
(yyval.list) = nil;
}
break;
- case 85:
-#line 720 "go.y"
+ case 86:
+#line 727 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list));
}
break;
- case 86:
-#line 725 "go.y"
+ case 87:
+#line 732 "go.y"
{
(yyval.list) = nil;
}
break;
- case 87:
-#line 729 "go.y"
+ case 88:
+#line 736 "go.y"
{
NodeList *node;
@@ -3140,15 +3136,15 @@ yyreduce:
}
break;
- case 88:
-#line 740 "go.y"
+ case 89:
+#line 747 "go.y"
{
markdcl();
}
break;
- case 89:
-#line 744 "go.y"
+ case 90:
+#line 751 "go.y"
{
Node *n;
n = (yyvsp[(3) - (3)].node)->ntest;
@@ -3158,8 +3154,8 @@ yyreduce:
}
break;
- case 90:
-#line 752 "go.y"
+ case 91:
+#line 759 "go.y"
{
(yyval.node) = (yyvsp[(3) - (7)].node);
(yyval.node)->op = OSWITCH;
@@ -3169,15 +3165,15 @@ yyreduce:
}
break;
- case 91:
-#line 762 "go.y"
+ case 92:
+#line 769 "go.y"
{
typesw = nod(OXXX, typesw, N);
}
break;
- case 92:
-#line 766 "go.y"
+ case 93:
+#line 773 "go.y"
{
(yyval.node) = nod(OSELECT, N, N);
(yyval.node)->lineno = typesw->lineno;
@@ -3186,155 +3182,155 @@ yyreduce:
}
break;
- case 94:
-#line 779 "go.y"
+ case 95:
+#line 786 "go.y"
{
(yyval.node) = nod(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 95:
-#line 783 "go.y"
+ case 96:
+#line 790 "go.y"
{
(yyval.node) = nod(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 96:
-#line 787 "go.y"
+ case 97:
+#line 794 "go.y"
{
(yyval.node) = nod(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 97:
-#line 791 "go.y"
+ case 98:
+#line 798 "go.y"
{
(yyval.node) = nod(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 98:
-#line 795 "go.y"
+ case 99:
+#line 802 "go.y"
{
(yyval.node) = nod(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 99:
-#line 799 "go.y"
+ case 100:
+#line 806 "go.y"
{
(yyval.node) = nod(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 100:
-#line 803 "go.y"
+ case 101:
+#line 810 "go.y"
{
(yyval.node) = nod(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 101:
-#line 807 "go.y"
+ case 102:
+#line 814 "go.y"
{
(yyval.node) = nod(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 102:
-#line 811 "go.y"
+ case 103:
+#line 818 "go.y"
{
(yyval.node) = nod(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 103:
-#line 815 "go.y"
+ case 104:
+#line 822 "go.y"
{
(yyval.node) = nod(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 104:
-#line 819 "go.y"
+ case 105:
+#line 826 "go.y"
{
(yyval.node) = nod(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 105:
-#line 823 "go.y"
+ case 106:
+#line 830 "go.y"
{
(yyval.node) = nod(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 106:
-#line 827 "go.y"
+ case 107:
+#line 834 "go.y"
{
(yyval.node) = nod(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 107:
-#line 831 "go.y"
+ case 108:
+#line 838 "go.y"
{
(yyval.node) = nod(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 108:
-#line 835 "go.y"
+ case 109:
+#line 842 "go.y"
{
(yyval.node) = nod(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 109:
-#line 839 "go.y"
+ case 110:
+#line 846 "go.y"
{
(yyval.node) = nod(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 110:
-#line 843 "go.y"
+ case 111:
+#line 850 "go.y"
{
(yyval.node) = nod(OANDNOT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 111:
-#line 847 "go.y"
+ case 112:
+#line 854 "go.y"
{
(yyval.node) = nod(OLSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 112:
-#line 851 "go.y"
+ case 113:
+#line 858 "go.y"
{
(yyval.node) = nod(ORSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 113:
-#line 856 "go.y"
+ case 114:
+#line 863 "go.y"
{
(yyval.node) = nod(OSEND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 115:
-#line 863 "go.y"
+ case 116:
+#line 870 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
- case 116:
-#line 867 "go.y"
+ case 117:
+#line 874 "go.y"
{
if((yyvsp[(2) - (2)].node)->op == OCOMPLIT) {
// Special case for &T{...}: turn into (*T){...}.
@@ -3347,66 +3343,66 @@ yyreduce:
}
break;
- case 117:
-#line 878 "go.y"
+ case 118:
+#line 885 "go.y"
{
(yyval.node) = nod(OPLUS, (yyvsp[(2) - (2)].node), N);
}
break;
- case 118:
-#line 882 "go.y"
+ case 119:
+#line 889 "go.y"
{
(yyval.node) = nod(OMINUS, (yyvsp[(2) - (2)].node), N);
}
break;
- case 119:
-#line 886 "go.y"
+ case 120:
+#line 893 "go.y"
{
(yyval.node) = nod(ONOT, (yyvsp[(2) - (2)].node), N);
}
break;
- case 120:
-#line 890 "go.y"
+ case 121:
+#line 897 "go.y"
{
yyerror("the bitwise complement operator is ^");
(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
}
break;
- case 121:
-#line 895 "go.y"
+ case 122:
+#line 902 "go.y"
{
(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
}
break;
- case 122:
-#line 899 "go.y"
+ case 123:
+#line 906 "go.y"
{
(yyval.node) = nod(ORECV, (yyvsp[(2) - (2)].node), N);
}
break;
- case 123:
-#line 909 "go.y"
+ case 124:
+#line 916 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (3)].node), N);
}
break;
- case 124:
-#line 913 "go.y"
+ case 125:
+#line 920 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
}
break;
- case 125:
-#line 918 "go.y"
+ case 126:
+#line 925 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (6)].node), N);
(yyval.node)->list = (yyvsp[(3) - (6)].list);
@@ -3414,15 +3410,15 @@ yyreduce:
}
break;
- case 126:
-#line 926 "go.y"
+ case 127:
+#line 933 "go.y"
{
(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
}
break;
- case 128:
-#line 931 "go.y"
+ case 129:
+#line 938 "go.y"
{
if((yyvsp[(1) - (3)].node)->op == OPACK) {
Sym *s;
@@ -3435,36 +3431,36 @@ yyreduce:
}
break;
- case 129:
-#line 942 "go.y"
+ case 130:
+#line 949 "go.y"
{
(yyval.node) = nod(ODOTTYPE, (yyvsp[(1) - (5)].node), (yyvsp[(4) - (5)].node));
}
break;
- case 130:
-#line 946 "go.y"
+ case 131:
+#line 953 "go.y"
{
(yyval.node) = nod(OTYPESW, N, (yyvsp[(1) - (5)].node));
}
break;
- case 131:
-#line 950 "go.y"
+ case 132:
+#line 957 "go.y"
{
(yyval.node) = nod(OINDEX, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
}
break;
- case 132:
-#line 954 "go.y"
+ case 133:
+#line 961 "go.y"
{
(yyval.node) = nod(OSLICE, (yyvsp[(1) - (6)].node), nod(OKEY, (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node)));
}
break;
- case 133:
-#line 958 "go.y"
+ case 134:
+#line 965 "go.y"
{
if((yyvsp[(5) - (8)].node) == N)
yyerror("middle index required in 3-index slice");
@@ -3474,8 +3470,8 @@ yyreduce:
}
break;
- case 135:
-#line 967 "go.y"
+ case 136:
+#line 974 "go.y"
{
// conversion
(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
@@ -3483,8 +3479,8 @@ yyreduce:
}
break;
- case 136:
-#line 973 "go.y"
+ case 137:
+#line 980 "go.y"
{
(yyval.node) = (yyvsp[(3) - (5)].node);
(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3493,8 +3489,8 @@ yyreduce:
}
break;
- case 137:
-#line 980 "go.y"
+ case 138:
+#line 987 "go.y"
{
(yyval.node) = (yyvsp[(3) - (5)].node);
(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3502,8 +3498,8 @@ yyreduce:
}
break;
- case 138:
-#line 986 "go.y"
+ case 139:
+#line 993 "go.y"
{
yyerror("cannot parenthesize type in composite literal");
(yyval.node) = (yyvsp[(5) - (7)].node);
@@ -3512,8 +3508,8 @@ yyreduce:
}
break;
- case 140:
-#line 995 "go.y"
+ case 141:
+#line 1002 "go.y"
{
// composite expression.
// make node early so we get the right line number.
@@ -3521,15 +3517,15 @@ yyreduce:
}
break;
- case 141:
-#line 1003 "go.y"
+ case 142:
+#line 1010 "go.y"
{
(yyval.node) = nod(OKEY, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
- case 142:
-#line 1009 "go.y"
+ case 143:
+#line 1016 "go.y"
{
// These nodes do not carry line numbers.
// Since a composite literal commonly spans several lines,
@@ -3548,24 +3544,24 @@ yyreduce:
}
break;
- case 143:
-#line 1026 "go.y"
+ case 144:
+#line 1033 "go.y"
{
(yyval.node) = (yyvsp[(2) - (4)].node);
(yyval.node)->list = (yyvsp[(3) - (4)].list);
}
break;
- case 145:
-#line 1034 "go.y"
+ case 146:
+#line 1041 "go.y"
{
(yyval.node) = (yyvsp[(2) - (4)].node);
(yyval.node)->list = (yyvsp[(3) - (4)].list);
}
break;
- case 147:
-#line 1042 "go.y"
+ case 148:
+#line 1049 "go.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
@@ -3584,22 +3580,22 @@ yyreduce:
}
break;
- case 151:
-#line 1068 "go.y"
+ case 152:
+#line 1075 "go.y"
{
(yyval.i) = LBODY;
}
break;
- case 152:
-#line 1072 "go.y"
+ case 153:
+#line 1079 "go.y"
{
(yyval.i) = '{';
}
break;
- case 153:
-#line 1083 "go.y"
+ case 154:
+#line 1090 "go.y"
{
if((yyvsp[(1) - (1)].sym) == S)
(yyval.node) = N;
@@ -3608,22 +3604,22 @@ yyreduce:
}
break;
- case 154:
-#line 1092 "go.y"
+ case 155:
+#line 1099 "go.y"
{
(yyval.node) = dclname((yyvsp[(1) - (1)].sym));
}
break;
- case 155:
-#line 1097 "go.y"
+ case 156:
+#line 1104 "go.y"
{
(yyval.node) = N;
}
break;
- case 157:
-#line 1104 "go.y"
+ case 158:
+#line 1111 "go.y"
{
(yyval.sym) = (yyvsp[(1) - (1)].sym);
// during imports, unqualified non-exported identifiers are from builtinpkg
@@ -3632,15 +3628,15 @@ yyreduce:
}
break;
- case 159:
-#line 1112 "go.y"
+ case 160:
+#line 1119 "go.y"
{
(yyval.sym) = S;
}
break;
- case 160:
-#line 1118 "go.y"
+ case 161:
+#line 1125 "go.y"
{
Pkg *p;
@@ -3655,8 +3651,8 @@ yyreduce:
}
break;
- case 161:
-#line 1131 "go.y"
+ case 162:
+#line 1138 "go.y"
{
Pkg *p;
@@ -3671,8 +3667,8 @@ yyreduce:
}
break;
- case 162:
-#line 1146 "go.y"
+ case 163:
+#line 1153 "go.y"
{
(yyval.node) = oldname((yyvsp[(1) - (1)].sym));
if((yyval.node)->pack != N)
@@ -3680,44 +3676,44 @@ yyreduce:
}
break;
- case 164:
-#line 1166 "go.y"
+ case 165:
+#line 1173 "go.y"
{
yyerror("final argument in variadic function missing type");
(yyval.node) = nod(ODDD, typenod(typ(TINTER)), N);
}
break;
- case 165:
-#line 1171 "go.y"
+ case 166:
+#line 1178 "go.y"
{
(yyval.node) = nod(ODDD, (yyvsp[(2) - (2)].node), N);
}
break;
- case 171:
-#line 1182 "go.y"
+ case 172:
+#line 1189 "go.y"
{
- (yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
+ (yyval.node) = (yyvsp[(2) - (3)].node);
}
break;
- case 175:
-#line 1191 "go.y"
+ case 176:
+#line 1198 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
- case 180:
-#line 1201 "go.y"
+ case 181:
+#line 1208 "go.y"
{
- (yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
+ (yyval.node) = (yyvsp[(2) - (3)].node);
}
break;
- case 190:
-#line 1222 "go.y"
+ case 191:
+#line 1229 "go.y"
{
if((yyvsp[(1) - (3)].node)->op == OPACK) {
Sym *s;
@@ -3730,61 +3726,61 @@ yyreduce:
}
break;
- case 191:
-#line 1235 "go.y"
+ case 192:
+#line 1242 "go.y"
{
(yyval.node) = nod(OTARRAY, (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].node));
}
break;
- case 192:
-#line 1239 "go.y"
+ case 193:
+#line 1246 "go.y"
{
// array literal of nelem
(yyval.node) = nod(OTARRAY, nod(ODDD, N, N), (yyvsp[(4) - (4)].node));
}
break;
- case 193:
-#line 1244 "go.y"
+ case 194:
+#line 1251 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(2) - (2)].node), N);
(yyval.node)->etype = Cboth;
}
break;
- case 194:
-#line 1249 "go.y"
+ case 195:
+#line 1256 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
(yyval.node)->etype = Csend;
}
break;
- case 195:
-#line 1254 "go.y"
+ case 196:
+#line 1261 "go.y"
{
(yyval.node) = nod(OTMAP, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
}
break;
- case 198:
-#line 1262 "go.y"
+ case 199:
+#line 1269 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
- case 199:
-#line 1268 "go.y"
+ case 200:
+#line 1275 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
(yyval.node)->etype = Crecv;
}
break;
- case 200:
-#line 1275 "go.y"
+ case 201:
+#line 1282 "go.y"
{
(yyval.node) = nod(OTSTRUCT, N, N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3792,16 +3788,16 @@ yyreduce:
}
break;
- case 201:
-#line 1281 "go.y"
+ case 202:
+#line 1288 "go.y"
{
(yyval.node) = nod(OTSTRUCT, N, N);
fixlbrace((yyvsp[(2) - (3)].i));
}
break;
- case 202:
-#line 1288 "go.y"
+ case 203:
+#line 1295 "go.y"
{
(yyval.node) = nod(OTINTER, N, N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3809,16 +3805,16 @@ yyreduce:
}
break;
- case 203:
-#line 1294 "go.y"
+ case 204:
+#line 1301 "go.y"
{
(yyval.node) = nod(OTINTER, N, N);
fixlbrace((yyvsp[(2) - (3)].i));
}
break;
- case 204:
-#line 1305 "go.y"
+ case 205:
+#line 1312 "go.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
if((yyval.node) == N)
@@ -3828,12 +3824,13 @@ yyreduce:
(yyval.node)->nbody = (yyvsp[(3) - (3)].list);
(yyval.node)->endlineno = lineno;
(yyval.node)->noescape = noescape;
+ (yyval.node)->nosplit = nosplit;
funcbody((yyval.node));
}
break;
- case 205:
-#line 1319 "go.y"
+ case 206:
+#line 1327 "go.y"
{
Node *t;
@@ -3864,8 +3861,8 @@ yyreduce:
}
break;
- case 206:
-#line 1348 "go.y"
+ case 207:
+#line 1356 "go.y"
{
Node *rcvr, *t;
@@ -3886,8 +3883,6 @@ yyreduce:
yyerror("bad receiver in method");
break;
}
- if(rcvr->right->op == OTPAREN || (rcvr->right->op == OIND && rcvr->right->left->op == OTPAREN))
- yyerror("cannot parenthesize receiver type");
t = nod(OTFUNC, rcvr, N);
t->list = (yyvsp[(6) - (8)].list);
@@ -3905,8 +3900,8 @@ yyreduce:
}
break;
- case 207:
-#line 1388 "go.y"
+ case 208:
+#line 1394 "go.y"
{
Sym *s;
Type *t;
@@ -3933,8 +3928,8 @@ yyreduce:
}
break;
- case 208:
-#line 1413 "go.y"
+ case 209:
+#line 1419 "go.y"
{
(yyval.node) = methodname1(newname((yyvsp[(4) - (8)].sym)), (yyvsp[(2) - (8)].list)->n->right);
(yyval.node)->type = functype((yyvsp[(2) - (8)].list)->n, (yyvsp[(6) - (8)].list), (yyvsp[(8) - (8)].list));
@@ -3952,8 +3947,8 @@ yyreduce:
}
break;
- case 209:
-#line 1431 "go.y"
+ case 210:
+#line 1437 "go.y"
{
(yyvsp[(3) - (5)].list) = checkarglist((yyvsp[(3) - (5)].list), 1);
(yyval.node) = nod(OTFUNC, N, N);
@@ -3962,15 +3957,15 @@ yyreduce:
}
break;
- case 210:
-#line 1439 "go.y"
+ case 211:
+#line 1445 "go.y"
{
(yyval.list) = nil;
}
break;
- case 211:
-#line 1443 "go.y"
+ case 212:
+#line 1449 "go.y"
{
(yyval.list) = (yyvsp[(2) - (3)].list);
if((yyval.list) == nil)
@@ -3978,119 +3973,120 @@ yyreduce:
}
break;
- case 212:
-#line 1451 "go.y"
+ case 213:
+#line 1457 "go.y"
{
(yyval.list) = nil;
}
break;
- case 213:
-#line 1455 "go.y"
+ case 214:
+#line 1461 "go.y"
{
(yyval.list) = list1(nod(ODCLFIELD, N, (yyvsp[(1) - (1)].node)));
}
break;
- case 214:
-#line 1459 "go.y"
+ case 215:
+#line 1465 "go.y"
{
(yyvsp[(2) - (3)].list) = checkarglist((yyvsp[(2) - (3)].list), 0);
(yyval.list) = (yyvsp[(2) - (3)].list);
}
break;
- case 215:
-#line 1466 "go.y"
+ case 216:
+#line 1472 "go.y"
{
closurehdr((yyvsp[(1) - (1)].node));
}
break;
- case 216:
-#line 1472 "go.y"
+ case 217:
+#line 1478 "go.y"
{
(yyval.node) = closurebody((yyvsp[(3) - (4)].list));
fixlbrace((yyvsp[(2) - (4)].i));
}
break;
- case 217:
-#line 1477 "go.y"
+ case 218:
+#line 1483 "go.y"
{
(yyval.node) = closurebody(nil);
}
break;
- case 218:
-#line 1488 "go.y"
+ case 219:
+#line 1494 "go.y"
{
(yyval.list) = nil;
}
break;
- case 219:
-#line 1492 "go.y"
+ case 220:
+#line 1498 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].list));
if(nsyntaxerrors == 0)
testdclstack();
nointerface = 0;
noescape = 0;
+ nosplit = 0;
}
break;
- case 221:
-#line 1503 "go.y"
+ case 222:
+#line 1510 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
- case 223:
-#line 1510 "go.y"
+ case 224:
+#line 1517 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
- case 224:
-#line 1516 "go.y"
+ case 225:
+#line 1523 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 225:
-#line 1520 "go.y"
+ case 226:
+#line 1527 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
- case 227:
-#line 1527 "go.y"
+ case 228:
+#line 1534 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
- case 228:
-#line 1533 "go.y"
+ case 229:
+#line 1540 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 229:
-#line 1537 "go.y"
+ case 230:
+#line 1544 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
- case 230:
-#line 1543 "go.y"
+ case 231:
+#line 1550 "go.y"
{
NodeList *l;
@@ -4115,16 +4111,16 @@ yyreduce:
}
break;
- case 231:
-#line 1566 "go.y"
+ case 232:
+#line 1573 "go.y"
{
(yyvsp[(1) - (2)].node)->val = (yyvsp[(2) - (2)].val);
(yyval.list) = list1((yyvsp[(1) - (2)].node));
}
break;
- case 232:
-#line 1571 "go.y"
+ case 233:
+#line 1578 "go.y"
{
(yyvsp[(2) - (4)].node)->val = (yyvsp[(4) - (4)].val);
(yyval.list) = list1((yyvsp[(2) - (4)].node));
@@ -4132,8 +4128,8 @@ yyreduce:
}
break;
- case 233:
-#line 1577 "go.y"
+ case 234:
+#line 1584 "go.y"
{
(yyvsp[(2) - (3)].node)->right = nod(OIND, (yyvsp[(2) - (3)].node)->right, N);
(yyvsp[(2) - (3)].node)->val = (yyvsp[(3) - (3)].val);
@@ -4141,8 +4137,8 @@ yyreduce:
}
break;
- case 234:
-#line 1583 "go.y"
+ case 235:
+#line 1590 "go.y"
{
(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4151,8 +4147,8 @@ yyreduce:
}
break;
- case 235:
-#line 1590 "go.y"
+ case 236:
+#line 1597 "go.y"
{
(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4161,8 +4157,8 @@ yyreduce:
}
break;
- case 236:
-#line 1599 "go.y"
+ case 237:
+#line 1606 "go.y"
{
Node *n;
@@ -4173,8 +4169,8 @@ yyreduce:
}
break;
- case 237:
-#line 1608 "go.y"
+ case 238:
+#line 1615 "go.y"
{
Pkg *pkg;
@@ -4189,38 +4185,38 @@ yyreduce:
}
break;
- case 238:
-#line 1623 "go.y"
+ case 239:
+#line 1630 "go.y"
{
(yyval.node) = embedded((yyvsp[(1) - (1)].sym), localpkg);
}
break;
- case 239:
-#line 1629 "go.y"
+ case 240:
+#line 1636 "go.y"
{
(yyval.node) = nod(ODCLFIELD, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
ifacedcl((yyval.node));
}
break;
- case 240:
-#line 1634 "go.y"
+ case 241:
+#line 1641 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(1) - (1)].sym)));
}
break;
- case 241:
-#line 1638 "go.y"
+ case 242:
+#line 1645 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(2) - (3)].sym)));
yyerror("cannot parenthesize embedded type");
}
break;
- case 242:
-#line 1645 "go.y"
+ case 243:
+#line 1652 "go.y"
{
// without func keyword
(yyvsp[(2) - (4)].list) = checkarglist((yyvsp[(2) - (4)].list), 1);
@@ -4230,8 +4226,8 @@ yyreduce:
}
break;
- case 244:
-#line 1659 "go.y"
+ case 245:
+#line 1666 "go.y"
{
(yyval.node) = nod(ONONAME, N, N);
(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4239,8 +4235,8 @@ yyreduce:
}
break;
- case 245:
-#line 1665 "go.y"
+ case 246:
+#line 1672 "go.y"
{
(yyval.node) = nod(ONONAME, N, N);
(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4248,65 +4244,65 @@ yyreduce:
}
break;
- case 247:
-#line 1674 "go.y"
+ case 248:
+#line 1681 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 248:
-#line 1678 "go.y"
+ case 249:
+#line 1685 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
- case 249:
-#line 1683 "go.y"
+ case 250:
+#line 1690 "go.y"
{
(yyval.list) = nil;
}
break;
- case 250:
-#line 1687 "go.y"
+ case 251:
+#line 1694 "go.y"
{
(yyval.list) = (yyvsp[(1) - (2)].list);
}
break;
- case 251:
-#line 1695 "go.y"
+ case 252:
+#line 1702 "go.y"
{
(yyval.node) = N;
}
break;
- case 253:
-#line 1700 "go.y"
+ case 254:
+#line 1707 "go.y"
{
(yyval.node) = liststmt((yyvsp[(1) - (1)].list));
}
break;
- case 255:
-#line 1705 "go.y"
+ case 256:
+#line 1712 "go.y"
{
(yyval.node) = N;
}
break;
- case 261:
-#line 1716 "go.y"
+ case 262:
+#line 1723 "go.y"
{
(yyvsp[(1) - (2)].node) = nod(OLABEL, (yyvsp[(1) - (2)].node), N);
(yyvsp[(1) - (2)].node)->sym = dclstack; // context, for goto restrictions
}
break;
- case 262:
-#line 1721 "go.y"
+ case 263:
+#line 1728 "go.y"
{
NodeList *l;
@@ -4318,8 +4314,8 @@ yyreduce:
}
break;
- case 263:
-#line 1731 "go.y"
+ case 264:
+#line 1738 "go.y"
{
// will be converted to OFALL
(yyval.node) = nod(OXFALL, N, N);
@@ -4327,44 +4323,44 @@ yyreduce:
}
break;
- case 264:
-#line 1737 "go.y"
+ case 265:
+#line 1744 "go.y"
{
(yyval.node) = nod(OBREAK, (yyvsp[(2) - (2)].node), N);
}
break;
- case 265:
-#line 1741 "go.y"
+ case 266:
+#line 1748 "go.y"
{
(yyval.node) = nod(OCONTINUE, (yyvsp[(2) - (2)].node), N);
}
break;
- case 266:
-#line 1745 "go.y"
+ case 267:
+#line 1752 "go.y"
{
(yyval.node) = nod(OPROC, (yyvsp[(2) - (2)].node), N);
}
break;
- case 267:
-#line 1749 "go.y"
+ case 268:
+#line 1756 "go.y"
{
(yyval.node) = nod(ODEFER, (yyvsp[(2) - (2)].node), N);
}
break;
- case 268:
-#line 1753 "go.y"
+ case 269:
+#line 1760 "go.y"
{
(yyval.node) = nod(OGOTO, (yyvsp[(2) - (2)].node), N);
(yyval.node)->sym = dclstack; // context, for goto restrictions
}
break;
- case 269:
-#line 1758 "go.y"
+ case 270:
+#line 1765 "go.y"
{
(yyval.node) = nod(ORETURN, N, N);
(yyval.node)->list = (yyvsp[(2) - (2)].list);
@@ -4383,8 +4379,8 @@ yyreduce:
}
break;
- case 270:
-#line 1777 "go.y"
+ case 271:
+#line 1784 "go.y"
{
(yyval.list) = nil;
if((yyvsp[(1) - (1)].node) != N)
@@ -4392,8 +4388,8 @@ yyreduce:
}
break;
- case 271:
-#line 1783 "go.y"
+ case 272:
+#line 1790 "go.y"
{
(yyval.list) = (yyvsp[(1) - (3)].list);
if((yyvsp[(3) - (3)].node) != N)
@@ -4401,190 +4397,190 @@ yyreduce:
}
break;
- case 272:
-#line 1791 "go.y"
+ case 273:
+#line 1798 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 273:
-#line 1795 "go.y"
+ case 274:
+#line 1802 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
- case 274:
-#line 1801 "go.y"
+ case 275:
+#line 1808 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 275:
-#line 1805 "go.y"
+ case 276:
+#line 1812 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
- case 276:
-#line 1811 "go.y"
+ case 277:
+#line 1818 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 277:
-#line 1815 "go.y"
+ case 278:
+#line 1822 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
- case 278:
-#line 1821 "go.y"
+ case 279:
+#line 1828 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 279:
-#line 1825 "go.y"
+ case 280:
+#line 1832 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
- case 280:
-#line 1834 "go.y"
+ case 281:
+#line 1841 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 281:
-#line 1838 "go.y"
+ case 282:
+#line 1845 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 282:
-#line 1842 "go.y"
+ case 283:
+#line 1849 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
- case 283:
-#line 1846 "go.y"
+ case 284:
+#line 1853 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
- case 284:
-#line 1851 "go.y"
+ case 285:
+#line 1858 "go.y"
{
(yyval.list) = nil;
}
break;
- case 285:
-#line 1855 "go.y"
+ case 286:
+#line 1862 "go.y"
{
(yyval.list) = (yyvsp[(1) - (2)].list);
}
break;
- case 290:
-#line 1869 "go.y"
+ case 291:
+#line 1876 "go.y"
{
(yyval.node) = N;
}
break;
- case 292:
-#line 1875 "go.y"
+ case 293:
+#line 1882 "go.y"
{
(yyval.list) = nil;
}
break;
- case 294:
-#line 1881 "go.y"
+ case 295:
+#line 1888 "go.y"
{
(yyval.node) = N;
}
break;
- case 296:
-#line 1887 "go.y"
+ case 297:
+#line 1894 "go.y"
{
(yyval.list) = nil;
}
break;
- case 298:
-#line 1893 "go.y"
+ case 299:
+#line 1900 "go.y"
{
(yyval.list) = nil;
}
break;
- case 300:
-#line 1899 "go.y"
+ case 301:
+#line 1906 "go.y"
{
(yyval.list) = nil;
}
break;
- case 302:
-#line 1905 "go.y"
+ case 303:
+#line 1912 "go.y"
{
(yyval.val).ctype = CTxxx;
}
break;
- case 304:
-#line 1915 "go.y"
+ case 305:
+#line 1922 "go.y"
{
importimport((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].val).u.sval);
}
break;
- case 305:
-#line 1919 "go.y"
+ case 306:
+#line 1926 "go.y"
{
importvar((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].type));
}
break;
- case 306:
-#line 1923 "go.y"
+ case 307:
+#line 1930 "go.y"
{
importconst((yyvsp[(2) - (5)].sym), types[TIDEAL], (yyvsp[(4) - (5)].node));
}
break;
- case 307:
-#line 1927 "go.y"
+ case 308:
+#line 1934 "go.y"
{
importconst((yyvsp[(2) - (6)].sym), (yyvsp[(3) - (6)].type), (yyvsp[(5) - (6)].node));
}
break;
- case 308:
-#line 1931 "go.y"
+ case 309:
+#line 1938 "go.y"
{
importtype((yyvsp[(2) - (4)].type), (yyvsp[(3) - (4)].type));
}
break;
- case 309:
-#line 1935 "go.y"
+ case 310:
+#line 1942 "go.y"
{
if((yyvsp[(2) - (4)].node) == N) {
dclcontext = PEXTERN; // since we skip the funcbody below
@@ -4604,31 +4600,31 @@ yyreduce:
}
break;
- case 310:
-#line 1955 "go.y"
+ case 311:
+#line 1962 "go.y"
{
(yyval.sym) = (yyvsp[(1) - (1)].sym);
structpkg = (yyval.sym)->pkg;
}
break;
- case 311:
-#line 1962 "go.y"
+ case 312:
+#line 1969 "go.y"
{
(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
importsym((yyvsp[(1) - (1)].sym), OTYPE);
}
break;
- case 317:
-#line 1982 "go.y"
+ case 318:
+#line 1989 "go.y"
{
(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
}
break;
- case 318:
-#line 1986 "go.y"
+ case 319:
+#line 1993 "go.y"
{
// predefined name like uint8
(yyvsp[(1) - (1)].sym) = pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg);
@@ -4640,50 +4636,50 @@ yyreduce:
}
break;
- case 319:
-#line 1996 "go.y"
+ case 320:
+#line 2003 "go.y"
{
(yyval.type) = aindex(N, (yyvsp[(3) - (3)].type));
}
break;
- case 320:
-#line 2000 "go.y"
+ case 321:
+#line 2007 "go.y"
{
(yyval.type) = aindex(nodlit((yyvsp[(2) - (4)].val)), (yyvsp[(4) - (4)].type));
}
break;
- case 321:
-#line 2004 "go.y"
+ case 322:
+#line 2011 "go.y"
{
(yyval.type) = maptype((yyvsp[(3) - (5)].type), (yyvsp[(5) - (5)].type));
}
break;
- case 322:
-#line 2008 "go.y"
+ case 323:
+#line 2015 "go.y"
{
(yyval.type) = tostruct((yyvsp[(3) - (4)].list));
}
break;
- case 323:
-#line 2012 "go.y"
+ case 324:
+#line 2019 "go.y"
{
(yyval.type) = tointerface((yyvsp[(3) - (4)].list));
}
break;
- case 324:
-#line 2016 "go.y"
+ case 325:
+#line 2023 "go.y"
{
(yyval.type) = ptrto((yyvsp[(2) - (2)].type));
}
break;
- case 325:
-#line 2020 "go.y"
+ case 326:
+#line 2027 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(2) - (2)].type);
@@ -4691,8 +4687,8 @@ yyreduce:
}
break;
- case 326:
-#line 2026 "go.y"
+ case 327:
+#line 2033 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (4)].type);
@@ -4700,8 +4696,8 @@ yyreduce:
}
break;
- case 327:
-#line 2032 "go.y"
+ case 328:
+#line 2039 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4709,8 +4705,8 @@ yyreduce:
}
break;
- case 328:
-#line 2040 "go.y"
+ case 329:
+#line 2047 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4718,15 +4714,15 @@ yyreduce:
}
break;
- case 329:
-#line 2048 "go.y"
+ case 330:
+#line 2055 "go.y"
{
(yyval.type) = functype(nil, (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list));
}
break;
- case 330:
-#line 2054 "go.y"
+ case 331:
+#line 2061 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(2) - (3)].type)));
if((yyvsp[(1) - (3)].sym))
@@ -4735,8 +4731,8 @@ yyreduce:
}
break;
- case 331:
-#line 2061 "go.y"
+ case 332:
+#line 2068 "go.y"
{
Type *t;
@@ -4752,8 +4748,8 @@ yyreduce:
}
break;
- case 332:
-#line 2077 "go.y"
+ case 333:
+#line 2084 "go.y"
{
Sym *s;
Pkg *p;
@@ -4775,50 +4771,50 @@ yyreduce:
}
break;
- case 333:
-#line 2099 "go.y"
+ case 334:
+#line 2106 "go.y"
{
(yyval.node) = nod(ODCLFIELD, newname((yyvsp[(1) - (5)].sym)), typenod(functype(fakethis(), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list))));
}
break;
- case 334:
-#line 2103 "go.y"
+ case 335:
+#line 2110 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type)));
}
break;
- case 335:
-#line 2108 "go.y"
+ case 336:
+#line 2115 "go.y"
{
(yyval.list) = nil;
}
break;
- case 337:
-#line 2115 "go.y"
+ case 338:
+#line 2122 "go.y"
{
(yyval.list) = (yyvsp[(2) - (3)].list);
}
break;
- case 338:
-#line 2119 "go.y"
+ case 339:
+#line 2126 "go.y"
{
(yyval.list) = list1(nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type))));
}
break;
- case 339:
-#line 2129 "go.y"
+ case 340:
+#line 2136 "go.y"
{
(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
}
break;
- case 340:
-#line 2133 "go.y"
+ case 341:
+#line 2140 "go.y"
{
(yyval.node) = nodlit((yyvsp[(2) - (2)].val));
switch((yyval.node)->val.ctype){
@@ -4839,8 +4835,8 @@ yyreduce:
}
break;
- case 341:
-#line 2152 "go.y"
+ case 342:
+#line 2159 "go.y"
{
(yyval.node) = oldname(pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg));
if((yyval.node)->op != OLITERAL)
@@ -4848,8 +4844,8 @@ yyreduce:
}
break;
- case 343:
-#line 2161 "go.y"
+ case 344:
+#line 2168 "go.y"
{
if((yyvsp[(2) - (5)].node)->val.ctype == CTRUNE && (yyvsp[(4) - (5)].node)->val.ctype == CTINT) {
(yyval.node) = (yyvsp[(2) - (5)].node);
@@ -4862,43 +4858,43 @@ yyreduce:
}
break;
- case 346:
-#line 2177 "go.y"
+ case 347:
+#line 2184 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 347:
-#line 2181 "go.y"
+ case 348:
+#line 2188 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
- case 348:
-#line 2187 "go.y"
+ case 349:
+#line 2194 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 349:
-#line 2191 "go.y"
+ case 350:
+#line 2198 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
- case 350:
-#line 2197 "go.y"
+ case 351:
+#line 2204 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
- case 351:
-#line 2201 "go.y"
+ case 352:
+#line 2208 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
@@ -4906,7 +4902,7 @@ yyreduce:
/* Line 1267 of yacc.c. */
-#line 4911 "y.tab.c"
+#line 4907 "y.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -5120,7 +5116,7 @@ yyreturn:
}
-#line 2205 "go.y"
+#line 2212 "go.y"
static void
diff --git a/src/cmd/gc/yerr.h b/src/cmd/gc/yerr.h
index 1526d8231..d0dd639ff 100644
--- a/src/cmd/gc/yerr.h
+++ b/src/cmd/gc/yerr.h
@@ -14,66 +14,66 @@ static struct {
// is converted by bisonerrors into the yystate and yychar caused
// by that token list.
- 222, ',',
- "unexpected comma during import block",
+ {222, ',',
+ "unexpected comma during import block"},
- 32, ';',
- "missing import path; require quoted string",
+ {32, ';',
+ "missing import path; require quoted string"},
- 378, ';',
- "missing { after if clause",
+ {380, ';',
+ "missing { after if clause"},
- 399, ';',
- "missing { after switch clause",
+ {401, ';',
+ "missing { after switch clause"},
- 238, ';',
- "missing { after for clause",
+ {239, ';',
+ "missing { after for clause"},
- 476, LBODY,
- "missing { after for clause",
+ {478, LBODY,
+ "missing { after for clause"},
- 22, '{',
- "unexpected semicolon or newline before {",
+ {22, '{',
+ "unexpected semicolon or newline before {"},
- 145, ';',
- "unexpected semicolon or newline in type declaration",
+ {145, ';',
+ "unexpected semicolon or newline in type declaration"},
- 37, '}',
- "unexpected } in channel type",
+ {37, '}',
+ "unexpected } in channel type"},
- 37, ')',
- "unexpected ) in channel type",
+ {37, ')',
+ "unexpected ) in channel type"},
- 37, ',',
- "unexpected comma in channel type",
+ {37, ',',
+ "unexpected comma in channel type"},
- 439, LELSE,
- "unexpected semicolon or newline before else",
+ {441, LELSE,
+ "unexpected semicolon or newline before else"},
- 258, ',',
- "name list not allowed in interface type",
+ {259, ',',
+ "name list not allowed in interface type"},
- 238, LVAR,
- "var declaration not allowed in for initializer",
+ {239, LVAR,
+ "var declaration not allowed in for initializer"},
- 65, '{',
- "unexpected { at end of statement",
+ {65, '{',
+ "unexpected { at end of statement"},
- 377, '{',
- "unexpected { at end of statement",
+ {379, '{',
+ "unexpected { at end of statement"},
- 126, ';',
- "argument to go/defer must be function call",
+ {126, ';',
+ "argument to go/defer must be function call"},
- 426, ';',
- "need trailing comma before newline in composite literal",
+ {428, ';',
+ "need trailing comma before newline in composite literal"},
- 437, ';',
- "need trailing comma before newline in composite literal",
+ {439, ';',
+ "need trailing comma before newline in composite literal"},
- 113, LNAME,
- "nested func not allowed",
+ {113, LNAME,
+ "nested func not allowed"},
- 645, ';',
- "else must be followed by if or statement block"
+ {647, ';',
+ "else must be followed by if or statement block"}
};
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 3645f1c2d..1dd4314da 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -57,6 +57,7 @@ and test commands:
-a
force rebuilding of packages that are already up-to-date.
+ In Go releases, does not apply to the standard library.
-n
print the commands but do not run them.
-p n
@@ -64,7 +65,7 @@ and test commands:
The default is the number of CPUs available.
-race
enable data race detection.
- Supported only on linux/amd64, darwin/amd64 and windows/amd64.
+ Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
-v
print the names of packages as they are compiled.
-work
@@ -284,23 +285,26 @@ func runBuild(cmd *Command, args []string) {
}
}
+ depMode := modeBuild
+ if buildI {
+ depMode = modeInstall
+ }
+
if *buildO != "" {
if len(pkgs) > 1 {
fatalf("go build: cannot use -o with multiple packages")
+ } else if len(pkgs) == 0 {
+ fatalf("no packages to build")
}
p := pkgs[0]
p.target = "" // must build - not up to date
- a := b.action(modeInstall, modeBuild, p)
+ a := b.action(modeInstall, depMode, p)
a.target = *buildO
b.do(a)
return
}
a := &action{}
- depMode := modeBuild
- if buildI {
- depMode = modeInstall
- }
for _, p := range packages(args) {
a.deps = append(a.deps, b.action(modeBuild, depMode, p))
}
@@ -431,12 +435,11 @@ const (
)
var (
- goroot = filepath.Clean(runtime.GOROOT())
- gobin = os.Getenv("GOBIN")
- gorootBin = filepath.Join(goroot, "bin")
- gorootSrcPkg = filepath.Join(goroot, "src/pkg")
- gorootPkg = filepath.Join(goroot, "pkg")
- gorootSrc = filepath.Join(goroot, "src")
+ goroot = filepath.Clean(runtime.GOROOT())
+ gobin = os.Getenv("GOBIN")
+ gorootBin = filepath.Join(goroot, "bin")
+ gorootPkg = filepath.Join(goroot, "pkg")
+ gorootSrc = filepath.Join(goroot, "src")
)
func (b *builder) init() {
@@ -503,8 +506,13 @@ func goFilesPackage(gofiles []string) *Package {
}
ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil }
- if !filepath.IsAbs(dir) {
- dir = filepath.Join(cwd, dir)
+ var err error
+ if dir == "" {
+ dir = cwd
+ }
+ dir, err = filepath.Abs(dir)
+ if err != nil {
+ fatalf("%s", err)
}
bp, err := ctxt.ImportDir(dir, 0)
@@ -823,12 +831,17 @@ func (b *builder) build(a *action) (err error) {
}
}
- var gofiles, cfiles, sfiles, objects, cgoObjects []string
+ var gofiles, cfiles, sfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string
gofiles = append(gofiles, a.p.GoFiles...)
cfiles = append(cfiles, a.p.CFiles...)
sfiles = append(sfiles, a.p.SFiles...)
+ if a.p.usesCgo() || a.p.usesSwig() {
+ if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.p); err != nil {
+ return
+ }
+ }
// Run cgo.
if a.p.usesCgo() {
// In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
@@ -859,7 +872,7 @@ func (b *builder) build(a *action) (err error) {
if a.cgo != nil && a.cgo.target != "" {
cgoExe = a.cgo.target
}
- outGo, outObj, err := b.cgo(a.p, cgoExe, obj, gccfiles, a.p.CXXFiles, a.p.MFiles)
+ outGo, outObj, err := b.cgo(a.p, cgoExe, obj, pcCFLAGS, pcLDFLAGS, gccfiles, a.p.CXXFiles, a.p.MFiles)
if err != nil {
return err
}
@@ -872,9 +885,18 @@ func (b *builder) build(a *action) (err error) {
// In a package using SWIG, any .c or .s files are
// compiled with gcc.
gccfiles := append(cfiles, sfiles...)
+ cxxfiles, mfiles := a.p.CXXFiles, a.p.MFiles
cfiles = nil
sfiles = nil
- outGo, outObj, err := b.swig(a.p, obj, gccfiles, a.p.CXXFiles, a.p.MFiles)
+
+ // Don't build c/c++ files twice if cgo is enabled (mainly for pkg-config).
+ if a.p.usesCgo() {
+ cxxfiles = nil
+ gccfiles = nil
+ mfiles = nil
+ }
+
+ outGo, outObj, err := b.swig(a.p, obj, pcCFLAGS, gccfiles, cxxfiles, mfiles)
if err != nil {
return err
}
@@ -883,7 +905,7 @@ func (b *builder) build(a *action) (err error) {
}
if len(gofiles) == 0 {
- return &build.NoGoError{a.p.Dir}
+ return &build.NoGoError{Dir: a.p.Dir}
}
// If we're doing coverage, preprocess the .go files and put them in the work directory
@@ -1018,6 +1040,34 @@ func (b *builder) build(a *action) (err error) {
return nil
}
+// Calls pkg-config if needed and returns the cflags/ldflags needed to build the package.
+func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err error) {
+ if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
+ var out []byte
+ out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs)
+ if err != nil {
+ b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out))
+ b.print(err.Error() + "\n")
+ err = errPrintedOutput
+ return
+ }
+ if len(out) > 0 {
+ cflags = strings.Fields(string(out))
+ }
+ out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs)
+ if err != nil {
+ b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out))
+ b.print(err.Error() + "\n")
+ err = errPrintedOutput
+ return
+ }
+ if len(out) > 0 {
+ ldflags = strings.Fields(string(out))
+ }
+ }
+ return
+}
+
// install is the action for installing a single package or executable.
func (b *builder) install(a *action) (err error) {
defer func() {
@@ -1253,7 +1303,7 @@ func (b *builder) showcmd(dir string, format string, args ...interface{}) {
// the source directory for the package that has failed to build.
// showOutput rewrites mentions of dir with a relative path to dir
// when the relative path is shorter. This is usually more pleasant.
-// For example, if fmt doesn't compile and we are in src/pkg/html,
+// For example, if fmt doesn't compile and we are in src/html,
// the output is
//
// $ go build
@@ -1265,7 +1315,7 @@ func (b *builder) showcmd(dir string, format string, args ...interface{}) {
//
// $ go build
// # fmt
-// /usr/gopher/go/src/pkg/fmt/print.go:1090: undefined: asdf
+// /usr/gopher/go/src/fmt/print.go:1090: undefined: asdf
// $
//
// showOutput also replaces references to the work directory with $WORK.
@@ -1425,6 +1475,14 @@ func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...inter
continue
}
+ // err can be something like 'exit status 1'.
+ // Add information about what program was running.
+ // Note that if buf.Bytes() is non-empty, the caller usually
+ // shows buf.Bytes() and does not print err at all, so the
+ // prefix here does not make most output any more verbose.
+ if err != nil {
+ err = errors.New(cmdline[0] + ": " + err.Error())
+ }
return buf.Bytes(), err
}
}
@@ -1587,7 +1645,7 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []
extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles)
if p.Standard {
switch p.ImportPath {
- case "os", "runtime/pprof", "sync", "time":
+ case "bytes", "net", "os", "runtime/pprof", "sync", "time":
extFiles++
}
}
@@ -1611,8 +1669,10 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []
}
func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
+ // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
+ inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
sfile = mkAbs(p.Dir, sfile)
- return b.run(p.Dir, p.ImportPath, nil, tool(archChar+"a"), "-trimpath", b.work, "-I", obj, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile)
+ return b.run(p.Dir, p.ImportPath, nil, tool(archChar+"a"), "-trimpath", b.work, "-I", obj, "-I", inc, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile)
}
func (gcToolchain) pkgpath(basedir string, p *Package) string {
@@ -1706,7 +1766,7 @@ func packInternal(b *builder, afile string, ofiles []string) error {
func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
importArgs := b.includeArgs("-L", allactions)
- cxx := false
+ cxx := len(p.CXXFiles) > 0
for _, a := range allactions {
if a.p != nil && len(a.p.CXXFiles) > 0 {
cxx = true
@@ -1766,14 +1826,30 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action,
func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
cfile = mkAbs(p.Dir, cfile)
- args := stringList(tool(archChar+"c"), "-F", "-V", "-w", "-trimpath", b.work, "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile)
+ warn := []string{"-w"}
+ if p.usesSwig() {
+ // When using SWIG, this compiler is only used to
+ // compile the C files generated by SWIG.
+ // We don't want warnings.
+ // See issue 9065 for details.
+ warn = nil
+ }
+ args := stringList(tool(archChar+"c"), "-F", "-V", warn, "-trimpath", b.work, "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile)
return b.run(p.Dir, p.ImportPath, nil, args)
}
// The Gccgo toolchain.
type gccgoToolchain struct{}
-var gccgoBin, _ = exec.LookPath("gccgo")
+var gccgoName, gccgoBin string
+
+func init() {
+ gccgoName = os.Getenv("GCCGO")
+ if gccgoName == "" {
+ gccgoName = "gccgo"
+ }
+ gccgoBin, _ = exec.LookPath(gccgoName)
+}
func (gccgoToolchain) compiler() string {
return gccgoBin
@@ -1784,7 +1860,7 @@ func (gccgoToolchain) linker() string {
}
func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
- out := p.Name + ".o"
+ out := "_go_.o"
ofile = obj + out
gcargs := []string{"-g"}
gcargs = append(gcargs, b.gccArchArgs()...)
@@ -1794,7 +1870,7 @@ func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, importArgs
if p.localPrefix != "" {
gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix)
}
- args := stringList("gccgo", importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
+ args := stringList(gccgoName, importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
for _, f := range gofiles {
args = append(args, mkAbs(p.Dir, f))
}
@@ -1810,7 +1886,7 @@ func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) erro
defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
}
defs = append(defs, b.gccArchArgs()...)
- return b.run(p.Dir, p.ImportPath, nil, "gccgo", "-I", obj, "-o", ofile, defs, sfile)
+ return b.run(p.Dir, p.ImportPath, nil, gccgoName, "-I", obj, "-o", ofile, defs, sfile)
}
func (gccgoToolchain) pkgpath(basedir string, p *Package) string {
@@ -1836,8 +1912,8 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
ldflags := b.gccArchArgs()
cgoldflags := []string{}
usesCgo := false
- cxx := false
- objc := false
+ cxx := len(p.CXXFiles) > 0
+ objc := len(p.MFiles) > 0
// Prefer the output of an install action to the output of a build action,
// because the install action will delete the output of the build action.
@@ -1877,6 +1953,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
}
ldflags = append(ldflags, afiles...)
ldflags = append(ldflags, cgoldflags...)
+ ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...)
ldflags = append(ldflags, p.CgoLDFLAGS...)
if usesCgo && goos == "linux" {
ldflags = append(ldflags, "-Wl,-E")
@@ -1887,7 +1964,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
if objc {
ldflags = append(ldflags, "-lobjc")
}
- return b.run(".", p.ImportPath, nil, "gccgo", "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags)
+ return b.run(".", p.ImportPath, nil, gccgoName, "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags)
}
func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
@@ -1898,8 +1975,7 @@ func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) er
if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
}
- // TODO: Support using clang here (during gccgo build)?
- return b.run(p.Dir, p.ImportPath, nil, "gcc", "-Wall", "-g",
+ return b.run(p.Dir, p.ImportPath, nil, envList("CC", defaultCC), "-Wall", "-g",
"-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile)
}
@@ -1950,9 +2026,9 @@ func (b *builder) libgcc(p *Package) (string, error) {
return "$LIBGCC", nil
}
- // clang might not be able to find libgcc, and in that case,
+ // 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 strings.Contains(gccCmd[0], "clang") && !filepath.IsAbs(string(f)) {
+ if !filepath.IsAbs(string(f)) {
return "", nil
}
@@ -2090,36 +2166,16 @@ var (
cgoLibGccFileOnce sync.Once
)
-func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) {
+func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) {
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true)
_, cgoexeCFLAGS, _, _ := b.cflags(p, false)
-
+ cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)
+ cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...)
// If we are compiling Objective-C code, then we need to link against libobjc
if len(mfiles) > 0 {
cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc")
}
- if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
- out, err := b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs)
- if err != nil {
- b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out))
- b.print(err.Error() + "\n")
- return nil, nil, errPrintedOutput
- }
- if len(out) > 0 {
- cgoCPPFLAGS = append(cgoCPPFLAGS, strings.Fields(string(out))...)
- }
- out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs)
- if err != nil {
- b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out))
- b.print(err.Error() + "\n")
- return nil, nil, errPrintedOutput
- }
- if len(out) > 0 {
- cgoLDFLAGS = append(cgoLDFLAGS, strings.Fields(string(out))...)
- }
- }
-
// Allows including _cgo_export.h from .[ch] files in the package.
cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj)
@@ -2196,6 +2252,14 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles
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
+ // the final link, we will link the resulting object file again. And
+ // so the program ends up with two copies of sanitizer runtime.
+ // See issue 8788 for details.
+ case strings.HasPrefix(f, "-fsanitize="):
+ continue
default:
bareLDFLAGS = append(bareLDFLAGS, f)
}
@@ -2262,13 +2326,14 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles
linkobj = append(linkobj, p.SysoFiles...)
dynobj := obj + "_cgo_.o"
- if goarch == "arm" && goos == "linux" { // we need to use -pie for Linux/ARM to get accurate imported sym
+ 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")
}
if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil {
return nil, nil, err
}
- if goarch == "arm" && goos == "linux" { // but we don't need -pie for normal cgo programs
+ if pie { // but we don't need -pie for normal cgo programs
cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1]
}
@@ -2302,7 +2367,23 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles
nonGccObjs = append(nonGccObjs, f)
}
}
- if err := b.gccld(p, ofile, stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs), gccObjs); err != nil {
+ ldflags := stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs)
+
+ // Some systems, such as Ubuntu, always add --build-id to
+ // every link, but we don't want a build ID since we are
+ // producing an object file. On some of those system a plain
+ // -r (not -Wl,-r) will turn off --build-id, but clang 3.0
+ // doesn't support a plain -r. I don't know how to turn off
+ // --build-id when using clang other than passing a trailing
+ // --build-id=none. So that is what we do, but only on
+ // systems likely to support it, which is to say, systems that
+ // normally use gold or the GNU linker.
+ switch goos {
+ case "android", "dragonfly", "linux", "netbsd":
+ ldflags = append(ldflags, "-Wl,--build-id=none")
+ }
+
+ if err := b.gccld(p, ofile, ldflags, gccObjs); err != nil {
return nil, nil, err
}
@@ -2317,7 +2398,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles
// Run SWIG on all SWIG input files.
// TODO: Don't build a shared library, once SWIG emits the necessary
// pragmas for external linking.
-func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) {
+func (b *builder) swig(p *Package, obj string, pcCFLAGS, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) {
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true)
cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS)
@@ -2358,7 +2439,7 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []stri
}
for _, f := range p.SwigFiles {
- goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, false, intgosize)
+ goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, pcCFLAGS, false, intgosize)
if err != nil {
return nil, nil, err
}
@@ -2373,7 +2454,7 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []stri
}
}
for _, f := range p.SwigCXXFiles {
- goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, true, intgosize)
+ goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, pcCFLAGS, true, intgosize)
if err != nil {
return nil, nil, err
}
@@ -2452,13 +2533,13 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
}
// Run SWIG on one SWIG input file.
-func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize string) (outGo, outObj, objGccObj string, err error) {
+func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outObj, objGccObj string, err error) {
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true)
var cflags []string
if cxx {
- cflags = stringList(cgoCPPFLAGS, cgoCXXFLAGS)
+ cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
} else {
- cflags = stringList(cgoCPPFLAGS, cgoCFLAGS)
+ cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS)
}
n := 5 // length of ".swig"
@@ -2484,6 +2565,13 @@ func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize stri
"-o", obj + gccBase + gccExt,
"-outdir", obj,
}
+
+ for _, f := range cflags {
+ if len(f) > 3 && f[:2] == "-I" {
+ args = append(args, f)
+ }
+ }
+
if gccgo {
args = append(args, "-gccgo")
if pkgpath := gccgoPkgpath(p); pkgpath != "" {
@@ -2556,8 +2644,8 @@ func raceInit() {
if !buildRace {
return
}
- if goarch != "amd64" || goos != "linux" && goos != "darwin" && goos != "windows" {
- fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
+ 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])
os.Exit(2)
}
buildGcflags = append(buildGcflags, "-race")
diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go
index 9840804ce..d0d8a8a5b 100644
--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -19,6 +19,7 @@ The commands are:
env print Go environment information
fix run go tool fix on packages
fmt run gofmt on package sources
+ generate generate Go files by processing source
get download and install packages and dependencies
install compile and install packages and dependencies
list list packages
@@ -75,6 +76,7 @@ and test commands:
-a
force rebuilding of packages that are already up-to-date.
+ In Go releases, does not apply to the standard library.
-n
print the commands but do not run them.
-p n
@@ -82,7 +84,7 @@ and test commands:
The default is the number of CPUs available.
-race
enable data race detection.
- Supported only on linux/amd64, darwin/amd64 and windows/amd64.
+ Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
-v
print the names of packages as they are compiled.
-work
@@ -219,11 +221,110 @@ To run gofmt with specific options, run gofmt itself.
See also: go fix, go vet.
+Generate Go files by processing source
+
+Usage:
+
+ go generate [-run regexp] [file.go... | packages]
+
+Generate runs commands described by directives within existing
+files. Those commands can run any process but the intent is to
+create or update Go source files, for instance by running yacc.
+
+Go generate is never run automatically by go build, go get, go test,
+and so on. It must be run explicitly.
+
+Go generate scans the file for directives, which are lines of
+the form,
+
+ //go:generate command argument...
+
+(note: no leading spaces and no space in "//go") where command
+is the generator to be run, corresponding to an executable file
+that can be run locally. It must either be in the shell path
+(gofmt), a fully qualified path (/usr/you/bin/mytool), or a
+command alias, described below.
+
+Note that go generate does not parse the file, so lines that look
+like directives in comments or multiline strings will be treated
+as directives.
+
+The arguments to the directive are space-separated tokens or
+double-quoted strings passed to the generator as individual
+arguments when it is run.
+
+Quoted strings use Go syntax and are evaluated before execution; a
+quoted string appears as a single argument to the generator.
+
+Go generate sets several variables when it runs the generator:
+
+ $GOARCH
+ The execution architecture (arm, amd64, etc.)
+ $GOOS
+ The execution operating system (linux, windows, etc.)
+ $GOFILE
+ The base name of the file.
+ $GOPACKAGE
+ The name of the package of the file containing the directive.
+
+Other than variable substitution and quoted-string evaluation, no
+special processing such as "globbing" is performed on the command
+line.
+
+As a last step before running the command, any invocations of any
+environment variables with alphanumeric names, such as $GOFILE or
+$HOME, are expanded throughout the command line. The syntax for
+variable expansion is $NAME on all operating systems. Due to the
+order of evaluation, variables are expanded even inside quoted
+strings. If the variable NAME is not set, $NAME expands to the
+empty string.
+
+A directive of the form,
+
+ //go:generate -command xxx args...
+
+specifies, for the remainder of this source file only, that the
+string xxx represents the command identified by the arguments. This
+can be used to create aliases or to handle multiword generators.
+For example,
+
+ //go:generate -command yacc go tool yacc
+
+specifies that the command "yacc" represents the generator
+"go tool yacc".
+
+Generate processes packages in the order given on the command line,
+one at a time. If the command line lists .go files, they are treated
+as a single package. Within a package, generate processes the
+source files in a package in file name order, one at a time. Within
+a source file, generate runs generators in the order they appear
+in the file, one at a time.
+
+If any generator returns an error exit status, "go generate" skips
+all further processing for that package.
+
+The generator is run in the package's source directory.
+
+Go generate accepts one specific flag:
+
+ -run=""
+ if non-empty, specifies a regular expression to
+ select directives whose command matches the expression.
+
+It also accepts the standard build flags -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 specifying packages, see 'go help packages'.
+
+
Download and install packages and dependencies
Usage:
- go get [-d] [-fix] [-t] [-u] [build flags] [packages]
+ go get [-d] [-f] [-fix] [-t] [-u] [build flags] [packages]
Get downloads and installs the packages named by the import paths,
along with their dependencies.
@@ -231,6 +332,11 @@ along with their dependencies.
The -d flag instructs get to stop after downloading the packages; that is,
it instructs get not to install the packages.
+The -f flag, valid only when -u is set, forces get -u not to verify that
+each package has been checked out from the source control repository
+implied by its import path. This can be useful if the source is a local fork
+of the original.
+
The -fix flag instructs get to run the fix tool on the downloaded packages
before resolving dependencies or building the code.
@@ -291,28 +397,29 @@ syntax of package template. The default output is equivalent to -f
'{{.ImportPath}}'. The struct being passed to the template is:
type Package struct {
- Dir string // directory containing package sources
- ImportPath string // import path of package in dir
- Name string // package name
- Doc string // package documentation string
- Target string // install path
- Goroot bool // is this package in the Go root?
- Standard bool // is this package part of the standard Go library?
- Stale bool // would 'go install' do anything for this package?
- Root string // Go root or Go path dir containing this package
+ Dir string // directory containing package sources
+ ImportPath string // import path of package in dir
+ ImportComment string // path in import comment on package statement
+ Name string // package name
+ Doc string // package documentation string
+ Target string // install path
+ Goroot bool // is this package in the Go root?
+ Standard bool // is this package part of the standard Go library?
+ Stale bool // would 'go install' do anything for this package?
+ Root string // Go root or Go path dir containing this package
// Source files
- GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
- CgoFiles []string // .go sources files that import "C"
+ GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+ CgoFiles []string // .go sources files that import "C"
IgnoredGoFiles []string // .go sources ignored due to build constraints
- CFiles []string // .c source files
- CXXFiles []string // .cc, .cxx and .cpp source files
- MFiles []string // .m source files
- HFiles []string // .h, .hh, .hpp and .hxx source files
- SFiles []string // .s source files
- SwigFiles []string // .swig files
- SwigCXXFiles []string // .swigcxx files
- SysoFiles []string // .syso object files to add to archive
+ CFiles []string // .c source files
+ CXXFiles []string // .cc, .cxx and .cpp source files
+ MFiles []string // .m source files
+ HFiles []string // .h, .hh, .hpp and .hxx source files
+ SFiles []string // .s source files
+ SwigFiles []string // .swig files
+ SwigCXXFiles []string // .swigcxx files
+ SysoFiles []string // .syso object files to add to archive
// Cgo directives
CgoCFLAGS []string // cgo: flags for C compiler
@@ -431,16 +538,23 @@ non-test installation.
In addition to the build flags, the flags handled by 'go test' itself are:
- -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.)
+ -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.
+
+ -exec xprog
+ Run the test binary using xprog. The behavior is the same as
+ in 'go run'. See 'go help run' for details.
-i
Install packages that are dependencies of the test.
Do not run the test.
- -exec xprog
- Run the test binary using xprog. The behavior is the same as
- in 'go run'. See 'go help run' for details.
+ -o file
+ 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.
@@ -488,7 +602,7 @@ Usage:
Vet runs the Go vet command on the packages named by the import paths.
-For more about vet, see 'godoc code.google.com/p/go.tools/cmd/vet'.
+For more about vet, see 'godoc golang.org/x/tools/cmd/vet'.
For more about specifying packages, see 'go help packages'.
To run the vet tool with specific options, run 'go tool vet'.
@@ -681,6 +795,11 @@ A few common code hosting sites have special syntax:
import "launchpad.net/~user/project/branch"
import "launchpad.net/~user/project/branch/sub/directory"
+ IBM DevOps Services (Git)
+
+ import "hub.jazz.net/git/user/project"
+ import "hub.jazz.net/git/user/project/sub/directory"
+
For code hosted on other servers, import paths may either be qualified
with the version control type, or the go tool can dynamically fetch
the import path over https/http and discover where the code resides
@@ -756,7 +875,26 @@ listed in the GOPATH environment variable (see 'go help gopath').
The go command attempts to download the version of the
package appropriate for the Go release being used.
-Run 'go help install' for more.
+Run 'go help get' for more.
+
+Import path checking
+
+When the custom import path feature described above redirects to a
+known code hosting site, each of the resulting packages has two possible
+import paths, using the custom domain or the known hosting site.
+
+A package statement is said to have an "import comment" if it is immediately
+followed (before the next newline) by a comment of one of these two forms:
+
+ package math // import "path"
+ package math /* import "path" * /
+
+The go command will refuse to install a package with an import comment
+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.
+
+See https://golang.org/s/go14customimport for details.
Description of package lists
@@ -812,7 +950,8 @@ single directory, the command is applied to a single synthesized
package made up of exactly those files, ignoring any build constraints
in those files and ignoring any other files in the directory.
-File names that begin with "." or "_" are ignored by the go tool.
+Directory and file names that begin with "." or "_" are ignored
+by the go tool, as are directories named "testdata".
Description of testing flags
@@ -844,6 +983,7 @@ control the execution of any test:
-blockprofile block.out
Write a goroutine blocking profile to the specified file
when all tests are complete.
+ Writes test binary as -c would.
-blockprofilerate n
Control the detail provided in goroutine blocking profiles by
@@ -875,8 +1015,7 @@ control the execution of any test:
Sets -cover.
-coverprofile cover.out
- Write a coverage profile to the specified file after all tests
- have passed.
+ Write a coverage profile to the file after all tests have passed.
Sets -cover.
-cpu 1,2,4
@@ -886,10 +1025,11 @@ control the execution of any test:
-cpuprofile cpu.out
Write a CPU profile to the specified file before exiting.
+ Writes test binary as -c would.
-memprofile mem.out
- Write a memory profile to the specified file after all tests
- have passed.
+ Write a memory profile to the file after all tests have passed.
+ Writes test binary as -c would.
-memprofilerate n
Enable more precise (and expensive) memory profiles by setting
diff --git a/src/cmd/go/generate.go b/src/cmd/go/generate.go
new file mode 100644
index 000000000..baf4d2b55
--- /dev/null
+++ b/src/cmd/go/generate.go
@@ -0,0 +1,398 @@
+// 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 main
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strconv"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+var cmdGenerate = &Command{
+ Run: runGenerate,
+ UsageLine: "generate [-run regexp] [file.go... | packages]",
+ Short: "generate Go files by processing source",
+ Long: `
+Generate runs commands described by directives within existing
+files. Those commands can run any process but the intent is to
+create or update Go source files, for instance by running yacc.
+
+Go generate is never run automatically by go build, go get, go test,
+and so on. It must be run explicitly.
+
+Go generate scans the file for directives, which are lines of
+the form,
+
+ //go:generate command argument...
+
+(note: no leading spaces and no space in "//go") where command
+is the generator to be run, corresponding to an executable file
+that can be run locally. It must either be in the shell path
+(gofmt), a fully qualified path (/usr/you/bin/mytool), or a
+command alias, described below.
+
+Note that go generate does not parse the file, so lines that look
+like directives in comments or multiline strings will be treated
+as directives.
+
+The arguments to the directive are space-separated tokens or
+double-quoted strings passed to the generator as individual
+arguments when it is run.
+
+Quoted strings use Go syntax and are evaluated before execution; a
+quoted string appears as a single argument to the generator.
+
+Go generate sets several variables when it runs the generator:
+
+ $GOARCH
+ The execution architecture (arm, amd64, etc.)
+ $GOOS
+ The execution operating system (linux, windows, etc.)
+ $GOFILE
+ The base name of the file.
+ $GOPACKAGE
+ The name of the package of the file containing the directive.
+
+Other than variable substitution and quoted-string evaluation, no
+special processing such as "globbing" is performed on the command
+line.
+
+As a last step before running the command, any invocations of any
+environment variables with alphanumeric names, such as $GOFILE or
+$HOME, are expanded throughout the command line. The syntax for
+variable expansion is $NAME on all operating systems. Due to the
+order of evaluation, variables are expanded even inside quoted
+strings. If the variable NAME is not set, $NAME expands to the
+empty string.
+
+A directive of the form,
+
+ //go:generate -command xxx args...
+
+specifies, for the remainder of this source file only, that the
+string xxx represents the command identified by the arguments. This
+can be used to create aliases or to handle multiword generators.
+For example,
+
+ //go:generate -command yacc go tool yacc
+
+specifies that the command "yacc" represents the generator
+"go tool yacc".
+
+Generate processes packages in the order given on the command line,
+one at a time. If the command line lists .go files, they are treated
+as a single package. Within a package, generate processes the
+source files in a package in file name order, one at a time. Within
+a source file, generate runs generators in the order they appear
+in the file, one at a time.
+
+If any generator returns an error exit status, "go generate" skips
+all further processing for that package.
+
+The generator is run in the package's source directory.
+
+Go generate accepts one specific flag:
+
+ -run=""
+ if non-empty, specifies a regular expression to
+ select directives whose command matches the expression.
+
+It also accepts the standard build flags -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 specifying packages, see 'go help packages'.
+ `,
+}
+
+var generateRunFlag string // generate -run flag
+
+func init() {
+ addBuildFlags(cmdGenerate)
+ cmdGenerate.Flag.StringVar(&generateRunFlag, "run", "", "")
+}
+
+func runGenerate(cmd *Command, args []string) {
+ // Even if the arguments are .go files, this loop suffices.
+ for _, pkg := range packages(args) {
+ for _, file := range pkg.gofiles {
+ if !generate(pkg.Name, file) {
+ break
+ }
+ }
+ }
+}
+
+// generate runs the generation directives for a single file.
+func generate(pkg, absFile string) bool {
+ fd, err := os.Open(absFile)
+ if err != nil {
+ log.Fatalf("generate: %s", err)
+ }
+ defer fd.Close()
+ g := &Generator{
+ r: fd,
+ path: absFile,
+ pkg: pkg,
+ commands: make(map[string][]string),
+ }
+ return g.run()
+}
+
+// A Generator represents the state of a single Go source file
+// being scanned for generator commands.
+type Generator struct {
+ r io.Reader
+ path string // full rooted path name.
+ dir string // full rooted directory of file.
+ file string // base name of file.
+ pkg string
+ commands map[string][]string
+ lineNum int
+}
+
+// run runs the generators in the current file.
+func (g *Generator) run() (ok bool) {
+ // Processing below here calls g.errorf on failure, which does panic(stop).
+ // If we encounter an error, we abort the package.
+ defer func() {
+ e := recover()
+ if e != nil {
+ ok = false
+ if e != stop {
+ panic(e)
+ }
+ setExitStatus(1)
+ }
+ }()
+ g.dir, g.file = filepath.Split(g.path)
+ g.dir = filepath.Clean(g.dir) // No final separator please.
+ if buildV {
+ fmt.Fprintf(os.Stderr, "%s\n", shortPath(g.path))
+ }
+
+ // Scan for lines that start "//go:generate".
+ // Can't use bufio.Scanner because it can't handle long lines,
+ // which are likely to appear when using generate.
+ input := bufio.NewReader(g.r)
+ var err error
+ // One line per loop.
+ for {
+ g.lineNum++ // 1-indexed.
+ var buf []byte
+ buf, err = input.ReadSlice('\n')
+ if err == bufio.ErrBufferFull {
+ // Line too long - consume and ignore.
+ if isGoGenerate(buf) {
+ g.errorf("directive too long")
+ }
+ for err == bufio.ErrBufferFull {
+ _, err = input.ReadSlice('\n')
+ }
+ if err != nil {
+ break
+ }
+ continue
+ }
+
+ if err != nil {
+ // Check for marker at EOF without final \n.
+ if err == io.EOF && isGoGenerate(buf) {
+ err = io.ErrUnexpectedEOF
+ }
+ break
+ }
+
+ if !isGoGenerate(buf) {
+ continue
+ }
+
+ words := g.split(string(buf))
+ if len(words) == 0 {
+ g.errorf("no arguments to directive")
+ }
+ if words[0] == "-command" {
+ g.setShorthand(words)
+ continue
+ }
+ // Run the command line.
+ if buildN || buildX {
+ fmt.Fprintf(os.Stderr, "%s\n", strings.Join(words, " "))
+ }
+ if buildN {
+ continue
+ }
+ g.exec(words)
+ }
+ if err != nil && err != io.EOF {
+ g.errorf("error reading %s: %s", shortPath(g.path), err)
+ }
+ return true
+}
+
+func isGoGenerate(buf []byte) bool {
+ return bytes.HasPrefix(buf, []byte("//go:generate ")) || bytes.HasPrefix(buf, []byte("//go:generate\t"))
+}
+
+// split breaks the line into words, evaluating quoted
+// strings and evaluating environment variables.
+// The initial //go:generate element is present in line.
+func (g *Generator) split(line string) []string {
+ // Parse line, obeying quoted strings.
+ var words []string
+ line = line[len("//go:generate ") : len(line)-1] // Drop preamble and final newline.
+ // One (possibly quoted) word per iteration.
+Words:
+ for {
+ line = strings.TrimLeft(line, " \t")
+ if len(line) == 0 {
+ break
+ }
+ if line[0] == '"' {
+ for i := 1; i < len(line); i++ {
+ c := line[i] // Only looking for ASCII so this is OK.
+ switch c {
+ case '\\':
+ if i+1 == len(line) {
+ g.errorf("bad backslash")
+ }
+ i++ // Absorb next byte (If it's a multibyte we'll get an error in Unquote).
+ case '"':
+ word, err := strconv.Unquote(line[0 : i+1])
+ if err != nil {
+ g.errorf("bad quoted string")
+ }
+ words = append(words, word)
+ line = line[i+1:]
+ // Check the next character is space or end of line.
+ if len(line) > 0 && line[0] != ' ' && line[0] != '\t' {
+ g.errorf("expect space after quoted argument")
+ }
+ continue Words
+ }
+ }
+ g.errorf("mismatched quoted string")
+ }
+ i := strings.IndexAny(line, " \t")
+ if i < 0 {
+ i = len(line)
+ }
+ words = append(words, line[0:i])
+ line = line[i:]
+ }
+ // Substitute command if required.
+ if len(words) > 0 && g.commands[words[0]] != nil {
+ // Replace 0th word by command substitution.
+ words = append(g.commands[words[0]], words[1:]...)
+ }
+ // Substitute environment variables.
+ for i, word := range words {
+ words[i] = g.expandEnv(word)
+ }
+ return words
+}
+
+var stop = fmt.Errorf("error in generation")
+
+// errorf logs an error message prefixed with the file and line number.
+// It then exits the program (with exit status 1) because generation stops
+// at the first error.
+func (g *Generator) errorf(format string, args ...interface{}) {
+ fmt.Fprintf(os.Stderr, "%s:%d: %s\n", shortPath(g.path), g.lineNum,
+ fmt.Sprintf(format, args...))
+ panic(stop)
+}
+
+// expandEnv expands any $XXX invocations in word.
+func (g *Generator) expandEnv(word string) string {
+ if !strings.ContainsRune(word, '$') {
+ return word
+ }
+ var buf bytes.Buffer
+ var w int
+ var r rune
+ for i := 0; i < len(word); i += w {
+ r, w = utf8.DecodeRuneInString(word[i:])
+ if r != '$' {
+ buf.WriteRune(r)
+ continue
+ }
+ w += g.identLength(word[i+w:])
+ envVar := word[i+1 : i+w]
+ var sub string
+ switch envVar {
+ case "GOARCH":
+ sub = runtime.GOARCH
+ case "GOOS":
+ sub = runtime.GOOS
+ case "GOFILE":
+ sub = g.file
+ case "GOPACKAGE":
+ sub = g.pkg
+ default:
+ sub = os.Getenv(envVar)
+ }
+ buf.WriteString(sub)
+ }
+ return buf.String()
+}
+
+// identLength returns the length of the identifier beginning the string.
+func (g *Generator) identLength(word string) int {
+ for i, r := range word {
+ if r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) {
+ continue
+ }
+ return i
+ }
+ return len(word)
+}
+
+// setShorthand installs a new shorthand as defined by a -command directive.
+func (g *Generator) setShorthand(words []string) {
+ // Create command shorthand.
+ if len(words) == 1 {
+ g.errorf("no command specified for -command")
+ }
+ command := words[1]
+ if g.commands[command] != nil {
+ g.errorf("command %q defined multiply defined", command)
+ }
+ g.commands[command] = words[2:len(words):len(words)] // force later append to make copy
+}
+
+// exec runs the command specified by the argument. The first word is
+// the command name itself.
+func (g *Generator) exec(words []string) {
+ cmd := exec.Command(words[0], words[1:]...)
+ // Standard in and out of generator should be the usual.
+ cmd.Stdout = os.Stdout
+ 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, os.Environ())
+ 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
new file mode 100644
index 000000000..660ebabbe
--- /dev/null
+++ b/src/cmd/go/generate_test.go
@@ -0,0 +1,48 @@
+// 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 main
+
+import (
+ "reflect"
+ "runtime"
+ "testing"
+)
+
+type splitTest struct {
+ in string
+ out []string
+}
+
+var splitTests = []splitTest{
+ {"", nil},
+ {"x", []string{"x"}},
+ {" a b\tc ", []string{"a", "b", "c"}},
+ {` " a " `, []string{" a "}},
+ {"$GOARCH", []string{runtime.GOARCH}},
+ {"$GOOS", []string{runtime.GOOS}},
+ {"$GOFILE", []string{"proc.go"}},
+ {"$GOPACKAGE", []string{"sys"}},
+ {"a $XXNOTDEFINEDXX b", []string{"a", "", "b"}},
+ {"/$XXNOTDEFINED/", []string{"//"}},
+ {"yacc -o $GOARCH/yacc_$GOFILE", []string{"go", "tool", "yacc", "-o", runtime.GOARCH + "/yacc_proc.go"}},
+}
+
+func TestGenerateCommandParse(t *testing.T) {
+ g := &Generator{
+ r: nil, // Unused here.
+ path: "/usr/ken/sys/proc.go",
+ dir: "/usr/ken/sys",
+ file: "proc.go",
+ pkg: "sys",
+ commands: make(map[string][]string),
+ }
+ g.setShorthand([]string{"-command", "yacc", "go", "tool", "yacc"})
+ for _, test := range splitTests {
+ got := g.split("//go:generate " + test.in + "\n")
+ if !reflect.DeepEqual(got, test.out) {
+ t.Errorf("split(%q): got %q expected %q", test.in, got, test.out)
+ }
+ }
+}
diff --git a/src/cmd/go/get.go b/src/cmd/go/get.go
index e708fcf77..86e169761 100644
--- a/src/cmd/go/get.go
+++ b/src/cmd/go/get.go
@@ -16,7 +16,7 @@ import (
)
var cmdGet = &Command{
- UsageLine: "get [-d] [-fix] [-t] [-u] [build flags] [packages]",
+ UsageLine: "get [-d] [-f] [-fix] [-t] [-u] [build flags] [packages]",
Short: "download and install packages and dependencies",
Long: `
Get downloads and installs the packages named by the import paths,
@@ -25,6 +25,11 @@ along with their dependencies.
The -d flag instructs get to stop after downloading the packages; that is,
it instructs get not to install the packages.
+The -f flag, valid only when -u is set, forces get -u not to verify that
+each package has been checked out from the source control repository
+implied by its import path. This can be useful if the source is a local fork
+of the original.
+
The -fix flag instructs get to run the fix tool on the downloaded packages
before resolving dependencies or building the code.
@@ -53,6 +58,7 @@ See also: go build, go install, go clean.
}
var getD = cmdGet.Flag.Bool("d", false, "")
+var getF = cmdGet.Flag.Bool("f", false, "")
var getT = cmdGet.Flag.Bool("t", false, "")
var getU = cmdGet.Flag.Bool("u", false, "")
var getFix = cmdGet.Flag.Bool("fix", false, "")
@@ -63,6 +69,10 @@ func init() {
}
func runGet(cmd *Command, args []string) {
+ if *getF && !*getU {
+ fatalf("go get: cannot use -f flag without -u")
+ }
+
// Phase 1. Download/update.
var stk importStack
for _, arg := range downloadPaths(args) {
@@ -151,7 +161,9 @@ func download(arg string, stk *importStack, getTestDeps bool) {
}
// Only process each package once.
- if downloadCache[arg] {
+ // (Unless we're fetching test dependencies for this package,
+ // in which case we want to process it again.)
+ if downloadCache[arg] && !getTestDeps {
return
}
downloadCache[arg] = true
@@ -264,6 +276,25 @@ func downloadPackage(p *Package) error {
return err
}
repo = "<local>" // should be unused; make distinctive
+
+ // Double-check where it came from.
+ if *getU && vcs.remoteRepo != nil && !*getF {
+ dir := filepath.Join(p.build.SrcRoot, rootPath)
+ if remote, err := vcs.remoteRepo(vcs, dir); err == nil {
+ if rr, err := repoRootForImportPath(p.ImportPath); err == nil {
+ repo := rr.repo
+ if rr.vcs.resolveRepo != nil {
+ resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo)
+ if err == nil {
+ repo = resolved
+ }
+ }
+ if remote != repo {
+ return fmt.Errorf("%s is from %s, should be from %s", dir, remote, repo)
+ }
+ }
+ }
+ }
} else {
// Analyze the import path to determine the version control system,
// repository, and the import path for the root of the repository.
diff --git a/src/cmd/go/go_windows_test.go b/src/cmd/go/go_windows_test.go
new file mode 100644
index 000000000..53d695ccc
--- /dev/null
+++ b/src/cmd/go/go_windows_test.go
@@ -0,0 +1,55 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+func TestAbsolutePath(t *testing.T) {
+ tmp, err := ioutil.TempDir("", "TestAbsolutePath")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmp)
+
+ file := filepath.Join(tmp, "a.go")
+ err = ioutil.WriteFile(file, []byte{}, 0644)
+ if err != nil {
+ t.Fatal(err)
+ }
+ dir := filepath.Join(tmp, "dir")
+ err = os.Mkdir(dir, 0777)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ wd, err := os.Getwd()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Chdir(wd)
+
+ // Chdir so current directory and a.go reside on the same drive.
+ err = os.Chdir(dir)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ noVolume := file[len(filepath.VolumeName(file)):]
+ wrongPath := filepath.Join(dir, noVolume)
+ output, err := exec.Command("go", "build", noVolume).CombinedOutput()
+ if err == nil {
+ t.Fatal("build should fail")
+ }
+ if strings.Contains(string(output), wrongPath) {
+ t.Fatalf("wrong output found: %v %v", err, string(output))
+ }
+}
diff --git a/src/cmd/go/help.go b/src/cmd/go/help.go
index 40da7e1f5..c590fdb37 100644
--- a/src/cmd/go/help.go
+++ b/src/cmd/go/help.go
@@ -81,7 +81,8 @@ single directory, the command is applied to a single synthesized
package made up of exactly those files, ignoring any build constraints
in those files and ignoring any other files in the directory.
-File names that begin with "." or "_" are ignored by the go tool.
+Directory and file names that begin with "." or "_" are ignored
+by the go tool, as are directories named "testdata".
`,
}
@@ -154,6 +155,11 @@ A few common code hosting sites have special syntax:
import "launchpad.net/~user/project/branch"
import "launchpad.net/~user/project/branch/sub/directory"
+ IBM DevOps Services (Git)
+
+ import "hub.jazz.net/git/user/project"
+ import "hub.jazz.net/git/user/project/sub/directory"
+
For code hosted on other servers, import paths may either be qualified
with the version control type, or the go tool can dynamically fetch
the import path over https/http and discover where the code resides
@@ -229,7 +235,26 @@ listed in the GOPATH environment variable (see 'go help gopath').
The go command attempts to download the version of the
package appropriate for the Go release being used.
-Run 'go help install' for more.
+Run 'go help get' for more.
+
+Import path checking
+
+When the custom import path feature described above redirects to a
+known code hosting site, each of the resulting packages has two possible
+import paths, using the custom domain or the known hosting site.
+
+A package statement is said to have an "import comment" if it is immediately
+followed (before the next newline) by a comment of one of these two forms:
+
+ package math // import "path"
+ package math /* import "path" */
+
+The go command will refuse to install a package with an import comment
+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.
+
+See https://golang.org/s/go14customimport for details.
`,
}
diff --git a/src/cmd/go/list.go b/src/cmd/go/list.go
index 0ead43502..fbf96167f 100644
--- a/src/cmd/go/list.go
+++ b/src/cmd/go/list.go
@@ -30,28 +30,29 @@ syntax of package template. The default output is equivalent to -f
'{{.ImportPath}}'. The struct being passed to the template is:
type Package struct {
- Dir string // directory containing package sources
- ImportPath string // import path of package in dir
- Name string // package name
- Doc string // package documentation string
- Target string // install path
- Goroot bool // is this package in the Go root?
- Standard bool // is this package part of the standard Go library?
- Stale bool // would 'go install' do anything for this package?
- Root string // Go root or Go path dir containing this package
+ Dir string // directory containing package sources
+ ImportPath string // import path of package in dir
+ ImportComment string // path in import comment on package statement
+ Name string // package name
+ Doc string // package documentation string
+ Target string // install path
+ Goroot bool // is this package in the Go root?
+ Standard bool // is this package part of the standard Go library?
+ Stale bool // would 'go install' do anything for this package?
+ Root string // Go root or Go path dir containing this package
// Source files
- GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
- CgoFiles []string // .go sources files that import "C"
+ GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+ CgoFiles []string // .go sources files that import "C"
IgnoredGoFiles []string // .go sources ignored due to build constraints
- CFiles []string // .c source files
- CXXFiles []string // .cc, .cxx and .cpp source files
- MFiles []string // .m source files
- HFiles []string // .h, .hh, .hpp and .hxx source files
- SFiles []string // .s source files
- SwigFiles []string // .swig files
- SwigCXXFiles []string // .swigcxx files
- SysoFiles []string // .syso object files to add to archive
+ CFiles []string // .c source files
+ CXXFiles []string // .cc, .cxx and .cpp source files
+ MFiles []string // .m source files
+ HFiles []string // .h, .hh, .hpp and .hxx source files
+ SFiles []string // .s source files
+ SwigFiles []string // .swig files
+ SwigCXXFiles []string // .swigcxx files
+ SysoFiles []string // .syso object files to add to archive
// Cgo directives
CgoCFLAGS []string // cgo: flags for C compiler
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
index 5b1194aaa..9691f39c7 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -79,6 +79,7 @@ var commands = []*Command{
cmdEnv,
cmdFix,
cmdFmt,
+ cmdGenerate,
cmdGet,
cmdInstall,
cmdList,
@@ -536,7 +537,7 @@ func matchPackages(pattern string) []string {
})
for _, src := range buildContext.SrcDirs() {
- if pattern == "std" && src != gorootSrcPkg {
+ if pattern == "std" && src != gorootSrc {
continue
}
src = filepath.Clean(src) + string(filepath.Separator)
@@ -618,7 +619,7 @@ func matchPackagesInFS(pattern string) []string {
// The initial case is not Cleaned, though, so we do this explicitly.
//
// This converts a path like "./io/" to "io". Without this step, running
- // "cd $GOROOT/src/pkg; go list ./io/..." would incorrectly skip the io
+ // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io
// package, because prepending the prefix "./" to the unclean path would
// result in "././io", and match("././io") returns false.
path = filepath.Clean(path)
diff --git a/src/cmd/go/mkdoc.sh b/src/cmd/go/mkdoc.sh
index 12fd7ba3e..e15e8809c 100755
--- a/src/cmd/go/mkdoc.sh
+++ b/src/cmd/go/mkdoc.sh
@@ -4,6 +4,6 @@
# license that can be found in the LICENSE file.
go install # So the next line will produce updated documentation.
-go help documentation > doc.go
+go help documentation | sed 's; \*/; * /;' >doc.go
gofmt -w doc.go
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index d45df265b..b71feb7a6 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -14,6 +14,7 @@ import (
"os"
pathpkg "path"
"path/filepath"
+ "runtime"
"sort"
"strings"
"time"
@@ -25,16 +26,17 @@ type Package struct {
// Note: These fields are part of the go command's public API.
// See list.go. It is okay to add fields, but not to change or
// remove existing ones. Keep in sync with list.go
- Dir string `json:",omitempty"` // directory containing package sources
- ImportPath string `json:",omitempty"` // import path of package in dir
- Name string `json:",omitempty"` // package name
- Doc string `json:",omitempty"` // package documentation string
- Target string `json:",omitempty"` // install path
- Goroot bool `json:",omitempty"` // is this package found in the Go root?
- Standard bool `json:",omitempty"` // is this package part of the standard Go library?
- Stale bool `json:",omitempty"` // would 'go install' do anything for this package?
- Root string `json:",omitempty"` // Go root or Go path dir containing this package
- ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
+ Dir string `json:",omitempty"` // directory containing package sources
+ ImportPath string `json:",omitempty"` // import path of package in dir
+ ImportComment string `json:",omitempty"` // path in import comment on package statement
+ Name string `json:",omitempty"` // package name
+ Doc string `json:",omitempty"` // package documentation string
+ Target string `json:",omitempty"` // install path
+ Goroot bool `json:",omitempty"` // is this package found in the Go root?
+ Standard bool `json:",omitempty"` // is this package part of the standard Go library?
+ Stale bool `json:",omitempty"` // would 'go install' do anything for this package?
+ Root string `json:",omitempty"` // Go root or Go path dir containing this package
+ ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
// Source files
GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
@@ -103,6 +105,7 @@ func (p *Package) copyBuild(pp *build.Package) {
p.Dir = pp.Dir
p.ImportPath = pp.ImportPath
+ p.ImportComment = pp.ImportComment
p.Name = pp.Name
p.Doc = pp.Doc
p.Root = pp.Root
@@ -218,7 +221,7 @@ func dirToImportPath(dir string) string {
}
func makeImportValid(r rune) rune {
- // Should match Go spec, compilers, and ../../pkg/go/parser/parser.go:/isValidImport.
+ // Should match Go spec, compilers, and ../../go/parser/parser.go:/isValidImport.
const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
return '_'
@@ -244,6 +247,9 @@ func loadImport(path string, srcDir string, stk *importStack, importPos []token.
importPath = dirToImportPath(filepath.Join(srcDir, path))
}
if p := packageCache[importPath]; p != nil {
+ if perr := disallowInternal(srcDir, p, stk); perr != p {
+ return perr
+ }
return reusePackage(p, stk)
}
@@ -258,11 +264,14 @@ func loadImport(path string, srcDir string, stk *importStack, importPos []token.
//
// TODO: After Go 1, decide when to pass build.AllowBinary here.
// See issue 3268 for mistakes to avoid.
- bp, err := buildContext.Import(path, srcDir, 0)
+ bp, err := buildContext.Import(path, srcDir, build.ImportComment)
bp.ImportPath = importPath
if gobin != "" {
bp.BinDir = gobin
}
+ if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path {
+ 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 {
pos := importPos[0]
@@ -270,6 +279,10 @@ func loadImport(path string, srcDir string, stk *importStack, importPos []token.
p.Error.Pos = pos.String()
}
+ if perr := disallowInternal(srcDir, p, stk); perr != p {
+ return perr
+ }
+
return p
}
@@ -298,12 +311,82 @@ func reusePackage(p *Package, stk *importStack) *Package {
return p
}
+// disallowInternal checks that srcDir is allowed to import p.
+// If the import is allowed, disallowInternal returns the original package p.
+// If not, it returns a new package containing just an appropriate error.
+func disallowInternal(srcDir string, p *Package, stk *importStack) *Package {
+ // golang.org/s/go14internal:
+ // An import of a path containing the element “internal”
+ // is disallowed if the importing code is outside the tree
+ // rooted at the parent of the “internal” directory.
+ //
+ // ... For Go 1.4, we will implement the rule first for $GOROOT, but not $GOPATH.
+
+ // Only applies to $GOROOT.
+ if !p.Standard {
+ return p
+ }
+
+ // The stack includes p.ImportPath.
+ // If that's the only thing on the stack, we started
+ // with a name given on the command line, not an
+ // import. Anything listed on the command line is fine.
+ if len(*stk) == 1 {
+ return p
+ }
+
+ // Check for "internal" element: four cases depending on begin of string and/or end of string.
+ i, ok := findInternal(p.ImportPath)
+ if !ok {
+ return p
+ }
+
+ // Internal is present.
+ // Map import path back to directory corresponding to parent of internal.
+ if i > 0 {
+ i-- // rewind over slash in ".../internal"
+ }
+ parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)]
+ if hasPathPrefix(filepath.ToSlash(srcDir), filepath.ToSlash(parent)) {
+ return p
+ }
+
+ // Internal is present, and srcDir is outside parent's tree. Not allowed.
+ perr := *p
+ perr.Error = &PackageError{
+ ImportStack: stk.copy(),
+ Err: "use of internal package not allowed",
+ }
+ perr.Incomplete = true
+ return &perr
+}
+
+// findInternal looks for the final "internal" path element in the given import path.
+// If there isn't one, findInternal returns ok=false.
+// Otherwise, findInternal returns ok=true and the index of the "internal".
+func findInternal(path string) (index int, ok bool) {
+ // Four cases, depending on internal at start/end of string or not.
+ // The order matters: we must return the index of the final element,
+ // because the final one produces the most restrictive requirement
+ // on the importer.
+ switch {
+ case strings.HasSuffix(path, "/internal"):
+ return len(path) - len("internal"), true
+ case strings.Contains(path, "/internal/"):
+ return strings.LastIndex(path, "/internal/") + 1, true
+ case path == "internal", strings.HasPrefix(path, "internal/"):
+ return 0, true
+ }
+ return 0, false
+}
+
type targetDir int
const (
- toRoot targetDir = iota // to bin dir inside package root (default)
- toTool // GOROOT/pkg/tool
- toBin // GOROOT/bin
+ toRoot targetDir = iota // to bin dir inside package root (default)
+ toTool // GOROOT/pkg/tool
+ toBin // GOROOT/bin
+ stalePath // the old import path; fail to build
)
// goTools is a map of Go program import path to install target directory.
@@ -316,10 +399,14 @@ var goTools = map[string]targetDir{
"cmd/nm": toTool,
"cmd/objdump": toTool,
"cmd/pack": toTool,
+ "cmd/pprof": toTool,
"cmd/yacc": toTool,
- "code.google.com/p/go.tools/cmd/cover": toTool,
- "code.google.com/p/go.tools/cmd/godoc": toBin,
- "code.google.com/p/go.tools/cmd/vet": toTool,
+ "golang.org/x/tools/cmd/cover": toTool,
+ "golang.org/x/tools/cmd/godoc": toBin,
+ "golang.org/x/tools/cmd/vet": toTool,
+ "code.google.com/p/go.tools/cmd/cover": stalePath,
+ "code.google.com/p/go.tools/cmd/godoc": stalePath,
+ "code.google.com/p/go.tools/cmd/vet": stalePath,
}
// expandScanner expands a scanner.List error into all the errors in the list.
@@ -380,6 +467,13 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
}
if p.Name == "main" {
+ // Report an error when the old code.google.com/p/go.tools paths are used.
+ if goTools[p.ImportPath] == stalePath {
+ newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1)
+ e := fmt.Sprintf("the %v command has moved; use %v instead.", p.ImportPath, newPath)
+ p.Error = &PackageError{Err: e}
+ return p
+ }
_, elem := filepath.Split(p.Dir)
full := buildContext.GOOS + "_" + buildContext.GOARCH + "/" + elem
if buildContext.GOOS != toolGOOS || buildContext.GOARCH != toolGOARCH {
@@ -482,7 +576,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
// Build list of imported packages and full dependency list.
imports := make([]*Package, 0, len(p.Imports))
- deps := make(map[string]bool)
+ deps := make(map[string]*Package)
for i, path := range importPaths {
if path == "C" {
continue
@@ -502,10 +596,10 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
path = p1.ImportPath
importPaths[i] = path
}
- deps[path] = true
+ deps[path] = p1
imports = append(imports, p1)
- for _, dep := range p1.Deps {
- deps[dep] = true
+ for _, dep := range p1.deps {
+ deps[dep.ImportPath] = dep
}
if p1.Incomplete {
p.Incomplete = true
@@ -519,7 +613,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
}
sort.Strings(p.Deps)
for _, dep := range p.Deps {
- p1 := packageCache[dep]
+ p1 := deps[dep]
if p1 == nil {
panic("impossible: missing entry in package cache for " + dep + " imported by " + p.ImportPath)
}
@@ -535,6 +629,16 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
}
p.Target = p.target
+ // Check for C code compiled with Plan 9 C compiler.
+ // No longer allowed except in runtime and runtime/cgo, for now.
+ if len(p.CFiles) > 0 && !p.usesCgo() && (!p.Standard || p.ImportPath != "runtime") {
+ p.Error = &PackageError{
+ ImportStack: stk.copy(),
+ Err: fmt.Sprintf("C source files not allowed when not using cgo: %s", strings.Join(p.CFiles, " ")),
+ }
+ return p
+ }
+
// In the absence of errors lower in the dependency tree,
// check for case-insensitive collisions of import paths.
if len(p.DepsErrors) == 0 {
@@ -596,6 +700,12 @@ func computeStale(pkgs ...*Package) {
}
}
+// The runtime version string takes one of two forms:
+// "go1.X[.Y]" for Go releases, and "devel +hash" at tip.
+// Determine whether we are in a released copy by
+// inspecting the version.
+var isGoRelease = strings.HasPrefix(runtime.Version(), "go1")
+
// isStale reports whether package p needs to be rebuilt.
func isStale(p *Package, topRoot map[string]bool) bool {
if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
@@ -616,7 +726,16 @@ func isStale(p *Package, topRoot map[string]bool) bool {
return false
}
- if buildA || p.target == "" || p.Stale {
+ // If we are running a release copy of Go, do not rebuild the standard packages.
+ // They may not be writable anyway, but they are certainly not changing.
+ // This makes 'go build -a' skip the standard packages when using an official release.
+ // See issue 4106 and issue 8290.
+ pkgBuildA := buildA
+ if p.Standard && isGoRelease {
+ pkgBuildA = false
+ }
+
+ if pkgBuildA || p.target == "" || p.Stale {
return true
}
@@ -704,24 +823,13 @@ func loadPackage(arg string, stk *importStack) *Package {
arg = sub
}
}
- if strings.HasPrefix(arg, "cmd/") {
+ if strings.HasPrefix(arg, "cmd/") && !strings.Contains(arg[4:], "/") {
if p := cmdCache[arg]; p != nil {
return p
}
stk.push(arg)
defer stk.pop()
- if strings.Contains(arg[4:], "/") {
- p := &Package{
- Error: &PackageError{
- ImportStack: stk.copy(),
- Err: fmt.Sprintf("invalid import path: cmd/... is reserved for Go commands"),
- hard: true,
- },
- }
- return p
- }
-
bp, err := buildContext.ImportDir(filepath.Join(gorootSrc, arg), 0)
bp.ImportPath = arg
bp.Goroot = true
diff --git a/src/cmd/go/test.bash b/src/cmd/go/test.bash
index 0060ce218..e0f066f18 100755
--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -4,18 +4,22 @@
# license that can be found in the LICENSE file.
set -e
-go build -o testgo
+go build -tags testgo -o testgo
go() {
echo TEST ERROR: ran go, not testgo: go "$@" >&2
exit 2
}
started=false
+testdesc=""
+nl="
+"
TEST() {
if $started; then
stop
fi
echo TEST: "$@"
+ testdesc="$@"
started=true
ok=true
}
@@ -29,6 +33,7 @@ stop() {
echo PASS
else
echo FAIL
+ testfail="$testfail $testdesc$nl"
allok=false
fi
}
@@ -55,12 +60,63 @@ if ! grep -q "^$fn:" $d/err.out; then
fi
rm -r $d
+TEST 'program name in crash messages'
+linker=$(./testgo env GOCHAR)l
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+./testgo build -ldflags -crash_for_testing $(./testgo env GOROOT)/test/helloworld.go 2>$d/err.out || true
+if ! grep -q "/tool/.*/$linker" $d/err.out; then
+ echo "missing linker name in error message"
+ cat $d/err.out
+ ok=false
+fi
+rm -r $d
+
+TEST broken tests without Test functions all fail
+d=$(mktemp -d -t testgoXXX)
+./testgo test ./testdata/src/badtest/... >$d/err 2>&1 || true
+if grep -q '^ok' $d/err; then
+ echo test passed unexpectedly:
+ grep '^ok' $d/err
+ ok=false
+elif ! grep -q 'FAIL.*badtest/badexec' $d/err || ! grep -q 'FAIL.*badtest/badsyntax' $d/err || ! grep -q 'FAIL.*badtest/badvar' $d/err; then
+ echo test did not run everything
+ cat $d/err
+ ok=false
+fi
+rm -rf $d
+
+TEST 'go build -a in dev branch'
+./testgo install math || ok=false # should be up to date already but just in case
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+if ! TESTGO_IS_GO_RELEASE=0 ./testgo build -v -a math 2>$d/err.out; then
+ cat $d/err.out
+ ok=false
+elif ! grep -q runtime $d/err.out; then
+ echo "testgo build -a math in dev branch DID NOT build runtime, but should have"
+ cat $d/err.out
+ ok=false
+fi
+rm -r $d
+
+TEST 'go build -a in release branch'
+./testgo install math || ok=false # should be up to date already but just in case
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+if ! TESTGO_IS_GO_RELEASE=1 ./testgo build -v -a math 2>$d/err.out; then
+ cat $d/err.out
+ ok=false
+elif grep -q runtime $d/err.out; then
+ echo "testgo build -a math in dev branch DID build runtime, but should NOT have"
+ cat $d/err.out
+ ok=false
+fi
+rm -r $d
+
# Test local (./) imports.
testlocal() {
local="$1"
TEST local imports $2 '(easy)'
- ./testgo build -o hello "testdata/$local/easy.go"
- ./hello >hello.out
+ ./testgo build -o hello "testdata/$local/easy.go" || ok=false
+ ./hello >hello.out || ok=false
if ! grep -q '^easysub\.Hello' hello.out; then
echo "testdata/$local/easy.go did not generate expected output"
cat hello.out
@@ -68,8 +124,8 @@ testlocal() {
fi
TEST local imports $2 '(easysub)'
- ./testgo build -o hello "testdata/$local/easysub/main.go"
- ./hello >hello.out
+ ./testgo build -o hello "testdata/$local/easysub/main.go" || ok=false
+ ./hello >hello.out || ok=false
if ! grep -q '^easysub\.Hello' hello.out; then
echo "testdata/$local/easysub/main.go did not generate expected output"
cat hello.out
@@ -77,8 +133,8 @@ testlocal() {
fi
TEST local imports $2 '(hard)'
- ./testgo build -o hello "testdata/$local/hard.go"
- ./hello >hello.out
+ ./testgo build -o hello "testdata/$local/hard.go" || ok=false
+ ./hello >hello.out || ok=false
if ! grep -q '^sub\.Hello' hello.out || ! grep -q '^subsub\.Hello' hello.out ; then
echo "testdata/$local/hard.go did not generate expected output"
cat hello.out
@@ -105,6 +161,132 @@ cp -R testdata/local "testdata/$bad"
testlocal "$bad" 'with bad characters in path'
rm -rf "testdata/$bad"
+TEST 'internal packages in $GOROOT are respected'
+if ./testgo build -v ./testdata/testinternal >testdata/std.out 2>&1; then
+ echo "go build ./testdata/testinternal succeeded incorrectly"
+ ok=false
+elif ! grep 'use of internal package not allowed' testdata/std.out >/dev/null; then
+ echo "wrong error message for testdata/testinternal"
+ cat std.out
+ ok=false
+fi
+
+TEST 'internal packages outside $GOROOT are not respected'
+if ! ./testgo build -v ./testdata/testinternal2; then
+ echo "go build ./testdata/testinternal2 failed"
+ ok=false
+fi
+
+# Test that 'go get -u' reports moved packages.
+testmove() {
+ vcs=$1
+ url=$2
+ base=$3
+ config=$4
+
+ TEST go get -u notices $vcs package that moved
+ d=$(mktemp -d -t testgoXXX)
+ mkdir -p $d/src
+ if ! GOPATH=$d ./testgo get -d $url; then
+ echo 'go get -d $url failed'
+ ok=false
+ elif ! GOPATH=$d ./testgo get -d -u $url; then
+ echo 'go get -d -u $url failed'
+ ok=false
+ else
+ set +e
+ case "$vcs" in
+ svn)
+ # SVN doesn't believe in text files so we can't just edit the config.
+ # Check out a different repo into the wrong place.
+ rm -rf $d/src/code.google.com/p/rsc-svn
+ GOPATH=$d ./testgo get -d -u code.google.com/p/rsc-svn2/trunk
+ mv $d/src/code.google.com/p/rsc-svn2 $d/src/code.google.com/p/rsc-svn
+ ;;
+ *)
+ echo '1,$s;'"$base"';'"$base"'XXX;
+w
+q' | ed $d/src/$config >/dev/null 2>&1
+ esac
+ set -e
+
+ if GOPATH=$d ./testgo get -d -u $url 2>$d/err; then
+ echo "go get -d -u $url succeeded with wrong remote repo"
+ cat $d/err
+ ok=false
+ elif ! grep 'should be from' $d/err >/dev/null; then
+ echo "go get -d -u $url failed for wrong reason"
+ cat $d/err
+ ok=false
+ fi
+
+ if GOPATH=$d ./testgo get -d -f -u $url 2>$d/err; then
+ echo "go get -d -u $url succeeded with wrong remote repo"
+ cat $d/err
+ ok=false
+ elif ! egrep -i 'validating server certificate|not found' $d/err >/dev/null; then
+ echo "go get -d -f -u $url failed for wrong reason"
+ cat $d/err
+ ok=false
+ fi
+ fi
+ rm -rf $d
+}
+
+testmove hg rsc.io/x86/x86asm x86 rsc.io/x86/.hg/hgrc
+testmove git rsc.io/pdf pdf rsc.io/pdf/.git/config
+testmove svn code.google.com/p/rsc-svn/trunk - -
+
+export GOPATH=$(pwd)/testdata/importcom
+TEST 'import comment - match'
+if ! ./testgo build ./testdata/importcom/works.go; then
+ echo 'go build ./testdata/importcom/works.go failed'
+ ok=false
+fi
+TEST 'import comment - mismatch'
+if ./testgo build ./testdata/importcom/wrongplace.go 2>testdata/err; then
+ echo 'go build ./testdata/importcom/wrongplace.go suceeded'
+ ok=false
+elif ! grep 'wrongplace expects import "my/x"' testdata/err >/dev/null; then
+ echo 'go build did not mention incorrect import:'
+ cat testdata/err
+ ok=false
+fi
+TEST 'import comment - syntax error'
+if ./testgo build ./testdata/importcom/bad.go 2>testdata/err; then
+ echo 'go build ./testdata/importcom/bad.go suceeded'
+ ok=false
+elif ! grep 'cannot parse import comment' testdata/err >/dev/null; then
+ echo 'go build did not mention syntax error:'
+ cat testdata/err
+ ok=false
+fi
+TEST 'import comment - conflict'
+if ./testgo build ./testdata/importcom/conflict.go 2>testdata/err; then
+ echo 'go build ./testdata/importcom/conflict.go suceeded'
+ ok=false
+elif ! grep 'found import comments' testdata/err >/dev/null; then
+ echo 'go build did not mention comment conflict:'
+ cat testdata/err
+ ok=false
+fi
+rm -f ./testdata/err
+unset GOPATH
+
+export GOPATH=$(pwd)/testdata/src
+TEST disallowed C source files
+export GOPATH=$(pwd)/testdata
+if ./testgo build badc 2>testdata/err; then
+ echo 'go build badc succeeded'
+ ok=false
+elif ! grep 'C source files not allowed' testdata/err >/dev/null; then
+ echo 'go test did not say C source files not allowed:'
+ cat testdata/err
+ ok=false
+fi
+rm -f ./testdata/err
+unset GOPATH
+
TEST error message for syntax error in test go file says FAIL
export GOPATH=$(pwd)/testdata
if ./testgo test syntaxerror 2>testdata/err; then
@@ -251,20 +433,20 @@ TEST godoc installs into GOBIN
d=$(mktemp -d -t testgoXXX)
export GOPATH=$d
mkdir $d/gobin
-GOBIN=$d/gobin ./testgo get code.google.com/p/go.tools/cmd/godoc
+GOBIN=$d/gobin ./testgo get golang.org/x/tools/cmd/godoc || ok=false
if [ ! -x $d/gobin/godoc ]; then
echo did not install godoc to '$GOBIN'
- GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc
+ GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' golang.org/x/tools/cmd/godoc || true
ok=false
fi
TEST godoc installs into GOROOT
GOROOT=$(./testgo env GOROOT)
rm -f $GOROOT/bin/godoc
-./testgo install code.google.com/p/go.tools/cmd/godoc
+./testgo install golang.org/x/tools/cmd/godoc || ok=false
if [ ! -x $GOROOT/bin/godoc ]; then
echo did not install godoc to '$GOROOT/bin'
- ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc
+ ./testgo list -f 'Target: {{.Target}}' golang.org/x/tools/cmd/godoc || true
ok=false
fi
@@ -272,36 +454,36 @@ TEST cmd/fix installs into tool
GOOS=$(./testgo env GOOS)
GOARCH=$(./testgo env GOARCH)
rm -f $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix
-./testgo install cmd/fix
+./testgo install cmd/fix || ok=false
if [ ! -x $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix ]; then
echo 'did not install cmd/fix to $GOROOT/pkg/tool'
- GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix
+ GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix || true
ok=false
fi
rm -f $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix
-GOBIN=$d/gobin ./testgo install cmd/fix
+GOBIN=$d/gobin ./testgo install cmd/fix || ok=false
if [ ! -x $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix ]; then
echo 'did not install cmd/fix to $GOROOT/pkg/tool with $GOBIN set'
- GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix
+ GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix || true
ok=false
fi
TEST gopath program installs into GOBIN
mkdir $d/src/progname
echo 'package main; func main() {}' >$d/src/progname/p.go
-GOBIN=$d/gobin ./testgo install progname
+GOBIN=$d/gobin ./testgo install progname || ok=false
if [ ! -x $d/gobin/progname ]; then
echo 'did not install progname to $GOBIN/progname'
- ./testgo list -f 'Target: {{.Target}}' cmd/api
+ ./testgo list -f 'Target: {{.Target}}' cmd/api || true
ok=false
fi
rm -f $d/gobin/progname $d/bin/progname
TEST gopath program installs into GOPATH/bin
-./testgo install progname
+./testgo install progname || ok=false
if [ ! -x $d/bin/progname ]; then
echo 'did not install progname to $GOPATH/bin/progname'
- ./testgo list -f 'Target: {{.Target}}' progname
+ ./testgo list -f 'Target: {{.Target}}' progname || true
ok=false
fi
@@ -330,7 +512,7 @@ fi
# ensure that output of 'go list' is consistent between runs
TEST go list is consistent
-./testgo list std > test_std.list
+./testgo list std > test_std.list || ok=false
if ! ./testgo list std | cmp -s test_std.list - ; then
echo "go list std ordering is inconsistent"
ok=false
@@ -378,9 +560,9 @@ fi
# Test that without GOPATH set, go get should fail
TEST without GOPATH, go get fails
d=$(mktemp -d -t testgoXXX)
-mkdir -p $d/src/pkg
-if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
- echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with $GOPATH unset'
+mkdir -p $d/src
+if GOPATH= GOROOT=$d ./testgo get -d golang.org/x/codereview/cmd/hgpatch ; then
+ echo 'go get golang.org/x/codereview/cmd/hgpatch should not succeed with $GOPATH unset'
ok=false
fi
rm -rf $d
@@ -388,9 +570,9 @@ rm -rf $d
# Test that with GOPATH=$GOROOT, go get should fail
TEST with GOPATH=GOROOT, go get fails
d=$(mktemp -d -t testgoXXX)
-mkdir -p $d/src/pkg
-if GOPATH=$d GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
- echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT'
+mkdir -p $d/src
+if GOPATH=$d GOROOT=$d ./testgo get -d golang.org/x/codereview/cmd/hgpatch ; then
+ echo 'go get golang.org/x/codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT'
ok=false
fi
rm -rf $d
@@ -404,7 +586,7 @@ func main() {
println(extern)
}
EOF
-./testgo run -ldflags '-X main.extern "hello world"' $d/main.go 2>hello.out
+./testgo run -ldflags '-X main.extern "hello world"' $d/main.go 2>hello.out || ok=false
if ! grep -q '^hello world' hello.out; then
echo "ldflags -X main.extern 'hello world' failed. Output:"
cat hello.out
@@ -420,6 +602,30 @@ if [ ! -x strings.test ]; then
fi
rm -f strings.prof strings.test
+TEST go test -cpuprofile -o controls binary location
+./testgo test -cpuprofile strings.prof -o mystrings.test strings || ok=false
+if [ ! -x mystrings.test ]; then
+ echo "go test -cpuprofile -o mystrings.test did not create mystrings.test"
+ ok=false
+fi
+rm -f strings.prof mystrings.test
+
+TEST go test -c -o controls binary location
+./testgo test -c -o mystrings.test strings || ok=false
+if [ ! -x mystrings.test ]; then
+ echo "go test -c -o mystrings.test did not create mystrings.test"
+ ok=false
+fi
+rm -f mystrings.test
+
+TEST go test -o writes binary
+./testgo test -o mystrings.test strings || ok=false
+if [ ! -x mystrings.test ]; then
+ echo "go test -o mystrings.test did not create mystrings.test"
+ ok=false
+fi
+rm -f mystrings.test
+
TEST symlinks do not confuse go list '(issue 4568)'
old=$(pwd)
tmp=$(cd /tmp && pwd -P)
@@ -522,37 +728,56 @@ elif ! grep "case-insensitive file name collision" $d/out >/dev/null; then
fi
TEST go get cover
-./testgo get code.google.com/p/go.tools/cmd/cover || ok=false
+./testgo get golang.org/x/tools/cmd/cover || ok=false
unset GOPATH
rm -rf $d
+TEST go get -t "code.google.com/p/go-get-issue-8181/{a,b}"
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+export GOPATH=$d
+if ./testgo get -t code.google.com/p/go-get-issue-8181/{a,b}; then
+ ./testgo list ... | grep go.tools/godoc > /dev/null || ok=false
+else
+ ok=false
+fi
+unset GOPATH
+rm -rf $d
+
TEST shadowing logic
export GOPATH=$(pwd)/testdata/shadow/root1:$(pwd)/testdata/shadow/root2
# The math in root1 is not "math" because the standard math is.
+set +e
cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/math)
-if [ "$cdir" != "(_$(pwd)/testdata/shadow/root1/src/math) ($GOROOT/src/pkg/math)" ]; then
+set -e
+if [ "$cdir" != "(_$(pwd)/testdata/shadow/root1/src/math) ($GOROOT/src/math)" ]; then
echo shadowed math is not shadowed: "$cdir"
ok=false
fi
# The foo in root1 is "foo".
+set +e
cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/foo)
+set -e
if [ "$cdir" != "(foo) ()" ]; then
echo unshadowed foo is shadowed: "$cdir"
ok=false
fi
# The foo in root2 is not "foo" because the foo in root1 got there first.
+set +e
cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root2/src/foo)
+set -e
if [ "$cdir" != "(_$(pwd)/testdata/shadow/root2/src/foo) ($(pwd)/testdata/shadow/root1/src/foo)" ]; then
echo shadowed foo is not shadowed: "$cdir"
ok=false
fi
# The error for go install should mention the conflicting directory.
-err=$(! ./testgo install ./testdata/shadow/root2/src/foo 2>&1)
+set +e
+err=$(./testgo install ./testdata/shadow/root2/src/foo 2>&1)
+set -e
if [ "$err" != "go install: no install location for $(pwd)/testdata/shadow/root2/src/foo: hidden by $(pwd)/testdata/shadow/root1/src/foo" ]; then
echo wrong shadowed install error: "$err"
ok=false
@@ -741,30 +966,46 @@ echo '
package foo
func F() {}
' >$d/src/x/y/foo/foo.go
+checkbar() {
+ desc="$1"
+ sleep 1
+ touch $d/src/x/y/foo/foo.go
+ if ! ./testgo build -v -i x/y/bar &> $d/err; then
+ echo build -i "$1" failed
+ cat $d/err
+ ok=false
+ elif ! grep x/y/foo $d/err >/dev/null; then
+ echo first build -i "$1" did not build x/y/foo
+ cat $d/err
+ ok=false
+ fi
+ if ! ./testgo build -v -i x/y/bar &> $d/err; then
+ echo second build -i "$1" failed
+ cat $d/err
+ ok=false
+ elif grep x/y/foo $d/err >/dev/null; then
+ echo second build -i "$1" built x/y/foo
+ cat $d/err
+ ok=false
+ fi
+}
+
echo '
package bar
import "x/y/foo"
func F() { foo.F() }
' >$d/src/x/y/bar/bar.go
-if ! ./testgo build -v -i x/y/bar &> $d/err; then
- echo build -i failed
- cat $d/err
- ok=false
-elif ! grep x/y/foo $d/err >/dev/null; then
- echo first build -i did not build x/y/foo
- cat $d/err
- ok=false
-fi
-if ! ./testgo build -v -i x/y/bar &> $d/err; then
- echo second build -i failed
- cat $d/err
- ok=false
-elif grep x/y/foo $d/err >/dev/null; then
- echo second build -i built x/y/foo
- cat $d/err
- ok=false
-fi
-rm -rf $d
+checkbar pkg
+
+TEST build -i installs dependencies for command
+echo '
+package main
+import "x/y/foo"
+func main() { foo.F() }
+' >$d/src/x/y/bar/bar.go
+checkbar cmd
+
+rm -rf $d bar
unset GOPATH
TEST 'go build in test-only directory fails with a good error'
@@ -799,13 +1040,74 @@ fi
TEST 'go test xtestonly works'
export GOPATH=$(pwd)/testdata
-./testgo clean -i xtestonly
+./testgo clean -i xtestonly || ok=false
if ! ./testgo test xtestonly >/dev/null; then
echo "go test xtestonly failed"
ok=false
fi
unset GOPATH
+TEST 'go test builds an xtest containing only non-runnable examples'
+if ! ./testgo test -v ./testdata/norunexample > testdata/std.out; then
+ echo "go test ./testdata/norunexample failed"
+ ok=false
+elif ! grep 'File with non-runnable example was built.' testdata/std.out > /dev/null; then
+ echo "file with non-runnable example was not built"
+ ok=false
+fi
+
+TEST 'go generate handles simple command'
+if ! ./testgo generate ./testdata/generate/test1.go > testdata/std.out; then
+ echo "go test ./testdata/generate/test1.go failed to run"
+ ok=false
+elif ! grep 'Success' testdata/std.out > /dev/null; then
+ echo "go test ./testdata/generate/test1.go generated wrong output"
+ ok=false
+fi
+
+TEST 'go generate handles command alias'
+if ! ./testgo generate ./testdata/generate/test2.go > testdata/std.out; then
+ echo "go test ./testdata/generate/test2.go failed to run"
+ ok=false
+elif ! grep 'Now is the time for all good men' testdata/std.out > /dev/null; then
+ echo "go test ./testdata/generate/test2.go generated wrong output"
+ ok=false
+fi
+
+TEST 'go generate variable substitution'
+if ! ./testgo generate ./testdata/generate/test3.go > testdata/std.out; then
+ echo "go test ./testdata/generate/test3.go failed to run"
+ ok=false
+elif ! grep "$GOARCH test3.go p xyzp/test3.go/123" testdata/std.out > /dev/null; then
+ echo "go test ./testdata/generate/test3.go generated wrong output"
+ ok=false
+fi
+
+TEST go get works with vanity wildcards
+d=$(mktemp -d -t testgoXXX)
+export GOPATH=$d
+if ! ./testgo get -u rsc.io/pdf/...; then
+ ok=false
+elif [ ! -x $d/bin/pdfpasswd ]; then
+ echo did not build rsc.io/pdf/pdfpasswd
+ ok=false
+fi
+unset GOPATH
+rm -rf $d
+
+TEST go vet with external tests
+d=$(mktemp -d -t testgoXXX)
+export GOPATH=$(pwd)/testdata
+if ./testgo vet vetpkg >$d/err 2>&1; then
+ echo "go vet vetpkg passes incorrectly"
+ ok=false
+elif ! grep -q 'missing argument for Printf' $d/err; then
+ echo "go vet vetpkg did not find missing argument for Printf"
+ cat $d/err
+ ok=false
+fi
+unset GOPATH
+rm -rf $d
# clean up
if $started; then stop; fi
@@ -815,6 +1117,7 @@ rm -f testgo
if $allok; then
echo PASS
else
- echo FAIL
+ echo FAIL:
+ echo "$testfail"
exit 1
fi
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index 5935c98db..c81e40639 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -6,6 +6,7 @@ package main
import (
"bytes"
+ "errors"
"fmt"
"go/ast"
"go/build"
@@ -48,7 +49,7 @@ It prints a summary of the test results in the format:
followed by detailed output for each failed package.
'Go test' recompiles each package along with any files with names matching
-the file pattern "*_test.go".
+the file pattern "*_test.go".
Files whose names begin with "_" (including "_test.go") or "." are ignored.
These additional files can contain test functions, benchmark functions, and
example functions. See 'go help testfunc' for more.
@@ -65,16 +66,23 @@ non-test installation.
In addition to the build flags, the flags handled by 'go test' itself are:
- -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.)
+ -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.
+
+ -exec xprog
+ Run the test binary using xprog. The behavior is the same as
+ in 'go run'. See 'go help run' for details.
-i
Install packages that are dependencies of the test.
Do not run the test.
- -exec xprog
- Run the test binary using xprog. The behavior is the same as
- in 'go run'. See 'go help run' for details.
+ -o file
+ 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.
@@ -122,6 +130,7 @@ control the execution of any test:
-blockprofile block.out
Write a goroutine blocking profile to the specified file
when all tests are complete.
+ Writes test binary as -c would.
-blockprofilerate n
Control the detail provided in goroutine blocking profiles by
@@ -153,8 +162,7 @@ control the execution of any test:
Sets -cover.
-coverprofile cover.out
- Write a coverage profile to the specified file after all tests
- have passed.
+ Write a coverage profile to the file after all tests have passed.
Sets -cover.
-cpu 1,2,4
@@ -164,10 +172,11 @@ control the execution of any test:
-cpuprofile cpu.out
Write a CPU profile to the specified file before exiting.
+ Writes test binary as -c would.
-memprofile mem.out
- Write a memory profile to the specified file after all tests
- have passed.
+ Write a memory profile to the file after all tests have passed.
+ Writes test binary as -c would.
-memprofilerate n
Enable more precise (and expensive) memory profiles by setting
@@ -274,10 +283,10 @@ var (
testCoverMode string // -covermode flag
testCoverPaths []string // -coverpkg flag
testCoverPkgs []*Package // -coverpkg flag
+ testO string // -o flag
testProfile bool // some profiling flag
testNeedBinary bool // profile needs to keep binary around
testV bool // -v flag
- testFiles []string // -file flag(s) TODO: not respected
testTimeout string // -timeout flag
testArgs []string
testBench bool
@@ -291,6 +300,7 @@ var testMainDeps = map[string]bool{
// Dependencies for testmain.
"testing": true,
"regexp": true,
+ "os": true,
}
func runTest(cmd *Command, args []string) {
@@ -308,6 +318,9 @@ func runTest(cmd *Command, args []string) {
if testC && len(pkgs) != 1 {
fatalf("cannot use -c flag with multiple packages")
}
+ if testO != "" && len(pkgs) != 1 {
+ fatalf("cannot use -o flag with multiple packages")
+ }
if testProfile && len(pkgs) != 1 {
fatalf("cannot use test profile flag with multiple packages")
}
@@ -522,6 +535,13 @@ func contains(x []string, s string) bool {
return false
}
+var windowsBadWords = []string{
+ "install",
+ "patch",
+ "setup",
+ "update",
+}
+
func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, err error) {
if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
build := b.action(modeBuild, modeBuild, p)
@@ -687,7 +707,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
omitDWARF: !testC && !testNeedBinary,
}
- // The generated main also imports testing and regexp.
+ // The generated main also imports testing, regexp, and os.
stk.push("testmain")
for dep := range testMainDeps {
if dep == ptest.ImportPath {
@@ -723,11 +743,13 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
if err != nil {
return nil, nil, nil, err
}
- if t.NeedTest || ptest.coverMode != "" {
+ if len(ptest.GoFiles) > 0 {
pmain.imports = append(pmain.imports, ptest)
+ t.ImportTest = true
}
- if t.NeedXtest {
+ if pxtest != nil {
pmain.imports = append(pmain.imports, pxtest)
+ t.ImportXtest = true
}
if ptest != p && localCover {
@@ -779,17 +801,54 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
a.objdir = testDir + string(filepath.Separator)
a.objpkg = filepath.Join(testDir, "main.a")
a.target = filepath.Join(testDir, testBinary) + exeSuffix
- pmainAction := a
+ if goos == "windows" {
+ // There are many reserved words on Windows that,
+ // if used in the name of an executable, cause Windows
+ // to try to ask for extra permissions.
+ // The word list includes setup, install, update, and patch,
+ // but it does not appear to be defined anywhere.
+ // We have run into this trying to run the
+ // go.codereview/patch tests.
+ // For package names containing those words, use test.test.exe
+ // instead of pkgname.test.exe.
+ // Note that this file name is only used in the Go command's
+ // temporary directory. If the -c or other flags are
+ // given, the code below will still use pkgname.test.exe.
+ // There are two user-visible effects of this change.
+ // First, you can actually run 'go test' in directories that
+ // have names that Windows thinks are installer-like,
+ // without getting a dialog box asking for more permissions.
+ // Second, in the Windows process listing during go test,
+ // the test shows up as test.test.exe, not pkgname.test.exe.
+ // That second one is a drawback, but it seems a small
+ // price to pay for the test running at all.
+ // If maintaining the list of bad words is too onerous,
+ // we could just do this always on Windows.
+ for _, bad := range windowsBadWords {
+ if strings.Contains(testBinary, bad) {
+ a.target = filepath.Join(testDir, "test.test") + exeSuffix
+ break
+ }
+ }
+ }
+ buildAction = a
if testC || testNeedBinary {
// -c or profiling flag: create action to copy binary to ./test.out.
- runAction = &action{
+ target := filepath.Join(cwd, testBinary+exeSuffix)
+ if testO != "" {
+ target = testO
+ if !filepath.IsAbs(target) {
+ target = filepath.Join(cwd, target)
+ }
+ }
+ buildAction = &action{
f: (*builder).install,
- deps: []*action{pmainAction},
+ deps: []*action{buildAction},
p: pmain,
- target: filepath.Join(cwd, testBinary+exeSuffix),
+ target: target,
}
- pmainAction = runAction // in case we are running the test
+ runAction = buildAction // make sure runAction != nil even if not running test
}
if testC {
printAction = &action{p: p, deps: []*action{runAction}} // nop
@@ -797,7 +856,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
// run test
runAction = &action{
f: (*builder).runTest,
- deps: []*action{pmainAction},
+ deps: []*action{buildAction},
p: p,
ignoreFail: true,
}
@@ -813,7 +872,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
}
}
- return pmainAction, runAction, printAction, nil
+ return buildAction, runAction, printAction, nil
}
func testImportStack(top string, p *Package, target string) []string {
@@ -1057,6 +1116,31 @@ func (b *builder) notest(a *action) error {
return nil
}
+// isTestMain tells whether fn is a TestMain(m *testing.M) function.
+func isTestMain(fn *ast.FuncDecl) bool {
+ if fn.Name.String() != "TestMain" ||
+ fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
+ fn.Type.Params == nil ||
+ len(fn.Type.Params.List) != 1 ||
+ len(fn.Type.Params.List[0].Names) > 1 {
+ return false
+ }
+ ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr)
+ if !ok {
+ return false
+ }
+ // We can't easily check that the type is *testing.M
+ // because we don't know how testing has been imported,
+ // but at least check that it's *M or *something.M.
+ if name, ok := ptr.X.(*ast.Ident); ok && name.Name == "M" {
+ return true
+ }
+ if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == "M" {
+ return true
+ }
+ return false
+}
+
// isTest tells whether name looks like a test (or benchmark, according to prefix).
// It is a Test (say) if there is a character after Test that is not a lower-case letter.
// We don't want TesticularCancer.
@@ -1082,12 +1166,12 @@ func loadTestFuncs(ptest *Package) (*testFuncs, error) {
Package: ptest,
}
for _, file := range ptest.TestGoFiles {
- if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.NeedTest); err != nil {
+ if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); err != nil {
return nil, err
}
}
for _, file := range ptest.XTestGoFiles {
- if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.NeedXtest); err != nil {
+ if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); err != nil {
return nil, err
}
}
@@ -1110,13 +1194,16 @@ func writeTestmain(out string, t *testFuncs) error {
}
type testFuncs struct {
- Tests []testFunc
- Benchmarks []testFunc
- Examples []testFunc
- Package *Package
- NeedTest bool
- NeedXtest bool
- Cover []coverInfo
+ Tests []testFunc
+ Benchmarks []testFunc
+ Examples []testFunc
+ TestMain *testFunc
+ Package *Package
+ ImportTest bool
+ NeedTest bool
+ ImportXtest bool
+ NeedXtest bool
+ Cover []coverInfo
}
func (t *testFuncs) CoverMode() string {
@@ -1151,7 +1238,7 @@ type testFunc struct {
var testFileSet = token.NewFileSet()
-func (t *testFuncs) load(filename, pkg string, seen *bool) error {
+func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
if err != nil {
return expandScanner(err)
@@ -1166,17 +1253,24 @@ func (t *testFuncs) load(filename, pkg string, seen *bool) error {
}
name := n.Name.String()
switch {
+ case isTestMain(n):
+ if t.TestMain != nil {
+ return errors.New("multiple definitions of TestMain")
+ }
+ t.TestMain = &testFunc{pkg, name, ""}
+ *doImport, *seen = true, true
case isTest(name, "Test"):
t.Tests = append(t.Tests, testFunc{pkg, name, ""})
- *seen = true
+ *doImport, *seen = true, true
case isTest(name, "Benchmark"):
t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, ""})
- *seen = true
+ *doImport, *seen = true, true
}
}
ex := doc.Examples(f)
sort.Sort(byOrder(ex))
for _, e := range ex {
+ *doImport = true // import test file whether executed or not
if e.Output == "" && !e.EmptyOutput {
// Don't run examples with no output.
continue
@@ -1197,14 +1291,17 @@ var testmainTmpl = template.Must(template.New("main").Parse(`
package main
import (
+{{if not .TestMain}}
+ "os"
+{{end}}
"regexp"
"testing"
-{{if .NeedTest}}
- _test {{.Package.ImportPath | printf "%q"}}
+{{if .ImportTest}}
+ {{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}}
{{end}}
-{{if .NeedXtest}}
- _xtest {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
+{{if .ImportXtest}}
+ {{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
{{end}}
{{range $i, $p := .Cover}}
_cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
@@ -1291,7 +1388,12 @@ func main() {
CoveredPackages: {{printf "%q" .Covered}},
})
{{end}}
- testing.Main(matchString, tests, benchmarks, examples)
+ m := testing.MainStart(matchString, tests, benchmarks, examples)
+{{with .TestMain}}
+ {{.Package}}.{{.Name}}(m)
+{{else}}
+ os.Exit(m.Run())
+{{end}}
}
`))
diff --git a/misc/cgo/test/backdoor/backdoor_gccgo.go b/src/cmd/go/testdata/generate/test1.go
index 514f76ec5..1f05734f0 100644
--- a/misc/cgo/test/backdoor/backdoor_gccgo.go
+++ b/src/cmd/go/testdata/generate/test1.go
@@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This is the gccgo version of the stub in runtime.c.
+// Simple test for go generate.
-// +build gccgo
+// We include a build tag that go generate should ignore.
-package backdoor
+// +build ignore
-func Issue7695(x1, x2, x3, x4, x5, x6, x7, x8 uintptr) {}
+//go:generate echo Success
+
+package p
diff --git a/src/cmd/go/testdata/generate/test2.go b/src/cmd/go/testdata/generate/test2.go
new file mode 100644
index 000000000..ef1a3d951
--- /dev/null
+++ b/src/cmd/go/testdata/generate/test2.go
@@ -0,0 +1,10 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that go generate handles command aliases.
+
+//go:generate -command run echo Now is the time
+//go:generate run for all good men
+
+package p
diff --git a/src/cmd/go/testdata/generate/test3.go b/src/cmd/go/testdata/generate/test3.go
new file mode 100644
index 000000000..41ffb7ea8
--- /dev/null
+++ b/src/cmd/go/testdata/generate/test3.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.
+
+// Test go generate variable substitution.
+
+//go:generate echo $GOARCH $GOFILE $GOPACKAGE xyz$GOPACKAGE/$GOFILE/123
+
+package p
diff --git a/src/cmd/go/testdata/importcom/bad.go b/src/cmd/go/testdata/importcom/bad.go
new file mode 100644
index 000000000..e104c2e99
--- /dev/null
+++ b/src/cmd/go/testdata/importcom/bad.go
@@ -0,0 +1,3 @@
+package p
+
+import "bad"
diff --git a/src/cmd/go/testdata/importcom/conflict.go b/src/cmd/go/testdata/importcom/conflict.go
new file mode 100644
index 000000000..995556c51
--- /dev/null
+++ b/src/cmd/go/testdata/importcom/conflict.go
@@ -0,0 +1,3 @@
+package p
+
+import "conflict"
diff --git a/src/cmd/go/testdata/importcom/src/bad/bad.go b/src/cmd/go/testdata/importcom/src/bad/bad.go
new file mode 100644
index 000000000..bc51fd3fd
--- /dev/null
+++ b/src/cmd/go/testdata/importcom/src/bad/bad.go
@@ -0,0 +1 @@
+package bad // import
diff --git a/src/cmd/go/testdata/importcom/src/conflict/a.go b/src/cmd/go/testdata/importcom/src/conflict/a.go
new file mode 100644
index 000000000..2d6770351
--- /dev/null
+++ b/src/cmd/go/testdata/importcom/src/conflict/a.go
@@ -0,0 +1 @@
+package conflict // import "a"
diff --git a/src/cmd/go/testdata/importcom/src/conflict/b.go b/src/cmd/go/testdata/importcom/src/conflict/b.go
new file mode 100644
index 000000000..8fcfb3c8b
--- /dev/null
+++ b/src/cmd/go/testdata/importcom/src/conflict/b.go
@@ -0,0 +1 @@
+package conflict /* import "b" */
diff --git a/src/cmd/go/testdata/importcom/src/works/x/x.go b/src/cmd/go/testdata/importcom/src/works/x/x.go
new file mode 100644
index 000000000..044c6eca8
--- /dev/null
+++ b/src/cmd/go/testdata/importcom/src/works/x/x.go
@@ -0,0 +1 @@
+package x // import "works/x"
diff --git a/src/cmd/go/testdata/importcom/src/works/x/x1.go b/src/cmd/go/testdata/importcom/src/works/x/x1.go
new file mode 100644
index 000000000..2449b29df
--- /dev/null
+++ b/src/cmd/go/testdata/importcom/src/works/x/x1.go
@@ -0,0 +1 @@
+package x // important! not an import comment
diff --git a/src/cmd/go/testdata/importcom/src/wrongplace/x.go b/src/cmd/go/testdata/importcom/src/wrongplace/x.go
new file mode 100644
index 000000000..b89849da7
--- /dev/null
+++ b/src/cmd/go/testdata/importcom/src/wrongplace/x.go
@@ -0,0 +1 @@
+package x // import "my/x"
diff --git a/src/cmd/go/testdata/importcom/works.go b/src/cmd/go/testdata/importcom/works.go
new file mode 100644
index 000000000..31b55d08a
--- /dev/null
+++ b/src/cmd/go/testdata/importcom/works.go
@@ -0,0 +1,3 @@
+package p
+
+import _ "works/x"
diff --git a/src/cmd/go/testdata/importcom/wrongplace.go b/src/cmd/go/testdata/importcom/wrongplace.go
new file mode 100644
index 000000000..e2535e01a
--- /dev/null
+++ b/src/cmd/go/testdata/importcom/wrongplace.go
@@ -0,0 +1,3 @@
+package p
+
+import "wrongplace"
diff --git a/src/cmd/go/testdata/norunexample/example_test.go b/src/cmd/go/testdata/norunexample/example_test.go
new file mode 100644
index 000000000..e158305a6
--- /dev/null
+++ b/src/cmd/go/testdata/norunexample/example_test.go
@@ -0,0 +1,11 @@
+package pkg_test
+
+import "os"
+
+func init() {
+ os.Stdout.Write([]byte("File with non-runnable example was built.\n"))
+}
+
+func Example_test() {
+ // This test will not be run, it has no "Output:" comment.
+}
diff --git a/src/cmd/go/testdata/norunexample/test_test.go b/src/cmd/go/testdata/norunexample/test_test.go
new file mode 100644
index 000000000..d2e919838
--- /dev/null
+++ b/src/cmd/go/testdata/norunexample/test_test.go
@@ -0,0 +1,10 @@
+package pkg
+
+import (
+ "os"
+ "testing"
+)
+
+func TestBuilt(t *testing.T) {
+ os.Stdout.Write([]byte("A normal test was executed.\n"))
+}
diff --git a/src/cmd/go/testdata/src/badc/x.c b/src/cmd/go/testdata/src/badc/x.c
new file mode 100644
index 000000000..f6cbf6924
--- /dev/null
+++ b/src/cmd/go/testdata/src/badc/x.c
@@ -0,0 +1 @@
+// C code!
diff --git a/src/cmd/go/testdata/src/badc/x.go b/src/cmd/go/testdata/src/badc/x.go
new file mode 100644
index 000000000..bfa1de28b
--- /dev/null
+++ b/src/cmd/go/testdata/src/badc/x.go
@@ -0,0 +1 @@
+package badc
diff --git a/src/cmd/go/testdata/src/badtest/badexec/x_test.go b/src/cmd/go/testdata/src/badtest/badexec/x_test.go
new file mode 100644
index 000000000..12f505171
--- /dev/null
+++ b/src/cmd/go/testdata/src/badtest/badexec/x_test.go
@@ -0,0 +1,5 @@
+package badexec
+
+func init() {
+ panic("badexec")
+}
diff --git a/src/cmd/go/testdata/src/badtest/badsyntax/x.go b/src/cmd/go/testdata/src/badtest/badsyntax/x.go
new file mode 100644
index 000000000..c8a5407a5
--- /dev/null
+++ b/src/cmd/go/testdata/src/badtest/badsyntax/x.go
@@ -0,0 +1 @@
+package badsyntax
diff --git a/src/cmd/go/testdata/src/badtest/badsyntax/x_test.go b/src/cmd/go/testdata/src/badtest/badsyntax/x_test.go
new file mode 100644
index 000000000..5be10745d
--- /dev/null
+++ b/src/cmd/go/testdata/src/badtest/badsyntax/x_test.go
@@ -0,0 +1,3 @@
+package badsyntax
+
+func func func func func!
diff --git a/src/cmd/go/testdata/src/badtest/badvar/x.go b/src/cmd/go/testdata/src/badtest/badvar/x.go
new file mode 100644
index 000000000..fdd46c4c7
--- /dev/null
+++ b/src/cmd/go/testdata/src/badtest/badvar/x.go
@@ -0,0 +1 @@
+package badvar
diff --git a/src/cmd/go/testdata/src/badtest/badvar/x_test.go b/src/cmd/go/testdata/src/badtest/badvar/x_test.go
new file mode 100644
index 000000000..c67df01c5
--- /dev/null
+++ b/src/cmd/go/testdata/src/badtest/badvar/x_test.go
@@ -0,0 +1,5 @@
+package badvar_test
+
+func f() {
+ _ = notdefined
+}
diff --git a/src/cmd/go/testdata/src/vetpkg/a_test.go b/src/cmd/go/testdata/src/vetpkg/a_test.go
new file mode 100644
index 000000000..9b64e8e1a
--- /dev/null
+++ b/src/cmd/go/testdata/src/vetpkg/a_test.go
@@ -0,0 +1 @@
+package p_test
diff --git a/src/cmd/go/testdata/src/vetpkg/b.go b/src/cmd/go/testdata/src/vetpkg/b.go
new file mode 100644
index 000000000..99e18f63d
--- /dev/null
+++ b/src/cmd/go/testdata/src/vetpkg/b.go
@@ -0,0 +1,7 @@
+package p
+
+import "fmt"
+
+func f() {
+ fmt.Printf("%d")
+}
diff --git a/src/cmd/go/testdata/testinternal/p.go b/src/cmd/go/testdata/testinternal/p.go
new file mode 100644
index 000000000..e3558a53b
--- /dev/null
+++ b/src/cmd/go/testdata/testinternal/p.go
@@ -0,0 +1,3 @@
+package p
+
+import _ "net/http/internal"
diff --git a/src/cmd/go/testdata/testinternal2/p.go b/src/cmd/go/testdata/testinternal2/p.go
new file mode 100644
index 000000000..c594f5c5e
--- /dev/null
+++ b/src/cmd/go/testdata/testinternal2/p.go
@@ -0,0 +1,3 @@
+package p
+
+import _ "./x/y/z/internal/w"
diff --git a/src/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go b/src/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go
new file mode 100644
index 000000000..a796c0b5f
--- /dev/null
+++ b/src/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go
@@ -0,0 +1 @@
+package w
diff --git a/src/cmd/go/testflag.go b/src/cmd/go/testflag.go
index 73f311e5f..6da74b996 100644
--- a/src/cmd/go/testflag.go
+++ b/src/cmd/go/testflag.go
@@ -65,9 +65,9 @@ type testFlagSpec struct {
var testFlagDefn = []*testFlagSpec{
// local.
{name: "c", boolVar: &testC},
- {name: "file", multiOK: true},
{name: "cover", boolVar: &testCover},
{name: "coverpkg"},
+ {name: "o"},
// build flags.
{name: "a", boolVar: &buildA},
@@ -153,6 +153,9 @@ func testFlags(args []string) (packageNames, passToTest []string) {
// bool flags.
case "a", "c", "i", "n", "x", "v", "race", "cover", "work":
setBoolFlag(f.boolVar, value)
+ case "o":
+ testO = value
+ testNeedBinary = true
case "p":
setIntFlag(&buildP, value)
case "exec":
@@ -184,8 +187,6 @@ func testFlags(args []string) (packageNames, passToTest []string) {
buildContext.BuildTags = strings.Fields(value)
case "compiler":
buildCompiler{}.Set(value)
- case "file":
- testFiles = append(testFiles, value)
case "bench":
// record that we saw the flag; don't care about the value
testBench = true
diff --git a/src/cmd/go/testgo.go b/src/cmd/go/testgo.go
new file mode 100644
index 000000000..01923f74b
--- /dev/null
+++ b/src/cmd/go/testgo.go
@@ -0,0 +1,21 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains extra hooks for testing the go command.
+// It is compiled into the Go binary only when building the
+// test copy; it does not get compiled into the standard go
+// command, so these testing hooks are not present in the
+// go command that everyone uses.
+
+// +build testgo
+
+package main
+
+import "os"
+
+func init() {
+ if v := os.Getenv("TESTGO_IS_GO_RELEASE"); v != "" {
+ isGoRelease = v == "1"
+ }
+}
diff --git a/src/cmd/go/tool.go b/src/cmd/go/tool.go
index 6d26f7a4b..3f11c3e3d 100644
--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -47,13 +47,13 @@ const toolWindowsExtension = ".exe"
func tool(toolName string) string {
toolPath := filepath.Join(toolDir, toolName)
- if toolIsWindows && toolName != "pprof" {
+ if toolIsWindows {
toolPath += toolWindowsExtension
}
// Give a nice message if there is no tool with that name.
if _, err := os.Stat(toolPath); err != nil {
if isInGoToolsRepo(toolName) {
- fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get code.google.com/p/go.tools/cmd/%s\n", toolName, toolName)
+ fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get golang.org/x/tools/cmd/%s\n", toolName, toolName)
} else {
fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
}
@@ -91,16 +91,6 @@ func runTool(cmd *Command, args []string) {
if toolPath == "" {
return
}
- if toolIsWindows && toolName == "pprof" {
- args = append([]string{"perl", toolPath}, args[1:]...)
- var err error
- toolPath, err = exec.LookPath("perl")
- if err != nil {
- fmt.Fprintf(os.Stderr, "go tool: perl not found\n")
- setExitStatus(3)
- return
- }
- }
if toolN {
fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " "))
return
diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go
index 8f0bae0b7..1cac61338 100644
--- a/src/cmd/go/vcs.go
+++ b/src/cmd/go/vcs.go
@@ -33,6 +33,9 @@ type vcsCmd struct {
scheme []string
pingCmd string
+
+ remoteRepo func(v *vcsCmd, rootDir string) (remoteRepo string, err error)
+ resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error)
}
// A tagCmd describes a command to list available tags
@@ -81,8 +84,17 @@ var vcsHg = &vcsCmd{
tagSyncCmd: "update -r {tag}",
tagSyncDefault: "update default",
- scheme: []string{"https", "http", "ssh"},
- pingCmd: "identify {scheme}://{repo}",
+ scheme: []string{"https", "http", "ssh"},
+ pingCmd: "identify {scheme}://{repo}",
+ remoteRepo: hgRemoteRepo,
+}
+
+func hgRemoteRepo(vcsHg *vcsCmd, rootDir string) (remoteRepo string, err error) {
+ out, err := vcsHg.runOutput(rootDir, "paths default")
+ if err != nil {
+ return "", err
+ }
+ return strings.TrimSpace(string(out)), nil
}
// vcsGit describes how to use Git.
@@ -104,8 +116,38 @@ var vcsGit = &vcsCmd{
tagSyncCmd: "checkout {tag}",
tagSyncDefault: "checkout master",
- scheme: []string{"git", "https", "http", "git+ssh"},
- pingCmd: "ls-remote {scheme}://{repo}",
+ scheme: []string{"git", "https", "http", "git+ssh"},
+ pingCmd: "ls-remote {scheme}://{repo}",
+ remoteRepo: gitRemoteRepo,
+}
+
+func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error) {
+ outb, err := vcsGit.runOutput(rootDir, "remote -v")
+ if err != nil {
+ return "", err
+ }
+ out := string(outb)
+
+ // Expect:
+ // origin https://github.com/rsc/pdf (fetch)
+ // origin https://github.com/rsc/pdf (push)
+ // use first line only.
+
+ if !strings.HasPrefix(out, "origin\t") {
+ return "", fmt.Errorf("unable to parse output of git remote -v")
+ }
+ out = strings.TrimPrefix(out, "origin\t")
+ i := strings.Index(out, "\n")
+ if i < 0 {
+ return "", fmt.Errorf("unable to parse output of git remote -v")
+ }
+ out = out[:i]
+ i = strings.LastIndex(out, " ")
+ if i < 0 {
+ return "", fmt.Errorf("unable to parse output of git remote -v")
+ }
+ out = out[:i]
+ return strings.TrimSpace(string(out)), nil
}
// vcsBzr describes how to use Bazaar.
@@ -123,8 +165,51 @@ var vcsBzr = &vcsCmd{
tagSyncCmd: "update -r {tag}",
tagSyncDefault: "update -r revno:-1",
- scheme: []string{"https", "http", "bzr", "bzr+ssh"},
- pingCmd: "info {scheme}://{repo}",
+ scheme: []string{"https", "http", "bzr", "bzr+ssh"},
+ pingCmd: "info {scheme}://{repo}",
+ remoteRepo: bzrRemoteRepo,
+ resolveRepo: bzrResolveRepo,
+}
+
+func bzrRemoteRepo(vcsBzr *vcsCmd, rootDir string) (remoteRepo string, err error) {
+ outb, err := vcsBzr.runOutput(rootDir, "config parent_location")
+ if err != nil {
+ return "", err
+ }
+ return strings.TrimSpace(string(outb)), nil
+}
+
+func bzrResolveRepo(vcsBzr *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) {
+ outb, err := vcsBzr.runOutput(rootDir, "info "+remoteRepo)
+ if err != nil {
+ return "", err
+ }
+ out := string(outb)
+
+ // Expect:
+ // ...
+ // (branch root|repository branch): <URL>
+ // ...
+
+ found := false
+ for _, prefix := range []string{"\n branch root: ", "\n repository branch: "} {
+ i := strings.Index(out, prefix)
+ if i >= 0 {
+ out = out[i+len(prefix):]
+ found = true
+ break
+ }
+ }
+ if !found {
+ return "", fmt.Errorf("unable to parse output of bzr info")
+ }
+
+ i := strings.Index(out, "\n")
+ if i < 0 {
+ return "", fmt.Errorf("unable to parse output of bzr info")
+ }
+ out = out[:i]
+ return strings.TrimSpace(string(out)), nil
}
// vcsSvn describes how to use Subversion.
@@ -138,8 +223,34 @@ var vcsSvn = &vcsCmd{
// There is no tag command in subversion.
// The branch information is all in the path names.
- scheme: []string{"https", "http", "svn", "svn+ssh"},
- pingCmd: "info {scheme}://{repo}",
+ scheme: []string{"https", "http", "svn", "svn+ssh"},
+ pingCmd: "info {scheme}://{repo}",
+ remoteRepo: svnRemoteRepo,
+}
+
+func svnRemoteRepo(vcsSvn *vcsCmd, rootDir string) (remoteRepo string, err error) {
+ outb, err := vcsSvn.runOutput(rootDir, "info")
+ if err != nil {
+ return "", err
+ }
+ out := string(outb)
+
+ // Expect:
+ // ...
+ // Repository Root: <URL>
+ // ...
+
+ i := strings.Index(out, "\nRepository Root: ")
+ if i < 0 {
+ return "", fmt.Errorf("unable to parse output of svn info")
+ }
+ out = out[i+len("\nRepository Root: "):]
+ i = strings.Index(out, "\n")
+ if i < 0 {
+ return "", fmt.Errorf("unable to parse output of svn info")
+ }
+ out = out[:i]
+ return strings.TrimSpace(string(out)), nil
}
func (v *vcsCmd) String() string {
@@ -361,7 +472,14 @@ var httpPrefixRE = regexp.MustCompile(`^https?:`)
func repoRootForImportPath(importPath string) (*repoRoot, error) {
rr, err := repoRootForImportPathStatic(importPath, "")
if err == errUnknownSite {
- rr, err = repoRootForImportDynamic(importPath)
+ // If there are wildcards, look up the thing before the wildcard,
+ // hoping it applies to the wildcarded parts too.
+ // This makes 'go get rsc.io/pdf/...' work in a fresh GOPATH.
+ lookup := strings.TrimSuffix(importPath, "/...")
+ if i := strings.Index(lookup, "/.../"); i >= 0 {
+ lookup = lookup[:i]
+ }
+ rr, err = repoRootForImportDynamic(lookup)
// repoRootForImportDynamic returns error detail
// that is irrelevant if the user didn't intend to use a
@@ -465,11 +583,11 @@ func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) {
func repoRootForImportDynamic(importPath string) (*repoRoot, error) {
slash := strings.Index(importPath, "/")
if slash < 0 {
- return nil, errors.New("import path doesn't contain a slash")
+ return nil, errors.New("import path does not contain a slash")
}
host := importPath[:slash]
if !strings.Contains(host, ".") {
- return nil, errors.New("import path doesn't contain a hostname")
+ return nil, errors.New("import path does not begin with hostname")
}
urlStr, body, err := httpsOrHTTP(importPath)
if err != nil {
@@ -613,6 +731,15 @@ var vcsPaths = []*vcsPath{
check: launchpadVCS,
},
+ // IBM DevOps Services (JazzHub)
+ {
+ prefix: "hub.jazz.net/git",
+ re: `^(?P<root>hub.jazz.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
+ vcs: "git",
+ repo: "https://{root}",
+ check: noVCSSuffix,
+ },
+
// General syntax for any server.
{
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_.\-]+)*$`,
diff --git a/src/cmd/go/vcs_test.go b/src/cmd/go/vcs_test.go
new file mode 100644
index 000000000..14d681ba6
--- /dev/null
+++ b/src/cmd/go/vcs_test.go
@@ -0,0 +1,124 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "runtime"
+ "testing"
+)
+
+// Test that RepoRootForImportPath creates the correct RepoRoot for a given importPath.
+// TODO(cmang): Add tests for SVN and BZR.
+func TestRepoRootForImportPath(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping test to avoid external network")
+ }
+ switch runtime.GOOS {
+ case "nacl", "android":
+ t.Skipf("no networking available on %s", runtime.GOOS)
+ }
+ tests := []struct {
+ 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,
+ repo: "https://code.google.com/r/go",
+ },
+ },*/
+ {
+ "github.com/golang/groupcache",
+ &repoRoot{
+ vcs: vcsGit,
+ repo: "https://github.com/golang/groupcache",
+ },
+ },
+ // IBM DevOps Services tests
+ {
+ "hub.jazz.net/git/user1/pkgname",
+ &repoRoot{
+ vcs: vcsGit,
+ repo: "https://hub.jazz.net/git/user1/pkgname",
+ },
+ },
+ {
+ "hub.jazz.net/git/user1/pkgname/submodule/submodule/submodule",
+ &repoRoot{
+ vcs: vcsGit,
+ repo: "https://hub.jazz.net/git/user1/pkgname",
+ },
+ },
+ {
+ "hub.jazz.net",
+ nil,
+ },
+ {
+ "hub2.jazz.net",
+ nil,
+ },
+ {
+ "hub.jazz.net/someotherprefix",
+ nil,
+ },
+ {
+ "hub.jazz.net/someotherprefix/user1/pkgname",
+ nil,
+ },
+ // Spaces are not valid in user names or package names
+ {
+ "hub.jazz.net/git/User 1/pkgname",
+ nil,
+ },
+ {
+ "hub.jazz.net/git/user1/pkg name",
+ nil,
+ },
+ // Dots are not valid in user names
+ {
+ "hub.jazz.net/git/user.1/pkgname",
+ nil,
+ },
+ {
+ "hub.jazz.net/git/user/pkg.name",
+ &repoRoot{
+ vcs: vcsGit,
+ repo: "https://hub.jazz.net/git/user/pkg.name",
+ },
+ },
+ // User names cannot have uppercase letters
+ {
+ "hub.jazz.net/git/USER/pkgname",
+ nil,
+ },
+ }
+
+ for _, test := range tests {
+ got, err := repoRootForImportPath(test.path)
+ want := test.want
+
+ if want == nil {
+ if err == nil {
+ t.Errorf("RepoRootForImport(%q): Error expected but not received", test.path)
+ }
+ continue
+ }
+ if err != nil {
+ t.Errorf("RepoRootForImport(%q): %v", test.path, err)
+ continue
+ }
+ if got.vcs.name != want.vcs.name || got.repo != want.repo {
+ t.Errorf("RepoRootForImport(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.vcs, got.repo, want.vcs, want.repo)
+ }
+ }
+}
diff --git a/src/cmd/go/vet.go b/src/cmd/go/vet.go
index ffb431837..02ff54b2a 100644
--- a/src/cmd/go/vet.go
+++ b/src/cmd/go/vet.go
@@ -4,6 +4,8 @@
package main
+import "path/filepath"
+
func init() {
addBuildFlagsNX(cmdVet)
}
@@ -15,7 +17,7 @@ var cmdVet = &Command{
Long: `
Vet runs the Go vet command on the packages named by the import paths.
-For more about vet, see 'godoc code.google.com/p/go.tools/cmd/vet'.
+For more about vet, see 'godoc golang.org/x/tools/cmd/vet'.
For more about specifying packages, see 'go help packages'.
To run the vet tool with specific options, run 'go tool vet'.
@@ -28,10 +30,21 @@ See also: go fmt, go fix.
}
func runVet(cmd *Command, args []string) {
- for _, pkg := range packages(args) {
- // Use pkg.gofiles instead of pkg.Dir so that
- // the command only applies to this package,
- // not to packages in subdirectories.
- run(tool("vet"), relPaths(stringList(pkg.gofiles, pkg.sfiles)))
+ for _, p := range packages(args) {
+ // Vet expects to be given a set of files all from the same package.
+ // Run once for package p and once for package p_test.
+ if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles) > 0 {
+ runVetFiles(p, stringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.SFiles))
+ }
+ if len(p.XTestGoFiles) > 0 {
+ runVetFiles(p, stringList(p.XTestGoFiles))
+ }
+ }
+}
+
+func runVetFiles(p *Package, files []string) {
+ for i := range files {
+ files[i] = filepath.Join(p.Dir, files[i])
}
+ run(tool("vet"), relPaths(files))
}
diff --git a/src/cmd/gofmt/doc.go b/src/cmd/gofmt/doc.go
index 8f73ef5b9..3fc043954 100644
--- a/src/cmd/gofmt/doc.go
+++ b/src/cmd/gofmt/doc.go
@@ -67,7 +67,7 @@ To remove the parentheses:
To convert the package tree from explicit slice upper bounds to implicit ones:
- gofmt -r 'α[β:len(α)] -> α[β:]' -w $GOROOT/src/pkg
+ gofmt -r 'α[β:len(α)] -> α[β:]' -w $GOROOT/src
The simplify command
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index 576cae522..81da21ff1 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -87,13 +87,13 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
return err
}
- file, adjust, err := parse(fileSet, filename, src, stdin)
+ file, sourceAdj, indentAdj, err := parse(fileSet, filename, src, stdin)
if err != nil {
return err
}
if rewrite != nil {
- if adjust == nil {
+ if sourceAdj == nil {
file = rewrite(file)
} else {
fmt.Fprintf(os.Stderr, "warning: rewrite ignored for incomplete programs\n")
@@ -106,15 +106,10 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
simplify(file)
}
- var buf bytes.Buffer
- err = (&printer.Config{Mode: printerMode, Tabwidth: tabWidth}).Fprint(&buf, fileSet, file)
+ res, err := format(fileSet, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth})
if err != nil {
return err
}
- res := buf.Bytes()
- if adjust != nil {
- res = adjust(src, res)
- }
if !bytes.Equal(src, res) {
// formatting has changed
@@ -122,7 +117,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
fmt.Fprintln(out, filename)
}
if *write {
- err = ioutil.WriteFile(filename, res, 0)
+ err = ioutil.WriteFile(filename, res, 0644)
if err != nil {
return err
}
@@ -186,6 +181,11 @@ func gofmtMain() {
initRewrite()
if flag.NArg() == 0 {
+ if *write {
+ fmt.Fprintln(os.Stderr, "error: cannot use -w with standard input")
+ exitCode = 2
+ return
+ }
if err := processFile("<standard input>", os.Stdin, os.Stdout, true); err != nil {
report(err)
}
@@ -235,19 +235,29 @@ func diff(b1, b2 []byte) (data []byte, err error) {
}
-// parse parses src, which was read from filename,
-// as a Go source file or statement list.
-func parse(fset *token.FileSet, filename string, src []byte, stdin bool) (*ast.File, func(orig, src []byte) []byte, error) {
+// ----------------------------------------------------------------------------
+// Support functions
+//
+// The functions parse, format, and isSpace below are identical to the
+// respective functions in src/go/format/format.go - keep them in sync!
+//
+// TODO(gri) Factor out this functionality, eventually.
+
+// 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 err == nil {
- return file, nil, nil
- }
- // If the error is that the source file didn't begin with a
- // package line and this is standard input, fall through to
+ 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 !stdin || !strings.Contains(err.Error(), "expected 'package'") {
- return nil, nil, err
+ if err == nil || !fragmentOk || !strings.Contains(err.Error(), "expected 'package'") {
+ return
}
// If this is a declaration list, make it a source file
@@ -257,19 +267,19 @@ func parse(fset *token.FileSet, filename string, src []byte, stdin bool) (*ast.F
psrc := append([]byte("package p;"), src...)
file, err = parser.ParseFile(fset, filename, psrc, parserMode)
if err == nil {
- adjust := func(orig, src []byte) []byte {
+ sourceAdj = func(src []byte, indent int) []byte {
// Remove the package clause.
// Gofmt has turned the ; into a \n.
- src = src[len("package p\n"):]
- return matchSpace(orig, src)
+ src = src[indent+len("package p\n"):]
+ return bytes.TrimSpace(src)
}
- return file, adjust, nil
+ 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 nil, nil, err
+ return
}
// If this is a statement list, make it a source file
@@ -277,68 +287,101 @@ func parse(fset *token.FileSet, filename string, src []byte, stdin bool) (*ast.F
// 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.
- fsrc := append(append([]byte("package p; func _() {"), src...), '}')
+ fsrc := append(append([]byte("package p; func _() {"), src...), '\n', '}')
file, err = parser.ParseFile(fset, filename, fsrc, parserMode)
if err == nil {
- adjust := func(orig, src []byte) []byte {
+ 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.
- src = src[len("package p\n\nfunc _() {"):]
- src = src[:len(src)-len("}\n")]
- // Gofmt has also indented the function body one level.
- // Remove that indent.
- src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1)
- return matchSpace(orig, src)
+ // There will be two non-blank lines with indent, hence 2*indent.
+ src = src[2*indent+len("package p\n\nfunc _() {"):]
+ src = src[:len(src)-(indent+len("\n}\n"))]
+ return bytes.TrimSpace(src)
}
- return file, adjust, nil
+ // Gofmt has also indented the function body one level.
+ // Adjust that with indentAdj.
+ indentAdj = -1
}
- // Failed, and out of options.
- return nil, nil, err
+ // Succeeded, or out of options.
+ return
}
-func cutSpace(b []byte) (before, middle, after []byte) {
- i := 0
- for i < len(b) && (b[i] == ' ' || b[i] == '\t' || b[i] == '\n') {
- i++
- }
- j := len(b)
- for j > 0 && (b[j-1] == ' ' || b[j-1] == '\t' || b[j-1] == '\n') {
- j--
- }
- if i <= j {
- return b[:i], b[i:j], b[j:]
+// 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
}
- return nil, nil, b[j:]
-}
-// matchSpace reformats src to use the same space context as orig.
-// 1) If orig begins with blank lines, matchSpace inserts them at the beginning of src.
-// 2) matchSpace copies the indentation of the first non-blank line in orig
-// to every non-blank line in src.
-// 3) matchSpace copies the trailing space from orig and uses it in place
-// of src's trailing space.
-func matchSpace(orig []byte, src []byte) []byte {
- before, _, after := cutSpace(orig)
- i := bytes.LastIndex(before, []byte{'\n'})
- before, indent := before[:i+1], before[i+1:]
-
- _, src, _ = cutSpace(src)
-
- var b bytes.Buffer
- b.Write(before)
- for len(src) > 0 {
- line := src
- if i := bytes.IndexByte(line, '\n'); i >= 0 {
- line, src = line[:i+1], line[i+1:]
- } else {
- src = 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
}
- if len(line) > 0 && line[0] != '\n' { // not blank
- b.Write(indent)
+ 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++
}
- b.Write(line)
}
- b.Write(after)
- return b.Bytes()
+ 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
+}
+
+func isSpace(b byte) bool {
+ return b == ' ' || b == '\t' || b == '\n' || b == '\r'
}
diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go
index b9335b8f3..d1edb7bcc 100644
--- a/src/cmd/gofmt/gofmt_test.go
+++ b/src/cmd/gofmt/gofmt_test.go
@@ -6,18 +6,60 @@ package main
import (
"bytes"
+ "flag"
"io/ioutil"
+ "os"
"path/filepath"
"strings"
"testing"
+ "text/scanner"
)
-func runTest(t *testing.T, in, out, flags string) {
+var update = flag.Bool("update", false, "update .golden files")
+
+// gofmtFlags looks for a comment of the form
+//
+// //gofmt flags
+//
+// within the first maxLines lines of the given file,
+// and returns the flags string, if any. Otherwise it
+// returns the empty string.
+func gofmtFlags(filename string, maxLines int) string {
+ f, err := os.Open(filename)
+ if err != nil {
+ return "" // ignore errors - they will be found later
+ }
+ defer f.Close()
+
+ // initialize scanner
+ var s scanner.Scanner
+ s.Init(f)
+ s.Error = func(*scanner.Scanner, string) {} // ignore errors
+ s.Mode = scanner.GoTokens &^ scanner.SkipComments // want comments
+
+ // look for //gofmt comment
+ for s.Line <= maxLines {
+ switch s.Scan() {
+ case scanner.Comment:
+ const prefix = "//gofmt "
+ if t := s.TokenText(); strings.HasPrefix(t, prefix) {
+ return strings.TrimSpace(t[len(prefix):])
+ }
+ case scanner.EOF:
+ return ""
+ }
+
+ }
+
+ return ""
+}
+
+func runTest(t *testing.T, in, out string) {
// process flags
*simplifyAST = false
*rewriteRule = ""
stdin := false
- for _, flag := range strings.Split(flags, " ") {
+ for _, flag := range strings.Split(gofmtFlags(in, 20), " ") {
elts := strings.SplitN(flag, "=", 2)
name := elts[0]
value := ""
@@ -56,6 +98,17 @@ func runTest(t *testing.T, in, out, flags string) {
}
if got := buf.Bytes(); !bytes.Equal(got, expected) {
+ if *update {
+ if in != out {
+ if err := ioutil.WriteFile(out, got, 0666); err != nil {
+ t.Error(err)
+ }
+ return
+ }
+ // in == out: don't accidentally destroy input
+ t.Errorf("WARNING: -update did not rewrite input file %s", in)
+ }
+
t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in)
d, err := diff(expected, got)
if err == nil {
@@ -67,51 +120,37 @@ func runTest(t *testing.T, in, out, flags string) {
}
}
-var tests = []struct {
- in, flags string
-}{
- {"gofmt.go", ""},
- {"gofmt_test.go", ""},
- {"testdata/composites.input", "-s"},
- {"testdata/slices1.input", "-s"},
- {"testdata/slices2.input", "-s"},
- {"testdata/old.input", ""},
- {"testdata/rewrite1.input", "-r=Foo->Bar"},
- {"testdata/rewrite2.input", "-r=int->bool"},
- {"testdata/rewrite3.input", "-r=x->x"},
- {"testdata/rewrite4.input", "-r=(x)->x"},
- {"testdata/rewrite5.input", "-r=x+x->2*x"},
- {"testdata/rewrite6.input", "-r=fun(x)->Fun(x)"},
- {"testdata/rewrite7.input", "-r=fun(x...)->Fun(x)"},
- {"testdata/rewrite8.input", "-r=interface{}->int"},
- {"testdata/stdin*.input", "-stdin"},
- {"testdata/comments.input", ""},
- {"testdata/import.input", ""},
- {"testdata/crlf.input", ""}, // test case for issue 3961; see also TestCRLF
- {"testdata/typeswitch.input", ""}, // test case for issue 4470
-}
-
+// TestRewrite processes testdata/*.input files and compares them to the
+// corresponding testdata/*.golden files. The gofmt flags used to process
+// a file must be provided via a comment of the form
+//
+// //gofmt flags
+//
+// in the processed file within the first 20 lines, if any.
func TestRewrite(t *testing.T) {
- for _, test := range tests {
- match, err := filepath.Glob(test.in)
- if err != nil {
- t.Error(err)
- continue
+ // determine input files
+ match, err := filepath.Glob("testdata/*.input")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // add larger examples
+ match = append(match, "gofmt.go", "gofmt_test.go")
+
+ for _, in := range match {
+ out := in // for files where input and output are identical
+ if strings.HasSuffix(in, ".input") {
+ out = in[:len(in)-len(".input")] + ".golden"
}
- for _, in := range match {
- out := in
- if strings.HasSuffix(in, ".input") {
- out = in[:len(in)-len(".input")] + ".golden"
- }
- runTest(t, in, out, test.flags)
- if in != out {
- // Check idempotence.
- runTest(t, out, out, test.flags)
- }
+ runTest(t, in, out)
+ if in != out {
+ // Check idempotence.
+ runTest(t, out, out)
}
}
}
+// Test case for issue 3961.
func TestCRLF(t *testing.T) {
const input = "testdata/crlf.input" // must contain CR/LF's
const golden = "testdata/crlf.golden" // must not contain any CR's
diff --git a/src/cmd/gofmt/long_test.go b/src/cmd/gofmt/long_test.go
index 108278b33..237b86021 100644
--- a/src/cmd/gofmt/long_test.go
+++ b/src/cmd/gofmt/long_test.go
@@ -32,7 +32,7 @@ var (
)
func gofmt(fset *token.FileSet, filename string, src *bytes.Buffer) error {
- f, _, err := parse(fset, filename, src.Bytes(), false)
+ f, _, _, err := parse(fset, filename, src.Bytes(), false)
if err != nil {
return err
}
@@ -60,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 = 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/rewrite.go b/src/cmd/gofmt/rewrite.go
index fb6c6fc81..d267cfcc1 100644
--- a/src/cmd/gofmt/rewrite.go
+++ b/src/cmd/gofmt/rewrite.go
@@ -226,9 +226,6 @@ func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
return true
case reflect.Struct:
- if p.NumField() != v.NumField() {
- return false
- }
for i := 0; i < p.NumField(); i++ {
if !match(m, p.Field(i), v.Field(i)) {
return false
diff --git a/src/cmd/gofmt/simplify.go b/src/cmd/gofmt/simplify.go
index 45d000d67..69f7bf23c 100644
--- a/src/cmd/gofmt/simplify.go
+++ b/src/cmd/gofmt/simplify.go
@@ -68,9 +68,10 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
// a slice expression of the form: s[a:len(s)]
// can be simplified to: s[a:]
// if s is "simple enough" (for now we only accept identifiers)
- if s.hasDotImport {
- // if dot imports are present, we cannot be certain that an
- // unresolved "len" identifier refers to the predefined len()
+ if n.Max != nil || s.hasDotImport {
+ // - 3-index slices always require the 2nd and 3rd index
+ // - if dot imports are present, we cannot be certain that an
+ // unresolved "len" identifier refers to the predefined len()
break
}
if s, _ := n.X.(*ast.Ident); s != nil && s.Obj != nil {
@@ -96,16 +97,26 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
// x, y := b[:n], b[n:]
case *ast.RangeStmt:
- // a range of the form: for x, _ = range v {...}
+ // - a range of the form: for x, _ = range v {...}
// can be simplified to: for x = range v {...}
- if ident, _ := n.Value.(*ast.Ident); ident != nil && ident.Name == "_" {
+ // - a range of the form: for _ = range v {...}
+ // can be simplified to: for range v {...}
+ if isBlank(n.Value) {
n.Value = nil
}
+ if isBlank(n.Key) && n.Value == nil {
+ n.Key = nil
+ }
}
return s
}
+func isBlank(x ast.Expr) bool {
+ ident, ok := x.(*ast.Ident)
+ return ok && ident.Name == "_"
+}
+
func simplify(f *ast.File) {
var s simplifier
@@ -117,5 +128,34 @@ func simplify(f *ast.File) {
}
}
+ // remove empty declarations such as "const ()", etc
+ removeEmptyDeclGroups(f)
+
ast.Walk(&s, f)
}
+
+func removeEmptyDeclGroups(f *ast.File) {
+ i := 0
+ for _, d := range f.Decls {
+ if g, ok := d.(*ast.GenDecl); !ok || !isEmpty(f, g) {
+ f.Decls[i] = d
+ i++
+ }
+ }
+ f.Decls = f.Decls[:i]
+}
+
+func isEmpty(f *ast.File, g *ast.GenDecl) bool {
+ if g.Doc != nil || g.Specs != nil {
+ return false
+ }
+
+ for _, c := range f.Comments {
+ // if there is a comment in the declaration, it is not considered empty
+ if g.Pos() <= c.Pos() && c.End() <= g.End() {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/src/cmd/gofmt/testdata/composites.golden b/src/cmd/gofmt/testdata/composites.golden
index b2825e732..fc9c98e62 100644
--- a/src/cmd/gofmt/testdata/composites.golden
+++ b/src/cmd/gofmt/testdata/composites.golden
@@ -1,3 +1,5 @@
+//gofmt -s
+
package P
type T struct {
diff --git a/src/cmd/gofmt/testdata/composites.input b/src/cmd/gofmt/testdata/composites.input
index 7210dafc9..fc7598af9 100644
--- a/src/cmd/gofmt/testdata/composites.input
+++ b/src/cmd/gofmt/testdata/composites.input
@@ -1,3 +1,5 @@
+//gofmt -s
+
package P
type T struct {
diff --git a/src/cmd/gofmt/testdata/crlf.golden b/src/cmd/gofmt/testdata/crlf.golden
index 57679f770..193dbacc7 100644
--- a/src/cmd/gofmt/testdata/crlf.golden
+++ b/src/cmd/gofmt/testdata/crlf.golden
@@ -2,6 +2,7 @@
Source containing CR/LF line endings.
The gofmt'ed output must only have LF
line endings.
+ Test case for issue 3961.
*/
package main
diff --git a/src/cmd/gofmt/testdata/crlf.input b/src/cmd/gofmt/testdata/crlf.input
index 61a1aa0b4..ae7e14dbf 100644
--- a/src/cmd/gofmt/testdata/crlf.input
+++ b/src/cmd/gofmt/testdata/crlf.input
@@ -2,6 +2,7 @@
Source containing CR/LF line endings.
The gofmt'ed output must only have LF
line endings.
+ Test case for issue 3961.
*/
package main
diff --git a/src/cmd/gofmt/testdata/emptydecl.golden b/src/cmd/gofmt/testdata/emptydecl.golden
new file mode 100644
index 000000000..33d6435e0
--- /dev/null
+++ b/src/cmd/gofmt/testdata/emptydecl.golden
@@ -0,0 +1,14 @@
+//gofmt -s
+
+// Test case for issue 7631.
+
+package main
+
+// Keep this declaration
+var ()
+
+const (
+// Keep this declaration
+)
+
+func main() {}
diff --git a/src/cmd/gofmt/testdata/emptydecl.input b/src/cmd/gofmt/testdata/emptydecl.input
new file mode 100644
index 000000000..4948a61f0
--- /dev/null
+++ b/src/cmd/gofmt/testdata/emptydecl.input
@@ -0,0 +1,16 @@
+//gofmt -s
+
+// Test case for issue 7631.
+
+package main
+
+// Keep this declaration
+var ()
+
+const (
+// Keep this declaration
+)
+
+type ()
+
+func main() {} \ No newline at end of file
diff --git a/src/cmd/gofmt/testdata/ranges.golden b/src/cmd/gofmt/testdata/ranges.golden
new file mode 100644
index 000000000..506b3a035
--- /dev/null
+++ b/src/cmd/gofmt/testdata/ranges.golden
@@ -0,0 +1,30 @@
+//gofmt -s
+
+// Test cases for range simplification.
+package p
+
+func _() {
+ for a, b = range x {
+ }
+ for a = range x {
+ }
+ for _, b = range x {
+ }
+ for range x {
+ }
+
+ for a = range x {
+ }
+ for range x {
+ }
+
+ for a, b := range x {
+ }
+ for a := range x {
+ }
+ for _, b := range x {
+ }
+
+ for a := range x {
+ }
+}
diff --git a/src/cmd/gofmt/testdata/ranges.input b/src/cmd/gofmt/testdata/ranges.input
new file mode 100644
index 000000000..df5f8333c
--- /dev/null
+++ b/src/cmd/gofmt/testdata/ranges.input
@@ -0,0 +1,20 @@
+//gofmt -s
+
+// Test cases for range simplification.
+package p
+
+func _() {
+ for a, b = range x {}
+ for a, _ = range x {}
+ for _, b = range x {}
+ for _, _ = range x {}
+
+ for a = range x {}
+ for _ = range x {}
+
+ for a, b := range x {}
+ for a, _ := range x {}
+ for _, b := range x {}
+
+ for a := range x {}
+}
diff --git a/src/cmd/gofmt/testdata/rewrite1.golden b/src/cmd/gofmt/testdata/rewrite1.golden
index d9beb3705..3ee5373a7 100644
--- a/src/cmd/gofmt/testdata/rewrite1.golden
+++ b/src/cmd/gofmt/testdata/rewrite1.golden
@@ -1,3 +1,5 @@
+//gofmt -r=Foo->Bar
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite1.input b/src/cmd/gofmt/testdata/rewrite1.input
index bdb894320..a84c8f781 100644
--- a/src/cmd/gofmt/testdata/rewrite1.input
+++ b/src/cmd/gofmt/testdata/rewrite1.input
@@ -1,3 +1,5 @@
+//gofmt -r=Foo->Bar
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite2.golden b/src/cmd/gofmt/testdata/rewrite2.golden
index 64c67ffa6..f980e0353 100644
--- a/src/cmd/gofmt/testdata/rewrite2.golden
+++ b/src/cmd/gofmt/testdata/rewrite2.golden
@@ -1,3 +1,5 @@
+//gofmt -r=int->bool
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite2.input b/src/cmd/gofmt/testdata/rewrite2.input
index 21171447a..489be4e07 100644
--- a/src/cmd/gofmt/testdata/rewrite2.input
+++ b/src/cmd/gofmt/testdata/rewrite2.input
@@ -1,3 +1,5 @@
+//gofmt -r=int->bool
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite3.golden b/src/cmd/gofmt/testdata/rewrite3.golden
index 0d16d1601..261a220c6 100644
--- a/src/cmd/gofmt/testdata/rewrite3.golden
+++ b/src/cmd/gofmt/testdata/rewrite3.golden
@@ -1,3 +1,5 @@
+//gofmt -r=x->x
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite3.input b/src/cmd/gofmt/testdata/rewrite3.input
index 0d16d1601..261a220c6 100644
--- a/src/cmd/gofmt/testdata/rewrite3.input
+++ b/src/cmd/gofmt/testdata/rewrite3.input
@@ -1,3 +1,5 @@
+//gofmt -r=x->x
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite4.golden b/src/cmd/gofmt/testdata/rewrite4.golden
index 8dfc81a07..b05547b4b 100644
--- a/src/cmd/gofmt/testdata/rewrite4.golden
+++ b/src/cmd/gofmt/testdata/rewrite4.golden
@@ -1,3 +1,5 @@
+//gofmt -r=(x)->x
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite4.input b/src/cmd/gofmt/testdata/rewrite4.input
index 164cc0451..081709920 100644
--- a/src/cmd/gofmt/testdata/rewrite4.input
+++ b/src/cmd/gofmt/testdata/rewrite4.input
@@ -1,3 +1,5 @@
+//gofmt -r=(x)->x
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite5.golden b/src/cmd/gofmt/testdata/rewrite5.golden
index 5a448a63d..9beb34aee 100644
--- a/src/cmd/gofmt/testdata/rewrite5.golden
+++ b/src/cmd/gofmt/testdata/rewrite5.golden
@@ -1,3 +1,5 @@
+//gofmt -r=x+x->2*x
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite5.input b/src/cmd/gofmt/testdata/rewrite5.input
index 0d759e69b..d7a6122d0 100644
--- a/src/cmd/gofmt/testdata/rewrite5.input
+++ b/src/cmd/gofmt/testdata/rewrite5.input
@@ -1,3 +1,5 @@
+//gofmt -r=x+x->2*x
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite6.golden b/src/cmd/gofmt/testdata/rewrite6.golden
index e565dbdd9..48ec9aa0d 100644
--- a/src/cmd/gofmt/testdata/rewrite6.golden
+++ b/src/cmd/gofmt/testdata/rewrite6.golden
@@ -1,3 +1,5 @@
+//gofmt -r=fun(x)->Fun(x)
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite6.input b/src/cmd/gofmt/testdata/rewrite6.input
index 8c088b3e8..b085a84fe 100644
--- a/src/cmd/gofmt/testdata/rewrite6.input
+++ b/src/cmd/gofmt/testdata/rewrite6.input
@@ -1,3 +1,5 @@
+//gofmt -r=fun(x)->Fun(x)
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite7.golden b/src/cmd/gofmt/testdata/rewrite7.golden
index 29babad9f..8386a0b2a 100644
--- a/src/cmd/gofmt/testdata/rewrite7.golden
+++ b/src/cmd/gofmt/testdata/rewrite7.golden
@@ -1,3 +1,5 @@
+//gofmt -r=fun(x...)->Fun(x)
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite7.input b/src/cmd/gofmt/testdata/rewrite7.input
index 073e2a3e6..c1984708e 100644
--- a/src/cmd/gofmt/testdata/rewrite7.input
+++ b/src/cmd/gofmt/testdata/rewrite7.input
@@ -1,3 +1,5 @@
+//gofmt -r=fun(x...)->Fun(x)
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite8.golden b/src/cmd/gofmt/testdata/rewrite8.golden
index cfc452b03..62f0419df 100644
--- a/src/cmd/gofmt/testdata/rewrite8.golden
+++ b/src/cmd/gofmt/testdata/rewrite8.golden
@@ -1,3 +1,5 @@
+//gofmt -r=interface{}->int
+
// 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.
diff --git a/src/cmd/gofmt/testdata/rewrite8.input b/src/cmd/gofmt/testdata/rewrite8.input
index 235efa91c..7964c5c75 100644
--- a/src/cmd/gofmt/testdata/rewrite8.input
+++ b/src/cmd/gofmt/testdata/rewrite8.input
@@ -1,3 +1,5 @@
+//gofmt -r=interface{}->int
+
// 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.
diff --git a/src/cmd/gofmt/testdata/slices1.golden b/src/cmd/gofmt/testdata/slices1.golden
index 61e074f68..04bc16f21 100644
--- a/src/cmd/gofmt/testdata/slices1.golden
+++ b/src/cmd/gofmt/testdata/slices1.golden
@@ -1,3 +1,5 @@
+//gofmt -s
+
// Test cases for slice expression simplification.
package p
@@ -15,6 +17,7 @@ var (
_ = a[3:(len(a))]
_ = a[len(a) : len(a)-1]
_ = a[0:len(b)]
+ _ = a[2:len(a):len(a)]
_ = a[:]
_ = a[:10]
@@ -22,6 +25,7 @@ var (
_ = a[:(len(a))]
_ = a[:len(a)-1]
_ = a[:len(b)]
+ _ = a[:len(a):len(a)]
_ = s[0:]
_ = s[1:10]
@@ -29,6 +33,7 @@ var (
_ = s[3:(len(s))]
_ = s[len(a) : len(s)-1]
_ = s[0:len(b)]
+ _ = s[2:len(s):len(s)]
_ = s[:]
_ = s[:10]
@@ -36,6 +41,7 @@ var (
_ = s[:(len(s))]
_ = s[:len(s)-1]
_ = s[:len(b)]
+ _ = s[:len(s):len(s)]
_ = t.s[0:]
_ = t.s[1:10]
@@ -43,6 +49,7 @@ var (
_ = t.s[3:(len(t.s))]
_ = t.s[len(a) : len(t.s)-1]
_ = t.s[0:len(b)]
+ _ = t.s[2:len(t.s):len(t.s)]
_ = t.s[:]
_ = t.s[:10]
@@ -50,6 +57,7 @@ var (
_ = t.s[:(len(t.s))]
_ = t.s[:len(t.s)-1]
_ = t.s[:len(b)]
+ _ = t.s[:len(t.s):len(t.s)]
)
func _() {
diff --git a/src/cmd/gofmt/testdata/slices1.input b/src/cmd/gofmt/testdata/slices1.input
index 4d2cbfff4..1f25c43cc 100644
--- a/src/cmd/gofmt/testdata/slices1.input
+++ b/src/cmd/gofmt/testdata/slices1.input
@@ -1,3 +1,5 @@
+//gofmt -s
+
// Test cases for slice expression simplification.
package p
@@ -15,6 +17,7 @@ var (
_ = a[3:(len(a))]
_ = a[len(a) : len(a)-1]
_ = a[0:len(b)]
+ _ = a[2:len(a):len(a)]
_ = a[:]
_ = a[:10]
@@ -22,6 +25,7 @@ var (
_ = a[:(len(a))]
_ = a[:len(a)-1]
_ = a[:len(b)]
+ _ = a[:len(a):len(a)]
_ = s[0:]
_ = s[1:10]
@@ -29,6 +33,7 @@ var (
_ = s[3:(len(s))]
_ = s[len(a) : len(s)-1]
_ = s[0:len(b)]
+ _ = s[2:len(s):len(s)]
_ = s[:]
_ = s[:10]
@@ -36,6 +41,7 @@ var (
_ = s[:(len(s))]
_ = s[:len(s)-1]
_ = s[:len(b)]
+ _ = s[:len(s):len(s)]
_ = t.s[0:]
_ = t.s[1:10]
@@ -43,6 +49,7 @@ var (
_ = t.s[3:(len(t.s))]
_ = t.s[len(a) : len(t.s)-1]
_ = t.s[0:len(b)]
+ _ = t.s[2:len(t.s):len(t.s)]
_ = t.s[:]
_ = t.s[:10]
@@ -50,6 +57,7 @@ var (
_ = t.s[:(len(t.s))]
_ = t.s[:len(t.s)-1]
_ = t.s[:len(b)]
+ _ = t.s[:len(t.s):len(t.s)]
)
func _() {
diff --git a/src/cmd/gofmt/testdata/slices2.golden b/src/cmd/gofmt/testdata/slices2.golden
index 433788e1e..ab657004e 100644
--- a/src/cmd/gofmt/testdata/slices2.golden
+++ b/src/cmd/gofmt/testdata/slices2.golden
@@ -1,3 +1,5 @@
+//gofmt -s
+
// Test cases for slice expression simplification.
// Because of a dot import, these slices must remain untouched.
package p
diff --git a/src/cmd/gofmt/testdata/slices2.input b/src/cmd/gofmt/testdata/slices2.input
index 433788e1e..ab657004e 100644
--- a/src/cmd/gofmt/testdata/slices2.input
+++ b/src/cmd/gofmt/testdata/slices2.input
@@ -1,3 +1,5 @@
+//gofmt -s
+
// Test cases for slice expression simplification.
// Because of a dot import, these slices must remain untouched.
package p
diff --git a/src/cmd/gofmt/testdata/stdin1.golden b/src/cmd/gofmt/testdata/stdin1.golden
index ff8b0b7ab..9e4dcd20f 100644
--- a/src/cmd/gofmt/testdata/stdin1.golden
+++ b/src/cmd/gofmt/testdata/stdin1.golden
@@ -1,3 +1,5 @@
+ //gofmt -stdin
+
if x {
y
}
diff --git a/src/cmd/gofmt/testdata/stdin1.golden.gofmt b/src/cmd/gofmt/testdata/stdin1.golden.gofmt
deleted file mode 100644
index 1f888877d..000000000
--- a/src/cmd/gofmt/testdata/stdin1.golden.gofmt
+++ /dev/null
@@ -1,3 +0,0 @@
- if x {
- y
-}
diff --git a/src/cmd/gofmt/testdata/stdin1.input b/src/cmd/gofmt/testdata/stdin1.input
index ff8b0b7ab..9e4dcd20f 100644
--- a/src/cmd/gofmt/testdata/stdin1.input
+++ b/src/cmd/gofmt/testdata/stdin1.input
@@ -1,3 +1,5 @@
+ //gofmt -stdin
+
if x {
y
}
diff --git a/src/cmd/gofmt/testdata/stdin1.input.gofmt b/src/cmd/gofmt/testdata/stdin1.input.gofmt
deleted file mode 100644
index 1f888877d..000000000
--- a/src/cmd/gofmt/testdata/stdin1.input.gofmt
+++ /dev/null
@@ -1,3 +0,0 @@
- if x {
- y
-}
diff --git a/src/cmd/gofmt/testdata/stdin2.golden b/src/cmd/gofmt/testdata/stdin2.golden
index 7eb1b54fe..57df35540 100644
--- a/src/cmd/gofmt/testdata/stdin2.golden
+++ b/src/cmd/gofmt/testdata/stdin2.golden
@@ -1,4 +1,4 @@
-
+//gofmt -stdin
var x int
diff --git a/src/cmd/gofmt/testdata/stdin2.golden.gofmt b/src/cmd/gofmt/testdata/stdin2.golden.gofmt
deleted file mode 100644
index 85e800300..000000000
--- a/src/cmd/gofmt/testdata/stdin2.golden.gofmt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-var x int
-
-func f() {
- y := z
-}
-
-
diff --git a/src/cmd/gofmt/testdata/stdin2.input b/src/cmd/gofmt/testdata/stdin2.input
index 99defd2d1..69d6bdd68 100644
--- a/src/cmd/gofmt/testdata/stdin2.input
+++ b/src/cmd/gofmt/testdata/stdin2.input
@@ -1,4 +1,4 @@
-
+//gofmt -stdin
var x int
diff --git a/src/cmd/gofmt/testdata/stdin2.input.gofmt b/src/cmd/gofmt/testdata/stdin2.input.gofmt
deleted file mode 100644
index 7eb1b54fe..000000000
--- a/src/cmd/gofmt/testdata/stdin2.input.gofmt
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-var x int
-
-func f() {
- y := z
- /* this is a comment */
- // this is a comment too
-}
-
-
diff --git a/src/cmd/gofmt/testdata/stdin3.golden b/src/cmd/gofmt/testdata/stdin3.golden
index 1bf2f5a48..d6da0e417 100644
--- a/src/cmd/gofmt/testdata/stdin3.golden
+++ b/src/cmd/gofmt/testdata/stdin3.golden
@@ -1,3 +1,4 @@
+ //gofmt -stdin
/* note: no newline at end of file */
for i := 0; i < 10; i++ {
diff --git a/src/cmd/gofmt/testdata/stdin3.golden.gofmt b/src/cmd/gofmt/testdata/stdin3.golden.gofmt
deleted file mode 100644
index b4d1d4663..000000000
--- a/src/cmd/gofmt/testdata/stdin3.golden.gofmt
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
- /* note: no newline at end of file */
- for i := 0; i < 10; i++ {
- s += i
- }
- \ No newline at end of file
diff --git a/src/cmd/gofmt/testdata/stdin3.input b/src/cmd/gofmt/testdata/stdin3.input
index d963bd0d2..ab46c1063 100644
--- a/src/cmd/gofmt/testdata/stdin3.input
+++ b/src/cmd/gofmt/testdata/stdin3.input
@@ -1,3 +1,4 @@
+ //gofmt -stdin
/* note: no newline at end of file */
for i := 0; i < 10; i++ { s += i }
diff --git a/src/cmd/gofmt/testdata/stdin3.input.gofmt b/src/cmd/gofmt/testdata/stdin3.input.gofmt
deleted file mode 100644
index b4d1d4663..000000000
--- a/src/cmd/gofmt/testdata/stdin3.input.gofmt
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
- /* note: no newline at end of file */
- for i := 0; i < 10; i++ {
- s += i
- }
- \ No newline at end of file
diff --git a/src/cmd/gofmt/testdata/stdin4.golden b/src/cmd/gofmt/testdata/stdin4.golden
index 5f7343551..0c7acace5 100644
--- a/src/cmd/gofmt/testdata/stdin4.golden
+++ b/src/cmd/gofmt/testdata/stdin4.golden
@@ -1,3 +1,5 @@
+ //gofmt -stdin
+
// comment
i := 0
diff --git a/src/cmd/gofmt/testdata/stdin4.golden.gofmt b/src/cmd/gofmt/testdata/stdin4.golden.gofmt
deleted file mode 100644
index 5f7343551..000000000
--- a/src/cmd/gofmt/testdata/stdin4.golden.gofmt
+++ /dev/null
@@ -1,3 +0,0 @@
- // comment
-
- i := 0
diff --git a/src/cmd/gofmt/testdata/stdin4.input b/src/cmd/gofmt/testdata/stdin4.input
index f02a54fb1..1fc73f31e 100644
--- a/src/cmd/gofmt/testdata/stdin4.input
+++ b/src/cmd/gofmt/testdata/stdin4.input
@@ -1,3 +1,5 @@
+ //gofmt -stdin
+
// comment
i := 0
diff --git a/src/cmd/gofmt/testdata/stdin4.input.gofmt b/src/cmd/gofmt/testdata/stdin4.input.gofmt
deleted file mode 100644
index 5f7343551..000000000
--- a/src/cmd/gofmt/testdata/stdin4.input.gofmt
+++ /dev/null
@@ -1,3 +0,0 @@
- // comment
-
- i := 0
diff --git a/src/cmd/gofmt/testdata/stdin5.golden b/src/cmd/gofmt/testdata/stdin5.golden
new file mode 100644
index 000000000..31ce6b248
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin5.golden
@@ -0,0 +1,3 @@
+//gofmt -stdin
+
+i := 5 // Line comment without newline. \ No newline at end of file
diff --git a/src/cmd/gofmt/testdata/stdin5.input b/src/cmd/gofmt/testdata/stdin5.input
new file mode 100644
index 000000000..0a7c97d18
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin5.input
@@ -0,0 +1,3 @@
+//gofmt -stdin
+
+i :=5// Line comment without newline. \ No newline at end of file
diff --git a/src/cmd/gofmt/testdata/stdin6.golden b/src/cmd/gofmt/testdata/stdin6.golden
new file mode 100644
index 000000000..ffcea8011
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin6.golden
@@ -0,0 +1,19 @@
+ //gofmt -stdin
+
+ if err != nil {
+ source := strings.NewReader(`line 1.
+line 2.
+`)
+ return source
+ }
+
+ f := func(hat, tail string) {
+
+ fmt.Println(hat+`
+foo
+
+
+`+tail,
+ "more",
+ "and more")
+ }
diff --git a/src/cmd/gofmt/testdata/stdin6.input b/src/cmd/gofmt/testdata/stdin6.input
new file mode 100644
index 000000000..78330020c
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin6.input
@@ -0,0 +1,21 @@
+ //gofmt -stdin
+
+ if err != nil {
+ source := strings.NewReader(`line 1.
+line 2.
+`)
+ return source
+ }
+
+ f:=func( hat, tail string){
+
+
+
+ fmt. Println ( hat+ `
+foo
+
+
+`+ tail ,
+ "more" ,
+ "and more" )
+ }
diff --git a/src/cmd/gofmt/testdata/stdin7.golden b/src/cmd/gofmt/testdata/stdin7.golden
new file mode 100644
index 000000000..bbac7133c
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin7.golden
@@ -0,0 +1,19 @@
+ //gofmt -stdin
+
+ if err != nil {
+ source := strings.NewReader(`line 1.
+line 2.
+`)
+ return source
+ }
+
+ f := func(hat, tail string) {
+
+ fmt.Println(hat+`
+ foo
+
+
+ `+tail,
+ "more",
+ "and more")
+ }
diff --git a/src/cmd/gofmt/testdata/stdin7.input b/src/cmd/gofmt/testdata/stdin7.input
new file mode 100644
index 000000000..fd772a3c4
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin7.input
@@ -0,0 +1,21 @@
+ //gofmt -stdin
+
+ if err != nil {
+ source := strings.NewReader(`line 1.
+line 2.
+`)
+ return source
+ }
+
+ f:=func( hat, tail string){
+
+
+
+ fmt. Println ( hat+ `
+ foo
+
+
+ `+ tail ,
+ "more" ,
+ "and more" )
+ }
diff --git a/src/cmd/nm/debug_goobj.go b/src/cmd/internal/goobj/read.go
index 9a067e2b9..79a83e59a 100644
--- a/src/cmd/nm/debug_goobj.go
+++ b/src/cmd/internal/goobj/read.go
@@ -1,8 +1,3 @@
-// DO NOT EDIT. Generated by code.google.com/p/rsc/cmd/bundle
-// bundle -p main -x goobj_ debug/goobj
-
-/* read.go */
-
// 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.
@@ -12,8 +7,7 @@
// TODO(rsc): Decide where this package should live. (golang.org/issue/6932)
// TODO(rsc): Decide the appropriate integer types for various fields.
// TODO(rsc): Write tests. (File format still up in the air a little.)
-
-package main
+package goobj
import (
"bufio"
@@ -26,7 +20,7 @@ import (
)
// A SymKind describes the kind of memory represented by a symbol.
-type goobj_SymKind int
+type SymKind int
// This list is taken from include/link.h.
@@ -34,108 +28,108 @@ type goobj_SymKind int
// TODO(rsc): Give idiomatic Go names.
// TODO(rsc): Reduce the number of symbol types in the object files.
const (
- _ goobj_SymKind = iota
+ _ SymKind = iota
// readonly, executable
- goobj_STEXT
- goobj_SELFRXSECT
+ STEXT
+ SELFRXSECT
// readonly, non-executable
- goobj_STYPE
- goobj_SSTRING
- goobj_SGOSTRING
- goobj_SGOFUNC
- goobj_SRODATA
- goobj_SFUNCTAB
- goobj_STYPELINK
- goobj_SSYMTAB // TODO: move to unmapped section
- goobj_SPCLNTAB
- goobj_SELFROSECT
+ STYPE
+ SSTRING
+ SGOSTRING
+ SGOFUNC
+ SRODATA
+ SFUNCTAB
+ STYPELINK
+ SSYMTAB // TODO: move to unmapped section
+ SPCLNTAB
+ SELFROSECT
// writable, non-executable
- goobj_SMACHOPLT
- goobj_SELFSECT
- goobj_SMACHO // Mach-O __nl_symbol_ptr
- goobj_SMACHOGOT
- goobj_SNOPTRDATA
- goobj_SINITARR
- goobj_SDATA
- goobj_SWINDOWS
- goobj_SBSS
- goobj_SNOPTRBSS
- goobj_STLSBSS
+ SMACHOPLT
+ SELFSECT
+ SMACHO // Mach-O __nl_symbol_ptr
+ SMACHOGOT
+ SNOPTRDATA
+ SINITARR
+ SDATA
+ SWINDOWS
+ SBSS
+ SNOPTRBSS
+ STLSBSS
// not mapped
- goobj_SXREF
- goobj_SMACHOSYMSTR
- goobj_SMACHOSYMTAB
- goobj_SMACHOINDIRECTPLT
- goobj_SMACHOINDIRECTGOT
- goobj_SFILE
- goobj_SFILEPATH
- goobj_SCONST
- goobj_SDYNIMPORT
- goobj_SHOSTOBJ
+ SXREF
+ SMACHOSYMSTR
+ SMACHOSYMTAB
+ SMACHOINDIRECTPLT
+ SMACHOINDIRECTGOT
+ SFILE
+ SFILEPATH
+ SCONST
+ SDYNIMPORT
+ SHOSTOBJ
)
-var goobj_symKindStrings = []string{
- goobj_SBSS: "SBSS",
- goobj_SCONST: "SCONST",
- goobj_SDATA: "SDATA",
- goobj_SDYNIMPORT: "SDYNIMPORT",
- goobj_SELFROSECT: "SELFROSECT",
- goobj_SELFRXSECT: "SELFRXSECT",
- goobj_SELFSECT: "SELFSECT",
- goobj_SFILE: "SFILE",
- goobj_SFILEPATH: "SFILEPATH",
- goobj_SFUNCTAB: "SFUNCTAB",
- goobj_SGOFUNC: "SGOFUNC",
- goobj_SGOSTRING: "SGOSTRING",
- goobj_SHOSTOBJ: "SHOSTOBJ",
- goobj_SINITARR: "SINITARR",
- goobj_SMACHO: "SMACHO",
- goobj_SMACHOGOT: "SMACHOGOT",
- goobj_SMACHOINDIRECTGOT: "SMACHOINDIRECTGOT",
- goobj_SMACHOINDIRECTPLT: "SMACHOINDIRECTPLT",
- goobj_SMACHOPLT: "SMACHOPLT",
- goobj_SMACHOSYMSTR: "SMACHOSYMSTR",
- goobj_SMACHOSYMTAB: "SMACHOSYMTAB",
- goobj_SNOPTRBSS: "SNOPTRBSS",
- goobj_SNOPTRDATA: "SNOPTRDATA",
- goobj_SPCLNTAB: "SPCLNTAB",
- goobj_SRODATA: "SRODATA",
- goobj_SSTRING: "SSTRING",
- goobj_SSYMTAB: "SSYMTAB",
- goobj_STEXT: "STEXT",
- goobj_STLSBSS: "STLSBSS",
- goobj_STYPE: "STYPE",
- goobj_STYPELINK: "STYPELINK",
- goobj_SWINDOWS: "SWINDOWS",
- goobj_SXREF: "SXREF",
+var symKindStrings = []string{
+ SBSS: "SBSS",
+ SCONST: "SCONST",
+ SDATA: "SDATA",
+ SDYNIMPORT: "SDYNIMPORT",
+ SELFROSECT: "SELFROSECT",
+ SELFRXSECT: "SELFRXSECT",
+ SELFSECT: "SELFSECT",
+ SFILE: "SFILE",
+ SFILEPATH: "SFILEPATH",
+ SFUNCTAB: "SFUNCTAB",
+ SGOFUNC: "SGOFUNC",
+ SGOSTRING: "SGOSTRING",
+ SHOSTOBJ: "SHOSTOBJ",
+ SINITARR: "SINITARR",
+ SMACHO: "SMACHO",
+ SMACHOGOT: "SMACHOGOT",
+ SMACHOINDIRECTGOT: "SMACHOINDIRECTGOT",
+ SMACHOINDIRECTPLT: "SMACHOINDIRECTPLT",
+ SMACHOPLT: "SMACHOPLT",
+ SMACHOSYMSTR: "SMACHOSYMSTR",
+ SMACHOSYMTAB: "SMACHOSYMTAB",
+ SNOPTRBSS: "SNOPTRBSS",
+ SNOPTRDATA: "SNOPTRDATA",
+ SPCLNTAB: "SPCLNTAB",
+ SRODATA: "SRODATA",
+ SSTRING: "SSTRING",
+ SSYMTAB: "SSYMTAB",
+ STEXT: "STEXT",
+ STLSBSS: "STLSBSS",
+ STYPE: "STYPE",
+ STYPELINK: "STYPELINK",
+ SWINDOWS: "SWINDOWS",
+ SXREF: "SXREF",
}
-func (k goobj_SymKind) String() string {
- if k < 0 || int(k) >= len(goobj_symKindStrings) {
+func (k SymKind) String() string {
+ if k < 0 || int(k) >= len(symKindStrings) {
return fmt.Sprintf("SymKind(%d)", k)
}
- return goobj_symKindStrings[k]
+ return symKindStrings[k]
}
// A Sym is a named symbol in an object file.
-type goobj_Sym struct {
- goobj_SymID // symbol identifier (name and version)
- Kind goobj_SymKind // kind of symbol
- DupOK bool // are duplicate definitions okay?
- Size int // size of corresponding data
- Type goobj_SymID // symbol for Go type information
- Data goobj_Data // memory image of symbol
- Reloc []goobj_Reloc // relocations to apply to Data
- Func *goobj_Func // additional data for functions
+type Sym struct {
+ SymID // symbol identifier (name and version)
+ Kind SymKind // kind of symbol
+ DupOK bool // are duplicate definitions okay?
+ Size int // size of corresponding data
+ Type SymID // symbol for Go type information
+ Data Data // memory image of symbol
+ Reloc []Reloc // relocations to apply to Data
+ Func *Func // additional data for functions
}
// A SymID - the combination of Name and Version - uniquely identifies
// a symbol within a package.
-type goobj_SymID struct {
+type SymID struct {
// Name is the name of a symbol.
Name string
@@ -147,7 +141,7 @@ type goobj_SymID struct {
Version int
}
-func (s goobj_SymID) String() string {
+func (s SymID) String() string {
if s.Version == 0 {
return s.Name
}
@@ -157,20 +151,20 @@ func (s goobj_SymID) String() string {
// A Data is a reference to data stored in an object file.
// It records the offset and size of the data, so that a client can
// read the data only if necessary.
-type goobj_Data struct {
+type Data struct {
Offset int64
Size int64
}
// A Reloc describes a relocation applied to a memory image to refer
// to an address within a particular symbol.
-type goobj_Reloc struct {
+type Reloc struct {
// The bytes at [Offset, Offset+Size) within the memory image
// should be updated to refer to the address Add bytes after the start
// of the symbol Sym.
Offset int
Size int
- Sym goobj_SymID
+ Sym SymID
Add int
// The Type records the form of address expected in the bytes
@@ -181,7 +175,7 @@ type goobj_Reloc struct {
// A Var describes a variable in a function stack frame: a declared
// local variable, an input argument, or an output result.
-type goobj_Var struct {
+type Var struct {
// The combination of Name, Kind, and Offset uniquely
// identifies a variable in a function stack frame.
// Using fewer of these - in particular, using only Name - does not.
@@ -189,57 +183,57 @@ type goobj_Var struct {
Kind int // TODO(rsc): Define meaning.
Offset int // Frame offset. TODO(rsc): Define meaning.
- Type goobj_SymID // Go type for variable.
+ Type SymID // Go type for variable.
}
// Func contains additional per-symbol information specific to functions.
-type goobj_Func struct {
- Args int // size in bytes of argument frame: inputs and outputs
- Frame int // size in bytes of local variable frame
- Leaf bool // function omits save of link register (ARM)
- NoSplit bool // function omits stack split prologue
- Var []goobj_Var // detail about local variables
- PCSP goobj_Data // PC → SP offset map
- PCFile goobj_Data // PC → file number map (index into File)
- PCLine goobj_Data // PC → line number map
- PCData []goobj_Data // PC → runtime support data map
- FuncData []goobj_FuncData // non-PC-specific runtime support data
- File []string // paths indexed by PCFile
+type Func struct {
+ Args int // size in bytes of argument frame: inputs and outputs
+ Frame int // size in bytes of local variable frame
+ Leaf bool // function omits save of link register (ARM)
+ NoSplit bool // function omits stack split prologue
+ Var []Var // detail about local variables
+ PCSP Data // PC → SP offset map
+ PCFile Data // PC → file number map (index into File)
+ PCLine Data // PC → line number map
+ PCData []Data // PC → runtime support data map
+ FuncData []FuncData // non-PC-specific runtime support data
+ File []string // paths indexed by PCFile
}
// TODO: Add PCData []byte and PCDataIter (similar to liblink).
// A FuncData is a single function-specific data value.
-type goobj_FuncData struct {
- Sym goobj_SymID // symbol holding data
- Offset int64 // offset into symbol for funcdata pointer
+type FuncData struct {
+ Sym SymID // symbol holding data
+ Offset int64 // offset into symbol for funcdata pointer
}
// A Package is a parsed Go object file or archive defining a Go package.
-type goobj_Package struct {
- ImportPath string // import path denoting this package
- Imports []string // packages imported by this package
- Syms []*goobj_Sym // symbols defined by this package
- MaxVersion int // maximum Version in any SymID in Syms
+type Package struct {
+ ImportPath string // import path denoting this package
+ Imports []string // packages imported by this package
+ Syms []*Sym // symbols defined by this package
+ MaxVersion int // maximum Version in any SymID in Syms
}
var (
- goobj_archiveHeader = []byte("!<arch>\n")
- goobj_archiveMagic = []byte("`\n")
- goobj_goobjHeader = []byte("go objec") // truncated to size of archiveHeader
+ archiveHeader = []byte("!<arch>\n")
+ archiveMagic = []byte("`\n")
+ goobjHeader = []byte("go objec") // truncated to size of archiveHeader
- goobj_errCorruptArchive = errors.New("corrupt archive")
- goobj_errTruncatedArchive = errors.New("truncated archive")
- goobj_errNotArchive = errors.New("unrecognized archive format")
+ errCorruptArchive = errors.New("corrupt archive")
+ errTruncatedArchive = errors.New("truncated archive")
+ errNotArchive = errors.New("unrecognized archive format")
- goobj_errCorruptObject = errors.New("corrupt object file")
- goobj_errTruncatedObject = errors.New("truncated object file")
- goobj_errNotObject = errors.New("unrecognized object file format")
+ errCorruptObject = errors.New("corrupt object file")
+ errTruncatedObject = errors.New("truncated object file")
+ errNotObject = errors.New("unrecognized object file format")
)
// An objReader is an object file reader.
-type goobj_objReader struct {
- p *goobj_Package
+type objReader struct {
+ p *Package
b *bufio.Reader
f io.ReadSeeker
err error
@@ -257,7 +251,7 @@ type goobj_objReader struct {
//
// See ../../../cmd/ld/lib.c:/^pathtoprefix and
// ../../../cmd/gc/subr.c:/^pathtoprefix.
-func goobj_importPathToPrefix(s string) string {
+func importPathToPrefix(s string) string {
// find index of last slash, if any, or else -1.
// used for determining whether an index is after the last slash.
slash := strings.LastIndex(s, "/")
@@ -290,21 +284,21 @@ func goobj_importPathToPrefix(s string) string {
}
// init initializes r to read package p from f.
-func (r *goobj_objReader) init(f io.ReadSeeker, p *goobj_Package) {
+func (r *objReader) init(f io.ReadSeeker, p *Package) {
r.f = f
r.p = p
r.offset, _ = f.Seek(0, 1)
r.limit, _ = f.Seek(0, 2)
f.Seek(r.offset, 0)
r.b = bufio.NewReader(f)
- r.pkgprefix = goobj_importPathToPrefix(p.ImportPath) + "."
+ r.pkgprefix = importPathToPrefix(p.ImportPath) + "."
}
// error records that an error occurred.
// It returns only the first error, so that an error
// caused by an earlier error does not discard information
// about the earlier error.
-func (r *goobj_objReader) error(err error) error {
+func (r *objReader) error(err error) error {
if r.err == nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
@@ -320,7 +314,7 @@ func (r *goobj_objReader) error(err error) error {
// A sequence of 0 bytes will eventually terminate any
// parsing state in the object file. In particular, it ends the
// reading of a varint.
-func (r *goobj_objReader) readByte() byte {
+func (r *objReader) readByte() byte {
if r.err != nil {
return 0
}
@@ -345,7 +339,7 @@ func (r *goobj_objReader) readByte() byte {
// If an error occurs, read returns the error but also
// records it, so it is safe for callers to ignore the result
// as long as delaying the report is not a problem.
-func (r *goobj_objReader) readFull(b []byte) error {
+func (r *objReader) readFull(b []byte) error {
if r.err != nil {
return r.err
}
@@ -361,12 +355,12 @@ func (r *goobj_objReader) readFull(b []byte) error {
}
// readInt reads a zigzag varint from the input file.
-func (r *goobj_objReader) readInt() int {
+func (r *objReader) readInt() int {
var u uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
- r.error(goobj_errCorruptObject)
+ r.error(errCorruptObject)
return 0
}
c := r.readByte()
@@ -378,14 +372,14 @@ func (r *goobj_objReader) readInt() int {
v := int64(u>>1) ^ (int64(u) << 63 >> 63)
if int64(int(v)) != v {
- r.error(goobj_errCorruptObject) // TODO
+ r.error(errCorruptObject) // TODO
return 0
}
return int(v)
}
// readString reads a length-delimited string from the input file.
-func (r *goobj_objReader) readString() string {
+func (r *objReader) readString() string {
n := r.readInt()
buf := make([]byte, n)
r.readFull(buf)
@@ -393,7 +387,7 @@ func (r *goobj_objReader) readString() string {
}
// readSymID reads a SymID from the input file.
-func (r *goobj_objReader) readSymID() goobj_SymID {
+func (r *objReader) readSymID() SymID {
name, vers := r.readString(), r.readInt()
// In a symbol name in an object file, "". denotes the
@@ -409,19 +403,19 @@ func (r *goobj_objReader) readSymID() goobj_SymID {
vers = r.p.MaxVersion
}
- return goobj_SymID{name, vers}
+ return SymID{name, vers}
}
// readData reads a data reference from the input file.
-func (r *goobj_objReader) readData() goobj_Data {
+func (r *objReader) readData() Data {
n := r.readInt()
- d := goobj_Data{Offset: r.offset, Size: int64(n)}
+ d := Data{Offset: r.offset, Size: int64(n)}
r.skip(int64(n))
return d
}
// skip skips n bytes in the input.
-func (r *goobj_objReader) skip(n int64) {
+func (r *objReader) skip(n int64) {
if n < 0 {
r.error(fmt.Errorf("debug/goobj: internal error: misuse of skip"))
}
@@ -450,14 +444,14 @@ func (r *goobj_objReader) skip(n int64) {
// Parse parses an object file or archive from r,
// assuming that its import path is pkgpath.
-func goobj_Parse(r io.ReadSeeker, pkgpath string) (*goobj_Package, error) {
+func Parse(r io.ReadSeeker, pkgpath string) (*Package, error) {
if pkgpath == "" {
pkgpath = `""`
}
- p := new(goobj_Package)
+ p := new(Package)
p.ImportPath = pkgpath
- var rd goobj_objReader
+ var rd objReader
rd.init(r, p)
err := rd.readFull(rd.tmp[:8])
if err != nil {
@@ -469,14 +463,14 @@ func goobj_Parse(r io.ReadSeeker, pkgpath string) (*goobj_Package, error) {
switch {
default:
- return nil, goobj_errNotObject
+ return nil, errNotObject
- case bytes.Equal(rd.tmp[:8], goobj_archiveHeader):
+ case bytes.Equal(rd.tmp[:8], archiveHeader):
if err := rd.parseArchive(); err != nil {
return nil, err
}
- case bytes.Equal(rd.tmp[:8], goobj_goobjHeader):
- if err := rd.parseObject(goobj_goobjHeader); err != nil {
+ case bytes.Equal(rd.tmp[:8], goobjHeader):
+ if err := rd.parseObject(goobjHeader); err != nil {
return nil, err
}
}
@@ -486,7 +480,7 @@ func goobj_Parse(r io.ReadSeeker, pkgpath string) (*goobj_Package, error) {
// trimSpace removes trailing spaces from b and returns the corresponding string.
// This effectively parses the form used in archive headers.
-func goobj_trimSpace(b []byte) string {
+func trimSpace(b []byte) string {
return string(bytes.TrimRight(b, " "))
}
@@ -494,7 +488,7 @@ func goobj_trimSpace(b []byte) string {
// TODO(rsc): Need to skip non-Go object files.
// TODO(rsc): Maybe record table of contents in r.p so that
// linker can avoid having code to parse archives too.
-func (r *goobj_objReader) parseArchive() error {
+func (r *objReader) parseArchive() error {
for r.offset < r.limit {
if err := r.readFull(r.tmp[:60]); err != nil {
return err
@@ -518,20 +512,20 @@ func (r *goobj_objReader) parseArchive() error {
// The file data that follows is padded to an even number of bytes:
// if size is odd, an extra padding byte is inserted betw the next header.
if len(data) < 60 {
- return goobj_errTruncatedArchive
+ return errTruncatedArchive
}
- if !bytes.Equal(data[58:60], goobj_archiveMagic) {
- return goobj_errCorruptArchive
+ if !bytes.Equal(data[58:60], archiveMagic) {
+ return errCorruptArchive
}
- name := goobj_trimSpace(data[0:16])
- size, err := strconv.ParseInt(goobj_trimSpace(data[48:58]), 10, 64)
+ name := trimSpace(data[0:16])
+ size, err := strconv.ParseInt(trimSpace(data[48:58]), 10, 64)
if err != nil {
- return goobj_errCorruptArchive
+ return errCorruptArchive
}
data = data[60:]
fsize := size + size&1
if fsize < 0 || fsize < size {
- return goobj_errCorruptArchive
+ return errCorruptArchive
}
switch name {
case "__.SYMDEF", "__.GOSYMDEF", "__.PKGDEF":
@@ -559,7 +553,7 @@ func (r *goobj_objReader) parseArchive() error {
// and then the part we want to parse begins.
// The format of that part is defined in a comment at the top
// of src/liblink/objfile.c.
-func (r *goobj_objReader) parseObject(prefix []byte) error {
+func (r *objReader) parseObject(prefix []byte) error {
// TODO(rsc): Maybe use prefix and the initial input to
// record the header line from the file, which would
// give the architecture and other version information.
@@ -569,7 +563,7 @@ func (r *goobj_objReader) parseObject(prefix []byte) error {
for {
c1, c2, c3 = c2, c3, r.readByte()
if c3 == 0 { // NUL or EOF, either is bad
- return goobj_errCorruptObject
+ return errCorruptObject
}
if c1 == '\n' && c2 == '!' && c3 == '\n' {
break
@@ -578,12 +572,12 @@ func (r *goobj_objReader) parseObject(prefix []byte) error {
r.readFull(r.tmp[:8])
if !bytes.Equal(r.tmp[:8], []byte("\x00\x00go13ld")) {
- return r.error(goobj_errCorruptObject)
+ return r.error(errCorruptObject)
}
b := r.readByte()
if b != 1 {
- return r.error(goobj_errCorruptObject)
+ return r.error(errCorruptObject)
}
// Direct package dependencies.
@@ -599,20 +593,21 @@ func (r *goobj_objReader) parseObject(prefix []byte) error {
for {
if b := r.readByte(); b != 0xfe {
if b != 0xff {
- return r.error(goobj_errCorruptObject)
+ return r.error(errCorruptObject)
}
break
}
typ := r.readInt()
- s := &goobj_Sym{goobj_SymID: r.readSymID()}
+ s := &Sym{SymID: r.readSymID()}
r.p.Syms = append(r.p.Syms, s)
- s.Kind = goobj_SymKind(typ)
- s.DupOK = r.readInt() != 0
+ s.Kind = SymKind(typ)
+ flags := r.readInt()
+ s.DupOK = flags&1 != 0
s.Size = r.readInt()
s.Type = r.readSymID()
s.Data = r.readData()
- s.Reloc = make([]goobj_Reloc, r.readInt())
+ s.Reloc = make([]Reloc, r.readInt())
for i := range s.Reloc {
rel := &s.Reloc[i]
rel.Offset = r.readInt()
@@ -624,14 +619,15 @@ func (r *goobj_objReader) parseObject(prefix []byte) error {
r.readSymID() // Xsym - ignored
}
- if s.Kind == goobj_STEXT {
- f := new(goobj_Func)
+ if s.Kind == STEXT {
+ f := new(Func)
s.Func = f
f.Args = r.readInt()
f.Frame = r.readInt()
- f.Leaf = r.readInt() != 0
+ flags := r.readInt()
+ f.Leaf = flags&1 != 0
f.NoSplit = r.readInt() != 0
- f.Var = make([]goobj_Var, r.readInt())
+ f.Var = make([]Var, r.readInt())
for i := range f.Var {
v := &f.Var[i]
v.Name = r.readSymID().Name
@@ -643,11 +639,11 @@ func (r *goobj_objReader) parseObject(prefix []byte) error {
f.PCSP = r.readData()
f.PCFile = r.readData()
f.PCLine = r.readData()
- f.PCData = make([]goobj_Data, r.readInt())
+ f.PCData = make([]Data, r.readInt())
for i := range f.PCData {
f.PCData[i] = r.readData()
}
- f.FuncData = make([]goobj_FuncData, r.readInt())
+ f.FuncData = make([]FuncData, r.readInt())
for i := range f.FuncData {
f.FuncData[i].Sym = r.readSymID()
}
@@ -663,7 +659,7 @@ func (r *goobj_objReader) parseObject(prefix []byte) error {
r.readFull(r.tmp[:7])
if !bytes.Equal(r.tmp[:7], []byte("\xffgo13ld")) {
- return r.error(goobj_errCorruptObject)
+ return r.error(errCorruptObject)
}
return nil
diff --git a/src/cmd/internal/goobj/read_test.go b/src/cmd/internal/goobj/read_test.go
new file mode 100644
index 000000000..cc991e5d9
--- /dev/null
+++ b/src/cmd/internal/goobj/read_test.go
@@ -0,0 +1,28 @@
+// 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 goobj
+
+import "testing"
+
+var importPathToPrefixTests = []struct {
+ in string
+ out string
+}{
+ {"runtime", "runtime"},
+ {"sync/atomic", "sync/atomic"},
+ {"golang.org/x/tools/godoc", "golang.org/x/tools/godoc"},
+ {"foo.bar/baz.quux", "foo.bar/baz%2equux"},
+ {"", ""},
+ {"%foo%bar", "%25foo%25bar"},
+ {"\x01\x00\x7F☺", "%01%00%7f%e2%98%ba"},
+}
+
+func TestImportPathToPrefix(t *testing.T) {
+ for _, tt := range importPathToPrefixTests {
+ if out := importPathToPrefix(tt.in); out != tt.out {
+ t.Errorf("importPathToPrefix(%q) = %q, want %q", tt.in, out, tt.out)
+ }
+ }
+}
diff --git a/src/cmd/internal/objfile/disasm.go b/src/cmd/internal/objfile/disasm.go
new file mode 100644
index 000000000..1a339c321
--- /dev/null
+++ b/src/cmd/internal/objfile/disasm.go
@@ -0,0 +1,248 @@
+// 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 objfile
+
+import (
+ "bufio"
+ "debug/gosym"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "regexp"
+ "sort"
+ "strings"
+ "text/tabwriter"
+
+ "cmd/internal/rsc.io/arm/armasm"
+ "cmd/internal/rsc.io/x86/x86asm"
+)
+
+// Disasm is a disassembler for a given File.
+type Disasm struct {
+ syms []Sym //symbols in file, sorted by address
+ pcln *gosym.Table // pcln table
+ text []byte // bytes of text segment (actual instructions)
+ textStart uint64 // start PC of text
+ textEnd uint64 // end PC of text
+ goarch string // GOARCH string
+ disasm disasmFunc // disassembler function for goarch
+ byteOrder binary.ByteOrder // byte order for goarch
+}
+
+// Disasm returns a disassembler for the file f.
+func (f *File) Disasm() (*Disasm, error) {
+ syms, err := f.Symbols()
+ if err != nil {
+ return nil, err
+ }
+
+ pcln, err := f.PCLineTable()
+ if err != nil {
+ return nil, err
+ }
+
+ textStart, textBytes, err := f.Text()
+ if err != nil {
+ return nil, err
+ }
+
+ goarch := f.GOARCH()
+ disasm := disasms[goarch]
+ byteOrder := byteOrders[goarch]
+ if disasm == nil || byteOrder == nil {
+ return nil, fmt.Errorf("unsupported architecture")
+ }
+
+ // Filter out section symbols, overwriting syms in place.
+ keep := syms[:0]
+ for _, sym := range syms {
+ switch sym.Name {
+ case "runtime.text", "text", "_text", "runtime.etext", "etext", "_etext":
+ // drop
+ default:
+ keep = append(keep, sym)
+ }
+ }
+ syms = keep
+ d := &Disasm{
+ syms: syms,
+ pcln: pcln,
+ text: textBytes,
+ textStart: textStart,
+ textEnd: textStart + uint64(len(textBytes)),
+ goarch: goarch,
+ disasm: disasm,
+ byteOrder: byteOrder,
+ }
+
+ return d, nil
+}
+
+// lookup finds the symbol name containing addr.
+func (d *Disasm) lookup(addr uint64) (name string, base uint64) {
+ i := sort.Search(len(d.syms), func(i int) bool { return addr < d.syms[i].Addr })
+ if i > 0 {
+ s := d.syms[i-1]
+ if s.Addr != 0 && s.Addr <= addr && addr < s.Addr+uint64(s.Size) {
+ return s.Name, s.Addr
+ }
+ }
+ return "", 0
+}
+
+// base returns the final element in the path.
+// It works on both Windows and Unix paths,
+// regardless of host operating system.
+func base(path string) string {
+ path = path[strings.LastIndex(path, "/")+1:]
+ path = path[strings.LastIndex(path, `\`)+1:]
+ return path
+}
+
+// Print prints a disassembly of the file to w.
+// If filter is non-nil, the disassembly only includes functions with names matching filter.
+// The disassembly only includes functions that overlap the range [start, end).
+func (d *Disasm) Print(w io.Writer, filter *regexp.Regexp, start, end uint64) {
+ if start < d.textStart {
+ start = d.textStart
+ }
+ if end > d.textEnd {
+ end = d.textEnd
+ }
+ printed := false
+ bw := bufio.NewWriter(w)
+ for _, sym := range d.syms {
+ symStart := sym.Addr
+ symEnd := sym.Addr + uint64(sym.Size)
+ if sym.Code != 'T' && sym.Code != 't' ||
+ symStart < d.textStart ||
+ symEnd <= start || end <= symStart ||
+ filter != nil && !filter.MatchString(sym.Name) {
+ continue
+ }
+ if printed {
+ fmt.Fprintf(bw, "\n")
+ }
+ printed = true
+
+ file, _, _ := d.pcln.PCToLine(sym.Addr)
+ fmt.Fprintf(bw, "TEXT %s(SB) %s\n", sym.Name, file)
+
+ tw := tabwriter.NewWriter(bw, 1, 8, 1, '\t', 0)
+ if symEnd > end {
+ symEnd = end
+ }
+ code := d.text[:end-d.textStart]
+ d.Decode(symStart, symEnd, func(pc, size uint64, file string, line int, text string) {
+ i := pc - d.textStart
+ fmt.Fprintf(tw, "\t%s:%d\t%#x\t", base(file), line, pc)
+ if size%4 != 0 || d.goarch == "386" || d.goarch == "amd64" {
+ // Print instruction as bytes.
+ fmt.Fprintf(tw, "%x", code[i:i+size])
+ } else {
+ // Print instruction as 32-bit words.
+ for j := uint64(0); j < size; j += 4 {
+ if j > 0 {
+ fmt.Fprintf(tw, " ")
+ }
+ fmt.Fprintf(tw, "%08x", d.byteOrder.Uint32(code[i+j:]))
+ }
+ }
+ fmt.Fprintf(tw, "\t%s\n", text)
+ })
+ tw.Flush()
+ }
+ bw.Flush()
+}
+
+// Decode disassembles the text segment range [start, end), calling f for each instruction.
+func (d *Disasm) Decode(start, end uint64, f func(pc, size uint64, file string, line int, text string)) {
+ if start < d.textStart {
+ start = d.textStart
+ }
+ if end > d.textEnd {
+ end = d.textEnd
+ }
+ code := d.text[:end-d.textStart]
+ lookup := d.lookup
+ for pc := start; pc < end; {
+ i := pc - d.textStart
+ text, size := d.disasm(code[i:], pc, lookup)
+ file, line, _ := d.pcln.PCToLine(pc)
+ f(pc, uint64(size), file, line, text)
+ pc += uint64(size)
+ }
+}
+
+type lookupFunc func(addr uint64) (sym string, base uint64)
+type disasmFunc func(code []byte, pc uint64, lookup lookupFunc) (text string, size int)
+
+func disasm_386(code []byte, pc uint64, lookup lookupFunc) (string, int) {
+ return disasm_x86(code, pc, lookup, 32)
+}
+
+func disasm_amd64(code []byte, pc uint64, lookup lookupFunc) (string, int) {
+ return disasm_x86(code, pc, lookup, 64)
+}
+
+func disasm_x86(code []byte, pc uint64, lookup lookupFunc, arch int) (string, int) {
+ inst, err := x86asm.Decode(code, 64)
+ var text string
+ size := inst.Len
+ if err != nil || size == 0 || inst.Op == 0 {
+ size = 1
+ text = "?"
+ } else {
+ text = x86asm.Plan9Syntax(inst, pc, lookup)
+ }
+ return text, size
+}
+
+type textReader struct {
+ code []byte
+ pc uint64
+}
+
+func (r textReader) ReadAt(data []byte, off int64) (n int, err error) {
+ if off < 0 || uint64(off) < r.pc {
+ return 0, io.EOF
+ }
+ d := uint64(off) - r.pc
+ if d >= uint64(len(r.code)) {
+ return 0, io.EOF
+ }
+ n = copy(data, r.code[d:])
+ if n < len(data) {
+ err = io.ErrUnexpectedEOF
+ }
+ return
+}
+
+func disasm_arm(code []byte, pc uint64, lookup lookupFunc) (string, int) {
+ inst, err := armasm.Decode(code, armasm.ModeARM)
+ var text string
+ size := inst.Len
+ if err != nil || size == 0 || inst.Op == 0 {
+ size = 4
+ text = "?"
+ } else {
+ text = armasm.Plan9Syntax(inst, pc, lookup, textReader{code, pc})
+ }
+ return text, size
+}
+
+var disasms = map[string]disasmFunc{
+ "386": disasm_386,
+ "amd64": disasm_amd64,
+ "arm": disasm_arm,
+}
+
+var byteOrders = map[string]binary.ByteOrder{
+ "386": binary.LittleEndian,
+ "amd64": binary.LittleEndian,
+ "arm": binary.LittleEndian,
+ "power64": binary.BigEndian,
+ "power64le": binary.LittleEndian,
+}
diff --git a/src/cmd/internal/objfile/elf.go b/src/cmd/internal/objfile/elf.go
new file mode 100644
index 000000000..17755b84d
--- /dev/null
+++ b/src/cmd/internal/objfile/elf.go
@@ -0,0 +1,104 @@
+// 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.
+
+// Parsing of ELF executables (Linux, FreeBSD, and so on).
+
+package objfile
+
+import (
+ "debug/elf"
+ "fmt"
+ "os"
+)
+
+type elfFile struct {
+ elf *elf.File
+}
+
+func openElf(r *os.File) (rawFile, error) {
+ f, err := elf.NewFile(r)
+ if err != nil {
+ return nil, err
+ }
+ return &elfFile{f}, nil
+}
+
+func (f *elfFile) symbols() ([]Sym, error) {
+ elfSyms, err := f.elf.Symbols()
+ if err != nil {
+ return nil, err
+ }
+
+ var syms []Sym
+ for _, s := range elfSyms {
+ sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'}
+ switch s.Section {
+ case elf.SHN_UNDEF:
+ sym.Code = 'U'
+ case elf.SHN_COMMON:
+ sym.Code = 'B'
+ default:
+ i := int(s.Section)
+ if i < 0 || i >= len(f.elf.Sections) {
+ break
+ }
+ sect := f.elf.Sections[i]
+ switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) {
+ case elf.SHF_ALLOC | elf.SHF_EXECINSTR:
+ sym.Code = 'T'
+ case elf.SHF_ALLOC:
+ sym.Code = 'R'
+ case elf.SHF_ALLOC | elf.SHF_WRITE:
+ sym.Code = 'D'
+ }
+ }
+ if elf.ST_BIND(s.Info) == elf.STB_LOCAL {
+ sym.Code += 'a' - 'A'
+ }
+ syms = append(syms, sym)
+ }
+
+ return syms, nil
+}
+
+func (f *elfFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
+ if sect := f.elf.Section(".text"); sect != nil {
+ textStart = sect.Addr
+ }
+ if sect := f.elf.Section(".gosymtab"); sect != nil {
+ if symtab, err = sect.Data(); err != nil {
+ return 0, nil, nil, err
+ }
+ }
+ if sect := f.elf.Section(".gopclntab"); sect != nil {
+ if pclntab, err = sect.Data(); err != nil {
+ return 0, nil, nil, err
+ }
+ }
+ return textStart, symtab, pclntab, nil
+}
+
+func (f *elfFile) text() (textStart uint64, text []byte, err error) {
+ sect := f.elf.Section(".text")
+ if sect == nil {
+ return 0, nil, fmt.Errorf("text section not found")
+ }
+ textStart = sect.Addr
+ text, err = sect.Data()
+ return
+}
+
+func (f *elfFile) goarch() string {
+ switch f.elf.Machine {
+ case elf.EM_386:
+ return "386"
+ case elf.EM_X86_64:
+ return "amd64"
+ case elf.EM_ARM:
+ return "arm"
+ case elf.EM_PPC64:
+ return "power64"
+ }
+ return ""
+}
diff --git a/src/cmd/internal/objfile/goobj.go b/src/cmd/internal/objfile/goobj.go
new file mode 100644
index 000000000..6b1607a17
--- /dev/null
+++ b/src/cmd/internal/objfile/goobj.go
@@ -0,0 +1,93 @@
+// 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.
+
+// Parsing of Go intermediate object files and archives.
+
+package objfile
+
+import (
+ "cmd/internal/goobj"
+ "fmt"
+ "os"
+)
+
+type goobjFile struct {
+ goobj *goobj.Package
+}
+
+func openGoobj(r *os.File) (rawFile, error) {
+ f, err := goobj.Parse(r, `""`)
+ if err != nil {
+ return nil, err
+ }
+ return &goobjFile{f}, nil
+}
+
+func goobjName(id goobj.SymID) string {
+ if id.Version == 0 {
+ return id.Name
+ }
+ return fmt.Sprintf("%s<%d>", id.Name, id.Version)
+}
+
+func (f *goobjFile) symbols() ([]Sym, error) {
+ seen := make(map[goobj.SymID]bool)
+
+ var syms []Sym
+ for _, s := range f.goobj.Syms {
+ seen[s.SymID] = true
+ sym := Sym{Addr: uint64(s.Data.Offset), Name: goobjName(s.SymID), Size: int64(s.Size), Type: s.Type.Name, Code: '?'}
+ switch s.Kind {
+ case goobj.STEXT, goobj.SELFRXSECT:
+ sym.Code = 'T'
+ case goobj.STYPE, goobj.SSTRING, goobj.SGOSTRING, goobj.SGOFUNC, goobj.SRODATA, goobj.SFUNCTAB, goobj.STYPELINK, goobj.SSYMTAB, goobj.SPCLNTAB, goobj.SELFROSECT:
+ sym.Code = 'R'
+ case goobj.SMACHOPLT, goobj.SELFSECT, goobj.SMACHO, goobj.SMACHOGOT, goobj.SNOPTRDATA, goobj.SINITARR, goobj.SDATA, goobj.SWINDOWS:
+ sym.Code = 'D'
+ case goobj.SBSS, goobj.SNOPTRBSS, goobj.STLSBSS:
+ sym.Code = 'B'
+ case goobj.SXREF, goobj.SMACHOSYMSTR, goobj.SMACHOSYMTAB, goobj.SMACHOINDIRECTPLT, goobj.SMACHOINDIRECTGOT, goobj.SFILE, goobj.SFILEPATH, goobj.SCONST, goobj.SDYNIMPORT, goobj.SHOSTOBJ:
+ sym.Code = 'X' // should not see
+ }
+ if s.Version != 0 {
+ sym.Code += 'a' - 'A'
+ }
+ syms = append(syms, sym)
+ }
+
+ for _, s := range f.goobj.Syms {
+ for _, r := range s.Reloc {
+ if !seen[r.Sym] {
+ seen[r.Sym] = true
+ sym := Sym{Name: goobjName(r.Sym), Code: 'U'}
+ if s.Version != 0 {
+ // should not happen but handle anyway
+ sym.Code = 'u'
+ }
+ syms = append(syms, sym)
+ }
+ }
+ }
+
+ return syms, nil
+}
+
+// pcln does not make sense for Go object files, because each
+// symbol has its own individual pcln table, so there is no global
+// space of addresses to map.
+func (f *goobjFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
+ return 0, nil, nil, fmt.Errorf("pcln not available in go object file")
+}
+
+// text does not make sense for Go object files, because
+// each function has a separate section.
+func (f *goobjFile) text() (textStart uint64, text []byte, err error) {
+ return 0, nil, fmt.Errorf("text not available in go object file")
+}
+
+// goarch makes sense but is not exposed in debug/goobj's API,
+// and we don't need it yet for any users of internal/objfile.
+func (f *goobjFile) goarch() string {
+ return "GOARCH unimplemented for debug/goobj files"
+}
diff --git a/src/cmd/internal/objfile/macho.go b/src/cmd/internal/objfile/macho.go
new file mode 100644
index 000000000..7dd84a339
--- /dev/null
+++ b/src/cmd/internal/objfile/macho.go
@@ -0,0 +1,116 @@
+// 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.
+
+// Parsing of Mach-O executables (OS X).
+
+package objfile
+
+import (
+ "debug/macho"
+ "fmt"
+ "os"
+ "sort"
+)
+
+type machoFile struct {
+ macho *macho.File
+}
+
+func openMacho(r *os.File) (rawFile, error) {
+ f, err := macho.NewFile(r)
+ if err != nil {
+ return nil, err
+ }
+ return &machoFile{f}, nil
+}
+
+func (f *machoFile) symbols() ([]Sym, error) {
+ if f.macho.Symtab == nil {
+ return nil, fmt.Errorf("missing symbol table")
+ }
+
+ // Build sorted list of addresses of all symbols.
+ // We infer the size of a symbol by looking at where the next symbol begins.
+ var addrs []uint64
+ for _, s := range f.macho.Symtab.Syms {
+ addrs = append(addrs, s.Value)
+ }
+ sort.Sort(uint64s(addrs))
+
+ var syms []Sym
+ for _, s := range f.macho.Symtab.Syms {
+ sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'}
+ i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value })
+ if i < len(addrs) {
+ sym.Size = int64(addrs[i] - s.Value)
+ }
+ if s.Sect == 0 {
+ sym.Code = 'U'
+ } else if int(s.Sect) <= len(f.macho.Sections) {
+ sect := f.macho.Sections[s.Sect-1]
+ switch sect.Seg {
+ case "__TEXT":
+ sym.Code = 'R'
+ case "__DATA":
+ sym.Code = 'D'
+ }
+ switch sect.Seg + " " + sect.Name {
+ case "__TEXT __text":
+ sym.Code = 'T'
+ case "__DATA __bss", "__DATA __noptrbss":
+ sym.Code = 'B'
+ }
+ }
+ syms = append(syms, sym)
+ }
+
+ return syms, nil
+}
+
+func (f *machoFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
+ if sect := f.macho.Section("__text"); sect != nil {
+ textStart = sect.Addr
+ }
+ if sect := f.macho.Section("__gosymtab"); sect != nil {
+ if symtab, err = sect.Data(); err != nil {
+ return 0, nil, nil, err
+ }
+ }
+ if sect := f.macho.Section("__gopclntab"); sect != nil {
+ if pclntab, err = sect.Data(); err != nil {
+ return 0, nil, nil, err
+ }
+ }
+ return textStart, symtab, pclntab, nil
+}
+
+func (f *machoFile) text() (textStart uint64, text []byte, err error) {
+ sect := f.macho.Section("__text")
+ if sect == nil {
+ return 0, nil, fmt.Errorf("text section not found")
+ }
+ textStart = sect.Addr
+ text, err = sect.Data()
+ return
+}
+
+func (f *machoFile) goarch() string {
+ switch f.macho.Cpu {
+ case macho.Cpu386:
+ return "386"
+ case macho.CpuAmd64:
+ return "amd64"
+ case macho.CpuArm:
+ return "arm"
+ case macho.CpuPpc64:
+ return "power64"
+ }
+ return ""
+}
+
+type uint64s []uint64
+
+func (x uint64s) Len() int { return len(x) }
+func (x uint64s) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x uint64s) Less(i, j int) bool { return x[i] < x[j] }
diff --git a/src/cmd/internal/objfile/objfile.go b/src/cmd/internal/objfile/objfile.go
new file mode 100644
index 000000000..9227ef387
--- /dev/null
+++ b/src/cmd/internal/objfile/objfile.go
@@ -0,0 +1,94 @@
+// 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 objfile implements portable access to OS-specific executable files.
+package objfile
+
+import (
+ "debug/gosym"
+ "fmt"
+ "os"
+ "sort"
+)
+
+type rawFile interface {
+ symbols() (syms []Sym, err error)
+ pcln() (textStart uint64, symtab, pclntab []byte, err error)
+ text() (textStart uint64, text []byte, err error)
+ goarch() string
+}
+
+// A File is an opened executable file.
+type File struct {
+ r *os.File
+ raw rawFile
+}
+
+// A Sym is a symbol defined in an executable file.
+type Sym struct {
+ Name string // symbol name
+ Addr uint64 // virtual address of symbol
+ Size int64 // size in bytes
+ Code rune // nm code (T for text, D for data, and so on)
+ Type string // XXX?
+}
+
+var openers = []func(*os.File) (rawFile, error){
+ openElf,
+ openGoobj,
+ openMacho,
+ openPE,
+ openPlan9,
+}
+
+// Open opens the named file.
+// The caller must call f.Close when the file is no longer needed.
+func Open(name string) (*File, error) {
+ r, err := os.Open(name)
+ if err != nil {
+ return nil, err
+ }
+ for _, try := range openers {
+ if raw, err := try(r); err == nil {
+ return &File{r, raw}, nil
+ }
+ }
+ r.Close()
+ return nil, fmt.Errorf("open %s: unrecognized object file", name)
+}
+
+func (f *File) Close() error {
+ return f.r.Close()
+}
+
+func (f *File) Symbols() ([]Sym, error) {
+ syms, err := f.raw.symbols()
+ if err != nil {
+ return nil, err
+ }
+ sort.Sort(byAddr(syms))
+ return syms, nil
+}
+
+type byAddr []Sym
+
+func (x byAddr) Less(i, j int) bool { return x[i].Addr < x[j].Addr }
+func (x byAddr) Len() int { return len(x) }
+func (x byAddr) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+func (f *File) PCLineTable() (*gosym.Table, error) {
+ textStart, symtab, pclntab, err := f.raw.pcln()
+ if err != nil {
+ return nil, err
+ }
+ return gosym.NewTable(symtab, gosym.NewLineTable(pclntab, textStart))
+}
+
+func (f *File) Text() (uint64, []byte, error) {
+ return f.raw.text()
+}
+
+func (f *File) GOARCH() string {
+ return f.raw.goarch()
+}
diff --git a/src/cmd/internal/objfile/pe.go b/src/cmd/internal/objfile/pe.go
new file mode 100644
index 000000000..67e59c226
--- /dev/null
+++ b/src/cmd/internal/objfile/pe.go
@@ -0,0 +1,201 @@
+// 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.
+
+// Parsing of PE executables (Microsoft Windows).
+
+package objfile
+
+import (
+ "debug/pe"
+ "fmt"
+ "os"
+ "sort"
+)
+
+type peFile struct {
+ pe *pe.File
+}
+
+func openPE(r *os.File) (rawFile, error) {
+ f, err := pe.NewFile(r)
+ if err != nil {
+ return nil, err
+ }
+ switch f.OptionalHeader.(type) {
+ case *pe.OptionalHeader32, *pe.OptionalHeader64:
+ // ok
+ default:
+ return nil, fmt.Errorf("unrecognized PE format")
+ }
+ return &peFile{f}, nil
+}
+
+func (f *peFile) symbols() ([]Sym, error) {
+ // Build sorted list of addresses of all symbols.
+ // We infer the size of a symbol by looking at where the next symbol begins.
+ var addrs []uint64
+
+ var imageBase uint64
+ switch oh := f.pe.OptionalHeader.(type) {
+ case *pe.OptionalHeader32:
+ imageBase = uint64(oh.ImageBase)
+ case *pe.OptionalHeader64:
+ imageBase = oh.ImageBase
+ }
+
+ var syms []Sym
+ for _, s := range f.pe.Symbols {
+ const (
+ N_UNDEF = 0 // An undefined (extern) symbol
+ N_ABS = -1 // An absolute symbol (e_value is a constant, not an address)
+ N_DEBUG = -2 // A debugging symbol
+ )
+ sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'}
+ switch s.SectionNumber {
+ case N_UNDEF:
+ sym.Code = 'U'
+ case N_ABS:
+ sym.Code = 'C'
+ case N_DEBUG:
+ sym.Code = '?'
+ default:
+ if s.SectionNumber < 0 || len(f.pe.Sections) < int(s.SectionNumber) {
+ return nil, fmt.Errorf("invalid section number in symbol table")
+ }
+ sect := f.pe.Sections[s.SectionNumber-1]
+ const (
+ text = 0x20
+ data = 0x40
+ bss = 0x80
+ permX = 0x20000000
+ permR = 0x40000000
+ permW = 0x80000000
+ )
+ ch := sect.Characteristics
+ switch {
+ case ch&text != 0:
+ sym.Code = 'T'
+ case ch&data != 0:
+ if ch&permW == 0 {
+ sym.Code = 'R'
+ } else {
+ sym.Code = 'D'
+ }
+ case ch&bss != 0:
+ sym.Code = 'B'
+ }
+ sym.Addr += imageBase + uint64(sect.VirtualAddress)
+ }
+ syms = append(syms, sym)
+ addrs = append(addrs, sym.Addr)
+ }
+
+ sort.Sort(uint64s(addrs))
+ for i := range syms {
+ j := sort.Search(len(addrs), func(x int) bool { return addrs[x] > syms[i].Addr })
+ if j < len(addrs) {
+ syms[i].Size = int64(addrs[j] - syms[i].Addr)
+ }
+ }
+
+ return syms, nil
+}
+
+func (f *peFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
+ var imageBase uint64
+ switch oh := f.pe.OptionalHeader.(type) {
+ case *pe.OptionalHeader32:
+ imageBase = uint64(oh.ImageBase)
+ case *pe.OptionalHeader64:
+ imageBase = oh.ImageBase
+ default:
+ return 0, nil, nil, fmt.Errorf("pe file format not recognized")
+ }
+ if sect := f.pe.Section(".text"); sect != nil {
+ textStart = imageBase + uint64(sect.VirtualAddress)
+ }
+ if pclntab, err = loadPETable(f.pe, "runtime.pclntab", "runtime.epclntab"); err != nil {
+ // We didn't find the symbols, so look for the names used in 1.3 and earlier.
+ // TODO: Remove code looking for the old symbols when we no longer care about 1.3.
+ var err2 error
+ if pclntab, err2 = loadPETable(f.pe, "pclntab", "epclntab"); err2 != nil {
+ return 0, nil, nil, err
+ }
+ }
+ if symtab, err = loadPETable(f.pe, "runtime.symtab", "runtime.esymtab"); err != nil {
+ // Same as above.
+ var err2 error
+ if symtab, err2 = loadPETable(f.pe, "symtab", "esymtab"); err2 != nil {
+ return 0, nil, nil, err
+ }
+ }
+ return textStart, symtab, pclntab, nil
+}
+
+func (f *peFile) text() (textStart uint64, text []byte, err error) {
+ var imageBase uint64
+ switch oh := f.pe.OptionalHeader.(type) {
+ case *pe.OptionalHeader32:
+ imageBase = uint64(oh.ImageBase)
+ case *pe.OptionalHeader64:
+ imageBase = oh.ImageBase
+ default:
+ return 0, nil, fmt.Errorf("pe file format not recognized")
+ }
+ sect := f.pe.Section(".text")
+ if sect == nil {
+ return 0, nil, fmt.Errorf("text section not found")
+ }
+ textStart = imageBase + uint64(sect.VirtualAddress)
+ text, err = sect.Data()
+ return
+}
+
+func findPESymbol(f *pe.File, name string) (*pe.Symbol, error) {
+ for _, s := range f.Symbols {
+ if s.Name != name {
+ continue
+ }
+ if s.SectionNumber <= 0 {
+ return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber)
+ }
+ if len(f.Sections) < int(s.SectionNumber) {
+ return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections))
+ }
+ return s, nil
+ }
+ return nil, fmt.Errorf("no %s symbol found", name)
+}
+
+func loadPETable(f *pe.File, sname, ename string) ([]byte, error) {
+ ssym, err := findPESymbol(f, sname)
+ if err != nil {
+ return nil, err
+ }
+ esym, err := findPESymbol(f, ename)
+ if err != nil {
+ return nil, err
+ }
+ if ssym.SectionNumber != esym.SectionNumber {
+ return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename)
+ }
+ sect := f.Sections[ssym.SectionNumber-1]
+ data, err := sect.Data()
+ if err != nil {
+ return nil, err
+ }
+ return data[ssym.Value:esym.Value], nil
+}
+
+func (f *peFile) goarch() string {
+ // Not sure how to get the info we want from PE header.
+ // Look in symbol table for telltale rt0 symbol.
+ if _, err := findPESymbol(f.pe, "_rt0_386_windows"); err == nil {
+ return "386"
+ }
+ if _, err := findPESymbol(f.pe, "_rt0_amd64_windows"); err == nil {
+ return "amd64"
+ }
+ return ""
+}
diff --git a/src/cmd/internal/objfile/plan9obj.go b/src/cmd/internal/objfile/plan9obj.go
new file mode 100644
index 000000000..eb6cba5eb
--- /dev/null
+++ b/src/cmd/internal/objfile/plan9obj.go
@@ -0,0 +1,146 @@
+// 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.
+
+// Parsing of Plan 9 a.out executables.
+
+package objfile
+
+import (
+ "debug/plan9obj"
+ "fmt"
+ "os"
+ "sort"
+)
+
+var validSymType = map[rune]bool{
+ 'T': true,
+ 't': true,
+ 'D': true,
+ 'd': true,
+ 'B': true,
+ 'b': true,
+}
+
+type plan9File struct {
+ plan9 *plan9obj.File
+}
+
+func openPlan9(r *os.File) (rawFile, error) {
+ f, err := plan9obj.NewFile(r)
+ if err != nil {
+ return nil, err
+ }
+ return &plan9File{f}, nil
+}
+
+func (f *plan9File) symbols() ([]Sym, error) {
+ plan9Syms, err := f.plan9.Symbols()
+ if err != nil {
+ return nil, err
+ }
+
+ // Build sorted list of addresses of all symbols.
+ // We infer the size of a symbol by looking at where the next symbol begins.
+ var addrs []uint64
+ for _, s := range plan9Syms {
+ if !validSymType[s.Type] {
+ continue
+ }
+ addrs = append(addrs, s.Value)
+ }
+ sort.Sort(uint64s(addrs))
+
+ var syms []Sym
+
+ for _, s := range plan9Syms {
+ if !validSymType[s.Type] {
+ continue
+ }
+ sym := Sym{Addr: s.Value, Name: s.Name, Code: rune(s.Type)}
+ i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value })
+ if i < len(addrs) {
+ sym.Size = int64(addrs[i] - s.Value)
+ }
+ syms = append(syms, sym)
+ }
+
+ return syms, nil
+}
+
+func (f *plan9File) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
+ textStart = f.plan9.LoadAddress + f.plan9.HdrSize
+ if pclntab, err = loadPlan9Table(f.plan9, "runtime.pclntab", "runtime.epclntab"); err != nil {
+ // We didn't find the symbols, so look for the names used in 1.3 and earlier.
+ // TODO: Remove code looking for the old symbols when we no longer care about 1.3.
+ var err2 error
+ if pclntab, err2 = loadPlan9Table(f.plan9, "pclntab", "epclntab"); err2 != nil {
+ return 0, nil, nil, err
+ }
+ }
+ if symtab, err = loadPlan9Table(f.plan9, "runtime.symtab", "runtime.esymtab"); err != nil {
+ // Same as above.
+ var err2 error
+ if symtab, err2 = loadPlan9Table(f.plan9, "symtab", "esymtab"); err2 != nil {
+ return 0, nil, nil, err
+ }
+ }
+ return textStart, symtab, pclntab, nil
+}
+
+func (f *plan9File) text() (textStart uint64, text []byte, err error) {
+ sect := f.plan9.Section("text")
+ if sect == nil {
+ return 0, nil, fmt.Errorf("text section not found")
+ }
+ textStart = f.plan9.LoadAddress + f.plan9.HdrSize
+ text, err = sect.Data()
+ return
+}
+
+func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) {
+ syms, err := f.Symbols()
+ if err != nil {
+ return nil, err
+ }
+ for _, s := range syms {
+ if s.Name != name {
+ continue
+ }
+ return &s, nil
+ }
+ return nil, fmt.Errorf("no %s symbol found", name)
+}
+
+func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) {
+ ssym, err := findPlan9Symbol(f, sname)
+ if err != nil {
+ return nil, err
+ }
+ esym, err := findPlan9Symbol(f, ename)
+ if err != nil {
+ return nil, err
+ }
+ sect := f.Section("text")
+ if sect == nil {
+ return nil, err
+ }
+ data, err := sect.Data()
+ if err != nil {
+ return nil, err
+ }
+ textStart := f.LoadAddress + f.HdrSize
+ return data[ssym.Value-textStart : esym.Value-textStart], nil
+}
+
+func (f *plan9File) goarch() string {
+ switch f.plan9.Magic {
+ case plan9obj.Magic386:
+ return "386"
+ case plan9obj.MagicAMD64:
+ return "amd64"
+ case plan9obj.MagicARM:
+ return "arm"
+ }
+ return ""
+}
diff --git a/src/cmd/internal/rsc.io/arm/armasm/Makefile b/src/cmd/internal/rsc.io/arm/armasm/Makefile
new file mode 100644
index 000000000..a3f57001f
--- /dev/null
+++ b/src/cmd/internal/rsc.io/arm/armasm/Makefile
@@ -0,0 +1,2 @@
+tables.go: ../armmap/map.go ../arm.csv
+ go run ../armmap/map.go -fmt=decoder ../arm.csv >_tables.go && gofmt _tables.go >tables.go && rm _tables.go
diff --git a/src/cmd/internal/rsc.io/arm/armasm/decode.go b/src/cmd/internal/rsc.io/arm/armasm/decode.go
new file mode 100644
index 000000000..6b4d73841
--- /dev/null
+++ b/src/cmd/internal/rsc.io/arm/armasm/decode.go
@@ -0,0 +1,567 @@
+// 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"
+ "fmt"
+)
+
+// An instFormat describes the format of an instruction encoding.
+// An instruction with 32-bit value x matches the format if x&mask == value
+// and the condition matches.
+// The condition matches if x>>28 == 0xF && value>>28==0xF
+// or if x>>28 != 0xF and value>>28 == 0.
+// If x matches the format, then the rest of the fields describe how to interpret x.
+// The opBits describe bits that should be extracted from x and added to the opcode.
+// For example opBits = 0x1234 means that the value
+// (2 bits at offset 1) followed by (4 bits at offset 3)
+// should be added to op.
+// Finally the args describe how to decode the instruction arguments.
+// args is stored as a fixed-size array; if there are fewer than len(args) arguments,
+// args[i] == 0 marks the end of the argument list.
+type instFormat struct {
+ mask uint32
+ value uint32
+ priority int8
+ op Op
+ opBits uint64
+ args instArgs
+}
+
+type instArgs [4]instArg
+
+var (
+ errMode = fmt.Errorf("unsupported execution mode")
+ errShort = fmt.Errorf("truncated instruction")
+ errUnknown = fmt.Errorf("unknown instruction")
+)
+
+var decoderCover []bool
+
+// Decode decodes the leading bytes in src as a single instruction.
+func Decode(src []byte, mode Mode) (inst Inst, err error) {
+ if mode != ModeARM {
+ return Inst{}, errMode
+ }
+ if len(src) < 4 {
+ return Inst{}, errShort
+ }
+
+ if decoderCover == nil {
+ decoderCover = make([]bool, len(instFormats))
+ }
+
+ x := binary.LittleEndian.Uint32(src)
+
+ // The instFormat table contains both conditional and unconditional instructions.
+ // Considering only the top 4 bits, the conditional instructions use mask=0, value=0,
+ // while the unconditional instructions use mask=f, value=f.
+ // Prepare a version of x with the condition cleared to 0 in conditional instructions
+ // and then assume mask=f during matching.
+ const condMask = 0xf0000000
+ xNoCond := x
+ if x&condMask != condMask {
+ xNoCond &^= condMask
+ }
+ var priority int8
+Search:
+ for i := range instFormats {
+ f := &instFormats[i]
+ if xNoCond&(f.mask|condMask) != f.value || f.priority <= priority {
+ continue
+ }
+ delta := uint32(0)
+ deltaShift := uint(0)
+ for opBits := f.opBits; opBits != 0; opBits >>= 16 {
+ n := uint(opBits & 0xFF)
+ off := uint((opBits >> 8) & 0xFF)
+ delta |= (x >> off) & (1<<n - 1) << deltaShift
+ deltaShift += n
+ }
+ op := f.op + Op(delta)
+
+ // Special case: BKPT encodes with condition but cannot have one.
+ if op&^15 == BKPT_EQ && op != BKPT {
+ continue Search
+ }
+
+ var args Args
+ for j, aop := range f.args {
+ if aop == 0 {
+ break
+ }
+ arg := decodeArg(aop, x)
+ if arg == nil { // cannot decode argument
+ continue Search
+ }
+ args[j] = arg
+ }
+
+ decoderCover[i] = true
+
+ inst = Inst{
+ Op: op,
+ Args: args,
+ Enc: x,
+ Len: 4,
+ }
+ priority = f.priority
+ continue Search
+ }
+ if inst.Op != 0 {
+ return inst, nil
+ }
+ return Inst{}, errUnknown
+}
+
+// An instArg describes the encoding of a single argument.
+// In the names used for arguments, _p_ means +, _m_ means -,
+// _pm_ means ± (usually keyed by the U bit).
+// The _W suffix indicates a general addressing mode based on the P and W bits.
+// The _offset and _postindex suffixes force the given addressing mode.
+// The rest should be somewhat self-explanatory, at least given
+// the decodeArg function.
+type instArg uint8
+
+const (
+ _ instArg = iota
+ arg_APSR
+ arg_FPSCR
+ arg_Dn_half
+ arg_R1_0
+ arg_R1_12
+ arg_R2_0
+ arg_R2_12
+ arg_R_0
+ arg_R_12
+ arg_R_12_nzcv
+ arg_R_16
+ arg_R_16_WB
+ arg_R_8
+ arg_R_rotate
+ arg_R_shift_R
+ arg_R_shift_imm
+ arg_SP
+ arg_Sd
+ arg_Sd_Dd
+ arg_Dd_Sd
+ arg_Sm
+ arg_Sm_Dm
+ arg_Sn
+ arg_Sn_Dn
+ arg_const
+ arg_endian
+ arg_fbits
+ arg_fp_0
+ arg_imm24
+ arg_imm5
+ arg_imm5_32
+ arg_imm5_nz
+ arg_imm_12at8_4at0
+ arg_imm_4at16_12at0
+ arg_imm_vfp
+ arg_label24
+ arg_label24H
+ arg_label_m_12
+ arg_label_p_12
+ arg_label_pm_12
+ arg_label_pm_4_4
+ arg_lsb_width
+ arg_mem_R
+ arg_mem_R_pm_R_W
+ arg_mem_R_pm_R_postindex
+ arg_mem_R_pm_R_shift_imm_W
+ arg_mem_R_pm_R_shift_imm_offset
+ arg_mem_R_pm_R_shift_imm_postindex
+ arg_mem_R_pm_imm12_W
+ arg_mem_R_pm_imm12_offset
+ arg_mem_R_pm_imm12_postindex
+ arg_mem_R_pm_imm8_W
+ arg_mem_R_pm_imm8_postindex
+ arg_mem_R_pm_imm8at0_offset
+ arg_option
+ arg_registers
+ arg_registers1
+ arg_registers2
+ arg_satimm4
+ arg_satimm5
+ arg_satimm4m1
+ arg_satimm5m1
+ arg_widthm1
+)
+
+// decodeArg decodes the arg described by aop from the instruction bits x.
+// It returns nil if x cannot be decoded according to aop.
+func decodeArg(aop instArg, x uint32) Arg {
+ switch aop {
+ default:
+ return nil
+
+ case arg_APSR:
+ return APSR
+ case arg_FPSCR:
+ return FPSCR
+
+ case arg_R_0:
+ return Reg(x & (1<<4 - 1))
+ case arg_R_8:
+ return Reg((x >> 8) & (1<<4 - 1))
+ case arg_R_12:
+ return Reg((x >> 12) & (1<<4 - 1))
+ case arg_R_16:
+ return Reg((x >> 16) & (1<<4 - 1))
+
+ case arg_R_12_nzcv:
+ r := Reg((x >> 12) & (1<<4 - 1))
+ if r == R15 {
+ return APSR_nzcv
+ }
+ return r
+
+ case arg_R_16_WB:
+ mode := AddrLDM
+ if (x>>21)&1 != 0 {
+ mode = AddrLDM_WB
+ }
+ return Mem{Base: Reg((x >> 16) & (1<<4 - 1)), Mode: mode}
+
+ case arg_R_rotate:
+ Rm := Reg(x & (1<<4 - 1))
+ typ, count := decodeShift(x)
+ // ROR #0 here means ROR #0, but decodeShift rewrites to RRX #1.
+ if typ == RotateRightExt {
+ return Reg(Rm)
+ }
+ return RegShift{Rm, typ, uint8(count)}
+
+ case arg_R_shift_R:
+ Rm := Reg(x & (1<<4 - 1))
+ Rs := Reg((x >> 8) & (1<<4 - 1))
+ typ := Shift((x >> 5) & (1<<2 - 1))
+ return RegShiftReg{Rm, typ, Rs}
+
+ case arg_R_shift_imm:
+ Rm := Reg(x & (1<<4 - 1))
+ typ, count := decodeShift(x)
+ if typ == ShiftLeft && count == 0 {
+ return Reg(Rm)
+ }
+ return RegShift{Rm, typ, uint8(count)}
+
+ case arg_R1_0:
+ return Reg((x & (1<<4 - 1)))
+ case arg_R1_12:
+ return Reg(((x >> 12) & (1<<4 - 1)))
+ case arg_R2_0:
+ return Reg((x & (1<<4 - 1)) | 1)
+ case arg_R2_12:
+ return Reg(((x >> 12) & (1<<4 - 1)) | 1)
+
+ case arg_SP:
+ return SP
+
+ case arg_Sd_Dd:
+ v := (x >> 12) & (1<<4 - 1)
+ vx := (x >> 22) & 1
+ sz := (x >> 8) & 1
+ if sz != 0 {
+ return D0 + Reg(vx<<4+v)
+ } else {
+ return S0 + Reg(v<<1+vx)
+ }
+
+ case arg_Dd_Sd:
+ return decodeArg(arg_Sd_Dd, x^(1<<8))
+
+ case arg_Sd:
+ v := (x >> 12) & (1<<4 - 1)
+ vx := (x >> 22) & 1
+ return S0 + Reg(v<<1+vx)
+
+ case arg_Sm_Dm:
+ v := (x >> 0) & (1<<4 - 1)
+ vx := (x >> 5) & 1
+ sz := (x >> 8) & 1
+ if sz != 0 {
+ return D0 + Reg(vx<<4+v)
+ } else {
+ return S0 + Reg(v<<1+vx)
+ }
+
+ case arg_Sm:
+ v := (x >> 0) & (1<<4 - 1)
+ vx := (x >> 5) & 1
+ return S0 + Reg(v<<1+vx)
+
+ case arg_Dn_half:
+ v := (x >> 16) & (1<<4 - 1)
+ vx := (x >> 7) & 1
+ return RegX{D0 + Reg(vx<<4+v), int((x >> 21) & 1)}
+
+ case arg_Sn_Dn:
+ v := (x >> 16) & (1<<4 - 1)
+ vx := (x >> 7) & 1
+ sz := (x >> 8) & 1
+ if sz != 0 {
+ return D0 + Reg(vx<<4+v)
+ } else {
+ return S0 + Reg(v<<1+vx)
+ }
+
+ case arg_Sn:
+ v := (x >> 16) & (1<<4 - 1)
+ vx := (x >> 7) & 1
+ return S0 + Reg(v<<1+vx)
+
+ case arg_const:
+ v := x & (1<<8 - 1)
+ rot := (x >> 8) & (1<<4 - 1) * 2
+ if rot > 0 && v&3 == 0 {
+ // could rotate less
+ return ImmAlt{uint8(v), uint8(rot)}
+ }
+ if rot >= 24 && ((v<<(32-rot))&0xFF)>>(32-rot) == v {
+ // could wrap around to rot==0.
+ return ImmAlt{uint8(v), uint8(rot)}
+ }
+ return Imm(v>>rot | v<<(32-rot))
+
+ case arg_endian:
+ return Endian((x >> 9) & 1)
+
+ case arg_fbits:
+ return Imm((16 << ((x >> 7) & 1)) - ((x&(1<<4-1))<<1 | (x>>5)&1))
+
+ case arg_fp_0:
+ return Imm(0)
+
+ case arg_imm24:
+ return Imm(x & (1<<24 - 1))
+
+ case arg_imm5:
+ return Imm((x >> 7) & (1<<5 - 1))
+
+ case arg_imm5_32:
+ x = (x >> 7) & (1<<5 - 1)
+ if x == 0 {
+ x = 32
+ }
+ return Imm(x)
+
+ case arg_imm5_nz:
+ x = (x >> 7) & (1<<5 - 1)
+ if x == 0 {
+ return nil
+ }
+ return Imm(x)
+
+ case arg_imm_4at16_12at0:
+ return Imm((x>>16)&(1<<4-1)<<12 | x&(1<<12-1))
+
+ case arg_imm_12at8_4at0:
+ return Imm((x>>8)&(1<<12-1)<<4 | x&(1<<4-1))
+
+ case arg_imm_vfp:
+ x = (x>>16)&(1<<4-1)<<4 | x&(1<<4-1)
+ return Imm(x)
+
+ case arg_label24:
+ imm := (x & (1<<24 - 1)) << 2
+ return PCRel(int32(imm<<6) >> 6)
+
+ case arg_label24H:
+ h := (x >> 24) & 1
+ imm := (x&(1<<24-1))<<2 | h<<1
+ return PCRel(int32(imm<<6) >> 6)
+
+ case arg_label_m_12:
+ d := int32(x & (1<<12 - 1))
+ return Mem{Base: PC, Mode: AddrOffset, Offset: int16(-d)}
+
+ case arg_label_p_12:
+ d := int32(x & (1<<12 - 1))
+ return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)}
+
+ case arg_label_pm_12:
+ d := int32(x & (1<<12 - 1))
+ u := (x >> 23) & 1
+ if u == 0 {
+ d = -d
+ }
+ return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)}
+
+ case arg_label_pm_4_4:
+ d := int32((x>>8)&(1<<4-1)<<4 | x&(1<<4-1))
+ u := (x >> 23) & 1
+ if u == 0 {
+ d = -d
+ }
+ return PCRel(d)
+
+ case arg_lsb_width:
+ lsb := (x >> 7) & (1<<5 - 1)
+ msb := (x >> 16) & (1<<5 - 1)
+ if msb < lsb || msb >= 32 {
+ return nil
+ }
+ return Imm(msb + 1 - lsb)
+
+ case arg_mem_R:
+ Rn := Reg((x >> 16) & (1<<4 - 1))
+ return Mem{Base: Rn, Mode: AddrOffset}
+
+ case arg_mem_R_pm_R_postindex:
+ // Treat [<Rn>],+/-<Rm> like [<Rn>,+/-<Rm>{,<shift>}]{!}
+ // by forcing shift bits to <<0 and P=0, W=0 (postindex=true).
+ return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5|1<<24|1<<21))
+
+ case arg_mem_R_pm_R_W:
+ // Treat [<Rn>,+/-<Rm>]{!} like [<Rn>,+/-<Rm>{,<shift>}]{!}
+ // by forcing shift bits to <<0.
+ return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5))
+
+ case arg_mem_R_pm_R_shift_imm_offset:
+ // Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!}
+ // by forcing P=1, W=0 (index=false, wback=false).
+ return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<21)|1<<24)
+
+ case arg_mem_R_pm_R_shift_imm_postindex:
+ // Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!}
+ // by forcing P=0, W=0 (postindex=true).
+ return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<24|1<<21))
+
+ case arg_mem_R_pm_R_shift_imm_W:
+ Rn := Reg((x >> 16) & (1<<4 - 1))
+ Rm := Reg(x & (1<<4 - 1))
+ typ, count := decodeShift(x)
+ u := (x >> 23) & 1
+ w := (x >> 21) & 1
+ p := (x >> 24) & 1
+ if p == 0 && w == 1 {
+ return nil
+ }
+ sign := int8(+1)
+ if u == 0 {
+ sign = -1
+ }
+ mode := AddrMode(uint8(p<<1) | uint8(w^1))
+ return Mem{Base: Rn, Mode: mode, Sign: sign, Index: Rm, Shift: typ, Count: count}
+
+ case arg_mem_R_pm_imm12_offset:
+ // Treat [<Rn>,#+/-<imm12>] like [<Rn>{,#+/-<imm12>}]{!}
+ // by forcing P=1, W=0 (index=false, wback=false).
+ return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<21)|1<<24)
+
+ case arg_mem_R_pm_imm12_postindex:
+ // Treat [<Rn>],#+/-<imm12> like [<Rn>{,#+/-<imm12>}]{!}
+ // by forcing P=0, W=0 (postindex=true).
+ return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<24|1<<21))
+
+ case arg_mem_R_pm_imm12_W:
+ Rn := Reg((x >> 16) & (1<<4 - 1))
+ u := (x >> 23) & 1
+ w := (x >> 21) & 1
+ p := (x >> 24) & 1
+ if p == 0 && w == 1 {
+ return nil
+ }
+ sign := int8(+1)
+ if u == 0 {
+ sign = -1
+ }
+ imm := int16(x & (1<<12 - 1))
+ mode := AddrMode(uint8(p<<1) | uint8(w^1))
+ return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm}
+
+ case arg_mem_R_pm_imm8_postindex:
+ // Treat [<Rn>],#+/-<imm8> like [<Rn>{,#+/-<imm8>}]{!}
+ // by forcing P=0, W=0 (postindex=true).
+ return decodeArg(arg_mem_R_pm_imm8_W, x&^(1<<24|1<<21))
+
+ case arg_mem_R_pm_imm8_W:
+ Rn := Reg((x >> 16) & (1<<4 - 1))
+ u := (x >> 23) & 1
+ w := (x >> 21) & 1
+ p := (x >> 24) & 1
+ if p == 0 && w == 1 {
+ return nil
+ }
+ sign := int8(+1)
+ if u == 0 {
+ sign = -1
+ }
+ imm := int16((x>>8)&(1<<4-1)<<4 | x&(1<<4-1))
+ mode := AddrMode(uint8(p<<1) | uint8(w^1))
+ return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm}
+
+ case arg_mem_R_pm_imm8at0_offset:
+ Rn := Reg((x >> 16) & (1<<4 - 1))
+ u := (x >> 23) & 1
+ sign := int8(+1)
+ if u == 0 {
+ sign = -1
+ }
+ imm := int16(x&(1<<8-1)) << 2
+ return Mem{Base: Rn, Mode: AddrOffset, Offset: int16(sign) * imm}
+
+ case arg_option:
+ return Imm(x & (1<<4 - 1))
+
+ case arg_registers:
+ return RegList(x & (1<<16 - 1))
+
+ case arg_registers2:
+ x &= 1<<16 - 1
+ n := 0
+ for i := 0; i < 16; i++ {
+ if x>>uint(i)&1 != 0 {
+ n++
+ }
+ }
+ if n < 2 {
+ return nil
+ }
+ return RegList(x)
+
+ case arg_registers1:
+ Rt := (x >> 12) & (1<<4 - 1)
+ return RegList(1 << Rt)
+
+ case arg_satimm4:
+ return Imm((x >> 16) & (1<<4 - 1))
+
+ case arg_satimm5:
+ return Imm((x >> 16) & (1<<5 - 1))
+
+ case arg_satimm4m1:
+ return Imm((x>>16)&(1<<4-1) + 1)
+
+ case arg_satimm5m1:
+ return Imm((x>>16)&(1<<5-1) + 1)
+
+ case arg_widthm1:
+ return Imm((x>>16)&(1<<5-1) + 1)
+
+ }
+}
+
+// decodeShift decodes the shift-by-immediate encoded in x.
+func decodeShift(x uint32) (Shift, uint8) {
+ count := (x >> 7) & (1<<5 - 1)
+ typ := Shift((x >> 5) & (1<<2 - 1))
+ switch typ {
+ case ShiftRight, ShiftRightSigned:
+ if count == 0 {
+ count = 32
+ }
+ case RotateRight:
+ if count == 0 {
+ typ = RotateRightExt
+ count = 1
+ }
+ }
+ return typ, uint8(count)
+}
diff --git a/src/cmd/internal/rsc.io/arm/armasm/decode_test.go b/src/cmd/internal/rsc.io/arm/armasm/decode_test.go
new file mode 100644
index 000000000..25a345a88
--- /dev/null
+++ b/src/cmd/internal/rsc.io/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":
+ 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
new file mode 100644
index 000000000..b0bd85597
--- /dev/null
+++ b/src/cmd/internal/rsc.io/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 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 sequenc 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/gnu.go b/src/cmd/internal/rsc.io/arm/armasm/gnu.go
new file mode 100644
index 000000000..1a97a5a84
--- /dev/null
+++ b/src/cmd/internal/rsc.io/arm/armasm/gnu.go
@@ -0,0 +1,164 @@
+// 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"
+ "fmt"
+ "strings"
+)
+
+var saveDot = strings.NewReplacer(
+ ".F16", "_dot_F16",
+ ".F32", "_dot_F32",
+ ".F64", "_dot_F64",
+ ".S32", "_dot_S32",
+ ".U32", "_dot_U32",
+ ".FXS", "_dot_S",
+ ".FXU", "_dot_U",
+ ".32", "_dot_32",
+)
+
+// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
+// This form typically matches the syntax defined in the ARM Reference Manual.
+func GNUSyntax(inst Inst) string {
+ var buf bytes.Buffer
+ op := inst.Op.String()
+ op = saveDot.Replace(op)
+ op = strings.Replace(op, ".", "", -1)
+ op = strings.Replace(op, "_dot_", ".", -1)
+ op = strings.ToLower(op)
+ buf.WriteString(op)
+ sep := " "
+ for i, arg := range inst.Args {
+ if arg == nil {
+ break
+ }
+ text := gnuArg(&inst, i, arg)
+ if text == "" {
+ continue
+ }
+ buf.WriteString(sep)
+ sep = ", "
+ buf.WriteString(text)
+ }
+ return buf.String()
+}
+
+func gnuArg(inst *Inst, argIndex int, arg Arg) string {
+ switch inst.Op &^ 15 {
+ case LDRD_EQ, LDREXD_EQ, STRD_EQ:
+ if argIndex == 1 {
+ // second argument in consecutive pair not printed
+ return ""
+ }
+ case STREXD_EQ:
+ if argIndex == 2 {
+ // second argument in consecutive pair not printed
+ return ""
+ }
+ }
+
+ switch arg := arg.(type) {
+ case Imm:
+ switch inst.Op &^ 15 {
+ case BKPT_EQ:
+ return fmt.Sprintf("%#04x", uint32(arg))
+ case SVC_EQ:
+ return fmt.Sprintf("%#08x", uint32(arg))
+ }
+ return fmt.Sprintf("#%d", int32(arg))
+
+ case ImmAlt:
+ return fmt.Sprintf("#%d, %d", arg.Val, arg.Rot)
+
+ case Mem:
+ R := gnuArg(inst, -1, arg.Base)
+ X := ""
+ if arg.Sign != 0 {
+ X = ""
+ if arg.Sign < 0 {
+ X = "-"
+ }
+ X += gnuArg(inst, -1, arg.Index)
+ if arg.Shift == ShiftLeft && arg.Count == 0 {
+ // nothing
+ } else if arg.Shift == RotateRightExt {
+ X += ", rrx"
+ } else {
+ X += fmt.Sprintf(", %s #%d", strings.ToLower(arg.Shift.String()), arg.Count)
+ }
+ } else {
+ X = fmt.Sprintf("#%d", arg.Offset)
+ }
+
+ switch arg.Mode {
+ case AddrOffset:
+ if X == "#0" {
+ return fmt.Sprintf("[%s]", R)
+ }
+ return fmt.Sprintf("[%s, %s]", R, X)
+ case AddrPreIndex:
+ return fmt.Sprintf("[%s, %s]!", R, X)
+ case AddrPostIndex:
+ return fmt.Sprintf("[%s], %s", R, X)
+ case AddrLDM:
+ if X == "#0" {
+ return R
+ }
+ case AddrLDM_WB:
+ if X == "#0" {
+ return R + "!"
+ }
+ }
+ return fmt.Sprintf("[%s Mode(%d) %s]", R, int(arg.Mode), X)
+
+ case PCRel:
+ return fmt.Sprintf(".%+#x", int32(arg)+4)
+
+ case Reg:
+ switch inst.Op &^ 15 {
+ case LDREX_EQ:
+ if argIndex == 0 {
+ return fmt.Sprintf("r%d", int32(arg))
+ }
+ }
+ switch arg {
+ case R10:
+ return "sl"
+ case R11:
+ return "fp"
+ case R12:
+ return "ip"
+ }
+
+ case RegList:
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, "{")
+ sep := ""
+ for i := 0; i < 16; i++ {
+ if arg&(1<<uint(i)) != 0 {
+ fmt.Fprintf(&buf, "%s%s", sep, gnuArg(inst, -1, Reg(i)))
+ sep = ", "
+ }
+ }
+ fmt.Fprintf(&buf, "}")
+ return buf.String()
+
+ case RegShift:
+ if arg.Shift == ShiftLeft && arg.Count == 0 {
+ return gnuArg(inst, -1, arg.Reg)
+ }
+ if arg.Shift == RotateRightExt {
+ return gnuArg(inst, -1, arg.Reg) + ", rrx"
+ }
+ return fmt.Sprintf("%s, %s #%d", gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), arg.Count)
+
+ case RegShiftReg:
+ return fmt.Sprintf("%s, %s %s", gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), gnuArg(inst, -1, arg.RegCount))
+
+ }
+ return strings.ToLower(arg.String())
+}
diff --git a/src/cmd/internal/rsc.io/arm/armasm/inst.go b/src/cmd/internal/rsc.io/arm/armasm/inst.go
new file mode 100644
index 000000000..60d633bdb
--- /dev/null
+++ b/src/cmd/internal/rsc.io/arm/armasm/inst.go
@@ -0,0 +1,438 @@
+// 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"
+ "fmt"
+)
+
+// A Mode is an instruction execution mode.
+type Mode int
+
+const (
+ _ Mode = iota
+ ModeARM
+ ModeThumb
+)
+
+func (m Mode) String() string {
+ switch m {
+ case ModeARM:
+ return "ARM"
+ case ModeThumb:
+ return "Thumb"
+ }
+ return fmt.Sprintf("Mode(%d)", int(m))
+}
+
+// An Op is an ARM opcode.
+type Op uint16
+
+// NOTE: The actual Op values are defined in tables.go.
+// They are chosen to simplify instruction decoding and
+// are not a dense packing from 0 to N, although the
+// density is high, probably at least 90%.
+
+func (op Op) String() string {
+ if op >= Op(len(opstr)) || opstr[op] == "" {
+ return fmt.Sprintf("Op(%d)", int(op))
+ }
+ return opstr[op]
+}
+
+// An Inst is a single instruction.
+type Inst struct {
+ Op Op // Opcode mnemonic
+ Enc uint32 // Raw encoding bits.
+ Len int // Length of encoding in bytes.
+ Args Args // Instruction arguments, in ARM manual order.
+}
+
+func (i Inst) String() string {
+ var buf bytes.Buffer
+ buf.WriteString(i.Op.String())
+ for j, arg := range i.Args {
+ if arg == nil {
+ break
+ }
+ if j == 0 {
+ buf.WriteString(" ")
+ } else {
+ buf.WriteString(", ")
+ }
+ buf.WriteString(arg.String())
+ }
+ return buf.String()
+}
+
+// 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:
+// Endian, Imm, Mem, PCRel, Reg, RegList, RegShift, RegShiftReg.
+type Arg interface {
+ IsArg()
+ String() string
+}
+
+type Float32Imm float32
+
+func (Float32Imm) IsArg() {}
+
+func (f Float32Imm) String() string {
+ return fmt.Sprintf("#%v", float32(f))
+}
+
+type Float64Imm float32
+
+func (Float64Imm) IsArg() {}
+
+func (f Float64Imm) String() string {
+ return fmt.Sprintf("#%v", float64(f))
+}
+
+// An Imm is an integer constant.
+type Imm uint32
+
+func (Imm) IsArg() {}
+
+func (i Imm) String() string {
+ return fmt.Sprintf("#%#x", uint32(i))
+}
+
+// A ImmAlt is an alternate encoding of an integer constant.
+type ImmAlt struct {
+ Val uint8
+ Rot uint8
+}
+
+func (ImmAlt) IsArg() {}
+
+func (i ImmAlt) Imm() Imm {
+ v := uint32(i.Val)
+ r := uint(i.Rot)
+ return Imm(v>>r | v<<(32-r))
+}
+
+func (i ImmAlt) String() string {
+ return fmt.Sprintf("#%#x, %d", i.Val, i.Rot)
+}
+
+// A Label is a text (code) address.
+type Label uint32
+
+func (Label) IsArg() {}
+
+func (i Label) String() string {
+ return fmt.Sprintf("%#x", uint32(i))
+}
+
+// A Reg is a single register.
+// The zero value denotes R0, not the absence of a register.
+type Reg uint8
+
+const (
+ R0 Reg = iota
+ R1
+ R2
+ R3
+ R4
+ R5
+ R6
+ R7
+ R8
+ R9
+ R10
+ R11
+ R12
+ R13
+ R14
+ R15
+
+ S0
+ S1
+ S2
+ S3
+ S4
+ S5
+ S6
+ S7
+ S8
+ S9
+ S10
+ S11
+ S12
+ S13
+ S14
+ S15
+ S16
+ S17
+ S18
+ S19
+ S20
+ S21
+ S22
+ S23
+ S24
+ S25
+ S26
+ S27
+ S28
+ S29
+ S30
+ S31
+
+ D0
+ D1
+ D2
+ D3
+ D4
+ D5
+ D6
+ D7
+ D8
+ D9
+ D10
+ D11
+ D12
+ D13
+ D14
+ D15
+ D16
+ D17
+ D18
+ D19
+ D20
+ D21
+ D22
+ D23
+ D24
+ D25
+ D26
+ D27
+ D28
+ D29
+ D30
+ D31
+
+ APSR
+ APSR_nzcv
+ FPSCR
+
+ SP = R13
+ LR = R14
+ PC = R15
+)
+
+func (Reg) IsArg() {}
+
+func (r Reg) String() string {
+ switch r {
+ case APSR:
+ return "APSR"
+ case APSR_nzcv:
+ return "APSR_nzcv"
+ case FPSCR:
+ return "FPSCR"
+ case SP:
+ return "SP"
+ case PC:
+ return "PC"
+ case LR:
+ return "LR"
+ }
+ if R0 <= r && r <= R15 {
+ return fmt.Sprintf("R%d", int(r-R0))
+ }
+ if S0 <= r && r <= S31 {
+ return fmt.Sprintf("S%d", int(r-S0))
+ }
+ if D0 <= r && r <= D31 {
+ return fmt.Sprintf("D%d", int(r-D0))
+ }
+ return fmt.Sprintf("Reg(%d)", int(r))
+}
+
+// A RegX represents a fraction of a multi-value register.
+// The Index field specifies the index number,
+// but the size of the fraction is not specified.
+// It must be inferred from the instruction and the register type.
+// For example, in a VMOV instruction, RegX{D5, 1} represents
+// the top 32 bits of the 64-bit D5 register.
+type RegX struct {
+ Reg Reg
+ Index int
+}
+
+func (RegX) IsArg() {}
+
+func (r RegX) String() string {
+ return fmt.Sprintf("%s[%d]", r.Reg, r.Index)
+}
+
+// A RegList is a register list.
+// Bits at indexes x = 0 through 15 indicate whether the corresponding Rx register is in the list.
+type RegList uint16
+
+func (RegList) IsArg() {}
+
+func (r RegList) String() string {
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, "{")
+ sep := ""
+ for i := 0; i < 16; i++ {
+ if r&(1<<uint(i)) != 0 {
+ fmt.Fprintf(&buf, "%s%s", sep, Reg(i).String())
+ sep = ","
+ }
+ }
+ fmt.Fprintf(&buf, "}")
+ return buf.String()
+}
+
+// An Endian is the argument to the SETEND instruction.
+type Endian uint8
+
+const (
+ LittleEndian Endian = 0
+ BigEndian Endian = 1
+)
+
+func (Endian) IsArg() {}
+
+func (e Endian) String() string {
+ if e != 0 {
+ return "BE"
+ }
+ return "LE"
+}
+
+// A Shift describes an ARM shift operation.
+type Shift uint8
+
+const (
+ ShiftLeft Shift = 0 // left shift
+ ShiftRight Shift = 1 // logical (unsigned) right shift
+ ShiftRightSigned Shift = 2 // arithmetic (signed) right shift
+ RotateRight Shift = 3 // right rotate
+ RotateRightExt Shift = 4 // right rotate through carry (Count will always be 1)
+)
+
+var shiftName = [...]string{
+ "LSL", "LSR", "ASR", "ROR", "RRX",
+}
+
+func (s Shift) String() string {
+ if s < 5 {
+ return shiftName[s]
+ }
+ return fmt.Sprintf("Shift(%d)", int(s))
+}
+
+// A RegShift is a register shifted by a constant.
+type RegShift struct {
+ Reg Reg
+ Shift Shift
+ Count uint8
+}
+
+func (RegShift) IsArg() {}
+
+func (r RegShift) String() string {
+ return fmt.Sprintf("%s %s #%d", r.Reg, r.Shift, r.Count)
+}
+
+// A RegShiftReg is a register shifted by a register.
+type RegShiftReg struct {
+ Reg Reg
+ Shift Shift
+ RegCount Reg
+}
+
+func (RegShiftReg) IsArg() {}
+
+func (r RegShiftReg) String() string {
+ return fmt.Sprintf("%s %s %s", r.Reg, r.Shift, r.RegCount)
+}
+
+// A PCRel describes a memory address (usually a code label)
+// as a distance relative to the program counter.
+// TODO(rsc): Define which program counter (PC+4? PC+8? PC?).
+type PCRel int32
+
+func (PCRel) IsArg() {}
+
+func (r PCRel) String() string {
+ return fmt.Sprintf("PC%+#x", int32(r))
+}
+
+// An AddrMode is an ARM addressing mode.
+type AddrMode uint8
+
+const (
+ _ AddrMode = iota
+ AddrPostIndex // [R], X – use address R, set R = R + X
+ AddrPreIndex // [R, X]! – use address R + X, set R = R + X
+ AddrOffset // [R, X] – use address R + X
+ AddrLDM // R – [R] but formats as R, for LDM/STM only
+ AddrLDM_WB // R! - [R], X where X is instruction-specific amount, for LDM/STM only
+)
+
+// A Mem is a memory reference made up of a base R and index expression X.
+// The effective memory address is R or R+X depending on AddrMode.
+// The index expression is X = Sign*(Index Shift Count) + Offset,
+// but in any instruction either Sign = 0 or Offset = 0.
+type Mem struct {
+ Base Reg
+ Mode AddrMode
+ Sign int8
+ Index Reg
+ Shift Shift
+ Count uint8
+ Offset int16
+}
+
+func (Mem) IsArg() {}
+
+func (m Mem) String() string {
+ R := m.Base.String()
+ X := ""
+ if m.Sign != 0 {
+ X = "+"
+ if m.Sign < 0 {
+ X = "-"
+ }
+ X += m.Index.String()
+ if m.Shift != ShiftLeft || m.Count != 0 {
+ X += fmt.Sprintf(", %s #%d", m.Shift, m.Count)
+ }
+ } else {
+ X = fmt.Sprintf("#%d", m.Offset)
+ }
+
+ switch m.Mode {
+ case AddrOffset:
+ if X == "#0" {
+ return fmt.Sprintf("[%s]", R)
+ }
+ return fmt.Sprintf("[%s, %s]", R, X)
+ case AddrPreIndex:
+ return fmt.Sprintf("[%s, %s]!", R, X)
+ case AddrPostIndex:
+ return fmt.Sprintf("[%s], %s", R, X)
+ case AddrLDM:
+ if X == "#0" {
+ return R
+ }
+ case AddrLDM_WB:
+ if X == "#0" {
+ return R + "!"
+ }
+ }
+ return fmt.Sprintf("[%s Mode(%d) %s]", R, int(m.Mode), X)
+}
diff --git a/src/cmd/internal/rsc.io/arm/armasm/objdump_test.go b/src/cmd/internal/rsc.io/arm/armasm/objdump_test.go
new file mode 100644
index 000000000..00a00e7dd
--- /dev/null
+++ b/src/cmd/internal/rsc.io/arm/armasm/objdump_test.go
@@ -0,0 +1,258 @@
+// 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
new file mode 100644
index 000000000..d88c67fc0
--- /dev/null
+++ b/src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go
@@ -0,0 +1,260 @@
+// 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
new file mode 100644
index 000000000..952c5190b
--- /dev/null
+++ b/src/cmd/internal/rsc.io/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"
+)
+
+// 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/arm/armasm/tables.go b/src/cmd/internal/rsc.io/arm/armasm/tables.go
new file mode 100644
index 000000000..58f51fe1f
--- /dev/null
+++ b/src/cmd/internal/rsc.io/arm/armasm/tables.go
@@ -0,0 +1,9448 @@
+package armasm
+
+const (
+ _ Op = iota
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ ADC_EQ
+ ADC_NE
+ ADC_CS
+ ADC_CC
+ ADC_MI
+ ADC_PL
+ ADC_VS
+ ADC_VC
+ ADC_HI
+ ADC_LS
+ ADC_GE
+ ADC_LT
+ ADC_GT
+ ADC_LE
+ ADC
+ ADC_ZZ
+ ADC_S_EQ
+ ADC_S_NE
+ ADC_S_CS
+ ADC_S_CC
+ ADC_S_MI
+ ADC_S_PL
+ ADC_S_VS
+ ADC_S_VC
+ ADC_S_HI
+ ADC_S_LS
+ ADC_S_GE
+ ADC_S_LT
+ ADC_S_GT
+ ADC_S_LE
+ ADC_S
+ ADC_S_ZZ
+ ADD_EQ
+ ADD_NE
+ ADD_CS
+ ADD_CC
+ ADD_MI
+ ADD_PL
+ ADD_VS
+ ADD_VC
+ ADD_HI
+ ADD_LS
+ ADD_GE
+ ADD_LT
+ ADD_GT
+ ADD_LE
+ ADD
+ ADD_ZZ
+ ADD_S_EQ
+ ADD_S_NE
+ ADD_S_CS
+ ADD_S_CC
+ ADD_S_MI
+ ADD_S_PL
+ ADD_S_VS
+ ADD_S_VC
+ ADD_S_HI
+ ADD_S_LS
+ ADD_S_GE
+ ADD_S_LT
+ ADD_S_GT
+ ADD_S_LE
+ ADD_S
+ ADD_S_ZZ
+ AND_EQ
+ AND_NE
+ AND_CS
+ AND_CC
+ AND_MI
+ AND_PL
+ AND_VS
+ AND_VC
+ AND_HI
+ AND_LS
+ AND_GE
+ AND_LT
+ AND_GT
+ AND_LE
+ AND
+ AND_ZZ
+ AND_S_EQ
+ AND_S_NE
+ AND_S_CS
+ AND_S_CC
+ AND_S_MI
+ AND_S_PL
+ AND_S_VS
+ AND_S_VC
+ AND_S_HI
+ AND_S_LS
+ AND_S_GE
+ AND_S_LT
+ AND_S_GT
+ AND_S_LE
+ AND_S
+ AND_S_ZZ
+ ASR_EQ
+ ASR_NE
+ ASR_CS
+ ASR_CC
+ ASR_MI
+ ASR_PL
+ ASR_VS
+ ASR_VC
+ ASR_HI
+ ASR_LS
+ ASR_GE
+ ASR_LT
+ ASR_GT
+ ASR_LE
+ ASR
+ ASR_ZZ
+ ASR_S_EQ
+ ASR_S_NE
+ ASR_S_CS
+ ASR_S_CC
+ ASR_S_MI
+ ASR_S_PL
+ ASR_S_VS
+ ASR_S_VC
+ ASR_S_HI
+ ASR_S_LS
+ ASR_S_GE
+ ASR_S_LT
+ ASR_S_GT
+ ASR_S_LE
+ ASR_S
+ ASR_S_ZZ
+ B_EQ
+ B_NE
+ B_CS
+ B_CC
+ B_MI
+ B_PL
+ B_VS
+ B_VC
+ B_HI
+ B_LS
+ B_GE
+ B_LT
+ B_GT
+ B_LE
+ B
+ B_ZZ
+ BFC_EQ
+ BFC_NE
+ BFC_CS
+ BFC_CC
+ BFC_MI
+ BFC_PL
+ BFC_VS
+ BFC_VC
+ BFC_HI
+ BFC_LS
+ BFC_GE
+ BFC_LT
+ BFC_GT
+ BFC_LE
+ BFC
+ BFC_ZZ
+ BFI_EQ
+ BFI_NE
+ BFI_CS
+ BFI_CC
+ BFI_MI
+ BFI_PL
+ BFI_VS
+ BFI_VC
+ BFI_HI
+ BFI_LS
+ BFI_GE
+ BFI_LT
+ BFI_GT
+ BFI_LE
+ BFI
+ BFI_ZZ
+ BIC_EQ
+ BIC_NE
+ BIC_CS
+ BIC_CC
+ BIC_MI
+ BIC_PL
+ BIC_VS
+ BIC_VC
+ BIC_HI
+ BIC_LS
+ BIC_GE
+ BIC_LT
+ BIC_GT
+ BIC_LE
+ BIC
+ BIC_ZZ
+ BIC_S_EQ
+ BIC_S_NE
+ BIC_S_CS
+ BIC_S_CC
+ BIC_S_MI
+ BIC_S_PL
+ BIC_S_VS
+ BIC_S_VC
+ BIC_S_HI
+ BIC_S_LS
+ BIC_S_GE
+ BIC_S_LT
+ BIC_S_GT
+ BIC_S_LE
+ BIC_S
+ BIC_S_ZZ
+ BKPT_EQ
+ BKPT_NE
+ BKPT_CS
+ BKPT_CC
+ BKPT_MI
+ BKPT_PL
+ BKPT_VS
+ BKPT_VC
+ BKPT_HI
+ BKPT_LS
+ BKPT_GE
+ BKPT_LT
+ BKPT_GT
+ BKPT_LE
+ BKPT
+ BKPT_ZZ
+ BL_EQ
+ BL_NE
+ BL_CS
+ BL_CC
+ BL_MI
+ BL_PL
+ BL_VS
+ BL_VC
+ BL_HI
+ BL_LS
+ BL_GE
+ BL_LT
+ BL_GT
+ BL_LE
+ BL
+ BL_ZZ
+ BLX_EQ
+ BLX_NE
+ BLX_CS
+ BLX_CC
+ BLX_MI
+ BLX_PL
+ BLX_VS
+ BLX_VC
+ BLX_HI
+ BLX_LS
+ BLX_GE
+ BLX_LT
+ BLX_GT
+ BLX_LE
+ BLX
+ BLX_ZZ
+ BX_EQ
+ BX_NE
+ BX_CS
+ BX_CC
+ BX_MI
+ BX_PL
+ BX_VS
+ BX_VC
+ BX_HI
+ BX_LS
+ BX_GE
+ BX_LT
+ BX_GT
+ BX_LE
+ BX
+ BX_ZZ
+ BXJ_EQ
+ BXJ_NE
+ BXJ_CS
+ BXJ_CC
+ BXJ_MI
+ BXJ_PL
+ BXJ_VS
+ BXJ_VC
+ BXJ_HI
+ BXJ_LS
+ BXJ_GE
+ BXJ_LT
+ BXJ_GT
+ BXJ_LE
+ BXJ
+ BXJ_ZZ
+ CLREX
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ CLZ_EQ
+ CLZ_NE
+ CLZ_CS
+ CLZ_CC
+ CLZ_MI
+ CLZ_PL
+ CLZ_VS
+ CLZ_VC
+ CLZ_HI
+ CLZ_LS
+ CLZ_GE
+ CLZ_LT
+ CLZ_GT
+ CLZ_LE
+ CLZ
+ CLZ_ZZ
+ CMN_EQ
+ CMN_NE
+ CMN_CS
+ CMN_CC
+ CMN_MI
+ CMN_PL
+ CMN_VS
+ CMN_VC
+ CMN_HI
+ CMN_LS
+ CMN_GE
+ CMN_LT
+ CMN_GT
+ CMN_LE
+ CMN
+ CMN_ZZ
+ CMP_EQ
+ CMP_NE
+ CMP_CS
+ CMP_CC
+ CMP_MI
+ CMP_PL
+ CMP_VS
+ CMP_VC
+ CMP_HI
+ CMP_LS
+ CMP_GE
+ CMP_LT
+ CMP_GT
+ CMP_LE
+ CMP
+ CMP_ZZ
+ DBG_EQ
+ DBG_NE
+ DBG_CS
+ DBG_CC
+ DBG_MI
+ DBG_PL
+ DBG_VS
+ DBG_VC
+ DBG_HI
+ DBG_LS
+ DBG_GE
+ DBG_LT
+ DBG_GT
+ DBG_LE
+ DBG
+ DBG_ZZ
+ DMB
+ DSB
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ EOR_EQ
+ EOR_NE
+ EOR_CS
+ EOR_CC
+ EOR_MI
+ EOR_PL
+ EOR_VS
+ EOR_VC
+ EOR_HI
+ EOR_LS
+ EOR_GE
+ EOR_LT
+ EOR_GT
+ EOR_LE
+ EOR
+ EOR_ZZ
+ EOR_S_EQ
+ EOR_S_NE
+ EOR_S_CS
+ EOR_S_CC
+ EOR_S_MI
+ EOR_S_PL
+ EOR_S_VS
+ EOR_S_VC
+ EOR_S_HI
+ EOR_S_LS
+ EOR_S_GE
+ EOR_S_LT
+ EOR_S_GT
+ EOR_S_LE
+ EOR_S
+ EOR_S_ZZ
+ ISB
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ LDM_EQ
+ LDM_NE
+ LDM_CS
+ LDM_CC
+ LDM_MI
+ LDM_PL
+ LDM_VS
+ LDM_VC
+ LDM_HI
+ LDM_LS
+ LDM_GE
+ LDM_LT
+ LDM_GT
+ LDM_LE
+ LDM
+ LDM_ZZ
+ LDMDA_EQ
+ LDMDA_NE
+ LDMDA_CS
+ LDMDA_CC
+ LDMDA_MI
+ LDMDA_PL
+ LDMDA_VS
+ LDMDA_VC
+ LDMDA_HI
+ LDMDA_LS
+ LDMDA_GE
+ LDMDA_LT
+ LDMDA_GT
+ LDMDA_LE
+ LDMDA
+ LDMDA_ZZ
+ LDMDB_EQ
+ LDMDB_NE
+ LDMDB_CS
+ LDMDB_CC
+ LDMDB_MI
+ LDMDB_PL
+ LDMDB_VS
+ LDMDB_VC
+ LDMDB_HI
+ LDMDB_LS
+ LDMDB_GE
+ LDMDB_LT
+ LDMDB_GT
+ LDMDB_LE
+ LDMDB
+ LDMDB_ZZ
+ LDMIB_EQ
+ LDMIB_NE
+ LDMIB_CS
+ LDMIB_CC
+ LDMIB_MI
+ LDMIB_PL
+ LDMIB_VS
+ LDMIB_VC
+ LDMIB_HI
+ LDMIB_LS
+ LDMIB_GE
+ LDMIB_LT
+ LDMIB_GT
+ LDMIB_LE
+ LDMIB
+ LDMIB_ZZ
+ LDR_EQ
+ LDR_NE
+ LDR_CS
+ LDR_CC
+ LDR_MI
+ LDR_PL
+ LDR_VS
+ LDR_VC
+ LDR_HI
+ LDR_LS
+ LDR_GE
+ LDR_LT
+ LDR_GT
+ LDR_LE
+ LDR
+ LDR_ZZ
+ LDRB_EQ
+ LDRB_NE
+ LDRB_CS
+ LDRB_CC
+ LDRB_MI
+ LDRB_PL
+ LDRB_VS
+ LDRB_VC
+ LDRB_HI
+ LDRB_LS
+ LDRB_GE
+ LDRB_LT
+ LDRB_GT
+ LDRB_LE
+ LDRB
+ LDRB_ZZ
+ LDRBT_EQ
+ LDRBT_NE
+ LDRBT_CS
+ LDRBT_CC
+ LDRBT_MI
+ LDRBT_PL
+ LDRBT_VS
+ LDRBT_VC
+ LDRBT_HI
+ LDRBT_LS
+ LDRBT_GE
+ LDRBT_LT
+ LDRBT_GT
+ LDRBT_LE
+ LDRBT
+ LDRBT_ZZ
+ LDRD_EQ
+ LDRD_NE
+ LDRD_CS
+ LDRD_CC
+ LDRD_MI
+ LDRD_PL
+ LDRD_VS
+ LDRD_VC
+ LDRD_HI
+ LDRD_LS
+ LDRD_GE
+ LDRD_LT
+ LDRD_GT
+ LDRD_LE
+ LDRD
+ LDRD_ZZ
+ LDREX_EQ
+ LDREX_NE
+ LDREX_CS
+ LDREX_CC
+ LDREX_MI
+ LDREX_PL
+ LDREX_VS
+ LDREX_VC
+ LDREX_HI
+ LDREX_LS
+ LDREX_GE
+ LDREX_LT
+ LDREX_GT
+ LDREX_LE
+ LDREX
+ LDREX_ZZ
+ LDREXB_EQ
+ LDREXB_NE
+ LDREXB_CS
+ LDREXB_CC
+ LDREXB_MI
+ LDREXB_PL
+ LDREXB_VS
+ LDREXB_VC
+ LDREXB_HI
+ LDREXB_LS
+ LDREXB_GE
+ LDREXB_LT
+ LDREXB_GT
+ LDREXB_LE
+ LDREXB
+ LDREXB_ZZ
+ LDREXD_EQ
+ LDREXD_NE
+ LDREXD_CS
+ LDREXD_CC
+ LDREXD_MI
+ LDREXD_PL
+ LDREXD_VS
+ LDREXD_VC
+ LDREXD_HI
+ LDREXD_LS
+ LDREXD_GE
+ LDREXD_LT
+ LDREXD_GT
+ LDREXD_LE
+ LDREXD
+ LDREXD_ZZ
+ LDREXH_EQ
+ LDREXH_NE
+ LDREXH_CS
+ LDREXH_CC
+ LDREXH_MI
+ LDREXH_PL
+ LDREXH_VS
+ LDREXH_VC
+ LDREXH_HI
+ LDREXH_LS
+ LDREXH_GE
+ LDREXH_LT
+ LDREXH_GT
+ LDREXH_LE
+ LDREXH
+ LDREXH_ZZ
+ LDRH_EQ
+ LDRH_NE
+ LDRH_CS
+ LDRH_CC
+ LDRH_MI
+ LDRH_PL
+ LDRH_VS
+ LDRH_VC
+ LDRH_HI
+ LDRH_LS
+ LDRH_GE
+ LDRH_LT
+ LDRH_GT
+ LDRH_LE
+ LDRH
+ LDRH_ZZ
+ LDRHT_EQ
+ LDRHT_NE
+ LDRHT_CS
+ LDRHT_CC
+ LDRHT_MI
+ LDRHT_PL
+ LDRHT_VS
+ LDRHT_VC
+ LDRHT_HI
+ LDRHT_LS
+ LDRHT_GE
+ LDRHT_LT
+ LDRHT_GT
+ LDRHT_LE
+ LDRHT
+ LDRHT_ZZ
+ LDRSB_EQ
+ LDRSB_NE
+ LDRSB_CS
+ LDRSB_CC
+ LDRSB_MI
+ LDRSB_PL
+ LDRSB_VS
+ LDRSB_VC
+ LDRSB_HI
+ LDRSB_LS
+ LDRSB_GE
+ LDRSB_LT
+ LDRSB_GT
+ LDRSB_LE
+ LDRSB
+ LDRSB_ZZ
+ LDRSBT_EQ
+ LDRSBT_NE
+ LDRSBT_CS
+ LDRSBT_CC
+ LDRSBT_MI
+ LDRSBT_PL
+ LDRSBT_VS
+ LDRSBT_VC
+ LDRSBT_HI
+ LDRSBT_LS
+ LDRSBT_GE
+ LDRSBT_LT
+ LDRSBT_GT
+ LDRSBT_LE
+ LDRSBT
+ LDRSBT_ZZ
+ LDRSH_EQ
+ LDRSH_NE
+ LDRSH_CS
+ LDRSH_CC
+ LDRSH_MI
+ LDRSH_PL
+ LDRSH_VS
+ LDRSH_VC
+ LDRSH_HI
+ LDRSH_LS
+ LDRSH_GE
+ LDRSH_LT
+ LDRSH_GT
+ LDRSH_LE
+ LDRSH
+ LDRSH_ZZ
+ LDRSHT_EQ
+ LDRSHT_NE
+ LDRSHT_CS
+ LDRSHT_CC
+ LDRSHT_MI
+ LDRSHT_PL
+ LDRSHT_VS
+ LDRSHT_VC
+ LDRSHT_HI
+ LDRSHT_LS
+ LDRSHT_GE
+ LDRSHT_LT
+ LDRSHT_GT
+ LDRSHT_LE
+ LDRSHT
+ LDRSHT_ZZ
+ LDRT_EQ
+ LDRT_NE
+ LDRT_CS
+ LDRT_CC
+ LDRT_MI
+ LDRT_PL
+ LDRT_VS
+ LDRT_VC
+ LDRT_HI
+ LDRT_LS
+ LDRT_GE
+ LDRT_LT
+ LDRT_GT
+ LDRT_LE
+ LDRT
+ LDRT_ZZ
+ LSL_EQ
+ LSL_NE
+ LSL_CS
+ LSL_CC
+ LSL_MI
+ LSL_PL
+ LSL_VS
+ LSL_VC
+ LSL_HI
+ LSL_LS
+ LSL_GE
+ LSL_LT
+ LSL_GT
+ LSL_LE
+ LSL
+ LSL_ZZ
+ LSL_S_EQ
+ LSL_S_NE
+ LSL_S_CS
+ LSL_S_CC
+ LSL_S_MI
+ LSL_S_PL
+ LSL_S_VS
+ LSL_S_VC
+ LSL_S_HI
+ LSL_S_LS
+ LSL_S_GE
+ LSL_S_LT
+ LSL_S_GT
+ LSL_S_LE
+ LSL_S
+ LSL_S_ZZ
+ LSR_EQ
+ LSR_NE
+ LSR_CS
+ LSR_CC
+ LSR_MI
+ LSR_PL
+ LSR_VS
+ LSR_VC
+ LSR_HI
+ LSR_LS
+ LSR_GE
+ LSR_LT
+ LSR_GT
+ LSR_LE
+ LSR
+ LSR_ZZ
+ LSR_S_EQ
+ LSR_S_NE
+ LSR_S_CS
+ LSR_S_CC
+ LSR_S_MI
+ LSR_S_PL
+ LSR_S_VS
+ LSR_S_VC
+ LSR_S_HI
+ LSR_S_LS
+ LSR_S_GE
+ LSR_S_LT
+ LSR_S_GT
+ LSR_S_LE
+ LSR_S
+ LSR_S_ZZ
+ MLA_EQ
+ MLA_NE
+ MLA_CS
+ MLA_CC
+ MLA_MI
+ MLA_PL
+ MLA_VS
+ MLA_VC
+ MLA_HI
+ MLA_LS
+ MLA_GE
+ MLA_LT
+ MLA_GT
+ MLA_LE
+ MLA
+ MLA_ZZ
+ MLA_S_EQ
+ MLA_S_NE
+ MLA_S_CS
+ MLA_S_CC
+ MLA_S_MI
+ MLA_S_PL
+ MLA_S_VS
+ MLA_S_VC
+ MLA_S_HI
+ MLA_S_LS
+ MLA_S_GE
+ MLA_S_LT
+ MLA_S_GT
+ MLA_S_LE
+ MLA_S
+ MLA_S_ZZ
+ MLS_EQ
+ MLS_NE
+ MLS_CS
+ MLS_CC
+ MLS_MI
+ MLS_PL
+ MLS_VS
+ MLS_VC
+ MLS_HI
+ MLS_LS
+ MLS_GE
+ MLS_LT
+ MLS_GT
+ MLS_LE
+ MLS
+ MLS_ZZ
+ MOV_EQ
+ MOV_NE
+ MOV_CS
+ MOV_CC
+ MOV_MI
+ MOV_PL
+ MOV_VS
+ MOV_VC
+ MOV_HI
+ MOV_LS
+ MOV_GE
+ MOV_LT
+ MOV_GT
+ MOV_LE
+ MOV
+ MOV_ZZ
+ MOV_S_EQ
+ MOV_S_NE
+ MOV_S_CS
+ MOV_S_CC
+ MOV_S_MI
+ MOV_S_PL
+ MOV_S_VS
+ MOV_S_VC
+ MOV_S_HI
+ MOV_S_LS
+ MOV_S_GE
+ MOV_S_LT
+ MOV_S_GT
+ MOV_S_LE
+ MOV_S
+ MOV_S_ZZ
+ MOVT_EQ
+ MOVT_NE
+ MOVT_CS
+ MOVT_CC
+ MOVT_MI
+ MOVT_PL
+ MOVT_VS
+ MOVT_VC
+ MOVT_HI
+ MOVT_LS
+ MOVT_GE
+ MOVT_LT
+ MOVT_GT
+ MOVT_LE
+ MOVT
+ MOVT_ZZ
+ MOVW_EQ
+ MOVW_NE
+ MOVW_CS
+ MOVW_CC
+ MOVW_MI
+ MOVW_PL
+ MOVW_VS
+ MOVW_VC
+ MOVW_HI
+ MOVW_LS
+ MOVW_GE
+ MOVW_LT
+ MOVW_GT
+ MOVW_LE
+ MOVW
+ MOVW_ZZ
+ MRS_EQ
+ MRS_NE
+ MRS_CS
+ MRS_CC
+ MRS_MI
+ MRS_PL
+ MRS_VS
+ MRS_VC
+ MRS_HI
+ MRS_LS
+ MRS_GE
+ MRS_LT
+ MRS_GT
+ MRS_LE
+ MRS
+ MRS_ZZ
+ MUL_EQ
+ MUL_NE
+ MUL_CS
+ MUL_CC
+ MUL_MI
+ MUL_PL
+ MUL_VS
+ MUL_VC
+ MUL_HI
+ MUL_LS
+ MUL_GE
+ MUL_LT
+ MUL_GT
+ MUL_LE
+ MUL
+ MUL_ZZ
+ MUL_S_EQ
+ MUL_S_NE
+ MUL_S_CS
+ MUL_S_CC
+ MUL_S_MI
+ MUL_S_PL
+ MUL_S_VS
+ MUL_S_VC
+ MUL_S_HI
+ MUL_S_LS
+ MUL_S_GE
+ MUL_S_LT
+ MUL_S_GT
+ MUL_S_LE
+ MUL_S
+ MUL_S_ZZ
+ MVN_EQ
+ MVN_NE
+ MVN_CS
+ MVN_CC
+ MVN_MI
+ MVN_PL
+ MVN_VS
+ MVN_VC
+ MVN_HI
+ MVN_LS
+ MVN_GE
+ MVN_LT
+ MVN_GT
+ MVN_LE
+ MVN
+ MVN_ZZ
+ MVN_S_EQ
+ MVN_S_NE
+ MVN_S_CS
+ MVN_S_CC
+ MVN_S_MI
+ MVN_S_PL
+ MVN_S_VS
+ MVN_S_VC
+ MVN_S_HI
+ MVN_S_LS
+ MVN_S_GE
+ MVN_S_LT
+ MVN_S_GT
+ MVN_S_LE
+ MVN_S
+ MVN_S_ZZ
+ NOP_EQ
+ NOP_NE
+ NOP_CS
+ NOP_CC
+ NOP_MI
+ NOP_PL
+ NOP_VS
+ NOP_VC
+ NOP_HI
+ NOP_LS
+ NOP_GE
+ NOP_LT
+ NOP_GT
+ NOP_LE
+ NOP
+ NOP_ZZ
+ ORR_EQ
+ ORR_NE
+ ORR_CS
+ ORR_CC
+ ORR_MI
+ ORR_PL
+ ORR_VS
+ ORR_VC
+ ORR_HI
+ ORR_LS
+ ORR_GE
+ ORR_LT
+ ORR_GT
+ ORR_LE
+ ORR
+ ORR_ZZ
+ ORR_S_EQ
+ ORR_S_NE
+ ORR_S_CS
+ ORR_S_CC
+ ORR_S_MI
+ ORR_S_PL
+ ORR_S_VS
+ ORR_S_VC
+ ORR_S_HI
+ ORR_S_LS
+ ORR_S_GE
+ ORR_S_LT
+ ORR_S_GT
+ ORR_S_LE
+ ORR_S
+ ORR_S_ZZ
+ PKHBT_EQ
+ PKHBT_NE
+ PKHBT_CS
+ PKHBT_CC
+ PKHBT_MI
+ PKHBT_PL
+ PKHBT_VS
+ PKHBT_VC
+ PKHBT_HI
+ PKHBT_LS
+ PKHBT_GE
+ PKHBT_LT
+ PKHBT_GT
+ PKHBT_LE
+ PKHBT
+ PKHBT_ZZ
+ PKHTB_EQ
+ PKHTB_NE
+ PKHTB_CS
+ PKHTB_CC
+ PKHTB_MI
+ PKHTB_PL
+ PKHTB_VS
+ PKHTB_VC
+ PKHTB_HI
+ PKHTB_LS
+ PKHTB_GE
+ PKHTB_LT
+ PKHTB_GT
+ PKHTB_LE
+ PKHTB
+ PKHTB_ZZ
+ PLD_W
+ PLD
+ PLI
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ POP_EQ
+ POP_NE
+ POP_CS
+ POP_CC
+ POP_MI
+ POP_PL
+ POP_VS
+ POP_VC
+ POP_HI
+ POP_LS
+ POP_GE
+ POP_LT
+ POP_GT
+ POP_LE
+ POP
+ POP_ZZ
+ PUSH_EQ
+ PUSH_NE
+ PUSH_CS
+ PUSH_CC
+ PUSH_MI
+ PUSH_PL
+ PUSH_VS
+ PUSH_VC
+ PUSH_HI
+ PUSH_LS
+ PUSH_GE
+ PUSH_LT
+ PUSH_GT
+ PUSH_LE
+ PUSH
+ PUSH_ZZ
+ QADD_EQ
+ QADD_NE
+ QADD_CS
+ QADD_CC
+ QADD_MI
+ QADD_PL
+ QADD_VS
+ QADD_VC
+ QADD_HI
+ QADD_LS
+ QADD_GE
+ QADD_LT
+ QADD_GT
+ QADD_LE
+ QADD
+ QADD_ZZ
+ QADD16_EQ
+ QADD16_NE
+ QADD16_CS
+ QADD16_CC
+ QADD16_MI
+ QADD16_PL
+ QADD16_VS
+ QADD16_VC
+ QADD16_HI
+ QADD16_LS
+ QADD16_GE
+ QADD16_LT
+ QADD16_GT
+ QADD16_LE
+ QADD16
+ QADD16_ZZ
+ QADD8_EQ
+ QADD8_NE
+ QADD8_CS
+ QADD8_CC
+ QADD8_MI
+ QADD8_PL
+ QADD8_VS
+ QADD8_VC
+ QADD8_HI
+ QADD8_LS
+ QADD8_GE
+ QADD8_LT
+ QADD8_GT
+ QADD8_LE
+ QADD8
+ QADD8_ZZ
+ QASX_EQ
+ QASX_NE
+ QASX_CS
+ QASX_CC
+ QASX_MI
+ QASX_PL
+ QASX_VS
+ QASX_VC
+ QASX_HI
+ QASX_LS
+ QASX_GE
+ QASX_LT
+ QASX_GT
+ QASX_LE
+ QASX
+ QASX_ZZ
+ QDADD_EQ
+ QDADD_NE
+ QDADD_CS
+ QDADD_CC
+ QDADD_MI
+ QDADD_PL
+ QDADD_VS
+ QDADD_VC
+ QDADD_HI
+ QDADD_LS
+ QDADD_GE
+ QDADD_LT
+ QDADD_GT
+ QDADD_LE
+ QDADD
+ QDADD_ZZ
+ QDSUB_EQ
+ QDSUB_NE
+ QDSUB_CS
+ QDSUB_CC
+ QDSUB_MI
+ QDSUB_PL
+ QDSUB_VS
+ QDSUB_VC
+ QDSUB_HI
+ QDSUB_LS
+ QDSUB_GE
+ QDSUB_LT
+ QDSUB_GT
+ QDSUB_LE
+ QDSUB
+ QDSUB_ZZ
+ QSAX_EQ
+ QSAX_NE
+ QSAX_CS
+ QSAX_CC
+ QSAX_MI
+ QSAX_PL
+ QSAX_VS
+ QSAX_VC
+ QSAX_HI
+ QSAX_LS
+ QSAX_GE
+ QSAX_LT
+ QSAX_GT
+ QSAX_LE
+ QSAX
+ QSAX_ZZ
+ QSUB_EQ
+ QSUB_NE
+ QSUB_CS
+ QSUB_CC
+ QSUB_MI
+ QSUB_PL
+ QSUB_VS
+ QSUB_VC
+ QSUB_HI
+ QSUB_LS
+ QSUB_GE
+ QSUB_LT
+ QSUB_GT
+ QSUB_LE
+ QSUB
+ QSUB_ZZ
+ QSUB16_EQ
+ QSUB16_NE
+ QSUB16_CS
+ QSUB16_CC
+ QSUB16_MI
+ QSUB16_PL
+ QSUB16_VS
+ QSUB16_VC
+ QSUB16_HI
+ QSUB16_LS
+ QSUB16_GE
+ QSUB16_LT
+ QSUB16_GT
+ QSUB16_LE
+ QSUB16
+ QSUB16_ZZ
+ QSUB8_EQ
+ QSUB8_NE
+ QSUB8_CS
+ QSUB8_CC
+ QSUB8_MI
+ QSUB8_PL
+ QSUB8_VS
+ QSUB8_VC
+ QSUB8_HI
+ QSUB8_LS
+ QSUB8_GE
+ QSUB8_LT
+ QSUB8_GT
+ QSUB8_LE
+ QSUB8
+ QSUB8_ZZ
+ RBIT_EQ
+ RBIT_NE
+ RBIT_CS
+ RBIT_CC
+ RBIT_MI
+ RBIT_PL
+ RBIT_VS
+ RBIT_VC
+ RBIT_HI
+ RBIT_LS
+ RBIT_GE
+ RBIT_LT
+ RBIT_GT
+ RBIT_LE
+ RBIT
+ RBIT_ZZ
+ REV_EQ
+ REV_NE
+ REV_CS
+ REV_CC
+ REV_MI
+ REV_PL
+ REV_VS
+ REV_VC
+ REV_HI
+ REV_LS
+ REV_GE
+ REV_LT
+ REV_GT
+ REV_LE
+ REV
+ REV_ZZ
+ REV16_EQ
+ REV16_NE
+ REV16_CS
+ REV16_CC
+ REV16_MI
+ REV16_PL
+ REV16_VS
+ REV16_VC
+ REV16_HI
+ REV16_LS
+ REV16_GE
+ REV16_LT
+ REV16_GT
+ REV16_LE
+ REV16
+ REV16_ZZ
+ REVSH_EQ
+ REVSH_NE
+ REVSH_CS
+ REVSH_CC
+ REVSH_MI
+ REVSH_PL
+ REVSH_VS
+ REVSH_VC
+ REVSH_HI
+ REVSH_LS
+ REVSH_GE
+ REVSH_LT
+ REVSH_GT
+ REVSH_LE
+ REVSH
+ REVSH_ZZ
+ ROR_EQ
+ ROR_NE
+ ROR_CS
+ ROR_CC
+ ROR_MI
+ ROR_PL
+ ROR_VS
+ ROR_VC
+ ROR_HI
+ ROR_LS
+ ROR_GE
+ ROR_LT
+ ROR_GT
+ ROR_LE
+ ROR
+ ROR_ZZ
+ ROR_S_EQ
+ ROR_S_NE
+ ROR_S_CS
+ ROR_S_CC
+ ROR_S_MI
+ ROR_S_PL
+ ROR_S_VS
+ ROR_S_VC
+ ROR_S_HI
+ ROR_S_LS
+ ROR_S_GE
+ ROR_S_LT
+ ROR_S_GT
+ ROR_S_LE
+ ROR_S
+ ROR_S_ZZ
+ RRX_EQ
+ RRX_NE
+ RRX_CS
+ RRX_CC
+ RRX_MI
+ RRX_PL
+ RRX_VS
+ RRX_VC
+ RRX_HI
+ RRX_LS
+ RRX_GE
+ RRX_LT
+ RRX_GT
+ RRX_LE
+ RRX
+ RRX_ZZ
+ RRX_S_EQ
+ RRX_S_NE
+ RRX_S_CS
+ RRX_S_CC
+ RRX_S_MI
+ RRX_S_PL
+ RRX_S_VS
+ RRX_S_VC
+ RRX_S_HI
+ RRX_S_LS
+ RRX_S_GE
+ RRX_S_LT
+ RRX_S_GT
+ RRX_S_LE
+ RRX_S
+ RRX_S_ZZ
+ RSB_EQ
+ RSB_NE
+ RSB_CS
+ RSB_CC
+ RSB_MI
+ RSB_PL
+ RSB_VS
+ RSB_VC
+ RSB_HI
+ RSB_LS
+ RSB_GE
+ RSB_LT
+ RSB_GT
+ RSB_LE
+ RSB
+ RSB_ZZ
+ RSB_S_EQ
+ RSB_S_NE
+ RSB_S_CS
+ RSB_S_CC
+ RSB_S_MI
+ RSB_S_PL
+ RSB_S_VS
+ RSB_S_VC
+ RSB_S_HI
+ RSB_S_LS
+ RSB_S_GE
+ RSB_S_LT
+ RSB_S_GT
+ RSB_S_LE
+ RSB_S
+ RSB_S_ZZ
+ RSC_EQ
+ RSC_NE
+ RSC_CS
+ RSC_CC
+ RSC_MI
+ RSC_PL
+ RSC_VS
+ RSC_VC
+ RSC_HI
+ RSC_LS
+ RSC_GE
+ RSC_LT
+ RSC_GT
+ RSC_LE
+ RSC
+ RSC_ZZ
+ RSC_S_EQ
+ RSC_S_NE
+ RSC_S_CS
+ RSC_S_CC
+ RSC_S_MI
+ RSC_S_PL
+ RSC_S_VS
+ RSC_S_VC
+ RSC_S_HI
+ RSC_S_LS
+ RSC_S_GE
+ RSC_S_LT
+ RSC_S_GT
+ RSC_S_LE
+ RSC_S
+ RSC_S_ZZ
+ SADD16_EQ
+ SADD16_NE
+ SADD16_CS
+ SADD16_CC
+ SADD16_MI
+ SADD16_PL
+ SADD16_VS
+ SADD16_VC
+ SADD16_HI
+ SADD16_LS
+ SADD16_GE
+ SADD16_LT
+ SADD16_GT
+ SADD16_LE
+ SADD16
+ SADD16_ZZ
+ SADD8_EQ
+ SADD8_NE
+ SADD8_CS
+ SADD8_CC
+ SADD8_MI
+ SADD8_PL
+ SADD8_VS
+ SADD8_VC
+ SADD8_HI
+ SADD8_LS
+ SADD8_GE
+ SADD8_LT
+ SADD8_GT
+ SADD8_LE
+ SADD8
+ SADD8_ZZ
+ SASX_EQ
+ SASX_NE
+ SASX_CS
+ SASX_CC
+ SASX_MI
+ SASX_PL
+ SASX_VS
+ SASX_VC
+ SASX_HI
+ SASX_LS
+ SASX_GE
+ SASX_LT
+ SASX_GT
+ SASX_LE
+ SASX
+ SASX_ZZ
+ SBC_EQ
+ SBC_NE
+ SBC_CS
+ SBC_CC
+ SBC_MI
+ SBC_PL
+ SBC_VS
+ SBC_VC
+ SBC_HI
+ SBC_LS
+ SBC_GE
+ SBC_LT
+ SBC_GT
+ SBC_LE
+ SBC
+ SBC_ZZ
+ SBC_S_EQ
+ SBC_S_NE
+ SBC_S_CS
+ SBC_S_CC
+ SBC_S_MI
+ SBC_S_PL
+ SBC_S_VS
+ SBC_S_VC
+ SBC_S_HI
+ SBC_S_LS
+ SBC_S_GE
+ SBC_S_LT
+ SBC_S_GT
+ SBC_S_LE
+ SBC_S
+ SBC_S_ZZ
+ SBFX_EQ
+ SBFX_NE
+ SBFX_CS
+ SBFX_CC
+ SBFX_MI
+ SBFX_PL
+ SBFX_VS
+ SBFX_VC
+ SBFX_HI
+ SBFX_LS
+ SBFX_GE
+ SBFX_LT
+ SBFX_GT
+ SBFX_LE
+ SBFX
+ SBFX_ZZ
+ SEL_EQ
+ SEL_NE
+ SEL_CS
+ SEL_CC
+ SEL_MI
+ SEL_PL
+ SEL_VS
+ SEL_VC
+ SEL_HI
+ SEL_LS
+ SEL_GE
+ SEL_LT
+ SEL_GT
+ SEL_LE
+ SEL
+ SEL_ZZ
+ SETEND
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ SEV_EQ
+ SEV_NE
+ SEV_CS
+ SEV_CC
+ SEV_MI
+ SEV_PL
+ SEV_VS
+ SEV_VC
+ SEV_HI
+ SEV_LS
+ SEV_GE
+ SEV_LT
+ SEV_GT
+ SEV_LE
+ SEV
+ SEV_ZZ
+ SHADD16_EQ
+ SHADD16_NE
+ SHADD16_CS
+ SHADD16_CC
+ SHADD16_MI
+ SHADD16_PL
+ SHADD16_VS
+ SHADD16_VC
+ SHADD16_HI
+ SHADD16_LS
+ SHADD16_GE
+ SHADD16_LT
+ SHADD16_GT
+ SHADD16_LE
+ SHADD16
+ SHADD16_ZZ
+ SHADD8_EQ
+ SHADD8_NE
+ SHADD8_CS
+ SHADD8_CC
+ SHADD8_MI
+ SHADD8_PL
+ SHADD8_VS
+ SHADD8_VC
+ SHADD8_HI
+ SHADD8_LS
+ SHADD8_GE
+ SHADD8_LT
+ SHADD8_GT
+ SHADD8_LE
+ SHADD8
+ SHADD8_ZZ
+ SHASX_EQ
+ SHASX_NE
+ SHASX_CS
+ SHASX_CC
+ SHASX_MI
+ SHASX_PL
+ SHASX_VS
+ SHASX_VC
+ SHASX_HI
+ SHASX_LS
+ SHASX_GE
+ SHASX_LT
+ SHASX_GT
+ SHASX_LE
+ SHASX
+ SHASX_ZZ
+ SHSAX_EQ
+ SHSAX_NE
+ SHSAX_CS
+ SHSAX_CC
+ SHSAX_MI
+ SHSAX_PL
+ SHSAX_VS
+ SHSAX_VC
+ SHSAX_HI
+ SHSAX_LS
+ SHSAX_GE
+ SHSAX_LT
+ SHSAX_GT
+ SHSAX_LE
+ SHSAX
+ SHSAX_ZZ
+ SHSUB16_EQ
+ SHSUB16_NE
+ SHSUB16_CS
+ SHSUB16_CC
+ SHSUB16_MI
+ SHSUB16_PL
+ SHSUB16_VS
+ SHSUB16_VC
+ SHSUB16_HI
+ SHSUB16_LS
+ SHSUB16_GE
+ SHSUB16_LT
+ SHSUB16_GT
+ SHSUB16_LE
+ SHSUB16
+ SHSUB16_ZZ
+ SHSUB8_EQ
+ SHSUB8_NE
+ SHSUB8_CS
+ SHSUB8_CC
+ SHSUB8_MI
+ SHSUB8_PL
+ SHSUB8_VS
+ SHSUB8_VC
+ SHSUB8_HI
+ SHSUB8_LS
+ SHSUB8_GE
+ SHSUB8_LT
+ SHSUB8_GT
+ SHSUB8_LE
+ SHSUB8
+ SHSUB8_ZZ
+ SMLABB_EQ
+ SMLABB_NE
+ SMLABB_CS
+ SMLABB_CC
+ SMLABB_MI
+ SMLABB_PL
+ SMLABB_VS
+ SMLABB_VC
+ SMLABB_HI
+ SMLABB_LS
+ SMLABB_GE
+ SMLABB_LT
+ SMLABB_GT
+ SMLABB_LE
+ SMLABB
+ SMLABB_ZZ
+ SMLABT_EQ
+ SMLABT_NE
+ SMLABT_CS
+ SMLABT_CC
+ SMLABT_MI
+ SMLABT_PL
+ SMLABT_VS
+ SMLABT_VC
+ SMLABT_HI
+ SMLABT_LS
+ SMLABT_GE
+ SMLABT_LT
+ SMLABT_GT
+ SMLABT_LE
+ SMLABT
+ SMLABT_ZZ
+ SMLATB_EQ
+ SMLATB_NE
+ SMLATB_CS
+ SMLATB_CC
+ SMLATB_MI
+ SMLATB_PL
+ SMLATB_VS
+ SMLATB_VC
+ SMLATB_HI
+ SMLATB_LS
+ SMLATB_GE
+ SMLATB_LT
+ SMLATB_GT
+ SMLATB_LE
+ SMLATB
+ SMLATB_ZZ
+ SMLATT_EQ
+ SMLATT_NE
+ SMLATT_CS
+ SMLATT_CC
+ SMLATT_MI
+ SMLATT_PL
+ SMLATT_VS
+ SMLATT_VC
+ SMLATT_HI
+ SMLATT_LS
+ SMLATT_GE
+ SMLATT_LT
+ SMLATT_GT
+ SMLATT_LE
+ SMLATT
+ SMLATT_ZZ
+ SMLAD_EQ
+ SMLAD_NE
+ SMLAD_CS
+ SMLAD_CC
+ SMLAD_MI
+ SMLAD_PL
+ SMLAD_VS
+ SMLAD_VC
+ SMLAD_HI
+ SMLAD_LS
+ SMLAD_GE
+ SMLAD_LT
+ SMLAD_GT
+ SMLAD_LE
+ SMLAD
+ SMLAD_ZZ
+ SMLAD_X_EQ
+ SMLAD_X_NE
+ SMLAD_X_CS
+ SMLAD_X_CC
+ SMLAD_X_MI
+ SMLAD_X_PL
+ SMLAD_X_VS
+ SMLAD_X_VC
+ SMLAD_X_HI
+ SMLAD_X_LS
+ SMLAD_X_GE
+ SMLAD_X_LT
+ SMLAD_X_GT
+ SMLAD_X_LE
+ SMLAD_X
+ SMLAD_X_ZZ
+ SMLAL_EQ
+ SMLAL_NE
+ SMLAL_CS
+ SMLAL_CC
+ SMLAL_MI
+ SMLAL_PL
+ SMLAL_VS
+ SMLAL_VC
+ SMLAL_HI
+ SMLAL_LS
+ SMLAL_GE
+ SMLAL_LT
+ SMLAL_GT
+ SMLAL_LE
+ SMLAL
+ SMLAL_ZZ
+ SMLAL_S_EQ
+ SMLAL_S_NE
+ SMLAL_S_CS
+ SMLAL_S_CC
+ SMLAL_S_MI
+ SMLAL_S_PL
+ SMLAL_S_VS
+ SMLAL_S_VC
+ SMLAL_S_HI
+ SMLAL_S_LS
+ SMLAL_S_GE
+ SMLAL_S_LT
+ SMLAL_S_GT
+ SMLAL_S_LE
+ SMLAL_S
+ SMLAL_S_ZZ
+ SMLALBB_EQ
+ SMLALBB_NE
+ SMLALBB_CS
+ SMLALBB_CC
+ SMLALBB_MI
+ SMLALBB_PL
+ SMLALBB_VS
+ SMLALBB_VC
+ SMLALBB_HI
+ SMLALBB_LS
+ SMLALBB_GE
+ SMLALBB_LT
+ SMLALBB_GT
+ SMLALBB_LE
+ SMLALBB
+ SMLALBB_ZZ
+ SMLALBT_EQ
+ SMLALBT_NE
+ SMLALBT_CS
+ SMLALBT_CC
+ SMLALBT_MI
+ SMLALBT_PL
+ SMLALBT_VS
+ SMLALBT_VC
+ SMLALBT_HI
+ SMLALBT_LS
+ SMLALBT_GE
+ SMLALBT_LT
+ SMLALBT_GT
+ SMLALBT_LE
+ SMLALBT
+ SMLALBT_ZZ
+ SMLALTB_EQ
+ SMLALTB_NE
+ SMLALTB_CS
+ SMLALTB_CC
+ SMLALTB_MI
+ SMLALTB_PL
+ SMLALTB_VS
+ SMLALTB_VC
+ SMLALTB_HI
+ SMLALTB_LS
+ SMLALTB_GE
+ SMLALTB_LT
+ SMLALTB_GT
+ SMLALTB_LE
+ SMLALTB
+ SMLALTB_ZZ
+ SMLALTT_EQ
+ SMLALTT_NE
+ SMLALTT_CS
+ SMLALTT_CC
+ SMLALTT_MI
+ SMLALTT_PL
+ SMLALTT_VS
+ SMLALTT_VC
+ SMLALTT_HI
+ SMLALTT_LS
+ SMLALTT_GE
+ SMLALTT_LT
+ SMLALTT_GT
+ SMLALTT_LE
+ SMLALTT
+ SMLALTT_ZZ
+ SMLALD_EQ
+ SMLALD_NE
+ SMLALD_CS
+ SMLALD_CC
+ SMLALD_MI
+ SMLALD_PL
+ SMLALD_VS
+ SMLALD_VC
+ SMLALD_HI
+ SMLALD_LS
+ SMLALD_GE
+ SMLALD_LT
+ SMLALD_GT
+ SMLALD_LE
+ SMLALD
+ SMLALD_ZZ
+ SMLALD_X_EQ
+ SMLALD_X_NE
+ SMLALD_X_CS
+ SMLALD_X_CC
+ SMLALD_X_MI
+ SMLALD_X_PL
+ SMLALD_X_VS
+ SMLALD_X_VC
+ SMLALD_X_HI
+ SMLALD_X_LS
+ SMLALD_X_GE
+ SMLALD_X_LT
+ SMLALD_X_GT
+ SMLALD_X_LE
+ SMLALD_X
+ SMLALD_X_ZZ
+ SMLAWB_EQ
+ SMLAWB_NE
+ SMLAWB_CS
+ SMLAWB_CC
+ SMLAWB_MI
+ SMLAWB_PL
+ SMLAWB_VS
+ SMLAWB_VC
+ SMLAWB_HI
+ SMLAWB_LS
+ SMLAWB_GE
+ SMLAWB_LT
+ SMLAWB_GT
+ SMLAWB_LE
+ SMLAWB
+ SMLAWB_ZZ
+ SMLAWT_EQ
+ SMLAWT_NE
+ SMLAWT_CS
+ SMLAWT_CC
+ SMLAWT_MI
+ SMLAWT_PL
+ SMLAWT_VS
+ SMLAWT_VC
+ SMLAWT_HI
+ SMLAWT_LS
+ SMLAWT_GE
+ SMLAWT_LT
+ SMLAWT_GT
+ SMLAWT_LE
+ SMLAWT
+ SMLAWT_ZZ
+ SMLSD_EQ
+ SMLSD_NE
+ SMLSD_CS
+ SMLSD_CC
+ SMLSD_MI
+ SMLSD_PL
+ SMLSD_VS
+ SMLSD_VC
+ SMLSD_HI
+ SMLSD_LS
+ SMLSD_GE
+ SMLSD_LT
+ SMLSD_GT
+ SMLSD_LE
+ SMLSD
+ SMLSD_ZZ
+ SMLSD_X_EQ
+ SMLSD_X_NE
+ SMLSD_X_CS
+ SMLSD_X_CC
+ SMLSD_X_MI
+ SMLSD_X_PL
+ SMLSD_X_VS
+ SMLSD_X_VC
+ SMLSD_X_HI
+ SMLSD_X_LS
+ SMLSD_X_GE
+ SMLSD_X_LT
+ SMLSD_X_GT
+ SMLSD_X_LE
+ SMLSD_X
+ SMLSD_X_ZZ
+ SMLSLD_EQ
+ SMLSLD_NE
+ SMLSLD_CS
+ SMLSLD_CC
+ SMLSLD_MI
+ SMLSLD_PL
+ SMLSLD_VS
+ SMLSLD_VC
+ SMLSLD_HI
+ SMLSLD_LS
+ SMLSLD_GE
+ SMLSLD_LT
+ SMLSLD_GT
+ SMLSLD_LE
+ SMLSLD
+ SMLSLD_ZZ
+ SMLSLD_X_EQ
+ SMLSLD_X_NE
+ SMLSLD_X_CS
+ SMLSLD_X_CC
+ SMLSLD_X_MI
+ SMLSLD_X_PL
+ SMLSLD_X_VS
+ SMLSLD_X_VC
+ SMLSLD_X_HI
+ SMLSLD_X_LS
+ SMLSLD_X_GE
+ SMLSLD_X_LT
+ SMLSLD_X_GT
+ SMLSLD_X_LE
+ SMLSLD_X
+ SMLSLD_X_ZZ
+ SMMLA_EQ
+ SMMLA_NE
+ SMMLA_CS
+ SMMLA_CC
+ SMMLA_MI
+ SMMLA_PL
+ SMMLA_VS
+ SMMLA_VC
+ SMMLA_HI
+ SMMLA_LS
+ SMMLA_GE
+ SMMLA_LT
+ SMMLA_GT
+ SMMLA_LE
+ SMMLA
+ SMMLA_ZZ
+ SMMLA_R_EQ
+ SMMLA_R_NE
+ SMMLA_R_CS
+ SMMLA_R_CC
+ SMMLA_R_MI
+ SMMLA_R_PL
+ SMMLA_R_VS
+ SMMLA_R_VC
+ SMMLA_R_HI
+ SMMLA_R_LS
+ SMMLA_R_GE
+ SMMLA_R_LT
+ SMMLA_R_GT
+ SMMLA_R_LE
+ SMMLA_R
+ SMMLA_R_ZZ
+ SMMLS_EQ
+ SMMLS_NE
+ SMMLS_CS
+ SMMLS_CC
+ SMMLS_MI
+ SMMLS_PL
+ SMMLS_VS
+ SMMLS_VC
+ SMMLS_HI
+ SMMLS_LS
+ SMMLS_GE
+ SMMLS_LT
+ SMMLS_GT
+ SMMLS_LE
+ SMMLS
+ SMMLS_ZZ
+ SMMLS_R_EQ
+ SMMLS_R_NE
+ SMMLS_R_CS
+ SMMLS_R_CC
+ SMMLS_R_MI
+ SMMLS_R_PL
+ SMMLS_R_VS
+ SMMLS_R_VC
+ SMMLS_R_HI
+ SMMLS_R_LS
+ SMMLS_R_GE
+ SMMLS_R_LT
+ SMMLS_R_GT
+ SMMLS_R_LE
+ SMMLS_R
+ SMMLS_R_ZZ
+ SMMUL_EQ
+ SMMUL_NE
+ SMMUL_CS
+ SMMUL_CC
+ SMMUL_MI
+ SMMUL_PL
+ SMMUL_VS
+ SMMUL_VC
+ SMMUL_HI
+ SMMUL_LS
+ SMMUL_GE
+ SMMUL_LT
+ SMMUL_GT
+ SMMUL_LE
+ SMMUL
+ SMMUL_ZZ
+ SMMUL_R_EQ
+ SMMUL_R_NE
+ SMMUL_R_CS
+ SMMUL_R_CC
+ SMMUL_R_MI
+ SMMUL_R_PL
+ SMMUL_R_VS
+ SMMUL_R_VC
+ SMMUL_R_HI
+ SMMUL_R_LS
+ SMMUL_R_GE
+ SMMUL_R_LT
+ SMMUL_R_GT
+ SMMUL_R_LE
+ SMMUL_R
+ SMMUL_R_ZZ
+ SMUAD_EQ
+ SMUAD_NE
+ SMUAD_CS
+ SMUAD_CC
+ SMUAD_MI
+ SMUAD_PL
+ SMUAD_VS
+ SMUAD_VC
+ SMUAD_HI
+ SMUAD_LS
+ SMUAD_GE
+ SMUAD_LT
+ SMUAD_GT
+ SMUAD_LE
+ SMUAD
+ SMUAD_ZZ
+ SMUAD_X_EQ
+ SMUAD_X_NE
+ SMUAD_X_CS
+ SMUAD_X_CC
+ SMUAD_X_MI
+ SMUAD_X_PL
+ SMUAD_X_VS
+ SMUAD_X_VC
+ SMUAD_X_HI
+ SMUAD_X_LS
+ SMUAD_X_GE
+ SMUAD_X_LT
+ SMUAD_X_GT
+ SMUAD_X_LE
+ SMUAD_X
+ SMUAD_X_ZZ
+ SMULBB_EQ
+ SMULBB_NE
+ SMULBB_CS
+ SMULBB_CC
+ SMULBB_MI
+ SMULBB_PL
+ SMULBB_VS
+ SMULBB_VC
+ SMULBB_HI
+ SMULBB_LS
+ SMULBB_GE
+ SMULBB_LT
+ SMULBB_GT
+ SMULBB_LE
+ SMULBB
+ SMULBB_ZZ
+ SMULBT_EQ
+ SMULBT_NE
+ SMULBT_CS
+ SMULBT_CC
+ SMULBT_MI
+ SMULBT_PL
+ SMULBT_VS
+ SMULBT_VC
+ SMULBT_HI
+ SMULBT_LS
+ SMULBT_GE
+ SMULBT_LT
+ SMULBT_GT
+ SMULBT_LE
+ SMULBT
+ SMULBT_ZZ
+ SMULTB_EQ
+ SMULTB_NE
+ SMULTB_CS
+ SMULTB_CC
+ SMULTB_MI
+ SMULTB_PL
+ SMULTB_VS
+ SMULTB_VC
+ SMULTB_HI
+ SMULTB_LS
+ SMULTB_GE
+ SMULTB_LT
+ SMULTB_GT
+ SMULTB_LE
+ SMULTB
+ SMULTB_ZZ
+ SMULTT_EQ
+ SMULTT_NE
+ SMULTT_CS
+ SMULTT_CC
+ SMULTT_MI
+ SMULTT_PL
+ SMULTT_VS
+ SMULTT_VC
+ SMULTT_HI
+ SMULTT_LS
+ SMULTT_GE
+ SMULTT_LT
+ SMULTT_GT
+ SMULTT_LE
+ SMULTT
+ SMULTT_ZZ
+ SMULL_EQ
+ SMULL_NE
+ SMULL_CS
+ SMULL_CC
+ SMULL_MI
+ SMULL_PL
+ SMULL_VS
+ SMULL_VC
+ SMULL_HI
+ SMULL_LS
+ SMULL_GE
+ SMULL_LT
+ SMULL_GT
+ SMULL_LE
+ SMULL
+ SMULL_ZZ
+ SMULL_S_EQ
+ SMULL_S_NE
+ SMULL_S_CS
+ SMULL_S_CC
+ SMULL_S_MI
+ SMULL_S_PL
+ SMULL_S_VS
+ SMULL_S_VC
+ SMULL_S_HI
+ SMULL_S_LS
+ SMULL_S_GE
+ SMULL_S_LT
+ SMULL_S_GT
+ SMULL_S_LE
+ SMULL_S
+ SMULL_S_ZZ
+ SMULWB_EQ
+ SMULWB_NE
+ SMULWB_CS
+ SMULWB_CC
+ SMULWB_MI
+ SMULWB_PL
+ SMULWB_VS
+ SMULWB_VC
+ SMULWB_HI
+ SMULWB_LS
+ SMULWB_GE
+ SMULWB_LT
+ SMULWB_GT
+ SMULWB_LE
+ SMULWB
+ SMULWB_ZZ
+ SMULWT_EQ
+ SMULWT_NE
+ SMULWT_CS
+ SMULWT_CC
+ SMULWT_MI
+ SMULWT_PL
+ SMULWT_VS
+ SMULWT_VC
+ SMULWT_HI
+ SMULWT_LS
+ SMULWT_GE
+ SMULWT_LT
+ SMULWT_GT
+ SMULWT_LE
+ SMULWT
+ SMULWT_ZZ
+ SMUSD_EQ
+ SMUSD_NE
+ SMUSD_CS
+ SMUSD_CC
+ SMUSD_MI
+ SMUSD_PL
+ SMUSD_VS
+ SMUSD_VC
+ SMUSD_HI
+ SMUSD_LS
+ SMUSD_GE
+ SMUSD_LT
+ SMUSD_GT
+ SMUSD_LE
+ SMUSD
+ SMUSD_ZZ
+ SMUSD_X_EQ
+ SMUSD_X_NE
+ SMUSD_X_CS
+ SMUSD_X_CC
+ SMUSD_X_MI
+ SMUSD_X_PL
+ SMUSD_X_VS
+ SMUSD_X_VC
+ SMUSD_X_HI
+ SMUSD_X_LS
+ SMUSD_X_GE
+ SMUSD_X_LT
+ SMUSD_X_GT
+ SMUSD_X_LE
+ SMUSD_X
+ SMUSD_X_ZZ
+ SSAT_EQ
+ SSAT_NE
+ SSAT_CS
+ SSAT_CC
+ SSAT_MI
+ SSAT_PL
+ SSAT_VS
+ SSAT_VC
+ SSAT_HI
+ SSAT_LS
+ SSAT_GE
+ SSAT_LT
+ SSAT_GT
+ SSAT_LE
+ SSAT
+ SSAT_ZZ
+ SSAT16_EQ
+ SSAT16_NE
+ SSAT16_CS
+ SSAT16_CC
+ SSAT16_MI
+ SSAT16_PL
+ SSAT16_VS
+ SSAT16_VC
+ SSAT16_HI
+ SSAT16_LS
+ SSAT16_GE
+ SSAT16_LT
+ SSAT16_GT
+ SSAT16_LE
+ SSAT16
+ SSAT16_ZZ
+ SSAX_EQ
+ SSAX_NE
+ SSAX_CS
+ SSAX_CC
+ SSAX_MI
+ SSAX_PL
+ SSAX_VS
+ SSAX_VC
+ SSAX_HI
+ SSAX_LS
+ SSAX_GE
+ SSAX_LT
+ SSAX_GT
+ SSAX_LE
+ SSAX
+ SSAX_ZZ
+ SSUB16_EQ
+ SSUB16_NE
+ SSUB16_CS
+ SSUB16_CC
+ SSUB16_MI
+ SSUB16_PL
+ SSUB16_VS
+ SSUB16_VC
+ SSUB16_HI
+ SSUB16_LS
+ SSUB16_GE
+ SSUB16_LT
+ SSUB16_GT
+ SSUB16_LE
+ SSUB16
+ SSUB16_ZZ
+ SSUB8_EQ
+ SSUB8_NE
+ SSUB8_CS
+ SSUB8_CC
+ SSUB8_MI
+ SSUB8_PL
+ SSUB8_VS
+ SSUB8_VC
+ SSUB8_HI
+ SSUB8_LS
+ SSUB8_GE
+ SSUB8_LT
+ SSUB8_GT
+ SSUB8_LE
+ SSUB8
+ SSUB8_ZZ
+ STM_EQ
+ STM_NE
+ STM_CS
+ STM_CC
+ STM_MI
+ STM_PL
+ STM_VS
+ STM_VC
+ STM_HI
+ STM_LS
+ STM_GE
+ STM_LT
+ STM_GT
+ STM_LE
+ STM
+ STM_ZZ
+ STMDA_EQ
+ STMDA_NE
+ STMDA_CS
+ STMDA_CC
+ STMDA_MI
+ STMDA_PL
+ STMDA_VS
+ STMDA_VC
+ STMDA_HI
+ STMDA_LS
+ STMDA_GE
+ STMDA_LT
+ STMDA_GT
+ STMDA_LE
+ STMDA
+ STMDA_ZZ
+ STMDB_EQ
+ STMDB_NE
+ STMDB_CS
+ STMDB_CC
+ STMDB_MI
+ STMDB_PL
+ STMDB_VS
+ STMDB_VC
+ STMDB_HI
+ STMDB_LS
+ STMDB_GE
+ STMDB_LT
+ STMDB_GT
+ STMDB_LE
+ STMDB
+ STMDB_ZZ
+ STMIB_EQ
+ STMIB_NE
+ STMIB_CS
+ STMIB_CC
+ STMIB_MI
+ STMIB_PL
+ STMIB_VS
+ STMIB_VC
+ STMIB_HI
+ STMIB_LS
+ STMIB_GE
+ STMIB_LT
+ STMIB_GT
+ STMIB_LE
+ STMIB
+ STMIB_ZZ
+ STR_EQ
+ STR_NE
+ STR_CS
+ STR_CC
+ STR_MI
+ STR_PL
+ STR_VS
+ STR_VC
+ STR_HI
+ STR_LS
+ STR_GE
+ STR_LT
+ STR_GT
+ STR_LE
+ STR
+ STR_ZZ
+ STRB_EQ
+ STRB_NE
+ STRB_CS
+ STRB_CC
+ STRB_MI
+ STRB_PL
+ STRB_VS
+ STRB_VC
+ STRB_HI
+ STRB_LS
+ STRB_GE
+ STRB_LT
+ STRB_GT
+ STRB_LE
+ STRB
+ STRB_ZZ
+ STRBT_EQ
+ STRBT_NE
+ STRBT_CS
+ STRBT_CC
+ STRBT_MI
+ STRBT_PL
+ STRBT_VS
+ STRBT_VC
+ STRBT_HI
+ STRBT_LS
+ STRBT_GE
+ STRBT_LT
+ STRBT_GT
+ STRBT_LE
+ STRBT
+ STRBT_ZZ
+ STRD_EQ
+ STRD_NE
+ STRD_CS
+ STRD_CC
+ STRD_MI
+ STRD_PL
+ STRD_VS
+ STRD_VC
+ STRD_HI
+ STRD_LS
+ STRD_GE
+ STRD_LT
+ STRD_GT
+ STRD_LE
+ STRD
+ STRD_ZZ
+ STREX_EQ
+ STREX_NE
+ STREX_CS
+ STREX_CC
+ STREX_MI
+ STREX_PL
+ STREX_VS
+ STREX_VC
+ STREX_HI
+ STREX_LS
+ STREX_GE
+ STREX_LT
+ STREX_GT
+ STREX_LE
+ STREX
+ STREX_ZZ
+ STREXB_EQ
+ STREXB_NE
+ STREXB_CS
+ STREXB_CC
+ STREXB_MI
+ STREXB_PL
+ STREXB_VS
+ STREXB_VC
+ STREXB_HI
+ STREXB_LS
+ STREXB_GE
+ STREXB_LT
+ STREXB_GT
+ STREXB_LE
+ STREXB
+ STREXB_ZZ
+ STREXD_EQ
+ STREXD_NE
+ STREXD_CS
+ STREXD_CC
+ STREXD_MI
+ STREXD_PL
+ STREXD_VS
+ STREXD_VC
+ STREXD_HI
+ STREXD_LS
+ STREXD_GE
+ STREXD_LT
+ STREXD_GT
+ STREXD_LE
+ STREXD
+ STREXD_ZZ
+ STREXH_EQ
+ STREXH_NE
+ STREXH_CS
+ STREXH_CC
+ STREXH_MI
+ STREXH_PL
+ STREXH_VS
+ STREXH_VC
+ STREXH_HI
+ STREXH_LS
+ STREXH_GE
+ STREXH_LT
+ STREXH_GT
+ STREXH_LE
+ STREXH
+ STREXH_ZZ
+ STRH_EQ
+ STRH_NE
+ STRH_CS
+ STRH_CC
+ STRH_MI
+ STRH_PL
+ STRH_VS
+ STRH_VC
+ STRH_HI
+ STRH_LS
+ STRH_GE
+ STRH_LT
+ STRH_GT
+ STRH_LE
+ STRH
+ STRH_ZZ
+ STRHT_EQ
+ STRHT_NE
+ STRHT_CS
+ STRHT_CC
+ STRHT_MI
+ STRHT_PL
+ STRHT_VS
+ STRHT_VC
+ STRHT_HI
+ STRHT_LS
+ STRHT_GE
+ STRHT_LT
+ STRHT_GT
+ STRHT_LE
+ STRHT
+ STRHT_ZZ
+ STRT_EQ
+ STRT_NE
+ STRT_CS
+ STRT_CC
+ STRT_MI
+ STRT_PL
+ STRT_VS
+ STRT_VC
+ STRT_HI
+ STRT_LS
+ STRT_GE
+ STRT_LT
+ STRT_GT
+ STRT_LE
+ STRT
+ STRT_ZZ
+ SUB_EQ
+ SUB_NE
+ SUB_CS
+ SUB_CC
+ SUB_MI
+ SUB_PL
+ SUB_VS
+ SUB_VC
+ SUB_HI
+ SUB_LS
+ SUB_GE
+ SUB_LT
+ SUB_GT
+ SUB_LE
+ SUB
+ SUB_ZZ
+ SUB_S_EQ
+ SUB_S_NE
+ SUB_S_CS
+ SUB_S_CC
+ SUB_S_MI
+ SUB_S_PL
+ SUB_S_VS
+ SUB_S_VC
+ SUB_S_HI
+ SUB_S_LS
+ SUB_S_GE
+ SUB_S_LT
+ SUB_S_GT
+ SUB_S_LE
+ SUB_S
+ SUB_S_ZZ
+ SVC_EQ
+ SVC_NE
+ SVC_CS
+ SVC_CC
+ SVC_MI
+ SVC_PL
+ SVC_VS
+ SVC_VC
+ SVC_HI
+ SVC_LS
+ SVC_GE
+ SVC_LT
+ SVC_GT
+ SVC_LE
+ SVC
+ SVC_ZZ
+ SWP_EQ
+ SWP_NE
+ SWP_CS
+ SWP_CC
+ SWP_MI
+ SWP_PL
+ SWP_VS
+ SWP_VC
+ SWP_HI
+ SWP_LS
+ SWP_GE
+ SWP_LT
+ SWP_GT
+ SWP_LE
+ SWP
+ SWP_ZZ
+ SWP_B_EQ
+ SWP_B_NE
+ SWP_B_CS
+ SWP_B_CC
+ SWP_B_MI
+ SWP_B_PL
+ SWP_B_VS
+ SWP_B_VC
+ SWP_B_HI
+ SWP_B_LS
+ SWP_B_GE
+ SWP_B_LT
+ SWP_B_GT
+ SWP_B_LE
+ SWP_B
+ SWP_B_ZZ
+ SXTAB_EQ
+ SXTAB_NE
+ SXTAB_CS
+ SXTAB_CC
+ SXTAB_MI
+ SXTAB_PL
+ SXTAB_VS
+ SXTAB_VC
+ SXTAB_HI
+ SXTAB_LS
+ SXTAB_GE
+ SXTAB_LT
+ SXTAB_GT
+ SXTAB_LE
+ SXTAB
+ SXTAB_ZZ
+ SXTAB16_EQ
+ SXTAB16_NE
+ SXTAB16_CS
+ SXTAB16_CC
+ SXTAB16_MI
+ SXTAB16_PL
+ SXTAB16_VS
+ SXTAB16_VC
+ SXTAB16_HI
+ SXTAB16_LS
+ SXTAB16_GE
+ SXTAB16_LT
+ SXTAB16_GT
+ SXTAB16_LE
+ SXTAB16
+ SXTAB16_ZZ
+ SXTAH_EQ
+ SXTAH_NE
+ SXTAH_CS
+ SXTAH_CC
+ SXTAH_MI
+ SXTAH_PL
+ SXTAH_VS
+ SXTAH_VC
+ SXTAH_HI
+ SXTAH_LS
+ SXTAH_GE
+ SXTAH_LT
+ SXTAH_GT
+ SXTAH_LE
+ SXTAH
+ SXTAH_ZZ
+ SXTB_EQ
+ SXTB_NE
+ SXTB_CS
+ SXTB_CC
+ SXTB_MI
+ SXTB_PL
+ SXTB_VS
+ SXTB_VC
+ SXTB_HI
+ SXTB_LS
+ SXTB_GE
+ SXTB_LT
+ SXTB_GT
+ SXTB_LE
+ SXTB
+ SXTB_ZZ
+ SXTB16_EQ
+ SXTB16_NE
+ SXTB16_CS
+ SXTB16_CC
+ SXTB16_MI
+ SXTB16_PL
+ SXTB16_VS
+ SXTB16_VC
+ SXTB16_HI
+ SXTB16_LS
+ SXTB16_GE
+ SXTB16_LT
+ SXTB16_GT
+ SXTB16_LE
+ SXTB16
+ SXTB16_ZZ
+ SXTH_EQ
+ SXTH_NE
+ SXTH_CS
+ SXTH_CC
+ SXTH_MI
+ SXTH_PL
+ SXTH_VS
+ SXTH_VC
+ SXTH_HI
+ SXTH_LS
+ SXTH_GE
+ SXTH_LT
+ SXTH_GT
+ SXTH_LE
+ SXTH
+ SXTH_ZZ
+ TEQ_EQ
+ TEQ_NE
+ TEQ_CS
+ TEQ_CC
+ TEQ_MI
+ TEQ_PL
+ TEQ_VS
+ TEQ_VC
+ TEQ_HI
+ TEQ_LS
+ TEQ_GE
+ TEQ_LT
+ TEQ_GT
+ TEQ_LE
+ TEQ
+ TEQ_ZZ
+ TST_EQ
+ TST_NE
+ TST_CS
+ TST_CC
+ TST_MI
+ TST_PL
+ TST_VS
+ TST_VC
+ TST_HI
+ TST_LS
+ TST_GE
+ TST_LT
+ TST_GT
+ TST_LE
+ TST
+ TST_ZZ
+ UADD16_EQ
+ UADD16_NE
+ UADD16_CS
+ UADD16_CC
+ UADD16_MI
+ UADD16_PL
+ UADD16_VS
+ UADD16_VC
+ UADD16_HI
+ UADD16_LS
+ UADD16_GE
+ UADD16_LT
+ UADD16_GT
+ UADD16_LE
+ UADD16
+ UADD16_ZZ
+ UADD8_EQ
+ UADD8_NE
+ UADD8_CS
+ UADD8_CC
+ UADD8_MI
+ UADD8_PL
+ UADD8_VS
+ UADD8_VC
+ UADD8_HI
+ UADD8_LS
+ UADD8_GE
+ UADD8_LT
+ UADD8_GT
+ UADD8_LE
+ UADD8
+ UADD8_ZZ
+ UASX_EQ
+ UASX_NE
+ UASX_CS
+ UASX_CC
+ UASX_MI
+ UASX_PL
+ UASX_VS
+ UASX_VC
+ UASX_HI
+ UASX_LS
+ UASX_GE
+ UASX_LT
+ UASX_GT
+ UASX_LE
+ UASX
+ UASX_ZZ
+ UBFX_EQ
+ UBFX_NE
+ UBFX_CS
+ UBFX_CC
+ UBFX_MI
+ UBFX_PL
+ UBFX_VS
+ UBFX_VC
+ UBFX_HI
+ UBFX_LS
+ UBFX_GE
+ UBFX_LT
+ UBFX_GT
+ UBFX_LE
+ UBFX
+ UBFX_ZZ
+ UHADD16_EQ
+ UHADD16_NE
+ UHADD16_CS
+ UHADD16_CC
+ UHADD16_MI
+ UHADD16_PL
+ UHADD16_VS
+ UHADD16_VC
+ UHADD16_HI
+ UHADD16_LS
+ UHADD16_GE
+ UHADD16_LT
+ UHADD16_GT
+ UHADD16_LE
+ UHADD16
+ UHADD16_ZZ
+ UHADD8_EQ
+ UHADD8_NE
+ UHADD8_CS
+ UHADD8_CC
+ UHADD8_MI
+ UHADD8_PL
+ UHADD8_VS
+ UHADD8_VC
+ UHADD8_HI
+ UHADD8_LS
+ UHADD8_GE
+ UHADD8_LT
+ UHADD8_GT
+ UHADD8_LE
+ UHADD8
+ UHADD8_ZZ
+ UHASX_EQ
+ UHASX_NE
+ UHASX_CS
+ UHASX_CC
+ UHASX_MI
+ UHASX_PL
+ UHASX_VS
+ UHASX_VC
+ UHASX_HI
+ UHASX_LS
+ UHASX_GE
+ UHASX_LT
+ UHASX_GT
+ UHASX_LE
+ UHASX
+ UHASX_ZZ
+ UHSAX_EQ
+ UHSAX_NE
+ UHSAX_CS
+ UHSAX_CC
+ UHSAX_MI
+ UHSAX_PL
+ UHSAX_VS
+ UHSAX_VC
+ UHSAX_HI
+ UHSAX_LS
+ UHSAX_GE
+ UHSAX_LT
+ UHSAX_GT
+ UHSAX_LE
+ UHSAX
+ UHSAX_ZZ
+ UHSUB16_EQ
+ UHSUB16_NE
+ UHSUB16_CS
+ UHSUB16_CC
+ UHSUB16_MI
+ UHSUB16_PL
+ UHSUB16_VS
+ UHSUB16_VC
+ UHSUB16_HI
+ UHSUB16_LS
+ UHSUB16_GE
+ UHSUB16_LT
+ UHSUB16_GT
+ UHSUB16_LE
+ UHSUB16
+ UHSUB16_ZZ
+ UHSUB8_EQ
+ UHSUB8_NE
+ UHSUB8_CS
+ UHSUB8_CC
+ UHSUB8_MI
+ UHSUB8_PL
+ UHSUB8_VS
+ UHSUB8_VC
+ UHSUB8_HI
+ UHSUB8_LS
+ UHSUB8_GE
+ UHSUB8_LT
+ UHSUB8_GT
+ UHSUB8_LE
+ UHSUB8
+ UHSUB8_ZZ
+ UMAAL_EQ
+ UMAAL_NE
+ UMAAL_CS
+ UMAAL_CC
+ UMAAL_MI
+ UMAAL_PL
+ UMAAL_VS
+ UMAAL_VC
+ UMAAL_HI
+ UMAAL_LS
+ UMAAL_GE
+ UMAAL_LT
+ UMAAL_GT
+ UMAAL_LE
+ UMAAL
+ UMAAL_ZZ
+ UMLAL_EQ
+ UMLAL_NE
+ UMLAL_CS
+ UMLAL_CC
+ UMLAL_MI
+ UMLAL_PL
+ UMLAL_VS
+ UMLAL_VC
+ UMLAL_HI
+ UMLAL_LS
+ UMLAL_GE
+ UMLAL_LT
+ UMLAL_GT
+ UMLAL_LE
+ UMLAL
+ UMLAL_ZZ
+ UMLAL_S_EQ
+ UMLAL_S_NE
+ UMLAL_S_CS
+ UMLAL_S_CC
+ UMLAL_S_MI
+ UMLAL_S_PL
+ UMLAL_S_VS
+ UMLAL_S_VC
+ UMLAL_S_HI
+ UMLAL_S_LS
+ UMLAL_S_GE
+ UMLAL_S_LT
+ UMLAL_S_GT
+ UMLAL_S_LE
+ UMLAL_S
+ UMLAL_S_ZZ
+ UMULL_EQ
+ UMULL_NE
+ UMULL_CS
+ UMULL_CC
+ UMULL_MI
+ UMULL_PL
+ UMULL_VS
+ UMULL_VC
+ UMULL_HI
+ UMULL_LS
+ UMULL_GE
+ UMULL_LT
+ UMULL_GT
+ UMULL_LE
+ UMULL
+ UMULL_ZZ
+ UMULL_S_EQ
+ UMULL_S_NE
+ UMULL_S_CS
+ UMULL_S_CC
+ UMULL_S_MI
+ UMULL_S_PL
+ UMULL_S_VS
+ UMULL_S_VC
+ UMULL_S_HI
+ UMULL_S_LS
+ UMULL_S_GE
+ UMULL_S_LT
+ UMULL_S_GT
+ UMULL_S_LE
+ UMULL_S
+ UMULL_S_ZZ
+ UNDEF
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ _
+ UQADD16_EQ
+ UQADD16_NE
+ UQADD16_CS
+ UQADD16_CC
+ UQADD16_MI
+ UQADD16_PL
+ UQADD16_VS
+ UQADD16_VC
+ UQADD16_HI
+ UQADD16_LS
+ UQADD16_GE
+ UQADD16_LT
+ UQADD16_GT
+ UQADD16_LE
+ UQADD16
+ UQADD16_ZZ
+ UQADD8_EQ
+ UQADD8_NE
+ UQADD8_CS
+ UQADD8_CC
+ UQADD8_MI
+ UQADD8_PL
+ UQADD8_VS
+ UQADD8_VC
+ UQADD8_HI
+ UQADD8_LS
+ UQADD8_GE
+ UQADD8_LT
+ UQADD8_GT
+ UQADD8_LE
+ UQADD8
+ UQADD8_ZZ
+ UQASX_EQ
+ UQASX_NE
+ UQASX_CS
+ UQASX_CC
+ UQASX_MI
+ UQASX_PL
+ UQASX_VS
+ UQASX_VC
+ UQASX_HI
+ UQASX_LS
+ UQASX_GE
+ UQASX_LT
+ UQASX_GT
+ UQASX_LE
+ UQASX
+ UQASX_ZZ
+ UQSAX_EQ
+ UQSAX_NE
+ UQSAX_CS
+ UQSAX_CC
+ UQSAX_MI
+ UQSAX_PL
+ UQSAX_VS
+ UQSAX_VC
+ UQSAX_HI
+ UQSAX_LS
+ UQSAX_GE
+ UQSAX_LT
+ UQSAX_GT
+ UQSAX_LE
+ UQSAX
+ UQSAX_ZZ
+ UQSUB16_EQ
+ UQSUB16_NE
+ UQSUB16_CS
+ UQSUB16_CC
+ UQSUB16_MI
+ UQSUB16_PL
+ UQSUB16_VS
+ UQSUB16_VC
+ UQSUB16_HI
+ UQSUB16_LS
+ UQSUB16_GE
+ UQSUB16_LT
+ UQSUB16_GT
+ UQSUB16_LE
+ UQSUB16
+ UQSUB16_ZZ
+ UQSUB8_EQ
+ UQSUB8_NE
+ UQSUB8_CS
+ UQSUB8_CC
+ UQSUB8_MI
+ UQSUB8_PL
+ UQSUB8_VS
+ UQSUB8_VC
+ UQSUB8_HI
+ UQSUB8_LS
+ UQSUB8_GE
+ UQSUB8_LT
+ UQSUB8_GT
+ UQSUB8_LE
+ UQSUB8
+ UQSUB8_ZZ
+ USAD8_EQ
+ USAD8_NE
+ USAD8_CS
+ USAD8_CC
+ USAD8_MI
+ USAD8_PL
+ USAD8_VS
+ USAD8_VC
+ USAD8_HI
+ USAD8_LS
+ USAD8_GE
+ USAD8_LT
+ USAD8_GT
+ USAD8_LE
+ USAD8
+ USAD8_ZZ
+ USADA8_EQ
+ USADA8_NE
+ USADA8_CS
+ USADA8_CC
+ USADA8_MI
+ USADA8_PL
+ USADA8_VS
+ USADA8_VC
+ USADA8_HI
+ USADA8_LS
+ USADA8_GE
+ USADA8_LT
+ USADA8_GT
+ USADA8_LE
+ USADA8
+ USADA8_ZZ
+ USAT_EQ
+ USAT_NE
+ USAT_CS
+ USAT_CC
+ USAT_MI
+ USAT_PL
+ USAT_VS
+ USAT_VC
+ USAT_HI
+ USAT_LS
+ USAT_GE
+ USAT_LT
+ USAT_GT
+ USAT_LE
+ USAT
+ USAT_ZZ
+ USAT16_EQ
+ USAT16_NE
+ USAT16_CS
+ USAT16_CC
+ USAT16_MI
+ USAT16_PL
+ USAT16_VS
+ USAT16_VC
+ USAT16_HI
+ USAT16_LS
+ USAT16_GE
+ USAT16_LT
+ USAT16_GT
+ USAT16_LE
+ USAT16
+ USAT16_ZZ
+ USAX_EQ
+ USAX_NE
+ USAX_CS
+ USAX_CC
+ USAX_MI
+ USAX_PL
+ USAX_VS
+ USAX_VC
+ USAX_HI
+ USAX_LS
+ USAX_GE
+ USAX_LT
+ USAX_GT
+ USAX_LE
+ USAX
+ USAX_ZZ
+ USUB16_EQ
+ USUB16_NE
+ USUB16_CS
+ USUB16_CC
+ USUB16_MI
+ USUB16_PL
+ USUB16_VS
+ USUB16_VC
+ USUB16_HI
+ USUB16_LS
+ USUB16_GE
+ USUB16_LT
+ USUB16_GT
+ USUB16_LE
+ USUB16
+ USUB16_ZZ
+ USUB8_EQ
+ USUB8_NE
+ USUB8_CS
+ USUB8_CC
+ USUB8_MI
+ USUB8_PL
+ USUB8_VS
+ USUB8_VC
+ USUB8_HI
+ USUB8_LS
+ USUB8_GE
+ USUB8_LT
+ USUB8_GT
+ USUB8_LE
+ USUB8
+ USUB8_ZZ
+ UXTAB_EQ
+ UXTAB_NE
+ UXTAB_CS
+ UXTAB_CC
+ UXTAB_MI
+ UXTAB_PL
+ UXTAB_VS
+ UXTAB_VC
+ UXTAB_HI
+ UXTAB_LS
+ UXTAB_GE
+ UXTAB_LT
+ UXTAB_GT
+ UXTAB_LE
+ UXTAB
+ UXTAB_ZZ
+ UXTAB16_EQ
+ UXTAB16_NE
+ UXTAB16_CS
+ UXTAB16_CC
+ UXTAB16_MI
+ UXTAB16_PL
+ UXTAB16_VS
+ UXTAB16_VC
+ UXTAB16_HI
+ UXTAB16_LS
+ UXTAB16_GE
+ UXTAB16_LT
+ UXTAB16_GT
+ UXTAB16_LE
+ UXTAB16
+ UXTAB16_ZZ
+ UXTAH_EQ
+ UXTAH_NE
+ UXTAH_CS
+ UXTAH_CC
+ UXTAH_MI
+ UXTAH_PL
+ UXTAH_VS
+ UXTAH_VC
+ UXTAH_HI
+ UXTAH_LS
+ UXTAH_GE
+ UXTAH_LT
+ UXTAH_GT
+ UXTAH_LE
+ UXTAH
+ UXTAH_ZZ
+ UXTB_EQ
+ UXTB_NE
+ UXTB_CS
+ UXTB_CC
+ UXTB_MI
+ UXTB_PL
+ UXTB_VS
+ UXTB_VC
+ UXTB_HI
+ UXTB_LS
+ UXTB_GE
+ UXTB_LT
+ UXTB_GT
+ UXTB_LE
+ UXTB
+ UXTB_ZZ
+ UXTB16_EQ
+ UXTB16_NE
+ UXTB16_CS
+ UXTB16_CC
+ UXTB16_MI
+ UXTB16_PL
+ UXTB16_VS
+ UXTB16_VC
+ UXTB16_HI
+ UXTB16_LS
+ UXTB16_GE
+ UXTB16_LT
+ UXTB16_GT
+ UXTB16_LE
+ UXTB16
+ UXTB16_ZZ
+ UXTH_EQ
+ UXTH_NE
+ UXTH_CS
+ UXTH_CC
+ UXTH_MI
+ UXTH_PL
+ UXTH_VS
+ UXTH_VC
+ UXTH_HI
+ UXTH_LS
+ UXTH_GE
+ UXTH_LT
+ UXTH_GT
+ UXTH_LE
+ UXTH
+ UXTH_ZZ
+ VABS_EQ_F32
+ VABS_NE_F32
+ VABS_CS_F32
+ VABS_CC_F32
+ VABS_MI_F32
+ VABS_PL_F32
+ VABS_VS_F32
+ VABS_VC_F32
+ VABS_HI_F32
+ VABS_LS_F32
+ VABS_GE_F32
+ VABS_LT_F32
+ VABS_GT_F32
+ VABS_LE_F32
+ VABS_F32
+ VABS_ZZ_F32
+ VABS_EQ_F64
+ VABS_NE_F64
+ VABS_CS_F64
+ VABS_CC_F64
+ VABS_MI_F64
+ VABS_PL_F64
+ VABS_VS_F64
+ VABS_VC_F64
+ VABS_HI_F64
+ VABS_LS_F64
+ VABS_GE_F64
+ VABS_LT_F64
+ VABS_GT_F64
+ VABS_LE_F64
+ VABS_F64
+ VABS_ZZ_F64
+ VADD_EQ_F32
+ VADD_NE_F32
+ VADD_CS_F32
+ VADD_CC_F32
+ VADD_MI_F32
+ VADD_PL_F32
+ VADD_VS_F32
+ VADD_VC_F32
+ VADD_HI_F32
+ VADD_LS_F32
+ VADD_GE_F32
+ VADD_LT_F32
+ VADD_GT_F32
+ VADD_LE_F32
+ VADD_F32
+ VADD_ZZ_F32
+ VADD_EQ_F64
+ VADD_NE_F64
+ VADD_CS_F64
+ VADD_CC_F64
+ VADD_MI_F64
+ VADD_PL_F64
+ VADD_VS_F64
+ VADD_VC_F64
+ VADD_HI_F64
+ VADD_LS_F64
+ VADD_GE_F64
+ VADD_LT_F64
+ VADD_GT_F64
+ VADD_LE_F64
+ VADD_F64
+ VADD_ZZ_F64
+ VCMP_EQ_F32
+ VCMP_NE_F32
+ VCMP_CS_F32
+ VCMP_CC_F32
+ VCMP_MI_F32
+ VCMP_PL_F32
+ VCMP_VS_F32
+ VCMP_VC_F32
+ VCMP_HI_F32
+ VCMP_LS_F32
+ VCMP_GE_F32
+ VCMP_LT_F32
+ VCMP_GT_F32
+ VCMP_LE_F32
+ VCMP_F32
+ VCMP_ZZ_F32
+ VCMP_EQ_F64
+ VCMP_NE_F64
+ VCMP_CS_F64
+ VCMP_CC_F64
+ VCMP_MI_F64
+ VCMP_PL_F64
+ VCMP_VS_F64
+ VCMP_VC_F64
+ VCMP_HI_F64
+ VCMP_LS_F64
+ VCMP_GE_F64
+ VCMP_LT_F64
+ VCMP_GT_F64
+ VCMP_LE_F64
+ VCMP_F64
+ VCMP_ZZ_F64
+ VCMP_E_EQ_F32
+ VCMP_E_NE_F32
+ VCMP_E_CS_F32
+ VCMP_E_CC_F32
+ VCMP_E_MI_F32
+ VCMP_E_PL_F32
+ VCMP_E_VS_F32
+ VCMP_E_VC_F32
+ VCMP_E_HI_F32
+ VCMP_E_LS_F32
+ VCMP_E_GE_F32
+ VCMP_E_LT_F32
+ VCMP_E_GT_F32
+ VCMP_E_LE_F32
+ VCMP_E_F32
+ VCMP_E_ZZ_F32
+ VCMP_E_EQ_F64
+ VCMP_E_NE_F64
+ VCMP_E_CS_F64
+ VCMP_E_CC_F64
+ VCMP_E_MI_F64
+ VCMP_E_PL_F64
+ VCMP_E_VS_F64
+ VCMP_E_VC_F64
+ VCMP_E_HI_F64
+ VCMP_E_LS_F64
+ VCMP_E_GE_F64
+ VCMP_E_LT_F64
+ VCMP_E_GT_F64
+ VCMP_E_LE_F64
+ VCMP_E_F64
+ VCMP_E_ZZ_F64
+ VCVT_EQ_F32_FXS16
+ VCVT_NE_F32_FXS16
+ VCVT_CS_F32_FXS16
+ VCVT_CC_F32_FXS16
+ VCVT_MI_F32_FXS16
+ VCVT_PL_F32_FXS16
+ VCVT_VS_F32_FXS16
+ VCVT_VC_F32_FXS16
+ VCVT_HI_F32_FXS16
+ VCVT_LS_F32_FXS16
+ VCVT_GE_F32_FXS16
+ VCVT_LT_F32_FXS16
+ VCVT_GT_F32_FXS16
+ VCVT_LE_F32_FXS16
+ VCVT_F32_FXS16
+ VCVT_ZZ_F32_FXS16
+ VCVT_EQ_F32_FXS32
+ VCVT_NE_F32_FXS32
+ VCVT_CS_F32_FXS32
+ VCVT_CC_F32_FXS32
+ VCVT_MI_F32_FXS32
+ VCVT_PL_F32_FXS32
+ VCVT_VS_F32_FXS32
+ VCVT_VC_F32_FXS32
+ VCVT_HI_F32_FXS32
+ VCVT_LS_F32_FXS32
+ VCVT_GE_F32_FXS32
+ VCVT_LT_F32_FXS32
+ VCVT_GT_F32_FXS32
+ VCVT_LE_F32_FXS32
+ VCVT_F32_FXS32
+ VCVT_ZZ_F32_FXS32
+ VCVT_EQ_F32_FXU16
+ VCVT_NE_F32_FXU16
+ VCVT_CS_F32_FXU16
+ VCVT_CC_F32_FXU16
+ VCVT_MI_F32_FXU16
+ VCVT_PL_F32_FXU16
+ VCVT_VS_F32_FXU16
+ VCVT_VC_F32_FXU16
+ VCVT_HI_F32_FXU16
+ VCVT_LS_F32_FXU16
+ VCVT_GE_F32_FXU16
+ VCVT_LT_F32_FXU16
+ VCVT_GT_F32_FXU16
+ VCVT_LE_F32_FXU16
+ VCVT_F32_FXU16
+ VCVT_ZZ_F32_FXU16
+ VCVT_EQ_F32_FXU32
+ VCVT_NE_F32_FXU32
+ VCVT_CS_F32_FXU32
+ VCVT_CC_F32_FXU32
+ VCVT_MI_F32_FXU32
+ VCVT_PL_F32_FXU32
+ VCVT_VS_F32_FXU32
+ VCVT_VC_F32_FXU32
+ VCVT_HI_F32_FXU32
+ VCVT_LS_F32_FXU32
+ VCVT_GE_F32_FXU32
+ VCVT_LT_F32_FXU32
+ VCVT_GT_F32_FXU32
+ VCVT_LE_F32_FXU32
+ VCVT_F32_FXU32
+ VCVT_ZZ_F32_FXU32
+ VCVT_EQ_F64_FXS16
+ VCVT_NE_F64_FXS16
+ VCVT_CS_F64_FXS16
+ VCVT_CC_F64_FXS16
+ VCVT_MI_F64_FXS16
+ VCVT_PL_F64_FXS16
+ VCVT_VS_F64_FXS16
+ VCVT_VC_F64_FXS16
+ VCVT_HI_F64_FXS16
+ VCVT_LS_F64_FXS16
+ VCVT_GE_F64_FXS16
+ VCVT_LT_F64_FXS16
+ VCVT_GT_F64_FXS16
+ VCVT_LE_F64_FXS16
+ VCVT_F64_FXS16
+ VCVT_ZZ_F64_FXS16
+ VCVT_EQ_F64_FXS32
+ VCVT_NE_F64_FXS32
+ VCVT_CS_F64_FXS32
+ VCVT_CC_F64_FXS32
+ VCVT_MI_F64_FXS32
+ VCVT_PL_F64_FXS32
+ VCVT_VS_F64_FXS32
+ VCVT_VC_F64_FXS32
+ VCVT_HI_F64_FXS32
+ VCVT_LS_F64_FXS32
+ VCVT_GE_F64_FXS32
+ VCVT_LT_F64_FXS32
+ VCVT_GT_F64_FXS32
+ VCVT_LE_F64_FXS32
+ VCVT_F64_FXS32
+ VCVT_ZZ_F64_FXS32
+ VCVT_EQ_F64_FXU16
+ VCVT_NE_F64_FXU16
+ VCVT_CS_F64_FXU16
+ VCVT_CC_F64_FXU16
+ VCVT_MI_F64_FXU16
+ VCVT_PL_F64_FXU16
+ VCVT_VS_F64_FXU16
+ VCVT_VC_F64_FXU16
+ VCVT_HI_F64_FXU16
+ VCVT_LS_F64_FXU16
+ VCVT_GE_F64_FXU16
+ VCVT_LT_F64_FXU16
+ VCVT_GT_F64_FXU16
+ VCVT_LE_F64_FXU16
+ VCVT_F64_FXU16
+ VCVT_ZZ_F64_FXU16
+ VCVT_EQ_F64_FXU32
+ VCVT_NE_F64_FXU32
+ VCVT_CS_F64_FXU32
+ VCVT_CC_F64_FXU32
+ VCVT_MI_F64_FXU32
+ VCVT_PL_F64_FXU32
+ VCVT_VS_F64_FXU32
+ VCVT_VC_F64_FXU32
+ VCVT_HI_F64_FXU32
+ VCVT_LS_F64_FXU32
+ VCVT_GE_F64_FXU32
+ VCVT_LT_F64_FXU32
+ VCVT_GT_F64_FXU32
+ VCVT_LE_F64_FXU32
+ VCVT_F64_FXU32
+ VCVT_ZZ_F64_FXU32
+ VCVT_EQ_F32_U32
+ VCVT_NE_F32_U32
+ VCVT_CS_F32_U32
+ VCVT_CC_F32_U32
+ VCVT_MI_F32_U32
+ VCVT_PL_F32_U32
+ VCVT_VS_F32_U32
+ VCVT_VC_F32_U32
+ VCVT_HI_F32_U32
+ VCVT_LS_F32_U32
+ VCVT_GE_F32_U32
+ VCVT_LT_F32_U32
+ VCVT_GT_F32_U32
+ VCVT_LE_F32_U32
+ VCVT_F32_U32
+ VCVT_ZZ_F32_U32
+ VCVT_EQ_F32_S32
+ VCVT_NE_F32_S32
+ VCVT_CS_F32_S32
+ VCVT_CC_F32_S32
+ VCVT_MI_F32_S32
+ VCVT_PL_F32_S32
+ VCVT_VS_F32_S32
+ VCVT_VC_F32_S32
+ VCVT_HI_F32_S32
+ VCVT_LS_F32_S32
+ VCVT_GE_F32_S32
+ VCVT_LT_F32_S32
+ VCVT_GT_F32_S32
+ VCVT_LE_F32_S32
+ VCVT_F32_S32
+ VCVT_ZZ_F32_S32
+ VCVT_EQ_F64_U32
+ VCVT_NE_F64_U32
+ VCVT_CS_F64_U32
+ VCVT_CC_F64_U32
+ VCVT_MI_F64_U32
+ VCVT_PL_F64_U32
+ VCVT_VS_F64_U32
+ VCVT_VC_F64_U32
+ VCVT_HI_F64_U32
+ VCVT_LS_F64_U32
+ VCVT_GE_F64_U32
+ VCVT_LT_F64_U32
+ VCVT_GT_F64_U32
+ VCVT_LE_F64_U32
+ VCVT_F64_U32
+ VCVT_ZZ_F64_U32
+ VCVT_EQ_F64_S32
+ VCVT_NE_F64_S32
+ VCVT_CS_F64_S32
+ VCVT_CC_F64_S32
+ VCVT_MI_F64_S32
+ VCVT_PL_F64_S32
+ VCVT_VS_F64_S32
+ VCVT_VC_F64_S32
+ VCVT_HI_F64_S32
+ VCVT_LS_F64_S32
+ VCVT_GE_F64_S32
+ VCVT_LT_F64_S32
+ VCVT_GT_F64_S32
+ VCVT_LE_F64_S32
+ VCVT_F64_S32
+ VCVT_ZZ_F64_S32
+ VCVT_EQ_F64_F32
+ VCVT_NE_F64_F32
+ VCVT_CS_F64_F32
+ VCVT_CC_F64_F32
+ VCVT_MI_F64_F32
+ VCVT_PL_F64_F32
+ VCVT_VS_F64_F32
+ VCVT_VC_F64_F32
+ VCVT_HI_F64_F32
+ VCVT_LS_F64_F32
+ VCVT_GE_F64_F32
+ VCVT_LT_F64_F32
+ VCVT_GT_F64_F32
+ VCVT_LE_F64_F32
+ VCVT_F64_F32
+ VCVT_ZZ_F64_F32
+ VCVT_EQ_F32_F64
+ VCVT_NE_F32_F64
+ VCVT_CS_F32_F64
+ VCVT_CC_F32_F64
+ VCVT_MI_F32_F64
+ VCVT_PL_F32_F64
+ VCVT_VS_F32_F64
+ VCVT_VC_F32_F64
+ VCVT_HI_F32_F64
+ VCVT_LS_F32_F64
+ VCVT_GE_F32_F64
+ VCVT_LT_F32_F64
+ VCVT_GT_F32_F64
+ VCVT_LE_F32_F64
+ VCVT_F32_F64
+ VCVT_ZZ_F32_F64
+ VCVT_EQ_FXS16_F32
+ VCVT_NE_FXS16_F32
+ VCVT_CS_FXS16_F32
+ VCVT_CC_FXS16_F32
+ VCVT_MI_FXS16_F32
+ VCVT_PL_FXS16_F32
+ VCVT_VS_FXS16_F32
+ VCVT_VC_FXS16_F32
+ VCVT_HI_FXS16_F32
+ VCVT_LS_FXS16_F32
+ VCVT_GE_FXS16_F32
+ VCVT_LT_FXS16_F32
+ VCVT_GT_FXS16_F32
+ VCVT_LE_FXS16_F32
+ VCVT_FXS16_F32
+ VCVT_ZZ_FXS16_F32
+ VCVT_EQ_FXS16_F64
+ VCVT_NE_FXS16_F64
+ VCVT_CS_FXS16_F64
+ VCVT_CC_FXS16_F64
+ VCVT_MI_FXS16_F64
+ VCVT_PL_FXS16_F64
+ VCVT_VS_FXS16_F64
+ VCVT_VC_FXS16_F64
+ VCVT_HI_FXS16_F64
+ VCVT_LS_FXS16_F64
+ VCVT_GE_FXS16_F64
+ VCVT_LT_FXS16_F64
+ VCVT_GT_FXS16_F64
+ VCVT_LE_FXS16_F64
+ VCVT_FXS16_F64
+ VCVT_ZZ_FXS16_F64
+ VCVT_EQ_FXS32_F32
+ VCVT_NE_FXS32_F32
+ VCVT_CS_FXS32_F32
+ VCVT_CC_FXS32_F32
+ VCVT_MI_FXS32_F32
+ VCVT_PL_FXS32_F32
+ VCVT_VS_FXS32_F32
+ VCVT_VC_FXS32_F32
+ VCVT_HI_FXS32_F32
+ VCVT_LS_FXS32_F32
+ VCVT_GE_FXS32_F32
+ VCVT_LT_FXS32_F32
+ VCVT_GT_FXS32_F32
+ VCVT_LE_FXS32_F32
+ VCVT_FXS32_F32
+ VCVT_ZZ_FXS32_F32
+ VCVT_EQ_FXS32_F64
+ VCVT_NE_FXS32_F64
+ VCVT_CS_FXS32_F64
+ VCVT_CC_FXS32_F64
+ VCVT_MI_FXS32_F64
+ VCVT_PL_FXS32_F64
+ VCVT_VS_FXS32_F64
+ VCVT_VC_FXS32_F64
+ VCVT_HI_FXS32_F64
+ VCVT_LS_FXS32_F64
+ VCVT_GE_FXS32_F64
+ VCVT_LT_FXS32_F64
+ VCVT_GT_FXS32_F64
+ VCVT_LE_FXS32_F64
+ VCVT_FXS32_F64
+ VCVT_ZZ_FXS32_F64
+ VCVT_EQ_FXU16_F32
+ VCVT_NE_FXU16_F32
+ VCVT_CS_FXU16_F32
+ VCVT_CC_FXU16_F32
+ VCVT_MI_FXU16_F32
+ VCVT_PL_FXU16_F32
+ VCVT_VS_FXU16_F32
+ VCVT_VC_FXU16_F32
+ VCVT_HI_FXU16_F32
+ VCVT_LS_FXU16_F32
+ VCVT_GE_FXU16_F32
+ VCVT_LT_FXU16_F32
+ VCVT_GT_FXU16_F32
+ VCVT_LE_FXU16_F32
+ VCVT_FXU16_F32
+ VCVT_ZZ_FXU16_F32
+ VCVT_EQ_FXU16_F64
+ VCVT_NE_FXU16_F64
+ VCVT_CS_FXU16_F64
+ VCVT_CC_FXU16_F64
+ VCVT_MI_FXU16_F64
+ VCVT_PL_FXU16_F64
+ VCVT_VS_FXU16_F64
+ VCVT_VC_FXU16_F64
+ VCVT_HI_FXU16_F64
+ VCVT_LS_FXU16_F64
+ VCVT_GE_FXU16_F64
+ VCVT_LT_FXU16_F64
+ VCVT_GT_FXU16_F64
+ VCVT_LE_FXU16_F64
+ VCVT_FXU16_F64
+ VCVT_ZZ_FXU16_F64
+ VCVT_EQ_FXU32_F32
+ VCVT_NE_FXU32_F32
+ VCVT_CS_FXU32_F32
+ VCVT_CC_FXU32_F32
+ VCVT_MI_FXU32_F32
+ VCVT_PL_FXU32_F32
+ VCVT_VS_FXU32_F32
+ VCVT_VC_FXU32_F32
+ VCVT_HI_FXU32_F32
+ VCVT_LS_FXU32_F32
+ VCVT_GE_FXU32_F32
+ VCVT_LT_FXU32_F32
+ VCVT_GT_FXU32_F32
+ VCVT_LE_FXU32_F32
+ VCVT_FXU32_F32
+ VCVT_ZZ_FXU32_F32
+ VCVT_EQ_FXU32_F64
+ VCVT_NE_FXU32_F64
+ VCVT_CS_FXU32_F64
+ VCVT_CC_FXU32_F64
+ VCVT_MI_FXU32_F64
+ VCVT_PL_FXU32_F64
+ VCVT_VS_FXU32_F64
+ VCVT_VC_FXU32_F64
+ VCVT_HI_FXU32_F64
+ VCVT_LS_FXU32_F64
+ VCVT_GE_FXU32_F64
+ VCVT_LT_FXU32_F64
+ VCVT_GT_FXU32_F64
+ VCVT_LE_FXU32_F64
+ VCVT_FXU32_F64
+ VCVT_ZZ_FXU32_F64
+ VCVTB_EQ_F32_F16
+ VCVTB_NE_F32_F16
+ VCVTB_CS_F32_F16
+ VCVTB_CC_F32_F16
+ VCVTB_MI_F32_F16
+ VCVTB_PL_F32_F16
+ VCVTB_VS_F32_F16
+ VCVTB_VC_F32_F16
+ VCVTB_HI_F32_F16
+ VCVTB_LS_F32_F16
+ VCVTB_GE_F32_F16
+ VCVTB_LT_F32_F16
+ VCVTB_GT_F32_F16
+ VCVTB_LE_F32_F16
+ VCVTB_F32_F16
+ VCVTB_ZZ_F32_F16
+ VCVTB_EQ_F16_F32
+ VCVTB_NE_F16_F32
+ VCVTB_CS_F16_F32
+ VCVTB_CC_F16_F32
+ VCVTB_MI_F16_F32
+ VCVTB_PL_F16_F32
+ VCVTB_VS_F16_F32
+ VCVTB_VC_F16_F32
+ VCVTB_HI_F16_F32
+ VCVTB_LS_F16_F32
+ VCVTB_GE_F16_F32
+ VCVTB_LT_F16_F32
+ VCVTB_GT_F16_F32
+ VCVTB_LE_F16_F32
+ VCVTB_F16_F32
+ VCVTB_ZZ_F16_F32
+ VCVTT_EQ_F32_F16
+ VCVTT_NE_F32_F16
+ VCVTT_CS_F32_F16
+ VCVTT_CC_F32_F16
+ VCVTT_MI_F32_F16
+ VCVTT_PL_F32_F16
+ VCVTT_VS_F32_F16
+ VCVTT_VC_F32_F16
+ VCVTT_HI_F32_F16
+ VCVTT_LS_F32_F16
+ VCVTT_GE_F32_F16
+ VCVTT_LT_F32_F16
+ VCVTT_GT_F32_F16
+ VCVTT_LE_F32_F16
+ VCVTT_F32_F16
+ VCVTT_ZZ_F32_F16
+ VCVTT_EQ_F16_F32
+ VCVTT_NE_F16_F32
+ VCVTT_CS_F16_F32
+ VCVTT_CC_F16_F32
+ VCVTT_MI_F16_F32
+ VCVTT_PL_F16_F32
+ VCVTT_VS_F16_F32
+ VCVTT_VC_F16_F32
+ VCVTT_HI_F16_F32
+ VCVTT_LS_F16_F32
+ VCVTT_GE_F16_F32
+ VCVTT_LT_F16_F32
+ VCVTT_GT_F16_F32
+ VCVTT_LE_F16_F32
+ VCVTT_F16_F32
+ VCVTT_ZZ_F16_F32
+ VCVTR_EQ_U32_F32
+ VCVTR_NE_U32_F32
+ VCVTR_CS_U32_F32
+ VCVTR_CC_U32_F32
+ VCVTR_MI_U32_F32
+ VCVTR_PL_U32_F32
+ VCVTR_VS_U32_F32
+ VCVTR_VC_U32_F32
+ VCVTR_HI_U32_F32
+ VCVTR_LS_U32_F32
+ VCVTR_GE_U32_F32
+ VCVTR_LT_U32_F32
+ VCVTR_GT_U32_F32
+ VCVTR_LE_U32_F32
+ VCVTR_U32_F32
+ VCVTR_ZZ_U32_F32
+ VCVTR_EQ_U32_F64
+ VCVTR_NE_U32_F64
+ VCVTR_CS_U32_F64
+ VCVTR_CC_U32_F64
+ VCVTR_MI_U32_F64
+ VCVTR_PL_U32_F64
+ VCVTR_VS_U32_F64
+ VCVTR_VC_U32_F64
+ VCVTR_HI_U32_F64
+ VCVTR_LS_U32_F64
+ VCVTR_GE_U32_F64
+ VCVTR_LT_U32_F64
+ VCVTR_GT_U32_F64
+ VCVTR_LE_U32_F64
+ VCVTR_U32_F64
+ VCVTR_ZZ_U32_F64
+ VCVTR_EQ_S32_F32
+ VCVTR_NE_S32_F32
+ VCVTR_CS_S32_F32
+ VCVTR_CC_S32_F32
+ VCVTR_MI_S32_F32
+ VCVTR_PL_S32_F32
+ VCVTR_VS_S32_F32
+ VCVTR_VC_S32_F32
+ VCVTR_HI_S32_F32
+ VCVTR_LS_S32_F32
+ VCVTR_GE_S32_F32
+ VCVTR_LT_S32_F32
+ VCVTR_GT_S32_F32
+ VCVTR_LE_S32_F32
+ VCVTR_S32_F32
+ VCVTR_ZZ_S32_F32
+ VCVTR_EQ_S32_F64
+ VCVTR_NE_S32_F64
+ VCVTR_CS_S32_F64
+ VCVTR_CC_S32_F64
+ VCVTR_MI_S32_F64
+ VCVTR_PL_S32_F64
+ VCVTR_VS_S32_F64
+ VCVTR_VC_S32_F64
+ VCVTR_HI_S32_F64
+ VCVTR_LS_S32_F64
+ VCVTR_GE_S32_F64
+ VCVTR_LT_S32_F64
+ VCVTR_GT_S32_F64
+ VCVTR_LE_S32_F64
+ VCVTR_S32_F64
+ VCVTR_ZZ_S32_F64
+ VCVT_EQ_U32_F32
+ VCVT_NE_U32_F32
+ VCVT_CS_U32_F32
+ VCVT_CC_U32_F32
+ VCVT_MI_U32_F32
+ VCVT_PL_U32_F32
+ VCVT_VS_U32_F32
+ VCVT_VC_U32_F32
+ VCVT_HI_U32_F32
+ VCVT_LS_U32_F32
+ VCVT_GE_U32_F32
+ VCVT_LT_U32_F32
+ VCVT_GT_U32_F32
+ VCVT_LE_U32_F32
+ VCVT_U32_F32
+ VCVT_ZZ_U32_F32
+ VCVT_EQ_U32_F64
+ VCVT_NE_U32_F64
+ VCVT_CS_U32_F64
+ VCVT_CC_U32_F64
+ VCVT_MI_U32_F64
+ VCVT_PL_U32_F64
+ VCVT_VS_U32_F64
+ VCVT_VC_U32_F64
+ VCVT_HI_U32_F64
+ VCVT_LS_U32_F64
+ VCVT_GE_U32_F64
+ VCVT_LT_U32_F64
+ VCVT_GT_U32_F64
+ VCVT_LE_U32_F64
+ VCVT_U32_F64
+ VCVT_ZZ_U32_F64
+ VCVT_EQ_S32_F32
+ VCVT_NE_S32_F32
+ VCVT_CS_S32_F32
+ VCVT_CC_S32_F32
+ VCVT_MI_S32_F32
+ VCVT_PL_S32_F32
+ VCVT_VS_S32_F32
+ VCVT_VC_S32_F32
+ VCVT_HI_S32_F32
+ VCVT_LS_S32_F32
+ VCVT_GE_S32_F32
+ VCVT_LT_S32_F32
+ VCVT_GT_S32_F32
+ VCVT_LE_S32_F32
+ VCVT_S32_F32
+ VCVT_ZZ_S32_F32
+ VCVT_EQ_S32_F64
+ VCVT_NE_S32_F64
+ VCVT_CS_S32_F64
+ VCVT_CC_S32_F64
+ VCVT_MI_S32_F64
+ VCVT_PL_S32_F64
+ VCVT_VS_S32_F64
+ VCVT_VC_S32_F64
+ VCVT_HI_S32_F64
+ VCVT_LS_S32_F64
+ VCVT_GE_S32_F64
+ VCVT_LT_S32_F64
+ VCVT_GT_S32_F64
+ VCVT_LE_S32_F64
+ VCVT_S32_F64
+ VCVT_ZZ_S32_F64
+ VDIV_EQ_F32
+ VDIV_NE_F32
+ VDIV_CS_F32
+ VDIV_CC_F32
+ VDIV_MI_F32
+ VDIV_PL_F32
+ VDIV_VS_F32
+ VDIV_VC_F32
+ VDIV_HI_F32
+ VDIV_LS_F32
+ VDIV_GE_F32
+ VDIV_LT_F32
+ VDIV_GT_F32
+ VDIV_LE_F32
+ VDIV_F32
+ VDIV_ZZ_F32
+ VDIV_EQ_F64
+ VDIV_NE_F64
+ VDIV_CS_F64
+ VDIV_CC_F64
+ VDIV_MI_F64
+ VDIV_PL_F64
+ VDIV_VS_F64
+ VDIV_VC_F64
+ VDIV_HI_F64
+ VDIV_LS_F64
+ VDIV_GE_F64
+ VDIV_LT_F64
+ VDIV_GT_F64
+ VDIV_LE_F64
+ VDIV_F64
+ VDIV_ZZ_F64
+ VLDR_EQ
+ VLDR_NE
+ VLDR_CS
+ VLDR_CC
+ VLDR_MI
+ VLDR_PL
+ VLDR_VS
+ VLDR_VC
+ VLDR_HI
+ VLDR_LS
+ VLDR_GE
+ VLDR_LT
+ VLDR_GT
+ VLDR_LE
+ VLDR
+ VLDR_ZZ
+ VMLA_EQ_F32
+ VMLA_NE_F32
+ VMLA_CS_F32
+ VMLA_CC_F32
+ VMLA_MI_F32
+ VMLA_PL_F32
+ VMLA_VS_F32
+ VMLA_VC_F32
+ VMLA_HI_F32
+ VMLA_LS_F32
+ VMLA_GE_F32
+ VMLA_LT_F32
+ VMLA_GT_F32
+ VMLA_LE_F32
+ VMLA_F32
+ VMLA_ZZ_F32
+ VMLA_EQ_F64
+ VMLA_NE_F64
+ VMLA_CS_F64
+ VMLA_CC_F64
+ VMLA_MI_F64
+ VMLA_PL_F64
+ VMLA_VS_F64
+ VMLA_VC_F64
+ VMLA_HI_F64
+ VMLA_LS_F64
+ VMLA_GE_F64
+ VMLA_LT_F64
+ VMLA_GT_F64
+ VMLA_LE_F64
+ VMLA_F64
+ VMLA_ZZ_F64
+ VMLS_EQ_F32
+ VMLS_NE_F32
+ VMLS_CS_F32
+ VMLS_CC_F32
+ VMLS_MI_F32
+ VMLS_PL_F32
+ VMLS_VS_F32
+ VMLS_VC_F32
+ VMLS_HI_F32
+ VMLS_LS_F32
+ VMLS_GE_F32
+ VMLS_LT_F32
+ VMLS_GT_F32
+ VMLS_LE_F32
+ VMLS_F32
+ VMLS_ZZ_F32
+ VMLS_EQ_F64
+ VMLS_NE_F64
+ VMLS_CS_F64
+ VMLS_CC_F64
+ VMLS_MI_F64
+ VMLS_PL_F64
+ VMLS_VS_F64
+ VMLS_VC_F64
+ VMLS_HI_F64
+ VMLS_LS_F64
+ VMLS_GE_F64
+ VMLS_LT_F64
+ VMLS_GT_F64
+ VMLS_LE_F64
+ VMLS_F64
+ VMLS_ZZ_F64
+ VMOV_EQ
+ VMOV_NE
+ VMOV_CS
+ VMOV_CC
+ VMOV_MI
+ VMOV_PL
+ VMOV_VS
+ VMOV_VC
+ VMOV_HI
+ VMOV_LS
+ VMOV_GE
+ VMOV_LT
+ VMOV_GT
+ VMOV_LE
+ VMOV
+ VMOV_ZZ
+ VMOV_EQ_32
+ VMOV_NE_32
+ VMOV_CS_32
+ VMOV_CC_32
+ VMOV_MI_32
+ VMOV_PL_32
+ VMOV_VS_32
+ VMOV_VC_32
+ VMOV_HI_32
+ VMOV_LS_32
+ VMOV_GE_32
+ VMOV_LT_32
+ VMOV_GT_32
+ VMOV_LE_32
+ VMOV_32
+ VMOV_ZZ_32
+ VMOV_EQ_F32
+ VMOV_NE_F32
+ VMOV_CS_F32
+ VMOV_CC_F32
+ VMOV_MI_F32
+ VMOV_PL_F32
+ VMOV_VS_F32
+ VMOV_VC_F32
+ VMOV_HI_F32
+ VMOV_LS_F32
+ VMOV_GE_F32
+ VMOV_LT_F32
+ VMOV_GT_F32
+ VMOV_LE_F32
+ VMOV_F32
+ VMOV_ZZ_F32
+ VMOV_EQ_F64
+ VMOV_NE_F64
+ VMOV_CS_F64
+ VMOV_CC_F64
+ VMOV_MI_F64
+ VMOV_PL_F64
+ VMOV_VS_F64
+ VMOV_VC_F64
+ VMOV_HI_F64
+ VMOV_LS_F64
+ VMOV_GE_F64
+ VMOV_LT_F64
+ VMOV_GT_F64
+ VMOV_LE_F64
+ VMOV_F64
+ VMOV_ZZ_F64
+ VMRS_EQ
+ VMRS_NE
+ VMRS_CS
+ VMRS_CC
+ VMRS_MI
+ VMRS_PL
+ VMRS_VS
+ VMRS_VC
+ VMRS_HI
+ VMRS_LS
+ VMRS_GE
+ VMRS_LT
+ VMRS_GT
+ VMRS_LE
+ VMRS
+ VMRS_ZZ
+ VMSR_EQ
+ VMSR_NE
+ VMSR_CS
+ VMSR_CC
+ VMSR_MI
+ VMSR_PL
+ VMSR_VS
+ VMSR_VC
+ VMSR_HI
+ VMSR_LS
+ VMSR_GE
+ VMSR_LT
+ VMSR_GT
+ VMSR_LE
+ VMSR
+ VMSR_ZZ
+ VMUL_EQ_F32
+ VMUL_NE_F32
+ VMUL_CS_F32
+ VMUL_CC_F32
+ VMUL_MI_F32
+ VMUL_PL_F32
+ VMUL_VS_F32
+ VMUL_VC_F32
+ VMUL_HI_F32
+ VMUL_LS_F32
+ VMUL_GE_F32
+ VMUL_LT_F32
+ VMUL_GT_F32
+ VMUL_LE_F32
+ VMUL_F32
+ VMUL_ZZ_F32
+ VMUL_EQ_F64
+ VMUL_NE_F64
+ VMUL_CS_F64
+ VMUL_CC_F64
+ VMUL_MI_F64
+ VMUL_PL_F64
+ VMUL_VS_F64
+ VMUL_VC_F64
+ VMUL_HI_F64
+ VMUL_LS_F64
+ VMUL_GE_F64
+ VMUL_LT_F64
+ VMUL_GT_F64
+ VMUL_LE_F64
+ VMUL_F64
+ VMUL_ZZ_F64
+ VNEG_EQ_F32
+ VNEG_NE_F32
+ VNEG_CS_F32
+ VNEG_CC_F32
+ VNEG_MI_F32
+ VNEG_PL_F32
+ VNEG_VS_F32
+ VNEG_VC_F32
+ VNEG_HI_F32
+ VNEG_LS_F32
+ VNEG_GE_F32
+ VNEG_LT_F32
+ VNEG_GT_F32
+ VNEG_LE_F32
+ VNEG_F32
+ VNEG_ZZ_F32
+ VNEG_EQ_F64
+ VNEG_NE_F64
+ VNEG_CS_F64
+ VNEG_CC_F64
+ VNEG_MI_F64
+ VNEG_PL_F64
+ VNEG_VS_F64
+ VNEG_VC_F64
+ VNEG_HI_F64
+ VNEG_LS_F64
+ VNEG_GE_F64
+ VNEG_LT_F64
+ VNEG_GT_F64
+ VNEG_LE_F64
+ VNEG_F64
+ VNEG_ZZ_F64
+ VNMLS_EQ_F32
+ VNMLS_NE_F32
+ VNMLS_CS_F32
+ VNMLS_CC_F32
+ VNMLS_MI_F32
+ VNMLS_PL_F32
+ VNMLS_VS_F32
+ VNMLS_VC_F32
+ VNMLS_HI_F32
+ VNMLS_LS_F32
+ VNMLS_GE_F32
+ VNMLS_LT_F32
+ VNMLS_GT_F32
+ VNMLS_LE_F32
+ VNMLS_F32
+ VNMLS_ZZ_F32
+ VNMLS_EQ_F64
+ VNMLS_NE_F64
+ VNMLS_CS_F64
+ VNMLS_CC_F64
+ VNMLS_MI_F64
+ VNMLS_PL_F64
+ VNMLS_VS_F64
+ VNMLS_VC_F64
+ VNMLS_HI_F64
+ VNMLS_LS_F64
+ VNMLS_GE_F64
+ VNMLS_LT_F64
+ VNMLS_GT_F64
+ VNMLS_LE_F64
+ VNMLS_F64
+ VNMLS_ZZ_F64
+ VNMLA_EQ_F32
+ VNMLA_NE_F32
+ VNMLA_CS_F32
+ VNMLA_CC_F32
+ VNMLA_MI_F32
+ VNMLA_PL_F32
+ VNMLA_VS_F32
+ VNMLA_VC_F32
+ VNMLA_HI_F32
+ VNMLA_LS_F32
+ VNMLA_GE_F32
+ VNMLA_LT_F32
+ VNMLA_GT_F32
+ VNMLA_LE_F32
+ VNMLA_F32
+ VNMLA_ZZ_F32
+ VNMLA_EQ_F64
+ VNMLA_NE_F64
+ VNMLA_CS_F64
+ VNMLA_CC_F64
+ VNMLA_MI_F64
+ VNMLA_PL_F64
+ VNMLA_VS_F64
+ VNMLA_VC_F64
+ VNMLA_HI_F64
+ VNMLA_LS_F64
+ VNMLA_GE_F64
+ VNMLA_LT_F64
+ VNMLA_GT_F64
+ VNMLA_LE_F64
+ VNMLA_F64
+ VNMLA_ZZ_F64
+ VNMUL_EQ_F32
+ VNMUL_NE_F32
+ VNMUL_CS_F32
+ VNMUL_CC_F32
+ VNMUL_MI_F32
+ VNMUL_PL_F32
+ VNMUL_VS_F32
+ VNMUL_VC_F32
+ VNMUL_HI_F32
+ VNMUL_LS_F32
+ VNMUL_GE_F32
+ VNMUL_LT_F32
+ VNMUL_GT_F32
+ VNMUL_LE_F32
+ VNMUL_F32
+ VNMUL_ZZ_F32
+ VNMUL_EQ_F64
+ VNMUL_NE_F64
+ VNMUL_CS_F64
+ VNMUL_CC_F64
+ VNMUL_MI_F64
+ VNMUL_PL_F64
+ VNMUL_VS_F64
+ VNMUL_VC_F64
+ VNMUL_HI_F64
+ VNMUL_LS_F64
+ VNMUL_GE_F64
+ VNMUL_LT_F64
+ VNMUL_GT_F64
+ VNMUL_LE_F64
+ VNMUL_F64
+ VNMUL_ZZ_F64
+ VSQRT_EQ_F32
+ VSQRT_NE_F32
+ VSQRT_CS_F32
+ VSQRT_CC_F32
+ VSQRT_MI_F32
+ VSQRT_PL_F32
+ VSQRT_VS_F32
+ VSQRT_VC_F32
+ VSQRT_HI_F32
+ VSQRT_LS_F32
+ VSQRT_GE_F32
+ VSQRT_LT_F32
+ VSQRT_GT_F32
+ VSQRT_LE_F32
+ VSQRT_F32
+ VSQRT_ZZ_F32
+ VSQRT_EQ_F64
+ VSQRT_NE_F64
+ VSQRT_CS_F64
+ VSQRT_CC_F64
+ VSQRT_MI_F64
+ VSQRT_PL_F64
+ VSQRT_VS_F64
+ VSQRT_VC_F64
+ VSQRT_HI_F64
+ VSQRT_LS_F64
+ VSQRT_GE_F64
+ VSQRT_LT_F64
+ VSQRT_GT_F64
+ VSQRT_LE_F64
+ VSQRT_F64
+ VSQRT_ZZ_F64
+ VSTR_EQ
+ VSTR_NE
+ VSTR_CS
+ VSTR_CC
+ VSTR_MI
+ VSTR_PL
+ VSTR_VS
+ VSTR_VC
+ VSTR_HI
+ VSTR_LS
+ VSTR_GE
+ VSTR_LT
+ VSTR_GT
+ VSTR_LE
+ VSTR
+ VSTR_ZZ
+ VSUB_EQ_F32
+ VSUB_NE_F32
+ VSUB_CS_F32
+ VSUB_CC_F32
+ VSUB_MI_F32
+ VSUB_PL_F32
+ VSUB_VS_F32
+ VSUB_VC_F32
+ VSUB_HI_F32
+ VSUB_LS_F32
+ VSUB_GE_F32
+ VSUB_LT_F32
+ VSUB_GT_F32
+ VSUB_LE_F32
+ VSUB_F32
+ VSUB_ZZ_F32
+ VSUB_EQ_F64
+ VSUB_NE_F64
+ VSUB_CS_F64
+ VSUB_CC_F64
+ VSUB_MI_F64
+ VSUB_PL_F64
+ VSUB_VS_F64
+ VSUB_VC_F64
+ VSUB_HI_F64
+ VSUB_LS_F64
+ VSUB_GE_F64
+ VSUB_LT_F64
+ VSUB_GT_F64
+ VSUB_LE_F64
+ VSUB_F64
+ VSUB_ZZ_F64
+ WFE_EQ
+ WFE_NE
+ WFE_CS
+ WFE_CC
+ WFE_MI
+ WFE_PL
+ WFE_VS
+ WFE_VC
+ WFE_HI
+ WFE_LS
+ WFE_GE
+ WFE_LT
+ WFE_GT
+ WFE_LE
+ WFE
+ WFE_ZZ
+ WFI_EQ
+ WFI_NE
+ WFI_CS
+ WFI_CC
+ WFI_MI
+ WFI_PL
+ WFI_VS
+ WFI_VC
+ WFI_HI
+ WFI_LS
+ WFI_GE
+ WFI_LT
+ WFI_GT
+ WFI_LE
+ WFI
+ WFI_ZZ
+ YIELD_EQ
+ YIELD_NE
+ YIELD_CS
+ YIELD_CC
+ YIELD_MI
+ YIELD_PL
+ YIELD_VS
+ YIELD_VC
+ YIELD_HI
+ YIELD_LS
+ YIELD_GE
+ YIELD_LT
+ YIELD_GT
+ YIELD_LE
+ YIELD
+ YIELD_ZZ
+)
+
+var opstr = [...]string{
+ ADC_EQ: "ADC.EQ",
+ ADC_NE: "ADC.NE",
+ ADC_CS: "ADC.CS",
+ ADC_CC: "ADC.CC",
+ ADC_MI: "ADC.MI",
+ ADC_PL: "ADC.PL",
+ ADC_VS: "ADC.VS",
+ ADC_VC: "ADC.VC",
+ ADC_HI: "ADC.HI",
+ ADC_LS: "ADC.LS",
+ ADC_GE: "ADC.GE",
+ ADC_LT: "ADC.LT",
+ ADC_GT: "ADC.GT",
+ ADC_LE: "ADC.LE",
+ ADC: "ADC",
+ ADC_ZZ: "ADC.ZZ",
+ ADC_S_EQ: "ADC.S.EQ",
+ ADC_S_NE: "ADC.S.NE",
+ ADC_S_CS: "ADC.S.CS",
+ ADC_S_CC: "ADC.S.CC",
+ ADC_S_MI: "ADC.S.MI",
+ ADC_S_PL: "ADC.S.PL",
+ ADC_S_VS: "ADC.S.VS",
+ ADC_S_VC: "ADC.S.VC",
+ ADC_S_HI: "ADC.S.HI",
+ ADC_S_LS: "ADC.S.LS",
+ ADC_S_GE: "ADC.S.GE",
+ ADC_S_LT: "ADC.S.LT",
+ ADC_S_GT: "ADC.S.GT",
+ ADC_S_LE: "ADC.S.LE",
+ ADC_S: "ADC.S",
+ ADC_S_ZZ: "ADC.S.ZZ",
+ ADD_EQ: "ADD.EQ",
+ ADD_NE: "ADD.NE",
+ ADD_CS: "ADD.CS",
+ ADD_CC: "ADD.CC",
+ ADD_MI: "ADD.MI",
+ ADD_PL: "ADD.PL",
+ ADD_VS: "ADD.VS",
+ ADD_VC: "ADD.VC",
+ ADD_HI: "ADD.HI",
+ ADD_LS: "ADD.LS",
+ ADD_GE: "ADD.GE",
+ ADD_LT: "ADD.LT",
+ ADD_GT: "ADD.GT",
+ ADD_LE: "ADD.LE",
+ ADD: "ADD",
+ ADD_ZZ: "ADD.ZZ",
+ ADD_S_EQ: "ADD.S.EQ",
+ ADD_S_NE: "ADD.S.NE",
+ ADD_S_CS: "ADD.S.CS",
+ ADD_S_CC: "ADD.S.CC",
+ ADD_S_MI: "ADD.S.MI",
+ ADD_S_PL: "ADD.S.PL",
+ ADD_S_VS: "ADD.S.VS",
+ ADD_S_VC: "ADD.S.VC",
+ ADD_S_HI: "ADD.S.HI",
+ ADD_S_LS: "ADD.S.LS",
+ ADD_S_GE: "ADD.S.GE",
+ ADD_S_LT: "ADD.S.LT",
+ ADD_S_GT: "ADD.S.GT",
+ ADD_S_LE: "ADD.S.LE",
+ ADD_S: "ADD.S",
+ ADD_S_ZZ: "ADD.S.ZZ",
+ AND_EQ: "AND.EQ",
+ AND_NE: "AND.NE",
+ AND_CS: "AND.CS",
+ AND_CC: "AND.CC",
+ AND_MI: "AND.MI",
+ AND_PL: "AND.PL",
+ AND_VS: "AND.VS",
+ AND_VC: "AND.VC",
+ AND_HI: "AND.HI",
+ AND_LS: "AND.LS",
+ AND_GE: "AND.GE",
+ AND_LT: "AND.LT",
+ AND_GT: "AND.GT",
+ AND_LE: "AND.LE",
+ AND: "AND",
+ AND_ZZ: "AND.ZZ",
+ AND_S_EQ: "AND.S.EQ",
+ AND_S_NE: "AND.S.NE",
+ AND_S_CS: "AND.S.CS",
+ AND_S_CC: "AND.S.CC",
+ AND_S_MI: "AND.S.MI",
+ AND_S_PL: "AND.S.PL",
+ AND_S_VS: "AND.S.VS",
+ AND_S_VC: "AND.S.VC",
+ AND_S_HI: "AND.S.HI",
+ AND_S_LS: "AND.S.LS",
+ AND_S_GE: "AND.S.GE",
+ AND_S_LT: "AND.S.LT",
+ AND_S_GT: "AND.S.GT",
+ AND_S_LE: "AND.S.LE",
+ AND_S: "AND.S",
+ AND_S_ZZ: "AND.S.ZZ",
+ ASR_EQ: "ASR.EQ",
+ ASR_NE: "ASR.NE",
+ ASR_CS: "ASR.CS",
+ ASR_CC: "ASR.CC",
+ ASR_MI: "ASR.MI",
+ ASR_PL: "ASR.PL",
+ ASR_VS: "ASR.VS",
+ ASR_VC: "ASR.VC",
+ ASR_HI: "ASR.HI",
+ ASR_LS: "ASR.LS",
+ ASR_GE: "ASR.GE",
+ ASR_LT: "ASR.LT",
+ ASR_GT: "ASR.GT",
+ ASR_LE: "ASR.LE",
+ ASR: "ASR",
+ ASR_ZZ: "ASR.ZZ",
+ ASR_S_EQ: "ASR.S.EQ",
+ ASR_S_NE: "ASR.S.NE",
+ ASR_S_CS: "ASR.S.CS",
+ ASR_S_CC: "ASR.S.CC",
+ ASR_S_MI: "ASR.S.MI",
+ ASR_S_PL: "ASR.S.PL",
+ ASR_S_VS: "ASR.S.VS",
+ ASR_S_VC: "ASR.S.VC",
+ ASR_S_HI: "ASR.S.HI",
+ ASR_S_LS: "ASR.S.LS",
+ ASR_S_GE: "ASR.S.GE",
+ ASR_S_LT: "ASR.S.LT",
+ ASR_S_GT: "ASR.S.GT",
+ ASR_S_LE: "ASR.S.LE",
+ ASR_S: "ASR.S",
+ ASR_S_ZZ: "ASR.S.ZZ",
+ B_EQ: "B.EQ",
+ B_NE: "B.NE",
+ B_CS: "B.CS",
+ B_CC: "B.CC",
+ B_MI: "B.MI",
+ B_PL: "B.PL",
+ B_VS: "B.VS",
+ B_VC: "B.VC",
+ B_HI: "B.HI",
+ B_LS: "B.LS",
+ B_GE: "B.GE",
+ B_LT: "B.LT",
+ B_GT: "B.GT",
+ B_LE: "B.LE",
+ B: "B",
+ B_ZZ: "B.ZZ",
+ BFC_EQ: "BFC.EQ",
+ BFC_NE: "BFC.NE",
+ BFC_CS: "BFC.CS",
+ BFC_CC: "BFC.CC",
+ BFC_MI: "BFC.MI",
+ BFC_PL: "BFC.PL",
+ BFC_VS: "BFC.VS",
+ BFC_VC: "BFC.VC",
+ BFC_HI: "BFC.HI",
+ BFC_LS: "BFC.LS",
+ BFC_GE: "BFC.GE",
+ BFC_LT: "BFC.LT",
+ BFC_GT: "BFC.GT",
+ BFC_LE: "BFC.LE",
+ BFC: "BFC",
+ BFC_ZZ: "BFC.ZZ",
+ BFI_EQ: "BFI.EQ",
+ BFI_NE: "BFI.NE",
+ BFI_CS: "BFI.CS",
+ BFI_CC: "BFI.CC",
+ BFI_MI: "BFI.MI",
+ BFI_PL: "BFI.PL",
+ BFI_VS: "BFI.VS",
+ BFI_VC: "BFI.VC",
+ BFI_HI: "BFI.HI",
+ BFI_LS: "BFI.LS",
+ BFI_GE: "BFI.GE",
+ BFI_LT: "BFI.LT",
+ BFI_GT: "BFI.GT",
+ BFI_LE: "BFI.LE",
+ BFI: "BFI",
+ BFI_ZZ: "BFI.ZZ",
+ BIC_EQ: "BIC.EQ",
+ BIC_NE: "BIC.NE",
+ BIC_CS: "BIC.CS",
+ BIC_CC: "BIC.CC",
+ BIC_MI: "BIC.MI",
+ BIC_PL: "BIC.PL",
+ BIC_VS: "BIC.VS",
+ BIC_VC: "BIC.VC",
+ BIC_HI: "BIC.HI",
+ BIC_LS: "BIC.LS",
+ BIC_GE: "BIC.GE",
+ BIC_LT: "BIC.LT",
+ BIC_GT: "BIC.GT",
+ BIC_LE: "BIC.LE",
+ BIC: "BIC",
+ BIC_ZZ: "BIC.ZZ",
+ BIC_S_EQ: "BIC.S.EQ",
+ BIC_S_NE: "BIC.S.NE",
+ BIC_S_CS: "BIC.S.CS",
+ BIC_S_CC: "BIC.S.CC",
+ BIC_S_MI: "BIC.S.MI",
+ BIC_S_PL: "BIC.S.PL",
+ BIC_S_VS: "BIC.S.VS",
+ BIC_S_VC: "BIC.S.VC",
+ BIC_S_HI: "BIC.S.HI",
+ BIC_S_LS: "BIC.S.LS",
+ BIC_S_GE: "BIC.S.GE",
+ BIC_S_LT: "BIC.S.LT",
+ BIC_S_GT: "BIC.S.GT",
+ BIC_S_LE: "BIC.S.LE",
+ BIC_S: "BIC.S",
+ BIC_S_ZZ: "BIC.S.ZZ",
+ BKPT_EQ: "BKPT.EQ",
+ BKPT_NE: "BKPT.NE",
+ BKPT_CS: "BKPT.CS",
+ BKPT_CC: "BKPT.CC",
+ BKPT_MI: "BKPT.MI",
+ BKPT_PL: "BKPT.PL",
+ BKPT_VS: "BKPT.VS",
+ BKPT_VC: "BKPT.VC",
+ BKPT_HI: "BKPT.HI",
+ BKPT_LS: "BKPT.LS",
+ BKPT_GE: "BKPT.GE",
+ BKPT_LT: "BKPT.LT",
+ BKPT_GT: "BKPT.GT",
+ BKPT_LE: "BKPT.LE",
+ BKPT: "BKPT",
+ BKPT_ZZ: "BKPT.ZZ",
+ BL_EQ: "BL.EQ",
+ BL_NE: "BL.NE",
+ BL_CS: "BL.CS",
+ BL_CC: "BL.CC",
+ BL_MI: "BL.MI",
+ BL_PL: "BL.PL",
+ BL_VS: "BL.VS",
+ BL_VC: "BL.VC",
+ BL_HI: "BL.HI",
+ BL_LS: "BL.LS",
+ BL_GE: "BL.GE",
+ BL_LT: "BL.LT",
+ BL_GT: "BL.GT",
+ BL_LE: "BL.LE",
+ BL: "BL",
+ BL_ZZ: "BL.ZZ",
+ BLX_EQ: "BLX.EQ",
+ BLX_NE: "BLX.NE",
+ BLX_CS: "BLX.CS",
+ BLX_CC: "BLX.CC",
+ BLX_MI: "BLX.MI",
+ BLX_PL: "BLX.PL",
+ BLX_VS: "BLX.VS",
+ BLX_VC: "BLX.VC",
+ BLX_HI: "BLX.HI",
+ BLX_LS: "BLX.LS",
+ BLX_GE: "BLX.GE",
+ BLX_LT: "BLX.LT",
+ BLX_GT: "BLX.GT",
+ BLX_LE: "BLX.LE",
+ BLX: "BLX",
+ BLX_ZZ: "BLX.ZZ",
+ BX_EQ: "BX.EQ",
+ BX_NE: "BX.NE",
+ BX_CS: "BX.CS",
+ BX_CC: "BX.CC",
+ BX_MI: "BX.MI",
+ BX_PL: "BX.PL",
+ BX_VS: "BX.VS",
+ BX_VC: "BX.VC",
+ BX_HI: "BX.HI",
+ BX_LS: "BX.LS",
+ BX_GE: "BX.GE",
+ BX_LT: "BX.LT",
+ BX_GT: "BX.GT",
+ BX_LE: "BX.LE",
+ BX: "BX",
+ BX_ZZ: "BX.ZZ",
+ BXJ_EQ: "BXJ.EQ",
+ BXJ_NE: "BXJ.NE",
+ BXJ_CS: "BXJ.CS",
+ BXJ_CC: "BXJ.CC",
+ BXJ_MI: "BXJ.MI",
+ BXJ_PL: "BXJ.PL",
+ BXJ_VS: "BXJ.VS",
+ BXJ_VC: "BXJ.VC",
+ BXJ_HI: "BXJ.HI",
+ BXJ_LS: "BXJ.LS",
+ BXJ_GE: "BXJ.GE",
+ BXJ_LT: "BXJ.LT",
+ BXJ_GT: "BXJ.GT",
+ BXJ_LE: "BXJ.LE",
+ BXJ: "BXJ",
+ BXJ_ZZ: "BXJ.ZZ",
+ CLREX: "CLREX",
+ CLZ_EQ: "CLZ.EQ",
+ CLZ_NE: "CLZ.NE",
+ CLZ_CS: "CLZ.CS",
+ CLZ_CC: "CLZ.CC",
+ CLZ_MI: "CLZ.MI",
+ CLZ_PL: "CLZ.PL",
+ CLZ_VS: "CLZ.VS",
+ CLZ_VC: "CLZ.VC",
+ CLZ_HI: "CLZ.HI",
+ CLZ_LS: "CLZ.LS",
+ CLZ_GE: "CLZ.GE",
+ CLZ_LT: "CLZ.LT",
+ CLZ_GT: "CLZ.GT",
+ CLZ_LE: "CLZ.LE",
+ CLZ: "CLZ",
+ CLZ_ZZ: "CLZ.ZZ",
+ CMN_EQ: "CMN.EQ",
+ CMN_NE: "CMN.NE",
+ CMN_CS: "CMN.CS",
+ CMN_CC: "CMN.CC",
+ CMN_MI: "CMN.MI",
+ CMN_PL: "CMN.PL",
+ CMN_VS: "CMN.VS",
+ CMN_VC: "CMN.VC",
+ CMN_HI: "CMN.HI",
+ CMN_LS: "CMN.LS",
+ CMN_GE: "CMN.GE",
+ CMN_LT: "CMN.LT",
+ CMN_GT: "CMN.GT",
+ CMN_LE: "CMN.LE",
+ CMN: "CMN",
+ CMN_ZZ: "CMN.ZZ",
+ CMP_EQ: "CMP.EQ",
+ CMP_NE: "CMP.NE",
+ CMP_CS: "CMP.CS",
+ CMP_CC: "CMP.CC",
+ CMP_MI: "CMP.MI",
+ CMP_PL: "CMP.PL",
+ CMP_VS: "CMP.VS",
+ CMP_VC: "CMP.VC",
+ CMP_HI: "CMP.HI",
+ CMP_LS: "CMP.LS",
+ CMP_GE: "CMP.GE",
+ CMP_LT: "CMP.LT",
+ CMP_GT: "CMP.GT",
+ CMP_LE: "CMP.LE",
+ CMP: "CMP",
+ CMP_ZZ: "CMP.ZZ",
+ DBG_EQ: "DBG.EQ",
+ DBG_NE: "DBG.NE",
+ DBG_CS: "DBG.CS",
+ DBG_CC: "DBG.CC",
+ DBG_MI: "DBG.MI",
+ DBG_PL: "DBG.PL",
+ DBG_VS: "DBG.VS",
+ DBG_VC: "DBG.VC",
+ DBG_HI: "DBG.HI",
+ DBG_LS: "DBG.LS",
+ DBG_GE: "DBG.GE",
+ DBG_LT: "DBG.LT",
+ DBG_GT: "DBG.GT",
+ DBG_LE: "DBG.LE",
+ DBG: "DBG",
+ DBG_ZZ: "DBG.ZZ",
+ DMB: "DMB",
+ DSB: "DSB",
+ EOR_EQ: "EOR.EQ",
+ EOR_NE: "EOR.NE",
+ EOR_CS: "EOR.CS",
+ EOR_CC: "EOR.CC",
+ EOR_MI: "EOR.MI",
+ EOR_PL: "EOR.PL",
+ EOR_VS: "EOR.VS",
+ EOR_VC: "EOR.VC",
+ EOR_HI: "EOR.HI",
+ EOR_LS: "EOR.LS",
+ EOR_GE: "EOR.GE",
+ EOR_LT: "EOR.LT",
+ EOR_GT: "EOR.GT",
+ EOR_LE: "EOR.LE",
+ EOR: "EOR",
+ EOR_ZZ: "EOR.ZZ",
+ EOR_S_EQ: "EOR.S.EQ",
+ EOR_S_NE: "EOR.S.NE",
+ EOR_S_CS: "EOR.S.CS",
+ EOR_S_CC: "EOR.S.CC",
+ EOR_S_MI: "EOR.S.MI",
+ EOR_S_PL: "EOR.S.PL",
+ EOR_S_VS: "EOR.S.VS",
+ EOR_S_VC: "EOR.S.VC",
+ EOR_S_HI: "EOR.S.HI",
+ EOR_S_LS: "EOR.S.LS",
+ EOR_S_GE: "EOR.S.GE",
+ EOR_S_LT: "EOR.S.LT",
+ EOR_S_GT: "EOR.S.GT",
+ EOR_S_LE: "EOR.S.LE",
+ EOR_S: "EOR.S",
+ EOR_S_ZZ: "EOR.S.ZZ",
+ ISB: "ISB",
+ LDM_EQ: "LDM.EQ",
+ LDM_NE: "LDM.NE",
+ LDM_CS: "LDM.CS",
+ LDM_CC: "LDM.CC",
+ LDM_MI: "LDM.MI",
+ LDM_PL: "LDM.PL",
+ LDM_VS: "LDM.VS",
+ LDM_VC: "LDM.VC",
+ LDM_HI: "LDM.HI",
+ LDM_LS: "LDM.LS",
+ LDM_GE: "LDM.GE",
+ LDM_LT: "LDM.LT",
+ LDM_GT: "LDM.GT",
+ LDM_LE: "LDM.LE",
+ LDM: "LDM",
+ LDM_ZZ: "LDM.ZZ",
+ LDMDA_EQ: "LDMDA.EQ",
+ LDMDA_NE: "LDMDA.NE",
+ LDMDA_CS: "LDMDA.CS",
+ LDMDA_CC: "LDMDA.CC",
+ LDMDA_MI: "LDMDA.MI",
+ LDMDA_PL: "LDMDA.PL",
+ LDMDA_VS: "LDMDA.VS",
+ LDMDA_VC: "LDMDA.VC",
+ LDMDA_HI: "LDMDA.HI",
+ LDMDA_LS: "LDMDA.LS",
+ LDMDA_GE: "LDMDA.GE",
+ LDMDA_LT: "LDMDA.LT",
+ LDMDA_GT: "LDMDA.GT",
+ LDMDA_LE: "LDMDA.LE",
+ LDMDA: "LDMDA",
+ LDMDA_ZZ: "LDMDA.ZZ",
+ LDMDB_EQ: "LDMDB.EQ",
+ LDMDB_NE: "LDMDB.NE",
+ LDMDB_CS: "LDMDB.CS",
+ LDMDB_CC: "LDMDB.CC",
+ LDMDB_MI: "LDMDB.MI",
+ LDMDB_PL: "LDMDB.PL",
+ LDMDB_VS: "LDMDB.VS",
+ LDMDB_VC: "LDMDB.VC",
+ LDMDB_HI: "LDMDB.HI",
+ LDMDB_LS: "LDMDB.LS",
+ LDMDB_GE: "LDMDB.GE",
+ LDMDB_LT: "LDMDB.LT",
+ LDMDB_GT: "LDMDB.GT",
+ LDMDB_LE: "LDMDB.LE",
+ LDMDB: "LDMDB",
+ LDMDB_ZZ: "LDMDB.ZZ",
+ LDMIB_EQ: "LDMIB.EQ",
+ LDMIB_NE: "LDMIB.NE",
+ LDMIB_CS: "LDMIB.CS",
+ LDMIB_CC: "LDMIB.CC",
+ LDMIB_MI: "LDMIB.MI",
+ LDMIB_PL: "LDMIB.PL",
+ LDMIB_VS: "LDMIB.VS",
+ LDMIB_VC: "LDMIB.VC",
+ LDMIB_HI: "LDMIB.HI",
+ LDMIB_LS: "LDMIB.LS",
+ LDMIB_GE: "LDMIB.GE",
+ LDMIB_LT: "LDMIB.LT",
+ LDMIB_GT: "LDMIB.GT",
+ LDMIB_LE: "LDMIB.LE",
+ LDMIB: "LDMIB",
+ LDMIB_ZZ: "LDMIB.ZZ",
+ LDR_EQ: "LDR.EQ",
+ LDR_NE: "LDR.NE",
+ LDR_CS: "LDR.CS",
+ LDR_CC: "LDR.CC",
+ LDR_MI: "LDR.MI",
+ LDR_PL: "LDR.PL",
+ LDR_VS: "LDR.VS",
+ LDR_VC: "LDR.VC",
+ LDR_HI: "LDR.HI",
+ LDR_LS: "LDR.LS",
+ LDR_GE: "LDR.GE",
+ LDR_LT: "LDR.LT",
+ LDR_GT: "LDR.GT",
+ LDR_LE: "LDR.LE",
+ LDR: "LDR",
+ LDR_ZZ: "LDR.ZZ",
+ LDRB_EQ: "LDRB.EQ",
+ LDRB_NE: "LDRB.NE",
+ LDRB_CS: "LDRB.CS",
+ LDRB_CC: "LDRB.CC",
+ LDRB_MI: "LDRB.MI",
+ LDRB_PL: "LDRB.PL",
+ LDRB_VS: "LDRB.VS",
+ LDRB_VC: "LDRB.VC",
+ LDRB_HI: "LDRB.HI",
+ LDRB_LS: "LDRB.LS",
+ LDRB_GE: "LDRB.GE",
+ LDRB_LT: "LDRB.LT",
+ LDRB_GT: "LDRB.GT",
+ LDRB_LE: "LDRB.LE",
+ LDRB: "LDRB",
+ LDRB_ZZ: "LDRB.ZZ",
+ LDRBT_EQ: "LDRBT.EQ",
+ LDRBT_NE: "LDRBT.NE",
+ LDRBT_CS: "LDRBT.CS",
+ LDRBT_CC: "LDRBT.CC",
+ LDRBT_MI: "LDRBT.MI",
+ LDRBT_PL: "LDRBT.PL",
+ LDRBT_VS: "LDRBT.VS",
+ LDRBT_VC: "LDRBT.VC",
+ LDRBT_HI: "LDRBT.HI",
+ LDRBT_LS: "LDRBT.LS",
+ LDRBT_GE: "LDRBT.GE",
+ LDRBT_LT: "LDRBT.LT",
+ LDRBT_GT: "LDRBT.GT",
+ LDRBT_LE: "LDRBT.LE",
+ LDRBT: "LDRBT",
+ LDRBT_ZZ: "LDRBT.ZZ",
+ LDRD_EQ: "LDRD.EQ",
+ LDRD_NE: "LDRD.NE",
+ LDRD_CS: "LDRD.CS",
+ LDRD_CC: "LDRD.CC",
+ LDRD_MI: "LDRD.MI",
+ LDRD_PL: "LDRD.PL",
+ LDRD_VS: "LDRD.VS",
+ LDRD_VC: "LDRD.VC",
+ LDRD_HI: "LDRD.HI",
+ LDRD_LS: "LDRD.LS",
+ LDRD_GE: "LDRD.GE",
+ LDRD_LT: "LDRD.LT",
+ LDRD_GT: "LDRD.GT",
+ LDRD_LE: "LDRD.LE",
+ LDRD: "LDRD",
+ LDRD_ZZ: "LDRD.ZZ",
+ LDREX_EQ: "LDREX.EQ",
+ LDREX_NE: "LDREX.NE",
+ LDREX_CS: "LDREX.CS",
+ LDREX_CC: "LDREX.CC",
+ LDREX_MI: "LDREX.MI",
+ LDREX_PL: "LDREX.PL",
+ LDREX_VS: "LDREX.VS",
+ LDREX_VC: "LDREX.VC",
+ LDREX_HI: "LDREX.HI",
+ LDREX_LS: "LDREX.LS",
+ LDREX_GE: "LDREX.GE",
+ LDREX_LT: "LDREX.LT",
+ LDREX_GT: "LDREX.GT",
+ LDREX_LE: "LDREX.LE",
+ LDREX: "LDREX",
+ LDREX_ZZ: "LDREX.ZZ",
+ LDREXB_EQ: "LDREXB.EQ",
+ LDREXB_NE: "LDREXB.NE",
+ LDREXB_CS: "LDREXB.CS",
+ LDREXB_CC: "LDREXB.CC",
+ LDREXB_MI: "LDREXB.MI",
+ LDREXB_PL: "LDREXB.PL",
+ LDREXB_VS: "LDREXB.VS",
+ LDREXB_VC: "LDREXB.VC",
+ LDREXB_HI: "LDREXB.HI",
+ LDREXB_LS: "LDREXB.LS",
+ LDREXB_GE: "LDREXB.GE",
+ LDREXB_LT: "LDREXB.LT",
+ LDREXB_GT: "LDREXB.GT",
+ LDREXB_LE: "LDREXB.LE",
+ LDREXB: "LDREXB",
+ LDREXB_ZZ: "LDREXB.ZZ",
+ LDREXD_EQ: "LDREXD.EQ",
+ LDREXD_NE: "LDREXD.NE",
+ LDREXD_CS: "LDREXD.CS",
+ LDREXD_CC: "LDREXD.CC",
+ LDREXD_MI: "LDREXD.MI",
+ LDREXD_PL: "LDREXD.PL",
+ LDREXD_VS: "LDREXD.VS",
+ LDREXD_VC: "LDREXD.VC",
+ LDREXD_HI: "LDREXD.HI",
+ LDREXD_LS: "LDREXD.LS",
+ LDREXD_GE: "LDREXD.GE",
+ LDREXD_LT: "LDREXD.LT",
+ LDREXD_GT: "LDREXD.GT",
+ LDREXD_LE: "LDREXD.LE",
+ LDREXD: "LDREXD",
+ LDREXD_ZZ: "LDREXD.ZZ",
+ LDREXH_EQ: "LDREXH.EQ",
+ LDREXH_NE: "LDREXH.NE",
+ LDREXH_CS: "LDREXH.CS",
+ LDREXH_CC: "LDREXH.CC",
+ LDREXH_MI: "LDREXH.MI",
+ LDREXH_PL: "LDREXH.PL",
+ LDREXH_VS: "LDREXH.VS",
+ LDREXH_VC: "LDREXH.VC",
+ LDREXH_HI: "LDREXH.HI",
+ LDREXH_LS: "LDREXH.LS",
+ LDREXH_GE: "LDREXH.GE",
+ LDREXH_LT: "LDREXH.LT",
+ LDREXH_GT: "LDREXH.GT",
+ LDREXH_LE: "LDREXH.LE",
+ LDREXH: "LDREXH",
+ LDREXH_ZZ: "LDREXH.ZZ",
+ LDRH_EQ: "LDRH.EQ",
+ LDRH_NE: "LDRH.NE",
+ LDRH_CS: "LDRH.CS",
+ LDRH_CC: "LDRH.CC",
+ LDRH_MI: "LDRH.MI",
+ LDRH_PL: "LDRH.PL",
+ LDRH_VS: "LDRH.VS",
+ LDRH_VC: "LDRH.VC",
+ LDRH_HI: "LDRH.HI",
+ LDRH_LS: "LDRH.LS",
+ LDRH_GE: "LDRH.GE",
+ LDRH_LT: "LDRH.LT",
+ LDRH_GT: "LDRH.GT",
+ LDRH_LE: "LDRH.LE",
+ LDRH: "LDRH",
+ LDRH_ZZ: "LDRH.ZZ",
+ LDRHT_EQ: "LDRHT.EQ",
+ LDRHT_NE: "LDRHT.NE",
+ LDRHT_CS: "LDRHT.CS",
+ LDRHT_CC: "LDRHT.CC",
+ LDRHT_MI: "LDRHT.MI",
+ LDRHT_PL: "LDRHT.PL",
+ LDRHT_VS: "LDRHT.VS",
+ LDRHT_VC: "LDRHT.VC",
+ LDRHT_HI: "LDRHT.HI",
+ LDRHT_LS: "LDRHT.LS",
+ LDRHT_GE: "LDRHT.GE",
+ LDRHT_LT: "LDRHT.LT",
+ LDRHT_GT: "LDRHT.GT",
+ LDRHT_LE: "LDRHT.LE",
+ LDRHT: "LDRHT",
+ LDRHT_ZZ: "LDRHT.ZZ",
+ LDRSB_EQ: "LDRSB.EQ",
+ LDRSB_NE: "LDRSB.NE",
+ LDRSB_CS: "LDRSB.CS",
+ LDRSB_CC: "LDRSB.CC",
+ LDRSB_MI: "LDRSB.MI",
+ LDRSB_PL: "LDRSB.PL",
+ LDRSB_VS: "LDRSB.VS",
+ LDRSB_VC: "LDRSB.VC",
+ LDRSB_HI: "LDRSB.HI",
+ LDRSB_LS: "LDRSB.LS",
+ LDRSB_GE: "LDRSB.GE",
+ LDRSB_LT: "LDRSB.LT",
+ LDRSB_GT: "LDRSB.GT",
+ LDRSB_LE: "LDRSB.LE",
+ LDRSB: "LDRSB",
+ LDRSB_ZZ: "LDRSB.ZZ",
+ LDRSBT_EQ: "LDRSBT.EQ",
+ LDRSBT_NE: "LDRSBT.NE",
+ LDRSBT_CS: "LDRSBT.CS",
+ LDRSBT_CC: "LDRSBT.CC",
+ LDRSBT_MI: "LDRSBT.MI",
+ LDRSBT_PL: "LDRSBT.PL",
+ LDRSBT_VS: "LDRSBT.VS",
+ LDRSBT_VC: "LDRSBT.VC",
+ LDRSBT_HI: "LDRSBT.HI",
+ LDRSBT_LS: "LDRSBT.LS",
+ LDRSBT_GE: "LDRSBT.GE",
+ LDRSBT_LT: "LDRSBT.LT",
+ LDRSBT_GT: "LDRSBT.GT",
+ LDRSBT_LE: "LDRSBT.LE",
+ LDRSBT: "LDRSBT",
+ LDRSBT_ZZ: "LDRSBT.ZZ",
+ LDRSH_EQ: "LDRSH.EQ",
+ LDRSH_NE: "LDRSH.NE",
+ LDRSH_CS: "LDRSH.CS",
+ LDRSH_CC: "LDRSH.CC",
+ LDRSH_MI: "LDRSH.MI",
+ LDRSH_PL: "LDRSH.PL",
+ LDRSH_VS: "LDRSH.VS",
+ LDRSH_VC: "LDRSH.VC",
+ LDRSH_HI: "LDRSH.HI",
+ LDRSH_LS: "LDRSH.LS",
+ LDRSH_GE: "LDRSH.GE",
+ LDRSH_LT: "LDRSH.LT",
+ LDRSH_GT: "LDRSH.GT",
+ LDRSH_LE: "LDRSH.LE",
+ LDRSH: "LDRSH",
+ LDRSH_ZZ: "LDRSH.ZZ",
+ LDRSHT_EQ: "LDRSHT.EQ",
+ LDRSHT_NE: "LDRSHT.NE",
+ LDRSHT_CS: "LDRSHT.CS",
+ LDRSHT_CC: "LDRSHT.CC",
+ LDRSHT_MI: "LDRSHT.MI",
+ LDRSHT_PL: "LDRSHT.PL",
+ LDRSHT_VS: "LDRSHT.VS",
+ LDRSHT_VC: "LDRSHT.VC",
+ LDRSHT_HI: "LDRSHT.HI",
+ LDRSHT_LS: "LDRSHT.LS",
+ LDRSHT_GE: "LDRSHT.GE",
+ LDRSHT_LT: "LDRSHT.LT",
+ LDRSHT_GT: "LDRSHT.GT",
+ LDRSHT_LE: "LDRSHT.LE",
+ LDRSHT: "LDRSHT",
+ LDRSHT_ZZ: "LDRSHT.ZZ",
+ LDRT_EQ: "LDRT.EQ",
+ LDRT_NE: "LDRT.NE",
+ LDRT_CS: "LDRT.CS",
+ LDRT_CC: "LDRT.CC",
+ LDRT_MI: "LDRT.MI",
+ LDRT_PL: "LDRT.PL",
+ LDRT_VS: "LDRT.VS",
+ LDRT_VC: "LDRT.VC",
+ LDRT_HI: "LDRT.HI",
+ LDRT_LS: "LDRT.LS",
+ LDRT_GE: "LDRT.GE",
+ LDRT_LT: "LDRT.LT",
+ LDRT_GT: "LDRT.GT",
+ LDRT_LE: "LDRT.LE",
+ LDRT: "LDRT",
+ LDRT_ZZ: "LDRT.ZZ",
+ LSL_EQ: "LSL.EQ",
+ LSL_NE: "LSL.NE",
+ LSL_CS: "LSL.CS",
+ LSL_CC: "LSL.CC",
+ LSL_MI: "LSL.MI",
+ LSL_PL: "LSL.PL",
+ LSL_VS: "LSL.VS",
+ LSL_VC: "LSL.VC",
+ LSL_HI: "LSL.HI",
+ LSL_LS: "LSL.LS",
+ LSL_GE: "LSL.GE",
+ LSL_LT: "LSL.LT",
+ LSL_GT: "LSL.GT",
+ LSL_LE: "LSL.LE",
+ LSL: "LSL",
+ LSL_ZZ: "LSL.ZZ",
+ LSL_S_EQ: "LSL.S.EQ",
+ LSL_S_NE: "LSL.S.NE",
+ LSL_S_CS: "LSL.S.CS",
+ LSL_S_CC: "LSL.S.CC",
+ LSL_S_MI: "LSL.S.MI",
+ LSL_S_PL: "LSL.S.PL",
+ LSL_S_VS: "LSL.S.VS",
+ LSL_S_VC: "LSL.S.VC",
+ LSL_S_HI: "LSL.S.HI",
+ LSL_S_LS: "LSL.S.LS",
+ LSL_S_GE: "LSL.S.GE",
+ LSL_S_LT: "LSL.S.LT",
+ LSL_S_GT: "LSL.S.GT",
+ LSL_S_LE: "LSL.S.LE",
+ LSL_S: "LSL.S",
+ LSL_S_ZZ: "LSL.S.ZZ",
+ LSR_EQ: "LSR.EQ",
+ LSR_NE: "LSR.NE",
+ LSR_CS: "LSR.CS",
+ LSR_CC: "LSR.CC",
+ LSR_MI: "LSR.MI",
+ LSR_PL: "LSR.PL",
+ LSR_VS: "LSR.VS",
+ LSR_VC: "LSR.VC",
+ LSR_HI: "LSR.HI",
+ LSR_LS: "LSR.LS",
+ LSR_GE: "LSR.GE",
+ LSR_LT: "LSR.LT",
+ LSR_GT: "LSR.GT",
+ LSR_LE: "LSR.LE",
+ LSR: "LSR",
+ LSR_ZZ: "LSR.ZZ",
+ LSR_S_EQ: "LSR.S.EQ",
+ LSR_S_NE: "LSR.S.NE",
+ LSR_S_CS: "LSR.S.CS",
+ LSR_S_CC: "LSR.S.CC",
+ LSR_S_MI: "LSR.S.MI",
+ LSR_S_PL: "LSR.S.PL",
+ LSR_S_VS: "LSR.S.VS",
+ LSR_S_VC: "LSR.S.VC",
+ LSR_S_HI: "LSR.S.HI",
+ LSR_S_LS: "LSR.S.LS",
+ LSR_S_GE: "LSR.S.GE",
+ LSR_S_LT: "LSR.S.LT",
+ LSR_S_GT: "LSR.S.GT",
+ LSR_S_LE: "LSR.S.LE",
+ LSR_S: "LSR.S",
+ LSR_S_ZZ: "LSR.S.ZZ",
+ MLA_EQ: "MLA.EQ",
+ MLA_NE: "MLA.NE",
+ MLA_CS: "MLA.CS",
+ MLA_CC: "MLA.CC",
+ MLA_MI: "MLA.MI",
+ MLA_PL: "MLA.PL",
+ MLA_VS: "MLA.VS",
+ MLA_VC: "MLA.VC",
+ MLA_HI: "MLA.HI",
+ MLA_LS: "MLA.LS",
+ MLA_GE: "MLA.GE",
+ MLA_LT: "MLA.LT",
+ MLA_GT: "MLA.GT",
+ MLA_LE: "MLA.LE",
+ MLA: "MLA",
+ MLA_ZZ: "MLA.ZZ",
+ MLA_S_EQ: "MLA.S.EQ",
+ MLA_S_NE: "MLA.S.NE",
+ MLA_S_CS: "MLA.S.CS",
+ MLA_S_CC: "MLA.S.CC",
+ MLA_S_MI: "MLA.S.MI",
+ MLA_S_PL: "MLA.S.PL",
+ MLA_S_VS: "MLA.S.VS",
+ MLA_S_VC: "MLA.S.VC",
+ MLA_S_HI: "MLA.S.HI",
+ MLA_S_LS: "MLA.S.LS",
+ MLA_S_GE: "MLA.S.GE",
+ MLA_S_LT: "MLA.S.LT",
+ MLA_S_GT: "MLA.S.GT",
+ MLA_S_LE: "MLA.S.LE",
+ MLA_S: "MLA.S",
+ MLA_S_ZZ: "MLA.S.ZZ",
+ MLS_EQ: "MLS.EQ",
+ MLS_NE: "MLS.NE",
+ MLS_CS: "MLS.CS",
+ MLS_CC: "MLS.CC",
+ MLS_MI: "MLS.MI",
+ MLS_PL: "MLS.PL",
+ MLS_VS: "MLS.VS",
+ MLS_VC: "MLS.VC",
+ MLS_HI: "MLS.HI",
+ MLS_LS: "MLS.LS",
+ MLS_GE: "MLS.GE",
+ MLS_LT: "MLS.LT",
+ MLS_GT: "MLS.GT",
+ MLS_LE: "MLS.LE",
+ MLS: "MLS",
+ MLS_ZZ: "MLS.ZZ",
+ MOV_EQ: "MOV.EQ",
+ MOV_NE: "MOV.NE",
+ MOV_CS: "MOV.CS",
+ MOV_CC: "MOV.CC",
+ MOV_MI: "MOV.MI",
+ MOV_PL: "MOV.PL",
+ MOV_VS: "MOV.VS",
+ MOV_VC: "MOV.VC",
+ MOV_HI: "MOV.HI",
+ MOV_LS: "MOV.LS",
+ MOV_GE: "MOV.GE",
+ MOV_LT: "MOV.LT",
+ MOV_GT: "MOV.GT",
+ MOV_LE: "MOV.LE",
+ MOV: "MOV",
+ MOV_ZZ: "MOV.ZZ",
+ MOV_S_EQ: "MOV.S.EQ",
+ MOV_S_NE: "MOV.S.NE",
+ MOV_S_CS: "MOV.S.CS",
+ MOV_S_CC: "MOV.S.CC",
+ MOV_S_MI: "MOV.S.MI",
+ MOV_S_PL: "MOV.S.PL",
+ MOV_S_VS: "MOV.S.VS",
+ MOV_S_VC: "MOV.S.VC",
+ MOV_S_HI: "MOV.S.HI",
+ MOV_S_LS: "MOV.S.LS",
+ MOV_S_GE: "MOV.S.GE",
+ MOV_S_LT: "MOV.S.LT",
+ MOV_S_GT: "MOV.S.GT",
+ MOV_S_LE: "MOV.S.LE",
+ MOV_S: "MOV.S",
+ MOV_S_ZZ: "MOV.S.ZZ",
+ MOVT_EQ: "MOVT.EQ",
+ MOVT_NE: "MOVT.NE",
+ MOVT_CS: "MOVT.CS",
+ MOVT_CC: "MOVT.CC",
+ MOVT_MI: "MOVT.MI",
+ MOVT_PL: "MOVT.PL",
+ MOVT_VS: "MOVT.VS",
+ MOVT_VC: "MOVT.VC",
+ MOVT_HI: "MOVT.HI",
+ MOVT_LS: "MOVT.LS",
+ MOVT_GE: "MOVT.GE",
+ MOVT_LT: "MOVT.LT",
+ MOVT_GT: "MOVT.GT",
+ MOVT_LE: "MOVT.LE",
+ MOVT: "MOVT",
+ MOVT_ZZ: "MOVT.ZZ",
+ MOVW_EQ: "MOVW.EQ",
+ MOVW_NE: "MOVW.NE",
+ MOVW_CS: "MOVW.CS",
+ MOVW_CC: "MOVW.CC",
+ MOVW_MI: "MOVW.MI",
+ MOVW_PL: "MOVW.PL",
+ MOVW_VS: "MOVW.VS",
+ MOVW_VC: "MOVW.VC",
+ MOVW_HI: "MOVW.HI",
+ MOVW_LS: "MOVW.LS",
+ MOVW_GE: "MOVW.GE",
+ MOVW_LT: "MOVW.LT",
+ MOVW_GT: "MOVW.GT",
+ MOVW_LE: "MOVW.LE",
+ MOVW: "MOVW",
+ MOVW_ZZ: "MOVW.ZZ",
+ MRS_EQ: "MRS.EQ",
+ MRS_NE: "MRS.NE",
+ MRS_CS: "MRS.CS",
+ MRS_CC: "MRS.CC",
+ MRS_MI: "MRS.MI",
+ MRS_PL: "MRS.PL",
+ MRS_VS: "MRS.VS",
+ MRS_VC: "MRS.VC",
+ MRS_HI: "MRS.HI",
+ MRS_LS: "MRS.LS",
+ MRS_GE: "MRS.GE",
+ MRS_LT: "MRS.LT",
+ MRS_GT: "MRS.GT",
+ MRS_LE: "MRS.LE",
+ MRS: "MRS",
+ MRS_ZZ: "MRS.ZZ",
+ MUL_EQ: "MUL.EQ",
+ MUL_NE: "MUL.NE",
+ MUL_CS: "MUL.CS",
+ MUL_CC: "MUL.CC",
+ MUL_MI: "MUL.MI",
+ MUL_PL: "MUL.PL",
+ MUL_VS: "MUL.VS",
+ MUL_VC: "MUL.VC",
+ MUL_HI: "MUL.HI",
+ MUL_LS: "MUL.LS",
+ MUL_GE: "MUL.GE",
+ MUL_LT: "MUL.LT",
+ MUL_GT: "MUL.GT",
+ MUL_LE: "MUL.LE",
+ MUL: "MUL",
+ MUL_ZZ: "MUL.ZZ",
+ MUL_S_EQ: "MUL.S.EQ",
+ MUL_S_NE: "MUL.S.NE",
+ MUL_S_CS: "MUL.S.CS",
+ MUL_S_CC: "MUL.S.CC",
+ MUL_S_MI: "MUL.S.MI",
+ MUL_S_PL: "MUL.S.PL",
+ MUL_S_VS: "MUL.S.VS",
+ MUL_S_VC: "MUL.S.VC",
+ MUL_S_HI: "MUL.S.HI",
+ MUL_S_LS: "MUL.S.LS",
+ MUL_S_GE: "MUL.S.GE",
+ MUL_S_LT: "MUL.S.LT",
+ MUL_S_GT: "MUL.S.GT",
+ MUL_S_LE: "MUL.S.LE",
+ MUL_S: "MUL.S",
+ MUL_S_ZZ: "MUL.S.ZZ",
+ MVN_EQ: "MVN.EQ",
+ MVN_NE: "MVN.NE",
+ MVN_CS: "MVN.CS",
+ MVN_CC: "MVN.CC",
+ MVN_MI: "MVN.MI",
+ MVN_PL: "MVN.PL",
+ MVN_VS: "MVN.VS",
+ MVN_VC: "MVN.VC",
+ MVN_HI: "MVN.HI",
+ MVN_LS: "MVN.LS",
+ MVN_GE: "MVN.GE",
+ MVN_LT: "MVN.LT",
+ MVN_GT: "MVN.GT",
+ MVN_LE: "MVN.LE",
+ MVN: "MVN",
+ MVN_ZZ: "MVN.ZZ",
+ MVN_S_EQ: "MVN.S.EQ",
+ MVN_S_NE: "MVN.S.NE",
+ MVN_S_CS: "MVN.S.CS",
+ MVN_S_CC: "MVN.S.CC",
+ MVN_S_MI: "MVN.S.MI",
+ MVN_S_PL: "MVN.S.PL",
+ MVN_S_VS: "MVN.S.VS",
+ MVN_S_VC: "MVN.S.VC",
+ MVN_S_HI: "MVN.S.HI",
+ MVN_S_LS: "MVN.S.LS",
+ MVN_S_GE: "MVN.S.GE",
+ MVN_S_LT: "MVN.S.LT",
+ MVN_S_GT: "MVN.S.GT",
+ MVN_S_LE: "MVN.S.LE",
+ MVN_S: "MVN.S",
+ MVN_S_ZZ: "MVN.S.ZZ",
+ NOP_EQ: "NOP.EQ",
+ NOP_NE: "NOP.NE",
+ NOP_CS: "NOP.CS",
+ NOP_CC: "NOP.CC",
+ NOP_MI: "NOP.MI",
+ NOP_PL: "NOP.PL",
+ NOP_VS: "NOP.VS",
+ NOP_VC: "NOP.VC",
+ NOP_HI: "NOP.HI",
+ NOP_LS: "NOP.LS",
+ NOP_GE: "NOP.GE",
+ NOP_LT: "NOP.LT",
+ NOP_GT: "NOP.GT",
+ NOP_LE: "NOP.LE",
+ NOP: "NOP",
+ NOP_ZZ: "NOP.ZZ",
+ ORR_EQ: "ORR.EQ",
+ ORR_NE: "ORR.NE",
+ ORR_CS: "ORR.CS",
+ ORR_CC: "ORR.CC",
+ ORR_MI: "ORR.MI",
+ ORR_PL: "ORR.PL",
+ ORR_VS: "ORR.VS",
+ ORR_VC: "ORR.VC",
+ ORR_HI: "ORR.HI",
+ ORR_LS: "ORR.LS",
+ ORR_GE: "ORR.GE",
+ ORR_LT: "ORR.LT",
+ ORR_GT: "ORR.GT",
+ ORR_LE: "ORR.LE",
+ ORR: "ORR",
+ ORR_ZZ: "ORR.ZZ",
+ ORR_S_EQ: "ORR.S.EQ",
+ ORR_S_NE: "ORR.S.NE",
+ ORR_S_CS: "ORR.S.CS",
+ ORR_S_CC: "ORR.S.CC",
+ ORR_S_MI: "ORR.S.MI",
+ ORR_S_PL: "ORR.S.PL",
+ ORR_S_VS: "ORR.S.VS",
+ ORR_S_VC: "ORR.S.VC",
+ ORR_S_HI: "ORR.S.HI",
+ ORR_S_LS: "ORR.S.LS",
+ ORR_S_GE: "ORR.S.GE",
+ ORR_S_LT: "ORR.S.LT",
+ ORR_S_GT: "ORR.S.GT",
+ ORR_S_LE: "ORR.S.LE",
+ ORR_S: "ORR.S",
+ ORR_S_ZZ: "ORR.S.ZZ",
+ PKHBT_EQ: "PKHBT.EQ",
+ PKHBT_NE: "PKHBT.NE",
+ PKHBT_CS: "PKHBT.CS",
+ PKHBT_CC: "PKHBT.CC",
+ PKHBT_MI: "PKHBT.MI",
+ PKHBT_PL: "PKHBT.PL",
+ PKHBT_VS: "PKHBT.VS",
+ PKHBT_VC: "PKHBT.VC",
+ PKHBT_HI: "PKHBT.HI",
+ PKHBT_LS: "PKHBT.LS",
+ PKHBT_GE: "PKHBT.GE",
+ PKHBT_LT: "PKHBT.LT",
+ PKHBT_GT: "PKHBT.GT",
+ PKHBT_LE: "PKHBT.LE",
+ PKHBT: "PKHBT",
+ PKHBT_ZZ: "PKHBT.ZZ",
+ PKHTB_EQ: "PKHTB.EQ",
+ PKHTB_NE: "PKHTB.NE",
+ PKHTB_CS: "PKHTB.CS",
+ PKHTB_CC: "PKHTB.CC",
+ PKHTB_MI: "PKHTB.MI",
+ PKHTB_PL: "PKHTB.PL",
+ PKHTB_VS: "PKHTB.VS",
+ PKHTB_VC: "PKHTB.VC",
+ PKHTB_HI: "PKHTB.HI",
+ PKHTB_LS: "PKHTB.LS",
+ PKHTB_GE: "PKHTB.GE",
+ PKHTB_LT: "PKHTB.LT",
+ PKHTB_GT: "PKHTB.GT",
+ PKHTB_LE: "PKHTB.LE",
+ PKHTB: "PKHTB",
+ PKHTB_ZZ: "PKHTB.ZZ",
+ PLD_W: "PLD.W",
+ PLD: "PLD",
+ PLI: "PLI",
+ POP_EQ: "POP.EQ",
+ POP_NE: "POP.NE",
+ POP_CS: "POP.CS",
+ POP_CC: "POP.CC",
+ POP_MI: "POP.MI",
+ POP_PL: "POP.PL",
+ POP_VS: "POP.VS",
+ POP_VC: "POP.VC",
+ POP_HI: "POP.HI",
+ POP_LS: "POP.LS",
+ POP_GE: "POP.GE",
+ POP_LT: "POP.LT",
+ POP_GT: "POP.GT",
+ POP_LE: "POP.LE",
+ POP: "POP",
+ POP_ZZ: "POP.ZZ",
+ PUSH_EQ: "PUSH.EQ",
+ PUSH_NE: "PUSH.NE",
+ PUSH_CS: "PUSH.CS",
+ PUSH_CC: "PUSH.CC",
+ PUSH_MI: "PUSH.MI",
+ PUSH_PL: "PUSH.PL",
+ PUSH_VS: "PUSH.VS",
+ PUSH_VC: "PUSH.VC",
+ PUSH_HI: "PUSH.HI",
+ PUSH_LS: "PUSH.LS",
+ PUSH_GE: "PUSH.GE",
+ PUSH_LT: "PUSH.LT",
+ PUSH_GT: "PUSH.GT",
+ PUSH_LE: "PUSH.LE",
+ PUSH: "PUSH",
+ PUSH_ZZ: "PUSH.ZZ",
+ QADD_EQ: "QADD.EQ",
+ QADD_NE: "QADD.NE",
+ QADD_CS: "QADD.CS",
+ QADD_CC: "QADD.CC",
+ QADD_MI: "QADD.MI",
+ QADD_PL: "QADD.PL",
+ QADD_VS: "QADD.VS",
+ QADD_VC: "QADD.VC",
+ QADD_HI: "QADD.HI",
+ QADD_LS: "QADD.LS",
+ QADD_GE: "QADD.GE",
+ QADD_LT: "QADD.LT",
+ QADD_GT: "QADD.GT",
+ QADD_LE: "QADD.LE",
+ QADD: "QADD",
+ QADD_ZZ: "QADD.ZZ",
+ QADD16_EQ: "QADD16.EQ",
+ QADD16_NE: "QADD16.NE",
+ QADD16_CS: "QADD16.CS",
+ QADD16_CC: "QADD16.CC",
+ QADD16_MI: "QADD16.MI",
+ QADD16_PL: "QADD16.PL",
+ QADD16_VS: "QADD16.VS",
+ QADD16_VC: "QADD16.VC",
+ QADD16_HI: "QADD16.HI",
+ QADD16_LS: "QADD16.LS",
+ QADD16_GE: "QADD16.GE",
+ QADD16_LT: "QADD16.LT",
+ QADD16_GT: "QADD16.GT",
+ QADD16_LE: "QADD16.LE",
+ QADD16: "QADD16",
+ QADD16_ZZ: "QADD16.ZZ",
+ QADD8_EQ: "QADD8.EQ",
+ QADD8_NE: "QADD8.NE",
+ QADD8_CS: "QADD8.CS",
+ QADD8_CC: "QADD8.CC",
+ QADD8_MI: "QADD8.MI",
+ QADD8_PL: "QADD8.PL",
+ QADD8_VS: "QADD8.VS",
+ QADD8_VC: "QADD8.VC",
+ QADD8_HI: "QADD8.HI",
+ QADD8_LS: "QADD8.LS",
+ QADD8_GE: "QADD8.GE",
+ QADD8_LT: "QADD8.LT",
+ QADD8_GT: "QADD8.GT",
+ QADD8_LE: "QADD8.LE",
+ QADD8: "QADD8",
+ QADD8_ZZ: "QADD8.ZZ",
+ QASX_EQ: "QASX.EQ",
+ QASX_NE: "QASX.NE",
+ QASX_CS: "QASX.CS",
+ QASX_CC: "QASX.CC",
+ QASX_MI: "QASX.MI",
+ QASX_PL: "QASX.PL",
+ QASX_VS: "QASX.VS",
+ QASX_VC: "QASX.VC",
+ QASX_HI: "QASX.HI",
+ QASX_LS: "QASX.LS",
+ QASX_GE: "QASX.GE",
+ QASX_LT: "QASX.LT",
+ QASX_GT: "QASX.GT",
+ QASX_LE: "QASX.LE",
+ QASX: "QASX",
+ QASX_ZZ: "QASX.ZZ",
+ QDADD_EQ: "QDADD.EQ",
+ QDADD_NE: "QDADD.NE",
+ QDADD_CS: "QDADD.CS",
+ QDADD_CC: "QDADD.CC",
+ QDADD_MI: "QDADD.MI",
+ QDADD_PL: "QDADD.PL",
+ QDADD_VS: "QDADD.VS",
+ QDADD_VC: "QDADD.VC",
+ QDADD_HI: "QDADD.HI",
+ QDADD_LS: "QDADD.LS",
+ QDADD_GE: "QDADD.GE",
+ QDADD_LT: "QDADD.LT",
+ QDADD_GT: "QDADD.GT",
+ QDADD_LE: "QDADD.LE",
+ QDADD: "QDADD",
+ QDADD_ZZ: "QDADD.ZZ",
+ QDSUB_EQ: "QDSUB.EQ",
+ QDSUB_NE: "QDSUB.NE",
+ QDSUB_CS: "QDSUB.CS",
+ QDSUB_CC: "QDSUB.CC",
+ QDSUB_MI: "QDSUB.MI",
+ QDSUB_PL: "QDSUB.PL",
+ QDSUB_VS: "QDSUB.VS",
+ QDSUB_VC: "QDSUB.VC",
+ QDSUB_HI: "QDSUB.HI",
+ QDSUB_LS: "QDSUB.LS",
+ QDSUB_GE: "QDSUB.GE",
+ QDSUB_LT: "QDSUB.LT",
+ QDSUB_GT: "QDSUB.GT",
+ QDSUB_LE: "QDSUB.LE",
+ QDSUB: "QDSUB",
+ QDSUB_ZZ: "QDSUB.ZZ",
+ QSAX_EQ: "QSAX.EQ",
+ QSAX_NE: "QSAX.NE",
+ QSAX_CS: "QSAX.CS",
+ QSAX_CC: "QSAX.CC",
+ QSAX_MI: "QSAX.MI",
+ QSAX_PL: "QSAX.PL",
+ QSAX_VS: "QSAX.VS",
+ QSAX_VC: "QSAX.VC",
+ QSAX_HI: "QSAX.HI",
+ QSAX_LS: "QSAX.LS",
+ QSAX_GE: "QSAX.GE",
+ QSAX_LT: "QSAX.LT",
+ QSAX_GT: "QSAX.GT",
+ QSAX_LE: "QSAX.LE",
+ QSAX: "QSAX",
+ QSAX_ZZ: "QSAX.ZZ",
+ QSUB_EQ: "QSUB.EQ",
+ QSUB_NE: "QSUB.NE",
+ QSUB_CS: "QSUB.CS",
+ QSUB_CC: "QSUB.CC",
+ QSUB_MI: "QSUB.MI",
+ QSUB_PL: "QSUB.PL",
+ QSUB_VS: "QSUB.VS",
+ QSUB_VC: "QSUB.VC",
+ QSUB_HI: "QSUB.HI",
+ QSUB_LS: "QSUB.LS",
+ QSUB_GE: "QSUB.GE",
+ QSUB_LT: "QSUB.LT",
+ QSUB_GT: "QSUB.GT",
+ QSUB_LE: "QSUB.LE",
+ QSUB: "QSUB",
+ QSUB_ZZ: "QSUB.ZZ",
+ QSUB16_EQ: "QSUB16.EQ",
+ QSUB16_NE: "QSUB16.NE",
+ QSUB16_CS: "QSUB16.CS",
+ QSUB16_CC: "QSUB16.CC",
+ QSUB16_MI: "QSUB16.MI",
+ QSUB16_PL: "QSUB16.PL",
+ QSUB16_VS: "QSUB16.VS",
+ QSUB16_VC: "QSUB16.VC",
+ QSUB16_HI: "QSUB16.HI",
+ QSUB16_LS: "QSUB16.LS",
+ QSUB16_GE: "QSUB16.GE",
+ QSUB16_LT: "QSUB16.LT",
+ QSUB16_GT: "QSUB16.GT",
+ QSUB16_LE: "QSUB16.LE",
+ QSUB16: "QSUB16",
+ QSUB16_ZZ: "QSUB16.ZZ",
+ QSUB8_EQ: "QSUB8.EQ",
+ QSUB8_NE: "QSUB8.NE",
+ QSUB8_CS: "QSUB8.CS",
+ QSUB8_CC: "QSUB8.CC",
+ QSUB8_MI: "QSUB8.MI",
+ QSUB8_PL: "QSUB8.PL",
+ QSUB8_VS: "QSUB8.VS",
+ QSUB8_VC: "QSUB8.VC",
+ QSUB8_HI: "QSUB8.HI",
+ QSUB8_LS: "QSUB8.LS",
+ QSUB8_GE: "QSUB8.GE",
+ QSUB8_LT: "QSUB8.LT",
+ QSUB8_GT: "QSUB8.GT",
+ QSUB8_LE: "QSUB8.LE",
+ QSUB8: "QSUB8",
+ QSUB8_ZZ: "QSUB8.ZZ",
+ RBIT_EQ: "RBIT.EQ",
+ RBIT_NE: "RBIT.NE",
+ RBIT_CS: "RBIT.CS",
+ RBIT_CC: "RBIT.CC",
+ RBIT_MI: "RBIT.MI",
+ RBIT_PL: "RBIT.PL",
+ RBIT_VS: "RBIT.VS",
+ RBIT_VC: "RBIT.VC",
+ RBIT_HI: "RBIT.HI",
+ RBIT_LS: "RBIT.LS",
+ RBIT_GE: "RBIT.GE",
+ RBIT_LT: "RBIT.LT",
+ RBIT_GT: "RBIT.GT",
+ RBIT_LE: "RBIT.LE",
+ RBIT: "RBIT",
+ RBIT_ZZ: "RBIT.ZZ",
+ REV_EQ: "REV.EQ",
+ REV_NE: "REV.NE",
+ REV_CS: "REV.CS",
+ REV_CC: "REV.CC",
+ REV_MI: "REV.MI",
+ REV_PL: "REV.PL",
+ REV_VS: "REV.VS",
+ REV_VC: "REV.VC",
+ REV_HI: "REV.HI",
+ REV_LS: "REV.LS",
+ REV_GE: "REV.GE",
+ REV_LT: "REV.LT",
+ REV_GT: "REV.GT",
+ REV_LE: "REV.LE",
+ REV: "REV",
+ REV_ZZ: "REV.ZZ",
+ REV16_EQ: "REV16.EQ",
+ REV16_NE: "REV16.NE",
+ REV16_CS: "REV16.CS",
+ REV16_CC: "REV16.CC",
+ REV16_MI: "REV16.MI",
+ REV16_PL: "REV16.PL",
+ REV16_VS: "REV16.VS",
+ REV16_VC: "REV16.VC",
+ REV16_HI: "REV16.HI",
+ REV16_LS: "REV16.LS",
+ REV16_GE: "REV16.GE",
+ REV16_LT: "REV16.LT",
+ REV16_GT: "REV16.GT",
+ REV16_LE: "REV16.LE",
+ REV16: "REV16",
+ REV16_ZZ: "REV16.ZZ",
+ REVSH_EQ: "REVSH.EQ",
+ REVSH_NE: "REVSH.NE",
+ REVSH_CS: "REVSH.CS",
+ REVSH_CC: "REVSH.CC",
+ REVSH_MI: "REVSH.MI",
+ REVSH_PL: "REVSH.PL",
+ REVSH_VS: "REVSH.VS",
+ REVSH_VC: "REVSH.VC",
+ REVSH_HI: "REVSH.HI",
+ REVSH_LS: "REVSH.LS",
+ REVSH_GE: "REVSH.GE",
+ REVSH_LT: "REVSH.LT",
+ REVSH_GT: "REVSH.GT",
+ REVSH_LE: "REVSH.LE",
+ REVSH: "REVSH",
+ REVSH_ZZ: "REVSH.ZZ",
+ ROR_EQ: "ROR.EQ",
+ ROR_NE: "ROR.NE",
+ ROR_CS: "ROR.CS",
+ ROR_CC: "ROR.CC",
+ ROR_MI: "ROR.MI",
+ ROR_PL: "ROR.PL",
+ ROR_VS: "ROR.VS",
+ ROR_VC: "ROR.VC",
+ ROR_HI: "ROR.HI",
+ ROR_LS: "ROR.LS",
+ ROR_GE: "ROR.GE",
+ ROR_LT: "ROR.LT",
+ ROR_GT: "ROR.GT",
+ ROR_LE: "ROR.LE",
+ ROR: "ROR",
+ ROR_ZZ: "ROR.ZZ",
+ ROR_S_EQ: "ROR.S.EQ",
+ ROR_S_NE: "ROR.S.NE",
+ ROR_S_CS: "ROR.S.CS",
+ ROR_S_CC: "ROR.S.CC",
+ ROR_S_MI: "ROR.S.MI",
+ ROR_S_PL: "ROR.S.PL",
+ ROR_S_VS: "ROR.S.VS",
+ ROR_S_VC: "ROR.S.VC",
+ ROR_S_HI: "ROR.S.HI",
+ ROR_S_LS: "ROR.S.LS",
+ ROR_S_GE: "ROR.S.GE",
+ ROR_S_LT: "ROR.S.LT",
+ ROR_S_GT: "ROR.S.GT",
+ ROR_S_LE: "ROR.S.LE",
+ ROR_S: "ROR.S",
+ ROR_S_ZZ: "ROR.S.ZZ",
+ RRX_EQ: "RRX.EQ",
+ RRX_NE: "RRX.NE",
+ RRX_CS: "RRX.CS",
+ RRX_CC: "RRX.CC",
+ RRX_MI: "RRX.MI",
+ RRX_PL: "RRX.PL",
+ RRX_VS: "RRX.VS",
+ RRX_VC: "RRX.VC",
+ RRX_HI: "RRX.HI",
+ RRX_LS: "RRX.LS",
+ RRX_GE: "RRX.GE",
+ RRX_LT: "RRX.LT",
+ RRX_GT: "RRX.GT",
+ RRX_LE: "RRX.LE",
+ RRX: "RRX",
+ RRX_ZZ: "RRX.ZZ",
+ RRX_S_EQ: "RRX.S.EQ",
+ RRX_S_NE: "RRX.S.NE",
+ RRX_S_CS: "RRX.S.CS",
+ RRX_S_CC: "RRX.S.CC",
+ RRX_S_MI: "RRX.S.MI",
+ RRX_S_PL: "RRX.S.PL",
+ RRX_S_VS: "RRX.S.VS",
+ RRX_S_VC: "RRX.S.VC",
+ RRX_S_HI: "RRX.S.HI",
+ RRX_S_LS: "RRX.S.LS",
+ RRX_S_GE: "RRX.S.GE",
+ RRX_S_LT: "RRX.S.LT",
+ RRX_S_GT: "RRX.S.GT",
+ RRX_S_LE: "RRX.S.LE",
+ RRX_S: "RRX.S",
+ RRX_S_ZZ: "RRX.S.ZZ",
+ RSB_EQ: "RSB.EQ",
+ RSB_NE: "RSB.NE",
+ RSB_CS: "RSB.CS",
+ RSB_CC: "RSB.CC",
+ RSB_MI: "RSB.MI",
+ RSB_PL: "RSB.PL",
+ RSB_VS: "RSB.VS",
+ RSB_VC: "RSB.VC",
+ RSB_HI: "RSB.HI",
+ RSB_LS: "RSB.LS",
+ RSB_GE: "RSB.GE",
+ RSB_LT: "RSB.LT",
+ RSB_GT: "RSB.GT",
+ RSB_LE: "RSB.LE",
+ RSB: "RSB",
+ RSB_ZZ: "RSB.ZZ",
+ RSB_S_EQ: "RSB.S.EQ",
+ RSB_S_NE: "RSB.S.NE",
+ RSB_S_CS: "RSB.S.CS",
+ RSB_S_CC: "RSB.S.CC",
+ RSB_S_MI: "RSB.S.MI",
+ RSB_S_PL: "RSB.S.PL",
+ RSB_S_VS: "RSB.S.VS",
+ RSB_S_VC: "RSB.S.VC",
+ RSB_S_HI: "RSB.S.HI",
+ RSB_S_LS: "RSB.S.LS",
+ RSB_S_GE: "RSB.S.GE",
+ RSB_S_LT: "RSB.S.LT",
+ RSB_S_GT: "RSB.S.GT",
+ RSB_S_LE: "RSB.S.LE",
+ RSB_S: "RSB.S",
+ RSB_S_ZZ: "RSB.S.ZZ",
+ RSC_EQ: "RSC.EQ",
+ RSC_NE: "RSC.NE",
+ RSC_CS: "RSC.CS",
+ RSC_CC: "RSC.CC",
+ RSC_MI: "RSC.MI",
+ RSC_PL: "RSC.PL",
+ RSC_VS: "RSC.VS",
+ RSC_VC: "RSC.VC",
+ RSC_HI: "RSC.HI",
+ RSC_LS: "RSC.LS",
+ RSC_GE: "RSC.GE",
+ RSC_LT: "RSC.LT",
+ RSC_GT: "RSC.GT",
+ RSC_LE: "RSC.LE",
+ RSC: "RSC",
+ RSC_ZZ: "RSC.ZZ",
+ RSC_S_EQ: "RSC.S.EQ",
+ RSC_S_NE: "RSC.S.NE",
+ RSC_S_CS: "RSC.S.CS",
+ RSC_S_CC: "RSC.S.CC",
+ RSC_S_MI: "RSC.S.MI",
+ RSC_S_PL: "RSC.S.PL",
+ RSC_S_VS: "RSC.S.VS",
+ RSC_S_VC: "RSC.S.VC",
+ RSC_S_HI: "RSC.S.HI",
+ RSC_S_LS: "RSC.S.LS",
+ RSC_S_GE: "RSC.S.GE",
+ RSC_S_LT: "RSC.S.LT",
+ RSC_S_GT: "RSC.S.GT",
+ RSC_S_LE: "RSC.S.LE",
+ RSC_S: "RSC.S",
+ RSC_S_ZZ: "RSC.S.ZZ",
+ SADD16_EQ: "SADD16.EQ",
+ SADD16_NE: "SADD16.NE",
+ SADD16_CS: "SADD16.CS",
+ SADD16_CC: "SADD16.CC",
+ SADD16_MI: "SADD16.MI",
+ SADD16_PL: "SADD16.PL",
+ SADD16_VS: "SADD16.VS",
+ SADD16_VC: "SADD16.VC",
+ SADD16_HI: "SADD16.HI",
+ SADD16_LS: "SADD16.LS",
+ SADD16_GE: "SADD16.GE",
+ SADD16_LT: "SADD16.LT",
+ SADD16_GT: "SADD16.GT",
+ SADD16_LE: "SADD16.LE",
+ SADD16: "SADD16",
+ SADD16_ZZ: "SADD16.ZZ",
+ SADD8_EQ: "SADD8.EQ",
+ SADD8_NE: "SADD8.NE",
+ SADD8_CS: "SADD8.CS",
+ SADD8_CC: "SADD8.CC",
+ SADD8_MI: "SADD8.MI",
+ SADD8_PL: "SADD8.PL",
+ SADD8_VS: "SADD8.VS",
+ SADD8_VC: "SADD8.VC",
+ SADD8_HI: "SADD8.HI",
+ SADD8_LS: "SADD8.LS",
+ SADD8_GE: "SADD8.GE",
+ SADD8_LT: "SADD8.LT",
+ SADD8_GT: "SADD8.GT",
+ SADD8_LE: "SADD8.LE",
+ SADD8: "SADD8",
+ SADD8_ZZ: "SADD8.ZZ",
+ SASX_EQ: "SASX.EQ",
+ SASX_NE: "SASX.NE",
+ SASX_CS: "SASX.CS",
+ SASX_CC: "SASX.CC",
+ SASX_MI: "SASX.MI",
+ SASX_PL: "SASX.PL",
+ SASX_VS: "SASX.VS",
+ SASX_VC: "SASX.VC",
+ SASX_HI: "SASX.HI",
+ SASX_LS: "SASX.LS",
+ SASX_GE: "SASX.GE",
+ SASX_LT: "SASX.LT",
+ SASX_GT: "SASX.GT",
+ SASX_LE: "SASX.LE",
+ SASX: "SASX",
+ SASX_ZZ: "SASX.ZZ",
+ SBC_EQ: "SBC.EQ",
+ SBC_NE: "SBC.NE",
+ SBC_CS: "SBC.CS",
+ SBC_CC: "SBC.CC",
+ SBC_MI: "SBC.MI",
+ SBC_PL: "SBC.PL",
+ SBC_VS: "SBC.VS",
+ SBC_VC: "SBC.VC",
+ SBC_HI: "SBC.HI",
+ SBC_LS: "SBC.LS",
+ SBC_GE: "SBC.GE",
+ SBC_LT: "SBC.LT",
+ SBC_GT: "SBC.GT",
+ SBC_LE: "SBC.LE",
+ SBC: "SBC",
+ SBC_ZZ: "SBC.ZZ",
+ SBC_S_EQ: "SBC.S.EQ",
+ SBC_S_NE: "SBC.S.NE",
+ SBC_S_CS: "SBC.S.CS",
+ SBC_S_CC: "SBC.S.CC",
+ SBC_S_MI: "SBC.S.MI",
+ SBC_S_PL: "SBC.S.PL",
+ SBC_S_VS: "SBC.S.VS",
+ SBC_S_VC: "SBC.S.VC",
+ SBC_S_HI: "SBC.S.HI",
+ SBC_S_LS: "SBC.S.LS",
+ SBC_S_GE: "SBC.S.GE",
+ SBC_S_LT: "SBC.S.LT",
+ SBC_S_GT: "SBC.S.GT",
+ SBC_S_LE: "SBC.S.LE",
+ SBC_S: "SBC.S",
+ SBC_S_ZZ: "SBC.S.ZZ",
+ SBFX_EQ: "SBFX.EQ",
+ SBFX_NE: "SBFX.NE",
+ SBFX_CS: "SBFX.CS",
+ SBFX_CC: "SBFX.CC",
+ SBFX_MI: "SBFX.MI",
+ SBFX_PL: "SBFX.PL",
+ SBFX_VS: "SBFX.VS",
+ SBFX_VC: "SBFX.VC",
+ SBFX_HI: "SBFX.HI",
+ SBFX_LS: "SBFX.LS",
+ SBFX_GE: "SBFX.GE",
+ SBFX_LT: "SBFX.LT",
+ SBFX_GT: "SBFX.GT",
+ SBFX_LE: "SBFX.LE",
+ SBFX: "SBFX",
+ SBFX_ZZ: "SBFX.ZZ",
+ SEL_EQ: "SEL.EQ",
+ SEL_NE: "SEL.NE",
+ SEL_CS: "SEL.CS",
+ SEL_CC: "SEL.CC",
+ SEL_MI: "SEL.MI",
+ SEL_PL: "SEL.PL",
+ SEL_VS: "SEL.VS",
+ SEL_VC: "SEL.VC",
+ SEL_HI: "SEL.HI",
+ SEL_LS: "SEL.LS",
+ SEL_GE: "SEL.GE",
+ SEL_LT: "SEL.LT",
+ SEL_GT: "SEL.GT",
+ SEL_LE: "SEL.LE",
+ SEL: "SEL",
+ SEL_ZZ: "SEL.ZZ",
+ SETEND: "SETEND",
+ SEV_EQ: "SEV.EQ",
+ SEV_NE: "SEV.NE",
+ SEV_CS: "SEV.CS",
+ SEV_CC: "SEV.CC",
+ SEV_MI: "SEV.MI",
+ SEV_PL: "SEV.PL",
+ SEV_VS: "SEV.VS",
+ SEV_VC: "SEV.VC",
+ SEV_HI: "SEV.HI",
+ SEV_LS: "SEV.LS",
+ SEV_GE: "SEV.GE",
+ SEV_LT: "SEV.LT",
+ SEV_GT: "SEV.GT",
+ SEV_LE: "SEV.LE",
+ SEV: "SEV",
+ SEV_ZZ: "SEV.ZZ",
+ SHADD16_EQ: "SHADD16.EQ",
+ SHADD16_NE: "SHADD16.NE",
+ SHADD16_CS: "SHADD16.CS",
+ SHADD16_CC: "SHADD16.CC",
+ SHADD16_MI: "SHADD16.MI",
+ SHADD16_PL: "SHADD16.PL",
+ SHADD16_VS: "SHADD16.VS",
+ SHADD16_VC: "SHADD16.VC",
+ SHADD16_HI: "SHADD16.HI",
+ SHADD16_LS: "SHADD16.LS",
+ SHADD16_GE: "SHADD16.GE",
+ SHADD16_LT: "SHADD16.LT",
+ SHADD16_GT: "SHADD16.GT",
+ SHADD16_LE: "SHADD16.LE",
+ SHADD16: "SHADD16",
+ SHADD16_ZZ: "SHADD16.ZZ",
+ SHADD8_EQ: "SHADD8.EQ",
+ SHADD8_NE: "SHADD8.NE",
+ SHADD8_CS: "SHADD8.CS",
+ SHADD8_CC: "SHADD8.CC",
+ SHADD8_MI: "SHADD8.MI",
+ SHADD8_PL: "SHADD8.PL",
+ SHADD8_VS: "SHADD8.VS",
+ SHADD8_VC: "SHADD8.VC",
+ SHADD8_HI: "SHADD8.HI",
+ SHADD8_LS: "SHADD8.LS",
+ SHADD8_GE: "SHADD8.GE",
+ SHADD8_LT: "SHADD8.LT",
+ SHADD8_GT: "SHADD8.GT",
+ SHADD8_LE: "SHADD8.LE",
+ SHADD8: "SHADD8",
+ SHADD8_ZZ: "SHADD8.ZZ",
+ SHASX_EQ: "SHASX.EQ",
+ SHASX_NE: "SHASX.NE",
+ SHASX_CS: "SHASX.CS",
+ SHASX_CC: "SHASX.CC",
+ SHASX_MI: "SHASX.MI",
+ SHASX_PL: "SHASX.PL",
+ SHASX_VS: "SHASX.VS",
+ SHASX_VC: "SHASX.VC",
+ SHASX_HI: "SHASX.HI",
+ SHASX_LS: "SHASX.LS",
+ SHASX_GE: "SHASX.GE",
+ SHASX_LT: "SHASX.LT",
+ SHASX_GT: "SHASX.GT",
+ SHASX_LE: "SHASX.LE",
+ SHASX: "SHASX",
+ SHASX_ZZ: "SHASX.ZZ",
+ SHSAX_EQ: "SHSAX.EQ",
+ SHSAX_NE: "SHSAX.NE",
+ SHSAX_CS: "SHSAX.CS",
+ SHSAX_CC: "SHSAX.CC",
+ SHSAX_MI: "SHSAX.MI",
+ SHSAX_PL: "SHSAX.PL",
+ SHSAX_VS: "SHSAX.VS",
+ SHSAX_VC: "SHSAX.VC",
+ SHSAX_HI: "SHSAX.HI",
+ SHSAX_LS: "SHSAX.LS",
+ SHSAX_GE: "SHSAX.GE",
+ SHSAX_LT: "SHSAX.LT",
+ SHSAX_GT: "SHSAX.GT",
+ SHSAX_LE: "SHSAX.LE",
+ SHSAX: "SHSAX",
+ SHSAX_ZZ: "SHSAX.ZZ",
+ SHSUB16_EQ: "SHSUB16.EQ",
+ SHSUB16_NE: "SHSUB16.NE",
+ SHSUB16_CS: "SHSUB16.CS",
+ SHSUB16_CC: "SHSUB16.CC",
+ SHSUB16_MI: "SHSUB16.MI",
+ SHSUB16_PL: "SHSUB16.PL",
+ SHSUB16_VS: "SHSUB16.VS",
+ SHSUB16_VC: "SHSUB16.VC",
+ SHSUB16_HI: "SHSUB16.HI",
+ SHSUB16_LS: "SHSUB16.LS",
+ SHSUB16_GE: "SHSUB16.GE",
+ SHSUB16_LT: "SHSUB16.LT",
+ SHSUB16_GT: "SHSUB16.GT",
+ SHSUB16_LE: "SHSUB16.LE",
+ SHSUB16: "SHSUB16",
+ SHSUB16_ZZ: "SHSUB16.ZZ",
+ SHSUB8_EQ: "SHSUB8.EQ",
+ SHSUB8_NE: "SHSUB8.NE",
+ SHSUB8_CS: "SHSUB8.CS",
+ SHSUB8_CC: "SHSUB8.CC",
+ SHSUB8_MI: "SHSUB8.MI",
+ SHSUB8_PL: "SHSUB8.PL",
+ SHSUB8_VS: "SHSUB8.VS",
+ SHSUB8_VC: "SHSUB8.VC",
+ SHSUB8_HI: "SHSUB8.HI",
+ SHSUB8_LS: "SHSUB8.LS",
+ SHSUB8_GE: "SHSUB8.GE",
+ SHSUB8_LT: "SHSUB8.LT",
+ SHSUB8_GT: "SHSUB8.GT",
+ SHSUB8_LE: "SHSUB8.LE",
+ SHSUB8: "SHSUB8",
+ SHSUB8_ZZ: "SHSUB8.ZZ",
+ SMLABB_EQ: "SMLABB.EQ",
+ SMLABB_NE: "SMLABB.NE",
+ SMLABB_CS: "SMLABB.CS",
+ SMLABB_CC: "SMLABB.CC",
+ SMLABB_MI: "SMLABB.MI",
+ SMLABB_PL: "SMLABB.PL",
+ SMLABB_VS: "SMLABB.VS",
+ SMLABB_VC: "SMLABB.VC",
+ SMLABB_HI: "SMLABB.HI",
+ SMLABB_LS: "SMLABB.LS",
+ SMLABB_GE: "SMLABB.GE",
+ SMLABB_LT: "SMLABB.LT",
+ SMLABB_GT: "SMLABB.GT",
+ SMLABB_LE: "SMLABB.LE",
+ SMLABB: "SMLABB",
+ SMLABB_ZZ: "SMLABB.ZZ",
+ SMLABT_EQ: "SMLABT.EQ",
+ SMLABT_NE: "SMLABT.NE",
+ SMLABT_CS: "SMLABT.CS",
+ SMLABT_CC: "SMLABT.CC",
+ SMLABT_MI: "SMLABT.MI",
+ SMLABT_PL: "SMLABT.PL",
+ SMLABT_VS: "SMLABT.VS",
+ SMLABT_VC: "SMLABT.VC",
+ SMLABT_HI: "SMLABT.HI",
+ SMLABT_LS: "SMLABT.LS",
+ SMLABT_GE: "SMLABT.GE",
+ SMLABT_LT: "SMLABT.LT",
+ SMLABT_GT: "SMLABT.GT",
+ SMLABT_LE: "SMLABT.LE",
+ SMLABT: "SMLABT",
+ SMLABT_ZZ: "SMLABT.ZZ",
+ SMLATB_EQ: "SMLATB.EQ",
+ SMLATB_NE: "SMLATB.NE",
+ SMLATB_CS: "SMLATB.CS",
+ SMLATB_CC: "SMLATB.CC",
+ SMLATB_MI: "SMLATB.MI",
+ SMLATB_PL: "SMLATB.PL",
+ SMLATB_VS: "SMLATB.VS",
+ SMLATB_VC: "SMLATB.VC",
+ SMLATB_HI: "SMLATB.HI",
+ SMLATB_LS: "SMLATB.LS",
+ SMLATB_GE: "SMLATB.GE",
+ SMLATB_LT: "SMLATB.LT",
+ SMLATB_GT: "SMLATB.GT",
+ SMLATB_LE: "SMLATB.LE",
+ SMLATB: "SMLATB",
+ SMLATB_ZZ: "SMLATB.ZZ",
+ SMLATT_EQ: "SMLATT.EQ",
+ SMLATT_NE: "SMLATT.NE",
+ SMLATT_CS: "SMLATT.CS",
+ SMLATT_CC: "SMLATT.CC",
+ SMLATT_MI: "SMLATT.MI",
+ SMLATT_PL: "SMLATT.PL",
+ SMLATT_VS: "SMLATT.VS",
+ SMLATT_VC: "SMLATT.VC",
+ SMLATT_HI: "SMLATT.HI",
+ SMLATT_LS: "SMLATT.LS",
+ SMLATT_GE: "SMLATT.GE",
+ SMLATT_LT: "SMLATT.LT",
+ SMLATT_GT: "SMLATT.GT",
+ SMLATT_LE: "SMLATT.LE",
+ SMLATT: "SMLATT",
+ SMLATT_ZZ: "SMLATT.ZZ",
+ SMLAD_EQ: "SMLAD.EQ",
+ SMLAD_NE: "SMLAD.NE",
+ SMLAD_CS: "SMLAD.CS",
+ SMLAD_CC: "SMLAD.CC",
+ SMLAD_MI: "SMLAD.MI",
+ SMLAD_PL: "SMLAD.PL",
+ SMLAD_VS: "SMLAD.VS",
+ SMLAD_VC: "SMLAD.VC",
+ SMLAD_HI: "SMLAD.HI",
+ SMLAD_LS: "SMLAD.LS",
+ SMLAD_GE: "SMLAD.GE",
+ SMLAD_LT: "SMLAD.LT",
+ SMLAD_GT: "SMLAD.GT",
+ SMLAD_LE: "SMLAD.LE",
+ SMLAD: "SMLAD",
+ SMLAD_ZZ: "SMLAD.ZZ",
+ SMLAD_X_EQ: "SMLAD.X.EQ",
+ SMLAD_X_NE: "SMLAD.X.NE",
+ SMLAD_X_CS: "SMLAD.X.CS",
+ SMLAD_X_CC: "SMLAD.X.CC",
+ SMLAD_X_MI: "SMLAD.X.MI",
+ SMLAD_X_PL: "SMLAD.X.PL",
+ SMLAD_X_VS: "SMLAD.X.VS",
+ SMLAD_X_VC: "SMLAD.X.VC",
+ SMLAD_X_HI: "SMLAD.X.HI",
+ SMLAD_X_LS: "SMLAD.X.LS",
+ SMLAD_X_GE: "SMLAD.X.GE",
+ SMLAD_X_LT: "SMLAD.X.LT",
+ SMLAD_X_GT: "SMLAD.X.GT",
+ SMLAD_X_LE: "SMLAD.X.LE",
+ SMLAD_X: "SMLAD.X",
+ SMLAD_X_ZZ: "SMLAD.X.ZZ",
+ SMLAL_EQ: "SMLAL.EQ",
+ SMLAL_NE: "SMLAL.NE",
+ SMLAL_CS: "SMLAL.CS",
+ SMLAL_CC: "SMLAL.CC",
+ SMLAL_MI: "SMLAL.MI",
+ SMLAL_PL: "SMLAL.PL",
+ SMLAL_VS: "SMLAL.VS",
+ SMLAL_VC: "SMLAL.VC",
+ SMLAL_HI: "SMLAL.HI",
+ SMLAL_LS: "SMLAL.LS",
+ SMLAL_GE: "SMLAL.GE",
+ SMLAL_LT: "SMLAL.LT",
+ SMLAL_GT: "SMLAL.GT",
+ SMLAL_LE: "SMLAL.LE",
+ SMLAL: "SMLAL",
+ SMLAL_ZZ: "SMLAL.ZZ",
+ SMLAL_S_EQ: "SMLAL.S.EQ",
+ SMLAL_S_NE: "SMLAL.S.NE",
+ SMLAL_S_CS: "SMLAL.S.CS",
+ SMLAL_S_CC: "SMLAL.S.CC",
+ SMLAL_S_MI: "SMLAL.S.MI",
+ SMLAL_S_PL: "SMLAL.S.PL",
+ SMLAL_S_VS: "SMLAL.S.VS",
+ SMLAL_S_VC: "SMLAL.S.VC",
+ SMLAL_S_HI: "SMLAL.S.HI",
+ SMLAL_S_LS: "SMLAL.S.LS",
+ SMLAL_S_GE: "SMLAL.S.GE",
+ SMLAL_S_LT: "SMLAL.S.LT",
+ SMLAL_S_GT: "SMLAL.S.GT",
+ SMLAL_S_LE: "SMLAL.S.LE",
+ SMLAL_S: "SMLAL.S",
+ SMLAL_S_ZZ: "SMLAL.S.ZZ",
+ SMLALBB_EQ: "SMLALBB.EQ",
+ SMLALBB_NE: "SMLALBB.NE",
+ SMLALBB_CS: "SMLALBB.CS",
+ SMLALBB_CC: "SMLALBB.CC",
+ SMLALBB_MI: "SMLALBB.MI",
+ SMLALBB_PL: "SMLALBB.PL",
+ SMLALBB_VS: "SMLALBB.VS",
+ SMLALBB_VC: "SMLALBB.VC",
+ SMLALBB_HI: "SMLALBB.HI",
+ SMLALBB_LS: "SMLALBB.LS",
+ SMLALBB_GE: "SMLALBB.GE",
+ SMLALBB_LT: "SMLALBB.LT",
+ SMLALBB_GT: "SMLALBB.GT",
+ SMLALBB_LE: "SMLALBB.LE",
+ SMLALBB: "SMLALBB",
+ SMLALBB_ZZ: "SMLALBB.ZZ",
+ SMLALBT_EQ: "SMLALBT.EQ",
+ SMLALBT_NE: "SMLALBT.NE",
+ SMLALBT_CS: "SMLALBT.CS",
+ SMLALBT_CC: "SMLALBT.CC",
+ SMLALBT_MI: "SMLALBT.MI",
+ SMLALBT_PL: "SMLALBT.PL",
+ SMLALBT_VS: "SMLALBT.VS",
+ SMLALBT_VC: "SMLALBT.VC",
+ SMLALBT_HI: "SMLALBT.HI",
+ SMLALBT_LS: "SMLALBT.LS",
+ SMLALBT_GE: "SMLALBT.GE",
+ SMLALBT_LT: "SMLALBT.LT",
+ SMLALBT_GT: "SMLALBT.GT",
+ SMLALBT_LE: "SMLALBT.LE",
+ SMLALBT: "SMLALBT",
+ SMLALBT_ZZ: "SMLALBT.ZZ",
+ SMLALTB_EQ: "SMLALTB.EQ",
+ SMLALTB_NE: "SMLALTB.NE",
+ SMLALTB_CS: "SMLALTB.CS",
+ SMLALTB_CC: "SMLALTB.CC",
+ SMLALTB_MI: "SMLALTB.MI",
+ SMLALTB_PL: "SMLALTB.PL",
+ SMLALTB_VS: "SMLALTB.VS",
+ SMLALTB_VC: "SMLALTB.VC",
+ SMLALTB_HI: "SMLALTB.HI",
+ SMLALTB_LS: "SMLALTB.LS",
+ SMLALTB_GE: "SMLALTB.GE",
+ SMLALTB_LT: "SMLALTB.LT",
+ SMLALTB_GT: "SMLALTB.GT",
+ SMLALTB_LE: "SMLALTB.LE",
+ SMLALTB: "SMLALTB",
+ SMLALTB_ZZ: "SMLALTB.ZZ",
+ SMLALTT_EQ: "SMLALTT.EQ",
+ SMLALTT_NE: "SMLALTT.NE",
+ SMLALTT_CS: "SMLALTT.CS",
+ SMLALTT_CC: "SMLALTT.CC",
+ SMLALTT_MI: "SMLALTT.MI",
+ SMLALTT_PL: "SMLALTT.PL",
+ SMLALTT_VS: "SMLALTT.VS",
+ SMLALTT_VC: "SMLALTT.VC",
+ SMLALTT_HI: "SMLALTT.HI",
+ SMLALTT_LS: "SMLALTT.LS",
+ SMLALTT_GE: "SMLALTT.GE",
+ SMLALTT_LT: "SMLALTT.LT",
+ SMLALTT_GT: "SMLALTT.GT",
+ SMLALTT_LE: "SMLALTT.LE",
+ SMLALTT: "SMLALTT",
+ SMLALTT_ZZ: "SMLALTT.ZZ",
+ SMLALD_EQ: "SMLALD.EQ",
+ SMLALD_NE: "SMLALD.NE",
+ SMLALD_CS: "SMLALD.CS",
+ SMLALD_CC: "SMLALD.CC",
+ SMLALD_MI: "SMLALD.MI",
+ SMLALD_PL: "SMLALD.PL",
+ SMLALD_VS: "SMLALD.VS",
+ SMLALD_VC: "SMLALD.VC",
+ SMLALD_HI: "SMLALD.HI",
+ SMLALD_LS: "SMLALD.LS",
+ SMLALD_GE: "SMLALD.GE",
+ SMLALD_LT: "SMLALD.LT",
+ SMLALD_GT: "SMLALD.GT",
+ SMLALD_LE: "SMLALD.LE",
+ SMLALD: "SMLALD",
+ SMLALD_ZZ: "SMLALD.ZZ",
+ SMLALD_X_EQ: "SMLALD.X.EQ",
+ SMLALD_X_NE: "SMLALD.X.NE",
+ SMLALD_X_CS: "SMLALD.X.CS",
+ SMLALD_X_CC: "SMLALD.X.CC",
+ SMLALD_X_MI: "SMLALD.X.MI",
+ SMLALD_X_PL: "SMLALD.X.PL",
+ SMLALD_X_VS: "SMLALD.X.VS",
+ SMLALD_X_VC: "SMLALD.X.VC",
+ SMLALD_X_HI: "SMLALD.X.HI",
+ SMLALD_X_LS: "SMLALD.X.LS",
+ SMLALD_X_GE: "SMLALD.X.GE",
+ SMLALD_X_LT: "SMLALD.X.LT",
+ SMLALD_X_GT: "SMLALD.X.GT",
+ SMLALD_X_LE: "SMLALD.X.LE",
+ SMLALD_X: "SMLALD.X",
+ SMLALD_X_ZZ: "SMLALD.X.ZZ",
+ SMLAWB_EQ: "SMLAWB.EQ",
+ SMLAWB_NE: "SMLAWB.NE",
+ SMLAWB_CS: "SMLAWB.CS",
+ SMLAWB_CC: "SMLAWB.CC",
+ SMLAWB_MI: "SMLAWB.MI",
+ SMLAWB_PL: "SMLAWB.PL",
+ SMLAWB_VS: "SMLAWB.VS",
+ SMLAWB_VC: "SMLAWB.VC",
+ SMLAWB_HI: "SMLAWB.HI",
+ SMLAWB_LS: "SMLAWB.LS",
+ SMLAWB_GE: "SMLAWB.GE",
+ SMLAWB_LT: "SMLAWB.LT",
+ SMLAWB_GT: "SMLAWB.GT",
+ SMLAWB_LE: "SMLAWB.LE",
+ SMLAWB: "SMLAWB",
+ SMLAWB_ZZ: "SMLAWB.ZZ",
+ SMLAWT_EQ: "SMLAWT.EQ",
+ SMLAWT_NE: "SMLAWT.NE",
+ SMLAWT_CS: "SMLAWT.CS",
+ SMLAWT_CC: "SMLAWT.CC",
+ SMLAWT_MI: "SMLAWT.MI",
+ SMLAWT_PL: "SMLAWT.PL",
+ SMLAWT_VS: "SMLAWT.VS",
+ SMLAWT_VC: "SMLAWT.VC",
+ SMLAWT_HI: "SMLAWT.HI",
+ SMLAWT_LS: "SMLAWT.LS",
+ SMLAWT_GE: "SMLAWT.GE",
+ SMLAWT_LT: "SMLAWT.LT",
+ SMLAWT_GT: "SMLAWT.GT",
+ SMLAWT_LE: "SMLAWT.LE",
+ SMLAWT: "SMLAWT",
+ SMLAWT_ZZ: "SMLAWT.ZZ",
+ SMLSD_EQ: "SMLSD.EQ",
+ SMLSD_NE: "SMLSD.NE",
+ SMLSD_CS: "SMLSD.CS",
+ SMLSD_CC: "SMLSD.CC",
+ SMLSD_MI: "SMLSD.MI",
+ SMLSD_PL: "SMLSD.PL",
+ SMLSD_VS: "SMLSD.VS",
+ SMLSD_VC: "SMLSD.VC",
+ SMLSD_HI: "SMLSD.HI",
+ SMLSD_LS: "SMLSD.LS",
+ SMLSD_GE: "SMLSD.GE",
+ SMLSD_LT: "SMLSD.LT",
+ SMLSD_GT: "SMLSD.GT",
+ SMLSD_LE: "SMLSD.LE",
+ SMLSD: "SMLSD",
+ SMLSD_ZZ: "SMLSD.ZZ",
+ SMLSD_X_EQ: "SMLSD.X.EQ",
+ SMLSD_X_NE: "SMLSD.X.NE",
+ SMLSD_X_CS: "SMLSD.X.CS",
+ SMLSD_X_CC: "SMLSD.X.CC",
+ SMLSD_X_MI: "SMLSD.X.MI",
+ SMLSD_X_PL: "SMLSD.X.PL",
+ SMLSD_X_VS: "SMLSD.X.VS",
+ SMLSD_X_VC: "SMLSD.X.VC",
+ SMLSD_X_HI: "SMLSD.X.HI",
+ SMLSD_X_LS: "SMLSD.X.LS",
+ SMLSD_X_GE: "SMLSD.X.GE",
+ SMLSD_X_LT: "SMLSD.X.LT",
+ SMLSD_X_GT: "SMLSD.X.GT",
+ SMLSD_X_LE: "SMLSD.X.LE",
+ SMLSD_X: "SMLSD.X",
+ SMLSD_X_ZZ: "SMLSD.X.ZZ",
+ SMLSLD_EQ: "SMLSLD.EQ",
+ SMLSLD_NE: "SMLSLD.NE",
+ SMLSLD_CS: "SMLSLD.CS",
+ SMLSLD_CC: "SMLSLD.CC",
+ SMLSLD_MI: "SMLSLD.MI",
+ SMLSLD_PL: "SMLSLD.PL",
+ SMLSLD_VS: "SMLSLD.VS",
+ SMLSLD_VC: "SMLSLD.VC",
+ SMLSLD_HI: "SMLSLD.HI",
+ SMLSLD_LS: "SMLSLD.LS",
+ SMLSLD_GE: "SMLSLD.GE",
+ SMLSLD_LT: "SMLSLD.LT",
+ SMLSLD_GT: "SMLSLD.GT",
+ SMLSLD_LE: "SMLSLD.LE",
+ SMLSLD: "SMLSLD",
+ SMLSLD_ZZ: "SMLSLD.ZZ",
+ SMLSLD_X_EQ: "SMLSLD.X.EQ",
+ SMLSLD_X_NE: "SMLSLD.X.NE",
+ SMLSLD_X_CS: "SMLSLD.X.CS",
+ SMLSLD_X_CC: "SMLSLD.X.CC",
+ SMLSLD_X_MI: "SMLSLD.X.MI",
+ SMLSLD_X_PL: "SMLSLD.X.PL",
+ SMLSLD_X_VS: "SMLSLD.X.VS",
+ SMLSLD_X_VC: "SMLSLD.X.VC",
+ SMLSLD_X_HI: "SMLSLD.X.HI",
+ SMLSLD_X_LS: "SMLSLD.X.LS",
+ SMLSLD_X_GE: "SMLSLD.X.GE",
+ SMLSLD_X_LT: "SMLSLD.X.LT",
+ SMLSLD_X_GT: "SMLSLD.X.GT",
+ SMLSLD_X_LE: "SMLSLD.X.LE",
+ SMLSLD_X: "SMLSLD.X",
+ SMLSLD_X_ZZ: "SMLSLD.X.ZZ",
+ SMMLA_EQ: "SMMLA.EQ",
+ SMMLA_NE: "SMMLA.NE",
+ SMMLA_CS: "SMMLA.CS",
+ SMMLA_CC: "SMMLA.CC",
+ SMMLA_MI: "SMMLA.MI",
+ SMMLA_PL: "SMMLA.PL",
+ SMMLA_VS: "SMMLA.VS",
+ SMMLA_VC: "SMMLA.VC",
+ SMMLA_HI: "SMMLA.HI",
+ SMMLA_LS: "SMMLA.LS",
+ SMMLA_GE: "SMMLA.GE",
+ SMMLA_LT: "SMMLA.LT",
+ SMMLA_GT: "SMMLA.GT",
+ SMMLA_LE: "SMMLA.LE",
+ SMMLA: "SMMLA",
+ SMMLA_ZZ: "SMMLA.ZZ",
+ SMMLA_R_EQ: "SMMLA.R.EQ",
+ SMMLA_R_NE: "SMMLA.R.NE",
+ SMMLA_R_CS: "SMMLA.R.CS",
+ SMMLA_R_CC: "SMMLA.R.CC",
+ SMMLA_R_MI: "SMMLA.R.MI",
+ SMMLA_R_PL: "SMMLA.R.PL",
+ SMMLA_R_VS: "SMMLA.R.VS",
+ SMMLA_R_VC: "SMMLA.R.VC",
+ SMMLA_R_HI: "SMMLA.R.HI",
+ SMMLA_R_LS: "SMMLA.R.LS",
+ SMMLA_R_GE: "SMMLA.R.GE",
+ SMMLA_R_LT: "SMMLA.R.LT",
+ SMMLA_R_GT: "SMMLA.R.GT",
+ SMMLA_R_LE: "SMMLA.R.LE",
+ SMMLA_R: "SMMLA.R",
+ SMMLA_R_ZZ: "SMMLA.R.ZZ",
+ SMMLS_EQ: "SMMLS.EQ",
+ SMMLS_NE: "SMMLS.NE",
+ SMMLS_CS: "SMMLS.CS",
+ SMMLS_CC: "SMMLS.CC",
+ SMMLS_MI: "SMMLS.MI",
+ SMMLS_PL: "SMMLS.PL",
+ SMMLS_VS: "SMMLS.VS",
+ SMMLS_VC: "SMMLS.VC",
+ SMMLS_HI: "SMMLS.HI",
+ SMMLS_LS: "SMMLS.LS",
+ SMMLS_GE: "SMMLS.GE",
+ SMMLS_LT: "SMMLS.LT",
+ SMMLS_GT: "SMMLS.GT",
+ SMMLS_LE: "SMMLS.LE",
+ SMMLS: "SMMLS",
+ SMMLS_ZZ: "SMMLS.ZZ",
+ SMMLS_R_EQ: "SMMLS.R.EQ",
+ SMMLS_R_NE: "SMMLS.R.NE",
+ SMMLS_R_CS: "SMMLS.R.CS",
+ SMMLS_R_CC: "SMMLS.R.CC",
+ SMMLS_R_MI: "SMMLS.R.MI",
+ SMMLS_R_PL: "SMMLS.R.PL",
+ SMMLS_R_VS: "SMMLS.R.VS",
+ SMMLS_R_VC: "SMMLS.R.VC",
+ SMMLS_R_HI: "SMMLS.R.HI",
+ SMMLS_R_LS: "SMMLS.R.LS",
+ SMMLS_R_GE: "SMMLS.R.GE",
+ SMMLS_R_LT: "SMMLS.R.LT",
+ SMMLS_R_GT: "SMMLS.R.GT",
+ SMMLS_R_LE: "SMMLS.R.LE",
+ SMMLS_R: "SMMLS.R",
+ SMMLS_R_ZZ: "SMMLS.R.ZZ",
+ SMMUL_EQ: "SMMUL.EQ",
+ SMMUL_NE: "SMMUL.NE",
+ SMMUL_CS: "SMMUL.CS",
+ SMMUL_CC: "SMMUL.CC",
+ SMMUL_MI: "SMMUL.MI",
+ SMMUL_PL: "SMMUL.PL",
+ SMMUL_VS: "SMMUL.VS",
+ SMMUL_VC: "SMMUL.VC",
+ SMMUL_HI: "SMMUL.HI",
+ SMMUL_LS: "SMMUL.LS",
+ SMMUL_GE: "SMMUL.GE",
+ SMMUL_LT: "SMMUL.LT",
+ SMMUL_GT: "SMMUL.GT",
+ SMMUL_LE: "SMMUL.LE",
+ SMMUL: "SMMUL",
+ SMMUL_ZZ: "SMMUL.ZZ",
+ SMMUL_R_EQ: "SMMUL.R.EQ",
+ SMMUL_R_NE: "SMMUL.R.NE",
+ SMMUL_R_CS: "SMMUL.R.CS",
+ SMMUL_R_CC: "SMMUL.R.CC",
+ SMMUL_R_MI: "SMMUL.R.MI",
+ SMMUL_R_PL: "SMMUL.R.PL",
+ SMMUL_R_VS: "SMMUL.R.VS",
+ SMMUL_R_VC: "SMMUL.R.VC",
+ SMMUL_R_HI: "SMMUL.R.HI",
+ SMMUL_R_LS: "SMMUL.R.LS",
+ SMMUL_R_GE: "SMMUL.R.GE",
+ SMMUL_R_LT: "SMMUL.R.LT",
+ SMMUL_R_GT: "SMMUL.R.GT",
+ SMMUL_R_LE: "SMMUL.R.LE",
+ SMMUL_R: "SMMUL.R",
+ SMMUL_R_ZZ: "SMMUL.R.ZZ",
+ SMUAD_EQ: "SMUAD.EQ",
+ SMUAD_NE: "SMUAD.NE",
+ SMUAD_CS: "SMUAD.CS",
+ SMUAD_CC: "SMUAD.CC",
+ SMUAD_MI: "SMUAD.MI",
+ SMUAD_PL: "SMUAD.PL",
+ SMUAD_VS: "SMUAD.VS",
+ SMUAD_VC: "SMUAD.VC",
+ SMUAD_HI: "SMUAD.HI",
+ SMUAD_LS: "SMUAD.LS",
+ SMUAD_GE: "SMUAD.GE",
+ SMUAD_LT: "SMUAD.LT",
+ SMUAD_GT: "SMUAD.GT",
+ SMUAD_LE: "SMUAD.LE",
+ SMUAD: "SMUAD",
+ SMUAD_ZZ: "SMUAD.ZZ",
+ SMUAD_X_EQ: "SMUAD.X.EQ",
+ SMUAD_X_NE: "SMUAD.X.NE",
+ SMUAD_X_CS: "SMUAD.X.CS",
+ SMUAD_X_CC: "SMUAD.X.CC",
+ SMUAD_X_MI: "SMUAD.X.MI",
+ SMUAD_X_PL: "SMUAD.X.PL",
+ SMUAD_X_VS: "SMUAD.X.VS",
+ SMUAD_X_VC: "SMUAD.X.VC",
+ SMUAD_X_HI: "SMUAD.X.HI",
+ SMUAD_X_LS: "SMUAD.X.LS",
+ SMUAD_X_GE: "SMUAD.X.GE",
+ SMUAD_X_LT: "SMUAD.X.LT",
+ SMUAD_X_GT: "SMUAD.X.GT",
+ SMUAD_X_LE: "SMUAD.X.LE",
+ SMUAD_X: "SMUAD.X",
+ SMUAD_X_ZZ: "SMUAD.X.ZZ",
+ SMULBB_EQ: "SMULBB.EQ",
+ SMULBB_NE: "SMULBB.NE",
+ SMULBB_CS: "SMULBB.CS",
+ SMULBB_CC: "SMULBB.CC",
+ SMULBB_MI: "SMULBB.MI",
+ SMULBB_PL: "SMULBB.PL",
+ SMULBB_VS: "SMULBB.VS",
+ SMULBB_VC: "SMULBB.VC",
+ SMULBB_HI: "SMULBB.HI",
+ SMULBB_LS: "SMULBB.LS",
+ SMULBB_GE: "SMULBB.GE",
+ SMULBB_LT: "SMULBB.LT",
+ SMULBB_GT: "SMULBB.GT",
+ SMULBB_LE: "SMULBB.LE",
+ SMULBB: "SMULBB",
+ SMULBB_ZZ: "SMULBB.ZZ",
+ SMULBT_EQ: "SMULBT.EQ",
+ SMULBT_NE: "SMULBT.NE",
+ SMULBT_CS: "SMULBT.CS",
+ SMULBT_CC: "SMULBT.CC",
+ SMULBT_MI: "SMULBT.MI",
+ SMULBT_PL: "SMULBT.PL",
+ SMULBT_VS: "SMULBT.VS",
+ SMULBT_VC: "SMULBT.VC",
+ SMULBT_HI: "SMULBT.HI",
+ SMULBT_LS: "SMULBT.LS",
+ SMULBT_GE: "SMULBT.GE",
+ SMULBT_LT: "SMULBT.LT",
+ SMULBT_GT: "SMULBT.GT",
+ SMULBT_LE: "SMULBT.LE",
+ SMULBT: "SMULBT",
+ SMULBT_ZZ: "SMULBT.ZZ",
+ SMULTB_EQ: "SMULTB.EQ",
+ SMULTB_NE: "SMULTB.NE",
+ SMULTB_CS: "SMULTB.CS",
+ SMULTB_CC: "SMULTB.CC",
+ SMULTB_MI: "SMULTB.MI",
+ SMULTB_PL: "SMULTB.PL",
+ SMULTB_VS: "SMULTB.VS",
+ SMULTB_VC: "SMULTB.VC",
+ SMULTB_HI: "SMULTB.HI",
+ SMULTB_LS: "SMULTB.LS",
+ SMULTB_GE: "SMULTB.GE",
+ SMULTB_LT: "SMULTB.LT",
+ SMULTB_GT: "SMULTB.GT",
+ SMULTB_LE: "SMULTB.LE",
+ SMULTB: "SMULTB",
+ SMULTB_ZZ: "SMULTB.ZZ",
+ SMULTT_EQ: "SMULTT.EQ",
+ SMULTT_NE: "SMULTT.NE",
+ SMULTT_CS: "SMULTT.CS",
+ SMULTT_CC: "SMULTT.CC",
+ SMULTT_MI: "SMULTT.MI",
+ SMULTT_PL: "SMULTT.PL",
+ SMULTT_VS: "SMULTT.VS",
+ SMULTT_VC: "SMULTT.VC",
+ SMULTT_HI: "SMULTT.HI",
+ SMULTT_LS: "SMULTT.LS",
+ SMULTT_GE: "SMULTT.GE",
+ SMULTT_LT: "SMULTT.LT",
+ SMULTT_GT: "SMULTT.GT",
+ SMULTT_LE: "SMULTT.LE",
+ SMULTT: "SMULTT",
+ SMULTT_ZZ: "SMULTT.ZZ",
+ SMULL_EQ: "SMULL.EQ",
+ SMULL_NE: "SMULL.NE",
+ SMULL_CS: "SMULL.CS",
+ SMULL_CC: "SMULL.CC",
+ SMULL_MI: "SMULL.MI",
+ SMULL_PL: "SMULL.PL",
+ SMULL_VS: "SMULL.VS",
+ SMULL_VC: "SMULL.VC",
+ SMULL_HI: "SMULL.HI",
+ SMULL_LS: "SMULL.LS",
+ SMULL_GE: "SMULL.GE",
+ SMULL_LT: "SMULL.LT",
+ SMULL_GT: "SMULL.GT",
+ SMULL_LE: "SMULL.LE",
+ SMULL: "SMULL",
+ SMULL_ZZ: "SMULL.ZZ",
+ SMULL_S_EQ: "SMULL.S.EQ",
+ SMULL_S_NE: "SMULL.S.NE",
+ SMULL_S_CS: "SMULL.S.CS",
+ SMULL_S_CC: "SMULL.S.CC",
+ SMULL_S_MI: "SMULL.S.MI",
+ SMULL_S_PL: "SMULL.S.PL",
+ SMULL_S_VS: "SMULL.S.VS",
+ SMULL_S_VC: "SMULL.S.VC",
+ SMULL_S_HI: "SMULL.S.HI",
+ SMULL_S_LS: "SMULL.S.LS",
+ SMULL_S_GE: "SMULL.S.GE",
+ SMULL_S_LT: "SMULL.S.LT",
+ SMULL_S_GT: "SMULL.S.GT",
+ SMULL_S_LE: "SMULL.S.LE",
+ SMULL_S: "SMULL.S",
+ SMULL_S_ZZ: "SMULL.S.ZZ",
+ SMULWB_EQ: "SMULWB.EQ",
+ SMULWB_NE: "SMULWB.NE",
+ SMULWB_CS: "SMULWB.CS",
+ SMULWB_CC: "SMULWB.CC",
+ SMULWB_MI: "SMULWB.MI",
+ SMULWB_PL: "SMULWB.PL",
+ SMULWB_VS: "SMULWB.VS",
+ SMULWB_VC: "SMULWB.VC",
+ SMULWB_HI: "SMULWB.HI",
+ SMULWB_LS: "SMULWB.LS",
+ SMULWB_GE: "SMULWB.GE",
+ SMULWB_LT: "SMULWB.LT",
+ SMULWB_GT: "SMULWB.GT",
+ SMULWB_LE: "SMULWB.LE",
+ SMULWB: "SMULWB",
+ SMULWB_ZZ: "SMULWB.ZZ",
+ SMULWT_EQ: "SMULWT.EQ",
+ SMULWT_NE: "SMULWT.NE",
+ SMULWT_CS: "SMULWT.CS",
+ SMULWT_CC: "SMULWT.CC",
+ SMULWT_MI: "SMULWT.MI",
+ SMULWT_PL: "SMULWT.PL",
+ SMULWT_VS: "SMULWT.VS",
+ SMULWT_VC: "SMULWT.VC",
+ SMULWT_HI: "SMULWT.HI",
+ SMULWT_LS: "SMULWT.LS",
+ SMULWT_GE: "SMULWT.GE",
+ SMULWT_LT: "SMULWT.LT",
+ SMULWT_GT: "SMULWT.GT",
+ SMULWT_LE: "SMULWT.LE",
+ SMULWT: "SMULWT",
+ SMULWT_ZZ: "SMULWT.ZZ",
+ SMUSD_EQ: "SMUSD.EQ",
+ SMUSD_NE: "SMUSD.NE",
+ SMUSD_CS: "SMUSD.CS",
+ SMUSD_CC: "SMUSD.CC",
+ SMUSD_MI: "SMUSD.MI",
+ SMUSD_PL: "SMUSD.PL",
+ SMUSD_VS: "SMUSD.VS",
+ SMUSD_VC: "SMUSD.VC",
+ SMUSD_HI: "SMUSD.HI",
+ SMUSD_LS: "SMUSD.LS",
+ SMUSD_GE: "SMUSD.GE",
+ SMUSD_LT: "SMUSD.LT",
+ SMUSD_GT: "SMUSD.GT",
+ SMUSD_LE: "SMUSD.LE",
+ SMUSD: "SMUSD",
+ SMUSD_ZZ: "SMUSD.ZZ",
+ SMUSD_X_EQ: "SMUSD.X.EQ",
+ SMUSD_X_NE: "SMUSD.X.NE",
+ SMUSD_X_CS: "SMUSD.X.CS",
+ SMUSD_X_CC: "SMUSD.X.CC",
+ SMUSD_X_MI: "SMUSD.X.MI",
+ SMUSD_X_PL: "SMUSD.X.PL",
+ SMUSD_X_VS: "SMUSD.X.VS",
+ SMUSD_X_VC: "SMUSD.X.VC",
+ SMUSD_X_HI: "SMUSD.X.HI",
+ SMUSD_X_LS: "SMUSD.X.LS",
+ SMUSD_X_GE: "SMUSD.X.GE",
+ SMUSD_X_LT: "SMUSD.X.LT",
+ SMUSD_X_GT: "SMUSD.X.GT",
+ SMUSD_X_LE: "SMUSD.X.LE",
+ SMUSD_X: "SMUSD.X",
+ SMUSD_X_ZZ: "SMUSD.X.ZZ",
+ SSAT_EQ: "SSAT.EQ",
+ SSAT_NE: "SSAT.NE",
+ SSAT_CS: "SSAT.CS",
+ SSAT_CC: "SSAT.CC",
+ SSAT_MI: "SSAT.MI",
+ SSAT_PL: "SSAT.PL",
+ SSAT_VS: "SSAT.VS",
+ SSAT_VC: "SSAT.VC",
+ SSAT_HI: "SSAT.HI",
+ SSAT_LS: "SSAT.LS",
+ SSAT_GE: "SSAT.GE",
+ SSAT_LT: "SSAT.LT",
+ SSAT_GT: "SSAT.GT",
+ SSAT_LE: "SSAT.LE",
+ SSAT: "SSAT",
+ SSAT_ZZ: "SSAT.ZZ",
+ SSAT16_EQ: "SSAT16.EQ",
+ SSAT16_NE: "SSAT16.NE",
+ SSAT16_CS: "SSAT16.CS",
+ SSAT16_CC: "SSAT16.CC",
+ SSAT16_MI: "SSAT16.MI",
+ SSAT16_PL: "SSAT16.PL",
+ SSAT16_VS: "SSAT16.VS",
+ SSAT16_VC: "SSAT16.VC",
+ SSAT16_HI: "SSAT16.HI",
+ SSAT16_LS: "SSAT16.LS",
+ SSAT16_GE: "SSAT16.GE",
+ SSAT16_LT: "SSAT16.LT",
+ SSAT16_GT: "SSAT16.GT",
+ SSAT16_LE: "SSAT16.LE",
+ SSAT16: "SSAT16",
+ SSAT16_ZZ: "SSAT16.ZZ",
+ SSAX_EQ: "SSAX.EQ",
+ SSAX_NE: "SSAX.NE",
+ SSAX_CS: "SSAX.CS",
+ SSAX_CC: "SSAX.CC",
+ SSAX_MI: "SSAX.MI",
+ SSAX_PL: "SSAX.PL",
+ SSAX_VS: "SSAX.VS",
+ SSAX_VC: "SSAX.VC",
+ SSAX_HI: "SSAX.HI",
+ SSAX_LS: "SSAX.LS",
+ SSAX_GE: "SSAX.GE",
+ SSAX_LT: "SSAX.LT",
+ SSAX_GT: "SSAX.GT",
+ SSAX_LE: "SSAX.LE",
+ SSAX: "SSAX",
+ SSAX_ZZ: "SSAX.ZZ",
+ SSUB16_EQ: "SSUB16.EQ",
+ SSUB16_NE: "SSUB16.NE",
+ SSUB16_CS: "SSUB16.CS",
+ SSUB16_CC: "SSUB16.CC",
+ SSUB16_MI: "SSUB16.MI",
+ SSUB16_PL: "SSUB16.PL",
+ SSUB16_VS: "SSUB16.VS",
+ SSUB16_VC: "SSUB16.VC",
+ SSUB16_HI: "SSUB16.HI",
+ SSUB16_LS: "SSUB16.LS",
+ SSUB16_GE: "SSUB16.GE",
+ SSUB16_LT: "SSUB16.LT",
+ SSUB16_GT: "SSUB16.GT",
+ SSUB16_LE: "SSUB16.LE",
+ SSUB16: "SSUB16",
+ SSUB16_ZZ: "SSUB16.ZZ",
+ SSUB8_EQ: "SSUB8.EQ",
+ SSUB8_NE: "SSUB8.NE",
+ SSUB8_CS: "SSUB8.CS",
+ SSUB8_CC: "SSUB8.CC",
+ SSUB8_MI: "SSUB8.MI",
+ SSUB8_PL: "SSUB8.PL",
+ SSUB8_VS: "SSUB8.VS",
+ SSUB8_VC: "SSUB8.VC",
+ SSUB8_HI: "SSUB8.HI",
+ SSUB8_LS: "SSUB8.LS",
+ SSUB8_GE: "SSUB8.GE",
+ SSUB8_LT: "SSUB8.LT",
+ SSUB8_GT: "SSUB8.GT",
+ SSUB8_LE: "SSUB8.LE",
+ SSUB8: "SSUB8",
+ SSUB8_ZZ: "SSUB8.ZZ",
+ STM_EQ: "STM.EQ",
+ STM_NE: "STM.NE",
+ STM_CS: "STM.CS",
+ STM_CC: "STM.CC",
+ STM_MI: "STM.MI",
+ STM_PL: "STM.PL",
+ STM_VS: "STM.VS",
+ STM_VC: "STM.VC",
+ STM_HI: "STM.HI",
+ STM_LS: "STM.LS",
+ STM_GE: "STM.GE",
+ STM_LT: "STM.LT",
+ STM_GT: "STM.GT",
+ STM_LE: "STM.LE",
+ STM: "STM",
+ STM_ZZ: "STM.ZZ",
+ STMDA_EQ: "STMDA.EQ",
+ STMDA_NE: "STMDA.NE",
+ STMDA_CS: "STMDA.CS",
+ STMDA_CC: "STMDA.CC",
+ STMDA_MI: "STMDA.MI",
+ STMDA_PL: "STMDA.PL",
+ STMDA_VS: "STMDA.VS",
+ STMDA_VC: "STMDA.VC",
+ STMDA_HI: "STMDA.HI",
+ STMDA_LS: "STMDA.LS",
+ STMDA_GE: "STMDA.GE",
+ STMDA_LT: "STMDA.LT",
+ STMDA_GT: "STMDA.GT",
+ STMDA_LE: "STMDA.LE",
+ STMDA: "STMDA",
+ STMDA_ZZ: "STMDA.ZZ",
+ STMDB_EQ: "STMDB.EQ",
+ STMDB_NE: "STMDB.NE",
+ STMDB_CS: "STMDB.CS",
+ STMDB_CC: "STMDB.CC",
+ STMDB_MI: "STMDB.MI",
+ STMDB_PL: "STMDB.PL",
+ STMDB_VS: "STMDB.VS",
+ STMDB_VC: "STMDB.VC",
+ STMDB_HI: "STMDB.HI",
+ STMDB_LS: "STMDB.LS",
+ STMDB_GE: "STMDB.GE",
+ STMDB_LT: "STMDB.LT",
+ STMDB_GT: "STMDB.GT",
+ STMDB_LE: "STMDB.LE",
+ STMDB: "STMDB",
+ STMDB_ZZ: "STMDB.ZZ",
+ STMIB_EQ: "STMIB.EQ",
+ STMIB_NE: "STMIB.NE",
+ STMIB_CS: "STMIB.CS",
+ STMIB_CC: "STMIB.CC",
+ STMIB_MI: "STMIB.MI",
+ STMIB_PL: "STMIB.PL",
+ STMIB_VS: "STMIB.VS",
+ STMIB_VC: "STMIB.VC",
+ STMIB_HI: "STMIB.HI",
+ STMIB_LS: "STMIB.LS",
+ STMIB_GE: "STMIB.GE",
+ STMIB_LT: "STMIB.LT",
+ STMIB_GT: "STMIB.GT",
+ STMIB_LE: "STMIB.LE",
+ STMIB: "STMIB",
+ STMIB_ZZ: "STMIB.ZZ",
+ STR_EQ: "STR.EQ",
+ STR_NE: "STR.NE",
+ STR_CS: "STR.CS",
+ STR_CC: "STR.CC",
+ STR_MI: "STR.MI",
+ STR_PL: "STR.PL",
+ STR_VS: "STR.VS",
+ STR_VC: "STR.VC",
+ STR_HI: "STR.HI",
+ STR_LS: "STR.LS",
+ STR_GE: "STR.GE",
+ STR_LT: "STR.LT",
+ STR_GT: "STR.GT",
+ STR_LE: "STR.LE",
+ STR: "STR",
+ STR_ZZ: "STR.ZZ",
+ STRB_EQ: "STRB.EQ",
+ STRB_NE: "STRB.NE",
+ STRB_CS: "STRB.CS",
+ STRB_CC: "STRB.CC",
+ STRB_MI: "STRB.MI",
+ STRB_PL: "STRB.PL",
+ STRB_VS: "STRB.VS",
+ STRB_VC: "STRB.VC",
+ STRB_HI: "STRB.HI",
+ STRB_LS: "STRB.LS",
+ STRB_GE: "STRB.GE",
+ STRB_LT: "STRB.LT",
+ STRB_GT: "STRB.GT",
+ STRB_LE: "STRB.LE",
+ STRB: "STRB",
+ STRB_ZZ: "STRB.ZZ",
+ STRBT_EQ: "STRBT.EQ",
+ STRBT_NE: "STRBT.NE",
+ STRBT_CS: "STRBT.CS",
+ STRBT_CC: "STRBT.CC",
+ STRBT_MI: "STRBT.MI",
+ STRBT_PL: "STRBT.PL",
+ STRBT_VS: "STRBT.VS",
+ STRBT_VC: "STRBT.VC",
+ STRBT_HI: "STRBT.HI",
+ STRBT_LS: "STRBT.LS",
+ STRBT_GE: "STRBT.GE",
+ STRBT_LT: "STRBT.LT",
+ STRBT_GT: "STRBT.GT",
+ STRBT_LE: "STRBT.LE",
+ STRBT: "STRBT",
+ STRBT_ZZ: "STRBT.ZZ",
+ STRD_EQ: "STRD.EQ",
+ STRD_NE: "STRD.NE",
+ STRD_CS: "STRD.CS",
+ STRD_CC: "STRD.CC",
+ STRD_MI: "STRD.MI",
+ STRD_PL: "STRD.PL",
+ STRD_VS: "STRD.VS",
+ STRD_VC: "STRD.VC",
+ STRD_HI: "STRD.HI",
+ STRD_LS: "STRD.LS",
+ STRD_GE: "STRD.GE",
+ STRD_LT: "STRD.LT",
+ STRD_GT: "STRD.GT",
+ STRD_LE: "STRD.LE",
+ STRD: "STRD",
+ STRD_ZZ: "STRD.ZZ",
+ STREX_EQ: "STREX.EQ",
+ STREX_NE: "STREX.NE",
+ STREX_CS: "STREX.CS",
+ STREX_CC: "STREX.CC",
+ STREX_MI: "STREX.MI",
+ STREX_PL: "STREX.PL",
+ STREX_VS: "STREX.VS",
+ STREX_VC: "STREX.VC",
+ STREX_HI: "STREX.HI",
+ STREX_LS: "STREX.LS",
+ STREX_GE: "STREX.GE",
+ STREX_LT: "STREX.LT",
+ STREX_GT: "STREX.GT",
+ STREX_LE: "STREX.LE",
+ STREX: "STREX",
+ STREX_ZZ: "STREX.ZZ",
+ STREXB_EQ: "STREXB.EQ",
+ STREXB_NE: "STREXB.NE",
+ STREXB_CS: "STREXB.CS",
+ STREXB_CC: "STREXB.CC",
+ STREXB_MI: "STREXB.MI",
+ STREXB_PL: "STREXB.PL",
+ STREXB_VS: "STREXB.VS",
+ STREXB_VC: "STREXB.VC",
+ STREXB_HI: "STREXB.HI",
+ STREXB_LS: "STREXB.LS",
+ STREXB_GE: "STREXB.GE",
+ STREXB_LT: "STREXB.LT",
+ STREXB_GT: "STREXB.GT",
+ STREXB_LE: "STREXB.LE",
+ STREXB: "STREXB",
+ STREXB_ZZ: "STREXB.ZZ",
+ STREXD_EQ: "STREXD.EQ",
+ STREXD_NE: "STREXD.NE",
+ STREXD_CS: "STREXD.CS",
+ STREXD_CC: "STREXD.CC",
+ STREXD_MI: "STREXD.MI",
+ STREXD_PL: "STREXD.PL",
+ STREXD_VS: "STREXD.VS",
+ STREXD_VC: "STREXD.VC",
+ STREXD_HI: "STREXD.HI",
+ STREXD_LS: "STREXD.LS",
+ STREXD_GE: "STREXD.GE",
+ STREXD_LT: "STREXD.LT",
+ STREXD_GT: "STREXD.GT",
+ STREXD_LE: "STREXD.LE",
+ STREXD: "STREXD",
+ STREXD_ZZ: "STREXD.ZZ",
+ STREXH_EQ: "STREXH.EQ",
+ STREXH_NE: "STREXH.NE",
+ STREXH_CS: "STREXH.CS",
+ STREXH_CC: "STREXH.CC",
+ STREXH_MI: "STREXH.MI",
+ STREXH_PL: "STREXH.PL",
+ STREXH_VS: "STREXH.VS",
+ STREXH_VC: "STREXH.VC",
+ STREXH_HI: "STREXH.HI",
+ STREXH_LS: "STREXH.LS",
+ STREXH_GE: "STREXH.GE",
+ STREXH_LT: "STREXH.LT",
+ STREXH_GT: "STREXH.GT",
+ STREXH_LE: "STREXH.LE",
+ STREXH: "STREXH",
+ STREXH_ZZ: "STREXH.ZZ",
+ STRH_EQ: "STRH.EQ",
+ STRH_NE: "STRH.NE",
+ STRH_CS: "STRH.CS",
+ STRH_CC: "STRH.CC",
+ STRH_MI: "STRH.MI",
+ STRH_PL: "STRH.PL",
+ STRH_VS: "STRH.VS",
+ STRH_VC: "STRH.VC",
+ STRH_HI: "STRH.HI",
+ STRH_LS: "STRH.LS",
+ STRH_GE: "STRH.GE",
+ STRH_LT: "STRH.LT",
+ STRH_GT: "STRH.GT",
+ STRH_LE: "STRH.LE",
+ STRH: "STRH",
+ STRH_ZZ: "STRH.ZZ",
+ STRHT_EQ: "STRHT.EQ",
+ STRHT_NE: "STRHT.NE",
+ STRHT_CS: "STRHT.CS",
+ STRHT_CC: "STRHT.CC",
+ STRHT_MI: "STRHT.MI",
+ STRHT_PL: "STRHT.PL",
+ STRHT_VS: "STRHT.VS",
+ STRHT_VC: "STRHT.VC",
+ STRHT_HI: "STRHT.HI",
+ STRHT_LS: "STRHT.LS",
+ STRHT_GE: "STRHT.GE",
+ STRHT_LT: "STRHT.LT",
+ STRHT_GT: "STRHT.GT",
+ STRHT_LE: "STRHT.LE",
+ STRHT: "STRHT",
+ STRHT_ZZ: "STRHT.ZZ",
+ STRT_EQ: "STRT.EQ",
+ STRT_NE: "STRT.NE",
+ STRT_CS: "STRT.CS",
+ STRT_CC: "STRT.CC",
+ STRT_MI: "STRT.MI",
+ STRT_PL: "STRT.PL",
+ STRT_VS: "STRT.VS",
+ STRT_VC: "STRT.VC",
+ STRT_HI: "STRT.HI",
+ STRT_LS: "STRT.LS",
+ STRT_GE: "STRT.GE",
+ STRT_LT: "STRT.LT",
+ STRT_GT: "STRT.GT",
+ STRT_LE: "STRT.LE",
+ STRT: "STRT",
+ STRT_ZZ: "STRT.ZZ",
+ SUB_EQ: "SUB.EQ",
+ SUB_NE: "SUB.NE",
+ SUB_CS: "SUB.CS",
+ SUB_CC: "SUB.CC",
+ SUB_MI: "SUB.MI",
+ SUB_PL: "SUB.PL",
+ SUB_VS: "SUB.VS",
+ SUB_VC: "SUB.VC",
+ SUB_HI: "SUB.HI",
+ SUB_LS: "SUB.LS",
+ SUB_GE: "SUB.GE",
+ SUB_LT: "SUB.LT",
+ SUB_GT: "SUB.GT",
+ SUB_LE: "SUB.LE",
+ SUB: "SUB",
+ SUB_ZZ: "SUB.ZZ",
+ SUB_S_EQ: "SUB.S.EQ",
+ SUB_S_NE: "SUB.S.NE",
+ SUB_S_CS: "SUB.S.CS",
+ SUB_S_CC: "SUB.S.CC",
+ SUB_S_MI: "SUB.S.MI",
+ SUB_S_PL: "SUB.S.PL",
+ SUB_S_VS: "SUB.S.VS",
+ SUB_S_VC: "SUB.S.VC",
+ SUB_S_HI: "SUB.S.HI",
+ SUB_S_LS: "SUB.S.LS",
+ SUB_S_GE: "SUB.S.GE",
+ SUB_S_LT: "SUB.S.LT",
+ SUB_S_GT: "SUB.S.GT",
+ SUB_S_LE: "SUB.S.LE",
+ SUB_S: "SUB.S",
+ SUB_S_ZZ: "SUB.S.ZZ",
+ SVC_EQ: "SVC.EQ",
+ SVC_NE: "SVC.NE",
+ SVC_CS: "SVC.CS",
+ SVC_CC: "SVC.CC",
+ SVC_MI: "SVC.MI",
+ SVC_PL: "SVC.PL",
+ SVC_VS: "SVC.VS",
+ SVC_VC: "SVC.VC",
+ SVC_HI: "SVC.HI",
+ SVC_LS: "SVC.LS",
+ SVC_GE: "SVC.GE",
+ SVC_LT: "SVC.LT",
+ SVC_GT: "SVC.GT",
+ SVC_LE: "SVC.LE",
+ SVC: "SVC",
+ SVC_ZZ: "SVC.ZZ",
+ SWP_EQ: "SWP.EQ",
+ SWP_NE: "SWP.NE",
+ SWP_CS: "SWP.CS",
+ SWP_CC: "SWP.CC",
+ SWP_MI: "SWP.MI",
+ SWP_PL: "SWP.PL",
+ SWP_VS: "SWP.VS",
+ SWP_VC: "SWP.VC",
+ SWP_HI: "SWP.HI",
+ SWP_LS: "SWP.LS",
+ SWP_GE: "SWP.GE",
+ SWP_LT: "SWP.LT",
+ SWP_GT: "SWP.GT",
+ SWP_LE: "SWP.LE",
+ SWP: "SWP",
+ SWP_ZZ: "SWP.ZZ",
+ SWP_B_EQ: "SWP.B.EQ",
+ SWP_B_NE: "SWP.B.NE",
+ SWP_B_CS: "SWP.B.CS",
+ SWP_B_CC: "SWP.B.CC",
+ SWP_B_MI: "SWP.B.MI",
+ SWP_B_PL: "SWP.B.PL",
+ SWP_B_VS: "SWP.B.VS",
+ SWP_B_VC: "SWP.B.VC",
+ SWP_B_HI: "SWP.B.HI",
+ SWP_B_LS: "SWP.B.LS",
+ SWP_B_GE: "SWP.B.GE",
+ SWP_B_LT: "SWP.B.LT",
+ SWP_B_GT: "SWP.B.GT",
+ SWP_B_LE: "SWP.B.LE",
+ SWP_B: "SWP.B",
+ SWP_B_ZZ: "SWP.B.ZZ",
+ SXTAB_EQ: "SXTAB.EQ",
+ SXTAB_NE: "SXTAB.NE",
+ SXTAB_CS: "SXTAB.CS",
+ SXTAB_CC: "SXTAB.CC",
+ SXTAB_MI: "SXTAB.MI",
+ SXTAB_PL: "SXTAB.PL",
+ SXTAB_VS: "SXTAB.VS",
+ SXTAB_VC: "SXTAB.VC",
+ SXTAB_HI: "SXTAB.HI",
+ SXTAB_LS: "SXTAB.LS",
+ SXTAB_GE: "SXTAB.GE",
+ SXTAB_LT: "SXTAB.LT",
+ SXTAB_GT: "SXTAB.GT",
+ SXTAB_LE: "SXTAB.LE",
+ SXTAB: "SXTAB",
+ SXTAB_ZZ: "SXTAB.ZZ",
+ SXTAB16_EQ: "SXTAB16.EQ",
+ SXTAB16_NE: "SXTAB16.NE",
+ SXTAB16_CS: "SXTAB16.CS",
+ SXTAB16_CC: "SXTAB16.CC",
+ SXTAB16_MI: "SXTAB16.MI",
+ SXTAB16_PL: "SXTAB16.PL",
+ SXTAB16_VS: "SXTAB16.VS",
+ SXTAB16_VC: "SXTAB16.VC",
+ SXTAB16_HI: "SXTAB16.HI",
+ SXTAB16_LS: "SXTAB16.LS",
+ SXTAB16_GE: "SXTAB16.GE",
+ SXTAB16_LT: "SXTAB16.LT",
+ SXTAB16_GT: "SXTAB16.GT",
+ SXTAB16_LE: "SXTAB16.LE",
+ SXTAB16: "SXTAB16",
+ SXTAB16_ZZ: "SXTAB16.ZZ",
+ SXTAH_EQ: "SXTAH.EQ",
+ SXTAH_NE: "SXTAH.NE",
+ SXTAH_CS: "SXTAH.CS",
+ SXTAH_CC: "SXTAH.CC",
+ SXTAH_MI: "SXTAH.MI",
+ SXTAH_PL: "SXTAH.PL",
+ SXTAH_VS: "SXTAH.VS",
+ SXTAH_VC: "SXTAH.VC",
+ SXTAH_HI: "SXTAH.HI",
+ SXTAH_LS: "SXTAH.LS",
+ SXTAH_GE: "SXTAH.GE",
+ SXTAH_LT: "SXTAH.LT",
+ SXTAH_GT: "SXTAH.GT",
+ SXTAH_LE: "SXTAH.LE",
+ SXTAH: "SXTAH",
+ SXTAH_ZZ: "SXTAH.ZZ",
+ SXTB_EQ: "SXTB.EQ",
+ SXTB_NE: "SXTB.NE",
+ SXTB_CS: "SXTB.CS",
+ SXTB_CC: "SXTB.CC",
+ SXTB_MI: "SXTB.MI",
+ SXTB_PL: "SXTB.PL",
+ SXTB_VS: "SXTB.VS",
+ SXTB_VC: "SXTB.VC",
+ SXTB_HI: "SXTB.HI",
+ SXTB_LS: "SXTB.LS",
+ SXTB_GE: "SXTB.GE",
+ SXTB_LT: "SXTB.LT",
+ SXTB_GT: "SXTB.GT",
+ SXTB_LE: "SXTB.LE",
+ SXTB: "SXTB",
+ SXTB_ZZ: "SXTB.ZZ",
+ SXTB16_EQ: "SXTB16.EQ",
+ SXTB16_NE: "SXTB16.NE",
+ SXTB16_CS: "SXTB16.CS",
+ SXTB16_CC: "SXTB16.CC",
+ SXTB16_MI: "SXTB16.MI",
+ SXTB16_PL: "SXTB16.PL",
+ SXTB16_VS: "SXTB16.VS",
+ SXTB16_VC: "SXTB16.VC",
+ SXTB16_HI: "SXTB16.HI",
+ SXTB16_LS: "SXTB16.LS",
+ SXTB16_GE: "SXTB16.GE",
+ SXTB16_LT: "SXTB16.LT",
+ SXTB16_GT: "SXTB16.GT",
+ SXTB16_LE: "SXTB16.LE",
+ SXTB16: "SXTB16",
+ SXTB16_ZZ: "SXTB16.ZZ",
+ SXTH_EQ: "SXTH.EQ",
+ SXTH_NE: "SXTH.NE",
+ SXTH_CS: "SXTH.CS",
+ SXTH_CC: "SXTH.CC",
+ SXTH_MI: "SXTH.MI",
+ SXTH_PL: "SXTH.PL",
+ SXTH_VS: "SXTH.VS",
+ SXTH_VC: "SXTH.VC",
+ SXTH_HI: "SXTH.HI",
+ SXTH_LS: "SXTH.LS",
+ SXTH_GE: "SXTH.GE",
+ SXTH_LT: "SXTH.LT",
+ SXTH_GT: "SXTH.GT",
+ SXTH_LE: "SXTH.LE",
+ SXTH: "SXTH",
+ SXTH_ZZ: "SXTH.ZZ",
+ TEQ_EQ: "TEQ.EQ",
+ TEQ_NE: "TEQ.NE",
+ TEQ_CS: "TEQ.CS",
+ TEQ_CC: "TEQ.CC",
+ TEQ_MI: "TEQ.MI",
+ TEQ_PL: "TEQ.PL",
+ TEQ_VS: "TEQ.VS",
+ TEQ_VC: "TEQ.VC",
+ TEQ_HI: "TEQ.HI",
+ TEQ_LS: "TEQ.LS",
+ TEQ_GE: "TEQ.GE",
+ TEQ_LT: "TEQ.LT",
+ TEQ_GT: "TEQ.GT",
+ TEQ_LE: "TEQ.LE",
+ TEQ: "TEQ",
+ TEQ_ZZ: "TEQ.ZZ",
+ TST_EQ: "TST.EQ",
+ TST_NE: "TST.NE",
+ TST_CS: "TST.CS",
+ TST_CC: "TST.CC",
+ TST_MI: "TST.MI",
+ TST_PL: "TST.PL",
+ TST_VS: "TST.VS",
+ TST_VC: "TST.VC",
+ TST_HI: "TST.HI",
+ TST_LS: "TST.LS",
+ TST_GE: "TST.GE",
+ TST_LT: "TST.LT",
+ TST_GT: "TST.GT",
+ TST_LE: "TST.LE",
+ TST: "TST",
+ TST_ZZ: "TST.ZZ",
+ UADD16_EQ: "UADD16.EQ",
+ UADD16_NE: "UADD16.NE",
+ UADD16_CS: "UADD16.CS",
+ UADD16_CC: "UADD16.CC",
+ UADD16_MI: "UADD16.MI",
+ UADD16_PL: "UADD16.PL",
+ UADD16_VS: "UADD16.VS",
+ UADD16_VC: "UADD16.VC",
+ UADD16_HI: "UADD16.HI",
+ UADD16_LS: "UADD16.LS",
+ UADD16_GE: "UADD16.GE",
+ UADD16_LT: "UADD16.LT",
+ UADD16_GT: "UADD16.GT",
+ UADD16_LE: "UADD16.LE",
+ UADD16: "UADD16",
+ UADD16_ZZ: "UADD16.ZZ",
+ UADD8_EQ: "UADD8.EQ",
+ UADD8_NE: "UADD8.NE",
+ UADD8_CS: "UADD8.CS",
+ UADD8_CC: "UADD8.CC",
+ UADD8_MI: "UADD8.MI",
+ UADD8_PL: "UADD8.PL",
+ UADD8_VS: "UADD8.VS",
+ UADD8_VC: "UADD8.VC",
+ UADD8_HI: "UADD8.HI",
+ UADD8_LS: "UADD8.LS",
+ UADD8_GE: "UADD8.GE",
+ UADD8_LT: "UADD8.LT",
+ UADD8_GT: "UADD8.GT",
+ UADD8_LE: "UADD8.LE",
+ UADD8: "UADD8",
+ UADD8_ZZ: "UADD8.ZZ",
+ UASX_EQ: "UASX.EQ",
+ UASX_NE: "UASX.NE",
+ UASX_CS: "UASX.CS",
+ UASX_CC: "UASX.CC",
+ UASX_MI: "UASX.MI",
+ UASX_PL: "UASX.PL",
+ UASX_VS: "UASX.VS",
+ UASX_VC: "UASX.VC",
+ UASX_HI: "UASX.HI",
+ UASX_LS: "UASX.LS",
+ UASX_GE: "UASX.GE",
+ UASX_LT: "UASX.LT",
+ UASX_GT: "UASX.GT",
+ UASX_LE: "UASX.LE",
+ UASX: "UASX",
+ UASX_ZZ: "UASX.ZZ",
+ UBFX_EQ: "UBFX.EQ",
+ UBFX_NE: "UBFX.NE",
+ UBFX_CS: "UBFX.CS",
+ UBFX_CC: "UBFX.CC",
+ UBFX_MI: "UBFX.MI",
+ UBFX_PL: "UBFX.PL",
+ UBFX_VS: "UBFX.VS",
+ UBFX_VC: "UBFX.VC",
+ UBFX_HI: "UBFX.HI",
+ UBFX_LS: "UBFX.LS",
+ UBFX_GE: "UBFX.GE",
+ UBFX_LT: "UBFX.LT",
+ UBFX_GT: "UBFX.GT",
+ UBFX_LE: "UBFX.LE",
+ UBFX: "UBFX",
+ UBFX_ZZ: "UBFX.ZZ",
+ UHADD16_EQ: "UHADD16.EQ",
+ UHADD16_NE: "UHADD16.NE",
+ UHADD16_CS: "UHADD16.CS",
+ UHADD16_CC: "UHADD16.CC",
+ UHADD16_MI: "UHADD16.MI",
+ UHADD16_PL: "UHADD16.PL",
+ UHADD16_VS: "UHADD16.VS",
+ UHADD16_VC: "UHADD16.VC",
+ UHADD16_HI: "UHADD16.HI",
+ UHADD16_LS: "UHADD16.LS",
+ UHADD16_GE: "UHADD16.GE",
+ UHADD16_LT: "UHADD16.LT",
+ UHADD16_GT: "UHADD16.GT",
+ UHADD16_LE: "UHADD16.LE",
+ UHADD16: "UHADD16",
+ UHADD16_ZZ: "UHADD16.ZZ",
+ UHADD8_EQ: "UHADD8.EQ",
+ UHADD8_NE: "UHADD8.NE",
+ UHADD8_CS: "UHADD8.CS",
+ UHADD8_CC: "UHADD8.CC",
+ UHADD8_MI: "UHADD8.MI",
+ UHADD8_PL: "UHADD8.PL",
+ UHADD8_VS: "UHADD8.VS",
+ UHADD8_VC: "UHADD8.VC",
+ UHADD8_HI: "UHADD8.HI",
+ UHADD8_LS: "UHADD8.LS",
+ UHADD8_GE: "UHADD8.GE",
+ UHADD8_LT: "UHADD8.LT",
+ UHADD8_GT: "UHADD8.GT",
+ UHADD8_LE: "UHADD8.LE",
+ UHADD8: "UHADD8",
+ UHADD8_ZZ: "UHADD8.ZZ",
+ UHASX_EQ: "UHASX.EQ",
+ UHASX_NE: "UHASX.NE",
+ UHASX_CS: "UHASX.CS",
+ UHASX_CC: "UHASX.CC",
+ UHASX_MI: "UHASX.MI",
+ UHASX_PL: "UHASX.PL",
+ UHASX_VS: "UHASX.VS",
+ UHASX_VC: "UHASX.VC",
+ UHASX_HI: "UHASX.HI",
+ UHASX_LS: "UHASX.LS",
+ UHASX_GE: "UHASX.GE",
+ UHASX_LT: "UHASX.LT",
+ UHASX_GT: "UHASX.GT",
+ UHASX_LE: "UHASX.LE",
+ UHASX: "UHASX",
+ UHASX_ZZ: "UHASX.ZZ",
+ UHSAX_EQ: "UHSAX.EQ",
+ UHSAX_NE: "UHSAX.NE",
+ UHSAX_CS: "UHSAX.CS",
+ UHSAX_CC: "UHSAX.CC",
+ UHSAX_MI: "UHSAX.MI",
+ UHSAX_PL: "UHSAX.PL",
+ UHSAX_VS: "UHSAX.VS",
+ UHSAX_VC: "UHSAX.VC",
+ UHSAX_HI: "UHSAX.HI",
+ UHSAX_LS: "UHSAX.LS",
+ UHSAX_GE: "UHSAX.GE",
+ UHSAX_LT: "UHSAX.LT",
+ UHSAX_GT: "UHSAX.GT",
+ UHSAX_LE: "UHSAX.LE",
+ UHSAX: "UHSAX",
+ UHSAX_ZZ: "UHSAX.ZZ",
+ UHSUB16_EQ: "UHSUB16.EQ",
+ UHSUB16_NE: "UHSUB16.NE",
+ UHSUB16_CS: "UHSUB16.CS",
+ UHSUB16_CC: "UHSUB16.CC",
+ UHSUB16_MI: "UHSUB16.MI",
+ UHSUB16_PL: "UHSUB16.PL",
+ UHSUB16_VS: "UHSUB16.VS",
+ UHSUB16_VC: "UHSUB16.VC",
+ UHSUB16_HI: "UHSUB16.HI",
+ UHSUB16_LS: "UHSUB16.LS",
+ UHSUB16_GE: "UHSUB16.GE",
+ UHSUB16_LT: "UHSUB16.LT",
+ UHSUB16_GT: "UHSUB16.GT",
+ UHSUB16_LE: "UHSUB16.LE",
+ UHSUB16: "UHSUB16",
+ UHSUB16_ZZ: "UHSUB16.ZZ",
+ UHSUB8_EQ: "UHSUB8.EQ",
+ UHSUB8_NE: "UHSUB8.NE",
+ UHSUB8_CS: "UHSUB8.CS",
+ UHSUB8_CC: "UHSUB8.CC",
+ UHSUB8_MI: "UHSUB8.MI",
+ UHSUB8_PL: "UHSUB8.PL",
+ UHSUB8_VS: "UHSUB8.VS",
+ UHSUB8_VC: "UHSUB8.VC",
+ UHSUB8_HI: "UHSUB8.HI",
+ UHSUB8_LS: "UHSUB8.LS",
+ UHSUB8_GE: "UHSUB8.GE",
+ UHSUB8_LT: "UHSUB8.LT",
+ UHSUB8_GT: "UHSUB8.GT",
+ UHSUB8_LE: "UHSUB8.LE",
+ UHSUB8: "UHSUB8",
+ UHSUB8_ZZ: "UHSUB8.ZZ",
+ UMAAL_EQ: "UMAAL.EQ",
+ UMAAL_NE: "UMAAL.NE",
+ UMAAL_CS: "UMAAL.CS",
+ UMAAL_CC: "UMAAL.CC",
+ UMAAL_MI: "UMAAL.MI",
+ UMAAL_PL: "UMAAL.PL",
+ UMAAL_VS: "UMAAL.VS",
+ UMAAL_VC: "UMAAL.VC",
+ UMAAL_HI: "UMAAL.HI",
+ UMAAL_LS: "UMAAL.LS",
+ UMAAL_GE: "UMAAL.GE",
+ UMAAL_LT: "UMAAL.LT",
+ UMAAL_GT: "UMAAL.GT",
+ UMAAL_LE: "UMAAL.LE",
+ UMAAL: "UMAAL",
+ UMAAL_ZZ: "UMAAL.ZZ",
+ UMLAL_EQ: "UMLAL.EQ",
+ UMLAL_NE: "UMLAL.NE",
+ UMLAL_CS: "UMLAL.CS",
+ UMLAL_CC: "UMLAL.CC",
+ UMLAL_MI: "UMLAL.MI",
+ UMLAL_PL: "UMLAL.PL",
+ UMLAL_VS: "UMLAL.VS",
+ UMLAL_VC: "UMLAL.VC",
+ UMLAL_HI: "UMLAL.HI",
+ UMLAL_LS: "UMLAL.LS",
+ UMLAL_GE: "UMLAL.GE",
+ UMLAL_LT: "UMLAL.LT",
+ UMLAL_GT: "UMLAL.GT",
+ UMLAL_LE: "UMLAL.LE",
+ UMLAL: "UMLAL",
+ UMLAL_ZZ: "UMLAL.ZZ",
+ UMLAL_S_EQ: "UMLAL.S.EQ",
+ UMLAL_S_NE: "UMLAL.S.NE",
+ UMLAL_S_CS: "UMLAL.S.CS",
+ UMLAL_S_CC: "UMLAL.S.CC",
+ UMLAL_S_MI: "UMLAL.S.MI",
+ UMLAL_S_PL: "UMLAL.S.PL",
+ UMLAL_S_VS: "UMLAL.S.VS",
+ UMLAL_S_VC: "UMLAL.S.VC",
+ UMLAL_S_HI: "UMLAL.S.HI",
+ UMLAL_S_LS: "UMLAL.S.LS",
+ UMLAL_S_GE: "UMLAL.S.GE",
+ UMLAL_S_LT: "UMLAL.S.LT",
+ UMLAL_S_GT: "UMLAL.S.GT",
+ UMLAL_S_LE: "UMLAL.S.LE",
+ UMLAL_S: "UMLAL.S",
+ UMLAL_S_ZZ: "UMLAL.S.ZZ",
+ UMULL_EQ: "UMULL.EQ",
+ UMULL_NE: "UMULL.NE",
+ UMULL_CS: "UMULL.CS",
+ UMULL_CC: "UMULL.CC",
+ UMULL_MI: "UMULL.MI",
+ UMULL_PL: "UMULL.PL",
+ UMULL_VS: "UMULL.VS",
+ UMULL_VC: "UMULL.VC",
+ UMULL_HI: "UMULL.HI",
+ UMULL_LS: "UMULL.LS",
+ UMULL_GE: "UMULL.GE",
+ UMULL_LT: "UMULL.LT",
+ UMULL_GT: "UMULL.GT",
+ UMULL_LE: "UMULL.LE",
+ UMULL: "UMULL",
+ UMULL_ZZ: "UMULL.ZZ",
+ UMULL_S_EQ: "UMULL.S.EQ",
+ UMULL_S_NE: "UMULL.S.NE",
+ UMULL_S_CS: "UMULL.S.CS",
+ UMULL_S_CC: "UMULL.S.CC",
+ UMULL_S_MI: "UMULL.S.MI",
+ UMULL_S_PL: "UMULL.S.PL",
+ UMULL_S_VS: "UMULL.S.VS",
+ UMULL_S_VC: "UMULL.S.VC",
+ UMULL_S_HI: "UMULL.S.HI",
+ UMULL_S_LS: "UMULL.S.LS",
+ UMULL_S_GE: "UMULL.S.GE",
+ UMULL_S_LT: "UMULL.S.LT",
+ UMULL_S_GT: "UMULL.S.GT",
+ UMULL_S_LE: "UMULL.S.LE",
+ UMULL_S: "UMULL.S",
+ UMULL_S_ZZ: "UMULL.S.ZZ",
+ UNDEF: "UNDEF",
+ UQADD16_EQ: "UQADD16.EQ",
+ UQADD16_NE: "UQADD16.NE",
+ UQADD16_CS: "UQADD16.CS",
+ UQADD16_CC: "UQADD16.CC",
+ UQADD16_MI: "UQADD16.MI",
+ UQADD16_PL: "UQADD16.PL",
+ UQADD16_VS: "UQADD16.VS",
+ UQADD16_VC: "UQADD16.VC",
+ UQADD16_HI: "UQADD16.HI",
+ UQADD16_LS: "UQADD16.LS",
+ UQADD16_GE: "UQADD16.GE",
+ UQADD16_LT: "UQADD16.LT",
+ UQADD16_GT: "UQADD16.GT",
+ UQADD16_LE: "UQADD16.LE",
+ UQADD16: "UQADD16",
+ UQADD16_ZZ: "UQADD16.ZZ",
+ UQADD8_EQ: "UQADD8.EQ",
+ UQADD8_NE: "UQADD8.NE",
+ UQADD8_CS: "UQADD8.CS",
+ UQADD8_CC: "UQADD8.CC",
+ UQADD8_MI: "UQADD8.MI",
+ UQADD8_PL: "UQADD8.PL",
+ UQADD8_VS: "UQADD8.VS",
+ UQADD8_VC: "UQADD8.VC",
+ UQADD8_HI: "UQADD8.HI",
+ UQADD8_LS: "UQADD8.LS",
+ UQADD8_GE: "UQADD8.GE",
+ UQADD8_LT: "UQADD8.LT",
+ UQADD8_GT: "UQADD8.GT",
+ UQADD8_LE: "UQADD8.LE",
+ UQADD8: "UQADD8",
+ UQADD8_ZZ: "UQADD8.ZZ",
+ UQASX_EQ: "UQASX.EQ",
+ UQASX_NE: "UQASX.NE",
+ UQASX_CS: "UQASX.CS",
+ UQASX_CC: "UQASX.CC",
+ UQASX_MI: "UQASX.MI",
+ UQASX_PL: "UQASX.PL",
+ UQASX_VS: "UQASX.VS",
+ UQASX_VC: "UQASX.VC",
+ UQASX_HI: "UQASX.HI",
+ UQASX_LS: "UQASX.LS",
+ UQASX_GE: "UQASX.GE",
+ UQASX_LT: "UQASX.LT",
+ UQASX_GT: "UQASX.GT",
+ UQASX_LE: "UQASX.LE",
+ UQASX: "UQASX",
+ UQASX_ZZ: "UQASX.ZZ",
+ UQSAX_EQ: "UQSAX.EQ",
+ UQSAX_NE: "UQSAX.NE",
+ UQSAX_CS: "UQSAX.CS",
+ UQSAX_CC: "UQSAX.CC",
+ UQSAX_MI: "UQSAX.MI",
+ UQSAX_PL: "UQSAX.PL",
+ UQSAX_VS: "UQSAX.VS",
+ UQSAX_VC: "UQSAX.VC",
+ UQSAX_HI: "UQSAX.HI",
+ UQSAX_LS: "UQSAX.LS",
+ UQSAX_GE: "UQSAX.GE",
+ UQSAX_LT: "UQSAX.LT",
+ UQSAX_GT: "UQSAX.GT",
+ UQSAX_LE: "UQSAX.LE",
+ UQSAX: "UQSAX",
+ UQSAX_ZZ: "UQSAX.ZZ",
+ UQSUB16_EQ: "UQSUB16.EQ",
+ UQSUB16_NE: "UQSUB16.NE",
+ UQSUB16_CS: "UQSUB16.CS",
+ UQSUB16_CC: "UQSUB16.CC",
+ UQSUB16_MI: "UQSUB16.MI",
+ UQSUB16_PL: "UQSUB16.PL",
+ UQSUB16_VS: "UQSUB16.VS",
+ UQSUB16_VC: "UQSUB16.VC",
+ UQSUB16_HI: "UQSUB16.HI",
+ UQSUB16_LS: "UQSUB16.LS",
+ UQSUB16_GE: "UQSUB16.GE",
+ UQSUB16_LT: "UQSUB16.LT",
+ UQSUB16_GT: "UQSUB16.GT",
+ UQSUB16_LE: "UQSUB16.LE",
+ UQSUB16: "UQSUB16",
+ UQSUB16_ZZ: "UQSUB16.ZZ",
+ UQSUB8_EQ: "UQSUB8.EQ",
+ UQSUB8_NE: "UQSUB8.NE",
+ UQSUB8_CS: "UQSUB8.CS",
+ UQSUB8_CC: "UQSUB8.CC",
+ UQSUB8_MI: "UQSUB8.MI",
+ UQSUB8_PL: "UQSUB8.PL",
+ UQSUB8_VS: "UQSUB8.VS",
+ UQSUB8_VC: "UQSUB8.VC",
+ UQSUB8_HI: "UQSUB8.HI",
+ UQSUB8_LS: "UQSUB8.LS",
+ UQSUB8_GE: "UQSUB8.GE",
+ UQSUB8_LT: "UQSUB8.LT",
+ UQSUB8_GT: "UQSUB8.GT",
+ UQSUB8_LE: "UQSUB8.LE",
+ UQSUB8: "UQSUB8",
+ UQSUB8_ZZ: "UQSUB8.ZZ",
+ USAD8_EQ: "USAD8.EQ",
+ USAD8_NE: "USAD8.NE",
+ USAD8_CS: "USAD8.CS",
+ USAD8_CC: "USAD8.CC",
+ USAD8_MI: "USAD8.MI",
+ USAD8_PL: "USAD8.PL",
+ USAD8_VS: "USAD8.VS",
+ USAD8_VC: "USAD8.VC",
+ USAD8_HI: "USAD8.HI",
+ USAD8_LS: "USAD8.LS",
+ USAD8_GE: "USAD8.GE",
+ USAD8_LT: "USAD8.LT",
+ USAD8_GT: "USAD8.GT",
+ USAD8_LE: "USAD8.LE",
+ USAD8: "USAD8",
+ USAD8_ZZ: "USAD8.ZZ",
+ USADA8_EQ: "USADA8.EQ",
+ USADA8_NE: "USADA8.NE",
+ USADA8_CS: "USADA8.CS",
+ USADA8_CC: "USADA8.CC",
+ USADA8_MI: "USADA8.MI",
+ USADA8_PL: "USADA8.PL",
+ USADA8_VS: "USADA8.VS",
+ USADA8_VC: "USADA8.VC",
+ USADA8_HI: "USADA8.HI",
+ USADA8_LS: "USADA8.LS",
+ USADA8_GE: "USADA8.GE",
+ USADA8_LT: "USADA8.LT",
+ USADA8_GT: "USADA8.GT",
+ USADA8_LE: "USADA8.LE",
+ USADA8: "USADA8",
+ USADA8_ZZ: "USADA8.ZZ",
+ USAT_EQ: "USAT.EQ",
+ USAT_NE: "USAT.NE",
+ USAT_CS: "USAT.CS",
+ USAT_CC: "USAT.CC",
+ USAT_MI: "USAT.MI",
+ USAT_PL: "USAT.PL",
+ USAT_VS: "USAT.VS",
+ USAT_VC: "USAT.VC",
+ USAT_HI: "USAT.HI",
+ USAT_LS: "USAT.LS",
+ USAT_GE: "USAT.GE",
+ USAT_LT: "USAT.LT",
+ USAT_GT: "USAT.GT",
+ USAT_LE: "USAT.LE",
+ USAT: "USAT",
+ USAT_ZZ: "USAT.ZZ",
+ USAT16_EQ: "USAT16.EQ",
+ USAT16_NE: "USAT16.NE",
+ USAT16_CS: "USAT16.CS",
+ USAT16_CC: "USAT16.CC",
+ USAT16_MI: "USAT16.MI",
+ USAT16_PL: "USAT16.PL",
+ USAT16_VS: "USAT16.VS",
+ USAT16_VC: "USAT16.VC",
+ USAT16_HI: "USAT16.HI",
+ USAT16_LS: "USAT16.LS",
+ USAT16_GE: "USAT16.GE",
+ USAT16_LT: "USAT16.LT",
+ USAT16_GT: "USAT16.GT",
+ USAT16_LE: "USAT16.LE",
+ USAT16: "USAT16",
+ USAT16_ZZ: "USAT16.ZZ",
+ USAX_EQ: "USAX.EQ",
+ USAX_NE: "USAX.NE",
+ USAX_CS: "USAX.CS",
+ USAX_CC: "USAX.CC",
+ USAX_MI: "USAX.MI",
+ USAX_PL: "USAX.PL",
+ USAX_VS: "USAX.VS",
+ USAX_VC: "USAX.VC",
+ USAX_HI: "USAX.HI",
+ USAX_LS: "USAX.LS",
+ USAX_GE: "USAX.GE",
+ USAX_LT: "USAX.LT",
+ USAX_GT: "USAX.GT",
+ USAX_LE: "USAX.LE",
+ USAX: "USAX",
+ USAX_ZZ: "USAX.ZZ",
+ USUB16_EQ: "USUB16.EQ",
+ USUB16_NE: "USUB16.NE",
+ USUB16_CS: "USUB16.CS",
+ USUB16_CC: "USUB16.CC",
+ USUB16_MI: "USUB16.MI",
+ USUB16_PL: "USUB16.PL",
+ USUB16_VS: "USUB16.VS",
+ USUB16_VC: "USUB16.VC",
+ USUB16_HI: "USUB16.HI",
+ USUB16_LS: "USUB16.LS",
+ USUB16_GE: "USUB16.GE",
+ USUB16_LT: "USUB16.LT",
+ USUB16_GT: "USUB16.GT",
+ USUB16_LE: "USUB16.LE",
+ USUB16: "USUB16",
+ USUB16_ZZ: "USUB16.ZZ",
+ USUB8_EQ: "USUB8.EQ",
+ USUB8_NE: "USUB8.NE",
+ USUB8_CS: "USUB8.CS",
+ USUB8_CC: "USUB8.CC",
+ USUB8_MI: "USUB8.MI",
+ USUB8_PL: "USUB8.PL",
+ USUB8_VS: "USUB8.VS",
+ USUB8_VC: "USUB8.VC",
+ USUB8_HI: "USUB8.HI",
+ USUB8_LS: "USUB8.LS",
+ USUB8_GE: "USUB8.GE",
+ USUB8_LT: "USUB8.LT",
+ USUB8_GT: "USUB8.GT",
+ USUB8_LE: "USUB8.LE",
+ USUB8: "USUB8",
+ USUB8_ZZ: "USUB8.ZZ",
+ UXTAB_EQ: "UXTAB.EQ",
+ UXTAB_NE: "UXTAB.NE",
+ UXTAB_CS: "UXTAB.CS",
+ UXTAB_CC: "UXTAB.CC",
+ UXTAB_MI: "UXTAB.MI",
+ UXTAB_PL: "UXTAB.PL",
+ UXTAB_VS: "UXTAB.VS",
+ UXTAB_VC: "UXTAB.VC",
+ UXTAB_HI: "UXTAB.HI",
+ UXTAB_LS: "UXTAB.LS",
+ UXTAB_GE: "UXTAB.GE",
+ UXTAB_LT: "UXTAB.LT",
+ UXTAB_GT: "UXTAB.GT",
+ UXTAB_LE: "UXTAB.LE",
+ UXTAB: "UXTAB",
+ UXTAB_ZZ: "UXTAB.ZZ",
+ UXTAB16_EQ: "UXTAB16.EQ",
+ UXTAB16_NE: "UXTAB16.NE",
+ UXTAB16_CS: "UXTAB16.CS",
+ UXTAB16_CC: "UXTAB16.CC",
+ UXTAB16_MI: "UXTAB16.MI",
+ UXTAB16_PL: "UXTAB16.PL",
+ UXTAB16_VS: "UXTAB16.VS",
+ UXTAB16_VC: "UXTAB16.VC",
+ UXTAB16_HI: "UXTAB16.HI",
+ UXTAB16_LS: "UXTAB16.LS",
+ UXTAB16_GE: "UXTAB16.GE",
+ UXTAB16_LT: "UXTAB16.LT",
+ UXTAB16_GT: "UXTAB16.GT",
+ UXTAB16_LE: "UXTAB16.LE",
+ UXTAB16: "UXTAB16",
+ UXTAB16_ZZ: "UXTAB16.ZZ",
+ UXTAH_EQ: "UXTAH.EQ",
+ UXTAH_NE: "UXTAH.NE",
+ UXTAH_CS: "UXTAH.CS",
+ UXTAH_CC: "UXTAH.CC",
+ UXTAH_MI: "UXTAH.MI",
+ UXTAH_PL: "UXTAH.PL",
+ UXTAH_VS: "UXTAH.VS",
+ UXTAH_VC: "UXTAH.VC",
+ UXTAH_HI: "UXTAH.HI",
+ UXTAH_LS: "UXTAH.LS",
+ UXTAH_GE: "UXTAH.GE",
+ UXTAH_LT: "UXTAH.LT",
+ UXTAH_GT: "UXTAH.GT",
+ UXTAH_LE: "UXTAH.LE",
+ UXTAH: "UXTAH",
+ UXTAH_ZZ: "UXTAH.ZZ",
+ UXTB_EQ: "UXTB.EQ",
+ UXTB_NE: "UXTB.NE",
+ UXTB_CS: "UXTB.CS",
+ UXTB_CC: "UXTB.CC",
+ UXTB_MI: "UXTB.MI",
+ UXTB_PL: "UXTB.PL",
+ UXTB_VS: "UXTB.VS",
+ UXTB_VC: "UXTB.VC",
+ UXTB_HI: "UXTB.HI",
+ UXTB_LS: "UXTB.LS",
+ UXTB_GE: "UXTB.GE",
+ UXTB_LT: "UXTB.LT",
+ UXTB_GT: "UXTB.GT",
+ UXTB_LE: "UXTB.LE",
+ UXTB: "UXTB",
+ UXTB_ZZ: "UXTB.ZZ",
+ UXTB16_EQ: "UXTB16.EQ",
+ UXTB16_NE: "UXTB16.NE",
+ UXTB16_CS: "UXTB16.CS",
+ UXTB16_CC: "UXTB16.CC",
+ UXTB16_MI: "UXTB16.MI",
+ UXTB16_PL: "UXTB16.PL",
+ UXTB16_VS: "UXTB16.VS",
+ UXTB16_VC: "UXTB16.VC",
+ UXTB16_HI: "UXTB16.HI",
+ UXTB16_LS: "UXTB16.LS",
+ UXTB16_GE: "UXTB16.GE",
+ UXTB16_LT: "UXTB16.LT",
+ UXTB16_GT: "UXTB16.GT",
+ UXTB16_LE: "UXTB16.LE",
+ UXTB16: "UXTB16",
+ UXTB16_ZZ: "UXTB16.ZZ",
+ UXTH_EQ: "UXTH.EQ",
+ UXTH_NE: "UXTH.NE",
+ UXTH_CS: "UXTH.CS",
+ UXTH_CC: "UXTH.CC",
+ UXTH_MI: "UXTH.MI",
+ UXTH_PL: "UXTH.PL",
+ UXTH_VS: "UXTH.VS",
+ UXTH_VC: "UXTH.VC",
+ UXTH_HI: "UXTH.HI",
+ UXTH_LS: "UXTH.LS",
+ UXTH_GE: "UXTH.GE",
+ UXTH_LT: "UXTH.LT",
+ UXTH_GT: "UXTH.GT",
+ UXTH_LE: "UXTH.LE",
+ UXTH: "UXTH",
+ UXTH_ZZ: "UXTH.ZZ",
+ VABS_EQ_F32: "VABS.EQ.F32",
+ VABS_NE_F32: "VABS.NE.F32",
+ VABS_CS_F32: "VABS.CS.F32",
+ VABS_CC_F32: "VABS.CC.F32",
+ VABS_MI_F32: "VABS.MI.F32",
+ VABS_PL_F32: "VABS.PL.F32",
+ VABS_VS_F32: "VABS.VS.F32",
+ VABS_VC_F32: "VABS.VC.F32",
+ VABS_HI_F32: "VABS.HI.F32",
+ VABS_LS_F32: "VABS.LS.F32",
+ VABS_GE_F32: "VABS.GE.F32",
+ VABS_LT_F32: "VABS.LT.F32",
+ VABS_GT_F32: "VABS.GT.F32",
+ VABS_LE_F32: "VABS.LE.F32",
+ VABS_F32: "VABS.F32",
+ VABS_ZZ_F32: "VABS.ZZ.F32",
+ VABS_EQ_F64: "VABS.EQ.F64",
+ VABS_NE_F64: "VABS.NE.F64",
+ VABS_CS_F64: "VABS.CS.F64",
+ VABS_CC_F64: "VABS.CC.F64",
+ VABS_MI_F64: "VABS.MI.F64",
+ VABS_PL_F64: "VABS.PL.F64",
+ VABS_VS_F64: "VABS.VS.F64",
+ VABS_VC_F64: "VABS.VC.F64",
+ VABS_HI_F64: "VABS.HI.F64",
+ VABS_LS_F64: "VABS.LS.F64",
+ VABS_GE_F64: "VABS.GE.F64",
+ VABS_LT_F64: "VABS.LT.F64",
+ VABS_GT_F64: "VABS.GT.F64",
+ VABS_LE_F64: "VABS.LE.F64",
+ VABS_F64: "VABS.F64",
+ VABS_ZZ_F64: "VABS.ZZ.F64",
+ VADD_EQ_F32: "VADD.EQ.F32",
+ VADD_NE_F32: "VADD.NE.F32",
+ VADD_CS_F32: "VADD.CS.F32",
+ VADD_CC_F32: "VADD.CC.F32",
+ VADD_MI_F32: "VADD.MI.F32",
+ VADD_PL_F32: "VADD.PL.F32",
+ VADD_VS_F32: "VADD.VS.F32",
+ VADD_VC_F32: "VADD.VC.F32",
+ VADD_HI_F32: "VADD.HI.F32",
+ VADD_LS_F32: "VADD.LS.F32",
+ VADD_GE_F32: "VADD.GE.F32",
+ VADD_LT_F32: "VADD.LT.F32",
+ VADD_GT_F32: "VADD.GT.F32",
+ VADD_LE_F32: "VADD.LE.F32",
+ VADD_F32: "VADD.F32",
+ VADD_ZZ_F32: "VADD.ZZ.F32",
+ VADD_EQ_F64: "VADD.EQ.F64",
+ VADD_NE_F64: "VADD.NE.F64",
+ VADD_CS_F64: "VADD.CS.F64",
+ VADD_CC_F64: "VADD.CC.F64",
+ VADD_MI_F64: "VADD.MI.F64",
+ VADD_PL_F64: "VADD.PL.F64",
+ VADD_VS_F64: "VADD.VS.F64",
+ VADD_VC_F64: "VADD.VC.F64",
+ VADD_HI_F64: "VADD.HI.F64",
+ VADD_LS_F64: "VADD.LS.F64",
+ VADD_GE_F64: "VADD.GE.F64",
+ VADD_LT_F64: "VADD.LT.F64",
+ VADD_GT_F64: "VADD.GT.F64",
+ VADD_LE_F64: "VADD.LE.F64",
+ VADD_F64: "VADD.F64",
+ VADD_ZZ_F64: "VADD.ZZ.F64",
+ VCMP_EQ_F32: "VCMP.EQ.F32",
+ VCMP_NE_F32: "VCMP.NE.F32",
+ VCMP_CS_F32: "VCMP.CS.F32",
+ VCMP_CC_F32: "VCMP.CC.F32",
+ VCMP_MI_F32: "VCMP.MI.F32",
+ VCMP_PL_F32: "VCMP.PL.F32",
+ VCMP_VS_F32: "VCMP.VS.F32",
+ VCMP_VC_F32: "VCMP.VC.F32",
+ VCMP_HI_F32: "VCMP.HI.F32",
+ VCMP_LS_F32: "VCMP.LS.F32",
+ VCMP_GE_F32: "VCMP.GE.F32",
+ VCMP_LT_F32: "VCMP.LT.F32",
+ VCMP_GT_F32: "VCMP.GT.F32",
+ VCMP_LE_F32: "VCMP.LE.F32",
+ VCMP_F32: "VCMP.F32",
+ VCMP_ZZ_F32: "VCMP.ZZ.F32",
+ VCMP_EQ_F64: "VCMP.EQ.F64",
+ VCMP_NE_F64: "VCMP.NE.F64",
+ VCMP_CS_F64: "VCMP.CS.F64",
+ VCMP_CC_F64: "VCMP.CC.F64",
+ VCMP_MI_F64: "VCMP.MI.F64",
+ VCMP_PL_F64: "VCMP.PL.F64",
+ VCMP_VS_F64: "VCMP.VS.F64",
+ VCMP_VC_F64: "VCMP.VC.F64",
+ VCMP_HI_F64: "VCMP.HI.F64",
+ VCMP_LS_F64: "VCMP.LS.F64",
+ VCMP_GE_F64: "VCMP.GE.F64",
+ VCMP_LT_F64: "VCMP.LT.F64",
+ VCMP_GT_F64: "VCMP.GT.F64",
+ VCMP_LE_F64: "VCMP.LE.F64",
+ VCMP_F64: "VCMP.F64",
+ VCMP_ZZ_F64: "VCMP.ZZ.F64",
+ VCMP_E_EQ_F32: "VCMP.E.EQ.F32",
+ VCMP_E_NE_F32: "VCMP.E.NE.F32",
+ VCMP_E_CS_F32: "VCMP.E.CS.F32",
+ VCMP_E_CC_F32: "VCMP.E.CC.F32",
+ VCMP_E_MI_F32: "VCMP.E.MI.F32",
+ VCMP_E_PL_F32: "VCMP.E.PL.F32",
+ VCMP_E_VS_F32: "VCMP.E.VS.F32",
+ VCMP_E_VC_F32: "VCMP.E.VC.F32",
+ VCMP_E_HI_F32: "VCMP.E.HI.F32",
+ VCMP_E_LS_F32: "VCMP.E.LS.F32",
+ VCMP_E_GE_F32: "VCMP.E.GE.F32",
+ VCMP_E_LT_F32: "VCMP.E.LT.F32",
+ VCMP_E_GT_F32: "VCMP.E.GT.F32",
+ VCMP_E_LE_F32: "VCMP.E.LE.F32",
+ VCMP_E_F32: "VCMP.E.F32",
+ VCMP_E_ZZ_F32: "VCMP.E.ZZ.F32",
+ VCMP_E_EQ_F64: "VCMP.E.EQ.F64",
+ VCMP_E_NE_F64: "VCMP.E.NE.F64",
+ VCMP_E_CS_F64: "VCMP.E.CS.F64",
+ VCMP_E_CC_F64: "VCMP.E.CC.F64",
+ VCMP_E_MI_F64: "VCMP.E.MI.F64",
+ VCMP_E_PL_F64: "VCMP.E.PL.F64",
+ VCMP_E_VS_F64: "VCMP.E.VS.F64",
+ VCMP_E_VC_F64: "VCMP.E.VC.F64",
+ VCMP_E_HI_F64: "VCMP.E.HI.F64",
+ VCMP_E_LS_F64: "VCMP.E.LS.F64",
+ VCMP_E_GE_F64: "VCMP.E.GE.F64",
+ VCMP_E_LT_F64: "VCMP.E.LT.F64",
+ VCMP_E_GT_F64: "VCMP.E.GT.F64",
+ VCMP_E_LE_F64: "VCMP.E.LE.F64",
+ VCMP_E_F64: "VCMP.E.F64",
+ VCMP_E_ZZ_F64: "VCMP.E.ZZ.F64",
+ VCVT_EQ_F32_FXS16: "VCVT.EQ.F32.FXS16",
+ VCVT_NE_F32_FXS16: "VCVT.NE.F32.FXS16",
+ VCVT_CS_F32_FXS16: "VCVT.CS.F32.FXS16",
+ VCVT_CC_F32_FXS16: "VCVT.CC.F32.FXS16",
+ VCVT_MI_F32_FXS16: "VCVT.MI.F32.FXS16",
+ VCVT_PL_F32_FXS16: "VCVT.PL.F32.FXS16",
+ VCVT_VS_F32_FXS16: "VCVT.VS.F32.FXS16",
+ VCVT_VC_F32_FXS16: "VCVT.VC.F32.FXS16",
+ VCVT_HI_F32_FXS16: "VCVT.HI.F32.FXS16",
+ VCVT_LS_F32_FXS16: "VCVT.LS.F32.FXS16",
+ VCVT_GE_F32_FXS16: "VCVT.GE.F32.FXS16",
+ VCVT_LT_F32_FXS16: "VCVT.LT.F32.FXS16",
+ VCVT_GT_F32_FXS16: "VCVT.GT.F32.FXS16",
+ VCVT_LE_F32_FXS16: "VCVT.LE.F32.FXS16",
+ VCVT_F32_FXS16: "VCVT.F32.FXS16",
+ VCVT_ZZ_F32_FXS16: "VCVT.ZZ.F32.FXS16",
+ VCVT_EQ_F32_FXS32: "VCVT.EQ.F32.FXS32",
+ VCVT_NE_F32_FXS32: "VCVT.NE.F32.FXS32",
+ VCVT_CS_F32_FXS32: "VCVT.CS.F32.FXS32",
+ VCVT_CC_F32_FXS32: "VCVT.CC.F32.FXS32",
+ VCVT_MI_F32_FXS32: "VCVT.MI.F32.FXS32",
+ VCVT_PL_F32_FXS32: "VCVT.PL.F32.FXS32",
+ VCVT_VS_F32_FXS32: "VCVT.VS.F32.FXS32",
+ VCVT_VC_F32_FXS32: "VCVT.VC.F32.FXS32",
+ VCVT_HI_F32_FXS32: "VCVT.HI.F32.FXS32",
+ VCVT_LS_F32_FXS32: "VCVT.LS.F32.FXS32",
+ VCVT_GE_F32_FXS32: "VCVT.GE.F32.FXS32",
+ VCVT_LT_F32_FXS32: "VCVT.LT.F32.FXS32",
+ VCVT_GT_F32_FXS32: "VCVT.GT.F32.FXS32",
+ VCVT_LE_F32_FXS32: "VCVT.LE.F32.FXS32",
+ VCVT_F32_FXS32: "VCVT.F32.FXS32",
+ VCVT_ZZ_F32_FXS32: "VCVT.ZZ.F32.FXS32",
+ VCVT_EQ_F32_FXU16: "VCVT.EQ.F32.FXU16",
+ VCVT_NE_F32_FXU16: "VCVT.NE.F32.FXU16",
+ VCVT_CS_F32_FXU16: "VCVT.CS.F32.FXU16",
+ VCVT_CC_F32_FXU16: "VCVT.CC.F32.FXU16",
+ VCVT_MI_F32_FXU16: "VCVT.MI.F32.FXU16",
+ VCVT_PL_F32_FXU16: "VCVT.PL.F32.FXU16",
+ VCVT_VS_F32_FXU16: "VCVT.VS.F32.FXU16",
+ VCVT_VC_F32_FXU16: "VCVT.VC.F32.FXU16",
+ VCVT_HI_F32_FXU16: "VCVT.HI.F32.FXU16",
+ VCVT_LS_F32_FXU16: "VCVT.LS.F32.FXU16",
+ VCVT_GE_F32_FXU16: "VCVT.GE.F32.FXU16",
+ VCVT_LT_F32_FXU16: "VCVT.LT.F32.FXU16",
+ VCVT_GT_F32_FXU16: "VCVT.GT.F32.FXU16",
+ VCVT_LE_F32_FXU16: "VCVT.LE.F32.FXU16",
+ VCVT_F32_FXU16: "VCVT.F32.FXU16",
+ VCVT_ZZ_F32_FXU16: "VCVT.ZZ.F32.FXU16",
+ VCVT_EQ_F32_FXU32: "VCVT.EQ.F32.FXU32",
+ VCVT_NE_F32_FXU32: "VCVT.NE.F32.FXU32",
+ VCVT_CS_F32_FXU32: "VCVT.CS.F32.FXU32",
+ VCVT_CC_F32_FXU32: "VCVT.CC.F32.FXU32",
+ VCVT_MI_F32_FXU32: "VCVT.MI.F32.FXU32",
+ VCVT_PL_F32_FXU32: "VCVT.PL.F32.FXU32",
+ VCVT_VS_F32_FXU32: "VCVT.VS.F32.FXU32",
+ VCVT_VC_F32_FXU32: "VCVT.VC.F32.FXU32",
+ VCVT_HI_F32_FXU32: "VCVT.HI.F32.FXU32",
+ VCVT_LS_F32_FXU32: "VCVT.LS.F32.FXU32",
+ VCVT_GE_F32_FXU32: "VCVT.GE.F32.FXU32",
+ VCVT_LT_F32_FXU32: "VCVT.LT.F32.FXU32",
+ VCVT_GT_F32_FXU32: "VCVT.GT.F32.FXU32",
+ VCVT_LE_F32_FXU32: "VCVT.LE.F32.FXU32",
+ VCVT_F32_FXU32: "VCVT.F32.FXU32",
+ VCVT_ZZ_F32_FXU32: "VCVT.ZZ.F32.FXU32",
+ VCVT_EQ_F64_FXS16: "VCVT.EQ.F64.FXS16",
+ VCVT_NE_F64_FXS16: "VCVT.NE.F64.FXS16",
+ VCVT_CS_F64_FXS16: "VCVT.CS.F64.FXS16",
+ VCVT_CC_F64_FXS16: "VCVT.CC.F64.FXS16",
+ VCVT_MI_F64_FXS16: "VCVT.MI.F64.FXS16",
+ VCVT_PL_F64_FXS16: "VCVT.PL.F64.FXS16",
+ VCVT_VS_F64_FXS16: "VCVT.VS.F64.FXS16",
+ VCVT_VC_F64_FXS16: "VCVT.VC.F64.FXS16",
+ VCVT_HI_F64_FXS16: "VCVT.HI.F64.FXS16",
+ VCVT_LS_F64_FXS16: "VCVT.LS.F64.FXS16",
+ VCVT_GE_F64_FXS16: "VCVT.GE.F64.FXS16",
+ VCVT_LT_F64_FXS16: "VCVT.LT.F64.FXS16",
+ VCVT_GT_F64_FXS16: "VCVT.GT.F64.FXS16",
+ VCVT_LE_F64_FXS16: "VCVT.LE.F64.FXS16",
+ VCVT_F64_FXS16: "VCVT.F64.FXS16",
+ VCVT_ZZ_F64_FXS16: "VCVT.ZZ.F64.FXS16",
+ VCVT_EQ_F64_FXS32: "VCVT.EQ.F64.FXS32",
+ VCVT_NE_F64_FXS32: "VCVT.NE.F64.FXS32",
+ VCVT_CS_F64_FXS32: "VCVT.CS.F64.FXS32",
+ VCVT_CC_F64_FXS32: "VCVT.CC.F64.FXS32",
+ VCVT_MI_F64_FXS32: "VCVT.MI.F64.FXS32",
+ VCVT_PL_F64_FXS32: "VCVT.PL.F64.FXS32",
+ VCVT_VS_F64_FXS32: "VCVT.VS.F64.FXS32",
+ VCVT_VC_F64_FXS32: "VCVT.VC.F64.FXS32",
+ VCVT_HI_F64_FXS32: "VCVT.HI.F64.FXS32",
+ VCVT_LS_F64_FXS32: "VCVT.LS.F64.FXS32",
+ VCVT_GE_F64_FXS32: "VCVT.GE.F64.FXS32",
+ VCVT_LT_F64_FXS32: "VCVT.LT.F64.FXS32",
+ VCVT_GT_F64_FXS32: "VCVT.GT.F64.FXS32",
+ VCVT_LE_F64_FXS32: "VCVT.LE.F64.FXS32",
+ VCVT_F64_FXS32: "VCVT.F64.FXS32",
+ VCVT_ZZ_F64_FXS32: "VCVT.ZZ.F64.FXS32",
+ VCVT_EQ_F64_FXU16: "VCVT.EQ.F64.FXU16",
+ VCVT_NE_F64_FXU16: "VCVT.NE.F64.FXU16",
+ VCVT_CS_F64_FXU16: "VCVT.CS.F64.FXU16",
+ VCVT_CC_F64_FXU16: "VCVT.CC.F64.FXU16",
+ VCVT_MI_F64_FXU16: "VCVT.MI.F64.FXU16",
+ VCVT_PL_F64_FXU16: "VCVT.PL.F64.FXU16",
+ VCVT_VS_F64_FXU16: "VCVT.VS.F64.FXU16",
+ VCVT_VC_F64_FXU16: "VCVT.VC.F64.FXU16",
+ VCVT_HI_F64_FXU16: "VCVT.HI.F64.FXU16",
+ VCVT_LS_F64_FXU16: "VCVT.LS.F64.FXU16",
+ VCVT_GE_F64_FXU16: "VCVT.GE.F64.FXU16",
+ VCVT_LT_F64_FXU16: "VCVT.LT.F64.FXU16",
+ VCVT_GT_F64_FXU16: "VCVT.GT.F64.FXU16",
+ VCVT_LE_F64_FXU16: "VCVT.LE.F64.FXU16",
+ VCVT_F64_FXU16: "VCVT.F64.FXU16",
+ VCVT_ZZ_F64_FXU16: "VCVT.ZZ.F64.FXU16",
+ VCVT_EQ_F64_FXU32: "VCVT.EQ.F64.FXU32",
+ VCVT_NE_F64_FXU32: "VCVT.NE.F64.FXU32",
+ VCVT_CS_F64_FXU32: "VCVT.CS.F64.FXU32",
+ VCVT_CC_F64_FXU32: "VCVT.CC.F64.FXU32",
+ VCVT_MI_F64_FXU32: "VCVT.MI.F64.FXU32",
+ VCVT_PL_F64_FXU32: "VCVT.PL.F64.FXU32",
+ VCVT_VS_F64_FXU32: "VCVT.VS.F64.FXU32",
+ VCVT_VC_F64_FXU32: "VCVT.VC.F64.FXU32",
+ VCVT_HI_F64_FXU32: "VCVT.HI.F64.FXU32",
+ VCVT_LS_F64_FXU32: "VCVT.LS.F64.FXU32",
+ VCVT_GE_F64_FXU32: "VCVT.GE.F64.FXU32",
+ VCVT_LT_F64_FXU32: "VCVT.LT.F64.FXU32",
+ VCVT_GT_F64_FXU32: "VCVT.GT.F64.FXU32",
+ VCVT_LE_F64_FXU32: "VCVT.LE.F64.FXU32",
+ VCVT_F64_FXU32: "VCVT.F64.FXU32",
+ VCVT_ZZ_F64_FXU32: "VCVT.ZZ.F64.FXU32",
+ VCVT_EQ_F32_U32: "VCVT.EQ.F32.U32",
+ VCVT_NE_F32_U32: "VCVT.NE.F32.U32",
+ VCVT_CS_F32_U32: "VCVT.CS.F32.U32",
+ VCVT_CC_F32_U32: "VCVT.CC.F32.U32",
+ VCVT_MI_F32_U32: "VCVT.MI.F32.U32",
+ VCVT_PL_F32_U32: "VCVT.PL.F32.U32",
+ VCVT_VS_F32_U32: "VCVT.VS.F32.U32",
+ VCVT_VC_F32_U32: "VCVT.VC.F32.U32",
+ VCVT_HI_F32_U32: "VCVT.HI.F32.U32",
+ VCVT_LS_F32_U32: "VCVT.LS.F32.U32",
+ VCVT_GE_F32_U32: "VCVT.GE.F32.U32",
+ VCVT_LT_F32_U32: "VCVT.LT.F32.U32",
+ VCVT_GT_F32_U32: "VCVT.GT.F32.U32",
+ VCVT_LE_F32_U32: "VCVT.LE.F32.U32",
+ VCVT_F32_U32: "VCVT.F32.U32",
+ VCVT_ZZ_F32_U32: "VCVT.ZZ.F32.U32",
+ VCVT_EQ_F32_S32: "VCVT.EQ.F32.S32",
+ VCVT_NE_F32_S32: "VCVT.NE.F32.S32",
+ VCVT_CS_F32_S32: "VCVT.CS.F32.S32",
+ VCVT_CC_F32_S32: "VCVT.CC.F32.S32",
+ VCVT_MI_F32_S32: "VCVT.MI.F32.S32",
+ VCVT_PL_F32_S32: "VCVT.PL.F32.S32",
+ VCVT_VS_F32_S32: "VCVT.VS.F32.S32",
+ VCVT_VC_F32_S32: "VCVT.VC.F32.S32",
+ VCVT_HI_F32_S32: "VCVT.HI.F32.S32",
+ VCVT_LS_F32_S32: "VCVT.LS.F32.S32",
+ VCVT_GE_F32_S32: "VCVT.GE.F32.S32",
+ VCVT_LT_F32_S32: "VCVT.LT.F32.S32",
+ VCVT_GT_F32_S32: "VCVT.GT.F32.S32",
+ VCVT_LE_F32_S32: "VCVT.LE.F32.S32",
+ VCVT_F32_S32: "VCVT.F32.S32",
+ VCVT_ZZ_F32_S32: "VCVT.ZZ.F32.S32",
+ VCVT_EQ_F64_U32: "VCVT.EQ.F64.U32",
+ VCVT_NE_F64_U32: "VCVT.NE.F64.U32",
+ VCVT_CS_F64_U32: "VCVT.CS.F64.U32",
+ VCVT_CC_F64_U32: "VCVT.CC.F64.U32",
+ VCVT_MI_F64_U32: "VCVT.MI.F64.U32",
+ VCVT_PL_F64_U32: "VCVT.PL.F64.U32",
+ VCVT_VS_F64_U32: "VCVT.VS.F64.U32",
+ VCVT_VC_F64_U32: "VCVT.VC.F64.U32",
+ VCVT_HI_F64_U32: "VCVT.HI.F64.U32",
+ VCVT_LS_F64_U32: "VCVT.LS.F64.U32",
+ VCVT_GE_F64_U32: "VCVT.GE.F64.U32",
+ VCVT_LT_F64_U32: "VCVT.LT.F64.U32",
+ VCVT_GT_F64_U32: "VCVT.GT.F64.U32",
+ VCVT_LE_F64_U32: "VCVT.LE.F64.U32",
+ VCVT_F64_U32: "VCVT.F64.U32",
+ VCVT_ZZ_F64_U32: "VCVT.ZZ.F64.U32",
+ VCVT_EQ_F64_S32: "VCVT.EQ.F64.S32",
+ VCVT_NE_F64_S32: "VCVT.NE.F64.S32",
+ VCVT_CS_F64_S32: "VCVT.CS.F64.S32",
+ VCVT_CC_F64_S32: "VCVT.CC.F64.S32",
+ VCVT_MI_F64_S32: "VCVT.MI.F64.S32",
+ VCVT_PL_F64_S32: "VCVT.PL.F64.S32",
+ VCVT_VS_F64_S32: "VCVT.VS.F64.S32",
+ VCVT_VC_F64_S32: "VCVT.VC.F64.S32",
+ VCVT_HI_F64_S32: "VCVT.HI.F64.S32",
+ VCVT_LS_F64_S32: "VCVT.LS.F64.S32",
+ VCVT_GE_F64_S32: "VCVT.GE.F64.S32",
+ VCVT_LT_F64_S32: "VCVT.LT.F64.S32",
+ VCVT_GT_F64_S32: "VCVT.GT.F64.S32",
+ VCVT_LE_F64_S32: "VCVT.LE.F64.S32",
+ VCVT_F64_S32: "VCVT.F64.S32",
+ VCVT_ZZ_F64_S32: "VCVT.ZZ.F64.S32",
+ VCVT_EQ_F64_F32: "VCVT.EQ.F64.F32",
+ VCVT_NE_F64_F32: "VCVT.NE.F64.F32",
+ VCVT_CS_F64_F32: "VCVT.CS.F64.F32",
+ VCVT_CC_F64_F32: "VCVT.CC.F64.F32",
+ VCVT_MI_F64_F32: "VCVT.MI.F64.F32",
+ VCVT_PL_F64_F32: "VCVT.PL.F64.F32",
+ VCVT_VS_F64_F32: "VCVT.VS.F64.F32",
+ VCVT_VC_F64_F32: "VCVT.VC.F64.F32",
+ VCVT_HI_F64_F32: "VCVT.HI.F64.F32",
+ VCVT_LS_F64_F32: "VCVT.LS.F64.F32",
+ VCVT_GE_F64_F32: "VCVT.GE.F64.F32",
+ VCVT_LT_F64_F32: "VCVT.LT.F64.F32",
+ VCVT_GT_F64_F32: "VCVT.GT.F64.F32",
+ VCVT_LE_F64_F32: "VCVT.LE.F64.F32",
+ VCVT_F64_F32: "VCVT.F64.F32",
+ VCVT_ZZ_F64_F32: "VCVT.ZZ.F64.F32",
+ VCVT_EQ_F32_F64: "VCVT.EQ.F32.F64",
+ VCVT_NE_F32_F64: "VCVT.NE.F32.F64",
+ VCVT_CS_F32_F64: "VCVT.CS.F32.F64",
+ VCVT_CC_F32_F64: "VCVT.CC.F32.F64",
+ VCVT_MI_F32_F64: "VCVT.MI.F32.F64",
+ VCVT_PL_F32_F64: "VCVT.PL.F32.F64",
+ VCVT_VS_F32_F64: "VCVT.VS.F32.F64",
+ VCVT_VC_F32_F64: "VCVT.VC.F32.F64",
+ VCVT_HI_F32_F64: "VCVT.HI.F32.F64",
+ VCVT_LS_F32_F64: "VCVT.LS.F32.F64",
+ VCVT_GE_F32_F64: "VCVT.GE.F32.F64",
+ VCVT_LT_F32_F64: "VCVT.LT.F32.F64",
+ VCVT_GT_F32_F64: "VCVT.GT.F32.F64",
+ VCVT_LE_F32_F64: "VCVT.LE.F32.F64",
+ VCVT_F32_F64: "VCVT.F32.F64",
+ VCVT_ZZ_F32_F64: "VCVT.ZZ.F32.F64",
+ VCVT_EQ_FXS16_F32: "VCVT.EQ.FXS16.F32",
+ VCVT_NE_FXS16_F32: "VCVT.NE.FXS16.F32",
+ VCVT_CS_FXS16_F32: "VCVT.CS.FXS16.F32",
+ VCVT_CC_FXS16_F32: "VCVT.CC.FXS16.F32",
+ VCVT_MI_FXS16_F32: "VCVT.MI.FXS16.F32",
+ VCVT_PL_FXS16_F32: "VCVT.PL.FXS16.F32",
+ VCVT_VS_FXS16_F32: "VCVT.VS.FXS16.F32",
+ VCVT_VC_FXS16_F32: "VCVT.VC.FXS16.F32",
+ VCVT_HI_FXS16_F32: "VCVT.HI.FXS16.F32",
+ VCVT_LS_FXS16_F32: "VCVT.LS.FXS16.F32",
+ VCVT_GE_FXS16_F32: "VCVT.GE.FXS16.F32",
+ VCVT_LT_FXS16_F32: "VCVT.LT.FXS16.F32",
+ VCVT_GT_FXS16_F32: "VCVT.GT.FXS16.F32",
+ VCVT_LE_FXS16_F32: "VCVT.LE.FXS16.F32",
+ VCVT_FXS16_F32: "VCVT.FXS16.F32",
+ VCVT_ZZ_FXS16_F32: "VCVT.ZZ.FXS16.F32",
+ VCVT_EQ_FXS16_F64: "VCVT.EQ.FXS16.F64",
+ VCVT_NE_FXS16_F64: "VCVT.NE.FXS16.F64",
+ VCVT_CS_FXS16_F64: "VCVT.CS.FXS16.F64",
+ VCVT_CC_FXS16_F64: "VCVT.CC.FXS16.F64",
+ VCVT_MI_FXS16_F64: "VCVT.MI.FXS16.F64",
+ VCVT_PL_FXS16_F64: "VCVT.PL.FXS16.F64",
+ VCVT_VS_FXS16_F64: "VCVT.VS.FXS16.F64",
+ VCVT_VC_FXS16_F64: "VCVT.VC.FXS16.F64",
+ VCVT_HI_FXS16_F64: "VCVT.HI.FXS16.F64",
+ VCVT_LS_FXS16_F64: "VCVT.LS.FXS16.F64",
+ VCVT_GE_FXS16_F64: "VCVT.GE.FXS16.F64",
+ VCVT_LT_FXS16_F64: "VCVT.LT.FXS16.F64",
+ VCVT_GT_FXS16_F64: "VCVT.GT.FXS16.F64",
+ VCVT_LE_FXS16_F64: "VCVT.LE.FXS16.F64",
+ VCVT_FXS16_F64: "VCVT.FXS16.F64",
+ VCVT_ZZ_FXS16_F64: "VCVT.ZZ.FXS16.F64",
+ VCVT_EQ_FXS32_F32: "VCVT.EQ.FXS32.F32",
+ VCVT_NE_FXS32_F32: "VCVT.NE.FXS32.F32",
+ VCVT_CS_FXS32_F32: "VCVT.CS.FXS32.F32",
+ VCVT_CC_FXS32_F32: "VCVT.CC.FXS32.F32",
+ VCVT_MI_FXS32_F32: "VCVT.MI.FXS32.F32",
+ VCVT_PL_FXS32_F32: "VCVT.PL.FXS32.F32",
+ VCVT_VS_FXS32_F32: "VCVT.VS.FXS32.F32",
+ VCVT_VC_FXS32_F32: "VCVT.VC.FXS32.F32",
+ VCVT_HI_FXS32_F32: "VCVT.HI.FXS32.F32",
+ VCVT_LS_FXS32_F32: "VCVT.LS.FXS32.F32",
+ VCVT_GE_FXS32_F32: "VCVT.GE.FXS32.F32",
+ VCVT_LT_FXS32_F32: "VCVT.LT.FXS32.F32",
+ VCVT_GT_FXS32_F32: "VCVT.GT.FXS32.F32",
+ VCVT_LE_FXS32_F32: "VCVT.LE.FXS32.F32",
+ VCVT_FXS32_F32: "VCVT.FXS32.F32",
+ VCVT_ZZ_FXS32_F32: "VCVT.ZZ.FXS32.F32",
+ VCVT_EQ_FXS32_F64: "VCVT.EQ.FXS32.F64",
+ VCVT_NE_FXS32_F64: "VCVT.NE.FXS32.F64",
+ VCVT_CS_FXS32_F64: "VCVT.CS.FXS32.F64",
+ VCVT_CC_FXS32_F64: "VCVT.CC.FXS32.F64",
+ VCVT_MI_FXS32_F64: "VCVT.MI.FXS32.F64",
+ VCVT_PL_FXS32_F64: "VCVT.PL.FXS32.F64",
+ VCVT_VS_FXS32_F64: "VCVT.VS.FXS32.F64",
+ VCVT_VC_FXS32_F64: "VCVT.VC.FXS32.F64",
+ VCVT_HI_FXS32_F64: "VCVT.HI.FXS32.F64",
+ VCVT_LS_FXS32_F64: "VCVT.LS.FXS32.F64",
+ VCVT_GE_FXS32_F64: "VCVT.GE.FXS32.F64",
+ VCVT_LT_FXS32_F64: "VCVT.LT.FXS32.F64",
+ VCVT_GT_FXS32_F64: "VCVT.GT.FXS32.F64",
+ VCVT_LE_FXS32_F64: "VCVT.LE.FXS32.F64",
+ VCVT_FXS32_F64: "VCVT.FXS32.F64",
+ VCVT_ZZ_FXS32_F64: "VCVT.ZZ.FXS32.F64",
+ VCVT_EQ_FXU16_F32: "VCVT.EQ.FXU16.F32",
+ VCVT_NE_FXU16_F32: "VCVT.NE.FXU16.F32",
+ VCVT_CS_FXU16_F32: "VCVT.CS.FXU16.F32",
+ VCVT_CC_FXU16_F32: "VCVT.CC.FXU16.F32",
+ VCVT_MI_FXU16_F32: "VCVT.MI.FXU16.F32",
+ VCVT_PL_FXU16_F32: "VCVT.PL.FXU16.F32",
+ VCVT_VS_FXU16_F32: "VCVT.VS.FXU16.F32",
+ VCVT_VC_FXU16_F32: "VCVT.VC.FXU16.F32",
+ VCVT_HI_FXU16_F32: "VCVT.HI.FXU16.F32",
+ VCVT_LS_FXU16_F32: "VCVT.LS.FXU16.F32",
+ VCVT_GE_FXU16_F32: "VCVT.GE.FXU16.F32",
+ VCVT_LT_FXU16_F32: "VCVT.LT.FXU16.F32",
+ VCVT_GT_FXU16_F32: "VCVT.GT.FXU16.F32",
+ VCVT_LE_FXU16_F32: "VCVT.LE.FXU16.F32",
+ VCVT_FXU16_F32: "VCVT.FXU16.F32",
+ VCVT_ZZ_FXU16_F32: "VCVT.ZZ.FXU16.F32",
+ VCVT_EQ_FXU16_F64: "VCVT.EQ.FXU16.F64",
+ VCVT_NE_FXU16_F64: "VCVT.NE.FXU16.F64",
+ VCVT_CS_FXU16_F64: "VCVT.CS.FXU16.F64",
+ VCVT_CC_FXU16_F64: "VCVT.CC.FXU16.F64",
+ VCVT_MI_FXU16_F64: "VCVT.MI.FXU16.F64",
+ VCVT_PL_FXU16_F64: "VCVT.PL.FXU16.F64",
+ VCVT_VS_FXU16_F64: "VCVT.VS.FXU16.F64",
+ VCVT_VC_FXU16_F64: "VCVT.VC.FXU16.F64",
+ VCVT_HI_FXU16_F64: "VCVT.HI.FXU16.F64",
+ VCVT_LS_FXU16_F64: "VCVT.LS.FXU16.F64",
+ VCVT_GE_FXU16_F64: "VCVT.GE.FXU16.F64",
+ VCVT_LT_FXU16_F64: "VCVT.LT.FXU16.F64",
+ VCVT_GT_FXU16_F64: "VCVT.GT.FXU16.F64",
+ VCVT_LE_FXU16_F64: "VCVT.LE.FXU16.F64",
+ VCVT_FXU16_F64: "VCVT.FXU16.F64",
+ VCVT_ZZ_FXU16_F64: "VCVT.ZZ.FXU16.F64",
+ VCVT_EQ_FXU32_F32: "VCVT.EQ.FXU32.F32",
+ VCVT_NE_FXU32_F32: "VCVT.NE.FXU32.F32",
+ VCVT_CS_FXU32_F32: "VCVT.CS.FXU32.F32",
+ VCVT_CC_FXU32_F32: "VCVT.CC.FXU32.F32",
+ VCVT_MI_FXU32_F32: "VCVT.MI.FXU32.F32",
+ VCVT_PL_FXU32_F32: "VCVT.PL.FXU32.F32",
+ VCVT_VS_FXU32_F32: "VCVT.VS.FXU32.F32",
+ VCVT_VC_FXU32_F32: "VCVT.VC.FXU32.F32",
+ VCVT_HI_FXU32_F32: "VCVT.HI.FXU32.F32",
+ VCVT_LS_FXU32_F32: "VCVT.LS.FXU32.F32",
+ VCVT_GE_FXU32_F32: "VCVT.GE.FXU32.F32",
+ VCVT_LT_FXU32_F32: "VCVT.LT.FXU32.F32",
+ VCVT_GT_FXU32_F32: "VCVT.GT.FXU32.F32",
+ VCVT_LE_FXU32_F32: "VCVT.LE.FXU32.F32",
+ VCVT_FXU32_F32: "VCVT.FXU32.F32",
+ VCVT_ZZ_FXU32_F32: "VCVT.ZZ.FXU32.F32",
+ VCVT_EQ_FXU32_F64: "VCVT.EQ.FXU32.F64",
+ VCVT_NE_FXU32_F64: "VCVT.NE.FXU32.F64",
+ VCVT_CS_FXU32_F64: "VCVT.CS.FXU32.F64",
+ VCVT_CC_FXU32_F64: "VCVT.CC.FXU32.F64",
+ VCVT_MI_FXU32_F64: "VCVT.MI.FXU32.F64",
+ VCVT_PL_FXU32_F64: "VCVT.PL.FXU32.F64",
+ VCVT_VS_FXU32_F64: "VCVT.VS.FXU32.F64",
+ VCVT_VC_FXU32_F64: "VCVT.VC.FXU32.F64",
+ VCVT_HI_FXU32_F64: "VCVT.HI.FXU32.F64",
+ VCVT_LS_FXU32_F64: "VCVT.LS.FXU32.F64",
+ VCVT_GE_FXU32_F64: "VCVT.GE.FXU32.F64",
+ VCVT_LT_FXU32_F64: "VCVT.LT.FXU32.F64",
+ VCVT_GT_FXU32_F64: "VCVT.GT.FXU32.F64",
+ VCVT_LE_FXU32_F64: "VCVT.LE.FXU32.F64",
+ VCVT_FXU32_F64: "VCVT.FXU32.F64",
+ VCVT_ZZ_FXU32_F64: "VCVT.ZZ.FXU32.F64",
+ VCVTB_EQ_F32_F16: "VCVTB.EQ.F32.F16",
+ VCVTB_NE_F32_F16: "VCVTB.NE.F32.F16",
+ VCVTB_CS_F32_F16: "VCVTB.CS.F32.F16",
+ VCVTB_CC_F32_F16: "VCVTB.CC.F32.F16",
+ VCVTB_MI_F32_F16: "VCVTB.MI.F32.F16",
+ VCVTB_PL_F32_F16: "VCVTB.PL.F32.F16",
+ VCVTB_VS_F32_F16: "VCVTB.VS.F32.F16",
+ VCVTB_VC_F32_F16: "VCVTB.VC.F32.F16",
+ VCVTB_HI_F32_F16: "VCVTB.HI.F32.F16",
+ VCVTB_LS_F32_F16: "VCVTB.LS.F32.F16",
+ VCVTB_GE_F32_F16: "VCVTB.GE.F32.F16",
+ VCVTB_LT_F32_F16: "VCVTB.LT.F32.F16",
+ VCVTB_GT_F32_F16: "VCVTB.GT.F32.F16",
+ VCVTB_LE_F32_F16: "VCVTB.LE.F32.F16",
+ VCVTB_F32_F16: "VCVTB.F32.F16",
+ VCVTB_ZZ_F32_F16: "VCVTB.ZZ.F32.F16",
+ VCVTB_EQ_F16_F32: "VCVTB.EQ.F16.F32",
+ VCVTB_NE_F16_F32: "VCVTB.NE.F16.F32",
+ VCVTB_CS_F16_F32: "VCVTB.CS.F16.F32",
+ VCVTB_CC_F16_F32: "VCVTB.CC.F16.F32",
+ VCVTB_MI_F16_F32: "VCVTB.MI.F16.F32",
+ VCVTB_PL_F16_F32: "VCVTB.PL.F16.F32",
+ VCVTB_VS_F16_F32: "VCVTB.VS.F16.F32",
+ VCVTB_VC_F16_F32: "VCVTB.VC.F16.F32",
+ VCVTB_HI_F16_F32: "VCVTB.HI.F16.F32",
+ VCVTB_LS_F16_F32: "VCVTB.LS.F16.F32",
+ VCVTB_GE_F16_F32: "VCVTB.GE.F16.F32",
+ VCVTB_LT_F16_F32: "VCVTB.LT.F16.F32",
+ VCVTB_GT_F16_F32: "VCVTB.GT.F16.F32",
+ VCVTB_LE_F16_F32: "VCVTB.LE.F16.F32",
+ VCVTB_F16_F32: "VCVTB.F16.F32",
+ VCVTB_ZZ_F16_F32: "VCVTB.ZZ.F16.F32",
+ VCVTT_EQ_F32_F16: "VCVTT.EQ.F32.F16",
+ VCVTT_NE_F32_F16: "VCVTT.NE.F32.F16",
+ VCVTT_CS_F32_F16: "VCVTT.CS.F32.F16",
+ VCVTT_CC_F32_F16: "VCVTT.CC.F32.F16",
+ VCVTT_MI_F32_F16: "VCVTT.MI.F32.F16",
+ VCVTT_PL_F32_F16: "VCVTT.PL.F32.F16",
+ VCVTT_VS_F32_F16: "VCVTT.VS.F32.F16",
+ VCVTT_VC_F32_F16: "VCVTT.VC.F32.F16",
+ VCVTT_HI_F32_F16: "VCVTT.HI.F32.F16",
+ VCVTT_LS_F32_F16: "VCVTT.LS.F32.F16",
+ VCVTT_GE_F32_F16: "VCVTT.GE.F32.F16",
+ VCVTT_LT_F32_F16: "VCVTT.LT.F32.F16",
+ VCVTT_GT_F32_F16: "VCVTT.GT.F32.F16",
+ VCVTT_LE_F32_F16: "VCVTT.LE.F32.F16",
+ VCVTT_F32_F16: "VCVTT.F32.F16",
+ VCVTT_ZZ_F32_F16: "VCVTT.ZZ.F32.F16",
+ VCVTT_EQ_F16_F32: "VCVTT.EQ.F16.F32",
+ VCVTT_NE_F16_F32: "VCVTT.NE.F16.F32",
+ VCVTT_CS_F16_F32: "VCVTT.CS.F16.F32",
+ VCVTT_CC_F16_F32: "VCVTT.CC.F16.F32",
+ VCVTT_MI_F16_F32: "VCVTT.MI.F16.F32",
+ VCVTT_PL_F16_F32: "VCVTT.PL.F16.F32",
+ VCVTT_VS_F16_F32: "VCVTT.VS.F16.F32",
+ VCVTT_VC_F16_F32: "VCVTT.VC.F16.F32",
+ VCVTT_HI_F16_F32: "VCVTT.HI.F16.F32",
+ VCVTT_LS_F16_F32: "VCVTT.LS.F16.F32",
+ VCVTT_GE_F16_F32: "VCVTT.GE.F16.F32",
+ VCVTT_LT_F16_F32: "VCVTT.LT.F16.F32",
+ VCVTT_GT_F16_F32: "VCVTT.GT.F16.F32",
+ VCVTT_LE_F16_F32: "VCVTT.LE.F16.F32",
+ VCVTT_F16_F32: "VCVTT.F16.F32",
+ VCVTT_ZZ_F16_F32: "VCVTT.ZZ.F16.F32",
+ VCVTR_EQ_U32_F32: "VCVTR.EQ.U32.F32",
+ VCVTR_NE_U32_F32: "VCVTR.NE.U32.F32",
+ VCVTR_CS_U32_F32: "VCVTR.CS.U32.F32",
+ VCVTR_CC_U32_F32: "VCVTR.CC.U32.F32",
+ VCVTR_MI_U32_F32: "VCVTR.MI.U32.F32",
+ VCVTR_PL_U32_F32: "VCVTR.PL.U32.F32",
+ VCVTR_VS_U32_F32: "VCVTR.VS.U32.F32",
+ VCVTR_VC_U32_F32: "VCVTR.VC.U32.F32",
+ VCVTR_HI_U32_F32: "VCVTR.HI.U32.F32",
+ VCVTR_LS_U32_F32: "VCVTR.LS.U32.F32",
+ VCVTR_GE_U32_F32: "VCVTR.GE.U32.F32",
+ VCVTR_LT_U32_F32: "VCVTR.LT.U32.F32",
+ VCVTR_GT_U32_F32: "VCVTR.GT.U32.F32",
+ VCVTR_LE_U32_F32: "VCVTR.LE.U32.F32",
+ VCVTR_U32_F32: "VCVTR.U32.F32",
+ VCVTR_ZZ_U32_F32: "VCVTR.ZZ.U32.F32",
+ VCVTR_EQ_U32_F64: "VCVTR.EQ.U32.F64",
+ VCVTR_NE_U32_F64: "VCVTR.NE.U32.F64",
+ VCVTR_CS_U32_F64: "VCVTR.CS.U32.F64",
+ VCVTR_CC_U32_F64: "VCVTR.CC.U32.F64",
+ VCVTR_MI_U32_F64: "VCVTR.MI.U32.F64",
+ VCVTR_PL_U32_F64: "VCVTR.PL.U32.F64",
+ VCVTR_VS_U32_F64: "VCVTR.VS.U32.F64",
+ VCVTR_VC_U32_F64: "VCVTR.VC.U32.F64",
+ VCVTR_HI_U32_F64: "VCVTR.HI.U32.F64",
+ VCVTR_LS_U32_F64: "VCVTR.LS.U32.F64",
+ VCVTR_GE_U32_F64: "VCVTR.GE.U32.F64",
+ VCVTR_LT_U32_F64: "VCVTR.LT.U32.F64",
+ VCVTR_GT_U32_F64: "VCVTR.GT.U32.F64",
+ VCVTR_LE_U32_F64: "VCVTR.LE.U32.F64",
+ VCVTR_U32_F64: "VCVTR.U32.F64",
+ VCVTR_ZZ_U32_F64: "VCVTR.ZZ.U32.F64",
+ VCVTR_EQ_S32_F32: "VCVTR.EQ.S32.F32",
+ VCVTR_NE_S32_F32: "VCVTR.NE.S32.F32",
+ VCVTR_CS_S32_F32: "VCVTR.CS.S32.F32",
+ VCVTR_CC_S32_F32: "VCVTR.CC.S32.F32",
+ VCVTR_MI_S32_F32: "VCVTR.MI.S32.F32",
+ VCVTR_PL_S32_F32: "VCVTR.PL.S32.F32",
+ VCVTR_VS_S32_F32: "VCVTR.VS.S32.F32",
+ VCVTR_VC_S32_F32: "VCVTR.VC.S32.F32",
+ VCVTR_HI_S32_F32: "VCVTR.HI.S32.F32",
+ VCVTR_LS_S32_F32: "VCVTR.LS.S32.F32",
+ VCVTR_GE_S32_F32: "VCVTR.GE.S32.F32",
+ VCVTR_LT_S32_F32: "VCVTR.LT.S32.F32",
+ VCVTR_GT_S32_F32: "VCVTR.GT.S32.F32",
+ VCVTR_LE_S32_F32: "VCVTR.LE.S32.F32",
+ VCVTR_S32_F32: "VCVTR.S32.F32",
+ VCVTR_ZZ_S32_F32: "VCVTR.ZZ.S32.F32",
+ VCVTR_EQ_S32_F64: "VCVTR.EQ.S32.F64",
+ VCVTR_NE_S32_F64: "VCVTR.NE.S32.F64",
+ VCVTR_CS_S32_F64: "VCVTR.CS.S32.F64",
+ VCVTR_CC_S32_F64: "VCVTR.CC.S32.F64",
+ VCVTR_MI_S32_F64: "VCVTR.MI.S32.F64",
+ VCVTR_PL_S32_F64: "VCVTR.PL.S32.F64",
+ VCVTR_VS_S32_F64: "VCVTR.VS.S32.F64",
+ VCVTR_VC_S32_F64: "VCVTR.VC.S32.F64",
+ VCVTR_HI_S32_F64: "VCVTR.HI.S32.F64",
+ VCVTR_LS_S32_F64: "VCVTR.LS.S32.F64",
+ VCVTR_GE_S32_F64: "VCVTR.GE.S32.F64",
+ VCVTR_LT_S32_F64: "VCVTR.LT.S32.F64",
+ VCVTR_GT_S32_F64: "VCVTR.GT.S32.F64",
+ VCVTR_LE_S32_F64: "VCVTR.LE.S32.F64",
+ VCVTR_S32_F64: "VCVTR.S32.F64",
+ VCVTR_ZZ_S32_F64: "VCVTR.ZZ.S32.F64",
+ VCVT_EQ_U32_F32: "VCVT.EQ.U32.F32",
+ VCVT_NE_U32_F32: "VCVT.NE.U32.F32",
+ VCVT_CS_U32_F32: "VCVT.CS.U32.F32",
+ VCVT_CC_U32_F32: "VCVT.CC.U32.F32",
+ VCVT_MI_U32_F32: "VCVT.MI.U32.F32",
+ VCVT_PL_U32_F32: "VCVT.PL.U32.F32",
+ VCVT_VS_U32_F32: "VCVT.VS.U32.F32",
+ VCVT_VC_U32_F32: "VCVT.VC.U32.F32",
+ VCVT_HI_U32_F32: "VCVT.HI.U32.F32",
+ VCVT_LS_U32_F32: "VCVT.LS.U32.F32",
+ VCVT_GE_U32_F32: "VCVT.GE.U32.F32",
+ VCVT_LT_U32_F32: "VCVT.LT.U32.F32",
+ VCVT_GT_U32_F32: "VCVT.GT.U32.F32",
+ VCVT_LE_U32_F32: "VCVT.LE.U32.F32",
+ VCVT_U32_F32: "VCVT.U32.F32",
+ VCVT_ZZ_U32_F32: "VCVT.ZZ.U32.F32",
+ VCVT_EQ_U32_F64: "VCVT.EQ.U32.F64",
+ VCVT_NE_U32_F64: "VCVT.NE.U32.F64",
+ VCVT_CS_U32_F64: "VCVT.CS.U32.F64",
+ VCVT_CC_U32_F64: "VCVT.CC.U32.F64",
+ VCVT_MI_U32_F64: "VCVT.MI.U32.F64",
+ VCVT_PL_U32_F64: "VCVT.PL.U32.F64",
+ VCVT_VS_U32_F64: "VCVT.VS.U32.F64",
+ VCVT_VC_U32_F64: "VCVT.VC.U32.F64",
+ VCVT_HI_U32_F64: "VCVT.HI.U32.F64",
+ VCVT_LS_U32_F64: "VCVT.LS.U32.F64",
+ VCVT_GE_U32_F64: "VCVT.GE.U32.F64",
+ VCVT_LT_U32_F64: "VCVT.LT.U32.F64",
+ VCVT_GT_U32_F64: "VCVT.GT.U32.F64",
+ VCVT_LE_U32_F64: "VCVT.LE.U32.F64",
+ VCVT_U32_F64: "VCVT.U32.F64",
+ VCVT_ZZ_U32_F64: "VCVT.ZZ.U32.F64",
+ VCVT_EQ_S32_F32: "VCVT.EQ.S32.F32",
+ VCVT_NE_S32_F32: "VCVT.NE.S32.F32",
+ VCVT_CS_S32_F32: "VCVT.CS.S32.F32",
+ VCVT_CC_S32_F32: "VCVT.CC.S32.F32",
+ VCVT_MI_S32_F32: "VCVT.MI.S32.F32",
+ VCVT_PL_S32_F32: "VCVT.PL.S32.F32",
+ VCVT_VS_S32_F32: "VCVT.VS.S32.F32",
+ VCVT_VC_S32_F32: "VCVT.VC.S32.F32",
+ VCVT_HI_S32_F32: "VCVT.HI.S32.F32",
+ VCVT_LS_S32_F32: "VCVT.LS.S32.F32",
+ VCVT_GE_S32_F32: "VCVT.GE.S32.F32",
+ VCVT_LT_S32_F32: "VCVT.LT.S32.F32",
+ VCVT_GT_S32_F32: "VCVT.GT.S32.F32",
+ VCVT_LE_S32_F32: "VCVT.LE.S32.F32",
+ VCVT_S32_F32: "VCVT.S32.F32",
+ VCVT_ZZ_S32_F32: "VCVT.ZZ.S32.F32",
+ VCVT_EQ_S32_F64: "VCVT.EQ.S32.F64",
+ VCVT_NE_S32_F64: "VCVT.NE.S32.F64",
+ VCVT_CS_S32_F64: "VCVT.CS.S32.F64",
+ VCVT_CC_S32_F64: "VCVT.CC.S32.F64",
+ VCVT_MI_S32_F64: "VCVT.MI.S32.F64",
+ VCVT_PL_S32_F64: "VCVT.PL.S32.F64",
+ VCVT_VS_S32_F64: "VCVT.VS.S32.F64",
+ VCVT_VC_S32_F64: "VCVT.VC.S32.F64",
+ VCVT_HI_S32_F64: "VCVT.HI.S32.F64",
+ VCVT_LS_S32_F64: "VCVT.LS.S32.F64",
+ VCVT_GE_S32_F64: "VCVT.GE.S32.F64",
+ VCVT_LT_S32_F64: "VCVT.LT.S32.F64",
+ VCVT_GT_S32_F64: "VCVT.GT.S32.F64",
+ VCVT_LE_S32_F64: "VCVT.LE.S32.F64",
+ VCVT_S32_F64: "VCVT.S32.F64",
+ VCVT_ZZ_S32_F64: "VCVT.ZZ.S32.F64",
+ VDIV_EQ_F32: "VDIV.EQ.F32",
+ VDIV_NE_F32: "VDIV.NE.F32",
+ VDIV_CS_F32: "VDIV.CS.F32",
+ VDIV_CC_F32: "VDIV.CC.F32",
+ VDIV_MI_F32: "VDIV.MI.F32",
+ VDIV_PL_F32: "VDIV.PL.F32",
+ VDIV_VS_F32: "VDIV.VS.F32",
+ VDIV_VC_F32: "VDIV.VC.F32",
+ VDIV_HI_F32: "VDIV.HI.F32",
+ VDIV_LS_F32: "VDIV.LS.F32",
+ VDIV_GE_F32: "VDIV.GE.F32",
+ VDIV_LT_F32: "VDIV.LT.F32",
+ VDIV_GT_F32: "VDIV.GT.F32",
+ VDIV_LE_F32: "VDIV.LE.F32",
+ VDIV_F32: "VDIV.F32",
+ VDIV_ZZ_F32: "VDIV.ZZ.F32",
+ VDIV_EQ_F64: "VDIV.EQ.F64",
+ VDIV_NE_F64: "VDIV.NE.F64",
+ VDIV_CS_F64: "VDIV.CS.F64",
+ VDIV_CC_F64: "VDIV.CC.F64",
+ VDIV_MI_F64: "VDIV.MI.F64",
+ VDIV_PL_F64: "VDIV.PL.F64",
+ VDIV_VS_F64: "VDIV.VS.F64",
+ VDIV_VC_F64: "VDIV.VC.F64",
+ VDIV_HI_F64: "VDIV.HI.F64",
+ VDIV_LS_F64: "VDIV.LS.F64",
+ VDIV_GE_F64: "VDIV.GE.F64",
+ VDIV_LT_F64: "VDIV.LT.F64",
+ VDIV_GT_F64: "VDIV.GT.F64",
+ VDIV_LE_F64: "VDIV.LE.F64",
+ VDIV_F64: "VDIV.F64",
+ VDIV_ZZ_F64: "VDIV.ZZ.F64",
+ VLDR_EQ: "VLDR.EQ",
+ VLDR_NE: "VLDR.NE",
+ VLDR_CS: "VLDR.CS",
+ VLDR_CC: "VLDR.CC",
+ VLDR_MI: "VLDR.MI",
+ VLDR_PL: "VLDR.PL",
+ VLDR_VS: "VLDR.VS",
+ VLDR_VC: "VLDR.VC",
+ VLDR_HI: "VLDR.HI",
+ VLDR_LS: "VLDR.LS",
+ VLDR_GE: "VLDR.GE",
+ VLDR_LT: "VLDR.LT",
+ VLDR_GT: "VLDR.GT",
+ VLDR_LE: "VLDR.LE",
+ VLDR: "VLDR",
+ VLDR_ZZ: "VLDR.ZZ",
+ VMLA_EQ_F32: "VMLA.EQ.F32",
+ VMLA_NE_F32: "VMLA.NE.F32",
+ VMLA_CS_F32: "VMLA.CS.F32",
+ VMLA_CC_F32: "VMLA.CC.F32",
+ VMLA_MI_F32: "VMLA.MI.F32",
+ VMLA_PL_F32: "VMLA.PL.F32",
+ VMLA_VS_F32: "VMLA.VS.F32",
+ VMLA_VC_F32: "VMLA.VC.F32",
+ VMLA_HI_F32: "VMLA.HI.F32",
+ VMLA_LS_F32: "VMLA.LS.F32",
+ VMLA_GE_F32: "VMLA.GE.F32",
+ VMLA_LT_F32: "VMLA.LT.F32",
+ VMLA_GT_F32: "VMLA.GT.F32",
+ VMLA_LE_F32: "VMLA.LE.F32",
+ VMLA_F32: "VMLA.F32",
+ VMLA_ZZ_F32: "VMLA.ZZ.F32",
+ VMLA_EQ_F64: "VMLA.EQ.F64",
+ VMLA_NE_F64: "VMLA.NE.F64",
+ VMLA_CS_F64: "VMLA.CS.F64",
+ VMLA_CC_F64: "VMLA.CC.F64",
+ VMLA_MI_F64: "VMLA.MI.F64",
+ VMLA_PL_F64: "VMLA.PL.F64",
+ VMLA_VS_F64: "VMLA.VS.F64",
+ VMLA_VC_F64: "VMLA.VC.F64",
+ VMLA_HI_F64: "VMLA.HI.F64",
+ VMLA_LS_F64: "VMLA.LS.F64",
+ VMLA_GE_F64: "VMLA.GE.F64",
+ VMLA_LT_F64: "VMLA.LT.F64",
+ VMLA_GT_F64: "VMLA.GT.F64",
+ VMLA_LE_F64: "VMLA.LE.F64",
+ VMLA_F64: "VMLA.F64",
+ VMLA_ZZ_F64: "VMLA.ZZ.F64",
+ VMLS_EQ_F32: "VMLS.EQ.F32",
+ VMLS_NE_F32: "VMLS.NE.F32",
+ VMLS_CS_F32: "VMLS.CS.F32",
+ VMLS_CC_F32: "VMLS.CC.F32",
+ VMLS_MI_F32: "VMLS.MI.F32",
+ VMLS_PL_F32: "VMLS.PL.F32",
+ VMLS_VS_F32: "VMLS.VS.F32",
+ VMLS_VC_F32: "VMLS.VC.F32",
+ VMLS_HI_F32: "VMLS.HI.F32",
+ VMLS_LS_F32: "VMLS.LS.F32",
+ VMLS_GE_F32: "VMLS.GE.F32",
+ VMLS_LT_F32: "VMLS.LT.F32",
+ VMLS_GT_F32: "VMLS.GT.F32",
+ VMLS_LE_F32: "VMLS.LE.F32",
+ VMLS_F32: "VMLS.F32",
+ VMLS_ZZ_F32: "VMLS.ZZ.F32",
+ VMLS_EQ_F64: "VMLS.EQ.F64",
+ VMLS_NE_F64: "VMLS.NE.F64",
+ VMLS_CS_F64: "VMLS.CS.F64",
+ VMLS_CC_F64: "VMLS.CC.F64",
+ VMLS_MI_F64: "VMLS.MI.F64",
+ VMLS_PL_F64: "VMLS.PL.F64",
+ VMLS_VS_F64: "VMLS.VS.F64",
+ VMLS_VC_F64: "VMLS.VC.F64",
+ VMLS_HI_F64: "VMLS.HI.F64",
+ VMLS_LS_F64: "VMLS.LS.F64",
+ VMLS_GE_F64: "VMLS.GE.F64",
+ VMLS_LT_F64: "VMLS.LT.F64",
+ VMLS_GT_F64: "VMLS.GT.F64",
+ VMLS_LE_F64: "VMLS.LE.F64",
+ VMLS_F64: "VMLS.F64",
+ VMLS_ZZ_F64: "VMLS.ZZ.F64",
+ VMOV_EQ: "VMOV.EQ",
+ VMOV_NE: "VMOV.NE",
+ VMOV_CS: "VMOV.CS",
+ VMOV_CC: "VMOV.CC",
+ VMOV_MI: "VMOV.MI",
+ VMOV_PL: "VMOV.PL",
+ VMOV_VS: "VMOV.VS",
+ VMOV_VC: "VMOV.VC",
+ VMOV_HI: "VMOV.HI",
+ VMOV_LS: "VMOV.LS",
+ VMOV_GE: "VMOV.GE",
+ VMOV_LT: "VMOV.LT",
+ VMOV_GT: "VMOV.GT",
+ VMOV_LE: "VMOV.LE",
+ VMOV: "VMOV",
+ VMOV_ZZ: "VMOV.ZZ",
+ VMOV_EQ_32: "VMOV.EQ.32",
+ VMOV_NE_32: "VMOV.NE.32",
+ VMOV_CS_32: "VMOV.CS.32",
+ VMOV_CC_32: "VMOV.CC.32",
+ VMOV_MI_32: "VMOV.MI.32",
+ VMOV_PL_32: "VMOV.PL.32",
+ VMOV_VS_32: "VMOV.VS.32",
+ VMOV_VC_32: "VMOV.VC.32",
+ VMOV_HI_32: "VMOV.HI.32",
+ VMOV_LS_32: "VMOV.LS.32",
+ VMOV_GE_32: "VMOV.GE.32",
+ VMOV_LT_32: "VMOV.LT.32",
+ VMOV_GT_32: "VMOV.GT.32",
+ VMOV_LE_32: "VMOV.LE.32",
+ VMOV_32: "VMOV.32",
+ VMOV_ZZ_32: "VMOV.ZZ.32",
+ VMOV_EQ_F32: "VMOV.EQ.F32",
+ VMOV_NE_F32: "VMOV.NE.F32",
+ VMOV_CS_F32: "VMOV.CS.F32",
+ VMOV_CC_F32: "VMOV.CC.F32",
+ VMOV_MI_F32: "VMOV.MI.F32",
+ VMOV_PL_F32: "VMOV.PL.F32",
+ VMOV_VS_F32: "VMOV.VS.F32",
+ VMOV_VC_F32: "VMOV.VC.F32",
+ VMOV_HI_F32: "VMOV.HI.F32",
+ VMOV_LS_F32: "VMOV.LS.F32",
+ VMOV_GE_F32: "VMOV.GE.F32",
+ VMOV_LT_F32: "VMOV.LT.F32",
+ VMOV_GT_F32: "VMOV.GT.F32",
+ VMOV_LE_F32: "VMOV.LE.F32",
+ VMOV_F32: "VMOV.F32",
+ VMOV_ZZ_F32: "VMOV.ZZ.F32",
+ VMOV_EQ_F64: "VMOV.EQ.F64",
+ VMOV_NE_F64: "VMOV.NE.F64",
+ VMOV_CS_F64: "VMOV.CS.F64",
+ VMOV_CC_F64: "VMOV.CC.F64",
+ VMOV_MI_F64: "VMOV.MI.F64",
+ VMOV_PL_F64: "VMOV.PL.F64",
+ VMOV_VS_F64: "VMOV.VS.F64",
+ VMOV_VC_F64: "VMOV.VC.F64",
+ VMOV_HI_F64: "VMOV.HI.F64",
+ VMOV_LS_F64: "VMOV.LS.F64",
+ VMOV_GE_F64: "VMOV.GE.F64",
+ VMOV_LT_F64: "VMOV.LT.F64",
+ VMOV_GT_F64: "VMOV.GT.F64",
+ VMOV_LE_F64: "VMOV.LE.F64",
+ VMOV_F64: "VMOV.F64",
+ VMOV_ZZ_F64: "VMOV.ZZ.F64",
+ VMRS_EQ: "VMRS.EQ",
+ VMRS_NE: "VMRS.NE",
+ VMRS_CS: "VMRS.CS",
+ VMRS_CC: "VMRS.CC",
+ VMRS_MI: "VMRS.MI",
+ VMRS_PL: "VMRS.PL",
+ VMRS_VS: "VMRS.VS",
+ VMRS_VC: "VMRS.VC",
+ VMRS_HI: "VMRS.HI",
+ VMRS_LS: "VMRS.LS",
+ VMRS_GE: "VMRS.GE",
+ VMRS_LT: "VMRS.LT",
+ VMRS_GT: "VMRS.GT",
+ VMRS_LE: "VMRS.LE",
+ VMRS: "VMRS",
+ VMRS_ZZ: "VMRS.ZZ",
+ VMSR_EQ: "VMSR.EQ",
+ VMSR_NE: "VMSR.NE",
+ VMSR_CS: "VMSR.CS",
+ VMSR_CC: "VMSR.CC",
+ VMSR_MI: "VMSR.MI",
+ VMSR_PL: "VMSR.PL",
+ VMSR_VS: "VMSR.VS",
+ VMSR_VC: "VMSR.VC",
+ VMSR_HI: "VMSR.HI",
+ VMSR_LS: "VMSR.LS",
+ VMSR_GE: "VMSR.GE",
+ VMSR_LT: "VMSR.LT",
+ VMSR_GT: "VMSR.GT",
+ VMSR_LE: "VMSR.LE",
+ VMSR: "VMSR",
+ VMSR_ZZ: "VMSR.ZZ",
+ VMUL_EQ_F32: "VMUL.EQ.F32",
+ VMUL_NE_F32: "VMUL.NE.F32",
+ VMUL_CS_F32: "VMUL.CS.F32",
+ VMUL_CC_F32: "VMUL.CC.F32",
+ VMUL_MI_F32: "VMUL.MI.F32",
+ VMUL_PL_F32: "VMUL.PL.F32",
+ VMUL_VS_F32: "VMUL.VS.F32",
+ VMUL_VC_F32: "VMUL.VC.F32",
+ VMUL_HI_F32: "VMUL.HI.F32",
+ VMUL_LS_F32: "VMUL.LS.F32",
+ VMUL_GE_F32: "VMUL.GE.F32",
+ VMUL_LT_F32: "VMUL.LT.F32",
+ VMUL_GT_F32: "VMUL.GT.F32",
+ VMUL_LE_F32: "VMUL.LE.F32",
+ VMUL_F32: "VMUL.F32",
+ VMUL_ZZ_F32: "VMUL.ZZ.F32",
+ VMUL_EQ_F64: "VMUL.EQ.F64",
+ VMUL_NE_F64: "VMUL.NE.F64",
+ VMUL_CS_F64: "VMUL.CS.F64",
+ VMUL_CC_F64: "VMUL.CC.F64",
+ VMUL_MI_F64: "VMUL.MI.F64",
+ VMUL_PL_F64: "VMUL.PL.F64",
+ VMUL_VS_F64: "VMUL.VS.F64",
+ VMUL_VC_F64: "VMUL.VC.F64",
+ VMUL_HI_F64: "VMUL.HI.F64",
+ VMUL_LS_F64: "VMUL.LS.F64",
+ VMUL_GE_F64: "VMUL.GE.F64",
+ VMUL_LT_F64: "VMUL.LT.F64",
+ VMUL_GT_F64: "VMUL.GT.F64",
+ VMUL_LE_F64: "VMUL.LE.F64",
+ VMUL_F64: "VMUL.F64",
+ VMUL_ZZ_F64: "VMUL.ZZ.F64",
+ VNEG_EQ_F32: "VNEG.EQ.F32",
+ VNEG_NE_F32: "VNEG.NE.F32",
+ VNEG_CS_F32: "VNEG.CS.F32",
+ VNEG_CC_F32: "VNEG.CC.F32",
+ VNEG_MI_F32: "VNEG.MI.F32",
+ VNEG_PL_F32: "VNEG.PL.F32",
+ VNEG_VS_F32: "VNEG.VS.F32",
+ VNEG_VC_F32: "VNEG.VC.F32",
+ VNEG_HI_F32: "VNEG.HI.F32",
+ VNEG_LS_F32: "VNEG.LS.F32",
+ VNEG_GE_F32: "VNEG.GE.F32",
+ VNEG_LT_F32: "VNEG.LT.F32",
+ VNEG_GT_F32: "VNEG.GT.F32",
+ VNEG_LE_F32: "VNEG.LE.F32",
+ VNEG_F32: "VNEG.F32",
+ VNEG_ZZ_F32: "VNEG.ZZ.F32",
+ VNEG_EQ_F64: "VNEG.EQ.F64",
+ VNEG_NE_F64: "VNEG.NE.F64",
+ VNEG_CS_F64: "VNEG.CS.F64",
+ VNEG_CC_F64: "VNEG.CC.F64",
+ VNEG_MI_F64: "VNEG.MI.F64",
+ VNEG_PL_F64: "VNEG.PL.F64",
+ VNEG_VS_F64: "VNEG.VS.F64",
+ VNEG_VC_F64: "VNEG.VC.F64",
+ VNEG_HI_F64: "VNEG.HI.F64",
+ VNEG_LS_F64: "VNEG.LS.F64",
+ VNEG_GE_F64: "VNEG.GE.F64",
+ VNEG_LT_F64: "VNEG.LT.F64",
+ VNEG_GT_F64: "VNEG.GT.F64",
+ VNEG_LE_F64: "VNEG.LE.F64",
+ VNEG_F64: "VNEG.F64",
+ VNEG_ZZ_F64: "VNEG.ZZ.F64",
+ VNMLS_EQ_F32: "VNMLS.EQ.F32",
+ VNMLS_NE_F32: "VNMLS.NE.F32",
+ VNMLS_CS_F32: "VNMLS.CS.F32",
+ VNMLS_CC_F32: "VNMLS.CC.F32",
+ VNMLS_MI_F32: "VNMLS.MI.F32",
+ VNMLS_PL_F32: "VNMLS.PL.F32",
+ VNMLS_VS_F32: "VNMLS.VS.F32",
+ VNMLS_VC_F32: "VNMLS.VC.F32",
+ VNMLS_HI_F32: "VNMLS.HI.F32",
+ VNMLS_LS_F32: "VNMLS.LS.F32",
+ VNMLS_GE_F32: "VNMLS.GE.F32",
+ VNMLS_LT_F32: "VNMLS.LT.F32",
+ VNMLS_GT_F32: "VNMLS.GT.F32",
+ VNMLS_LE_F32: "VNMLS.LE.F32",
+ VNMLS_F32: "VNMLS.F32",
+ VNMLS_ZZ_F32: "VNMLS.ZZ.F32",
+ VNMLS_EQ_F64: "VNMLS.EQ.F64",
+ VNMLS_NE_F64: "VNMLS.NE.F64",
+ VNMLS_CS_F64: "VNMLS.CS.F64",
+ VNMLS_CC_F64: "VNMLS.CC.F64",
+ VNMLS_MI_F64: "VNMLS.MI.F64",
+ VNMLS_PL_F64: "VNMLS.PL.F64",
+ VNMLS_VS_F64: "VNMLS.VS.F64",
+ VNMLS_VC_F64: "VNMLS.VC.F64",
+ VNMLS_HI_F64: "VNMLS.HI.F64",
+ VNMLS_LS_F64: "VNMLS.LS.F64",
+ VNMLS_GE_F64: "VNMLS.GE.F64",
+ VNMLS_LT_F64: "VNMLS.LT.F64",
+ VNMLS_GT_F64: "VNMLS.GT.F64",
+ VNMLS_LE_F64: "VNMLS.LE.F64",
+ VNMLS_F64: "VNMLS.F64",
+ VNMLS_ZZ_F64: "VNMLS.ZZ.F64",
+ VNMLA_EQ_F32: "VNMLA.EQ.F32",
+ VNMLA_NE_F32: "VNMLA.NE.F32",
+ VNMLA_CS_F32: "VNMLA.CS.F32",
+ VNMLA_CC_F32: "VNMLA.CC.F32",
+ VNMLA_MI_F32: "VNMLA.MI.F32",
+ VNMLA_PL_F32: "VNMLA.PL.F32",
+ VNMLA_VS_F32: "VNMLA.VS.F32",
+ VNMLA_VC_F32: "VNMLA.VC.F32",
+ VNMLA_HI_F32: "VNMLA.HI.F32",
+ VNMLA_LS_F32: "VNMLA.LS.F32",
+ VNMLA_GE_F32: "VNMLA.GE.F32",
+ VNMLA_LT_F32: "VNMLA.LT.F32",
+ VNMLA_GT_F32: "VNMLA.GT.F32",
+ VNMLA_LE_F32: "VNMLA.LE.F32",
+ VNMLA_F32: "VNMLA.F32",
+ VNMLA_ZZ_F32: "VNMLA.ZZ.F32",
+ VNMLA_EQ_F64: "VNMLA.EQ.F64",
+ VNMLA_NE_F64: "VNMLA.NE.F64",
+ VNMLA_CS_F64: "VNMLA.CS.F64",
+ VNMLA_CC_F64: "VNMLA.CC.F64",
+ VNMLA_MI_F64: "VNMLA.MI.F64",
+ VNMLA_PL_F64: "VNMLA.PL.F64",
+ VNMLA_VS_F64: "VNMLA.VS.F64",
+ VNMLA_VC_F64: "VNMLA.VC.F64",
+ VNMLA_HI_F64: "VNMLA.HI.F64",
+ VNMLA_LS_F64: "VNMLA.LS.F64",
+ VNMLA_GE_F64: "VNMLA.GE.F64",
+ VNMLA_LT_F64: "VNMLA.LT.F64",
+ VNMLA_GT_F64: "VNMLA.GT.F64",
+ VNMLA_LE_F64: "VNMLA.LE.F64",
+ VNMLA_F64: "VNMLA.F64",
+ VNMLA_ZZ_F64: "VNMLA.ZZ.F64",
+ VNMUL_EQ_F32: "VNMUL.EQ.F32",
+ VNMUL_NE_F32: "VNMUL.NE.F32",
+ VNMUL_CS_F32: "VNMUL.CS.F32",
+ VNMUL_CC_F32: "VNMUL.CC.F32",
+ VNMUL_MI_F32: "VNMUL.MI.F32",
+ VNMUL_PL_F32: "VNMUL.PL.F32",
+ VNMUL_VS_F32: "VNMUL.VS.F32",
+ VNMUL_VC_F32: "VNMUL.VC.F32",
+ VNMUL_HI_F32: "VNMUL.HI.F32",
+ VNMUL_LS_F32: "VNMUL.LS.F32",
+ VNMUL_GE_F32: "VNMUL.GE.F32",
+ VNMUL_LT_F32: "VNMUL.LT.F32",
+ VNMUL_GT_F32: "VNMUL.GT.F32",
+ VNMUL_LE_F32: "VNMUL.LE.F32",
+ VNMUL_F32: "VNMUL.F32",
+ VNMUL_ZZ_F32: "VNMUL.ZZ.F32",
+ VNMUL_EQ_F64: "VNMUL.EQ.F64",
+ VNMUL_NE_F64: "VNMUL.NE.F64",
+ VNMUL_CS_F64: "VNMUL.CS.F64",
+ VNMUL_CC_F64: "VNMUL.CC.F64",
+ VNMUL_MI_F64: "VNMUL.MI.F64",
+ VNMUL_PL_F64: "VNMUL.PL.F64",
+ VNMUL_VS_F64: "VNMUL.VS.F64",
+ VNMUL_VC_F64: "VNMUL.VC.F64",
+ VNMUL_HI_F64: "VNMUL.HI.F64",
+ VNMUL_LS_F64: "VNMUL.LS.F64",
+ VNMUL_GE_F64: "VNMUL.GE.F64",
+ VNMUL_LT_F64: "VNMUL.LT.F64",
+ VNMUL_GT_F64: "VNMUL.GT.F64",
+ VNMUL_LE_F64: "VNMUL.LE.F64",
+ VNMUL_F64: "VNMUL.F64",
+ VNMUL_ZZ_F64: "VNMUL.ZZ.F64",
+ VSQRT_EQ_F32: "VSQRT.EQ.F32",
+ VSQRT_NE_F32: "VSQRT.NE.F32",
+ VSQRT_CS_F32: "VSQRT.CS.F32",
+ VSQRT_CC_F32: "VSQRT.CC.F32",
+ VSQRT_MI_F32: "VSQRT.MI.F32",
+ VSQRT_PL_F32: "VSQRT.PL.F32",
+ VSQRT_VS_F32: "VSQRT.VS.F32",
+ VSQRT_VC_F32: "VSQRT.VC.F32",
+ VSQRT_HI_F32: "VSQRT.HI.F32",
+ VSQRT_LS_F32: "VSQRT.LS.F32",
+ VSQRT_GE_F32: "VSQRT.GE.F32",
+ VSQRT_LT_F32: "VSQRT.LT.F32",
+ VSQRT_GT_F32: "VSQRT.GT.F32",
+ VSQRT_LE_F32: "VSQRT.LE.F32",
+ VSQRT_F32: "VSQRT.F32",
+ VSQRT_ZZ_F32: "VSQRT.ZZ.F32",
+ VSQRT_EQ_F64: "VSQRT.EQ.F64",
+ VSQRT_NE_F64: "VSQRT.NE.F64",
+ VSQRT_CS_F64: "VSQRT.CS.F64",
+ VSQRT_CC_F64: "VSQRT.CC.F64",
+ VSQRT_MI_F64: "VSQRT.MI.F64",
+ VSQRT_PL_F64: "VSQRT.PL.F64",
+ VSQRT_VS_F64: "VSQRT.VS.F64",
+ VSQRT_VC_F64: "VSQRT.VC.F64",
+ VSQRT_HI_F64: "VSQRT.HI.F64",
+ VSQRT_LS_F64: "VSQRT.LS.F64",
+ VSQRT_GE_F64: "VSQRT.GE.F64",
+ VSQRT_LT_F64: "VSQRT.LT.F64",
+ VSQRT_GT_F64: "VSQRT.GT.F64",
+ VSQRT_LE_F64: "VSQRT.LE.F64",
+ VSQRT_F64: "VSQRT.F64",
+ VSQRT_ZZ_F64: "VSQRT.ZZ.F64",
+ VSTR_EQ: "VSTR.EQ",
+ VSTR_NE: "VSTR.NE",
+ VSTR_CS: "VSTR.CS",
+ VSTR_CC: "VSTR.CC",
+ VSTR_MI: "VSTR.MI",
+ VSTR_PL: "VSTR.PL",
+ VSTR_VS: "VSTR.VS",
+ VSTR_VC: "VSTR.VC",
+ VSTR_HI: "VSTR.HI",
+ VSTR_LS: "VSTR.LS",
+ VSTR_GE: "VSTR.GE",
+ VSTR_LT: "VSTR.LT",
+ VSTR_GT: "VSTR.GT",
+ VSTR_LE: "VSTR.LE",
+ VSTR: "VSTR",
+ VSTR_ZZ: "VSTR.ZZ",
+ VSUB_EQ_F32: "VSUB.EQ.F32",
+ VSUB_NE_F32: "VSUB.NE.F32",
+ VSUB_CS_F32: "VSUB.CS.F32",
+ VSUB_CC_F32: "VSUB.CC.F32",
+ VSUB_MI_F32: "VSUB.MI.F32",
+ VSUB_PL_F32: "VSUB.PL.F32",
+ VSUB_VS_F32: "VSUB.VS.F32",
+ VSUB_VC_F32: "VSUB.VC.F32",
+ VSUB_HI_F32: "VSUB.HI.F32",
+ VSUB_LS_F32: "VSUB.LS.F32",
+ VSUB_GE_F32: "VSUB.GE.F32",
+ VSUB_LT_F32: "VSUB.LT.F32",
+ VSUB_GT_F32: "VSUB.GT.F32",
+ VSUB_LE_F32: "VSUB.LE.F32",
+ VSUB_F32: "VSUB.F32",
+ VSUB_ZZ_F32: "VSUB.ZZ.F32",
+ VSUB_EQ_F64: "VSUB.EQ.F64",
+ VSUB_NE_F64: "VSUB.NE.F64",
+ VSUB_CS_F64: "VSUB.CS.F64",
+ VSUB_CC_F64: "VSUB.CC.F64",
+ VSUB_MI_F64: "VSUB.MI.F64",
+ VSUB_PL_F64: "VSUB.PL.F64",
+ VSUB_VS_F64: "VSUB.VS.F64",
+ VSUB_VC_F64: "VSUB.VC.F64",
+ VSUB_HI_F64: "VSUB.HI.F64",
+ VSUB_LS_F64: "VSUB.LS.F64",
+ VSUB_GE_F64: "VSUB.GE.F64",
+ VSUB_LT_F64: "VSUB.LT.F64",
+ VSUB_GT_F64: "VSUB.GT.F64",
+ VSUB_LE_F64: "VSUB.LE.F64",
+ VSUB_F64: "VSUB.F64",
+ VSUB_ZZ_F64: "VSUB.ZZ.F64",
+ WFE_EQ: "WFE.EQ",
+ WFE_NE: "WFE.NE",
+ WFE_CS: "WFE.CS",
+ WFE_CC: "WFE.CC",
+ WFE_MI: "WFE.MI",
+ WFE_PL: "WFE.PL",
+ WFE_VS: "WFE.VS",
+ WFE_VC: "WFE.VC",
+ WFE_HI: "WFE.HI",
+ WFE_LS: "WFE.LS",
+ WFE_GE: "WFE.GE",
+ WFE_LT: "WFE.LT",
+ WFE_GT: "WFE.GT",
+ WFE_LE: "WFE.LE",
+ WFE: "WFE",
+ WFE_ZZ: "WFE.ZZ",
+ WFI_EQ: "WFI.EQ",
+ WFI_NE: "WFI.NE",
+ WFI_CS: "WFI.CS",
+ WFI_CC: "WFI.CC",
+ WFI_MI: "WFI.MI",
+ WFI_PL: "WFI.PL",
+ WFI_VS: "WFI.VS",
+ WFI_VC: "WFI.VC",
+ WFI_HI: "WFI.HI",
+ WFI_LS: "WFI.LS",
+ WFI_GE: "WFI.GE",
+ WFI_LT: "WFI.LT",
+ WFI_GT: "WFI.GT",
+ WFI_LE: "WFI.LE",
+ WFI: "WFI",
+ WFI_ZZ: "WFI.ZZ",
+ YIELD_EQ: "YIELD.EQ",
+ YIELD_NE: "YIELD.NE",
+ YIELD_CS: "YIELD.CS",
+ YIELD_CC: "YIELD.CC",
+ YIELD_MI: "YIELD.MI",
+ YIELD_PL: "YIELD.PL",
+ YIELD_VS: "YIELD.VS",
+ YIELD_VC: "YIELD.VC",
+ YIELD_HI: "YIELD.HI",
+ YIELD_LS: "YIELD.LS",
+ YIELD_GE: "YIELD.GE",
+ YIELD_LT: "YIELD.LT",
+ YIELD_GT: "YIELD.GT",
+ YIELD_LE: "YIELD.LE",
+ YIELD: "YIELD",
+ YIELD_ZZ: "YIELD.ZZ",
+}
+
+var instFormats = [...]instFormat{
+ {0x0fe00000, 0x02a00000, 2, ADC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // ADC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|0|1|S|Rn:4|Rd:4|imm12:12
+ {0x0fe00090, 0x00a00010, 4, ADC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // ADC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fe00010, 0x00a00000, 2, ADC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // ADC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0fe00000, 0x02800000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // ADD{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|0|0|S|Rn:4|Rd:4|imm12:12
+ {0x0fe00090, 0x00800010, 4, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // ADD{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fe00010, 0x00800000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // ADD{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0fef0000, 0x028d0000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_SP, arg_const}}, // ADD{S}<c> <Rd>,SP,#<const> cond:4|0|0|1|0|1|0|0|S|1|1|0|1|Rd:4|imm12:12
+ {0x0fef0010, 0x008d0000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_SP, arg_R_shift_imm}}, // ADD{S}<c> <Rd>,SP,<Rm>{,<shift>} cond:4|0|0|0|0|1|0|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0fe00000, 0x02000000, 2, AND_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // AND{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|0|0|S|Rn:4|Rd:4|imm12:12
+ {0x0fe00090, 0x00000010, 4, AND_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // AND{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fe00010, 0x00000000, 2, AND_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // AND{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0fef0070, 0x01a00040, 4, ASR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_imm5_32}}, // ASR{S}<c> <Rd>,<Rm>,#<imm5_32> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|0|0|Rm:4
+ {0x0fef00f0, 0x01a00050, 4, ASR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_R_8}}, // ASR{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|0|1|Rn:4
+ {0x0f000000, 0x0a000000, 4, B_EQ, 0x1c04, instArgs{arg_label24}}, // B<c> <label24> cond:4|1|0|1|0|imm24:24
+ {0x0fe0007f, 0x07c0001f, 4, BFC_EQ, 0x1c04, instArgs{arg_R_12, arg_imm5, arg_lsb_width}}, // BFC<c> <Rd>,#<lsb>,#<width> cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|1|1|1|1
+ {0x0fe00070, 0x07c00010, 2, BFI_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_imm5, arg_lsb_width}}, // BFI<c> <Rd>,<Rn>,#<lsb>,#<width> cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|Rn:4
+ {0x0fe00000, 0x03c00000, 2, BIC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // BIC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|1|1|1|0|S|Rn:4|Rd:4|imm12:12
+ {0x0fe00090, 0x01c00010, 4, BIC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // BIC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fe00010, 0x01c00000, 2, BIC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // BIC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0ff000f0, 0x01200070, 4, BKPT_EQ, 0x1c04, instArgs{arg_imm_12at8_4at0}}, // BKPT<c> #<imm12+4> cond:4|0|0|0|1|0|0|1|0|imm12:12|0|1|1|1|imm4:4
+ {0x0f000000, 0x0b000000, 4, BL_EQ, 0x1c04, instArgs{arg_label24}}, // BL<c> <label24> cond:4|1|0|1|1|imm24:24
+ {0xfe000000, 0xfa000000, 4, BLX, 0x0, instArgs{arg_label24H}}, // BLX <label24H> 1|1|1|1|1|0|1|H|imm24:24
+ {0x0ffffff0, 0x012fff30, 4, BLX_EQ, 0x1c04, instArgs{arg_R_0}}, // BLX<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff000f0, 0x012fff30, 3, BLX_EQ, 0x1c04, instArgs{arg_R_0}}, // BLX<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ffffff0, 0x012fff10, 4, BX_EQ, 0x1c04, instArgs{arg_R_0}}, // BX<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff000f0, 0x012fff10, 3, BX_EQ, 0x1c04, instArgs{arg_R_0}}, // BX<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ffffff0, 0x012fff20, 4, BXJ_EQ, 0x1c04, instArgs{arg_R_0}}, // BXJ<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4
+ {0x0ff000f0, 0x012fff20, 3, BXJ_EQ, 0x1c04, instArgs{arg_R_0}}, // BXJ<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4
+ {0xffffffff, 0xf57ff01f, 4, CLREX, 0x0, instArgs{}}, // CLREX 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1)
+ {0xfff000f0, 0xf57ff01f, 3, CLREX, 0x0, instArgs{}}, // CLREX 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1)
+ {0x0fff0ff0, 0x016f0f10, 4, CLZ_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // CLZ<c> <Rd>,<Rm> cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff000f0, 0x016f0f10, 3, CLZ_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // CLZ<c> <Rd>,<Rm> cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff0f000, 0x03700000, 4, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMN<c> <Rn>,#<const> cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
+ {0x0ff00000, 0x03700000, 3, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMN<c> <Rn>,#<const> cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
+ {0x0ff0f090, 0x01700010, 4, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMN<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
+ {0x0ff00090, 0x01700010, 3, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMN<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
+ {0x0ff0f010, 0x01700000, 4, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMN<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
+ {0x0ff00010, 0x01700000, 3, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMN<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
+ {0x0ff0f000, 0x03500000, 4, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMP<c> <Rn>,#<const> cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
+ {0x0ff00000, 0x03500000, 3, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMP<c> <Rn>,#<const> cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
+ {0x0ff0f090, 0x01500010, 4, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMP<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
+ {0x0ff00090, 0x01500010, 3, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMP<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
+ {0x0ff0f010, 0x01500000, 4, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMP<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
+ {0x0ff00010, 0x01500000, 3, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMP<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
+ {0x0ffffff0, 0x0320f0f0, 4, DBG_EQ, 0x1c04, instArgs{arg_option}}, // DBG<c> #<option> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|1|1|1|1|option:4
+ {0x0fff00f0, 0x0320f0f0, 3, DBG_EQ, 0x1c04, instArgs{arg_option}}, // DBG<c> #<option> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|1|1|1|1|option:4
+ {0xfffffff0, 0xf57ff050, 4, DMB, 0x0, instArgs{arg_option}}, // DMB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|1|option:4
+ {0xfff000f0, 0xf57ff050, 3, DMB, 0x0, instArgs{arg_option}}, // DMB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|1|option:4
+ {0xfffffff0, 0xf57ff040, 4, DSB, 0x0, instArgs{arg_option}}, // DSB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|0|option:4
+ {0xfff000f0, 0xf57ff040, 3, DSB, 0x0, instArgs{arg_option}}, // DSB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|0|option:4
+ {0x0fe00000, 0x02200000, 2, EOR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // EOR{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|0|1|S|Rn:4|Rd:4|imm12:12
+ {0x0fe00090, 0x00200010, 4, EOR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // EOR{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fe00010, 0x00200000, 2, EOR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // EOR{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
+ {0xfffffff0, 0xf57ff060, 4, ISB, 0x0, instArgs{arg_option}}, // ISB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|1|0|option:4
+ {0xfff000f0, 0xf57ff060, 3, ISB, 0x0, instArgs{arg_option}}, // ISB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|1|0|option:4
+ {0x0fd00000, 0x08900000, 2, LDM_EQ, 0x1c04, instArgs{arg_R_16_WB, arg_registers}}, // LDM<c> <Rn>{!},<registers> cond:4|1|0|0|0|1|0|W|1|Rn:4|register_list:16
+ {0x0fd00000, 0x08100000, 4, LDMDA_EQ, 0x1c04, instArgs{arg_R_16_WB, arg_registers}}, // LDMDA<c> <Rn>{!},<registers> cond:4|1|0|0|0|0|0|W|1|Rn:4|register_list:16
+ {0x0fd00000, 0x09100000, 4, LDMDB_EQ, 0x1c04, instArgs{arg_R_16_WB, arg_registers}}, // LDMDB<c> <Rn>{!},<registers> cond:4|1|0|0|1|0|0|W|1|Rn:4|register_list:16
+ {0x0fd00000, 0x09900000, 4, LDMIB_EQ, 0x1c04, instArgs{arg_R_16_WB, arg_registers}}, // LDMIB<c> <Rn>{!},<registers> cond:4|1|0|0|1|1|0|W|1|Rn:4|register_list:16
+ {0x0f7f0000, 0x051f0000, 4, LDR_EQ, 0x1c04, instArgs{arg_R_12, arg_label_pm_12}}, // LDR<c> <Rt>,<label+/-12> cond:4|0|1|0|(1)|U|0|(0)|1|1|1|1|1|Rt:4|imm12:12
+ {0x0e5f0000, 0x051f0000, 3, LDR_EQ, 0x1c04, instArgs{arg_R_12, arg_label_pm_12}}, // LDR<c> <Rt>,<label+/-12> cond:4|0|1|0|(1)|U|0|(0)|1|1|1|1|1|Rt:4|imm12:12
+ {0x0e500010, 0x06100000, 2, LDR_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_shift_imm_W}}, // LDR<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|0|W|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
+ {0x0e500000, 0x04100000, 2, LDR_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm12_W}}, // LDR<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|0|W|1|Rn:4|Rt:4|imm12:12
+ {0x0f7f0000, 0x055f0000, 4, LDRB_EQ, 0x1c04, instArgs{arg_R_12, arg_label_pm_12}}, // LDRB<c> <Rt>,<label+/-12> cond:4|0|1|0|(1)|U|1|(0)|1|1|1|1|1|Rt:4|imm12:12
+ {0x0e5f0000, 0x055f0000, 3, LDRB_EQ, 0x1c04, instArgs{arg_R_12, arg_label_pm_12}}, // LDRB<c> <Rt>,<label+/-12> cond:4|0|1|0|(1)|U|1|(0)|1|1|1|1|1|Rt:4|imm12:12
+ {0x0e500010, 0x06500000, 2, LDRB_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_shift_imm_W}}, // LDRB<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|1|W|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
+ {0x0e500000, 0x04500000, 2, LDRB_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm12_W}}, // LDRB<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|1|W|1|Rn:4|Rt:4|imm12:12
+ {0x0f700000, 0x04700000, 4, LDRBT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm12_postindex}}, // LDRBT<c> <Rt>,[<Rn>],#+/-<imm12> cond:4|0|1|0|0|U|1|1|1|Rn:4|Rt:4|imm12:12
+ {0x0f700010, 0x06700000, 4, LDRBT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_shift_imm_postindex}}, // LDRBT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|1|1|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
+ {0x0e500ff0, 0x000000d0, 4, LDRD_EQ, 0x1c04, instArgs{arg_R1_12, arg_R2_12, arg_mem_R_pm_R_W}}, // LDRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|0|1|Rm:4
+ {0x0e5000f0, 0x000000d0, 3, LDRD_EQ, 0x1c04, instArgs{arg_R1_12, arg_R2_12, arg_mem_R_pm_R_W}}, // LDRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|0|1|Rm:4
+ {0x0e5000f0, 0x004000d0, 2, LDRD_EQ, 0x1c04, instArgs{arg_R1_12, arg_R2_12, arg_mem_R_pm_imm8_W}}, // LDRD<c> <Rt1>,<Rt2>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4
+ {0x0ff00fff, 0x01900f9f, 4, LDREX_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R}}, // LDREX<c> <Rt>,[<Rn>] cond:4|0|0|0|1|1|0|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
+ {0x0ff000f0, 0x01900f9f, 3, LDREX_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R}}, // LDREX<c> <Rt>,[<Rn>] cond:4|0|0|0|1|1|0|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
+ {0x0ff00fff, 0x01d00f9f, 4, LDREXB_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R}}, // LDREXB<c> <Rt>, [<Rn>] cond:4|0|0|0|1|1|1|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
+ {0x0ff000f0, 0x01d00f9f, 3, LDREXB_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R}}, // LDREXB<c> <Rt>, [<Rn>] cond:4|0|0|0|1|1|1|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
+ {0x0ff00fff, 0x01b00f9f, 4, LDREXD_EQ, 0x1c04, instArgs{arg_R1_12, arg_R2_12, arg_mem_R}}, // LDREXD<c> <Rt1>,<Rt2>,[<Rn>] cond:4|0|0|0|1|1|0|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
+ {0x0ff000f0, 0x01b00f9f, 3, LDREXD_EQ, 0x1c04, instArgs{arg_R1_12, arg_R2_12, arg_mem_R}}, // LDREXD<c> <Rt1>,<Rt2>,[<Rn>] cond:4|0|0|0|1|1|0|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
+ {0x0ff00fff, 0x01f00f9f, 4, LDREXH_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R}}, // LDREXH<c> <Rt>, [<Rn>] cond:4|0|0|0|1|1|1|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
+ {0x0ff000f0, 0x01f00f9f, 3, LDREXH_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R}}, // LDREXH<c> <Rt>, [<Rn>] cond:4|0|0|0|1|1|1|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
+ {0x0e500ff0, 0x001000b0, 2, LDRH_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_W}}, // LDRH<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4
+ {0x0e5000f0, 0x005000b0, 2, LDRH_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm8_W}}, // LDRH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4
+ {0x0f7000f0, 0x007000b0, 4, LDRHT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm8_postindex}}, // LDRHT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4
+ {0x0f700ff0, 0x003000b0, 4, LDRHT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_postindex}}, // LDRHT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4
+ {0x0e500ff0, 0x001000d0, 2, LDRSB_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_W}}, // LDRSB<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|1|0|1|Rm:4
+ {0x0e5000f0, 0x005000d0, 2, LDRSB_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm8_W}}, // LDRSB<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4
+ {0x0f7000f0, 0x007000d0, 4, LDRSBT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm8_postindex}}, // LDRSBT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4
+ {0x0f700ff0, 0x003000d0, 4, LDRSBT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_postindex}}, // LDRSBT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|1|0|1|Rm:4
+ {0x0e500ff0, 0x001000f0, 2, LDRSH_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_W}}, // LDRSH<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|1|1|1|Rm:4
+ {0x0e5000f0, 0x005000f0, 2, LDRSH_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm8_W}}, // LDRSH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4
+ {0x0f7000f0, 0x007000f0, 4, LDRSHT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm8_postindex}}, // LDRSHT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4
+ {0x0f700ff0, 0x003000f0, 4, LDRSHT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_postindex}}, // LDRSHT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|1|1|1|Rm:4
+ {0x0f700000, 0x04300000, 4, LDRT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm12_postindex}}, // LDRT<c> <Rt>, [<Rn>] {,#+/-<imm12>} cond:4|0|1|0|0|U|0|1|1|Rn:4|Rt:4|imm12:12
+ {0x0f700010, 0x06300000, 4, LDRT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_shift_imm_postindex}}, // LDRT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|0|1|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
+ {0x0fef0070, 0x01a00000, 2, LSL_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_imm5_nz}}, // LSL{S}<c> <Rd>,<Rm>,#<imm5_nz> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|0|0|0|Rm:4
+ {0x0fef00f0, 0x01a00010, 4, LSL_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_R_8}}, // LSL{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|0|0|1|Rn:4
+ {0x0fef0070, 0x01a00020, 4, LSR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_imm5_32}}, // LSR{S}<c> <Rd>,<Rm>,#<imm5_32> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|0|1|0|Rm:4
+ {0x0fef00f0, 0x01a00030, 4, LSR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_R_8}}, // LSR{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|0|1|1|Rn:4
+ {0x0fe000f0, 0x00200090, 4, MLA_EQ, 0x14011c04, instArgs{arg_R_16, arg_R_0, arg_R_8, arg_R_12}}, // MLA{S}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|0|0|0|1|S|Rd:4|Ra:4|Rm:4|1|0|0|1|Rn:4
+ {0x0ff000f0, 0x00600090, 4, MLS_EQ, 0x1c04, instArgs{arg_R_16, arg_R_0, arg_R_8, arg_R_12}}, // MLS<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|0|0|1|1|0|Rd:4|Ra:4|Rm:4|1|0|0|1|Rn:4
+ {0x0ff00000, 0x03400000, 4, MOVT_EQ, 0x1c04, instArgs{arg_R_12, arg_imm_4at16_12at0}}, // MOVT<c> <Rd>,#<imm12+4> cond:4|0|0|1|1|0|1|0|0|imm4:4|Rd:4|imm12:12
+ {0x0ff00000, 0x03000000, 4, MOVW_EQ, 0x1c04, instArgs{arg_R_12, arg_imm_4at16_12at0}}, // MOVW<c> <Rd>,#<imm12+4> cond:4|0|0|1|1|0|0|0|0|imm4:4|Rd:4|imm12:12
+ {0x0fef0000, 0x03a00000, 2, MOV_EQ, 0x14011c04, instArgs{arg_R_12, arg_const}}, // MOV{S}<c> <Rd>,#<const> cond:4|0|0|1|1|1|0|1|S|0|0|0|0|Rd:4|imm12:12
+ {0x0fef0ff0, 0x01a00000, 2, MOV_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0}}, // MOV{S}<c> <Rd>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|0|0|0|0|0|0|0|0|Rm:4
+ {0x0fff0fff, 0x010f0000, 4, MRS_EQ, 0x1c04, instArgs{arg_R_12, arg_APSR}}, // MRS<c> <Rd>,APSR cond:4|0|0|0|1|0|0|0|0|(1)|(1)|(1)|(1)|Rd:4|(0)|(0)|(0)|(0)|0|0|0|0|(0)|(0)|(0)|(0)
+ {0x0ff000f0, 0x010f0000, 3, MRS_EQ, 0x1c04, instArgs{arg_R_12, arg_APSR}}, // MRS<c> <Rd>,APSR cond:4|0|0|0|1|0|0|0|0|(1)|(1)|(1)|(1)|Rd:4|(0)|(0)|(0)|(0)|0|0|0|0|(0)|(0)|(0)|(0)
+ {0x0fe0f0f0, 0x00000090, 4, MUL_EQ, 0x14011c04, instArgs{arg_R_16, arg_R_0, arg_R_8}}, // MUL{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|0|0|0|0|S|Rd:4|(0)|(0)|(0)|(0)|Rm:4|1|0|0|1|Rn:4
+ {0x0fe000f0, 0x00000090, 3, MUL_EQ, 0x14011c04, instArgs{arg_R_16, arg_R_0, arg_R_8}}, // MUL{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|0|0|0|0|S|Rd:4|(0)|(0)|(0)|(0)|Rm:4|1|0|0|1|Rn:4
+ {0x0fef0000, 0x03e00000, 2, MVN_EQ, 0x14011c04, instArgs{arg_R_12, arg_const}}, // MVN{S}<c> <Rd>,#<const> cond:4|0|0|1|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm12:12
+ {0x0fe00000, 0x03e00000, 1, MVN_EQ, 0x14011c04, instArgs{arg_R_12, arg_const}}, // MVN{S}<c> <Rd>,#<const> cond:4|0|0|1|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm12:12
+ {0x0fef0090, 0x01e00010, 4, MVN_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_shift_R}}, // MVN{S}<c> <Rd>,<Rm>,<type> <Rs> cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fe00090, 0x01e00010, 3, MVN_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_shift_R}}, // MVN{S}<c> <Rd>,<Rm>,<type> <Rs> cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fef0010, 0x01e00000, 2, MVN_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_shift_imm}}, // MVN{S}<c> <Rd>,<Rm>{,<shift>} cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0fe00010, 0x01e00000, 1, MVN_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_shift_imm}}, // MVN{S}<c> <Rd>,<Rm>{,<shift>} cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0fffffff, 0x0320f000, 4, NOP_EQ, 0x1c04, instArgs{}}, // NOP<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|0
+ {0x0fff00ff, 0x0320f000, 3, NOP_EQ, 0x1c04, instArgs{}}, // NOP<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|0
+ {0x0fe00000, 0x03800000, 2, ORR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // ORR{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|1|1|0|0|S|Rn:4|Rd:4|imm12:12
+ {0x0fe00090, 0x01800010, 4, ORR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // ORR{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fe00010, 0x01800000, 2, ORR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // ORR{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0ff00030, 0x06800010, 4, PKHBT_EQ, 0x6011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // PKH<BT,TB><c> <Rd>,<Rn>,<Rm>{,LSL #<imm5>} cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|imm5:5|tb|0|1|Rm:4
+ {0xff7ff000, 0xf55ff000, 4, PLD, 0x0, instArgs{arg_label_pm_12}}, // PLD <label+/-12> 1|1|1|1|0|1|0|1|U|(1)|0|1|1|1|1|1|(1)|(1)|(1)|(1)|imm12:12
+ {0xff3f0000, 0xf55ff000, 3, PLD, 0x0, instArgs{arg_label_pm_12}}, // PLD <label+/-12> 1|1|1|1|0|1|0|1|U|(1)|0|1|1|1|1|1|(1)|(1)|(1)|(1)|imm12:12
+ {0xff30f000, 0xf510f000, 2, PLD_W, 0x1601, instArgs{arg_mem_R_pm_imm12_offset}}, // PLD{W} [<Rn>,#+/-<imm12>] 1|1|1|1|0|1|0|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12
+ {0xff300000, 0xf510f000, 1, PLD_W, 0x1601, instArgs{arg_mem_R_pm_imm12_offset}}, // PLD{W} [<Rn>,#+/-<imm12>] 1|1|1|1|0|1|0|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12
+ {0xff30f010, 0xf710f000, 4, PLD_W, 0x1601, instArgs{arg_mem_R_pm_R_shift_imm_offset}}, // PLD{W} [<Rn>,+/-<Rm>{, <shift>}] 1|1|1|1|0|1|1|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4
+ {0xff300010, 0xf710f000, 3, PLD_W, 0x1601, instArgs{arg_mem_R_pm_R_shift_imm_offset}}, // PLD{W} [<Rn>,+/-<Rm>{, <shift>}] 1|1|1|1|0|1|1|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4
+ {0xff70f000, 0xf450f000, 4, PLI, 0x0, instArgs{arg_mem_R_pm_imm12_offset}}, // PLI [<Rn>,#+/-<imm12>] 1|1|1|1|0|1|0|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12
+ {0xff700000, 0xf450f000, 3, PLI, 0x0, instArgs{arg_mem_R_pm_imm12_offset}}, // PLI [<Rn>,#+/-<imm12>] 1|1|1|1|0|1|0|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12
+ {0xff70f010, 0xf650f000, 4, PLI, 0x0, instArgs{arg_mem_R_pm_R_shift_imm_offset}}, // PLI [<Rn>,+/-<Rm>{, <shift>}] 1|1|1|1|0|1|1|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4
+ {0xff700010, 0xf650f000, 3, PLI, 0x0, instArgs{arg_mem_R_pm_R_shift_imm_offset}}, // PLI [<Rn>,+/-<Rm>{, <shift>}] 1|1|1|1|0|1|1|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4
+ {0x0fff0000, 0x08bd0000, 4, POP_EQ, 0x1c04, instArgs{arg_registers2}}, // POP<c> <registers2> cond:4|1|0|0|0|1|0|1|1|1|1|0|1|register_list:16
+ {0x0fff0fff, 0x049d0004, 4, POP_EQ, 0x1c04, instArgs{arg_registers1}}, // POP<c> <registers1> cond:4|0|1|0|0|1|0|0|1|1|1|0|1|Rt:4|0|0|0|0|0|0|0|0|0|1|0|0
+ {0x0fff0000, 0x092d0000, 4, PUSH_EQ, 0x1c04, instArgs{arg_registers2}}, // PUSH<c> <registers2> cond:4|1|0|0|1|0|0|1|0|1|1|0|1|register_list:16
+ {0x0fff0fff, 0x052d0004, 4, PUSH_EQ, 0x1c04, instArgs{arg_registers1}}, // PUSH<c> <registers1> cond:4|0|1|0|1|0|0|1|0|1|1|0|1|Rt:4|0|0|0|0|0|0|0|0|0|1|0|0
+ {0x0ff00ff0, 0x06200f10, 4, QADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff000f0, 0x06200f10, 3, QADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff00ff0, 0x06200f90, 4, QADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff000f0, 0x06200f90, 3, QADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff00ff0, 0x01000050, 4, QADD_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_R_16}}, // QADD<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|0|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4
+ {0x0ff000f0, 0x01000050, 3, QADD_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_R_16}}, // QADD<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|0|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4
+ {0x0ff00ff0, 0x06200f30, 4, QASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff000f0, 0x06200f30, 3, QASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff00ff0, 0x01400050, 4, QDADD_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_R_16}}, // QDADD<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|1|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4
+ {0x0ff000f0, 0x01400050, 3, QDADD_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_R_16}}, // QDADD<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|1|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4
+ {0x0ff00ff0, 0x01600050, 4, QDSUB_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_R_16}}, // QDSUB<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|1|1|0|Rn:4|Rd:4|0|0|0|0|0|1|0|1|Rm:4
+ {0x0ff00ff0, 0x06200f50, 4, QSAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff000f0, 0x06200f50, 3, QSAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff00ff0, 0x06200f70, 4, QSUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff000f0, 0x06200f70, 3, QSUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff00ff0, 0x06200ff0, 4, QSUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0ff000f0, 0x06200ff0, 3, QSUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // QSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0ff00ff0, 0x01200050, 4, QSUB_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_R_16}}, // QSUB<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|0|1|0|Rn:4|Rd:4|0|0|0|0|0|1|0|1|Rm:4
+ {0x0fff0ff0, 0x06ff0f30, 4, RBIT_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // RBIT<c> <Rd>,<Rm> cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff000f0, 0x06ff0f30, 3, RBIT_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // RBIT<c> <Rd>,<Rm> cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0fff0ff0, 0x06bf0fb0, 4, REV16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // REV16<c> <Rd>,<Rm> cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
+ {0x0ff000f0, 0x06bf0fb0, 3, REV16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // REV16<c> <Rd>,<Rm> cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
+ {0x0fff0ff0, 0x06bf0f30, 4, REV_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // REV<c> <Rd>,<Rm> cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff000f0, 0x06bf0f30, 3, REV_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // REV<c> <Rd>,<Rm> cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0fff0ff0, 0x06ff0fb0, 4, REVSH_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // REVSH<c> <Rd>,<Rm> cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
+ {0x0ff000f0, 0x06ff0fb0, 3, REVSH_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // REVSH<c> <Rd>,<Rm> cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
+ {0x0fef0070, 0x01a00060, 2, ROR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_imm5}}, // ROR{S}<c> <Rd>,<Rm>,#<imm5> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|1|0|Rm:4
+ {0x0fef00f0, 0x01a00070, 4, ROR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_R_8}}, // ROR{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|1|1|Rn:4
+ {0x0fef0ff0, 0x01a00060, 4, RRX_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0}}, // RRX{S}<c> <Rd>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|0|0|0|0|0|1|1|0|Rm:4
+ {0x0fe00000, 0x02600000, 2, RSB_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // RSB{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|1|1|S|Rn:4|Rd:4|imm12:12
+ {0x0fe00090, 0x00600010, 4, RSB_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // RSB{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|1|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fe00010, 0x00600000, 2, RSB_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // RSB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|1|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0fe00000, 0x02e00000, 2, RSC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // RSC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|1|1|S|Rn:4|Rd:4|imm12:12
+ {0x0fe00090, 0x00e00010, 4, RSC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // RSC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|1|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fe00010, 0x00e00000, 2, RSC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // RSC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|1|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0ff00ff0, 0x06100f10, 4, SADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff000f0, 0x06100f10, 3, SADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff00ff0, 0x06100f90, 4, SADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff000f0, 0x06100f90, 3, SADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff00ff0, 0x06100f30, 4, SASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff000f0, 0x06100f30, 3, SASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0fe00000, 0x02c00000, 2, SBC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // SBC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|1|0|S|Rn:4|Rd:4|imm12:12
+ {0x0fe00090, 0x00c00010, 4, SBC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // SBC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fe00010, 0x00c00000, 2, SBC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // SBC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0fe00070, 0x07a00050, 4, SBFX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_imm5, arg_widthm1}}, // SBFX<c> <Rd>,<Rn>,#<lsb>,#<widthm1> cond:4|0|1|1|1|1|0|1|widthm1:5|Rd:4|lsb:5|1|0|1|Rn:4
+ {0x0ff00ff0, 0x06800fb0, 4, SEL_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SEL<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
+ {0x0ff000f0, 0x06800fb0, 3, SEL_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SEL<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
+ {0xfffffdff, 0xf1010000, 4, SETEND, 0x0, instArgs{arg_endian}}, // SETEND <endian_specifier> 1|1|1|1|0|0|0|1|0|0|0|0|0|0|0|1|0|0|0|0|0|0|E|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)
+ {0xfffffc00, 0xf1010000, 3, SETEND, 0x0, instArgs{arg_endian}}, // SETEND <endian_specifier> 1|1|1|1|0|0|0|1|0|0|0|0|0|0|0|1|0|0|0|0|0|0|E|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)
+ {0x0fffffff, 0x0320f004, 4, SEV_EQ, 0x1c04, instArgs{}}, // SEV<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|1|0|0
+ {0x0fff00ff, 0x0320f004, 3, SEV_EQ, 0x1c04, instArgs{}}, // SEV<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|1|0|0
+ {0x0ff00ff0, 0x06300f10, 4, SHADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff000f0, 0x06300f10, 3, SHADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff00ff0, 0x06300f90, 4, SHADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff000f0, 0x06300f90, 3, SHADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff00ff0, 0x06300f30, 4, SHASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff000f0, 0x06300f30, 3, SHASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff00ff0, 0x06300f50, 4, SHSAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff000f0, 0x06300f50, 3, SHSAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff00ff0, 0x06300f70, 4, SHSUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff000f0, 0x06300f70, 3, SHSUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff00ff0, 0x06300ff0, 4, SHSUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0ff000f0, 0x06300ff0, 3, SHSUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SHSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0ff00090, 0x01000080, 4, SMLABB_EQ, 0x50106011c04, instArgs{arg_R_16, arg_R_0, arg_R_8, arg_R_12}}, // SMLA<x><y><c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|1|0|0|0|0|Rd:4|Ra:4|Rm:4|1|M|N|0|Rn:4
+ {0x0ff000d0, 0x07000010, 2, SMLAD_EQ, 0x5011c04, instArgs{arg_R_16, arg_R_0, arg_R_8, arg_R_12}}, // SMLAD{X}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|0|0|0|Rd:4|Ra:4|Rm:4|0|0|M|1|Rn:4
+ {0x0ff00090, 0x01400080, 4, SMLALBB_EQ, 0x50106011c04, instArgs{arg_R_12, arg_R_16, arg_R_0, arg_R_8}}, // SMLAL<x><y><c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|1|M|N|0|Rn:4
+ {0x0ff000d0, 0x07400010, 4, SMLALD_EQ, 0x5011c04, instArgs{arg_R_12, arg_R_16, arg_R_0, arg_R_8}}, // SMLALD{X}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|1|1|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|0|0|M|1|Rn:4
+ {0x0fe000f0, 0x00e00090, 4, SMLAL_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_0, arg_R_8}}, // SMLAL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|1|1|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
+ {0x0ff000b0, 0x01200080, 4, SMLAWB_EQ, 0x6011c04, instArgs{arg_R_16, arg_R_0, arg_R_8, arg_R_12}}, // SMLAW<y><c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|1|0|0|1|0|Rd:4|Ra:4|Rm:4|1|M|0|0|Rn:4
+ {0x0ff000d0, 0x07000050, 2, SMLSD_EQ, 0x5011c04, instArgs{arg_R_16, arg_R_0, arg_R_8, arg_R_12}}, // SMLSD{X}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|0|0|0|Rd:4|Ra:4|Rm:4|0|1|M|1|Rn:4
+ {0x0ff000d0, 0x07400050, 4, SMLSLD_EQ, 0x5011c04, instArgs{arg_R_12, arg_R_16, arg_R_0, arg_R_8}}, // SMLSLD{X}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|1|1|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|0|1|M|1|Rn:4
+ {0x0ff000d0, 0x07500010, 2, SMMLA_EQ, 0x5011c04, instArgs{arg_R_16, arg_R_0, arg_R_8, arg_R_12}}, // SMMLA{R}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|1|0|1|Rd:4|Ra:4|Rm:4|0|0|R|1|Rn:4
+ {0x0ff000d0, 0x075000d0, 4, SMMLS_EQ, 0x5011c04, instArgs{arg_R_16, arg_R_0, arg_R_8, arg_R_12}}, // SMMLS{R}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|1|0|1|Rd:4|Ra:4|Rm:4|1|1|R|1|Rn:4
+ {0x0ff0f0d0, 0x0750f010, 4, SMMUL_EQ, 0x5011c04, instArgs{arg_R_16, arg_R_0, arg_R_8}}, // SMMUL{R}<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|0|1|0|1|Rd:4|1|1|1|1|Rm:4|0|0|R|1|Rn:4
+ {0x0ff0f0d0, 0x0700f010, 4, SMUAD_EQ, 0x5011c04, instArgs{arg_R_16, arg_R_0, arg_R_8}}, // SMUAD{X}<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|0|0|0|0|Rd:4|1|1|1|1|Rm:4|0|0|M|1|Rn:4
+ {0x0ff0f090, 0x01600080, 4, SMULBB_EQ, 0x50106011c04, instArgs{arg_R_16, arg_R_0, arg_R_8}}, // SMUL<x><y><c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|0|1|1|0|Rd:4|0|0|0|0|Rm:4|1|M|N|0|Rn:4
+ {0x0fe000f0, 0x00c00090, 4, SMULL_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_0, arg_R_8}}, // SMULL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|1|0|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
+ {0x0ff0f0b0, 0x012000a0, 4, SMULWB_EQ, 0x6011c04, instArgs{arg_R_16, arg_R_0, arg_R_8}}, // SMULW<y><c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|0|0|1|0|Rd:4|0|0|0|0|Rm:4|1|M|1|0|Rn:4
+ {0x0ff0f0d0, 0x0700f050, 4, SMUSD_EQ, 0x5011c04, instArgs{arg_R_16, arg_R_0, arg_R_8}}, // SMUSD{X}<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|0|0|0|0|Rd:4|1|1|1|1|Rm:4|0|1|M|1|Rn:4
+ {0x0ff00ff0, 0x06a00f30, 4, SSAT16_EQ, 0x1c04, instArgs{arg_R_12, arg_satimm4m1, arg_R_0}}, // SSAT16<c> <Rd>,#<sat_imm4m1>,<Rn> cond:4|0|1|1|0|1|0|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4
+ {0x0ff000f0, 0x06a00f30, 3, SSAT16_EQ, 0x1c04, instArgs{arg_R_12, arg_satimm4m1, arg_R_0}}, // SSAT16<c> <Rd>,#<sat_imm4m1>,<Rn> cond:4|0|1|1|0|1|0|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4
+ {0x0fe00030, 0x06a00010, 4, SSAT_EQ, 0x1c04, instArgs{arg_R_12, arg_satimm5m1, arg_R_shift_imm}}, // SSAT<c> <Rd>,#<sat_imm5m1>,<Rn>{,<shift>} cond:4|0|1|1|0|1|0|1|sat_imm:5|Rd:4|imm5:5|sh|0|1|Rn:4
+ {0x0ff00ff0, 0x06100f50, 4, SSAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff000f0, 0x06100f50, 3, SSAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff00ff0, 0x06100f70, 4, SSUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff000f0, 0x06100f70, 3, SSUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff00ff0, 0x06100ff0, 4, SSUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0ff000f0, 0x06100ff0, 3, SSUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // SSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0fd00000, 0x08800000, 4, STM_EQ, 0x1c04, instArgs{arg_R_16_WB, arg_registers}}, // STM<c> <Rn>{!},<registers> cond:4|1|0|0|0|1|0|W|0|Rn:4|register_list:16
+ {0x0fd00000, 0x08000000, 4, STMDA_EQ, 0x1c04, instArgs{arg_R_16_WB, arg_registers}}, // STMDA<c> <Rn>{!},<registers> cond:4|1|0|0|0|0|0|W|0|Rn:4|register_list:16
+ {0x0fd00000, 0x09000000, 2, STMDB_EQ, 0x1c04, instArgs{arg_R_16_WB, arg_registers}}, // STMDB<c> <Rn>{!},<registers> cond:4|1|0|0|1|0|0|W|0|Rn:4|register_list:16
+ {0x0fd00000, 0x09800000, 4, STMIB_EQ, 0x1c04, instArgs{arg_R_16_WB, arg_registers}}, // STMIB<c> <Rn>{!},<registers> cond:4|1|0|0|1|1|0|W|0|Rn:4|register_list:16
+ {0x0e500018, 0x06000000, 2, STR_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_shift_imm_W}}, // STR<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|0|W|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
+ {0x0e500000, 0x04000000, 2, STR_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm12_W}}, // STR<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|0|W|0|Rn:4|Rt:4|imm12:12
+ {0x0e500010, 0x06400000, 2, STRB_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_shift_imm_W}}, // STRB<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|1|W|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
+ {0x0e500000, 0x04400000, 2, STRB_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm12_W}}, // STRB<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|1|W|0|Rn:4|Rt:4|imm12:12
+ {0x0f700000, 0x04600000, 4, STRBT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm12_postindex}}, // STRBT<c> <Rt>,[<Rn>],#+/-<imm12> cond:4|0|1|0|0|U|1|1|0|Rn:4|Rt:4|imm12:12
+ {0x0f700010, 0x06600000, 4, STRBT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_shift_imm_postindex}}, // STRBT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|1|1|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
+ {0x0e500ff0, 0x000000f0, 4, STRD_EQ, 0x1c04, instArgs{arg_R1_12, arg_R2_12, arg_mem_R_pm_R_W}}, // STRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|1|1|Rm:4
+ {0x0e5000f0, 0x000000f0, 3, STRD_EQ, 0x1c04, instArgs{arg_R1_12, arg_R2_12, arg_mem_R_pm_R_W}}, // STRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|1|1|Rm:4
+ {0x0e5000f0, 0x004000f0, 4, STRD_EQ, 0x1c04, instArgs{arg_R1_12, arg_R2_12, arg_mem_R_pm_imm8_W}}, // STRD<c> <Rt1>,<Rt2>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4
+ {0x0ff00ff0, 0x01800f90, 4, STREX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_mem_R}}, // STREX<c> <Rd>,<Rt>,[<Rn>] cond:4|0|0|0|1|1|0|0|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
+ {0x0ff00ff0, 0x01c00f90, 4, STREXB_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_mem_R}}, // STREXB<c> <Rd>,<Rt>,[<Rn>] cond:4|0|0|0|1|1|1|0|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
+ {0x0ff00ff0, 0x01a00f90, 4, STREXD_EQ, 0x1c04, instArgs{arg_R_12, arg_R1_0, arg_R2_0, arg_mem_R}}, // STREXD<c> <Rd>,<Rt1>,<Rt2>,[<Rn>] cond:4|0|0|0|1|1|0|1|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
+ {0x0ff00ff0, 0x01e00f90, 4, STREXH_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_mem_R}}, // STREXH<c> <Rd>,<Rt>,[<Rn>] cond:4|0|0|0|1|1|1|1|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
+ {0x0e500ff0, 0x000000b0, 2, STRH_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_W}}, // STRH<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4
+ {0x0e5000f0, 0x004000b0, 2, STRH_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm8_W}}, // STRH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4
+ {0x0f7000f0, 0x006000b0, 4, STRHT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm8_postindex}}, // STRHT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|0|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4
+ {0x0f700ff0, 0x002000b0, 4, STRHT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_postindex}}, // STRHT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|0|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4
+ {0x0f700000, 0x04200000, 4, STRT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_imm12_postindex}}, // STRT<c> <Rt>, [<Rn>] {,#+/-<imm12>} cond:4|0|1|0|0|U|0|1|0|Rn:4|Rt:4|imm12:12
+ {0x0f700010, 0x06200000, 4, STRT_EQ, 0x1c04, instArgs{arg_R_12, arg_mem_R_pm_R_shift_imm_postindex}}, // STRT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|0|1|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
+ {0x0fe00000, 0x02400000, 2, SUB_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // SUB{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|1|0|S|Rn:4|Rd:4|imm12:12
+ {0x0fe00090, 0x00400010, 4, SUB_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // SUB{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
+ {0x0fe00010, 0x00400000, 2, SUB_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // SUB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0fef0000, 0x024d0000, 2, SUB_EQ, 0x14011c04, instArgs{arg_R_12, arg_SP, arg_const}}, // SUB{S}<c> <Rd>,SP,#<const> cond:4|0|0|1|0|0|1|0|S|1|1|0|1|Rd:4|imm12:12
+ {0x0fef0010, 0x004d0000, 2, SUB_EQ, 0x14011c04, instArgs{arg_R_12, arg_SP, arg_R_shift_imm}}, // SUB{S}<c> <Rd>,SP,<Rm>{,<shift>} cond:4|0|0|0|0|0|1|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4
+ {0x0f000000, 0x0f000000, 4, SVC_EQ, 0x1c04, instArgs{arg_imm24}}, // SVC<c> #<imm24> cond:4|1|1|1|1|imm24:24
+ {0x0fb00ff0, 0x01000090, 4, SWP_EQ, 0x16011c04, instArgs{arg_R_12, arg_R_0, arg_mem_R}}, // SWP{B}<c> <Rt>,<Rm>,[<Rn>] cond:4|0|0|0|1|0|B|0|0|Rn:4|Rt:4|0|0|0|0|1|0|0|1|Rm:4
+ {0x0ff003f0, 0x06800070, 2, SXTAB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_rotate}}, // SXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0ff003f0, 0x06a00070, 2, SXTAB_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_rotate}}, // SXTAB<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0ff003f0, 0x06b00070, 2, SXTAH_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_rotate}}, // SXTAH<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|1|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0fff03f0, 0x068f0070, 4, SXTB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_rotate}}, // SXTB16<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|0|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0fff03f0, 0x06af0070, 4, SXTB_EQ, 0x1c04, instArgs{arg_R_12, arg_R_rotate}}, // SXTB<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0fff03f0, 0x06bf0070, 4, SXTH_EQ, 0x1c04, instArgs{arg_R_12, arg_R_rotate}}, // SXTH<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|1|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0ff0f000, 0x03300000, 4, TEQ_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // TEQ<c> <Rn>,#<const> cond:4|0|0|1|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
+ {0x0ff00000, 0x03300000, 3, TEQ_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // TEQ<c> <Rn>,#<const> cond:4|0|0|1|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
+ {0x0ff0f090, 0x01300010, 4, TEQ_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // TEQ<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
+ {0x0ff00090, 0x01300010, 3, TEQ_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // TEQ<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
+ {0x0ff0f010, 0x01300000, 4, TEQ_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // TEQ<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
+ {0x0ff00010, 0x01300000, 3, TEQ_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // TEQ<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
+ {0x0ff0f000, 0x03100000, 4, TST_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // TST<c> <Rn>,#<const> cond:4|0|0|1|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
+ {0x0ff00000, 0x03100000, 3, TST_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // TST<c> <Rn>,#<const> cond:4|0|0|1|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
+ {0x0ff0f090, 0x01100010, 4, TST_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // TST<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
+ {0x0ff00090, 0x01100010, 3, TST_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // TST<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
+ {0x0ff0f010, 0x01100000, 4, TST_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // TST<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
+ {0x0ff00010, 0x01100000, 3, TST_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // TST<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
+ {0x0ff00ff0, 0x06500f10, 4, UADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff000f0, 0x06500f10, 3, UADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff00ff0, 0x06500f90, 4, UADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff000f0, 0x06500f90, 3, UADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff00ff0, 0x06500f30, 4, UASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff000f0, 0x06500f30, 3, UASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0fe00070, 0x07e00050, 4, UBFX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_imm5, arg_widthm1}}, // UBFX<c> <Rd>,<Rn>,#<lsb>,#<widthm1> cond:4|0|1|1|1|1|1|1|widthm1:5|Rd:4|lsb:5|1|0|1|Rn:4
+ {0x0ff00ff0, 0x06700f10, 4, UHADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff000f0, 0x06700f10, 3, UHADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff00ff0, 0x06700f90, 4, UHADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff000f0, 0x06700f90, 3, UHADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff00ff0, 0x06700f30, 4, UHASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff000f0, 0x06700f30, 3, UHASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff00ff0, 0x06700f50, 4, UHSAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff000f0, 0x06700f50, 3, UHSAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff00ff0, 0x06700f70, 4, UHSUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff000f0, 0x06700f70, 3, UHSUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff00ff0, 0x06700ff0, 4, UHSUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0ff000f0, 0x06700ff0, 3, UHSUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UHSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0ff000f0, 0x00400090, 4, UMAAL_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0, arg_R_8}}, // UMAAL<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|0|1|0|0|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
+ {0x0fe000f0, 0x00a00090, 4, UMLAL_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_0, arg_R_8}}, // UMLAL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|0|1|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
+ {0x0fe000f0, 0x00800090, 4, UMULL_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_0, arg_R_8}}, // UMULL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|0|0|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
+ {0x0ff00ff0, 0x06600f10, 4, UQADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff000f0, 0x06600f10, 3, UQADD16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
+ {0x0ff00ff0, 0x06600f90, 4, UQADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff000f0, 0x06600f90, 3, UQADD8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
+ {0x0ff00ff0, 0x06600f30, 4, UQASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff000f0, 0x06600f30, 3, UQASX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
+ {0x0ff00ff0, 0x06600f50, 4, UQSAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff000f0, 0x06600f50, 3, UQSAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff00ff0, 0x06600f70, 4, UQSUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff000f0, 0x06600f70, 3, UQSUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff00ff0, 0x06600ff0, 4, UQSUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0ff000f0, 0x06600ff0, 3, UQSUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // UQSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0ff0f0f0, 0x0780f010, 4, USAD8_EQ, 0x1c04, instArgs{arg_R_16, arg_R_0, arg_R_8}}, // USAD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|1|0|0|0|Rd:4|1|1|1|1|Rm:4|0|0|0|1|Rn:4
+ {0x0ff000f0, 0x07800010, 2, USADA8_EQ, 0x1c04, instArgs{arg_R_16, arg_R_0, arg_R_8, arg_R_12}}, // USADA8<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|1|0|0|0|Rd:4|Ra:4|Rm:4|0|0|0|1|Rn:4
+ {0x0ff00ff0, 0x06e00f30, 4, USAT16_EQ, 0x1c04, instArgs{arg_R_12, arg_satimm4, arg_R_0}}, // USAT16<c> <Rd>,#<sat_imm4>,<Rn> cond:4|0|1|1|0|1|1|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4
+ {0x0ff000f0, 0x06e00f30, 3, USAT16_EQ, 0x1c04, instArgs{arg_R_12, arg_satimm4, arg_R_0}}, // USAT16<c> <Rd>,#<sat_imm4>,<Rn> cond:4|0|1|1|0|1|1|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4
+ {0x0fe00030, 0x06e00010, 4, USAT_EQ, 0x1c04, instArgs{arg_R_12, arg_satimm5, arg_R_shift_imm}}, // USAT<c> <Rd>,#<sat_imm5>,<Rn>{,<shift>} cond:4|0|1|1|0|1|1|1|sat_imm:5|Rd:4|imm5:5|sh|0|1|Rn:4
+ {0x0ff00ff0, 0x06500f50, 4, USAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // USAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff000f0, 0x06500f50, 3, USAX_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // USAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
+ {0x0ff00ff0, 0x06500f70, 4, USUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // USUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff000f0, 0x06500f70, 3, USUB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // USUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
+ {0x0ff00ff0, 0x06500ff0, 4, USUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // USUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0ff000f0, 0x06500ff0, 3, USUB8_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_0}}, // USUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
+ {0x0ff003f0, 0x06c00070, 2, UXTAB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_rotate}}, // UXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|0|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0ff003f0, 0x06e00070, 2, UXTAB_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_rotate}}, // UXTAB<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0ff003f0, 0x06f00070, 2, UXTAH_EQ, 0x1c04, instArgs{arg_R_12, arg_R_16, arg_R_rotate}}, // UXTAH<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|1|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0fff03f0, 0x06cf0070, 4, UXTB16_EQ, 0x1c04, instArgs{arg_R_12, arg_R_rotate}}, // UXTB16<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|0|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0fff03f0, 0x06ef0070, 4, UXTB_EQ, 0x1c04, instArgs{arg_R_12, arg_R_rotate}}, // UXTB<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0fff03f0, 0x06ff0070, 4, UXTH_EQ, 0x1c04, instArgs{arg_R_12, arg_R_rotate}}, // UXTH<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|1|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
+ {0x0fb00e10, 0x0e000a00, 4, VMLA_EQ_F32, 0x60108011c04, instArgs{arg_Sd_Dd, arg_Sn_Dn, arg_Sm_Dm}}, // V<MLA,MLS><c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|0|0|Vn:4|Vd:4|1|0|1|sz|N|op|M|0|Vm:4
+ {0x0fbf0ed0, 0x0eb00ac0, 4, VABS_EQ_F32, 0x8011c04, instArgs{arg_Sd_Dd, arg_Sm_Dm}}, // VABS<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|0|Vd:4|1|0|1|sz|1|1|M|0|Vm:4
+ {0x0fb00e50, 0x0e300a00, 4, VADD_EQ_F32, 0x8011c04, instArgs{arg_Sd_Dd, arg_Sn_Dn, arg_Sm_Dm}}, // VADD<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|1|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4
+ {0x0fbf0e7f, 0x0eb50a40, 4, VCMP_EQ_F32, 0x70108011c04, instArgs{arg_Sd_Dd, arg_fp_0}}, // VCMP{E}<c>.F<32,64> <Sd,Dd>, #0.0 cond:4|1|1|1|0|1|D|1|1|0|1|0|1|Vd:4|1|0|1|sz|E|1|0|0|(0)|(0)|(0)|(0)
+ {0x0fbf0e70, 0x0eb50a40, 3, VCMP_EQ_F32, 0x70108011c04, instArgs{arg_Sd_Dd, arg_fp_0}}, // VCMP{E}<c>.F<32,64> <Sd,Dd>, #0.0 cond:4|1|1|1|0|1|D|1|1|0|1|0|1|Vd:4|1|0|1|sz|E|1|0|0|(0)|(0)|(0)|(0)
+ {0x0fbf0e50, 0x0eb40a40, 4, VCMP_EQ_F32, 0x70108011c04, instArgs{arg_Sd_Dd, arg_Sm_Dm}}, // VCMP{E}<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|1|0|0|Vd:4|1|0|1|sz|E|1|M|0|Vm:4
+ {0x0fbe0e50, 0x0eba0a40, 4, VCVT_EQ_F32_FXS16, 0x801100107011c04, instArgs{arg_Sd_Dd, arg_Sd_Dd, arg_fbits}}, // VCVT<c>.F<32,64>.FX<S,U><16,32> <Sd,Dd>, <Sd,Dd>, #<fbits> cond:4|1|1|1|0|1|D|1|1|1|0|1|U|Vd:4|1|0|1|sz|sx|1|i|0|imm4:4
+ {0x0fbe0e50, 0x0ebe0a40, 4, VCVT_EQ_FXS16_F32, 0x1001070108011c04, instArgs{arg_Sd_Dd, arg_Sd_Dd, arg_fbits}}, // VCVT<c>.FX<S,U><16,32>.F<32,64> <Sd,Dd>, <Sd,Dd>, #<fbits> cond:4|1|1|1|0|1|D|1|1|1|1|1|U|Vd:4|1|0|1|sz|sx|1|i|0|imm4:4
+ {0x0fbf0ed0, 0x0eb70ac0, 4, VCVT_EQ_F64_F32, 0x8011c04, instArgs{arg_Dd_Sd, arg_Sm_Dm}}, // VCVT<c>.<F64.F32,F32.F64> <Dd,Sd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|1|1|1|Vd:4|1|0|1|sz|1|1|M|0|Vm:4
+ {0x0fbe0f50, 0x0eb20a40, 4, VCVTB_EQ_F32_F16, 0x70110011c04, instArgs{arg_Sd, arg_Sm}}, // VCVT<B,T><c>.<F32.F16,F16.F32> <Sd>, <Sm> cond:4|1|1|1|0|1|D|1|1|0|0|1|op|Vd:4|1|0|1|0|T|1|M|0|Vm:4
+ {0x0fbf0e50, 0x0eb80a40, 4, VCVT_EQ_F32_U32, 0x80107011c04, instArgs{arg_Sd_Dd, arg_Sm}}, // VCVT<c>.F<32,64>.<U,S>32 <Sd,Dd>, <Sm> cond:4|1|1|1|0|1|D|1|1|1|0|0|0|Vd:4|1|0|1|sz|op|1|M|0|Vm:4
+ {0x0fbe0e50, 0x0ebc0a40, 4, VCVTR_EQ_U32_F32, 0x701100108011c04, instArgs{arg_Sd, arg_Sm_Dm}}, // VCVT<R,><c>.<U,S>32.F<32,64> <Sd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|1|1|0|signed|Vd:4|1|0|1|sz|op|1|M|0|Vm:4
+ {0x0fb00e50, 0x0e800a00, 4, VDIV_EQ_F32, 0x8011c04, instArgs{arg_Sd_Dd, arg_Sn_Dn, arg_Sm_Dm}}, // VDIV<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|1|D|0|0|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4
+ {0x0f300e00, 0x0d100a00, 4, VLDR_EQ, 0x1c04, instArgs{arg_Sd_Dd, arg_mem_R_pm_imm8at0_offset}}, // VLDR<c> <Sd,Dd>, [<Rn>{,#+/-<imm8>}] cond:4|1|1|0|1|U|D|0|1|Rn:4|Vd:4|1|0|1|sz|imm8:8
+ {0x0ff00f7f, 0x0e000a10, 4, VMOV_EQ, 0x1c04, instArgs{arg_Sn, arg_R_12}}, // VMOV<c> <Sn>, <Rt> cond:4|1|1|1|0|0|0|0|0|Vn:4|Rt:4|1|0|1|0|N|0|0|1|0|0|0|0
+ {0x0ff00f7f, 0x0e100a10, 4, VMOV_EQ, 0x1c04, instArgs{arg_R_12, arg_Sn}}, // VMOV<c> <Rt>, <Sn> cond:4|1|1|1|0|0|0|0|1|Vn:4|Rt:4|1|0|1|0|N|0|0|1|0|0|0|0
+ {0x0fd00f7f, 0x0e100b10, 4, VMOV_EQ_32, 0x1c04, instArgs{arg_R_12, arg_Dn_half}}, // VMOV<c>.32 <Rt>, <Dn[x]> cond:4|1|1|1|0|0|0|opc1|1|Vn:4|Rt:4|1|0|1|1|N|0|0|1|0|0|0|0
+ {0x0fd00f7f, 0x0e000b10, 4, VMOV_EQ_32, 0x1c04, instArgs{arg_Dn_half, arg_R_12}}, // VMOV<c>.32 <Dd[x]>, <Rt> cond:4|1|1|1|0|0|0|opc1|0|Vd:4|Rt:4|1|0|1|1|D|0|0|1|0|0|0|0
+ {0x0fb00ef0, 0x0eb00a00, 4, VMOV_EQ_F32, 0x8011c04, instArgs{arg_Sd_Dd, arg_imm_vfp}}, // VMOV<c>.F<32,64> <Sd,Dd>, #<imm_vfp> cond:4|1|1|1|0|1|D|1|1|imm4H:4|Vd:4|1|0|1|sz|0|0|0|0|imm4L:4
+ {0x0fbf0ed0, 0x0eb00a40, 4, VMOV_EQ_F32, 0x8011c04, instArgs{arg_Sd_Dd, arg_Sm_Dm}}, // VMOV<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|0|Vd:4|1|0|1|sz|0|1|M|0|Vm:4
+ {0x0fff0fff, 0x0ef10a10, 4, VMRS_EQ, 0x1c04, instArgs{arg_R_12_nzcv, arg_FPSCR}}, // VMRS<c> <Rt_nzcv>, FPSCR cond:4|1|1|1|0|1|1|1|1|0|0|0|1|Rt:4|1|0|1|0|0|0|0|1|0|0|0|0
+ {0x0fff0fff, 0x0ee10a10, 4, VMSR_EQ, 0x1c04, instArgs{arg_FPSCR, arg_R_12}}, // VMSR<c> FPSCR, <Rt> cond:4|1|1|1|0|1|1|1|0|0|0|0|1|Rt:4|1|0|1|0|0|0|0|1|0|0|0|0
+ {0x0fb00e50, 0x0e200a00, 4, VMUL_EQ_F32, 0x8011c04, instArgs{arg_Sd_Dd, arg_Sn_Dn, arg_Sm_Dm}}, // VMUL<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|0|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4
+ {0x0fbf0ed0, 0x0eb10a40, 4, VNEG_EQ_F32, 0x8011c04, instArgs{arg_Sd_Dd, arg_Sm_Dm}}, // VNEG<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|1|Vd:4|1|0|1|sz|0|1|M|0|Vm:4
+ {0x0fb00e10, 0x0e100a00, 4, VNMLS_EQ_F32, 0x60108011c04, instArgs{arg_Sd_Dd, arg_Sn_Dn, arg_Sm_Dm}}, // VN<MLS,MLA><c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|0|1|Vn:4|Vd:4|1|0|1|sz|N|op|M|0|Vm:4
+ {0x0fb00e50, 0x0e200a40, 4, VNMUL_EQ_F32, 0x8011c04, instArgs{arg_Sd_Dd, arg_Sn_Dn, arg_Sm_Dm}}, // VNMUL<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|0|Vn:4|Vd:4|1|0|1|sz|N|1|M|0|Vm:4
+ {0x0fbf0ed0, 0x0eb10ac0, 4, VSQRT_EQ_F32, 0x8011c04, instArgs{arg_Sd_Dd, arg_Sm_Dm}}, // VSQRT<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|1|Vd:4|1|0|1|sz|1|1|M|0|Vm:4
+ {0x0f300e00, 0x0d000a00, 4, VSTR_EQ, 0x1c04, instArgs{arg_Sd_Dd, arg_mem_R_pm_imm8at0_offset}}, // VSTR<c> <Sd,Dd>, [<Rn>{,#+/-<imm8>}] cond:4|1|1|0|1|U|D|0|0|Rn:4|Vd:4|1|0|1|sz|imm8:8
+ {0x0fb00e50, 0x0e300a40, 4, VSUB_EQ_F32, 0x8011c04, instArgs{arg_Sd_Dd, arg_Sn_Dn, arg_Sm_Dm}}, // VSUB<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|1|Vn:4|Vd:4|1|0|1|sz|N|1|M|0|Vm:4
+ {0x0fffffff, 0x0320f002, 4, WFE_EQ, 0x1c04, instArgs{}}, // WFE<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|0
+ {0x0fff00ff, 0x0320f002, 3, WFE_EQ, 0x1c04, instArgs{}}, // WFE<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|0
+ {0x0fffffff, 0x0320f003, 4, WFI_EQ, 0x1c04, instArgs{}}, // WFI<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|1
+ {0x0fff00ff, 0x0320f003, 3, WFI_EQ, 0x1c04, instArgs{}}, // WFI<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|1
+ {0x0fffffff, 0x0320f001, 4, YIELD_EQ, 0x1c04, instArgs{}}, // YIELD<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|1
+ {0x0fff00ff, 0x0320f001, 3, YIELD_EQ, 0x1c04, instArgs{}}, // YIELD<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|1
+ {0xffffffff, 0xf7fabcfd, 4, UNDEF, 0x0, instArgs{}}, // UNDEF 1|1|1|1|0|1|1|1|1|1|1|1|1|0|1|0|1|0|1|1|1|1|0|0|1|1|1|1|1|1|0|1
+}
diff --git a/src/cmd/internal/rsc.io/arm/armasm/testdata/Makefile b/src/cmd/internal/rsc.io/arm/armasm/testdata/Makefile
new file mode 100644
index 000000000..1adab6851
--- /dev/null
+++ b/src/cmd/internal/rsc.io/arm/armasm/testdata/Makefile
@@ -0,0 +1,5 @@
+newdecode.txt:
+ cd ..; go test -cover -run 'ObjdumpARMCond' -v -timeout 10h -printtests -long 2>&1 | tee log
+ cd ..; go test -cover -run 'ObjdumpARMUncond' -v -timeout 10h -printtests -long 2>&1 | tee -a log
+ egrep ' (gnu|plan9) ' ../log |sort >newdecode.txt
+
diff --git a/src/cmd/internal/rsc.io/arm/armasm/testdata/decode.txt b/src/cmd/internal/rsc.io/arm/armasm/testdata/decode.txt
new file mode 100644
index 000000000..cc1ea0abe
--- /dev/null
+++ b/src/cmd/internal/rsc.io/arm/armasm/testdata/decode.txt
@@ -0,0 +1,306 @@
+000001f1| 1 gnu setend le
+00100f61| 1 gnu mrsvs r1, apsr
+00f02053| 1 gnu noppl
+00f0d4f4| 1 gnu pli [r4]
+01f020d3| 1 gnu yieldle
+02002d59| 1 gnu stmdbpl sp!, {r1}
+021da9d8| 1 gnu stmle r9!, {r1, r8, sl, fp, ip}
+02c0b071| 1 gnu movsvc ip, r2
+02f02073| 1 gnu wfevc
+03f02013| 1 gnu wfine
+03f05df7| 1 gnu pld [sp, -r3]
+04009d34| 1 gnu popcc {r0}
+043a52b1| 1 gnu cmplt r2, r4, lsl #20
+04402de5| 1 gnu push {r4}
+045b148d| 1 gnu vldrhi d5, [r4, #-16]
+04f02093| 1 gnu sevls
+0793eab0| 1 gnu rsclt r9, sl, r7, lsl #6
+079bfb9e| 1 gnu vmovls.f64 d25, #183
+0a4fc9d3| 1 gnu bicle r4, r9, #10, 30
+0bac7ab6| 1 gnu ldrbtlt sl, [sl], -fp, lsl #24
+0c2aee44| 1 gnu strbtmi r2, [lr], #2572
+0c4bb000| 1 gnu adcseq r4, r0, ip, lsl #22
+0e26d561| 1 gnu bicsvs r2, r5, lr, lsl #12
+0f0fa011| 1 gnu lslne r0, pc, #30
+0fa448e0| 1 gnu sub sl, r8, pc, lsl #8
+101af1de| 1 gnu vmrsle r1, fpscr
+108a0cee| 1 gnu vmov s24, r8
+108a1dae| 1 gnu vmovge r8, s26
+108ae14e| 1 gnu vmsrmi fpscr, r8
+10faf1ae| 1 gnu vmrsge apsr_nzcv, fpscr
+10fb052e| 1 gnu vmovcs.32 d5[0], pc
+11c902b7| 1 gnu smladlt r2, r1, r9, ip
+11ef5b16| 1 gnu uadd16ne lr, fp, r1
+12fa87a7| 1 gnu usad8ge r7, r2, sl
+135f2956| 1 gnu qadd16pl r5, r9, r3
+13de9aa1| 1 gnu orrsge sp, sl, r3, lsl lr
+145c0e40| 1 gnu andmi r5, lr, r4, lsl ip
+150f7fd6| 1 gnu uhadd16le r0, pc, r5
+15b9bf12| 1 gnu adcsne fp, pc, #344064
+16373391| 1 gnu teqls r3, r6, lsl r7
+19ef1966| 1 gnu sadd16vs lr, r9, r9
+1ab0b091| 1 gnu lslsls fp, sl, r0
+1b9f6fe6| 1 gnu uqadd16 r9, pc, fp
+1bb58557| 1 gnu usada8pl r5, fp, r5, fp
+1beff8e0| 1 gnu rscs lr, r8, fp, lsl pc
+1caff0e6| 1 gnu usat sl, #16, ip, lsl #30
+1d0f3d36| 1 gnu shadd16cc r0, sp, sp
+1dca1d52| 1 gnu andspl ip, sp, #118784
+1e4891d0| 1 gnu addsle r4, r1, lr, lsl r8
+1f0889e6| 1 gnu pkhbt r0, r9, pc, lsl #16
+1f1f6fe1| 1 gnu clz r1, pc
+1f26d157| 1 gnu bfcpl r2, #12, #6
+1ff07ff5| 1 gnu clrex
+1fff2fd1| 1 gnu bxle pc
+20f153f6| 1 gnu pli [r3, -r0, lsr #2]
+21047013| 1 gnu cmnne r0, #553648128
+21c2eb8b| 1 gnu blhi .-0x50f778
+21c2ebfb| 1 gnu blx .-0x50f776
+21fa62ee| 1 gnu vmul.f32 s31, s4, s3
+23005720| 1 gnu subscs r0, r7, r3, lsr #32
+236a303e| 1 gnu vaddcc.f32 s12, s0, s7
+23f055f6| 1 gnu pli [r5, -r3, lsr #32]
+2430a031| 1 gnu lsrcc r3, r4, #32
+245d0803| 1 gnu movweq r5, #36132
+251a86be| 1 gnu vdivlt.f32 s2, s12, s11
+25db7b81| 1 gnu cmnhi fp, r5, lsr #22
+26bc3553| 1 gnu teqpl r5, #9728
+277c2d69| 1 gnu pushvs {r0, r1, r2, r5, sl, fp, ip, sp, lr}
+29fc1cf5| 1 gnu pldw [ip, #-3113]
+29ff2fc1| 1 gnu bxjgt r9
+2decd9c0| 1 gnu sbcsgt lr, r9, sp, lsr #24
+30fa5e47| 1 gnu smmulrmi lr, r0, sl
+316f64d6| 1 gnu uqasxle r6, r4, r1
+323f5da6| 1 gnu uasxge r3, sp, r2
+327fe5e6| 1 gnu usat16 r7, #5, r2
+330151e3| 1 gnu cmp r1, #-1073741812
+34af2ae6| 1 gnu qasx sl, sl, r4
+35fd3710| 1 gnu eorsne pc, r7, r5, lsr sp
+36def1c1| 1 gnu mvnsgt sp, r6, lsr lr
+3801b061| 1 gnu lsrsvs r0, r8, r1
+38985477| 1 gnu smmlarvc r4, r8, r8, r9
+3a2fbfa6| 1 gnu revge r2, sl
+3a3f1b06| 1 gnu sasxeq r3, fp, sl
+3a7fa346| 1 gnu ssat16mi r7, #4, sl
+3a943b94| 1 gnu ldrtls r9, [fp], #-1082
+3bf505e7| 1 gnu smuadx r5, fp, r5
+3cef7086| 1 gnu uhasxhi lr, r0, ip
+3e5f3ec6| 1 gnu shasxgt r5, lr, lr
+3f4fff86| 1 gnu rbithi r4, pc
+3faf4717| 1 gnu smlaldxne sl, r7, pc, pc
+3fff2fc1| 1 gnu blxgt pc
+402bbf7e| 1 gnu vcvtvc.u16.f64 d2, d2, #16
+403ab5de| 1 gnu vcmple.f32 s6, #0
+40eb363e| 1 gnu vsubcc.f64 d14, d6, d0
+420f73d1| 1 gnu cmnle r3, r2, asr #30
+424a648e| 1 gnu vnmulhi.f32 s9, s8, s4
+4284d717| 1 gnu ldrbne r8, [r7, r2, asr #8]
+42a599c3| 1 gnu orrsgt sl, r9, #276824064
+42abf0be| 1 gnu vmovlt.f64 d26, d2
+446ea031| 1 gnu asrcc r6, r4, #28
+4a953557| 1 gnu ldrpl r9, [r5, -sl, asr #10]!
+4ab6f712| 1 gnu rscsne fp, r7, #77594624
+4af07ff5| 1 gnu dsb #10
+4df6def4| 1 gnu pli [lr, #1613]
+4efbf52e| 1 gnu vcmpcs.f64 d31, #0
+50aaac79| 1 gnu stmibvc ip!, {r4, r6, r9, fp, sp, pc}
+50caf011| 1 gnu mvnsne ip, r0, asr sl
+50f04961| 1 gnu qdaddvs pc, r0, r9
+51282008| 1 gnu stmdaeq r0!, {r0, r4, r6, fp, sp}
+52bf6576| 1 gnu uqsaxvc fp, r5, r2
+5345c9d0| 1 gnu sbcle r4, r9, r3, asr r5
+538f5e46| 1 gnu usaxmi r8, lr, r3
+54106d31| 1 gnu qdsubcc r1, r4, sp
+56e0e557| 1 gnu ubfxpl lr, r6, #0, #6
+57073d11| 1 gnu teqne sp, r7, asr r7
+58bb0aa9| 1 gnu stmdbge sl, {r3, r4, r6, r8, r9, fp, ip, sp, pc}
+58f007b1| 1 gnu qaddlt pc, r8, r7
+59fd0e77| 1 gnu smusdvc lr, r9, sp
+5ab7f1c5| 1 gnu ldrbgt fp, [r1, #1882]!
+5abf23c6| 1 gnu qsaxgt fp, r3, sl
+5b8f1c96| 1 gnu ssaxls r8, ip, fp
+5b98ab97| 1 gnu sbfxls r9, fp, #16, #12
+5bc9b041| 1 gnu asrsmi ip, fp, r9
+5bf07ff5| 1 gnu dmb #11
+5c102b81| 1 gnu qsubhi r1, ip, fp
+5caa49e1| 1 gnu qdadd sl, ip, r9
+5d3f7226| 1 gnu uhsaxcs r3, r2, sp
+5db55470| 1 gnu subsvc fp, r4, sp, asr r5
+5ef14387| 1 gnu smlsldhi pc, r3, lr, r1
+5f540a11| 1 gnu qaddne r5, pc, sl
+5f9079d1| 1 gnu cmnle r9, pc, asr r0
+5faf3f66| 1 gnu shsaxvs sl, pc, pc
+605071d7| 1 gnu ldrble r5, [r1, -r0, rrx]!
+614adc76| 1 gnu ldrbvc r4, [ip], r1, ror #20
+616b9e42| 1 gnu addsmi r6, lr, #99328
+62c84f15| 1 gnu strbne ip, [pc, #-2146]
+62f051f7| 1 gnu pld [r1, -r2, rrx]
+6346c393| 1 gnu bicls r4, r3, #103809024
+654abbae| 1 gnu vcvtge.f32.u16 s8, s8, #5
+65a5f0e3| 1 gnu mvns sl, #423624704
+65f796f7| 1 gnu pldw [r6, r5, ror #14]
+670bb12e| 1 gnu vnegcs.f64 d0, d23
+67903731| 1 gnu teqcc r7, r7, rrx
+68ddc637| 1 gnu strbcc sp, [r6, r8, ror #26]
+695b3ab6| 1 gnu ldrtlt r5, [sl], -r9, ror #22
+697cfc71| 1 gnu mvnsvc r7, r9, ror #24
+6a0ab3ee| 1 gnu vcvtb.f16.f32 s0, s21
+6ad9ad54| 1 gnu strtpl sp, [sp], #2410
+6af07ff5| 1 gnu isb #10
+6afa6f10| 1 gnu rsbne pc, pc, sl, ror #20
+6d5b19ee| 1 gnu vnmla.f64 d5, d9, d29
+6d60b071| 1 gnu rrxsvc r6, sp
+6df754f7| 1 gnu pld [r4, -sp, ror #14]
+70065821| 1 gnu cmpcs r8, r0, ror r6
+7050ed86| 1 gnu uxtabhi r5, sp, r0
+715f1186| 1 gnu ssub16hi r5, r1, r1
+716c9805| 1 gnu ldreq r6, [r8, #3185]
+718d5ab1| 1 gnu cmplt sl, r1, ror sp
+71c8cfb6| 1 gnu uxtb16lt ip, r1, ror #16
+7294af06| 1 gnu sxtbeq r9, r2, ror #8
+72c0bac6| 1 gnu sxtahgt ip, sl, r2
+730f6716| 1 gnu uqsub16ne r0, r7, r3
+73608f46| 1 gnu sxtb16mi r6, r3
+73687f22| 1 gnu rsbscs r6, pc, #7536640
+74308816| 1 gnu sxtab16ne r3, r8, r4
+757f3456| 1 gnu shsub16pl r7, r4, r5
+77788016| 1 gnu sxtab16ne r7, r0, r7, ror #16
+78061671| 1 gnu tstvc r6, r8, ror r6
+780a2fe1| 1 gnu bkpt 0xf0a8
+7850abd6| 1 gnu sxtable r5, fp, r8
+792cef26| 1 gnu uxtbcs r2, r9, ror #24
+799eb8e0| 1 gnu adcs r9, r8, r9, ror lr
+799f5726| 1 gnu usub16cs r9, r7, r9
+79d0bf16| 1 gnu sxthne sp, r9
+7a037ba1| 1 gnu cmnge fp, sl, ror r3
+7b0f2566| 1 gnu qsub16vs r0, r5, fp
+7b79dd51| 1 gnu bicspl r7, sp, fp, ror r9
+7b9a9f1d| 1 gnu vldrne s18, [pc, #492]
+7c70cea6| 1 gnu uxtab16ge r7, lr, ip
+7d48f966| 1 gnu uxtahvs r4, r9, sp, ror #16
+7d5c13a1| 1 gnu tstge r3, sp, ror ip
+7e0001f1| 1 gnu setend le
+7e1c0ba7| 1 gnu smlsdxge fp, lr, ip, r1
+7e567e40| 1 gnu rsbsmi r5, lr, lr, ror r6
+7e8f73b6| 1 gnu uhsub16lt r8, r3, lr
+7ef0ffd6| 1 gnu uxthle pc, lr
+7faaa011| 1 gnu rorne sl, pc, sl
+81f19af7| 1 gnu pldw [sl, r1, lsl #3]
+82033901| 1 gnu teqeq r9, r2, lsl #7
+82f316f5| 1 gnu pldw [r6, #-898]
+830201f1| 1 gnu setend be
+838a3b91| 1 gnu teqls fp, r3, lsl #21
+8408af2f| 1 gnu svccs 0x00af0884
+884201d1| 1 gnu smlabble r1, r8, r2, r4
+8aa12e31| 1 gnu smlawbcc lr, sl, r1, sl
+8b9b99c0| 1 gnu addsgt r9, r9, fp, lsl #23
+8c005c81| 1 gnu cmphi ip, ip, lsl #1
+8fb429c6| 1 gnu strtgt fp, [r9], -pc, lsl #9
+907b1f9e| 1 gnu vmovls.32 r7, d31[0]
+91975f25| 1 gnu ldrbcs r9, [pc, #-1937]
+91b010e3| 1 gnu tst r0, #145
+927facb1| 1 gnu strexdlt r7, r2, [ip]
+92904c91| 1 gnu swpbls r9, r2, [ip]
+92af1226| 1 gnu sadd8cs sl, r2, r2
+92b28c70| 1 gnu umullvc fp, ip, r2, r2
+945f68a6| 1 gnu uqadd8ge r5, r8, r4
+950b2560| 1 gnu mlavs r5, r5, fp, r0
+969fcf71| 1 gnu strexbvc r9, r6, [pc]
+96cf35e6| 1 gnu shadd8 ip, r5, r6
+98060eb0| 1 gnu mullt lr, r8, r6
+9843fb93| 1 gnu mvnsls r4, #152, 6
+9a3fe2b0| 1 gnu smlallt r3, r2, sl, pc
+9aef58b6| 1 gnu uadd8lt lr, r8, sl
+9afcdff5| 1 gnu pld [pc, #3226]
+9c221810| 1 gnu mulsne r8, ip, r2
+9c3bc9dd| 1 gnu vstrle d19, [r9, #624]
+9c5f2606| 1 gnu qadd8eq r5, r6, ip
+9d87dac0| 1 gnu smullsgt r8, sl, sp, r7
+9e0f7c86| 1 gnu uhadd8hi r0, ip, lr
+9e814560| 1 gnu umaalvs r8, r5, lr, r1
+9e9f8dc1| 1 gnu strexgt r9, lr, [sp]
+9ec3c9d7| 1 gnu bfile ip, lr, #7, #3
+9ed26d90| 1 gnu mlsls sp, lr, r2, sp
+9f7fd9c1| 1 gnu ldrexbgt r7, [r9]
+9f7fea91| 1 gnu strexhls r7, pc, [sl]
+9f9f9921| 1 gnu ldrexcs r9, [r9]
+9faffd21| 1 gnu ldrexhcs sl, [sp]
+9fcfbd61| 1 gnu ldrexdvs ip, [sp]
+9ff7a710| 1 gnu umlalne pc, r7, pc, r7
+a05459d3| 1 gnu cmple r9, #160, 8
+a3062be1| 1 gnu smulwb fp, r3, r6
+a68a92b1| 1 gnu orrslt r8, r2, r6, lsr #21
+abff55f6| 1 gnu pli [r5, -fp, lsr #31]
+addbf8ea| 1 gnu b .-0x1c9148
+ae79b021| 1 gnu lsrscs r7, lr, #19
+b590a3b1| 1 gnu strhlt r9, [r3, r5]!
+b5b2e390| 1 gnu strhtls fp, [r3], #37
+b6ac4e30| 1 gnu strhcc sl, [lr], #-198
+b73fff86| 1 gnu revshhi r3, r7
+b75fbfc6| 1 gnu rev16gt r5, r7
+b80b7c80| 1 gnu ldrhthi r0, [ip], #-184
+b82035e0| 1 gnu ldrht r2, [r5], -r8
+b8877391| 1 gnu ldrhls r8, [r3, #-120]!
+b9703e41| 1 gnu ldrhmi r7, [lr, -r9]!
+b9cf8c16| 1 gnu selne ip, ip, r9
+bd81bd58| 1 gnu poppl {r0, r2, r3, r4, r5, r7, r8, pc}
+bdfdb469| 1 gnu ldmibvs r4!, {r0, r2, r3, r4, r5, r7, r8, sl, fp, ip, sp, lr, pc}
+beb02500| 1 gnu strhteq fp, [r5], -lr
+bf1a5e42| 1 gnu subsmi r1, lr, #782336
+c19a4d5e| 1 gnu vmlspl.f32 s19, s27, s2
+c1aab15e| 1 gnu vsqrtpl.f32 s20, s2
+c354b003| 1 gnu movseq r5, #-1023410176
+c4091dc1| 1 gnu tstgt sp, r4, asr #19
+c50e13a9| 1 gnu ldmdbge r3, {r0, r2, r6, r7, r9, sl, fp}
+c68c8637| 1 gnu strcc r8, [r6, r6, asr #25]
+c6ad48e3| 1 gnu movt sl, #36294
+c6f65ff5| 1 gnu pld [pc, #-1734]
+c8a92f10| 1 gnu eorne sl, pc, r8, asr #19
+c9016b61| 1 gnu smulbtvs fp, r9, r1
+cadbf49e| 1 gnu vcmpels.f64 d29, d10
+ce9de476| 1 gnu strbtvc r9, [r4], lr, asr #27
+cf3c1ab1| 1 gnu tstlt sl, pc, asr #25
+d355aab6| 1 gnu ssatlt r5, #11, r3, asr #11
+d4f4df10| 1 gnu ldrsbne pc, [pc], #68
+d6530d61| 1 gnu ldrdvs r5, [sp, -r6]
+d74d7800| 1 gnu ldrsbteq r4, [r8], #-215
+d9703680| 1 gnu ldrsbthi r7, [r6], -r9
+dbe003c0| 1 gnu ldrdgt lr, [r3], -fp
+dc709561| 1 gnu ldrsbvs r7, [r5, ip]
+dcc3b9c8| 1 gnu ldmgt r9!, {r2, r3, r4, r6, r7, r8, r9, lr, pc}
+debfa0e5| 1 gnu str fp, [r0, #4062]!
+dee062a1| 1 gnu ldrdge lr, [r2, #-14]!
+dfa05ab7| 1 gnu smmlslt sl, pc, r0, sl
+e02ef011| 1 gnu mvnsne r2, r0, ror #29
+e4d41718| 1 gnu ldmdane r7, {r2, r5, r6, r7, sl, ip, lr, pc}
+e6d0fe34| 1 gnu ldrbtcc sp, [lr], #230
+e73bf7be| 1 gnu vcvtlt.f32.f64 s7, d23
+e74e72b3| 1 gnu cmnlt r2, #3696
+e80bf07e| 1 gnu vabsvc.f64 d16, d24
+e9b5b001| 1 gnu rorseq fp, r9, #11
+ea7bbdbe| 1 gnu vcvtlt.s32.f64 s14, d26
+ec063813| 1 gnu teqne r8, #236, 12
+ec0e49e1| 1 gnu smlaltt r0, r9, ip, lr
+ee4ab85e| 1 gnu vcvtpl.f32.s32 s8, s29
+ef461f25| 1 gnu ldrcs r4, [pc, #-1775]
+ef5fd002| 1 gnu sbcseq r5, r0, #956
+f4cf1d36| 1 gnu ssub8cc ip, sp, r4
+f67f73b6| 1 gnu uhsub8lt r7, r3, r6
+f6e09ca0| 1 gnu ldrshge lr, [ip], r6
+f7702e32| 1 gnu eorcc r7, lr, #247
+fa4dcf20| 1 gnu strdcs r4, [pc], #218
+fac03720| 1 gnu ldrshtcs ip, [r7], -sl
+fc0f64c6| 1 gnu uqsub8gt r0, r4, ip
+fc28f481| 1 gnu ldrshhi r2, [r4, #140]!
+fc300560| 1 gnu strdvs r3, [r5], -ip
+fcacfc70| 1 gnu ldrshtvc sl, [ip], #204
+fdbcfaf7| 1 gnu undef
+fddf5c86| 1 gnu usub8hi sp, ip, sp
+fdf02013| 1 gnu dbgne #13
+fe0319e3| 1 gnu tst r9, #-134217725
+fe7f3116| 1 gnu shsub8ne r7, r1, lr
+ff4f2ac6| 1 gnu qsub8gt r4, sl, pc
+ff818c71| 1 gnu strdvc r8, [ip, pc]
+|6b5721d3 1 gnu error: unknown instruction
+|76452001 1 gnu error: unknown instruction
+|97acd647 1 gnu error: unknown instruction
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/Makefile b/src/cmd/internal/rsc.io/x86/x86asm/Makefile
new file mode 100644
index 000000000..9eb4557c1
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/Makefile
@@ -0,0 +1,3 @@
+tables.go: ../x86map/map.go ../x86.csv
+ go run ../x86map/map.go -fmt=decoder ../x86.csv >_tables.go && gofmt _tables.go >tables.go && rm _tables.go
+
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/decode.go b/src/cmd/internal/rsc.io/x86/x86asm/decode.go
new file mode 100644
index 000000000..91e8876c8
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/decode.go
@@ -0,0 +1,1616 @@
+// 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
new file mode 100644
index 000000000..fb284583a
--- /dev/null
+++ b/src/cmd/internal/rsc.io/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":
+ 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
new file mode 100644
index 000000000..f65d6b2d5
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/ext_test.go
@@ -0,0 +1,811 @@
+// 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 sequenc 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/gnu.go b/src/cmd/internal/rsc.io/x86/x86asm/gnu.go
new file mode 100644
index 000000000..e2ff80118
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/gnu.go
@@ -0,0 +1,926 @@
+// 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"
+)
+
+// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
+// This general form is often called ``AT&T syntax'' as a reference to AT&T System V Unix.
+func GNUSyntax(inst Inst) string {
+ // Rewrite instruction to mimic GNU peculiarities.
+ // Note that inst has been passed by value and contains
+ // no pointers, so any changes we make here are local
+ // and will not propagate back out to the caller.
+
+ // Adjust opcode [sic].
+ switch inst.Op {
+ case FDIV, FDIVR, FSUB, FSUBR, FDIVP, FDIVRP, FSUBP, FSUBRP:
+ // DC E0, DC F0: libopcodes swaps FSUBR/FSUB and FDIVR/FDIV, at least
+ // if you believe the Intel manual is correct (the encoding is irregular as given;
+ // libopcodes uses the more regular expected encoding).
+ // TODO(rsc): Test to ensure Intel manuals are correct and report to libopcodes maintainers?
+ // NOTE: iant thinks this is deliberate, but we can't find the history.
+ _, reg1 := inst.Args[0].(Reg)
+ _, reg2 := inst.Args[1].(Reg)
+ if reg1 && reg2 && (inst.Opcode>>24 == 0xDC || inst.Opcode>>24 == 0xDE) {
+ switch inst.Op {
+ case FDIV:
+ inst.Op = FDIVR
+ case FDIVR:
+ inst.Op = FDIV
+ case FSUB:
+ inst.Op = FSUBR
+ case FSUBR:
+ inst.Op = FSUB
+ case FDIVP:
+ inst.Op = FDIVRP
+ case FDIVRP:
+ inst.Op = FDIVP
+ case FSUBP:
+ inst.Op = FSUBRP
+ case FSUBRP:
+ inst.Op = FSUBP
+ }
+ }
+
+ case MOVNTSD:
+ // MOVNTSD is F2 0F 2B /r.
+ // MOVNTSS is F3 0F 2B /r (supposedly; not in manuals).
+ // Usually inner prefixes win for display,
+ // so that F3 F2 0F 2B 11 is REP MOVNTSD
+ // and F2 F3 0F 2B 11 is REPN MOVNTSS.
+ // Libopcodes always prefers MOVNTSS regardless of prefix order.
+ if countPrefix(&inst, 0xF3) > 0 {
+ found := false
+ for i := len(inst.Prefix) - 1; i >= 0; i-- {
+ switch inst.Prefix[i] & 0xFF {
+ case 0xF3:
+ if !found {
+ found = true
+ inst.Prefix[i] |= PrefixImplicit
+ }
+ case 0xF2:
+ inst.Prefix[i] &^= PrefixImplicit
+ }
+ }
+ inst.Op = MOVNTSS
+ }
+ }
+
+ // Add implicit arguments.
+ switch inst.Op {
+ case MONITOR:
+ inst.Args[0] = EDX
+ inst.Args[1] = ECX
+ inst.Args[2] = EAX
+ if inst.AddrSize == 16 {
+ inst.Args[2] = AX
+ }
+
+ case MWAIT:
+ if inst.Mode == 64 {
+ inst.Args[0] = RCX
+ inst.Args[1] = RAX
+ } else {
+ inst.Args[0] = ECX
+ inst.Args[1] = EAX
+ }
+ }
+
+ // Adjust which prefixes will be displayed.
+ // The rule is to display all the prefixes not implied by
+ // the usual instruction display, that is, all the prefixes
+ // except the ones with PrefixImplicit set.
+ // However, of course, there are exceptions to the rule.
+ switch inst.Op {
+ case CRC32:
+ // CRC32 has a mandatory F2 prefix.
+ // If there are multiple F2s and no F3s, the extra F2s do not print.
+ // (And Decode has already marked them implicit.)
+ // However, if there is an F3 anywhere, then the extra F2s do print.
+ // If there are multiple F2 prefixes *and* an (ignored) F3,
+ // then libopcodes prints the extra F2s as REPNs.
+ if countPrefix(&inst, 0xF2) > 1 {
+ unmarkImplicit(&inst, 0xF2)
+ markLastImplicit(&inst, 0xF2)
+ }
+
+ // An unused data size override should probably be shown,
+ // to distinguish DATA16 CRC32B from plain CRC32B,
+ // but libopcodes always treats the final override as implicit
+ // and the others as explicit.
+ unmarkImplicit(&inst, PrefixDataSize)
+ markLastImplicit(&inst, PrefixDataSize)
+
+ case CVTSI2SD, CVTSI2SS:
+ if !isMem(inst.Args[1]) {
+ markLastImplicit(&inst, PrefixDataSize)
+ }
+
+ case CVTSD2SI, CVTSS2SI, CVTTSD2SI, CVTTSS2SI,
+ ENTER, FLDENV, FNSAVE, FNSTENV, FRSTOR, LGDT, LIDT, LRET,
+ POP, PUSH, RET, SGDT, SIDT, SYSRET, XBEGIN:
+ markLastImplicit(&inst, PrefixDataSize)
+
+ case LOOP, LOOPE, LOOPNE, MONITOR:
+ markLastImplicit(&inst, PrefixAddrSize)
+
+ case MOV:
+ // The 16-bit and 32-bit forms of MOV Sreg, dst and MOV src, Sreg
+ // cannot be distinguished when src or dst refers to memory, because
+ // Sreg is always a 16-bit value, even when we're doing a 32-bit
+ // instruction. Because the instruction tables distinguished these two,
+ // any operand size prefix has been marked as used (to decide which
+ // branch to take). Unmark it, so that it will show up in disassembly,
+ // so that the reader can tell the size of memory operand.
+ // up with the same arguments
+ dst, _ := inst.Args[0].(Reg)
+ src, _ := inst.Args[1].(Reg)
+ if ES <= src && src <= GS && isMem(inst.Args[0]) || ES <= dst && dst <= GS && isMem(inst.Args[1]) {
+ unmarkImplicit(&inst, PrefixDataSize)
+ }
+
+ case MOVDQU:
+ if countPrefix(&inst, 0xF3) > 1 {
+ unmarkImplicit(&inst, 0xF3)
+ markLastImplicit(&inst, 0xF3)
+ }
+
+ case MOVQ2DQ:
+ markLastImplicit(&inst, PrefixDataSize)
+
+ case SLDT, SMSW, STR, FXRSTOR, XRSTOR, XSAVE, XSAVEOPT, CMPXCHG8B:
+ if isMem(inst.Args[0]) {
+ unmarkImplicit(&inst, PrefixDataSize)
+ }
+
+ case SYSEXIT:
+ unmarkImplicit(&inst, PrefixDataSize)
+ }
+
+ if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
+ if countPrefix(&inst, PrefixCS) > 0 && countPrefix(&inst, PrefixDS) > 0 {
+ for i, p := range inst.Prefix {
+ switch p & 0xFFF {
+ case PrefixPN, PrefixPT:
+ inst.Prefix[i] &= 0xF0FF // cut interpretation bits, producing original segment prefix
+ }
+ }
+ }
+ }
+
+ // XACQUIRE/XRELEASE adjustment.
+ if inst.Op == MOV {
+ // MOV into memory is a candidate for turning REP into XRELEASE.
+ // However, if the REP is followed by a REPN, that REPN blocks the
+ // conversion.
+ haveREPN := false
+ for i := len(inst.Prefix) - 1; i >= 0; i-- {
+ switch inst.Prefix[i] &^ PrefixIgnored {
+ case PrefixREPN:
+ haveREPN = true
+ case PrefixXRELEASE:
+ if haveREPN {
+ inst.Prefix[i] = PrefixREP
+ }
+ }
+ }
+ }
+
+ // We only format the final F2/F3 as XRELEASE/XACQUIRE.
+ haveXA := false
+ haveXR := false
+ for i := len(inst.Prefix) - 1; i >= 0; i-- {
+ switch inst.Prefix[i] &^ PrefixIgnored {
+ case PrefixXRELEASE:
+ if !haveXR {
+ haveXR = true
+ } else {
+ inst.Prefix[i] = PrefixREP
+ }
+
+ case PrefixXACQUIRE:
+ if !haveXA {
+ haveXA = true
+ } else {
+ inst.Prefix[i] = PrefixREPN
+ }
+ }
+ }
+
+ // Determine opcode.
+ op := strings.ToLower(inst.Op.String())
+ if alt := gnuOp[inst.Op]; alt != "" {
+ op = alt
+ }
+
+ // Determine opcode suffix.
+ // Libopcodes omits the suffix if the width of the operation
+ // can be inferred from a register arguments. For example,
+ // add $1, %ebx has no suffix because you can tell from the
+ // 32-bit register destination that it is a 32-bit add,
+ // but in addl $1, (%ebx), the destination is memory, so the
+ // size is not evident without the l suffix.
+ needSuffix := true
+SuffixLoop:
+ for i, a := range inst.Args {
+ if a == nil {
+ break
+ }
+ switch a := a.(type) {
+ case Reg:
+ switch inst.Op {
+ case MOVSX, MOVZX:
+ continue
+
+ case SHL, SHR, RCL, RCR, ROL, ROR, SAR:
+ if i == 1 {
+ // shift count does not tell us operand size
+ continue
+ }
+
+ case CRC32:
+ // The source argument does tell us operand size,
+ // but libopcodes still always puts a suffix on crc32.
+ continue
+
+ case PUSH, POP:
+ // Even though segment registers are 16-bit, push and pop
+ // can save/restore them from 32-bit slots, so they
+ // do not imply operand size.
+ if ES <= a && a <= GS {
+ continue
+ }
+
+ case CVTSI2SD, CVTSI2SS:
+ // The integer register argument takes priority.
+ if X0 <= a && a <= X15 {
+ continue
+ }
+ }
+
+ if AL <= a && a <= R15 || ES <= a && a <= GS || X0 <= a && a <= X15 || M0 <= a && a <= M7 {
+ needSuffix = false
+ break SuffixLoop
+ }
+ }
+ }
+
+ if needSuffix {
+ switch inst.Op {
+ case CMPXCHG8B, FLDCW, FNSTCW, FNSTSW, LDMXCSR, LLDT, LMSW, LTR, PCLMULQDQ,
+ SETA, SETAE, SETB, SETBE, SETE, SETG, SETGE, SETL, SETLE, SETNE, SETNO, SETNP, SETNS, SETO, SETP, SETS,
+ SLDT, SMSW, STMXCSR, STR, VERR, VERW:
+ // For various reasons, libopcodes emits no suffix for these instructions.
+
+ case CRC32:
+ op += byteSizeSuffix(argBytes(&inst, inst.Args[1]))
+
+ case LGDT, LIDT, SGDT, SIDT:
+ op += byteSizeSuffix(inst.DataSize / 8)
+
+ case MOVZX, MOVSX:
+ // Integer size conversions get two suffixes.
+ op = op[:4] + byteSizeSuffix(argBytes(&inst, inst.Args[1])) + byteSizeSuffix(argBytes(&inst, inst.Args[0]))
+
+ case LOOP, LOOPE, LOOPNE:
+ // Add w suffix to indicate use of CX register instead of ECX.
+ if inst.AddrSize == 16 {
+ op += "w"
+ }
+
+ case CALL, ENTER, JMP, LCALL, LEAVE, LJMP, LRET, RET, SYSRET, XBEGIN:
+ // Add w suffix to indicate use of 16-bit target.
+ // Exclude JMP rel8.
+ if inst.Opcode>>24 == 0xEB {
+ break
+ }
+ if inst.DataSize == 16 && inst.Mode != 16 {
+ markLastImplicit(&inst, PrefixDataSize)
+ op += "w"
+ } else if inst.Mode == 64 {
+ op += "q"
+ }
+
+ case FRSTOR, FNSAVE, FNSTENV, FLDENV:
+ // Add s suffix to indicate shortened FPU state (I guess).
+ if inst.DataSize == 16 {
+ op += "s"
+ }
+
+ case PUSH, POP:
+ if markLastImplicit(&inst, PrefixDataSize) {
+ op += byteSizeSuffix(inst.DataSize / 8)
+ } else if inst.Mode == 64 {
+ op += "q"
+ } else {
+ op += byteSizeSuffix(inst.MemBytes)
+ }
+
+ default:
+ if isFloat(inst.Op) {
+ // I can't explain any of this, but it's what libopcodes does.
+ switch inst.MemBytes {
+ default:
+ if (inst.Op == FLD || inst.Op == FSTP) && isMem(inst.Args[0]) {
+ op += "t"
+ }
+ case 4:
+ if isFloatInt(inst.Op) {
+ op += "l"
+ } else {
+ op += "s"
+ }
+ case 8:
+ if isFloatInt(inst.Op) {
+ op += "ll"
+ } else {
+ op += "l"
+ }
+ }
+ break
+ }
+
+ op += byteSizeSuffix(inst.MemBytes)
+ }
+ }
+
+ // Adjust special case opcodes.
+ switch inst.Op {
+ case 0:
+ if inst.Prefix[0] != 0 {
+ return strings.ToLower(inst.Prefix[0].String())
+ }
+
+ case INT:
+ if inst.Opcode>>24 == 0xCC {
+ inst.Args[0] = nil
+ op = "int3"
+ }
+
+ case CMPPS, CMPPD, CMPSD_XMM, CMPSS:
+ imm, ok := inst.Args[2].(Imm)
+ if ok && 0 <= imm && imm < 8 {
+ inst.Args[2] = nil
+ op = cmppsOps[imm] + op[3:]
+ }
+
+ case PCLMULQDQ:
+ imm, ok := inst.Args[2].(Imm)
+ if ok && imm&^0x11 == 0 {
+ inst.Args[2] = nil
+ op = pclmulqOps[(imm&0x10)>>3|(imm&1)]
+ }
+
+ case XLATB:
+ if markLastImplicit(&inst, PrefixAddrSize) {
+ op = "xlat" // not xlatb
+ }
+ }
+
+ // Build list of argument strings.
+ var (
+ usedPrefixes bool // segment prefixes consumed by Mem formatting
+ args []string // formatted arguments
+ )
+ for i, a := range inst.Args {
+ if a == nil {
+ break
+ }
+ switch inst.Op {
+ case MOVSB, MOVSW, MOVSD, MOVSQ, OUTSB, OUTSW, OUTSD:
+ if i == 0 {
+ usedPrefixes = true // disable use of prefixes for first argument
+ } else {
+ usedPrefixes = false
+ }
+ }
+ if a == Imm(1) && (inst.Opcode>>24)&^1 == 0xD0 {
+ continue
+ }
+ args = append(args, gnuArg(&inst, a, &usedPrefixes))
+ }
+
+ // The default is to print the arguments in reverse Intel order.
+ // A few instructions inhibit this behavior.
+ switch inst.Op {
+ case BOUND, LCALL, ENTER, LJMP:
+ // no reverse
+ default:
+ // reverse args
+ for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
+ args[i], args[j] = args[j], args[i]
+ }
+ }
+
+ // Build prefix string.
+ // Must be after argument formatting, which can turn off segment prefixes.
+ var (
+ prefix = "" // output string
+ numAddr = 0
+ numData = 0
+ implicitData = false
+ )
+ for _, p := range inst.Prefix {
+ if p&0xFF == PrefixDataSize && p&PrefixImplicit != 0 {
+ implicitData = true
+ }
+ }
+ for _, p := range inst.Prefix {
+ if p == 0 {
+ break
+ }
+ if p&PrefixImplicit != 0 {
+ continue
+ }
+ switch p &^ (PrefixIgnored | PrefixInvalid) {
+ default:
+ if p.IsREX() {
+ if p&0xFF == PrefixREX {
+ prefix += "rex "
+ } else {
+ prefix += "rex." + p.String()[4:] + " "
+ }
+ break
+ }
+ prefix += strings.ToLower(p.String()) + " "
+
+ case PrefixPN:
+ op += ",pn"
+ continue
+
+ case PrefixPT:
+ op += ",pt"
+ continue
+
+ case PrefixAddrSize, PrefixAddr16, PrefixAddr32:
+ // For unknown reasons, if the addr16 prefix is repeated,
+ // libopcodes displays all but the last as addr32, even though
+ // the addressing form used in a memory reference is clearly
+ // still 16-bit.
+ n := 32
+ if inst.Mode == 32 {
+ n = 16
+ }
+ numAddr++
+ if countPrefix(&inst, PrefixAddrSize) > numAddr {
+ n = inst.Mode
+ }
+ prefix += fmt.Sprintf("addr%d ", n)
+ continue
+
+ case PrefixData16, PrefixData32:
+ if implicitData && countPrefix(&inst, PrefixDataSize) > 1 {
+ // Similar to the addr32 logic above, but it only kicks in
+ // when something used the data size prefix (one is implicit).
+ n := 16
+ if inst.Mode == 16 {
+ n = 32
+ }
+ numData++
+ if countPrefix(&inst, PrefixDataSize) > numData {
+ if inst.Mode == 16 {
+ n = 16
+ } else {
+ n = 32
+ }
+ }
+ prefix += fmt.Sprintf("data%d ", n)
+ continue
+ }
+ prefix += strings.ToLower(p.String()) + " "
+ }
+ }
+
+ // Finally! Put it all together.
+ text := prefix + op
+ if args != nil {
+ text += " "
+ // Indirect call/jmp gets a star to distinguish from direct jump address.
+ if (inst.Op == CALL || inst.Op == JMP || inst.Op == LJMP || inst.Op == LCALL) && (isMem(inst.Args[0]) || isReg(inst.Args[0])) {
+ text += "*"
+ }
+ text += strings.Join(args, ",")
+ }
+ return text
+}
+
+// gnuArg returns the GNU syntax for the argument x from the instruction inst.
+// If *usedPrefixes is false and x is a Mem, then the formatting
+// includes any segment prefixes and sets *usedPrefixes to true.
+func gnuArg(inst *Inst, x Arg, usedPrefixes *bool) string {
+ if x == nil {
+ return "<nil>"
+ }
+ switch x := x.(type) {
+ case Reg:
+ switch inst.Op {
+ case CVTSI2SS, CVTSI2SD, CVTSS2SI, CVTSD2SI, CVTTSD2SI, CVTTSS2SI:
+ if inst.DataSize == 16 && EAX <= x && x <= R15L {
+ x -= EAX - AX
+ }
+
+ case IN, INSB, INSW, INSD, OUT, OUTSB, OUTSW, OUTSD:
+ // DX is the port, but libopcodes prints it as if it were a memory reference.
+ if x == DX {
+ return "(%dx)"
+ }
+ }
+ return gccRegName[x]
+ case Mem:
+ seg := ""
+ var haveCS, haveDS, haveES, haveFS, haveGS, haveSS bool
+ switch x.Segment {
+ case CS:
+ haveCS = true
+ case DS:
+ haveDS = true
+ case ES:
+ haveES = true
+ case FS:
+ haveFS = true
+ case GS:
+ haveGS = true
+ case SS:
+ haveSS = true
+ }
+ switch inst.Op {
+ case INSB, INSW, INSD, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ:
+ // These do not accept segment prefixes, at least in the GNU rendering.
+ default:
+ if *usedPrefixes {
+ break
+ }
+ for i := len(inst.Prefix) - 1; i >= 0; i-- {
+ p := inst.Prefix[i] &^ PrefixIgnored
+ if p == 0 {
+ continue
+ }
+ switch p {
+ case PrefixCS:
+ if !haveCS {
+ haveCS = true
+ inst.Prefix[i] |= PrefixImplicit
+ }
+ case PrefixDS:
+ if !haveDS {
+ haveDS = true
+ inst.Prefix[i] |= PrefixImplicit
+ }
+ case PrefixES:
+ if !haveES {
+ haveES = true
+ inst.Prefix[i] |= PrefixImplicit
+ }
+ case PrefixFS:
+ if !haveFS {
+ haveFS = true
+ inst.Prefix[i] |= PrefixImplicit
+ }
+ case PrefixGS:
+ if !haveGS {
+ haveGS = true
+ inst.Prefix[i] |= PrefixImplicit
+ }
+ case PrefixSS:
+ if !haveSS {
+ haveSS = true
+ inst.Prefix[i] |= PrefixImplicit
+ }
+ }
+ }
+ *usedPrefixes = true
+ }
+ if haveCS {
+ seg += "%cs:"
+ }
+ if haveDS {
+ seg += "%ds:"
+ }
+ if haveSS {
+ seg += "%ss:"
+ }
+ if haveES {
+ seg += "%es:"
+ }
+ if haveFS {
+ seg += "%fs:"
+ }
+ if haveGS {
+ seg += "%gs:"
+ }
+ disp := ""
+ if x.Disp != 0 {
+ disp = fmt.Sprintf("%#x", x.Disp)
+ }
+ if x.Scale == 0 || x.Index == 0 && x.Scale == 1 && (x.Base == ESP || x.Base == RSP || x.Base == 0 && inst.Mode == 64) {
+ if x.Base == 0 {
+ return seg + disp
+ }
+ return fmt.Sprintf("%s%s(%s)", seg, disp, gccRegName[x.Base])
+ }
+ base := gccRegName[x.Base]
+ if x.Base == 0 {
+ base = ""
+ }
+ index := gccRegName[x.Index]
+ if x.Index == 0 {
+ if inst.AddrSize == 64 {
+ index = "%riz"
+ } else {
+ index = "%eiz"
+ }
+ }
+ if AX <= x.Base && x.Base <= DI {
+ // 16-bit addressing - no scale
+ return fmt.Sprintf("%s%s(%s,%s)", seg, disp, base, index)
+ }
+ return fmt.Sprintf("%s%s(%s,%s,%d)", seg, disp, base, index, x.Scale)
+ case Rel:
+ return fmt.Sprintf(".%+#x", int32(x))
+ case Imm:
+ if inst.Mode == 32 {
+ return fmt.Sprintf("$%#x", uint32(x))
+ }
+ return fmt.Sprintf("$%#x", int64(x))
+ }
+ return x.String()
+}
+
+var gccRegName = [...]string{
+ 0: "REG0",
+ AL: "%al",
+ CL: "%cl",
+ BL: "%bl",
+ DL: "%dl",
+ AH: "%ah",
+ CH: "%ch",
+ BH: "%bh",
+ DH: "%dh",
+ SPB: "%spl",
+ BPB: "%bpl",
+ SIB: "%sil",
+ DIB: "%dil",
+ 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: "%r8d",
+ R9L: "%r9d",
+ R10L: "%r10d",
+ R11L: "%r11d",
+ R12L: "%r12d",
+ R13L: "%r13d",
+ R14L: "%r14d",
+ R15L: "%r15d",
+ 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: "%st",
+ F1: "%st(1)",
+ F2: "%st(2)",
+ F3: "%st(3)",
+ F4: "%st(4)",
+ F5: "%st(5)",
+ F6: "%st(6)",
+ F7: "%st(7)",
+ M0: "%mm0",
+ M1: "%mm1",
+ M2: "%mm2",
+ M3: "%mm3",
+ M4: "%mm4",
+ M5: "%mm5",
+ M6: "%mm6",
+ M7: "%mm7",
+ X0: "%xmm0",
+ X1: "%xmm1",
+ X2: "%xmm2",
+ X3: "%xmm3",
+ X4: "%xmm4",
+ X5: "%xmm5",
+ X6: "%xmm6",
+ X7: "%xmm7",
+ X8: "%xmm8",
+ X9: "%xmm9",
+ X10: "%xmm10",
+ X11: "%xmm11",
+ X12: "%xmm12",
+ X13: "%xmm13",
+ X14: "%xmm14",
+ X15: "%xmm15",
+ 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: "%db0",
+ DR1: "%db1",
+ DR2: "%db2",
+ DR3: "%db3",
+ DR4: "%db4",
+ DR5: "%db5",
+ DR6: "%db6",
+ DR7: "%db7",
+ TR0: "%tr0",
+ TR1: "%tr1",
+ TR2: "%tr2",
+ TR3: "%tr3",
+ TR4: "%tr4",
+ TR5: "%tr5",
+ TR6: "%tr6",
+ TR7: "%tr7",
+}
+
+var gnuOp = map[Op]string{
+ CBW: "cbtw",
+ CDQ: "cltd",
+ CMPSD: "cmpsl",
+ CMPSD_XMM: "cmpsd",
+ CWD: "cwtd",
+ CWDE: "cwtl",
+ CQO: "cqto",
+ INSD: "insl",
+ IRET: "iretw",
+ IRETD: "iret",
+ IRETQ: "iretq",
+ LODSB: "lods",
+ LODSD: "lods",
+ LODSQ: "lods",
+ LODSW: "lods",
+ MOVSD: "movsl",
+ MOVSD_XMM: "movsd",
+ OUTSD: "outsl",
+ POPA: "popaw",
+ POPAD: "popa",
+ POPF: "popfw",
+ POPFD: "popf",
+ PUSHA: "pushaw",
+ PUSHAD: "pusha",
+ PUSHF: "pushfw",
+ PUSHFD: "pushf",
+ SCASB: "scas",
+ SCASD: "scas",
+ SCASQ: "scas",
+ SCASW: "scas",
+ STOSB: "stos",
+ STOSD: "stos",
+ STOSQ: "stos",
+ STOSW: "stos",
+ XLATB: "xlat",
+}
+
+var cmppsOps = []string{
+ "cmpeq",
+ "cmplt",
+ "cmple",
+ "cmpunord",
+ "cmpneq",
+ "cmpnlt",
+ "cmpnle",
+ "cmpord",
+}
+
+var pclmulqOps = []string{
+ "pclmullqlqdq",
+ "pclmulhqlqdq",
+ "pclmullqhqdq",
+ "pclmulhqhqdq",
+}
+
+func countPrefix(inst *Inst, target Prefix) int {
+ n := 0
+ for _, p := range inst.Prefix {
+ if p&0xFF == target&0xFF {
+ n++
+ }
+ }
+ return n
+}
+
+func markLastImplicit(inst *Inst, prefix Prefix) bool {
+ for i := len(inst.Prefix) - 1; i >= 0; i-- {
+ p := inst.Prefix[i]
+ if p&0xFF == prefix {
+ inst.Prefix[i] |= PrefixImplicit
+ return true
+ }
+ }
+ return false
+}
+
+func unmarkImplicit(inst *Inst, prefix Prefix) {
+ for i := len(inst.Prefix) - 1; i >= 0; i-- {
+ p := inst.Prefix[i]
+ if p&0xFF == prefix {
+ inst.Prefix[i] &^= PrefixImplicit
+ }
+ }
+}
+
+func byteSizeSuffix(b int) string {
+ switch b {
+ case 1:
+ return "b"
+ case 2:
+ return "w"
+ case 4:
+ return "l"
+ case 8:
+ return "q"
+ }
+ return ""
+}
+
+func argBytes(inst *Inst, arg Arg) int {
+ if isMem(arg) {
+ return inst.MemBytes
+ }
+ return regBytes(arg)
+}
+
+func isFloat(op Op) bool {
+ switch op {
+ case FADD, FCOM, FCOMP, FDIV, FDIVR, FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR, FLD, FMUL, FST, FSTP, FSUB, FSUBR:
+ return true
+ }
+ return false
+}
+
+func isFloatInt(op Op) bool {
+ switch op {
+ case FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR:
+ 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
new file mode 100644
index 000000000..d4c1b6ce3
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/inst.go
@@ -0,0 +1,641 @@
+// 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/inst_test.go b/src/cmd/internal/rsc.io/x86/x86asm/inst_test.go
new file mode 100644
index 000000000..23ac52320
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/inst_test.go
@@ -0,0 +1,20 @@
+// 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 (
+ "strings"
+ "testing"
+)
+
+func TestRegString(t *testing.T) {
+ for r := Reg(1); r <= regMax; r++ {
+ if regNames[r] == "" {
+ t.Errorf("regNames[%d] is missing", int(r))
+ } else if s := r.String(); strings.Contains(s, "Reg(") {
+ t.Errorf("Reg(%d).String() = %s, want proper name", int(r), s)
+ }
+ }
+}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/intel.go b/src/cmd/internal/rsc.io/x86/x86asm/intel.go
new file mode 100644
index 000000000..90af9dd63
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/intel.go
@@ -0,0 +1,518 @@
+// 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"
+)
+
+// IntelSyntax returns the Intel assembler syntax for the instruction, as defined by Intel's XED tool.
+func IntelSyntax(inst Inst) string {
+ var iargs []Arg
+ for _, a := range inst.Args {
+ if a == nil {
+ break
+ }
+ iargs = append(iargs, a)
+ }
+
+ switch inst.Op {
+ case INSB, INSD, INSW, OUTSB, OUTSD, OUTSW, LOOPNE, JCXZ, JECXZ, JRCXZ, LOOP, LOOPE, MOV, XLATB:
+ if inst.Op == MOV && (inst.Opcode>>16)&0xFFFC != 0x0F20 {
+ break
+ }
+ for i, p := range inst.Prefix {
+ if p&0xFF == PrefixAddrSize {
+ inst.Prefix[i] &^= PrefixImplicit
+ }
+ }
+ }
+
+ switch inst.Op {
+ case MOV:
+ dst, _ := inst.Args[0].(Reg)
+ src, _ := inst.Args[1].(Reg)
+ if ES <= dst && dst <= GS && EAX <= src && src <= R15L {
+ src -= EAX - AX
+ iargs[1] = src
+ }
+ if ES <= dst && dst <= GS && RAX <= src && src <= R15 {
+ src -= RAX - AX
+ iargs[1] = src
+ }
+
+ if inst.Opcode>>24&^3 == 0xA0 {
+ for i, p := range inst.Prefix {
+ if p&0xFF == PrefixAddrSize {
+ inst.Prefix[i] |= PrefixImplicit
+ }
+ }
+ }
+ }
+
+ switch inst.Op {
+ case AAM, AAD:
+ if imm, ok := iargs[0].(Imm); ok {
+ if inst.DataSize == 32 {
+ iargs[0] = Imm(uint32(int8(imm)))
+ } else if inst.DataSize == 16 {
+ iargs[0] = Imm(uint16(int8(imm)))
+ }
+ }
+
+ case PUSH:
+ if imm, ok := iargs[0].(Imm); ok {
+ iargs[0] = Imm(uint32(imm))
+ }
+ }
+
+ for _, p := range inst.Prefix {
+ if p&PrefixImplicit != 0 {
+ for j, pj := range inst.Prefix {
+ if pj&0xFF == p&0xFF {
+ inst.Prefix[j] |= PrefixImplicit
+ }
+ }
+ }
+ }
+
+ if inst.Op != 0 {
+ for i, p := range inst.Prefix {
+ switch p &^ PrefixIgnored {
+ case PrefixData16, PrefixData32, PrefixCS, PrefixDS, PrefixES, PrefixSS:
+ inst.Prefix[i] |= PrefixImplicit
+ }
+ if p.IsREX() {
+ inst.Prefix[i] |= PrefixImplicit
+ }
+ }
+ }
+
+ if isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
+ for i, p := range inst.Prefix {
+ if p == PrefixPT || p == PrefixPN {
+ inst.Prefix[i] |= PrefixImplicit
+ }
+ }
+ }
+
+ switch inst.Op {
+ case AAA, AAS, CBW, CDQE, CLC, CLD, CLI, CLTS, CMC, CPUID, CQO, CWD, DAA, DAS,
+ FDECSTP, FINCSTP, FNCLEX, FNINIT, FNOP, FWAIT, HLT,
+ ICEBP, INSB, INSD, INSW, INT, INTO, INVD, IRET, IRETQ,
+ LAHF, LEAVE, LRET, MONITOR, MWAIT, NOP, OUTSB, OUTSD, OUTSW,
+ PAUSE, POPA, POPF, POPFQ, PUSHA, PUSHF, PUSHFQ,
+ RDMSR, RDPMC, RDTSC, RDTSCP, RET, RSM,
+ SAHF, STC, STD, STI, SYSENTER, SYSEXIT, SYSRET,
+ UD2, WBINVD, WRMSR, XEND, XLATB, XTEST:
+
+ if inst.Op == NOP && inst.Opcode>>24 != 0x90 {
+ break
+ }
+ if inst.Op == RET && inst.Opcode>>24 != 0xC3 {
+ break
+ }
+ if inst.Op == INT && inst.Opcode>>24 != 0xCC {
+ break
+ }
+ if inst.Op == LRET && inst.Opcode>>24 != 0xcb {
+ break
+ }
+ for i, p := range inst.Prefix {
+ if p&0xFF == PrefixDataSize {
+ inst.Prefix[i] &^= PrefixImplicit | PrefixIgnored
+ }
+ }
+
+ case 0:
+ // ok
+ }
+
+ switch inst.Op {
+ case INSB, INSD, INSW, OUTSB, OUTSD, OUTSW, MONITOR, MWAIT, XLATB:
+ iargs = nil
+
+ case STOSB, STOSW, STOSD, STOSQ:
+ iargs = iargs[:1]
+
+ case LODSB, LODSW, LODSD, LODSQ, SCASB, SCASW, SCASD, SCASQ:
+ iargs = iargs[1:]
+ }
+
+ const (
+ haveData16 = 1 << iota
+ haveData32
+ haveAddr16
+ haveAddr32
+ haveXacquire
+ haveXrelease
+ haveLock
+ haveHintTaken
+ haveHintNotTaken
+ haveBnd
+ )
+ var prefixBits uint32
+ prefix := ""
+ for _, p := range inst.Prefix {
+ if p == 0 {
+ break
+ }
+ if p&0xFF == 0xF3 {
+ prefixBits &^= haveBnd
+ }
+ if p&(PrefixImplicit|PrefixIgnored) != 0 {
+ continue
+ }
+ switch p {
+ default:
+ prefix += strings.ToLower(p.String()) + " "
+ case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
+ if inst.Op == 0 {
+ prefix += strings.ToLower(p.String()) + " "
+ }
+ case PrefixREPN:
+ prefix += "repne "
+ case PrefixLOCK:
+ prefixBits |= haveLock
+ case PrefixData16, PrefixDataSize:
+ prefixBits |= haveData16
+ case PrefixData32:
+ prefixBits |= haveData32
+ case PrefixAddrSize, PrefixAddr16:
+ prefixBits |= haveAddr16
+ case PrefixAddr32:
+ prefixBits |= haveAddr32
+ case PrefixXACQUIRE:
+ prefixBits |= haveXacquire
+ case PrefixXRELEASE:
+ prefixBits |= haveXrelease
+ case PrefixPT:
+ prefixBits |= haveHintTaken
+ case PrefixPN:
+ prefixBits |= haveHintNotTaken
+ case PrefixBND:
+ prefixBits |= haveBnd
+ }
+ }
+ switch inst.Op {
+ case JMP:
+ if inst.Opcode>>24 == 0xEB {
+ prefixBits &^= haveBnd
+ }
+ case RET, LRET:
+ prefixBits &^= haveData16 | haveData32
+ }
+
+ if prefixBits&haveXacquire != 0 {
+ prefix += "xacquire "
+ }
+ if prefixBits&haveXrelease != 0 {
+ prefix += "xrelease "
+ }
+ if prefixBits&haveLock != 0 {
+ prefix += "lock "
+ }
+ if prefixBits&haveBnd != 0 {
+ prefix += "bnd "
+ }
+ if prefixBits&haveHintTaken != 0 {
+ prefix += "hint-taken "
+ }
+ if prefixBits&haveHintNotTaken != 0 {
+ prefix += "hint-not-taken "
+ }
+ if prefixBits&haveAddr16 != 0 {
+ prefix += "addr16 "
+ }
+ if prefixBits&haveAddr32 != 0 {
+ prefix += "addr32 "
+ }
+ if prefixBits&haveData16 != 0 {
+ prefix += "data16 "
+ }
+ if prefixBits&haveData32 != 0 {
+ prefix += "data32 "
+ }
+
+ if inst.Op == 0 {
+ if prefix == "" {
+ return "<no instruction>"
+ }
+ return prefix[:len(prefix)-1]
+ }
+
+ var args []string
+ for _, a := range iargs {
+ if a == nil {
+ break
+ }
+ args = append(args, intelArg(&inst, a))
+ }
+
+ var op string
+ switch inst.Op {
+ case NOP:
+ if inst.Opcode>>24 == 0x0F {
+ if inst.DataSize == 16 {
+ args = append(args, "ax")
+ } else {
+ args = append(args, "eax")
+ }
+ }
+
+ case BLENDVPD, BLENDVPS, PBLENDVB:
+ args = args[:2]
+
+ case INT:
+ if inst.Opcode>>24 == 0xCC {
+ args = nil
+ op = "int3"
+ }
+
+ case LCALL, LJMP:
+ if len(args) == 2 {
+ args[0], args[1] = args[1], args[0]
+ }
+
+ case FCHS, FABS, FTST, FLDPI, FLDL2E, FLDLG2, F2XM1, FXAM, FLD1, FLDL2T, FSQRT, FRNDINT, FCOS, FSIN:
+ if len(args) == 0 {
+ args = append(args, "st0")
+ }
+
+ case FPTAN, FSINCOS, FUCOMPP, FCOMPP, FYL2X, FPATAN, FXTRACT, FPREM1, FPREM, FYL2XP1, FSCALE:
+ if len(args) == 0 {
+ args = []string{"st0", "st1"}
+ }
+
+ case FST, FSTP, FISTTP, FIST, FISTP, FBSTP:
+ if len(args) == 1 {
+ args = append(args, "st0")
+ }
+
+ case FLD, FXCH, FCOM, FCOMP, FIADD, FIMUL, FICOM, FICOMP, FISUBR, FIDIV, FUCOM, FUCOMP, FILD, FBLD, FADD, FMUL, FSUB, FSUBR, FISUB, FDIV, FDIVR, FIDIVR:
+ if len(args) == 1 {
+ args = []string{"st0", args[0]}
+ }
+
+ case MASKMOVDQU, MASKMOVQ, XLATB, OUTSB, OUTSW, OUTSD:
+ FixSegment:
+ for i := len(inst.Prefix) - 1; i >= 0; i-- {
+ p := inst.Prefix[i] & 0xFF
+ switch p {
+ case PrefixCS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
+ if inst.Mode != 64 || p == PrefixFS || p == PrefixGS {
+ args = append(args, strings.ToLower((inst.Prefix[i] & 0xFF).String()))
+ break FixSegment
+ }
+ case PrefixDS:
+ if inst.Mode != 64 {
+ break FixSegment
+ }
+ }
+ }
+ }
+
+ if op == "" {
+ op = intelOp[inst.Op]
+ }
+ if op == "" {
+ op = strings.ToLower(inst.Op.String())
+ }
+ if args != nil {
+ op += " " + strings.Join(args, ", ")
+ }
+ return prefix + op
+}
+
+func intelArg(inst *Inst, arg Arg) string {
+ switch a := arg.(type) {
+ case Imm:
+ 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.Base == EIP {
+ a.Base = RIP
+ }
+ prefix := ""
+ switch inst.MemBytes {
+ case 1:
+ prefix = "byte "
+ case 2:
+ prefix = "word "
+ case 4:
+ prefix = "dword "
+ case 8:
+ prefix = "qword "
+ case 16:
+ prefix = "xmmword "
+ }
+ switch inst.Op {
+ case INVLPG:
+ prefix = "byte "
+ case STOSB, MOVSB, CMPSB, LODSB, SCASB:
+ prefix = "byte "
+ case STOSW, MOVSW, CMPSW, LODSW, SCASW:
+ prefix = "word "
+ case STOSD, MOVSD, CMPSD, LODSD, SCASD:
+ prefix = "dword "
+ case STOSQ, MOVSQ, CMPSQ, LODSQ, SCASQ:
+ prefix = "qword "
+ case LAR:
+ prefix = "word "
+ case BOUND:
+ if inst.Mode == 32 {
+ prefix = "qword "
+ } else {
+ prefix = "dword "
+ }
+ case PREFETCHW, PREFETCHNTA, PREFETCHT0, PREFETCHT1, PREFETCHT2, CLFLUSH:
+ prefix = "zmmword "
+ }
+ switch inst.Op {
+ case MOVSB, MOVSW, MOVSD, MOVSQ, CMPSB, CMPSW, CMPSD, CMPSQ, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ, LODSB, LODSW, LODSD, LODSQ:
+ switch a.Base {
+ case DI, EDI, RDI:
+ if a.Segment == ES {
+ a.Segment = 0
+ }
+ case SI, ESI, RSI:
+ if a.Segment == DS {
+ a.Segment = 0
+ }
+ }
+ case LEA:
+ a.Segment = 0
+ default:
+ switch a.Base {
+ case SP, ESP, RSP, BP, EBP, RBP:
+ if a.Segment == SS {
+ a.Segment = 0
+ }
+ default:
+ if a.Segment == DS {
+ a.Segment = 0
+ }
+ }
+ }
+
+ if inst.Mode == 64 && a.Segment != FS && a.Segment != GS {
+ a.Segment = 0
+ }
+
+ prefix += "ptr "
+ if a.Segment != 0 {
+ prefix += strings.ToLower(a.Segment.String()) + ":"
+ }
+ prefix += "["
+ if a.Base != 0 {
+ prefix += intelArg(inst, a.Base)
+ }
+ if a.Scale != 0 && a.Index != 0 {
+ if a.Base != 0 {
+ prefix += "+"
+ }
+ prefix += fmt.Sprintf("%s*%d", intelArg(inst, a.Index), a.Scale)
+ }
+ if a.Disp != 0 {
+ if prefix[len(prefix)-1] == '[' && (a.Disp >= 0 || int64(int32(a.Disp)) != a.Disp) {
+ prefix += fmt.Sprintf("%#x", uint64(a.Disp))
+ } else {
+ prefix += fmt.Sprintf("%+#x", a.Disp)
+ }
+ }
+ prefix += "]"
+ return prefix
+ case Rel:
+ return fmt.Sprintf(".%+#x", int64(a))
+ case Reg:
+ if int(a) < len(intelReg) && intelReg[a] != "" {
+ return intelReg[a]
+ }
+ }
+ return strings.ToLower(arg.String())
+}
+
+var intelOp = map[Op]string{
+ JAE: "jnb",
+ JA: "jnbe",
+ JGE: "jnl",
+ JNE: "jnz",
+ JG: "jnle",
+ JE: "jz",
+ SETAE: "setnb",
+ SETA: "setnbe",
+ SETGE: "setnl",
+ SETNE: "setnz",
+ SETG: "setnle",
+ SETE: "setz",
+ CMOVAE: "cmovnb",
+ CMOVA: "cmovnbe",
+ CMOVGE: "cmovnl",
+ CMOVNE: "cmovnz",
+ CMOVG: "cmovnle",
+ CMOVE: "cmovz",
+ LCALL: "call far",
+ LJMP: "jmp far",
+ LRET: "ret far",
+ ICEBP: "int1",
+ MOVSD_XMM: "movsd",
+ XLATB: "xlat",
+}
+
+var intelReg = [...]string{
+ F0: "st0",
+ F1: "st1",
+ F2: "st2",
+ F3: "st3",
+ F4: "st4",
+ F5: "st5",
+ F6: "st6",
+ F7: "st7",
+ M0: "mmx0",
+ M1: "mmx1",
+ M2: "mmx2",
+ M3: "mmx3",
+ M4: "mmx4",
+ M5: "mmx5",
+ M6: "mmx6",
+ M7: "mmx7",
+ X0: "xmm0",
+ X1: "xmm1",
+ X2: "xmm2",
+ X3: "xmm3",
+ X4: "xmm4",
+ X5: "xmm5",
+ X6: "xmm6",
+ X7: "xmm7",
+ X8: "xmm8",
+ X9: "xmm9",
+ X10: "xmm10",
+ X11: "xmm11",
+ X12: "xmm12",
+ X13: "xmm13",
+ X14: "xmm14",
+ X15: "xmm15",
+
+ // TODO: Maybe the constants are named wrong.
+ SPB: "spl",
+ BPB: "bpl",
+ SIB: "sil",
+ DIB: "dil",
+
+ R8L: "r8d",
+ R9L: "r9d",
+ R10L: "r10d",
+ R11L: "r11d",
+ R12L: "r12d",
+ R13L: "r13d",
+ R14L: "r14d",
+ R15L: "r15d",
+}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/objdump_test.go b/src/cmd/internal/rsc.io/x86/x86asm/objdump_test.go
new file mode 100644
index 000000000..6f7260544
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/objdump_test.go
@@ -0,0 +1,383 @@
+// 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
new file mode 100644
index 000000000..37a5513d3
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/objdumpext_test.go
@@ -0,0 +1,314 @@
+// 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
new file mode 100644
index 000000000..21f5bfd12
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/plan9ext_test.go
@@ -0,0 +1,120 @@
+// 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
new file mode 100644
index 000000000..5a0bd8776
--- /dev/null
+++ b/src/cmd/internal/rsc.io/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"
+)
+
+// 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/plan9x_test.go b/src/cmd/internal/rsc.io/x86/x86asm/plan9x_test.go
new file mode 100644
index 000000000..f2ea28cd9
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/plan9x_test.go
@@ -0,0 +1,54 @@
+// 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 (
+ "strings"
+ "testing"
+)
+
+func TestPlan932Manual(t *testing.T) { testPlan932(t, hexCases(t, plan9ManualTests)) }
+func TestPlan932Testdata(t *testing.T) { testPlan932(t, concat(basicPrefixes, testdataCases(t))) }
+func TestPlan932ModRM(t *testing.T) { testPlan932(t, concat(basicPrefixes, enumModRM)) }
+func TestPlan932OneByte(t *testing.T) { testBasic(t, testPlan932) }
+func TestPlan9320F(t *testing.T) { testBasic(t, testPlan932, 0x0F) }
+func TestPlan9320F38(t *testing.T) { testBasic(t, testPlan932, 0x0F, 0x38) }
+func TestPlan9320F3A(t *testing.T) { testBasic(t, testPlan932, 0x0F, 0x3A) }
+func TestPlan932Prefix(t *testing.T) { testPrefix(t, testPlan932) }
+
+func TestPlan964Manual(t *testing.T) { testPlan964(t, hexCases(t, plan9ManualTests)) }
+func TestPlan964Testdata(t *testing.T) { testPlan964(t, concat(basicPrefixes, testdataCases(t))) }
+func TestPlan964ModRM(t *testing.T) { testPlan964(t, concat(basicPrefixes, enumModRM)) }
+func TestPlan964OneByte(t *testing.T) { testBasic(t, testPlan964) }
+func TestPlan9640F(t *testing.T) { testBasic(t, testPlan964, 0x0F) }
+func TestPlan9640F38(t *testing.T) { testBasic(t, testPlan964, 0x0F, 0x38) }
+func TestPlan9640F3A(t *testing.T) { testBasic(t, testPlan964, 0x0F, 0x3A) }
+func TestPlan964Prefix(t *testing.T) { testPrefix(t, testPlan964) }
+
+func TestPlan964REXTestdata(t *testing.T) {
+ testPlan964(t, filter(concat3(basicPrefixes, rexPrefixes, testdataCases(t)), isValidREX))
+}
+func TestPlan964REXModRM(t *testing.T) { testPlan964(t, concat3(basicPrefixes, rexPrefixes, enumModRM)) }
+func TestPlan964REXOneByte(t *testing.T) { testBasicREX(t, testPlan964) }
+func TestPlan964REX0F(t *testing.T) { testBasicREX(t, testPlan964, 0x0F) }
+func TestPlan964REX0F38(t *testing.T) { testBasicREX(t, testPlan964, 0x0F, 0x38) }
+func TestPlan964REX0F3A(t *testing.T) { testBasicREX(t, testPlan964, 0x0F, 0x3A) }
+func TestPlan964REXPrefix(t *testing.T) { testPrefixREX(t, testPlan964) }
+
+// plan9ManualTests holds test cases that will be run by TestPlan9Manual32 and TestPlan9Manual64.
+// 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=Plan9Manual, particularly with tracing enabled.
+var plan9ManualTests = `
+`
+
+// allowedMismatchPlan9 reports whether the mismatch between text and dec
+// should be allowed by the test.
+func allowedMismatchPlan9(text string, size int, inst *Inst, dec ExtInst) bool {
+ return false
+}
+
+// Instructions known to us but not to plan9.
+var plan9Unsupported = strings.Fields(`
+`)
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/tables.go b/src/cmd/internal/rsc.io/x86/x86asm/tables.go
new file mode 100644
index 000000000..3d08d5ebe
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/tables.go
@@ -0,0 +1,9760 @@
+// DO NOT EDIT
+// generated by: x86map -fmt=decoder ../x86.csv
+
+package x86asm
+
+var decoder = [...]uint16{
+ uint16(xFail),
+ /*1*/ uint16(xCondByte), 243,
+ 0x00, 490,
+ 0x01, 496,
+ 0x02, 525,
+ 0x03, 531,
+ 0x04, 560,
+ 0x05, 566,
+ 0x06, 595,
+ 0x07, 602,
+ 0x08, 609,
+ 0x09, 615,
+ 0x0A, 644,
+ 0x0B, 650,
+ 0x0C, 679,
+ 0x0D, 685,
+ 0x0E, 714,
+ 0x0F, 721,
+ 0x10, 8026,
+ 0x11, 8032,
+ 0x12, 8061,
+ 0x13, 8067,
+ 0x14, 8096,
+ 0x15, 8102,
+ 0x16, 8131,
+ 0x17, 8138,
+ 0x18, 8145,
+ 0x19, 8151,
+ 0x1A, 8180,
+ 0x1B, 8186,
+ 0x1C, 8215,
+ 0x1D, 8221,
+ 0x1E, 8250,
+ 0x1F, 8257,
+ 0x20, 8264,
+ 0x21, 8270,
+ 0x22, 8299,
+ 0x23, 8305,
+ 0x24, 8334,
+ 0x25, 8340,
+ 0x27, 8369,
+ 0x28, 8375,
+ 0x29, 8381,
+ 0x2A, 8410,
+ 0x2B, 8416,
+ 0x2C, 8445,
+ 0x2D, 8451,
+ 0x2F, 8480,
+ 0x30, 8486,
+ 0x31, 8492,
+ 0x32, 8521,
+ 0x33, 8527,
+ 0x34, 8556,
+ 0x35, 8562,
+ 0x37, 8591,
+ 0x38, 8597,
+ 0x39, 8603,
+ 0x3A, 8632,
+ 0x3B, 8638,
+ 0x3C, 8667,
+ 0x3D, 8673,
+ 0x3F, 8702,
+ 0x40, 8708,
+ 0x41, 8708,
+ 0x42, 8708,
+ 0x43, 8708,
+ 0x44, 8708,
+ 0x45, 8708,
+ 0x46, 8708,
+ 0x47, 8708,
+ 0x48, 8723,
+ 0x49, 8723,
+ 0x4a, 8723,
+ 0x4b, 8723,
+ 0x4c, 8723,
+ 0x4d, 8723,
+ 0x4e, 8723,
+ 0x4f, 8723,
+ 0x50, 8738,
+ 0x51, 8738,
+ 0x52, 8738,
+ 0x53, 8738,
+ 0x54, 8738,
+ 0x55, 8738,
+ 0x56, 8738,
+ 0x57, 8738,
+ 0x58, 8765,
+ 0x59, 8765,
+ 0x5a, 8765,
+ 0x5b, 8765,
+ 0x5c, 8765,
+ 0x5d, 8765,
+ 0x5e, 8765,
+ 0x5f, 8765,
+ 0x60, 8792,
+ 0x61, 8805,
+ 0x62, 8818,
+ 0x63, 8837,
+ 0x68, 8868,
+ 0x69, 8887,
+ 0x6A, 8922,
+ 0x6B, 8927,
+ 0x6C, 8962,
+ 0x6D, 8965,
+ 0x6E, 8978,
+ 0x6F, 8981,
+ 0x70, 8994,
+ 0x71, 8999,
+ 0x72, 9004,
+ 0x73, 9009,
+ 0x74, 9014,
+ 0x75, 9019,
+ 0x76, 9024,
+ 0x77, 9029,
+ 0x78, 9034,
+ 0x79, 9039,
+ 0x7A, 9044,
+ 0x7B, 9049,
+ 0x7C, 9054,
+ 0x7D, 9059,
+ 0x7E, 9064,
+ 0x7F, 9069,
+ 0x80, 9074,
+ 0x81, 9131,
+ 0x83, 9372,
+ 0x84, 9613,
+ 0x85, 9619,
+ 0x86, 9648,
+ 0x87, 9654,
+ 0x88, 9683,
+ 0x89, 9689,
+ 0x8A, 9711,
+ 0x8B, 9717,
+ 0x8C, 9739,
+ 0x8D, 9768,
+ 0x8E, 9797,
+ 0x8F, 9826,
+ 0x90, 9862,
+ 0x91, 9862,
+ 0x92, 9862,
+ 0x93, 9862,
+ 0x94, 9862,
+ 0x95, 9862,
+ 0x96, 9862,
+ 0x97, 9862,
+ 0x98, 9888,
+ 0x99, 9908,
+ 0x9A, 9928,
+ 0x9B, 9945,
+ 0x9C, 9948,
+ 0x9D, 9971,
+ 0x9E, 9994,
+ 0x9F, 9997,
+ 0xA0, 10000,
+ 0xA1, 10019,
+ 0xA2, 10041,
+ 0xA3, 10060,
+ 0xA4, 10082,
+ 0xA5, 10085,
+ 0xA6, 10105,
+ 0xA7, 10108,
+ 0xA8, 10128,
+ 0xA9, 10134,
+ 0xAA, 10163,
+ 0xAB, 10166,
+ 0xAC, 10186,
+ 0xAD, 10189,
+ 0xAE, 10209,
+ 0xAF, 10212,
+ 0xb0, 10232,
+ 0xb1, 10232,
+ 0xb2, 10232,
+ 0xb3, 10232,
+ 0xb4, 10232,
+ 0xb5, 10232,
+ 0xb6, 10232,
+ 0xb7, 10232,
+ 0xb8, 10238,
+ 0xb9, 10238,
+ 0xba, 10238,
+ 0xbb, 10238,
+ 0xbc, 10238,
+ 0xbd, 10238,
+ 0xbe, 10238,
+ 0xbf, 10238,
+ 0xC0, 10267,
+ 0xC1, 10318,
+ 0xC2, 10516,
+ 0xC3, 10521,
+ 0xC4, 10524,
+ 0xC5, 10543,
+ 0xC6, 10562,
+ 0xC7, 10586,
+ 0xC8, 10647,
+ 0xC9, 10654,
+ 0xCA, 10677,
+ 0xCB, 10682,
+ 0xCC, 10685,
+ 0xCD, 10689,
+ 0xCE, 10694,
+ 0xCF, 10700,
+ 0xD0, 10720,
+ 0xD1, 10764,
+ 0xD2, 10955,
+ 0xD3, 10999,
+ 0xD4, 11190,
+ 0xD5, 11198,
+ 0xD7, 11206,
+ 0xD8, 11219,
+ 0xD9, 11428,
+ 0xDA, 11637,
+ 0xDB, 11769,
+ 0xDC, 11940,
+ 0xDD, 12109,
+ 0xDE, 12248,
+ 0xDF, 12422,
+ 0xE0, 12533,
+ 0xE1, 12538,
+ 0xE2, 12543,
+ 0xE3, 12548,
+ 0xE4, 12574,
+ 0xE5, 12580,
+ 0xE6, 12602,
+ 0xE7, 12608,
+ 0xE8, 12630,
+ 0xE9, 12661,
+ 0xEA, 12692,
+ 0xEB, 12709,
+ 0xEC, 12714,
+ 0xED, 12719,
+ 0xEE, 12738,
+ 0xEF, 12743,
+ 0xF1, 12762,
+ 0xF4, 12765,
+ 0xF5, 12768,
+ 0xF6, 12771,
+ 0xF7, 12810,
+ 0xF8, 12986,
+ 0xF9, 12989,
+ 0xFA, 12992,
+ 0xFB, 12995,
+ 0xFC, 12998,
+ 0xFD, 13001,
+ 0xFE, 13004,
+ 0xFF, 13021,
+ uint16(xFail),
+ /*490*/ uint16(xSetOp), uint16(ADD),
+ /*492*/ uint16(xReadSlashR),
+ /*493*/ uint16(xArgRM8),
+ /*494*/ uint16(xArgR8),
+ /*495*/ uint16(xMatch),
+ /*496*/ uint16(xCondIs64), 499, 515,
+ /*499*/ uint16(xCondDataSize), 503, 509, 0,
+ /*503*/ uint16(xSetOp), uint16(ADD),
+ /*505*/ uint16(xReadSlashR),
+ /*506*/ uint16(xArgRM16),
+ /*507*/ uint16(xArgR16),
+ /*508*/ uint16(xMatch),
+ /*509*/ uint16(xSetOp), uint16(ADD),
+ /*511*/ uint16(xReadSlashR),
+ /*512*/ uint16(xArgRM32),
+ /*513*/ uint16(xArgR32),
+ /*514*/ uint16(xMatch),
+ /*515*/ uint16(xCondDataSize), 503, 509, 519,
+ /*519*/ uint16(xSetOp), uint16(ADD),
+ /*521*/ uint16(xReadSlashR),
+ /*522*/ uint16(xArgRM64),
+ /*523*/ uint16(xArgR64),
+ /*524*/ uint16(xMatch),
+ /*525*/ uint16(xSetOp), uint16(ADD),
+ /*527*/ uint16(xReadSlashR),
+ /*528*/ uint16(xArgR8),
+ /*529*/ uint16(xArgRM8),
+ /*530*/ uint16(xMatch),
+ /*531*/ uint16(xCondIs64), 534, 550,
+ /*534*/ uint16(xCondDataSize), 538, 544, 0,
+ /*538*/ uint16(xSetOp), uint16(ADD),
+ /*540*/ uint16(xReadSlashR),
+ /*541*/ uint16(xArgR16),
+ /*542*/ uint16(xArgRM16),
+ /*543*/ uint16(xMatch),
+ /*544*/ uint16(xSetOp), uint16(ADD),
+ /*546*/ uint16(xReadSlashR),
+ /*547*/ uint16(xArgR32),
+ /*548*/ uint16(xArgRM32),
+ /*549*/ uint16(xMatch),
+ /*550*/ uint16(xCondDataSize), 538, 544, 554,
+ /*554*/ uint16(xSetOp), uint16(ADD),
+ /*556*/ uint16(xReadSlashR),
+ /*557*/ uint16(xArgR64),
+ /*558*/ uint16(xArgRM64),
+ /*559*/ uint16(xMatch),
+ /*560*/ uint16(xSetOp), uint16(ADD),
+ /*562*/ uint16(xReadIb),
+ /*563*/ uint16(xArgAL),
+ /*564*/ uint16(xArgImm8u),
+ /*565*/ uint16(xMatch),
+ /*566*/ uint16(xCondIs64), 569, 585,
+ /*569*/ uint16(xCondDataSize), 573, 579, 0,
+ /*573*/ uint16(xSetOp), uint16(ADD),
+ /*575*/ uint16(xReadIw),
+ /*576*/ uint16(xArgAX),
+ /*577*/ uint16(xArgImm16),
+ /*578*/ uint16(xMatch),
+ /*579*/ uint16(xSetOp), uint16(ADD),
+ /*581*/ uint16(xReadId),
+ /*582*/ uint16(xArgEAX),
+ /*583*/ uint16(xArgImm32),
+ /*584*/ uint16(xMatch),
+ /*585*/ uint16(xCondDataSize), 573, 579, 589,
+ /*589*/ uint16(xSetOp), uint16(ADD),
+ /*591*/ uint16(xReadId),
+ /*592*/ uint16(xArgRAX),
+ /*593*/ uint16(xArgImm32),
+ /*594*/ uint16(xMatch),
+ /*595*/ uint16(xCondIs64), 598, 0,
+ /*598*/ uint16(xSetOp), uint16(PUSH),
+ /*600*/ uint16(xArgES),
+ /*601*/ uint16(xMatch),
+ /*602*/ uint16(xCondIs64), 605, 0,
+ /*605*/ uint16(xSetOp), uint16(POP),
+ /*607*/ uint16(xArgES),
+ /*608*/ uint16(xMatch),
+ /*609*/ uint16(xSetOp), uint16(OR),
+ /*611*/ uint16(xReadSlashR),
+ /*612*/ uint16(xArgRM8),
+ /*613*/ uint16(xArgR8),
+ /*614*/ uint16(xMatch),
+ /*615*/ uint16(xCondIs64), 618, 634,
+ /*618*/ uint16(xCondDataSize), 622, 628, 0,
+ /*622*/ uint16(xSetOp), uint16(OR),
+ /*624*/ uint16(xReadSlashR),
+ /*625*/ uint16(xArgRM16),
+ /*626*/ uint16(xArgR16),
+ /*627*/ uint16(xMatch),
+ /*628*/ uint16(xSetOp), uint16(OR),
+ /*630*/ uint16(xReadSlashR),
+ /*631*/ uint16(xArgRM32),
+ /*632*/ uint16(xArgR32),
+ /*633*/ uint16(xMatch),
+ /*634*/ uint16(xCondDataSize), 622, 628, 638,
+ /*638*/ uint16(xSetOp), uint16(OR),
+ /*640*/ uint16(xReadSlashR),
+ /*641*/ uint16(xArgRM64),
+ /*642*/ uint16(xArgR64),
+ /*643*/ uint16(xMatch),
+ /*644*/ uint16(xSetOp), uint16(OR),
+ /*646*/ uint16(xReadSlashR),
+ /*647*/ uint16(xArgR8),
+ /*648*/ uint16(xArgRM8),
+ /*649*/ uint16(xMatch),
+ /*650*/ uint16(xCondIs64), 653, 669,
+ /*653*/ uint16(xCondDataSize), 657, 663, 0,
+ /*657*/ uint16(xSetOp), uint16(OR),
+ /*659*/ uint16(xReadSlashR),
+ /*660*/ uint16(xArgR16),
+ /*661*/ uint16(xArgRM16),
+ /*662*/ uint16(xMatch),
+ /*663*/ uint16(xSetOp), uint16(OR),
+ /*665*/ uint16(xReadSlashR),
+ /*666*/ uint16(xArgR32),
+ /*667*/ uint16(xArgRM32),
+ /*668*/ uint16(xMatch),
+ /*669*/ uint16(xCondDataSize), 657, 663, 673,
+ /*673*/ uint16(xSetOp), uint16(OR),
+ /*675*/ uint16(xReadSlashR),
+ /*676*/ uint16(xArgR64),
+ /*677*/ uint16(xArgRM64),
+ /*678*/ uint16(xMatch),
+ /*679*/ uint16(xSetOp), uint16(OR),
+ /*681*/ uint16(xReadIb),
+ /*682*/ uint16(xArgAL),
+ /*683*/ uint16(xArgImm8u),
+ /*684*/ uint16(xMatch),
+ /*685*/ uint16(xCondIs64), 688, 704,
+ /*688*/ uint16(xCondDataSize), 692, 698, 0,
+ /*692*/ uint16(xSetOp), uint16(OR),
+ /*694*/ uint16(xReadIw),
+ /*695*/ uint16(xArgAX),
+ /*696*/ uint16(xArgImm16),
+ /*697*/ uint16(xMatch),
+ /*698*/ uint16(xSetOp), uint16(OR),
+ /*700*/ uint16(xReadId),
+ /*701*/ uint16(xArgEAX),
+ /*702*/ uint16(xArgImm32),
+ /*703*/ uint16(xMatch),
+ /*704*/ uint16(xCondDataSize), 692, 698, 708,
+ /*708*/ uint16(xSetOp), uint16(OR),
+ /*710*/ uint16(xReadId),
+ /*711*/ uint16(xArgRAX),
+ /*712*/ uint16(xArgImm32),
+ /*713*/ uint16(xMatch),
+ /*714*/ uint16(xCondIs64), 717, 0,
+ /*717*/ uint16(xSetOp), uint16(PUSH),
+ /*719*/ uint16(xArgCS),
+ /*720*/ uint16(xMatch),
+ /*721*/ uint16(xCondByte), 228,
+ 0x00, 1180,
+ 0x01, 1237,
+ 0x02, 1345,
+ 0x03, 1367,
+ 0x05, 1389,
+ 0x06, 1395,
+ 0x07, 1398,
+ 0x08, 1404,
+ 0x09, 1407,
+ 0x0B, 1410,
+ 0x0D, 1413,
+ 0x10, 1426,
+ 0x11, 1460,
+ 0x12, 1494,
+ 0x13, 1537,
+ 0x14, 1555,
+ 0x15, 1573,
+ 0x16, 1591,
+ 0x17, 1626,
+ 0x18, 1644,
+ 0x1F, 1669,
+ 0x20, 1690,
+ 0x21, 1705,
+ 0x22, 1720,
+ 0x23, 1735,
+ 0x24, 1750,
+ 0x26, 1765,
+ 0x28, 1780,
+ 0x29, 1798,
+ 0x2A, 1816,
+ 0x2B, 1903,
+ 0x2C, 1937,
+ 0x2D, 2024,
+ 0x2E, 2111,
+ 0x2F, 2129,
+ 0x30, 2147,
+ 0x31, 2150,
+ 0x32, 2153,
+ 0x33, 2156,
+ 0x34, 2159,
+ 0x35, 2162,
+ 0x38, 2172,
+ 0x3A, 3073,
+ 0x40, 3484,
+ 0x41, 3513,
+ 0x42, 3542,
+ 0x43, 3571,
+ 0x44, 3600,
+ 0x45, 3629,
+ 0x46, 3658,
+ 0x47, 3687,
+ 0x48, 3716,
+ 0x49, 3745,
+ 0x4A, 3774,
+ 0x4B, 3803,
+ 0x4C, 3832,
+ 0x4D, 3861,
+ 0x4E, 3890,
+ 0x4F, 3919,
+ 0x50, 3948,
+ 0x51, 3966,
+ 0x52, 4000,
+ 0x53, 4018,
+ 0x54, 4036,
+ 0x55, 4054,
+ 0x56, 4072,
+ 0x57, 4090,
+ 0x58, 4108,
+ 0x59, 4142,
+ 0x5A, 4176,
+ 0x5B, 4210,
+ 0x5C, 4236,
+ 0x5D, 4270,
+ 0x5E, 4304,
+ 0x5F, 4338,
+ 0x60, 4372,
+ 0x61, 4390,
+ 0x62, 4408,
+ 0x63, 4426,
+ 0x64, 4444,
+ 0x65, 4462,
+ 0x66, 4480,
+ 0x67, 4498,
+ 0x68, 4516,
+ 0x69, 4534,
+ 0x6A, 4552,
+ 0x6B, 4570,
+ 0x6C, 4588,
+ 0x6D, 4598,
+ 0x6E, 4608,
+ 0x6F, 4675,
+ 0x70, 4701,
+ 0x71, 4743,
+ 0x72, 4806,
+ 0x73, 4869,
+ 0x74, 4934,
+ 0x75, 4952,
+ 0x76, 4970,
+ 0x77, 4988,
+ 0x7C, 4991,
+ 0x7D, 5009,
+ 0x7E, 5027,
+ 0x7F, 5104,
+ 0x80, 5130,
+ 0x81, 5161,
+ 0x82, 5192,
+ 0x83, 5223,
+ 0x84, 5254,
+ 0x85, 5285,
+ 0x86, 5316,
+ 0x87, 5347,
+ 0x88, 5378,
+ 0x89, 5409,
+ 0x8A, 5440,
+ 0x8B, 5471,
+ 0x8C, 5502,
+ 0x8D, 5533,
+ 0x8E, 5564,
+ 0x8F, 5595,
+ 0x90, 5626,
+ 0x91, 5631,
+ 0x92, 5636,
+ 0x93, 5641,
+ 0x94, 5646,
+ 0x95, 5651,
+ 0x96, 5656,
+ 0x97, 5661,
+ 0x98, 5666,
+ 0x99, 5671,
+ 0x9A, 5676,
+ 0x9B, 5681,
+ 0x9C, 5686,
+ 0x9D, 5691,
+ 0x9E, 5696,
+ 0x9F, 5701,
+ 0xA0, 5706,
+ 0xA1, 5710,
+ 0xA2, 5737,
+ 0xA3, 5740,
+ 0xA4, 5769,
+ 0xA5, 5804,
+ 0xA8, 5836,
+ 0xA9, 5840,
+ 0xAA, 5867,
+ 0xAB, 5870,
+ 0xAC, 5899,
+ 0xAD, 5934,
+ 0xAE, 5966,
+ 0xAF, 6224,
+ 0xB0, 6253,
+ 0xB1, 6259,
+ 0xB2, 6288,
+ 0xB3, 6317,
+ 0xB4, 6346,
+ 0xB5, 6375,
+ 0xB6, 6404,
+ 0xB7, 6433,
+ 0xB8, 6462,
+ 0xB9, 6499,
+ 0xBA, 6502,
+ 0xBB, 6627,
+ 0xBC, 6656,
+ 0xBD, 6723,
+ 0xBE, 6790,
+ 0xBF, 6819,
+ 0xC0, 6848,
+ 0xC1, 6854,
+ 0xC2, 6883,
+ 0xC3, 6925,
+ 0xC4, 6954,
+ 0xC5, 6976,
+ 0xC6, 6998,
+ 0xC7, 7020,
+ 0xc8, 7149,
+ 0xc9, 7149,
+ 0xca, 7149,
+ 0xcb, 7149,
+ 0xcc, 7149,
+ 0xcd, 7149,
+ 0xce, 7149,
+ 0xcf, 7149,
+ 0xD0, 7172,
+ 0xD1, 7190,
+ 0xD2, 7208,
+ 0xD3, 7226,
+ 0xD4, 7244,
+ 0xD5, 7262,
+ 0xD6, 7280,
+ 0xD7, 7306,
+ 0xD8, 7324,
+ 0xD9, 7342,
+ 0xDA, 7360,
+ 0xDB, 7378,
+ 0xDC, 7396,
+ 0xDD, 7414,
+ 0xDE, 7432,
+ 0xDF, 7450,
+ 0xE0, 7468,
+ 0xE1, 7486,
+ 0xE2, 7504,
+ 0xE3, 7522,
+ 0xE4, 7540,
+ 0xE5, 7558,
+ 0xE6, 7576,
+ 0xE7, 7602,
+ 0xE8, 7620,
+ 0xE9, 7638,
+ 0xEA, 7656,
+ 0xEB, 7674,
+ 0xEC, 7692,
+ 0xED, 7710,
+ 0xEE, 7728,
+ 0xEF, 7746,
+ 0xF0, 7764,
+ 0xF1, 7774,
+ 0xF2, 7792,
+ 0xF3, 7810,
+ 0xF4, 7828,
+ 0xF5, 7846,
+ 0xF6, 7864,
+ 0xF7, 7882,
+ 0xF8, 7900,
+ 0xF9, 7918,
+ 0xFA, 7936,
+ 0xFB, 7954,
+ 0xFC, 7972,
+ 0xFD, 7990,
+ 0xFE, 8008,
+ uint16(xFail),
+ /*1180*/ uint16(xCondSlashR),
+ 1189, // 0
+ 1205, // 1
+ 1221, // 2
+ 1225, // 3
+ 1229, // 4
+ 1233, // 5
+ 0, // 6
+ 0, // 7
+ /*1189*/ uint16(xCondDataSize), 1193, 1197, 1201,
+ /*1193*/ uint16(xSetOp), uint16(SLDT),
+ /*1195*/ uint16(xArgRM16),
+ /*1196*/ uint16(xMatch),
+ /*1197*/ uint16(xSetOp), uint16(SLDT),
+ /*1199*/ uint16(xArgR32M16),
+ /*1200*/ uint16(xMatch),
+ /*1201*/ uint16(xSetOp), uint16(SLDT),
+ /*1203*/ uint16(xArgR64M16),
+ /*1204*/ uint16(xMatch),
+ /*1205*/ uint16(xCondDataSize), 1209, 1213, 1217,
+ /*1209*/ uint16(xSetOp), uint16(STR),
+ /*1211*/ uint16(xArgRM16),
+ /*1212*/ uint16(xMatch),
+ /*1213*/ uint16(xSetOp), uint16(STR),
+ /*1215*/ uint16(xArgR32M16),
+ /*1216*/ uint16(xMatch),
+ /*1217*/ uint16(xSetOp), uint16(STR),
+ /*1219*/ uint16(xArgR64M16),
+ /*1220*/ uint16(xMatch),
+ /*1221*/ uint16(xSetOp), uint16(LLDT),
+ /*1223*/ uint16(xArgRM16),
+ /*1224*/ uint16(xMatch),
+ /*1225*/ uint16(xSetOp), uint16(LTR),
+ /*1227*/ uint16(xArgRM16),
+ /*1228*/ uint16(xMatch),
+ /*1229*/ uint16(xSetOp), uint16(VERR),
+ /*1231*/ uint16(xArgRM16),
+ /*1232*/ uint16(xMatch),
+ /*1233*/ uint16(xSetOp), uint16(VERW),
+ /*1235*/ uint16(xArgRM16),
+ /*1236*/ uint16(xMatch),
+ /*1237*/ uint16(xCondByte), 8,
+ 0xC8, 1318,
+ 0xC9, 1321,
+ 0xD0, 1324,
+ 0xD1, 1327,
+ 0xD5, 1330,
+ 0xD6, 1333,
+ 0xF8, 1336,
+ 0xF9, 1342,
+ /*1255*/ uint16(xCondSlashR),
+ 1264, // 0
+ 1268, // 1
+ 1272, // 2
+ 1283, // 3
+ 1294, // 4
+ 0, // 5
+ 1310, // 6
+ 1314, // 7
+ /*1264*/ uint16(xSetOp), uint16(SGDT),
+ /*1266*/ uint16(xArgM),
+ /*1267*/ uint16(xMatch),
+ /*1268*/ uint16(xSetOp), uint16(SIDT),
+ /*1270*/ uint16(xArgM),
+ /*1271*/ uint16(xMatch),
+ /*1272*/ uint16(xCondIs64), 1275, 1279,
+ /*1275*/ uint16(xSetOp), uint16(LGDT),
+ /*1277*/ uint16(xArgM16and32),
+ /*1278*/ uint16(xMatch),
+ /*1279*/ uint16(xSetOp), uint16(LGDT),
+ /*1281*/ uint16(xArgM16and64),
+ /*1282*/ uint16(xMatch),
+ /*1283*/ uint16(xCondIs64), 1286, 1290,
+ /*1286*/ uint16(xSetOp), uint16(LIDT),
+ /*1288*/ uint16(xArgM16and32),
+ /*1289*/ uint16(xMatch),
+ /*1290*/ uint16(xSetOp), uint16(LIDT),
+ /*1292*/ uint16(xArgM16and64),
+ /*1293*/ uint16(xMatch),
+ /*1294*/ uint16(xCondDataSize), 1298, 1302, 1306,
+ /*1298*/ uint16(xSetOp), uint16(SMSW),
+ /*1300*/ uint16(xArgRM16),
+ /*1301*/ uint16(xMatch),
+ /*1302*/ uint16(xSetOp), uint16(SMSW),
+ /*1304*/ uint16(xArgR32M16),
+ /*1305*/ uint16(xMatch),
+ /*1306*/ uint16(xSetOp), uint16(SMSW),
+ /*1308*/ uint16(xArgR64M16),
+ /*1309*/ uint16(xMatch),
+ /*1310*/ uint16(xSetOp), uint16(LMSW),
+ /*1312*/ uint16(xArgRM16),
+ /*1313*/ uint16(xMatch),
+ /*1314*/ uint16(xSetOp), uint16(INVLPG),
+ /*1316*/ uint16(xArgM),
+ /*1317*/ uint16(xMatch),
+ /*1318*/ uint16(xSetOp), uint16(MONITOR),
+ /*1320*/ uint16(xMatch),
+ /*1321*/ uint16(xSetOp), uint16(MWAIT),
+ /*1323*/ uint16(xMatch),
+ /*1324*/ uint16(xSetOp), uint16(XGETBV),
+ /*1326*/ uint16(xMatch),
+ /*1327*/ uint16(xSetOp), uint16(XSETBV),
+ /*1329*/ uint16(xMatch),
+ /*1330*/ uint16(xSetOp), uint16(XEND),
+ /*1332*/ uint16(xMatch),
+ /*1333*/ uint16(xSetOp), uint16(XTEST),
+ /*1335*/ uint16(xMatch),
+ /*1336*/ uint16(xCondIs64), 0, 1339,
+ /*1339*/ uint16(xSetOp), uint16(SWAPGS),
+ /*1341*/ uint16(xMatch),
+ /*1342*/ uint16(xSetOp), uint16(RDTSCP),
+ /*1344*/ uint16(xMatch),
+ /*1345*/ uint16(xCondDataSize), 1349, 1355, 1361,
+ /*1349*/ uint16(xSetOp), uint16(LAR),
+ /*1351*/ uint16(xReadSlashR),
+ /*1352*/ uint16(xArgR16),
+ /*1353*/ uint16(xArgRM16),
+ /*1354*/ uint16(xMatch),
+ /*1355*/ uint16(xSetOp), uint16(LAR),
+ /*1357*/ uint16(xReadSlashR),
+ /*1358*/ uint16(xArgR32),
+ /*1359*/ uint16(xArgR32M16),
+ /*1360*/ uint16(xMatch),
+ /*1361*/ uint16(xSetOp), uint16(LAR),
+ /*1363*/ uint16(xReadSlashR),
+ /*1364*/ uint16(xArgR64),
+ /*1365*/ uint16(xArgR64M16),
+ /*1366*/ uint16(xMatch),
+ /*1367*/ uint16(xCondDataSize), 1371, 1377, 1383,
+ /*1371*/ uint16(xSetOp), uint16(LSL),
+ /*1373*/ uint16(xReadSlashR),
+ /*1374*/ uint16(xArgR16),
+ /*1375*/ uint16(xArgRM16),
+ /*1376*/ uint16(xMatch),
+ /*1377*/ uint16(xSetOp), uint16(LSL),
+ /*1379*/ uint16(xReadSlashR),
+ /*1380*/ uint16(xArgR32),
+ /*1381*/ uint16(xArgR32M16),
+ /*1382*/ uint16(xMatch),
+ /*1383*/ uint16(xSetOp), uint16(LSL),
+ /*1385*/ uint16(xReadSlashR),
+ /*1386*/ uint16(xArgR64),
+ /*1387*/ uint16(xArgR32M16),
+ /*1388*/ uint16(xMatch),
+ /*1389*/ uint16(xCondIs64), 0, 1392,
+ /*1392*/ uint16(xSetOp), uint16(SYSCALL),
+ /*1394*/ uint16(xMatch),
+ /*1395*/ uint16(xSetOp), uint16(CLTS),
+ /*1397*/ uint16(xMatch),
+ /*1398*/ uint16(xCondIs64), 0, 1401,
+ /*1401*/ uint16(xSetOp), uint16(SYSRET),
+ /*1403*/ uint16(xMatch),
+ /*1404*/ uint16(xSetOp), uint16(INVD),
+ /*1406*/ uint16(xMatch),
+ /*1407*/ uint16(xSetOp), uint16(WBINVD),
+ /*1409*/ uint16(xMatch),
+ /*1410*/ uint16(xSetOp), uint16(UD2),
+ /*1412*/ uint16(xMatch),
+ /*1413*/ uint16(xCondSlashR),
+ 0, // 0
+ 1422, // 1
+ 0, // 2
+ 0, // 3
+ 0, // 4
+ 0, // 5
+ 0, // 6
+ 0, // 7
+ /*1422*/ uint16(xSetOp), uint16(PREFETCHW),
+ /*1424*/ uint16(xArgM8),
+ /*1425*/ uint16(xMatch),
+ /*1426*/ uint16(xCondPrefix), 4,
+ 0xF3, 1454,
+ 0xF2, 1448,
+ 0x66, 1442,
+ 0x0, 1436,
+ /*1436*/ uint16(xSetOp), uint16(MOVUPS),
+ /*1438*/ uint16(xReadSlashR),
+ /*1439*/ uint16(xArgXmm1),
+ /*1440*/ uint16(xArgXmm2M128),
+ /*1441*/ uint16(xMatch),
+ /*1442*/ uint16(xSetOp), uint16(MOVUPD),
+ /*1444*/ uint16(xReadSlashR),
+ /*1445*/ uint16(xArgXmm1),
+ /*1446*/ uint16(xArgXmm2M128),
+ /*1447*/ uint16(xMatch),
+ /*1448*/ uint16(xSetOp), uint16(MOVSD_XMM),
+ /*1450*/ uint16(xReadSlashR),
+ /*1451*/ uint16(xArgXmm1),
+ /*1452*/ uint16(xArgXmm2M64),
+ /*1453*/ uint16(xMatch),
+ /*1454*/ uint16(xSetOp), uint16(MOVSS),
+ /*1456*/ uint16(xReadSlashR),
+ /*1457*/ uint16(xArgXmm1),
+ /*1458*/ uint16(xArgXmm2M32),
+ /*1459*/ uint16(xMatch),
+ /*1460*/ uint16(xCondPrefix), 4,
+ 0xF3, 1488,
+ 0xF2, 1482,
+ 0x66, 1476,
+ 0x0, 1470,
+ /*1470*/ uint16(xSetOp), uint16(MOVUPS),
+ /*1472*/ uint16(xReadSlashR),
+ /*1473*/ uint16(xArgXmm2M128),
+ /*1474*/ uint16(xArgXmm1),
+ /*1475*/ uint16(xMatch),
+ /*1476*/ uint16(xSetOp), uint16(MOVUPD),
+ /*1478*/ uint16(xReadSlashR),
+ /*1479*/ uint16(xArgXmm2M128),
+ /*1480*/ uint16(xArgXmm),
+ /*1481*/ uint16(xMatch),
+ /*1482*/ uint16(xSetOp), uint16(MOVSD_XMM),
+ /*1484*/ uint16(xReadSlashR),
+ /*1485*/ uint16(xArgXmm2M64),
+ /*1486*/ uint16(xArgXmm1),
+ /*1487*/ uint16(xMatch),
+ /*1488*/ uint16(xSetOp), uint16(MOVSS),
+ /*1490*/ uint16(xReadSlashR),
+ /*1491*/ uint16(xArgXmm2M32),
+ /*1492*/ uint16(xArgXmm),
+ /*1493*/ uint16(xMatch),
+ /*1494*/ uint16(xCondPrefix), 4,
+ 0xF3, 1531,
+ 0xF2, 1525,
+ 0x66, 1519,
+ 0x0, 1504,
+ /*1504*/ uint16(xCondIsMem), 1507, 1513,
+ /*1507*/ uint16(xSetOp), uint16(MOVHLPS),
+ /*1509*/ uint16(xReadSlashR),
+ /*1510*/ uint16(xArgXmm1),
+ /*1511*/ uint16(xArgXmm2),
+ /*1512*/ uint16(xMatch),
+ /*1513*/ uint16(xSetOp), uint16(MOVLPS),
+ /*1515*/ uint16(xReadSlashR),
+ /*1516*/ uint16(xArgXmm),
+ /*1517*/ uint16(xArgM64),
+ /*1518*/ uint16(xMatch),
+ /*1519*/ uint16(xSetOp), uint16(MOVLPD),
+ /*1521*/ uint16(xReadSlashR),
+ /*1522*/ uint16(xArgXmm),
+ /*1523*/ uint16(xArgXmm2M64),
+ /*1524*/ uint16(xMatch),
+ /*1525*/ uint16(xSetOp), uint16(MOVDDUP),
+ /*1527*/ uint16(xReadSlashR),
+ /*1528*/ uint16(xArgXmm1),
+ /*1529*/ uint16(xArgXmm2M64),
+ /*1530*/ uint16(xMatch),
+ /*1531*/ uint16(xSetOp), uint16(MOVSLDUP),
+ /*1533*/ uint16(xReadSlashR),
+ /*1534*/ uint16(xArgXmm1),
+ /*1535*/ uint16(xArgXmm2M128),
+ /*1536*/ uint16(xMatch),
+ /*1537*/ uint16(xCondPrefix), 2,
+ 0x66, 1549,
+ 0x0, 1543,
+ /*1543*/ uint16(xSetOp), uint16(MOVLPS),
+ /*1545*/ uint16(xReadSlashR),
+ /*1546*/ uint16(xArgM64),
+ /*1547*/ uint16(xArgXmm),
+ /*1548*/ uint16(xMatch),
+ /*1549*/ uint16(xSetOp), uint16(MOVLPD),
+ /*1551*/ uint16(xReadSlashR),
+ /*1552*/ uint16(xArgXmm2M64),
+ /*1553*/ uint16(xArgXmm),
+ /*1554*/ uint16(xMatch),
+ /*1555*/ uint16(xCondPrefix), 2,
+ 0x66, 1567,
+ 0x0, 1561,
+ /*1561*/ uint16(xSetOp), uint16(UNPCKLPS),
+ /*1563*/ uint16(xReadSlashR),
+ /*1564*/ uint16(xArgXmm1),
+ /*1565*/ uint16(xArgXmm2M128),
+ /*1566*/ uint16(xMatch),
+ /*1567*/ uint16(xSetOp), uint16(UNPCKLPD),
+ /*1569*/ uint16(xReadSlashR),
+ /*1570*/ uint16(xArgXmm1),
+ /*1571*/ uint16(xArgXmm2M128),
+ /*1572*/ uint16(xMatch),
+ /*1573*/ uint16(xCondPrefix), 2,
+ 0x66, 1585,
+ 0x0, 1579,
+ /*1579*/ uint16(xSetOp), uint16(UNPCKHPS),
+ /*1581*/ uint16(xReadSlashR),
+ /*1582*/ uint16(xArgXmm1),
+ /*1583*/ uint16(xArgXmm2M128),
+ /*1584*/ uint16(xMatch),
+ /*1585*/ uint16(xSetOp), uint16(UNPCKHPD),
+ /*1587*/ uint16(xReadSlashR),
+ /*1588*/ uint16(xArgXmm1),
+ /*1589*/ uint16(xArgXmm2M128),
+ /*1590*/ uint16(xMatch),
+ /*1591*/ uint16(xCondPrefix), 3,
+ 0xF3, 1620,
+ 0x66, 1614,
+ 0x0, 1599,
+ /*1599*/ uint16(xCondIsMem), 1602, 1608,
+ /*1602*/ uint16(xSetOp), uint16(MOVLHPS),
+ /*1604*/ uint16(xReadSlashR),
+ /*1605*/ uint16(xArgXmm1),
+ /*1606*/ uint16(xArgXmm2),
+ /*1607*/ uint16(xMatch),
+ /*1608*/ uint16(xSetOp), uint16(MOVHPS),
+ /*1610*/ uint16(xReadSlashR),
+ /*1611*/ uint16(xArgXmm),
+ /*1612*/ uint16(xArgM64),
+ /*1613*/ uint16(xMatch),
+ /*1614*/ uint16(xSetOp), uint16(MOVHPD),
+ /*1616*/ uint16(xReadSlashR),
+ /*1617*/ uint16(xArgXmm),
+ /*1618*/ uint16(xArgXmm2M64),
+ /*1619*/ uint16(xMatch),
+ /*1620*/ uint16(xSetOp), uint16(MOVSHDUP),
+ /*1622*/ uint16(xReadSlashR),
+ /*1623*/ uint16(xArgXmm1),
+ /*1624*/ uint16(xArgXmm2M128),
+ /*1625*/ uint16(xMatch),
+ /*1626*/ uint16(xCondPrefix), 2,
+ 0x66, 1638,
+ 0x0, 1632,
+ /*1632*/ uint16(xSetOp), uint16(MOVHPS),
+ /*1634*/ uint16(xReadSlashR),
+ /*1635*/ uint16(xArgM64),
+ /*1636*/ uint16(xArgXmm),
+ /*1637*/ uint16(xMatch),
+ /*1638*/ uint16(xSetOp), uint16(MOVHPD),
+ /*1640*/ uint16(xReadSlashR),
+ /*1641*/ uint16(xArgXmm2M64),
+ /*1642*/ uint16(xArgXmm),
+ /*1643*/ uint16(xMatch),
+ /*1644*/ uint16(xCondSlashR),
+ 1653, // 0
+ 1657, // 1
+ 1661, // 2
+ 1665, // 3
+ 0, // 4
+ 0, // 5
+ 0, // 6
+ 0, // 7
+ /*1653*/ uint16(xSetOp), uint16(PREFETCHNTA),
+ /*1655*/ uint16(xArgM8),
+ /*1656*/ uint16(xMatch),
+ /*1657*/ uint16(xSetOp), uint16(PREFETCHT0),
+ /*1659*/ uint16(xArgM8),
+ /*1660*/ uint16(xMatch),
+ /*1661*/ uint16(xSetOp), uint16(PREFETCHT1),
+ /*1663*/ uint16(xArgM8),
+ /*1664*/ uint16(xMatch),
+ /*1665*/ uint16(xSetOp), uint16(PREFETCHT2),
+ /*1667*/ uint16(xArgM8),
+ /*1668*/ uint16(xMatch),
+ /*1669*/ uint16(xCondSlashR),
+ 1678, // 0
+ 0, // 1
+ 0, // 2
+ 0, // 3
+ 0, // 4
+ 0, // 5
+ 0, // 6
+ 0, // 7
+ /*1678*/ uint16(xCondDataSize), 1682, 1686, 0,
+ /*1682*/ uint16(xSetOp), uint16(NOP),
+ /*1684*/ uint16(xArgRM16),
+ /*1685*/ uint16(xMatch),
+ /*1686*/ uint16(xSetOp), uint16(NOP),
+ /*1688*/ uint16(xArgRM32),
+ /*1689*/ uint16(xMatch),
+ /*1690*/ uint16(xCondIs64), 1693, 1699,
+ /*1693*/ uint16(xSetOp), uint16(MOV),
+ /*1695*/ uint16(xReadSlashR),
+ /*1696*/ uint16(xArgRmf32),
+ /*1697*/ uint16(xArgCR0dashCR7),
+ /*1698*/ uint16(xMatch),
+ /*1699*/ uint16(xSetOp), uint16(MOV),
+ /*1701*/ uint16(xReadSlashR),
+ /*1702*/ uint16(xArgRmf64),
+ /*1703*/ uint16(xArgCR0dashCR7),
+ /*1704*/ uint16(xMatch),
+ /*1705*/ uint16(xCondIs64), 1708, 1714,
+ /*1708*/ uint16(xSetOp), uint16(MOV),
+ /*1710*/ uint16(xReadSlashR),
+ /*1711*/ uint16(xArgRmf32),
+ /*1712*/ uint16(xArgDR0dashDR7),
+ /*1713*/ uint16(xMatch),
+ /*1714*/ uint16(xSetOp), uint16(MOV),
+ /*1716*/ uint16(xReadSlashR),
+ /*1717*/ uint16(xArgRmf64),
+ /*1718*/ uint16(xArgDR0dashDR7),
+ /*1719*/ uint16(xMatch),
+ /*1720*/ uint16(xCondIs64), 1723, 1729,
+ /*1723*/ uint16(xSetOp), uint16(MOV),
+ /*1725*/ uint16(xReadSlashR),
+ /*1726*/ uint16(xArgCR0dashCR7),
+ /*1727*/ uint16(xArgRmf32),
+ /*1728*/ uint16(xMatch),
+ /*1729*/ uint16(xSetOp), uint16(MOV),
+ /*1731*/ uint16(xReadSlashR),
+ /*1732*/ uint16(xArgCR0dashCR7),
+ /*1733*/ uint16(xArgRmf64),
+ /*1734*/ uint16(xMatch),
+ /*1735*/ uint16(xCondIs64), 1738, 1744,
+ /*1738*/ uint16(xSetOp), uint16(MOV),
+ /*1740*/ uint16(xReadSlashR),
+ /*1741*/ uint16(xArgDR0dashDR7),
+ /*1742*/ uint16(xArgRmf32),
+ /*1743*/ uint16(xMatch),
+ /*1744*/ uint16(xSetOp), uint16(MOV),
+ /*1746*/ uint16(xReadSlashR),
+ /*1747*/ uint16(xArgDR0dashDR7),
+ /*1748*/ uint16(xArgRmf64),
+ /*1749*/ uint16(xMatch),
+ /*1750*/ uint16(xCondIs64), 1753, 1759,
+ /*1753*/ uint16(xSetOp), uint16(MOV),
+ /*1755*/ uint16(xReadSlashR),
+ /*1756*/ uint16(xArgRmf32),
+ /*1757*/ uint16(xArgTR0dashTR7),
+ /*1758*/ uint16(xMatch),
+ /*1759*/ uint16(xSetOp), uint16(MOV),
+ /*1761*/ uint16(xReadSlashR),
+ /*1762*/ uint16(xArgRmf64),
+ /*1763*/ uint16(xArgTR0dashTR7),
+ /*1764*/ uint16(xMatch),
+ /*1765*/ uint16(xCondIs64), 1768, 1774,
+ /*1768*/ uint16(xSetOp), uint16(MOV),
+ /*1770*/ uint16(xReadSlashR),
+ /*1771*/ uint16(xArgTR0dashTR7),
+ /*1772*/ uint16(xArgRmf32),
+ /*1773*/ uint16(xMatch),
+ /*1774*/ uint16(xSetOp), uint16(MOV),
+ /*1776*/ uint16(xReadSlashR),
+ /*1777*/ uint16(xArgTR0dashTR7),
+ /*1778*/ uint16(xArgRmf64),
+ /*1779*/ uint16(xMatch),
+ /*1780*/ uint16(xCondPrefix), 2,
+ 0x66, 1792,
+ 0x0, 1786,
+ /*1786*/ uint16(xSetOp), uint16(MOVAPS),
+ /*1788*/ uint16(xReadSlashR),
+ /*1789*/ uint16(xArgXmm1),
+ /*1790*/ uint16(xArgXmm2M128),
+ /*1791*/ uint16(xMatch),
+ /*1792*/ uint16(xSetOp), uint16(MOVAPD),
+ /*1794*/ uint16(xReadSlashR),
+ /*1795*/ uint16(xArgXmm1),
+ /*1796*/ uint16(xArgXmm2M128),
+ /*1797*/ uint16(xMatch),
+ /*1798*/ uint16(xCondPrefix), 2,
+ 0x66, 1810,
+ 0x0, 1804,
+ /*1804*/ uint16(xSetOp), uint16(MOVAPS),
+ /*1806*/ uint16(xReadSlashR),
+ /*1807*/ uint16(xArgXmm2M128),
+ /*1808*/ uint16(xArgXmm1),
+ /*1809*/ uint16(xMatch),
+ /*1810*/ uint16(xSetOp), uint16(MOVAPD),
+ /*1812*/ uint16(xReadSlashR),
+ /*1813*/ uint16(xArgXmm2M128),
+ /*1814*/ uint16(xArgXmm1),
+ /*1815*/ uint16(xMatch),
+ /*1816*/ uint16(xCondIs64), 1819, 1873,
+ /*1819*/ uint16(xCondPrefix), 4,
+ 0xF3, 1857,
+ 0xF2, 1841,
+ 0x66, 1835,
+ 0x0, 1829,
+ /*1829*/ uint16(xSetOp), uint16(CVTPI2PS),
+ /*1831*/ uint16(xReadSlashR),
+ /*1832*/ uint16(xArgXmm),
+ /*1833*/ uint16(xArgMmM64),
+ /*1834*/ uint16(xMatch),
+ /*1835*/ uint16(xSetOp), uint16(CVTPI2PD),
+ /*1837*/ uint16(xReadSlashR),
+ /*1838*/ uint16(xArgXmm),
+ /*1839*/ uint16(xArgMmM64),
+ /*1840*/ uint16(xMatch),
+ /*1841*/ uint16(xCondDataSize), 1845, 1851, 0,
+ /*1845*/ uint16(xSetOp), uint16(CVTSI2SD),
+ /*1847*/ uint16(xReadSlashR),
+ /*1848*/ uint16(xArgXmm),
+ /*1849*/ uint16(xArgRM32),
+ /*1850*/ uint16(xMatch),
+ /*1851*/ uint16(xSetOp), uint16(CVTSI2SD),
+ /*1853*/ uint16(xReadSlashR),
+ /*1854*/ uint16(xArgXmm),
+ /*1855*/ uint16(xArgRM32),
+ /*1856*/ uint16(xMatch),
+ /*1857*/ uint16(xCondDataSize), 1861, 1867, 0,
+ /*1861*/ uint16(xSetOp), uint16(CVTSI2SS),
+ /*1863*/ uint16(xReadSlashR),
+ /*1864*/ uint16(xArgXmm),
+ /*1865*/ uint16(xArgRM32),
+ /*1866*/ uint16(xMatch),
+ /*1867*/ uint16(xSetOp), uint16(CVTSI2SS),
+ /*1869*/ uint16(xReadSlashR),
+ /*1870*/ uint16(xArgXmm),
+ /*1871*/ uint16(xArgRM32),
+ /*1872*/ uint16(xMatch),
+ /*1873*/ uint16(xCondPrefix), 4,
+ 0xF3, 1893,
+ 0xF2, 1883,
+ 0x66, 1835,
+ 0x0, 1829,
+ /*1883*/ uint16(xCondDataSize), 1845, 1851, 1887,
+ /*1887*/ uint16(xSetOp), uint16(CVTSI2SD),
+ /*1889*/ uint16(xReadSlashR),
+ /*1890*/ uint16(xArgXmm),
+ /*1891*/ uint16(xArgRM64),
+ /*1892*/ uint16(xMatch),
+ /*1893*/ uint16(xCondDataSize), 1861, 1867, 1897,
+ /*1897*/ uint16(xSetOp), uint16(CVTSI2SS),
+ /*1899*/ uint16(xReadSlashR),
+ /*1900*/ uint16(xArgXmm),
+ /*1901*/ uint16(xArgRM64),
+ /*1902*/ uint16(xMatch),
+ /*1903*/ uint16(xCondPrefix), 4,
+ 0xF3, 1931,
+ 0xF2, 1925,
+ 0x66, 1919,
+ 0x0, 1913,
+ /*1913*/ uint16(xSetOp), uint16(MOVNTPS),
+ /*1915*/ uint16(xReadSlashR),
+ /*1916*/ uint16(xArgM128),
+ /*1917*/ uint16(xArgXmm),
+ /*1918*/ uint16(xMatch),
+ /*1919*/ uint16(xSetOp), uint16(MOVNTPD),
+ /*1921*/ uint16(xReadSlashR),
+ /*1922*/ uint16(xArgM128),
+ /*1923*/ uint16(xArgXmm),
+ /*1924*/ uint16(xMatch),
+ /*1925*/ uint16(xSetOp), uint16(MOVNTSD),
+ /*1927*/ uint16(xReadSlashR),
+ /*1928*/ uint16(xArgM64),
+ /*1929*/ uint16(xArgXmm),
+ /*1930*/ uint16(xMatch),
+ /*1931*/ uint16(xSetOp), uint16(MOVNTSS),
+ /*1933*/ uint16(xReadSlashR),
+ /*1934*/ uint16(xArgM32),
+ /*1935*/ uint16(xArgXmm),
+ /*1936*/ uint16(xMatch),
+ /*1937*/ uint16(xCondIs64), 1940, 1994,
+ /*1940*/ uint16(xCondPrefix), 4,
+ 0xF3, 1978,
+ 0xF2, 1962,
+ 0x66, 1956,
+ 0x0, 1950,
+ /*1950*/ uint16(xSetOp), uint16(CVTTPS2PI),
+ /*1952*/ uint16(xReadSlashR),
+ /*1953*/ uint16(xArgMm),
+ /*1954*/ uint16(xArgXmmM64),
+ /*1955*/ uint16(xMatch),
+ /*1956*/ uint16(xSetOp), uint16(CVTTPD2PI),
+ /*1958*/ uint16(xReadSlashR),
+ /*1959*/ uint16(xArgMm),
+ /*1960*/ uint16(xArgXmmM128),
+ /*1961*/ uint16(xMatch),
+ /*1962*/ uint16(xCondDataSize), 1966, 1972, 0,
+ /*1966*/ uint16(xSetOp), uint16(CVTTSD2SI),
+ /*1968*/ uint16(xReadSlashR),
+ /*1969*/ uint16(xArgR32),
+ /*1970*/ uint16(xArgXmmM64),
+ /*1971*/ uint16(xMatch),
+ /*1972*/ uint16(xSetOp), uint16(CVTTSD2SI),
+ /*1974*/ uint16(xReadSlashR),
+ /*1975*/ uint16(xArgR32),
+ /*1976*/ uint16(xArgXmmM64),
+ /*1977*/ uint16(xMatch),
+ /*1978*/ uint16(xCondDataSize), 1982, 1988, 0,
+ /*1982*/ uint16(xSetOp), uint16(CVTTSS2SI),
+ /*1984*/ uint16(xReadSlashR),
+ /*1985*/ uint16(xArgR32),
+ /*1986*/ uint16(xArgXmmM32),
+ /*1987*/ uint16(xMatch),
+ /*1988*/ uint16(xSetOp), uint16(CVTTSS2SI),
+ /*1990*/ uint16(xReadSlashR),
+ /*1991*/ uint16(xArgR32),
+ /*1992*/ uint16(xArgXmmM32),
+ /*1993*/ uint16(xMatch),
+ /*1994*/ uint16(xCondPrefix), 4,
+ 0xF3, 2014,
+ 0xF2, 2004,
+ 0x66, 1956,
+ 0x0, 1950,
+ /*2004*/ uint16(xCondDataSize), 1966, 1972, 2008,
+ /*2008*/ uint16(xSetOp), uint16(CVTTSD2SI),
+ /*2010*/ uint16(xReadSlashR),
+ /*2011*/ uint16(xArgR64),
+ /*2012*/ uint16(xArgXmmM64),
+ /*2013*/ uint16(xMatch),
+ /*2014*/ uint16(xCondDataSize), 1982, 1988, 2018,
+ /*2018*/ uint16(xSetOp), uint16(CVTTSS2SI),
+ /*2020*/ uint16(xReadSlashR),
+ /*2021*/ uint16(xArgR64),
+ /*2022*/ uint16(xArgXmmM32),
+ /*2023*/ uint16(xMatch),
+ /*2024*/ uint16(xCondIs64), 2027, 2081,
+ /*2027*/ uint16(xCondPrefix), 4,
+ 0xF3, 2065,
+ 0xF2, 2049,
+ 0x66, 2043,
+ 0x0, 2037,
+ /*2037*/ uint16(xSetOp), uint16(CVTPS2PI),
+ /*2039*/ uint16(xReadSlashR),
+ /*2040*/ uint16(xArgMm),
+ /*2041*/ uint16(xArgXmmM64),
+ /*2042*/ uint16(xMatch),
+ /*2043*/ uint16(xSetOp), uint16(CVTPD2PI),
+ /*2045*/ uint16(xReadSlashR),
+ /*2046*/ uint16(xArgMm),
+ /*2047*/ uint16(xArgXmmM128),
+ /*2048*/ uint16(xMatch),
+ /*2049*/ uint16(xCondDataSize), 2053, 2059, 0,
+ /*2053*/ uint16(xSetOp), uint16(CVTSD2SI),
+ /*2055*/ uint16(xReadSlashR),
+ /*2056*/ uint16(xArgR32),
+ /*2057*/ uint16(xArgXmmM64),
+ /*2058*/ uint16(xMatch),
+ /*2059*/ uint16(xSetOp), uint16(CVTSD2SI),
+ /*2061*/ uint16(xReadSlashR),
+ /*2062*/ uint16(xArgR32),
+ /*2063*/ uint16(xArgXmmM64),
+ /*2064*/ uint16(xMatch),
+ /*2065*/ uint16(xCondDataSize), 2069, 2075, 0,
+ /*2069*/ uint16(xSetOp), uint16(CVTSS2SI),
+ /*2071*/ uint16(xReadSlashR),
+ /*2072*/ uint16(xArgR32),
+ /*2073*/ uint16(xArgXmmM32),
+ /*2074*/ uint16(xMatch),
+ /*2075*/ uint16(xSetOp), uint16(CVTSS2SI),
+ /*2077*/ uint16(xReadSlashR),
+ /*2078*/ uint16(xArgR32),
+ /*2079*/ uint16(xArgXmmM32),
+ /*2080*/ uint16(xMatch),
+ /*2081*/ uint16(xCondPrefix), 4,
+ 0xF3, 2101,
+ 0xF2, 2091,
+ 0x66, 2043,
+ 0x0, 2037,
+ /*2091*/ uint16(xCondDataSize), 2053, 2059, 2095,
+ /*2095*/ uint16(xSetOp), uint16(CVTSD2SI),
+ /*2097*/ uint16(xReadSlashR),
+ /*2098*/ uint16(xArgR64),
+ /*2099*/ uint16(xArgXmmM64),
+ /*2100*/ uint16(xMatch),
+ /*2101*/ uint16(xCondDataSize), 2069, 2075, 2105,
+ /*2105*/ uint16(xSetOp), uint16(CVTSS2SI),
+ /*2107*/ uint16(xReadSlashR),
+ /*2108*/ uint16(xArgR64),
+ /*2109*/ uint16(xArgXmmM32),
+ /*2110*/ uint16(xMatch),
+ /*2111*/ uint16(xCondPrefix), 2,
+ 0x66, 2123,
+ 0x0, 2117,
+ /*2117*/ uint16(xSetOp), uint16(UCOMISS),
+ /*2119*/ uint16(xReadSlashR),
+ /*2120*/ uint16(xArgXmm1),
+ /*2121*/ uint16(xArgXmm2M32),
+ /*2122*/ uint16(xMatch),
+ /*2123*/ uint16(xSetOp), uint16(UCOMISD),
+ /*2125*/ uint16(xReadSlashR),
+ /*2126*/ uint16(xArgXmm1),
+ /*2127*/ uint16(xArgXmm2M64),
+ /*2128*/ uint16(xMatch),
+ /*2129*/ uint16(xCondPrefix), 2,
+ 0x66, 2141,
+ 0x0, 2135,
+ /*2135*/ uint16(xSetOp), uint16(COMISS),
+ /*2137*/ uint16(xReadSlashR),
+ /*2138*/ uint16(xArgXmm1),
+ /*2139*/ uint16(xArgXmm2M32),
+ /*2140*/ uint16(xMatch),
+ /*2141*/ uint16(xSetOp), uint16(COMISD),
+ /*2143*/ uint16(xReadSlashR),
+ /*2144*/ uint16(xArgXmm1),
+ /*2145*/ uint16(xArgXmm2M64),
+ /*2146*/ uint16(xMatch),
+ /*2147*/ uint16(xSetOp), uint16(WRMSR),
+ /*2149*/ uint16(xMatch),
+ /*2150*/ uint16(xSetOp), uint16(RDTSC),
+ /*2152*/ uint16(xMatch),
+ /*2153*/ uint16(xSetOp), uint16(RDMSR),
+ /*2155*/ uint16(xMatch),
+ /*2156*/ uint16(xSetOp), uint16(RDPMC),
+ /*2158*/ uint16(xMatch),
+ /*2159*/ uint16(xSetOp), uint16(SYSENTER),
+ /*2161*/ uint16(xMatch),
+ /*2162*/ uint16(xCondDataSize), 2166, 2166, 2169,
+ /*2166*/ uint16(xSetOp), uint16(SYSEXIT),
+ /*2168*/ uint16(xMatch),
+ /*2169*/ uint16(xSetOp), uint16(SYSEXIT),
+ /*2171*/ uint16(xMatch),
+ /*2172*/ uint16(xCondByte), 54,
+ 0x00, 2283,
+ 0x01, 2301,
+ 0x02, 2319,
+ 0x03, 2337,
+ 0x04, 2355,
+ 0x05, 2373,
+ 0x06, 2391,
+ 0x07, 2409,
+ 0x08, 2427,
+ 0x09, 2445,
+ 0x0A, 2463,
+ 0x0B, 2481,
+ 0x10, 2499,
+ 0x14, 2510,
+ 0x15, 2521,
+ 0x17, 2532,
+ 0x1C, 2542,
+ 0x1D, 2560,
+ 0x1E, 2578,
+ 0x20, 2596,
+ 0x21, 2606,
+ 0x22, 2616,
+ 0x23, 2626,
+ 0x24, 2636,
+ 0x25, 2646,
+ 0x28, 2656,
+ 0x29, 2666,
+ 0x2A, 2676,
+ 0x2B, 2686,
+ 0x30, 2696,
+ 0x31, 2706,
+ 0x32, 2716,
+ 0x33, 2726,
+ 0x34, 2736,
+ 0x35, 2746,
+ 0x37, 2756,
+ 0x38, 2766,
+ 0x39, 2776,
+ 0x3A, 2786,
+ 0x3B, 2796,
+ 0x3C, 2806,
+ 0x3D, 2816,
+ 0x3E, 2826,
+ 0x3F, 2836,
+ 0x40, 2846,
+ 0x41, 2856,
+ 0x82, 2866,
+ 0xDB, 2889,
+ 0xDC, 2899,
+ 0xDD, 2909,
+ 0xDE, 2919,
+ 0xDF, 2929,
+ 0xF0, 2939,
+ 0xF1, 3006,
+ uint16(xFail),
+ /*2283*/ uint16(xCondPrefix), 2,
+ 0x66, 2295,
+ 0x0, 2289,
+ /*2289*/ uint16(xSetOp), uint16(PSHUFB),
+ /*2291*/ uint16(xReadSlashR),
+ /*2292*/ uint16(xArgMm1),
+ /*2293*/ uint16(xArgMm2M64),
+ /*2294*/ uint16(xMatch),
+ /*2295*/ uint16(xSetOp), uint16(PSHUFB),
+ /*2297*/ uint16(xReadSlashR),
+ /*2298*/ uint16(xArgXmm1),
+ /*2299*/ uint16(xArgXmm2M128),
+ /*2300*/ uint16(xMatch),
+ /*2301*/ uint16(xCondPrefix), 2,
+ 0x66, 2313,
+ 0x0, 2307,
+ /*2307*/ uint16(xSetOp), uint16(PHADDW),
+ /*2309*/ uint16(xReadSlashR),
+ /*2310*/ uint16(xArgMm1),
+ /*2311*/ uint16(xArgMm2M64),
+ /*2312*/ uint16(xMatch),
+ /*2313*/ uint16(xSetOp), uint16(PHADDW),
+ /*2315*/ uint16(xReadSlashR),
+ /*2316*/ uint16(xArgXmm1),
+ /*2317*/ uint16(xArgXmm2M128),
+ /*2318*/ uint16(xMatch),
+ /*2319*/ uint16(xCondPrefix), 2,
+ 0x66, 2331,
+ 0x0, 2325,
+ /*2325*/ uint16(xSetOp), uint16(PHADDD),
+ /*2327*/ uint16(xReadSlashR),
+ /*2328*/ uint16(xArgMm1),
+ /*2329*/ uint16(xArgMm2M64),
+ /*2330*/ uint16(xMatch),
+ /*2331*/ uint16(xSetOp), uint16(PHADDD),
+ /*2333*/ uint16(xReadSlashR),
+ /*2334*/ uint16(xArgXmm1),
+ /*2335*/ uint16(xArgXmm2M128),
+ /*2336*/ uint16(xMatch),
+ /*2337*/ uint16(xCondPrefix), 2,
+ 0x66, 2349,
+ 0x0, 2343,
+ /*2343*/ uint16(xSetOp), uint16(PHADDSW),
+ /*2345*/ uint16(xReadSlashR),
+ /*2346*/ uint16(xArgMm1),
+ /*2347*/ uint16(xArgMm2M64),
+ /*2348*/ uint16(xMatch),
+ /*2349*/ uint16(xSetOp), uint16(PHADDSW),
+ /*2351*/ uint16(xReadSlashR),
+ /*2352*/ uint16(xArgXmm1),
+ /*2353*/ uint16(xArgXmm2M128),
+ /*2354*/ uint16(xMatch),
+ /*2355*/ uint16(xCondPrefix), 2,
+ 0x66, 2367,
+ 0x0, 2361,
+ /*2361*/ uint16(xSetOp), uint16(PMADDUBSW),
+ /*2363*/ uint16(xReadSlashR),
+ /*2364*/ uint16(xArgMm1),
+ /*2365*/ uint16(xArgMm2M64),
+ /*2366*/ uint16(xMatch),
+ /*2367*/ uint16(xSetOp), uint16(PMADDUBSW),
+ /*2369*/ uint16(xReadSlashR),
+ /*2370*/ uint16(xArgXmm1),
+ /*2371*/ uint16(xArgXmm2M128),
+ /*2372*/ uint16(xMatch),
+ /*2373*/ uint16(xCondPrefix), 2,
+ 0x66, 2385,
+ 0x0, 2379,
+ /*2379*/ uint16(xSetOp), uint16(PHSUBW),
+ /*2381*/ uint16(xReadSlashR),
+ /*2382*/ uint16(xArgMm1),
+ /*2383*/ uint16(xArgMm2M64),
+ /*2384*/ uint16(xMatch),
+ /*2385*/ uint16(xSetOp), uint16(PHSUBW),
+ /*2387*/ uint16(xReadSlashR),
+ /*2388*/ uint16(xArgXmm1),
+ /*2389*/ uint16(xArgXmm2M128),
+ /*2390*/ uint16(xMatch),
+ /*2391*/ uint16(xCondPrefix), 2,
+ 0x66, 2403,
+ 0x0, 2397,
+ /*2397*/ uint16(xSetOp), uint16(PHSUBD),
+ /*2399*/ uint16(xReadSlashR),
+ /*2400*/ uint16(xArgMm1),
+ /*2401*/ uint16(xArgMm2M64),
+ /*2402*/ uint16(xMatch),
+ /*2403*/ uint16(xSetOp), uint16(PHSUBD),
+ /*2405*/ uint16(xReadSlashR),
+ /*2406*/ uint16(xArgXmm1),
+ /*2407*/ uint16(xArgXmm2M128),
+ /*2408*/ uint16(xMatch),
+ /*2409*/ uint16(xCondPrefix), 2,
+ 0x66, 2421,
+ 0x0, 2415,
+ /*2415*/ uint16(xSetOp), uint16(PHSUBSW),
+ /*2417*/ uint16(xReadSlashR),
+ /*2418*/ uint16(xArgMm1),
+ /*2419*/ uint16(xArgMm2M64),
+ /*2420*/ uint16(xMatch),
+ /*2421*/ uint16(xSetOp), uint16(PHSUBSW),
+ /*2423*/ uint16(xReadSlashR),
+ /*2424*/ uint16(xArgXmm1),
+ /*2425*/ uint16(xArgXmm2M128),
+ /*2426*/ uint16(xMatch),
+ /*2427*/ uint16(xCondPrefix), 2,
+ 0x66, 2439,
+ 0x0, 2433,
+ /*2433*/ uint16(xSetOp), uint16(PSIGNB),
+ /*2435*/ uint16(xReadSlashR),
+ /*2436*/ uint16(xArgMm1),
+ /*2437*/ uint16(xArgMm2M64),
+ /*2438*/ uint16(xMatch),
+ /*2439*/ uint16(xSetOp), uint16(PSIGNB),
+ /*2441*/ uint16(xReadSlashR),
+ /*2442*/ uint16(xArgXmm1),
+ /*2443*/ uint16(xArgXmm2M128),
+ /*2444*/ uint16(xMatch),
+ /*2445*/ uint16(xCondPrefix), 2,
+ 0x66, 2457,
+ 0x0, 2451,
+ /*2451*/ uint16(xSetOp), uint16(PSIGNW),
+ /*2453*/ uint16(xReadSlashR),
+ /*2454*/ uint16(xArgMm1),
+ /*2455*/ uint16(xArgMm2M64),
+ /*2456*/ uint16(xMatch),
+ /*2457*/ uint16(xSetOp), uint16(PSIGNW),
+ /*2459*/ uint16(xReadSlashR),
+ /*2460*/ uint16(xArgXmm1),
+ /*2461*/ uint16(xArgXmm2M128),
+ /*2462*/ uint16(xMatch),
+ /*2463*/ uint16(xCondPrefix), 2,
+ 0x66, 2475,
+ 0x0, 2469,
+ /*2469*/ uint16(xSetOp), uint16(PSIGND),
+ /*2471*/ uint16(xReadSlashR),
+ /*2472*/ uint16(xArgMm1),
+ /*2473*/ uint16(xArgMm2M64),
+ /*2474*/ uint16(xMatch),
+ /*2475*/ uint16(xSetOp), uint16(PSIGND),
+ /*2477*/ uint16(xReadSlashR),
+ /*2478*/ uint16(xArgXmm1),
+ /*2479*/ uint16(xArgXmm2M128),
+ /*2480*/ uint16(xMatch),
+ /*2481*/ uint16(xCondPrefix), 2,
+ 0x66, 2493,
+ 0x0, 2487,
+ /*2487*/ uint16(xSetOp), uint16(PMULHRSW),
+ /*2489*/ uint16(xReadSlashR),
+ /*2490*/ uint16(xArgMm1),
+ /*2491*/ uint16(xArgMm2M64),
+ /*2492*/ uint16(xMatch),
+ /*2493*/ uint16(xSetOp), uint16(PMULHRSW),
+ /*2495*/ uint16(xReadSlashR),
+ /*2496*/ uint16(xArgXmm1),
+ /*2497*/ uint16(xArgXmm2M128),
+ /*2498*/ uint16(xMatch),
+ /*2499*/ uint16(xCondPrefix), 1,
+ 0x66, 2503,
+ /*2503*/ uint16(xSetOp), uint16(PBLENDVB),
+ /*2505*/ uint16(xReadSlashR),
+ /*2506*/ uint16(xArgXmm1),
+ /*2507*/ uint16(xArgXmm2M128),
+ /*2508*/ uint16(xArgXMM0),
+ /*2509*/ uint16(xMatch),
+ /*2510*/ uint16(xCondPrefix), 1,
+ 0x66, 2514,
+ /*2514*/ uint16(xSetOp), uint16(BLENDVPS),
+ /*2516*/ uint16(xReadSlashR),
+ /*2517*/ uint16(xArgXmm1),
+ /*2518*/ uint16(xArgXmm2M128),
+ /*2519*/ uint16(xArgXMM0),
+ /*2520*/ uint16(xMatch),
+ /*2521*/ uint16(xCondPrefix), 1,
+ 0x66, 2525,
+ /*2525*/ uint16(xSetOp), uint16(BLENDVPD),
+ /*2527*/ uint16(xReadSlashR),
+ /*2528*/ uint16(xArgXmm1),
+ /*2529*/ uint16(xArgXmm2M128),
+ /*2530*/ uint16(xArgXMM0),
+ /*2531*/ uint16(xMatch),
+ /*2532*/ uint16(xCondPrefix), 1,
+ 0x66, 2536,
+ /*2536*/ uint16(xSetOp), uint16(PTEST),
+ /*2538*/ uint16(xReadSlashR),
+ /*2539*/ uint16(xArgXmm1),
+ /*2540*/ uint16(xArgXmm2M128),
+ /*2541*/ uint16(xMatch),
+ /*2542*/ uint16(xCondPrefix), 2,
+ 0x66, 2554,
+ 0x0, 2548,
+ /*2548*/ uint16(xSetOp), uint16(PABSB),
+ /*2550*/ uint16(xReadSlashR),
+ /*2551*/ uint16(xArgMm1),
+ /*2552*/ uint16(xArgMm2M64),
+ /*2553*/ uint16(xMatch),
+ /*2554*/ uint16(xSetOp), uint16(PABSB),
+ /*2556*/ uint16(xReadSlashR),
+ /*2557*/ uint16(xArgXmm1),
+ /*2558*/ uint16(xArgXmm2M128),
+ /*2559*/ uint16(xMatch),
+ /*2560*/ uint16(xCondPrefix), 2,
+ 0x66, 2572,
+ 0x0, 2566,
+ /*2566*/ uint16(xSetOp), uint16(PABSW),
+ /*2568*/ uint16(xReadSlashR),
+ /*2569*/ uint16(xArgMm1),
+ /*2570*/ uint16(xArgMm2M64),
+ /*2571*/ uint16(xMatch),
+ /*2572*/ uint16(xSetOp), uint16(PABSW),
+ /*2574*/ uint16(xReadSlashR),
+ /*2575*/ uint16(xArgXmm1),
+ /*2576*/ uint16(xArgXmm2M128),
+ /*2577*/ uint16(xMatch),
+ /*2578*/ uint16(xCondPrefix), 2,
+ 0x66, 2590,
+ 0x0, 2584,
+ /*2584*/ uint16(xSetOp), uint16(PABSD),
+ /*2586*/ uint16(xReadSlashR),
+ /*2587*/ uint16(xArgMm1),
+ /*2588*/ uint16(xArgMm2M64),
+ /*2589*/ uint16(xMatch),
+ /*2590*/ uint16(xSetOp), uint16(PABSD),
+ /*2592*/ uint16(xReadSlashR),
+ /*2593*/ uint16(xArgXmm1),
+ /*2594*/ uint16(xArgXmm2M128),
+ /*2595*/ uint16(xMatch),
+ /*2596*/ uint16(xCondPrefix), 1,
+ 0x66, 2600,
+ /*2600*/ uint16(xSetOp), uint16(PMOVSXBW),
+ /*2602*/ uint16(xReadSlashR),
+ /*2603*/ uint16(xArgXmm1),
+ /*2604*/ uint16(xArgXmm2M64),
+ /*2605*/ uint16(xMatch),
+ /*2606*/ uint16(xCondPrefix), 1,
+ 0x66, 2610,
+ /*2610*/ uint16(xSetOp), uint16(PMOVSXBD),
+ /*2612*/ uint16(xReadSlashR),
+ /*2613*/ uint16(xArgXmm1),
+ /*2614*/ uint16(xArgXmm2M32),
+ /*2615*/ uint16(xMatch),
+ /*2616*/ uint16(xCondPrefix), 1,
+ 0x66, 2620,
+ /*2620*/ uint16(xSetOp), uint16(PMOVSXBQ),
+ /*2622*/ uint16(xReadSlashR),
+ /*2623*/ uint16(xArgXmm1),
+ /*2624*/ uint16(xArgXmm2M16),
+ /*2625*/ uint16(xMatch),
+ /*2626*/ uint16(xCondPrefix), 1,
+ 0x66, 2630,
+ /*2630*/ uint16(xSetOp), uint16(PMOVSXWD),
+ /*2632*/ uint16(xReadSlashR),
+ /*2633*/ uint16(xArgXmm1),
+ /*2634*/ uint16(xArgXmm2M64),
+ /*2635*/ uint16(xMatch),
+ /*2636*/ uint16(xCondPrefix), 1,
+ 0x66, 2640,
+ /*2640*/ uint16(xSetOp), uint16(PMOVSXWQ),
+ /*2642*/ uint16(xReadSlashR),
+ /*2643*/ uint16(xArgXmm1),
+ /*2644*/ uint16(xArgXmm2M32),
+ /*2645*/ uint16(xMatch),
+ /*2646*/ uint16(xCondPrefix), 1,
+ 0x66, 2650,
+ /*2650*/ uint16(xSetOp), uint16(PMOVSXDQ),
+ /*2652*/ uint16(xReadSlashR),
+ /*2653*/ uint16(xArgXmm1),
+ /*2654*/ uint16(xArgXmm2M64),
+ /*2655*/ uint16(xMatch),
+ /*2656*/ uint16(xCondPrefix), 1,
+ 0x66, 2660,
+ /*2660*/ uint16(xSetOp), uint16(PMULDQ),
+ /*2662*/ uint16(xReadSlashR),
+ /*2663*/ uint16(xArgXmm1),
+ /*2664*/ uint16(xArgXmm2M128),
+ /*2665*/ uint16(xMatch),
+ /*2666*/ uint16(xCondPrefix), 1,
+ 0x66, 2670,
+ /*2670*/ uint16(xSetOp), uint16(PCMPEQQ),
+ /*2672*/ uint16(xReadSlashR),
+ /*2673*/ uint16(xArgXmm1),
+ /*2674*/ uint16(xArgXmm2M128),
+ /*2675*/ uint16(xMatch),
+ /*2676*/ uint16(xCondPrefix), 1,
+ 0x66, 2680,
+ /*2680*/ uint16(xSetOp), uint16(MOVNTDQA),
+ /*2682*/ uint16(xReadSlashR),
+ /*2683*/ uint16(xArgXmm1),
+ /*2684*/ uint16(xArgM128),
+ /*2685*/ uint16(xMatch),
+ /*2686*/ uint16(xCondPrefix), 1,
+ 0x66, 2690,
+ /*2690*/ uint16(xSetOp), uint16(PACKUSDW),
+ /*2692*/ uint16(xReadSlashR),
+ /*2693*/ uint16(xArgXmm1),
+ /*2694*/ uint16(xArgXmm2M128),
+ /*2695*/ uint16(xMatch),
+ /*2696*/ uint16(xCondPrefix), 1,
+ 0x66, 2700,
+ /*2700*/ uint16(xSetOp), uint16(PMOVZXBW),
+ /*2702*/ uint16(xReadSlashR),
+ /*2703*/ uint16(xArgXmm1),
+ /*2704*/ uint16(xArgXmm2M64),
+ /*2705*/ uint16(xMatch),
+ /*2706*/ uint16(xCondPrefix), 1,
+ 0x66, 2710,
+ /*2710*/ uint16(xSetOp), uint16(PMOVZXBD),
+ /*2712*/ uint16(xReadSlashR),
+ /*2713*/ uint16(xArgXmm1),
+ /*2714*/ uint16(xArgXmm2M32),
+ /*2715*/ uint16(xMatch),
+ /*2716*/ uint16(xCondPrefix), 1,
+ 0x66, 2720,
+ /*2720*/ uint16(xSetOp), uint16(PMOVZXBQ),
+ /*2722*/ uint16(xReadSlashR),
+ /*2723*/ uint16(xArgXmm1),
+ /*2724*/ uint16(xArgXmm2M16),
+ /*2725*/ uint16(xMatch),
+ /*2726*/ uint16(xCondPrefix), 1,
+ 0x66, 2730,
+ /*2730*/ uint16(xSetOp), uint16(PMOVZXWD),
+ /*2732*/ uint16(xReadSlashR),
+ /*2733*/ uint16(xArgXmm1),
+ /*2734*/ uint16(xArgXmm2M64),
+ /*2735*/ uint16(xMatch),
+ /*2736*/ uint16(xCondPrefix), 1,
+ 0x66, 2740,
+ /*2740*/ uint16(xSetOp), uint16(PMOVZXWQ),
+ /*2742*/ uint16(xReadSlashR),
+ /*2743*/ uint16(xArgXmm1),
+ /*2744*/ uint16(xArgXmm2M32),
+ /*2745*/ uint16(xMatch),
+ /*2746*/ uint16(xCondPrefix), 1,
+ 0x66, 2750,
+ /*2750*/ uint16(xSetOp), uint16(PMOVZXDQ),
+ /*2752*/ uint16(xReadSlashR),
+ /*2753*/ uint16(xArgXmm1),
+ /*2754*/ uint16(xArgXmm2M64),
+ /*2755*/ uint16(xMatch),
+ /*2756*/ uint16(xCondPrefix), 1,
+ 0x66, 2760,
+ /*2760*/ uint16(xSetOp), uint16(PCMPGTQ),
+ /*2762*/ uint16(xReadSlashR),
+ /*2763*/ uint16(xArgXmm1),
+ /*2764*/ uint16(xArgXmm2M128),
+ /*2765*/ uint16(xMatch),
+ /*2766*/ uint16(xCondPrefix), 1,
+ 0x66, 2770,
+ /*2770*/ uint16(xSetOp), uint16(PMINSB),
+ /*2772*/ uint16(xReadSlashR),
+ /*2773*/ uint16(xArgXmm1),
+ /*2774*/ uint16(xArgXmm2M128),
+ /*2775*/ uint16(xMatch),
+ /*2776*/ uint16(xCondPrefix), 1,
+ 0x66, 2780,
+ /*2780*/ uint16(xSetOp), uint16(PMINSD),
+ /*2782*/ uint16(xReadSlashR),
+ /*2783*/ uint16(xArgXmm1),
+ /*2784*/ uint16(xArgXmm2M128),
+ /*2785*/ uint16(xMatch),
+ /*2786*/ uint16(xCondPrefix), 1,
+ 0x66, 2790,
+ /*2790*/ uint16(xSetOp), uint16(PMINUW),
+ /*2792*/ uint16(xReadSlashR),
+ /*2793*/ uint16(xArgXmm1),
+ /*2794*/ uint16(xArgXmm2M128),
+ /*2795*/ uint16(xMatch),
+ /*2796*/ uint16(xCondPrefix), 1,
+ 0x66, 2800,
+ /*2800*/ uint16(xSetOp), uint16(PMINUD),
+ /*2802*/ uint16(xReadSlashR),
+ /*2803*/ uint16(xArgXmm1),
+ /*2804*/ uint16(xArgXmm2M128),
+ /*2805*/ uint16(xMatch),
+ /*2806*/ uint16(xCondPrefix), 1,
+ 0x66, 2810,
+ /*2810*/ uint16(xSetOp), uint16(PMAXSB),
+ /*2812*/ uint16(xReadSlashR),
+ /*2813*/ uint16(xArgXmm1),
+ /*2814*/ uint16(xArgXmm2M128),
+ /*2815*/ uint16(xMatch),
+ /*2816*/ uint16(xCondPrefix), 1,
+ 0x66, 2820,
+ /*2820*/ uint16(xSetOp), uint16(PMAXSD),
+ /*2822*/ uint16(xReadSlashR),
+ /*2823*/ uint16(xArgXmm1),
+ /*2824*/ uint16(xArgXmm2M128),
+ /*2825*/ uint16(xMatch),
+ /*2826*/ uint16(xCondPrefix), 1,
+ 0x66, 2830,
+ /*2830*/ uint16(xSetOp), uint16(PMAXUW),
+ /*2832*/ uint16(xReadSlashR),
+ /*2833*/ uint16(xArgXmm1),
+ /*2834*/ uint16(xArgXmm2M128),
+ /*2835*/ uint16(xMatch),
+ /*2836*/ uint16(xCondPrefix), 1,
+ 0x66, 2840,
+ /*2840*/ uint16(xSetOp), uint16(PMAXUD),
+ /*2842*/ uint16(xReadSlashR),
+ /*2843*/ uint16(xArgXmm1),
+ /*2844*/ uint16(xArgXmm2M128),
+ /*2845*/ uint16(xMatch),
+ /*2846*/ uint16(xCondPrefix), 1,
+ 0x66, 2850,
+ /*2850*/ uint16(xSetOp), uint16(PMULLD),
+ /*2852*/ uint16(xReadSlashR),
+ /*2853*/ uint16(xArgXmm1),
+ /*2854*/ uint16(xArgXmm2M128),
+ /*2855*/ uint16(xMatch),
+ /*2856*/ uint16(xCondPrefix), 1,
+ 0x66, 2860,
+ /*2860*/ uint16(xSetOp), uint16(PHMINPOSUW),
+ /*2862*/ uint16(xReadSlashR),
+ /*2863*/ uint16(xArgXmm1),
+ /*2864*/ uint16(xArgXmm2M128),
+ /*2865*/ uint16(xMatch),
+ /*2866*/ uint16(xCondIs64), 2869, 2879,
+ /*2869*/ uint16(xCondPrefix), 1,
+ 0x66, 2873,
+ /*2873*/ uint16(xSetOp), uint16(INVPCID),
+ /*2875*/ uint16(xReadSlashR),
+ /*2876*/ uint16(xArgR32),
+ /*2877*/ uint16(xArgM128),
+ /*2878*/ uint16(xMatch),
+ /*2879*/ uint16(xCondPrefix), 1,
+ 0x66, 2883,
+ /*2883*/ uint16(xSetOp), uint16(INVPCID),
+ /*2885*/ uint16(xReadSlashR),
+ /*2886*/ uint16(xArgR64),
+ /*2887*/ uint16(xArgM128),
+ /*2888*/ uint16(xMatch),
+ /*2889*/ uint16(xCondPrefix), 1,
+ 0x66, 2893,
+ /*2893*/ uint16(xSetOp), uint16(AESIMC),
+ /*2895*/ uint16(xReadSlashR),
+ /*2896*/ uint16(xArgXmm1),
+ /*2897*/ uint16(xArgXmm2M128),
+ /*2898*/ uint16(xMatch),
+ /*2899*/ uint16(xCondPrefix), 1,
+ 0x66, 2903,
+ /*2903*/ uint16(xSetOp), uint16(AESENC),
+ /*2905*/ uint16(xReadSlashR),
+ /*2906*/ uint16(xArgXmm1),
+ /*2907*/ uint16(xArgXmm2M128),
+ /*2908*/ uint16(xMatch),
+ /*2909*/ uint16(xCondPrefix), 1,
+ 0x66, 2913,
+ /*2913*/ uint16(xSetOp), uint16(AESENCLAST),
+ /*2915*/ uint16(xReadSlashR),
+ /*2916*/ uint16(xArgXmm1),
+ /*2917*/ uint16(xArgXmm2M128),
+ /*2918*/ uint16(xMatch),
+ /*2919*/ uint16(xCondPrefix), 1,
+ 0x66, 2923,
+ /*2923*/ uint16(xSetOp), uint16(AESDEC),
+ /*2925*/ uint16(xReadSlashR),
+ /*2926*/ uint16(xArgXmm1),
+ /*2927*/ uint16(xArgXmm2M128),
+ /*2928*/ uint16(xMatch),
+ /*2929*/ uint16(xCondPrefix), 1,
+ 0x66, 2933,
+ /*2933*/ uint16(xSetOp), uint16(AESDECLAST),
+ /*2935*/ uint16(xReadSlashR),
+ /*2936*/ uint16(xArgXmm1),
+ /*2937*/ uint16(xArgXmm2M128),
+ /*2938*/ uint16(xMatch),
+ /*2939*/ uint16(xCondIs64), 2942, 2980,
+ /*2942*/ uint16(xCondPrefix), 2,
+ 0xF2, 2964,
+ 0x0, 2948,
+ /*2948*/ uint16(xCondDataSize), 2952, 2958, 0,
+ /*2952*/ uint16(xSetOp), uint16(MOVBE),
+ /*2954*/ uint16(xReadSlashR),
+ /*2955*/ uint16(xArgR16),
+ /*2956*/ uint16(xArgM16),
+ /*2957*/ uint16(xMatch),
+ /*2958*/ uint16(xSetOp), uint16(MOVBE),
+ /*2960*/ uint16(xReadSlashR),
+ /*2961*/ uint16(xArgR32),
+ /*2962*/ uint16(xArgM32),
+ /*2963*/ uint16(xMatch),
+ /*2964*/ uint16(xCondDataSize), 2968, 2974, 0,
+ /*2968*/ uint16(xSetOp), uint16(CRC32),
+ /*2970*/ uint16(xReadSlashR),
+ /*2971*/ uint16(xArgR32),
+ /*2972*/ uint16(xArgRM8),
+ /*2973*/ uint16(xMatch),
+ /*2974*/ uint16(xSetOp), uint16(CRC32),
+ /*2976*/ uint16(xReadSlashR),
+ /*2977*/ uint16(xArgR32),
+ /*2978*/ uint16(xArgRM8),
+ /*2979*/ uint16(xMatch),
+ /*2980*/ uint16(xCondPrefix), 2,
+ 0xF2, 2996,
+ 0x0, 2986,
+ /*2986*/ uint16(xCondDataSize), 2952, 2958, 2990,
+ /*2990*/ uint16(xSetOp), uint16(MOVBE),
+ /*2992*/ uint16(xReadSlashR),
+ /*2993*/ uint16(xArgR64),
+ /*2994*/ uint16(xArgM64),
+ /*2995*/ uint16(xMatch),
+ /*2996*/ uint16(xCondDataSize), 2968, 2974, 3000,
+ /*3000*/ uint16(xSetOp), uint16(CRC32),
+ /*3002*/ uint16(xReadSlashR),
+ /*3003*/ uint16(xArgR64),
+ /*3004*/ uint16(xArgRM8),
+ /*3005*/ uint16(xMatch),
+ /*3006*/ uint16(xCondIs64), 3009, 3047,
+ /*3009*/ uint16(xCondPrefix), 2,
+ 0xF2, 3031,
+ 0x0, 3015,
+ /*3015*/ uint16(xCondDataSize), 3019, 3025, 0,
+ /*3019*/ uint16(xSetOp), uint16(MOVBE),
+ /*3021*/ uint16(xReadSlashR),
+ /*3022*/ uint16(xArgM16),
+ /*3023*/ uint16(xArgR16),
+ /*3024*/ uint16(xMatch),
+ /*3025*/ uint16(xSetOp), uint16(MOVBE),
+ /*3027*/ uint16(xReadSlashR),
+ /*3028*/ uint16(xArgM32),
+ /*3029*/ uint16(xArgR32),
+ /*3030*/ uint16(xMatch),
+ /*3031*/ uint16(xCondDataSize), 3035, 3041, 0,
+ /*3035*/ uint16(xSetOp), uint16(CRC32),
+ /*3037*/ uint16(xReadSlashR),
+ /*3038*/ uint16(xArgR32),
+ /*3039*/ uint16(xArgRM16),
+ /*3040*/ uint16(xMatch),
+ /*3041*/ uint16(xSetOp), uint16(CRC32),
+ /*3043*/ uint16(xReadSlashR),
+ /*3044*/ uint16(xArgR32),
+ /*3045*/ uint16(xArgRM32),
+ /*3046*/ uint16(xMatch),
+ /*3047*/ uint16(xCondPrefix), 2,
+ 0xF2, 3063,
+ 0x0, 3053,
+ /*3053*/ uint16(xCondDataSize), 3019, 3025, 3057,
+ /*3057*/ uint16(xSetOp), uint16(MOVBE),
+ /*3059*/ uint16(xReadSlashR),
+ /*3060*/ uint16(xArgM64),
+ /*3061*/ uint16(xArgR64),
+ /*3062*/ uint16(xMatch),
+ /*3063*/ uint16(xCondDataSize), 3035, 3041, 3067,
+ /*3067*/ uint16(xSetOp), uint16(CRC32),
+ /*3069*/ uint16(xReadSlashR),
+ /*3070*/ uint16(xArgR64),
+ /*3071*/ uint16(xArgRM64),
+ /*3072*/ uint16(xMatch),
+ /*3073*/ uint16(xCondByte), 24,
+ 0x08, 3124,
+ 0x09, 3136,
+ 0x0A, 3148,
+ 0x0B, 3160,
+ 0x0C, 3172,
+ 0x0D, 3184,
+ 0x0E, 3196,
+ 0x0F, 3208,
+ 0x14, 3230,
+ 0x15, 3242,
+ 0x16, 3254,
+ 0x17, 3297,
+ 0x20, 3309,
+ 0x21, 3321,
+ 0x22, 3333,
+ 0x40, 3376,
+ 0x41, 3388,
+ 0x42, 3400,
+ 0x44, 3412,
+ 0x60, 3424,
+ 0x61, 3436,
+ 0x62, 3448,
+ 0x63, 3460,
+ 0xDF, 3472,
+ uint16(xFail),
+ /*3124*/ uint16(xCondPrefix), 1,
+ 0x66, 3128,
+ /*3128*/ uint16(xSetOp), uint16(ROUNDPS),
+ /*3130*/ uint16(xReadSlashR),
+ /*3131*/ uint16(xReadIb),
+ /*3132*/ uint16(xArgXmm1),
+ /*3133*/ uint16(xArgXmm2M128),
+ /*3134*/ uint16(xArgImm8u),
+ /*3135*/ uint16(xMatch),
+ /*3136*/ uint16(xCondPrefix), 1,
+ 0x66, 3140,
+ /*3140*/ uint16(xSetOp), uint16(ROUNDPD),
+ /*3142*/ uint16(xReadSlashR),
+ /*3143*/ uint16(xReadIb),
+ /*3144*/ uint16(xArgXmm1),
+ /*3145*/ uint16(xArgXmm2M128),
+ /*3146*/ uint16(xArgImm8u),
+ /*3147*/ uint16(xMatch),
+ /*3148*/ uint16(xCondPrefix), 1,
+ 0x66, 3152,
+ /*3152*/ uint16(xSetOp), uint16(ROUNDSS),
+ /*3154*/ uint16(xReadSlashR),
+ /*3155*/ uint16(xReadIb),
+ /*3156*/ uint16(xArgXmm1),
+ /*3157*/ uint16(xArgXmm2M32),
+ /*3158*/ uint16(xArgImm8u),
+ /*3159*/ uint16(xMatch),
+ /*3160*/ uint16(xCondPrefix), 1,
+ 0x66, 3164,
+ /*3164*/ uint16(xSetOp), uint16(ROUNDSD),
+ /*3166*/ uint16(xReadSlashR),
+ /*3167*/ uint16(xReadIb),
+ /*3168*/ uint16(xArgXmm1),
+ /*3169*/ uint16(xArgXmm2M64),
+ /*3170*/ uint16(xArgImm8u),
+ /*3171*/ uint16(xMatch),
+ /*3172*/ uint16(xCondPrefix), 1,
+ 0x66, 3176,
+ /*3176*/ uint16(xSetOp), uint16(BLENDPS),
+ /*3178*/ uint16(xReadSlashR),
+ /*3179*/ uint16(xReadIb),
+ /*3180*/ uint16(xArgXmm1),
+ /*3181*/ uint16(xArgXmm2M128),
+ /*3182*/ uint16(xArgImm8u),
+ /*3183*/ uint16(xMatch),
+ /*3184*/ uint16(xCondPrefix), 1,
+ 0x66, 3188,
+ /*3188*/ uint16(xSetOp), uint16(BLENDPD),
+ /*3190*/ uint16(xReadSlashR),
+ /*3191*/ uint16(xReadIb),
+ /*3192*/ uint16(xArgXmm1),
+ /*3193*/ uint16(xArgXmm2M128),
+ /*3194*/ uint16(xArgImm8u),
+ /*3195*/ uint16(xMatch),
+ /*3196*/ uint16(xCondPrefix), 1,
+ 0x66, 3200,
+ /*3200*/ uint16(xSetOp), uint16(PBLENDW),
+ /*3202*/ uint16(xReadSlashR),
+ /*3203*/ uint16(xReadIb),
+ /*3204*/ uint16(xArgXmm1),
+ /*3205*/ uint16(xArgXmm2M128),
+ /*3206*/ uint16(xArgImm8u),
+ /*3207*/ uint16(xMatch),
+ /*3208*/ uint16(xCondPrefix), 2,
+ 0x66, 3222,
+ 0x0, 3214,
+ /*3214*/ uint16(xSetOp), uint16(PALIGNR),
+ /*3216*/ uint16(xReadSlashR),
+ /*3217*/ uint16(xReadIb),
+ /*3218*/ uint16(xArgMm1),
+ /*3219*/ uint16(xArgMm2M64),
+ /*3220*/ uint16(xArgImm8u),
+ /*3221*/ uint16(xMatch),
+ /*3222*/ uint16(xSetOp), uint16(PALIGNR),
+ /*3224*/ uint16(xReadSlashR),
+ /*3225*/ uint16(xReadIb),
+ /*3226*/ uint16(xArgXmm1),
+ /*3227*/ uint16(xArgXmm2M128),
+ /*3228*/ uint16(xArgImm8u),
+ /*3229*/ uint16(xMatch),
+ /*3230*/ uint16(xCondPrefix), 1,
+ 0x66, 3234,
+ /*3234*/ uint16(xSetOp), uint16(PEXTRB),
+ /*3236*/ uint16(xReadSlashR),
+ /*3237*/ uint16(xReadIb),
+ /*3238*/ uint16(xArgR32M8),
+ /*3239*/ uint16(xArgXmm1),
+ /*3240*/ uint16(xArgImm8u),
+ /*3241*/ uint16(xMatch),
+ /*3242*/ uint16(xCondPrefix), 1,
+ 0x66, 3246,
+ /*3246*/ uint16(xSetOp), uint16(PEXTRW),
+ /*3248*/ uint16(xReadSlashR),
+ /*3249*/ uint16(xReadIb),
+ /*3250*/ uint16(xArgR32M16),
+ /*3251*/ uint16(xArgXmm1),
+ /*3252*/ uint16(xArgImm8u),
+ /*3253*/ uint16(xMatch),
+ /*3254*/ uint16(xCondIs64), 3257, 3281,
+ /*3257*/ uint16(xCondPrefix), 1,
+ 0x66, 3261,
+ /*3261*/ uint16(xCondDataSize), 3265, 3273, 0,
+ /*3265*/ uint16(xSetOp), uint16(PEXTRD),
+ /*3267*/ uint16(xReadSlashR),
+ /*3268*/ uint16(xReadIb),
+ /*3269*/ uint16(xArgRM32),
+ /*3270*/ uint16(xArgXmm1),
+ /*3271*/ uint16(xArgImm8u),
+ /*3272*/ uint16(xMatch),
+ /*3273*/ uint16(xSetOp), uint16(PEXTRD),
+ /*3275*/ uint16(xReadSlashR),
+ /*3276*/ uint16(xReadIb),
+ /*3277*/ uint16(xArgRM32),
+ /*3278*/ uint16(xArgXmm1),
+ /*3279*/ uint16(xArgImm8u),
+ /*3280*/ uint16(xMatch),
+ /*3281*/ uint16(xCondPrefix), 1,
+ 0x66, 3285,
+ /*3285*/ uint16(xCondDataSize), 3265, 3273, 3289,
+ /*3289*/ uint16(xSetOp), uint16(PEXTRQ),
+ /*3291*/ uint16(xReadSlashR),
+ /*3292*/ uint16(xReadIb),
+ /*3293*/ uint16(xArgRM64),
+ /*3294*/ uint16(xArgXmm1),
+ /*3295*/ uint16(xArgImm8u),
+ /*3296*/ uint16(xMatch),
+ /*3297*/ uint16(xCondPrefix), 1,
+ 0x66, 3301,
+ /*3301*/ uint16(xSetOp), uint16(EXTRACTPS),
+ /*3303*/ uint16(xReadSlashR),
+ /*3304*/ uint16(xReadIb),
+ /*3305*/ uint16(xArgRM32),
+ /*3306*/ uint16(xArgXmm1),
+ /*3307*/ uint16(xArgImm8u),
+ /*3308*/ uint16(xMatch),
+ /*3309*/ uint16(xCondPrefix), 1,
+ 0x66, 3313,
+ /*3313*/ uint16(xSetOp), uint16(PINSRB),
+ /*3315*/ uint16(xReadSlashR),
+ /*3316*/ uint16(xReadIb),
+ /*3317*/ uint16(xArgXmm1),
+ /*3318*/ uint16(xArgR32M8),
+ /*3319*/ uint16(xArgImm8u),
+ /*3320*/ uint16(xMatch),
+ /*3321*/ uint16(xCondPrefix), 1,
+ 0x66, 3325,
+ /*3325*/ uint16(xSetOp), uint16(INSERTPS),
+ /*3327*/ uint16(xReadSlashR),
+ /*3328*/ uint16(xReadIb),
+ /*3329*/ uint16(xArgXmm1),
+ /*3330*/ uint16(xArgXmm2M32),
+ /*3331*/ uint16(xArgImm8u),
+ /*3332*/ uint16(xMatch),
+ /*3333*/ uint16(xCondIs64), 3336, 3360,
+ /*3336*/ uint16(xCondPrefix), 1,
+ 0x66, 3340,
+ /*3340*/ uint16(xCondDataSize), 3344, 3352, 0,
+ /*3344*/ uint16(xSetOp), uint16(PINSRD),
+ /*3346*/ uint16(xReadSlashR),
+ /*3347*/ uint16(xReadIb),
+ /*3348*/ uint16(xArgXmm1),
+ /*3349*/ uint16(xArgRM32),
+ /*3350*/ uint16(xArgImm8u),
+ /*3351*/ uint16(xMatch),
+ /*3352*/ uint16(xSetOp), uint16(PINSRD),
+ /*3354*/ uint16(xReadSlashR),
+ /*3355*/ uint16(xReadIb),
+ /*3356*/ uint16(xArgXmm1),
+ /*3357*/ uint16(xArgRM32),
+ /*3358*/ uint16(xArgImm8u),
+ /*3359*/ uint16(xMatch),
+ /*3360*/ uint16(xCondPrefix), 1,
+ 0x66, 3364,
+ /*3364*/ uint16(xCondDataSize), 3344, 3352, 3368,
+ /*3368*/ uint16(xSetOp), uint16(PINSRQ),
+ /*3370*/ uint16(xReadSlashR),
+ /*3371*/ uint16(xReadIb),
+ /*3372*/ uint16(xArgXmm1),
+ /*3373*/ uint16(xArgRM64),
+ /*3374*/ uint16(xArgImm8u),
+ /*3375*/ uint16(xMatch),
+ /*3376*/ uint16(xCondPrefix), 1,
+ 0x66, 3380,
+ /*3380*/ uint16(xSetOp), uint16(DPPS),
+ /*3382*/ uint16(xReadSlashR),
+ /*3383*/ uint16(xReadIb),
+ /*3384*/ uint16(xArgXmm1),
+ /*3385*/ uint16(xArgXmm2M128),
+ /*3386*/ uint16(xArgImm8u),
+ /*3387*/ uint16(xMatch),
+ /*3388*/ uint16(xCondPrefix), 1,
+ 0x66, 3392,
+ /*3392*/ uint16(xSetOp), uint16(DPPD),
+ /*3394*/ uint16(xReadSlashR),
+ /*3395*/ uint16(xReadIb),
+ /*3396*/ uint16(xArgXmm1),
+ /*3397*/ uint16(xArgXmm2M128),
+ /*3398*/ uint16(xArgImm8u),
+ /*3399*/ uint16(xMatch),
+ /*3400*/ uint16(xCondPrefix), 1,
+ 0x66, 3404,
+ /*3404*/ uint16(xSetOp), uint16(MPSADBW),
+ /*3406*/ uint16(xReadSlashR),
+ /*3407*/ uint16(xReadIb),
+ /*3408*/ uint16(xArgXmm1),
+ /*3409*/ uint16(xArgXmm2M128),
+ /*3410*/ uint16(xArgImm8u),
+ /*3411*/ uint16(xMatch),
+ /*3412*/ uint16(xCondPrefix), 1,
+ 0x66, 3416,
+ /*3416*/ uint16(xSetOp), uint16(PCLMULQDQ),
+ /*3418*/ uint16(xReadSlashR),
+ /*3419*/ uint16(xReadIb),
+ /*3420*/ uint16(xArgXmm1),
+ /*3421*/ uint16(xArgXmm2M128),
+ /*3422*/ uint16(xArgImm8u),
+ /*3423*/ uint16(xMatch),
+ /*3424*/ uint16(xCondPrefix), 1,
+ 0x66, 3428,
+ /*3428*/ uint16(xSetOp), uint16(PCMPESTRM),
+ /*3430*/ uint16(xReadSlashR),
+ /*3431*/ uint16(xReadIb),
+ /*3432*/ uint16(xArgXmm1),
+ /*3433*/ uint16(xArgXmm2M128),
+ /*3434*/ uint16(xArgImm8u),
+ /*3435*/ uint16(xMatch),
+ /*3436*/ uint16(xCondPrefix), 1,
+ 0x66, 3440,
+ /*3440*/ uint16(xSetOp), uint16(PCMPESTRI),
+ /*3442*/ uint16(xReadSlashR),
+ /*3443*/ uint16(xReadIb),
+ /*3444*/ uint16(xArgXmm1),
+ /*3445*/ uint16(xArgXmm2M128),
+ /*3446*/ uint16(xArgImm8u),
+ /*3447*/ uint16(xMatch),
+ /*3448*/ uint16(xCondPrefix), 1,
+ 0x66, 3452,
+ /*3452*/ uint16(xSetOp), uint16(PCMPISTRM),
+ /*3454*/ uint16(xReadSlashR),
+ /*3455*/ uint16(xReadIb),
+ /*3456*/ uint16(xArgXmm1),
+ /*3457*/ uint16(xArgXmm2M128),
+ /*3458*/ uint16(xArgImm8u),
+ /*3459*/ uint16(xMatch),
+ /*3460*/ uint16(xCondPrefix), 1,
+ 0x66, 3464,
+ /*3464*/ uint16(xSetOp), uint16(PCMPISTRI),
+ /*3466*/ uint16(xReadSlashR),
+ /*3467*/ uint16(xReadIb),
+ /*3468*/ uint16(xArgXmm1),
+ /*3469*/ uint16(xArgXmm2M128),
+ /*3470*/ uint16(xArgImm8u),
+ /*3471*/ uint16(xMatch),
+ /*3472*/ uint16(xCondPrefix), 1,
+ 0x66, 3476,
+ /*3476*/ uint16(xSetOp), uint16(AESKEYGENASSIST),
+ /*3478*/ uint16(xReadSlashR),
+ /*3479*/ uint16(xReadIb),
+ /*3480*/ uint16(xArgXmm1),
+ /*3481*/ uint16(xArgXmm2M128),
+ /*3482*/ uint16(xArgImm8u),
+ /*3483*/ uint16(xMatch),
+ /*3484*/ uint16(xCondIs64), 3487, 3503,
+ /*3487*/ uint16(xCondDataSize), 3491, 3497, 0,
+ /*3491*/ uint16(xSetOp), uint16(CMOVO),
+ /*3493*/ uint16(xReadSlashR),
+ /*3494*/ uint16(xArgR16),
+ /*3495*/ uint16(xArgRM16),
+ /*3496*/ uint16(xMatch),
+ /*3497*/ uint16(xSetOp), uint16(CMOVO),
+ /*3499*/ uint16(xReadSlashR),
+ /*3500*/ uint16(xArgR32),
+ /*3501*/ uint16(xArgRM32),
+ /*3502*/ uint16(xMatch),
+ /*3503*/ uint16(xCondDataSize), 3491, 3497, 3507,
+ /*3507*/ uint16(xSetOp), uint16(CMOVO),
+ /*3509*/ uint16(xReadSlashR),
+ /*3510*/ uint16(xArgR64),
+ /*3511*/ uint16(xArgRM64),
+ /*3512*/ uint16(xMatch),
+ /*3513*/ uint16(xCondIs64), 3516, 3532,
+ /*3516*/ uint16(xCondDataSize), 3520, 3526, 0,
+ /*3520*/ uint16(xSetOp), uint16(CMOVNO),
+ /*3522*/ uint16(xReadSlashR),
+ /*3523*/ uint16(xArgR16),
+ /*3524*/ uint16(xArgRM16),
+ /*3525*/ uint16(xMatch),
+ /*3526*/ uint16(xSetOp), uint16(CMOVNO),
+ /*3528*/ uint16(xReadSlashR),
+ /*3529*/ uint16(xArgR32),
+ /*3530*/ uint16(xArgRM32),
+ /*3531*/ uint16(xMatch),
+ /*3532*/ uint16(xCondDataSize), 3520, 3526, 3536,
+ /*3536*/ uint16(xSetOp), uint16(CMOVNO),
+ /*3538*/ uint16(xReadSlashR),
+ /*3539*/ uint16(xArgR64),
+ /*3540*/ uint16(xArgRM64),
+ /*3541*/ uint16(xMatch),
+ /*3542*/ uint16(xCondIs64), 3545, 3561,
+ /*3545*/ uint16(xCondDataSize), 3549, 3555, 0,
+ /*3549*/ uint16(xSetOp), uint16(CMOVB),
+ /*3551*/ uint16(xReadSlashR),
+ /*3552*/ uint16(xArgR16),
+ /*3553*/ uint16(xArgRM16),
+ /*3554*/ uint16(xMatch),
+ /*3555*/ uint16(xSetOp), uint16(CMOVB),
+ /*3557*/ uint16(xReadSlashR),
+ /*3558*/ uint16(xArgR32),
+ /*3559*/ uint16(xArgRM32),
+ /*3560*/ uint16(xMatch),
+ /*3561*/ uint16(xCondDataSize), 3549, 3555, 3565,
+ /*3565*/ uint16(xSetOp), uint16(CMOVB),
+ /*3567*/ uint16(xReadSlashR),
+ /*3568*/ uint16(xArgR64),
+ /*3569*/ uint16(xArgRM64),
+ /*3570*/ uint16(xMatch),
+ /*3571*/ uint16(xCondIs64), 3574, 3590,
+ /*3574*/ uint16(xCondDataSize), 3578, 3584, 0,
+ /*3578*/ uint16(xSetOp), uint16(CMOVAE),
+ /*3580*/ uint16(xReadSlashR),
+ /*3581*/ uint16(xArgR16),
+ /*3582*/ uint16(xArgRM16),
+ /*3583*/ uint16(xMatch),
+ /*3584*/ uint16(xSetOp), uint16(CMOVAE),
+ /*3586*/ uint16(xReadSlashR),
+ /*3587*/ uint16(xArgR32),
+ /*3588*/ uint16(xArgRM32),
+ /*3589*/ uint16(xMatch),
+ /*3590*/ uint16(xCondDataSize), 3578, 3584, 3594,
+ /*3594*/ uint16(xSetOp), uint16(CMOVAE),
+ /*3596*/ uint16(xReadSlashR),
+ /*3597*/ uint16(xArgR64),
+ /*3598*/ uint16(xArgRM64),
+ /*3599*/ uint16(xMatch),
+ /*3600*/ uint16(xCondIs64), 3603, 3619,
+ /*3603*/ uint16(xCondDataSize), 3607, 3613, 0,
+ /*3607*/ uint16(xSetOp), uint16(CMOVE),
+ /*3609*/ uint16(xReadSlashR),
+ /*3610*/ uint16(xArgR16),
+ /*3611*/ uint16(xArgRM16),
+ /*3612*/ uint16(xMatch),
+ /*3613*/ uint16(xSetOp), uint16(CMOVE),
+ /*3615*/ uint16(xReadSlashR),
+ /*3616*/ uint16(xArgR32),
+ /*3617*/ uint16(xArgRM32),
+ /*3618*/ uint16(xMatch),
+ /*3619*/ uint16(xCondDataSize), 3607, 3613, 3623,
+ /*3623*/ uint16(xSetOp), uint16(CMOVE),
+ /*3625*/ uint16(xReadSlashR),
+ /*3626*/ uint16(xArgR64),
+ /*3627*/ uint16(xArgRM64),
+ /*3628*/ uint16(xMatch),
+ /*3629*/ uint16(xCondIs64), 3632, 3648,
+ /*3632*/ uint16(xCondDataSize), 3636, 3642, 0,
+ /*3636*/ uint16(xSetOp), uint16(CMOVNE),
+ /*3638*/ uint16(xReadSlashR),
+ /*3639*/ uint16(xArgR16),
+ /*3640*/ uint16(xArgRM16),
+ /*3641*/ uint16(xMatch),
+ /*3642*/ uint16(xSetOp), uint16(CMOVNE),
+ /*3644*/ uint16(xReadSlashR),
+ /*3645*/ uint16(xArgR32),
+ /*3646*/ uint16(xArgRM32),
+ /*3647*/ uint16(xMatch),
+ /*3648*/ uint16(xCondDataSize), 3636, 3642, 3652,
+ /*3652*/ uint16(xSetOp), uint16(CMOVNE),
+ /*3654*/ uint16(xReadSlashR),
+ /*3655*/ uint16(xArgR64),
+ /*3656*/ uint16(xArgRM64),
+ /*3657*/ uint16(xMatch),
+ /*3658*/ uint16(xCondIs64), 3661, 3677,
+ /*3661*/ uint16(xCondDataSize), 3665, 3671, 0,
+ /*3665*/ uint16(xSetOp), uint16(CMOVBE),
+ /*3667*/ uint16(xReadSlashR),
+ /*3668*/ uint16(xArgR16),
+ /*3669*/ uint16(xArgRM16),
+ /*3670*/ uint16(xMatch),
+ /*3671*/ uint16(xSetOp), uint16(CMOVBE),
+ /*3673*/ uint16(xReadSlashR),
+ /*3674*/ uint16(xArgR32),
+ /*3675*/ uint16(xArgRM32),
+ /*3676*/ uint16(xMatch),
+ /*3677*/ uint16(xCondDataSize), 3665, 3671, 3681,
+ /*3681*/ uint16(xSetOp), uint16(CMOVBE),
+ /*3683*/ uint16(xReadSlashR),
+ /*3684*/ uint16(xArgR64),
+ /*3685*/ uint16(xArgRM64),
+ /*3686*/ uint16(xMatch),
+ /*3687*/ uint16(xCondIs64), 3690, 3706,
+ /*3690*/ uint16(xCondDataSize), 3694, 3700, 0,
+ /*3694*/ uint16(xSetOp), uint16(CMOVA),
+ /*3696*/ uint16(xReadSlashR),
+ /*3697*/ uint16(xArgR16),
+ /*3698*/ uint16(xArgRM16),
+ /*3699*/ uint16(xMatch),
+ /*3700*/ uint16(xSetOp), uint16(CMOVA),
+ /*3702*/ uint16(xReadSlashR),
+ /*3703*/ uint16(xArgR32),
+ /*3704*/ uint16(xArgRM32),
+ /*3705*/ uint16(xMatch),
+ /*3706*/ uint16(xCondDataSize), 3694, 3700, 3710,
+ /*3710*/ uint16(xSetOp), uint16(CMOVA),
+ /*3712*/ uint16(xReadSlashR),
+ /*3713*/ uint16(xArgR64),
+ /*3714*/ uint16(xArgRM64),
+ /*3715*/ uint16(xMatch),
+ /*3716*/ uint16(xCondIs64), 3719, 3735,
+ /*3719*/ uint16(xCondDataSize), 3723, 3729, 0,
+ /*3723*/ uint16(xSetOp), uint16(CMOVS),
+ /*3725*/ uint16(xReadSlashR),
+ /*3726*/ uint16(xArgR16),
+ /*3727*/ uint16(xArgRM16),
+ /*3728*/ uint16(xMatch),
+ /*3729*/ uint16(xSetOp), uint16(CMOVS),
+ /*3731*/ uint16(xReadSlashR),
+ /*3732*/ uint16(xArgR32),
+ /*3733*/ uint16(xArgRM32),
+ /*3734*/ uint16(xMatch),
+ /*3735*/ uint16(xCondDataSize), 3723, 3729, 3739,
+ /*3739*/ uint16(xSetOp), uint16(CMOVS),
+ /*3741*/ uint16(xReadSlashR),
+ /*3742*/ uint16(xArgR64),
+ /*3743*/ uint16(xArgRM64),
+ /*3744*/ uint16(xMatch),
+ /*3745*/ uint16(xCondIs64), 3748, 3764,
+ /*3748*/ uint16(xCondDataSize), 3752, 3758, 0,
+ /*3752*/ uint16(xSetOp), uint16(CMOVNS),
+ /*3754*/ uint16(xReadSlashR),
+ /*3755*/ uint16(xArgR16),
+ /*3756*/ uint16(xArgRM16),
+ /*3757*/ uint16(xMatch),
+ /*3758*/ uint16(xSetOp), uint16(CMOVNS),
+ /*3760*/ uint16(xReadSlashR),
+ /*3761*/ uint16(xArgR32),
+ /*3762*/ uint16(xArgRM32),
+ /*3763*/ uint16(xMatch),
+ /*3764*/ uint16(xCondDataSize), 3752, 3758, 3768,
+ /*3768*/ uint16(xSetOp), uint16(CMOVNS),
+ /*3770*/ uint16(xReadSlashR),
+ /*3771*/ uint16(xArgR64),
+ /*3772*/ uint16(xArgRM64),
+ /*3773*/ uint16(xMatch),
+ /*3774*/ uint16(xCondIs64), 3777, 3793,
+ /*3777*/ uint16(xCondDataSize), 3781, 3787, 0,
+ /*3781*/ uint16(xSetOp), uint16(CMOVP),
+ /*3783*/ uint16(xReadSlashR),
+ /*3784*/ uint16(xArgR16),
+ /*3785*/ uint16(xArgRM16),
+ /*3786*/ uint16(xMatch),
+ /*3787*/ uint16(xSetOp), uint16(CMOVP),
+ /*3789*/ uint16(xReadSlashR),
+ /*3790*/ uint16(xArgR32),
+ /*3791*/ uint16(xArgRM32),
+ /*3792*/ uint16(xMatch),
+ /*3793*/ uint16(xCondDataSize), 3781, 3787, 3797,
+ /*3797*/ uint16(xSetOp), uint16(CMOVP),
+ /*3799*/ uint16(xReadSlashR),
+ /*3800*/ uint16(xArgR64),
+ /*3801*/ uint16(xArgRM64),
+ /*3802*/ uint16(xMatch),
+ /*3803*/ uint16(xCondIs64), 3806, 3822,
+ /*3806*/ uint16(xCondDataSize), 3810, 3816, 0,
+ /*3810*/ uint16(xSetOp), uint16(CMOVNP),
+ /*3812*/ uint16(xReadSlashR),
+ /*3813*/ uint16(xArgR16),
+ /*3814*/ uint16(xArgRM16),
+ /*3815*/ uint16(xMatch),
+ /*3816*/ uint16(xSetOp), uint16(CMOVNP),
+ /*3818*/ uint16(xReadSlashR),
+ /*3819*/ uint16(xArgR32),
+ /*3820*/ uint16(xArgRM32),
+ /*3821*/ uint16(xMatch),
+ /*3822*/ uint16(xCondDataSize), 3810, 3816, 3826,
+ /*3826*/ uint16(xSetOp), uint16(CMOVNP),
+ /*3828*/ uint16(xReadSlashR),
+ /*3829*/ uint16(xArgR64),
+ /*3830*/ uint16(xArgRM64),
+ /*3831*/ uint16(xMatch),
+ /*3832*/ uint16(xCondIs64), 3835, 3851,
+ /*3835*/ uint16(xCondDataSize), 3839, 3845, 0,
+ /*3839*/ uint16(xSetOp), uint16(CMOVL),
+ /*3841*/ uint16(xReadSlashR),
+ /*3842*/ uint16(xArgR16),
+ /*3843*/ uint16(xArgRM16),
+ /*3844*/ uint16(xMatch),
+ /*3845*/ uint16(xSetOp), uint16(CMOVL),
+ /*3847*/ uint16(xReadSlashR),
+ /*3848*/ uint16(xArgR32),
+ /*3849*/ uint16(xArgRM32),
+ /*3850*/ uint16(xMatch),
+ /*3851*/ uint16(xCondDataSize), 3839, 3845, 3855,
+ /*3855*/ uint16(xSetOp), uint16(CMOVL),
+ /*3857*/ uint16(xReadSlashR),
+ /*3858*/ uint16(xArgR64),
+ /*3859*/ uint16(xArgRM64),
+ /*3860*/ uint16(xMatch),
+ /*3861*/ uint16(xCondIs64), 3864, 3880,
+ /*3864*/ uint16(xCondDataSize), 3868, 3874, 0,
+ /*3868*/ uint16(xSetOp), uint16(CMOVGE),
+ /*3870*/ uint16(xReadSlashR),
+ /*3871*/ uint16(xArgR16),
+ /*3872*/ uint16(xArgRM16),
+ /*3873*/ uint16(xMatch),
+ /*3874*/ uint16(xSetOp), uint16(CMOVGE),
+ /*3876*/ uint16(xReadSlashR),
+ /*3877*/ uint16(xArgR32),
+ /*3878*/ uint16(xArgRM32),
+ /*3879*/ uint16(xMatch),
+ /*3880*/ uint16(xCondDataSize), 3868, 3874, 3884,
+ /*3884*/ uint16(xSetOp), uint16(CMOVGE),
+ /*3886*/ uint16(xReadSlashR),
+ /*3887*/ uint16(xArgR64),
+ /*3888*/ uint16(xArgRM64),
+ /*3889*/ uint16(xMatch),
+ /*3890*/ uint16(xCondIs64), 3893, 3909,
+ /*3893*/ uint16(xCondDataSize), 3897, 3903, 0,
+ /*3897*/ uint16(xSetOp), uint16(CMOVLE),
+ /*3899*/ uint16(xReadSlashR),
+ /*3900*/ uint16(xArgR16),
+ /*3901*/ uint16(xArgRM16),
+ /*3902*/ uint16(xMatch),
+ /*3903*/ uint16(xSetOp), uint16(CMOVLE),
+ /*3905*/ uint16(xReadSlashR),
+ /*3906*/ uint16(xArgR32),
+ /*3907*/ uint16(xArgRM32),
+ /*3908*/ uint16(xMatch),
+ /*3909*/ uint16(xCondDataSize), 3897, 3903, 3913,
+ /*3913*/ uint16(xSetOp), uint16(CMOVLE),
+ /*3915*/ uint16(xReadSlashR),
+ /*3916*/ uint16(xArgR64),
+ /*3917*/ uint16(xArgRM64),
+ /*3918*/ uint16(xMatch),
+ /*3919*/ uint16(xCondIs64), 3922, 3938,
+ /*3922*/ uint16(xCondDataSize), 3926, 3932, 0,
+ /*3926*/ uint16(xSetOp), uint16(CMOVG),
+ /*3928*/ uint16(xReadSlashR),
+ /*3929*/ uint16(xArgR16),
+ /*3930*/ uint16(xArgRM16),
+ /*3931*/ uint16(xMatch),
+ /*3932*/ uint16(xSetOp), uint16(CMOVG),
+ /*3934*/ uint16(xReadSlashR),
+ /*3935*/ uint16(xArgR32),
+ /*3936*/ uint16(xArgRM32),
+ /*3937*/ uint16(xMatch),
+ /*3938*/ uint16(xCondDataSize), 3926, 3932, 3942,
+ /*3942*/ uint16(xSetOp), uint16(CMOVG),
+ /*3944*/ uint16(xReadSlashR),
+ /*3945*/ uint16(xArgR64),
+ /*3946*/ uint16(xArgRM64),
+ /*3947*/ uint16(xMatch),
+ /*3948*/ uint16(xCondPrefix), 2,
+ 0x66, 3960,
+ 0x0, 3954,
+ /*3954*/ uint16(xSetOp), uint16(MOVMSKPS),
+ /*3956*/ uint16(xReadSlashR),
+ /*3957*/ uint16(xArgR32),
+ /*3958*/ uint16(xArgXmm2),
+ /*3959*/ uint16(xMatch),
+ /*3960*/ uint16(xSetOp), uint16(MOVMSKPD),
+ /*3962*/ uint16(xReadSlashR),
+ /*3963*/ uint16(xArgR32),
+ /*3964*/ uint16(xArgXmm2),
+ /*3965*/ uint16(xMatch),
+ /*3966*/ uint16(xCondPrefix), 4,
+ 0xF3, 3994,
+ 0xF2, 3988,
+ 0x66, 3982,
+ 0x0, 3976,
+ /*3976*/ uint16(xSetOp), uint16(SQRTPS),
+ /*3978*/ uint16(xReadSlashR),
+ /*3979*/ uint16(xArgXmm1),
+ /*3980*/ uint16(xArgXmm2M128),
+ /*3981*/ uint16(xMatch),
+ /*3982*/ uint16(xSetOp), uint16(SQRTPD),
+ /*3984*/ uint16(xReadSlashR),
+ /*3985*/ uint16(xArgXmm1),
+ /*3986*/ uint16(xArgXmm2M128),
+ /*3987*/ uint16(xMatch),
+ /*3988*/ uint16(xSetOp), uint16(SQRTSD),
+ /*3990*/ uint16(xReadSlashR),
+ /*3991*/ uint16(xArgXmm1),
+ /*3992*/ uint16(xArgXmm2M64),
+ /*3993*/ uint16(xMatch),
+ /*3994*/ uint16(xSetOp), uint16(SQRTSS),
+ /*3996*/ uint16(xReadSlashR),
+ /*3997*/ uint16(xArgXmm1),
+ /*3998*/ uint16(xArgXmm2M32),
+ /*3999*/ uint16(xMatch),
+ /*4000*/ uint16(xCondPrefix), 2,
+ 0xF3, 4012,
+ 0x0, 4006,
+ /*4006*/ uint16(xSetOp), uint16(RSQRTPS),
+ /*4008*/ uint16(xReadSlashR),
+ /*4009*/ uint16(xArgXmm1),
+ /*4010*/ uint16(xArgXmm2M128),
+ /*4011*/ uint16(xMatch),
+ /*4012*/ uint16(xSetOp), uint16(RSQRTSS),
+ /*4014*/ uint16(xReadSlashR),
+ /*4015*/ uint16(xArgXmm1),
+ /*4016*/ uint16(xArgXmm2M32),
+ /*4017*/ uint16(xMatch),
+ /*4018*/ uint16(xCondPrefix), 2,
+ 0xF3, 4030,
+ 0x0, 4024,
+ /*4024*/ uint16(xSetOp), uint16(RCPPS),
+ /*4026*/ uint16(xReadSlashR),
+ /*4027*/ uint16(xArgXmm1),
+ /*4028*/ uint16(xArgXmm2M128),
+ /*4029*/ uint16(xMatch),
+ /*4030*/ uint16(xSetOp), uint16(RCPSS),
+ /*4032*/ uint16(xReadSlashR),
+ /*4033*/ uint16(xArgXmm1),
+ /*4034*/ uint16(xArgXmm2M32),
+ /*4035*/ uint16(xMatch),
+ /*4036*/ uint16(xCondPrefix), 2,
+ 0x66, 4048,
+ 0x0, 4042,
+ /*4042*/ uint16(xSetOp), uint16(ANDPS),
+ /*4044*/ uint16(xReadSlashR),
+ /*4045*/ uint16(xArgXmm1),
+ /*4046*/ uint16(xArgXmm2M128),
+ /*4047*/ uint16(xMatch),
+ /*4048*/ uint16(xSetOp), uint16(ANDPD),
+ /*4050*/ uint16(xReadSlashR),
+ /*4051*/ uint16(xArgXmm1),
+ /*4052*/ uint16(xArgXmm2M128),
+ /*4053*/ uint16(xMatch),
+ /*4054*/ uint16(xCondPrefix), 2,
+ 0x66, 4066,
+ 0x0, 4060,
+ /*4060*/ uint16(xSetOp), uint16(ANDNPS),
+ /*4062*/ uint16(xReadSlashR),
+ /*4063*/ uint16(xArgXmm1),
+ /*4064*/ uint16(xArgXmm2M128),
+ /*4065*/ uint16(xMatch),
+ /*4066*/ uint16(xSetOp), uint16(ANDNPD),
+ /*4068*/ uint16(xReadSlashR),
+ /*4069*/ uint16(xArgXmm1),
+ /*4070*/ uint16(xArgXmm2M128),
+ /*4071*/ uint16(xMatch),
+ /*4072*/ uint16(xCondPrefix), 2,
+ 0x66, 4084,
+ 0x0, 4078,
+ /*4078*/ uint16(xSetOp), uint16(ORPS),
+ /*4080*/ uint16(xReadSlashR),
+ /*4081*/ uint16(xArgXmm1),
+ /*4082*/ uint16(xArgXmm2M128),
+ /*4083*/ uint16(xMatch),
+ /*4084*/ uint16(xSetOp), uint16(ORPD),
+ /*4086*/ uint16(xReadSlashR),
+ /*4087*/ uint16(xArgXmm1),
+ /*4088*/ uint16(xArgXmm2M128),
+ /*4089*/ uint16(xMatch),
+ /*4090*/ uint16(xCondPrefix), 2,
+ 0x66, 4102,
+ 0x0, 4096,
+ /*4096*/ uint16(xSetOp), uint16(XORPS),
+ /*4098*/ uint16(xReadSlashR),
+ /*4099*/ uint16(xArgXmm1),
+ /*4100*/ uint16(xArgXmm2M128),
+ /*4101*/ uint16(xMatch),
+ /*4102*/ uint16(xSetOp), uint16(XORPD),
+ /*4104*/ uint16(xReadSlashR),
+ /*4105*/ uint16(xArgXmm1),
+ /*4106*/ uint16(xArgXmm2M128),
+ /*4107*/ uint16(xMatch),
+ /*4108*/ uint16(xCondPrefix), 4,
+ 0xF3, 4136,
+ 0xF2, 4130,
+ 0x66, 4124,
+ 0x0, 4118,
+ /*4118*/ uint16(xSetOp), uint16(ADDPS),
+ /*4120*/ uint16(xReadSlashR),
+ /*4121*/ uint16(xArgXmm1),
+ /*4122*/ uint16(xArgXmm2M128),
+ /*4123*/ uint16(xMatch),
+ /*4124*/ uint16(xSetOp), uint16(ADDPD),
+ /*4126*/ uint16(xReadSlashR),
+ /*4127*/ uint16(xArgXmm1),
+ /*4128*/ uint16(xArgXmm2M128),
+ /*4129*/ uint16(xMatch),
+ /*4130*/ uint16(xSetOp), uint16(ADDSD),
+ /*4132*/ uint16(xReadSlashR),
+ /*4133*/ uint16(xArgXmm1),
+ /*4134*/ uint16(xArgXmm2M64),
+ /*4135*/ uint16(xMatch),
+ /*4136*/ uint16(xSetOp), uint16(ADDSS),
+ /*4138*/ uint16(xReadSlashR),
+ /*4139*/ uint16(xArgXmm1),
+ /*4140*/ uint16(xArgXmm2M32),
+ /*4141*/ uint16(xMatch),
+ /*4142*/ uint16(xCondPrefix), 4,
+ 0xF3, 4170,
+ 0xF2, 4164,
+ 0x66, 4158,
+ 0x0, 4152,
+ /*4152*/ uint16(xSetOp), uint16(MULPS),
+ /*4154*/ uint16(xReadSlashR),
+ /*4155*/ uint16(xArgXmm1),
+ /*4156*/ uint16(xArgXmm2M128),
+ /*4157*/ uint16(xMatch),
+ /*4158*/ uint16(xSetOp), uint16(MULPD),
+ /*4160*/ uint16(xReadSlashR),
+ /*4161*/ uint16(xArgXmm1),
+ /*4162*/ uint16(xArgXmm2M128),
+ /*4163*/ uint16(xMatch),
+ /*4164*/ uint16(xSetOp), uint16(MULSD),
+ /*4166*/ uint16(xReadSlashR),
+ /*4167*/ uint16(xArgXmm1),
+ /*4168*/ uint16(xArgXmm2M64),
+ /*4169*/ uint16(xMatch),
+ /*4170*/ uint16(xSetOp), uint16(MULSS),
+ /*4172*/ uint16(xReadSlashR),
+ /*4173*/ uint16(xArgXmm1),
+ /*4174*/ uint16(xArgXmm2M32),
+ /*4175*/ uint16(xMatch),
+ /*4176*/ uint16(xCondPrefix), 4,
+ 0xF3, 4204,
+ 0xF2, 4198,
+ 0x66, 4192,
+ 0x0, 4186,
+ /*4186*/ uint16(xSetOp), uint16(CVTPS2PD),
+ /*4188*/ uint16(xReadSlashR),
+ /*4189*/ uint16(xArgXmm1),
+ /*4190*/ uint16(xArgXmm2M64),
+ /*4191*/ uint16(xMatch),
+ /*4192*/ uint16(xSetOp), uint16(CVTPD2PS),
+ /*4194*/ uint16(xReadSlashR),
+ /*4195*/ uint16(xArgXmm1),
+ /*4196*/ uint16(xArgXmm2M128),
+ /*4197*/ uint16(xMatch),
+ /*4198*/ uint16(xSetOp), uint16(CVTSD2SS),
+ /*4200*/ uint16(xReadSlashR),
+ /*4201*/ uint16(xArgXmm1),
+ /*4202*/ uint16(xArgXmm2M64),
+ /*4203*/ uint16(xMatch),
+ /*4204*/ uint16(xSetOp), uint16(CVTSS2SD),
+ /*4206*/ uint16(xReadSlashR),
+ /*4207*/ uint16(xArgXmm1),
+ /*4208*/ uint16(xArgXmm2M32),
+ /*4209*/ uint16(xMatch),
+ /*4210*/ uint16(xCondPrefix), 3,
+ 0xF3, 4230,
+ 0x66, 4224,
+ 0x0, 4218,
+ /*4218*/ uint16(xSetOp), uint16(CVTDQ2PS),
+ /*4220*/ uint16(xReadSlashR),
+ /*4221*/ uint16(xArgXmm1),
+ /*4222*/ uint16(xArgXmm2M128),
+ /*4223*/ uint16(xMatch),
+ /*4224*/ uint16(xSetOp), uint16(CVTPS2DQ),
+ /*4226*/ uint16(xReadSlashR),
+ /*4227*/ uint16(xArgXmm1),
+ /*4228*/ uint16(xArgXmm2M128),
+ /*4229*/ uint16(xMatch),
+ /*4230*/ uint16(xSetOp), uint16(CVTTPS2DQ),
+ /*4232*/ uint16(xReadSlashR),
+ /*4233*/ uint16(xArgXmm1),
+ /*4234*/ uint16(xArgXmm2M128),
+ /*4235*/ uint16(xMatch),
+ /*4236*/ uint16(xCondPrefix), 4,
+ 0xF3, 4264,
+ 0xF2, 4258,
+ 0x66, 4252,
+ 0x0, 4246,
+ /*4246*/ uint16(xSetOp), uint16(SUBPS),
+ /*4248*/ uint16(xReadSlashR),
+ /*4249*/ uint16(xArgXmm1),
+ /*4250*/ uint16(xArgXmm2M128),
+ /*4251*/ uint16(xMatch),
+ /*4252*/ uint16(xSetOp), uint16(SUBPD),
+ /*4254*/ uint16(xReadSlashR),
+ /*4255*/ uint16(xArgXmm1),
+ /*4256*/ uint16(xArgXmm2M128),
+ /*4257*/ uint16(xMatch),
+ /*4258*/ uint16(xSetOp), uint16(SUBSD),
+ /*4260*/ uint16(xReadSlashR),
+ /*4261*/ uint16(xArgXmm1),
+ /*4262*/ uint16(xArgXmm2M64),
+ /*4263*/ uint16(xMatch),
+ /*4264*/ uint16(xSetOp), uint16(SUBSS),
+ /*4266*/ uint16(xReadSlashR),
+ /*4267*/ uint16(xArgXmm1),
+ /*4268*/ uint16(xArgXmm2M32),
+ /*4269*/ uint16(xMatch),
+ /*4270*/ uint16(xCondPrefix), 4,
+ 0xF3, 4298,
+ 0xF2, 4292,
+ 0x66, 4286,
+ 0x0, 4280,
+ /*4280*/ uint16(xSetOp), uint16(MINPS),
+ /*4282*/ uint16(xReadSlashR),
+ /*4283*/ uint16(xArgXmm1),
+ /*4284*/ uint16(xArgXmm2M128),
+ /*4285*/ uint16(xMatch),
+ /*4286*/ uint16(xSetOp), uint16(MINPD),
+ /*4288*/ uint16(xReadSlashR),
+ /*4289*/ uint16(xArgXmm1),
+ /*4290*/ uint16(xArgXmm2M128),
+ /*4291*/ uint16(xMatch),
+ /*4292*/ uint16(xSetOp), uint16(MINSD),
+ /*4294*/ uint16(xReadSlashR),
+ /*4295*/ uint16(xArgXmm1),
+ /*4296*/ uint16(xArgXmm2M64),
+ /*4297*/ uint16(xMatch),
+ /*4298*/ uint16(xSetOp), uint16(MINSS),
+ /*4300*/ uint16(xReadSlashR),
+ /*4301*/ uint16(xArgXmm1),
+ /*4302*/ uint16(xArgXmm2M32),
+ /*4303*/ uint16(xMatch),
+ /*4304*/ uint16(xCondPrefix), 4,
+ 0xF3, 4332,
+ 0xF2, 4326,
+ 0x66, 4320,
+ 0x0, 4314,
+ /*4314*/ uint16(xSetOp), uint16(DIVPS),
+ /*4316*/ uint16(xReadSlashR),
+ /*4317*/ uint16(xArgXmm1),
+ /*4318*/ uint16(xArgXmm2M128),
+ /*4319*/ uint16(xMatch),
+ /*4320*/ uint16(xSetOp), uint16(DIVPD),
+ /*4322*/ uint16(xReadSlashR),
+ /*4323*/ uint16(xArgXmm1),
+ /*4324*/ uint16(xArgXmm2M128),
+ /*4325*/ uint16(xMatch),
+ /*4326*/ uint16(xSetOp), uint16(DIVSD),
+ /*4328*/ uint16(xReadSlashR),
+ /*4329*/ uint16(xArgXmm1),
+ /*4330*/ uint16(xArgXmm2M64),
+ /*4331*/ uint16(xMatch),
+ /*4332*/ uint16(xSetOp), uint16(DIVSS),
+ /*4334*/ uint16(xReadSlashR),
+ /*4335*/ uint16(xArgXmm1),
+ /*4336*/ uint16(xArgXmm2M32),
+ /*4337*/ uint16(xMatch),
+ /*4338*/ uint16(xCondPrefix), 4,
+ 0xF3, 4366,
+ 0xF2, 4360,
+ 0x66, 4354,
+ 0x0, 4348,
+ /*4348*/ uint16(xSetOp), uint16(MAXPS),
+ /*4350*/ uint16(xReadSlashR),
+ /*4351*/ uint16(xArgXmm1),
+ /*4352*/ uint16(xArgXmm2M128),
+ /*4353*/ uint16(xMatch),
+ /*4354*/ uint16(xSetOp), uint16(MAXPD),
+ /*4356*/ uint16(xReadSlashR),
+ /*4357*/ uint16(xArgXmm1),
+ /*4358*/ uint16(xArgXmm2M128),
+ /*4359*/ uint16(xMatch),
+ /*4360*/ uint16(xSetOp), uint16(MAXSD),
+ /*4362*/ uint16(xReadSlashR),
+ /*4363*/ uint16(xArgXmm1),
+ /*4364*/ uint16(xArgXmm2M64),
+ /*4365*/ uint16(xMatch),
+ /*4366*/ uint16(xSetOp), uint16(MAXSS),
+ /*4368*/ uint16(xReadSlashR),
+ /*4369*/ uint16(xArgXmm1),
+ /*4370*/ uint16(xArgXmm2M32),
+ /*4371*/ uint16(xMatch),
+ /*4372*/ uint16(xCondPrefix), 2,
+ 0x66, 4384,
+ 0x0, 4378,
+ /*4378*/ uint16(xSetOp), uint16(PUNPCKLBW),
+ /*4380*/ uint16(xReadSlashR),
+ /*4381*/ uint16(xArgMm),
+ /*4382*/ uint16(xArgMmM32),
+ /*4383*/ uint16(xMatch),
+ /*4384*/ uint16(xSetOp), uint16(PUNPCKLBW),
+ /*4386*/ uint16(xReadSlashR),
+ /*4387*/ uint16(xArgXmm1),
+ /*4388*/ uint16(xArgXmm2M128),
+ /*4389*/ uint16(xMatch),
+ /*4390*/ uint16(xCondPrefix), 2,
+ 0x66, 4402,
+ 0x0, 4396,
+ /*4396*/ uint16(xSetOp), uint16(PUNPCKLWD),
+ /*4398*/ uint16(xReadSlashR),
+ /*4399*/ uint16(xArgMm),
+ /*4400*/ uint16(xArgMmM32),
+ /*4401*/ uint16(xMatch),
+ /*4402*/ uint16(xSetOp), uint16(PUNPCKLWD),
+ /*4404*/ uint16(xReadSlashR),
+ /*4405*/ uint16(xArgXmm1),
+ /*4406*/ uint16(xArgXmm2M128),
+ /*4407*/ uint16(xMatch),
+ /*4408*/ uint16(xCondPrefix), 2,
+ 0x66, 4420,
+ 0x0, 4414,
+ /*4414*/ uint16(xSetOp), uint16(PUNPCKLDQ),
+ /*4416*/ uint16(xReadSlashR),
+ /*4417*/ uint16(xArgMm),
+ /*4418*/ uint16(xArgMmM32),
+ /*4419*/ uint16(xMatch),
+ /*4420*/ uint16(xSetOp), uint16(PUNPCKLDQ),
+ /*4422*/ uint16(xReadSlashR),
+ /*4423*/ uint16(xArgXmm1),
+ /*4424*/ uint16(xArgXmm2M128),
+ /*4425*/ uint16(xMatch),
+ /*4426*/ uint16(xCondPrefix), 2,
+ 0x66, 4438,
+ 0x0, 4432,
+ /*4432*/ uint16(xSetOp), uint16(PACKSSWB),
+ /*4434*/ uint16(xReadSlashR),
+ /*4435*/ uint16(xArgMm1),
+ /*4436*/ uint16(xArgMm2M64),
+ /*4437*/ uint16(xMatch),
+ /*4438*/ uint16(xSetOp), uint16(PACKSSWB),
+ /*4440*/ uint16(xReadSlashR),
+ /*4441*/ uint16(xArgXmm1),
+ /*4442*/ uint16(xArgXmm2M128),
+ /*4443*/ uint16(xMatch),
+ /*4444*/ uint16(xCondPrefix), 2,
+ 0x66, 4456,
+ 0x0, 4450,
+ /*4450*/ uint16(xSetOp), uint16(PCMPGTB),
+ /*4452*/ uint16(xReadSlashR),
+ /*4453*/ uint16(xArgMm),
+ /*4454*/ uint16(xArgMmM64),
+ /*4455*/ uint16(xMatch),
+ /*4456*/ uint16(xSetOp), uint16(PCMPGTB),
+ /*4458*/ uint16(xReadSlashR),
+ /*4459*/ uint16(xArgXmm1),
+ /*4460*/ uint16(xArgXmm2M128),
+ /*4461*/ uint16(xMatch),
+ /*4462*/ uint16(xCondPrefix), 2,
+ 0x66, 4474,
+ 0x0, 4468,
+ /*4468*/ uint16(xSetOp), uint16(PCMPGTW),
+ /*4470*/ uint16(xReadSlashR),
+ /*4471*/ uint16(xArgMm),
+ /*4472*/ uint16(xArgMmM64),
+ /*4473*/ uint16(xMatch),
+ /*4474*/ uint16(xSetOp), uint16(PCMPGTW),
+ /*4476*/ uint16(xReadSlashR),
+ /*4477*/ uint16(xArgXmm1),
+ /*4478*/ uint16(xArgXmm2M128),
+ /*4479*/ uint16(xMatch),
+ /*4480*/ uint16(xCondPrefix), 2,
+ 0x66, 4492,
+ 0x0, 4486,
+ /*4486*/ uint16(xSetOp), uint16(PCMPGTD),
+ /*4488*/ uint16(xReadSlashR),
+ /*4489*/ uint16(xArgMm),
+ /*4490*/ uint16(xArgMmM64),
+ /*4491*/ uint16(xMatch),
+ /*4492*/ uint16(xSetOp), uint16(PCMPGTD),
+ /*4494*/ uint16(xReadSlashR),
+ /*4495*/ uint16(xArgXmm1),
+ /*4496*/ uint16(xArgXmm2M128),
+ /*4497*/ uint16(xMatch),
+ /*4498*/ uint16(xCondPrefix), 2,
+ 0x66, 4510,
+ 0x0, 4504,
+ /*4504*/ uint16(xSetOp), uint16(PACKUSWB),
+ /*4506*/ uint16(xReadSlashR),
+ /*4507*/ uint16(xArgMm),
+ /*4508*/ uint16(xArgMmM64),
+ /*4509*/ uint16(xMatch),
+ /*4510*/ uint16(xSetOp), uint16(PACKUSWB),
+ /*4512*/ uint16(xReadSlashR),
+ /*4513*/ uint16(xArgXmm1),
+ /*4514*/ uint16(xArgXmm2M128),
+ /*4515*/ uint16(xMatch),
+ /*4516*/ uint16(xCondPrefix), 2,
+ 0x66, 4528,
+ 0x0, 4522,
+ /*4522*/ uint16(xSetOp), uint16(PUNPCKHBW),
+ /*4524*/ uint16(xReadSlashR),
+ /*4525*/ uint16(xArgMm),
+ /*4526*/ uint16(xArgMmM64),
+ /*4527*/ uint16(xMatch),
+ /*4528*/ uint16(xSetOp), uint16(PUNPCKHBW),
+ /*4530*/ uint16(xReadSlashR),
+ /*4531*/ uint16(xArgXmm1),
+ /*4532*/ uint16(xArgXmm2M128),
+ /*4533*/ uint16(xMatch),
+ /*4534*/ uint16(xCondPrefix), 2,
+ 0x66, 4546,
+ 0x0, 4540,
+ /*4540*/ uint16(xSetOp), uint16(PUNPCKHWD),
+ /*4542*/ uint16(xReadSlashR),
+ /*4543*/ uint16(xArgMm),
+ /*4544*/ uint16(xArgMmM64),
+ /*4545*/ uint16(xMatch),
+ /*4546*/ uint16(xSetOp), uint16(PUNPCKHWD),
+ /*4548*/ uint16(xReadSlashR),
+ /*4549*/ uint16(xArgXmm1),
+ /*4550*/ uint16(xArgXmm2M128),
+ /*4551*/ uint16(xMatch),
+ /*4552*/ uint16(xCondPrefix), 2,
+ 0x66, 4564,
+ 0x0, 4558,
+ /*4558*/ uint16(xSetOp), uint16(PUNPCKHDQ),
+ /*4560*/ uint16(xReadSlashR),
+ /*4561*/ uint16(xArgMm),
+ /*4562*/ uint16(xArgMmM64),
+ /*4563*/ uint16(xMatch),
+ /*4564*/ uint16(xSetOp), uint16(PUNPCKHDQ),
+ /*4566*/ uint16(xReadSlashR),
+ /*4567*/ uint16(xArgXmm1),
+ /*4568*/ uint16(xArgXmm2M128),
+ /*4569*/ uint16(xMatch),
+ /*4570*/ uint16(xCondPrefix), 2,
+ 0x66, 4582,
+ 0x0, 4576,
+ /*4576*/ uint16(xSetOp), uint16(PACKSSDW),
+ /*4578*/ uint16(xReadSlashR),
+ /*4579*/ uint16(xArgMm1),
+ /*4580*/ uint16(xArgMm2M64),
+ /*4581*/ uint16(xMatch),
+ /*4582*/ uint16(xSetOp), uint16(PACKSSDW),
+ /*4584*/ uint16(xReadSlashR),
+ /*4585*/ uint16(xArgXmm1),
+ /*4586*/ uint16(xArgXmm2M128),
+ /*4587*/ uint16(xMatch),
+ /*4588*/ uint16(xCondPrefix), 1,
+ 0x66, 4592,
+ /*4592*/ uint16(xSetOp), uint16(PUNPCKLQDQ),
+ /*4594*/ uint16(xReadSlashR),
+ /*4595*/ uint16(xArgXmm1),
+ /*4596*/ uint16(xArgXmm2M128),
+ /*4597*/ uint16(xMatch),
+ /*4598*/ uint16(xCondPrefix), 1,
+ 0x66, 4602,
+ /*4602*/ uint16(xSetOp), uint16(PUNPCKHQDQ),
+ /*4604*/ uint16(xReadSlashR),
+ /*4605*/ uint16(xArgXmm1),
+ /*4606*/ uint16(xArgXmm2M128),
+ /*4607*/ uint16(xMatch),
+ /*4608*/ uint16(xCondIs64), 4611, 4649,
+ /*4611*/ uint16(xCondPrefix), 2,
+ 0x66, 4633,
+ 0x0, 4617,
+ /*4617*/ uint16(xCondDataSize), 4621, 4627, 0,
+ /*4621*/ uint16(xSetOp), uint16(MOVD),
+ /*4623*/ uint16(xReadSlashR),
+ /*4624*/ uint16(xArgMm),
+ /*4625*/ uint16(xArgRM32),
+ /*4626*/ uint16(xMatch),
+ /*4627*/ uint16(xSetOp), uint16(MOVD),
+ /*4629*/ uint16(xReadSlashR),
+ /*4630*/ uint16(xArgMm),
+ /*4631*/ uint16(xArgRM32),
+ /*4632*/ uint16(xMatch),
+ /*4633*/ uint16(xCondDataSize), 4637, 4643, 0,
+ /*4637*/ uint16(xSetOp), uint16(MOVD),
+ /*4639*/ uint16(xReadSlashR),
+ /*4640*/ uint16(xArgXmm),
+ /*4641*/ uint16(xArgRM32),
+ /*4642*/ uint16(xMatch),
+ /*4643*/ uint16(xSetOp), uint16(MOVD),
+ /*4645*/ uint16(xReadSlashR),
+ /*4646*/ uint16(xArgXmm),
+ /*4647*/ uint16(xArgRM32),
+ /*4648*/ uint16(xMatch),
+ /*4649*/ uint16(xCondPrefix), 2,
+ 0x66, 4665,
+ 0x0, 4655,
+ /*4655*/ uint16(xCondDataSize), 4621, 4627, 4659,
+ /*4659*/ uint16(xSetOp), uint16(MOVQ),
+ /*4661*/ uint16(xReadSlashR),
+ /*4662*/ uint16(xArgMm),
+ /*4663*/ uint16(xArgRM64),
+ /*4664*/ uint16(xMatch),
+ /*4665*/ uint16(xCondDataSize), 4637, 4643, 4669,
+ /*4669*/ uint16(xSetOp), uint16(MOVQ),
+ /*4671*/ uint16(xReadSlashR),
+ /*4672*/ uint16(xArgXmm),
+ /*4673*/ uint16(xArgRM64),
+ /*4674*/ uint16(xMatch),
+ /*4675*/ uint16(xCondPrefix), 3,
+ 0xF3, 4695,
+ 0x66, 4689,
+ 0x0, 4683,
+ /*4683*/ uint16(xSetOp), uint16(MOVQ),
+ /*4685*/ uint16(xReadSlashR),
+ /*4686*/ uint16(xArgMm),
+ /*4687*/ uint16(xArgMmM64),
+ /*4688*/ uint16(xMatch),
+ /*4689*/ uint16(xSetOp), uint16(MOVDQA),
+ /*4691*/ uint16(xReadSlashR),
+ /*4692*/ uint16(xArgXmm1),
+ /*4693*/ uint16(xArgXmm2M128),
+ /*4694*/ uint16(xMatch),
+ /*4695*/ uint16(xSetOp), uint16(MOVDQU),
+ /*4697*/ uint16(xReadSlashR),
+ /*4698*/ uint16(xArgXmm1),
+ /*4699*/ uint16(xArgXmm2M128),
+ /*4700*/ uint16(xMatch),
+ /*4701*/ uint16(xCondPrefix), 4,
+ 0xF3, 4735,
+ 0xF2, 4727,
+ 0x66, 4719,
+ 0x0, 4711,
+ /*4711*/ uint16(xSetOp), uint16(PSHUFW),
+ /*4713*/ uint16(xReadSlashR),
+ /*4714*/ uint16(xReadIb),
+ /*4715*/ uint16(xArgMm1),
+ /*4716*/ uint16(xArgMm2M64),
+ /*4717*/ uint16(xArgImm8u),
+ /*4718*/ uint16(xMatch),
+ /*4719*/ uint16(xSetOp), uint16(PSHUFD),
+ /*4721*/ uint16(xReadSlashR),
+ /*4722*/ uint16(xReadIb),
+ /*4723*/ uint16(xArgXmm1),
+ /*4724*/ uint16(xArgXmm2M128),
+ /*4725*/ uint16(xArgImm8u),
+ /*4726*/ uint16(xMatch),
+ /*4727*/ uint16(xSetOp), uint16(PSHUFLW),
+ /*4729*/ uint16(xReadSlashR),
+ /*4730*/ uint16(xReadIb),
+ /*4731*/ uint16(xArgXmm1),
+ /*4732*/ uint16(xArgXmm2M128),
+ /*4733*/ uint16(xArgImm8u),
+ /*4734*/ uint16(xMatch),
+ /*4735*/ uint16(xSetOp), uint16(PSHUFHW),
+ /*4737*/ uint16(xReadSlashR),
+ /*4738*/ uint16(xReadIb),
+ /*4739*/ uint16(xArgXmm1),
+ /*4740*/ uint16(xArgXmm2M128),
+ /*4741*/ uint16(xArgImm8u),
+ /*4742*/ uint16(xMatch),
+ /*4743*/ uint16(xCondSlashR),
+ 0, // 0
+ 0, // 1
+ 4752, // 2
+ 0, // 3
+ 4770, // 4
+ 0, // 5
+ 4788, // 6
+ 0, // 7
+ /*4752*/ uint16(xCondPrefix), 2,
+ 0x66, 4764,
+ 0x0, 4758,
+ /*4758*/ uint16(xSetOp), uint16(PSRLW),
+ /*4760*/ uint16(xReadIb),
+ /*4761*/ uint16(xArgMm2),
+ /*4762*/ uint16(xArgImm8u),
+ /*4763*/ uint16(xMatch),
+ /*4764*/ uint16(xSetOp), uint16(PSRLW),
+ /*4766*/ uint16(xReadIb),
+ /*4767*/ uint16(xArgXmm2),
+ /*4768*/ uint16(xArgImm8u),
+ /*4769*/ uint16(xMatch),
+ /*4770*/ uint16(xCondPrefix), 2,
+ 0x66, 4782,
+ 0x0, 4776,
+ /*4776*/ uint16(xSetOp), uint16(PSRAW),
+ /*4778*/ uint16(xReadIb),
+ /*4779*/ uint16(xArgMm2),
+ /*4780*/ uint16(xArgImm8u),
+ /*4781*/ uint16(xMatch),
+ /*4782*/ uint16(xSetOp), uint16(PSRAW),
+ /*4784*/ uint16(xReadIb),
+ /*4785*/ uint16(xArgXmm2),
+ /*4786*/ uint16(xArgImm8u),
+ /*4787*/ uint16(xMatch),
+ /*4788*/ uint16(xCondPrefix), 2,
+ 0x66, 4800,
+ 0x0, 4794,
+ /*4794*/ uint16(xSetOp), uint16(PSLLW),
+ /*4796*/ uint16(xReadIb),
+ /*4797*/ uint16(xArgMm2),
+ /*4798*/ uint16(xArgImm8u),
+ /*4799*/ uint16(xMatch),
+ /*4800*/ uint16(xSetOp), uint16(PSLLW),
+ /*4802*/ uint16(xReadIb),
+ /*4803*/ uint16(xArgXmm2),
+ /*4804*/ uint16(xArgImm8u),
+ /*4805*/ uint16(xMatch),
+ /*4806*/ uint16(xCondSlashR),
+ 0, // 0
+ 0, // 1
+ 4815, // 2
+ 0, // 3
+ 4833, // 4
+ 0, // 5
+ 4851, // 6
+ 0, // 7
+ /*4815*/ uint16(xCondPrefix), 2,
+ 0x66, 4827,
+ 0x0, 4821,
+ /*4821*/ uint16(xSetOp), uint16(PSRLD),
+ /*4823*/ uint16(xReadIb),
+ /*4824*/ uint16(xArgMm2),
+ /*4825*/ uint16(xArgImm8u),
+ /*4826*/ uint16(xMatch),
+ /*4827*/ uint16(xSetOp), uint16(PSRLD),
+ /*4829*/ uint16(xReadIb),
+ /*4830*/ uint16(xArgXmm2),
+ /*4831*/ uint16(xArgImm8u),
+ /*4832*/ uint16(xMatch),
+ /*4833*/ uint16(xCondPrefix), 2,
+ 0x66, 4845,
+ 0x0, 4839,
+ /*4839*/ uint16(xSetOp), uint16(PSRAD),
+ /*4841*/ uint16(xReadIb),
+ /*4842*/ uint16(xArgMm2),
+ /*4843*/ uint16(xArgImm8u),
+ /*4844*/ uint16(xMatch),
+ /*4845*/ uint16(xSetOp), uint16(PSRAD),
+ /*4847*/ uint16(xReadIb),
+ /*4848*/ uint16(xArgXmm2),
+ /*4849*/ uint16(xArgImm8u),
+ /*4850*/ uint16(xMatch),
+ /*4851*/ uint16(xCondPrefix), 2,
+ 0x66, 4863,
+ 0x0, 4857,
+ /*4857*/ uint16(xSetOp), uint16(PSLLD),
+ /*4859*/ uint16(xReadIb),
+ /*4860*/ uint16(xArgMm2),
+ /*4861*/ uint16(xArgImm8u),
+ /*4862*/ uint16(xMatch),
+ /*4863*/ uint16(xSetOp), uint16(PSLLD),
+ /*4865*/ uint16(xReadIb),
+ /*4866*/ uint16(xArgXmm2),
+ /*4867*/ uint16(xArgImm8u),
+ /*4868*/ uint16(xMatch),
+ /*4869*/ uint16(xCondSlashR),
+ 0, // 0
+ 0, // 1
+ 4878, // 2
+ 4896, // 3
+ 0, // 4
+ 0, // 5
+ 4906, // 6
+ 4924, // 7
+ /*4878*/ uint16(xCondPrefix), 2,
+ 0x66, 4890,
+ 0x0, 4884,
+ /*4884*/ uint16(xSetOp), uint16(PSRLQ),
+ /*4886*/ uint16(xReadIb),
+ /*4887*/ uint16(xArgMm2),
+ /*4888*/ uint16(xArgImm8u),
+ /*4889*/ uint16(xMatch),
+ /*4890*/ uint16(xSetOp), uint16(PSRLQ),
+ /*4892*/ uint16(xReadIb),
+ /*4893*/ uint16(xArgXmm2),
+ /*4894*/ uint16(xArgImm8u),
+ /*4895*/ uint16(xMatch),
+ /*4896*/ uint16(xCondPrefix), 1,
+ 0x66, 4900,
+ /*4900*/ uint16(xSetOp), uint16(PSRLDQ),
+ /*4902*/ uint16(xReadIb),
+ /*4903*/ uint16(xArgXmm2),
+ /*4904*/ uint16(xArgImm8u),
+ /*4905*/ uint16(xMatch),
+ /*4906*/ uint16(xCondPrefix), 2,
+ 0x66, 4918,
+ 0x0, 4912,
+ /*4912*/ uint16(xSetOp), uint16(PSLLQ),
+ /*4914*/ uint16(xReadIb),
+ /*4915*/ uint16(xArgMm2),
+ /*4916*/ uint16(xArgImm8u),
+ /*4917*/ uint16(xMatch),
+ /*4918*/ uint16(xSetOp), uint16(PSLLQ),
+ /*4920*/ uint16(xReadIb),
+ /*4921*/ uint16(xArgXmm2),
+ /*4922*/ uint16(xArgImm8u),
+ /*4923*/ uint16(xMatch),
+ /*4924*/ uint16(xCondPrefix), 1,
+ 0x66, 4928,
+ /*4928*/ uint16(xSetOp), uint16(PSLLDQ),
+ /*4930*/ uint16(xReadIb),
+ /*4931*/ uint16(xArgXmm2),
+ /*4932*/ uint16(xArgImm8u),
+ /*4933*/ uint16(xMatch),
+ /*4934*/ uint16(xCondPrefix), 2,
+ 0x66, 4946,
+ 0x0, 4940,
+ /*4940*/ uint16(xSetOp), uint16(PCMPEQB),
+ /*4942*/ uint16(xReadSlashR),
+ /*4943*/ uint16(xArgMm),
+ /*4944*/ uint16(xArgMmM64),
+ /*4945*/ uint16(xMatch),
+ /*4946*/ uint16(xSetOp), uint16(PCMPEQB),
+ /*4948*/ uint16(xReadSlashR),
+ /*4949*/ uint16(xArgXmm1),
+ /*4950*/ uint16(xArgXmm2M128),
+ /*4951*/ uint16(xMatch),
+ /*4952*/ uint16(xCondPrefix), 2,
+ 0x66, 4964,
+ 0x0, 4958,
+ /*4958*/ uint16(xSetOp), uint16(PCMPEQW),
+ /*4960*/ uint16(xReadSlashR),
+ /*4961*/ uint16(xArgMm),
+ /*4962*/ uint16(xArgMmM64),
+ /*4963*/ uint16(xMatch),
+ /*4964*/ uint16(xSetOp), uint16(PCMPEQW),
+ /*4966*/ uint16(xReadSlashR),
+ /*4967*/ uint16(xArgXmm1),
+ /*4968*/ uint16(xArgXmm2M128),
+ /*4969*/ uint16(xMatch),
+ /*4970*/ uint16(xCondPrefix), 2,
+ 0x66, 4982,
+ 0x0, 4976,
+ /*4976*/ uint16(xSetOp), uint16(PCMPEQD),
+ /*4978*/ uint16(xReadSlashR),
+ /*4979*/ uint16(xArgMm),
+ /*4980*/ uint16(xArgMmM64),
+ /*4981*/ uint16(xMatch),
+ /*4982*/ uint16(xSetOp), uint16(PCMPEQD),
+ /*4984*/ uint16(xReadSlashR),
+ /*4985*/ uint16(xArgXmm1),
+ /*4986*/ uint16(xArgXmm2M128),
+ /*4987*/ uint16(xMatch),
+ /*4988*/ uint16(xSetOp), uint16(EMMS),
+ /*4990*/ uint16(xMatch),
+ /*4991*/ uint16(xCondPrefix), 2,
+ 0xF2, 5003,
+ 0x66, 4997,
+ /*4997*/ uint16(xSetOp), uint16(HADDPD),
+ /*4999*/ uint16(xReadSlashR),
+ /*5000*/ uint16(xArgXmm1),
+ /*5001*/ uint16(xArgXmm2M128),
+ /*5002*/ uint16(xMatch),
+ /*5003*/ uint16(xSetOp), uint16(HADDPS),
+ /*5005*/ uint16(xReadSlashR),
+ /*5006*/ uint16(xArgXmm1),
+ /*5007*/ uint16(xArgXmm2M128),
+ /*5008*/ uint16(xMatch),
+ /*5009*/ uint16(xCondPrefix), 2,
+ 0xF2, 5021,
+ 0x66, 5015,
+ /*5015*/ uint16(xSetOp), uint16(HSUBPD),
+ /*5017*/ uint16(xReadSlashR),
+ /*5018*/ uint16(xArgXmm1),
+ /*5019*/ uint16(xArgXmm2M128),
+ /*5020*/ uint16(xMatch),
+ /*5021*/ uint16(xSetOp), uint16(HSUBPS),
+ /*5023*/ uint16(xReadSlashR),
+ /*5024*/ uint16(xArgXmm1),
+ /*5025*/ uint16(xArgXmm2M128),
+ /*5026*/ uint16(xMatch),
+ /*5027*/ uint16(xCondIs64), 5030, 5076,
+ /*5030*/ uint16(xCondPrefix), 3,
+ 0xF3, 5070,
+ 0x66, 5054,
+ 0x0, 5038,
+ /*5038*/ uint16(xCondDataSize), 5042, 5048, 0,
+ /*5042*/ uint16(xSetOp), uint16(MOVD),
+ /*5044*/ uint16(xReadSlashR),
+ /*5045*/ uint16(xArgRM32),
+ /*5046*/ uint16(xArgMm),
+ /*5047*/ uint16(xMatch),
+ /*5048*/ uint16(xSetOp), uint16(MOVD),
+ /*5050*/ uint16(xReadSlashR),
+ /*5051*/ uint16(xArgRM32),
+ /*5052*/ uint16(xArgMm),
+ /*5053*/ uint16(xMatch),
+ /*5054*/ uint16(xCondDataSize), 5058, 5064, 0,
+ /*5058*/ uint16(xSetOp), uint16(MOVD),
+ /*5060*/ uint16(xReadSlashR),
+ /*5061*/ uint16(xArgRM32),
+ /*5062*/ uint16(xArgXmm),
+ /*5063*/ uint16(xMatch),
+ /*5064*/ uint16(xSetOp), uint16(MOVD),
+ /*5066*/ uint16(xReadSlashR),
+ /*5067*/ uint16(xArgRM32),
+ /*5068*/ uint16(xArgXmm),
+ /*5069*/ uint16(xMatch),
+ /*5070*/ uint16(xSetOp), uint16(MOVQ),
+ /*5072*/ uint16(xReadSlashR),
+ /*5073*/ uint16(xArgXmm1),
+ /*5074*/ uint16(xArgXmm2M64),
+ /*5075*/ uint16(xMatch),
+ /*5076*/ uint16(xCondPrefix), 3,
+ 0xF3, 5070,
+ 0x66, 5094,
+ 0x0, 5084,
+ /*5084*/ uint16(xCondDataSize), 5042, 5048, 5088,
+ /*5088*/ uint16(xSetOp), uint16(MOVQ),
+ /*5090*/ uint16(xReadSlashR),
+ /*5091*/ uint16(xArgRM64),
+ /*5092*/ uint16(xArgMm),
+ /*5093*/ uint16(xMatch),
+ /*5094*/ uint16(xCondDataSize), 5058, 5064, 5098,
+ /*5098*/ uint16(xSetOp), uint16(MOVQ),
+ /*5100*/ uint16(xReadSlashR),
+ /*5101*/ uint16(xArgRM64),
+ /*5102*/ uint16(xArgXmm),
+ /*5103*/ uint16(xMatch),
+ /*5104*/ uint16(xCondPrefix), 3,
+ 0xF3, 5124,
+ 0x66, 5118,
+ 0x0, 5112,
+ /*5112*/ uint16(xSetOp), uint16(MOVQ),
+ /*5114*/ uint16(xReadSlashR),
+ /*5115*/ uint16(xArgMmM64),
+ /*5116*/ uint16(xArgMm),
+ /*5117*/ uint16(xMatch),
+ /*5118*/ uint16(xSetOp), uint16(MOVDQA),
+ /*5120*/ uint16(xReadSlashR),
+ /*5121*/ uint16(xArgXmm2M128),
+ /*5122*/ uint16(xArgXmm1),
+ /*5123*/ uint16(xMatch),
+ /*5124*/ uint16(xSetOp), uint16(MOVDQU),
+ /*5126*/ uint16(xReadSlashR),
+ /*5127*/ uint16(xArgXmm2M128),
+ /*5128*/ uint16(xArgXmm1),
+ /*5129*/ uint16(xMatch),
+ /*5130*/ uint16(xCondIs64), 5133, 5147,
+ /*5133*/ uint16(xCondDataSize), 5137, 5142, 0,
+ /*5137*/ uint16(xSetOp), uint16(JO),
+ /*5139*/ uint16(xReadCw),
+ /*5140*/ uint16(xArgRel16),
+ /*5141*/ uint16(xMatch),
+ /*5142*/ uint16(xSetOp), uint16(JO),
+ /*5144*/ uint16(xReadCd),
+ /*5145*/ uint16(xArgRel32),
+ /*5146*/ uint16(xMatch),
+ /*5147*/ uint16(xCondDataSize), 5151, 5142, 5156,
+ /*5151*/ uint16(xSetOp), uint16(JO),
+ /*5153*/ uint16(xReadCd),
+ /*5154*/ uint16(xArgRel32),
+ /*5155*/ uint16(xMatch),
+ /*5156*/ uint16(xSetOp), uint16(JO),
+ /*5158*/ uint16(xReadCd),
+ /*5159*/ uint16(xArgRel32),
+ /*5160*/ uint16(xMatch),
+ /*5161*/ uint16(xCondIs64), 5164, 5178,
+ /*5164*/ uint16(xCondDataSize), 5168, 5173, 0,
+ /*5168*/ uint16(xSetOp), uint16(JNO),
+ /*5170*/ uint16(xReadCw),
+ /*5171*/ uint16(xArgRel16),
+ /*5172*/ uint16(xMatch),
+ /*5173*/ uint16(xSetOp), uint16(JNO),
+ /*5175*/ uint16(xReadCd),
+ /*5176*/ uint16(xArgRel32),
+ /*5177*/ uint16(xMatch),
+ /*5178*/ uint16(xCondDataSize), 5182, 5173, 5187,
+ /*5182*/ uint16(xSetOp), uint16(JNO),
+ /*5184*/ uint16(xReadCd),
+ /*5185*/ uint16(xArgRel32),
+ /*5186*/ uint16(xMatch),
+ /*5187*/ uint16(xSetOp), uint16(JNO),
+ /*5189*/ uint16(xReadCd),
+ /*5190*/ uint16(xArgRel32),
+ /*5191*/ uint16(xMatch),
+ /*5192*/ uint16(xCondIs64), 5195, 5209,
+ /*5195*/ uint16(xCondDataSize), 5199, 5204, 0,
+ /*5199*/ uint16(xSetOp), uint16(JB),
+ /*5201*/ uint16(xReadCw),
+ /*5202*/ uint16(xArgRel16),
+ /*5203*/ uint16(xMatch),
+ /*5204*/ uint16(xSetOp), uint16(JB),
+ /*5206*/ uint16(xReadCd),
+ /*5207*/ uint16(xArgRel32),
+ /*5208*/ uint16(xMatch),
+ /*5209*/ uint16(xCondDataSize), 5213, 5204, 5218,
+ /*5213*/ uint16(xSetOp), uint16(JB),
+ /*5215*/ uint16(xReadCd),
+ /*5216*/ uint16(xArgRel32),
+ /*5217*/ uint16(xMatch),
+ /*5218*/ uint16(xSetOp), uint16(JB),
+ /*5220*/ uint16(xReadCd),
+ /*5221*/ uint16(xArgRel32),
+ /*5222*/ uint16(xMatch),
+ /*5223*/ uint16(xCondIs64), 5226, 5240,
+ /*5226*/ uint16(xCondDataSize), 5230, 5235, 0,
+ /*5230*/ uint16(xSetOp), uint16(JAE),
+ /*5232*/ uint16(xReadCw),
+ /*5233*/ uint16(xArgRel16),
+ /*5234*/ uint16(xMatch),
+ /*5235*/ uint16(xSetOp), uint16(JAE),
+ /*5237*/ uint16(xReadCd),
+ /*5238*/ uint16(xArgRel32),
+ /*5239*/ uint16(xMatch),
+ /*5240*/ uint16(xCondDataSize), 5244, 5235, 5249,
+ /*5244*/ uint16(xSetOp), uint16(JAE),
+ /*5246*/ uint16(xReadCd),
+ /*5247*/ uint16(xArgRel32),
+ /*5248*/ uint16(xMatch),
+ /*5249*/ uint16(xSetOp), uint16(JAE),
+ /*5251*/ uint16(xReadCd),
+ /*5252*/ uint16(xArgRel32),
+ /*5253*/ uint16(xMatch),
+ /*5254*/ uint16(xCondIs64), 5257, 5271,
+ /*5257*/ uint16(xCondDataSize), 5261, 5266, 0,
+ /*5261*/ uint16(xSetOp), uint16(JE),
+ /*5263*/ uint16(xReadCw),
+ /*5264*/ uint16(xArgRel16),
+ /*5265*/ uint16(xMatch),
+ /*5266*/ uint16(xSetOp), uint16(JE),
+ /*5268*/ uint16(xReadCd),
+ /*5269*/ uint16(xArgRel32),
+ /*5270*/ uint16(xMatch),
+ /*5271*/ uint16(xCondDataSize), 5275, 5266, 5280,
+ /*5275*/ uint16(xSetOp), uint16(JE),
+ /*5277*/ uint16(xReadCd),
+ /*5278*/ uint16(xArgRel32),
+ /*5279*/ uint16(xMatch),
+ /*5280*/ uint16(xSetOp), uint16(JE),
+ /*5282*/ uint16(xReadCd),
+ /*5283*/ uint16(xArgRel32),
+ /*5284*/ uint16(xMatch),
+ /*5285*/ uint16(xCondIs64), 5288, 5302,
+ /*5288*/ uint16(xCondDataSize), 5292, 5297, 0,
+ /*5292*/ uint16(xSetOp), uint16(JNE),
+ /*5294*/ uint16(xReadCw),
+ /*5295*/ uint16(xArgRel16),
+ /*5296*/ uint16(xMatch),
+ /*5297*/ uint16(xSetOp), uint16(JNE),
+ /*5299*/ uint16(xReadCd),
+ /*5300*/ uint16(xArgRel32),
+ /*5301*/ uint16(xMatch),
+ /*5302*/ uint16(xCondDataSize), 5306, 5297, 5311,
+ /*5306*/ uint16(xSetOp), uint16(JNE),
+ /*5308*/ uint16(xReadCd),
+ /*5309*/ uint16(xArgRel32),
+ /*5310*/ uint16(xMatch),
+ /*5311*/ uint16(xSetOp), uint16(JNE),
+ /*5313*/ uint16(xReadCd),
+ /*5314*/ uint16(xArgRel32),
+ /*5315*/ uint16(xMatch),
+ /*5316*/ uint16(xCondIs64), 5319, 5333,
+ /*5319*/ uint16(xCondDataSize), 5323, 5328, 0,
+ /*5323*/ uint16(xSetOp), uint16(JBE),
+ /*5325*/ uint16(xReadCw),
+ /*5326*/ uint16(xArgRel16),
+ /*5327*/ uint16(xMatch),
+ /*5328*/ uint16(xSetOp), uint16(JBE),
+ /*5330*/ uint16(xReadCd),
+ /*5331*/ uint16(xArgRel32),
+ /*5332*/ uint16(xMatch),
+ /*5333*/ uint16(xCondDataSize), 5337, 5328, 5342,
+ /*5337*/ uint16(xSetOp), uint16(JBE),
+ /*5339*/ uint16(xReadCd),
+ /*5340*/ uint16(xArgRel32),
+ /*5341*/ uint16(xMatch),
+ /*5342*/ uint16(xSetOp), uint16(JBE),
+ /*5344*/ uint16(xReadCd),
+ /*5345*/ uint16(xArgRel32),
+ /*5346*/ uint16(xMatch),
+ /*5347*/ uint16(xCondIs64), 5350, 5364,
+ /*5350*/ uint16(xCondDataSize), 5354, 5359, 0,
+ /*5354*/ uint16(xSetOp), uint16(JA),
+ /*5356*/ uint16(xReadCw),
+ /*5357*/ uint16(xArgRel16),
+ /*5358*/ uint16(xMatch),
+ /*5359*/ uint16(xSetOp), uint16(JA),
+ /*5361*/ uint16(xReadCd),
+ /*5362*/ uint16(xArgRel32),
+ /*5363*/ uint16(xMatch),
+ /*5364*/ uint16(xCondDataSize), 5368, 5359, 5373,
+ /*5368*/ uint16(xSetOp), uint16(JA),
+ /*5370*/ uint16(xReadCd),
+ /*5371*/ uint16(xArgRel32),
+ /*5372*/ uint16(xMatch),
+ /*5373*/ uint16(xSetOp), uint16(JA),
+ /*5375*/ uint16(xReadCd),
+ /*5376*/ uint16(xArgRel32),
+ /*5377*/ uint16(xMatch),
+ /*5378*/ uint16(xCondIs64), 5381, 5395,
+ /*5381*/ uint16(xCondDataSize), 5385, 5390, 0,
+ /*5385*/ uint16(xSetOp), uint16(JS),
+ /*5387*/ uint16(xReadCw),
+ /*5388*/ uint16(xArgRel16),
+ /*5389*/ uint16(xMatch),
+ /*5390*/ uint16(xSetOp), uint16(JS),
+ /*5392*/ uint16(xReadCd),
+ /*5393*/ uint16(xArgRel32),
+ /*5394*/ uint16(xMatch),
+ /*5395*/ uint16(xCondDataSize), 5399, 5390, 5404,
+ /*5399*/ uint16(xSetOp), uint16(JS),
+ /*5401*/ uint16(xReadCd),
+ /*5402*/ uint16(xArgRel32),
+ /*5403*/ uint16(xMatch),
+ /*5404*/ uint16(xSetOp), uint16(JS),
+ /*5406*/ uint16(xReadCd),
+ /*5407*/ uint16(xArgRel32),
+ /*5408*/ uint16(xMatch),
+ /*5409*/ uint16(xCondIs64), 5412, 5426,
+ /*5412*/ uint16(xCondDataSize), 5416, 5421, 0,
+ /*5416*/ uint16(xSetOp), uint16(JNS),
+ /*5418*/ uint16(xReadCw),
+ /*5419*/ uint16(xArgRel16),
+ /*5420*/ uint16(xMatch),
+ /*5421*/ uint16(xSetOp), uint16(JNS),
+ /*5423*/ uint16(xReadCd),
+ /*5424*/ uint16(xArgRel32),
+ /*5425*/ uint16(xMatch),
+ /*5426*/ uint16(xCondDataSize), 5430, 5421, 5435,
+ /*5430*/ uint16(xSetOp), uint16(JNS),
+ /*5432*/ uint16(xReadCd),
+ /*5433*/ uint16(xArgRel32),
+ /*5434*/ uint16(xMatch),
+ /*5435*/ uint16(xSetOp), uint16(JNS),
+ /*5437*/ uint16(xReadCd),
+ /*5438*/ uint16(xArgRel32),
+ /*5439*/ uint16(xMatch),
+ /*5440*/ uint16(xCondIs64), 5443, 5457,
+ /*5443*/ uint16(xCondDataSize), 5447, 5452, 0,
+ /*5447*/ uint16(xSetOp), uint16(JP),
+ /*5449*/ uint16(xReadCw),
+ /*5450*/ uint16(xArgRel16),
+ /*5451*/ uint16(xMatch),
+ /*5452*/ uint16(xSetOp), uint16(JP),
+ /*5454*/ uint16(xReadCd),
+ /*5455*/ uint16(xArgRel32),
+ /*5456*/ uint16(xMatch),
+ /*5457*/ uint16(xCondDataSize), 5461, 5452, 5466,
+ /*5461*/ uint16(xSetOp), uint16(JP),
+ /*5463*/ uint16(xReadCd),
+ /*5464*/ uint16(xArgRel32),
+ /*5465*/ uint16(xMatch),
+ /*5466*/ uint16(xSetOp), uint16(JP),
+ /*5468*/ uint16(xReadCd),
+ /*5469*/ uint16(xArgRel32),
+ /*5470*/ uint16(xMatch),
+ /*5471*/ uint16(xCondIs64), 5474, 5488,
+ /*5474*/ uint16(xCondDataSize), 5478, 5483, 0,
+ /*5478*/ uint16(xSetOp), uint16(JNP),
+ /*5480*/ uint16(xReadCw),
+ /*5481*/ uint16(xArgRel16),
+ /*5482*/ uint16(xMatch),
+ /*5483*/ uint16(xSetOp), uint16(JNP),
+ /*5485*/ uint16(xReadCd),
+ /*5486*/ uint16(xArgRel32),
+ /*5487*/ uint16(xMatch),
+ /*5488*/ uint16(xCondDataSize), 5492, 5483, 5497,
+ /*5492*/ uint16(xSetOp), uint16(JNP),
+ /*5494*/ uint16(xReadCd),
+ /*5495*/ uint16(xArgRel32),
+ /*5496*/ uint16(xMatch),
+ /*5497*/ uint16(xSetOp), uint16(JNP),
+ /*5499*/ uint16(xReadCd),
+ /*5500*/ uint16(xArgRel32),
+ /*5501*/ uint16(xMatch),
+ /*5502*/ uint16(xCondIs64), 5505, 5519,
+ /*5505*/ uint16(xCondDataSize), 5509, 5514, 0,
+ /*5509*/ uint16(xSetOp), uint16(JL),
+ /*5511*/ uint16(xReadCw),
+ /*5512*/ uint16(xArgRel16),
+ /*5513*/ uint16(xMatch),
+ /*5514*/ uint16(xSetOp), uint16(JL),
+ /*5516*/ uint16(xReadCd),
+ /*5517*/ uint16(xArgRel32),
+ /*5518*/ uint16(xMatch),
+ /*5519*/ uint16(xCondDataSize), 5523, 5514, 5528,
+ /*5523*/ uint16(xSetOp), uint16(JL),
+ /*5525*/ uint16(xReadCd),
+ /*5526*/ uint16(xArgRel32),
+ /*5527*/ uint16(xMatch),
+ /*5528*/ uint16(xSetOp), uint16(JL),
+ /*5530*/ uint16(xReadCd),
+ /*5531*/ uint16(xArgRel32),
+ /*5532*/ uint16(xMatch),
+ /*5533*/ uint16(xCondIs64), 5536, 5550,
+ /*5536*/ uint16(xCondDataSize), 5540, 5545, 0,
+ /*5540*/ uint16(xSetOp), uint16(JGE),
+ /*5542*/ uint16(xReadCw),
+ /*5543*/ uint16(xArgRel16),
+ /*5544*/ uint16(xMatch),
+ /*5545*/ uint16(xSetOp), uint16(JGE),
+ /*5547*/ uint16(xReadCd),
+ /*5548*/ uint16(xArgRel32),
+ /*5549*/ uint16(xMatch),
+ /*5550*/ uint16(xCondDataSize), 5554, 5545, 5559,
+ /*5554*/ uint16(xSetOp), uint16(JGE),
+ /*5556*/ uint16(xReadCd),
+ /*5557*/ uint16(xArgRel32),
+ /*5558*/ uint16(xMatch),
+ /*5559*/ uint16(xSetOp), uint16(JGE),
+ /*5561*/ uint16(xReadCd),
+ /*5562*/ uint16(xArgRel32),
+ /*5563*/ uint16(xMatch),
+ /*5564*/ uint16(xCondIs64), 5567, 5581,
+ /*5567*/ uint16(xCondDataSize), 5571, 5576, 0,
+ /*5571*/ uint16(xSetOp), uint16(JLE),
+ /*5573*/ uint16(xReadCw),
+ /*5574*/ uint16(xArgRel16),
+ /*5575*/ uint16(xMatch),
+ /*5576*/ uint16(xSetOp), uint16(JLE),
+ /*5578*/ uint16(xReadCd),
+ /*5579*/ uint16(xArgRel32),
+ /*5580*/ uint16(xMatch),
+ /*5581*/ uint16(xCondDataSize), 5585, 5576, 5590,
+ /*5585*/ uint16(xSetOp), uint16(JLE),
+ /*5587*/ uint16(xReadCd),
+ /*5588*/ uint16(xArgRel32),
+ /*5589*/ uint16(xMatch),
+ /*5590*/ uint16(xSetOp), uint16(JLE),
+ /*5592*/ uint16(xReadCd),
+ /*5593*/ uint16(xArgRel32),
+ /*5594*/ uint16(xMatch),
+ /*5595*/ uint16(xCondIs64), 5598, 5612,
+ /*5598*/ uint16(xCondDataSize), 5602, 5607, 0,
+ /*5602*/ uint16(xSetOp), uint16(JG),
+ /*5604*/ uint16(xReadCw),
+ /*5605*/ uint16(xArgRel16),
+ /*5606*/ uint16(xMatch),
+ /*5607*/ uint16(xSetOp), uint16(JG),
+ /*5609*/ uint16(xReadCd),
+ /*5610*/ uint16(xArgRel32),
+ /*5611*/ uint16(xMatch),
+ /*5612*/ uint16(xCondDataSize), 5616, 5607, 5621,
+ /*5616*/ uint16(xSetOp), uint16(JG),
+ /*5618*/ uint16(xReadCd),
+ /*5619*/ uint16(xArgRel32),
+ /*5620*/ uint16(xMatch),
+ /*5621*/ uint16(xSetOp), uint16(JG),
+ /*5623*/ uint16(xReadCd),
+ /*5624*/ uint16(xArgRel32),
+ /*5625*/ uint16(xMatch),
+ /*5626*/ uint16(xSetOp), uint16(SETO),
+ /*5628*/ uint16(xReadSlashR),
+ /*5629*/ uint16(xArgRM8),
+ /*5630*/ uint16(xMatch),
+ /*5631*/ uint16(xSetOp), uint16(SETNO),
+ /*5633*/ uint16(xReadSlashR),
+ /*5634*/ uint16(xArgRM8),
+ /*5635*/ uint16(xMatch),
+ /*5636*/ uint16(xSetOp), uint16(SETB),
+ /*5638*/ uint16(xReadSlashR),
+ /*5639*/ uint16(xArgRM8),
+ /*5640*/ uint16(xMatch),
+ /*5641*/ uint16(xSetOp), uint16(SETAE),
+ /*5643*/ uint16(xReadSlashR),
+ /*5644*/ uint16(xArgRM8),
+ /*5645*/ uint16(xMatch),
+ /*5646*/ uint16(xSetOp), uint16(SETE),
+ /*5648*/ uint16(xReadSlashR),
+ /*5649*/ uint16(xArgRM8),
+ /*5650*/ uint16(xMatch),
+ /*5651*/ uint16(xSetOp), uint16(SETNE),
+ /*5653*/ uint16(xReadSlashR),
+ /*5654*/ uint16(xArgRM8),
+ /*5655*/ uint16(xMatch),
+ /*5656*/ uint16(xSetOp), uint16(SETBE),
+ /*5658*/ uint16(xReadSlashR),
+ /*5659*/ uint16(xArgRM8),
+ /*5660*/ uint16(xMatch),
+ /*5661*/ uint16(xSetOp), uint16(SETA),
+ /*5663*/ uint16(xReadSlashR),
+ /*5664*/ uint16(xArgRM8),
+ /*5665*/ uint16(xMatch),
+ /*5666*/ uint16(xSetOp), uint16(SETS),
+ /*5668*/ uint16(xReadSlashR),
+ /*5669*/ uint16(xArgRM8),
+ /*5670*/ uint16(xMatch),
+ /*5671*/ uint16(xSetOp), uint16(SETNS),
+ /*5673*/ uint16(xReadSlashR),
+ /*5674*/ uint16(xArgRM8),
+ /*5675*/ uint16(xMatch),
+ /*5676*/ uint16(xSetOp), uint16(SETP),
+ /*5678*/ uint16(xReadSlashR),
+ /*5679*/ uint16(xArgRM8),
+ /*5680*/ uint16(xMatch),
+ /*5681*/ uint16(xSetOp), uint16(SETNP),
+ /*5683*/ uint16(xReadSlashR),
+ /*5684*/ uint16(xArgRM8),
+ /*5685*/ uint16(xMatch),
+ /*5686*/ uint16(xSetOp), uint16(SETL),
+ /*5688*/ uint16(xReadSlashR),
+ /*5689*/ uint16(xArgRM8),
+ /*5690*/ uint16(xMatch),
+ /*5691*/ uint16(xSetOp), uint16(SETGE),
+ /*5693*/ uint16(xReadSlashR),
+ /*5694*/ uint16(xArgRM8),
+ /*5695*/ uint16(xMatch),
+ /*5696*/ uint16(xSetOp), uint16(SETLE),
+ /*5698*/ uint16(xReadSlashR),
+ /*5699*/ uint16(xArgRM8),
+ /*5700*/ uint16(xMatch),
+ /*5701*/ uint16(xSetOp), uint16(SETG),
+ /*5703*/ uint16(xReadSlashR),
+ /*5704*/ uint16(xArgRM8),
+ /*5705*/ uint16(xMatch),
+ /*5706*/ uint16(xSetOp), uint16(PUSH),
+ /*5708*/ uint16(xArgFS),
+ /*5709*/ uint16(xMatch),
+ /*5710*/ uint16(xCondIs64), 5713, 5725,
+ /*5713*/ uint16(xCondDataSize), 5717, 5721, 0,
+ /*5717*/ uint16(xSetOp), uint16(POP),
+ /*5719*/ uint16(xArgFS),
+ /*5720*/ uint16(xMatch),
+ /*5721*/ uint16(xSetOp), uint16(POP),
+ /*5723*/ uint16(xArgFS),
+ /*5724*/ uint16(xMatch),
+ /*5725*/ uint16(xCondDataSize), 5717, 5729, 5733,
+ /*5729*/ uint16(xSetOp), uint16(POP),
+ /*5731*/ uint16(xArgFS),
+ /*5732*/ uint16(xMatch),
+ /*5733*/ uint16(xSetOp), uint16(POP),
+ /*5735*/ uint16(xArgFS),
+ /*5736*/ uint16(xMatch),
+ /*5737*/ uint16(xSetOp), uint16(CPUID),
+ /*5739*/ uint16(xMatch),
+ /*5740*/ uint16(xCondIs64), 5743, 5759,
+ /*5743*/ uint16(xCondDataSize), 5747, 5753, 0,
+ /*5747*/ uint16(xSetOp), uint16(BT),
+ /*5749*/ uint16(xReadSlashR),
+ /*5750*/ uint16(xArgRM16),
+ /*5751*/ uint16(xArgR16),
+ /*5752*/ uint16(xMatch),
+ /*5753*/ uint16(xSetOp), uint16(BT),
+ /*5755*/ uint16(xReadSlashR),
+ /*5756*/ uint16(xArgRM32),
+ /*5757*/ uint16(xArgR32),
+ /*5758*/ uint16(xMatch),
+ /*5759*/ uint16(xCondDataSize), 5747, 5753, 5763,
+ /*5763*/ uint16(xSetOp), uint16(BT),
+ /*5765*/ uint16(xReadSlashR),
+ /*5766*/ uint16(xArgRM64),
+ /*5767*/ uint16(xArgR64),
+ /*5768*/ uint16(xMatch),
+ /*5769*/ uint16(xCondIs64), 5772, 5792,
+ /*5772*/ uint16(xCondDataSize), 5776, 5784, 0,
+ /*5776*/ uint16(xSetOp), uint16(SHLD),
+ /*5778*/ uint16(xReadSlashR),
+ /*5779*/ uint16(xReadIb),
+ /*5780*/ uint16(xArgRM16),
+ /*5781*/ uint16(xArgR16),
+ /*5782*/ uint16(xArgImm8u),
+ /*5783*/ uint16(xMatch),
+ /*5784*/ uint16(xSetOp), uint16(SHLD),
+ /*5786*/ uint16(xReadSlashR),
+ /*5787*/ uint16(xReadIb),
+ /*5788*/ uint16(xArgRM32),
+ /*5789*/ uint16(xArgR32),
+ /*5790*/ uint16(xArgImm8u),
+ /*5791*/ uint16(xMatch),
+ /*5792*/ uint16(xCondDataSize), 5776, 5784, 5796,
+ /*5796*/ uint16(xSetOp), uint16(SHLD),
+ /*5798*/ uint16(xReadSlashR),
+ /*5799*/ uint16(xReadIb),
+ /*5800*/ uint16(xArgRM64),
+ /*5801*/ uint16(xArgR64),
+ /*5802*/ uint16(xArgImm8u),
+ /*5803*/ uint16(xMatch),
+ /*5804*/ uint16(xCondIs64), 5807, 5825,
+ /*5807*/ uint16(xCondDataSize), 5811, 5818, 0,
+ /*5811*/ uint16(xSetOp), uint16(SHLD),
+ /*5813*/ uint16(xReadSlashR),
+ /*5814*/ uint16(xArgRM16),
+ /*5815*/ uint16(xArgR16),
+ /*5816*/ uint16(xArgCL),
+ /*5817*/ uint16(xMatch),
+ /*5818*/ uint16(xSetOp), uint16(SHLD),
+ /*5820*/ uint16(xReadSlashR),
+ /*5821*/ uint16(xArgRM32),
+ /*5822*/ uint16(xArgR32),
+ /*5823*/ uint16(xArgCL),
+ /*5824*/ uint16(xMatch),
+ /*5825*/ uint16(xCondDataSize), 5811, 5818, 5829,
+ /*5829*/ uint16(xSetOp), uint16(SHLD),
+ /*5831*/ uint16(xReadSlashR),
+ /*5832*/ uint16(xArgRM64),
+ /*5833*/ uint16(xArgR64),
+ /*5834*/ uint16(xArgCL),
+ /*5835*/ uint16(xMatch),
+ /*5836*/ uint16(xSetOp), uint16(PUSH),
+ /*5838*/ uint16(xArgGS),
+ /*5839*/ uint16(xMatch),
+ /*5840*/ uint16(xCondIs64), 5843, 5855,
+ /*5843*/ uint16(xCondDataSize), 5847, 5851, 0,
+ /*5847*/ uint16(xSetOp), uint16(POP),
+ /*5849*/ uint16(xArgGS),
+ /*5850*/ uint16(xMatch),
+ /*5851*/ uint16(xSetOp), uint16(POP),
+ /*5853*/ uint16(xArgGS),
+ /*5854*/ uint16(xMatch),
+ /*5855*/ uint16(xCondDataSize), 5847, 5859, 5863,
+ /*5859*/ uint16(xSetOp), uint16(POP),
+ /*5861*/ uint16(xArgGS),
+ /*5862*/ uint16(xMatch),
+ /*5863*/ uint16(xSetOp), uint16(POP),
+ /*5865*/ uint16(xArgGS),
+ /*5866*/ uint16(xMatch),
+ /*5867*/ uint16(xSetOp), uint16(RSM),
+ /*5869*/ uint16(xMatch),
+ /*5870*/ uint16(xCondIs64), 5873, 5889,
+ /*5873*/ uint16(xCondDataSize), 5877, 5883, 0,
+ /*5877*/ uint16(xSetOp), uint16(BTS),
+ /*5879*/ uint16(xReadSlashR),
+ /*5880*/ uint16(xArgRM16),
+ /*5881*/ uint16(xArgR16),
+ /*5882*/ uint16(xMatch),
+ /*5883*/ uint16(xSetOp), uint16(BTS),
+ /*5885*/ uint16(xReadSlashR),
+ /*5886*/ uint16(xArgRM32),
+ /*5887*/ uint16(xArgR32),
+ /*5888*/ uint16(xMatch),
+ /*5889*/ uint16(xCondDataSize), 5877, 5883, 5893,
+ /*5893*/ uint16(xSetOp), uint16(BTS),
+ /*5895*/ uint16(xReadSlashR),
+ /*5896*/ uint16(xArgRM64),
+ /*5897*/ uint16(xArgR64),
+ /*5898*/ uint16(xMatch),
+ /*5899*/ uint16(xCondIs64), 5902, 5922,
+ /*5902*/ uint16(xCondDataSize), 5906, 5914, 0,
+ /*5906*/ uint16(xSetOp), uint16(SHRD),
+ /*5908*/ uint16(xReadSlashR),
+ /*5909*/ uint16(xReadIb),
+ /*5910*/ uint16(xArgRM16),
+ /*5911*/ uint16(xArgR16),
+ /*5912*/ uint16(xArgImm8u),
+ /*5913*/ uint16(xMatch),
+ /*5914*/ uint16(xSetOp), uint16(SHRD),
+ /*5916*/ uint16(xReadSlashR),
+ /*5917*/ uint16(xReadIb),
+ /*5918*/ uint16(xArgRM32),
+ /*5919*/ uint16(xArgR32),
+ /*5920*/ uint16(xArgImm8u),
+ /*5921*/ uint16(xMatch),
+ /*5922*/ uint16(xCondDataSize), 5906, 5914, 5926,
+ /*5926*/ uint16(xSetOp), uint16(SHRD),
+ /*5928*/ uint16(xReadSlashR),
+ /*5929*/ uint16(xReadIb),
+ /*5930*/ uint16(xArgRM64),
+ /*5931*/ uint16(xArgR64),
+ /*5932*/ uint16(xArgImm8u),
+ /*5933*/ uint16(xMatch),
+ /*5934*/ uint16(xCondIs64), 5937, 5955,
+ /*5937*/ uint16(xCondDataSize), 5941, 5948, 0,
+ /*5941*/ uint16(xSetOp), uint16(SHRD),
+ /*5943*/ uint16(xReadSlashR),
+ /*5944*/ uint16(xArgRM16),
+ /*5945*/ uint16(xArgR16),
+ /*5946*/ uint16(xArgCL),
+ /*5947*/ uint16(xMatch),
+ /*5948*/ uint16(xSetOp), uint16(SHRD),
+ /*5950*/ uint16(xReadSlashR),
+ /*5951*/ uint16(xArgRM32),
+ /*5952*/ uint16(xArgR32),
+ /*5953*/ uint16(xArgCL),
+ /*5954*/ uint16(xMatch),
+ /*5955*/ uint16(xCondDataSize), 5941, 5948, 5959,
+ /*5959*/ uint16(xSetOp), uint16(SHRD),
+ /*5961*/ uint16(xReadSlashR),
+ /*5962*/ uint16(xArgRM64),
+ /*5963*/ uint16(xArgR64),
+ /*5964*/ uint16(xArgCL),
+ /*5965*/ uint16(xMatch),
+ /*5966*/ uint16(xCondByte), 3,
+ 0xE8, 6215,
+ 0xF0, 6218,
+ 0xF8, 6221,
+ /*5974*/ uint16(xCondSlashR),
+ 5983, // 0
+ 6037, // 1
+ 6091, // 2
+ 6120, // 3
+ 6149, // 4
+ 6172, // 5
+ 6195, // 6
+ 6211, // 7
+ /*5983*/ uint16(xCondIs64), 5986, 5998,
+ /*5986*/ uint16(xCondDataSize), 5990, 5994, 0,
+ /*5990*/ uint16(xSetOp), uint16(FXSAVE),
+ /*5992*/ uint16(xArgM512byte),
+ /*5993*/ uint16(xMatch),
+ /*5994*/ uint16(xSetOp), uint16(FXSAVE),
+ /*5996*/ uint16(xArgM512byte),
+ /*5997*/ uint16(xMatch),
+ /*5998*/ uint16(xCondPrefix), 2,
+ 0xF3, 6012,
+ 0x0, 6004,
+ /*6004*/ uint16(xCondDataSize), 5990, 5994, 6008,
+ /*6008*/ uint16(xSetOp), uint16(FXSAVE64),
+ /*6010*/ uint16(xArgM512byte),
+ /*6011*/ uint16(xMatch),
+ /*6012*/ uint16(xCondDataSize), 6016, 6023, 6030,
+ /*6016*/ uint16(xCondIsMem), 6019, 0,
+ /*6019*/ uint16(xSetOp), uint16(RDFSBASE),
+ /*6021*/ uint16(xArgRM32),
+ /*6022*/ uint16(xMatch),
+ /*6023*/ uint16(xCondIsMem), 6026, 0,
+ /*6026*/ uint16(xSetOp), uint16(RDFSBASE),
+ /*6028*/ uint16(xArgRM32),
+ /*6029*/ uint16(xMatch),
+ /*6030*/ uint16(xCondIsMem), 6033, 0,
+ /*6033*/ uint16(xSetOp), uint16(RDFSBASE),
+ /*6035*/ uint16(xArgRM64),
+ /*6036*/ uint16(xMatch),
+ /*6037*/ uint16(xCondIs64), 6040, 6052,
+ /*6040*/ uint16(xCondDataSize), 6044, 6048, 0,
+ /*6044*/ uint16(xSetOp), uint16(FXRSTOR),
+ /*6046*/ uint16(xArgM512byte),
+ /*6047*/ uint16(xMatch),
+ /*6048*/ uint16(xSetOp), uint16(FXRSTOR),
+ /*6050*/ uint16(xArgM512byte),
+ /*6051*/ uint16(xMatch),
+ /*6052*/ uint16(xCondPrefix), 2,
+ 0xF3, 6066,
+ 0x0, 6058,
+ /*6058*/ uint16(xCondDataSize), 6044, 6048, 6062,
+ /*6062*/ uint16(xSetOp), uint16(FXRSTOR64),
+ /*6064*/ uint16(xArgM512byte),
+ /*6065*/ uint16(xMatch),
+ /*6066*/ uint16(xCondDataSize), 6070, 6077, 6084,
+ /*6070*/ uint16(xCondIsMem), 6073, 0,
+ /*6073*/ uint16(xSetOp), uint16(RDGSBASE),
+ /*6075*/ uint16(xArgRM32),
+ /*6076*/ uint16(xMatch),
+ /*6077*/ uint16(xCondIsMem), 6080, 0,
+ /*6080*/ uint16(xSetOp), uint16(RDGSBASE),
+ /*6082*/ uint16(xArgRM32),
+ /*6083*/ uint16(xMatch),
+ /*6084*/ uint16(xCondIsMem), 6087, 0,
+ /*6087*/ uint16(xSetOp), uint16(RDGSBASE),
+ /*6089*/ uint16(xArgRM64),
+ /*6090*/ uint16(xMatch),
+ /*6091*/ uint16(xCondIs64), 6094, 6098,
+ /*6094*/ uint16(xSetOp), uint16(LDMXCSR),
+ /*6096*/ uint16(xArgM32),
+ /*6097*/ uint16(xMatch),
+ /*6098*/ uint16(xCondPrefix), 2,
+ 0xF3, 6104,
+ 0x0, 6094,
+ /*6104*/ uint16(xCondDataSize), 6108, 6112, 6116,
+ /*6108*/ uint16(xSetOp), uint16(WRFSBASE),
+ /*6110*/ uint16(xArgRM32),
+ /*6111*/ uint16(xMatch),
+ /*6112*/ uint16(xSetOp), uint16(WRFSBASE),
+ /*6114*/ uint16(xArgRM32),
+ /*6115*/ uint16(xMatch),
+ /*6116*/ uint16(xSetOp), uint16(WRFSBASE),
+ /*6118*/ uint16(xArgRM64),
+ /*6119*/ uint16(xMatch),
+ /*6120*/ uint16(xCondIs64), 6123, 6127,
+ /*6123*/ uint16(xSetOp), uint16(STMXCSR),
+ /*6125*/ uint16(xArgM32),
+ /*6126*/ uint16(xMatch),
+ /*6127*/ uint16(xCondPrefix), 2,
+ 0xF3, 6133,
+ 0x0, 6123,
+ /*6133*/ uint16(xCondDataSize), 6137, 6141, 6145,
+ /*6137*/ uint16(xSetOp), uint16(WRGSBASE),
+ /*6139*/ uint16(xArgRM32),
+ /*6140*/ uint16(xMatch),
+ /*6141*/ uint16(xSetOp), uint16(WRGSBASE),
+ /*6143*/ uint16(xArgRM32),
+ /*6144*/ uint16(xMatch),
+ /*6145*/ uint16(xSetOp), uint16(WRGSBASE),
+ /*6147*/ uint16(xArgRM64),
+ /*6148*/ uint16(xMatch),
+ /*6149*/ uint16(xCondIs64), 6152, 6164,
+ /*6152*/ uint16(xCondDataSize), 6156, 6160, 0,
+ /*6156*/ uint16(xSetOp), uint16(XSAVE),
+ /*6158*/ uint16(xArgMem),
+ /*6159*/ uint16(xMatch),
+ /*6160*/ uint16(xSetOp), uint16(XSAVE),
+ /*6162*/ uint16(xArgMem),
+ /*6163*/ uint16(xMatch),
+ /*6164*/ uint16(xCondDataSize), 6156, 6160, 6168,
+ /*6168*/ uint16(xSetOp), uint16(XSAVE64),
+ /*6170*/ uint16(xArgMem),
+ /*6171*/ uint16(xMatch),
+ /*6172*/ uint16(xCondIs64), 6175, 6187,
+ /*6175*/ uint16(xCondDataSize), 6179, 6183, 0,
+ /*6179*/ uint16(xSetOp), uint16(XRSTOR),
+ /*6181*/ uint16(xArgMem),
+ /*6182*/ uint16(xMatch),
+ /*6183*/ uint16(xSetOp), uint16(XRSTOR),
+ /*6185*/ uint16(xArgMem),
+ /*6186*/ uint16(xMatch),
+ /*6187*/ uint16(xCondDataSize), 6179, 6183, 6191,
+ /*6191*/ uint16(xSetOp), uint16(XRSTOR64),
+ /*6193*/ uint16(xArgMem),
+ /*6194*/ uint16(xMatch),
+ /*6195*/ uint16(xCondDataSize), 6199, 6203, 6207,
+ /*6199*/ uint16(xSetOp), uint16(XSAVEOPT),
+ /*6201*/ uint16(xArgMem),
+ /*6202*/ uint16(xMatch),
+ /*6203*/ uint16(xSetOp), uint16(XSAVEOPT),
+ /*6205*/ uint16(xArgMem),
+ /*6206*/ uint16(xMatch),
+ /*6207*/ uint16(xSetOp), uint16(XSAVEOPT64),
+ /*6209*/ uint16(xArgMem),
+ /*6210*/ uint16(xMatch),
+ /*6211*/ uint16(xSetOp), uint16(CLFLUSH),
+ /*6213*/ uint16(xArgM8),
+ /*6214*/ uint16(xMatch),
+ /*6215*/ uint16(xSetOp), uint16(LFENCE),
+ /*6217*/ uint16(xMatch),
+ /*6218*/ uint16(xSetOp), uint16(MFENCE),
+ /*6220*/ uint16(xMatch),
+ /*6221*/ uint16(xSetOp), uint16(SFENCE),
+ /*6223*/ uint16(xMatch),
+ /*6224*/ uint16(xCondIs64), 6227, 6243,
+ /*6227*/ uint16(xCondDataSize), 6231, 6237, 0,
+ /*6231*/ uint16(xSetOp), uint16(IMUL),
+ /*6233*/ uint16(xReadSlashR),
+ /*6234*/ uint16(xArgR16),
+ /*6235*/ uint16(xArgRM16),
+ /*6236*/ uint16(xMatch),
+ /*6237*/ uint16(xSetOp), uint16(IMUL),
+ /*6239*/ uint16(xReadSlashR),
+ /*6240*/ uint16(xArgR32),
+ /*6241*/ uint16(xArgRM32),
+ /*6242*/ uint16(xMatch),
+ /*6243*/ uint16(xCondDataSize), 6231, 6237, 6247,
+ /*6247*/ uint16(xSetOp), uint16(IMUL),
+ /*6249*/ uint16(xReadSlashR),
+ /*6250*/ uint16(xArgR64),
+ /*6251*/ uint16(xArgRM64),
+ /*6252*/ uint16(xMatch),
+ /*6253*/ uint16(xSetOp), uint16(CMPXCHG),
+ /*6255*/ uint16(xReadSlashR),
+ /*6256*/ uint16(xArgRM8),
+ /*6257*/ uint16(xArgR8),
+ /*6258*/ uint16(xMatch),
+ /*6259*/ uint16(xCondIs64), 6262, 6278,
+ /*6262*/ uint16(xCondDataSize), 6266, 6272, 0,
+ /*6266*/ uint16(xSetOp), uint16(CMPXCHG),
+ /*6268*/ uint16(xReadSlashR),
+ /*6269*/ uint16(xArgRM16),
+ /*6270*/ uint16(xArgR16),
+ /*6271*/ uint16(xMatch),
+ /*6272*/ uint16(xSetOp), uint16(CMPXCHG),
+ /*6274*/ uint16(xReadSlashR),
+ /*6275*/ uint16(xArgRM32),
+ /*6276*/ uint16(xArgR32),
+ /*6277*/ uint16(xMatch),
+ /*6278*/ uint16(xCondDataSize), 6266, 6272, 6282,
+ /*6282*/ uint16(xSetOp), uint16(CMPXCHG),
+ /*6284*/ uint16(xReadSlashR),
+ /*6285*/ uint16(xArgRM64),
+ /*6286*/ uint16(xArgR64),
+ /*6287*/ uint16(xMatch),
+ /*6288*/ uint16(xCondIs64), 6291, 6307,
+ /*6291*/ uint16(xCondDataSize), 6295, 6301, 0,
+ /*6295*/ uint16(xSetOp), uint16(LSS),
+ /*6297*/ uint16(xReadSlashR),
+ /*6298*/ uint16(xArgR16),
+ /*6299*/ uint16(xArgM16colon16),
+ /*6300*/ uint16(xMatch),
+ /*6301*/ uint16(xSetOp), uint16(LSS),
+ /*6303*/ uint16(xReadSlashR),
+ /*6304*/ uint16(xArgR32),
+ /*6305*/ uint16(xArgM16colon32),
+ /*6306*/ uint16(xMatch),
+ /*6307*/ uint16(xCondDataSize), 6295, 6301, 6311,
+ /*6311*/ uint16(xSetOp), uint16(LSS),
+ /*6313*/ uint16(xReadSlashR),
+ /*6314*/ uint16(xArgR64),
+ /*6315*/ uint16(xArgM16colon64),
+ /*6316*/ uint16(xMatch),
+ /*6317*/ uint16(xCondIs64), 6320, 6336,
+ /*6320*/ uint16(xCondDataSize), 6324, 6330, 0,
+ /*6324*/ uint16(xSetOp), uint16(BTR),
+ /*6326*/ uint16(xReadSlashR),
+ /*6327*/ uint16(xArgRM16),
+ /*6328*/ uint16(xArgR16),
+ /*6329*/ uint16(xMatch),
+ /*6330*/ uint16(xSetOp), uint16(BTR),
+ /*6332*/ uint16(xReadSlashR),
+ /*6333*/ uint16(xArgRM32),
+ /*6334*/ uint16(xArgR32),
+ /*6335*/ uint16(xMatch),
+ /*6336*/ uint16(xCondDataSize), 6324, 6330, 6340,
+ /*6340*/ uint16(xSetOp), uint16(BTR),
+ /*6342*/ uint16(xReadSlashR),
+ /*6343*/ uint16(xArgRM64),
+ /*6344*/ uint16(xArgR64),
+ /*6345*/ uint16(xMatch),
+ /*6346*/ uint16(xCondIs64), 6349, 6365,
+ /*6349*/ uint16(xCondDataSize), 6353, 6359, 0,
+ /*6353*/ uint16(xSetOp), uint16(LFS),
+ /*6355*/ uint16(xReadSlashR),
+ /*6356*/ uint16(xArgR16),
+ /*6357*/ uint16(xArgM16colon16),
+ /*6358*/ uint16(xMatch),
+ /*6359*/ uint16(xSetOp), uint16(LFS),
+ /*6361*/ uint16(xReadSlashR),
+ /*6362*/ uint16(xArgR32),
+ /*6363*/ uint16(xArgM16colon32),
+ /*6364*/ uint16(xMatch),
+ /*6365*/ uint16(xCondDataSize), 6353, 6359, 6369,
+ /*6369*/ uint16(xSetOp), uint16(LFS),
+ /*6371*/ uint16(xReadSlashR),
+ /*6372*/ uint16(xArgR64),
+ /*6373*/ uint16(xArgM16colon64),
+ /*6374*/ uint16(xMatch),
+ /*6375*/ uint16(xCondIs64), 6378, 6394,
+ /*6378*/ uint16(xCondDataSize), 6382, 6388, 0,
+ /*6382*/ uint16(xSetOp), uint16(LGS),
+ /*6384*/ uint16(xReadSlashR),
+ /*6385*/ uint16(xArgR16),
+ /*6386*/ uint16(xArgM16colon16),
+ /*6387*/ uint16(xMatch),
+ /*6388*/ uint16(xSetOp), uint16(LGS),
+ /*6390*/ uint16(xReadSlashR),
+ /*6391*/ uint16(xArgR32),
+ /*6392*/ uint16(xArgM16colon32),
+ /*6393*/ uint16(xMatch),
+ /*6394*/ uint16(xCondDataSize), 6382, 6388, 6398,
+ /*6398*/ uint16(xSetOp), uint16(LGS),
+ /*6400*/ uint16(xReadSlashR),
+ /*6401*/ uint16(xArgR64),
+ /*6402*/ uint16(xArgM16colon64),
+ /*6403*/ uint16(xMatch),
+ /*6404*/ uint16(xCondIs64), 6407, 6423,
+ /*6407*/ uint16(xCondDataSize), 6411, 6417, 0,
+ /*6411*/ uint16(xSetOp), uint16(MOVZX),
+ /*6413*/ uint16(xReadSlashR),
+ /*6414*/ uint16(xArgR16),
+ /*6415*/ uint16(xArgRM8),
+ /*6416*/ uint16(xMatch),
+ /*6417*/ uint16(xSetOp), uint16(MOVZX),
+ /*6419*/ uint16(xReadSlashR),
+ /*6420*/ uint16(xArgR32),
+ /*6421*/ uint16(xArgRM8),
+ /*6422*/ uint16(xMatch),
+ /*6423*/ uint16(xCondDataSize), 6411, 6417, 6427,
+ /*6427*/ uint16(xSetOp), uint16(MOVZX),
+ /*6429*/ uint16(xReadSlashR),
+ /*6430*/ uint16(xArgR64),
+ /*6431*/ uint16(xArgRM8),
+ /*6432*/ uint16(xMatch),
+ /*6433*/ uint16(xCondIs64), 6436, 6452,
+ /*6436*/ uint16(xCondDataSize), 6440, 6446, 0,
+ /*6440*/ uint16(xSetOp), uint16(MOVZX),
+ /*6442*/ uint16(xReadSlashR),
+ /*6443*/ uint16(xArgR16),
+ /*6444*/ uint16(xArgRM16),
+ /*6445*/ uint16(xMatch),
+ /*6446*/ uint16(xSetOp), uint16(MOVZX),
+ /*6448*/ uint16(xReadSlashR),
+ /*6449*/ uint16(xArgR32),
+ /*6450*/ uint16(xArgRM16),
+ /*6451*/ uint16(xMatch),
+ /*6452*/ uint16(xCondDataSize), 6440, 6446, 6456,
+ /*6456*/ uint16(xSetOp), uint16(MOVZX),
+ /*6458*/ uint16(xReadSlashR),
+ /*6459*/ uint16(xArgR64),
+ /*6460*/ uint16(xArgRM16),
+ /*6461*/ uint16(xMatch),
+ /*6462*/ uint16(xCondIs64), 6465, 6485,
+ /*6465*/ uint16(xCondPrefix), 1,
+ 0xF3, 6469,
+ /*6469*/ uint16(xCondDataSize), 6473, 6479, 0,
+ /*6473*/ uint16(xSetOp), uint16(POPCNT),
+ /*6475*/ uint16(xReadSlashR),
+ /*6476*/ uint16(xArgR16),
+ /*6477*/ uint16(xArgRM16),
+ /*6478*/ uint16(xMatch),
+ /*6479*/ uint16(xSetOp), uint16(POPCNT),
+ /*6481*/ uint16(xReadSlashR),
+ /*6482*/ uint16(xArgR32),
+ /*6483*/ uint16(xArgRM32),
+ /*6484*/ uint16(xMatch),
+ /*6485*/ uint16(xCondPrefix), 1,
+ 0xF3, 6489,
+ /*6489*/ uint16(xCondDataSize), 6473, 6479, 6493,
+ /*6493*/ uint16(xSetOp), uint16(POPCNT),
+ /*6495*/ uint16(xReadSlashR),
+ /*6496*/ uint16(xArgR64),
+ /*6497*/ uint16(xArgRM64),
+ /*6498*/ uint16(xMatch),
+ /*6499*/ uint16(xSetOp), uint16(UD1),
+ /*6501*/ uint16(xMatch),
+ /*6502*/ uint16(xCondSlashR),
+ 0, // 0
+ 0, // 1
+ 0, // 2
+ 0, // 3
+ 6511, // 4
+ 6540, // 5
+ 6569, // 6
+ 6598, // 7
+ /*6511*/ uint16(xCondIs64), 6514, 6530,
+ /*6514*/ uint16(xCondDataSize), 6518, 6524, 0,
+ /*6518*/ uint16(xSetOp), uint16(BT),
+ /*6520*/ uint16(xReadIb),
+ /*6521*/ uint16(xArgRM16),
+ /*6522*/ uint16(xArgImm8u),
+ /*6523*/ uint16(xMatch),
+ /*6524*/ uint16(xSetOp), uint16(BT),
+ /*6526*/ uint16(xReadIb),
+ /*6527*/ uint16(xArgRM32),
+ /*6528*/ uint16(xArgImm8u),
+ /*6529*/ uint16(xMatch),
+ /*6530*/ uint16(xCondDataSize), 6518, 6524, 6534,
+ /*6534*/ uint16(xSetOp), uint16(BT),
+ /*6536*/ uint16(xReadIb),
+ /*6537*/ uint16(xArgRM64),
+ /*6538*/ uint16(xArgImm8u),
+ /*6539*/ uint16(xMatch),
+ /*6540*/ uint16(xCondIs64), 6543, 6559,
+ /*6543*/ uint16(xCondDataSize), 6547, 6553, 0,
+ /*6547*/ uint16(xSetOp), uint16(BTS),
+ /*6549*/ uint16(xReadIb),
+ /*6550*/ uint16(xArgRM16),
+ /*6551*/ uint16(xArgImm8u),
+ /*6552*/ uint16(xMatch),
+ /*6553*/ uint16(xSetOp), uint16(BTS),
+ /*6555*/ uint16(xReadIb),
+ /*6556*/ uint16(xArgRM32),
+ /*6557*/ uint16(xArgImm8u),
+ /*6558*/ uint16(xMatch),
+ /*6559*/ uint16(xCondDataSize), 6547, 6553, 6563,
+ /*6563*/ uint16(xSetOp), uint16(BTS),
+ /*6565*/ uint16(xReadIb),
+ /*6566*/ uint16(xArgRM64),
+ /*6567*/ uint16(xArgImm8u),
+ /*6568*/ uint16(xMatch),
+ /*6569*/ uint16(xCondIs64), 6572, 6588,
+ /*6572*/ uint16(xCondDataSize), 6576, 6582, 0,
+ /*6576*/ uint16(xSetOp), uint16(BTR),
+ /*6578*/ uint16(xReadIb),
+ /*6579*/ uint16(xArgRM16),
+ /*6580*/ uint16(xArgImm8u),
+ /*6581*/ uint16(xMatch),
+ /*6582*/ uint16(xSetOp), uint16(BTR),
+ /*6584*/ uint16(xReadIb),
+ /*6585*/ uint16(xArgRM32),
+ /*6586*/ uint16(xArgImm8u),
+ /*6587*/ uint16(xMatch),
+ /*6588*/ uint16(xCondDataSize), 6576, 6582, 6592,
+ /*6592*/ uint16(xSetOp), uint16(BTR),
+ /*6594*/ uint16(xReadIb),
+ /*6595*/ uint16(xArgRM64),
+ /*6596*/ uint16(xArgImm8u),
+ /*6597*/ uint16(xMatch),
+ /*6598*/ uint16(xCondIs64), 6601, 6617,
+ /*6601*/ uint16(xCondDataSize), 6605, 6611, 0,
+ /*6605*/ uint16(xSetOp), uint16(BTC),
+ /*6607*/ uint16(xReadIb),
+ /*6608*/ uint16(xArgRM16),
+ /*6609*/ uint16(xArgImm8u),
+ /*6610*/ uint16(xMatch),
+ /*6611*/ uint16(xSetOp), uint16(BTC),
+ /*6613*/ uint16(xReadIb),
+ /*6614*/ uint16(xArgRM32),
+ /*6615*/ uint16(xArgImm8u),
+ /*6616*/ uint16(xMatch),
+ /*6617*/ uint16(xCondDataSize), 6605, 6611, 6621,
+ /*6621*/ uint16(xSetOp), uint16(BTC),
+ /*6623*/ uint16(xReadIb),
+ /*6624*/ uint16(xArgRM64),
+ /*6625*/ uint16(xArgImm8u),
+ /*6626*/ uint16(xMatch),
+ /*6627*/ uint16(xCondIs64), 6630, 6646,
+ /*6630*/ uint16(xCondDataSize), 6634, 6640, 0,
+ /*6634*/ uint16(xSetOp), uint16(BTC),
+ /*6636*/ uint16(xReadSlashR),
+ /*6637*/ uint16(xArgRM16),
+ /*6638*/ uint16(xArgR16),
+ /*6639*/ uint16(xMatch),
+ /*6640*/ uint16(xSetOp), uint16(BTC),
+ /*6642*/ uint16(xReadSlashR),
+ /*6643*/ uint16(xArgRM32),
+ /*6644*/ uint16(xArgR32),
+ /*6645*/ uint16(xMatch),
+ /*6646*/ uint16(xCondDataSize), 6634, 6640, 6650,
+ /*6650*/ uint16(xSetOp), uint16(BTC),
+ /*6652*/ uint16(xReadSlashR),
+ /*6653*/ uint16(xArgRM64),
+ /*6654*/ uint16(xArgR64),
+ /*6655*/ uint16(xMatch),
+ /*6656*/ uint16(xCondIs64), 6659, 6697,
+ /*6659*/ uint16(xCondPrefix), 2,
+ 0xF3, 6681,
+ 0x0, 6665,
+ /*6665*/ uint16(xCondDataSize), 6669, 6675, 0,
+ /*6669*/ uint16(xSetOp), uint16(BSF),
+ /*6671*/ uint16(xReadSlashR),
+ /*6672*/ uint16(xArgR16),
+ /*6673*/ uint16(xArgRM16),
+ /*6674*/ uint16(xMatch),
+ /*6675*/ uint16(xSetOp), uint16(BSF),
+ /*6677*/ uint16(xReadSlashR),
+ /*6678*/ uint16(xArgR32),
+ /*6679*/ uint16(xArgRM32),
+ /*6680*/ uint16(xMatch),
+ /*6681*/ uint16(xCondDataSize), 6685, 6691, 0,
+ /*6685*/ uint16(xSetOp), uint16(TZCNT),
+ /*6687*/ uint16(xReadSlashR),
+ /*6688*/ uint16(xArgR16),
+ /*6689*/ uint16(xArgRM16),
+ /*6690*/ uint16(xMatch),
+ /*6691*/ uint16(xSetOp), uint16(TZCNT),
+ /*6693*/ uint16(xReadSlashR),
+ /*6694*/ uint16(xArgR32),
+ /*6695*/ uint16(xArgRM32),
+ /*6696*/ uint16(xMatch),
+ /*6697*/ uint16(xCondPrefix), 2,
+ 0xF3, 6713,
+ 0x0, 6703,
+ /*6703*/ uint16(xCondDataSize), 6669, 6675, 6707,
+ /*6707*/ uint16(xSetOp), uint16(BSF),
+ /*6709*/ uint16(xReadSlashR),
+ /*6710*/ uint16(xArgR64),
+ /*6711*/ uint16(xArgRM64),
+ /*6712*/ uint16(xMatch),
+ /*6713*/ uint16(xCondDataSize), 6685, 6691, 6717,
+ /*6717*/ uint16(xSetOp), uint16(TZCNT),
+ /*6719*/ uint16(xReadSlashR),
+ /*6720*/ uint16(xArgR64),
+ /*6721*/ uint16(xArgRM64),
+ /*6722*/ uint16(xMatch),
+ /*6723*/ uint16(xCondIs64), 6726, 6764,
+ /*6726*/ uint16(xCondPrefix), 2,
+ 0xF3, 6748,
+ 0x0, 6732,
+ /*6732*/ uint16(xCondDataSize), 6736, 6742, 0,
+ /*6736*/ uint16(xSetOp), uint16(BSR),
+ /*6738*/ uint16(xReadSlashR),
+ /*6739*/ uint16(xArgR16),
+ /*6740*/ uint16(xArgRM16),
+ /*6741*/ uint16(xMatch),
+ /*6742*/ uint16(xSetOp), uint16(BSR),
+ /*6744*/ uint16(xReadSlashR),
+ /*6745*/ uint16(xArgR32),
+ /*6746*/ uint16(xArgRM32),
+ /*6747*/ uint16(xMatch),
+ /*6748*/ uint16(xCondDataSize), 6752, 6758, 0,
+ /*6752*/ uint16(xSetOp), uint16(LZCNT),
+ /*6754*/ uint16(xReadSlashR),
+ /*6755*/ uint16(xArgR16),
+ /*6756*/ uint16(xArgRM16),
+ /*6757*/ uint16(xMatch),
+ /*6758*/ uint16(xSetOp), uint16(LZCNT),
+ /*6760*/ uint16(xReadSlashR),
+ /*6761*/ uint16(xArgR32),
+ /*6762*/ uint16(xArgRM32),
+ /*6763*/ uint16(xMatch),
+ /*6764*/ uint16(xCondPrefix), 2,
+ 0xF3, 6780,
+ 0x0, 6770,
+ /*6770*/ uint16(xCondDataSize), 6736, 6742, 6774,
+ /*6774*/ uint16(xSetOp), uint16(BSR),
+ /*6776*/ uint16(xReadSlashR),
+ /*6777*/ uint16(xArgR64),
+ /*6778*/ uint16(xArgRM64),
+ /*6779*/ uint16(xMatch),
+ /*6780*/ uint16(xCondDataSize), 6752, 6758, 6784,
+ /*6784*/ uint16(xSetOp), uint16(LZCNT),
+ /*6786*/ uint16(xReadSlashR),
+ /*6787*/ uint16(xArgR64),
+ /*6788*/ uint16(xArgRM64),
+ /*6789*/ uint16(xMatch),
+ /*6790*/ uint16(xCondIs64), 6793, 6809,
+ /*6793*/ uint16(xCondDataSize), 6797, 6803, 0,
+ /*6797*/ uint16(xSetOp), uint16(MOVSX),
+ /*6799*/ uint16(xReadSlashR),
+ /*6800*/ uint16(xArgR16),
+ /*6801*/ uint16(xArgRM8),
+ /*6802*/ uint16(xMatch),
+ /*6803*/ uint16(xSetOp), uint16(MOVSX),
+ /*6805*/ uint16(xReadSlashR),
+ /*6806*/ uint16(xArgR32),
+ /*6807*/ uint16(xArgRM8),
+ /*6808*/ uint16(xMatch),
+ /*6809*/ uint16(xCondDataSize), 6797, 6803, 6813,
+ /*6813*/ uint16(xSetOp), uint16(MOVSX),
+ /*6815*/ uint16(xReadSlashR),
+ /*6816*/ uint16(xArgR64),
+ /*6817*/ uint16(xArgRM8),
+ /*6818*/ uint16(xMatch),
+ /*6819*/ uint16(xCondIs64), 6822, 6838,
+ /*6822*/ uint16(xCondDataSize), 6826, 6832, 0,
+ /*6826*/ uint16(xSetOp), uint16(MOVSX),
+ /*6828*/ uint16(xReadSlashR),
+ /*6829*/ uint16(xArgR16),
+ /*6830*/ uint16(xArgRM16),
+ /*6831*/ uint16(xMatch),
+ /*6832*/ uint16(xSetOp), uint16(MOVSX),
+ /*6834*/ uint16(xReadSlashR),
+ /*6835*/ uint16(xArgR32),
+ /*6836*/ uint16(xArgRM16),
+ /*6837*/ uint16(xMatch),
+ /*6838*/ uint16(xCondDataSize), 6826, 6832, 6842,
+ /*6842*/ uint16(xSetOp), uint16(MOVSX),
+ /*6844*/ uint16(xReadSlashR),
+ /*6845*/ uint16(xArgR64),
+ /*6846*/ uint16(xArgRM16),
+ /*6847*/ uint16(xMatch),
+ /*6848*/ uint16(xSetOp), uint16(XADD),
+ /*6850*/ uint16(xReadSlashR),
+ /*6851*/ uint16(xArgRM8),
+ /*6852*/ uint16(xArgR8),
+ /*6853*/ uint16(xMatch),
+ /*6854*/ uint16(xCondIs64), 6857, 6873,
+ /*6857*/ uint16(xCondDataSize), 6861, 6867, 0,
+ /*6861*/ uint16(xSetOp), uint16(XADD),
+ /*6863*/ uint16(xReadSlashR),
+ /*6864*/ uint16(xArgRM16),
+ /*6865*/ uint16(xArgR16),
+ /*6866*/ uint16(xMatch),
+ /*6867*/ uint16(xSetOp), uint16(XADD),
+ /*6869*/ uint16(xReadSlashR),
+ /*6870*/ uint16(xArgRM32),
+ /*6871*/ uint16(xArgR32),
+ /*6872*/ uint16(xMatch),
+ /*6873*/ uint16(xCondDataSize), 6861, 6867, 6877,
+ /*6877*/ uint16(xSetOp), uint16(XADD),
+ /*6879*/ uint16(xReadSlashR),
+ /*6880*/ uint16(xArgRM64),
+ /*6881*/ uint16(xArgR64),
+ /*6882*/ uint16(xMatch),
+ /*6883*/ uint16(xCondPrefix), 4,
+ 0xF3, 6917,
+ 0xF2, 6909,
+ 0x66, 6901,
+ 0x0, 6893,
+ /*6893*/ uint16(xSetOp), uint16(CMPPS),
+ /*6895*/ uint16(xReadSlashR),
+ /*6896*/ uint16(xReadIb),
+ /*6897*/ uint16(xArgXmm1),
+ /*6898*/ uint16(xArgXmm2M128),
+ /*6899*/ uint16(xArgImm8u),
+ /*6900*/ uint16(xMatch),
+ /*6901*/ uint16(xSetOp), uint16(CMPPD),
+ /*6903*/ uint16(xReadSlashR),
+ /*6904*/ uint16(xReadIb),
+ /*6905*/ uint16(xArgXmm1),
+ /*6906*/ uint16(xArgXmm2M128),
+ /*6907*/ uint16(xArgImm8u),
+ /*6908*/ uint16(xMatch),
+ /*6909*/ uint16(xSetOp), uint16(CMPSD_XMM),
+ /*6911*/ uint16(xReadSlashR),
+ /*6912*/ uint16(xReadIb),
+ /*6913*/ uint16(xArgXmm1),
+ /*6914*/ uint16(xArgXmm2M64),
+ /*6915*/ uint16(xArgImm8u),
+ /*6916*/ uint16(xMatch),
+ /*6917*/ uint16(xSetOp), uint16(CMPSS),
+ /*6919*/ uint16(xReadSlashR),
+ /*6920*/ uint16(xReadIb),
+ /*6921*/ uint16(xArgXmm1),
+ /*6922*/ uint16(xArgXmm2M32),
+ /*6923*/ uint16(xArgImm8u),
+ /*6924*/ uint16(xMatch),
+ /*6925*/ uint16(xCondIs64), 6928, 6944,
+ /*6928*/ uint16(xCondDataSize), 6932, 6938, 0,
+ /*6932*/ uint16(xSetOp), uint16(MOVNTI),
+ /*6934*/ uint16(xReadSlashR),
+ /*6935*/ uint16(xArgM32),
+ /*6936*/ uint16(xArgR32),
+ /*6937*/ uint16(xMatch),
+ /*6938*/ uint16(xSetOp), uint16(MOVNTI),
+ /*6940*/ uint16(xReadSlashR),
+ /*6941*/ uint16(xArgM32),
+ /*6942*/ uint16(xArgR32),
+ /*6943*/ uint16(xMatch),
+ /*6944*/ uint16(xCondDataSize), 6932, 6938, 6948,
+ /*6948*/ uint16(xSetOp), uint16(MOVNTI),
+ /*6950*/ uint16(xReadSlashR),
+ /*6951*/ uint16(xArgM64),
+ /*6952*/ uint16(xArgR64),
+ /*6953*/ uint16(xMatch),
+ /*6954*/ uint16(xCondPrefix), 2,
+ 0x66, 6968,
+ 0x0, 6960,
+ /*6960*/ uint16(xSetOp), uint16(PINSRW),
+ /*6962*/ uint16(xReadSlashR),
+ /*6963*/ uint16(xReadIb),
+ /*6964*/ uint16(xArgMm),
+ /*6965*/ uint16(xArgR32M16),
+ /*6966*/ uint16(xArgImm8u),
+ /*6967*/ uint16(xMatch),
+ /*6968*/ uint16(xSetOp), uint16(PINSRW),
+ /*6970*/ uint16(xReadSlashR),
+ /*6971*/ uint16(xReadIb),
+ /*6972*/ uint16(xArgXmm),
+ /*6973*/ uint16(xArgR32M16),
+ /*6974*/ uint16(xArgImm8u),
+ /*6975*/ uint16(xMatch),
+ /*6976*/ uint16(xCondPrefix), 2,
+ 0x66, 6990,
+ 0x0, 6982,
+ /*6982*/ uint16(xSetOp), uint16(PEXTRW),
+ /*6984*/ uint16(xReadSlashR),
+ /*6985*/ uint16(xReadIb),
+ /*6986*/ uint16(xArgR32),
+ /*6987*/ uint16(xArgMm2),
+ /*6988*/ uint16(xArgImm8u),
+ /*6989*/ uint16(xMatch),
+ /*6990*/ uint16(xSetOp), uint16(PEXTRW),
+ /*6992*/ uint16(xReadSlashR),
+ /*6993*/ uint16(xReadIb),
+ /*6994*/ uint16(xArgR32),
+ /*6995*/ uint16(xArgXmm2),
+ /*6996*/ uint16(xArgImm8u),
+ /*6997*/ uint16(xMatch),
+ /*6998*/ uint16(xCondPrefix), 2,
+ 0x66, 7012,
+ 0x0, 7004,
+ /*7004*/ uint16(xSetOp), uint16(SHUFPS),
+ /*7006*/ uint16(xReadSlashR),
+ /*7007*/ uint16(xReadIb),
+ /*7008*/ uint16(xArgXmm1),
+ /*7009*/ uint16(xArgXmm2M128),
+ /*7010*/ uint16(xArgImm8u),
+ /*7011*/ uint16(xMatch),
+ /*7012*/ uint16(xSetOp), uint16(SHUFPD),
+ /*7014*/ uint16(xReadSlashR),
+ /*7015*/ uint16(xReadIb),
+ /*7016*/ uint16(xArgXmm1),
+ /*7017*/ uint16(xArgXmm2M128),
+ /*7018*/ uint16(xArgImm8u),
+ /*7019*/ uint16(xMatch),
+ /*7020*/ uint16(xCondSlashR),
+ 0, // 0
+ 7029, // 1
+ 0, // 2
+ 7052, // 3
+ 7075, // 4
+ 7098, // 5
+ 7121, // 6
+ 0, // 7
+ /*7029*/ uint16(xCondIs64), 7032, 7044,
+ /*7032*/ uint16(xCondDataSize), 7036, 7040, 0,
+ /*7036*/ uint16(xSetOp), uint16(CMPXCHG8B),
+ /*7038*/ uint16(xArgM64),
+ /*7039*/ uint16(xMatch),
+ /*7040*/ uint16(xSetOp), uint16(CMPXCHG8B),
+ /*7042*/ uint16(xArgM64),
+ /*7043*/ uint16(xMatch),
+ /*7044*/ uint16(xCondDataSize), 7036, 7040, 7048,
+ /*7048*/ uint16(xSetOp), uint16(CMPXCHG16B),
+ /*7050*/ uint16(xArgM128),
+ /*7051*/ uint16(xMatch),
+ /*7052*/ uint16(xCondIs64), 7055, 7067,
+ /*7055*/ uint16(xCondDataSize), 7059, 7063, 0,
+ /*7059*/ uint16(xSetOp), uint16(XRSTORS),
+ /*7061*/ uint16(xArgMem),
+ /*7062*/ uint16(xMatch),
+ /*7063*/ uint16(xSetOp), uint16(XRSTORS),
+ /*7065*/ uint16(xArgMem),
+ /*7066*/ uint16(xMatch),
+ /*7067*/ uint16(xCondDataSize), 7059, 7063, 7071,
+ /*7071*/ uint16(xSetOp), uint16(XRSTORS64),
+ /*7073*/ uint16(xArgMem),
+ /*7074*/ uint16(xMatch),
+ /*7075*/ uint16(xCondIs64), 7078, 7090,
+ /*7078*/ uint16(xCondDataSize), 7082, 7086, 0,
+ /*7082*/ uint16(xSetOp), uint16(XSAVEC),
+ /*7084*/ uint16(xArgMem),
+ /*7085*/ uint16(xMatch),
+ /*7086*/ uint16(xSetOp), uint16(XSAVEC),
+ /*7088*/ uint16(xArgMem),
+ /*7089*/ uint16(xMatch),
+ /*7090*/ uint16(xCondDataSize), 7082, 7086, 7094,
+ /*7094*/ uint16(xSetOp), uint16(XSAVEC64),
+ /*7096*/ uint16(xArgMem),
+ /*7097*/ uint16(xMatch),
+ /*7098*/ uint16(xCondIs64), 7101, 7113,
+ /*7101*/ uint16(xCondDataSize), 7105, 7109, 0,
+ /*7105*/ uint16(xSetOp), uint16(XSAVES),
+ /*7107*/ uint16(xArgMem),
+ /*7108*/ uint16(xMatch),
+ /*7109*/ uint16(xSetOp), uint16(XSAVES),
+ /*7111*/ uint16(xArgMem),
+ /*7112*/ uint16(xMatch),
+ /*7113*/ uint16(xCondDataSize), 7105, 7109, 7117,
+ /*7117*/ uint16(xSetOp), uint16(XSAVES64),
+ /*7119*/ uint16(xArgMem),
+ /*7120*/ uint16(xMatch),
+ /*7121*/ uint16(xCondIs64), 7124, 7142,
+ /*7124*/ uint16(xCondDataSize), 7128, 7135, 0,
+ /*7128*/ uint16(xCondIsMem), 7131, 0,
+ /*7131*/ uint16(xSetOp), uint16(RDRAND),
+ /*7133*/ uint16(xArgRmf16),
+ /*7134*/ uint16(xMatch),
+ /*7135*/ uint16(xCondIsMem), 7138, 0,
+ /*7138*/ uint16(xSetOp), uint16(RDRAND),
+ /*7140*/ uint16(xArgRmf32),
+ /*7141*/ uint16(xMatch),
+ /*7142*/ uint16(xCondDataSize), 7128, 7135, 7146,
+ /*7146*/ uint16(xSetOp), uint16(RDRAND),
+ /*7148*/ uint16(xMatch),
+ /*7149*/ uint16(xCondIs64), 7152, 7164,
+ /*7152*/ uint16(xCondDataSize), 7156, 7160, 0,
+ /*7156*/ uint16(xSetOp), uint16(BSWAP),
+ /*7158*/ uint16(xArgR16op),
+ /*7159*/ uint16(xMatch),
+ /*7160*/ uint16(xSetOp), uint16(BSWAP),
+ /*7162*/ uint16(xArgR32op),
+ /*7163*/ uint16(xMatch),
+ /*7164*/ uint16(xCondDataSize), 7156, 7160, 7168,
+ /*7168*/ uint16(xSetOp), uint16(BSWAP),
+ /*7170*/ uint16(xArgR64op),
+ /*7171*/ uint16(xMatch),
+ /*7172*/ uint16(xCondPrefix), 2,
+ 0xF2, 7184,
+ 0x66, 7178,
+ /*7178*/ uint16(xSetOp), uint16(ADDSUBPD),
+ /*7180*/ uint16(xReadSlashR),
+ /*7181*/ uint16(xArgXmm1),
+ /*7182*/ uint16(xArgXmm2M128),
+ /*7183*/ uint16(xMatch),
+ /*7184*/ uint16(xSetOp), uint16(ADDSUBPS),
+ /*7186*/ uint16(xReadSlashR),
+ /*7187*/ uint16(xArgXmm1),
+ /*7188*/ uint16(xArgXmm2M128),
+ /*7189*/ uint16(xMatch),
+ /*7190*/ uint16(xCondPrefix), 2,
+ 0x66, 7202,
+ 0x0, 7196,
+ /*7196*/ uint16(xSetOp), uint16(PSRLW),
+ /*7198*/ uint16(xReadSlashR),
+ /*7199*/ uint16(xArgMm),
+ /*7200*/ uint16(xArgMmM64),
+ /*7201*/ uint16(xMatch),
+ /*7202*/ uint16(xSetOp), uint16(PSRLW),
+ /*7204*/ uint16(xReadSlashR),
+ /*7205*/ uint16(xArgXmm1),
+ /*7206*/ uint16(xArgXmm2M128),
+ /*7207*/ uint16(xMatch),
+ /*7208*/ uint16(xCondPrefix), 2,
+ 0x66, 7220,
+ 0x0, 7214,
+ /*7214*/ uint16(xSetOp), uint16(PSRLD),
+ /*7216*/ uint16(xReadSlashR),
+ /*7217*/ uint16(xArgMm),
+ /*7218*/ uint16(xArgMmM64),
+ /*7219*/ uint16(xMatch),
+ /*7220*/ uint16(xSetOp), uint16(PSRLD),
+ /*7222*/ uint16(xReadSlashR),
+ /*7223*/ uint16(xArgXmm1),
+ /*7224*/ uint16(xArgXmm2M128),
+ /*7225*/ uint16(xMatch),
+ /*7226*/ uint16(xCondPrefix), 2,
+ 0x66, 7238,
+ 0x0, 7232,
+ /*7232*/ uint16(xSetOp), uint16(PSRLQ),
+ /*7234*/ uint16(xReadSlashR),
+ /*7235*/ uint16(xArgMm),
+ /*7236*/ uint16(xArgMmM64),
+ /*7237*/ uint16(xMatch),
+ /*7238*/ uint16(xSetOp), uint16(PSRLQ),
+ /*7240*/ uint16(xReadSlashR),
+ /*7241*/ uint16(xArgXmm1),
+ /*7242*/ uint16(xArgXmm2M128),
+ /*7243*/ uint16(xMatch),
+ /*7244*/ uint16(xCondPrefix), 2,
+ 0x66, 7256,
+ 0x0, 7250,
+ /*7250*/ uint16(xSetOp), uint16(PADDQ),
+ /*7252*/ uint16(xReadSlashR),
+ /*7253*/ uint16(xArgMm1),
+ /*7254*/ uint16(xArgMm2M64),
+ /*7255*/ uint16(xMatch),
+ /*7256*/ uint16(xSetOp), uint16(PADDQ),
+ /*7258*/ uint16(xReadSlashR),
+ /*7259*/ uint16(xArgXmm1),
+ /*7260*/ uint16(xArgXmm2M128),
+ /*7261*/ uint16(xMatch),
+ /*7262*/ uint16(xCondPrefix), 2,
+ 0x66, 7274,
+ 0x0, 7268,
+ /*7268*/ uint16(xSetOp), uint16(PMULLW),
+ /*7270*/ uint16(xReadSlashR),
+ /*7271*/ uint16(xArgMm),
+ /*7272*/ uint16(xArgMmM64),
+ /*7273*/ uint16(xMatch),
+ /*7274*/ uint16(xSetOp), uint16(PMULLW),
+ /*7276*/ uint16(xReadSlashR),
+ /*7277*/ uint16(xArgXmm1),
+ /*7278*/ uint16(xArgXmm2M128),
+ /*7279*/ uint16(xMatch),
+ /*7280*/ uint16(xCondPrefix), 3,
+ 0xF3, 7300,
+ 0xF2, 7294,
+ 0x66, 7288,
+ /*7288*/ uint16(xSetOp), uint16(MOVQ),
+ /*7290*/ uint16(xReadSlashR),
+ /*7291*/ uint16(xArgXmm2M64),
+ /*7292*/ uint16(xArgXmm1),
+ /*7293*/ uint16(xMatch),
+ /*7294*/ uint16(xSetOp), uint16(MOVDQ2Q),
+ /*7296*/ uint16(xReadSlashR),
+ /*7297*/ uint16(xArgMm),
+ /*7298*/ uint16(xArgXmm2),
+ /*7299*/ uint16(xMatch),
+ /*7300*/ uint16(xSetOp), uint16(MOVQ2DQ),
+ /*7302*/ uint16(xReadSlashR),
+ /*7303*/ uint16(xArgXmm1),
+ /*7304*/ uint16(xArgMm2),
+ /*7305*/ uint16(xMatch),
+ /*7306*/ uint16(xCondPrefix), 2,
+ 0x66, 7318,
+ 0x0, 7312,
+ /*7312*/ uint16(xSetOp), uint16(PMOVMSKB),
+ /*7314*/ uint16(xReadSlashR),
+ /*7315*/ uint16(xArgR32),
+ /*7316*/ uint16(xArgMm2),
+ /*7317*/ uint16(xMatch),
+ /*7318*/ uint16(xSetOp), uint16(PMOVMSKB),
+ /*7320*/ uint16(xReadSlashR),
+ /*7321*/ uint16(xArgR32),
+ /*7322*/ uint16(xArgXmm2),
+ /*7323*/ uint16(xMatch),
+ /*7324*/ uint16(xCondPrefix), 2,
+ 0x66, 7336,
+ 0x0, 7330,
+ /*7330*/ uint16(xSetOp), uint16(PSUBUSB),
+ /*7332*/ uint16(xReadSlashR),
+ /*7333*/ uint16(xArgMm),
+ /*7334*/ uint16(xArgMmM64),
+ /*7335*/ uint16(xMatch),
+ /*7336*/ uint16(xSetOp), uint16(PSUBUSB),
+ /*7338*/ uint16(xReadSlashR),
+ /*7339*/ uint16(xArgXmm1),
+ /*7340*/ uint16(xArgXmm2M128),
+ /*7341*/ uint16(xMatch),
+ /*7342*/ uint16(xCondPrefix), 2,
+ 0x66, 7354,
+ 0x0, 7348,
+ /*7348*/ uint16(xSetOp), uint16(PSUBUSW),
+ /*7350*/ uint16(xReadSlashR),
+ /*7351*/ uint16(xArgMm),
+ /*7352*/ uint16(xArgMmM64),
+ /*7353*/ uint16(xMatch),
+ /*7354*/ uint16(xSetOp), uint16(PSUBUSW),
+ /*7356*/ uint16(xReadSlashR),
+ /*7357*/ uint16(xArgXmm1),
+ /*7358*/ uint16(xArgXmm2M128),
+ /*7359*/ uint16(xMatch),
+ /*7360*/ uint16(xCondPrefix), 2,
+ 0x66, 7372,
+ 0x0, 7366,
+ /*7366*/ uint16(xSetOp), uint16(PMINUB),
+ /*7368*/ uint16(xReadSlashR),
+ /*7369*/ uint16(xArgMm1),
+ /*7370*/ uint16(xArgMm2M64),
+ /*7371*/ uint16(xMatch),
+ /*7372*/ uint16(xSetOp), uint16(PMINUB),
+ /*7374*/ uint16(xReadSlashR),
+ /*7375*/ uint16(xArgXmm1),
+ /*7376*/ uint16(xArgXmm2M128),
+ /*7377*/ uint16(xMatch),
+ /*7378*/ uint16(xCondPrefix), 2,
+ 0x66, 7390,
+ 0x0, 7384,
+ /*7384*/ uint16(xSetOp), uint16(PAND),
+ /*7386*/ uint16(xReadSlashR),
+ /*7387*/ uint16(xArgMm),
+ /*7388*/ uint16(xArgMmM64),
+ /*7389*/ uint16(xMatch),
+ /*7390*/ uint16(xSetOp), uint16(PAND),
+ /*7392*/ uint16(xReadSlashR),
+ /*7393*/ uint16(xArgXmm1),
+ /*7394*/ uint16(xArgXmm2M128),
+ /*7395*/ uint16(xMatch),
+ /*7396*/ uint16(xCondPrefix), 2,
+ 0x66, 7408,
+ 0x0, 7402,
+ /*7402*/ uint16(xSetOp), uint16(PADDUSB),
+ /*7404*/ uint16(xReadSlashR),
+ /*7405*/ uint16(xArgMm),
+ /*7406*/ uint16(xArgMmM64),
+ /*7407*/ uint16(xMatch),
+ /*7408*/ uint16(xSetOp), uint16(PADDUSB),
+ /*7410*/ uint16(xReadSlashR),
+ /*7411*/ uint16(xArgXmm1),
+ /*7412*/ uint16(xArgXmm2M128),
+ /*7413*/ uint16(xMatch),
+ /*7414*/ uint16(xCondPrefix), 2,
+ 0x66, 7426,
+ 0x0, 7420,
+ /*7420*/ uint16(xSetOp), uint16(PADDUSW),
+ /*7422*/ uint16(xReadSlashR),
+ /*7423*/ uint16(xArgMm),
+ /*7424*/ uint16(xArgMmM64),
+ /*7425*/ uint16(xMatch),
+ /*7426*/ uint16(xSetOp), uint16(PADDUSW),
+ /*7428*/ uint16(xReadSlashR),
+ /*7429*/ uint16(xArgXmm1),
+ /*7430*/ uint16(xArgXmm2M128),
+ /*7431*/ uint16(xMatch),
+ /*7432*/ uint16(xCondPrefix), 2,
+ 0x66, 7444,
+ 0x0, 7438,
+ /*7438*/ uint16(xSetOp), uint16(PMAXUB),
+ /*7440*/ uint16(xReadSlashR),
+ /*7441*/ uint16(xArgMm1),
+ /*7442*/ uint16(xArgMm2M64),
+ /*7443*/ uint16(xMatch),
+ /*7444*/ uint16(xSetOp), uint16(PMAXUB),
+ /*7446*/ uint16(xReadSlashR),
+ /*7447*/ uint16(xArgXmm1),
+ /*7448*/ uint16(xArgXmm2M128),
+ /*7449*/ uint16(xMatch),
+ /*7450*/ uint16(xCondPrefix), 2,
+ 0x66, 7462,
+ 0x0, 7456,
+ /*7456*/ uint16(xSetOp), uint16(PANDN),
+ /*7458*/ uint16(xReadSlashR),
+ /*7459*/ uint16(xArgMm),
+ /*7460*/ uint16(xArgMmM64),
+ /*7461*/ uint16(xMatch),
+ /*7462*/ uint16(xSetOp), uint16(PANDN),
+ /*7464*/ uint16(xReadSlashR),
+ /*7465*/ uint16(xArgXmm1),
+ /*7466*/ uint16(xArgXmm2M128),
+ /*7467*/ uint16(xMatch),
+ /*7468*/ uint16(xCondPrefix), 2,
+ 0x66, 7480,
+ 0x0, 7474,
+ /*7474*/ uint16(xSetOp), uint16(PAVGB),
+ /*7476*/ uint16(xReadSlashR),
+ /*7477*/ uint16(xArgMm1),
+ /*7478*/ uint16(xArgMm2M64),
+ /*7479*/ uint16(xMatch),
+ /*7480*/ uint16(xSetOp), uint16(PAVGB),
+ /*7482*/ uint16(xReadSlashR),
+ /*7483*/ uint16(xArgXmm1),
+ /*7484*/ uint16(xArgXmm2M128),
+ /*7485*/ uint16(xMatch),
+ /*7486*/ uint16(xCondPrefix), 2,
+ 0x66, 7498,
+ 0x0, 7492,
+ /*7492*/ uint16(xSetOp), uint16(PSRAW),
+ /*7494*/ uint16(xReadSlashR),
+ /*7495*/ uint16(xArgMm),
+ /*7496*/ uint16(xArgMmM64),
+ /*7497*/ uint16(xMatch),
+ /*7498*/ uint16(xSetOp), uint16(PSRAW),
+ /*7500*/ uint16(xReadSlashR),
+ /*7501*/ uint16(xArgXmm1),
+ /*7502*/ uint16(xArgXmm2M128),
+ /*7503*/ uint16(xMatch),
+ /*7504*/ uint16(xCondPrefix), 2,
+ 0x66, 7516,
+ 0x0, 7510,
+ /*7510*/ uint16(xSetOp), uint16(PSRAD),
+ /*7512*/ uint16(xReadSlashR),
+ /*7513*/ uint16(xArgMm),
+ /*7514*/ uint16(xArgMmM64),
+ /*7515*/ uint16(xMatch),
+ /*7516*/ uint16(xSetOp), uint16(PSRAD),
+ /*7518*/ uint16(xReadSlashR),
+ /*7519*/ uint16(xArgXmm1),
+ /*7520*/ uint16(xArgXmm2M128),
+ /*7521*/ uint16(xMatch),
+ /*7522*/ uint16(xCondPrefix), 2,
+ 0x66, 7534,
+ 0x0, 7528,
+ /*7528*/ uint16(xSetOp), uint16(PAVGW),
+ /*7530*/ uint16(xReadSlashR),
+ /*7531*/ uint16(xArgMm1),
+ /*7532*/ uint16(xArgMm2M64),
+ /*7533*/ uint16(xMatch),
+ /*7534*/ uint16(xSetOp), uint16(PAVGW),
+ /*7536*/ uint16(xReadSlashR),
+ /*7537*/ uint16(xArgXmm1),
+ /*7538*/ uint16(xArgXmm2M128),
+ /*7539*/ uint16(xMatch),
+ /*7540*/ uint16(xCondPrefix), 2,
+ 0x66, 7552,
+ 0x0, 7546,
+ /*7546*/ uint16(xSetOp), uint16(PMULHUW),
+ /*7548*/ uint16(xReadSlashR),
+ /*7549*/ uint16(xArgMm1),
+ /*7550*/ uint16(xArgMm2M64),
+ /*7551*/ uint16(xMatch),
+ /*7552*/ uint16(xSetOp), uint16(PMULHUW),
+ /*7554*/ uint16(xReadSlashR),
+ /*7555*/ uint16(xArgXmm1),
+ /*7556*/ uint16(xArgXmm2M128),
+ /*7557*/ uint16(xMatch),
+ /*7558*/ uint16(xCondPrefix), 2,
+ 0x66, 7570,
+ 0x0, 7564,
+ /*7564*/ uint16(xSetOp), uint16(PMULHW),
+ /*7566*/ uint16(xReadSlashR),
+ /*7567*/ uint16(xArgMm),
+ /*7568*/ uint16(xArgMmM64),
+ /*7569*/ uint16(xMatch),
+ /*7570*/ uint16(xSetOp), uint16(PMULHW),
+ /*7572*/ uint16(xReadSlashR),
+ /*7573*/ uint16(xArgXmm1),
+ /*7574*/ uint16(xArgXmm2M128),
+ /*7575*/ uint16(xMatch),
+ /*7576*/ uint16(xCondPrefix), 3,
+ 0xF3, 7596,
+ 0xF2, 7590,
+ 0x66, 7584,
+ /*7584*/ uint16(xSetOp), uint16(CVTTPD2DQ),
+ /*7586*/ uint16(xReadSlashR),
+ /*7587*/ uint16(xArgXmm1),
+ /*7588*/ uint16(xArgXmm2M128),
+ /*7589*/ uint16(xMatch),
+ /*7590*/ uint16(xSetOp), uint16(CVTPD2DQ),
+ /*7592*/ uint16(xReadSlashR),
+ /*7593*/ uint16(xArgXmm1),
+ /*7594*/ uint16(xArgXmm2M128),
+ /*7595*/ uint16(xMatch),
+ /*7596*/ uint16(xSetOp), uint16(CVTDQ2PD),
+ /*7598*/ uint16(xReadSlashR),
+ /*7599*/ uint16(xArgXmm1),
+ /*7600*/ uint16(xArgXmm2M64),
+ /*7601*/ uint16(xMatch),
+ /*7602*/ uint16(xCondPrefix), 2,
+ 0x66, 7614,
+ 0x0, 7608,
+ /*7608*/ uint16(xSetOp), uint16(MOVNTQ),
+ /*7610*/ uint16(xReadSlashR),
+ /*7611*/ uint16(xArgM64),
+ /*7612*/ uint16(xArgMm),
+ /*7613*/ uint16(xMatch),
+ /*7614*/ uint16(xSetOp), uint16(MOVNTDQ),
+ /*7616*/ uint16(xReadSlashR),
+ /*7617*/ uint16(xArgM128),
+ /*7618*/ uint16(xArgXmm),
+ /*7619*/ uint16(xMatch),
+ /*7620*/ uint16(xCondPrefix), 2,
+ 0x66, 7632,
+ 0x0, 7626,
+ /*7626*/ uint16(xSetOp), uint16(PSUBSB),
+ /*7628*/ uint16(xReadSlashR),
+ /*7629*/ uint16(xArgMm),
+ /*7630*/ uint16(xArgMmM64),
+ /*7631*/ uint16(xMatch),
+ /*7632*/ uint16(xSetOp), uint16(PSUBSB),
+ /*7634*/ uint16(xReadSlashR),
+ /*7635*/ uint16(xArgXmm1),
+ /*7636*/ uint16(xArgXmm2M128),
+ /*7637*/ uint16(xMatch),
+ /*7638*/ uint16(xCondPrefix), 2,
+ 0x66, 7650,
+ 0x0, 7644,
+ /*7644*/ uint16(xSetOp), uint16(PSUBSW),
+ /*7646*/ uint16(xReadSlashR),
+ /*7647*/ uint16(xArgMm),
+ /*7648*/ uint16(xArgMmM64),
+ /*7649*/ uint16(xMatch),
+ /*7650*/ uint16(xSetOp), uint16(PSUBSW),
+ /*7652*/ uint16(xReadSlashR),
+ /*7653*/ uint16(xArgXmm1),
+ /*7654*/ uint16(xArgXmm2M128),
+ /*7655*/ uint16(xMatch),
+ /*7656*/ uint16(xCondPrefix), 2,
+ 0x66, 7668,
+ 0x0, 7662,
+ /*7662*/ uint16(xSetOp), uint16(PMINSW),
+ /*7664*/ uint16(xReadSlashR),
+ /*7665*/ uint16(xArgMm1),
+ /*7666*/ uint16(xArgMm2M64),
+ /*7667*/ uint16(xMatch),
+ /*7668*/ uint16(xSetOp), uint16(PMINSW),
+ /*7670*/ uint16(xReadSlashR),
+ /*7671*/ uint16(xArgXmm1),
+ /*7672*/ uint16(xArgXmm2M128),
+ /*7673*/ uint16(xMatch),
+ /*7674*/ uint16(xCondPrefix), 2,
+ 0x66, 7686,
+ 0x0, 7680,
+ /*7680*/ uint16(xSetOp), uint16(POR),
+ /*7682*/ uint16(xReadSlashR),
+ /*7683*/ uint16(xArgMm),
+ /*7684*/ uint16(xArgMmM64),
+ /*7685*/ uint16(xMatch),
+ /*7686*/ uint16(xSetOp), uint16(POR),
+ /*7688*/ uint16(xReadSlashR),
+ /*7689*/ uint16(xArgXmm1),
+ /*7690*/ uint16(xArgXmm2M128),
+ /*7691*/ uint16(xMatch),
+ /*7692*/ uint16(xCondPrefix), 2,
+ 0x66, 7704,
+ 0x0, 7698,
+ /*7698*/ uint16(xSetOp), uint16(PADDSB),
+ /*7700*/ uint16(xReadSlashR),
+ /*7701*/ uint16(xArgMm),
+ /*7702*/ uint16(xArgMmM64),
+ /*7703*/ uint16(xMatch),
+ /*7704*/ uint16(xSetOp), uint16(PADDSB),
+ /*7706*/ uint16(xReadSlashR),
+ /*7707*/ uint16(xArgXmm1),
+ /*7708*/ uint16(xArgXmm2M128),
+ /*7709*/ uint16(xMatch),
+ /*7710*/ uint16(xCondPrefix), 2,
+ 0x66, 7722,
+ 0x0, 7716,
+ /*7716*/ uint16(xSetOp), uint16(PADDSW),
+ /*7718*/ uint16(xReadSlashR),
+ /*7719*/ uint16(xArgMm),
+ /*7720*/ uint16(xArgMmM64),
+ /*7721*/ uint16(xMatch),
+ /*7722*/ uint16(xSetOp), uint16(PADDSW),
+ /*7724*/ uint16(xReadSlashR),
+ /*7725*/ uint16(xArgXmm1),
+ /*7726*/ uint16(xArgXmm2M128),
+ /*7727*/ uint16(xMatch),
+ /*7728*/ uint16(xCondPrefix), 2,
+ 0x66, 7740,
+ 0x0, 7734,
+ /*7734*/ uint16(xSetOp), uint16(PMAXSW),
+ /*7736*/ uint16(xReadSlashR),
+ /*7737*/ uint16(xArgMm1),
+ /*7738*/ uint16(xArgMm2M64),
+ /*7739*/ uint16(xMatch),
+ /*7740*/ uint16(xSetOp), uint16(PMAXSW),
+ /*7742*/ uint16(xReadSlashR),
+ /*7743*/ uint16(xArgXmm1),
+ /*7744*/ uint16(xArgXmm2M128),
+ /*7745*/ uint16(xMatch),
+ /*7746*/ uint16(xCondPrefix), 2,
+ 0x66, 7758,
+ 0x0, 7752,
+ /*7752*/ uint16(xSetOp), uint16(PXOR),
+ /*7754*/ uint16(xReadSlashR),
+ /*7755*/ uint16(xArgMm),
+ /*7756*/ uint16(xArgMmM64),
+ /*7757*/ uint16(xMatch),
+ /*7758*/ uint16(xSetOp), uint16(PXOR),
+ /*7760*/ uint16(xReadSlashR),
+ /*7761*/ uint16(xArgXmm1),
+ /*7762*/ uint16(xArgXmm2M128),
+ /*7763*/ uint16(xMatch),
+ /*7764*/ uint16(xCondPrefix), 1,
+ 0xF2, 7768,
+ /*7768*/ uint16(xSetOp), uint16(LDDQU),
+ /*7770*/ uint16(xReadSlashR),
+ /*7771*/ uint16(xArgXmm1),
+ /*7772*/ uint16(xArgM128),
+ /*7773*/ uint16(xMatch),
+ /*7774*/ uint16(xCondPrefix), 2,
+ 0x66, 7786,
+ 0x0, 7780,
+ /*7780*/ uint16(xSetOp), uint16(PSLLW),
+ /*7782*/ uint16(xReadSlashR),
+ /*7783*/ uint16(xArgMm),
+ /*7784*/ uint16(xArgMmM64),
+ /*7785*/ uint16(xMatch),
+ /*7786*/ uint16(xSetOp), uint16(PSLLW),
+ /*7788*/ uint16(xReadSlashR),
+ /*7789*/ uint16(xArgXmm1),
+ /*7790*/ uint16(xArgXmm2M128),
+ /*7791*/ uint16(xMatch),
+ /*7792*/ uint16(xCondPrefix), 2,
+ 0x66, 7804,
+ 0x0, 7798,
+ /*7798*/ uint16(xSetOp), uint16(PSLLD),
+ /*7800*/ uint16(xReadSlashR),
+ /*7801*/ uint16(xArgMm),
+ /*7802*/ uint16(xArgMmM64),
+ /*7803*/ uint16(xMatch),
+ /*7804*/ uint16(xSetOp), uint16(PSLLD),
+ /*7806*/ uint16(xReadSlashR),
+ /*7807*/ uint16(xArgXmm1),
+ /*7808*/ uint16(xArgXmm2M128),
+ /*7809*/ uint16(xMatch),
+ /*7810*/ uint16(xCondPrefix), 2,
+ 0x66, 7822,
+ 0x0, 7816,
+ /*7816*/ uint16(xSetOp), uint16(PSLLQ),
+ /*7818*/ uint16(xReadSlashR),
+ /*7819*/ uint16(xArgMm),
+ /*7820*/ uint16(xArgMmM64),
+ /*7821*/ uint16(xMatch),
+ /*7822*/ uint16(xSetOp), uint16(PSLLQ),
+ /*7824*/ uint16(xReadSlashR),
+ /*7825*/ uint16(xArgXmm1),
+ /*7826*/ uint16(xArgXmm2M128),
+ /*7827*/ uint16(xMatch),
+ /*7828*/ uint16(xCondPrefix), 2,
+ 0x66, 7840,
+ 0x0, 7834,
+ /*7834*/ uint16(xSetOp), uint16(PMULUDQ),
+ /*7836*/ uint16(xReadSlashR),
+ /*7837*/ uint16(xArgMm1),
+ /*7838*/ uint16(xArgMm2M64),
+ /*7839*/ uint16(xMatch),
+ /*7840*/ uint16(xSetOp), uint16(PMULUDQ),
+ /*7842*/ uint16(xReadSlashR),
+ /*7843*/ uint16(xArgXmm1),
+ /*7844*/ uint16(xArgXmm2M128),
+ /*7845*/ uint16(xMatch),
+ /*7846*/ uint16(xCondPrefix), 2,
+ 0x66, 7858,
+ 0x0, 7852,
+ /*7852*/ uint16(xSetOp), uint16(PMADDWD),
+ /*7854*/ uint16(xReadSlashR),
+ /*7855*/ uint16(xArgMm),
+ /*7856*/ uint16(xArgMmM64),
+ /*7857*/ uint16(xMatch),
+ /*7858*/ uint16(xSetOp), uint16(PMADDWD),
+ /*7860*/ uint16(xReadSlashR),
+ /*7861*/ uint16(xArgXmm1),
+ /*7862*/ uint16(xArgXmm2M128),
+ /*7863*/ uint16(xMatch),
+ /*7864*/ uint16(xCondPrefix), 2,
+ 0x66, 7876,
+ 0x0, 7870,
+ /*7870*/ uint16(xSetOp), uint16(PSADBW),
+ /*7872*/ uint16(xReadSlashR),
+ /*7873*/ uint16(xArgMm1),
+ /*7874*/ uint16(xArgMm2M64),
+ /*7875*/ uint16(xMatch),
+ /*7876*/ uint16(xSetOp), uint16(PSADBW),
+ /*7878*/ uint16(xReadSlashR),
+ /*7879*/ uint16(xArgXmm1),
+ /*7880*/ uint16(xArgXmm2M128),
+ /*7881*/ uint16(xMatch),
+ /*7882*/ uint16(xCondPrefix), 2,
+ 0x66, 7894,
+ 0x0, 7888,
+ /*7888*/ uint16(xSetOp), uint16(MASKMOVQ),
+ /*7890*/ uint16(xReadSlashR),
+ /*7891*/ uint16(xArgMm1),
+ /*7892*/ uint16(xArgMm2),
+ /*7893*/ uint16(xMatch),
+ /*7894*/ uint16(xSetOp), uint16(MASKMOVDQU),
+ /*7896*/ uint16(xReadSlashR),
+ /*7897*/ uint16(xArgXmm1),
+ /*7898*/ uint16(xArgXmm2),
+ /*7899*/ uint16(xMatch),
+ /*7900*/ uint16(xCondPrefix), 2,
+ 0x66, 7912,
+ 0x0, 7906,
+ /*7906*/ uint16(xSetOp), uint16(PSUBB),
+ /*7908*/ uint16(xReadSlashR),
+ /*7909*/ uint16(xArgMm),
+ /*7910*/ uint16(xArgMmM64),
+ /*7911*/ uint16(xMatch),
+ /*7912*/ uint16(xSetOp), uint16(PSUBB),
+ /*7914*/ uint16(xReadSlashR),
+ /*7915*/ uint16(xArgXmm1),
+ /*7916*/ uint16(xArgXmm2M128),
+ /*7917*/ uint16(xMatch),
+ /*7918*/ uint16(xCondPrefix), 2,
+ 0x66, 7930,
+ 0x0, 7924,
+ /*7924*/ uint16(xSetOp), uint16(PSUBW),
+ /*7926*/ uint16(xReadSlashR),
+ /*7927*/ uint16(xArgMm),
+ /*7928*/ uint16(xArgMmM64),
+ /*7929*/ uint16(xMatch),
+ /*7930*/ uint16(xSetOp), uint16(PSUBW),
+ /*7932*/ uint16(xReadSlashR),
+ /*7933*/ uint16(xArgXmm1),
+ /*7934*/ uint16(xArgXmm2M128),
+ /*7935*/ uint16(xMatch),
+ /*7936*/ uint16(xCondPrefix), 2,
+ 0x66, 7948,
+ 0x0, 7942,
+ /*7942*/ uint16(xSetOp), uint16(PSUBD),
+ /*7944*/ uint16(xReadSlashR),
+ /*7945*/ uint16(xArgMm),
+ /*7946*/ uint16(xArgMmM64),
+ /*7947*/ uint16(xMatch),
+ /*7948*/ uint16(xSetOp), uint16(PSUBD),
+ /*7950*/ uint16(xReadSlashR),
+ /*7951*/ uint16(xArgXmm1),
+ /*7952*/ uint16(xArgXmm2M128),
+ /*7953*/ uint16(xMatch),
+ /*7954*/ uint16(xCondPrefix), 2,
+ 0x66, 7966,
+ 0x0, 7960,
+ /*7960*/ uint16(xSetOp), uint16(PSUBQ),
+ /*7962*/ uint16(xReadSlashR),
+ /*7963*/ uint16(xArgMm1),
+ /*7964*/ uint16(xArgMm2M64),
+ /*7965*/ uint16(xMatch),
+ /*7966*/ uint16(xSetOp), uint16(PSUBQ),
+ /*7968*/ uint16(xReadSlashR),
+ /*7969*/ uint16(xArgXmm1),
+ /*7970*/ uint16(xArgXmm2M128),
+ /*7971*/ uint16(xMatch),
+ /*7972*/ uint16(xCondPrefix), 2,
+ 0x66, 7984,
+ 0x0, 7978,
+ /*7978*/ uint16(xSetOp), uint16(PADDB),
+ /*7980*/ uint16(xReadSlashR),
+ /*7981*/ uint16(xArgMm),
+ /*7982*/ uint16(xArgMmM64),
+ /*7983*/ uint16(xMatch),
+ /*7984*/ uint16(xSetOp), uint16(PADDB),
+ /*7986*/ uint16(xReadSlashR),
+ /*7987*/ uint16(xArgXmm1),
+ /*7988*/ uint16(xArgXmm2M128),
+ /*7989*/ uint16(xMatch),
+ /*7990*/ uint16(xCondPrefix), 2,
+ 0x66, 8002,
+ 0x0, 7996,
+ /*7996*/ uint16(xSetOp), uint16(PADDW),
+ /*7998*/ uint16(xReadSlashR),
+ /*7999*/ uint16(xArgMm),
+ /*8000*/ uint16(xArgMmM64),
+ /*8001*/ uint16(xMatch),
+ /*8002*/ uint16(xSetOp), uint16(PADDW),
+ /*8004*/ uint16(xReadSlashR),
+ /*8005*/ uint16(xArgXmm1),
+ /*8006*/ uint16(xArgXmm2M128),
+ /*8007*/ uint16(xMatch),
+ /*8008*/ uint16(xCondPrefix), 2,
+ 0x66, 8020,
+ 0x0, 8014,
+ /*8014*/ uint16(xSetOp), uint16(PADDD),
+ /*8016*/ uint16(xReadSlashR),
+ /*8017*/ uint16(xArgMm),
+ /*8018*/ uint16(xArgMmM64),
+ /*8019*/ uint16(xMatch),
+ /*8020*/ uint16(xSetOp), uint16(PADDD),
+ /*8022*/ uint16(xReadSlashR),
+ /*8023*/ uint16(xArgXmm1),
+ /*8024*/ uint16(xArgXmm2M128),
+ /*8025*/ uint16(xMatch),
+ /*8026*/ uint16(xSetOp), uint16(ADC),
+ /*8028*/ uint16(xReadSlashR),
+ /*8029*/ uint16(xArgRM8),
+ /*8030*/ uint16(xArgR8),
+ /*8031*/ uint16(xMatch),
+ /*8032*/ uint16(xCondIs64), 8035, 8051,
+ /*8035*/ uint16(xCondDataSize), 8039, 8045, 0,
+ /*8039*/ uint16(xSetOp), uint16(ADC),
+ /*8041*/ uint16(xReadSlashR),
+ /*8042*/ uint16(xArgRM16),
+ /*8043*/ uint16(xArgR16),
+ /*8044*/ uint16(xMatch),
+ /*8045*/ uint16(xSetOp), uint16(ADC),
+ /*8047*/ uint16(xReadSlashR),
+ /*8048*/ uint16(xArgRM32),
+ /*8049*/ uint16(xArgR32),
+ /*8050*/ uint16(xMatch),
+ /*8051*/ uint16(xCondDataSize), 8039, 8045, 8055,
+ /*8055*/ uint16(xSetOp), uint16(ADC),
+ /*8057*/ uint16(xReadSlashR),
+ /*8058*/ uint16(xArgRM64),
+ /*8059*/ uint16(xArgR64),
+ /*8060*/ uint16(xMatch),
+ /*8061*/ uint16(xSetOp), uint16(ADC),
+ /*8063*/ uint16(xReadSlashR),
+ /*8064*/ uint16(xArgR8),
+ /*8065*/ uint16(xArgRM8),
+ /*8066*/ uint16(xMatch),
+ /*8067*/ uint16(xCondIs64), 8070, 8086,
+ /*8070*/ uint16(xCondDataSize), 8074, 8080, 0,
+ /*8074*/ uint16(xSetOp), uint16(ADC),
+ /*8076*/ uint16(xReadSlashR),
+ /*8077*/ uint16(xArgR16),
+ /*8078*/ uint16(xArgRM16),
+ /*8079*/ uint16(xMatch),
+ /*8080*/ uint16(xSetOp), uint16(ADC),
+ /*8082*/ uint16(xReadSlashR),
+ /*8083*/ uint16(xArgR32),
+ /*8084*/ uint16(xArgRM32),
+ /*8085*/ uint16(xMatch),
+ /*8086*/ uint16(xCondDataSize), 8074, 8080, 8090,
+ /*8090*/ uint16(xSetOp), uint16(ADC),
+ /*8092*/ uint16(xReadSlashR),
+ /*8093*/ uint16(xArgR64),
+ /*8094*/ uint16(xArgRM64),
+ /*8095*/ uint16(xMatch),
+ /*8096*/ uint16(xSetOp), uint16(ADC),
+ /*8098*/ uint16(xReadIb),
+ /*8099*/ uint16(xArgAL),
+ /*8100*/ uint16(xArgImm8u),
+ /*8101*/ uint16(xMatch),
+ /*8102*/ uint16(xCondIs64), 8105, 8121,
+ /*8105*/ uint16(xCondDataSize), 8109, 8115, 0,
+ /*8109*/ uint16(xSetOp), uint16(ADC),
+ /*8111*/ uint16(xReadIw),
+ /*8112*/ uint16(xArgAX),
+ /*8113*/ uint16(xArgImm16),
+ /*8114*/ uint16(xMatch),
+ /*8115*/ uint16(xSetOp), uint16(ADC),
+ /*8117*/ uint16(xReadId),
+ /*8118*/ uint16(xArgEAX),
+ /*8119*/ uint16(xArgImm32),
+ /*8120*/ uint16(xMatch),
+ /*8121*/ uint16(xCondDataSize), 8109, 8115, 8125,
+ /*8125*/ uint16(xSetOp), uint16(ADC),
+ /*8127*/ uint16(xReadId),
+ /*8128*/ uint16(xArgRAX),
+ /*8129*/ uint16(xArgImm32),
+ /*8130*/ uint16(xMatch),
+ /*8131*/ uint16(xCondIs64), 8134, 0,
+ /*8134*/ uint16(xSetOp), uint16(PUSH),
+ /*8136*/ uint16(xArgSS),
+ /*8137*/ uint16(xMatch),
+ /*8138*/ uint16(xCondIs64), 8141, 0,
+ /*8141*/ uint16(xSetOp), uint16(POP),
+ /*8143*/ uint16(xArgSS),
+ /*8144*/ uint16(xMatch),
+ /*8145*/ uint16(xSetOp), uint16(SBB),
+ /*8147*/ uint16(xReadSlashR),
+ /*8148*/ uint16(xArgRM8),
+ /*8149*/ uint16(xArgR8),
+ /*8150*/ uint16(xMatch),
+ /*8151*/ uint16(xCondIs64), 8154, 8170,
+ /*8154*/ uint16(xCondDataSize), 8158, 8164, 0,
+ /*8158*/ uint16(xSetOp), uint16(SBB),
+ /*8160*/ uint16(xReadSlashR),
+ /*8161*/ uint16(xArgRM16),
+ /*8162*/ uint16(xArgR16),
+ /*8163*/ uint16(xMatch),
+ /*8164*/ uint16(xSetOp), uint16(SBB),
+ /*8166*/ uint16(xReadSlashR),
+ /*8167*/ uint16(xArgRM32),
+ /*8168*/ uint16(xArgR32),
+ /*8169*/ uint16(xMatch),
+ /*8170*/ uint16(xCondDataSize), 8158, 8164, 8174,
+ /*8174*/ uint16(xSetOp), uint16(SBB),
+ /*8176*/ uint16(xReadSlashR),
+ /*8177*/ uint16(xArgRM64),
+ /*8178*/ uint16(xArgR64),
+ /*8179*/ uint16(xMatch),
+ /*8180*/ uint16(xSetOp), uint16(SBB),
+ /*8182*/ uint16(xReadSlashR),
+ /*8183*/ uint16(xArgR8),
+ /*8184*/ uint16(xArgRM8),
+ /*8185*/ uint16(xMatch),
+ /*8186*/ uint16(xCondIs64), 8189, 8205,
+ /*8189*/ uint16(xCondDataSize), 8193, 8199, 0,
+ /*8193*/ uint16(xSetOp), uint16(SBB),
+ /*8195*/ uint16(xReadSlashR),
+ /*8196*/ uint16(xArgR16),
+ /*8197*/ uint16(xArgRM16),
+ /*8198*/ uint16(xMatch),
+ /*8199*/ uint16(xSetOp), uint16(SBB),
+ /*8201*/ uint16(xReadSlashR),
+ /*8202*/ uint16(xArgR32),
+ /*8203*/ uint16(xArgRM32),
+ /*8204*/ uint16(xMatch),
+ /*8205*/ uint16(xCondDataSize), 8193, 8199, 8209,
+ /*8209*/ uint16(xSetOp), uint16(SBB),
+ /*8211*/ uint16(xReadSlashR),
+ /*8212*/ uint16(xArgR64),
+ /*8213*/ uint16(xArgRM64),
+ /*8214*/ uint16(xMatch),
+ /*8215*/ uint16(xSetOp), uint16(SBB),
+ /*8217*/ uint16(xReadIb),
+ /*8218*/ uint16(xArgAL),
+ /*8219*/ uint16(xArgImm8u),
+ /*8220*/ uint16(xMatch),
+ /*8221*/ uint16(xCondIs64), 8224, 8240,
+ /*8224*/ uint16(xCondDataSize), 8228, 8234, 0,
+ /*8228*/ uint16(xSetOp), uint16(SBB),
+ /*8230*/ uint16(xReadIw),
+ /*8231*/ uint16(xArgAX),
+ /*8232*/ uint16(xArgImm16),
+ /*8233*/ uint16(xMatch),
+ /*8234*/ uint16(xSetOp), uint16(SBB),
+ /*8236*/ uint16(xReadId),
+ /*8237*/ uint16(xArgEAX),
+ /*8238*/ uint16(xArgImm32),
+ /*8239*/ uint16(xMatch),
+ /*8240*/ uint16(xCondDataSize), 8228, 8234, 8244,
+ /*8244*/ uint16(xSetOp), uint16(SBB),
+ /*8246*/ uint16(xReadId),
+ /*8247*/ uint16(xArgRAX),
+ /*8248*/ uint16(xArgImm32),
+ /*8249*/ uint16(xMatch),
+ /*8250*/ uint16(xCondIs64), 8253, 0,
+ /*8253*/ uint16(xSetOp), uint16(PUSH),
+ /*8255*/ uint16(xArgDS),
+ /*8256*/ uint16(xMatch),
+ /*8257*/ uint16(xCondIs64), 8260, 0,
+ /*8260*/ uint16(xSetOp), uint16(POP),
+ /*8262*/ uint16(xArgDS),
+ /*8263*/ uint16(xMatch),
+ /*8264*/ uint16(xSetOp), uint16(AND),
+ /*8266*/ uint16(xReadSlashR),
+ /*8267*/ uint16(xArgRM8),
+ /*8268*/ uint16(xArgR8),
+ /*8269*/ uint16(xMatch),
+ /*8270*/ uint16(xCondIs64), 8273, 8289,
+ /*8273*/ uint16(xCondDataSize), 8277, 8283, 0,
+ /*8277*/ uint16(xSetOp), uint16(AND),
+ /*8279*/ uint16(xReadSlashR),
+ /*8280*/ uint16(xArgRM16),
+ /*8281*/ uint16(xArgR16),
+ /*8282*/ uint16(xMatch),
+ /*8283*/ uint16(xSetOp), uint16(AND),
+ /*8285*/ uint16(xReadSlashR),
+ /*8286*/ uint16(xArgRM32),
+ /*8287*/ uint16(xArgR32),
+ /*8288*/ uint16(xMatch),
+ /*8289*/ uint16(xCondDataSize), 8277, 8283, 8293,
+ /*8293*/ uint16(xSetOp), uint16(AND),
+ /*8295*/ uint16(xReadSlashR),
+ /*8296*/ uint16(xArgRM64),
+ /*8297*/ uint16(xArgR64),
+ /*8298*/ uint16(xMatch),
+ /*8299*/ uint16(xSetOp), uint16(AND),
+ /*8301*/ uint16(xReadSlashR),
+ /*8302*/ uint16(xArgR8),
+ /*8303*/ uint16(xArgRM8),
+ /*8304*/ uint16(xMatch),
+ /*8305*/ uint16(xCondIs64), 8308, 8324,
+ /*8308*/ uint16(xCondDataSize), 8312, 8318, 0,
+ /*8312*/ uint16(xSetOp), uint16(AND),
+ /*8314*/ uint16(xReadSlashR),
+ /*8315*/ uint16(xArgR16),
+ /*8316*/ uint16(xArgRM16),
+ /*8317*/ uint16(xMatch),
+ /*8318*/ uint16(xSetOp), uint16(AND),
+ /*8320*/ uint16(xReadSlashR),
+ /*8321*/ uint16(xArgR32),
+ /*8322*/ uint16(xArgRM32),
+ /*8323*/ uint16(xMatch),
+ /*8324*/ uint16(xCondDataSize), 8312, 8318, 8328,
+ /*8328*/ uint16(xSetOp), uint16(AND),
+ /*8330*/ uint16(xReadSlashR),
+ /*8331*/ uint16(xArgR64),
+ /*8332*/ uint16(xArgRM64),
+ /*8333*/ uint16(xMatch),
+ /*8334*/ uint16(xSetOp), uint16(AND),
+ /*8336*/ uint16(xReadIb),
+ /*8337*/ uint16(xArgAL),
+ /*8338*/ uint16(xArgImm8u),
+ /*8339*/ uint16(xMatch),
+ /*8340*/ uint16(xCondIs64), 8343, 8359,
+ /*8343*/ uint16(xCondDataSize), 8347, 8353, 0,
+ /*8347*/ uint16(xSetOp), uint16(AND),
+ /*8349*/ uint16(xReadIw),
+ /*8350*/ uint16(xArgAX),
+ /*8351*/ uint16(xArgImm16),
+ /*8352*/ uint16(xMatch),
+ /*8353*/ uint16(xSetOp), uint16(AND),
+ /*8355*/ uint16(xReadId),
+ /*8356*/ uint16(xArgEAX),
+ /*8357*/ uint16(xArgImm32),
+ /*8358*/ uint16(xMatch),
+ /*8359*/ uint16(xCondDataSize), 8347, 8353, 8363,
+ /*8363*/ uint16(xSetOp), uint16(AND),
+ /*8365*/ uint16(xReadId),
+ /*8366*/ uint16(xArgRAX),
+ /*8367*/ uint16(xArgImm32),
+ /*8368*/ uint16(xMatch),
+ /*8369*/ uint16(xCondIs64), 8372, 0,
+ /*8372*/ uint16(xSetOp), uint16(DAA),
+ /*8374*/ uint16(xMatch),
+ /*8375*/ uint16(xSetOp), uint16(SUB),
+ /*8377*/ uint16(xReadSlashR),
+ /*8378*/ uint16(xArgRM8),
+ /*8379*/ uint16(xArgR8),
+ /*8380*/ uint16(xMatch),
+ /*8381*/ uint16(xCondIs64), 8384, 8400,
+ /*8384*/ uint16(xCondDataSize), 8388, 8394, 0,
+ /*8388*/ uint16(xSetOp), uint16(SUB),
+ /*8390*/ uint16(xReadSlashR),
+ /*8391*/ uint16(xArgRM16),
+ /*8392*/ uint16(xArgR16),
+ /*8393*/ uint16(xMatch),
+ /*8394*/ uint16(xSetOp), uint16(SUB),
+ /*8396*/ uint16(xReadSlashR),
+ /*8397*/ uint16(xArgRM32),
+ /*8398*/ uint16(xArgR32),
+ /*8399*/ uint16(xMatch),
+ /*8400*/ uint16(xCondDataSize), 8388, 8394, 8404,
+ /*8404*/ uint16(xSetOp), uint16(SUB),
+ /*8406*/ uint16(xReadSlashR),
+ /*8407*/ uint16(xArgRM64),
+ /*8408*/ uint16(xArgR64),
+ /*8409*/ uint16(xMatch),
+ /*8410*/ uint16(xSetOp), uint16(SUB),
+ /*8412*/ uint16(xReadSlashR),
+ /*8413*/ uint16(xArgR8),
+ /*8414*/ uint16(xArgRM8),
+ /*8415*/ uint16(xMatch),
+ /*8416*/ uint16(xCondIs64), 8419, 8435,
+ /*8419*/ uint16(xCondDataSize), 8423, 8429, 0,
+ /*8423*/ uint16(xSetOp), uint16(SUB),
+ /*8425*/ uint16(xReadSlashR),
+ /*8426*/ uint16(xArgR16),
+ /*8427*/ uint16(xArgRM16),
+ /*8428*/ uint16(xMatch),
+ /*8429*/ uint16(xSetOp), uint16(SUB),
+ /*8431*/ uint16(xReadSlashR),
+ /*8432*/ uint16(xArgR32),
+ /*8433*/ uint16(xArgRM32),
+ /*8434*/ uint16(xMatch),
+ /*8435*/ uint16(xCondDataSize), 8423, 8429, 8439,
+ /*8439*/ uint16(xSetOp), uint16(SUB),
+ /*8441*/ uint16(xReadSlashR),
+ /*8442*/ uint16(xArgR64),
+ /*8443*/ uint16(xArgRM64),
+ /*8444*/ uint16(xMatch),
+ /*8445*/ uint16(xSetOp), uint16(SUB),
+ /*8447*/ uint16(xReadIb),
+ /*8448*/ uint16(xArgAL),
+ /*8449*/ uint16(xArgImm8u),
+ /*8450*/ uint16(xMatch),
+ /*8451*/ uint16(xCondIs64), 8454, 8470,
+ /*8454*/ uint16(xCondDataSize), 8458, 8464, 0,
+ /*8458*/ uint16(xSetOp), uint16(SUB),
+ /*8460*/ uint16(xReadIw),
+ /*8461*/ uint16(xArgAX),
+ /*8462*/ uint16(xArgImm16),
+ /*8463*/ uint16(xMatch),
+ /*8464*/ uint16(xSetOp), uint16(SUB),
+ /*8466*/ uint16(xReadId),
+ /*8467*/ uint16(xArgEAX),
+ /*8468*/ uint16(xArgImm32),
+ /*8469*/ uint16(xMatch),
+ /*8470*/ uint16(xCondDataSize), 8458, 8464, 8474,
+ /*8474*/ uint16(xSetOp), uint16(SUB),
+ /*8476*/ uint16(xReadId),
+ /*8477*/ uint16(xArgRAX),
+ /*8478*/ uint16(xArgImm32),
+ /*8479*/ uint16(xMatch),
+ /*8480*/ uint16(xCondIs64), 8483, 0,
+ /*8483*/ uint16(xSetOp), uint16(DAS),
+ /*8485*/ uint16(xMatch),
+ /*8486*/ uint16(xSetOp), uint16(XOR),
+ /*8488*/ uint16(xReadSlashR),
+ /*8489*/ uint16(xArgRM8),
+ /*8490*/ uint16(xArgR8),
+ /*8491*/ uint16(xMatch),
+ /*8492*/ uint16(xCondIs64), 8495, 8511,
+ /*8495*/ uint16(xCondDataSize), 8499, 8505, 0,
+ /*8499*/ uint16(xSetOp), uint16(XOR),
+ /*8501*/ uint16(xReadSlashR),
+ /*8502*/ uint16(xArgRM16),
+ /*8503*/ uint16(xArgR16),
+ /*8504*/ uint16(xMatch),
+ /*8505*/ uint16(xSetOp), uint16(XOR),
+ /*8507*/ uint16(xReadSlashR),
+ /*8508*/ uint16(xArgRM32),
+ /*8509*/ uint16(xArgR32),
+ /*8510*/ uint16(xMatch),
+ /*8511*/ uint16(xCondDataSize), 8499, 8505, 8515,
+ /*8515*/ uint16(xSetOp), uint16(XOR),
+ /*8517*/ uint16(xReadSlashR),
+ /*8518*/ uint16(xArgRM64),
+ /*8519*/ uint16(xArgR64),
+ /*8520*/ uint16(xMatch),
+ /*8521*/ uint16(xSetOp), uint16(XOR),
+ /*8523*/ uint16(xReadSlashR),
+ /*8524*/ uint16(xArgR8),
+ /*8525*/ uint16(xArgRM8),
+ /*8526*/ uint16(xMatch),
+ /*8527*/ uint16(xCondIs64), 8530, 8546,
+ /*8530*/ uint16(xCondDataSize), 8534, 8540, 0,
+ /*8534*/ uint16(xSetOp), uint16(XOR),
+ /*8536*/ uint16(xReadSlashR),
+ /*8537*/ uint16(xArgR16),
+ /*8538*/ uint16(xArgRM16),
+ /*8539*/ uint16(xMatch),
+ /*8540*/ uint16(xSetOp), uint16(XOR),
+ /*8542*/ uint16(xReadSlashR),
+ /*8543*/ uint16(xArgR32),
+ /*8544*/ uint16(xArgRM32),
+ /*8545*/ uint16(xMatch),
+ /*8546*/ uint16(xCondDataSize), 8534, 8540, 8550,
+ /*8550*/ uint16(xSetOp), uint16(XOR),
+ /*8552*/ uint16(xReadSlashR),
+ /*8553*/ uint16(xArgR64),
+ /*8554*/ uint16(xArgRM64),
+ /*8555*/ uint16(xMatch),
+ /*8556*/ uint16(xSetOp), uint16(XOR),
+ /*8558*/ uint16(xReadIb),
+ /*8559*/ uint16(xArgAL),
+ /*8560*/ uint16(xArgImm8u),
+ /*8561*/ uint16(xMatch),
+ /*8562*/ uint16(xCondIs64), 8565, 8581,
+ /*8565*/ uint16(xCondDataSize), 8569, 8575, 0,
+ /*8569*/ uint16(xSetOp), uint16(XOR),
+ /*8571*/ uint16(xReadIw),
+ /*8572*/ uint16(xArgAX),
+ /*8573*/ uint16(xArgImm16),
+ /*8574*/ uint16(xMatch),
+ /*8575*/ uint16(xSetOp), uint16(XOR),
+ /*8577*/ uint16(xReadId),
+ /*8578*/ uint16(xArgEAX),
+ /*8579*/ uint16(xArgImm32),
+ /*8580*/ uint16(xMatch),
+ /*8581*/ uint16(xCondDataSize), 8569, 8575, 8585,
+ /*8585*/ uint16(xSetOp), uint16(XOR),
+ /*8587*/ uint16(xReadId),
+ /*8588*/ uint16(xArgRAX),
+ /*8589*/ uint16(xArgImm32),
+ /*8590*/ uint16(xMatch),
+ /*8591*/ uint16(xCondIs64), 8594, 0,
+ /*8594*/ uint16(xSetOp), uint16(AAA),
+ /*8596*/ uint16(xMatch),
+ /*8597*/ uint16(xSetOp), uint16(CMP),
+ /*8599*/ uint16(xReadSlashR),
+ /*8600*/ uint16(xArgRM8),
+ /*8601*/ uint16(xArgR8),
+ /*8602*/ uint16(xMatch),
+ /*8603*/ uint16(xCondIs64), 8606, 8622,
+ /*8606*/ uint16(xCondDataSize), 8610, 8616, 0,
+ /*8610*/ uint16(xSetOp), uint16(CMP),
+ /*8612*/ uint16(xReadSlashR),
+ /*8613*/ uint16(xArgRM16),
+ /*8614*/ uint16(xArgR16),
+ /*8615*/ uint16(xMatch),
+ /*8616*/ uint16(xSetOp), uint16(CMP),
+ /*8618*/ uint16(xReadSlashR),
+ /*8619*/ uint16(xArgRM32),
+ /*8620*/ uint16(xArgR32),
+ /*8621*/ uint16(xMatch),
+ /*8622*/ uint16(xCondDataSize), 8610, 8616, 8626,
+ /*8626*/ uint16(xSetOp), uint16(CMP),
+ /*8628*/ uint16(xReadSlashR),
+ /*8629*/ uint16(xArgRM64),
+ /*8630*/ uint16(xArgR64),
+ /*8631*/ uint16(xMatch),
+ /*8632*/ uint16(xSetOp), uint16(CMP),
+ /*8634*/ uint16(xReadSlashR),
+ /*8635*/ uint16(xArgR8),
+ /*8636*/ uint16(xArgRM8),
+ /*8637*/ uint16(xMatch),
+ /*8638*/ uint16(xCondIs64), 8641, 8657,
+ /*8641*/ uint16(xCondDataSize), 8645, 8651, 0,
+ /*8645*/ uint16(xSetOp), uint16(CMP),
+ /*8647*/ uint16(xReadSlashR),
+ /*8648*/ uint16(xArgR16),
+ /*8649*/ uint16(xArgRM16),
+ /*8650*/ uint16(xMatch),
+ /*8651*/ uint16(xSetOp), uint16(CMP),
+ /*8653*/ uint16(xReadSlashR),
+ /*8654*/ uint16(xArgR32),
+ /*8655*/ uint16(xArgRM32),
+ /*8656*/ uint16(xMatch),
+ /*8657*/ uint16(xCondDataSize), 8645, 8651, 8661,
+ /*8661*/ uint16(xSetOp), uint16(CMP),
+ /*8663*/ uint16(xReadSlashR),
+ /*8664*/ uint16(xArgR64),
+ /*8665*/ uint16(xArgRM64),
+ /*8666*/ uint16(xMatch),
+ /*8667*/ uint16(xSetOp), uint16(CMP),
+ /*8669*/ uint16(xReadIb),
+ /*8670*/ uint16(xArgAL),
+ /*8671*/ uint16(xArgImm8u),
+ /*8672*/ uint16(xMatch),
+ /*8673*/ uint16(xCondIs64), 8676, 8692,
+ /*8676*/ uint16(xCondDataSize), 8680, 8686, 0,
+ /*8680*/ uint16(xSetOp), uint16(CMP),
+ /*8682*/ uint16(xReadIw),
+ /*8683*/ uint16(xArgAX),
+ /*8684*/ uint16(xArgImm16),
+ /*8685*/ uint16(xMatch),
+ /*8686*/ uint16(xSetOp), uint16(CMP),
+ /*8688*/ uint16(xReadId),
+ /*8689*/ uint16(xArgEAX),
+ /*8690*/ uint16(xArgImm32),
+ /*8691*/ uint16(xMatch),
+ /*8692*/ uint16(xCondDataSize), 8680, 8686, 8696,
+ /*8696*/ uint16(xSetOp), uint16(CMP),
+ /*8698*/ uint16(xReadId),
+ /*8699*/ uint16(xArgRAX),
+ /*8700*/ uint16(xArgImm32),
+ /*8701*/ uint16(xMatch),
+ /*8702*/ uint16(xCondIs64), 8705, 0,
+ /*8705*/ uint16(xSetOp), uint16(AAS),
+ /*8707*/ uint16(xMatch),
+ /*8708*/ uint16(xCondIs64), 8711, 0,
+ /*8711*/ uint16(xCondDataSize), 8715, 8719, 0,
+ /*8715*/ uint16(xSetOp), uint16(INC),
+ /*8717*/ uint16(xArgR16op),
+ /*8718*/ uint16(xMatch),
+ /*8719*/ uint16(xSetOp), uint16(INC),
+ /*8721*/ uint16(xArgR32op),
+ /*8722*/ uint16(xMatch),
+ /*8723*/ uint16(xCondIs64), 8726, 0,
+ /*8726*/ uint16(xCondDataSize), 8730, 8734, 0,
+ /*8730*/ uint16(xSetOp), uint16(DEC),
+ /*8732*/ uint16(xArgR16op),
+ /*8733*/ uint16(xMatch),
+ /*8734*/ uint16(xSetOp), uint16(DEC),
+ /*8736*/ uint16(xArgR32op),
+ /*8737*/ uint16(xMatch),
+ /*8738*/ uint16(xCondIs64), 8741, 8753,
+ /*8741*/ uint16(xCondDataSize), 8745, 8749, 0,
+ /*8745*/ uint16(xSetOp), uint16(PUSH),
+ /*8747*/ uint16(xArgR16op),
+ /*8748*/ uint16(xMatch),
+ /*8749*/ uint16(xSetOp), uint16(PUSH),
+ /*8751*/ uint16(xArgR32op),
+ /*8752*/ uint16(xMatch),
+ /*8753*/ uint16(xCondDataSize), 8745, 8757, 8761,
+ /*8757*/ uint16(xSetOp), uint16(PUSH),
+ /*8759*/ uint16(xArgR64op),
+ /*8760*/ uint16(xMatch),
+ /*8761*/ uint16(xSetOp), uint16(PUSH),
+ /*8763*/ uint16(xArgR64op),
+ /*8764*/ uint16(xMatch),
+ /*8765*/ uint16(xCondIs64), 8768, 8780,
+ /*8768*/ uint16(xCondDataSize), 8772, 8776, 0,
+ /*8772*/ uint16(xSetOp), uint16(POP),
+ /*8774*/ uint16(xArgR16op),
+ /*8775*/ uint16(xMatch),
+ /*8776*/ uint16(xSetOp), uint16(POP),
+ /*8778*/ uint16(xArgR32op),
+ /*8779*/ uint16(xMatch),
+ /*8780*/ uint16(xCondDataSize), 8772, 8784, 8788,
+ /*8784*/ uint16(xSetOp), uint16(POP),
+ /*8786*/ uint16(xArgR64op),
+ /*8787*/ uint16(xMatch),
+ /*8788*/ uint16(xSetOp), uint16(POP),
+ /*8790*/ uint16(xArgR64op),
+ /*8791*/ uint16(xMatch),
+ /*8792*/ uint16(xCondIs64), 8795, 0,
+ /*8795*/ uint16(xCondDataSize), 8799, 8802, 0,
+ /*8799*/ uint16(xSetOp), uint16(PUSHA),
+ /*8801*/ uint16(xMatch),
+ /*8802*/ uint16(xSetOp), uint16(PUSHAD),
+ /*8804*/ uint16(xMatch),
+ /*8805*/ uint16(xCondIs64), 8808, 0,
+ /*8808*/ uint16(xCondDataSize), 8812, 8815, 0,
+ /*8812*/ uint16(xSetOp), uint16(POPA),
+ /*8814*/ uint16(xMatch),
+ /*8815*/ uint16(xSetOp), uint16(POPAD),
+ /*8817*/ uint16(xMatch),
+ /*8818*/ uint16(xCondIs64), 8821, 0,
+ /*8821*/ uint16(xCondDataSize), 8825, 8831, 0,
+ /*8825*/ uint16(xSetOp), uint16(BOUND),
+ /*8827*/ uint16(xReadSlashR),
+ /*8828*/ uint16(xArgR16),
+ /*8829*/ uint16(xArgM16and16),
+ /*8830*/ uint16(xMatch),
+ /*8831*/ uint16(xSetOp), uint16(BOUND),
+ /*8833*/ uint16(xReadSlashR),
+ /*8834*/ uint16(xArgR32),
+ /*8835*/ uint16(xArgM32and32),
+ /*8836*/ uint16(xMatch),
+ /*8837*/ uint16(xCondIs64), 8840, 8846,
+ /*8840*/ uint16(xSetOp), uint16(ARPL),
+ /*8842*/ uint16(xReadSlashR),
+ /*8843*/ uint16(xArgRM16),
+ /*8844*/ uint16(xArgR16),
+ /*8845*/ uint16(xMatch),
+ /*8846*/ uint16(xCondDataSize), 8850, 8856, 8862,
+ /*8850*/ uint16(xSetOp), uint16(MOVSXD),
+ /*8852*/ uint16(xReadSlashR),
+ /*8853*/ uint16(xArgR16),
+ /*8854*/ uint16(xArgRM32),
+ /*8855*/ uint16(xMatch),
+ /*8856*/ uint16(xSetOp), uint16(MOVSXD),
+ /*8858*/ uint16(xReadSlashR),
+ /*8859*/ uint16(xArgR32),
+ /*8860*/ uint16(xArgRM32),
+ /*8861*/ uint16(xMatch),
+ /*8862*/ uint16(xSetOp), uint16(MOVSXD),
+ /*8864*/ uint16(xReadSlashR),
+ /*8865*/ uint16(xArgR64),
+ /*8866*/ uint16(xArgRM32),
+ /*8867*/ uint16(xMatch),
+ /*8868*/ uint16(xCondDataSize), 8872, 8877, 8882,
+ /*8872*/ uint16(xSetOp), uint16(PUSH),
+ /*8874*/ uint16(xReadIw),
+ /*8875*/ uint16(xArgImm16),
+ /*8876*/ uint16(xMatch),
+ /*8877*/ uint16(xSetOp), uint16(PUSH),
+ /*8879*/ uint16(xReadId),
+ /*8880*/ uint16(xArgImm32),
+ /*8881*/ uint16(xMatch),
+ /*8882*/ uint16(xSetOp), uint16(PUSH),
+ /*8884*/ uint16(xReadId),
+ /*8885*/ uint16(xArgImm32),
+ /*8886*/ uint16(xMatch),
+ /*8887*/ uint16(xCondIs64), 8890, 8910,
+ /*8890*/ uint16(xCondDataSize), 8894, 8902, 0,
+ /*8894*/ uint16(xSetOp), uint16(IMUL),
+ /*8896*/ uint16(xReadSlashR),
+ /*8897*/ uint16(xReadIw),
+ /*8898*/ uint16(xArgR16),
+ /*8899*/ uint16(xArgRM16),
+ /*8900*/ uint16(xArgImm16),
+ /*8901*/ uint16(xMatch),
+ /*8902*/ uint16(xSetOp), uint16(IMUL),
+ /*8904*/ uint16(xReadSlashR),
+ /*8905*/ uint16(xReadId),
+ /*8906*/ uint16(xArgR32),
+ /*8907*/ uint16(xArgRM32),
+ /*8908*/ uint16(xArgImm32),
+ /*8909*/ uint16(xMatch),
+ /*8910*/ uint16(xCondDataSize), 8894, 8902, 8914,
+ /*8914*/ uint16(xSetOp), uint16(IMUL),
+ /*8916*/ uint16(xReadSlashR),
+ /*8917*/ uint16(xReadId),
+ /*8918*/ uint16(xArgR64),
+ /*8919*/ uint16(xArgRM64),
+ /*8920*/ uint16(xArgImm32),
+ /*8921*/ uint16(xMatch),
+ /*8922*/ uint16(xSetOp), uint16(PUSH),
+ /*8924*/ uint16(xReadIb),
+ /*8925*/ uint16(xArgImm8),
+ /*8926*/ uint16(xMatch),
+ /*8927*/ uint16(xCondIs64), 8930, 8950,
+ /*8930*/ uint16(xCondDataSize), 8934, 8942, 0,
+ /*8934*/ uint16(xSetOp), uint16(IMUL),
+ /*8936*/ uint16(xReadSlashR),
+ /*8937*/ uint16(xReadIb),
+ /*8938*/ uint16(xArgR16),
+ /*8939*/ uint16(xArgRM16),
+ /*8940*/ uint16(xArgImm8),
+ /*8941*/ uint16(xMatch),
+ /*8942*/ uint16(xSetOp), uint16(IMUL),
+ /*8944*/ uint16(xReadSlashR),
+ /*8945*/ uint16(xReadIb),
+ /*8946*/ uint16(xArgR32),
+ /*8947*/ uint16(xArgRM32),
+ /*8948*/ uint16(xArgImm8),
+ /*8949*/ uint16(xMatch),
+ /*8950*/ uint16(xCondDataSize), 8934, 8942, 8954,
+ /*8954*/ uint16(xSetOp), uint16(IMUL),
+ /*8956*/ uint16(xReadSlashR),
+ /*8957*/ uint16(xReadIb),
+ /*8958*/ uint16(xArgR64),
+ /*8959*/ uint16(xArgRM64),
+ /*8960*/ uint16(xArgImm8),
+ /*8961*/ uint16(xMatch),
+ /*8962*/ uint16(xSetOp), uint16(INSB),
+ /*8964*/ uint16(xMatch),
+ /*8965*/ uint16(xCondDataSize), 8969, 8972, 8975,
+ /*8969*/ uint16(xSetOp), uint16(INSW),
+ /*8971*/ uint16(xMatch),
+ /*8972*/ uint16(xSetOp), uint16(INSD),
+ /*8974*/ uint16(xMatch),
+ /*8975*/ uint16(xSetOp), uint16(INSD),
+ /*8977*/ uint16(xMatch),
+ /*8978*/ uint16(xSetOp), uint16(OUTSB),
+ /*8980*/ uint16(xMatch),
+ /*8981*/ uint16(xCondDataSize), 8985, 8988, 8991,
+ /*8985*/ uint16(xSetOp), uint16(OUTSW),
+ /*8987*/ uint16(xMatch),
+ /*8988*/ uint16(xSetOp), uint16(OUTSD),
+ /*8990*/ uint16(xMatch),
+ /*8991*/ uint16(xSetOp), uint16(OUTSD),
+ /*8993*/ uint16(xMatch),
+ /*8994*/ uint16(xSetOp), uint16(JO),
+ /*8996*/ uint16(xReadCb),
+ /*8997*/ uint16(xArgRel8),
+ /*8998*/ uint16(xMatch),
+ /*8999*/ uint16(xSetOp), uint16(JNO),
+ /*9001*/ uint16(xReadCb),
+ /*9002*/ uint16(xArgRel8),
+ /*9003*/ uint16(xMatch),
+ /*9004*/ uint16(xSetOp), uint16(JB),
+ /*9006*/ uint16(xReadCb),
+ /*9007*/ uint16(xArgRel8),
+ /*9008*/ uint16(xMatch),
+ /*9009*/ uint16(xSetOp), uint16(JAE),
+ /*9011*/ uint16(xReadCb),
+ /*9012*/ uint16(xArgRel8),
+ /*9013*/ uint16(xMatch),
+ /*9014*/ uint16(xSetOp), uint16(JE),
+ /*9016*/ uint16(xReadCb),
+ /*9017*/ uint16(xArgRel8),
+ /*9018*/ uint16(xMatch),
+ /*9019*/ uint16(xSetOp), uint16(JNE),
+ /*9021*/ uint16(xReadCb),
+ /*9022*/ uint16(xArgRel8),
+ /*9023*/ uint16(xMatch),
+ /*9024*/ uint16(xSetOp), uint16(JBE),
+ /*9026*/ uint16(xReadCb),
+ /*9027*/ uint16(xArgRel8),
+ /*9028*/ uint16(xMatch),
+ /*9029*/ uint16(xSetOp), uint16(JA),
+ /*9031*/ uint16(xReadCb),
+ /*9032*/ uint16(xArgRel8),
+ /*9033*/ uint16(xMatch),
+ /*9034*/ uint16(xSetOp), uint16(JS),
+ /*9036*/ uint16(xReadCb),
+ /*9037*/ uint16(xArgRel8),
+ /*9038*/ uint16(xMatch),
+ /*9039*/ uint16(xSetOp), uint16(JNS),
+ /*9041*/ uint16(xReadCb),
+ /*9042*/ uint16(xArgRel8),
+ /*9043*/ uint16(xMatch),
+ /*9044*/ uint16(xSetOp), uint16(JP),
+ /*9046*/ uint16(xReadCb),
+ /*9047*/ uint16(xArgRel8),
+ /*9048*/ uint16(xMatch),
+ /*9049*/ uint16(xSetOp), uint16(JNP),
+ /*9051*/ uint16(xReadCb),
+ /*9052*/ uint16(xArgRel8),
+ /*9053*/ uint16(xMatch),
+ /*9054*/ uint16(xSetOp), uint16(JL),
+ /*9056*/ uint16(xReadCb),
+ /*9057*/ uint16(xArgRel8),
+ /*9058*/ uint16(xMatch),
+ /*9059*/ uint16(xSetOp), uint16(JGE),
+ /*9061*/ uint16(xReadCb),
+ /*9062*/ uint16(xArgRel8),
+ /*9063*/ uint16(xMatch),
+ /*9064*/ uint16(xSetOp), uint16(JLE),
+ /*9066*/ uint16(xReadCb),
+ /*9067*/ uint16(xArgRel8),
+ /*9068*/ uint16(xMatch),
+ /*9069*/ uint16(xSetOp), uint16(JG),
+ /*9071*/ uint16(xReadCb),
+ /*9072*/ uint16(xArgRel8),
+ /*9073*/ uint16(xMatch),
+ /*9074*/ uint16(xCondSlashR),
+ 9083, // 0
+ 9089, // 1
+ 9095, // 2
+ 9101, // 3
+ 9107, // 4
+ 9113, // 5
+ 9119, // 6
+ 9125, // 7
+ /*9083*/ uint16(xSetOp), uint16(ADD),
+ /*9085*/ uint16(xReadIb),
+ /*9086*/ uint16(xArgRM8),
+ /*9087*/ uint16(xArgImm8u),
+ /*9088*/ uint16(xMatch),
+ /*9089*/ uint16(xSetOp), uint16(OR),
+ /*9091*/ uint16(xReadIb),
+ /*9092*/ uint16(xArgRM8),
+ /*9093*/ uint16(xArgImm8u),
+ /*9094*/ uint16(xMatch),
+ /*9095*/ uint16(xSetOp), uint16(ADC),
+ /*9097*/ uint16(xReadIb),
+ /*9098*/ uint16(xArgRM8),
+ /*9099*/ uint16(xArgImm8u),
+ /*9100*/ uint16(xMatch),
+ /*9101*/ uint16(xSetOp), uint16(SBB),
+ /*9103*/ uint16(xReadIb),
+ /*9104*/ uint16(xArgRM8),
+ /*9105*/ uint16(xArgImm8u),
+ /*9106*/ uint16(xMatch),
+ /*9107*/ uint16(xSetOp), uint16(AND),
+ /*9109*/ uint16(xReadIb),
+ /*9110*/ uint16(xArgRM8),
+ /*9111*/ uint16(xArgImm8u),
+ /*9112*/ uint16(xMatch),
+ /*9113*/ uint16(xSetOp), uint16(SUB),
+ /*9115*/ uint16(xReadIb),
+ /*9116*/ uint16(xArgRM8),
+ /*9117*/ uint16(xArgImm8u),
+ /*9118*/ uint16(xMatch),
+ /*9119*/ uint16(xSetOp), uint16(XOR),
+ /*9121*/ uint16(xReadIb),
+ /*9122*/ uint16(xArgRM8),
+ /*9123*/ uint16(xArgImm8u),
+ /*9124*/ uint16(xMatch),
+ /*9125*/ uint16(xSetOp), uint16(CMP),
+ /*9127*/ uint16(xReadIb),
+ /*9128*/ uint16(xArgRM8),
+ /*9129*/ uint16(xArgImm8u),
+ /*9130*/ uint16(xMatch),
+ /*9131*/ uint16(xCondSlashR),
+ 9140, // 0
+ 9169, // 1
+ 9198, // 2
+ 9227, // 3
+ 9256, // 4
+ 9285, // 5
+ 9314, // 6
+ 9343, // 7
+ /*9140*/ uint16(xCondIs64), 9143, 9159,
+ /*9143*/ uint16(xCondDataSize), 9147, 9153, 0,
+ /*9147*/ uint16(xSetOp), uint16(ADD),
+ /*9149*/ uint16(xReadIw),
+ /*9150*/ uint16(xArgRM16),
+ /*9151*/ uint16(xArgImm16),
+ /*9152*/ uint16(xMatch),
+ /*9153*/ uint16(xSetOp), uint16(ADD),
+ /*9155*/ uint16(xReadId),
+ /*9156*/ uint16(xArgRM32),
+ /*9157*/ uint16(xArgImm32),
+ /*9158*/ uint16(xMatch),
+ /*9159*/ uint16(xCondDataSize), 9147, 9153, 9163,
+ /*9163*/ uint16(xSetOp), uint16(ADD),
+ /*9165*/ uint16(xReadId),
+ /*9166*/ uint16(xArgRM64),
+ /*9167*/ uint16(xArgImm32),
+ /*9168*/ uint16(xMatch),
+ /*9169*/ uint16(xCondIs64), 9172, 9188,
+ /*9172*/ uint16(xCondDataSize), 9176, 9182, 0,
+ /*9176*/ uint16(xSetOp), uint16(OR),
+ /*9178*/ uint16(xReadIw),
+ /*9179*/ uint16(xArgRM16),
+ /*9180*/ uint16(xArgImm16),
+ /*9181*/ uint16(xMatch),
+ /*9182*/ uint16(xSetOp), uint16(OR),
+ /*9184*/ uint16(xReadId),
+ /*9185*/ uint16(xArgRM32),
+ /*9186*/ uint16(xArgImm32),
+ /*9187*/ uint16(xMatch),
+ /*9188*/ uint16(xCondDataSize), 9176, 9182, 9192,
+ /*9192*/ uint16(xSetOp), uint16(OR),
+ /*9194*/ uint16(xReadId),
+ /*9195*/ uint16(xArgRM64),
+ /*9196*/ uint16(xArgImm32),
+ /*9197*/ uint16(xMatch),
+ /*9198*/ uint16(xCondIs64), 9201, 9217,
+ /*9201*/ uint16(xCondDataSize), 9205, 9211, 0,
+ /*9205*/ uint16(xSetOp), uint16(ADC),
+ /*9207*/ uint16(xReadIw),
+ /*9208*/ uint16(xArgRM16),
+ /*9209*/ uint16(xArgImm16),
+ /*9210*/ uint16(xMatch),
+ /*9211*/ uint16(xSetOp), uint16(ADC),
+ /*9213*/ uint16(xReadId),
+ /*9214*/ uint16(xArgRM32),
+ /*9215*/ uint16(xArgImm32),
+ /*9216*/ uint16(xMatch),
+ /*9217*/ uint16(xCondDataSize), 9205, 9211, 9221,
+ /*9221*/ uint16(xSetOp), uint16(ADC),
+ /*9223*/ uint16(xReadId),
+ /*9224*/ uint16(xArgRM64),
+ /*9225*/ uint16(xArgImm32),
+ /*9226*/ uint16(xMatch),
+ /*9227*/ uint16(xCondIs64), 9230, 9246,
+ /*9230*/ uint16(xCondDataSize), 9234, 9240, 0,
+ /*9234*/ uint16(xSetOp), uint16(SBB),
+ /*9236*/ uint16(xReadIw),
+ /*9237*/ uint16(xArgRM16),
+ /*9238*/ uint16(xArgImm16),
+ /*9239*/ uint16(xMatch),
+ /*9240*/ uint16(xSetOp), uint16(SBB),
+ /*9242*/ uint16(xReadId),
+ /*9243*/ uint16(xArgRM32),
+ /*9244*/ uint16(xArgImm32),
+ /*9245*/ uint16(xMatch),
+ /*9246*/ uint16(xCondDataSize), 9234, 9240, 9250,
+ /*9250*/ uint16(xSetOp), uint16(SBB),
+ /*9252*/ uint16(xReadId),
+ /*9253*/ uint16(xArgRM64),
+ /*9254*/ uint16(xArgImm32),
+ /*9255*/ uint16(xMatch),
+ /*9256*/ uint16(xCondIs64), 9259, 9275,
+ /*9259*/ uint16(xCondDataSize), 9263, 9269, 0,
+ /*9263*/ uint16(xSetOp), uint16(AND),
+ /*9265*/ uint16(xReadIw),
+ /*9266*/ uint16(xArgRM16),
+ /*9267*/ uint16(xArgImm16),
+ /*9268*/ uint16(xMatch),
+ /*9269*/ uint16(xSetOp), uint16(AND),
+ /*9271*/ uint16(xReadId),
+ /*9272*/ uint16(xArgRM32),
+ /*9273*/ uint16(xArgImm32),
+ /*9274*/ uint16(xMatch),
+ /*9275*/ uint16(xCondDataSize), 9263, 9269, 9279,
+ /*9279*/ uint16(xSetOp), uint16(AND),
+ /*9281*/ uint16(xReadId),
+ /*9282*/ uint16(xArgRM64),
+ /*9283*/ uint16(xArgImm32),
+ /*9284*/ uint16(xMatch),
+ /*9285*/ uint16(xCondIs64), 9288, 9304,
+ /*9288*/ uint16(xCondDataSize), 9292, 9298, 0,
+ /*9292*/ uint16(xSetOp), uint16(SUB),
+ /*9294*/ uint16(xReadIw),
+ /*9295*/ uint16(xArgRM16),
+ /*9296*/ uint16(xArgImm16),
+ /*9297*/ uint16(xMatch),
+ /*9298*/ uint16(xSetOp), uint16(SUB),
+ /*9300*/ uint16(xReadId),
+ /*9301*/ uint16(xArgRM32),
+ /*9302*/ uint16(xArgImm32),
+ /*9303*/ uint16(xMatch),
+ /*9304*/ uint16(xCondDataSize), 9292, 9298, 9308,
+ /*9308*/ uint16(xSetOp), uint16(SUB),
+ /*9310*/ uint16(xReadId),
+ /*9311*/ uint16(xArgRM64),
+ /*9312*/ uint16(xArgImm32),
+ /*9313*/ uint16(xMatch),
+ /*9314*/ uint16(xCondIs64), 9317, 9333,
+ /*9317*/ uint16(xCondDataSize), 9321, 9327, 0,
+ /*9321*/ uint16(xSetOp), uint16(XOR),
+ /*9323*/ uint16(xReadIw),
+ /*9324*/ uint16(xArgRM16),
+ /*9325*/ uint16(xArgImm16),
+ /*9326*/ uint16(xMatch),
+ /*9327*/ uint16(xSetOp), uint16(XOR),
+ /*9329*/ uint16(xReadId),
+ /*9330*/ uint16(xArgRM32),
+ /*9331*/ uint16(xArgImm32),
+ /*9332*/ uint16(xMatch),
+ /*9333*/ uint16(xCondDataSize), 9321, 9327, 9337,
+ /*9337*/ uint16(xSetOp), uint16(XOR),
+ /*9339*/ uint16(xReadId),
+ /*9340*/ uint16(xArgRM64),
+ /*9341*/ uint16(xArgImm32),
+ /*9342*/ uint16(xMatch),
+ /*9343*/ uint16(xCondIs64), 9346, 9362,
+ /*9346*/ uint16(xCondDataSize), 9350, 9356, 0,
+ /*9350*/ uint16(xSetOp), uint16(CMP),
+ /*9352*/ uint16(xReadIw),
+ /*9353*/ uint16(xArgRM16),
+ /*9354*/ uint16(xArgImm16),
+ /*9355*/ uint16(xMatch),
+ /*9356*/ uint16(xSetOp), uint16(CMP),
+ /*9358*/ uint16(xReadId),
+ /*9359*/ uint16(xArgRM32),
+ /*9360*/ uint16(xArgImm32),
+ /*9361*/ uint16(xMatch),
+ /*9362*/ uint16(xCondDataSize), 9350, 9356, 9366,
+ /*9366*/ uint16(xSetOp), uint16(CMP),
+ /*9368*/ uint16(xReadId),
+ /*9369*/ uint16(xArgRM64),
+ /*9370*/ uint16(xArgImm32),
+ /*9371*/ uint16(xMatch),
+ /*9372*/ uint16(xCondSlashR),
+ 9381, // 0
+ 9410, // 1
+ 9439, // 2
+ 9468, // 3
+ 9497, // 4
+ 9526, // 5
+ 9555, // 6
+ 9584, // 7
+ /*9381*/ uint16(xCondIs64), 9384, 9400,
+ /*9384*/ uint16(xCondDataSize), 9388, 9394, 0,
+ /*9388*/ uint16(xSetOp), uint16(ADD),
+ /*9390*/ uint16(xReadIb),
+ /*9391*/ uint16(xArgRM16),
+ /*9392*/ uint16(xArgImm8),
+ /*9393*/ uint16(xMatch),
+ /*9394*/ uint16(xSetOp), uint16(ADD),
+ /*9396*/ uint16(xReadIb),
+ /*9397*/ uint16(xArgRM32),
+ /*9398*/ uint16(xArgImm8),
+ /*9399*/ uint16(xMatch),
+ /*9400*/ uint16(xCondDataSize), 9388, 9394, 9404,
+ /*9404*/ uint16(xSetOp), uint16(ADD),
+ /*9406*/ uint16(xReadIb),
+ /*9407*/ uint16(xArgRM64),
+ /*9408*/ uint16(xArgImm8),
+ /*9409*/ uint16(xMatch),
+ /*9410*/ uint16(xCondIs64), 9413, 9429,
+ /*9413*/ uint16(xCondDataSize), 9417, 9423, 0,
+ /*9417*/ uint16(xSetOp), uint16(OR),
+ /*9419*/ uint16(xReadIb),
+ /*9420*/ uint16(xArgRM16),
+ /*9421*/ uint16(xArgImm8),
+ /*9422*/ uint16(xMatch),
+ /*9423*/ uint16(xSetOp), uint16(OR),
+ /*9425*/ uint16(xReadIb),
+ /*9426*/ uint16(xArgRM32),
+ /*9427*/ uint16(xArgImm8),
+ /*9428*/ uint16(xMatch),
+ /*9429*/ uint16(xCondDataSize), 9417, 9423, 9433,
+ /*9433*/ uint16(xSetOp), uint16(OR),
+ /*9435*/ uint16(xReadIb),
+ /*9436*/ uint16(xArgRM64),
+ /*9437*/ uint16(xArgImm8),
+ /*9438*/ uint16(xMatch),
+ /*9439*/ uint16(xCondIs64), 9442, 9458,
+ /*9442*/ uint16(xCondDataSize), 9446, 9452, 0,
+ /*9446*/ uint16(xSetOp), uint16(ADC),
+ /*9448*/ uint16(xReadIb),
+ /*9449*/ uint16(xArgRM16),
+ /*9450*/ uint16(xArgImm8),
+ /*9451*/ uint16(xMatch),
+ /*9452*/ uint16(xSetOp), uint16(ADC),
+ /*9454*/ uint16(xReadIb),
+ /*9455*/ uint16(xArgRM32),
+ /*9456*/ uint16(xArgImm8),
+ /*9457*/ uint16(xMatch),
+ /*9458*/ uint16(xCondDataSize), 9446, 9452, 9462,
+ /*9462*/ uint16(xSetOp), uint16(ADC),
+ /*9464*/ uint16(xReadIb),
+ /*9465*/ uint16(xArgRM64),
+ /*9466*/ uint16(xArgImm8),
+ /*9467*/ uint16(xMatch),
+ /*9468*/ uint16(xCondIs64), 9471, 9487,
+ /*9471*/ uint16(xCondDataSize), 9475, 9481, 0,
+ /*9475*/ uint16(xSetOp), uint16(SBB),
+ /*9477*/ uint16(xReadIb),
+ /*9478*/ uint16(xArgRM16),
+ /*9479*/ uint16(xArgImm8),
+ /*9480*/ uint16(xMatch),
+ /*9481*/ uint16(xSetOp), uint16(SBB),
+ /*9483*/ uint16(xReadIb),
+ /*9484*/ uint16(xArgRM32),
+ /*9485*/ uint16(xArgImm8),
+ /*9486*/ uint16(xMatch),
+ /*9487*/ uint16(xCondDataSize), 9475, 9481, 9491,
+ /*9491*/ uint16(xSetOp), uint16(SBB),
+ /*9493*/ uint16(xReadIb),
+ /*9494*/ uint16(xArgRM64),
+ /*9495*/ uint16(xArgImm8),
+ /*9496*/ uint16(xMatch),
+ /*9497*/ uint16(xCondIs64), 9500, 9516,
+ /*9500*/ uint16(xCondDataSize), 9504, 9510, 0,
+ /*9504*/ uint16(xSetOp), uint16(AND),
+ /*9506*/ uint16(xReadIb),
+ /*9507*/ uint16(xArgRM16),
+ /*9508*/ uint16(xArgImm8),
+ /*9509*/ uint16(xMatch),
+ /*9510*/ uint16(xSetOp), uint16(AND),
+ /*9512*/ uint16(xReadIb),
+ /*9513*/ uint16(xArgRM32),
+ /*9514*/ uint16(xArgImm8),
+ /*9515*/ uint16(xMatch),
+ /*9516*/ uint16(xCondDataSize), 9504, 9510, 9520,
+ /*9520*/ uint16(xSetOp), uint16(AND),
+ /*9522*/ uint16(xReadIb),
+ /*9523*/ uint16(xArgRM64),
+ /*9524*/ uint16(xArgImm8),
+ /*9525*/ uint16(xMatch),
+ /*9526*/ uint16(xCondIs64), 9529, 9545,
+ /*9529*/ uint16(xCondDataSize), 9533, 9539, 0,
+ /*9533*/ uint16(xSetOp), uint16(SUB),
+ /*9535*/ uint16(xReadIb),
+ /*9536*/ uint16(xArgRM16),
+ /*9537*/ uint16(xArgImm8),
+ /*9538*/ uint16(xMatch),
+ /*9539*/ uint16(xSetOp), uint16(SUB),
+ /*9541*/ uint16(xReadIb),
+ /*9542*/ uint16(xArgRM32),
+ /*9543*/ uint16(xArgImm8),
+ /*9544*/ uint16(xMatch),
+ /*9545*/ uint16(xCondDataSize), 9533, 9539, 9549,
+ /*9549*/ uint16(xSetOp), uint16(SUB),
+ /*9551*/ uint16(xReadIb),
+ /*9552*/ uint16(xArgRM64),
+ /*9553*/ uint16(xArgImm8),
+ /*9554*/ uint16(xMatch),
+ /*9555*/ uint16(xCondIs64), 9558, 9574,
+ /*9558*/ uint16(xCondDataSize), 9562, 9568, 0,
+ /*9562*/ uint16(xSetOp), uint16(XOR),
+ /*9564*/ uint16(xReadIb),
+ /*9565*/ uint16(xArgRM16),
+ /*9566*/ uint16(xArgImm8),
+ /*9567*/ uint16(xMatch),
+ /*9568*/ uint16(xSetOp), uint16(XOR),
+ /*9570*/ uint16(xReadIb),
+ /*9571*/ uint16(xArgRM32),
+ /*9572*/ uint16(xArgImm8),
+ /*9573*/ uint16(xMatch),
+ /*9574*/ uint16(xCondDataSize), 9562, 9568, 9578,
+ /*9578*/ uint16(xSetOp), uint16(XOR),
+ /*9580*/ uint16(xReadIb),
+ /*9581*/ uint16(xArgRM64),
+ /*9582*/ uint16(xArgImm8),
+ /*9583*/ uint16(xMatch),
+ /*9584*/ uint16(xCondIs64), 9587, 9603,
+ /*9587*/ uint16(xCondDataSize), 9591, 9597, 0,
+ /*9591*/ uint16(xSetOp), uint16(CMP),
+ /*9593*/ uint16(xReadIb),
+ /*9594*/ uint16(xArgRM16),
+ /*9595*/ uint16(xArgImm8),
+ /*9596*/ uint16(xMatch),
+ /*9597*/ uint16(xSetOp), uint16(CMP),
+ /*9599*/ uint16(xReadIb),
+ /*9600*/ uint16(xArgRM32),
+ /*9601*/ uint16(xArgImm8),
+ /*9602*/ uint16(xMatch),
+ /*9603*/ uint16(xCondDataSize), 9591, 9597, 9607,
+ /*9607*/ uint16(xSetOp), uint16(CMP),
+ /*9609*/ uint16(xReadIb),
+ /*9610*/ uint16(xArgRM64),
+ /*9611*/ uint16(xArgImm8),
+ /*9612*/ uint16(xMatch),
+ /*9613*/ uint16(xSetOp), uint16(TEST),
+ /*9615*/ uint16(xReadSlashR),
+ /*9616*/ uint16(xArgRM8),
+ /*9617*/ uint16(xArgR8),
+ /*9618*/ uint16(xMatch),
+ /*9619*/ uint16(xCondIs64), 9622, 9638,
+ /*9622*/ uint16(xCondDataSize), 9626, 9632, 0,
+ /*9626*/ uint16(xSetOp), uint16(TEST),
+ /*9628*/ uint16(xReadSlashR),
+ /*9629*/ uint16(xArgRM16),
+ /*9630*/ uint16(xArgR16),
+ /*9631*/ uint16(xMatch),
+ /*9632*/ uint16(xSetOp), uint16(TEST),
+ /*9634*/ uint16(xReadSlashR),
+ /*9635*/ uint16(xArgRM32),
+ /*9636*/ uint16(xArgR32),
+ /*9637*/ uint16(xMatch),
+ /*9638*/ uint16(xCondDataSize), 9626, 9632, 9642,
+ /*9642*/ uint16(xSetOp), uint16(TEST),
+ /*9644*/ uint16(xReadSlashR),
+ /*9645*/ uint16(xArgRM64),
+ /*9646*/ uint16(xArgR64),
+ /*9647*/ uint16(xMatch),
+ /*9648*/ uint16(xSetOp), uint16(XCHG),
+ /*9650*/ uint16(xReadSlashR),
+ /*9651*/ uint16(xArgRM8),
+ /*9652*/ uint16(xArgR8),
+ /*9653*/ uint16(xMatch),
+ /*9654*/ uint16(xCondIs64), 9657, 9673,
+ /*9657*/ uint16(xCondDataSize), 9661, 9667, 0,
+ /*9661*/ uint16(xSetOp), uint16(XCHG),
+ /*9663*/ uint16(xReadSlashR),
+ /*9664*/ uint16(xArgRM16),
+ /*9665*/ uint16(xArgR16),
+ /*9666*/ uint16(xMatch),
+ /*9667*/ uint16(xSetOp), uint16(XCHG),
+ /*9669*/ uint16(xReadSlashR),
+ /*9670*/ uint16(xArgRM32),
+ /*9671*/ uint16(xArgR32),
+ /*9672*/ uint16(xMatch),
+ /*9673*/ uint16(xCondDataSize), 9661, 9667, 9677,
+ /*9677*/ uint16(xSetOp), uint16(XCHG),
+ /*9679*/ uint16(xReadSlashR),
+ /*9680*/ uint16(xArgRM64),
+ /*9681*/ uint16(xArgR64),
+ /*9682*/ uint16(xMatch),
+ /*9683*/ uint16(xSetOp), uint16(MOV),
+ /*9685*/ uint16(xReadSlashR),
+ /*9686*/ uint16(xArgRM8),
+ /*9687*/ uint16(xArgR8),
+ /*9688*/ uint16(xMatch),
+ /*9689*/ uint16(xCondDataSize), 9693, 9699, 9705,
+ /*9693*/ uint16(xSetOp), uint16(MOV),
+ /*9695*/ uint16(xReadSlashR),
+ /*9696*/ uint16(xArgRM16),
+ /*9697*/ uint16(xArgR16),
+ /*9698*/ uint16(xMatch),
+ /*9699*/ uint16(xSetOp), uint16(MOV),
+ /*9701*/ uint16(xReadSlashR),
+ /*9702*/ uint16(xArgRM32),
+ /*9703*/ uint16(xArgR32),
+ /*9704*/ uint16(xMatch),
+ /*9705*/ uint16(xSetOp), uint16(MOV),
+ /*9707*/ uint16(xReadSlashR),
+ /*9708*/ uint16(xArgRM64),
+ /*9709*/ uint16(xArgR64),
+ /*9710*/ uint16(xMatch),
+ /*9711*/ uint16(xSetOp), uint16(MOV),
+ /*9713*/ uint16(xReadSlashR),
+ /*9714*/ uint16(xArgR8),
+ /*9715*/ uint16(xArgRM8),
+ /*9716*/ uint16(xMatch),
+ /*9717*/ uint16(xCondDataSize), 9721, 9727, 9733,
+ /*9721*/ uint16(xSetOp), uint16(MOV),
+ /*9723*/ uint16(xReadSlashR),
+ /*9724*/ uint16(xArgR16),
+ /*9725*/ uint16(xArgRM16),
+ /*9726*/ uint16(xMatch),
+ /*9727*/ uint16(xSetOp), uint16(MOV),
+ /*9729*/ uint16(xReadSlashR),
+ /*9730*/ uint16(xArgR32),
+ /*9731*/ uint16(xArgRM32),
+ /*9732*/ uint16(xMatch),
+ /*9733*/ uint16(xSetOp), uint16(MOV),
+ /*9735*/ uint16(xReadSlashR),
+ /*9736*/ uint16(xArgR64),
+ /*9737*/ uint16(xArgRM64),
+ /*9738*/ uint16(xMatch),
+ /*9739*/ uint16(xCondIs64), 9742, 9758,
+ /*9742*/ uint16(xCondDataSize), 9746, 9752, 0,
+ /*9746*/ uint16(xSetOp), uint16(MOV),
+ /*9748*/ uint16(xReadSlashR),
+ /*9749*/ uint16(xArgRM16),
+ /*9750*/ uint16(xArgSreg),
+ /*9751*/ uint16(xMatch),
+ /*9752*/ uint16(xSetOp), uint16(MOV),
+ /*9754*/ uint16(xReadSlashR),
+ /*9755*/ uint16(xArgR32M16),
+ /*9756*/ uint16(xArgSreg),
+ /*9757*/ uint16(xMatch),
+ /*9758*/ uint16(xCondDataSize), 9746, 9752, 9762,
+ /*9762*/ uint16(xSetOp), uint16(MOV),
+ /*9764*/ uint16(xReadSlashR),
+ /*9765*/ uint16(xArgR64M16),
+ /*9766*/ uint16(xArgSreg),
+ /*9767*/ uint16(xMatch),
+ /*9768*/ uint16(xCondIs64), 9771, 9787,
+ /*9771*/ uint16(xCondDataSize), 9775, 9781, 0,
+ /*9775*/ uint16(xSetOp), uint16(LEA),
+ /*9777*/ uint16(xReadSlashR),
+ /*9778*/ uint16(xArgR16),
+ /*9779*/ uint16(xArgM),
+ /*9780*/ uint16(xMatch),
+ /*9781*/ uint16(xSetOp), uint16(LEA),
+ /*9783*/ uint16(xReadSlashR),
+ /*9784*/ uint16(xArgR32),
+ /*9785*/ uint16(xArgM),
+ /*9786*/ uint16(xMatch),
+ /*9787*/ uint16(xCondDataSize), 9775, 9781, 9791,
+ /*9791*/ uint16(xSetOp), uint16(LEA),
+ /*9793*/ uint16(xReadSlashR),
+ /*9794*/ uint16(xArgR64),
+ /*9795*/ uint16(xArgM),
+ /*9796*/ uint16(xMatch),
+ /*9797*/ uint16(xCondIs64), 9800, 9816,
+ /*9800*/ uint16(xCondDataSize), 9804, 9810, 0,
+ /*9804*/ uint16(xSetOp), uint16(MOV),
+ /*9806*/ uint16(xReadSlashR),
+ /*9807*/ uint16(xArgSreg),
+ /*9808*/ uint16(xArgRM16),
+ /*9809*/ uint16(xMatch),
+ /*9810*/ uint16(xSetOp), uint16(MOV),
+ /*9812*/ uint16(xReadSlashR),
+ /*9813*/ uint16(xArgSreg),
+ /*9814*/ uint16(xArgR32M16),
+ /*9815*/ uint16(xMatch),
+ /*9816*/ uint16(xCondDataSize), 9804, 9810, 9820,
+ /*9820*/ uint16(xSetOp), uint16(MOV),
+ /*9822*/ uint16(xReadSlashR),
+ /*9823*/ uint16(xArgSreg),
+ /*9824*/ uint16(xArgR64M16),
+ /*9825*/ uint16(xMatch),
+ /*9826*/ uint16(xCondSlashR),
+ 9835, // 0
+ 0, // 1
+ 0, // 2
+ 0, // 3
+ 0, // 4
+ 0, // 5
+ 0, // 6
+ 0, // 7
+ /*9835*/ uint16(xCondIs64), 9838, 9850,
+ /*9838*/ uint16(xCondDataSize), 9842, 9846, 0,
+ /*9842*/ uint16(xSetOp), uint16(POP),
+ /*9844*/ uint16(xArgRM16),
+ /*9845*/ uint16(xMatch),
+ /*9846*/ uint16(xSetOp), uint16(POP),
+ /*9848*/ uint16(xArgRM32),
+ /*9849*/ uint16(xMatch),
+ /*9850*/ uint16(xCondDataSize), 9842, 9854, 9858,
+ /*9854*/ uint16(xSetOp), uint16(POP),
+ /*9856*/ uint16(xArgRM64),
+ /*9857*/ uint16(xMatch),
+ /*9858*/ uint16(xSetOp), uint16(POP),
+ /*9860*/ uint16(xArgRM64),
+ /*9861*/ uint16(xMatch),
+ /*9862*/ uint16(xCondIs64), 9865, 9879,
+ /*9865*/ uint16(xCondDataSize), 9869, 9874, 0,
+ /*9869*/ uint16(xSetOp), uint16(XCHG),
+ /*9871*/ uint16(xArgR16op),
+ /*9872*/ uint16(xArgAX),
+ /*9873*/ uint16(xMatch),
+ /*9874*/ uint16(xSetOp), uint16(XCHG),
+ /*9876*/ uint16(xArgR32op),
+ /*9877*/ uint16(xArgEAX),
+ /*9878*/ uint16(xMatch),
+ /*9879*/ uint16(xCondDataSize), 9869, 9874, 9883,
+ /*9883*/ uint16(xSetOp), uint16(XCHG),
+ /*9885*/ uint16(xArgR64op),
+ /*9886*/ uint16(xArgRAX),
+ /*9887*/ uint16(xMatch),
+ /*9888*/ uint16(xCondIs64), 9891, 9901,
+ /*9891*/ uint16(xCondDataSize), 9895, 9898, 0,
+ /*9895*/ uint16(xSetOp), uint16(CBW),
+ /*9897*/ uint16(xMatch),
+ /*9898*/ uint16(xSetOp), uint16(CWDE),
+ /*9900*/ uint16(xMatch),
+ /*9901*/ uint16(xCondDataSize), 9895, 9898, 9905,
+ /*9905*/ uint16(xSetOp), uint16(CDQE),
+ /*9907*/ uint16(xMatch),
+ /*9908*/ uint16(xCondIs64), 9911, 9921,
+ /*9911*/ uint16(xCondDataSize), 9915, 9918, 0,
+ /*9915*/ uint16(xSetOp), uint16(CWD),
+ /*9917*/ uint16(xMatch),
+ /*9918*/ uint16(xSetOp), uint16(CDQ),
+ /*9920*/ uint16(xMatch),
+ /*9921*/ uint16(xCondDataSize), 9915, 9918, 9925,
+ /*9925*/ uint16(xSetOp), uint16(CQO),
+ /*9927*/ uint16(xMatch),
+ /*9928*/ uint16(xCondIs64), 9931, 0,
+ /*9931*/ uint16(xCondDataSize), 9935, 9940, 0,
+ /*9935*/ uint16(xSetOp), uint16(LCALL),
+ /*9937*/ uint16(xReadCd),
+ /*9938*/ uint16(xArgPtr16colon16),
+ /*9939*/ uint16(xMatch),
+ /*9940*/ uint16(xSetOp), uint16(LCALL),
+ /*9942*/ uint16(xReadCp),
+ /*9943*/ uint16(xArgPtr16colon32),
+ /*9944*/ uint16(xMatch),
+ /*9945*/ uint16(xSetOp), uint16(FWAIT),
+ /*9947*/ uint16(xMatch),
+ /*9948*/ uint16(xCondIs64), 9951, 9961,
+ /*9951*/ uint16(xCondDataSize), 9955, 9958, 0,
+ /*9955*/ uint16(xSetOp), uint16(PUSHF),
+ /*9957*/ uint16(xMatch),
+ /*9958*/ uint16(xSetOp), uint16(PUSHFD),
+ /*9960*/ uint16(xMatch),
+ /*9961*/ uint16(xCondDataSize), 9955, 9965, 9968,
+ /*9965*/ uint16(xSetOp), uint16(PUSHFQ),
+ /*9967*/ uint16(xMatch),
+ /*9968*/ uint16(xSetOp), uint16(PUSHFQ),
+ /*9970*/ uint16(xMatch),
+ /*9971*/ uint16(xCondIs64), 9974, 9984,
+ /*9974*/ uint16(xCondDataSize), 9978, 9981, 0,
+ /*9978*/ uint16(xSetOp), uint16(POPF),
+ /*9980*/ uint16(xMatch),
+ /*9981*/ uint16(xSetOp), uint16(POPFD),
+ /*9983*/ uint16(xMatch),
+ /*9984*/ uint16(xCondDataSize), 9978, 9988, 9991,
+ /*9988*/ uint16(xSetOp), uint16(POPFQ),
+ /*9990*/ uint16(xMatch),
+ /*9991*/ uint16(xSetOp), uint16(POPFQ),
+ /*9993*/ uint16(xMatch),
+ /*9994*/ uint16(xSetOp), uint16(SAHF),
+ /*9996*/ uint16(xMatch),
+ /*9997*/ uint16(xSetOp), uint16(LAHF),
+ /*9999*/ uint16(xMatch),
+ /*10000*/ uint16(xCondIs64), 10003, 10009,
+ /*10003*/ uint16(xSetOp), uint16(MOV),
+ /*10005*/ uint16(xReadCm),
+ /*10006*/ uint16(xArgAL),
+ /*10007*/ uint16(xArgMoffs8),
+ /*10008*/ uint16(xMatch),
+ /*10009*/ uint16(xCondDataSize), 10003, 10003, 10013,
+ /*10013*/ uint16(xSetOp), uint16(MOV),
+ /*10015*/ uint16(xReadCm),
+ /*10016*/ uint16(xArgAL),
+ /*10017*/ uint16(xArgMoffs8),
+ /*10018*/ uint16(xMatch),
+ /*10019*/ uint16(xCondDataSize), 10023, 10029, 10035,
+ /*10023*/ uint16(xSetOp), uint16(MOV),
+ /*10025*/ uint16(xReadCm),
+ /*10026*/ uint16(xArgAX),
+ /*10027*/ uint16(xArgMoffs16),
+ /*10028*/ uint16(xMatch),
+ /*10029*/ uint16(xSetOp), uint16(MOV),
+ /*10031*/ uint16(xReadCm),
+ /*10032*/ uint16(xArgEAX),
+ /*10033*/ uint16(xArgMoffs32),
+ /*10034*/ uint16(xMatch),
+ /*10035*/ uint16(xSetOp), uint16(MOV),
+ /*10037*/ uint16(xReadCm),
+ /*10038*/ uint16(xArgRAX),
+ /*10039*/ uint16(xArgMoffs64),
+ /*10040*/ uint16(xMatch),
+ /*10041*/ uint16(xCondIs64), 10044, 10050,
+ /*10044*/ uint16(xSetOp), uint16(MOV),
+ /*10046*/ uint16(xReadCm),
+ /*10047*/ uint16(xArgMoffs8),
+ /*10048*/ uint16(xArgAL),
+ /*10049*/ uint16(xMatch),
+ /*10050*/ uint16(xCondDataSize), 10044, 10044, 10054,
+ /*10054*/ uint16(xSetOp), uint16(MOV),
+ /*10056*/ uint16(xReadCm),
+ /*10057*/ uint16(xArgMoffs8),
+ /*10058*/ uint16(xArgAL),
+ /*10059*/ uint16(xMatch),
+ /*10060*/ uint16(xCondDataSize), 10064, 10070, 10076,
+ /*10064*/ uint16(xSetOp), uint16(MOV),
+ /*10066*/ uint16(xReadCm),
+ /*10067*/ uint16(xArgMoffs16),
+ /*10068*/ uint16(xArgAX),
+ /*10069*/ uint16(xMatch),
+ /*10070*/ uint16(xSetOp), uint16(MOV),
+ /*10072*/ uint16(xReadCm),
+ /*10073*/ uint16(xArgMoffs32),
+ /*10074*/ uint16(xArgEAX),
+ /*10075*/ uint16(xMatch),
+ /*10076*/ uint16(xSetOp), uint16(MOV),
+ /*10078*/ uint16(xReadCm),
+ /*10079*/ uint16(xArgMoffs64),
+ /*10080*/ uint16(xArgRAX),
+ /*10081*/ uint16(xMatch),
+ /*10082*/ uint16(xSetOp), uint16(MOVSB),
+ /*10084*/ uint16(xMatch),
+ /*10085*/ uint16(xCondIs64), 10088, 10098,
+ /*10088*/ uint16(xCondDataSize), 10092, 10095, 0,
+ /*10092*/ uint16(xSetOp), uint16(MOVSW),
+ /*10094*/ uint16(xMatch),
+ /*10095*/ uint16(xSetOp), uint16(MOVSD),
+ /*10097*/ uint16(xMatch),
+ /*10098*/ uint16(xCondDataSize), 10092, 10095, 10102,
+ /*10102*/ uint16(xSetOp), uint16(MOVSQ),
+ /*10104*/ uint16(xMatch),
+ /*10105*/ uint16(xSetOp), uint16(CMPSB),
+ /*10107*/ uint16(xMatch),
+ /*10108*/ uint16(xCondIs64), 10111, 10121,
+ /*10111*/ uint16(xCondDataSize), 10115, 10118, 0,
+ /*10115*/ uint16(xSetOp), uint16(CMPSW),
+ /*10117*/ uint16(xMatch),
+ /*10118*/ uint16(xSetOp), uint16(CMPSD),
+ /*10120*/ uint16(xMatch),
+ /*10121*/ uint16(xCondDataSize), 10115, 10118, 10125,
+ /*10125*/ uint16(xSetOp), uint16(CMPSQ),
+ /*10127*/ uint16(xMatch),
+ /*10128*/ uint16(xSetOp), uint16(TEST),
+ /*10130*/ uint16(xReadIb),
+ /*10131*/ uint16(xArgAL),
+ /*10132*/ uint16(xArgImm8u),
+ /*10133*/ uint16(xMatch),
+ /*10134*/ uint16(xCondIs64), 10137, 10153,
+ /*10137*/ uint16(xCondDataSize), 10141, 10147, 0,
+ /*10141*/ uint16(xSetOp), uint16(TEST),
+ /*10143*/ uint16(xReadIw),
+ /*10144*/ uint16(xArgAX),
+ /*10145*/ uint16(xArgImm16),
+ /*10146*/ uint16(xMatch),
+ /*10147*/ uint16(xSetOp), uint16(TEST),
+ /*10149*/ uint16(xReadId),
+ /*10150*/ uint16(xArgEAX),
+ /*10151*/ uint16(xArgImm32),
+ /*10152*/ uint16(xMatch),
+ /*10153*/ uint16(xCondDataSize), 10141, 10147, 10157,
+ /*10157*/ uint16(xSetOp), uint16(TEST),
+ /*10159*/ uint16(xReadId),
+ /*10160*/ uint16(xArgRAX),
+ /*10161*/ uint16(xArgImm32),
+ /*10162*/ uint16(xMatch),
+ /*10163*/ uint16(xSetOp), uint16(STOSB),
+ /*10165*/ uint16(xMatch),
+ /*10166*/ uint16(xCondIs64), 10169, 10179,
+ /*10169*/ uint16(xCondDataSize), 10173, 10176, 0,
+ /*10173*/ uint16(xSetOp), uint16(STOSW),
+ /*10175*/ uint16(xMatch),
+ /*10176*/ uint16(xSetOp), uint16(STOSD),
+ /*10178*/ uint16(xMatch),
+ /*10179*/ uint16(xCondDataSize), 10173, 10176, 10183,
+ /*10183*/ uint16(xSetOp), uint16(STOSQ),
+ /*10185*/ uint16(xMatch),
+ /*10186*/ uint16(xSetOp), uint16(LODSB),
+ /*10188*/ uint16(xMatch),
+ /*10189*/ uint16(xCondIs64), 10192, 10202,
+ /*10192*/ uint16(xCondDataSize), 10196, 10199, 0,
+ /*10196*/ uint16(xSetOp), uint16(LODSW),
+ /*10198*/ uint16(xMatch),
+ /*10199*/ uint16(xSetOp), uint16(LODSD),
+ /*10201*/ uint16(xMatch),
+ /*10202*/ uint16(xCondDataSize), 10196, 10199, 10206,
+ /*10206*/ uint16(xSetOp), uint16(LODSQ),
+ /*10208*/ uint16(xMatch),
+ /*10209*/ uint16(xSetOp), uint16(SCASB),
+ /*10211*/ uint16(xMatch),
+ /*10212*/ uint16(xCondIs64), 10215, 10225,
+ /*10215*/ uint16(xCondDataSize), 10219, 10222, 0,
+ /*10219*/ uint16(xSetOp), uint16(SCASW),
+ /*10221*/ uint16(xMatch),
+ /*10222*/ uint16(xSetOp), uint16(SCASD),
+ /*10224*/ uint16(xMatch),
+ /*10225*/ uint16(xCondDataSize), 10219, 10222, 10229,
+ /*10229*/ uint16(xSetOp), uint16(SCASQ),
+ /*10231*/ uint16(xMatch),
+ /*10232*/ uint16(xSetOp), uint16(MOV),
+ /*10234*/ uint16(xReadIb),
+ /*10235*/ uint16(xArgR8op),
+ /*10236*/ uint16(xArgImm8u),
+ /*10237*/ uint16(xMatch),
+ /*10238*/ uint16(xCondIs64), 10241, 10257,
+ /*10241*/ uint16(xCondDataSize), 10245, 10251, 0,
+ /*10245*/ uint16(xSetOp), uint16(MOV),
+ /*10247*/ uint16(xReadIw),
+ /*10248*/ uint16(xArgR16op),
+ /*10249*/ uint16(xArgImm16),
+ /*10250*/ uint16(xMatch),
+ /*10251*/ uint16(xSetOp), uint16(MOV),
+ /*10253*/ uint16(xReadId),
+ /*10254*/ uint16(xArgR32op),
+ /*10255*/ uint16(xArgImm32),
+ /*10256*/ uint16(xMatch),
+ /*10257*/ uint16(xCondDataSize), 10245, 10251, 10261,
+ /*10261*/ uint16(xSetOp), uint16(MOV),
+ /*10263*/ uint16(xReadIo),
+ /*10264*/ uint16(xArgR64op),
+ /*10265*/ uint16(xArgImm64),
+ /*10266*/ uint16(xMatch),
+ /*10267*/ uint16(xCondSlashR),
+ 10276, // 0
+ 10282, // 1
+ 10288, // 2
+ 10294, // 3
+ 10300, // 4
+ 10306, // 5
+ 0, // 6
+ 10312, // 7
+ /*10276*/ uint16(xSetOp), uint16(ROL),
+ /*10278*/ uint16(xReadIb),
+ /*10279*/ uint16(xArgRM8),
+ /*10280*/ uint16(xArgImm8u),
+ /*10281*/ uint16(xMatch),
+ /*10282*/ uint16(xSetOp), uint16(ROR),
+ /*10284*/ uint16(xReadIb),
+ /*10285*/ uint16(xArgRM8),
+ /*10286*/ uint16(xArgImm8u),
+ /*10287*/ uint16(xMatch),
+ /*10288*/ uint16(xSetOp), uint16(RCL),
+ /*10290*/ uint16(xReadIb),
+ /*10291*/ uint16(xArgRM8),
+ /*10292*/ uint16(xArgImm8u),
+ /*10293*/ uint16(xMatch),
+ /*10294*/ uint16(xSetOp), uint16(RCR),
+ /*10296*/ uint16(xReadIb),
+ /*10297*/ uint16(xArgRM8),
+ /*10298*/ uint16(xArgImm8u),
+ /*10299*/ uint16(xMatch),
+ /*10300*/ uint16(xSetOp), uint16(SHL),
+ /*10302*/ uint16(xReadIb),
+ /*10303*/ uint16(xArgRM8),
+ /*10304*/ uint16(xArgImm8u),
+ /*10305*/ uint16(xMatch),
+ /*10306*/ uint16(xSetOp), uint16(SHR),
+ /*10308*/ uint16(xReadIb),
+ /*10309*/ uint16(xArgRM8),
+ /*10310*/ uint16(xArgImm8u),
+ /*10311*/ uint16(xMatch),
+ /*10312*/ uint16(xSetOp), uint16(SAR),
+ /*10314*/ uint16(xReadIb),
+ /*10315*/ uint16(xArgRM8),
+ /*10316*/ uint16(xArgImm8u),
+ /*10317*/ uint16(xMatch),
+ /*10318*/ uint16(xCondSlashR),
+ 10327, // 0
+ 10349, // 1
+ 10371, // 2
+ 10400, // 3
+ 10429, // 4
+ 10458, // 5
+ 0, // 6
+ 10487, // 7
+ /*10327*/ uint16(xCondDataSize), 10331, 10337, 10343,
+ /*10331*/ uint16(xSetOp), uint16(ROL),
+ /*10333*/ uint16(xReadIb),
+ /*10334*/ uint16(xArgRM16),
+ /*10335*/ uint16(xArgImm8u),
+ /*10336*/ uint16(xMatch),
+ /*10337*/ uint16(xSetOp), uint16(ROL),
+ /*10339*/ uint16(xReadIb),
+ /*10340*/ uint16(xArgRM32),
+ /*10341*/ uint16(xArgImm8u),
+ /*10342*/ uint16(xMatch),
+ /*10343*/ uint16(xSetOp), uint16(ROL),
+ /*10345*/ uint16(xReadIb),
+ /*10346*/ uint16(xArgRM64),
+ /*10347*/ uint16(xArgImm8u),
+ /*10348*/ uint16(xMatch),
+ /*10349*/ uint16(xCondDataSize), 10353, 10359, 10365,
+ /*10353*/ uint16(xSetOp), uint16(ROR),
+ /*10355*/ uint16(xReadIb),
+ /*10356*/ uint16(xArgRM16),
+ /*10357*/ uint16(xArgImm8u),
+ /*10358*/ uint16(xMatch),
+ /*10359*/ uint16(xSetOp), uint16(ROR),
+ /*10361*/ uint16(xReadIb),
+ /*10362*/ uint16(xArgRM32),
+ /*10363*/ uint16(xArgImm8u),
+ /*10364*/ uint16(xMatch),
+ /*10365*/ uint16(xSetOp), uint16(ROR),
+ /*10367*/ uint16(xReadIb),
+ /*10368*/ uint16(xArgRM64),
+ /*10369*/ uint16(xArgImm8u),
+ /*10370*/ uint16(xMatch),
+ /*10371*/ uint16(xCondIs64), 10374, 10390,
+ /*10374*/ uint16(xCondDataSize), 10378, 10384, 0,
+ /*10378*/ uint16(xSetOp), uint16(RCL),
+ /*10380*/ uint16(xReadIb),
+ /*10381*/ uint16(xArgRM16),
+ /*10382*/ uint16(xArgImm8u),
+ /*10383*/ uint16(xMatch),
+ /*10384*/ uint16(xSetOp), uint16(RCL),
+ /*10386*/ uint16(xReadIb),
+ /*10387*/ uint16(xArgRM32),
+ /*10388*/ uint16(xArgImm8u),
+ /*10389*/ uint16(xMatch),
+ /*10390*/ uint16(xCondDataSize), 10378, 10384, 10394,
+ /*10394*/ uint16(xSetOp), uint16(RCL),
+ /*10396*/ uint16(xReadIb),
+ /*10397*/ uint16(xArgRM64),
+ /*10398*/ uint16(xArgImm8u),
+ /*10399*/ uint16(xMatch),
+ /*10400*/ uint16(xCondIs64), 10403, 10419,
+ /*10403*/ uint16(xCondDataSize), 10407, 10413, 0,
+ /*10407*/ uint16(xSetOp), uint16(RCR),
+ /*10409*/ uint16(xReadIb),
+ /*10410*/ uint16(xArgRM16),
+ /*10411*/ uint16(xArgImm8u),
+ /*10412*/ uint16(xMatch),
+ /*10413*/ uint16(xSetOp), uint16(RCR),
+ /*10415*/ uint16(xReadIb),
+ /*10416*/ uint16(xArgRM32),
+ /*10417*/ uint16(xArgImm8u),
+ /*10418*/ uint16(xMatch),
+ /*10419*/ uint16(xCondDataSize), 10407, 10413, 10423,
+ /*10423*/ uint16(xSetOp), uint16(RCR),
+ /*10425*/ uint16(xReadIb),
+ /*10426*/ uint16(xArgRM64),
+ /*10427*/ uint16(xArgImm8u),
+ /*10428*/ uint16(xMatch),
+ /*10429*/ uint16(xCondIs64), 10432, 10448,
+ /*10432*/ uint16(xCondDataSize), 10436, 10442, 0,
+ /*10436*/ uint16(xSetOp), uint16(SHL),
+ /*10438*/ uint16(xReadIb),
+ /*10439*/ uint16(xArgRM16),
+ /*10440*/ uint16(xArgImm8u),
+ /*10441*/ uint16(xMatch),
+ /*10442*/ uint16(xSetOp), uint16(SHL),
+ /*10444*/ uint16(xReadIb),
+ /*10445*/ uint16(xArgRM32),
+ /*10446*/ uint16(xArgImm8u),
+ /*10447*/ uint16(xMatch),
+ /*10448*/ uint16(xCondDataSize), 10436, 10442, 10452,
+ /*10452*/ uint16(xSetOp), uint16(SHL),
+ /*10454*/ uint16(xReadIb),
+ /*10455*/ uint16(xArgRM64),
+ /*10456*/ uint16(xArgImm8u),
+ /*10457*/ uint16(xMatch),
+ /*10458*/ uint16(xCondIs64), 10461, 10477,
+ /*10461*/ uint16(xCondDataSize), 10465, 10471, 0,
+ /*10465*/ uint16(xSetOp), uint16(SHR),
+ /*10467*/ uint16(xReadIb),
+ /*10468*/ uint16(xArgRM16),
+ /*10469*/ uint16(xArgImm8u),
+ /*10470*/ uint16(xMatch),
+ /*10471*/ uint16(xSetOp), uint16(SHR),
+ /*10473*/ uint16(xReadIb),
+ /*10474*/ uint16(xArgRM32),
+ /*10475*/ uint16(xArgImm8u),
+ /*10476*/ uint16(xMatch),
+ /*10477*/ uint16(xCondDataSize), 10465, 10471, 10481,
+ /*10481*/ uint16(xSetOp), uint16(SHR),
+ /*10483*/ uint16(xReadIb),
+ /*10484*/ uint16(xArgRM64),
+ /*10485*/ uint16(xArgImm8u),
+ /*10486*/ uint16(xMatch),
+ /*10487*/ uint16(xCondIs64), 10490, 10506,
+ /*10490*/ uint16(xCondDataSize), 10494, 10500, 0,
+ /*10494*/ uint16(xSetOp), uint16(SAR),
+ /*10496*/ uint16(xReadIb),
+ /*10497*/ uint16(xArgRM16),
+ /*10498*/ uint16(xArgImm8u),
+ /*10499*/ uint16(xMatch),
+ /*10500*/ uint16(xSetOp), uint16(SAR),
+ /*10502*/ uint16(xReadIb),
+ /*10503*/ uint16(xArgRM32),
+ /*10504*/ uint16(xArgImm8u),
+ /*10505*/ uint16(xMatch),
+ /*10506*/ uint16(xCondDataSize), 10494, 10500, 10510,
+ /*10510*/ uint16(xSetOp), uint16(SAR),
+ /*10512*/ uint16(xReadIb),
+ /*10513*/ uint16(xArgRM64),
+ /*10514*/ uint16(xArgImm8u),
+ /*10515*/ uint16(xMatch),
+ /*10516*/ uint16(xSetOp), uint16(RET),
+ /*10518*/ uint16(xReadIw),
+ /*10519*/ uint16(xArgImm16u),
+ /*10520*/ uint16(xMatch),
+ /*10521*/ uint16(xSetOp), uint16(RET),
+ /*10523*/ uint16(xMatch),
+ /*10524*/ uint16(xCondIs64), 10527, 0,
+ /*10527*/ uint16(xCondDataSize), 10531, 10537, 0,
+ /*10531*/ uint16(xSetOp), uint16(LES),
+ /*10533*/ uint16(xReadSlashR),
+ /*10534*/ uint16(xArgR16),
+ /*10535*/ uint16(xArgM16colon16),
+ /*10536*/ uint16(xMatch),
+ /*10537*/ uint16(xSetOp), uint16(LES),
+ /*10539*/ uint16(xReadSlashR),
+ /*10540*/ uint16(xArgR32),
+ /*10541*/ uint16(xArgM16colon32),
+ /*10542*/ uint16(xMatch),
+ /*10543*/ uint16(xCondIs64), 10546, 0,
+ /*10546*/ uint16(xCondDataSize), 10550, 10556, 0,
+ /*10550*/ uint16(xSetOp), uint16(LDS),
+ /*10552*/ uint16(xReadSlashR),
+ /*10553*/ uint16(xArgR16),
+ /*10554*/ uint16(xArgM16colon16),
+ /*10555*/ uint16(xMatch),
+ /*10556*/ uint16(xSetOp), uint16(LDS),
+ /*10558*/ uint16(xReadSlashR),
+ /*10559*/ uint16(xArgR32),
+ /*10560*/ uint16(xArgM16colon32),
+ /*10561*/ uint16(xMatch),
+ /*10562*/ uint16(xCondByte), 1,
+ 0xF8, 10581,
+ /*10566*/ uint16(xCondSlashR),
+ 10575, // 0
+ 0, // 1
+ 0, // 2
+ 0, // 3
+ 0, // 4
+ 0, // 5
+ 0, // 6
+ 0, // 7
+ /*10575*/ uint16(xSetOp), uint16(MOV),
+ /*10577*/ uint16(xReadIb),
+ /*10578*/ uint16(xArgRM8),
+ /*10579*/ uint16(xArgImm8u),
+ /*10580*/ uint16(xMatch),
+ /*10581*/ uint16(xSetOp), uint16(XABORT),
+ /*10583*/ uint16(xReadIb),
+ /*10584*/ uint16(xArgImm8u),
+ /*10585*/ uint16(xMatch),
+ /*10586*/ uint16(xCondByte), 1,
+ 0xF8, 10628,
+ /*10590*/ uint16(xCondSlashR),
+ 10599, // 0
+ 0, // 1
+ 0, // 2
+ 0, // 3
+ 0, // 4
+ 0, // 5
+ 0, // 6
+ 0, // 7
+ /*10599*/ uint16(xCondIs64), 10602, 10618,
+ /*10602*/ uint16(xCondDataSize), 10606, 10612, 0,
+ /*10606*/ uint16(xSetOp), uint16(MOV),
+ /*10608*/ uint16(xReadIw),
+ /*10609*/ uint16(xArgRM16),
+ /*10610*/ uint16(xArgImm16),
+ /*10611*/ uint16(xMatch),
+ /*10612*/ uint16(xSetOp), uint16(MOV),
+ /*10614*/ uint16(xReadId),
+ /*10615*/ uint16(xArgRM32),
+ /*10616*/ uint16(xArgImm32),
+ /*10617*/ uint16(xMatch),
+ /*10618*/ uint16(xCondDataSize), 10606, 10612, 10622,
+ /*10622*/ uint16(xSetOp), uint16(MOV),
+ /*10624*/ uint16(xReadId),
+ /*10625*/ uint16(xArgRM64),
+ /*10626*/ uint16(xArgImm32),
+ /*10627*/ uint16(xMatch),
+ /*10628*/ uint16(xCondDataSize), 10632, 10637, 10642,
+ /*10632*/ uint16(xSetOp), uint16(XBEGIN),
+ /*10634*/ uint16(xReadCw),
+ /*10635*/ uint16(xArgRel16),
+ /*10636*/ uint16(xMatch),
+ /*10637*/ uint16(xSetOp), uint16(XBEGIN),
+ /*10639*/ uint16(xReadCd),
+ /*10640*/ uint16(xArgRel32),
+ /*10641*/ uint16(xMatch),
+ /*10642*/ uint16(xSetOp), uint16(XBEGIN),
+ /*10644*/ uint16(xReadCd),
+ /*10645*/ uint16(xArgRel32),
+ /*10646*/ uint16(xMatch),
+ /*10647*/ uint16(xSetOp), uint16(ENTER),
+ /*10649*/ uint16(xReadIw),
+ /*10650*/ uint16(xReadIb),
+ /*10651*/ uint16(xArgImm16u),
+ /*10652*/ uint16(xArgImm8u),
+ /*10653*/ uint16(xMatch),
+ /*10654*/ uint16(xCondIs64), 10657, 10667,
+ /*10657*/ uint16(xCondDataSize), 10661, 10664, 0,
+ /*10661*/ uint16(xSetOp), uint16(LEAVE),
+ /*10663*/ uint16(xMatch),
+ /*10664*/ uint16(xSetOp), uint16(LEAVE),
+ /*10666*/ uint16(xMatch),
+ /*10667*/ uint16(xCondDataSize), 10661, 10671, 10674,
+ /*10671*/ uint16(xSetOp), uint16(LEAVE),
+ /*10673*/ uint16(xMatch),
+ /*10674*/ uint16(xSetOp), uint16(LEAVE),
+ /*10676*/ uint16(xMatch),
+ /*10677*/ uint16(xSetOp), uint16(LRET),
+ /*10679*/ uint16(xReadIw),
+ /*10680*/ uint16(xArgImm16u),
+ /*10681*/ uint16(xMatch),
+ /*10682*/ uint16(xSetOp), uint16(LRET),
+ /*10684*/ uint16(xMatch),
+ /*10685*/ uint16(xSetOp), uint16(INT),
+ /*10687*/ uint16(xArg3),
+ /*10688*/ uint16(xMatch),
+ /*10689*/ uint16(xSetOp), uint16(INT),
+ /*10691*/ uint16(xReadIb),
+ /*10692*/ uint16(xArgImm8u),
+ /*10693*/ uint16(xMatch),
+ /*10694*/ uint16(xCondIs64), 10697, 0,
+ /*10697*/ uint16(xSetOp), uint16(INTO),
+ /*10699*/ uint16(xMatch),
+ /*10700*/ uint16(xCondIs64), 10703, 10713,
+ /*10703*/ uint16(xCondDataSize), 10707, 10710, 0,
+ /*10707*/ uint16(xSetOp), uint16(IRET),
+ /*10709*/ uint16(xMatch),
+ /*10710*/ uint16(xSetOp), uint16(IRETD),
+ /*10712*/ uint16(xMatch),
+ /*10713*/ uint16(xCondDataSize), 10707, 10710, 10717,
+ /*10717*/ uint16(xSetOp), uint16(IRETQ),
+ /*10719*/ uint16(xMatch),
+ /*10720*/ uint16(xCondSlashR),
+ 10729, // 0
+ 10734, // 1
+ 10739, // 2
+ 10744, // 3
+ 10749, // 4
+ 10754, // 5
+ 0, // 6
+ 10759, // 7
+ /*10729*/ uint16(xSetOp), uint16(ROL),
+ /*10731*/ uint16(xArgRM8),
+ /*10732*/ uint16(xArg1),
+ /*10733*/ uint16(xMatch),
+ /*10734*/ uint16(xSetOp), uint16(ROR),
+ /*10736*/ uint16(xArgRM8),
+ /*10737*/ uint16(xArg1),
+ /*10738*/ uint16(xMatch),
+ /*10739*/ uint16(xSetOp), uint16(RCL),
+ /*10741*/ uint16(xArgRM8),
+ /*10742*/ uint16(xArg1),
+ /*10743*/ uint16(xMatch),
+ /*10744*/ uint16(xSetOp), uint16(RCR),
+ /*10746*/ uint16(xArgRM8),
+ /*10747*/ uint16(xArg1),
+ /*10748*/ uint16(xMatch),
+ /*10749*/ uint16(xSetOp), uint16(SHL),
+ /*10751*/ uint16(xArgRM8),
+ /*10752*/ uint16(xArg1),
+ /*10753*/ uint16(xMatch),
+ /*10754*/ uint16(xSetOp), uint16(SHR),
+ /*10756*/ uint16(xArgRM8),
+ /*10757*/ uint16(xArg1),
+ /*10758*/ uint16(xMatch),
+ /*10759*/ uint16(xSetOp), uint16(SAR),
+ /*10761*/ uint16(xArgRM8),
+ /*10762*/ uint16(xArg1),
+ /*10763*/ uint16(xMatch),
+ /*10764*/ uint16(xCondSlashR),
+ 10773, // 0
+ 10799, // 1
+ 10825, // 2
+ 10851, // 3
+ 10877, // 4
+ 10903, // 5
+ 0, // 6
+ 10929, // 7
+ /*10773*/ uint16(xCondIs64), 10776, 10790,
+ /*10776*/ uint16(xCondDataSize), 10780, 10785, 0,
+ /*10780*/ uint16(xSetOp), uint16(ROL),
+ /*10782*/ uint16(xArgRM16),
+ /*10783*/ uint16(xArg1),
+ /*10784*/ uint16(xMatch),
+ /*10785*/ uint16(xSetOp), uint16(ROL),
+ /*10787*/ uint16(xArgRM32),
+ /*10788*/ uint16(xArg1),
+ /*10789*/ uint16(xMatch),
+ /*10790*/ uint16(xCondDataSize), 10780, 10785, 10794,
+ /*10794*/ uint16(xSetOp), uint16(ROL),
+ /*10796*/ uint16(xArgRM64),
+ /*10797*/ uint16(xArg1),
+ /*10798*/ uint16(xMatch),
+ /*10799*/ uint16(xCondIs64), 10802, 10816,
+ /*10802*/ uint16(xCondDataSize), 10806, 10811, 0,
+ /*10806*/ uint16(xSetOp), uint16(ROR),
+ /*10808*/ uint16(xArgRM16),
+ /*10809*/ uint16(xArg1),
+ /*10810*/ uint16(xMatch),
+ /*10811*/ uint16(xSetOp), uint16(ROR),
+ /*10813*/ uint16(xArgRM32),
+ /*10814*/ uint16(xArg1),
+ /*10815*/ uint16(xMatch),
+ /*10816*/ uint16(xCondDataSize), 10806, 10811, 10820,
+ /*10820*/ uint16(xSetOp), uint16(ROR),
+ /*10822*/ uint16(xArgRM64),
+ /*10823*/ uint16(xArg1),
+ /*10824*/ uint16(xMatch),
+ /*10825*/ uint16(xCondIs64), 10828, 10842,
+ /*10828*/ uint16(xCondDataSize), 10832, 10837, 0,
+ /*10832*/ uint16(xSetOp), uint16(RCL),
+ /*10834*/ uint16(xArgRM16),
+ /*10835*/ uint16(xArg1),
+ /*10836*/ uint16(xMatch),
+ /*10837*/ uint16(xSetOp), uint16(RCL),
+ /*10839*/ uint16(xArgRM32),
+ /*10840*/ uint16(xArg1),
+ /*10841*/ uint16(xMatch),
+ /*10842*/ uint16(xCondDataSize), 10832, 10837, 10846,
+ /*10846*/ uint16(xSetOp), uint16(RCL),
+ /*10848*/ uint16(xArgRM64),
+ /*10849*/ uint16(xArg1),
+ /*10850*/ uint16(xMatch),
+ /*10851*/ uint16(xCondIs64), 10854, 10868,
+ /*10854*/ uint16(xCondDataSize), 10858, 10863, 0,
+ /*10858*/ uint16(xSetOp), uint16(RCR),
+ /*10860*/ uint16(xArgRM16),
+ /*10861*/ uint16(xArg1),
+ /*10862*/ uint16(xMatch),
+ /*10863*/ uint16(xSetOp), uint16(RCR),
+ /*10865*/ uint16(xArgRM32),
+ /*10866*/ uint16(xArg1),
+ /*10867*/ uint16(xMatch),
+ /*10868*/ uint16(xCondDataSize), 10858, 10863, 10872,
+ /*10872*/ uint16(xSetOp), uint16(RCR),
+ /*10874*/ uint16(xArgRM64),
+ /*10875*/ uint16(xArg1),
+ /*10876*/ uint16(xMatch),
+ /*10877*/ uint16(xCondIs64), 10880, 10894,
+ /*10880*/ uint16(xCondDataSize), 10884, 10889, 0,
+ /*10884*/ uint16(xSetOp), uint16(SHL),
+ /*10886*/ uint16(xArgRM16),
+ /*10887*/ uint16(xArg1),
+ /*10888*/ uint16(xMatch),
+ /*10889*/ uint16(xSetOp), uint16(SHL),
+ /*10891*/ uint16(xArgRM32),
+ /*10892*/ uint16(xArg1),
+ /*10893*/ uint16(xMatch),
+ /*10894*/ uint16(xCondDataSize), 10884, 10889, 10898,
+ /*10898*/ uint16(xSetOp), uint16(SHL),
+ /*10900*/ uint16(xArgRM64),
+ /*10901*/ uint16(xArg1),
+ /*10902*/ uint16(xMatch),
+ /*10903*/ uint16(xCondIs64), 10906, 10920,
+ /*10906*/ uint16(xCondDataSize), 10910, 10915, 0,
+ /*10910*/ uint16(xSetOp), uint16(SHR),
+ /*10912*/ uint16(xArgRM16),
+ /*10913*/ uint16(xArg1),
+ /*10914*/ uint16(xMatch),
+ /*10915*/ uint16(xSetOp), uint16(SHR),
+ /*10917*/ uint16(xArgRM32),
+ /*10918*/ uint16(xArg1),
+ /*10919*/ uint16(xMatch),
+ /*10920*/ uint16(xCondDataSize), 10910, 10915, 10924,
+ /*10924*/ uint16(xSetOp), uint16(SHR),
+ /*10926*/ uint16(xArgRM64),
+ /*10927*/ uint16(xArg1),
+ /*10928*/ uint16(xMatch),
+ /*10929*/ uint16(xCondIs64), 10932, 10946,
+ /*10932*/ uint16(xCondDataSize), 10936, 10941, 0,
+ /*10936*/ uint16(xSetOp), uint16(SAR),
+ /*10938*/ uint16(xArgRM16),
+ /*10939*/ uint16(xArg1),
+ /*10940*/ uint16(xMatch),
+ /*10941*/ uint16(xSetOp), uint16(SAR),
+ /*10943*/ uint16(xArgRM32),
+ /*10944*/ uint16(xArg1),
+ /*10945*/ uint16(xMatch),
+ /*10946*/ uint16(xCondDataSize), 10936, 10941, 10950,
+ /*10950*/ uint16(xSetOp), uint16(SAR),
+ /*10952*/ uint16(xArgRM64),
+ /*10953*/ uint16(xArg1),
+ /*10954*/ uint16(xMatch),
+ /*10955*/ uint16(xCondSlashR),
+ 10964, // 0
+ 10969, // 1
+ 10974, // 2
+ 10979, // 3
+ 10984, // 4
+ 10989, // 5
+ 0, // 6
+ 10994, // 7
+ /*10964*/ uint16(xSetOp), uint16(ROL),
+ /*10966*/ uint16(xArgRM8),
+ /*10967*/ uint16(xArgCL),
+ /*10968*/ uint16(xMatch),
+ /*10969*/ uint16(xSetOp), uint16(ROR),
+ /*10971*/ uint16(xArgRM8),
+ /*10972*/ uint16(xArgCL),
+ /*10973*/ uint16(xMatch),
+ /*10974*/ uint16(xSetOp), uint16(RCL),
+ /*10976*/ uint16(xArgRM8),
+ /*10977*/ uint16(xArgCL),
+ /*10978*/ uint16(xMatch),
+ /*10979*/ uint16(xSetOp), uint16(RCR),
+ /*10981*/ uint16(xArgRM8),
+ /*10982*/ uint16(xArgCL),
+ /*10983*/ uint16(xMatch),
+ /*10984*/ uint16(xSetOp), uint16(SHL),
+ /*10986*/ uint16(xArgRM8),
+ /*10987*/ uint16(xArgCL),
+ /*10988*/ uint16(xMatch),
+ /*10989*/ uint16(xSetOp), uint16(SHR),
+ /*10991*/ uint16(xArgRM8),
+ /*10992*/ uint16(xArgCL),
+ /*10993*/ uint16(xMatch),
+ /*10994*/ uint16(xSetOp), uint16(SAR),
+ /*10996*/ uint16(xArgRM8),
+ /*10997*/ uint16(xArgCL),
+ /*10998*/ uint16(xMatch),
+ /*10999*/ uint16(xCondSlashR),
+ 11008, // 0
+ 11034, // 1
+ 11060, // 2
+ 11086, // 3
+ 11112, // 4
+ 11138, // 5
+ 0, // 6
+ 11164, // 7
+ /*11008*/ uint16(xCondIs64), 11011, 11025,
+ /*11011*/ uint16(xCondDataSize), 11015, 11020, 0,
+ /*11015*/ uint16(xSetOp), uint16(ROL),
+ /*11017*/ uint16(xArgRM16),
+ /*11018*/ uint16(xArgCL),
+ /*11019*/ uint16(xMatch),
+ /*11020*/ uint16(xSetOp), uint16(ROL),
+ /*11022*/ uint16(xArgRM32),
+ /*11023*/ uint16(xArgCL),
+ /*11024*/ uint16(xMatch),
+ /*11025*/ uint16(xCondDataSize), 11015, 11020, 11029,
+ /*11029*/ uint16(xSetOp), uint16(ROL),
+ /*11031*/ uint16(xArgRM64),
+ /*11032*/ uint16(xArgCL),
+ /*11033*/ uint16(xMatch),
+ /*11034*/ uint16(xCondIs64), 11037, 11051,
+ /*11037*/ uint16(xCondDataSize), 11041, 11046, 0,
+ /*11041*/ uint16(xSetOp), uint16(ROR),
+ /*11043*/ uint16(xArgRM16),
+ /*11044*/ uint16(xArgCL),
+ /*11045*/ uint16(xMatch),
+ /*11046*/ uint16(xSetOp), uint16(ROR),
+ /*11048*/ uint16(xArgRM32),
+ /*11049*/ uint16(xArgCL),
+ /*11050*/ uint16(xMatch),
+ /*11051*/ uint16(xCondDataSize), 11041, 11046, 11055,
+ /*11055*/ uint16(xSetOp), uint16(ROR),
+ /*11057*/ uint16(xArgRM64),
+ /*11058*/ uint16(xArgCL),
+ /*11059*/ uint16(xMatch),
+ /*11060*/ uint16(xCondIs64), 11063, 11077,
+ /*11063*/ uint16(xCondDataSize), 11067, 11072, 0,
+ /*11067*/ uint16(xSetOp), uint16(RCL),
+ /*11069*/ uint16(xArgRM16),
+ /*11070*/ uint16(xArgCL),
+ /*11071*/ uint16(xMatch),
+ /*11072*/ uint16(xSetOp), uint16(RCL),
+ /*11074*/ uint16(xArgRM32),
+ /*11075*/ uint16(xArgCL),
+ /*11076*/ uint16(xMatch),
+ /*11077*/ uint16(xCondDataSize), 11067, 11072, 11081,
+ /*11081*/ uint16(xSetOp), uint16(RCL),
+ /*11083*/ uint16(xArgRM64),
+ /*11084*/ uint16(xArgCL),
+ /*11085*/ uint16(xMatch),
+ /*11086*/ uint16(xCondIs64), 11089, 11103,
+ /*11089*/ uint16(xCondDataSize), 11093, 11098, 0,
+ /*11093*/ uint16(xSetOp), uint16(RCR),
+ /*11095*/ uint16(xArgRM16),
+ /*11096*/ uint16(xArgCL),
+ /*11097*/ uint16(xMatch),
+ /*11098*/ uint16(xSetOp), uint16(RCR),
+ /*11100*/ uint16(xArgRM32),
+ /*11101*/ uint16(xArgCL),
+ /*11102*/ uint16(xMatch),
+ /*11103*/ uint16(xCondDataSize), 11093, 11098, 11107,
+ /*11107*/ uint16(xSetOp), uint16(RCR),
+ /*11109*/ uint16(xArgRM64),
+ /*11110*/ uint16(xArgCL),
+ /*11111*/ uint16(xMatch),
+ /*11112*/ uint16(xCondIs64), 11115, 11129,
+ /*11115*/ uint16(xCondDataSize), 11119, 11124, 0,
+ /*11119*/ uint16(xSetOp), uint16(SHL),
+ /*11121*/ uint16(xArgRM16),
+ /*11122*/ uint16(xArgCL),
+ /*11123*/ uint16(xMatch),
+ /*11124*/ uint16(xSetOp), uint16(SHL),
+ /*11126*/ uint16(xArgRM32),
+ /*11127*/ uint16(xArgCL),
+ /*11128*/ uint16(xMatch),
+ /*11129*/ uint16(xCondDataSize), 11119, 11124, 11133,
+ /*11133*/ uint16(xSetOp), uint16(SHL),
+ /*11135*/ uint16(xArgRM64),
+ /*11136*/ uint16(xArgCL),
+ /*11137*/ uint16(xMatch),
+ /*11138*/ uint16(xCondIs64), 11141, 11155,
+ /*11141*/ uint16(xCondDataSize), 11145, 11150, 0,
+ /*11145*/ uint16(xSetOp), uint16(SHR),
+ /*11147*/ uint16(xArgRM16),
+ /*11148*/ uint16(xArgCL),
+ /*11149*/ uint16(xMatch),
+ /*11150*/ uint16(xSetOp), uint16(SHR),
+ /*11152*/ uint16(xArgRM32),
+ /*11153*/ uint16(xArgCL),
+ /*11154*/ uint16(xMatch),
+ /*11155*/ uint16(xCondDataSize), 11145, 11150, 11159,
+ /*11159*/ uint16(xSetOp), uint16(SHR),
+ /*11161*/ uint16(xArgRM64),
+ /*11162*/ uint16(xArgCL),
+ /*11163*/ uint16(xMatch),
+ /*11164*/ uint16(xCondIs64), 11167, 11181,
+ /*11167*/ uint16(xCondDataSize), 11171, 11176, 0,
+ /*11171*/ uint16(xSetOp), uint16(SAR),
+ /*11173*/ uint16(xArgRM16),
+ /*11174*/ uint16(xArgCL),
+ /*11175*/ uint16(xMatch),
+ /*11176*/ uint16(xSetOp), uint16(SAR),
+ /*11178*/ uint16(xArgRM32),
+ /*11179*/ uint16(xArgCL),
+ /*11180*/ uint16(xMatch),
+ /*11181*/ uint16(xCondDataSize), 11171, 11176, 11185,
+ /*11185*/ uint16(xSetOp), uint16(SAR),
+ /*11187*/ uint16(xArgRM64),
+ /*11188*/ uint16(xArgCL),
+ /*11189*/ uint16(xMatch),
+ /*11190*/ uint16(xCondIs64), 11193, 0,
+ /*11193*/ uint16(xSetOp), uint16(AAM),
+ /*11195*/ uint16(xReadIb),
+ /*11196*/ uint16(xArgImm8u),
+ /*11197*/ uint16(xMatch),
+ /*11198*/ uint16(xCondIs64), 11201, 0,
+ /*11201*/ uint16(xSetOp), uint16(AAD),
+ /*11203*/ uint16(xReadIb),
+ /*11204*/ uint16(xArgImm8u),
+ /*11205*/ uint16(xMatch),
+ /*11206*/ uint16(xCondIs64), 11209, 11212,
+ /*11209*/ uint16(xSetOp), uint16(XLATB),
+ /*11211*/ uint16(xMatch),
+ /*11212*/ uint16(xCondDataSize), 11209, 11209, 11216,
+ /*11216*/ uint16(xSetOp), uint16(XLATB),
+ /*11218*/ uint16(xMatch),
+ /*11219*/ uint16(xCondByte), 64,
+ 0xc0, 11390,
+ 0xc1, 11390,
+ 0xc2, 11390,
+ 0xc3, 11390,
+ 0xc4, 11390,
+ 0xc5, 11390,
+ 0xc6, 11390,
+ 0xc7, 11390,
+ 0xc8, 11395,
+ 0xc9, 11395,
+ 0xca, 11395,
+ 0xcb, 11395,
+ 0xcc, 11395,
+ 0xcd, 11395,
+ 0xce, 11395,
+ 0xcf, 11395,
+ 0xd0, 11400,
+ 0xd1, 11400,
+ 0xd2, 11400,
+ 0xd3, 11400,
+ 0xd4, 11400,
+ 0xd5, 11400,
+ 0xd6, 11400,
+ 0xd7, 11400,
+ 0xd8, 11404,
+ 0xd9, 11404,
+ 0xda, 11404,
+ 0xdb, 11404,
+ 0xdc, 11404,
+ 0xdd, 11404,
+ 0xde, 11404,
+ 0xdf, 11404,
+ 0xe0, 11408,
+ 0xe1, 11408,
+ 0xe2, 11408,
+ 0xe3, 11408,
+ 0xe4, 11408,
+ 0xe5, 11408,
+ 0xe6, 11408,
+ 0xe7, 11408,
+ 0xe8, 11413,
+ 0xe9, 11413,
+ 0xea, 11413,
+ 0xeb, 11413,
+ 0xec, 11413,
+ 0xed, 11413,
+ 0xee, 11413,
+ 0xef, 11413,
+ 0xf0, 11418,
+ 0xf1, 11418,
+ 0xf2, 11418,
+ 0xf3, 11418,
+ 0xf4, 11418,
+ 0xf5, 11418,
+ 0xf6, 11418,
+ 0xf7, 11418,
+ 0xf8, 11423,
+ 0xf9, 11423,
+ 0xfa, 11423,
+ 0xfb, 11423,
+ 0xfc, 11423,
+ 0xfd, 11423,
+ 0xfe, 11423,
+ 0xff, 11423,
+ /*11349*/ uint16(xCondSlashR),
+ 11358, // 0
+ 11362, // 1
+ 11366, // 2
+ 11370, // 3
+ 11374, // 4
+ 11378, // 5
+ 11382, // 6
+ 11386, // 7
+ /*11358*/ uint16(xSetOp), uint16(FADD),
+ /*11360*/ uint16(xArgM32fp),
+ /*11361*/ uint16(xMatch),
+ /*11362*/ uint16(xSetOp), uint16(FMUL),
+ /*11364*/ uint16(xArgM32fp),
+ /*11365*/ uint16(xMatch),
+ /*11366*/ uint16(xSetOp), uint16(FCOM),
+ /*11368*/ uint16(xArgM32fp),
+ /*11369*/ uint16(xMatch),
+ /*11370*/ uint16(xSetOp), uint16(FCOMP),
+ /*11372*/ uint16(xArgM32fp),
+ /*11373*/ uint16(xMatch),
+ /*11374*/ uint16(xSetOp), uint16(FSUB),
+ /*11376*/ uint16(xArgM32fp),
+ /*11377*/ uint16(xMatch),
+ /*11378*/ uint16(xSetOp), uint16(FSUBR),
+ /*11380*/ uint16(xArgM32fp),
+ /*11381*/ uint16(xMatch),
+ /*11382*/ uint16(xSetOp), uint16(FDIV),
+ /*11384*/ uint16(xArgM32fp),
+ /*11385*/ uint16(xMatch),
+ /*11386*/ uint16(xSetOp), uint16(FDIVR),
+ /*11388*/ uint16(xArgM32fp),
+ /*11389*/ uint16(xMatch),
+ /*11390*/ uint16(xSetOp), uint16(FADD),
+ /*11392*/ uint16(xArgST),
+ /*11393*/ uint16(xArgSTi),
+ /*11394*/ uint16(xMatch),
+ /*11395*/ uint16(xSetOp), uint16(FMUL),
+ /*11397*/ uint16(xArgST),
+ /*11398*/ uint16(xArgSTi),
+ /*11399*/ uint16(xMatch),
+ /*11400*/ uint16(xSetOp), uint16(FCOM),
+ /*11402*/ uint16(xArgSTi),
+ /*11403*/ uint16(xMatch),
+ /*11404*/ uint16(xSetOp), uint16(FCOMP),
+ /*11406*/ uint16(xArgSTi),
+ /*11407*/ uint16(xMatch),
+ /*11408*/ uint16(xSetOp), uint16(FSUB),
+ /*11410*/ uint16(xArgST),
+ /*11411*/ uint16(xArgSTi),
+ /*11412*/ uint16(xMatch),
+ /*11413*/ uint16(xSetOp), uint16(FSUBR),
+ /*11415*/ uint16(xArgST),
+ /*11416*/ uint16(xArgSTi),
+ /*11417*/ uint16(xMatch),
+ /*11418*/ uint16(xSetOp), uint16(FDIV),
+ /*11420*/ uint16(xArgST),
+ /*11421*/ uint16(xArgSTi),
+ /*11422*/ uint16(xMatch),
+ /*11423*/ uint16(xSetOp), uint16(FDIVR),
+ /*11425*/ uint16(xArgST),
+ /*11426*/ uint16(xArgSTi),
+ /*11427*/ uint16(xMatch),
+ /*11428*/ uint16(xCondByte), 42,
+ 0xc0, 11551,
+ 0xc1, 11551,
+ 0xc2, 11551,
+ 0xc3, 11551,
+ 0xc4, 11551,
+ 0xc5, 11551,
+ 0xc6, 11551,
+ 0xc7, 11551,
+ 0xc8, 11555,
+ 0xc9, 11555,
+ 0xca, 11555,
+ 0xcb, 11555,
+ 0xcc, 11555,
+ 0xcd, 11555,
+ 0xce, 11555,
+ 0xcf, 11555,
+ 0xD0, 11559,
+ 0xE0, 11562,
+ 0xE1, 11565,
+ 0xE4, 11568,
+ 0xE5, 11571,
+ 0xE8, 11574,
+ 0xE9, 11577,
+ 0xEA, 11580,
+ 0xEB, 11583,
+ 0xEC, 11586,
+ 0xF0, 11589,
+ 0xF1, 11592,
+ 0xF2, 11595,
+ 0xF3, 11598,
+ 0xF4, 11601,
+ 0xF5, 11604,
+ 0xF6, 11607,
+ 0xF7, 11610,
+ 0xF8, 11613,
+ 0xF9, 11616,
+ 0xFA, 11619,
+ 0xFB, 11622,
+ 0xFC, 11625,
+ 0xFD, 11628,
+ 0xFE, 11631,
+ 0xFF, 11634,
+ /*11514*/ uint16(xCondSlashR),
+ 11523, // 0
+ 0, // 1
+ 11527, // 2
+ 11531, // 3
+ 11535, // 4
+ 11539, // 5
+ 11543, // 6
+ 11547, // 7
+ /*11523*/ uint16(xSetOp), uint16(FLD),
+ /*11525*/ uint16(xArgM32fp),
+ /*11526*/ uint16(xMatch),
+ /*11527*/ uint16(xSetOp), uint16(FST),
+ /*11529*/ uint16(xArgM32fp),
+ /*11530*/ uint16(xMatch),
+ /*11531*/ uint16(xSetOp), uint16(FSTP),
+ /*11533*/ uint16(xArgM32fp),
+ /*11534*/ uint16(xMatch),
+ /*11535*/ uint16(xSetOp), uint16(FLDENV),
+ /*11537*/ uint16(xArgM1428byte),
+ /*11538*/ uint16(xMatch),
+ /*11539*/ uint16(xSetOp), uint16(FLDCW),
+ /*11541*/ uint16(xArgM2byte),
+ /*11542*/ uint16(xMatch),
+ /*11543*/ uint16(xSetOp), uint16(FNSTENV),
+ /*11545*/ uint16(xArgM1428byte),
+ /*11546*/ uint16(xMatch),
+ /*11547*/ uint16(xSetOp), uint16(FNSTCW),
+ /*11549*/ uint16(xArgM2byte),
+ /*11550*/ uint16(xMatch),
+ /*11551*/ uint16(xSetOp), uint16(FLD),
+ /*11553*/ uint16(xArgSTi),
+ /*11554*/ uint16(xMatch),
+ /*11555*/ uint16(xSetOp), uint16(FXCH),
+ /*11557*/ uint16(xArgSTi),
+ /*11558*/ uint16(xMatch),
+ /*11559*/ uint16(xSetOp), uint16(FNOP),
+ /*11561*/ uint16(xMatch),
+ /*11562*/ uint16(xSetOp), uint16(FCHS),
+ /*11564*/ uint16(xMatch),
+ /*11565*/ uint16(xSetOp), uint16(FABS),
+ /*11567*/ uint16(xMatch),
+ /*11568*/ uint16(xSetOp), uint16(FTST),
+ /*11570*/ uint16(xMatch),
+ /*11571*/ uint16(xSetOp), uint16(FXAM),
+ /*11573*/ uint16(xMatch),
+ /*11574*/ uint16(xSetOp), uint16(FLD1),
+ /*11576*/ uint16(xMatch),
+ /*11577*/ uint16(xSetOp), uint16(FLDL2T),
+ /*11579*/ uint16(xMatch),
+ /*11580*/ uint16(xSetOp), uint16(FLDL2E),
+ /*11582*/ uint16(xMatch),
+ /*11583*/ uint16(xSetOp), uint16(FLDPI),
+ /*11585*/ uint16(xMatch),
+ /*11586*/ uint16(xSetOp), uint16(FLDLG2),
+ /*11588*/ uint16(xMatch),
+ /*11589*/ uint16(xSetOp), uint16(F2XM1),
+ /*11591*/ uint16(xMatch),
+ /*11592*/ uint16(xSetOp), uint16(FYL2X),
+ /*11594*/ uint16(xMatch),
+ /*11595*/ uint16(xSetOp), uint16(FPTAN),
+ /*11597*/ uint16(xMatch),
+ /*11598*/ uint16(xSetOp), uint16(FPATAN),
+ /*11600*/ uint16(xMatch),
+ /*11601*/ uint16(xSetOp), uint16(FXTRACT),
+ /*11603*/ uint16(xMatch),
+ /*11604*/ uint16(xSetOp), uint16(FPREM1),
+ /*11606*/ uint16(xMatch),
+ /*11607*/ uint16(xSetOp), uint16(FDECSTP),
+ /*11609*/ uint16(xMatch),
+ /*11610*/ uint16(xSetOp), uint16(FINCSTP),
+ /*11612*/ uint16(xMatch),
+ /*11613*/ uint16(xSetOp), uint16(FPREM),
+ /*11615*/ uint16(xMatch),
+ /*11616*/ uint16(xSetOp), uint16(FYL2XP1),
+ /*11618*/ uint16(xMatch),
+ /*11619*/ uint16(xSetOp), uint16(FSQRT),
+ /*11621*/ uint16(xMatch),
+ /*11622*/ uint16(xSetOp), uint16(FSINCOS),
+ /*11624*/ uint16(xMatch),
+ /*11625*/ uint16(xSetOp), uint16(FRNDINT),
+ /*11627*/ uint16(xMatch),
+ /*11628*/ uint16(xSetOp), uint16(FSCALE),
+ /*11630*/ uint16(xMatch),
+ /*11631*/ uint16(xSetOp), uint16(FSIN),
+ /*11633*/ uint16(xMatch),
+ /*11634*/ uint16(xSetOp), uint16(FCOS),
+ /*11636*/ uint16(xMatch),
+ /*11637*/ uint16(xCondByte), 33,
+ 0xc0, 11746,
+ 0xc1, 11746,
+ 0xc2, 11746,
+ 0xc3, 11746,
+ 0xc4, 11746,
+ 0xc5, 11746,
+ 0xc6, 11746,
+ 0xc7, 11746,
+ 0xc8, 11751,
+ 0xc9, 11751,
+ 0xca, 11751,
+ 0xcb, 11751,
+ 0xcc, 11751,
+ 0xcd, 11751,
+ 0xce, 11751,
+ 0xcf, 11751,
+ 0xd0, 11756,
+ 0xd1, 11756,
+ 0xd2, 11756,
+ 0xd3, 11756,
+ 0xd4, 11756,
+ 0xd5, 11756,
+ 0xd6, 11756,
+ 0xd7, 11756,
+ 0xd8, 11761,
+ 0xd9, 11761,
+ 0xda, 11761,
+ 0xdb, 11761,
+ 0xdc, 11761,
+ 0xdd, 11761,
+ 0xde, 11761,
+ 0xdf, 11761,
+ 0xE9, 11766,
+ /*11705*/ uint16(xCondSlashR),
+ 11714, // 0
+ 11718, // 1
+ 11722, // 2
+ 11726, // 3
+ 11730, // 4
+ 11734, // 5
+ 11738, // 6
+ 11742, // 7
+ /*11714*/ uint16(xSetOp), uint16(FIADD),
+ /*11716*/ uint16(xArgM32int),
+ /*11717*/ uint16(xMatch),
+ /*11718*/ uint16(xSetOp), uint16(FIMUL),
+ /*11720*/ uint16(xArgM32int),
+ /*11721*/ uint16(xMatch),
+ /*11722*/ uint16(xSetOp), uint16(FICOM),
+ /*11724*/ uint16(xArgM32int),
+ /*11725*/ uint16(xMatch),
+ /*11726*/ uint16(xSetOp), uint16(FICOMP),
+ /*11728*/ uint16(xArgM32int),
+ /*11729*/ uint16(xMatch),
+ /*11730*/ uint16(xSetOp), uint16(FISUB),
+ /*11732*/ uint16(xArgM32int),
+ /*11733*/ uint16(xMatch),
+ /*11734*/ uint16(xSetOp), uint16(FISUBR),
+ /*11736*/ uint16(xArgM32int),
+ /*11737*/ uint16(xMatch),
+ /*11738*/ uint16(xSetOp), uint16(FIDIV),
+ /*11740*/ uint16(xArgM32int),
+ /*11741*/ uint16(xMatch),
+ /*11742*/ uint16(xSetOp), uint16(FIDIVR),
+ /*11744*/ uint16(xArgM32int),
+ /*11745*/ uint16(xMatch),
+ /*11746*/ uint16(xSetOp), uint16(FCMOVB),
+ /*11748*/ uint16(xArgST),
+ /*11749*/ uint16(xArgSTi),
+ /*11750*/ uint16(xMatch),
+ /*11751*/ uint16(xSetOp), uint16(FCMOVE),
+ /*11753*/ uint16(xArgST),
+ /*11754*/ uint16(xArgSTi),
+ /*11755*/ uint16(xMatch),
+ /*11756*/ uint16(xSetOp), uint16(FCMOVBE),
+ /*11758*/ uint16(xArgST),
+ /*11759*/ uint16(xArgSTi),
+ /*11760*/ uint16(xMatch),
+ /*11761*/ uint16(xSetOp), uint16(FCMOVU),
+ /*11763*/ uint16(xArgST),
+ /*11764*/ uint16(xArgSTi),
+ /*11765*/ uint16(xMatch),
+ /*11766*/ uint16(xSetOp), uint16(FUCOMPP),
+ /*11768*/ uint16(xMatch),
+ /*11769*/ uint16(xCondByte), 50,
+ 0xc0, 11904,
+ 0xc1, 11904,
+ 0xc2, 11904,
+ 0xc3, 11904,
+ 0xc4, 11904,
+ 0xc5, 11904,
+ 0xc6, 11904,
+ 0xc7, 11904,
+ 0xc8, 11909,
+ 0xc9, 11909,
+ 0xca, 11909,
+ 0xcb, 11909,
+ 0xcc, 11909,
+ 0xcd, 11909,
+ 0xce, 11909,
+ 0xcf, 11909,
+ 0xd0, 11914,
+ 0xd1, 11914,
+ 0xd2, 11914,
+ 0xd3, 11914,
+ 0xd4, 11914,
+ 0xd5, 11914,
+ 0xd6, 11914,
+ 0xd7, 11914,
+ 0xd8, 11919,
+ 0xd9, 11919,
+ 0xda, 11919,
+ 0xdb, 11919,
+ 0xdc, 11919,
+ 0xdd, 11919,
+ 0xde, 11919,
+ 0xdf, 11919,
+ 0xE2, 11924,
+ 0xE3, 11927,
+ 0xe8, 11930,
+ 0xe9, 11930,
+ 0xea, 11930,
+ 0xeb, 11930,
+ 0xec, 11930,
+ 0xed, 11930,
+ 0xee, 11930,
+ 0xef, 11930,
+ 0xf0, 11935,
+ 0xf1, 11935,
+ 0xf2, 11935,
+ 0xf3, 11935,
+ 0xf4, 11935,
+ 0xf5, 11935,
+ 0xf6, 11935,
+ 0xf7, 11935,
+ /*11871*/ uint16(xCondSlashR),
+ 11880, // 0
+ 11884, // 1
+ 11888, // 2
+ 11892, // 3
+ 0, // 4
+ 11896, // 5
+ 0, // 6
+ 11900, // 7
+ /*11880*/ uint16(xSetOp), uint16(FILD),
+ /*11882*/ uint16(xArgM32int),
+ /*11883*/ uint16(xMatch),
+ /*11884*/ uint16(xSetOp), uint16(FISTTP),
+ /*11886*/ uint16(xArgM32int),
+ /*11887*/ uint16(xMatch),
+ /*11888*/ uint16(xSetOp), uint16(FIST),
+ /*11890*/ uint16(xArgM32int),
+ /*11891*/ uint16(xMatch),
+ /*11892*/ uint16(xSetOp), uint16(FISTP),
+ /*11894*/ uint16(xArgM32int),
+ /*11895*/ uint16(xMatch),
+ /*11896*/ uint16(xSetOp), uint16(FLD),
+ /*11898*/ uint16(xArgM80fp),
+ /*11899*/ uint16(xMatch),
+ /*11900*/ uint16(xSetOp), uint16(FSTP),
+ /*11902*/ uint16(xArgM80fp),
+ /*11903*/ uint16(xMatch),
+ /*11904*/ uint16(xSetOp), uint16(FCMOVNB),
+ /*11906*/ uint16(xArgST),
+ /*11907*/ uint16(xArgSTi),
+ /*11908*/ uint16(xMatch),
+ /*11909*/ uint16(xSetOp), uint16(FCMOVNE),
+ /*11911*/ uint16(xArgST),
+ /*11912*/ uint16(xArgSTi),
+ /*11913*/ uint16(xMatch),
+ /*11914*/ uint16(xSetOp), uint16(FCMOVNBE),
+ /*11916*/ uint16(xArgST),
+ /*11917*/ uint16(xArgSTi),
+ /*11918*/ uint16(xMatch),
+ /*11919*/ uint16(xSetOp), uint16(FCMOVNU),
+ /*11921*/ uint16(xArgST),
+ /*11922*/ uint16(xArgSTi),
+ /*11923*/ uint16(xMatch),
+ /*11924*/ uint16(xSetOp), uint16(FNCLEX),
+ /*11926*/ uint16(xMatch),
+ /*11927*/ uint16(xSetOp), uint16(FNINIT),
+ /*11929*/ uint16(xMatch),
+ /*11930*/ uint16(xSetOp), uint16(FUCOMI),
+ /*11932*/ uint16(xArgST),
+ /*11933*/ uint16(xArgSTi),
+ /*11934*/ uint16(xMatch),
+ /*11935*/ uint16(xSetOp), uint16(FCOMI),
+ /*11937*/ uint16(xArgST),
+ /*11938*/ uint16(xArgSTi),
+ /*11939*/ uint16(xMatch),
+ /*11940*/ uint16(xCondByte), 48,
+ 0xc0, 12079,
+ 0xc1, 12079,
+ 0xc2, 12079,
+ 0xc3, 12079,
+ 0xc4, 12079,
+ 0xc5, 12079,
+ 0xc6, 12079,
+ 0xc7, 12079,
+ 0xc8, 12084,
+ 0xc9, 12084,
+ 0xca, 12084,
+ 0xcb, 12084,
+ 0xcc, 12084,
+ 0xcd, 12084,
+ 0xce, 12084,
+ 0xcf, 12084,
+ 0xe0, 12089,
+ 0xe1, 12089,
+ 0xe2, 12089,
+ 0xe3, 12089,
+ 0xe4, 12089,
+ 0xe5, 12089,
+ 0xe6, 12089,
+ 0xe7, 12089,
+ 0xe8, 12094,
+ 0xe9, 12094,
+ 0xea, 12094,
+ 0xeb, 12094,
+ 0xec, 12094,
+ 0xed, 12094,
+ 0xee, 12094,
+ 0xef, 12094,
+ 0xf0, 12099,
+ 0xf1, 12099,
+ 0xf2, 12099,
+ 0xf3, 12099,
+ 0xf4, 12099,
+ 0xf5, 12099,
+ 0xf6, 12099,
+ 0xf7, 12099,
+ 0xf8, 12104,
+ 0xf9, 12104,
+ 0xfa, 12104,
+ 0xfb, 12104,
+ 0xfc, 12104,
+ 0xfd, 12104,
+ 0xfe, 12104,
+ 0xff, 12104,
+ /*12038*/ uint16(xCondSlashR),
+ 12047, // 0
+ 12051, // 1
+ 12055, // 2
+ 12059, // 3
+ 12063, // 4
+ 12067, // 5
+ 12071, // 6
+ 12075, // 7
+ /*12047*/ uint16(xSetOp), uint16(FADD),
+ /*12049*/ uint16(xArgM64fp),
+ /*12050*/ uint16(xMatch),
+ /*12051*/ uint16(xSetOp), uint16(FMUL),
+ /*12053*/ uint16(xArgM64fp),
+ /*12054*/ uint16(xMatch),
+ /*12055*/ uint16(xSetOp), uint16(FCOM),
+ /*12057*/ uint16(xArgM64fp),
+ /*12058*/ uint16(xMatch),
+ /*12059*/ uint16(xSetOp), uint16(FCOMP),
+ /*12061*/ uint16(xArgM64fp),
+ /*12062*/ uint16(xMatch),
+ /*12063*/ uint16(xSetOp), uint16(FSUB),
+ /*12065*/ uint16(xArgM64fp),
+ /*12066*/ uint16(xMatch),
+ /*12067*/ uint16(xSetOp), uint16(FSUBR),
+ /*12069*/ uint16(xArgM64fp),
+ /*12070*/ uint16(xMatch),
+ /*12071*/ uint16(xSetOp), uint16(FDIV),
+ /*12073*/ uint16(xArgM64fp),
+ /*12074*/ uint16(xMatch),
+ /*12075*/ uint16(xSetOp), uint16(FDIVR),
+ /*12077*/ uint16(xArgM64fp),
+ /*12078*/ uint16(xMatch),
+ /*12079*/ uint16(xSetOp), uint16(FADD),
+ /*12081*/ uint16(xArgSTi),
+ /*12082*/ uint16(xArgST),
+ /*12083*/ uint16(xMatch),
+ /*12084*/ uint16(xSetOp), uint16(FMUL),
+ /*12086*/ uint16(xArgSTi),
+ /*12087*/ uint16(xArgST),
+ /*12088*/ uint16(xMatch),
+ /*12089*/ uint16(xSetOp), uint16(FSUBR),
+ /*12091*/ uint16(xArgSTi),
+ /*12092*/ uint16(xArgST),
+ /*12093*/ uint16(xMatch),
+ /*12094*/ uint16(xSetOp), uint16(FSUB),
+ /*12096*/ uint16(xArgSTi),
+ /*12097*/ uint16(xArgST),
+ /*12098*/ uint16(xMatch),
+ /*12099*/ uint16(xSetOp), uint16(FDIVR),
+ /*12101*/ uint16(xArgSTi),
+ /*12102*/ uint16(xArgST),
+ /*12103*/ uint16(xMatch),
+ /*12104*/ uint16(xSetOp), uint16(FDIV),
+ /*12106*/ uint16(xArgSTi),
+ /*12107*/ uint16(xArgST),
+ /*12108*/ uint16(xMatch),
+ /*12109*/ uint16(xCondByte), 40,
+ 0xc0, 12228,
+ 0xc1, 12228,
+ 0xc2, 12228,
+ 0xc3, 12228,
+ 0xc4, 12228,
+ 0xc5, 12228,
+ 0xc6, 12228,
+ 0xc7, 12228,
+ 0xd0, 12232,
+ 0xd1, 12232,
+ 0xd2, 12232,
+ 0xd3, 12232,
+ 0xd4, 12232,
+ 0xd5, 12232,
+ 0xd6, 12232,
+ 0xd7, 12232,
+ 0xd8, 12236,
+ 0xd9, 12236,
+ 0xda, 12236,
+ 0xdb, 12236,
+ 0xdc, 12236,
+ 0xdd, 12236,
+ 0xde, 12236,
+ 0xdf, 12236,
+ 0xe0, 12240,
+ 0xe1, 12240,
+ 0xe2, 12240,
+ 0xe3, 12240,
+ 0xe4, 12240,
+ 0xe5, 12240,
+ 0xe6, 12240,
+ 0xe7, 12240,
+ 0xe8, 12244,
+ 0xe9, 12244,
+ 0xea, 12244,
+ 0xeb, 12244,
+ 0xec, 12244,
+ 0xed, 12244,
+ 0xee, 12244,
+ 0xef, 12244,
+ /*12191*/ uint16(xCondSlashR),
+ 12200, // 0
+ 12204, // 1
+ 12208, // 2
+ 12212, // 3
+ 12216, // 4
+ 0, // 5
+ 12220, // 6
+ 12224, // 7
+ /*12200*/ uint16(xSetOp), uint16(FLD),
+ /*12202*/ uint16(xArgM64fp),
+ /*12203*/ uint16(xMatch),
+ /*12204*/ uint16(xSetOp), uint16(FISTTP),
+ /*12206*/ uint16(xArgM64int),
+ /*12207*/ uint16(xMatch),
+ /*12208*/ uint16(xSetOp), uint16(FST),
+ /*12210*/ uint16(xArgM64fp),
+ /*12211*/ uint16(xMatch),
+ /*12212*/ uint16(xSetOp), uint16(FSTP),
+ /*12214*/ uint16(xArgM64fp),
+ /*12215*/ uint16(xMatch),
+ /*12216*/ uint16(xSetOp), uint16(FRSTOR),
+ /*12218*/ uint16(xArgM94108byte),
+ /*12219*/ uint16(xMatch),
+ /*12220*/ uint16(xSetOp), uint16(FNSAVE),
+ /*12222*/ uint16(xArgM94108byte),
+ /*12223*/ uint16(xMatch),
+ /*12224*/ uint16(xSetOp), uint16(FNSTSW),
+ /*12226*/ uint16(xArgM2byte),
+ /*12227*/ uint16(xMatch),
+ /*12228*/ uint16(xSetOp), uint16(FFREE),
+ /*12230*/ uint16(xArgSTi),
+ /*12231*/ uint16(xMatch),
+ /*12232*/ uint16(xSetOp), uint16(FST),
+ /*12234*/ uint16(xArgSTi),
+ /*12235*/ uint16(xMatch),
+ /*12236*/ uint16(xSetOp), uint16(FSTP),
+ /*12238*/ uint16(xArgSTi),
+ /*12239*/ uint16(xMatch),
+ /*12240*/ uint16(xSetOp), uint16(FUCOM),
+ /*12242*/ uint16(xArgSTi),
+ /*12243*/ uint16(xMatch),
+ /*12244*/ uint16(xSetOp), uint16(FUCOMP),
+ /*12246*/ uint16(xArgSTi),
+ /*12247*/ uint16(xMatch),
+ /*12248*/ uint16(xCondByte), 49,
+ 0xc0, 12389,
+ 0xc1, 12389,
+ 0xc2, 12389,
+ 0xc3, 12389,
+ 0xc4, 12389,
+ 0xc5, 12389,
+ 0xc6, 12389,
+ 0xc7, 12389,
+ 0xc8, 12394,
+ 0xc9, 12394,
+ 0xca, 12394,
+ 0xcb, 12394,
+ 0xcc, 12394,
+ 0xcd, 12394,
+ 0xce, 12394,
+ 0xcf, 12394,
+ 0xD9, 12399,
+ 0xe0, 12402,
+ 0xe1, 12402,
+ 0xe2, 12402,
+ 0xe3, 12402,
+ 0xe4, 12402,
+ 0xe5, 12402,
+ 0xe6, 12402,
+ 0xe7, 12402,
+ 0xe8, 12407,
+ 0xe9, 12407,
+ 0xea, 12407,
+ 0xeb, 12407,
+ 0xec, 12407,
+ 0xed, 12407,
+ 0xee, 12407,
+ 0xef, 12407,
+ 0xf0, 12412,
+ 0xf1, 12412,
+ 0xf2, 12412,
+ 0xf3, 12412,
+ 0xf4, 12412,
+ 0xf5, 12412,
+ 0xf6, 12412,
+ 0xf7, 12412,
+ 0xf8, 12417,
+ 0xf9, 12417,
+ 0xfa, 12417,
+ 0xfb, 12417,
+ 0xfc, 12417,
+ 0xfd, 12417,
+ 0xfe, 12417,
+ 0xff, 12417,
+ /*12348*/ uint16(xCondSlashR),
+ 12357, // 0
+ 12361, // 1
+ 12365, // 2
+ 12369, // 3
+ 12373, // 4
+ 12377, // 5
+ 12381, // 6
+ 12385, // 7
+ /*12357*/ uint16(xSetOp), uint16(FIADD),
+ /*12359*/ uint16(xArgM16int),
+ /*12360*/ uint16(xMatch),
+ /*12361*/ uint16(xSetOp), uint16(FIMUL),
+ /*12363*/ uint16(xArgM16int),
+ /*12364*/ uint16(xMatch),
+ /*12365*/ uint16(xSetOp), uint16(FICOM),
+ /*12367*/ uint16(xArgM16int),
+ /*12368*/ uint16(xMatch),
+ /*12369*/ uint16(xSetOp), uint16(FICOMP),
+ /*12371*/ uint16(xArgM16int),
+ /*12372*/ uint16(xMatch),
+ /*12373*/ uint16(xSetOp), uint16(FISUB),
+ /*12375*/ uint16(xArgM16int),
+ /*12376*/ uint16(xMatch),
+ /*12377*/ uint16(xSetOp), uint16(FISUBR),
+ /*12379*/ uint16(xArgM16int),
+ /*12380*/ uint16(xMatch),
+ /*12381*/ uint16(xSetOp), uint16(FIDIV),
+ /*12383*/ uint16(xArgM16int),
+ /*12384*/ uint16(xMatch),
+ /*12385*/ uint16(xSetOp), uint16(FIDIVR),
+ /*12387*/ uint16(xArgM16int),
+ /*12388*/ uint16(xMatch),
+ /*12389*/ uint16(xSetOp), uint16(FADDP),
+ /*12391*/ uint16(xArgSTi),
+ /*12392*/ uint16(xArgST),
+ /*12393*/ uint16(xMatch),
+ /*12394*/ uint16(xSetOp), uint16(FMULP),
+ /*12396*/ uint16(xArgSTi),
+ /*12397*/ uint16(xArgST),
+ /*12398*/ uint16(xMatch),
+ /*12399*/ uint16(xSetOp), uint16(FCOMPP),
+ /*12401*/ uint16(xMatch),
+ /*12402*/ uint16(xSetOp), uint16(FSUBRP),
+ /*12404*/ uint16(xArgSTi),
+ /*12405*/ uint16(xArgST),
+ /*12406*/ uint16(xMatch),
+ /*12407*/ uint16(xSetOp), uint16(FSUBP),
+ /*12409*/ uint16(xArgSTi),
+ /*12410*/ uint16(xArgST),
+ /*12411*/ uint16(xMatch),
+ /*12412*/ uint16(xSetOp), uint16(FDIVRP),
+ /*12414*/ uint16(xArgSTi),
+ /*12415*/ uint16(xArgST),
+ /*12416*/ uint16(xMatch),
+ /*12417*/ uint16(xSetOp), uint16(FDIVP),
+ /*12419*/ uint16(xArgSTi),
+ /*12420*/ uint16(xArgST),
+ /*12421*/ uint16(xMatch),
+ /*12422*/ uint16(xCondByte), 25,
+ 0xc0, 12515,
+ 0xc1, 12515,
+ 0xc2, 12515,
+ 0xc3, 12515,
+ 0xc4, 12515,
+ 0xc5, 12515,
+ 0xc6, 12515,
+ 0xc7, 12515,
+ 0xE0, 12519,
+ 0xe8, 12523,
+ 0xe9, 12523,
+ 0xea, 12523,
+ 0xeb, 12523,
+ 0xec, 12523,
+ 0xed, 12523,
+ 0xee, 12523,
+ 0xef, 12523,
+ 0xf0, 12528,
+ 0xf1, 12528,
+ 0xf2, 12528,
+ 0xf3, 12528,
+ 0xf4, 12528,
+ 0xf5, 12528,
+ 0xf6, 12528,
+ 0xf7, 12528,
+ /*12474*/ uint16(xCondSlashR),
+ 12483, // 0
+ 12487, // 1
+ 12491, // 2
+ 12495, // 3
+ 12499, // 4
+ 12503, // 5
+ 12507, // 6
+ 12511, // 7
+ /*12483*/ uint16(xSetOp), uint16(FILD),
+ /*12485*/ uint16(xArgM16int),
+ /*12486*/ uint16(xMatch),
+ /*12487*/ uint16(xSetOp), uint16(FISTTP),
+ /*12489*/ uint16(xArgM16int),
+ /*12490*/ uint16(xMatch),
+ /*12491*/ uint16(xSetOp), uint16(FIST),
+ /*12493*/ uint16(xArgM16int),
+ /*12494*/ uint16(xMatch),
+ /*12495*/ uint16(xSetOp), uint16(FISTP),
+ /*12497*/ uint16(xArgM16int),
+ /*12498*/ uint16(xMatch),
+ /*12499*/ uint16(xSetOp), uint16(FBLD),
+ /*12501*/ uint16(xArgM80dec),
+ /*12502*/ uint16(xMatch),
+ /*12503*/ uint16(xSetOp), uint16(FILD),
+ /*12505*/ uint16(xArgM64int),
+ /*12506*/ uint16(xMatch),
+ /*12507*/ uint16(xSetOp), uint16(FBSTP),
+ /*12509*/ uint16(xArgM80bcd),
+ /*12510*/ uint16(xMatch),
+ /*12511*/ uint16(xSetOp), uint16(FISTP),
+ /*12513*/ uint16(xArgM64int),
+ /*12514*/ uint16(xMatch),
+ /*12515*/ uint16(xSetOp), uint16(FFREEP),
+ /*12517*/ uint16(xArgSTi),
+ /*12518*/ uint16(xMatch),
+ /*12519*/ uint16(xSetOp), uint16(FNSTSW),
+ /*12521*/ uint16(xArgAX),
+ /*12522*/ uint16(xMatch),
+ /*12523*/ uint16(xSetOp), uint16(FUCOMIP),
+ /*12525*/ uint16(xArgST),
+ /*12526*/ uint16(xArgSTi),
+ /*12527*/ uint16(xMatch),
+ /*12528*/ uint16(xSetOp), uint16(FCOMIP),
+ /*12530*/ uint16(xArgST),
+ /*12531*/ uint16(xArgSTi),
+ /*12532*/ uint16(xMatch),
+ /*12533*/ uint16(xSetOp), uint16(LOOPNE),
+ /*12535*/ uint16(xReadCb),
+ /*12536*/ uint16(xArgRel8),
+ /*12537*/ uint16(xMatch),
+ /*12538*/ uint16(xSetOp), uint16(LOOPE),
+ /*12540*/ uint16(xReadCb),
+ /*12541*/ uint16(xArgRel8),
+ /*12542*/ uint16(xMatch),
+ /*12543*/ uint16(xSetOp), uint16(LOOP),
+ /*12545*/ uint16(xReadCb),
+ /*12546*/ uint16(xArgRel8),
+ /*12547*/ uint16(xMatch),
+ /*12548*/ uint16(xCondIs64), 12551, 12565,
+ /*12551*/ uint16(xCondAddrSize), 12555, 12560, 0,
+ /*12555*/ uint16(xSetOp), uint16(JCXZ),
+ /*12557*/ uint16(xReadCb),
+ /*12558*/ uint16(xArgRel8),
+ /*12559*/ uint16(xMatch),
+ /*12560*/ uint16(xSetOp), uint16(JECXZ),
+ /*12562*/ uint16(xReadCb),
+ /*12563*/ uint16(xArgRel8),
+ /*12564*/ uint16(xMatch),
+ /*12565*/ uint16(xCondAddrSize), 0, 12560, 12569,
+ /*12569*/ uint16(xSetOp), uint16(JRCXZ),
+ /*12571*/ uint16(xReadCb),
+ /*12572*/ uint16(xArgRel8),
+ /*12573*/ uint16(xMatch),
+ /*12574*/ uint16(xSetOp), uint16(IN),
+ /*12576*/ uint16(xReadIb),
+ /*12577*/ uint16(xArgAL),
+ /*12578*/ uint16(xArgImm8u),
+ /*12579*/ uint16(xMatch),
+ /*12580*/ uint16(xCondDataSize), 12584, 12590, 12596,
+ /*12584*/ uint16(xSetOp), uint16(IN),
+ /*12586*/ uint16(xReadIb),
+ /*12587*/ uint16(xArgAX),
+ /*12588*/ uint16(xArgImm8u),
+ /*12589*/ uint16(xMatch),
+ /*12590*/ uint16(xSetOp), uint16(IN),
+ /*12592*/ uint16(xReadIb),
+ /*12593*/ uint16(xArgEAX),
+ /*12594*/ uint16(xArgImm8u),
+ /*12595*/ uint16(xMatch),
+ /*12596*/ uint16(xSetOp), uint16(IN),
+ /*12598*/ uint16(xReadIb),
+ /*12599*/ uint16(xArgEAX),
+ /*12600*/ uint16(xArgImm8u),
+ /*12601*/ uint16(xMatch),
+ /*12602*/ uint16(xSetOp), uint16(OUT),
+ /*12604*/ uint16(xReadIb),
+ /*12605*/ uint16(xArgImm8u),
+ /*12606*/ uint16(xArgAL),
+ /*12607*/ uint16(xMatch),
+ /*12608*/ uint16(xCondDataSize), 12612, 12618, 12624,
+ /*12612*/ uint16(xSetOp), uint16(OUT),
+ /*12614*/ uint16(xReadIb),
+ /*12615*/ uint16(xArgImm8u),
+ /*12616*/ uint16(xArgAX),
+ /*12617*/ uint16(xMatch),
+ /*12618*/ uint16(xSetOp), uint16(OUT),
+ /*12620*/ uint16(xReadIb),
+ /*12621*/ uint16(xArgImm8u),
+ /*12622*/ uint16(xArgEAX),
+ /*12623*/ uint16(xMatch),
+ /*12624*/ uint16(xSetOp), uint16(OUT),
+ /*12626*/ uint16(xReadIb),
+ /*12627*/ uint16(xArgImm8u),
+ /*12628*/ uint16(xArgEAX),
+ /*12629*/ uint16(xMatch),
+ /*12630*/ uint16(xCondIs64), 12633, 12647,
+ /*12633*/ uint16(xCondDataSize), 12637, 12642, 0,
+ /*12637*/ uint16(xSetOp), uint16(CALL),
+ /*12639*/ uint16(xReadCw),
+ /*12640*/ uint16(xArgRel16),
+ /*12641*/ uint16(xMatch),
+ /*12642*/ uint16(xSetOp), uint16(CALL),
+ /*12644*/ uint16(xReadCd),
+ /*12645*/ uint16(xArgRel32),
+ /*12646*/ uint16(xMatch),
+ /*12647*/ uint16(xCondDataSize), 12651, 12642, 12656,
+ /*12651*/ uint16(xSetOp), uint16(CALL),
+ /*12653*/ uint16(xReadCd),
+ /*12654*/ uint16(xArgRel32),
+ /*12655*/ uint16(xMatch),
+ /*12656*/ uint16(xSetOp), uint16(CALL),
+ /*12658*/ uint16(xReadCd),
+ /*12659*/ uint16(xArgRel32),
+ /*12660*/ uint16(xMatch),
+ /*12661*/ uint16(xCondIs64), 12664, 12678,
+ /*12664*/ uint16(xCondDataSize), 12668, 12673, 0,
+ /*12668*/ uint16(xSetOp), uint16(JMP),
+ /*12670*/ uint16(xReadCw),
+ /*12671*/ uint16(xArgRel16),
+ /*12672*/ uint16(xMatch),
+ /*12673*/ uint16(xSetOp), uint16(JMP),
+ /*12675*/ uint16(xReadCd),
+ /*12676*/ uint16(xArgRel32),
+ /*12677*/ uint16(xMatch),
+ /*12678*/ uint16(xCondDataSize), 12682, 12673, 12687,
+ /*12682*/ uint16(xSetOp), uint16(JMP),
+ /*12684*/ uint16(xReadCd),
+ /*12685*/ uint16(xArgRel32),
+ /*12686*/ uint16(xMatch),
+ /*12687*/ uint16(xSetOp), uint16(JMP),
+ /*12689*/ uint16(xReadCd),
+ /*12690*/ uint16(xArgRel32),
+ /*12691*/ uint16(xMatch),
+ /*12692*/ uint16(xCondIs64), 12695, 0,
+ /*12695*/ uint16(xCondDataSize), 12699, 12704, 0,
+ /*12699*/ uint16(xSetOp), uint16(LJMP),
+ /*12701*/ uint16(xReadCd),
+ /*12702*/ uint16(xArgPtr16colon16),
+ /*12703*/ uint16(xMatch),
+ /*12704*/ uint16(xSetOp), uint16(LJMP),
+ /*12706*/ uint16(xReadCp),
+ /*12707*/ uint16(xArgPtr16colon32),
+ /*12708*/ uint16(xMatch),
+ /*12709*/ uint16(xSetOp), uint16(JMP),
+ /*12711*/ uint16(xReadCb),
+ /*12712*/ uint16(xArgRel8),
+ /*12713*/ uint16(xMatch),
+ /*12714*/ uint16(xSetOp), uint16(IN),
+ /*12716*/ uint16(xArgAL),
+ /*12717*/ uint16(xArgDX),
+ /*12718*/ uint16(xMatch),
+ /*12719*/ uint16(xCondDataSize), 12723, 12728, 12733,
+ /*12723*/ uint16(xSetOp), uint16(IN),
+ /*12725*/ uint16(xArgAX),
+ /*12726*/ uint16(xArgDX),
+ /*12727*/ uint16(xMatch),
+ /*12728*/ uint16(xSetOp), uint16(IN),
+ /*12730*/ uint16(xArgEAX),
+ /*12731*/ uint16(xArgDX),
+ /*12732*/ uint16(xMatch),
+ /*12733*/ uint16(xSetOp), uint16(IN),
+ /*12735*/ uint16(xArgEAX),
+ /*12736*/ uint16(xArgDX),
+ /*12737*/ uint16(xMatch),
+ /*12738*/ uint16(xSetOp), uint16(OUT),
+ /*12740*/ uint16(xArgDX),
+ /*12741*/ uint16(xArgAL),
+ /*12742*/ uint16(xMatch),
+ /*12743*/ uint16(xCondDataSize), 12747, 12752, 12757,
+ /*12747*/ uint16(xSetOp), uint16(OUT),
+ /*12749*/ uint16(xArgDX),
+ /*12750*/ uint16(xArgAX),
+ /*12751*/ uint16(xMatch),
+ /*12752*/ uint16(xSetOp), uint16(OUT),
+ /*12754*/ uint16(xArgDX),
+ /*12755*/ uint16(xArgEAX),
+ /*12756*/ uint16(xMatch),
+ /*12757*/ uint16(xSetOp), uint16(OUT),
+ /*12759*/ uint16(xArgDX),
+ /*12760*/ uint16(xArgEAX),
+ /*12761*/ uint16(xMatch),
+ /*12762*/ uint16(xSetOp), uint16(ICEBP),
+ /*12764*/ uint16(xMatch),
+ /*12765*/ uint16(xSetOp), uint16(HLT),
+ /*12767*/ uint16(xMatch),
+ /*12768*/ uint16(xSetOp), uint16(CMC),
+ /*12770*/ uint16(xMatch),
+ /*12771*/ uint16(xCondSlashR),
+ 12780, // 0
+ 0, // 1
+ 12786, // 2
+ 12790, // 3
+ 12794, // 4
+ 12798, // 5
+ 12802, // 6
+ 12806, // 7
+ /*12780*/ uint16(xSetOp), uint16(TEST),
+ /*12782*/ uint16(xReadIb),
+ /*12783*/ uint16(xArgRM8),
+ /*12784*/ uint16(xArgImm8u),
+ /*12785*/ uint16(xMatch),
+ /*12786*/ uint16(xSetOp), uint16(NOT),
+ /*12788*/ uint16(xArgRM8),
+ /*12789*/ uint16(xMatch),
+ /*12790*/ uint16(xSetOp), uint16(NEG),
+ /*12792*/ uint16(xArgRM8),
+ /*12793*/ uint16(xMatch),
+ /*12794*/ uint16(xSetOp), uint16(MUL),
+ /*12796*/ uint16(xArgRM8),
+ /*12797*/ uint16(xMatch),
+ /*12798*/ uint16(xSetOp), uint16(IMUL),
+ /*12800*/ uint16(xArgRM8),
+ /*12801*/ uint16(xMatch),
+ /*12802*/ uint16(xSetOp), uint16(DIV),
+ /*12804*/ uint16(xArgRM8),
+ /*12805*/ uint16(xMatch),
+ /*12806*/ uint16(xSetOp), uint16(IDIV),
+ /*12808*/ uint16(xArgRM8),
+ /*12809*/ uint16(xMatch),
+ /*12810*/ uint16(xCondSlashR),
+ 12819, // 0
+ 0, // 1
+ 12848, // 2
+ 12871, // 3
+ 12894, // 4
+ 12917, // 5
+ 12940, // 6
+ 12963, // 7
+ /*12819*/ uint16(xCondIs64), 12822, 12838,
+ /*12822*/ uint16(xCondDataSize), 12826, 12832, 0,
+ /*12826*/ uint16(xSetOp), uint16(TEST),
+ /*12828*/ uint16(xReadIw),
+ /*12829*/ uint16(xArgRM16),
+ /*12830*/ uint16(xArgImm16),
+ /*12831*/ uint16(xMatch),
+ /*12832*/ uint16(xSetOp), uint16(TEST),
+ /*12834*/ uint16(xReadId),
+ /*12835*/ uint16(xArgRM32),
+ /*12836*/ uint16(xArgImm32),
+ /*12837*/ uint16(xMatch),
+ /*12838*/ uint16(xCondDataSize), 12826, 12832, 12842,
+ /*12842*/ uint16(xSetOp), uint16(TEST),
+ /*12844*/ uint16(xReadId),
+ /*12845*/ uint16(xArgRM64),
+ /*12846*/ uint16(xArgImm32),
+ /*12847*/ uint16(xMatch),
+ /*12848*/ uint16(xCondIs64), 12851, 12863,
+ /*12851*/ uint16(xCondDataSize), 12855, 12859, 0,
+ /*12855*/ uint16(xSetOp), uint16(NOT),
+ /*12857*/ uint16(xArgRM16),
+ /*12858*/ uint16(xMatch),
+ /*12859*/ uint16(xSetOp), uint16(NOT),
+ /*12861*/ uint16(xArgRM32),
+ /*12862*/ uint16(xMatch),
+ /*12863*/ uint16(xCondDataSize), 12855, 12859, 12867,
+ /*12867*/ uint16(xSetOp), uint16(NOT),
+ /*12869*/ uint16(xArgRM64),
+ /*12870*/ uint16(xMatch),
+ /*12871*/ uint16(xCondIs64), 12874, 12886,
+ /*12874*/ uint16(xCondDataSize), 12878, 12882, 0,
+ /*12878*/ uint16(xSetOp), uint16(NEG),
+ /*12880*/ uint16(xArgRM16),
+ /*12881*/ uint16(xMatch),
+ /*12882*/ uint16(xSetOp), uint16(NEG),
+ /*12884*/ uint16(xArgRM32),
+ /*12885*/ uint16(xMatch),
+ /*12886*/ uint16(xCondDataSize), 12878, 12882, 12890,
+ /*12890*/ uint16(xSetOp), uint16(NEG),
+ /*12892*/ uint16(xArgRM64),
+ /*12893*/ uint16(xMatch),
+ /*12894*/ uint16(xCondIs64), 12897, 12909,
+ /*12897*/ uint16(xCondDataSize), 12901, 12905, 0,
+ /*12901*/ uint16(xSetOp), uint16(MUL),
+ /*12903*/ uint16(xArgRM16),
+ /*12904*/ uint16(xMatch),
+ /*12905*/ uint16(xSetOp), uint16(MUL),
+ /*12907*/ uint16(xArgRM32),
+ /*12908*/ uint16(xMatch),
+ /*12909*/ uint16(xCondDataSize), 12901, 12905, 12913,
+ /*12913*/ uint16(xSetOp), uint16(MUL),
+ /*12915*/ uint16(xArgRM64),
+ /*12916*/ uint16(xMatch),
+ /*12917*/ uint16(xCondIs64), 12920, 12932,
+ /*12920*/ uint16(xCondDataSize), 12924, 12928, 0,
+ /*12924*/ uint16(xSetOp), uint16(IMUL),
+ /*12926*/ uint16(xArgRM16),
+ /*12927*/ uint16(xMatch),
+ /*12928*/ uint16(xSetOp), uint16(IMUL),
+ /*12930*/ uint16(xArgRM32),
+ /*12931*/ uint16(xMatch),
+ /*12932*/ uint16(xCondDataSize), 12924, 12928, 12936,
+ /*12936*/ uint16(xSetOp), uint16(IMUL),
+ /*12938*/ uint16(xArgRM64),
+ /*12939*/ uint16(xMatch),
+ /*12940*/ uint16(xCondIs64), 12943, 12955,
+ /*12943*/ uint16(xCondDataSize), 12947, 12951, 0,
+ /*12947*/ uint16(xSetOp), uint16(DIV),
+ /*12949*/ uint16(xArgRM16),
+ /*12950*/ uint16(xMatch),
+ /*12951*/ uint16(xSetOp), uint16(DIV),
+ /*12953*/ uint16(xArgRM32),
+ /*12954*/ uint16(xMatch),
+ /*12955*/ uint16(xCondDataSize), 12947, 12951, 12959,
+ /*12959*/ uint16(xSetOp), uint16(DIV),
+ /*12961*/ uint16(xArgRM64),
+ /*12962*/ uint16(xMatch),
+ /*12963*/ uint16(xCondIs64), 12966, 12978,
+ /*12966*/ uint16(xCondDataSize), 12970, 12974, 0,
+ /*12970*/ uint16(xSetOp), uint16(IDIV),
+ /*12972*/ uint16(xArgRM16),
+ /*12973*/ uint16(xMatch),
+ /*12974*/ uint16(xSetOp), uint16(IDIV),
+ /*12976*/ uint16(xArgRM32),
+ /*12977*/ uint16(xMatch),
+ /*12978*/ uint16(xCondDataSize), 12970, 12974, 12982,
+ /*12982*/ uint16(xSetOp), uint16(IDIV),
+ /*12984*/ uint16(xArgRM64),
+ /*12985*/ uint16(xMatch),
+ /*12986*/ uint16(xSetOp), uint16(CLC),
+ /*12988*/ uint16(xMatch),
+ /*12989*/ uint16(xSetOp), uint16(STC),
+ /*12991*/ uint16(xMatch),
+ /*12992*/ uint16(xSetOp), uint16(CLI),
+ /*12994*/ uint16(xMatch),
+ /*12995*/ uint16(xSetOp), uint16(STI),
+ /*12997*/ uint16(xMatch),
+ /*12998*/ uint16(xSetOp), uint16(CLD),
+ /*13000*/ uint16(xMatch),
+ /*13001*/ uint16(xSetOp), uint16(STD),
+ /*13003*/ uint16(xMatch),
+ /*13004*/ uint16(xCondSlashR),
+ 13013, // 0
+ 13017, // 1
+ 0, // 2
+ 0, // 3
+ 0, // 4
+ 0, // 5
+ 0, // 6
+ 0, // 7
+ /*13013*/ uint16(xSetOp), uint16(INC),
+ /*13015*/ uint16(xArgRM8),
+ /*13016*/ uint16(xMatch),
+ /*13017*/ uint16(xSetOp), uint16(DEC),
+ /*13019*/ uint16(xArgRM8),
+ /*13020*/ uint16(xMatch),
+ /*13021*/ uint16(xCondSlashR),
+ 13030, // 0
+ 13053, // 1
+ 13076, // 2
+ 13095, // 3
+ 13118, // 4
+ 13137, // 5
+ 13160, // 6
+ 0, // 7
+ /*13030*/ uint16(xCondIs64), 13033, 13045,
+ /*13033*/ uint16(xCondDataSize), 13037, 13041, 0,
+ /*13037*/ uint16(xSetOp), uint16(INC),
+ /*13039*/ uint16(xArgRM16),
+ /*13040*/ uint16(xMatch),
+ /*13041*/ uint16(xSetOp), uint16(INC),
+ /*13043*/ uint16(xArgRM32),
+ /*13044*/ uint16(xMatch),
+ /*13045*/ uint16(xCondDataSize), 13037, 13041, 13049,
+ /*13049*/ uint16(xSetOp), uint16(INC),
+ /*13051*/ uint16(xArgRM64),
+ /*13052*/ uint16(xMatch),
+ /*13053*/ uint16(xCondIs64), 13056, 13068,
+ /*13056*/ uint16(xCondDataSize), 13060, 13064, 0,
+ /*13060*/ uint16(xSetOp), uint16(DEC),
+ /*13062*/ uint16(xArgRM16),
+ /*13063*/ uint16(xMatch),
+ /*13064*/ uint16(xSetOp), uint16(DEC),
+ /*13066*/ uint16(xArgRM32),
+ /*13067*/ uint16(xMatch),
+ /*13068*/ uint16(xCondDataSize), 13060, 13064, 13072,
+ /*13072*/ uint16(xSetOp), uint16(DEC),
+ /*13074*/ uint16(xArgRM64),
+ /*13075*/ uint16(xMatch),
+ /*13076*/ uint16(xCondIs64), 13079, 13091,
+ /*13079*/ uint16(xCondDataSize), 13083, 13087, 0,
+ /*13083*/ uint16(xSetOp), uint16(CALL),
+ /*13085*/ uint16(xArgRM16),
+ /*13086*/ uint16(xMatch),
+ /*13087*/ uint16(xSetOp), uint16(CALL),
+ /*13089*/ uint16(xArgRM32),
+ /*13090*/ uint16(xMatch),
+ /*13091*/ uint16(xSetOp), uint16(CALL),
+ /*13093*/ uint16(xArgRM64),
+ /*13094*/ uint16(xMatch),
+ /*13095*/ uint16(xCondIs64), 13098, 13110,
+ /*13098*/ uint16(xCondDataSize), 13102, 13106, 0,
+ /*13102*/ uint16(xSetOp), uint16(LCALL),
+ /*13104*/ uint16(xArgM16colon16),
+ /*13105*/ uint16(xMatch),
+ /*13106*/ uint16(xSetOp), uint16(LCALL),
+ /*13108*/ uint16(xArgM16colon32),
+ /*13109*/ uint16(xMatch),
+ /*13110*/ uint16(xCondDataSize), 13102, 13106, 13114,
+ /*13114*/ uint16(xSetOp), uint16(LCALL),
+ /*13116*/ uint16(xArgM16colon64),
+ /*13117*/ uint16(xMatch),
+ /*13118*/ uint16(xCondIs64), 13121, 13133,
+ /*13121*/ uint16(xCondDataSize), 13125, 13129, 0,
+ /*13125*/ uint16(xSetOp), uint16(JMP),
+ /*13127*/ uint16(xArgRM16),
+ /*13128*/ uint16(xMatch),
+ /*13129*/ uint16(xSetOp), uint16(JMP),
+ /*13131*/ uint16(xArgRM32),
+ /*13132*/ uint16(xMatch),
+ /*13133*/ uint16(xSetOp), uint16(JMP),
+ /*13135*/ uint16(xArgRM64),
+ /*13136*/ uint16(xMatch),
+ /*13137*/ uint16(xCondIs64), 13140, 13152,
+ /*13140*/ uint16(xCondDataSize), 13144, 13148, 0,
+ /*13144*/ uint16(xSetOp), uint16(LJMP),
+ /*13146*/ uint16(xArgM16colon16),
+ /*13147*/ uint16(xMatch),
+ /*13148*/ uint16(xSetOp), uint16(LJMP),
+ /*13150*/ uint16(xArgM16colon32),
+ /*13151*/ uint16(xMatch),
+ /*13152*/ uint16(xCondDataSize), 13144, 13148, 13156,
+ /*13156*/ uint16(xSetOp), uint16(LJMP),
+ /*13158*/ uint16(xArgM16colon64),
+ /*13159*/ uint16(xMatch),
+ /*13160*/ uint16(xCondIs64), 13163, 13175,
+ /*13163*/ uint16(xCondDataSize), 13167, 13171, 0,
+ /*13167*/ uint16(xSetOp), uint16(PUSH),
+ /*13169*/ uint16(xArgRM16),
+ /*13170*/ uint16(xMatch),
+ /*13171*/ uint16(xSetOp), uint16(PUSH),
+ /*13173*/ uint16(xArgRM32),
+ /*13174*/ uint16(xMatch),
+ /*13175*/ uint16(xCondDataSize), 13167, 13179, 13183,
+ /*13179*/ uint16(xSetOp), uint16(PUSH),
+ /*13181*/ uint16(xArgRM64),
+ /*13182*/ uint16(xMatch),
+ /*13183*/ uint16(xSetOp), uint16(PUSH),
+ /*13185*/ uint16(xArgRM64),
+ /*13186*/ uint16(xMatch),
+}
+
+const (
+ _ Op = iota
+
+ AAA
+ AAD
+ AAM
+ AAS
+ ADC
+ ADD
+ ADDPD
+ ADDPS
+ ADDSD
+ ADDSS
+ ADDSUBPD
+ ADDSUBPS
+ AESDEC
+ AESDECLAST
+ AESENC
+ AESENCLAST
+ AESIMC
+ AESKEYGENASSIST
+ AND
+ ANDNPD
+ ANDNPS
+ ANDPD
+ ANDPS
+ ARPL
+ BLENDPD
+ BLENDPS
+ BLENDVPD
+ BLENDVPS
+ BOUND
+ BSF
+ BSR
+ BSWAP
+ BT
+ BTC
+ BTR
+ BTS
+ CALL
+ CBW
+ CDQ
+ CDQE
+ CLC
+ CLD
+ CLFLUSH
+ CLI
+ CLTS
+ CMC
+ CMOVA
+ CMOVAE
+ CMOVB
+ CMOVBE
+ CMOVE
+ CMOVG
+ CMOVGE
+ CMOVL
+ CMOVLE
+ CMOVNE
+ CMOVNO
+ CMOVNP
+ CMOVNS
+ CMOVO
+ CMOVP
+ CMOVS
+ CMP
+ CMPPD
+ CMPPS
+ CMPSB
+ CMPSD
+ CMPSD_XMM
+ CMPSQ
+ CMPSS
+ CMPSW
+ CMPXCHG
+ CMPXCHG16B
+ CMPXCHG8B
+ COMISD
+ COMISS
+ CPUID
+ CQO
+ CRC32
+ CVTDQ2PD
+ CVTDQ2PS
+ CVTPD2DQ
+ CVTPD2PI
+ CVTPD2PS
+ CVTPI2PD
+ CVTPI2PS
+ CVTPS2DQ
+ CVTPS2PD
+ CVTPS2PI
+ CVTSD2SI
+ CVTSD2SS
+ CVTSI2SD
+ CVTSI2SS
+ CVTSS2SD
+ CVTSS2SI
+ CVTTPD2DQ
+ CVTTPD2PI
+ CVTTPS2DQ
+ CVTTPS2PI
+ CVTTSD2SI
+ CVTTSS2SI
+ CWD
+ CWDE
+ DAA
+ DAS
+ DEC
+ DIV
+ DIVPD
+ DIVPS
+ DIVSD
+ DIVSS
+ DPPD
+ DPPS
+ EMMS
+ ENTER
+ EXTRACTPS
+ F2XM1
+ FABS
+ FADD
+ FADDP
+ FBLD
+ FBSTP
+ FCHS
+ FCMOVB
+ FCMOVBE
+ FCMOVE
+ FCMOVNB
+ FCMOVNBE
+ FCMOVNE
+ FCMOVNU
+ FCMOVU
+ FCOM
+ FCOMI
+ FCOMIP
+ FCOMP
+ FCOMPP
+ FCOS
+ FDECSTP
+ FDIV
+ FDIVP
+ FDIVR
+ FDIVRP
+ FFREE
+ FFREEP
+ FIADD
+ FICOM
+ FICOMP
+ FIDIV
+ FIDIVR
+ FILD
+ FIMUL
+ FINCSTP
+ FIST
+ FISTP
+ FISTTP
+ FISUB
+ FISUBR
+ FLD
+ FLD1
+ FLDCW
+ FLDENV
+ FLDL2E
+ FLDL2T
+ FLDLG2
+ FLDPI
+ FMUL
+ FMULP
+ FNCLEX
+ FNINIT
+ FNOP
+ FNSAVE
+ FNSTCW
+ FNSTENV
+ FNSTSW
+ FPATAN
+ FPREM
+ FPREM1
+ FPTAN
+ FRNDINT
+ FRSTOR
+ FSCALE
+ FSIN
+ FSINCOS
+ FSQRT
+ FST
+ FSTP
+ FSUB
+ FSUBP
+ FSUBR
+ FSUBRP
+ FTST
+ FUCOM
+ FUCOMI
+ FUCOMIP
+ FUCOMP
+ FUCOMPP
+ FWAIT
+ FXAM
+ FXCH
+ FXRSTOR
+ FXRSTOR64
+ FXSAVE
+ FXSAVE64
+ FXTRACT
+ FYL2X
+ FYL2XP1
+ HADDPD
+ HADDPS
+ HLT
+ HSUBPD
+ HSUBPS
+ ICEBP
+ IDIV
+ IMUL
+ IN
+ INC
+ INSB
+ INSD
+ INSERTPS
+ INSW
+ INT
+ INTO
+ INVD
+ INVLPG
+ INVPCID
+ IRET
+ IRETD
+ IRETQ
+ JA
+ JAE
+ JB
+ JBE
+ JCXZ
+ JE
+ JECXZ
+ JG
+ JGE
+ JL
+ JLE
+ JMP
+ JNE
+ JNO
+ JNP
+ JNS
+ JO
+ JP
+ JRCXZ
+ JS
+ LAHF
+ LAR
+ LCALL
+ LDDQU
+ LDMXCSR
+ LDS
+ LEA
+ LEAVE
+ LES
+ LFENCE
+ LFS
+ LGDT
+ LGS
+ LIDT
+ LJMP
+ LLDT
+ LMSW
+ LODSB
+ LODSD
+ LODSQ
+ LODSW
+ LOOP
+ LOOPE
+ LOOPNE
+ LRET
+ LSL
+ LSS
+ LTR
+ LZCNT
+ MASKMOVDQU
+ MASKMOVQ
+ MAXPD
+ MAXPS
+ MAXSD
+ MAXSS
+ MFENCE
+ MINPD
+ MINPS
+ MINSD
+ MINSS
+ MONITOR
+ MOV
+ MOVAPD
+ MOVAPS
+ MOVBE
+ MOVD
+ MOVDDUP
+ MOVDQ2Q
+ MOVDQA
+ MOVDQU
+ MOVHLPS
+ MOVHPD
+ MOVHPS
+ MOVLHPS
+ MOVLPD
+ MOVLPS
+ MOVMSKPD
+ MOVMSKPS
+ MOVNTDQ
+ MOVNTDQA
+ MOVNTI
+ MOVNTPD
+ MOVNTPS
+ MOVNTQ
+ MOVNTSD
+ MOVNTSS
+ MOVQ
+ MOVQ2DQ
+ MOVSB
+ MOVSD
+ MOVSD_XMM
+ MOVSHDUP
+ MOVSLDUP
+ MOVSQ
+ MOVSS
+ MOVSW
+ MOVSX
+ MOVSXD
+ MOVUPD
+ MOVUPS
+ MOVZX
+ MPSADBW
+ MUL
+ MULPD
+ MULPS
+ MULSD
+ MULSS
+ MWAIT
+ NEG
+ NOP
+ NOT
+ OR
+ ORPD
+ ORPS
+ OUT
+ OUTSB
+ OUTSD
+ OUTSW
+ PABSB
+ PABSD
+ PABSW
+ PACKSSDW
+ PACKSSWB
+ PACKUSDW
+ PACKUSWB
+ PADDB
+ PADDD
+ PADDQ
+ PADDSB
+ PADDSW
+ PADDUSB
+ PADDUSW
+ PADDW
+ PALIGNR
+ PAND
+ PANDN
+ PAUSE
+ PAVGB
+ PAVGW
+ PBLENDVB
+ PBLENDW
+ PCLMULQDQ
+ PCMPEQB
+ PCMPEQD
+ PCMPEQQ
+ PCMPEQW
+ PCMPESTRI
+ PCMPESTRM
+ PCMPGTB
+ PCMPGTD
+ PCMPGTQ
+ PCMPGTW
+ PCMPISTRI
+ PCMPISTRM
+ PEXTRB
+ PEXTRD
+ PEXTRQ
+ PEXTRW
+ PHADDD
+ PHADDSW
+ PHADDW
+ PHMINPOSUW
+ PHSUBD
+ PHSUBSW
+ PHSUBW
+ PINSRB
+ PINSRD
+ PINSRQ
+ PINSRW
+ PMADDUBSW
+ PMADDWD
+ PMAXSB
+ PMAXSD
+ PMAXSW
+ PMAXUB
+ PMAXUD
+ PMAXUW
+ PMINSB
+ PMINSD
+ PMINSW
+ PMINUB
+ PMINUD
+ PMINUW
+ PMOVMSKB
+ PMOVSXBD
+ PMOVSXBQ
+ PMOVSXBW
+ PMOVSXDQ
+ PMOVSXWD
+ PMOVSXWQ
+ PMOVZXBD
+ PMOVZXBQ
+ PMOVZXBW
+ PMOVZXDQ
+ PMOVZXWD
+ PMOVZXWQ
+ PMULDQ
+ PMULHRSW
+ PMULHUW
+ PMULHW
+ PMULLD
+ PMULLW
+ PMULUDQ
+ POP
+ POPA
+ POPAD
+ POPCNT
+ POPF
+ POPFD
+ POPFQ
+ POR
+ PREFETCHNTA
+ PREFETCHT0
+ PREFETCHT1
+ PREFETCHT2
+ PREFETCHW
+ PSADBW
+ PSHUFB
+ PSHUFD
+ PSHUFHW
+ PSHUFLW
+ PSHUFW
+ PSIGNB
+ PSIGND
+ PSIGNW
+ PSLLD
+ PSLLDQ
+ PSLLQ
+ PSLLW
+ PSRAD
+ PSRAW
+ PSRLD
+ PSRLDQ
+ PSRLQ
+ PSRLW
+ PSUBB
+ PSUBD
+ PSUBQ
+ PSUBSB
+ PSUBSW
+ PSUBUSB
+ PSUBUSW
+ PSUBW
+ PTEST
+ PUNPCKHBW
+ PUNPCKHDQ
+ PUNPCKHQDQ
+ PUNPCKHWD
+ PUNPCKLBW
+ PUNPCKLDQ
+ PUNPCKLQDQ
+ PUNPCKLWD
+ PUSH
+ PUSHA
+ PUSHAD
+ PUSHF
+ PUSHFD
+ PUSHFQ
+ PXOR
+ RCL
+ RCPPS
+ RCPSS
+ RCR
+ RDFSBASE
+ RDGSBASE
+ RDMSR
+ RDPMC
+ RDRAND
+ RDTSC
+ RDTSCP
+ RET
+ ROL
+ ROR
+ ROUNDPD
+ ROUNDPS
+ ROUNDSD
+ ROUNDSS
+ RSM
+ RSQRTPS
+ RSQRTSS
+ SAHF
+ SAR
+ SBB
+ SCASB
+ SCASD
+ SCASQ
+ SCASW
+ SETA
+ SETAE
+ SETB
+ SETBE
+ SETE
+ SETG
+ SETGE
+ SETL
+ SETLE
+ SETNE
+ SETNO
+ SETNP
+ SETNS
+ SETO
+ SETP
+ SETS
+ SFENCE
+ SGDT
+ SHL
+ SHLD
+ SHR
+ SHRD
+ SHUFPD
+ SHUFPS
+ SIDT
+ SLDT
+ SMSW
+ SQRTPD
+ SQRTPS
+ SQRTSD
+ SQRTSS
+ STC
+ STD
+ STI
+ STMXCSR
+ STOSB
+ STOSD
+ STOSQ
+ STOSW
+ STR
+ SUB
+ SUBPD
+ SUBPS
+ SUBSD
+ SUBSS
+ SWAPGS
+ SYSCALL
+ SYSENTER
+ SYSEXIT
+ SYSRET
+ TEST
+ TZCNT
+ UCOMISD
+ UCOMISS
+ UD1
+ UD2
+ UNPCKHPD
+ UNPCKHPS
+ UNPCKLPD
+ UNPCKLPS
+ VERR
+ VERW
+ WBINVD
+ WRFSBASE
+ WRGSBASE
+ WRMSR
+ XABORT
+ XADD
+ XBEGIN
+ XCHG
+ XEND
+ XGETBV
+ XLATB
+ XOR
+ XORPD
+ XORPS
+ XRSTOR
+ XRSTOR64
+ XRSTORS
+ XRSTORS64
+ XSAVE
+ XSAVE64
+ XSAVEC
+ XSAVEC64
+ XSAVEOPT
+ XSAVEOPT64
+ XSAVES
+ XSAVES64
+ XSETBV
+ XTEST
+)
+
+const maxOp = XTEST
+
+var opNames = [...]string{
+ AAA: "AAA",
+ AAD: "AAD",
+ AAM: "AAM",
+ AAS: "AAS",
+ ADC: "ADC",
+ ADD: "ADD",
+ ADDPD: "ADDPD",
+ ADDPS: "ADDPS",
+ ADDSD: "ADDSD",
+ ADDSS: "ADDSS",
+ ADDSUBPD: "ADDSUBPD",
+ ADDSUBPS: "ADDSUBPS",
+ AESDEC: "AESDEC",
+ AESDECLAST: "AESDECLAST",
+ AESENC: "AESENC",
+ AESENCLAST: "AESENCLAST",
+ AESIMC: "AESIMC",
+ AESKEYGENASSIST: "AESKEYGENASSIST",
+ AND: "AND",
+ ANDNPD: "ANDNPD",
+ ANDNPS: "ANDNPS",
+ ANDPD: "ANDPD",
+ ANDPS: "ANDPS",
+ ARPL: "ARPL",
+ BLENDPD: "BLENDPD",
+ BLENDPS: "BLENDPS",
+ BLENDVPD: "BLENDVPD",
+ BLENDVPS: "BLENDVPS",
+ BOUND: "BOUND",
+ BSF: "BSF",
+ BSR: "BSR",
+ BSWAP: "BSWAP",
+ BT: "BT",
+ BTC: "BTC",
+ BTR: "BTR",
+ BTS: "BTS",
+ CALL: "CALL",
+ CBW: "CBW",
+ CDQ: "CDQ",
+ CDQE: "CDQE",
+ CLC: "CLC",
+ CLD: "CLD",
+ CLFLUSH: "CLFLUSH",
+ CLI: "CLI",
+ CLTS: "CLTS",
+ CMC: "CMC",
+ CMOVA: "CMOVA",
+ CMOVAE: "CMOVAE",
+ CMOVB: "CMOVB",
+ CMOVBE: "CMOVBE",
+ CMOVE: "CMOVE",
+ CMOVG: "CMOVG",
+ CMOVGE: "CMOVGE",
+ CMOVL: "CMOVL",
+ CMOVLE: "CMOVLE",
+ CMOVNE: "CMOVNE",
+ CMOVNO: "CMOVNO",
+ CMOVNP: "CMOVNP",
+ CMOVNS: "CMOVNS",
+ CMOVO: "CMOVO",
+ CMOVP: "CMOVP",
+ CMOVS: "CMOVS",
+ CMP: "CMP",
+ CMPPD: "CMPPD",
+ CMPPS: "CMPPS",
+ CMPSB: "CMPSB",
+ CMPSD: "CMPSD",
+ CMPSD_XMM: "CMPSD_XMM",
+ CMPSQ: "CMPSQ",
+ CMPSS: "CMPSS",
+ CMPSW: "CMPSW",
+ CMPXCHG: "CMPXCHG",
+ CMPXCHG16B: "CMPXCHG16B",
+ CMPXCHG8B: "CMPXCHG8B",
+ COMISD: "COMISD",
+ COMISS: "COMISS",
+ CPUID: "CPUID",
+ CQO: "CQO",
+ CRC32: "CRC32",
+ CVTDQ2PD: "CVTDQ2PD",
+ CVTDQ2PS: "CVTDQ2PS",
+ CVTPD2DQ: "CVTPD2DQ",
+ CVTPD2PI: "CVTPD2PI",
+ CVTPD2PS: "CVTPD2PS",
+ CVTPI2PD: "CVTPI2PD",
+ CVTPI2PS: "CVTPI2PS",
+ CVTPS2DQ: "CVTPS2DQ",
+ CVTPS2PD: "CVTPS2PD",
+ CVTPS2PI: "CVTPS2PI",
+ CVTSD2SI: "CVTSD2SI",
+ CVTSD2SS: "CVTSD2SS",
+ CVTSI2SD: "CVTSI2SD",
+ CVTSI2SS: "CVTSI2SS",
+ CVTSS2SD: "CVTSS2SD",
+ CVTSS2SI: "CVTSS2SI",
+ CVTTPD2DQ: "CVTTPD2DQ",
+ CVTTPD2PI: "CVTTPD2PI",
+ CVTTPS2DQ: "CVTTPS2DQ",
+ CVTTPS2PI: "CVTTPS2PI",
+ CVTTSD2SI: "CVTTSD2SI",
+ CVTTSS2SI: "CVTTSS2SI",
+ CWD: "CWD",
+ CWDE: "CWDE",
+ DAA: "DAA",
+ DAS: "DAS",
+ DEC: "DEC",
+ DIV: "DIV",
+ DIVPD: "DIVPD",
+ DIVPS: "DIVPS",
+ DIVSD: "DIVSD",
+ DIVSS: "DIVSS",
+ DPPD: "DPPD",
+ DPPS: "DPPS",
+ EMMS: "EMMS",
+ ENTER: "ENTER",
+ EXTRACTPS: "EXTRACTPS",
+ F2XM1: "F2XM1",
+ FABS: "FABS",
+ FADD: "FADD",
+ FADDP: "FADDP",
+ FBLD: "FBLD",
+ FBSTP: "FBSTP",
+ FCHS: "FCHS",
+ FCMOVB: "FCMOVB",
+ FCMOVBE: "FCMOVBE",
+ FCMOVE: "FCMOVE",
+ FCMOVNB: "FCMOVNB",
+ FCMOVNBE: "FCMOVNBE",
+ FCMOVNE: "FCMOVNE",
+ FCMOVNU: "FCMOVNU",
+ FCMOVU: "FCMOVU",
+ FCOM: "FCOM",
+ FCOMI: "FCOMI",
+ FCOMIP: "FCOMIP",
+ FCOMP: "FCOMP",
+ FCOMPP: "FCOMPP",
+ FCOS: "FCOS",
+ FDECSTP: "FDECSTP",
+ FDIV: "FDIV",
+ FDIVP: "FDIVP",
+ FDIVR: "FDIVR",
+ FDIVRP: "FDIVRP",
+ FFREE: "FFREE",
+ FFREEP: "FFREEP",
+ FIADD: "FIADD",
+ FICOM: "FICOM",
+ FICOMP: "FICOMP",
+ FIDIV: "FIDIV",
+ FIDIVR: "FIDIVR",
+ FILD: "FILD",
+ FIMUL: "FIMUL",
+ FINCSTP: "FINCSTP",
+ FIST: "FIST",
+ FISTP: "FISTP",
+ FISTTP: "FISTTP",
+ FISUB: "FISUB",
+ FISUBR: "FISUBR",
+ FLD: "FLD",
+ FLD1: "FLD1",
+ FLDCW: "FLDCW",
+ FLDENV: "FLDENV",
+ FLDL2E: "FLDL2E",
+ FLDL2T: "FLDL2T",
+ FLDLG2: "FLDLG2",
+ FLDPI: "FLDPI",
+ FMUL: "FMUL",
+ FMULP: "FMULP",
+ FNCLEX: "FNCLEX",
+ FNINIT: "FNINIT",
+ FNOP: "FNOP",
+ FNSAVE: "FNSAVE",
+ FNSTCW: "FNSTCW",
+ FNSTENV: "FNSTENV",
+ FNSTSW: "FNSTSW",
+ FPATAN: "FPATAN",
+ FPREM: "FPREM",
+ FPREM1: "FPREM1",
+ FPTAN: "FPTAN",
+ FRNDINT: "FRNDINT",
+ FRSTOR: "FRSTOR",
+ FSCALE: "FSCALE",
+ FSIN: "FSIN",
+ FSINCOS: "FSINCOS",
+ FSQRT: "FSQRT",
+ FST: "FST",
+ FSTP: "FSTP",
+ FSUB: "FSUB",
+ FSUBP: "FSUBP",
+ FSUBR: "FSUBR",
+ FSUBRP: "FSUBRP",
+ FTST: "FTST",
+ FUCOM: "FUCOM",
+ FUCOMI: "FUCOMI",
+ FUCOMIP: "FUCOMIP",
+ FUCOMP: "FUCOMP",
+ FUCOMPP: "FUCOMPP",
+ FWAIT: "FWAIT",
+ FXAM: "FXAM",
+ FXCH: "FXCH",
+ FXRSTOR: "FXRSTOR",
+ FXRSTOR64: "FXRSTOR64",
+ FXSAVE: "FXSAVE",
+ FXSAVE64: "FXSAVE64",
+ FXTRACT: "FXTRACT",
+ FYL2X: "FYL2X",
+ FYL2XP1: "FYL2XP1",
+ HADDPD: "HADDPD",
+ HADDPS: "HADDPS",
+ HLT: "HLT",
+ HSUBPD: "HSUBPD",
+ HSUBPS: "HSUBPS",
+ ICEBP: "ICEBP",
+ IDIV: "IDIV",
+ IMUL: "IMUL",
+ IN: "IN",
+ INC: "INC",
+ INSB: "INSB",
+ INSD: "INSD",
+ INSERTPS: "INSERTPS",
+ INSW: "INSW",
+ INT: "INT",
+ INTO: "INTO",
+ INVD: "INVD",
+ INVLPG: "INVLPG",
+ INVPCID: "INVPCID",
+ IRET: "IRET",
+ IRETD: "IRETD",
+ IRETQ: "IRETQ",
+ JA: "JA",
+ JAE: "JAE",
+ JB: "JB",
+ JBE: "JBE",
+ JCXZ: "JCXZ",
+ JE: "JE",
+ JECXZ: "JECXZ",
+ JG: "JG",
+ JGE: "JGE",
+ JL: "JL",
+ JLE: "JLE",
+ JMP: "JMP",
+ JNE: "JNE",
+ JNO: "JNO",
+ JNP: "JNP",
+ JNS: "JNS",
+ JO: "JO",
+ JP: "JP",
+ JRCXZ: "JRCXZ",
+ JS: "JS",
+ LAHF: "LAHF",
+ LAR: "LAR",
+ LCALL: "LCALL",
+ LDDQU: "LDDQU",
+ LDMXCSR: "LDMXCSR",
+ LDS: "LDS",
+ LEA: "LEA",
+ LEAVE: "LEAVE",
+ LES: "LES",
+ LFENCE: "LFENCE",
+ LFS: "LFS",
+ LGDT: "LGDT",
+ LGS: "LGS",
+ LIDT: "LIDT",
+ LJMP: "LJMP",
+ LLDT: "LLDT",
+ LMSW: "LMSW",
+ LODSB: "LODSB",
+ LODSD: "LODSD",
+ LODSQ: "LODSQ",
+ LODSW: "LODSW",
+ LOOP: "LOOP",
+ LOOPE: "LOOPE",
+ LOOPNE: "LOOPNE",
+ LRET: "LRET",
+ LSL: "LSL",
+ LSS: "LSS",
+ LTR: "LTR",
+ LZCNT: "LZCNT",
+ MASKMOVDQU: "MASKMOVDQU",
+ MASKMOVQ: "MASKMOVQ",
+ MAXPD: "MAXPD",
+ MAXPS: "MAXPS",
+ MAXSD: "MAXSD",
+ MAXSS: "MAXSS",
+ MFENCE: "MFENCE",
+ MINPD: "MINPD",
+ MINPS: "MINPS",
+ MINSD: "MINSD",
+ MINSS: "MINSS",
+ MONITOR: "MONITOR",
+ MOV: "MOV",
+ MOVAPD: "MOVAPD",
+ MOVAPS: "MOVAPS",
+ MOVBE: "MOVBE",
+ MOVD: "MOVD",
+ MOVDDUP: "MOVDDUP",
+ MOVDQ2Q: "MOVDQ2Q",
+ MOVDQA: "MOVDQA",
+ MOVDQU: "MOVDQU",
+ MOVHLPS: "MOVHLPS",
+ MOVHPD: "MOVHPD",
+ MOVHPS: "MOVHPS",
+ MOVLHPS: "MOVLHPS",
+ MOVLPD: "MOVLPD",
+ MOVLPS: "MOVLPS",
+ MOVMSKPD: "MOVMSKPD",
+ MOVMSKPS: "MOVMSKPS",
+ MOVNTDQ: "MOVNTDQ",
+ MOVNTDQA: "MOVNTDQA",
+ MOVNTI: "MOVNTI",
+ MOVNTPD: "MOVNTPD",
+ MOVNTPS: "MOVNTPS",
+ MOVNTQ: "MOVNTQ",
+ MOVNTSD: "MOVNTSD",
+ MOVNTSS: "MOVNTSS",
+ MOVQ: "MOVQ",
+ MOVQ2DQ: "MOVQ2DQ",
+ MOVSB: "MOVSB",
+ MOVSD: "MOVSD",
+ MOVSD_XMM: "MOVSD_XMM",
+ MOVSHDUP: "MOVSHDUP",
+ MOVSLDUP: "MOVSLDUP",
+ MOVSQ: "MOVSQ",
+ MOVSS: "MOVSS",
+ MOVSW: "MOVSW",
+ MOVSX: "MOVSX",
+ MOVSXD: "MOVSXD",
+ MOVUPD: "MOVUPD",
+ MOVUPS: "MOVUPS",
+ MOVZX: "MOVZX",
+ MPSADBW: "MPSADBW",
+ MUL: "MUL",
+ MULPD: "MULPD",
+ MULPS: "MULPS",
+ MULSD: "MULSD",
+ MULSS: "MULSS",
+ MWAIT: "MWAIT",
+ NEG: "NEG",
+ NOP: "NOP",
+ NOT: "NOT",
+ OR: "OR",
+ ORPD: "ORPD",
+ ORPS: "ORPS",
+ OUT: "OUT",
+ OUTSB: "OUTSB",
+ OUTSD: "OUTSD",
+ OUTSW: "OUTSW",
+ PABSB: "PABSB",
+ PABSD: "PABSD",
+ PABSW: "PABSW",
+ PACKSSDW: "PACKSSDW",
+ PACKSSWB: "PACKSSWB",
+ PACKUSDW: "PACKUSDW",
+ PACKUSWB: "PACKUSWB",
+ PADDB: "PADDB",
+ PADDD: "PADDD",
+ PADDQ: "PADDQ",
+ PADDSB: "PADDSB",
+ PADDSW: "PADDSW",
+ PADDUSB: "PADDUSB",
+ PADDUSW: "PADDUSW",
+ PADDW: "PADDW",
+ PALIGNR: "PALIGNR",
+ PAND: "PAND",
+ PANDN: "PANDN",
+ PAUSE: "PAUSE",
+ PAVGB: "PAVGB",
+ PAVGW: "PAVGW",
+ PBLENDVB: "PBLENDVB",
+ PBLENDW: "PBLENDW",
+ PCLMULQDQ: "PCLMULQDQ",
+ PCMPEQB: "PCMPEQB",
+ PCMPEQD: "PCMPEQD",
+ PCMPEQQ: "PCMPEQQ",
+ PCMPEQW: "PCMPEQW",
+ PCMPESTRI: "PCMPESTRI",
+ PCMPESTRM: "PCMPESTRM",
+ PCMPGTB: "PCMPGTB",
+ PCMPGTD: "PCMPGTD",
+ PCMPGTQ: "PCMPGTQ",
+ PCMPGTW: "PCMPGTW",
+ PCMPISTRI: "PCMPISTRI",
+ PCMPISTRM: "PCMPISTRM",
+ PEXTRB: "PEXTRB",
+ PEXTRD: "PEXTRD",
+ PEXTRQ: "PEXTRQ",
+ PEXTRW: "PEXTRW",
+ PHADDD: "PHADDD",
+ PHADDSW: "PHADDSW",
+ PHADDW: "PHADDW",
+ PHMINPOSUW: "PHMINPOSUW",
+ PHSUBD: "PHSUBD",
+ PHSUBSW: "PHSUBSW",
+ PHSUBW: "PHSUBW",
+ PINSRB: "PINSRB",
+ PINSRD: "PINSRD",
+ PINSRQ: "PINSRQ",
+ PINSRW: "PINSRW",
+ PMADDUBSW: "PMADDUBSW",
+ PMADDWD: "PMADDWD",
+ PMAXSB: "PMAXSB",
+ PMAXSD: "PMAXSD",
+ PMAXSW: "PMAXSW",
+ PMAXUB: "PMAXUB",
+ PMAXUD: "PMAXUD",
+ PMAXUW: "PMAXUW",
+ PMINSB: "PMINSB",
+ PMINSD: "PMINSD",
+ PMINSW: "PMINSW",
+ PMINUB: "PMINUB",
+ PMINUD: "PMINUD",
+ PMINUW: "PMINUW",
+ PMOVMSKB: "PMOVMSKB",
+ PMOVSXBD: "PMOVSXBD",
+ PMOVSXBQ: "PMOVSXBQ",
+ PMOVSXBW: "PMOVSXBW",
+ PMOVSXDQ: "PMOVSXDQ",
+ PMOVSXWD: "PMOVSXWD",
+ PMOVSXWQ: "PMOVSXWQ",
+ PMOVZXBD: "PMOVZXBD",
+ PMOVZXBQ: "PMOVZXBQ",
+ PMOVZXBW: "PMOVZXBW",
+ PMOVZXDQ: "PMOVZXDQ",
+ PMOVZXWD: "PMOVZXWD",
+ PMOVZXWQ: "PMOVZXWQ",
+ PMULDQ: "PMULDQ",
+ PMULHRSW: "PMULHRSW",
+ PMULHUW: "PMULHUW",
+ PMULHW: "PMULHW",
+ PMULLD: "PMULLD",
+ PMULLW: "PMULLW",
+ PMULUDQ: "PMULUDQ",
+ POP: "POP",
+ POPA: "POPA",
+ POPAD: "POPAD",
+ POPCNT: "POPCNT",
+ POPF: "POPF",
+ POPFD: "POPFD",
+ POPFQ: "POPFQ",
+ POR: "POR",
+ PREFETCHNTA: "PREFETCHNTA",
+ PREFETCHT0: "PREFETCHT0",
+ PREFETCHT1: "PREFETCHT1",
+ PREFETCHT2: "PREFETCHT2",
+ PREFETCHW: "PREFETCHW",
+ PSADBW: "PSADBW",
+ PSHUFB: "PSHUFB",
+ PSHUFD: "PSHUFD",
+ PSHUFHW: "PSHUFHW",
+ PSHUFLW: "PSHUFLW",
+ PSHUFW: "PSHUFW",
+ PSIGNB: "PSIGNB",
+ PSIGND: "PSIGND",
+ PSIGNW: "PSIGNW",
+ PSLLD: "PSLLD",
+ PSLLDQ: "PSLLDQ",
+ PSLLQ: "PSLLQ",
+ PSLLW: "PSLLW",
+ PSRAD: "PSRAD",
+ PSRAW: "PSRAW",
+ PSRLD: "PSRLD",
+ PSRLDQ: "PSRLDQ",
+ PSRLQ: "PSRLQ",
+ PSRLW: "PSRLW",
+ PSUBB: "PSUBB",
+ PSUBD: "PSUBD",
+ PSUBQ: "PSUBQ",
+ PSUBSB: "PSUBSB",
+ PSUBSW: "PSUBSW",
+ PSUBUSB: "PSUBUSB",
+ PSUBUSW: "PSUBUSW",
+ PSUBW: "PSUBW",
+ PTEST: "PTEST",
+ PUNPCKHBW: "PUNPCKHBW",
+ PUNPCKHDQ: "PUNPCKHDQ",
+ PUNPCKHQDQ: "PUNPCKHQDQ",
+ PUNPCKHWD: "PUNPCKHWD",
+ PUNPCKLBW: "PUNPCKLBW",
+ PUNPCKLDQ: "PUNPCKLDQ",
+ PUNPCKLQDQ: "PUNPCKLQDQ",
+ PUNPCKLWD: "PUNPCKLWD",
+ PUSH: "PUSH",
+ PUSHA: "PUSHA",
+ PUSHAD: "PUSHAD",
+ PUSHF: "PUSHF",
+ PUSHFD: "PUSHFD",
+ PUSHFQ: "PUSHFQ",
+ PXOR: "PXOR",
+ RCL: "RCL",
+ RCPPS: "RCPPS",
+ RCPSS: "RCPSS",
+ RCR: "RCR",
+ RDFSBASE: "RDFSBASE",
+ RDGSBASE: "RDGSBASE",
+ RDMSR: "RDMSR",
+ RDPMC: "RDPMC",
+ RDRAND: "RDRAND",
+ RDTSC: "RDTSC",
+ RDTSCP: "RDTSCP",
+ RET: "RET",
+ ROL: "ROL",
+ ROR: "ROR",
+ ROUNDPD: "ROUNDPD",
+ ROUNDPS: "ROUNDPS",
+ ROUNDSD: "ROUNDSD",
+ ROUNDSS: "ROUNDSS",
+ RSM: "RSM",
+ RSQRTPS: "RSQRTPS",
+ RSQRTSS: "RSQRTSS",
+ SAHF: "SAHF",
+ SAR: "SAR",
+ SBB: "SBB",
+ SCASB: "SCASB",
+ SCASD: "SCASD",
+ SCASQ: "SCASQ",
+ SCASW: "SCASW",
+ SETA: "SETA",
+ SETAE: "SETAE",
+ SETB: "SETB",
+ SETBE: "SETBE",
+ SETE: "SETE",
+ SETG: "SETG",
+ SETGE: "SETGE",
+ SETL: "SETL",
+ SETLE: "SETLE",
+ SETNE: "SETNE",
+ SETNO: "SETNO",
+ SETNP: "SETNP",
+ SETNS: "SETNS",
+ SETO: "SETO",
+ SETP: "SETP",
+ SETS: "SETS",
+ SFENCE: "SFENCE",
+ SGDT: "SGDT",
+ SHL: "SHL",
+ SHLD: "SHLD",
+ SHR: "SHR",
+ SHRD: "SHRD",
+ SHUFPD: "SHUFPD",
+ SHUFPS: "SHUFPS",
+ SIDT: "SIDT",
+ SLDT: "SLDT",
+ SMSW: "SMSW",
+ SQRTPD: "SQRTPD",
+ SQRTPS: "SQRTPS",
+ SQRTSD: "SQRTSD",
+ SQRTSS: "SQRTSS",
+ STC: "STC",
+ STD: "STD",
+ STI: "STI",
+ STMXCSR: "STMXCSR",
+ STOSB: "STOSB",
+ STOSD: "STOSD",
+ STOSQ: "STOSQ",
+ STOSW: "STOSW",
+ STR: "STR",
+ SUB: "SUB",
+ SUBPD: "SUBPD",
+ SUBPS: "SUBPS",
+ SUBSD: "SUBSD",
+ SUBSS: "SUBSS",
+ SWAPGS: "SWAPGS",
+ SYSCALL: "SYSCALL",
+ SYSENTER: "SYSENTER",
+ SYSEXIT: "SYSEXIT",
+ SYSRET: "SYSRET",
+ TEST: "TEST",
+ TZCNT: "TZCNT",
+ UCOMISD: "UCOMISD",
+ UCOMISS: "UCOMISS",
+ UD1: "UD1",
+ UD2: "UD2",
+ UNPCKHPD: "UNPCKHPD",
+ UNPCKHPS: "UNPCKHPS",
+ UNPCKLPD: "UNPCKLPD",
+ UNPCKLPS: "UNPCKLPS",
+ VERR: "VERR",
+ VERW: "VERW",
+ WBINVD: "WBINVD",
+ WRFSBASE: "WRFSBASE",
+ WRGSBASE: "WRGSBASE",
+ WRMSR: "WRMSR",
+ XABORT: "XABORT",
+ XADD: "XADD",
+ XBEGIN: "XBEGIN",
+ XCHG: "XCHG",
+ XEND: "XEND",
+ XGETBV: "XGETBV",
+ XLATB: "XLATB",
+ XOR: "XOR",
+ XORPD: "XORPD",
+ XORPS: "XORPS",
+ XRSTOR: "XRSTOR",
+ XRSTOR64: "XRSTOR64",
+ XRSTORS: "XRSTORS",
+ XRSTORS64: "XRSTORS64",
+ XSAVE: "XSAVE",
+ XSAVE64: "XSAVE64",
+ XSAVEC: "XSAVEC",
+ XSAVEC64: "XSAVEC64",
+ XSAVEOPT: "XSAVEOPT",
+ XSAVEOPT64: "XSAVEOPT64",
+ XSAVES: "XSAVES",
+ XSAVES64: "XSAVES64",
+ XSETBV: "XSETBV",
+ XTEST: "XTEST",
+}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/testdata/Makefile b/src/cmd/internal/rsc.io/x86/x86asm/testdata/Makefile
new file mode 100644
index 000000000..9cb44127a
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/testdata/Makefile
@@ -0,0 +1,12 @@
+libmach8db: libmach8db.c
+ 9c libmach8db.c && 9l -o libmach8db libmach8db.o; rm libmach8db.o
+
+newdecode.txt:
+ cd ..; go test -cover -run 'Objdump.*32' -v -timeout 10h -printtests 2>&1 | tee log
+ cd ..; go test -cover -run 'Objdump.*64' -v -timeout 10h -printtests 2>&1 | tee -a log
+ cd ..; go test -cover -run 'Xed.*32' -v -timeout 10h -printtests 2>&1 | tee -a log
+ cd ..; go test -cover -run 'Xed.*64' -v -timeout 10h -printtests 2>&1 | tee -a log
+ cd ..; go test -cover -run 'Plan9.*32' -v -timeout 10h -printtests 2>&1 | tee -a log
+ cd ..; go test -cover -run 'Plan9.*64' -v -timeout 10h -printtests 2>&1 | tee -a log
+ egrep ' (gnu|intel|plan9) ' ../log |sort >newdecode.txt
+
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/testdata/decode.txt b/src/cmd/internal/rsc.io/x86/x86asm/testdata/decode.txt
new file mode 100644
index 000000000..a899d75fd
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/testdata/decode.txt
@@ -0,0 +1,6731 @@
+000511223344|556677885f5f5f5f5f5f 32 intel add byte ptr [0x44332211], al
+000511223344|556677885f5f5f5f5f5f 64 gnu add %al,0x44332211(%rip)
+000511223344|556677885f5f5f5f5f5f 64 intel add byte ptr [rip+0x44332211], al
+0100|11223344556677885f5f5f5f5f5f 32 intel add dword ptr [eax], eax
+0100|11223344556677885f5f5f5f5f5f 32 plan9 ADDL AX, 0(AX)
+0100|11223344556677885f5f5f5f5f5f 64 gnu add %eax,(%rax)
+0100|11223344556677885f5f5f5f5f5f 64 intel add dword ptr [rax], eax
+0100|11223344556677885f5f5f5f5f5f 64 plan9 ADDL AX, 0(AX)
+0211|223344556677885f5f5f5f5f5f5f 32 intel add dl, byte ptr [ecx]
+0211|223344556677885f5f5f5f5f5f5f 32 plan9 ADDL 0(CX), DL
+0211|223344556677885f5f5f5f5f5f5f 64 gnu add (%rcx),%dl
+0211|223344556677885f5f5f5f5f5f5f 64 intel add dl, byte ptr [rcx]
+0211|223344556677885f5f5f5f5f5f5f 64 plan9 ADDL 0(CX), DL
+0311|223344556677885f5f5f5f5f5f5f 32 intel add edx, dword ptr [ecx]
+0311|223344556677885f5f5f5f5f5f5f 32 plan9 ADDL 0(CX), DX
+0311|223344556677885f5f5f5f5f5f5f 64 gnu add (%rcx),%edx
+0311|223344556677885f5f5f5f5f5f5f 64 intel add edx, dword ptr [rcx]
+0311|223344556677885f5f5f5f5f5f5f 64 plan9 ADDL 0(CX), DX
+0411|223344556677885f5f5f5f5f5f5f 32 intel add al, 0x11
+0411|223344556677885f5f5f5f5f5f5f 32 plan9 ADDL $0x11, AL
+0411|223344556677885f5f5f5f5f5f5f 64 gnu add $0x11,%al
+0411|223344556677885f5f5f5f5f5f5f 64 intel add al, 0x11
+0411|223344556677885f5f5f5f5f5f5f 64 plan9 ADDL $0x11, AL
+0511223344|556677885f5f5f5f5f5f5f 32 intel add eax, 0x44332211
+0511223344|556677885f5f5f5f5f5f5f 32 plan9 ADDL $0x44332211, AX
+0511223344|556677885f5f5f5f5f5f5f 64 gnu add $0x44332211,%eax
+0511223344|556677885f5f5f5f5f5f5f 64 intel add eax, 0x44332211
+0511223344|556677885f5f5f5f5f5f5f 64 plan9 ADDL $0x44332211, AX
+06|11223344556677885f5f5f5f5f5f5f 32 intel push es
+06|11223344556677885f5f5f5f5f5f5f 32 plan9 PUSHL ES
+06|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+06|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+06|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+07|11223344556677885f5f5f5f5f5f5f 32 intel pop es
+07|11223344556677885f5f5f5f5f5f5f 32 plan9 POPL ES
+07|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+07|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+07|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0811|223344556677885f5f5f5f5f5f5f 32 intel or byte ptr [ecx], dl
+0811|223344556677885f5f5f5f5f5f5f 32 plan9 ORL DL, 0(CX)
+0811|223344556677885f5f5f5f5f5f5f 64 gnu or %dl,(%rcx)
+0811|223344556677885f5f5f5f5f5f5f 64 intel or byte ptr [rcx], dl
+0811|223344556677885f5f5f5f5f5f5f 64 plan9 ORL DL, 0(CX)
+0911|223344556677885f5f5f5f5f5f5f 32 intel or dword ptr [ecx], edx
+0911|223344556677885f5f5f5f5f5f5f 32 plan9 ORL DX, 0(CX)
+0911|223344556677885f5f5f5f5f5f5f 64 gnu or %edx,(%rcx)
+0911|223344556677885f5f5f5f5f5f5f 64 intel or dword ptr [rcx], edx
+0911|223344556677885f5f5f5f5f5f5f 64 plan9 ORL DX, 0(CX)
+0a11|223344556677885f5f5f5f5f5f5f 32 intel or dl, byte ptr [ecx]
+0a11|223344556677885f5f5f5f5f5f5f 32 plan9 ORL 0(CX), DL
+0a11|223344556677885f5f5f5f5f5f5f 64 gnu or (%rcx),%dl
+0a11|223344556677885f5f5f5f5f5f5f 64 intel or dl, byte ptr [rcx]
+0a11|223344556677885f5f5f5f5f5f5f 64 plan9 ORL 0(CX), DL
+0b11|223344556677885f5f5f5f5f5f5f 32 intel or edx, dword ptr [ecx]
+0b11|223344556677885f5f5f5f5f5f5f 32 plan9 ORL 0(CX), DX
+0b11|223344556677885f5f5f5f5f5f5f 64 gnu or (%rcx),%edx
+0b11|223344556677885f5f5f5f5f5f5f 64 intel or edx, dword ptr [rcx]
+0b11|223344556677885f5f5f5f5f5f5f 64 plan9 ORL 0(CX), DX
+0c11|223344556677885f5f5f5f5f5f5f 32 intel or al, 0x11
+0c11|223344556677885f5f5f5f5f5f5f 32 plan9 ORL $0x11, AL
+0c11|223344556677885f5f5f5f5f5f5f 64 gnu or $0x11,%al
+0c11|223344556677885f5f5f5f5f5f5f 64 intel or al, 0x11
+0c11|223344556677885f5f5f5f5f5f5f 64 plan9 ORL $0x11, AL
+0d11223344|556677885f5f5f5f5f5f5f 32 intel or eax, 0x44332211
+0d11223344|556677885f5f5f5f5f5f5f 32 plan9 ORL $0x44332211, AX
+0d11223344|556677885f5f5f5f5f5f5f 64 gnu or $0x44332211,%eax
+0d11223344|556677885f5f5f5f5f5f5f 64 intel or eax, 0x44332211
+0d11223344|556677885f5f5f5f5f5f5f 64 plan9 ORL $0x44332211, AX
+0e|11223344556677885f5f5f5f5f5f5f 32 intel push cs
+0e|11223344556677885f5f5f5f5f5f5f 32 plan9 PUSHL CS
+0e|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0e|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+0e|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f0000|11223344556677885f5f5f5f5f 32 intel sldt word ptr [eax]
+0f0000|11223344556677885f5f5f5f5f 32 plan9 SLDT 0(AX)
+0f0000|11223344556677885f5f5f5f5f 64 gnu sldt (%rax)
+0f0000|11223344556677885f5f5f5f5f 64 intel sldt word ptr [rax]
+0f0000|11223344556677885f5f5f5f5f 64 plan9 SLDT 0(AX)
+0f0008|11223344556677885f5f5f5f5f 32 intel str word ptr [eax]
+0f0008|11223344556677885f5f5f5f5f 32 plan9 STR 0(AX)
+0f0008|11223344556677885f5f5f5f5f 64 gnu str (%rax)
+0f0008|11223344556677885f5f5f5f5f 64 intel str word ptr [rax]
+0f0008|11223344556677885f5f5f5f5f 64 plan9 STR 0(AX)
+0f0011|223344556677885f5f5f5f5f5f 32 intel lldt word ptr [ecx]
+0f0011|223344556677885f5f5f5f5f5f 32 plan9 LLDT 0(CX)
+0f0011|223344556677885f5f5f5f5f5f 64 gnu lldt (%rcx)
+0f0011|223344556677885f5f5f5f5f5f 64 intel lldt word ptr [rcx]
+0f0011|223344556677885f5f5f5f5f5f 64 plan9 LLDT 0(CX)
+0f0018|11223344556677885f5f5f5f5f 32 intel ltr word ptr [eax]
+0f0018|11223344556677885f5f5f5f5f 32 plan9 LTR 0(AX)
+0f0018|11223344556677885f5f5f5f5f 64 gnu ltr (%rax)
+0f0018|11223344556677885f5f5f5f5f 64 intel ltr word ptr [rax]
+0f0018|11223344556677885f5f5f5f5f 64 plan9 LTR 0(AX)
+0f0020|11223344556677885f5f5f5f5f 32 intel verr word ptr [eax]
+0f0020|11223344556677885f5f5f5f5f 32 plan9 VERR 0(AX)
+0f0020|11223344556677885f5f5f5f5f 64 gnu verr (%rax)
+0f0020|11223344556677885f5f5f5f5f 64 intel verr word ptr [rax]
+0f0020|11223344556677885f5f5f5f5f 64 plan9 VERR 0(AX)
+0f0028|11223344556677885f5f5f5f5f 32 intel verw word ptr [eax]
+0f0028|11223344556677885f5f5f5f5f 32 plan9 VERW 0(AX)
+0f0028|11223344556677885f5f5f5f5f 64 gnu verw (%rax)
+0f0028|11223344556677885f5f5f5f5f 64 intel verw word ptr [rax]
+0f0028|11223344556677885f5f5f5f5f 64 plan9 VERW 0(AX)
+0f0030|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f0030|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f0100|11223344556677885f5f5f5f5f 32 intel sgdt ptr [eax]
+0f0100|11223344556677885f5f5f5f5f 32 plan9 SGDT 0(AX)
+0f0100|11223344556677885f5f5f5f5f 64 gnu sgdtl (%rax)
+0f0100|11223344556677885f5f5f5f5f 64 intel sgdt ptr [rax]
+0f0100|11223344556677885f5f5f5f5f 64 plan9 SGDT 0(AX)
+0f0108|11223344556677885f5f5f5f5f 32 intel sidt ptr [eax]
+0f0108|11223344556677885f5f5f5f5f 32 plan9 SIDT 0(AX)
+0f0108|11223344556677885f5f5f5f5f 64 gnu sidtl (%rax)
+0f0108|11223344556677885f5f5f5f5f 64 intel sidt ptr [rax]
+0f0108|11223344556677885f5f5f5f5f 64 plan9 SIDT 0(AX)
+0f0111|223344556677885f5f5f5f5f5f 32 intel lgdt ptr [ecx]
+0f0111|223344556677885f5f5f5f5f5f 32 plan9 LGDT 0(CX)
+0f0111|223344556677885f5f5f5f5f5f 64 gnu lgdtl (%rcx)
+0f0111|223344556677885f5f5f5f5f5f 64 intel lgdt ptr [rcx]
+0f0111|223344556677885f5f5f5f5f5f 64 plan9 LGDT 0(CX)
+0f0118|11223344556677885f5f5f5f5f 32 intel lidt ptr [eax]
+0f0118|11223344556677885f5f5f5f5f 32 plan9 LIDT 0(AX)
+0f0118|11223344556677885f5f5f5f5f 64 gnu lidtl (%rax)
+0f0118|11223344556677885f5f5f5f5f 64 intel lidt ptr [rax]
+0f0118|11223344556677885f5f5f5f5f 64 plan9 LIDT 0(AX)
+0f0120|11223344556677885f5f5f5f5f 32 intel smsw word ptr [eax]
+0f0120|11223344556677885f5f5f5f5f 32 plan9 SMSW 0(AX)
+0f0120|11223344556677885f5f5f5f5f 64 gnu smsw (%rax)
+0f0120|11223344556677885f5f5f5f5f 64 intel smsw word ptr [rax]
+0f0120|11223344556677885f5f5f5f5f 64 plan9 SMSW 0(AX)
+0f0130|11223344556677885f5f5f5f5f 32 intel lmsw word ptr [eax]
+0f0130|11223344556677885f5f5f5f5f 32 plan9 LMSW 0(AX)
+0f0130|11223344556677885f5f5f5f5f 64 gnu lmsw (%rax)
+0f0130|11223344556677885f5f5f5f5f 64 intel lmsw word ptr [rax]
+0f0130|11223344556677885f5f5f5f5f 64 plan9 LMSW 0(AX)
+0f0138|11223344556677885f5f5f5f5f 32 intel invlpg byte ptr [eax]
+0f0138|11223344556677885f5f5f5f5f 32 plan9 INVLPG 0(AX)
+0f0138|11223344556677885f5f5f5f5f 64 gnu invlpg (%rax)
+0f0138|11223344556677885f5f5f5f5f 64 intel invlpg byte ptr [rax]
+0f0138|11223344556677885f5f5f5f5f 64 plan9 INVLPG 0(AX)
+0f01c8|11223344556677885f5f5f5f5f 32 intel monitor
+0f01c8|11223344556677885f5f5f5f5f 32 plan9 MONITOR
+0f01c8|11223344556677885f5f5f5f5f 64 gnu monitor %eax,%ecx,%edx
+0f01c8|11223344556677885f5f5f5f5f 64 intel monitor
+0f01c8|11223344556677885f5f5f5f5f 64 plan9 MONITOR
+0f01c9|11223344556677885f5f5f5f5f 32 intel mwait
+0f01c9|11223344556677885f5f5f5f5f 32 plan9 MWAIT
+0f01c9|11223344556677885f5f5f5f5f 64 gnu mwait %rax,%rcx
+0f01c9|11223344556677885f5f5f5f5f 64 intel mwait
+0f01c9|11223344556677885f5f5f5f5f 64 plan9 MWAIT
+0f01d0|11223344556677885f5f5f5f5f 32 intel xgetbv
+0f01d0|11223344556677885f5f5f5f5f 32 plan9 XGETBV
+0f01d0|11223344556677885f5f5f5f5f 64 gnu xgetbv
+0f01d0|11223344556677885f5f5f5f5f 64 intel xgetbv
+0f01d0|11223344556677885f5f5f5f5f 64 plan9 XGETBV
+0f01d1|11223344556677885f5f5f5f5f 32 intel xsetbv
+0f01d1|11223344556677885f5f5f5f5f 32 plan9 XSETBV
+0f01d1|11223344556677885f5f5f5f5f 64 gnu xsetbv
+0f01d1|11223344556677885f5f5f5f5f 64 intel xsetbv
+0f01d1|11223344556677885f5f5f5f5f 64 plan9 XSETBV
+0f01d5|11223344556677885f5f5f5f5f 32 intel xend
+0f01d5|11223344556677885f5f5f5f5f 32 plan9 XEND
+0f01d5|11223344556677885f5f5f5f5f 64 gnu xend
+0f01d5|11223344556677885f5f5f5f5f 64 intel xend
+0f01d5|11223344556677885f5f5f5f5f 64 plan9 XEND
+0f01d6|11223344556677885f5f5f5f5f 32 intel xtest
+0f01d6|11223344556677885f5f5f5f5f 32 plan9 XTEST
+0f01d6|11223344556677885f5f5f5f5f 64 gnu xtest
+0f01d6|11223344556677885f5f5f5f5f 64 intel xtest
+0f01d6|11223344556677885f5f5f5f5f 64 plan9 XTEST
+0f01f8|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f01f8|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f01f8|11223344556677885f5f5f5f5f 64 gnu swapgs
+0f01f8|11223344556677885f5f5f5f5f 64 intel swapgs
+0f01f8|11223344556677885f5f5f5f5f 64 plan9 SWAPGS
+0f01f9|11223344556677885f5f5f5f5f 32 intel rdtscp
+0f01f9|11223344556677885f5f5f5f5f 32 plan9 RDTSCP
+0f01f9|11223344556677885f5f5f5f5f 64 gnu rdtscp
+0f01f9|11223344556677885f5f5f5f5f 64 intel rdtscp
+0f01f9|11223344556677885f5f5f5f5f 64 plan9 RDTSCP
+0f0211|223344556677885f5f5f5f5f5f 32 intel lar edx, word ptr [ecx]
+0f0211|223344556677885f5f5f5f5f5f 32 plan9 LAR 0(CX), DX
+0f0211|223344556677885f5f5f5f5f5f 64 gnu lar (%rcx),%edx
+0f0211|223344556677885f5f5f5f5f5f 64 intel lar edx, word ptr [rcx]
+0f0211|223344556677885f5f5f5f5f5f 64 plan9 LAR 0(CX), DX
+0f0311|223344556677885f5f5f5f5f5f 32 intel lsl edx, word ptr [ecx]
+0f0311|223344556677885f5f5f5f5f5f 32 plan9 LSL 0(CX), DX
+0f0311|223344556677885f5f5f5f5f5f 64 gnu lsl (%rcx),%edx
+0f0311|223344556677885f5f5f5f5f5f 64 intel lsl edx, word ptr [rcx]
+0f0311|223344556677885f5f5f5f5f5f 64 plan9 LSL 0(CX), DX
+0f04|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f04|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f04|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0f04|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0f04|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f05|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f05|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f05|11223344556677885f5f5f5f5f5f 64 gnu syscall
+0f05|11223344556677885f5f5f5f5f5f 64 intel syscall
+0f05|11223344556677885f5f5f5f5f5f 64 plan9 SYSCALL
+0f06|11223344556677885f5f5f5f5f5f 32 intel clts
+0f06|11223344556677885f5f5f5f5f5f 32 plan9 CLTS
+0f06|11223344556677885f5f5f5f5f5f 64 gnu clts
+0f06|11223344556677885f5f5f5f5f5f 64 intel clts
+0f06|11223344556677885f5f5f5f5f5f 64 plan9 CLTS
+0f07|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f07|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f07|11223344556677885f5f5f5f5f5f 64 gnu sysretq
+0f07|11223344556677885f5f5f5f5f5f 64 intel sysret
+0f07|11223344556677885f5f5f5f5f5f 64 plan9 SYSRET
+0f08|11223344556677885f5f5f5f5f5f 32 intel invd
+0f08|11223344556677885f5f5f5f5f5f 32 plan9 INVD
+0f08|11223344556677885f5f5f5f5f5f 64 gnu invd
+0f08|11223344556677885f5f5f5f5f5f 64 intel invd
+0f08|11223344556677885f5f5f5f5f5f 64 plan9 INVD
+0f09|11223344556677885f5f5f5f5f5f 32 intel wbinvd
+0f09|11223344556677885f5f5f5f5f5f 32 plan9 WBINVD
+0f09|11223344556677885f5f5f5f5f5f 64 gnu wbinvd
+0f09|11223344556677885f5f5f5f5f5f 64 intel wbinvd
+0f09|11223344556677885f5f5f5f5f5f 64 plan9 WBINVD
+0f0b|11223344556677885f5f5f5f5f5f 32 intel ud2
+0f0b|11223344556677885f5f5f5f5f5f 32 plan9 UD2
+0f0b|11223344556677885f5f5f5f5f5f 64 gnu ud2
+0f0b|11223344556677885f5f5f5f5f5f 64 intel ud2
+0f0b|11223344556677885f5f5f5f5f5f 64 plan9 UD2
+0f0d08|11223344556677885f5f5f5f5f 32 intel prefetchw zmmword ptr [eax]
+0f0d08|11223344556677885f5f5f5f5f 32 plan9 PREFETCHW 0(AX)
+0f0d08|11223344556677885f5f5f5f5f 64 gnu prefetchw (%rax)
+0f0d08|11223344556677885f5f5f5f5f 64 intel prefetchw zmmword ptr [rax]
+0f0d08|11223344556677885f5f5f5f5f 64 plan9 PREFETCHW 0(AX)
+0f1011|223344556677885f5f5f5f5f5f 32 intel movups xmm2, xmmword ptr [ecx]
+0f1011|223344556677885f5f5f5f5f5f 32 plan9 MOVUPS 0(CX), X2
+0f1011|223344556677885f5f5f5f5f5f 64 gnu movups (%rcx),%xmm2
+0f1011|223344556677885f5f5f5f5f5f 64 intel movups xmm2, xmmword ptr [rcx]
+0f1011|223344556677885f5f5f5f5f5f 64 plan9 MOVUPS 0(CX), X2
+0f1122|3344556677885f5f5f5f5f5f5f 32 intel movups xmmword ptr [edx], xmm4
+0f1122|3344556677885f5f5f5f5f5f5f 32 plan9 MOVUPS X4, 0(DX)
+0f1122|3344556677885f5f5f5f5f5f5f 64 gnu movups %xmm4,(%rdx)
+0f1122|3344556677885f5f5f5f5f5f5f 64 intel movups xmmword ptr [rdx], xmm4
+0f1122|3344556677885f5f5f5f5f5f5f 64 plan9 MOVUPS X4, 0(DX)
+0f1211|223344556677885f5f5f5f5f5f 32 intel movlps xmm2, qword ptr [ecx]
+0f1211|223344556677885f5f5f5f5f5f 32 plan9 MOVLPS 0(CX), X2
+0f1211|223344556677885f5f5f5f5f5f 64 gnu movlps (%rcx),%xmm2
+0f1211|223344556677885f5f5f5f5f5f 64 intel movlps xmm2, qword ptr [rcx]
+0f1211|223344556677885f5f5f5f5f5f 64 plan9 MOVLPS 0(CX), X2
+0f12c0|11223344556677885f5f5f5f5f 32 intel movhlps xmm0, xmm0
+0f12c0|11223344556677885f5f5f5f5f 32 plan9 MOVHLPS X0, X0
+0f12c0|11223344556677885f5f5f5f5f 64 gnu movhlps %xmm0,%xmm0
+0f12c0|11223344556677885f5f5f5f5f 64 intel movhlps xmm0, xmm0
+0f12c0|11223344556677885f5f5f5f5f 64 plan9 MOVHLPS X0, X0
+0f1311|223344556677885f5f5f5f5f5f 32 intel movlps qword ptr [ecx], xmm2
+0f1311|223344556677885f5f5f5f5f5f 32 plan9 MOVLPS X2, 0(CX)
+0f1311|223344556677885f5f5f5f5f5f 64 gnu movlps %xmm2,(%rcx)
+0f1311|223344556677885f5f5f5f5f5f 64 intel movlps qword ptr [rcx], xmm2
+0f1311|223344556677885f5f5f5f5f5f 64 plan9 MOVLPS X2, 0(CX)
+0f1411|223344556677885f5f5f5f5f5f 32 intel unpcklps xmm2, xmmword ptr [ecx]
+0f1411|223344556677885f5f5f5f5f5f 32 plan9 UNPCKLPS 0(CX), X2
+0f1411|223344556677885f5f5f5f5f5f 64 gnu unpcklps (%rcx),%xmm2
+0f1411|223344556677885f5f5f5f5f5f 64 intel unpcklps xmm2, xmmword ptr [rcx]
+0f1411|223344556677885f5f5f5f5f5f 64 plan9 UNPCKLPS 0(CX), X2
+0f1511|223344556677885f5f5f5f5f5f 32 intel unpckhps xmm2, xmmword ptr [ecx]
+0f1511|223344556677885f5f5f5f5f5f 32 plan9 UNPCKHPS 0(CX), X2
+0f1511|223344556677885f5f5f5f5f5f 64 gnu unpckhps (%rcx),%xmm2
+0f1511|223344556677885f5f5f5f5f5f 64 intel unpckhps xmm2, xmmword ptr [rcx]
+0f1511|223344556677885f5f5f5f5f5f 64 plan9 UNPCKHPS 0(CX), X2
+0f1611|223344556677885f5f5f5f5f5f 32 intel movhps xmm2, qword ptr [ecx]
+0f1611|223344556677885f5f5f5f5f5f 32 plan9 MOVHPS 0(CX), X2
+0f1611|223344556677885f5f5f5f5f5f 64 gnu movhps (%rcx),%xmm2
+0f1611|223344556677885f5f5f5f5f5f 64 intel movhps xmm2, qword ptr [rcx]
+0f1611|223344556677885f5f5f5f5f5f 64 plan9 MOVHPS 0(CX), X2
+0f16c0|11223344556677885f5f5f5f5f 32 intel movlhps xmm0, xmm0
+0f16c0|11223344556677885f5f5f5f5f 32 plan9 MOVLHPS X0, X0
+0f16c0|11223344556677885f5f5f5f5f 64 gnu movlhps %xmm0,%xmm0
+0f16c0|11223344556677885f5f5f5f5f 64 intel movlhps xmm0, xmm0
+0f16c0|11223344556677885f5f5f5f5f 64 plan9 MOVLHPS X0, X0
+0f1711|223344556677885f5f5f5f5f5f 32 intel movhps qword ptr [ecx], xmm2
+0f1711|223344556677885f5f5f5f5f5f 32 plan9 MOVHPS X2, 0(CX)
+0f1711|223344556677885f5f5f5f5f5f 64 gnu movhps %xmm2,(%rcx)
+0f1711|223344556677885f5f5f5f5f5f 64 intel movhps qword ptr [rcx], xmm2
+0f1711|223344556677885f5f5f5f5f5f 64 plan9 MOVHPS X2, 0(CX)
+0f1800|11223344556677885f5f5f5f5f 32 intel prefetchnta zmmword ptr [eax]
+0f1800|11223344556677885f5f5f5f5f 32 plan9 PREFETCHNTA 0(AX)
+0f1800|11223344556677885f5f5f5f5f 64 gnu prefetchnta (%rax)
+0f1800|11223344556677885f5f5f5f5f 64 intel prefetchnta zmmword ptr [rax]
+0f1800|11223344556677885f5f5f5f5f 64 plan9 PREFETCHNTA 0(AX)
+0f1808|11223344556677885f5f5f5f5f 32 intel prefetcht0 zmmword ptr [eax]
+0f1808|11223344556677885f5f5f5f5f 32 plan9 PREFETCHT0 0(AX)
+0f1808|11223344556677885f5f5f5f5f 64 gnu prefetcht0 (%rax)
+0f1808|11223344556677885f5f5f5f5f 64 intel prefetcht0 zmmword ptr [rax]
+0f1808|11223344556677885f5f5f5f5f 64 plan9 PREFETCHT0 0(AX)
+0f1811|223344556677885f5f5f5f5f5f 32 intel prefetcht1 zmmword ptr [ecx]
+0f1811|223344556677885f5f5f5f5f5f 32 plan9 PREFETCHT1 0(CX)
+0f1811|223344556677885f5f5f5f5f5f 64 gnu prefetcht1 (%rcx)
+0f1811|223344556677885f5f5f5f5f5f 64 intel prefetcht1 zmmword ptr [rcx]
+0f1811|223344556677885f5f5f5f5f5f 64 plan9 PREFETCHT1 0(CX)
+0f1818|11223344556677885f5f5f5f5f 32 intel prefetcht2 zmmword ptr [eax]
+0f1818|11223344556677885f5f5f5f5f 32 plan9 PREFETCHT2 0(AX)
+0f1818|11223344556677885f5f5f5f5f 64 gnu prefetcht2 (%rax)
+0f1818|11223344556677885f5f5f5f5f 64 intel prefetcht2 zmmword ptr [rax]
+0f1818|11223344556677885f5f5f5f5f 64 plan9 PREFETCHT2 0(AX)
+0f1f00|11223344556677885f5f5f5f5f 32 intel nop dword ptr [eax], eax
+0f1f00|11223344556677885f5f5f5f5f 32 plan9 NOPL 0(AX)
+0f1f00|11223344556677885f5f5f5f5f 64 gnu nopl (%rax)
+0f1f00|11223344556677885f5f5f5f5f 64 intel nop dword ptr [rax], eax
+0f1f00|11223344556677885f5f5f5f5f 64 plan9 NOPL 0(AX)
+0f2011|223344556677885f5f5f5f5f5f 32 intel mov ecx, cr2
+0f2011|223344556677885f5f5f5f5f5f 32 plan9 MOVL CR2, CX
+0f2011|223344556677885f5f5f5f5f5f 64 gnu mov %cr2,%rcx
+0f2011|223344556677885f5f5f5f5f5f 64 intel mov rcx, cr2
+0f2011|223344556677885f5f5f5f5f5f 64 plan9 MOVL CR2, CX
+0f2111|223344556677885f5f5f5f5f5f 32 intel mov ecx, dr2
+0f2111|223344556677885f5f5f5f5f5f 32 plan9 MOVL DR2, CX
+0f2111|223344556677885f5f5f5f5f5f 64 gnu mov %db2,%rcx
+0f2111|223344556677885f5f5f5f5f5f 64 intel mov rcx, dr2
+0f2111|223344556677885f5f5f5f5f5f 64 plan9 MOVL DR2, CX
+0f2211|223344556677885f5f5f5f5f5f 32 intel mov cr2, ecx
+0f2211|223344556677885f5f5f5f5f5f 32 plan9 MOVL CX, CR2
+0f2211|223344556677885f5f5f5f5f5f 64 gnu mov %rcx,%cr2
+0f2211|223344556677885f5f5f5f5f5f 64 intel mov cr2, rcx
+0f2211|223344556677885f5f5f5f5f5f 64 plan9 MOVL CX, CR2
+0f2311|223344556677885f5f5f5f5f5f 32 intel mov dr2, ecx
+0f2311|223344556677885f5f5f5f5f5f 32 plan9 MOVL CX, DR2
+0f2311|223344556677885f5f5f5f5f5f 64 gnu mov %rcx,%db2
+0f2311|223344556677885f5f5f5f5f5f 64 intel mov dr2, rcx
+0f2311|223344556677885f5f5f5f5f5f 64 plan9 MOVL CX, DR2
+0f2411|223344556677885f5f5f5f5f5f 32 intel mov ecx, tr2
+0f2411|223344556677885f5f5f5f5f5f 32 plan9 MOVL TR2, CX
+0f2411|223344556677885f5f5f5f5f5f 64 gnu mov %tr2,%rcx
+0f2411|223344556677885f5f5f5f5f5f 64 intel mov rcx, tr2
+0f2411|223344556677885f5f5f5f5f5f 64 plan9 MOVL TR2, CX
+0f2611|223344556677885f5f5f5f5f5f 32 intel mov tr2, ecx
+0f2611|223344556677885f5f5f5f5f5f 32 plan9 MOVL CX, TR2
+0f2611|223344556677885f5f5f5f5f5f 64 gnu mov %rcx,%tr2
+0f2611|223344556677885f5f5f5f5f5f 64 intel mov tr2, rcx
+0f2611|223344556677885f5f5f5f5f5f 64 plan9 MOVL CX, TR2
+0f2811|223344556677885f5f5f5f5f5f 32 intel movaps xmm2, xmmword ptr [ecx]
+0f2811|223344556677885f5f5f5f5f5f 32 plan9 MOVAPS 0(CX), X2
+0f2811|223344556677885f5f5f5f5f5f 64 gnu movaps (%rcx),%xmm2
+0f2811|223344556677885f5f5f5f5f5f 64 intel movaps xmm2, xmmword ptr [rcx]
+0f2811|223344556677885f5f5f5f5f5f 64 plan9 MOVAPS 0(CX), X2
+0f2911|223344556677885f5f5f5f5f5f 32 intel movaps xmmword ptr [ecx], xmm2
+0f2911|223344556677885f5f5f5f5f5f 32 plan9 MOVAPS X2, 0(CX)
+0f2911|223344556677885f5f5f5f5f5f 64 gnu movaps %xmm2,(%rcx)
+0f2911|223344556677885f5f5f5f5f5f 64 intel movaps xmmword ptr [rcx], xmm2
+0f2911|223344556677885f5f5f5f5f5f 64 plan9 MOVAPS X2, 0(CX)
+0f2a11|223344556677885f5f5f5f5f5f 32 intel cvtpi2ps xmm2, qword ptr [ecx]
+0f2a11|223344556677885f5f5f5f5f5f 32 plan9 CVTPI2PS 0(CX), X2
+0f2a11|223344556677885f5f5f5f5f5f 64 gnu cvtpi2ps (%rcx),%xmm2
+0f2a11|223344556677885f5f5f5f5f5f 64 intel cvtpi2ps xmm2, qword ptr [rcx]
+0f2a11|223344556677885f5f5f5f5f5f 64 plan9 CVTPI2PS 0(CX), X2
+0f2b11|223344556677885f5f5f5f5f5f 32 intel movntps xmmword ptr [ecx], xmm2
+0f2b11|223344556677885f5f5f5f5f5f 32 plan9 MOVNTPS X2, 0(CX)
+0f2b11|223344556677885f5f5f5f5f5f 64 gnu movntps %xmm2,(%rcx)
+0f2b11|223344556677885f5f5f5f5f5f 64 intel movntps xmmword ptr [rcx], xmm2
+0f2b11|223344556677885f5f5f5f5f5f 64 plan9 MOVNTPS X2, 0(CX)
+0f2c11|223344556677885f5f5f5f5f5f 32 intel cvttps2pi mmx2, qword ptr [ecx]
+0f2c11|223344556677885f5f5f5f5f5f 32 plan9 CVTTPS2PI 0(CX), M2
+0f2c11|223344556677885f5f5f5f5f5f 64 gnu cvttps2pi (%rcx),%mm2
+0f2c11|223344556677885f5f5f5f5f5f 64 intel cvttps2pi mmx2, qword ptr [rcx]
+0f2c11|223344556677885f5f5f5f5f5f 64 plan9 CVTTPS2PI 0(CX), M2
+0f2d11|223344556677885f5f5f5f5f5f 32 intel cvtps2pi mmx2, qword ptr [ecx]
+0f2d11|223344556677885f5f5f5f5f5f 32 plan9 CVTPS2PI 0(CX), M2
+0f2d11|223344556677885f5f5f5f5f5f 64 gnu cvtps2pi (%rcx),%mm2
+0f2d11|223344556677885f5f5f5f5f5f 64 intel cvtps2pi mmx2, qword ptr [rcx]
+0f2d11|223344556677885f5f5f5f5f5f 64 plan9 CVTPS2PI 0(CX), M2
+0f2e11|223344556677885f5f5f5f5f5f 32 intel ucomiss xmm2, dword ptr [ecx]
+0f2e11|223344556677885f5f5f5f5f5f 32 plan9 UCOMISS 0(CX), X2
+0f2e11|223344556677885f5f5f5f5f5f 64 gnu ucomiss (%rcx),%xmm2
+0f2e11|223344556677885f5f5f5f5f5f 64 intel ucomiss xmm2, dword ptr [rcx]
+0f2e11|223344556677885f5f5f5f5f5f 64 plan9 UCOMISS 0(CX), X2
+0f2f11|223344556677885f5f5f5f5f5f 32 intel comiss xmm2, dword ptr [ecx]
+0f2f11|223344556677885f5f5f5f5f5f 32 plan9 COMISS 0(CX), X2
+0f2f11|223344556677885f5f5f5f5f5f 64 gnu comiss (%rcx),%xmm2
+0f2f11|223344556677885f5f5f5f5f5f 64 intel comiss xmm2, dword ptr [rcx]
+0f2f11|223344556677885f5f5f5f5f5f 64 plan9 COMISS 0(CX), X2
+0f30|11223344556677885f5f5f5f5f5f 32 intel wrmsr
+0f30|11223344556677885f5f5f5f5f5f 32 plan9 WRMSR
+0f30|11223344556677885f5f5f5f5f5f 64 gnu wrmsr
+0f30|11223344556677885f5f5f5f5f5f 64 intel wrmsr
+0f30|11223344556677885f5f5f5f5f5f 64 plan9 WRMSR
+0f31|11223344556677885f5f5f5f5f5f 32 intel rdtsc
+0f31|11223344556677885f5f5f5f5f5f 32 plan9 RDTSC
+0f31|11223344556677885f5f5f5f5f5f 64 gnu rdtsc
+0f31|11223344556677885f5f5f5f5f5f 64 intel rdtsc
+0f31|11223344556677885f5f5f5f5f5f 64 plan9 RDTSC
+0f32|11223344556677885f5f5f5f5f5f 32 intel rdmsr
+0f32|11223344556677885f5f5f5f5f5f 32 plan9 RDMSR
+0f32|11223344556677885f5f5f5f5f5f 64 gnu rdmsr
+0f32|11223344556677885f5f5f5f5f5f 64 intel rdmsr
+0f32|11223344556677885f5f5f5f5f5f 64 plan9 RDMSR
+0f33|11223344556677885f5f5f5f5f5f 32 intel rdpmc
+0f33|11223344556677885f5f5f5f5f5f 32 plan9 RDPMC
+0f33|11223344556677885f5f5f5f5f5f 64 gnu rdpmc
+0f33|11223344556677885f5f5f5f5f5f 64 intel rdpmc
+0f33|11223344556677885f5f5f5f5f5f 64 plan9 RDPMC
+0f34|11223344556677885f5f5f5f5f5f 32 intel sysenter
+0f34|11223344556677885f5f5f5f5f5f 32 plan9 SYSENTER
+0f34|11223344556677885f5f5f5f5f5f 64 gnu sysenter
+0f34|11223344556677885f5f5f5f5f5f 64 intel sysenter
+0f34|11223344556677885f5f5f5f5f5f 64 plan9 SYSENTER
+0f35|11223344556677885f5f5f5f5f5f 32 intel sysexit
+0f35|11223344556677885f5f5f5f5f5f 32 plan9 SYSEXIT
+0f35|11223344556677885f5f5f5f5f5f 64 gnu sysexit
+0f35|11223344556677885f5f5f5f5f5f 64 intel sysexit
+0f35|11223344556677885f5f5f5f5f5f 64 plan9 SYSEXIT
+0f380011|223344556677885f5f5f5f5f 32 intel pshufb mmx2, qword ptr [ecx]
+0f380011|223344556677885f5f5f5f5f 32 plan9 PSHUFB 0(CX), M2
+0f380011|223344556677885f5f5f5f5f 64 gnu pshufb (%rcx),%mm2
+0f380011|223344556677885f5f5f5f5f 64 intel pshufb mmx2, qword ptr [rcx]
+0f380011|223344556677885f5f5f5f5f 64 plan9 PSHUFB 0(CX), M2
+0f380111|223344556677885f5f5f5f5f 32 intel phaddw mmx2, qword ptr [ecx]
+0f380111|223344556677885f5f5f5f5f 32 plan9 PHADDW 0(CX), M2
+0f380111|223344556677885f5f5f5f5f 64 gnu phaddw (%rcx),%mm2
+0f380111|223344556677885f5f5f5f5f 64 intel phaddw mmx2, qword ptr [rcx]
+0f380111|223344556677885f5f5f5f5f 64 plan9 PHADDW 0(CX), M2
+0f380211|223344556677885f5f5f5f5f 32 intel phaddd mmx2, qword ptr [ecx]
+0f380211|223344556677885f5f5f5f5f 32 plan9 PHADDD 0(CX), M2
+0f380211|223344556677885f5f5f5f5f 64 gnu phaddd (%rcx),%mm2
+0f380211|223344556677885f5f5f5f5f 64 intel phaddd mmx2, qword ptr [rcx]
+0f380211|223344556677885f5f5f5f5f 64 plan9 PHADDD 0(CX), M2
+0f380311|223344556677885f5f5f5f5f 32 intel phaddsw mmx2, qword ptr [ecx]
+0f380311|223344556677885f5f5f5f5f 32 plan9 PHADDSW 0(CX), M2
+0f380311|223344556677885f5f5f5f5f 64 gnu phaddsw (%rcx),%mm2
+0f380311|223344556677885f5f5f5f5f 64 intel phaddsw mmx2, qword ptr [rcx]
+0f380311|223344556677885f5f5f5f5f 64 plan9 PHADDSW 0(CX), M2
+0f380411|223344556677885f5f5f5f5f 32 intel pmaddubsw mmx2, qword ptr [ecx]
+0f380411|223344556677885f5f5f5f5f 32 plan9 PMADDUBSW 0(CX), M2
+0f380411|223344556677885f5f5f5f5f 64 gnu pmaddubsw (%rcx),%mm2
+0f380411|223344556677885f5f5f5f5f 64 intel pmaddubsw mmx2, qword ptr [rcx]
+0f380411|223344556677885f5f5f5f5f 64 plan9 PMADDUBSW 0(CX), M2
+0f380511|223344556677885f5f5f5f5f 32 intel phsubw mmx2, qword ptr [ecx]
+0f380511|223344556677885f5f5f5f5f 32 plan9 PHSUBW 0(CX), M2
+0f380511|223344556677885f5f5f5f5f 64 gnu phsubw (%rcx),%mm2
+0f380511|223344556677885f5f5f5f5f 64 intel phsubw mmx2, qword ptr [rcx]
+0f380511|223344556677885f5f5f5f5f 64 plan9 PHSUBW 0(CX), M2
+0f380611|223344556677885f5f5f5f5f 32 intel phsubd mmx2, qword ptr [ecx]
+0f380611|223344556677885f5f5f5f5f 32 plan9 PHSUBD 0(CX), M2
+0f380611|223344556677885f5f5f5f5f 64 gnu phsubd (%rcx),%mm2
+0f380611|223344556677885f5f5f5f5f 64 intel phsubd mmx2, qword ptr [rcx]
+0f380611|223344556677885f5f5f5f5f 64 plan9 PHSUBD 0(CX), M2
+0f380711|223344556677885f5f5f5f5f 32 intel phsubsw mmx2, qword ptr [ecx]
+0f380711|223344556677885f5f5f5f5f 32 plan9 PHSUBSW 0(CX), M2
+0f380711|223344556677885f5f5f5f5f 64 gnu phsubsw (%rcx),%mm2
+0f380711|223344556677885f5f5f5f5f 64 intel phsubsw mmx2, qword ptr [rcx]
+0f380711|223344556677885f5f5f5f5f 64 plan9 PHSUBSW 0(CX), M2
+0f380811|223344556677885f5f5f5f5f 32 intel psignb mmx2, qword ptr [ecx]
+0f380811|223344556677885f5f5f5f5f 32 plan9 PSIGNB 0(CX), M2
+0f380811|223344556677885f5f5f5f5f 64 gnu psignb (%rcx),%mm2
+0f380811|223344556677885f5f5f5f5f 64 intel psignb mmx2, qword ptr [rcx]
+0f380811|223344556677885f5f5f5f5f 64 plan9 PSIGNB 0(CX), M2
+0f380911|223344556677885f5f5f5f5f 32 intel psignw mmx2, qword ptr [ecx]
+0f380911|223344556677885f5f5f5f5f 32 plan9 PSIGNW 0(CX), M2
+0f380911|223344556677885f5f5f5f5f 64 gnu psignw (%rcx),%mm2
+0f380911|223344556677885f5f5f5f5f 64 intel psignw mmx2, qword ptr [rcx]
+0f380911|223344556677885f5f5f5f5f 64 plan9 PSIGNW 0(CX), M2
+0f380a11|223344556677885f5f5f5f5f 32 intel psignd mmx2, qword ptr [ecx]
+0f380a11|223344556677885f5f5f5f5f 32 plan9 PSIGND 0(CX), M2
+0f380a11|223344556677885f5f5f5f5f 64 gnu psignd (%rcx),%mm2
+0f380a11|223344556677885f5f5f5f5f 64 intel psignd mmx2, qword ptr [rcx]
+0f380a11|223344556677885f5f5f5f5f 64 plan9 PSIGND 0(CX), M2
+0f380b11|223344556677885f5f5f5f5f 32 intel pmulhrsw mmx2, qword ptr [ecx]
+0f380b11|223344556677885f5f5f5f5f 32 plan9 PMULHRSW 0(CX), M2
+0f380b11|223344556677885f5f5f5f5f 64 gnu pmulhrsw (%rcx),%mm2
+0f380b11|223344556677885f5f5f5f5f 64 intel pmulhrsw mmx2, qword ptr [rcx]
+0f380b11|223344556677885f5f5f5f5f 64 plan9 PMULHRSW 0(CX), M2
+0f3810|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3810|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3810|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3810|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3810|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3811|223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f3811|223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3811|223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3811|223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0f3811|223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3814|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3814|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3814|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3814|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3814|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3815|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3815|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3815|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3815|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3815|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3817|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3817|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3817|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3817|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3817|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f381c11|223344556677885f5f5f5f5f 32 intel pabsb mmx2, qword ptr [ecx]
+0f381c11|223344556677885f5f5f5f5f 32 plan9 PABSB 0(CX), M2
+0f381c11|223344556677885f5f5f5f5f 64 gnu pabsb (%rcx),%mm2
+0f381c11|223344556677885f5f5f5f5f 64 intel pabsb mmx2, qword ptr [rcx]
+0f381c11|223344556677885f5f5f5f5f 64 plan9 PABSB 0(CX), M2
+0f381d11|223344556677885f5f5f5f5f 32 intel pabsw mmx2, qword ptr [ecx]
+0f381d11|223344556677885f5f5f5f5f 32 plan9 PABSW 0(CX), M2
+0f381d11|223344556677885f5f5f5f5f 64 gnu pabsw (%rcx),%mm2
+0f381d11|223344556677885f5f5f5f5f 64 intel pabsw mmx2, qword ptr [rcx]
+0f381d11|223344556677885f5f5f5f5f 64 plan9 PABSW 0(CX), M2
+0f381e11|223344556677885f5f5f5f5f 32 intel pabsd mmx2, qword ptr [ecx]
+0f381e11|223344556677885f5f5f5f5f 32 plan9 PABSD 0(CX), M2
+0f381e11|223344556677885f5f5f5f5f 64 gnu pabsd (%rcx),%mm2
+0f381e11|223344556677885f5f5f5f5f 64 intel pabsd mmx2, qword ptr [rcx]
+0f381e11|223344556677885f5f5f5f5f 64 plan9 PABSD 0(CX), M2
+0f3820|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3820|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3820|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3820|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3820|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3821|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3821|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3821|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3821|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3821|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3822|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3822|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3822|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3822|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3822|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3823|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3823|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3823|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3823|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3823|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3824|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3824|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3824|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3824|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3824|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3825|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3825|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3825|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3825|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3825|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3828|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3828|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3828|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3828|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3828|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3829|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3829|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3829|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3829|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3829|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f382a|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f382a|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f382a|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f382a|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f382a|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f382b|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f382b|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f382b|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f382b|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f382b|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3830|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3830|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3830|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3830|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3830|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3831|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3831|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3831|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3831|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3831|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3832|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3832|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3832|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3832|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3832|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3833|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3833|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3833|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3833|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3833|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3834|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3834|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3834|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3834|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3834|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3835|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3835|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3835|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3835|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3835|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3837|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3837|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3837|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3837|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3837|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3838|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3838|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3838|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3838|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3838|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3839|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3839|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3839|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3839|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3839|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f383a|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f383a|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f383a|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f383a|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f383a|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f383b|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f383b|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f383b|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f383b|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f383b|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f383c|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f383c|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f383c|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f383c|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f383c|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f383d|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f383d|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f383d|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f383d|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f383d|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f383e|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f383e|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f383e|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f383e|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f383e|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f383f|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f383f|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f383f|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f383f|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f383f|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3840|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3840|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3840|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3840|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3840|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3841|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3841|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3841|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3841|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3841|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3882|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3882|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3882|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3882|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3882|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f38db|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f38db|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f38db|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f38db|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f38db|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f38dc|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f38dc|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f38dc|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f38dc|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f38dc|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f38dd|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f38dd|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f38dd|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f38dd|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f38dd|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f38de|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f38de|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f38de|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f38de|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f38de|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f38df|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f38df|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f38df|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f38df|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f38df|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f38f011|223344556677885f5f5f5f5f 32 intel movbe edx, dword ptr [ecx]
+0f38f011|223344556677885f5f5f5f5f 32 plan9 MOVBE 0(CX), DX
+0f38f011|223344556677885f5f5f5f5f 64 gnu movbe (%rcx),%edx
+0f38f011|223344556677885f5f5f5f5f 64 intel movbe edx, dword ptr [rcx]
+0f38f011|223344556677885f5f5f5f5f 64 plan9 MOVBE 0(CX), DX
+0f38f111|223344556677885f5f5f5f5f 32 intel movbe dword ptr [ecx], edx
+0f38f111|223344556677885f5f5f5f5f 32 plan9 MOVBE DX, 0(CX)
+0f38f111|223344556677885f5f5f5f5f 64 gnu movbe %edx,(%rcx)
+0f38f111|223344556677885f5f5f5f5f 64 intel movbe dword ptr [rcx], edx
+0f38f111|223344556677885f5f5f5f5f 64 plan9 MOVBE DX, 0(CX)
+0f3a08|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a08|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a08|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a08|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a08|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a09|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a09|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a09|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a09|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a09|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a0a|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a0a|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a0a|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a0a|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a0a|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a0b|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a0b|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a0b|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a0b|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a0b|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a0c|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a0c|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a0c|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a0c|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a0c|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a0d|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a0d|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a0d|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a0d|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a0d|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a0e|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a0e|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a0e|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a0e|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a0e|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a0f1122|3344556677885f5f5f5f5f 32 intel palignr mmx2, qword ptr [ecx], 0x22
+0f3a0f1122|3344556677885f5f5f5f5f 32 plan9 PALIGNR $0x22, 0(CX), M2
+0f3a0f1122|3344556677885f5f5f5f5f 64 gnu palignr $0x22,(%rcx),%mm2
+0f3a0f1122|3344556677885f5f5f5f5f 64 intel palignr mmx2, qword ptr [rcx], 0x22
+0f3a0f1122|3344556677885f5f5f5f5f 64 plan9 PALIGNR $0x22, 0(CX), M2
+0f3a11|223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a11|223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a11|223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a11|223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a11|223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a14|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a14|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a14|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a14|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a14|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a15|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a15|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a15|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a15|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a15|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a16|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a16|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a16|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a16|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a16|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a17|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a17|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a17|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a17|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a17|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a20|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a20|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a20|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a20|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a20|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a21|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a21|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a21|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a21|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a21|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a22|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a22|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a22|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a22|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a22|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a40|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a40|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a40|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a40|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a40|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a41|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a41|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a41|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a41|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a41|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a42|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a42|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a42|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a42|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a42|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a44|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a44|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a44|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a44|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a44|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a60|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a60|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a60|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a60|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a60|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a61|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a61|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a61|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a61|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a61|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a62|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a62|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a62|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a62|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a62|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3a63|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3a63|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3a63|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3a63|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3a63|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f3adf|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f3adf|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f3adf|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f3adf|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f3adf|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f4011|223344556677885f5f5f5f5f5f 32 intel cmovo edx, dword ptr [ecx]
+0f4011|223344556677885f5f5f5f5f5f 32 plan9 CMOVO 0(CX), DX
+0f4011|223344556677885f5f5f5f5f5f 64 gnu cmovo (%rcx),%edx
+0f4011|223344556677885f5f5f5f5f5f 64 intel cmovo edx, dword ptr [rcx]
+0f4011|223344556677885f5f5f5f5f5f 64 plan9 CMOVO 0(CX), DX
+0f4111|223344556677885f5f5f5f5f5f 32 intel cmovno edx, dword ptr [ecx]
+0f4111|223344556677885f5f5f5f5f5f 32 plan9 CMOVNO 0(CX), DX
+0f4111|223344556677885f5f5f5f5f5f 64 gnu cmovno (%rcx),%edx
+0f4111|223344556677885f5f5f5f5f5f 64 intel cmovno edx, dword ptr [rcx]
+0f4111|223344556677885f5f5f5f5f5f 64 plan9 CMOVNO 0(CX), DX
+0f4211|223344556677885f5f5f5f5f5f 32 intel cmovb edx, dword ptr [ecx]
+0f4211|223344556677885f5f5f5f5f5f 32 plan9 CMOVB 0(CX), DX
+0f4211|223344556677885f5f5f5f5f5f 64 gnu cmovb (%rcx),%edx
+0f4211|223344556677885f5f5f5f5f5f 64 intel cmovb edx, dword ptr [rcx]
+0f4211|223344556677885f5f5f5f5f5f 64 plan9 CMOVB 0(CX), DX
+0f4311|223344556677885f5f5f5f5f5f 32 intel cmovnb edx, dword ptr [ecx]
+0f4311|223344556677885f5f5f5f5f5f 32 plan9 CMOVAE 0(CX), DX
+0f4311|223344556677885f5f5f5f5f5f 64 gnu cmovae (%rcx),%edx
+0f4311|223344556677885f5f5f5f5f5f 64 intel cmovnb edx, dword ptr [rcx]
+0f4311|223344556677885f5f5f5f5f5f 64 plan9 CMOVAE 0(CX), DX
+0f4411|223344556677885f5f5f5f5f5f 32 intel cmovz edx, dword ptr [ecx]
+0f4411|223344556677885f5f5f5f5f5f 32 plan9 CMOVE 0(CX), DX
+0f4411|223344556677885f5f5f5f5f5f 64 gnu cmove (%rcx),%edx
+0f4411|223344556677885f5f5f5f5f5f 64 intel cmovz edx, dword ptr [rcx]
+0f4411|223344556677885f5f5f5f5f5f 64 plan9 CMOVE 0(CX), DX
+0f4511|223344556677885f5f5f5f5f5f 32 intel cmovnz edx, dword ptr [ecx]
+0f4511|223344556677885f5f5f5f5f5f 32 plan9 CMOVNE 0(CX), DX
+0f4511|223344556677885f5f5f5f5f5f 64 gnu cmovne (%rcx),%edx
+0f4511|223344556677885f5f5f5f5f5f 64 intel cmovnz edx, dword ptr [rcx]
+0f4511|223344556677885f5f5f5f5f5f 64 plan9 CMOVNE 0(CX), DX
+0f4611|223344556677885f5f5f5f5f5f 32 intel cmovbe edx, dword ptr [ecx]
+0f4611|223344556677885f5f5f5f5f5f 32 plan9 CMOVBE 0(CX), DX
+0f4611|223344556677885f5f5f5f5f5f 64 gnu cmovbe (%rcx),%edx
+0f4611|223344556677885f5f5f5f5f5f 64 intel cmovbe edx, dword ptr [rcx]
+0f4611|223344556677885f5f5f5f5f5f 64 plan9 CMOVBE 0(CX), DX
+0f4711|223344556677885f5f5f5f5f5f 32 intel cmovnbe edx, dword ptr [ecx]
+0f4711|223344556677885f5f5f5f5f5f 32 plan9 CMOVA 0(CX), DX
+0f4711|223344556677885f5f5f5f5f5f 64 gnu cmova (%rcx),%edx
+0f4711|223344556677885f5f5f5f5f5f 64 intel cmovnbe edx, dword ptr [rcx]
+0f4711|223344556677885f5f5f5f5f5f 64 plan9 CMOVA 0(CX), DX
+0f4811|223344556677885f5f5f5f5f5f 32 intel cmovs edx, dword ptr [ecx]
+0f4811|223344556677885f5f5f5f5f5f 32 plan9 CMOVS 0(CX), DX
+0f4811|223344556677885f5f5f5f5f5f 64 gnu cmovs (%rcx),%edx
+0f4811|223344556677885f5f5f5f5f5f 64 intel cmovs edx, dword ptr [rcx]
+0f4811|223344556677885f5f5f5f5f5f 64 plan9 CMOVS 0(CX), DX
+0f4911|223344556677885f5f5f5f5f5f 32 intel cmovns edx, dword ptr [ecx]
+0f4911|223344556677885f5f5f5f5f5f 32 plan9 CMOVNS 0(CX), DX
+0f4911|223344556677885f5f5f5f5f5f 64 gnu cmovns (%rcx),%edx
+0f4911|223344556677885f5f5f5f5f5f 64 intel cmovns edx, dword ptr [rcx]
+0f4911|223344556677885f5f5f5f5f5f 64 plan9 CMOVNS 0(CX), DX
+0f4a11|223344556677885f5f5f5f5f5f 32 intel cmovp edx, dword ptr [ecx]
+0f4a11|223344556677885f5f5f5f5f5f 32 plan9 CMOVP 0(CX), DX
+0f4a11|223344556677885f5f5f5f5f5f 64 gnu cmovp (%rcx),%edx
+0f4a11|223344556677885f5f5f5f5f5f 64 intel cmovp edx, dword ptr [rcx]
+0f4a11|223344556677885f5f5f5f5f5f 64 plan9 CMOVP 0(CX), DX
+0f4b11|223344556677885f5f5f5f5f5f 32 intel cmovnp edx, dword ptr [ecx]
+0f4b11|223344556677885f5f5f5f5f5f 32 plan9 CMOVNP 0(CX), DX
+0f4b11|223344556677885f5f5f5f5f5f 64 gnu cmovnp (%rcx),%edx
+0f4b11|223344556677885f5f5f5f5f5f 64 intel cmovnp edx, dword ptr [rcx]
+0f4b11|223344556677885f5f5f5f5f5f 64 plan9 CMOVNP 0(CX), DX
+0f4c11|223344556677885f5f5f5f5f5f 32 intel cmovl edx, dword ptr [ecx]
+0f4c11|223344556677885f5f5f5f5f5f 32 plan9 CMOVL 0(CX), DX
+0f4c11|223344556677885f5f5f5f5f5f 64 gnu cmovl (%rcx),%edx
+0f4c11|223344556677885f5f5f5f5f5f 64 intel cmovl edx, dword ptr [rcx]
+0f4c11|223344556677885f5f5f5f5f5f 64 plan9 CMOVL 0(CX), DX
+0f4d11|223344556677885f5f5f5f5f5f 32 intel cmovnl edx, dword ptr [ecx]
+0f4d11|223344556677885f5f5f5f5f5f 32 plan9 CMOVGE 0(CX), DX
+0f4d11|223344556677885f5f5f5f5f5f 64 gnu cmovge (%rcx),%edx
+0f4d11|223344556677885f5f5f5f5f5f 64 intel cmovnl edx, dword ptr [rcx]
+0f4d11|223344556677885f5f5f5f5f5f 64 plan9 CMOVGE 0(CX), DX
+0f4e11|223344556677885f5f5f5f5f5f 32 intel cmovle edx, dword ptr [ecx]
+0f4e11|223344556677885f5f5f5f5f5f 32 plan9 CMOVLE 0(CX), DX
+0f4e11|223344556677885f5f5f5f5f5f 64 gnu cmovle (%rcx),%edx
+0f4e11|223344556677885f5f5f5f5f5f 64 intel cmovle edx, dword ptr [rcx]
+0f4e11|223344556677885f5f5f5f5f5f 64 plan9 CMOVLE 0(CX), DX
+0f4f11|223344556677885f5f5f5f5f5f 32 intel cmovnle edx, dword ptr [ecx]
+0f4f11|223344556677885f5f5f5f5f5f 32 plan9 CMOVG 0(CX), DX
+0f4f11|223344556677885f5f5f5f5f5f 64 gnu cmovg (%rcx),%edx
+0f4f11|223344556677885f5f5f5f5f5f 64 intel cmovnle edx, dword ptr [rcx]
+0f4f11|223344556677885f5f5f5f5f5f 64 plan9 CMOVG 0(CX), DX
+0f5011|223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f5011|223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f5011|223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0f5011|223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0f5011|223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f50c0|11223344556677885f5f5f5f5f 32 intel movmskps eax, xmm0
+0f50c0|11223344556677885f5f5f5f5f 32 plan9 MOVMSKPS X0, AX
+0f50c0|11223344556677885f5f5f5f5f 64 gnu movmskps %xmm0,%eax
+0f50c0|11223344556677885f5f5f5f5f 64 intel movmskps eax, xmm0
+0f50c0|11223344556677885f5f5f5f5f 64 plan9 MOVMSKPS X0, AX
+0f5111|223344556677885f5f5f5f5f5f 32 intel sqrtps xmm2, xmmword ptr [ecx]
+0f5111|223344556677885f5f5f5f5f5f 32 plan9 SQRTPS 0(CX), X2
+0f5111|223344556677885f5f5f5f5f5f 64 gnu sqrtps (%rcx),%xmm2
+0f5111|223344556677885f5f5f5f5f5f 64 intel sqrtps xmm2, xmmword ptr [rcx]
+0f5111|223344556677885f5f5f5f5f5f 64 plan9 SQRTPS 0(CX), X2
+0f5211|223344556677885f5f5f5f5f5f 32 intel rsqrtps xmm2, xmmword ptr [ecx]
+0f5211|223344556677885f5f5f5f5f5f 32 plan9 RSQRTPS 0(CX), X2
+0f5211|223344556677885f5f5f5f5f5f 64 gnu rsqrtps (%rcx),%xmm2
+0f5211|223344556677885f5f5f5f5f5f 64 intel rsqrtps xmm2, xmmword ptr [rcx]
+0f5211|223344556677885f5f5f5f5f5f 64 plan9 RSQRTPS 0(CX), X2
+0f5311|223344556677885f5f5f5f5f5f 32 intel rcpps xmm2, xmmword ptr [ecx]
+0f5311|223344556677885f5f5f5f5f5f 32 plan9 RCPPS 0(CX), X2
+0f5311|223344556677885f5f5f5f5f5f 64 gnu rcpps (%rcx),%xmm2
+0f5311|223344556677885f5f5f5f5f5f 64 intel rcpps xmm2, xmmword ptr [rcx]
+0f5311|223344556677885f5f5f5f5f5f 64 plan9 RCPPS 0(CX), X2
+0f5411|223344556677885f5f5f5f5f5f 32 intel andps xmm2, xmmword ptr [ecx]
+0f5411|223344556677885f5f5f5f5f5f 32 plan9 ANDPS 0(CX), X2
+0f5411|223344556677885f5f5f5f5f5f 64 gnu andps (%rcx),%xmm2
+0f5411|223344556677885f5f5f5f5f5f 64 intel andps xmm2, xmmword ptr [rcx]
+0f5411|223344556677885f5f5f5f5f5f 64 plan9 ANDPS 0(CX), X2
+0f5511|223344556677885f5f5f5f5f5f 32 intel andnps xmm2, xmmword ptr [ecx]
+0f5511|223344556677885f5f5f5f5f5f 32 plan9 ANDNPS 0(CX), X2
+0f5511|223344556677885f5f5f5f5f5f 64 gnu andnps (%rcx),%xmm2
+0f5511|223344556677885f5f5f5f5f5f 64 intel andnps xmm2, xmmword ptr [rcx]
+0f5511|223344556677885f5f5f5f5f5f 64 plan9 ANDNPS 0(CX), X2
+0f5611|223344556677885f5f5f5f5f5f 32 intel orps xmm2, xmmword ptr [ecx]
+0f5611|223344556677885f5f5f5f5f5f 32 plan9 ORPS 0(CX), X2
+0f5611|223344556677885f5f5f5f5f5f 64 gnu orps (%rcx),%xmm2
+0f5611|223344556677885f5f5f5f5f5f 64 intel orps xmm2, xmmword ptr [rcx]
+0f5611|223344556677885f5f5f5f5f5f 64 plan9 ORPS 0(CX), X2
+0f5711|223344556677885f5f5f5f5f5f 32 intel xorps xmm2, xmmword ptr [ecx]
+0f5711|223344556677885f5f5f5f5f5f 32 plan9 XORPS 0(CX), X2
+0f5711|223344556677885f5f5f5f5f5f 64 gnu xorps (%rcx),%xmm2
+0f5711|223344556677885f5f5f5f5f5f 64 intel xorps xmm2, xmmword ptr [rcx]
+0f5711|223344556677885f5f5f5f5f5f 64 plan9 XORPS 0(CX), X2
+0f5811|223344556677885f5f5f5f5f5f 32 intel addps xmm2, xmmword ptr [ecx]
+0f5811|223344556677885f5f5f5f5f5f 32 plan9 ADDPS 0(CX), X2
+0f5811|223344556677885f5f5f5f5f5f 64 gnu addps (%rcx),%xmm2
+0f5811|223344556677885f5f5f5f5f5f 64 intel addps xmm2, xmmword ptr [rcx]
+0f5811|223344556677885f5f5f5f5f5f 64 plan9 ADDPS 0(CX), X2
+0f5911|223344556677885f5f5f5f5f5f 32 intel mulps xmm2, xmmword ptr [ecx]
+0f5911|223344556677885f5f5f5f5f5f 32 plan9 MULPS 0(CX), X2
+0f5911|223344556677885f5f5f5f5f5f 64 gnu mulps (%rcx),%xmm2
+0f5911|223344556677885f5f5f5f5f5f 64 intel mulps xmm2, xmmword ptr [rcx]
+0f5911|223344556677885f5f5f5f5f5f 64 plan9 MULPS 0(CX), X2
+0f5a11|223344556677885f5f5f5f5f5f 32 intel cvtps2pd xmm2, qword ptr [ecx]
+0f5a11|223344556677885f5f5f5f5f5f 32 plan9 CVTPS2PD 0(CX), X2
+0f5a11|223344556677885f5f5f5f5f5f 64 gnu cvtps2pd (%rcx),%xmm2
+0f5a11|223344556677885f5f5f5f5f5f 64 intel cvtps2pd xmm2, qword ptr [rcx]
+0f5a11|223344556677885f5f5f5f5f5f 64 plan9 CVTPS2PD 0(CX), X2
+0f5b11|223344556677885f5f5f5f5f5f 32 intel cvtdq2ps xmm2, xmmword ptr [ecx]
+0f5b11|223344556677885f5f5f5f5f5f 32 plan9 CVTDQ2PS 0(CX), X2
+0f5b11|223344556677885f5f5f5f5f5f 64 gnu cvtdq2ps (%rcx),%xmm2
+0f5b11|223344556677885f5f5f5f5f5f 64 intel cvtdq2ps xmm2, xmmword ptr [rcx]
+0f5b11|223344556677885f5f5f5f5f5f 64 plan9 CVTDQ2PS 0(CX), X2
+0f5c11|223344556677885f5f5f5f5f5f 32 intel subps xmm2, xmmword ptr [ecx]
+0f5c11|223344556677885f5f5f5f5f5f 32 plan9 SUBPS 0(CX), X2
+0f5c11|223344556677885f5f5f5f5f5f 64 gnu subps (%rcx),%xmm2
+0f5c11|223344556677885f5f5f5f5f5f 64 intel subps xmm2, xmmword ptr [rcx]
+0f5c11|223344556677885f5f5f5f5f5f 64 plan9 SUBPS 0(CX), X2
+0f5d11|223344556677885f5f5f5f5f5f 32 intel minps xmm2, xmmword ptr [ecx]
+0f5d11|223344556677885f5f5f5f5f5f 32 plan9 MINPS 0(CX), X2
+0f5d11|223344556677885f5f5f5f5f5f 64 gnu minps (%rcx),%xmm2
+0f5d11|223344556677885f5f5f5f5f5f 64 intel minps xmm2, xmmword ptr [rcx]
+0f5d11|223344556677885f5f5f5f5f5f 64 plan9 MINPS 0(CX), X2
+0f5e11|223344556677885f5f5f5f5f5f 32 intel divps xmm2, xmmword ptr [ecx]
+0f5e11|223344556677885f5f5f5f5f5f 32 plan9 DIVPS 0(CX), X2
+0f5e11|223344556677885f5f5f5f5f5f 64 gnu divps (%rcx),%xmm2
+0f5e11|223344556677885f5f5f5f5f5f 64 intel divps xmm2, xmmword ptr [rcx]
+0f5e11|223344556677885f5f5f5f5f5f 64 plan9 DIVPS 0(CX), X2
+0f5f11|223344556677885f5f5f5f5f5f 32 intel maxps xmm2, xmmword ptr [ecx]
+0f5f11|223344556677885f5f5f5f5f5f 32 plan9 MAXPS 0(CX), X2
+0f5f11|223344556677885f5f5f5f5f5f 64 gnu maxps (%rcx),%xmm2
+0f5f11|223344556677885f5f5f5f5f5f 64 intel maxps xmm2, xmmword ptr [rcx]
+0f5f11|223344556677885f5f5f5f5f5f 64 plan9 MAXPS 0(CX), X2
+0f6011|223344556677885f5f5f5f5f5f 32 intel punpcklbw mmx2, dword ptr [ecx]
+0f6011|223344556677885f5f5f5f5f5f 32 plan9 PUNPCKLBW 0(CX), M2
+0f6011|223344556677885f5f5f5f5f5f 64 gnu punpcklbw (%rcx),%mm2
+0f6011|223344556677885f5f5f5f5f5f 64 intel punpcklbw mmx2, dword ptr [rcx]
+0f6011|223344556677885f5f5f5f5f5f 64 plan9 PUNPCKLBW 0(CX), M2
+0f6111|223344556677885f5f5f5f5f5f 32 intel punpcklwd mmx2, dword ptr [ecx]
+0f6111|223344556677885f5f5f5f5f5f 32 plan9 PUNPCKLWD 0(CX), M2
+0f6111|223344556677885f5f5f5f5f5f 64 gnu punpcklwd (%rcx),%mm2
+0f6111|223344556677885f5f5f5f5f5f 64 intel punpcklwd mmx2, dword ptr [rcx]
+0f6111|223344556677885f5f5f5f5f5f 64 plan9 PUNPCKLWD 0(CX), M2
+0f6211|223344556677885f5f5f5f5f5f 32 intel punpckldq mmx2, dword ptr [ecx]
+0f6211|223344556677885f5f5f5f5f5f 32 plan9 PUNPCKLDQ 0(CX), M2
+0f6211|223344556677885f5f5f5f5f5f 64 gnu punpckldq (%rcx),%mm2
+0f6211|223344556677885f5f5f5f5f5f 64 intel punpckldq mmx2, dword ptr [rcx]
+0f6211|223344556677885f5f5f5f5f5f 64 plan9 PUNPCKLDQ 0(CX), M2
+0f6311|223344556677885f5f5f5f5f5f 32 intel packsswb mmx2, qword ptr [ecx]
+0f6311|223344556677885f5f5f5f5f5f 32 plan9 PACKSSWB 0(CX), M2
+0f6311|223344556677885f5f5f5f5f5f 64 gnu packsswb (%rcx),%mm2
+0f6311|223344556677885f5f5f5f5f5f 64 intel packsswb mmx2, qword ptr [rcx]
+0f6311|223344556677885f5f5f5f5f5f 64 plan9 PACKSSWB 0(CX), M2
+0f6411|223344556677885f5f5f5f5f5f 32 intel pcmpgtb mmx2, qword ptr [ecx]
+0f6411|223344556677885f5f5f5f5f5f 32 plan9 PCMPGTB 0(CX), M2
+0f6411|223344556677885f5f5f5f5f5f 64 gnu pcmpgtb (%rcx),%mm2
+0f6411|223344556677885f5f5f5f5f5f 64 intel pcmpgtb mmx2, qword ptr [rcx]
+0f6411|223344556677885f5f5f5f5f5f 64 plan9 PCMPGTB 0(CX), M2
+0f6511|223344556677885f5f5f5f5f5f 32 intel pcmpgtw mmx2, qword ptr [ecx]
+0f6511|223344556677885f5f5f5f5f5f 32 plan9 PCMPGTW 0(CX), M2
+0f6511|223344556677885f5f5f5f5f5f 64 gnu pcmpgtw (%rcx),%mm2
+0f6511|223344556677885f5f5f5f5f5f 64 intel pcmpgtw mmx2, qword ptr [rcx]
+0f6511|223344556677885f5f5f5f5f5f 64 plan9 PCMPGTW 0(CX), M2
+0f6611|223344556677885f5f5f5f5f5f 32 intel pcmpgtd mmx2, qword ptr [ecx]
+0f6611|223344556677885f5f5f5f5f5f 32 plan9 PCMPGTD 0(CX), M2
+0f6611|223344556677885f5f5f5f5f5f 64 gnu pcmpgtd (%rcx),%mm2
+0f6611|223344556677885f5f5f5f5f5f 64 intel pcmpgtd mmx2, qword ptr [rcx]
+0f6611|223344556677885f5f5f5f5f5f 64 plan9 PCMPGTD 0(CX), M2
+0f6711|223344556677885f5f5f5f5f5f 32 intel packuswb mmx2, qword ptr [ecx]
+0f6711|223344556677885f5f5f5f5f5f 32 plan9 PACKUSWB 0(CX), M2
+0f6711|223344556677885f5f5f5f5f5f 64 gnu packuswb (%rcx),%mm2
+0f6711|223344556677885f5f5f5f5f5f 64 intel packuswb mmx2, qword ptr [rcx]
+0f6711|223344556677885f5f5f5f5f5f 64 plan9 PACKUSWB 0(CX), M2
+0f6811|223344556677885f5f5f5f5f5f 32 intel punpckhbw mmx2, qword ptr [ecx]
+0f6811|223344556677885f5f5f5f5f5f 32 plan9 PUNPCKHBW 0(CX), M2
+0f6811|223344556677885f5f5f5f5f5f 64 gnu punpckhbw (%rcx),%mm2
+0f6811|223344556677885f5f5f5f5f5f 64 intel punpckhbw mmx2, qword ptr [rcx]
+0f6811|223344556677885f5f5f5f5f5f 64 plan9 PUNPCKHBW 0(CX), M2
+0f6911|223344556677885f5f5f5f5f5f 32 intel punpckhwd mmx2, qword ptr [ecx]
+0f6911|223344556677885f5f5f5f5f5f 32 plan9 PUNPCKHWD 0(CX), M2
+0f6911|223344556677885f5f5f5f5f5f 64 gnu punpckhwd (%rcx),%mm2
+0f6911|223344556677885f5f5f5f5f5f 64 intel punpckhwd mmx2, qword ptr [rcx]
+0f6911|223344556677885f5f5f5f5f5f 64 plan9 PUNPCKHWD 0(CX), M2
+0f6a11|223344556677885f5f5f5f5f5f 32 intel punpckhdq mmx2, qword ptr [ecx]
+0f6a11|223344556677885f5f5f5f5f5f 32 plan9 PUNPCKHDQ 0(CX), M2
+0f6a11|223344556677885f5f5f5f5f5f 64 gnu punpckhdq (%rcx),%mm2
+0f6a11|223344556677885f5f5f5f5f5f 64 intel punpckhdq mmx2, qword ptr [rcx]
+0f6a11|223344556677885f5f5f5f5f5f 64 plan9 PUNPCKHDQ 0(CX), M2
+0f6b11|223344556677885f5f5f5f5f5f 32 intel packssdw mmx2, qword ptr [ecx]
+0f6b11|223344556677885f5f5f5f5f5f 32 plan9 PACKSSDW 0(CX), M2
+0f6b11|223344556677885f5f5f5f5f5f 64 gnu packssdw (%rcx),%mm2
+0f6b11|223344556677885f5f5f5f5f5f 64 intel packssdw mmx2, qword ptr [rcx]
+0f6b11|223344556677885f5f5f5f5f5f 64 plan9 PACKSSDW 0(CX), M2
+0f6c|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f6c|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f6c|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0f6c|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0f6c|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f6d|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f6d|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f6d|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0f6d|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0f6d|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f6e11|223344556677885f5f5f5f5f5f 32 intel movd mmx2, dword ptr [ecx]
+0f6e11|223344556677885f5f5f5f5f5f 32 plan9 MOVD 0(CX), M2
+0f6e11|223344556677885f5f5f5f5f5f 64 gnu movd (%rcx),%mm2
+0f6e11|223344556677885f5f5f5f5f5f 64 intel movd mmx2, dword ptr [rcx]
+0f6e11|223344556677885f5f5f5f5f5f 64 plan9 MOVD 0(CX), M2
+0f6f11|223344556677885f5f5f5f5f5f 32 intel movq mmx2, qword ptr [ecx]
+0f6f11|223344556677885f5f5f5f5f5f 32 plan9 MOVQ 0(CX), M2
+0f6f11|223344556677885f5f5f5f5f5f 64 gnu movq (%rcx),%mm2
+0f6f11|223344556677885f5f5f5f5f5f 64 intel movq mmx2, qword ptr [rcx]
+0f6f11|223344556677885f5f5f5f5f5f 64 plan9 MOVQ 0(CX), M2
+0f701122|3344556677885f5f5f5f5f5f 32 intel pshufw mmx2, qword ptr [ecx], 0x22
+0f701122|3344556677885f5f5f5f5f5f 32 plan9 PSHUFW $0x22, 0(CX), M2
+0f701122|3344556677885f5f5f5f5f5f 64 gnu pshufw $0x22,(%rcx),%mm2
+0f701122|3344556677885f5f5f5f5f5f 64 intel pshufw mmx2, qword ptr [rcx], 0x22
+0f701122|3344556677885f5f5f5f5f5f 64 plan9 PSHUFW $0x22, 0(CX), M2
+0f7100|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f7100|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f7100|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f7100|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f7100|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f711122|3344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f711122|3344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f711122|3344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0f711122|3344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0f711122|3344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f712011|223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f712011|223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f712011|223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f712011|223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f712011|223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f713011|223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f713011|223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f713011|223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f713011|223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f713011|223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f71d011|223344556677885f5f5f5f5f 32 intel psrlw mmx0, 0x11
+0f71d011|223344556677885f5f5f5f5f 32 plan9 PSRLW $0x11, M0
+0f71d011|223344556677885f5f5f5f5f 64 gnu psrlw $0x11,%mm0
+0f71d011|223344556677885f5f5f5f5f 64 intel psrlw mmx0, 0x11
+0f71d011|223344556677885f5f5f5f5f 64 plan9 PSRLW $0x11, M0
+0f71e011|223344556677885f5f5f5f5f 32 intel psraw mmx0, 0x11
+0f71e011|223344556677885f5f5f5f5f 32 plan9 PSRAW $0x11, M0
+0f71e011|223344556677885f5f5f5f5f 64 gnu psraw $0x11,%mm0
+0f71e011|223344556677885f5f5f5f5f 64 intel psraw mmx0, 0x11
+0f71e011|223344556677885f5f5f5f5f 64 plan9 PSRAW $0x11, M0
+0f71f011|223344556677885f5f5f5f5f 32 intel psllw mmx0, 0x11
+0f71f011|223344556677885f5f5f5f5f 32 plan9 PSLLW $0x11, M0
+0f71f011|223344556677885f5f5f5f5f 64 gnu psllw $0x11,%mm0
+0f71f011|223344556677885f5f5f5f5f 64 intel psllw mmx0, 0x11
+0f71f011|223344556677885f5f5f5f5f 64 plan9 PSLLW $0x11, M0
+0f7200|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f7200|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f7200|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f7200|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f7200|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f721122|3344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f721122|3344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f721122|3344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0f721122|3344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0f721122|3344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f722011|223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f722011|223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f722011|223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f722011|223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f722011|223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f723011|223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f723011|223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f723011|223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f723011|223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f723011|223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f72d011|223344556677885f5f5f5f5f 32 intel psrld mmx0, 0x11
+0f72d011|223344556677885f5f5f5f5f 32 plan9 PSRLD $0x11, M0
+0f72d011|223344556677885f5f5f5f5f 64 gnu psrld $0x11,%mm0
+0f72d011|223344556677885f5f5f5f5f 64 intel psrld mmx0, 0x11
+0f72d011|223344556677885f5f5f5f5f 64 plan9 PSRLD $0x11, M0
+0f72e011|223344556677885f5f5f5f5f 32 intel psrad mmx0, 0x11
+0f72e011|223344556677885f5f5f5f5f 32 plan9 PSRAD $0x11, M0
+0f72e011|223344556677885f5f5f5f5f 64 gnu psrad $0x11,%mm0
+0f72e011|223344556677885f5f5f5f5f 64 intel psrad mmx0, 0x11
+0f72e011|223344556677885f5f5f5f5f 64 plan9 PSRAD $0x11, M0
+0f72f011|223344556677885f5f5f5f5f 32 intel pslld mmx0, 0x11
+0f72f011|223344556677885f5f5f5f5f 32 plan9 PSLLD $0x11, M0
+0f72f011|223344556677885f5f5f5f5f 64 gnu pslld $0x11,%mm0
+0f72f011|223344556677885f5f5f5f5f 64 intel pslld mmx0, 0x11
+0f72f011|223344556677885f5f5f5f5f 64 plan9 PSLLD $0x11, M0
+0f7300|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f7300|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f7300|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f7300|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f7300|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f731122|3344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f731122|3344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f731122|3344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0f731122|3344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0f731122|3344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f7318|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f7318|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f7318|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f7318|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f7318|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f733011|223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f733011|223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f733011|223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f733011|223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f733011|223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f7338|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0f7338|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f7338|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0f7338|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0f7338|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f73d011|223344556677885f5f5f5f5f 32 intel psrlq mmx0, 0x11
+0f73d011|223344556677885f5f5f5f5f 32 plan9 PSRLQ $0x11, M0
+0f73d011|223344556677885f5f5f5f5f 64 gnu psrlq $0x11,%mm0
+0f73d011|223344556677885f5f5f5f5f 64 intel psrlq mmx0, 0x11
+0f73d011|223344556677885f5f5f5f5f 64 plan9 PSRLQ $0x11, M0
+0f73f011|223344556677885f5f5f5f5f 32 intel psllq mmx0, 0x11
+0f73f011|223344556677885f5f5f5f5f 32 plan9 PSLLQ $0x11, M0
+0f73f011|223344556677885f5f5f5f5f 64 gnu psllq $0x11,%mm0
+0f73f011|223344556677885f5f5f5f5f 64 intel psllq mmx0, 0x11
+0f73f011|223344556677885f5f5f5f5f 64 plan9 PSLLQ $0x11, M0
+0f7411|223344556677885f5f5f5f5f5f 32 intel pcmpeqb mmx2, qword ptr [ecx]
+0f7411|223344556677885f5f5f5f5f5f 32 plan9 PCMPEQB 0(CX), M2
+0f7411|223344556677885f5f5f5f5f5f 64 gnu pcmpeqb (%rcx),%mm2
+0f7411|223344556677885f5f5f5f5f5f 64 intel pcmpeqb mmx2, qword ptr [rcx]
+0f7411|223344556677885f5f5f5f5f5f 64 plan9 PCMPEQB 0(CX), M2
+0f7511|223344556677885f5f5f5f5f5f 32 intel pcmpeqw mmx2, qword ptr [ecx]
+0f7511|223344556677885f5f5f5f5f5f 32 plan9 PCMPEQW 0(CX), M2
+0f7511|223344556677885f5f5f5f5f5f 64 gnu pcmpeqw (%rcx),%mm2
+0f7511|223344556677885f5f5f5f5f5f 64 intel pcmpeqw mmx2, qword ptr [rcx]
+0f7511|223344556677885f5f5f5f5f5f 64 plan9 PCMPEQW 0(CX), M2
+0f7611|223344556677885f5f5f5f5f5f 32 intel pcmpeqd mmx2, qword ptr [ecx]
+0f7611|223344556677885f5f5f5f5f5f 32 plan9 PCMPEQD 0(CX), M2
+0f7611|223344556677885f5f5f5f5f5f 64 gnu pcmpeqd (%rcx),%mm2
+0f7611|223344556677885f5f5f5f5f5f 64 intel pcmpeqd mmx2, qword ptr [rcx]
+0f7611|223344556677885f5f5f5f5f5f 64 plan9 PCMPEQD 0(CX), M2
+0f77|11223344556677885f5f5f5f5f5f 32 intel emms
+0f77|11223344556677885f5f5f5f5f5f 32 plan9 EMMS
+0f77|11223344556677885f5f5f5f5f5f 64 gnu emms
+0f77|11223344556677885f5f5f5f5f5f 64 intel emms
+0f77|11223344556677885f5f5f5f5f5f 64 plan9 EMMS
+0f7c|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f7c|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f7c|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0f7c|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0f7c|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f7d|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0f7d|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0f7d|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0f7d|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0f7d|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0f7e11|223344556677885f5f5f5f5f5f 32 intel movd dword ptr [ecx], mmx2
+0f7e11|223344556677885f5f5f5f5f5f 32 plan9 MOVD M2, 0(CX)
+0f7e11|223344556677885f5f5f5f5f5f 64 gnu movd %mm2,(%rcx)
+0f7e11|223344556677885f5f5f5f5f5f 64 intel movd dword ptr [rcx], mmx2
+0f7e11|223344556677885f5f5f5f5f5f 64 plan9 MOVD M2, 0(CX)
+0f7f11|223344556677885f5f5f5f5f5f 32 intel movq qword ptr [ecx], mmx2
+0f7f11|223344556677885f5f5f5f5f5f 32 plan9 MOVQ M2, 0(CX)
+0f7f11|223344556677885f5f5f5f5f5f 64 gnu movq %mm2,(%rcx)
+0f7f11|223344556677885f5f5f5f5f5f 64 intel movq qword ptr [rcx], mmx2
+0f7f11|223344556677885f5f5f5f5f5f 64 plan9 MOVQ M2, 0(CX)
+0f8011223344|556677885f5f5f5f5f5f 32 intel jo .+0x44332211
+0f8011223344|556677885f5f5f5f5f5f 32 plan9 JO .+1144201745
+0f8011223344|556677885f5f5f5f5f5f 64 gnu jo .+0x44332211
+0f8011223344|556677885f5f5f5f5f5f 64 intel jo .+0x44332211
+0f8011223344|556677885f5f5f5f5f5f 64 plan9 JO .+1144201745
+0f8111223344|556677885f5f5f5f5f5f 32 intel jno .+0x44332211
+0f8111223344|556677885f5f5f5f5f5f 32 plan9 JNO .+1144201745
+0f8111223344|556677885f5f5f5f5f5f 64 gnu jno .+0x44332211
+0f8111223344|556677885f5f5f5f5f5f 64 intel jno .+0x44332211
+0f8111223344|556677885f5f5f5f5f5f 64 plan9 JNO .+1144201745
+0f8211223344|556677885f5f5f5f5f5f 32 intel jb .+0x44332211
+0f8211223344|556677885f5f5f5f5f5f 32 plan9 JB .+1144201745
+0f8211223344|556677885f5f5f5f5f5f 64 gnu jb .+0x44332211
+0f8211223344|556677885f5f5f5f5f5f 64 intel jb .+0x44332211
+0f8211223344|556677885f5f5f5f5f5f 64 plan9 JB .+1144201745
+0f8311223344|556677885f5f5f5f5f5f 32 intel jnb .+0x44332211
+0f8311223344|556677885f5f5f5f5f5f 32 plan9 JAE .+1144201745
+0f8311223344|556677885f5f5f5f5f5f 64 gnu jae .+0x44332211
+0f8311223344|556677885f5f5f5f5f5f 64 intel jnb .+0x44332211
+0f8311223344|556677885f5f5f5f5f5f 64 plan9 JAE .+1144201745
+0f8411223344|556677885f5f5f5f5f5f 32 intel jz .+0x44332211
+0f8411223344|556677885f5f5f5f5f5f 32 plan9 JE .+1144201745
+0f8411223344|556677885f5f5f5f5f5f 64 gnu je .+0x44332211
+0f8411223344|556677885f5f5f5f5f5f 64 intel jz .+0x44332211
+0f8411223344|556677885f5f5f5f5f5f 64 plan9 JE .+1144201745
+0f8511223344|556677885f5f5f5f5f5f 32 intel jnz .+0x44332211
+0f8511223344|556677885f5f5f5f5f5f 32 plan9 JNE .+1144201745
+0f8511223344|556677885f5f5f5f5f5f 64 gnu jne .+0x44332211
+0f8511223344|556677885f5f5f5f5f5f 64 intel jnz .+0x44332211
+0f8511223344|556677885f5f5f5f5f5f 64 plan9 JNE .+1144201745
+0f8611223344|556677885f5f5f5f5f5f 32 intel jbe .+0x44332211
+0f8611223344|556677885f5f5f5f5f5f 32 plan9 JBE .+1144201745
+0f8611223344|556677885f5f5f5f5f5f 64 gnu jbe .+0x44332211
+0f8611223344|556677885f5f5f5f5f5f 64 intel jbe .+0x44332211
+0f8611223344|556677885f5f5f5f5f5f 64 plan9 JBE .+1144201745
+0f8711223344|556677885f5f5f5f5f5f 32 intel jnbe .+0x44332211
+0f8711223344|556677885f5f5f5f5f5f 32 plan9 JA .+1144201745
+0f8711223344|556677885f5f5f5f5f5f 64 gnu ja .+0x44332211
+0f8711223344|556677885f5f5f5f5f5f 64 intel jnbe .+0x44332211
+0f8711223344|556677885f5f5f5f5f5f 64 plan9 JA .+1144201745
+0f8811223344|556677885f5f5f5f5f5f 32 intel js .+0x44332211
+0f8811223344|556677885f5f5f5f5f5f 32 plan9 JS .+1144201745
+0f8811223344|556677885f5f5f5f5f5f 64 gnu js .+0x44332211
+0f8811223344|556677885f5f5f5f5f5f 64 intel js .+0x44332211
+0f8811223344|556677885f5f5f5f5f5f 64 plan9 JS .+1144201745
+0f8911223344|556677885f5f5f5f5f5f 32 intel jns .+0x44332211
+0f8911223344|556677885f5f5f5f5f5f 32 plan9 JNS .+1144201745
+0f8911223344|556677885f5f5f5f5f5f 64 gnu jns .+0x44332211
+0f8911223344|556677885f5f5f5f5f5f 64 intel jns .+0x44332211
+0f8911223344|556677885f5f5f5f5f5f 64 plan9 JNS .+1144201745
+0f8a11223344|556677885f5f5f5f5f5f 32 intel jp .+0x44332211
+0f8a11223344|556677885f5f5f5f5f5f 32 plan9 JP .+1144201745
+0f8a11223344|556677885f5f5f5f5f5f 64 gnu jp .+0x44332211
+0f8a11223344|556677885f5f5f5f5f5f 64 intel jp .+0x44332211
+0f8a11223344|556677885f5f5f5f5f5f 64 plan9 JP .+1144201745
+0f8b11223344|556677885f5f5f5f5f5f 32 intel jnp .+0x44332211
+0f8b11223344|556677885f5f5f5f5f5f 32 plan9 JNP .+1144201745
+0f8b11223344|556677885f5f5f5f5f5f 64 gnu jnp .+0x44332211
+0f8b11223344|556677885f5f5f5f5f5f 64 intel jnp .+0x44332211
+0f8b11223344|556677885f5f5f5f5f5f 64 plan9 JNP .+1144201745
+0f8c11223344|556677885f5f5f5f5f5f 32 intel jl .+0x44332211
+0f8c11223344|556677885f5f5f5f5f5f 32 plan9 JL .+1144201745
+0f8c11223344|556677885f5f5f5f5f5f 64 gnu jl .+0x44332211
+0f8c11223344|556677885f5f5f5f5f5f 64 intel jl .+0x44332211
+0f8c11223344|556677885f5f5f5f5f5f 64 plan9 JL .+1144201745
+0f8d11223344|556677885f5f5f5f5f5f 32 intel jnl .+0x44332211
+0f8d11223344|556677885f5f5f5f5f5f 32 plan9 JGE .+1144201745
+0f8d11223344|556677885f5f5f5f5f5f 64 gnu jge .+0x44332211
+0f8d11223344|556677885f5f5f5f5f5f 64 intel jnl .+0x44332211
+0f8d11223344|556677885f5f5f5f5f5f 64 plan9 JGE .+1144201745
+0f8e11223344|556677885f5f5f5f5f5f 32 intel jle .+0x44332211
+0f8e11223344|556677885f5f5f5f5f5f 32 plan9 JLE .+1144201745
+0f8e11223344|556677885f5f5f5f5f5f 64 gnu jle .+0x44332211
+0f8e11223344|556677885f5f5f5f5f5f 64 intel jle .+0x44332211
+0f8e11223344|556677885f5f5f5f5f5f 64 plan9 JLE .+1144201745
+0f8f11223344|556677885f5f5f5f5f5f 32 intel jnle .+0x44332211
+0f8f11223344|556677885f5f5f5f5f5f 32 plan9 JG .+1144201745
+0f8f11223344|556677885f5f5f5f5f5f 64 gnu jg .+0x44332211
+0f8f11223344|556677885f5f5f5f5f5f 64 intel jnle .+0x44332211
+0f8f11223344|556677885f5f5f5f5f5f 64 plan9 JG .+1144201745
+0f9011|223344556677885f5f5f5f5f5f 32 intel seto byte ptr [ecx]
+0f9011|223344556677885f5f5f5f5f5f 32 plan9 SETO 0(CX)
+0f9011|223344556677885f5f5f5f5f5f 64 gnu seto (%rcx)
+0f9011|223344556677885f5f5f5f5f5f 64 intel seto byte ptr [rcx]
+0f9011|223344556677885f5f5f5f5f5f 64 plan9 SETO 0(CX)
+0f9111|223344556677885f5f5f5f5f5f 32 intel setno byte ptr [ecx]
+0f9111|223344556677885f5f5f5f5f5f 32 plan9 SETNO 0(CX)
+0f9111|223344556677885f5f5f5f5f5f 64 gnu setno (%rcx)
+0f9111|223344556677885f5f5f5f5f5f 64 intel setno byte ptr [rcx]
+0f9111|223344556677885f5f5f5f5f5f 64 plan9 SETNO 0(CX)
+0f9211|223344556677885f5f5f5f5f5f 32 intel setb byte ptr [ecx]
+0f9211|223344556677885f5f5f5f5f5f 32 plan9 SETB 0(CX)
+0f9211|223344556677885f5f5f5f5f5f 64 gnu setb (%rcx)
+0f9211|223344556677885f5f5f5f5f5f 64 intel setb byte ptr [rcx]
+0f9211|223344556677885f5f5f5f5f5f 64 plan9 SETB 0(CX)
+0f9311|223344556677885f5f5f5f5f5f 32 intel setnb byte ptr [ecx]
+0f9311|223344556677885f5f5f5f5f5f 32 plan9 SETAE 0(CX)
+0f9311|223344556677885f5f5f5f5f5f 64 gnu setae (%rcx)
+0f9311|223344556677885f5f5f5f5f5f 64 intel setnb byte ptr [rcx]
+0f9311|223344556677885f5f5f5f5f5f 64 plan9 SETAE 0(CX)
+0f9411|223344556677885f5f5f5f5f5f 32 intel setz byte ptr [ecx]
+0f9411|223344556677885f5f5f5f5f5f 32 plan9 SETE 0(CX)
+0f9411|223344556677885f5f5f5f5f5f 64 gnu sete (%rcx)
+0f9411|223344556677885f5f5f5f5f5f 64 intel setz byte ptr [rcx]
+0f9411|223344556677885f5f5f5f5f5f 64 plan9 SETE 0(CX)
+0f9511|223344556677885f5f5f5f5f5f 32 intel setnz byte ptr [ecx]
+0f9511|223344556677885f5f5f5f5f5f 32 plan9 SETNE 0(CX)
+0f9511|223344556677885f5f5f5f5f5f 64 gnu setne (%rcx)
+0f9511|223344556677885f5f5f5f5f5f 64 intel setnz byte ptr [rcx]
+0f9511|223344556677885f5f5f5f5f5f 64 plan9 SETNE 0(CX)
+0f9611|223344556677885f5f5f5f5f5f 32 intel setbe byte ptr [ecx]
+0f9611|223344556677885f5f5f5f5f5f 32 plan9 SETBE 0(CX)
+0f9611|223344556677885f5f5f5f5f5f 64 gnu setbe (%rcx)
+0f9611|223344556677885f5f5f5f5f5f 64 intel setbe byte ptr [rcx]
+0f9611|223344556677885f5f5f5f5f5f 64 plan9 SETBE 0(CX)
+0f9711|223344556677885f5f5f5f5f5f 32 intel setnbe byte ptr [ecx]
+0f9711|223344556677885f5f5f5f5f5f 32 plan9 SETA 0(CX)
+0f9711|223344556677885f5f5f5f5f5f 64 gnu seta (%rcx)
+0f9711|223344556677885f5f5f5f5f5f 64 intel setnbe byte ptr [rcx]
+0f9711|223344556677885f5f5f5f5f5f 64 plan9 SETA 0(CX)
+0f9811|223344556677885f5f5f5f5f5f 32 intel sets byte ptr [ecx]
+0f9811|223344556677885f5f5f5f5f5f 32 plan9 SETS 0(CX)
+0f9811|223344556677885f5f5f5f5f5f 64 gnu sets (%rcx)
+0f9811|223344556677885f5f5f5f5f5f 64 intel sets byte ptr [rcx]
+0f9811|223344556677885f5f5f5f5f5f 64 plan9 SETS 0(CX)
+0f9911|223344556677885f5f5f5f5f5f 32 intel setns byte ptr [ecx]
+0f9911|223344556677885f5f5f5f5f5f 32 plan9 SETNS 0(CX)
+0f9911|223344556677885f5f5f5f5f5f 64 gnu setns (%rcx)
+0f9911|223344556677885f5f5f5f5f5f 64 intel setns byte ptr [rcx]
+0f9911|223344556677885f5f5f5f5f5f 64 plan9 SETNS 0(CX)
+0f9a11|223344556677885f5f5f5f5f5f 32 intel setp byte ptr [ecx]
+0f9a11|223344556677885f5f5f5f5f5f 32 plan9 SETP 0(CX)
+0f9a11|223344556677885f5f5f5f5f5f 64 gnu setp (%rcx)
+0f9a11|223344556677885f5f5f5f5f5f 64 intel setp byte ptr [rcx]
+0f9a11|223344556677885f5f5f5f5f5f 64 plan9 SETP 0(CX)
+0f9b11|223344556677885f5f5f5f5f5f 32 intel setnp byte ptr [ecx]
+0f9b11|223344556677885f5f5f5f5f5f 32 plan9 SETNP 0(CX)
+0f9b11|223344556677885f5f5f5f5f5f 64 gnu setnp (%rcx)
+0f9b11|223344556677885f5f5f5f5f5f 64 intel setnp byte ptr [rcx]
+0f9b11|223344556677885f5f5f5f5f5f 64 plan9 SETNP 0(CX)
+0f9c11|223344556677885f5f5f5f5f5f 32 intel setl byte ptr [ecx]
+0f9c11|223344556677885f5f5f5f5f5f 32 plan9 SETL 0(CX)
+0f9c11|223344556677885f5f5f5f5f5f 64 gnu setl (%rcx)
+0f9c11|223344556677885f5f5f5f5f5f 64 intel setl byte ptr [rcx]
+0f9c11|223344556677885f5f5f5f5f5f 64 plan9 SETL 0(CX)
+0f9d11|223344556677885f5f5f5f5f5f 32 intel setnl byte ptr [ecx]
+0f9d11|223344556677885f5f5f5f5f5f 32 plan9 SETGE 0(CX)
+0f9d11|223344556677885f5f5f5f5f5f 64 gnu setge (%rcx)
+0f9d11|223344556677885f5f5f5f5f5f 64 intel setnl byte ptr [rcx]
+0f9d11|223344556677885f5f5f5f5f5f 64 plan9 SETGE 0(CX)
+0f9e11|223344556677885f5f5f5f5f5f 32 intel setle byte ptr [ecx]
+0f9e11|223344556677885f5f5f5f5f5f 32 plan9 SETLE 0(CX)
+0f9e11|223344556677885f5f5f5f5f5f 64 gnu setle (%rcx)
+0f9e11|223344556677885f5f5f5f5f5f 64 intel setle byte ptr [rcx]
+0f9e11|223344556677885f5f5f5f5f5f 64 plan9 SETLE 0(CX)
+0f9f11|223344556677885f5f5f5f5f5f 32 intel setnle byte ptr [ecx]
+0f9f11|223344556677885f5f5f5f5f5f 32 plan9 SETG 0(CX)
+0f9f11|223344556677885f5f5f5f5f5f 64 gnu setg (%rcx)
+0f9f11|223344556677885f5f5f5f5f5f 64 intel setnle byte ptr [rcx]
+0f9f11|223344556677885f5f5f5f5f5f 64 plan9 SETG 0(CX)
+0fa0|11223344556677885f5f5f5f5f5f 32 intel push fs
+0fa0|11223344556677885f5f5f5f5f5f 32 plan9 PUSHL FS
+0fa0|11223344556677885f5f5f5f5f5f 64 gnu pushq %fs
+0fa0|11223344556677885f5f5f5f5f5f 64 intel push fs
+0fa0|11223344556677885f5f5f5f5f5f 64 plan9 PUSHL FS
+0fa1|11223344556677885f5f5f5f5f5f 32 intel pop fs
+0fa1|11223344556677885f5f5f5f5f5f 32 plan9 POPL FS
+0fa1|11223344556677885f5f5f5f5f5f 64 gnu popq %fs
+0fa1|11223344556677885f5f5f5f5f5f 64 intel pop fs
+0fa1|11223344556677885f5f5f5f5f5f 64 plan9 POPL FS
+0fa2|11223344556677885f5f5f5f5f5f 32 intel cpuid
+0fa2|11223344556677885f5f5f5f5f5f 32 plan9 CPUID
+0fa2|11223344556677885f5f5f5f5f5f 64 gnu cpuid
+0fa2|11223344556677885f5f5f5f5f5f 64 intel cpuid
+0fa2|11223344556677885f5f5f5f5f5f 64 plan9 CPUID
+0fa311|223344556677885f5f5f5f5f5f 32 intel bt dword ptr [ecx], edx
+0fa311|223344556677885f5f5f5f5f5f 32 plan9 BTL DX, 0(CX)
+0fa311|223344556677885f5f5f5f5f5f 64 gnu bt %edx,(%rcx)
+0fa311|223344556677885f5f5f5f5f5f 64 intel bt dword ptr [rcx], edx
+0fa311|223344556677885f5f5f5f5f5f 64 plan9 BTL DX, 0(CX)
+0fa41122|3344556677885f5f5f5f5f5f 32 intel shld dword ptr [ecx], edx, 0x22
+0fa41122|3344556677885f5f5f5f5f5f 32 plan9 SHLDL $0x22, DX, 0(CX)
+0fa41122|3344556677885f5f5f5f5f5f 64 gnu shld $0x22,%edx,(%rcx)
+0fa41122|3344556677885f5f5f5f5f5f 64 intel shld dword ptr [rcx], edx, 0x22
+0fa41122|3344556677885f5f5f5f5f5f 64 plan9 SHLDL $0x22, DX, 0(CX)
+0fa511|223344556677885f5f5f5f5f5f 32 intel shld dword ptr [ecx], edx, cl
+0fa511|223344556677885f5f5f5f5f5f 32 plan9 SHLDL CL, DX, 0(CX)
+0fa511|223344556677885f5f5f5f5f5f 64 gnu shld %cl,%edx,(%rcx)
+0fa511|223344556677885f5f5f5f5f5f 64 intel shld dword ptr [rcx], edx, cl
+0fa511|223344556677885f5f5f5f5f5f 64 plan9 SHLDL CL, DX, 0(CX)
+0fa8|11223344556677885f5f5f5f5f5f 32 intel push gs
+0fa8|11223344556677885f5f5f5f5f5f 32 plan9 PUSHL GS
+0fa8|11223344556677885f5f5f5f5f5f 64 gnu pushq %gs
+0fa8|11223344556677885f5f5f5f5f5f 64 intel push gs
+0fa8|11223344556677885f5f5f5f5f5f 64 plan9 PUSHL GS
+0fa9|11223344556677885f5f5f5f5f5f 32 intel pop gs
+0fa9|11223344556677885f5f5f5f5f5f 32 plan9 POPL GS
+0fa9|11223344556677885f5f5f5f5f5f 64 gnu popq %gs
+0fa9|11223344556677885f5f5f5f5f5f 64 intel pop gs
+0fa9|11223344556677885f5f5f5f5f5f 64 plan9 POPL GS
+0faa|11223344556677885f5f5f5f5f5f 32 intel rsm
+0faa|11223344556677885f5f5f5f5f5f 32 plan9 RSM
+0faa|11223344556677885f5f5f5f5f5f 64 gnu rsm
+0faa|11223344556677885f5f5f5f5f5f 64 intel rsm
+0faa|11223344556677885f5f5f5f5f5f 64 plan9 RSM
+0fab11|223344556677885f5f5f5f5f5f 32 intel bts dword ptr [ecx], edx
+0fab11|223344556677885f5f5f5f5f5f 32 plan9 BTSL DX, 0(CX)
+0fab11|223344556677885f5f5f5f5f5f 64 gnu bts %edx,(%rcx)
+0fab11|223344556677885f5f5f5f5f5f 64 intel bts dword ptr [rcx], edx
+0fab11|223344556677885f5f5f5f5f5f 64 plan9 BTSL DX, 0(CX)
+0fac1122|3344556677885f5f5f5f5f5f 32 intel shrd dword ptr [ecx], edx, 0x22
+0fac1122|3344556677885f5f5f5f5f5f 32 plan9 SHRDL $0x22, DX, 0(CX)
+0fac1122|3344556677885f5f5f5f5f5f 64 gnu shrd $0x22,%edx,(%rcx)
+0fac1122|3344556677885f5f5f5f5f5f 64 intel shrd dword ptr [rcx], edx, 0x22
+0fac1122|3344556677885f5f5f5f5f5f 64 plan9 SHRDL $0x22, DX, 0(CX)
+0fad11|223344556677885f5f5f5f5f5f 32 intel shrd dword ptr [ecx], edx, cl
+0fad11|223344556677885f5f5f5f5f5f 32 plan9 SHRDL CL, DX, 0(CX)
+0fad11|223344556677885f5f5f5f5f5f 64 gnu shrd %cl,%edx,(%rcx)
+0fad11|223344556677885f5f5f5f5f5f 64 intel shrd dword ptr [rcx], edx, cl
+0fad11|223344556677885f5f5f5f5f5f 64 plan9 SHRDL CL, DX, 0(CX)
+0fae00|11223344556677885f5f5f5f5f 32 intel fxsave ptr [eax]
+0fae00|11223344556677885f5f5f5f5f 32 plan9 FXSAVE 0(AX)
+0fae00|11223344556677885f5f5f5f5f 64 gnu fxsave (%rax)
+0fae00|11223344556677885f5f5f5f5f 64 intel fxsave ptr [rax]
+0fae00|11223344556677885f5f5f5f5f 64 plan9 FXSAVE 0(AX)
+0fae08|11223344556677885f5f5f5f5f 32 intel fxrstor ptr [eax]
+0fae08|11223344556677885f5f5f5f5f 32 plan9 FXRSTOR 0(AX)
+0fae08|11223344556677885f5f5f5f5f 64 gnu fxrstor (%rax)
+0fae08|11223344556677885f5f5f5f5f 64 intel fxrstor ptr [rax]
+0fae08|11223344556677885f5f5f5f5f 64 plan9 FXRSTOR 0(AX)
+0fae11|223344556677885f5f5f5f5f5f 32 intel ldmxcsr dword ptr [ecx]
+0fae11|223344556677885f5f5f5f5f5f 32 plan9 LDMXCSR 0(CX)
+0fae11|223344556677885f5f5f5f5f5f 64 gnu ldmxcsr (%rcx)
+0fae11|223344556677885f5f5f5f5f5f 64 intel ldmxcsr dword ptr [rcx]
+0fae11|223344556677885f5f5f5f5f5f 64 plan9 LDMXCSR 0(CX)
+0fae18|11223344556677885f5f5f5f5f 32 intel stmxcsr dword ptr [eax]
+0fae18|11223344556677885f5f5f5f5f 32 plan9 STMXCSR 0(AX)
+0fae18|11223344556677885f5f5f5f5f 64 gnu stmxcsr (%rax)
+0fae18|11223344556677885f5f5f5f5f 64 intel stmxcsr dword ptr [rax]
+0fae18|11223344556677885f5f5f5f5f 64 plan9 STMXCSR 0(AX)
+0fae20|11223344556677885f5f5f5f5f 32 intel xsave ptr [eax]
+0fae20|11223344556677885f5f5f5f5f 32 plan9 XSAVE 0(AX)
+0fae20|11223344556677885f5f5f5f5f 64 gnu xsave (%rax)
+0fae20|11223344556677885f5f5f5f5f 64 intel xsave ptr [rax]
+0fae20|11223344556677885f5f5f5f5f 64 plan9 XSAVE 0(AX)
+0fae28|11223344556677885f5f5f5f5f 32 intel xrstor ptr [eax]
+0fae28|11223344556677885f5f5f5f5f 32 plan9 XRSTOR 0(AX)
+0fae28|11223344556677885f5f5f5f5f 64 gnu xrstor (%rax)
+0fae28|11223344556677885f5f5f5f5f 64 intel xrstor ptr [rax]
+0fae28|11223344556677885f5f5f5f5f 64 plan9 XRSTOR 0(AX)
+0fae30|11223344556677885f5f5f5f5f 32 intel xsaveopt ptr [eax]
+0fae30|11223344556677885f5f5f5f5f 32 plan9 XSAVEOPT 0(AX)
+0fae30|11223344556677885f5f5f5f5f 64 gnu xsaveopt (%rax)
+0fae30|11223344556677885f5f5f5f5f 64 intel xsaveopt ptr [rax]
+0fae30|11223344556677885f5f5f5f5f 64 plan9 XSAVEOPT 0(AX)
+0fae38|11223344556677885f5f5f5f5f 32 intel clflush zmmword ptr [eax]
+0fae38|11223344556677885f5f5f5f5f 32 plan9 CLFLUSH 0(AX)
+0fae38|11223344556677885f5f5f5f5f 64 gnu clflush (%rax)
+0fae38|11223344556677885f5f5f5f5f 64 intel clflush zmmword ptr [rax]
+0fae38|11223344556677885f5f5f5f5f 64 plan9 CLFLUSH 0(AX)
+0faee8|11223344556677885f5f5f5f5f 32 intel lfence
+0faee8|11223344556677885f5f5f5f5f 32 plan9 LFENCE
+0faee8|11223344556677885f5f5f5f5f 64 gnu lfence
+0faee8|11223344556677885f5f5f5f5f 64 intel lfence
+0faee8|11223344556677885f5f5f5f5f 64 plan9 LFENCE
+0faef0|11223344556677885f5f5f5f5f 32 intel mfence
+0faef0|11223344556677885f5f5f5f5f 32 plan9 MFENCE
+0faef0|11223344556677885f5f5f5f5f 64 gnu mfence
+0faef0|11223344556677885f5f5f5f5f 64 intel mfence
+0faef0|11223344556677885f5f5f5f5f 64 plan9 MFENCE
+0faef8|11223344556677885f5f5f5f5f 32 intel sfence
+0faef8|11223344556677885f5f5f5f5f 32 plan9 SFENCE
+0faef8|11223344556677885f5f5f5f5f 64 gnu sfence
+0faef8|11223344556677885f5f5f5f5f 64 intel sfence
+0faef8|11223344556677885f5f5f5f5f 64 plan9 SFENCE
+0faf11|223344556677885f5f5f5f5f5f 32 intel imul edx, dword ptr [ecx]
+0faf11|223344556677885f5f5f5f5f5f 32 plan9 IMULL 0(CX), DX
+0faf11|223344556677885f5f5f5f5f5f 64 gnu imul (%rcx),%edx
+0faf11|223344556677885f5f5f5f5f5f 64 intel imul edx, dword ptr [rcx]
+0faf11|223344556677885f5f5f5f5f5f 64 plan9 IMULL 0(CX), DX
+0fb011|223344556677885f5f5f5f5f5f 32 intel cmpxchg byte ptr [ecx], dl
+0fb011|223344556677885f5f5f5f5f5f 32 plan9 CMPXCHGL DL, 0(CX)
+0fb011|223344556677885f5f5f5f5f5f 64 gnu cmpxchg %dl,(%rcx)
+0fb011|223344556677885f5f5f5f5f5f 64 intel cmpxchg byte ptr [rcx], dl
+0fb011|223344556677885f5f5f5f5f5f 64 plan9 CMPXCHGL DL, 0(CX)
+0fb111|223344556677885f5f5f5f5f5f 32 intel cmpxchg dword ptr [ecx], edx
+0fb111|223344556677885f5f5f5f5f5f 32 plan9 CMPXCHGL DX, 0(CX)
+0fb111|223344556677885f5f5f5f5f5f 64 gnu cmpxchg %edx,(%rcx)
+0fb111|223344556677885f5f5f5f5f5f 64 intel cmpxchg dword ptr [rcx], edx
+0fb111|223344556677885f5f5f5f5f5f 64 plan9 CMPXCHGL DX, 0(CX)
+0fb211|223344556677885f5f5f5f5f5f 32 intel lss edx, ptr [ecx]
+0fb211|223344556677885f5f5f5f5f5f 32 plan9 LSS 0(CX), DX
+0fb211|223344556677885f5f5f5f5f5f 64 gnu lss (%rcx),%edx
+0fb211|223344556677885f5f5f5f5f5f 64 intel lss edx, ptr [rcx]
+0fb211|223344556677885f5f5f5f5f5f 64 plan9 LSS 0(CX), DX
+0fb311|223344556677885f5f5f5f5f5f 32 intel btr dword ptr [ecx], edx
+0fb311|223344556677885f5f5f5f5f5f 32 plan9 BTRL DX, 0(CX)
+0fb311|223344556677885f5f5f5f5f5f 64 gnu btr %edx,(%rcx)
+0fb311|223344556677885f5f5f5f5f5f 64 intel btr dword ptr [rcx], edx
+0fb311|223344556677885f5f5f5f5f5f 64 plan9 BTRL DX, 0(CX)
+0fb411|223344556677885f5f5f5f5f5f 32 intel lfs edx, ptr [ecx]
+0fb411|223344556677885f5f5f5f5f5f 32 plan9 LFS 0(CX), DX
+0fb411|223344556677885f5f5f5f5f5f 64 gnu lfs (%rcx),%edx
+0fb411|223344556677885f5f5f5f5f5f 64 intel lfs edx, ptr [rcx]
+0fb411|223344556677885f5f5f5f5f5f 64 plan9 LFS 0(CX), DX
+0fb511|223344556677885f5f5f5f5f5f 32 intel lgs edx, ptr [ecx]
+0fb511|223344556677885f5f5f5f5f5f 32 plan9 LGS 0(CX), DX
+0fb511|223344556677885f5f5f5f5f5f 64 gnu lgs (%rcx),%edx
+0fb511|223344556677885f5f5f5f5f5f 64 intel lgs edx, ptr [rcx]
+0fb511|223344556677885f5f5f5f5f5f 64 plan9 LGS 0(CX), DX
+0fb611|223344556677885f5f5f5f5f5f 32 intel movzx edx, byte ptr [ecx]
+0fb611|223344556677885f5f5f5f5f5f 32 plan9 MOVZX 0(CX), DX
+0fb611|223344556677885f5f5f5f5f5f 64 gnu movzbl (%rcx),%edx
+0fb611|223344556677885f5f5f5f5f5f 64 intel movzx edx, byte ptr [rcx]
+0fb611|223344556677885f5f5f5f5f5f 64 plan9 MOVZX 0(CX), DX
+0fb711|223344556677885f5f5f5f5f5f 32 intel movzx edx, word ptr [ecx]
+0fb711|223344556677885f5f5f5f5f5f 32 plan9 MOVZX 0(CX), DX
+0fb711|223344556677885f5f5f5f5f5f 64 gnu movzwl (%rcx),%edx
+0fb711|223344556677885f5f5f5f5f5f 64 intel movzx edx, word ptr [rcx]
+0fb711|223344556677885f5f5f5f5f5f 64 plan9 MOVZX 0(CX), DX
+0fb8|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0fb8|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0fb8|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0fb8|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0fb8|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0fb9|11223344556677885f5f5f5f5f5f 32 intel ud1
+0fb9|11223344556677885f5f5f5f5f5f 32 plan9 UD1
+0fb9|11223344556677885f5f5f5f5f5f 64 gnu ud1
+0fb9|11223344556677885f5f5f5f5f5f 64 intel ud1
+0fb9|11223344556677885f5f5f5f5f5f 64 plan9 UD1
+0fba11|223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0fba11|223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0fba11|223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0fba11|223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0fba11|223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0fba2011|223344556677885f5f5f5f5f 32 intel bt dword ptr [eax], 0x11
+0fba2011|223344556677885f5f5f5f5f 32 plan9 BTL $0x11, 0(AX)
+0fba2011|223344556677885f5f5f5f5f 64 gnu btl $0x11,(%rax)
+0fba2011|223344556677885f5f5f5f5f 64 intel bt dword ptr [rax], 0x11
+0fba2011|223344556677885f5f5f5f5f 64 plan9 BTL $0x11, 0(AX)
+0fba2811|223344556677885f5f5f5f5f 32 intel bts dword ptr [eax], 0x11
+0fba2811|223344556677885f5f5f5f5f 32 plan9 BTSL $0x11, 0(AX)
+0fba2811|223344556677885f5f5f5f5f 64 gnu btsl $0x11,(%rax)
+0fba2811|223344556677885f5f5f5f5f 64 intel bts dword ptr [rax], 0x11
+0fba2811|223344556677885f5f5f5f5f 64 plan9 BTSL $0x11, 0(AX)
+0fba3011|223344556677885f5f5f5f5f 32 intel btr dword ptr [eax], 0x11
+0fba3011|223344556677885f5f5f5f5f 32 plan9 BTRL $0x11, 0(AX)
+0fba3011|223344556677885f5f5f5f5f 64 gnu btrl $0x11,(%rax)
+0fba3011|223344556677885f5f5f5f5f 64 intel btr dword ptr [rax], 0x11
+0fba3011|223344556677885f5f5f5f5f 64 plan9 BTRL $0x11, 0(AX)
+0fba3811|223344556677885f5f5f5f5f 32 intel btc dword ptr [eax], 0x11
+0fba3811|223344556677885f5f5f5f5f 32 plan9 BTCL $0x11, 0(AX)
+0fba3811|223344556677885f5f5f5f5f 64 gnu btcl $0x11,(%rax)
+0fba3811|223344556677885f5f5f5f5f 64 intel btc dword ptr [rax], 0x11
+0fba3811|223344556677885f5f5f5f5f 64 plan9 BTCL $0x11, 0(AX)
+0fbb11|223344556677885f5f5f5f5f5f 32 intel btc dword ptr [ecx], edx
+0fbb11|223344556677885f5f5f5f5f5f 32 plan9 BTCL DX, 0(CX)
+0fbb11|223344556677885f5f5f5f5f5f 64 gnu btc %edx,(%rcx)
+0fbb11|223344556677885f5f5f5f5f5f 64 intel btc dword ptr [rcx], edx
+0fbb11|223344556677885f5f5f5f5f5f 64 plan9 BTCL DX, 0(CX)
+0fbc11|223344556677885f5f5f5f5f5f 32 intel bsf edx, dword ptr [ecx]
+0fbc11|223344556677885f5f5f5f5f5f 32 plan9 BSFL 0(CX), DX
+0fbc11|223344556677885f5f5f5f5f5f 64 gnu bsf (%rcx),%edx
+0fbc11|223344556677885f5f5f5f5f5f 64 intel bsf edx, dword ptr [rcx]
+0fbc11|223344556677885f5f5f5f5f5f 64 plan9 BSFL 0(CX), DX
+0fbd11|223344556677885f5f5f5f5f5f 32 intel bsr edx, dword ptr [ecx]
+0fbd11|223344556677885f5f5f5f5f5f 32 plan9 BSRL 0(CX), DX
+0fbd11|223344556677885f5f5f5f5f5f 64 gnu bsr (%rcx),%edx
+0fbd11|223344556677885f5f5f5f5f5f 64 intel bsr edx, dword ptr [rcx]
+0fbd11|223344556677885f5f5f5f5f5f 64 plan9 BSRL 0(CX), DX
+0fbe11|223344556677885f5f5f5f5f5f 32 intel movsx edx, byte ptr [ecx]
+0fbe11|223344556677885f5f5f5f5f5f 32 plan9 MOVSX 0(CX), DX
+0fbe11|223344556677885f5f5f5f5f5f 64 gnu movsbl (%rcx),%edx
+0fbe11|223344556677885f5f5f5f5f5f 64 intel movsx edx, byte ptr [rcx]
+0fbe11|223344556677885f5f5f5f5f5f 64 plan9 MOVSX 0(CX), DX
+0fbf11|223344556677885f5f5f5f5f5f 32 intel movsx edx, word ptr [ecx]
+0fbf11|223344556677885f5f5f5f5f5f 32 plan9 MOVSX 0(CX), DX
+0fbf11|223344556677885f5f5f5f5f5f 64 gnu movswl (%rcx),%edx
+0fbf11|223344556677885f5f5f5f5f5f 64 intel movsx edx, word ptr [rcx]
+0fbf11|223344556677885f5f5f5f5f5f 64 plan9 MOVSX 0(CX), DX
+0fc011|223344556677885f5f5f5f5f5f 32 intel xadd byte ptr [ecx], dl
+0fc011|223344556677885f5f5f5f5f5f 32 plan9 XADDL DL, 0(CX)
+0fc011|223344556677885f5f5f5f5f5f 64 gnu xadd %dl,(%rcx)
+0fc011|223344556677885f5f5f5f5f5f 64 intel xadd byte ptr [rcx], dl
+0fc011|223344556677885f5f5f5f5f5f 64 plan9 XADDL DL, 0(CX)
+0fc111|223344556677885f5f5f5f5f5f 32 intel xadd dword ptr [ecx], edx
+0fc111|223344556677885f5f5f5f5f5f 32 plan9 XADDL DX, 0(CX)
+0fc111|223344556677885f5f5f5f5f5f 64 gnu xadd %edx,(%rcx)
+0fc111|223344556677885f5f5f5f5f5f 64 intel xadd dword ptr [rcx], edx
+0fc111|223344556677885f5f5f5f5f5f 64 plan9 XADDL DX, 0(CX)
+0fc20000|11223344556677885f5f5f5f 32 intel cmpps xmm0, xmmword ptr [eax], 0x0
+0fc20000|11223344556677885f5f5f5f 32 plan9 CMPPS $0x0, 0(AX), X0
+0fc20000|11223344556677885f5f5f5f 64 gnu cmpeqps (%rax),%xmm0
+0fc20000|11223344556677885f5f5f5f 64 intel cmpps xmm0, xmmword ptr [rax], 0x0
+0fc20000|11223344556677885f5f5f5f 64 plan9 CMPPS $0x0, 0(AX), X0
+0fc311|223344556677885f5f5f5f5f5f 32 intel movnti dword ptr [ecx], edx
+0fc311|223344556677885f5f5f5f5f5f 32 plan9 MOVNTIL DX, 0(CX)
+0fc311|223344556677885f5f5f5f5f5f 64 gnu movnti %edx,(%rcx)
+0fc311|223344556677885f5f5f5f5f5f 64 intel movnti dword ptr [rcx], edx
+0fc311|223344556677885f5f5f5f5f5f 64 plan9 MOVNTIL DX, 0(CX)
+0fc41122|3344556677885f5f5f5f5f5f 32 intel pinsrw mmx2, word ptr [ecx], 0x22
+0fc41122|3344556677885f5f5f5f5f5f 32 plan9 PINSRW $0x22, 0(CX), M2
+0fc41122|3344556677885f5f5f5f5f5f 64 gnu pinsrw $0x22,(%rcx),%mm2
+0fc41122|3344556677885f5f5f5f5f5f 64 intel pinsrw mmx2, word ptr [rcx], 0x22
+0fc41122|3344556677885f5f5f5f5f5f 64 plan9 PINSRW $0x22, 0(CX), M2
+0fc51122|3344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0fc51122|3344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0fc51122|3344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0fc51122|3344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0fc51122|3344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0fc5c011|223344556677885f5f5f5f5f 32 intel pextrw eax, mmx0, 0x11
+0fc5c011|223344556677885f5f5f5f5f 32 plan9 PEXTRW $0x11, M0, AX
+0fc5c011|223344556677885f5f5f5f5f 64 gnu pextrw $0x11,%mm0,%eax
+0fc5c011|223344556677885f5f5f5f5f 64 intel pextrw eax, mmx0, 0x11
+0fc5c011|223344556677885f5f5f5f5f 64 plan9 PEXTRW $0x11, M0, AX
+0fc61122|3344556677885f5f5f5f5f5f 32 intel shufps xmm2, xmmword ptr [ecx], 0x22
+0fc61122|3344556677885f5f5f5f5f5f 32 plan9 SHUFPS $0x22, 0(CX), X2
+0fc61122|3344556677885f5f5f5f5f5f 64 gnu shufps $0x22,(%rcx),%xmm2
+0fc61122|3344556677885f5f5f5f5f5f 64 intel shufps xmm2, xmmword ptr [rcx], 0x22
+0fc61122|3344556677885f5f5f5f5f5f 64 plan9 SHUFPS $0x22, 0(CX), X2
+0fc708|11223344556677885f5f5f5f5f 32 intel cmpxchg8b qword ptr [eax]
+0fc708|11223344556677885f5f5f5f5f 32 plan9 CMPXCHG8B 0(AX)
+0fc708|11223344556677885f5f5f5f5f 64 gnu cmpxchg8b (%rax)
+0fc708|11223344556677885f5f5f5f5f 64 intel cmpxchg8b qword ptr [rax]
+0fc708|11223344556677885f5f5f5f5f 64 plan9 CMPXCHG8B 0(AX)
+0fc718|11223344556677885f5f5f5f5f 32 intel xrstors ptr [eax]
+0fc718|11223344556677885f5f5f5f5f 32 plan9 XRSTORS 0(AX)
+0fc718|11223344556677885f5f5f5f5f 64 gnu xrstors (%rax)
+0fc718|11223344556677885f5f5f5f5f 64 intel xrstors ptr [rax]
+0fc718|11223344556677885f5f5f5f5f 64 plan9 XRSTORS 0(AX)
+0fc720|11223344556677885f5f5f5f5f 32 intel xsavec ptr [eax]
+0fc720|11223344556677885f5f5f5f5f 32 plan9 XSAVEC 0(AX)
+0fc720|11223344556677885f5f5f5f5f 64 gnu xsavec (%rax)
+0fc720|11223344556677885f5f5f5f5f 64 intel xsavec ptr [rax]
+0fc720|11223344556677885f5f5f5f5f 64 plan9 XSAVEC 0(AX)
+0fc728|11223344556677885f5f5f5f5f 32 intel xsaves ptr [eax]
+0fc728|11223344556677885f5f5f5f5f 32 plan9 XSAVES 0(AX)
+0fc728|11223344556677885f5f5f5f5f 64 gnu xsaves (%rax)
+0fc728|11223344556677885f5f5f5f5f 64 intel xsaves ptr [rax]
+0fc728|11223344556677885f5f5f5f5f 64 plan9 XSAVES 0(AX)
+0fc730|11223344556677885f5f5f5f5f 32 intel error: unrecognized instruction
+0fc730|11223344556677885f5f5f5f5f 32 plan9 error: unrecognized instruction
+0fc730|11223344556677885f5f5f5f5f 64 gnu error: unrecognized instruction
+0fc730|11223344556677885f5f5f5f5f 64 intel error: unrecognized instruction
+0fc730|11223344556677885f5f5f5f5f 64 plan9 error: unrecognized instruction
+0fc7f0|11223344556677885f5f5f5f5f 32 intel rdrand eax
+0fc7f0|11223344556677885f5f5f5f5f 32 plan9 RDRAND AX
+0fc7f0|11223344556677885f5f5f5f5f 64 gnu rdrand %eax
+0fc7f0|11223344556677885f5f5f5f5f 64 intel rdrand eax
+0fc7f0|11223344556677885f5f5f5f5f 64 plan9 RDRAND AX
+0fc8|11223344556677885f5f5f5f5f5f 32 intel bswap eax
+0fc8|11223344556677885f5f5f5f5f5f 32 plan9 BSWAP AX
+0fc8|11223344556677885f5f5f5f5f5f 64 gnu bswap %eax
+0fc8|11223344556677885f5f5f5f5f5f 64 intel bswap eax
+0fc8|11223344556677885f5f5f5f5f5f 64 plan9 BSWAP AX
+0fd0|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0fd0|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0fd0|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0fd0|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0fd0|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0fd111|223344556677885f5f5f5f5f5f 32 intel psrlw mmx2, qword ptr [ecx]
+0fd111|223344556677885f5f5f5f5f5f 32 plan9 PSRLW 0(CX), M2
+0fd111|223344556677885f5f5f5f5f5f 64 gnu psrlw (%rcx),%mm2
+0fd111|223344556677885f5f5f5f5f5f 64 intel psrlw mmx2, qword ptr [rcx]
+0fd111|223344556677885f5f5f5f5f5f 64 plan9 PSRLW 0(CX), M2
+0fd211|223344556677885f5f5f5f5f5f 32 intel psrld mmx2, qword ptr [ecx]
+0fd211|223344556677885f5f5f5f5f5f 32 plan9 PSRLD 0(CX), M2
+0fd211|223344556677885f5f5f5f5f5f 64 gnu psrld (%rcx),%mm2
+0fd211|223344556677885f5f5f5f5f5f 64 intel psrld mmx2, qword ptr [rcx]
+0fd211|223344556677885f5f5f5f5f5f 64 plan9 PSRLD 0(CX), M2
+0fd311|223344556677885f5f5f5f5f5f 32 intel psrlq mmx2, qword ptr [ecx]
+0fd311|223344556677885f5f5f5f5f5f 32 plan9 PSRLQ 0(CX), M2
+0fd311|223344556677885f5f5f5f5f5f 64 gnu psrlq (%rcx),%mm2
+0fd311|223344556677885f5f5f5f5f5f 64 intel psrlq mmx2, qword ptr [rcx]
+0fd311|223344556677885f5f5f5f5f5f 64 plan9 PSRLQ 0(CX), M2
+0fd411|223344556677885f5f5f5f5f5f 32 intel paddq mmx2, qword ptr [ecx]
+0fd411|223344556677885f5f5f5f5f5f 32 plan9 PADDQ 0(CX), M2
+0fd411|223344556677885f5f5f5f5f5f 64 gnu paddq (%rcx),%mm2
+0fd411|223344556677885f5f5f5f5f5f 64 intel paddq mmx2, qword ptr [rcx]
+0fd411|223344556677885f5f5f5f5f5f 64 plan9 PADDQ 0(CX), M2
+0fd511|223344556677885f5f5f5f5f5f 32 intel pmullw mmx2, qword ptr [ecx]
+0fd511|223344556677885f5f5f5f5f5f 32 plan9 PMULLW 0(CX), M2
+0fd511|223344556677885f5f5f5f5f5f 64 gnu pmullw (%rcx),%mm2
+0fd511|223344556677885f5f5f5f5f5f 64 intel pmullw mmx2, qword ptr [rcx]
+0fd511|223344556677885f5f5f5f5f5f 64 plan9 PMULLW 0(CX), M2
+0fd6|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0fd6|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0fd6|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0fd6|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0fd6|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0fd711|223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0fd711|223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0fd711|223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0fd711|223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0fd711|223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0fd7c0|11223344556677885f5f5f5f5f 32 intel pmovmskb eax, mmx0
+0fd7c0|11223344556677885f5f5f5f5f 32 plan9 PMOVMSKB M0, AX
+0fd7c0|11223344556677885f5f5f5f5f 64 gnu pmovmskb %mm0,%eax
+0fd7c0|11223344556677885f5f5f5f5f 64 intel pmovmskb eax, mmx0
+0fd7c0|11223344556677885f5f5f5f5f 64 plan9 PMOVMSKB M0, AX
+0fd811|223344556677885f5f5f5f5f5f 32 intel psubusb mmx2, qword ptr [ecx]
+0fd811|223344556677885f5f5f5f5f5f 32 plan9 PSUBUSB 0(CX), M2
+0fd811|223344556677885f5f5f5f5f5f 64 gnu psubusb (%rcx),%mm2
+0fd811|223344556677885f5f5f5f5f5f 64 intel psubusb mmx2, qword ptr [rcx]
+0fd811|223344556677885f5f5f5f5f5f 64 plan9 PSUBUSB 0(CX), M2
+0fd911|223344556677885f5f5f5f5f5f 32 intel psubusw mmx2, qword ptr [ecx]
+0fd911|223344556677885f5f5f5f5f5f 32 plan9 PSUBUSW 0(CX), M2
+0fd911|223344556677885f5f5f5f5f5f 64 gnu psubusw (%rcx),%mm2
+0fd911|223344556677885f5f5f5f5f5f 64 intel psubusw mmx2, qword ptr [rcx]
+0fd911|223344556677885f5f5f5f5f5f 64 plan9 PSUBUSW 0(CX), M2
+0fda11|223344556677885f5f5f5f5f5f 32 intel pminub mmx2, qword ptr [ecx]
+0fda11|223344556677885f5f5f5f5f5f 32 plan9 PMINUB 0(CX), M2
+0fda11|223344556677885f5f5f5f5f5f 64 gnu pminub (%rcx),%mm2
+0fda11|223344556677885f5f5f5f5f5f 64 intel pminub mmx2, qword ptr [rcx]
+0fda11|223344556677885f5f5f5f5f5f 64 plan9 PMINUB 0(CX), M2
+0fdb11|223344556677885f5f5f5f5f5f 32 intel pand mmx2, qword ptr [ecx]
+0fdb11|223344556677885f5f5f5f5f5f 32 plan9 PAND 0(CX), M2
+0fdb11|223344556677885f5f5f5f5f5f 64 gnu pand (%rcx),%mm2
+0fdb11|223344556677885f5f5f5f5f5f 64 intel pand mmx2, qword ptr [rcx]
+0fdb11|223344556677885f5f5f5f5f5f 64 plan9 PAND 0(CX), M2
+0fdc11|223344556677885f5f5f5f5f5f 32 intel paddusb mmx2, qword ptr [ecx]
+0fdc11|223344556677885f5f5f5f5f5f 32 plan9 PADDUSB 0(CX), M2
+0fdc11|223344556677885f5f5f5f5f5f 64 gnu paddusb (%rcx),%mm2
+0fdc11|223344556677885f5f5f5f5f5f 64 intel paddusb mmx2, qword ptr [rcx]
+0fdc11|223344556677885f5f5f5f5f5f 64 plan9 PADDUSB 0(CX), M2
+0fdd11|223344556677885f5f5f5f5f5f 32 intel paddusw mmx2, qword ptr [ecx]
+0fdd11|223344556677885f5f5f5f5f5f 32 plan9 PADDUSW 0(CX), M2
+0fdd11|223344556677885f5f5f5f5f5f 64 gnu paddusw (%rcx),%mm2
+0fdd11|223344556677885f5f5f5f5f5f 64 intel paddusw mmx2, qword ptr [rcx]
+0fdd11|223344556677885f5f5f5f5f5f 64 plan9 PADDUSW 0(CX), M2
+0fde11|223344556677885f5f5f5f5f5f 32 intel pmaxub mmx2, qword ptr [ecx]
+0fde11|223344556677885f5f5f5f5f5f 32 plan9 PMAXUB 0(CX), M2
+0fde11|223344556677885f5f5f5f5f5f 64 gnu pmaxub (%rcx),%mm2
+0fde11|223344556677885f5f5f5f5f5f 64 intel pmaxub mmx2, qword ptr [rcx]
+0fde11|223344556677885f5f5f5f5f5f 64 plan9 PMAXUB 0(CX), M2
+0fdf11|223344556677885f5f5f5f5f5f 32 intel pandn mmx2, qword ptr [ecx]
+0fdf11|223344556677885f5f5f5f5f5f 32 plan9 PANDN 0(CX), M2
+0fdf11|223344556677885f5f5f5f5f5f 64 gnu pandn (%rcx),%mm2
+0fdf11|223344556677885f5f5f5f5f5f 64 intel pandn mmx2, qword ptr [rcx]
+0fdf11|223344556677885f5f5f5f5f5f 64 plan9 PANDN 0(CX), M2
+0fe011|223344556677885f5f5f5f5f5f 32 intel pavgb mmx2, qword ptr [ecx]
+0fe011|223344556677885f5f5f5f5f5f 32 plan9 PAVGB 0(CX), M2
+0fe011|223344556677885f5f5f5f5f5f 64 gnu pavgb (%rcx),%mm2
+0fe011|223344556677885f5f5f5f5f5f 64 intel pavgb mmx2, qword ptr [rcx]
+0fe011|223344556677885f5f5f5f5f5f 64 plan9 PAVGB 0(CX), M2
+0fe111|223344556677885f5f5f5f5f5f 32 intel psraw mmx2, qword ptr [ecx]
+0fe111|223344556677885f5f5f5f5f5f 32 plan9 PSRAW 0(CX), M2
+0fe111|223344556677885f5f5f5f5f5f 64 gnu psraw (%rcx),%mm2
+0fe111|223344556677885f5f5f5f5f5f 64 intel psraw mmx2, qword ptr [rcx]
+0fe111|223344556677885f5f5f5f5f5f 64 plan9 PSRAW 0(CX), M2
+0fe211|223344556677885f5f5f5f5f5f 32 intel psrad mmx2, qword ptr [ecx]
+0fe211|223344556677885f5f5f5f5f5f 32 plan9 PSRAD 0(CX), M2
+0fe211|223344556677885f5f5f5f5f5f 64 gnu psrad (%rcx),%mm2
+0fe211|223344556677885f5f5f5f5f5f 64 intel psrad mmx2, qword ptr [rcx]
+0fe211|223344556677885f5f5f5f5f5f 64 plan9 PSRAD 0(CX), M2
+0fe311|223344556677885f5f5f5f5f5f 32 intel pavgw mmx2, qword ptr [ecx]
+0fe311|223344556677885f5f5f5f5f5f 32 plan9 PAVGW 0(CX), M2
+0fe311|223344556677885f5f5f5f5f5f 64 gnu pavgw (%rcx),%mm2
+0fe311|223344556677885f5f5f5f5f5f 64 intel pavgw mmx2, qword ptr [rcx]
+0fe311|223344556677885f5f5f5f5f5f 64 plan9 PAVGW 0(CX), M2
+0fe411|223344556677885f5f5f5f5f5f 32 intel pmulhuw mmx2, qword ptr [ecx]
+0fe411|223344556677885f5f5f5f5f5f 32 plan9 PMULHUW 0(CX), M2
+0fe411|223344556677885f5f5f5f5f5f 64 gnu pmulhuw (%rcx),%mm2
+0fe411|223344556677885f5f5f5f5f5f 64 intel pmulhuw mmx2, qword ptr [rcx]
+0fe411|223344556677885f5f5f5f5f5f 64 plan9 PMULHUW 0(CX), M2
+0fe511|223344556677885f5f5f5f5f5f 32 intel pmulhw mmx2, qword ptr [ecx]
+0fe511|223344556677885f5f5f5f5f5f 32 plan9 PMULHW 0(CX), M2
+0fe511|223344556677885f5f5f5f5f5f 64 gnu pmulhw (%rcx),%mm2
+0fe511|223344556677885f5f5f5f5f5f 64 intel pmulhw mmx2, qword ptr [rcx]
+0fe511|223344556677885f5f5f5f5f5f 64 plan9 PMULHW 0(CX), M2
+0fe6|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0fe6|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0fe6|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0fe6|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0fe6|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0fe711|223344556677885f5f5f5f5f5f 32 intel movntq qword ptr [ecx], mmx2
+0fe711|223344556677885f5f5f5f5f5f 32 plan9 MOVNTQ M2, 0(CX)
+0fe711|223344556677885f5f5f5f5f5f 64 gnu movntq %mm2,(%rcx)
+0fe711|223344556677885f5f5f5f5f5f 64 intel movntq qword ptr [rcx], mmx2
+0fe711|223344556677885f5f5f5f5f5f 64 plan9 MOVNTQ M2, 0(CX)
+0fe811|223344556677885f5f5f5f5f5f 32 intel psubsb mmx2, qword ptr [ecx]
+0fe811|223344556677885f5f5f5f5f5f 32 plan9 PSUBSB 0(CX), M2
+0fe811|223344556677885f5f5f5f5f5f 64 gnu psubsb (%rcx),%mm2
+0fe811|223344556677885f5f5f5f5f5f 64 intel psubsb mmx2, qword ptr [rcx]
+0fe811|223344556677885f5f5f5f5f5f 64 plan9 PSUBSB 0(CX), M2
+0fe911|223344556677885f5f5f5f5f5f 32 intel psubsw mmx2, qword ptr [ecx]
+0fe911|223344556677885f5f5f5f5f5f 32 plan9 PSUBSW 0(CX), M2
+0fe911|223344556677885f5f5f5f5f5f 64 gnu psubsw (%rcx),%mm2
+0fe911|223344556677885f5f5f5f5f5f 64 intel psubsw mmx2, qword ptr [rcx]
+0fe911|223344556677885f5f5f5f5f5f 64 plan9 PSUBSW 0(CX), M2
+0fea11|223344556677885f5f5f5f5f5f 32 intel pminsw mmx2, qword ptr [ecx]
+0fea11|223344556677885f5f5f5f5f5f 32 plan9 PMINSW 0(CX), M2
+0fea11|223344556677885f5f5f5f5f5f 64 gnu pminsw (%rcx),%mm2
+0fea11|223344556677885f5f5f5f5f5f 64 intel pminsw mmx2, qword ptr [rcx]
+0fea11|223344556677885f5f5f5f5f5f 64 plan9 PMINSW 0(CX), M2
+0feb11|223344556677885f5f5f5f5f5f 32 intel por mmx2, qword ptr [ecx]
+0feb11|223344556677885f5f5f5f5f5f 32 plan9 POR 0(CX), M2
+0feb11|223344556677885f5f5f5f5f5f 64 gnu por (%rcx),%mm2
+0feb11|223344556677885f5f5f5f5f5f 64 intel por mmx2, qword ptr [rcx]
+0feb11|223344556677885f5f5f5f5f5f 64 plan9 POR 0(CX), M2
+0fec11|223344556677885f5f5f5f5f5f 32 intel paddsb mmx2, qword ptr [ecx]
+0fec11|223344556677885f5f5f5f5f5f 32 plan9 PADDSB 0(CX), M2
+0fec11|223344556677885f5f5f5f5f5f 64 gnu paddsb (%rcx),%mm2
+0fec11|223344556677885f5f5f5f5f5f 64 intel paddsb mmx2, qword ptr [rcx]
+0fec11|223344556677885f5f5f5f5f5f 64 plan9 PADDSB 0(CX), M2
+0fed11|223344556677885f5f5f5f5f5f 32 intel paddsw mmx2, qword ptr [ecx]
+0fed11|223344556677885f5f5f5f5f5f 32 plan9 PADDSW 0(CX), M2
+0fed11|223344556677885f5f5f5f5f5f 64 gnu paddsw (%rcx),%mm2
+0fed11|223344556677885f5f5f5f5f5f 64 intel paddsw mmx2, qword ptr [rcx]
+0fed11|223344556677885f5f5f5f5f5f 64 plan9 PADDSW 0(CX), M2
+0fee11|223344556677885f5f5f5f5f5f 32 intel pmaxsw mmx2, qword ptr [ecx]
+0fee11|223344556677885f5f5f5f5f5f 32 plan9 PMAXSW 0(CX), M2
+0fee11|223344556677885f5f5f5f5f5f 64 gnu pmaxsw (%rcx),%mm2
+0fee11|223344556677885f5f5f5f5f5f 64 intel pmaxsw mmx2, qword ptr [rcx]
+0fee11|223344556677885f5f5f5f5f5f 64 plan9 PMAXSW 0(CX), M2
+0fef11|223344556677885f5f5f5f5f5f 32 intel pxor mmx2, qword ptr [ecx]
+0fef11|223344556677885f5f5f5f5f5f 32 plan9 PXOR 0(CX), M2
+0fef11|223344556677885f5f5f5f5f5f 64 gnu pxor (%rcx),%mm2
+0fef11|223344556677885f5f5f5f5f5f 64 intel pxor mmx2, qword ptr [rcx]
+0fef11|223344556677885f5f5f5f5f5f 64 plan9 PXOR 0(CX), M2
+0ff0|11223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0ff0|11223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0ff0|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0ff0|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0ff0|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0ff111|223344556677885f5f5f5f5f5f 32 intel psllw mmx2, qword ptr [ecx]
+0ff111|223344556677885f5f5f5f5f5f 32 plan9 PSLLW 0(CX), M2
+0ff111|223344556677885f5f5f5f5f5f 64 gnu psllw (%rcx),%mm2
+0ff111|223344556677885f5f5f5f5f5f 64 intel psllw mmx2, qword ptr [rcx]
+0ff111|223344556677885f5f5f5f5f5f 64 plan9 PSLLW 0(CX), M2
+0ff211|223344556677885f5f5f5f5f5f 32 intel pslld mmx2, qword ptr [ecx]
+0ff211|223344556677885f5f5f5f5f5f 32 plan9 PSLLD 0(CX), M2
+0ff211|223344556677885f5f5f5f5f5f 64 gnu pslld (%rcx),%mm2
+0ff211|223344556677885f5f5f5f5f5f 64 intel pslld mmx2, qword ptr [rcx]
+0ff211|223344556677885f5f5f5f5f5f 64 plan9 PSLLD 0(CX), M2
+0ff311|223344556677885f5f5f5f5f5f 32 intel psllq mmx2, qword ptr [ecx]
+0ff311|223344556677885f5f5f5f5f5f 32 plan9 PSLLQ 0(CX), M2
+0ff311|223344556677885f5f5f5f5f5f 64 gnu psllq (%rcx),%mm2
+0ff311|223344556677885f5f5f5f5f5f 64 intel psllq mmx2, qword ptr [rcx]
+0ff311|223344556677885f5f5f5f5f5f 64 plan9 PSLLQ 0(CX), M2
+0ff411|223344556677885f5f5f5f5f5f 32 intel pmuludq mmx2, qword ptr [ecx]
+0ff411|223344556677885f5f5f5f5f5f 32 plan9 PMULUDQ 0(CX), M2
+0ff411|223344556677885f5f5f5f5f5f 64 gnu pmuludq (%rcx),%mm2
+0ff411|223344556677885f5f5f5f5f5f 64 intel pmuludq mmx2, qword ptr [rcx]
+0ff411|223344556677885f5f5f5f5f5f 64 plan9 PMULUDQ 0(CX), M2
+0ff511|223344556677885f5f5f5f5f5f 32 intel pmaddwd mmx2, qword ptr [ecx]
+0ff511|223344556677885f5f5f5f5f5f 32 plan9 PMADDWD 0(CX), M2
+0ff511|223344556677885f5f5f5f5f5f 64 gnu pmaddwd (%rcx),%mm2
+0ff511|223344556677885f5f5f5f5f5f 64 intel pmaddwd mmx2, qword ptr [rcx]
+0ff511|223344556677885f5f5f5f5f5f 64 plan9 PMADDWD 0(CX), M2
+0ff611|223344556677885f5f5f5f5f5f 32 intel psadbw mmx2, qword ptr [ecx]
+0ff611|223344556677885f5f5f5f5f5f 32 plan9 PSADBW 0(CX), M2
+0ff611|223344556677885f5f5f5f5f5f 64 gnu psadbw (%rcx),%mm2
+0ff611|223344556677885f5f5f5f5f5f 64 intel psadbw mmx2, qword ptr [rcx]
+0ff611|223344556677885f5f5f5f5f5f 64 plan9 PSADBW 0(CX), M2
+0ff711|223344556677885f5f5f5f5f5f 32 intel error: unrecognized instruction
+0ff711|223344556677885f5f5f5f5f5f 32 plan9 error: unrecognized instruction
+0ff711|223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+0ff711|223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+0ff711|223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+0ff7c0|11223344556677885f5f5f5f5f 32 intel maskmovq mmx0, mmx0
+0ff7c0|11223344556677885f5f5f5f5f 32 plan9 MASKMOVQ M0, M0
+0ff7c0|11223344556677885f5f5f5f5f 64 gnu maskmovq %mm0,%mm0
+0ff7c0|11223344556677885f5f5f5f5f 64 intel maskmovq mmx0, mmx0
+0ff7c0|11223344556677885f5f5f5f5f 64 plan9 MASKMOVQ M0, M0
+0ff811|223344556677885f5f5f5f5f5f 32 intel psubb mmx2, qword ptr [ecx]
+0ff811|223344556677885f5f5f5f5f5f 32 plan9 PSUBB 0(CX), M2
+0ff811|223344556677885f5f5f5f5f5f 64 gnu psubb (%rcx),%mm2
+0ff811|223344556677885f5f5f5f5f5f 64 intel psubb mmx2, qword ptr [rcx]
+0ff811|223344556677885f5f5f5f5f5f 64 plan9 PSUBB 0(CX), M2
+0ff911|223344556677885f5f5f5f5f5f 32 intel psubw mmx2, qword ptr [ecx]
+0ff911|223344556677885f5f5f5f5f5f 32 plan9 PSUBW 0(CX), M2
+0ff911|223344556677885f5f5f5f5f5f 64 gnu psubw (%rcx),%mm2
+0ff911|223344556677885f5f5f5f5f5f 64 intel psubw mmx2, qword ptr [rcx]
+0ff911|223344556677885f5f5f5f5f5f 64 plan9 PSUBW 0(CX), M2
+0ffa11|223344556677885f5f5f5f5f5f 32 intel psubd mmx2, qword ptr [ecx]
+0ffa11|223344556677885f5f5f5f5f5f 32 plan9 PSUBD 0(CX), M2
+0ffa11|223344556677885f5f5f5f5f5f 64 gnu psubd (%rcx),%mm2
+0ffa11|223344556677885f5f5f5f5f5f 64 intel psubd mmx2, qword ptr [rcx]
+0ffa11|223344556677885f5f5f5f5f5f 64 plan9 PSUBD 0(CX), M2
+0ffb11|223344556677885f5f5f5f5f5f 32 intel psubq mmx2, qword ptr [ecx]
+0ffb11|223344556677885f5f5f5f5f5f 32 plan9 PSUBQ 0(CX), M2
+0ffb11|223344556677885f5f5f5f5f5f 64 gnu psubq (%rcx),%mm2
+0ffb11|223344556677885f5f5f5f5f5f 64 intel psubq mmx2, qword ptr [rcx]
+0ffb11|223344556677885f5f5f5f5f5f 64 plan9 PSUBQ 0(CX), M2
+0ffc11|223344556677885f5f5f5f5f5f 32 intel paddb mmx2, qword ptr [ecx]
+0ffc11|223344556677885f5f5f5f5f5f 32 plan9 PADDB 0(CX), M2
+0ffc11|223344556677885f5f5f5f5f5f 64 gnu paddb (%rcx),%mm2
+0ffc11|223344556677885f5f5f5f5f5f 64 intel paddb mmx2, qword ptr [rcx]
+0ffc11|223344556677885f5f5f5f5f5f 64 plan9 PADDB 0(CX), M2
+0ffd11|223344556677885f5f5f5f5f5f 32 intel paddw mmx2, qword ptr [ecx]
+0ffd11|223344556677885f5f5f5f5f5f 32 plan9 PADDW 0(CX), M2
+0ffd11|223344556677885f5f5f5f5f5f 64 gnu paddw (%rcx),%mm2
+0ffd11|223344556677885f5f5f5f5f5f 64 intel paddw mmx2, qword ptr [rcx]
+0ffd11|223344556677885f5f5f5f5f5f 64 plan9 PADDW 0(CX), M2
+0ffe11|223344556677885f5f5f5f5f5f 32 intel paddd mmx2, qword ptr [ecx]
+0ffe11|223344556677885f5f5f5f5f5f 32 plan9 PADDD 0(CX), M2
+0ffe11|223344556677885f5f5f5f5f5f 64 gnu paddd (%rcx),%mm2
+0ffe11|223344556677885f5f5f5f5f5f 64 intel paddd mmx2, qword ptr [rcx]
+0ffe11|223344556677885f5f5f5f5f5f 64 plan9 PADDD 0(CX), M2
+1011|223344556677885f5f5f5f5f5f5f 32 intel adc byte ptr [ecx], dl
+1011|223344556677885f5f5f5f5f5f5f 32 plan9 ADCL DL, 0(CX)
+1011|223344556677885f5f5f5f5f5f5f 64 gnu adc %dl,(%rcx)
+1011|223344556677885f5f5f5f5f5f5f 64 intel adc byte ptr [rcx], dl
+1011|223344556677885f5f5f5f5f5f5f 64 plan9 ADCL DL, 0(CX)
+1111|223344556677885f5f5f5f5f5f5f 32 intel adc dword ptr [ecx], edx
+1111|223344556677885f5f5f5f5f5f5f 32 plan9 ADCL DX, 0(CX)
+1111|223344556677885f5f5f5f5f5f5f 64 gnu adc %edx,(%rcx)
+1111|223344556677885f5f5f5f5f5f5f 64 intel adc dword ptr [rcx], edx
+1111|223344556677885f5f5f5f5f5f5f 64 plan9 ADCL DX, 0(CX)
+1211|223344556677885f5f5f5f5f5f5f 32 intel adc dl, byte ptr [ecx]
+1211|223344556677885f5f5f5f5f5f5f 32 plan9 ADCL 0(CX), DL
+1211|223344556677885f5f5f5f5f5f5f 64 gnu adc (%rcx),%dl
+1211|223344556677885f5f5f5f5f5f5f 64 intel adc dl, byte ptr [rcx]
+1211|223344556677885f5f5f5f5f5f5f 64 plan9 ADCL 0(CX), DL
+1311|223344556677885f5f5f5f5f5f5f 32 intel adc edx, dword ptr [ecx]
+1311|223344556677885f5f5f5f5f5f5f 32 plan9 ADCL 0(CX), DX
+1311|223344556677885f5f5f5f5f5f5f 64 gnu adc (%rcx),%edx
+1311|223344556677885f5f5f5f5f5f5f 64 intel adc edx, dword ptr [rcx]
+1311|223344556677885f5f5f5f5f5f5f 64 plan9 ADCL 0(CX), DX
+1411|223344556677885f5f5f5f5f5f5f 32 intel adc al, 0x11
+1411|223344556677885f5f5f5f5f5f5f 32 plan9 ADCL $0x11, AL
+1411|223344556677885f5f5f5f5f5f5f 64 gnu adc $0x11,%al
+1411|223344556677885f5f5f5f5f5f5f 64 intel adc al, 0x11
+1411|223344556677885f5f5f5f5f5f5f 64 plan9 ADCL $0x11, AL
+1511223344|556677885f5f5f5f5f5f5f 32 intel adc eax, 0x44332211
+1511223344|556677885f5f5f5f5f5f5f 32 plan9 ADCL $0x44332211, AX
+1511223344|556677885f5f5f5f5f5f5f 64 gnu adc $0x44332211,%eax
+1511223344|556677885f5f5f5f5f5f5f 64 intel adc eax, 0x44332211
+1511223344|556677885f5f5f5f5f5f5f 64 plan9 ADCL $0x44332211, AX
+16|11223344556677885f5f5f5f5f5f5f 32 intel push ss
+16|11223344556677885f5f5f5f5f5f5f 32 plan9 PUSHL SS
+16|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+16|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+16|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+17|11223344556677885f5f5f5f5f5f5f 32 intel pop ss
+17|11223344556677885f5f5f5f5f5f5f 32 plan9 POPL SS
+17|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+17|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+17|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+1811|223344556677885f5f5f5f5f5f5f 32 intel sbb byte ptr [ecx], dl
+1811|223344556677885f5f5f5f5f5f5f 32 plan9 SBBL DL, 0(CX)
+1811|223344556677885f5f5f5f5f5f5f 64 gnu sbb %dl,(%rcx)
+1811|223344556677885f5f5f5f5f5f5f 64 intel sbb byte ptr [rcx], dl
+1811|223344556677885f5f5f5f5f5f5f 64 plan9 SBBL DL, 0(CX)
+1911|223344556677885f5f5f5f5f5f5f 32 intel sbb dword ptr [ecx], edx
+1911|223344556677885f5f5f5f5f5f5f 32 plan9 SBBL DX, 0(CX)
+1911|223344556677885f5f5f5f5f5f5f 64 gnu sbb %edx,(%rcx)
+1911|223344556677885f5f5f5f5f5f5f 64 intel sbb dword ptr [rcx], edx
+1911|223344556677885f5f5f5f5f5f5f 64 plan9 SBBL DX, 0(CX)
+1a11|223344556677885f5f5f5f5f5f5f 32 intel sbb dl, byte ptr [ecx]
+1a11|223344556677885f5f5f5f5f5f5f 32 plan9 SBBL 0(CX), DL
+1a11|223344556677885f5f5f5f5f5f5f 64 gnu sbb (%rcx),%dl
+1a11|223344556677885f5f5f5f5f5f5f 64 intel sbb dl, byte ptr [rcx]
+1a11|223344556677885f5f5f5f5f5f5f 64 plan9 SBBL 0(CX), DL
+1b11|223344556677885f5f5f5f5f5f5f 32 intel sbb edx, dword ptr [ecx]
+1b11|223344556677885f5f5f5f5f5f5f 32 plan9 SBBL 0(CX), DX
+1b11|223344556677885f5f5f5f5f5f5f 64 gnu sbb (%rcx),%edx
+1b11|223344556677885f5f5f5f5f5f5f 64 intel sbb edx, dword ptr [rcx]
+1b11|223344556677885f5f5f5f5f5f5f 64 plan9 SBBL 0(CX), DX
+1c11|223344556677885f5f5f5f5f5f5f 32 intel sbb al, 0x11
+1c11|223344556677885f5f5f5f5f5f5f 32 plan9 SBBL $0x11, AL
+1c11|223344556677885f5f5f5f5f5f5f 64 gnu sbb $0x11,%al
+1c11|223344556677885f5f5f5f5f5f5f 64 intel sbb al, 0x11
+1c11|223344556677885f5f5f5f5f5f5f 64 plan9 SBBL $0x11, AL
+1d11223344|556677885f5f5f5f5f5f5f 32 intel sbb eax, 0x44332211
+1d11223344|556677885f5f5f5f5f5f5f 32 plan9 SBBL $0x44332211, AX
+1d11223344|556677885f5f5f5f5f5f5f 64 gnu sbb $0x44332211,%eax
+1d11223344|556677885f5f5f5f5f5f5f 64 intel sbb eax, 0x44332211
+1d11223344|556677885f5f5f5f5f5f5f 64 plan9 SBBL $0x44332211, AX
+1e|11223344556677885f5f5f5f5f5f5f 32 intel push ds
+1e|11223344556677885f5f5f5f5f5f5f 32 plan9 PUSHL DS
+1e|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+1e|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+1e|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+1f|11223344556677885f5f5f5f5f5f5f 32 intel pop ds
+1f|11223344556677885f5f5f5f5f5f5f 32 plan9 POPL DS
+1f|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+1f|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+1f|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+2011|223344556677885f5f5f5f5f5f5f 32 intel and byte ptr [ecx], dl
+2011|223344556677885f5f5f5f5f5f5f 32 plan9 ANDL DL, 0(CX)
+2011|223344556677885f5f5f5f5f5f5f 64 gnu and %dl,(%rcx)
+2011|223344556677885f5f5f5f5f5f5f 64 intel and byte ptr [rcx], dl
+2011|223344556677885f5f5f5f5f5f5f 64 plan9 ANDL DL, 0(CX)
+2111|223344556677885f5f5f5f5f5f5f 32 intel and dword ptr [ecx], edx
+2111|223344556677885f5f5f5f5f5f5f 32 plan9 ANDL DX, 0(CX)
+2111|223344556677885f5f5f5f5f5f5f 64 gnu and %edx,(%rcx)
+2111|223344556677885f5f5f5f5f5f5f 64 intel and dword ptr [rcx], edx
+2111|223344556677885f5f5f5f5f5f5f 64 plan9 ANDL DX, 0(CX)
+2211|223344556677885f5f5f5f5f5f5f 32 intel and dl, byte ptr [ecx]
+2211|223344556677885f5f5f5f5f5f5f 32 plan9 ANDL 0(CX), DL
+2211|223344556677885f5f5f5f5f5f5f 64 gnu and (%rcx),%dl
+2211|223344556677885f5f5f5f5f5f5f 64 intel and dl, byte ptr [rcx]
+2211|223344556677885f5f5f5f5f5f5f 64 plan9 ANDL 0(CX), DL
+2311|223344556677885f5f5f5f5f5f5f 32 intel and edx, dword ptr [ecx]
+2311|223344556677885f5f5f5f5f5f5f 32 plan9 ANDL 0(CX), DX
+2311|223344556677885f5f5f5f5f5f5f 64 gnu and (%rcx),%edx
+2311|223344556677885f5f5f5f5f5f5f 64 intel and edx, dword ptr [rcx]
+2311|223344556677885f5f5f5f5f5f5f 64 plan9 ANDL 0(CX), DX
+2411|223344556677885f5f5f5f5f5f5f 32 intel and al, 0x11
+2411|223344556677885f5f5f5f5f5f5f 32 plan9 ANDL $0x11, AL
+2411|223344556677885f5f5f5f5f5f5f 64 gnu and $0x11,%al
+2411|223344556677885f5f5f5f5f5f5f 64 intel and al, 0x11
+2411|223344556677885f5f5f5f5f5f5f 64 plan9 ANDL $0x11, AL
+2511223344|556677885f5f5f5f5f5f5f 32 intel and eax, 0x44332211
+2511223344|556677885f5f5f5f5f5f5f 32 plan9 ANDL $0x44332211, AX
+2511223344|556677885f5f5f5f5f5f5f 64 gnu and $0x44332211,%eax
+2511223344|556677885f5f5f5f5f5f5f 64 intel and eax, 0x44332211
+2511223344|556677885f5f5f5f5f5f5f 64 plan9 ANDL $0x44332211, AX
+266e|11223344556677885f5f5f5f5f5f 32 intel outsb es
+266e|11223344556677885f5f5f5f5f5f 32 plan9 ES OUTSB ES:0(SI), DX
+266e|11223344556677885f5f5f5f5f5f 64 gnu outsb %ds:%es:(%rsi),(%dx)
+266e|11223344556677885f5f5f5f5f5f 64 intel outsb
+266e|11223344556677885f5f5f5f5f5f 64 plan9 ES OUTSB DS:0(SI), DX
+267011|223344556677885f5f5f5f5f5f 32 intel jo .+0x11
+267011|223344556677885f5f5f5f5f5f 32 plan9 ES JO .+17
+267011|223344556677885f5f5f5f5f5f 64 gnu es jo .+0x11
+267011|223344556677885f5f5f5f5f5f 64 intel jo .+0x11
+267011|223344556677885f5f5f5f5f5f 64 plan9 ES JO .+17
+26a01122334455667788|5f5f5f5f5f5f 64 gnu mov %es:-0x778899aabbccddef,%al
+26a01122334455667788|5f5f5f5f5f5f 64 intel mov al, byte ptr [0x8877665544332211]
+26a01122334455667788|5f5f5f5f5f5f 64 plan9 ES MOVL -0x778899aabbccddef, AL
+26a011223344|556677885f5f5f5f5f5f 32 intel mov al, byte ptr es:[0x44332211]
+26a011223344|556677885f5f5f5f5f5f 32 plan9 ES MOVL ES:0x44332211, AL
+26|8211223344556677885f5f5f5f5f5f 32 intel es
+26|8211223344556677885f5f5f5f5f5f 32 plan9 ES Op(0)
+26|8211223344556677885f5f5f5f5f5f 64 gnu es
+26|8211223344556677885f5f5f5f5f5f 64 intel es
+26|8211223344556677885f5f5f5f5f5f 64 plan9 ES Op(0)
+27|11223344556677885f5f5f5f5f5f5f 32 intel daa
+27|11223344556677885f5f5f5f5f5f5f 32 plan9 DAA
+27|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+27|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+27|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+2811|223344556677885f5f5f5f5f5f5f 32 intel sub byte ptr [ecx], dl
+2811|223344556677885f5f5f5f5f5f5f 32 plan9 SUBL DL, 0(CX)
+2811|223344556677885f5f5f5f5f5f5f 64 gnu sub %dl,(%rcx)
+2811|223344556677885f5f5f5f5f5f5f 64 intel sub byte ptr [rcx], dl
+2811|223344556677885f5f5f5f5f5f5f 64 plan9 SUBL DL, 0(CX)
+2911|223344556677885f5f5f5f5f5f5f 32 intel sub dword ptr [ecx], edx
+2911|223344556677885f5f5f5f5f5f5f 32 plan9 SUBL DX, 0(CX)
+2911|223344556677885f5f5f5f5f5f5f 64 gnu sub %edx,(%rcx)
+2911|223344556677885f5f5f5f5f5f5f 64 intel sub dword ptr [rcx], edx
+2911|223344556677885f5f5f5f5f5f5f 64 plan9 SUBL DX, 0(CX)
+2a11|223344556677885f5f5f5f5f5f5f 32 intel sub dl, byte ptr [ecx]
+2a11|223344556677885f5f5f5f5f5f5f 32 plan9 SUBL 0(CX), DL
+2a11|223344556677885f5f5f5f5f5f5f 64 gnu sub (%rcx),%dl
+2a11|223344556677885f5f5f5f5f5f5f 64 intel sub dl, byte ptr [rcx]
+2a11|223344556677885f5f5f5f5f5f5f 64 plan9 SUBL 0(CX), DL
+2b11|223344556677885f5f5f5f5f5f5f 32 intel sub edx, dword ptr [ecx]
+2b11|223344556677885f5f5f5f5f5f5f 32 plan9 SUBL 0(CX), DX
+2b11|223344556677885f5f5f5f5f5f5f 64 gnu sub (%rcx),%edx
+2b11|223344556677885f5f5f5f5f5f5f 64 intel sub edx, dword ptr [rcx]
+2b11|223344556677885f5f5f5f5f5f5f 64 plan9 SUBL 0(CX), DX
+2c11|223344556677885f5f5f5f5f5f5f 32 intel sub al, 0x11
+2c11|223344556677885f5f5f5f5f5f5f 32 plan9 SUBL $0x11, AL
+2c11|223344556677885f5f5f5f5f5f5f 64 gnu sub $0x11,%al
+2c11|223344556677885f5f5f5f5f5f5f 64 intel sub al, 0x11
+2c11|223344556677885f5f5f5f5f5f5f 64 plan9 SUBL $0x11, AL
+2d11223344|556677885f5f5f5f5f5f5f 32 intel sub eax, 0x44332211
+2d11223344|556677885f5f5f5f5f5f5f 32 plan9 SUBL $0x44332211, AX
+2d11223344|556677885f5f5f5f5f5f5f 64 gnu sub $0x44332211,%eax
+2d11223344|556677885f5f5f5f5f5f5f 64 intel sub eax, 0x44332211
+2d11223344|556677885f5f5f5f5f5f5f 64 plan9 SUBL $0x44332211, AX
+2f|11223344556677885f5f5f5f5f5f5f 32 intel das
+2f|11223344556677885f5f5f5f5f5f5f 32 plan9 DAS
+2f|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+2f|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+2f|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+3011|223344556677885f5f5f5f5f5f5f 32 intel xor byte ptr [ecx], dl
+3011|223344556677885f5f5f5f5f5f5f 32 plan9 XORL DL, 0(CX)
+3011|223344556677885f5f5f5f5f5f5f 64 gnu xor %dl,(%rcx)
+3011|223344556677885f5f5f5f5f5f5f 64 intel xor byte ptr [rcx], dl
+3011|223344556677885f5f5f5f5f5f5f 64 plan9 XORL DL, 0(CX)
+3111|223344556677885f5f5f5f5f5f5f 32 intel xor dword ptr [ecx], edx
+3111|223344556677885f5f5f5f5f5f5f 32 plan9 XORL DX, 0(CX)
+3111|223344556677885f5f5f5f5f5f5f 64 gnu xor %edx,(%rcx)
+3111|223344556677885f5f5f5f5f5f5f 64 intel xor dword ptr [rcx], edx
+3111|223344556677885f5f5f5f5f5f5f 64 plan9 XORL DX, 0(CX)
+3211|223344556677885f5f5f5f5f5f5f 32 intel xor dl, byte ptr [ecx]
+3211|223344556677885f5f5f5f5f5f5f 32 plan9 XORL 0(CX), DL
+3211|223344556677885f5f5f5f5f5f5f 64 gnu xor (%rcx),%dl
+3211|223344556677885f5f5f5f5f5f5f 64 intel xor dl, byte ptr [rcx]
+3211|223344556677885f5f5f5f5f5f5f 64 plan9 XORL 0(CX), DL
+3311|223344556677885f5f5f5f5f5f5f 32 intel xor edx, dword ptr [ecx]
+3311|223344556677885f5f5f5f5f5f5f 32 plan9 XORL 0(CX), DX
+3311|223344556677885f5f5f5f5f5f5f 64 gnu xor (%rcx),%edx
+3311|223344556677885f5f5f5f5f5f5f 64 intel xor edx, dword ptr [rcx]
+3311|223344556677885f5f5f5f5f5f5f 64 plan9 XORL 0(CX), DX
+3411|223344556677885f5f5f5f5f5f5f 32 intel xor al, 0x11
+3411|223344556677885f5f5f5f5f5f5f 32 plan9 XORL $0x11, AL
+3411|223344556677885f5f5f5f5f5f5f 64 gnu xor $0x11,%al
+3411|223344556677885f5f5f5f5f5f5f 64 intel xor al, 0x11
+3411|223344556677885f5f5f5f5f5f5f 64 plan9 XORL $0x11, AL
+3511223344|556677885f5f5f5f5f5f5f 32 intel xor eax, 0x44332211
+3511223344|556677885f5f5f5f5f5f5f 32 plan9 XORL $0x44332211, AX
+3511223344|556677885f5f5f5f5f5f5f 64 gnu xor $0x44332211,%eax
+3511223344|556677885f5f5f5f5f5f5f 64 intel xor eax, 0x44332211
+3511223344|556677885f5f5f5f5f5f5f 64 plan9 XORL $0x44332211, AX
+3667f3660f2ac0|11223344556677885f 32 intel addr16 cvtsi2ss xmm0, eax
+3667f3660f2ac0|11223344556677885f 32 plan9 CVTSI2SSW AX, X0
+3667f3660f2ac0|11223344556677885f 64 gnu ss addr32 cvtsi2ss %ax,%xmm0
+3667f3660f2ac0|11223344556677885f 64 intel addr32 cvtsi2ss xmm0, eax
+3667f3660f2ac0|11223344556677885f 64 plan9 CVTSI2SSW AX, X0
+36|67f3660ff7c011223344556677885f 64 gnu ss
+36|f0f2f33e66f066f2f33e3666818411 32 intel ss
+36|f0f2f33e66f066f2f33e3666818411 32 plan9 SS Op(0)
+36|f0f2f33e66f066f2f33e3666818411 64 gnu ss
+36|f0f2f33e66f066f2f33e3666818411 64 intel ss
+36|f0f2f33e66f066f2f33e3666818411 64 plan9 SS Op(0)
+36|f2f33ef0f78411223344556677885f 32 intel ss
+36|f2f33ef0f78411223344556677885f 32 plan9 SS Op(0)
+36|f2f33ef0f78411223344556677885f 64 gnu ss
+36|f2f33ef0f78411223344556677885f 64 intel ss
+36|f2f33ef0f78411223344556677885f 64 plan9 SS Op(0)
+37|11223344556677885f5f5f5f5f5f5f 32 intel aaa
+37|11223344556677885f5f5f5f5f5f5f 32 plan9 AAA
+37|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+37|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+37|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+3811|223344556677885f5f5f5f5f5f5f 32 intel cmp byte ptr [ecx], dl
+3811|223344556677885f5f5f5f5f5f5f 32 plan9 CMPL DL, 0(CX)
+3811|223344556677885f5f5f5f5f5f5f 64 gnu cmp %dl,(%rcx)
+3811|223344556677885f5f5f5f5f5f5f 64 intel cmp byte ptr [rcx], dl
+3811|223344556677885f5f5f5f5f5f5f 64 plan9 CMPL DL, 0(CX)
+3911|223344556677885f5f5f5f5f5f5f 32 intel cmp dword ptr [ecx], edx
+3911|223344556677885f5f5f5f5f5f5f 32 plan9 CMPL DX, 0(CX)
+3911|223344556677885f5f5f5f5f5f5f 64 gnu cmp %edx,(%rcx)
+3911|223344556677885f5f5f5f5f5f5f 64 intel cmp dword ptr [rcx], edx
+3911|223344556677885f5f5f5f5f5f5f 64 plan9 CMPL DX, 0(CX)
+3a11|223344556677885f5f5f5f5f5f5f 32 intel cmp dl, byte ptr [ecx]
+3a11|223344556677885f5f5f5f5f5f5f 32 plan9 CMPL 0(CX), DL
+3a11|223344556677885f5f5f5f5f5f5f 64 gnu cmp (%rcx),%dl
+3a11|223344556677885f5f5f5f5f5f5f 64 intel cmp dl, byte ptr [rcx]
+3a11|223344556677885f5f5f5f5f5f5f 64 plan9 CMPL 0(CX), DL
+3b11|223344556677885f5f5f5f5f5f5f 32 intel cmp edx, dword ptr [ecx]
+3b11|223344556677885f5f5f5f5f5f5f 32 plan9 CMPL 0(CX), DX
+3b11|223344556677885f5f5f5f5f5f5f 64 gnu cmp (%rcx),%edx
+3b11|223344556677885f5f5f5f5f5f5f 64 intel cmp edx, dword ptr [rcx]
+3b11|223344556677885f5f5f5f5f5f5f 64 plan9 CMPL 0(CX), DX
+3c11|223344556677885f5f5f5f5f5f5f 32 intel cmp al, 0x11
+3c11|223344556677885f5f5f5f5f5f5f 32 plan9 CMPL $0x11, AL
+3c11|223344556677885f5f5f5f5f5f5f 64 gnu cmp $0x11,%al
+3c11|223344556677885f5f5f5f5f5f5f 64 intel cmp al, 0x11
+3c11|223344556677885f5f5f5f5f5f5f 64 plan9 CMPL $0x11, AL
+3d11223344|556677885f5f5f5f5f5f5f 32 intel cmp eax, 0x44332211
+3d11223344|556677885f5f5f5f5f5f5f 32 plan9 CMPL $0x44332211, AX
+3d11223344|556677885f5f5f5f5f5f5f 64 gnu cmp $0x44332211,%eax
+3d11223344|556677885f5f5f5f5f5f5f 64 intel cmp eax, 0x44332211
+3d11223344|556677885f5f5f5f5f5f5f 64 plan9 CMPL $0x44332211, AX
+3e67e011|223344556677885f5f5f5f5f 32 intel addr16 loopne .+0x11
+3e67e011|223344556677885f5f5f5f5f 32 plan9 LOOPNE .+17
+3e67e011|223344556677885f5f5f5f5f 64 gnu loopne,pt .+0x11
+3e67e011|223344556677885f5f5f5f5f 64 intel addr32 loopne .+0x11
+3e67e011|223344556677885f5f5f5f5f 64 plan9 LOOPNE .+17
+3ef367660f38f011|223344556677885f 32 intel movbe dx, word ptr [bx+di*1]
+3ef367660f38f011|223344556677885f 32 plan9 MOVBE DS:0(BX)(DI*1), DX
+3ef367660f38f011|223344556677885f 64 gnu rep movbe %ds:(%ecx),%dx
+3ef367660f38f011|223344556677885f 64 intel movbe dx, word ptr [ecx]
+3ef367660f38f011|223344556677885f 64 plan9 MOVBE 0(CX), DX
+3f|11223344556677885f5f5f5f5f5f5f 32 intel aas
+3f|11223344556677885f5f5f5f5f5f5f 32 plan9 AAS
+3f|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+3f|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+3f|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+4040|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+4040|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+4040|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+4048|11223344556677885f5f5f5f5f5f 64 gnu error: unrecognized instruction
+4048|11223344556677885f5f5f5f5f5f 64 intel error: unrecognized instruction
+4048|11223344556677885f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+40|11223344556677885f5f5f5f5f5f5f 32 intel inc eax
+40|11223344556677885f5f5f5f5f5f5f 32 plan9 INCL AX
+480100|11223344556677885f5f5f5f5f 64 gnu add %rax,(%rax)
+480100|11223344556677885f5f5f5f5f 64 intel add qword ptr [rax], rax
+480100|11223344556677885f5f5f5f5f 64 plan9 ADDQ AX, 0(AX)
+480311|223344556677885f5f5f5f5f5f 64 gnu add (%rcx),%rdx
+480311|223344556677885f5f5f5f5f5f 64 intel add rdx, qword ptr [rcx]
+480311|223344556677885f5f5f5f5f5f 64 plan9 ADDQ 0(CX), DX
+480511223344|556677885f5f5f5f5f5f 64 gnu add $0x44332211,%rax
+480511223344|556677885f5f5f5f5f5f 64 intel add rax, 0x44332211
+480511223344|556677885f5f5f5f5f5f 64 plan9 ADDQ $0x44332211, AX
+480911|223344556677885f5f5f5f5f5f 64 gnu or %rdx,(%rcx)
+480911|223344556677885f5f5f5f5f5f 64 intel or qword ptr [rcx], rdx
+480911|223344556677885f5f5f5f5f5f 64 plan9 ORQ DX, 0(CX)
+480b11|223344556677885f5f5f5f5f5f 64 gnu or (%rcx),%rdx
+480b11|223344556677885f5f5f5f5f5f 64 intel or rdx, qword ptr [rcx]
+480b11|223344556677885f5f5f5f5f5f 64 plan9 ORQ 0(CX), DX
+480d11223344|556677885f5f5f5f5f5f 64 gnu or $0x44332211,%rax
+480d11223344|556677885f5f5f5f5f5f 64 intel or rax, 0x44332211
+480d11223344|556677885f5f5f5f5f5f 64 plan9 ORQ $0x44332211, AX
+480f0000|11223344556677885f5f5f5f 64 gnu sldt (%rax)
+480f0000|11223344556677885f5f5f5f 64 intel sldt word ptr [rax]
+480f0000|11223344556677885f5f5f5f 64 plan9 SLDT 0(AX)
+480f0008|11223344556677885f5f5f5f 64 gnu str (%rax)
+480f0008|11223344556677885f5f5f5f 64 intel str word ptr [rax]
+480f0008|11223344556677885f5f5f5f 64 plan9 STR 0(AX)
+480f0120|11223344556677885f5f5f5f 64 gnu smsw (%rax)
+480f0120|11223344556677885f5f5f5f 64 intel smsw word ptr [rax]
+480f0120|11223344556677885f5f5f5f 64 plan9 SMSW 0(AX)
+480f0211|223344556677885f5f5f5f5f 64 gnu lar (%rcx),%rdx
+480f0211|223344556677885f5f5f5f5f 64 intel lar rdx, word ptr [rcx]
+480f0211|223344556677885f5f5f5f5f 64 plan9 LAR 0(CX), DX
+480f0311|223344556677885f5f5f5f5f 64 gnu lsl (%rcx),%rdx
+480f0311|223344556677885f5f5f5f5f 64 intel lsl rdx, word ptr [rcx]
+480f0311|223344556677885f5f5f5f5f 64 plan9 LSL 0(CX), DX
+480f35|11223344556677885f5f5f5f5f 64 gnu sysexit
+480f35|11223344556677885f5f5f5f5f 64 intel sysexit
+480f35|11223344556677885f5f5f5f5f 64 plan9 SYSEXIT
+480f38f011|223344556677885f5f5f5f 64 gnu movbe (%rcx),%rdx
+480f38f011|223344556677885f5f5f5f 64 intel movbe rdx, qword ptr [rcx]
+480f38f011|223344556677885f5f5f5f 64 plan9 MOVBE 0(CX), DX
+480f38f111|223344556677885f5f5f5f 64 gnu movbe %rdx,(%rcx)
+480f38f111|223344556677885f5f5f5f 64 intel movbe qword ptr [rcx], rdx
+480f38f111|223344556677885f5f5f5f 64 plan9 MOVBE DX, 0(CX)
+480f4011|223344556677885f5f5f5f5f 64 gnu cmovo (%rcx),%rdx
+480f4011|223344556677885f5f5f5f5f 64 intel cmovo rdx, qword ptr [rcx]
+480f4011|223344556677885f5f5f5f5f 64 plan9 CMOVO 0(CX), DX
+480f4111|223344556677885f5f5f5f5f 64 gnu cmovno (%rcx),%rdx
+480f4111|223344556677885f5f5f5f5f 64 intel cmovno rdx, qword ptr [rcx]
+480f4111|223344556677885f5f5f5f5f 64 plan9 CMOVNO 0(CX), DX
+480f4211|223344556677885f5f5f5f5f 64 gnu cmovb (%rcx),%rdx
+480f4211|223344556677885f5f5f5f5f 64 intel cmovb rdx, qword ptr [rcx]
+480f4211|223344556677885f5f5f5f5f 64 plan9 CMOVB 0(CX), DX
+480f4311|223344556677885f5f5f5f5f 64 gnu cmovae (%rcx),%rdx
+480f4311|223344556677885f5f5f5f5f 64 intel cmovnb rdx, qword ptr [rcx]
+480f4311|223344556677885f5f5f5f5f 64 plan9 CMOVAE 0(CX), DX
+480f4411|223344556677885f5f5f5f5f 64 gnu cmove (%rcx),%rdx
+480f4411|223344556677885f5f5f5f5f 64 intel cmovz rdx, qword ptr [rcx]
+480f4411|223344556677885f5f5f5f5f 64 plan9 CMOVE 0(CX), DX
+480f4511|223344556677885f5f5f5f5f 64 gnu cmovne (%rcx),%rdx
+480f4511|223344556677885f5f5f5f5f 64 intel cmovnz rdx, qword ptr [rcx]
+480f4511|223344556677885f5f5f5f5f 64 plan9 CMOVNE 0(CX), DX
+480f4611|223344556677885f5f5f5f5f 64 gnu cmovbe (%rcx),%rdx
+480f4611|223344556677885f5f5f5f5f 64 intel cmovbe rdx, qword ptr [rcx]
+480f4611|223344556677885f5f5f5f5f 64 plan9 CMOVBE 0(CX), DX
+480f4711|223344556677885f5f5f5f5f 64 gnu cmova (%rcx),%rdx
+480f4711|223344556677885f5f5f5f5f 64 intel cmovnbe rdx, qword ptr [rcx]
+480f4711|223344556677885f5f5f5f5f 64 plan9 CMOVA 0(CX), DX
+480f4811|223344556677885f5f5f5f5f 64 gnu cmovs (%rcx),%rdx
+480f4811|223344556677885f5f5f5f5f 64 intel cmovs rdx, qword ptr [rcx]
+480f4811|223344556677885f5f5f5f5f 64 plan9 CMOVS 0(CX), DX
+480f4911|223344556677885f5f5f5f5f 64 gnu cmovns (%rcx),%rdx
+480f4911|223344556677885f5f5f5f5f 64 intel cmovns rdx, qword ptr [rcx]
+480f4911|223344556677885f5f5f5f5f 64 plan9 CMOVNS 0(CX), DX
+480f4a11|223344556677885f5f5f5f5f 64 gnu cmovp (%rcx),%rdx
+480f4a11|223344556677885f5f5f5f5f 64 intel cmovp rdx, qword ptr [rcx]
+480f4a11|223344556677885f5f5f5f5f 64 plan9 CMOVP 0(CX), DX
+480f4b11|223344556677885f5f5f5f5f 64 gnu cmovnp (%rcx),%rdx
+480f4b11|223344556677885f5f5f5f5f 64 intel cmovnp rdx, qword ptr [rcx]
+480f4b11|223344556677885f5f5f5f5f 64 plan9 CMOVNP 0(CX), DX
+480f4c11|223344556677885f5f5f5f5f 64 gnu cmovl (%rcx),%rdx
+480f4c11|223344556677885f5f5f5f5f 64 intel cmovl rdx, qword ptr [rcx]
+480f4c11|223344556677885f5f5f5f5f 64 plan9 CMOVL 0(CX), DX
+480f4d11|223344556677885f5f5f5f5f 64 gnu cmovge (%rcx),%rdx
+480f4d11|223344556677885f5f5f5f5f 64 intel cmovnl rdx, qword ptr [rcx]
+480f4d11|223344556677885f5f5f5f5f 64 plan9 CMOVGE 0(CX), DX
+480f4e11|223344556677885f5f5f5f5f 64 gnu cmovle (%rcx),%rdx
+480f4e11|223344556677885f5f5f5f5f 64 intel cmovle rdx, qword ptr [rcx]
+480f4e11|223344556677885f5f5f5f5f 64 plan9 CMOVLE 0(CX), DX
+480f4f11|223344556677885f5f5f5f5f 64 gnu cmovg (%rcx),%rdx
+480f4f11|223344556677885f5f5f5f5f 64 intel cmovnle rdx, qword ptr [rcx]
+480f4f11|223344556677885f5f5f5f5f 64 plan9 CMOVG 0(CX), DX
+480f6e11|223344556677885f5f5f5f5f 64 gnu movq (%rcx),%mm2
+480f6e11|223344556677885f5f5f5f5f 64 intel movq mmx2, qword ptr [rcx]
+480f6e11|223344556677885f5f5f5f5f 64 plan9 MOVQ 0(CX), M2
+480f7e11|223344556677885f5f5f5f5f 64 gnu movq %mm2,(%rcx)
+480f7e11|223344556677885f5f5f5f5f 64 intel movq qword ptr [rcx], mmx2
+480f7e11|223344556677885f5f5f5f5f 64 plan9 MOVQ M2, 0(CX)
+480f8011223344|556677885f5f5f5f5f 64 gnu jo .+0x44332211
+480f8011223344|556677885f5f5f5f5f 64 intel jo .+0x44332211
+480f8011223344|556677885f5f5f5f5f 64 plan9 JO .+1144201745
+480f8111223344|556677885f5f5f5f5f 64 gnu jno .+0x44332211
+480f8111223344|556677885f5f5f5f5f 64 intel jno .+0x44332211
+480f8111223344|556677885f5f5f5f5f 64 plan9 JNO .+1144201745
+480f8211223344|556677885f5f5f5f5f 64 gnu jb .+0x44332211
+480f8211223344|556677885f5f5f5f5f 64 intel jb .+0x44332211
+480f8211223344|556677885f5f5f5f5f 64 plan9 JB .+1144201745
+480f8311223344|556677885f5f5f5f5f 64 gnu jae .+0x44332211
+480f8311223344|556677885f5f5f5f5f 64 intel jnb .+0x44332211
+480f8311223344|556677885f5f5f5f5f 64 plan9 JAE .+1144201745
+480f8411223344|556677885f5f5f5f5f 64 gnu je .+0x44332211
+480f8411223344|556677885f5f5f5f5f 64 intel jz .+0x44332211
+480f8411223344|556677885f5f5f5f5f 64 plan9 JE .+1144201745
+480f8511223344|556677885f5f5f5f5f 64 gnu jne .+0x44332211
+480f8511223344|556677885f5f5f5f5f 64 intel jnz .+0x44332211
+480f8511223344|556677885f5f5f5f5f 64 plan9 JNE .+1144201745
+480f8611223344|556677885f5f5f5f5f 64 gnu jbe .+0x44332211
+480f8611223344|556677885f5f5f5f5f 64 intel jbe .+0x44332211
+480f8611223344|556677885f5f5f5f5f 64 plan9 JBE .+1144201745
+480f8711223344|556677885f5f5f5f5f 64 gnu ja .+0x44332211
+480f8711223344|556677885f5f5f5f5f 64 intel jnbe .+0x44332211
+480f8711223344|556677885f5f5f5f5f 64 plan9 JA .+1144201745
+480f8811223344|556677885f5f5f5f5f 64 gnu js .+0x44332211
+480f8811223344|556677885f5f5f5f5f 64 intel js .+0x44332211
+480f8811223344|556677885f5f5f5f5f 64 plan9 JS .+1144201745
+480f8911223344|556677885f5f5f5f5f 64 gnu jns .+0x44332211
+480f8911223344|556677885f5f5f5f5f 64 intel jns .+0x44332211
+480f8911223344|556677885f5f5f5f5f 64 plan9 JNS .+1144201745
+480f8a11223344|556677885f5f5f5f5f 64 gnu jp .+0x44332211
+480f8a11223344|556677885f5f5f5f5f 64 intel jp .+0x44332211
+480f8a11223344|556677885f5f5f5f5f 64 plan9 JP .+1144201745
+480f8b11223344|556677885f5f5f5f5f 64 gnu jnp .+0x44332211
+480f8b11223344|556677885f5f5f5f5f 64 intel jnp .+0x44332211
+480f8b11223344|556677885f5f5f5f5f 64 plan9 JNP .+1144201745
+480f8c11223344|556677885f5f5f5f5f 64 gnu jl .+0x44332211
+480f8c11223344|556677885f5f5f5f5f 64 intel jl .+0x44332211
+480f8c11223344|556677885f5f5f5f5f 64 plan9 JL .+1144201745
+480f8d11223344|556677885f5f5f5f5f 64 gnu jge .+0x44332211
+480f8d11223344|556677885f5f5f5f5f 64 intel jnl .+0x44332211
+480f8d11223344|556677885f5f5f5f5f 64 plan9 JGE .+1144201745
+480f8e11223344|556677885f5f5f5f5f 64 gnu jle .+0x44332211
+480f8e11223344|556677885f5f5f5f5f 64 intel jle .+0x44332211
+480f8e11223344|556677885f5f5f5f5f 64 plan9 JLE .+1144201745
+480f8f11223344|556677885f5f5f5f5f 64 gnu jg .+0x44332211
+480f8f11223344|556677885f5f5f5f5f 64 intel jnle .+0x44332211
+480f8f11223344|556677885f5f5f5f5f 64 plan9 JG .+1144201745
+480fa1|11223344556677885f5f5f5f5f 64 gnu popq %fs
+480fa1|11223344556677885f5f5f5f5f 64 intel pop fs
+480fa1|11223344556677885f5f5f5f5f 64 plan9 POPQ FS
+480fa311|223344556677885f5f5f5f5f 64 gnu bt %rdx,(%rcx)
+480fa311|223344556677885f5f5f5f5f 64 intel bt qword ptr [rcx], rdx
+480fa311|223344556677885f5f5f5f5f 64 plan9 BTQ DX, 0(CX)
+480fa41122|3344556677885f5f5f5f5f 64 gnu shld $0x22,%rdx,(%rcx)
+480fa41122|3344556677885f5f5f5f5f 64 intel shld qword ptr [rcx], rdx, 0x22
+480fa41122|3344556677885f5f5f5f5f 64 plan9 SHLDQ $0x22, DX, 0(CX)
+480fa511|223344556677885f5f5f5f5f 64 gnu shld %cl,%rdx,(%rcx)
+480fa511|223344556677885f5f5f5f5f 64 intel shld qword ptr [rcx], rdx, cl
+480fa511|223344556677885f5f5f5f5f 64 plan9 SHLDQ CL, DX, 0(CX)
+480fa9|11223344556677885f5f5f5f5f 64 gnu popq %gs
+480fa9|11223344556677885f5f5f5f5f 64 intel pop gs
+480fa9|11223344556677885f5f5f5f5f 64 plan9 POPQ GS
+480fab11|223344556677885f5f5f5f5f 64 gnu bts %rdx,(%rcx)
+480fab11|223344556677885f5f5f5f5f 64 intel bts qword ptr [rcx], rdx
+480fab11|223344556677885f5f5f5f5f 64 plan9 BTSQ DX, 0(CX)
+480fac1122|3344556677885f5f5f5f5f 64 gnu shrd $0x22,%rdx,(%rcx)
+480fac1122|3344556677885f5f5f5f5f 64 intel shrd qword ptr [rcx], rdx, 0x22
+480fac1122|3344556677885f5f5f5f5f 64 plan9 SHRDQ $0x22, DX, 0(CX)
+480fad11|223344556677885f5f5f5f5f 64 gnu shrd %cl,%rdx,(%rcx)
+480fad11|223344556677885f5f5f5f5f 64 intel shrd qword ptr [rcx], rdx, cl
+480fad11|223344556677885f5f5f5f5f 64 plan9 SHRDQ CL, DX, 0(CX)
+480fae00|11223344556677885f5f5f5f 64 gnu fxsave64 (%rax)
+480fae00|11223344556677885f5f5f5f 64 intel fxsave64 ptr [rax]
+480fae00|11223344556677885f5f5f5f 64 plan9 FXSAVE64 0(AX)
+480fae08|11223344556677885f5f5f5f 64 gnu fxrstor64 (%rax)
+480fae08|11223344556677885f5f5f5f 64 intel fxrstor64 ptr [rax]
+480fae08|11223344556677885f5f5f5f 64 plan9 FXRSTOR64 0(AX)
+480fae20|11223344556677885f5f5f5f 64 gnu xsave64 (%rax)
+480fae20|11223344556677885f5f5f5f 64 intel xsave64 ptr [rax]
+480fae20|11223344556677885f5f5f5f 64 plan9 XSAVE64 0(AX)
+480fae28|11223344556677885f5f5f5f 64 gnu xrstor64 (%rax)
+480fae28|11223344556677885f5f5f5f 64 intel xrstor64 ptr [rax]
+480fae28|11223344556677885f5f5f5f 64 plan9 XRSTOR64 0(AX)
+480fae30|11223344556677885f5f5f5f 64 gnu xsaveopt64 (%rax)
+480fae30|11223344556677885f5f5f5f 64 intel xsaveopt64 ptr [rax]
+480fae30|11223344556677885f5f5f5f 64 plan9 XSAVEOPT64 0(AX)
+480faf11|223344556677885f5f5f5f5f 64 gnu imul (%rcx),%rdx
+480faf11|223344556677885f5f5f5f5f 64 intel imul rdx, qword ptr [rcx]
+480faf11|223344556677885f5f5f5f5f 64 plan9 IMULQ 0(CX), DX
+480fb111|223344556677885f5f5f5f5f 64 gnu cmpxchg %rdx,(%rcx)
+480fb111|223344556677885f5f5f5f5f 64 intel cmpxchg qword ptr [rcx], rdx
+480fb111|223344556677885f5f5f5f5f 64 plan9 CMPXCHGQ DX, 0(CX)
+480fb211|223344556677885f5f5f5f5f 64 gnu lss (%rcx),%rdx
+480fb211|223344556677885f5f5f5f5f 64 intel lss rdx, ptr [rcx]
+480fb211|223344556677885f5f5f5f5f 64 plan9 LSS 0(CX), DX
+480fb311|223344556677885f5f5f5f5f 64 gnu btr %rdx,(%rcx)
+480fb311|223344556677885f5f5f5f5f 64 intel btr qword ptr [rcx], rdx
+480fb311|223344556677885f5f5f5f5f 64 plan9 BTRQ DX, 0(CX)
+480fb411|223344556677885f5f5f5f5f 64 gnu lfs (%rcx),%rdx
+480fb411|223344556677885f5f5f5f5f 64 intel lfs rdx, ptr [rcx]
+480fb411|223344556677885f5f5f5f5f 64 plan9 LFS 0(CX), DX
+480fb511|223344556677885f5f5f5f5f 64 gnu lgs (%rcx),%rdx
+480fb511|223344556677885f5f5f5f5f 64 intel lgs rdx, ptr [rcx]
+480fb511|223344556677885f5f5f5f5f 64 plan9 LGS 0(CX), DX
+480fb611|223344556677885f5f5f5f5f 64 gnu movzbq (%rcx),%rdx
+480fb611|223344556677885f5f5f5f5f 64 intel movzx rdx, byte ptr [rcx]
+480fb611|223344556677885f5f5f5f5f 64 plan9 MOVZX 0(CX), DX
+480fb711|223344556677885f5f5f5f5f 64 gnu movzwq (%rcx),%rdx
+480fb711|223344556677885f5f5f5f5f 64 intel movzx rdx, word ptr [rcx]
+480fb711|223344556677885f5f5f5f5f 64 plan9 MOVZX 0(CX), DX
+480fba2011|223344556677885f5f5f5f 64 gnu btq $0x11,(%rax)
+480fba2011|223344556677885f5f5f5f 64 intel bt qword ptr [rax], 0x11
+480fba2011|223344556677885f5f5f5f 64 plan9 BTQ $0x11, 0(AX)
+480fba2811|223344556677885f5f5f5f 64 gnu btsq $0x11,(%rax)
+480fba2811|223344556677885f5f5f5f 64 intel bts qword ptr [rax], 0x11
+480fba2811|223344556677885f5f5f5f 64 plan9 BTSQ $0x11, 0(AX)
+480fba3011|223344556677885f5f5f5f 64 gnu btrq $0x11,(%rax)
+480fba3011|223344556677885f5f5f5f 64 intel btr qword ptr [rax], 0x11
+480fba3011|223344556677885f5f5f5f 64 plan9 BTRQ $0x11, 0(AX)
+480fba3811|223344556677885f5f5f5f 64 gnu btcq $0x11,(%rax)
+480fba3811|223344556677885f5f5f5f 64 intel btc qword ptr [rax], 0x11
+480fba3811|223344556677885f5f5f5f 64 plan9 BTCQ $0x11, 0(AX)
+480fbb11|223344556677885f5f5f5f5f 64 gnu btc %rdx,(%rcx)
+480fbb11|223344556677885f5f5f5f5f 64 intel btc qword ptr [rcx], rdx
+480fbb11|223344556677885f5f5f5f5f 64 plan9 BTCQ DX, 0(CX)
+480fbc11|223344556677885f5f5f5f5f 64 gnu bsf (%rcx),%rdx
+480fbc11|223344556677885f5f5f5f5f 64 intel bsf rdx, qword ptr [rcx]
+480fbc11|223344556677885f5f5f5f5f 64 plan9 BSFQ 0(CX), DX
+480fbd11|223344556677885f5f5f5f5f 64 gnu bsr (%rcx),%rdx
+480fbd11|223344556677885f5f5f5f5f 64 intel bsr rdx, qword ptr [rcx]
+480fbd11|223344556677885f5f5f5f5f 64 plan9 BSRQ 0(CX), DX
+480fbe11|223344556677885f5f5f5f5f 64 gnu movsbq (%rcx),%rdx
+480fbe11|223344556677885f5f5f5f5f 64 intel movsx rdx, byte ptr [rcx]
+480fbe11|223344556677885f5f5f5f5f 64 plan9 MOVSX 0(CX), DX
+480fbf11|223344556677885f5f5f5f5f 64 gnu movswq (%rcx),%rdx
+480fbf11|223344556677885f5f5f5f5f 64 intel movsx rdx, word ptr [rcx]
+480fbf11|223344556677885f5f5f5f5f 64 plan9 MOVSX 0(CX), DX
+480fc111|223344556677885f5f5f5f5f 64 gnu xadd %rdx,(%rcx)
+480fc111|223344556677885f5f5f5f5f 64 intel xadd qword ptr [rcx], rdx
+480fc111|223344556677885f5f5f5f5f 64 plan9 XADDQ DX, 0(CX)
+480fc311|223344556677885f5f5f5f5f 64 gnu movnti %rdx,(%rcx)
+480fc311|223344556677885f5f5f5f5f 64 intel movnti qword ptr [rcx], rdx
+480fc311|223344556677885f5f5f5f5f 64 plan9 MOVNTIQ DX, 0(CX)
+480fc708|11223344556677885f5f5f5f 64 gnu cmpxchg16b (%rax)
+480fc708|11223344556677885f5f5f5f 64 intel cmpxchg16b xmmword ptr [rax]
+480fc708|11223344556677885f5f5f5f 64 plan9 CMPXCHG16B 0(AX)
+480fc718|11223344556677885f5f5f5f 64 gnu xrstors64 (%rax)
+480fc718|11223344556677885f5f5f5f 64 intel xrstors64 ptr [rax]
+480fc718|11223344556677885f5f5f5f 64 plan9 XRSTORS64 0(AX)
+480fc720|11223344556677885f5f5f5f 64 gnu xsavec64 (%rax)
+480fc720|11223344556677885f5f5f5f 64 intel xsavec64 ptr [rax]
+480fc720|11223344556677885f5f5f5f 64 plan9 XSAVEC64 0(AX)
+480fc728|11223344556677885f5f5f5f 64 gnu xsaves64 (%rax)
+480fc728|11223344556677885f5f5f5f 64 intel xsaves64 ptr [rax]
+480fc728|11223344556677885f5f5f5f 64 plan9 XSAVES64 0(AX)
+480fc730|11223344556677885f5f5f5f 64 gnu rdrand
+480fc730|11223344556677885f5f5f5f 64 intel rdrand
+480fc730|11223344556677885f5f5f5f 64 plan9 RDRAND
+480fc8|11223344556677885f5f5f5f5f 64 gnu bswap %rax
+480fc8|11223344556677885f5f5f5f5f 64 intel bswap rax
+480fc8|11223344556677885f5f5f5f5f 64 plan9 BSWAP AX
+481122|3344556677885f5f5f5f5f5f5f 64 gnu adc %rsp,(%rdx)
+481122|3344556677885f5f5f5f5f5f5f 64 intel adc qword ptr [rdx], rsp
+481122|3344556677885f5f5f5f5f5f5f 64 plan9 ADCQ SP, 0(DX)
+481311|223344556677885f5f5f5f5f5f 64 gnu adc (%rcx),%rdx
+481311|223344556677885f5f5f5f5f5f 64 intel adc rdx, qword ptr [rcx]
+481311|223344556677885f5f5f5f5f5f 64 plan9 ADCQ 0(CX), DX
+481511223344|556677885f5f5f5f5f5f 64 gnu adc $0x44332211,%rax
+481511223344|556677885f5f5f5f5f5f 64 intel adc rax, 0x44332211
+481511223344|556677885f5f5f5f5f5f 64 plan9 ADCQ $0x44332211, AX
+481911|223344556677885f5f5f5f5f5f 64 gnu sbb %rdx,(%rcx)
+481911|223344556677885f5f5f5f5f5f 64 intel sbb qword ptr [rcx], rdx
+481911|223344556677885f5f5f5f5f5f 64 plan9 SBBQ DX, 0(CX)
+481b11|223344556677885f5f5f5f5f5f 64 gnu sbb (%rcx),%rdx
+481b11|223344556677885f5f5f5f5f5f 64 intel sbb rdx, qword ptr [rcx]
+481b11|223344556677885f5f5f5f5f5f 64 plan9 SBBQ 0(CX), DX
+481d11223344|556677885f5f5f5f5f5f 64 gnu sbb $0x44332211,%rax
+481d11223344|556677885f5f5f5f5f5f 64 intel sbb rax, 0x44332211
+481d11223344|556677885f5f5f5f5f5f 64 plan9 SBBQ $0x44332211, AX
+482111|223344556677885f5f5f5f5f5f 64 gnu and %rdx,(%rcx)
+482111|223344556677885f5f5f5f5f5f 64 intel and qword ptr [rcx], rdx
+482111|223344556677885f5f5f5f5f5f 64 plan9 ANDQ DX, 0(CX)
+482311|223344556677885f5f5f5f5f5f 64 gnu and (%rcx),%rdx
+482311|223344556677885f5f5f5f5f5f 64 intel and rdx, qword ptr [rcx]
+482311|223344556677885f5f5f5f5f5f 64 plan9 ANDQ 0(CX), DX
+482511223344|556677885f5f5f5f5f5f 64 gnu and $0x44332211,%rax
+482511223344|556677885f5f5f5f5f5f 64 intel and rax, 0x44332211
+482511223344|556677885f5f5f5f5f5f 64 plan9 ANDQ $0x44332211, AX
+482911|223344556677885f5f5f5f5f5f 64 gnu sub %rdx,(%rcx)
+482911|223344556677885f5f5f5f5f5f 64 intel sub qword ptr [rcx], rdx
+482911|223344556677885f5f5f5f5f5f 64 plan9 SUBQ DX, 0(CX)
+482b11|223344556677885f5f5f5f5f5f 64 gnu sub (%rcx),%rdx
+482b11|223344556677885f5f5f5f5f5f 64 intel sub rdx, qword ptr [rcx]
+482b11|223344556677885f5f5f5f5f5f 64 plan9 SUBQ 0(CX), DX
+482d11223344|556677885f5f5f5f5f5f 64 gnu sub $0x44332211,%rax
+482d11223344|556677885f5f5f5f5f5f 64 intel sub rax, 0x44332211
+482d11223344|556677885f5f5f5f5f5f 64 plan9 SUBQ $0x44332211, AX
+483111|223344556677885f5f5f5f5f5f 64 gnu xor %rdx,(%rcx)
+483111|223344556677885f5f5f5f5f5f 64 intel xor qword ptr [rcx], rdx
+483111|223344556677885f5f5f5f5f5f 64 plan9 XORQ DX, 0(CX)
+483311|223344556677885f5f5f5f5f5f 64 gnu xor (%rcx),%rdx
+483311|223344556677885f5f5f5f5f5f 64 intel xor rdx, qword ptr [rcx]
+483311|223344556677885f5f5f5f5f5f 64 plan9 XORQ 0(CX), DX
+483511223344|556677885f5f5f5f5f5f 64 gnu xor $0x44332211,%rax
+483511223344|556677885f5f5f5f5f5f 64 intel xor rax, 0x44332211
+483511223344|556677885f5f5f5f5f5f 64 plan9 XORQ $0x44332211, AX
+483911|223344556677885f5f5f5f5f5f 64 gnu cmp %rdx,(%rcx)
+483911|223344556677885f5f5f5f5f5f 64 intel cmp qword ptr [rcx], rdx
+483911|223344556677885f5f5f5f5f5f 64 plan9 CMPQ DX, 0(CX)
+483b11|223344556677885f5f5f5f5f5f 64 gnu cmp (%rcx),%rdx
+483b11|223344556677885f5f5f5f5f5f 64 intel cmp rdx, qword ptr [rcx]
+483b11|223344556677885f5f5f5f5f5f 64 plan9 CMPQ 0(CX), DX
+483d11223344|556677885f5f5f5f5f5f 64 gnu cmp $0x44332211,%rax
+483d11223344|556677885f5f5f5f5f5f 64 intel cmp rax, 0x44332211
+483d11223344|556677885f5f5f5f5f5f 64 plan9 CMPQ $0x44332211, AX
+4850|11223344556677885f5f5f5f5f5f 64 gnu push %rax
+4850|11223344556677885f5f5f5f5f5f 64 intel push rax
+4850|11223344556677885f5f5f5f5f5f 64 plan9 PUSHQ AX
+4858|11223344556677885f5f5f5f5f5f 64 gnu pop %rax
+4858|11223344556677885f5f5f5f5f5f 64 intel pop rax
+4858|11223344556677885f5f5f5f5f5f 64 plan9 POPQ AX
+486311|223344556677885f5f5f5f5f5f 64 gnu movsxd (%rcx),%rdx
+486311|223344556677885f5f5f5f5f5f 64 intel movsxd rdx, dword ptr [rcx]
+486311|223344556677885f5f5f5f5f5f 64 plan9 MOVSXD 0(CX), DX
+486811223344|556677885f5f5f5f5f5f 64 gnu pushq $0x44332211
+486811223344|556677885f5f5f5f5f5f 64 intel push 0x44332211
+486811223344|556677885f5f5f5f5f5f 64 plan9 PUSHQ $0x44332211
+48691122334455|6677885f5f5f5f5f5f 64 gnu imul $0x55443322,(%rcx),%rdx
+48691122334455|6677885f5f5f5f5f5f 64 intel imul rdx, qword ptr [rcx], 0x55443322
+48691122334455|6677885f5f5f5f5f5f 64 plan9 IMULQ $0x55443322, 0(CX), DX
+486b1122|3344556677885f5f5f5f5f5f 64 gnu imul $0x22,(%rcx),%rdx
+486b1122|3344556677885f5f5f5f5f5f 64 intel imul rdx, qword ptr [rcx], 0x22
+486b1122|3344556677885f5f5f5f5f5f 64 plan9 IMULQ $0x22, 0(CX), DX
+486d|11223344556677885f5f5f5f5f5f 64 gnu insl (%dx),%es:(%rdi)
+486d|11223344556677885f5f5f5f5f5f 64 intel insd
+486d|11223344556677885f5f5f5f5f5f 64 plan9 INSD DX, ES:0(DI)
+486f|11223344556677885f5f5f5f5f5f 64 gnu outsl %ds:(%rsi),(%dx)
+486f|11223344556677885f5f5f5f5f5f 64 intel outsd
+486f|11223344556677885f5f5f5f5f5f 64 plan9 OUTSD DS:0(SI), DX
+48810011223344|556677885f5f5f5f5f 64 gnu addq $0x44332211,(%rax)
+48810011223344|556677885f5f5f5f5f 64 intel add qword ptr [rax], 0x44332211
+48810011223344|556677885f5f5f5f5f 64 plan9 ADDQ $0x44332211, 0(AX)
+48810811223344|556677885f5f5f5f5f 64 gnu orq $0x44332211,(%rax)
+48810811223344|556677885f5f5f5f5f 64 intel or qword ptr [rax], 0x44332211
+48810811223344|556677885f5f5f5f5f 64 plan9 ORQ $0x44332211, 0(AX)
+48811122334455|6677885f5f5f5f5f5f 64 gnu adcq $0x55443322,(%rcx)
+48811122334455|6677885f5f5f5f5f5f 64 intel adc qword ptr [rcx], 0x55443322
+48811122334455|6677885f5f5f5f5f5f 64 plan9 ADCQ $0x55443322, 0(CX)
+48811811223344|556677885f5f5f5f5f 64 gnu sbbq $0x44332211,(%rax)
+48811811223344|556677885f5f5f5f5f 64 intel sbb qword ptr [rax], 0x44332211
+48811811223344|556677885f5f5f5f5f 64 plan9 SBBQ $0x44332211, 0(AX)
+48812011223344|556677885f5f5f5f5f 64 gnu andq $0x44332211,(%rax)
+48812011223344|556677885f5f5f5f5f 64 intel and qword ptr [rax], 0x44332211
+48812011223344|556677885f5f5f5f5f 64 plan9 ANDQ $0x44332211, 0(AX)
+48812811223344|556677885f5f5f5f5f 64 gnu subq $0x44332211,(%rax)
+48812811223344|556677885f5f5f5f5f 64 intel sub qword ptr [rax], 0x44332211
+48812811223344|556677885f5f5f5f5f 64 plan9 SUBQ $0x44332211, 0(AX)
+48813011223344|556677885f5f5f5f5f 64 gnu xorq $0x44332211,(%rax)
+48813011223344|556677885f5f5f5f5f 64 intel xor qword ptr [rax], 0x44332211
+48813011223344|556677885f5f5f5f5f 64 plan9 XORQ $0x44332211, 0(AX)
+48813811223344|556677885f5f5f5f5f 64 gnu cmpq $0x44332211,(%rax)
+48813811223344|556677885f5f5f5f5f 64 intel cmp qword ptr [rax], 0x44332211
+48813811223344|556677885f5f5f5f5f 64 plan9 CMPQ $0x44332211, 0(AX)
+48830011|223344556677885f5f5f5f5f 64 gnu addq $0x11,(%rax)
+48830011|223344556677885f5f5f5f5f 64 intel add qword ptr [rax], 0x11
+48830011|223344556677885f5f5f5f5f 64 plan9 ADDQ $0x11, 0(AX)
+48830811|223344556677885f5f5f5f5f 64 gnu orq $0x11,(%rax)
+48830811|223344556677885f5f5f5f5f 64 intel or qword ptr [rax], 0x11
+48830811|223344556677885f5f5f5f5f 64 plan9 ORQ $0x11, 0(AX)
+48831122|3344556677885f5f5f5f5f5f 64 gnu adcq $0x22,(%rcx)
+48831122|3344556677885f5f5f5f5f5f 64 intel adc qword ptr [rcx], 0x22
+48831122|3344556677885f5f5f5f5f5f 64 plan9 ADCQ $0x22, 0(CX)
+48831811|223344556677885f5f5f5f5f 64 gnu sbbq $0x11,(%rax)
+48831811|223344556677885f5f5f5f5f 64 intel sbb qword ptr [rax], 0x11
+48831811|223344556677885f5f5f5f5f 64 plan9 SBBQ $0x11, 0(AX)
+48832011|223344556677885f5f5f5f5f 64 gnu andq $0x11,(%rax)
+48832011|223344556677885f5f5f5f5f 64 intel and qword ptr [rax], 0x11
+48832011|223344556677885f5f5f5f5f 64 plan9 ANDQ $0x11, 0(AX)
+48832811|223344556677885f5f5f5f5f 64 gnu subq $0x11,(%rax)
+48832811|223344556677885f5f5f5f5f 64 intel sub qword ptr [rax], 0x11
+48832811|223344556677885f5f5f5f5f 64 plan9 SUBQ $0x11, 0(AX)
+48833011|223344556677885f5f5f5f5f 64 gnu xorq $0x11,(%rax)
+48833011|223344556677885f5f5f5f5f 64 intel xor qword ptr [rax], 0x11
+48833011|223344556677885f5f5f5f5f 64 plan9 XORQ $0x11, 0(AX)
+48833811|223344556677885f5f5f5f5f 64 gnu cmpq $0x11,(%rax)
+48833811|223344556677885f5f5f5f5f 64 intel cmp qword ptr [rax], 0x11
+48833811|223344556677885f5f5f5f5f 64 plan9 CMPQ $0x11, 0(AX)
+488511|223344556677885f5f5f5f5f5f 64 gnu test %rdx,(%rcx)
+488511|223344556677885f5f5f5f5f5f 64 intel test qword ptr [rcx], rdx
+488511|223344556677885f5f5f5f5f5f 64 plan9 TESTQ DX, 0(CX)
+488711|223344556677885f5f5f5f5f5f 64 gnu xchg %rdx,(%rcx)
+488711|223344556677885f5f5f5f5f5f 64 intel xchg qword ptr [rcx], rdx
+488711|223344556677885f5f5f5f5f5f 64 plan9 XCHGQ DX, 0(CX)
+488911|223344556677885f5f5f5f5f5f 64 gnu mov %rdx,(%rcx)
+488911|223344556677885f5f5f5f5f5f 64 intel mov qword ptr [rcx], rdx
+488911|223344556677885f5f5f5f5f5f 64 plan9 MOVQ DX, 0(CX)
+488b11|223344556677885f5f5f5f5f5f 64 gnu mov (%rcx),%rdx
+488b11|223344556677885f5f5f5f5f5f 64 intel mov rdx, qword ptr [rcx]
+488b11|223344556677885f5f5f5f5f5f 64 plan9 MOVQ 0(CX), DX
+488c11|223344556677885f5f5f5f5f5f 64 gnu mov %ss,(%rcx)
+488c11|223344556677885f5f5f5f5f5f 64 intel mov word ptr [rcx], ss
+488c11|223344556677885f5f5f5f5f5f 64 plan9 MOVQ SS, 0(CX)
+488d11|223344556677885f5f5f5f5f5f 64 gnu lea (%rcx),%rdx
+488d11|223344556677885f5f5f5f5f5f 64 intel lea rdx, ptr [rcx]
+488d11|223344556677885f5f5f5f5f5f 64 plan9 LEAQ 0(CX), DX
+488e11|223344556677885f5f5f5f5f5f 64 gnu mov (%rcx),%ss
+488e11|223344556677885f5f5f5f5f5f 64 intel mov ss, word ptr [rcx]
+488e11|223344556677885f5f5f5f5f5f 64 plan9 MOVQ 0(CX), SS
+488f00|11223344556677885f5f5f5f5f 64 gnu popq (%rax)
+488f00|11223344556677885f5f5f5f5f 64 intel pop qword ptr [rax]
+488f00|11223344556677885f5f5f5f5f 64 plan9 POPQ 0(AX)
+4891|11223344556677885f5f5f5f5f5f 64 gnu xchg %rax,%rcx
+4891|11223344556677885f5f5f5f5f5f 64 intel xchg rcx, rax
+4891|11223344556677885f5f5f5f5f5f 64 plan9 XCHGQ AX, CX
+4898|11223344556677885f5f5f5f5f5f 64 gnu cdqe
+4898|11223344556677885f5f5f5f5f5f 64 intel cdqe
+4898|11223344556677885f5f5f5f5f5f 64 plan9 CDQE
+4899|11223344556677885f5f5f5f5f5f 64 gnu cqto
+4899|11223344556677885f5f5f5f5f5f 64 intel cqo
+4899|11223344556677885f5f5f5f5f5f 64 plan9 CQO
+489c|11223344556677885f5f5f5f5f5f 64 gnu pushfq
+489c|11223344556677885f5f5f5f5f5f 64 intel pushfq
+489c|11223344556677885f5f5f5f5f5f 64 plan9 PUSHFQ
+489d|11223344556677885f5f5f5f5f5f 64 gnu popfq
+489d|11223344556677885f5f5f5f5f5f 64 intel popfq
+489d|11223344556677885f5f5f5f5f5f 64 plan9 POPFQ
+48a01122334455667788|5f5f5f5f5f5f 64 gnu mov -0x778899aabbccddef,%al
+48a01122334455667788|5f5f5f5f5f5f 64 intel mov al, byte ptr [0x8877665544332211]
+48a01122334455667788|5f5f5f5f5f5f 64 plan9 MOVQ -0x778899aabbccddef, AL
+48a11122334455667788|5f5f5f5f5f5f 64 gnu mov -0x778899aabbccddef,%rax
+48a11122334455667788|5f5f5f5f5f5f 64 intel mov rax, qword ptr [0x8877665544332211]
+48a11122334455667788|5f5f5f5f5f5f 64 plan9 MOVQ -0x778899aabbccddef, AX
+48a21122334455667788|5f5f5f5f5f5f 64 gnu mov %al,-0x778899aabbccddef
+48a21122334455667788|5f5f5f5f5f5f 64 intel mov byte ptr [0x8877665544332211], al
+48a21122334455667788|5f5f5f5f5f5f 64 plan9 MOVQ AL, -0x778899aabbccddef
+48a31122334455667788|5f5f5f5f5f5f 64 gnu mov %rax,-0x778899aabbccddef
+48a31122334455667788|5f5f5f5f5f5f 64 intel mov qword ptr [0x8877665544332211], rax
+48a31122334455667788|5f5f5f5f5f5f 64 plan9 MOVQ AX, -0x778899aabbccddef
+48a5|11223344556677885f5f5f5f5f5f 64 gnu movsq %ds:(%rsi),%es:(%rdi)
+48a5|11223344556677885f5f5f5f5f5f 64 intel movsq qword ptr [rdi], qword ptr [rsi]
+48a5|11223344556677885f5f5f5f5f5f 64 plan9 MOVSQ DS:0(SI), ES:0(DI)
+48a7|11223344556677885f5f5f5f5f5f 64 gnu cmpsq %es:(%rdi),%ds:(%rsi)
+48a7|11223344556677885f5f5f5f5f5f 64 intel cmpsq qword ptr [rsi], qword ptr [rdi]
+48a7|11223344556677885f5f5f5f5f5f 64 plan9 CMPSQ ES:0(DI), DS:0(SI)
+48a911223344|556677885f5f5f5f5f5f 64 gnu test $0x44332211,%rax
+48a911223344|556677885f5f5f5f5f5f 64 intel test rax, 0x44332211
+48a911223344|556677885f5f5f5f5f5f 64 plan9 TESTQ $0x44332211, AX
+48ab|11223344556677885f5f5f5f5f5f 64 gnu stos %rax,%es:(%rdi)
+48ab|11223344556677885f5f5f5f5f5f 64 intel stosq qword ptr [rdi]
+48ab|11223344556677885f5f5f5f5f5f 64 plan9 STOSQ AX, ES:0(DI)
+48ad|11223344556677885f5f5f5f5f5f 64 gnu lods %ds:(%rsi),%rax
+48ad|11223344556677885f5f5f5f5f5f 64 intel lodsq qword ptr [rsi]
+48ad|11223344556677885f5f5f5f5f5f 64 plan9 LODSQ DS:0(SI), AX
+48af|11223344556677885f5f5f5f5f5f 64 gnu scas %es:(%rdi),%rax
+48af|11223344556677885f5f5f5f5f5f 64 intel scasq qword ptr [rdi]
+48af|11223344556677885f5f5f5f5f5f 64 plan9 SCASQ ES:0(DI), AX
+48b81122334455667788|5f5f5f5f5f5f 64 gnu mov $-0x778899aabbccddef,%rax
+48b81122334455667788|5f5f5f5f5f5f 64 intel mov rax, 0x8877665544332211
+48b81122334455667788|5f5f5f5f5f5f 64 plan9 MOVQ $0x8877665544332211, AX
+48c10011|223344556677885f5f5f5f5f 64 gnu rolq $0x11,(%rax)
+48c10011|223344556677885f5f5f5f5f 64 intel rol qword ptr [rax], 0x11
+48c10011|223344556677885f5f5f5f5f 64 plan9 ROLQ $0x11, 0(AX)
+48c10811|223344556677885f5f5f5f5f 64 gnu rorq $0x11,(%rax)
+48c10811|223344556677885f5f5f5f5f 64 intel ror qword ptr [rax], 0x11
+48c10811|223344556677885f5f5f5f5f 64 plan9 RORQ $0x11, 0(AX)
+48c11122|3344556677885f5f5f5f5f5f 64 gnu rclq $0x22,(%rcx)
+48c11122|3344556677885f5f5f5f5f5f 64 intel rcl qword ptr [rcx], 0x22
+48c11122|3344556677885f5f5f5f5f5f 64 plan9 RCLQ $0x22, 0(CX)
+48c11811|223344556677885f5f5f5f5f 64 gnu rcrq $0x11,(%rax)
+48c11811|223344556677885f5f5f5f5f 64 intel rcr qword ptr [rax], 0x11
+48c11811|223344556677885f5f5f5f5f 64 plan9 RCRQ $0x11, 0(AX)
+48c12011|223344556677885f5f5f5f5f 64 gnu shlq $0x11,(%rax)
+48c12011|223344556677885f5f5f5f5f 64 intel shl qword ptr [rax], 0x11
+48c12011|223344556677885f5f5f5f5f 64 plan9 SHLQ $0x11, 0(AX)
+48c12811|223344556677885f5f5f5f5f 64 gnu shrq $0x11,(%rax)
+48c12811|223344556677885f5f5f5f5f 64 intel shr qword ptr [rax], 0x11
+48c12811|223344556677885f5f5f5f5f 64 plan9 SHRQ $0x11, 0(AX)
+48c13811|223344556677885f5f5f5f5f 64 gnu sarq $0x11,(%rax)
+48c13811|223344556677885f5f5f5f5f 64 intel sar qword ptr [rax], 0x11
+48c13811|223344556677885f5f5f5f5f 64 plan9 SARQ $0x11, 0(AX)
+48c70011223344|556677885f5f5f5f5f 64 gnu movq $0x44332211,(%rax)
+48c70011223344|556677885f5f5f5f5f 64 intel mov qword ptr [rax], 0x44332211
+48c70011223344|556677885f5f5f5f5f 64 plan9 MOVQ $0x44332211, 0(AX)
+48c7f811223344|556677885f5f5f5f5f 64 gnu xbeginq .+0x44332211
+48c7f811223344|556677885f5f5f5f5f 64 intel xbegin .+0x44332211
+48c7f811223344|556677885f5f5f5f5f 64 plan9 XBEGIN .+1144201745
+48c9|11223344556677885f5f5f5f5f5f 64 gnu leaveq
+48c9|11223344556677885f5f5f5f5f5f 64 intel leave
+48c9|11223344556677885f5f5f5f5f5f 64 plan9 LEAVE
+48cf|11223344556677885f5f5f5f5f5f 64 gnu iretq
+48cf|11223344556677885f5f5f5f5f5f 64 intel iretq
+48cf|11223344556677885f5f5f5f5f5f 64 plan9 IRETQ
+48d100|11223344556677885f5f5f5f5f 64 gnu rolq (%rax)
+48d100|11223344556677885f5f5f5f5f 64 intel rol qword ptr [rax], 0x1
+48d100|11223344556677885f5f5f5f5f 64 plan9 ROLQ $0x1, 0(AX)
+48d108|11223344556677885f5f5f5f5f 64 gnu rorq (%rax)
+48d108|11223344556677885f5f5f5f5f 64 intel ror qword ptr [rax], 0x1
+48d108|11223344556677885f5f5f5f5f 64 plan9 RORQ $0x1, 0(AX)
+48d111|223344556677885f5f5f5f5f5f 64 gnu rclq (%rcx)
+48d111|223344556677885f5f5f5f5f5f 64 intel rcl qword ptr [rcx], 0x1
+48d111|223344556677885f5f5f5f5f5f 64 plan9 RCLQ $0x1, 0(CX)
+48d118|11223344556677885f5f5f5f5f 64 gnu rcrq (%rax)
+48d118|11223344556677885f5f5f5f5f 64 intel rcr qword ptr [rax], 0x1
+48d118|11223344556677885f5f5f5f5f 64 plan9 RCRQ $0x1, 0(AX)
+48d120|11223344556677885f5f5f5f5f 64 gnu shlq (%rax)
+48d120|11223344556677885f5f5f5f5f 64 intel shl qword ptr [rax], 0x1
+48d120|11223344556677885f5f5f5f5f 64 plan9 SHLQ $0x1, 0(AX)
+48d128|11223344556677885f5f5f5f5f 64 gnu shrq (%rax)
+48d128|11223344556677885f5f5f5f5f 64 intel shr qword ptr [rax], 0x1
+48d128|11223344556677885f5f5f5f5f 64 plan9 SHRQ $0x1, 0(AX)
+48d138|11223344556677885f5f5f5f5f 64 gnu sarq (%rax)
+48d138|11223344556677885f5f5f5f5f 64 intel sar qword ptr [rax], 0x1
+48d138|11223344556677885f5f5f5f5f 64 plan9 SARQ $0x1, 0(AX)
+48d300|11223344556677885f5f5f5f5f 64 gnu rolq %cl,(%rax)
+48d300|11223344556677885f5f5f5f5f 64 intel rol qword ptr [rax], cl
+48d300|11223344556677885f5f5f5f5f 64 plan9 ROLQ CL, 0(AX)
+48d308|11223344556677885f5f5f5f5f 64 gnu rorq %cl,(%rax)
+48d308|11223344556677885f5f5f5f5f 64 intel ror qword ptr [rax], cl
+48d308|11223344556677885f5f5f5f5f 64 plan9 RORQ CL, 0(AX)
+48d311|223344556677885f5f5f5f5f5f 64 gnu rclq %cl,(%rcx)
+48d311|223344556677885f5f5f5f5f5f 64 intel rcl qword ptr [rcx], cl
+48d311|223344556677885f5f5f5f5f5f 64 plan9 RCLQ CL, 0(CX)
+48d318|11223344556677885f5f5f5f5f 64 gnu rcrq %cl,(%rax)
+48d318|11223344556677885f5f5f5f5f 64 intel rcr qword ptr [rax], cl
+48d318|11223344556677885f5f5f5f5f 64 plan9 RCRQ CL, 0(AX)
+48d320|11223344556677885f5f5f5f5f 64 gnu shlq %cl,(%rax)
+48d320|11223344556677885f5f5f5f5f 64 intel shl qword ptr [rax], cl
+48d320|11223344556677885f5f5f5f5f 64 plan9 SHLQ CL, 0(AX)
+48d328|11223344556677885f5f5f5f5f 64 gnu shrq %cl,(%rax)
+48d328|11223344556677885f5f5f5f5f 64 intel shr qword ptr [rax], cl
+48d328|11223344556677885f5f5f5f5f 64 plan9 SHRQ CL, 0(AX)
+48d338|11223344556677885f5f5f5f5f 64 gnu sarq %cl,(%rax)
+48d338|11223344556677885f5f5f5f5f 64 intel sar qword ptr [rax], cl
+48d338|11223344556677885f5f5f5f5f 64 plan9 SARQ CL, 0(AX)
+48d7|11223344556677885f5f5f5f5f5f 64 gnu xlat %ds:(%rbx)
+48d7|11223344556677885f5f5f5f5f5f 64 intel xlat
+48d7|11223344556677885f5f5f5f5f5f 64 plan9 XLATB DS:0(BX)
+48e511|223344556677885f5f5f5f5f5f 64 gnu in $0x11,%eax
+48e511|223344556677885f5f5f5f5f5f 64 intel in eax, 0x11
+48e511|223344556677885f5f5f5f5f5f 64 plan9 INQ $0x11, AX
+48e711|223344556677885f5f5f5f5f5f 64 gnu out %eax,$0x11
+48e711|223344556677885f5f5f5f5f5f 64 intel out 0x11, eax
+48e711|223344556677885f5f5f5f5f5f 64 plan9 OUTQ AX, $0x11
+48e811223344|556677885f5f5f5f5f5f 64 gnu callq .+0x44332211
+48e811223344|556677885f5f5f5f5f5f 64 intel call .+0x44332211
+48e811223344|556677885f5f5f5f5f5f 64 plan9 CALL .+1144201745
+48e911223344|556677885f5f5f5f5f5f 64 gnu jmpq .+0x44332211
+48e911223344|556677885f5f5f5f5f5f 64 intel jmp .+0x44332211
+48e911223344|556677885f5f5f5f5f5f 64 plan9 JMP .+1144201745
+48ed|11223344556677885f5f5f5f5f5f 64 gnu in (%dx),%eax
+48ed|11223344556677885f5f5f5f5f5f 64 intel in eax, dx
+48ed|11223344556677885f5f5f5f5f5f 64 plan9 INQ DX, AX
+48ef|11223344556677885f5f5f5f5f5f 64 gnu out %eax,(%dx)
+48ef|11223344556677885f5f5f5f5f5f 64 intel out dx, eax
+48ef|11223344556677885f5f5f5f5f5f 64 plan9 OUTQ AX, DX
+48f70011223344|556677885f5f5f5f5f 64 gnu testq $0x44332211,(%rax)
+48f70011223344|556677885f5f5f5f5f 64 intel test qword ptr [rax], 0x44332211
+48f70011223344|556677885f5f5f5f5f 64 plan9 TESTQ $0x44332211, 0(AX)
+48f711|223344556677885f5f5f5f5f5f 64 gnu notq (%rcx)
+48f711|223344556677885f5f5f5f5f5f 64 intel not qword ptr [rcx]
+48f711|223344556677885f5f5f5f5f5f 64 plan9 NOTQ 0(CX)
+48f718|11223344556677885f5f5f5f5f 64 gnu negq (%rax)
+48f718|11223344556677885f5f5f5f5f 64 intel neg qword ptr [rax]
+48f718|11223344556677885f5f5f5f5f 64 plan9 NEGQ 0(AX)
+48f720|11223344556677885f5f5f5f5f 64 gnu mulq (%rax)
+48f720|11223344556677885f5f5f5f5f 64 intel mul qword ptr [rax]
+48f720|11223344556677885f5f5f5f5f 64 plan9 MULQ 0(AX)
+48f728|11223344556677885f5f5f5f5f 64 gnu imulq (%rax)
+48f728|11223344556677885f5f5f5f5f 64 intel imul qword ptr [rax]
+48f728|11223344556677885f5f5f5f5f 64 plan9 IMULQ 0(AX)
+48f730|11223344556677885f5f5f5f5f 64 gnu divq (%rax)
+48f730|11223344556677885f5f5f5f5f 64 intel div qword ptr [rax]
+48f730|11223344556677885f5f5f5f5f 64 plan9 DIVQ 0(AX)
+48f738|11223344556677885f5f5f5f5f 64 gnu idivq (%rax)
+48f738|11223344556677885f5f5f5f5f 64 intel idiv qword ptr [rax]
+48f738|11223344556677885f5f5f5f5f 64 plan9 IDIVQ 0(AX)
+48ff00|11223344556677885f5f5f5f5f 64 gnu incq (%rax)
+48ff00|11223344556677885f5f5f5f5f 64 intel inc qword ptr [rax]
+48ff00|11223344556677885f5f5f5f5f 64 plan9 INCQ 0(AX)
+48ff08|11223344556677885f5f5f5f5f 64 gnu decq (%rax)
+48ff08|11223344556677885f5f5f5f5f 64 intel dec qword ptr [rax]
+48ff08|11223344556677885f5f5f5f5f 64 plan9 DECQ 0(AX)
+48ff18|11223344556677885f5f5f5f5f 64 gnu lcallq *(%rax)
+48ff18|11223344556677885f5f5f5f5f 64 intel call far ptr [rax]
+48ff18|11223344556677885f5f5f5f5f 64 plan9 LCALL 0(AX)
+48ff28|11223344556677885f5f5f5f5f 64 gnu ljmpq *(%rax)
+48ff28|11223344556677885f5f5f5f5f 64 intel jmp far ptr [rax]
+48ff28|11223344556677885f5f5f5f5f 64 plan9 LJMP 0(AX)
+48ff30|11223344556677885f5f5f5f5f 64 gnu pushq (%rax)
+48ff30|11223344556677885f5f5f5f5f 64 intel push qword ptr [rax]
+48ff30|11223344556677885f5f5f5f5f 64 plan9 PUSHQ 0(AX)
+48|010011223344556677885f5f5f5f5f 32 intel dec eax
+48|010011223344556677885f5f5f5f5f 32 plan9 DECL AX
+50|11223344556677885f5f5f5f5f5f5f 32 intel push eax
+50|11223344556677885f5f5f5f5f5f5f 32 plan9 PUSHL AX
+50|11223344556677885f5f5f5f5f5f5f 64 gnu push %rax
+50|11223344556677885f5f5f5f5f5f5f 64 intel push rax
+50|11223344556677885f5f5f5f5f5f5f 64 plan9 PUSHL AX
+58|11223344556677885f5f5f5f5f5f5f 32 intel pop eax
+58|11223344556677885f5f5f5f5f5f5f 32 plan9 POPL AX
+58|11223344556677885f5f5f5f5f5f5f 64 gnu pop %rax
+58|11223344556677885f5f5f5f5f5f5f 64 intel pop rax
+58|11223344556677885f5f5f5f5f5f5f 64 plan9 POPL AX
+60|11223344556677885f5f5f5f5f5f5f 32 intel pushad
+60|11223344556677885f5f5f5f5f5f5f 32 plan9 PUSHAD
+60|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+60|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+60|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+61|11223344556677885f5f5f5f5f5f5f 32 intel popad
+61|11223344556677885f5f5f5f5f5f5f 32 plan9 POPAD
+61|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+61|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+61|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+6211|223344556677885f5f5f5f5f5f5f 32 intel bound edx, qword ptr [ecx]
+6211|223344556677885f5f5f5f5f5f5f 32 plan9 BOUND 0(CX), DX
+62|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+62|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+62|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+6311|223344556677885f5f5f5f5f5f5f 32 intel arpl word ptr [ecx], dx
+6311|223344556677885f5f5f5f5f5f5f 32 plan9 ARPL DX, 0(CX)
+6311|223344556677885f5f5f5f5f5f5f 64 gnu movsxd (%rcx),%edx
+6311|223344556677885f5f5f5f5f5f5f 64 intel movsxd edx, dword ptr [rcx]
+6311|223344556677885f5f5f5f5f5f5f 64 plan9 MOVSXD 0(CX), DX
+660111|223344556677885f5f5f5f5f5f 32 intel add word ptr [ecx], dx
+660111|223344556677885f5f5f5f5f5f 32 plan9 ADDW DX, 0(CX)
+660111|223344556677885f5f5f5f5f5f 64 gnu add %dx,(%rcx)
+660111|223344556677885f5f5f5f5f5f 64 intel add word ptr [rcx], dx
+660111|223344556677885f5f5f5f5f5f 64 plan9 ADDW DX, 0(CX)
+660311|223344556677885f5f5f5f5f5f 32 intel add dx, word ptr [ecx]
+660311|223344556677885f5f5f5f5f5f 32 plan9 ADDW 0(CX), DX
+660311|223344556677885f5f5f5f5f5f 64 gnu add (%rcx),%dx
+660311|223344556677885f5f5f5f5f5f 64 intel add dx, word ptr [rcx]
+660311|223344556677885f5f5f5f5f5f 64 plan9 ADDW 0(CX), DX
+66051122|3344556677885f5f5f5f5f5f 32 intel add ax, 0x2211
+66051122|3344556677885f5f5f5f5f5f 32 plan9 ADDW $0x2211, AX
+66051122|3344556677885f5f5f5f5f5f 64 gnu add $0x2211,%ax
+66051122|3344556677885f5f5f5f5f5f 64 intel add ax, 0x2211
+66051122|3344556677885f5f5f5f5f5f 64 plan9 ADDW $0x2211, AX
+660911|223344556677885f5f5f5f5f5f 32 intel or word ptr [ecx], dx
+660911|223344556677885f5f5f5f5f5f 32 plan9 ORW DX, 0(CX)
+660911|223344556677885f5f5f5f5f5f 64 gnu or %dx,(%rcx)
+660911|223344556677885f5f5f5f5f5f 64 intel or word ptr [rcx], dx
+660911|223344556677885f5f5f5f5f5f 64 plan9 ORW DX, 0(CX)
+660b11|223344556677885f5f5f5f5f5f 32 intel or dx, word ptr [ecx]
+660b11|223344556677885f5f5f5f5f5f 32 plan9 ORW 0(CX), DX
+660b11|223344556677885f5f5f5f5f5f 64 gnu or (%rcx),%dx
+660b11|223344556677885f5f5f5f5f5f 64 intel or dx, word ptr [rcx]
+660b11|223344556677885f5f5f5f5f5f 64 plan9 ORW 0(CX), DX
+660d1122|3344556677885f5f5f5f5f5f 32 intel or ax, 0x2211
+660d1122|3344556677885f5f5f5f5f5f 32 plan9 ORW $0x2211, AX
+660d1122|3344556677885f5f5f5f5f5f 64 gnu or $0x2211,%ax
+660d1122|3344556677885f5f5f5f5f5f 64 intel or ax, 0x2211
+660d1122|3344556677885f5f5f5f5f5f 64 plan9 ORW $0x2211, AX
+660f0000|11223344556677885f5f5f5f 32 intel sldt word ptr [eax]
+660f0000|11223344556677885f5f5f5f 32 plan9 SLDT 0(AX)
+660f0000|11223344556677885f5f5f5f 64 gnu data16 sldt (%rax)
+660f0000|11223344556677885f5f5f5f 64 intel sldt word ptr [rax]
+660f0000|11223344556677885f5f5f5f 64 plan9 SLDT 0(AX)
+660f0008|11223344556677885f5f5f5f 32 intel str word ptr [eax]
+660f0008|11223344556677885f5f5f5f 32 plan9 STR 0(AX)
+660f0008|11223344556677885f5f5f5f 64 gnu data16 str (%rax)
+660f0008|11223344556677885f5f5f5f 64 intel str word ptr [rax]
+660f0008|11223344556677885f5f5f5f 64 plan9 STR 0(AX)
+660f01a611223344|556677885f5f5f5f 32 intel smsw word ptr [esi+0x44332211]
+660f01a611223344|556677885f5f5f5f 32 plan9 SMSW 0x44332211(SI)
+660f01a611223344|556677885f5f5f5f 64 gnu data16 smsw 0x44332211(%rsi)
+660f01a611223344|556677885f5f5f5f 64 intel smsw word ptr [rsi+0x44332211]
+660f01a611223344|556677885f5f5f5f 64 plan9 SMSW 0x44332211(SI)
+660f0211|223344556677885f5f5f5f5f 32 intel lar dx, word ptr [ecx]
+660f0211|223344556677885f5f5f5f5f 32 plan9 LAR 0(CX), DX
+660f0211|223344556677885f5f5f5f5f 64 gnu lar (%rcx),%dx
+660f0211|223344556677885f5f5f5f5f 64 intel lar dx, word ptr [rcx]
+660f0211|223344556677885f5f5f5f5f 64 plan9 LAR 0(CX), DX
+660f0311|223344556677885f5f5f5f5f 32 intel lsl dx, word ptr [ecx]
+660f0311|223344556677885f5f5f5f5f 32 plan9 LSL 0(CX), DX
+660f0311|223344556677885f5f5f5f5f 64 gnu lsl (%rcx),%dx
+660f0311|223344556677885f5f5f5f5f 64 intel lsl dx, word ptr [rcx]
+660f0311|223344556677885f5f5f5f5f 64 plan9 LSL 0(CX), DX
+660f1011|223344556677885f5f5f5f5f 32 intel movupd xmm2, xmmword ptr [ecx]
+660f1011|223344556677885f5f5f5f5f 32 plan9 MOVUPD 0(CX), X2
+660f1011|223344556677885f5f5f5f5f 64 gnu movupd (%rcx),%xmm2
+660f1011|223344556677885f5f5f5f5f 64 intel movupd xmm2, xmmword ptr [rcx]
+660f1011|223344556677885f5f5f5f5f 64 plan9 MOVUPD 0(CX), X2
+660f1122|3344556677885f5f5f5f5f5f 32 intel movupd xmmword ptr [edx], xmm4
+660f1122|3344556677885f5f5f5f5f5f 32 plan9 MOVUPD X4, 0(DX)
+660f1122|3344556677885f5f5f5f5f5f 64 gnu movupd %xmm4,(%rdx)
+660f1122|3344556677885f5f5f5f5f5f 64 intel movupd xmmword ptr [rdx], xmm4
+660f1122|3344556677885f5f5f5f5f5f 64 plan9 MOVUPD X4, 0(DX)
+660f1211|223344556677885f5f5f5f5f 32 intel movlpd xmm2, qword ptr [ecx]
+660f1211|223344556677885f5f5f5f5f 32 plan9 MOVLPD 0(CX), X2
+660f1211|223344556677885f5f5f5f5f 64 gnu movlpd (%rcx),%xmm2
+660f1211|223344556677885f5f5f5f5f 64 intel movlpd xmm2, qword ptr [rcx]
+660f1211|223344556677885f5f5f5f5f 64 plan9 MOVLPD 0(CX), X2
+660f1311|223344556677885f5f5f5f5f 32 intel movlpd qword ptr [ecx], xmm2
+660f1311|223344556677885f5f5f5f5f 32 plan9 MOVLPD X2, 0(CX)
+660f1311|223344556677885f5f5f5f5f 64 gnu movlpd %xmm2,(%rcx)
+660f1311|223344556677885f5f5f5f5f 64 intel movlpd qword ptr [rcx], xmm2
+660f1311|223344556677885f5f5f5f5f 64 plan9 MOVLPD X2, 0(CX)
+660f1411|223344556677885f5f5f5f5f 32 intel unpcklpd xmm2, xmmword ptr [ecx]
+660f1411|223344556677885f5f5f5f5f 32 plan9 UNPCKLPD 0(CX), X2
+660f1411|223344556677885f5f5f5f5f 64 gnu unpcklpd (%rcx),%xmm2
+660f1411|223344556677885f5f5f5f5f 64 intel unpcklpd xmm2, xmmword ptr [rcx]
+660f1411|223344556677885f5f5f5f5f 64 plan9 UNPCKLPD 0(CX), X2
+660f1511|223344556677885f5f5f5f5f 32 intel unpckhpd xmm2, xmmword ptr [ecx]
+660f1511|223344556677885f5f5f5f5f 32 plan9 UNPCKHPD 0(CX), X2
+660f1511|223344556677885f5f5f5f5f 64 gnu unpckhpd (%rcx),%xmm2
+660f1511|223344556677885f5f5f5f5f 64 intel unpckhpd xmm2, xmmword ptr [rcx]
+660f1511|223344556677885f5f5f5f5f 64 plan9 UNPCKHPD 0(CX), X2
+660f1611|223344556677885f5f5f5f5f 32 intel movhpd xmm2, qword ptr [ecx]
+660f1611|223344556677885f5f5f5f5f 32 plan9 MOVHPD 0(CX), X2
+660f1611|223344556677885f5f5f5f5f 64 gnu movhpd (%rcx),%xmm2
+660f1611|223344556677885f5f5f5f5f 64 intel movhpd xmm2, qword ptr [rcx]
+660f1611|223344556677885f5f5f5f5f 64 plan9 MOVHPD 0(CX), X2
+660f1711|223344556677885f5f5f5f5f 32 intel movhpd qword ptr [ecx], xmm2
+660f1711|223344556677885f5f5f5f5f 32 plan9 MOVHPD X2, 0(CX)
+660f1711|223344556677885f5f5f5f5f 64 gnu movhpd %xmm2,(%rcx)
+660f1711|223344556677885f5f5f5f5f 64 intel movhpd qword ptr [rcx], xmm2
+660f1711|223344556677885f5f5f5f5f 64 plan9 MOVHPD X2, 0(CX)
+660f1f00|11223344556677885f5f5f5f 32 intel nop word ptr [eax], ax
+660f1f00|11223344556677885f5f5f5f 32 plan9 NOPW 0(AX)
+660f1f00|11223344556677885f5f5f5f 64 gnu nopw (%rax)
+660f1f00|11223344556677885f5f5f5f 64 intel nop word ptr [rax], ax
+660f1f00|11223344556677885f5f5f5f 64 plan9 NOPW 0(AX)
+660f2811|223344556677885f5f5f5f5f 32 intel movapd xmm2, xmmword ptr [ecx]
+660f2811|223344556677885f5f5f5f5f 32 plan9 MOVAPD 0(CX), X2
+660f2811|223344556677885f5f5f5f5f 64 gnu movapd (%rcx),%xmm2
+660f2811|223344556677885f5f5f5f5f 64 intel movapd xmm2, xmmword ptr [rcx]
+660f2811|223344556677885f5f5f5f5f 64 plan9 MOVAPD 0(CX), X2
+660f2911|223344556677885f5f5f5f5f 32 intel movapd xmmword ptr [ecx], xmm2
+660f2911|223344556677885f5f5f5f5f 32 plan9 MOVAPD X2, 0(CX)
+660f2911|223344556677885f5f5f5f5f 64 gnu movapd %xmm2,(%rcx)
+660f2911|223344556677885f5f5f5f5f 64 intel movapd xmmword ptr [rcx], xmm2
+660f2911|223344556677885f5f5f5f5f 64 plan9 MOVAPD X2, 0(CX)
+660f2a11|223344556677885f5f5f5f5f 32 intel cvtpi2pd xmm2, qword ptr [ecx]
+660f2a11|223344556677885f5f5f5f5f 32 plan9 CVTPI2PD 0(CX), X2
+660f2a11|223344556677885f5f5f5f5f 64 gnu cvtpi2pd (%rcx),%xmm2
+660f2a11|223344556677885f5f5f5f5f 64 intel cvtpi2pd xmm2, qword ptr [rcx]
+660f2a11|223344556677885f5f5f5f5f 64 plan9 CVTPI2PD 0(CX), X2
+660f2b11|223344556677885f5f5f5f5f 32 intel movntpd xmmword ptr [ecx], xmm2
+660f2b11|223344556677885f5f5f5f5f 32 plan9 MOVNTPD X2, 0(CX)
+660f2b11|223344556677885f5f5f5f5f 64 gnu movntpd %xmm2,(%rcx)
+660f2b11|223344556677885f5f5f5f5f 64 intel movntpd xmmword ptr [rcx], xmm2
+660f2b11|223344556677885f5f5f5f5f 64 plan9 MOVNTPD X2, 0(CX)
+660f2c11|223344556677885f5f5f5f5f 32 intel cvttpd2pi mmx2, xmmword ptr [ecx]
+660f2c11|223344556677885f5f5f5f5f 32 plan9 CVTTPD2PI 0(CX), M2
+660f2c11|223344556677885f5f5f5f5f 64 gnu cvttpd2pi (%rcx),%mm2
+660f2c11|223344556677885f5f5f5f5f 64 intel cvttpd2pi mmx2, xmmword ptr [rcx]
+660f2c11|223344556677885f5f5f5f5f 64 plan9 CVTTPD2PI 0(CX), M2
+660f2d11|223344556677885f5f5f5f5f 32 intel cvtpd2pi mmx2, xmmword ptr [ecx]
+660f2d11|223344556677885f5f5f5f5f 32 plan9 CVTPD2PI 0(CX), M2
+660f2d11|223344556677885f5f5f5f5f 64 gnu cvtpd2pi (%rcx),%mm2
+660f2d11|223344556677885f5f5f5f5f 64 intel cvtpd2pi mmx2, xmmword ptr [rcx]
+660f2d11|223344556677885f5f5f5f5f 64 plan9 CVTPD2PI 0(CX), M2
+660f2e11|223344556677885f5f5f5f5f 32 intel ucomisd xmm2, qword ptr [ecx]
+660f2e11|223344556677885f5f5f5f5f 32 plan9 UCOMISD 0(CX), X2
+660f2e11|223344556677885f5f5f5f5f 64 gnu ucomisd (%rcx),%xmm2
+660f2e11|223344556677885f5f5f5f5f 64 intel ucomisd xmm2, qword ptr [rcx]
+660f2e11|223344556677885f5f5f5f5f 64 plan9 UCOMISD 0(CX), X2
+660f2f11|223344556677885f5f5f5f5f 32 intel comisd xmm2, qword ptr [ecx]
+660f2f11|223344556677885f5f5f5f5f 32 plan9 COMISD 0(CX), X2
+660f2f11|223344556677885f5f5f5f5f 64 gnu comisd (%rcx),%xmm2
+660f2f11|223344556677885f5f5f5f5f 64 intel comisd xmm2, qword ptr [rcx]
+660f2f11|223344556677885f5f5f5f5f 64 plan9 COMISD 0(CX), X2
+660f380011|223344556677885f5f5f5f 32 intel pshufb xmm2, xmmword ptr [ecx]
+660f380011|223344556677885f5f5f5f 32 plan9 PSHUFB 0(CX), X2
+660f380011|223344556677885f5f5f5f 64 gnu pshufb (%rcx),%xmm2
+660f380011|223344556677885f5f5f5f 64 intel pshufb xmm2, xmmword ptr [rcx]
+660f380011|223344556677885f5f5f5f 64 plan9 PSHUFB 0(CX), X2
+660f380111|223344556677885f5f5f5f 32 intel phaddw xmm2, xmmword ptr [ecx]
+660f380111|223344556677885f5f5f5f 32 plan9 PHADDW 0(CX), X2
+660f380111|223344556677885f5f5f5f 64 gnu phaddw (%rcx),%xmm2
+660f380111|223344556677885f5f5f5f 64 intel phaddw xmm2, xmmword ptr [rcx]
+660f380111|223344556677885f5f5f5f 64 plan9 PHADDW 0(CX), X2
+660f380211|223344556677885f5f5f5f 32 intel phaddd xmm2, xmmword ptr [ecx]
+660f380211|223344556677885f5f5f5f 32 plan9 PHADDD 0(CX), X2
+660f380211|223344556677885f5f5f5f 64 gnu phaddd (%rcx),%xmm2
+660f380211|223344556677885f5f5f5f 64 intel phaddd xmm2, xmmword ptr [rcx]
+660f380211|223344556677885f5f5f5f 64 plan9 PHADDD 0(CX), X2
+660f380311|223344556677885f5f5f5f 32 intel phaddsw xmm2, xmmword ptr [ecx]
+660f380311|223344556677885f5f5f5f 32 plan9 PHADDSW 0(CX), X2
+660f380311|223344556677885f5f5f5f 64 gnu phaddsw (%rcx),%xmm2
+660f380311|223344556677885f5f5f5f 64 intel phaddsw xmm2, xmmword ptr [rcx]
+660f380311|223344556677885f5f5f5f 64 plan9 PHADDSW 0(CX), X2
+660f380411|223344556677885f5f5f5f 32 intel pmaddubsw xmm2, xmmword ptr [ecx]
+660f380411|223344556677885f5f5f5f 32 plan9 PMADDUBSW 0(CX), X2
+660f380411|223344556677885f5f5f5f 64 gnu pmaddubsw (%rcx),%xmm2
+660f380411|223344556677885f5f5f5f 64 intel pmaddubsw xmm2, xmmword ptr [rcx]
+660f380411|223344556677885f5f5f5f 64 plan9 PMADDUBSW 0(CX), X2
+660f380511|223344556677885f5f5f5f 32 intel phsubw xmm2, xmmword ptr [ecx]
+660f380511|223344556677885f5f5f5f 32 plan9 PHSUBW 0(CX), X2
+660f380511|223344556677885f5f5f5f 64 gnu phsubw (%rcx),%xmm2
+660f380511|223344556677885f5f5f5f 64 intel phsubw xmm2, xmmword ptr [rcx]
+660f380511|223344556677885f5f5f5f 64 plan9 PHSUBW 0(CX), X2
+660f380611|223344556677885f5f5f5f 32 intel phsubd xmm2, xmmword ptr [ecx]
+660f380611|223344556677885f5f5f5f 32 plan9 PHSUBD 0(CX), X2
+660f380611|223344556677885f5f5f5f 64 gnu phsubd (%rcx),%xmm2
+660f380611|223344556677885f5f5f5f 64 intel phsubd xmm2, xmmword ptr [rcx]
+660f380611|223344556677885f5f5f5f 64 plan9 PHSUBD 0(CX), X2
+660f380711|223344556677885f5f5f5f 32 intel phsubsw xmm2, xmmword ptr [ecx]
+660f380711|223344556677885f5f5f5f 32 plan9 PHSUBSW 0(CX), X2
+660f380711|223344556677885f5f5f5f 64 gnu phsubsw (%rcx),%xmm2
+660f380711|223344556677885f5f5f5f 64 intel phsubsw xmm2, xmmword ptr [rcx]
+660f380711|223344556677885f5f5f5f 64 plan9 PHSUBSW 0(CX), X2
+660f380811|223344556677885f5f5f5f 32 intel psignb xmm2, xmmword ptr [ecx]
+660f380811|223344556677885f5f5f5f 32 plan9 PSIGNB 0(CX), X2
+660f380811|223344556677885f5f5f5f 64 gnu psignb (%rcx),%xmm2
+660f380811|223344556677885f5f5f5f 64 intel psignb xmm2, xmmword ptr [rcx]
+660f380811|223344556677885f5f5f5f 64 plan9 PSIGNB 0(CX), X2
+660f380911|223344556677885f5f5f5f 32 intel psignw xmm2, xmmword ptr [ecx]
+660f380911|223344556677885f5f5f5f 32 plan9 PSIGNW 0(CX), X2
+660f380911|223344556677885f5f5f5f 64 gnu psignw (%rcx),%xmm2
+660f380911|223344556677885f5f5f5f 64 intel psignw xmm2, xmmword ptr [rcx]
+660f380911|223344556677885f5f5f5f 64 plan9 PSIGNW 0(CX), X2
+660f380a11|223344556677885f5f5f5f 32 intel psignd xmm2, xmmword ptr [ecx]
+660f380a11|223344556677885f5f5f5f 32 plan9 PSIGND 0(CX), X2
+660f380a11|223344556677885f5f5f5f 64 gnu psignd (%rcx),%xmm2
+660f380a11|223344556677885f5f5f5f 64 intel psignd xmm2, xmmword ptr [rcx]
+660f380a11|223344556677885f5f5f5f 64 plan9 PSIGND 0(CX), X2
+660f380b11|223344556677885f5f5f5f 32 intel pmulhrsw xmm2, xmmword ptr [ecx]
+660f380b11|223344556677885f5f5f5f 32 plan9 PMULHRSW 0(CX), X2
+660f380b11|223344556677885f5f5f5f 64 gnu pmulhrsw (%rcx),%xmm2
+660f380b11|223344556677885f5f5f5f 64 intel pmulhrsw xmm2, xmmword ptr [rcx]
+660f380b11|223344556677885f5f5f5f 64 plan9 PMULHRSW 0(CX), X2
+660f381011|223344556677885f5f5f5f 32 intel pblendvb xmm2, xmmword ptr [ecx]
+660f381011|223344556677885f5f5f5f 32 plan9 PBLENDVB X0, 0(CX), X2
+660f381011|223344556677885f5f5f5f 64 gnu pblendvb %xmm0,(%rcx),%xmm2
+660f381011|223344556677885f5f5f5f 64 intel pblendvb xmm2, xmmword ptr [rcx]
+660f381011|223344556677885f5f5f5f 64 plan9 PBLENDVB X0, 0(CX), X2
+660f381411|223344556677885f5f5f5f 32 intel blendvps xmm2, xmmword ptr [ecx]
+660f381411|223344556677885f5f5f5f 32 plan9 BLENDVPS X0, 0(CX), X2
+660f381411|223344556677885f5f5f5f 64 gnu blendvps %xmm0,(%rcx),%xmm2
+660f381411|223344556677885f5f5f5f 64 intel blendvps xmm2, xmmword ptr [rcx]
+660f381411|223344556677885f5f5f5f 64 plan9 BLENDVPS X0, 0(CX), X2
+660f381511|223344556677885f5f5f5f 32 intel blendvpd xmm2, xmmword ptr [ecx]
+660f381511|223344556677885f5f5f5f 32 plan9 BLENDVPD X0, 0(CX), X2
+660f381511|223344556677885f5f5f5f 64 gnu blendvpd %xmm0,(%rcx),%xmm2
+660f381511|223344556677885f5f5f5f 64 intel blendvpd xmm2, xmmword ptr [rcx]
+660f381511|223344556677885f5f5f5f 64 plan9 BLENDVPD X0, 0(CX), X2
+660f381711|223344556677885f5f5f5f 32 intel ptest xmm2, xmmword ptr [ecx]
+660f381711|223344556677885f5f5f5f 32 plan9 PTEST 0(CX), X2
+660f381711|223344556677885f5f5f5f 64 gnu ptest (%rcx),%xmm2
+660f381711|223344556677885f5f5f5f 64 intel ptest xmm2, xmmword ptr [rcx]
+660f381711|223344556677885f5f5f5f 64 plan9 PTEST 0(CX), X2
+660f381c11|223344556677885f5f5f5f 32 intel pabsb xmm2, xmmword ptr [ecx]
+660f381c11|223344556677885f5f5f5f 32 plan9 PABSB 0(CX), X2
+660f381c11|223344556677885f5f5f5f 64 gnu pabsb (%rcx),%xmm2
+660f381c11|223344556677885f5f5f5f 64 intel pabsb xmm2, xmmword ptr [rcx]
+660f381c11|223344556677885f5f5f5f 64 plan9 PABSB 0(CX), X2
+660f381d11|223344556677885f5f5f5f 32 intel pabsw xmm2, xmmword ptr [ecx]
+660f381d11|223344556677885f5f5f5f 32 plan9 PABSW 0(CX), X2
+660f381d11|223344556677885f5f5f5f 64 gnu pabsw (%rcx),%xmm2
+660f381d11|223344556677885f5f5f5f 64 intel pabsw xmm2, xmmword ptr [rcx]
+660f381d11|223344556677885f5f5f5f 64 plan9 PABSW 0(CX), X2
+660f381e11|223344556677885f5f5f5f 32 intel pabsd xmm2, xmmword ptr [ecx]
+660f381e11|223344556677885f5f5f5f 32 plan9 PABSD 0(CX), X2
+660f381e11|223344556677885f5f5f5f 64 gnu pabsd (%rcx),%xmm2
+660f381e11|223344556677885f5f5f5f 64 intel pabsd xmm2, xmmword ptr [rcx]
+660f381e11|223344556677885f5f5f5f 64 plan9 PABSD 0(CX), X2
+660f382011|223344556677885f5f5f5f 32 intel pmovsxbw xmm2, qword ptr [ecx]
+660f382011|223344556677885f5f5f5f 32 plan9 PMOVSXBW 0(CX), X2
+660f382011|223344556677885f5f5f5f 64 gnu pmovsxbw (%rcx),%xmm2
+660f382011|223344556677885f5f5f5f 64 intel pmovsxbw xmm2, qword ptr [rcx]
+660f382011|223344556677885f5f5f5f 64 plan9 PMOVSXBW 0(CX), X2
+660f382111|223344556677885f5f5f5f 32 intel pmovsxbd xmm2, dword ptr [ecx]
+660f382111|223344556677885f5f5f5f 32 plan9 PMOVSXBD 0(CX), X2
+660f382111|223344556677885f5f5f5f 64 gnu pmovsxbd (%rcx),%xmm2
+660f382111|223344556677885f5f5f5f 64 intel pmovsxbd xmm2, dword ptr [rcx]
+660f382111|223344556677885f5f5f5f 64 plan9 PMOVSXBD 0(CX), X2
+660f382211|223344556677885f5f5f5f 32 intel pmovsxbq xmm2, word ptr [ecx]
+660f382211|223344556677885f5f5f5f 32 plan9 PMOVSXBQ 0(CX), X2
+660f382211|223344556677885f5f5f5f 64 gnu pmovsxbq (%rcx),%xmm2
+660f382211|223344556677885f5f5f5f 64 intel pmovsxbq xmm2, word ptr [rcx]
+660f382211|223344556677885f5f5f5f 64 plan9 PMOVSXBQ 0(CX), X2
+660f382311|223344556677885f5f5f5f 32 intel pmovsxwd xmm2, qword ptr [ecx]
+660f382311|223344556677885f5f5f5f 32 plan9 PMOVSXWD 0(CX), X2
+660f382311|223344556677885f5f5f5f 64 gnu pmovsxwd (%rcx),%xmm2
+660f382311|223344556677885f5f5f5f 64 intel pmovsxwd xmm2, qword ptr [rcx]
+660f382311|223344556677885f5f5f5f 64 plan9 PMOVSXWD 0(CX), X2
+660f382411|223344556677885f5f5f5f 32 intel pmovsxwq xmm2, dword ptr [ecx]
+660f382411|223344556677885f5f5f5f 32 plan9 PMOVSXWQ 0(CX), X2
+660f382411|223344556677885f5f5f5f 64 gnu pmovsxwq (%rcx),%xmm2
+660f382411|223344556677885f5f5f5f 64 intel pmovsxwq xmm2, dword ptr [rcx]
+660f382411|223344556677885f5f5f5f 64 plan9 PMOVSXWQ 0(CX), X2
+660f382511|223344556677885f5f5f5f 32 intel pmovsxdq xmm2, qword ptr [ecx]
+660f382511|223344556677885f5f5f5f 32 plan9 PMOVSXDQ 0(CX), X2
+660f382511|223344556677885f5f5f5f 64 gnu pmovsxdq (%rcx),%xmm2
+660f382511|223344556677885f5f5f5f 64 intel pmovsxdq xmm2, qword ptr [rcx]
+660f382511|223344556677885f5f5f5f 64 plan9 PMOVSXDQ 0(CX), X2
+660f382811|223344556677885f5f5f5f 32 intel pmuldq xmm2, xmmword ptr [ecx]
+660f382811|223344556677885f5f5f5f 32 plan9 PMULDQ 0(CX), X2
+660f382811|223344556677885f5f5f5f 64 gnu pmuldq (%rcx),%xmm2
+660f382811|223344556677885f5f5f5f 64 intel pmuldq xmm2, xmmword ptr [rcx]
+660f382811|223344556677885f5f5f5f 64 plan9 PMULDQ 0(CX), X2
+660f382911|223344556677885f5f5f5f 32 intel pcmpeqq xmm2, xmmword ptr [ecx]
+660f382911|223344556677885f5f5f5f 32 plan9 PCMPEQQ 0(CX), X2
+660f382911|223344556677885f5f5f5f 64 gnu pcmpeqq (%rcx),%xmm2
+660f382911|223344556677885f5f5f5f 64 intel pcmpeqq xmm2, xmmword ptr [rcx]
+660f382911|223344556677885f5f5f5f 64 plan9 PCMPEQQ 0(CX), X2
+660f382a11|223344556677885f5f5f5f 32 intel movntdqa xmm2, xmmword ptr [ecx]
+660f382a11|223344556677885f5f5f5f 32 plan9 MOVNTDQA 0(CX), X2
+660f382a11|223344556677885f5f5f5f 64 gnu movntdqa (%rcx),%xmm2
+660f382a11|223344556677885f5f5f5f 64 intel movntdqa xmm2, xmmword ptr [rcx]
+660f382a11|223344556677885f5f5f5f 64 plan9 MOVNTDQA 0(CX), X2
+660f382b11|223344556677885f5f5f5f 32 intel packusdw xmm2, xmmword ptr [ecx]
+660f382b11|223344556677885f5f5f5f 32 plan9 PACKUSDW 0(CX), X2
+660f382b11|223344556677885f5f5f5f 64 gnu packusdw (%rcx),%xmm2
+660f382b11|223344556677885f5f5f5f 64 intel packusdw xmm2, xmmword ptr [rcx]
+660f382b11|223344556677885f5f5f5f 64 plan9 PACKUSDW 0(CX), X2
+660f383011|223344556677885f5f5f5f 32 intel pmovzxbw xmm2, qword ptr [ecx]
+660f383011|223344556677885f5f5f5f 32 plan9 PMOVZXBW 0(CX), X2
+660f383011|223344556677885f5f5f5f 64 gnu pmovzxbw (%rcx),%xmm2
+660f383011|223344556677885f5f5f5f 64 intel pmovzxbw xmm2, qword ptr [rcx]
+660f383011|223344556677885f5f5f5f 64 plan9 PMOVZXBW 0(CX), X2
+660f383111|223344556677885f5f5f5f 32 intel pmovzxbd xmm2, dword ptr [ecx]
+660f383111|223344556677885f5f5f5f 32 plan9 PMOVZXBD 0(CX), X2
+660f383111|223344556677885f5f5f5f 64 gnu pmovzxbd (%rcx),%xmm2
+660f383111|223344556677885f5f5f5f 64 intel pmovzxbd xmm2, dword ptr [rcx]
+660f383111|223344556677885f5f5f5f 64 plan9 PMOVZXBD 0(CX), X2
+660f383211|223344556677885f5f5f5f 32 intel pmovzxbq xmm2, word ptr [ecx]
+660f383211|223344556677885f5f5f5f 32 plan9 PMOVZXBQ 0(CX), X2
+660f383211|223344556677885f5f5f5f 64 gnu pmovzxbq (%rcx),%xmm2
+660f383211|223344556677885f5f5f5f 64 intel pmovzxbq xmm2, word ptr [rcx]
+660f383211|223344556677885f5f5f5f 64 plan9 PMOVZXBQ 0(CX), X2
+660f383311|223344556677885f5f5f5f 32 intel pmovzxwd xmm2, qword ptr [ecx]
+660f383311|223344556677885f5f5f5f 32 plan9 PMOVZXWD 0(CX), X2
+660f383311|223344556677885f5f5f5f 64 gnu pmovzxwd (%rcx),%xmm2
+660f383311|223344556677885f5f5f5f 64 intel pmovzxwd xmm2, qword ptr [rcx]
+660f383311|223344556677885f5f5f5f 64 plan9 PMOVZXWD 0(CX), X2
+660f383411|223344556677885f5f5f5f 32 intel pmovzxwq xmm2, dword ptr [ecx]
+660f383411|223344556677885f5f5f5f 32 plan9 PMOVZXWQ 0(CX), X2
+660f383411|223344556677885f5f5f5f 64 gnu pmovzxwq (%rcx),%xmm2
+660f383411|223344556677885f5f5f5f 64 intel pmovzxwq xmm2, dword ptr [rcx]
+660f383411|223344556677885f5f5f5f 64 plan9 PMOVZXWQ 0(CX), X2
+660f383511|223344556677885f5f5f5f 32 intel pmovzxdq xmm2, qword ptr [ecx]
+660f383511|223344556677885f5f5f5f 32 plan9 PMOVZXDQ 0(CX), X2
+660f383511|223344556677885f5f5f5f 64 gnu pmovzxdq (%rcx),%xmm2
+660f383511|223344556677885f5f5f5f 64 intel pmovzxdq xmm2, qword ptr [rcx]
+660f383511|223344556677885f5f5f5f 64 plan9 PMOVZXDQ 0(CX), X2
+660f383711|223344556677885f5f5f5f 32 intel pcmpgtq xmm2, xmmword ptr [ecx]
+660f383711|223344556677885f5f5f5f 32 plan9 PCMPGTQ 0(CX), X2
+660f383711|223344556677885f5f5f5f 64 gnu pcmpgtq (%rcx),%xmm2
+660f383711|223344556677885f5f5f5f 64 intel pcmpgtq xmm2, xmmword ptr [rcx]
+660f383711|223344556677885f5f5f5f 64 plan9 PCMPGTQ 0(CX), X2
+660f383811|223344556677885f5f5f5f 32 intel pminsb xmm2, xmmword ptr [ecx]
+660f383811|223344556677885f5f5f5f 32 plan9 PMINSB 0(CX), X2
+660f383811|223344556677885f5f5f5f 64 gnu pminsb (%rcx),%xmm2
+660f383811|223344556677885f5f5f5f 64 intel pminsb xmm2, xmmword ptr [rcx]
+660f383811|223344556677885f5f5f5f 64 plan9 PMINSB 0(CX), X2
+660f383911|223344556677885f5f5f5f 32 intel pminsd xmm2, xmmword ptr [ecx]
+660f383911|223344556677885f5f5f5f 32 plan9 PMINSD 0(CX), X2
+660f383911|223344556677885f5f5f5f 64 gnu pminsd (%rcx),%xmm2
+660f383911|223344556677885f5f5f5f 64 intel pminsd xmm2, xmmword ptr [rcx]
+660f383911|223344556677885f5f5f5f 64 plan9 PMINSD 0(CX), X2
+660f383a11|223344556677885f5f5f5f 32 intel pminuw xmm2, xmmword ptr [ecx]
+660f383a11|223344556677885f5f5f5f 32 plan9 PMINUW 0(CX), X2
+660f383a11|223344556677885f5f5f5f 64 gnu pminuw (%rcx),%xmm2
+660f383a11|223344556677885f5f5f5f 64 intel pminuw xmm2, xmmword ptr [rcx]
+660f383a11|223344556677885f5f5f5f 64 plan9 PMINUW 0(CX), X2
+660f383b11|223344556677885f5f5f5f 32 intel pminud xmm2, xmmword ptr [ecx]
+660f383b11|223344556677885f5f5f5f 32 plan9 PMINUD 0(CX), X2
+660f383b11|223344556677885f5f5f5f 64 gnu pminud (%rcx),%xmm2
+660f383b11|223344556677885f5f5f5f 64 intel pminud xmm2, xmmword ptr [rcx]
+660f383b11|223344556677885f5f5f5f 64 plan9 PMINUD 0(CX), X2
+660f383c11|223344556677885f5f5f5f 32 intel pmaxsb xmm2, xmmword ptr [ecx]
+660f383c11|223344556677885f5f5f5f 32 plan9 PMAXSB 0(CX), X2
+660f383c11|223344556677885f5f5f5f 64 gnu pmaxsb (%rcx),%xmm2
+660f383c11|223344556677885f5f5f5f 64 intel pmaxsb xmm2, xmmword ptr [rcx]
+660f383c11|223344556677885f5f5f5f 64 plan9 PMAXSB 0(CX), X2
+660f383d11|223344556677885f5f5f5f 32 intel pmaxsd xmm2, xmmword ptr [ecx]
+660f383d11|223344556677885f5f5f5f 32 plan9 PMAXSD 0(CX), X2
+660f383d11|223344556677885f5f5f5f 64 gnu pmaxsd (%rcx),%xmm2
+660f383d11|223344556677885f5f5f5f 64 intel pmaxsd xmm2, xmmword ptr [rcx]
+660f383d11|223344556677885f5f5f5f 64 plan9 PMAXSD 0(CX), X2
+660f383e11|223344556677885f5f5f5f 32 intel pmaxuw xmm2, xmmword ptr [ecx]
+660f383e11|223344556677885f5f5f5f 32 plan9 PMAXUW 0(CX), X2
+660f383e11|223344556677885f5f5f5f 64 gnu pmaxuw (%rcx),%xmm2
+660f383e11|223344556677885f5f5f5f 64 intel pmaxuw xmm2, xmmword ptr [rcx]
+660f383e11|223344556677885f5f5f5f 64 plan9 PMAXUW 0(CX), X2
+660f383f11|223344556677885f5f5f5f 32 intel pmaxud xmm2, xmmword ptr [ecx]
+660f383f11|223344556677885f5f5f5f 32 plan9 PMAXUD 0(CX), X2
+660f383f11|223344556677885f5f5f5f 64 gnu pmaxud (%rcx),%xmm2
+660f383f11|223344556677885f5f5f5f 64 intel pmaxud xmm2, xmmword ptr [rcx]
+660f383f11|223344556677885f5f5f5f 64 plan9 PMAXUD 0(CX), X2
+660f384011|223344556677885f5f5f5f 32 intel pmulld xmm2, xmmword ptr [ecx]
+660f384011|223344556677885f5f5f5f 32 plan9 PMULLD 0(CX), X2
+660f384011|223344556677885f5f5f5f 64 gnu pmulld (%rcx),%xmm2
+660f384011|223344556677885f5f5f5f 64 intel pmulld xmm2, xmmword ptr [rcx]
+660f384011|223344556677885f5f5f5f 64 plan9 PMULLD 0(CX), X2
+660f384111|223344556677885f5f5f5f 32 intel phminposuw xmm2, xmmword ptr [ecx]
+660f384111|223344556677885f5f5f5f 32 plan9 PHMINPOSUW 0(CX), X2
+660f384111|223344556677885f5f5f5f 64 gnu phminposuw (%rcx),%xmm2
+660f384111|223344556677885f5f5f5f 64 intel phminposuw xmm2, xmmword ptr [rcx]
+660f384111|223344556677885f5f5f5f 64 plan9 PHMINPOSUW 0(CX), X2
+660f388211|223344556677885f5f5f5f 32 intel invpcid edx, xmmword ptr [ecx]
+660f388211|223344556677885f5f5f5f 32 plan9 INVPCID 0(CX), DX
+660f388211|223344556677885f5f5f5f 64 gnu invpcid (%rcx),%rdx
+660f388211|223344556677885f5f5f5f 64 intel invpcid rdx, xmmword ptr [rcx]
+660f388211|223344556677885f5f5f5f 64 plan9 INVPCID 0(CX), DX
+660f38db11|223344556677885f5f5f5f 32 intel aesimc xmm2, xmmword ptr [ecx]
+660f38db11|223344556677885f5f5f5f 32 plan9 AESIMC 0(CX), X2
+660f38db11|223344556677885f5f5f5f 64 gnu aesimc (%rcx),%xmm2
+660f38db11|223344556677885f5f5f5f 64 intel aesimc xmm2, xmmword ptr [rcx]
+660f38db11|223344556677885f5f5f5f 64 plan9 AESIMC 0(CX), X2
+660f38dc11|223344556677885f5f5f5f 32 intel aesenc xmm2, xmmword ptr [ecx]
+660f38dc11|223344556677885f5f5f5f 32 plan9 AESENC 0(CX), X2
+660f38dc11|223344556677885f5f5f5f 64 gnu aesenc (%rcx),%xmm2
+660f38dc11|223344556677885f5f5f5f 64 intel aesenc xmm2, xmmword ptr [rcx]
+660f38dc11|223344556677885f5f5f5f 64 plan9 AESENC 0(CX), X2
+660f38dd11|223344556677885f5f5f5f 32 intel aesenclast xmm2, xmmword ptr [ecx]
+660f38dd11|223344556677885f5f5f5f 32 plan9 AESENCLAST 0(CX), X2
+660f38dd11|223344556677885f5f5f5f 64 gnu aesenclast (%rcx),%xmm2
+660f38dd11|223344556677885f5f5f5f 64 intel aesenclast xmm2, xmmword ptr [rcx]
+660f38dd11|223344556677885f5f5f5f 64 plan9 AESENCLAST 0(CX), X2
+660f38de11|223344556677885f5f5f5f 32 intel aesdec xmm2, xmmword ptr [ecx]
+660f38de11|223344556677885f5f5f5f 32 plan9 AESDEC 0(CX), X2
+660f38de11|223344556677885f5f5f5f 64 gnu aesdec (%rcx),%xmm2
+660f38de11|223344556677885f5f5f5f 64 intel aesdec xmm2, xmmword ptr [rcx]
+660f38de11|223344556677885f5f5f5f 64 plan9 AESDEC 0(CX), X2
+660f38df11|223344556677885f5f5f5f 32 intel aesdeclast xmm2, xmmword ptr [ecx]
+660f38df11|223344556677885f5f5f5f 32 plan9 AESDECLAST 0(CX), X2
+660f38df11|223344556677885f5f5f5f 64 gnu aesdeclast (%rcx),%xmm2
+660f38df11|223344556677885f5f5f5f 64 intel aesdeclast xmm2, xmmword ptr [rcx]
+660f38df11|223344556677885f5f5f5f 64 plan9 AESDECLAST 0(CX), X2
+660f3a081122|3344556677885f5f5f5f 32 intel roundps xmm2, xmmword ptr [ecx], 0x22
+660f3a081122|3344556677885f5f5f5f 32 plan9 ROUNDPS $0x22, 0(CX), X2
+660f3a081122|3344556677885f5f5f5f 64 gnu roundps $0x22,(%rcx),%xmm2
+660f3a081122|3344556677885f5f5f5f 64 intel roundps xmm2, xmmword ptr [rcx], 0x22
+660f3a081122|3344556677885f5f5f5f 64 plan9 ROUNDPS $0x22, 0(CX), X2
+660f3a091122|3344556677885f5f5f5f 32 intel roundpd xmm2, xmmword ptr [ecx], 0x22
+660f3a091122|3344556677885f5f5f5f 32 plan9 ROUNDPD $0x22, 0(CX), X2
+660f3a091122|3344556677885f5f5f5f 64 gnu roundpd $0x22,(%rcx),%xmm2
+660f3a091122|3344556677885f5f5f5f 64 intel roundpd xmm2, xmmword ptr [rcx], 0x22
+660f3a091122|3344556677885f5f5f5f 64 plan9 ROUNDPD $0x22, 0(CX), X2
+660f3a0a1122|3344556677885f5f5f5f 32 intel roundss xmm2, dword ptr [ecx], 0x22
+660f3a0a1122|3344556677885f5f5f5f 32 plan9 ROUNDSS $0x22, 0(CX), X2
+660f3a0a1122|3344556677885f5f5f5f 64 gnu roundss $0x22,(%rcx),%xmm2
+660f3a0a1122|3344556677885f5f5f5f 64 intel roundss xmm2, dword ptr [rcx], 0x22
+660f3a0a1122|3344556677885f5f5f5f 64 plan9 ROUNDSS $0x22, 0(CX), X2
+660f3a0b1122|3344556677885f5f5f5f 32 intel roundsd xmm2, qword ptr [ecx], 0x22
+660f3a0b1122|3344556677885f5f5f5f 32 plan9 ROUNDSD $0x22, 0(CX), X2
+660f3a0b1122|3344556677885f5f5f5f 64 gnu roundsd $0x22,(%rcx),%xmm2
+660f3a0b1122|3344556677885f5f5f5f 64 intel roundsd xmm2, qword ptr [rcx], 0x22
+660f3a0b1122|3344556677885f5f5f5f 64 plan9 ROUNDSD $0x22, 0(CX), X2
+660f3a0c1122|3344556677885f5f5f5f 32 intel blendps xmm2, xmmword ptr [ecx], 0x22
+660f3a0c1122|3344556677885f5f5f5f 32 plan9 BLENDPS $0x22, 0(CX), X2
+660f3a0c1122|3344556677885f5f5f5f 64 gnu blendps $0x22,(%rcx),%xmm2
+660f3a0c1122|3344556677885f5f5f5f 64 intel blendps xmm2, xmmword ptr [rcx], 0x22
+660f3a0c1122|3344556677885f5f5f5f 64 plan9 BLENDPS $0x22, 0(CX), X2
+660f3a0d1122|3344556677885f5f5f5f 32 intel blendpd xmm2, xmmword ptr [ecx], 0x22
+660f3a0d1122|3344556677885f5f5f5f 32 plan9 BLENDPD $0x22, 0(CX), X2
+660f3a0d1122|3344556677885f5f5f5f 64 gnu blendpd $0x22,(%rcx),%xmm2
+660f3a0d1122|3344556677885f5f5f5f 64 intel blendpd xmm2, xmmword ptr [rcx], 0x22
+660f3a0d1122|3344556677885f5f5f5f 64 plan9 BLENDPD $0x22, 0(CX), X2
+660f3a0e1122|3344556677885f5f5f5f 32 intel pblendw xmm2, xmmword ptr [ecx], 0x22
+660f3a0e1122|3344556677885f5f5f5f 32 plan9 PBLENDW $0x22, 0(CX), X2
+660f3a0e1122|3344556677885f5f5f5f 64 gnu pblendw $0x22,(%rcx),%xmm2
+660f3a0e1122|3344556677885f5f5f5f 64 intel pblendw xmm2, xmmword ptr [rcx], 0x22
+660f3a0e1122|3344556677885f5f5f5f 64 plan9 PBLENDW $0x22, 0(CX), X2
+660f3a0f1122|3344556677885f5f5f5f 32 intel palignr xmm2, xmmword ptr [ecx], 0x22
+660f3a0f1122|3344556677885f5f5f5f 32 plan9 PALIGNR $0x22, 0(CX), X2
+660f3a0f1122|3344556677885f5f5f5f 64 gnu palignr $0x22,(%rcx),%xmm2
+660f3a0f1122|3344556677885f5f5f5f 64 intel palignr xmm2, xmmword ptr [rcx], 0x22
+660f3a0f1122|3344556677885f5f5f5f 64 plan9 PALIGNR $0x22, 0(CX), X2
+660f3a141122|3344556677885f5f5f5f 32 intel pextrb byte ptr [ecx], xmm2, 0x22
+660f3a141122|3344556677885f5f5f5f 32 plan9 PEXTRB $0x22, X2, 0(CX)
+660f3a141122|3344556677885f5f5f5f 64 gnu pextrb $0x22,%xmm2,(%rcx)
+660f3a141122|3344556677885f5f5f5f 64 intel pextrb byte ptr [rcx], xmm2, 0x22
+660f3a141122|3344556677885f5f5f5f 64 plan9 PEXTRB $0x22, X2, 0(CX)
+660f3a151122|3344556677885f5f5f5f 32 intel pextrw word ptr [ecx], xmm2, 0x22
+660f3a151122|3344556677885f5f5f5f 32 plan9 PEXTRW $0x22, X2, 0(CX)
+660f3a151122|3344556677885f5f5f5f 64 gnu pextrw $0x22,%xmm2,(%rcx)
+660f3a151122|3344556677885f5f5f5f 64 intel pextrw word ptr [rcx], xmm2, 0x22
+660f3a151122|3344556677885f5f5f5f 64 plan9 PEXTRW $0x22, X2, 0(CX)
+660f3a161122|3344556677885f5f5f5f 32 intel pextrd dword ptr [ecx], xmm2, 0x22
+660f3a161122|3344556677885f5f5f5f 32 plan9 PEXTRD $0x22, X2, 0(CX)
+660f3a161122|3344556677885f5f5f5f 64 gnu pextrd $0x22,%xmm2,(%rcx)
+660f3a161122|3344556677885f5f5f5f 64 intel pextrd dword ptr [rcx], xmm2, 0x22
+660f3a161122|3344556677885f5f5f5f 64 plan9 PEXTRD $0x22, X2, 0(CX)
+660f3a171122|3344556677885f5f5f5f 32 intel extractps dword ptr [ecx], xmm2, 0x22
+660f3a171122|3344556677885f5f5f5f 32 plan9 EXTRACTPS $0x22, X2, 0(CX)
+660f3a171122|3344556677885f5f5f5f 64 gnu extractps $0x22,%xmm2,(%rcx)
+660f3a171122|3344556677885f5f5f5f 64 intel extractps dword ptr [rcx], xmm2, 0x22
+660f3a171122|3344556677885f5f5f5f 64 plan9 EXTRACTPS $0x22, X2, 0(CX)
+660f3a201122|3344556677885f5f5f5f 32 intel pinsrb xmm2, byte ptr [ecx], 0x22
+660f3a201122|3344556677885f5f5f5f 32 plan9 PINSRB $0x22, 0(CX), X2
+660f3a201122|3344556677885f5f5f5f 64 gnu pinsrb $0x22,(%rcx),%xmm2
+660f3a201122|3344556677885f5f5f5f 64 intel pinsrb xmm2, byte ptr [rcx], 0x22
+660f3a201122|3344556677885f5f5f5f 64 plan9 PINSRB $0x22, 0(CX), X2
+660f3a211122|3344556677885f5f5f5f 32 intel insertps xmm2, dword ptr [ecx], 0x22
+660f3a211122|3344556677885f5f5f5f 32 plan9 INSERTPS $0x22, 0(CX), X2
+660f3a211122|3344556677885f5f5f5f 64 gnu insertps $0x22,(%rcx),%xmm2
+660f3a211122|3344556677885f5f5f5f 64 intel insertps xmm2, dword ptr [rcx], 0x22
+660f3a211122|3344556677885f5f5f5f 64 plan9 INSERTPS $0x22, 0(CX), X2
+660f3a221122|3344556677885f5f5f5f 32 intel pinsrd xmm2, dword ptr [ecx], 0x22
+660f3a221122|3344556677885f5f5f5f 32 plan9 PINSRD $0x22, 0(CX), X2
+660f3a221122|3344556677885f5f5f5f 64 gnu pinsrd $0x22,(%rcx),%xmm2
+660f3a221122|3344556677885f5f5f5f 64 intel pinsrd xmm2, dword ptr [rcx], 0x22
+660f3a221122|3344556677885f5f5f5f 64 plan9 PINSRD $0x22, 0(CX), X2
+660f3a401122|3344556677885f5f5f5f 32 intel dpps xmm2, xmmword ptr [ecx], 0x22
+660f3a401122|3344556677885f5f5f5f 32 plan9 DPPS $0x22, 0(CX), X2
+660f3a401122|3344556677885f5f5f5f 64 gnu dpps $0x22,(%rcx),%xmm2
+660f3a401122|3344556677885f5f5f5f 64 intel dpps xmm2, xmmword ptr [rcx], 0x22
+660f3a401122|3344556677885f5f5f5f 64 plan9 DPPS $0x22, 0(CX), X2
+660f3a411122|3344556677885f5f5f5f 32 intel dppd xmm2, xmmword ptr [ecx], 0x22
+660f3a411122|3344556677885f5f5f5f 32 plan9 DPPD $0x22, 0(CX), X2
+660f3a411122|3344556677885f5f5f5f 64 gnu dppd $0x22,(%rcx),%xmm2
+660f3a411122|3344556677885f5f5f5f 64 intel dppd xmm2, xmmword ptr [rcx], 0x22
+660f3a411122|3344556677885f5f5f5f 64 plan9 DPPD $0x22, 0(CX), X2
+660f3a421122|3344556677885f5f5f5f 32 intel mpsadbw xmm2, xmmword ptr [ecx], 0x22
+660f3a421122|3344556677885f5f5f5f 32 plan9 MPSADBW $0x22, 0(CX), X2
+660f3a421122|3344556677885f5f5f5f 64 gnu mpsadbw $0x22,(%rcx),%xmm2
+660f3a421122|3344556677885f5f5f5f 64 intel mpsadbw xmm2, xmmword ptr [rcx], 0x22
+660f3a421122|3344556677885f5f5f5f 64 plan9 MPSADBW $0x22, 0(CX), X2
+660f3a441122|3344556677885f5f5f5f 32 intel pclmulqdq xmm2, xmmword ptr [ecx], 0x22
+660f3a441122|3344556677885f5f5f5f 32 plan9 PCLMULQDQ $0x22, 0(CX), X2
+660f3a441122|3344556677885f5f5f5f 64 gnu pclmulqdq $0x22,(%rcx),%xmm2
+660f3a441122|3344556677885f5f5f5f 64 intel pclmulqdq xmm2, xmmword ptr [rcx], 0x22
+660f3a441122|3344556677885f5f5f5f 64 plan9 PCLMULQDQ $0x22, 0(CX), X2
+660f3a601122|3344556677885f5f5f5f 32 intel pcmpestrm xmm2, xmmword ptr [ecx], 0x22
+660f3a601122|3344556677885f5f5f5f 32 plan9 PCMPESTRM $0x22, 0(CX), X2
+660f3a601122|3344556677885f5f5f5f 64 gnu pcmpestrm $0x22,(%rcx),%xmm2
+660f3a601122|3344556677885f5f5f5f 64 intel pcmpestrm xmm2, xmmword ptr [rcx], 0x22
+660f3a601122|3344556677885f5f5f5f 64 plan9 PCMPESTRM $0x22, 0(CX), X2
+660f3a611122|3344556677885f5f5f5f 32 intel pcmpestri xmm2, xmmword ptr [ecx], 0x22
+660f3a611122|3344556677885f5f5f5f 32 plan9 PCMPESTRI $0x22, 0(CX), X2
+660f3a611122|3344556677885f5f5f5f 64 gnu pcmpestri $0x22,(%rcx),%xmm2
+660f3a611122|3344556677885f5f5f5f 64 intel pcmpestri xmm2, xmmword ptr [rcx], 0x22
+660f3a611122|3344556677885f5f5f5f 64 plan9 PCMPESTRI $0x22, 0(CX), X2
+660f3a621122|3344556677885f5f5f5f 32 intel pcmpistrm xmm2, xmmword ptr [ecx], 0x22
+660f3a621122|3344556677885f5f5f5f 32 plan9 PCMPISTRM $0x22, 0(CX), X2
+660f3a621122|3344556677885f5f5f5f 64 gnu pcmpistrm $0x22,(%rcx),%xmm2
+660f3a621122|3344556677885f5f5f5f 64 intel pcmpistrm xmm2, xmmword ptr [rcx], 0x22
+660f3a621122|3344556677885f5f5f5f 64 plan9 PCMPISTRM $0x22, 0(CX), X2
+660f3a631122|3344556677885f5f5f5f 32 intel pcmpistri xmm2, xmmword ptr [ecx], 0x22
+660f3a631122|3344556677885f5f5f5f 32 plan9 PCMPISTRI $0x22, 0(CX), X2
+660f3a631122|3344556677885f5f5f5f 64 gnu pcmpistri $0x22,(%rcx),%xmm2
+660f3a631122|3344556677885f5f5f5f 64 intel pcmpistri xmm2, xmmword ptr [rcx], 0x22
+660f3a631122|3344556677885f5f5f5f 64 plan9 PCMPISTRI $0x22, 0(CX), X2
+660f3adf1122|3344556677885f5f5f5f 32 intel aeskeygenassist xmm2, xmmword ptr [ecx], 0x22
+660f3adf1122|3344556677885f5f5f5f 32 plan9 AESKEYGENASSIST $0x22, 0(CX), X2
+660f3adf1122|3344556677885f5f5f5f 64 gnu aeskeygenassist $0x22,(%rcx),%xmm2
+660f3adf1122|3344556677885f5f5f5f 64 intel aeskeygenassist xmm2, xmmword ptr [rcx], 0x22
+660f3adf1122|3344556677885f5f5f5f 64 plan9 AESKEYGENASSIST $0x22, 0(CX), X2
+660f4011|223344556677885f5f5f5f5f 32 intel cmovo dx, word ptr [ecx]
+660f4011|223344556677885f5f5f5f5f 32 plan9 CMOVO 0(CX), DX
+660f4011|223344556677885f5f5f5f5f 64 gnu cmovo (%rcx),%dx
+660f4011|223344556677885f5f5f5f5f 64 intel cmovo dx, word ptr [rcx]
+660f4011|223344556677885f5f5f5f5f 64 plan9 CMOVO 0(CX), DX
+660f4111|223344556677885f5f5f5f5f 32 intel cmovno dx, word ptr [ecx]
+660f4111|223344556677885f5f5f5f5f 32 plan9 CMOVNO 0(CX), DX
+660f4111|223344556677885f5f5f5f5f 64 gnu cmovno (%rcx),%dx
+660f4111|223344556677885f5f5f5f5f 64 intel cmovno dx, word ptr [rcx]
+660f4111|223344556677885f5f5f5f5f 64 plan9 CMOVNO 0(CX), DX
+660f4211|223344556677885f5f5f5f5f 32 intel cmovb dx, word ptr [ecx]
+660f4211|223344556677885f5f5f5f5f 32 plan9 CMOVB 0(CX), DX
+660f4211|223344556677885f5f5f5f5f 64 gnu cmovb (%rcx),%dx
+660f4211|223344556677885f5f5f5f5f 64 intel cmovb dx, word ptr [rcx]
+660f4211|223344556677885f5f5f5f5f 64 plan9 CMOVB 0(CX), DX
+660f4311|223344556677885f5f5f5f5f 32 intel cmovnb dx, word ptr [ecx]
+660f4311|223344556677885f5f5f5f5f 32 plan9 CMOVAE 0(CX), DX
+660f4311|223344556677885f5f5f5f5f 64 gnu cmovae (%rcx),%dx
+660f4311|223344556677885f5f5f5f5f 64 intel cmovnb dx, word ptr [rcx]
+660f4311|223344556677885f5f5f5f5f 64 plan9 CMOVAE 0(CX), DX
+660f4411|223344556677885f5f5f5f5f 32 intel cmovz dx, word ptr [ecx]
+660f4411|223344556677885f5f5f5f5f 32 plan9 CMOVE 0(CX), DX
+660f4411|223344556677885f5f5f5f5f 64 gnu cmove (%rcx),%dx
+660f4411|223344556677885f5f5f5f5f 64 intel cmovz dx, word ptr [rcx]
+660f4411|223344556677885f5f5f5f5f 64 plan9 CMOVE 0(CX), DX
+660f4511|223344556677885f5f5f5f5f 32 intel cmovnz dx, word ptr [ecx]
+660f4511|223344556677885f5f5f5f5f 32 plan9 CMOVNE 0(CX), DX
+660f4511|223344556677885f5f5f5f5f 64 gnu cmovne (%rcx),%dx
+660f4511|223344556677885f5f5f5f5f 64 intel cmovnz dx, word ptr [rcx]
+660f4511|223344556677885f5f5f5f5f 64 plan9 CMOVNE 0(CX), DX
+660f4611|223344556677885f5f5f5f5f 32 intel cmovbe dx, word ptr [ecx]
+660f4611|223344556677885f5f5f5f5f 32 plan9 CMOVBE 0(CX), DX
+660f4611|223344556677885f5f5f5f5f 64 gnu cmovbe (%rcx),%dx
+660f4611|223344556677885f5f5f5f5f 64 intel cmovbe dx, word ptr [rcx]
+660f4611|223344556677885f5f5f5f5f 64 plan9 CMOVBE 0(CX), DX
+660f4711|223344556677885f5f5f5f5f 32 intel cmovnbe dx, word ptr [ecx]
+660f4711|223344556677885f5f5f5f5f 32 plan9 CMOVA 0(CX), DX
+660f4711|223344556677885f5f5f5f5f 64 gnu cmova (%rcx),%dx
+660f4711|223344556677885f5f5f5f5f 64 intel cmovnbe dx, word ptr [rcx]
+660f4711|223344556677885f5f5f5f5f 64 plan9 CMOVA 0(CX), DX
+660f4811|223344556677885f5f5f5f5f 32 intel cmovs dx, word ptr [ecx]
+660f4811|223344556677885f5f5f5f5f 32 plan9 CMOVS 0(CX), DX
+660f4811|223344556677885f5f5f5f5f 64 gnu cmovs (%rcx),%dx
+660f4811|223344556677885f5f5f5f5f 64 intel cmovs dx, word ptr [rcx]
+660f4811|223344556677885f5f5f5f5f 64 plan9 CMOVS 0(CX), DX
+660f4911|223344556677885f5f5f5f5f 32 intel cmovns dx, word ptr [ecx]
+660f4911|223344556677885f5f5f5f5f 32 plan9 CMOVNS 0(CX), DX
+660f4911|223344556677885f5f5f5f5f 64 gnu cmovns (%rcx),%dx
+660f4911|223344556677885f5f5f5f5f 64 intel cmovns dx, word ptr [rcx]
+660f4911|223344556677885f5f5f5f5f 64 plan9 CMOVNS 0(CX), DX
+660f4a11|223344556677885f5f5f5f5f 32 intel cmovp dx, word ptr [ecx]
+660f4a11|223344556677885f5f5f5f5f 32 plan9 CMOVP 0(CX), DX
+660f4a11|223344556677885f5f5f5f5f 64 gnu cmovp (%rcx),%dx
+660f4a11|223344556677885f5f5f5f5f 64 intel cmovp dx, word ptr [rcx]
+660f4a11|223344556677885f5f5f5f5f 64 plan9 CMOVP 0(CX), DX
+660f4b11|223344556677885f5f5f5f5f 32 intel cmovnp dx, word ptr [ecx]
+660f4b11|223344556677885f5f5f5f5f 32 plan9 CMOVNP 0(CX), DX
+660f4b11|223344556677885f5f5f5f5f 64 gnu cmovnp (%rcx),%dx
+660f4b11|223344556677885f5f5f5f5f 64 intel cmovnp dx, word ptr [rcx]
+660f4b11|223344556677885f5f5f5f5f 64 plan9 CMOVNP 0(CX), DX
+660f4c11|223344556677885f5f5f5f5f 32 intel cmovl dx, word ptr [ecx]
+660f4c11|223344556677885f5f5f5f5f 32 plan9 CMOVL 0(CX), DX
+660f4c11|223344556677885f5f5f5f5f 64 gnu cmovl (%rcx),%dx
+660f4c11|223344556677885f5f5f5f5f 64 intel cmovl dx, word ptr [rcx]
+660f4c11|223344556677885f5f5f5f5f 64 plan9 CMOVL 0(CX), DX
+660f4d11|223344556677885f5f5f5f5f 32 intel cmovnl dx, word ptr [ecx]
+660f4d11|223344556677885f5f5f5f5f 32 plan9 CMOVGE 0(CX), DX
+660f4d11|223344556677885f5f5f5f5f 64 gnu cmovge (%rcx),%dx
+660f4d11|223344556677885f5f5f5f5f 64 intel cmovnl dx, word ptr [rcx]
+660f4d11|223344556677885f5f5f5f5f 64 plan9 CMOVGE 0(CX), DX
+660f4e11|223344556677885f5f5f5f5f 32 intel cmovle dx, word ptr [ecx]
+660f4e11|223344556677885f5f5f5f5f 32 plan9 CMOVLE 0(CX), DX
+660f4e11|223344556677885f5f5f5f5f 64 gnu cmovle (%rcx),%dx
+660f4e11|223344556677885f5f5f5f5f 64 intel cmovle dx, word ptr [rcx]
+660f4e11|223344556677885f5f5f5f5f 64 plan9 CMOVLE 0(CX), DX
+660f4f11|223344556677885f5f5f5f5f 32 intel cmovnle dx, word ptr [ecx]
+660f4f11|223344556677885f5f5f5f5f 32 plan9 CMOVG 0(CX), DX
+660f4f11|223344556677885f5f5f5f5f 64 gnu cmovg (%rcx),%dx
+660f4f11|223344556677885f5f5f5f5f 64 intel cmovnle dx, word ptr [rcx]
+660f4f11|223344556677885f5f5f5f5f 64 plan9 CMOVG 0(CX), DX
+660f50c0|11223344556677885f5f5f5f 32 intel movmskpd eax, xmm0
+660f50c0|11223344556677885f5f5f5f 32 plan9 MOVMSKPD X0, AX
+660f50c0|11223344556677885f5f5f5f 64 gnu movmskpd %xmm0,%eax
+660f50c0|11223344556677885f5f5f5f 64 intel movmskpd eax, xmm0
+660f50c0|11223344556677885f5f5f5f 64 plan9 MOVMSKPD X0, AX
+660f5111|223344556677885f5f5f5f5f 32 intel sqrtpd xmm2, xmmword ptr [ecx]
+660f5111|223344556677885f5f5f5f5f 32 plan9 SQRTPD 0(CX), X2
+660f5111|223344556677885f5f5f5f5f 64 gnu sqrtpd (%rcx),%xmm2
+660f5111|223344556677885f5f5f5f5f 64 intel sqrtpd xmm2, xmmword ptr [rcx]
+660f5111|223344556677885f5f5f5f5f 64 plan9 SQRTPD 0(CX), X2
+660f5411|223344556677885f5f5f5f5f 32 intel andpd xmm2, xmmword ptr [ecx]
+660f5411|223344556677885f5f5f5f5f 32 plan9 ANDPD 0(CX), X2
+660f5411|223344556677885f5f5f5f5f 64 gnu andpd (%rcx),%xmm2
+660f5411|223344556677885f5f5f5f5f 64 intel andpd xmm2, xmmword ptr [rcx]
+660f5411|223344556677885f5f5f5f5f 64 plan9 ANDPD 0(CX), X2
+660f5511|223344556677885f5f5f5f5f 32 intel andnpd xmm2, xmmword ptr [ecx]
+660f5511|223344556677885f5f5f5f5f 32 plan9 ANDNPD 0(CX), X2
+660f5511|223344556677885f5f5f5f5f 64 gnu andnpd (%rcx),%xmm2
+660f5511|223344556677885f5f5f5f5f 64 intel andnpd xmm2, xmmword ptr [rcx]
+660f5511|223344556677885f5f5f5f5f 64 plan9 ANDNPD 0(CX), X2
+660f5611|223344556677885f5f5f5f5f 32 intel orpd xmm2, xmmword ptr [ecx]
+660f5611|223344556677885f5f5f5f5f 32 plan9 ORPD 0(CX), X2
+660f5611|223344556677885f5f5f5f5f 64 gnu orpd (%rcx),%xmm2
+660f5611|223344556677885f5f5f5f5f 64 intel orpd xmm2, xmmword ptr [rcx]
+660f5611|223344556677885f5f5f5f5f 64 plan9 ORPD 0(CX), X2
+660f5711|223344556677885f5f5f5f5f 32 intel xorpd xmm2, xmmword ptr [ecx]
+660f5711|223344556677885f5f5f5f5f 32 plan9 XORPD 0(CX), X2
+660f5711|223344556677885f5f5f5f5f 64 gnu xorpd (%rcx),%xmm2
+660f5711|223344556677885f5f5f5f5f 64 intel xorpd xmm2, xmmword ptr [rcx]
+660f5711|223344556677885f5f5f5f5f 64 plan9 XORPD 0(CX), X2
+660f5811|223344556677885f5f5f5f5f 32 intel addpd xmm2, xmmword ptr [ecx]
+660f5811|223344556677885f5f5f5f5f 32 plan9 ADDPD 0(CX), X2
+660f5811|223344556677885f5f5f5f5f 64 gnu addpd (%rcx),%xmm2
+660f5811|223344556677885f5f5f5f5f 64 intel addpd xmm2, xmmword ptr [rcx]
+660f5811|223344556677885f5f5f5f5f 64 plan9 ADDPD 0(CX), X2
+660f5911|223344556677885f5f5f5f5f 32 intel mulpd xmm2, xmmword ptr [ecx]
+660f5911|223344556677885f5f5f5f5f 32 plan9 MULPD 0(CX), X2
+660f5911|223344556677885f5f5f5f5f 64 gnu mulpd (%rcx),%xmm2
+660f5911|223344556677885f5f5f5f5f 64 intel mulpd xmm2, xmmword ptr [rcx]
+660f5911|223344556677885f5f5f5f5f 64 plan9 MULPD 0(CX), X2
+660f5a11|223344556677885f5f5f5f5f 32 intel cvtpd2ps xmm2, xmmword ptr [ecx]
+660f5a11|223344556677885f5f5f5f5f 32 plan9 CVTPD2PS 0(CX), X2
+660f5a11|223344556677885f5f5f5f5f 64 gnu cvtpd2ps (%rcx),%xmm2
+660f5a11|223344556677885f5f5f5f5f 64 intel cvtpd2ps xmm2, xmmword ptr [rcx]
+660f5a11|223344556677885f5f5f5f5f 64 plan9 CVTPD2PS 0(CX), X2
+660f5b11|223344556677885f5f5f5f5f 32 intel cvtps2dq xmm2, xmmword ptr [ecx]
+660f5b11|223344556677885f5f5f5f5f 32 plan9 CVTPS2DQ 0(CX), X2
+660f5b11|223344556677885f5f5f5f5f 64 gnu cvtps2dq (%rcx),%xmm2
+660f5b11|223344556677885f5f5f5f5f 64 intel cvtps2dq xmm2, xmmword ptr [rcx]
+660f5b11|223344556677885f5f5f5f5f 64 plan9 CVTPS2DQ 0(CX), X2
+660f5c11|223344556677885f5f5f5f5f 32 intel subpd xmm2, xmmword ptr [ecx]
+660f5c11|223344556677885f5f5f5f5f 32 plan9 SUBPD 0(CX), X2
+660f5c11|223344556677885f5f5f5f5f 64 gnu subpd (%rcx),%xmm2
+660f5c11|223344556677885f5f5f5f5f 64 intel subpd xmm2, xmmword ptr [rcx]
+660f5c11|223344556677885f5f5f5f5f 64 plan9 SUBPD 0(CX), X2
+660f5d11|223344556677885f5f5f5f5f 32 intel minpd xmm2, xmmword ptr [ecx]
+660f5d11|223344556677885f5f5f5f5f 32 plan9 MINPD 0(CX), X2
+660f5d11|223344556677885f5f5f5f5f 64 gnu minpd (%rcx),%xmm2
+660f5d11|223344556677885f5f5f5f5f 64 intel minpd xmm2, xmmword ptr [rcx]
+660f5d11|223344556677885f5f5f5f5f 64 plan9 MINPD 0(CX), X2
+660f5e11|223344556677885f5f5f5f5f 32 intel divpd xmm2, xmmword ptr [ecx]
+660f5e11|223344556677885f5f5f5f5f 32 plan9 DIVPD 0(CX), X2
+660f5e11|223344556677885f5f5f5f5f 64 gnu divpd (%rcx),%xmm2
+660f5e11|223344556677885f5f5f5f5f 64 intel divpd xmm2, xmmword ptr [rcx]
+660f5e11|223344556677885f5f5f5f5f 64 plan9 DIVPD 0(CX), X2
+660f5f11|223344556677885f5f5f5f5f 32 intel maxpd xmm2, xmmword ptr [ecx]
+660f5f11|223344556677885f5f5f5f5f 32 plan9 MAXPD 0(CX), X2
+660f5f11|223344556677885f5f5f5f5f 64 gnu maxpd (%rcx),%xmm2
+660f5f11|223344556677885f5f5f5f5f 64 intel maxpd xmm2, xmmword ptr [rcx]
+660f5f11|223344556677885f5f5f5f5f 64 plan9 MAXPD 0(CX), X2
+660f6011|223344556677885f5f5f5f5f 32 intel punpcklbw xmm2, xmmword ptr [ecx]
+660f6011|223344556677885f5f5f5f5f 32 plan9 PUNPCKLBW 0(CX), X2
+660f6011|223344556677885f5f5f5f5f 64 gnu punpcklbw (%rcx),%xmm2
+660f6011|223344556677885f5f5f5f5f 64 intel punpcklbw xmm2, xmmword ptr [rcx]
+660f6011|223344556677885f5f5f5f5f 64 plan9 PUNPCKLBW 0(CX), X2
+660f6111|223344556677885f5f5f5f5f 32 intel punpcklwd xmm2, xmmword ptr [ecx]
+660f6111|223344556677885f5f5f5f5f 32 plan9 PUNPCKLWD 0(CX), X2
+660f6111|223344556677885f5f5f5f5f 64 gnu punpcklwd (%rcx),%xmm2
+660f6111|223344556677885f5f5f5f5f 64 intel punpcklwd xmm2, xmmword ptr [rcx]
+660f6111|223344556677885f5f5f5f5f 64 plan9 PUNPCKLWD 0(CX), X2
+660f6211|223344556677885f5f5f5f5f 32 intel punpckldq xmm2, xmmword ptr [ecx]
+660f6211|223344556677885f5f5f5f5f 32 plan9 PUNPCKLDQ 0(CX), X2
+660f6211|223344556677885f5f5f5f5f 64 gnu punpckldq (%rcx),%xmm2
+660f6211|223344556677885f5f5f5f5f 64 intel punpckldq xmm2, xmmword ptr [rcx]
+660f6211|223344556677885f5f5f5f5f 64 plan9 PUNPCKLDQ 0(CX), X2
+660f6311|223344556677885f5f5f5f5f 32 intel packsswb xmm2, xmmword ptr [ecx]
+660f6311|223344556677885f5f5f5f5f 32 plan9 PACKSSWB 0(CX), X2
+660f6311|223344556677885f5f5f5f5f 64 gnu packsswb (%rcx),%xmm2
+660f6311|223344556677885f5f5f5f5f 64 intel packsswb xmm2, xmmword ptr [rcx]
+660f6311|223344556677885f5f5f5f5f 64 plan9 PACKSSWB 0(CX), X2
+660f6411|223344556677885f5f5f5f5f 32 intel pcmpgtb xmm2, xmmword ptr [ecx]
+660f6411|223344556677885f5f5f5f5f 32 plan9 PCMPGTB 0(CX), X2
+660f6411|223344556677885f5f5f5f5f 64 gnu pcmpgtb (%rcx),%xmm2
+660f6411|223344556677885f5f5f5f5f 64 intel pcmpgtb xmm2, xmmword ptr [rcx]
+660f6411|223344556677885f5f5f5f5f 64 plan9 PCMPGTB 0(CX), X2
+660f6511|223344556677885f5f5f5f5f 32 intel pcmpgtw xmm2, xmmword ptr [ecx]
+660f6511|223344556677885f5f5f5f5f 32 plan9 PCMPGTW 0(CX), X2
+660f6511|223344556677885f5f5f5f5f 64 gnu pcmpgtw (%rcx),%xmm2
+660f6511|223344556677885f5f5f5f5f 64 intel pcmpgtw xmm2, xmmword ptr [rcx]
+660f6511|223344556677885f5f5f5f5f 64 plan9 PCMPGTW 0(CX), X2
+660f6611|223344556677885f5f5f5f5f 32 intel pcmpgtd xmm2, xmmword ptr [ecx]
+660f6611|223344556677885f5f5f5f5f 32 plan9 PCMPGTD 0(CX), X2
+660f6611|223344556677885f5f5f5f5f 64 gnu pcmpgtd (%rcx),%xmm2
+660f6611|223344556677885f5f5f5f5f 64 intel pcmpgtd xmm2, xmmword ptr [rcx]
+660f6611|223344556677885f5f5f5f5f 64 plan9 PCMPGTD 0(CX), X2
+660f6711|223344556677885f5f5f5f5f 32 intel packuswb xmm2, xmmword ptr [ecx]
+660f6711|223344556677885f5f5f5f5f 32 plan9 PACKUSWB 0(CX), X2
+660f6711|223344556677885f5f5f5f5f 64 gnu packuswb (%rcx),%xmm2
+660f6711|223344556677885f5f5f5f5f 64 intel packuswb xmm2, xmmword ptr [rcx]
+660f6711|223344556677885f5f5f5f5f 64 plan9 PACKUSWB 0(CX), X2
+660f6811|223344556677885f5f5f5f5f 32 intel punpckhbw xmm2, xmmword ptr [ecx]
+660f6811|223344556677885f5f5f5f5f 32 plan9 PUNPCKHBW 0(CX), X2
+660f6811|223344556677885f5f5f5f5f 64 gnu punpckhbw (%rcx),%xmm2
+660f6811|223344556677885f5f5f5f5f 64 intel punpckhbw xmm2, xmmword ptr [rcx]
+660f6811|223344556677885f5f5f5f5f 64 plan9 PUNPCKHBW 0(CX), X2
+660f6911|223344556677885f5f5f5f5f 32 intel punpckhwd xmm2, xmmword ptr [ecx]
+660f6911|223344556677885f5f5f5f5f 32 plan9 PUNPCKHWD 0(CX), X2
+660f6911|223344556677885f5f5f5f5f 64 gnu punpckhwd (%rcx),%xmm2
+660f6911|223344556677885f5f5f5f5f 64 intel punpckhwd xmm2, xmmword ptr [rcx]
+660f6911|223344556677885f5f5f5f5f 64 plan9 PUNPCKHWD 0(CX), X2
+660f6a11|223344556677885f5f5f5f5f 32 intel punpckhdq xmm2, xmmword ptr [ecx]
+660f6a11|223344556677885f5f5f5f5f 32 plan9 PUNPCKHDQ 0(CX), X2
+660f6a11|223344556677885f5f5f5f5f 64 gnu punpckhdq (%rcx),%xmm2
+660f6a11|223344556677885f5f5f5f5f 64 intel punpckhdq xmm2, xmmword ptr [rcx]
+660f6a11|223344556677885f5f5f5f5f 64 plan9 PUNPCKHDQ 0(CX), X2
+660f6b11|223344556677885f5f5f5f5f 32 intel packssdw xmm2, xmmword ptr [ecx]
+660f6b11|223344556677885f5f5f5f5f 32 plan9 PACKSSDW 0(CX), X2
+660f6b11|223344556677885f5f5f5f5f 64 gnu packssdw (%rcx),%xmm2
+660f6b11|223344556677885f5f5f5f5f 64 intel packssdw xmm2, xmmword ptr [rcx]
+660f6b11|223344556677885f5f5f5f5f 64 plan9 PACKSSDW 0(CX), X2
+660f6c11|223344556677885f5f5f5f5f 32 intel punpcklqdq xmm2, xmmword ptr [ecx]
+660f6c11|223344556677885f5f5f5f5f 32 plan9 PUNPCKLQDQ 0(CX), X2
+660f6c11|223344556677885f5f5f5f5f 64 gnu punpcklqdq (%rcx),%xmm2
+660f6c11|223344556677885f5f5f5f5f 64 intel punpcklqdq xmm2, xmmword ptr [rcx]
+660f6c11|223344556677885f5f5f5f5f 64 plan9 PUNPCKLQDQ 0(CX), X2
+660f6d11|223344556677885f5f5f5f5f 32 intel punpckhqdq xmm2, xmmword ptr [ecx]
+660f6d11|223344556677885f5f5f5f5f 32 plan9 PUNPCKHQDQ 0(CX), X2
+660f6d11|223344556677885f5f5f5f5f 64 gnu punpckhqdq (%rcx),%xmm2
+660f6d11|223344556677885f5f5f5f5f 64 intel punpckhqdq xmm2, xmmword ptr [rcx]
+660f6d11|223344556677885f5f5f5f5f 64 plan9 PUNPCKHQDQ 0(CX), X2
+660f6e11|223344556677885f5f5f5f5f 32 intel movd xmm2, dword ptr [ecx]
+660f6e11|223344556677885f5f5f5f5f 32 plan9 MOVD 0(CX), X2
+660f6e11|223344556677885f5f5f5f5f 64 gnu movd (%rcx),%xmm2
+660f6e11|223344556677885f5f5f5f5f 64 intel movd xmm2, dword ptr [rcx]
+660f6e11|223344556677885f5f5f5f5f 64 plan9 MOVD 0(CX), X2
+660f6f11|223344556677885f5f5f5f5f 32 intel movdqa xmm2, xmmword ptr [ecx]
+660f6f11|223344556677885f5f5f5f5f 32 plan9 MOVDQA 0(CX), X2
+660f6f11|223344556677885f5f5f5f5f 64 gnu movdqa (%rcx),%xmm2
+660f6f11|223344556677885f5f5f5f5f 64 intel movdqa xmm2, xmmword ptr [rcx]
+660f6f11|223344556677885f5f5f5f5f 64 plan9 MOVDQA 0(CX), X2
+660f701122|3344556677885f5f5f5f5f 32 intel pshufd xmm2, xmmword ptr [ecx], 0x22
+660f701122|3344556677885f5f5f5f5f 32 plan9 PSHUFD $0x22, 0(CX), X2
+660f701122|3344556677885f5f5f5f5f 64 gnu pshufd $0x22,(%rcx),%xmm2
+660f701122|3344556677885f5f5f5f5f 64 intel pshufd xmm2, xmmword ptr [rcx], 0x22
+660f701122|3344556677885f5f5f5f5f 64 plan9 PSHUFD $0x22, 0(CX), X2
+660f71d011|223344556677885f5f5f5f 32 intel psrlw xmm0, 0x11
+660f71d011|223344556677885f5f5f5f 32 plan9 PSRLW $0x11, X0
+660f71d011|223344556677885f5f5f5f 64 gnu psrlw $0x11,%xmm0
+660f71d011|223344556677885f5f5f5f 64 intel psrlw xmm0, 0x11
+660f71d011|223344556677885f5f5f5f 64 plan9 PSRLW $0x11, X0
+660f71e011|223344556677885f5f5f5f 32 intel psraw xmm0, 0x11
+660f71e011|223344556677885f5f5f5f 32 plan9 PSRAW $0x11, X0
+660f71e011|223344556677885f5f5f5f 64 gnu psraw $0x11,%xmm0
+660f71e011|223344556677885f5f5f5f 64 intel psraw xmm0, 0x11
+660f71e011|223344556677885f5f5f5f 64 plan9 PSRAW $0x11, X0
+660f71f011|223344556677885f5f5f5f 32 intel psllw xmm0, 0x11
+660f71f011|223344556677885f5f5f5f 32 plan9 PSLLW $0x11, X0
+660f71f011|223344556677885f5f5f5f 64 gnu psllw $0x11,%xmm0
+660f71f011|223344556677885f5f5f5f 64 intel psllw xmm0, 0x11
+660f71f011|223344556677885f5f5f5f 64 plan9 PSLLW $0x11, X0
+660f72d011|223344556677885f5f5f5f 32 intel psrld xmm0, 0x11
+660f72d011|223344556677885f5f5f5f 32 plan9 PSRLD $0x11, X0
+660f72d011|223344556677885f5f5f5f 64 gnu psrld $0x11,%xmm0
+660f72d011|223344556677885f5f5f5f 64 intel psrld xmm0, 0x11
+660f72d011|223344556677885f5f5f5f 64 plan9 PSRLD $0x11, X0
+660f72e011|223344556677885f5f5f5f 32 intel psrad xmm0, 0x11
+660f72e011|223344556677885f5f5f5f 32 plan9 PSRAD $0x11, X0
+660f72e011|223344556677885f5f5f5f 64 gnu psrad $0x11,%xmm0
+660f72e011|223344556677885f5f5f5f 64 intel psrad xmm0, 0x11
+660f72e011|223344556677885f5f5f5f 64 plan9 PSRAD $0x11, X0
+660f72f011|223344556677885f5f5f5f 32 intel pslld xmm0, 0x11
+660f72f011|223344556677885f5f5f5f 32 plan9 PSLLD $0x11, X0
+660f72f011|223344556677885f5f5f5f 64 gnu pslld $0x11,%xmm0
+660f72f011|223344556677885f5f5f5f 64 intel pslld xmm0, 0x11
+660f72f011|223344556677885f5f5f5f 64 plan9 PSLLD $0x11, X0
+660f73d011|223344556677885f5f5f5f 32 intel psrlq xmm0, 0x11
+660f73d011|223344556677885f5f5f5f 32 plan9 PSRLQ $0x11, X0
+660f73d011|223344556677885f5f5f5f 64 gnu psrlq $0x11,%xmm0
+660f73d011|223344556677885f5f5f5f 64 intel psrlq xmm0, 0x11
+660f73d011|223344556677885f5f5f5f 64 plan9 PSRLQ $0x11, X0
+660f73d811|223344556677885f5f5f5f 32 intel psrldq xmm0, 0x11
+660f73d811|223344556677885f5f5f5f 32 plan9 PSRLDQ $0x11, X0
+660f73d811|223344556677885f5f5f5f 64 gnu psrldq $0x11,%xmm0
+660f73d811|223344556677885f5f5f5f 64 intel psrldq xmm0, 0x11
+660f73d811|223344556677885f5f5f5f 64 plan9 PSRLDQ $0x11, X0
+660f73f011|223344556677885f5f5f5f 32 intel psllq xmm0, 0x11
+660f73f011|223344556677885f5f5f5f 32 plan9 PSLLQ $0x11, X0
+660f73f011|223344556677885f5f5f5f 64 gnu psllq $0x11,%xmm0
+660f73f011|223344556677885f5f5f5f 64 intel psllq xmm0, 0x11
+660f73f011|223344556677885f5f5f5f 64 plan9 PSLLQ $0x11, X0
+660f73f811|223344556677885f5f5f5f 32 intel pslldq xmm0, 0x11
+660f73f811|223344556677885f5f5f5f 32 plan9 PSLLDQ $0x11, X0
+660f73f811|223344556677885f5f5f5f 64 gnu pslldq $0x11,%xmm0
+660f73f811|223344556677885f5f5f5f 64 intel pslldq xmm0, 0x11
+660f73f811|223344556677885f5f5f5f 64 plan9 PSLLDQ $0x11, X0
+660f7411|223344556677885f5f5f5f5f 32 intel pcmpeqb xmm2, xmmword ptr [ecx]
+660f7411|223344556677885f5f5f5f5f 32 plan9 PCMPEQB 0(CX), X2
+660f7411|223344556677885f5f5f5f5f 64 gnu pcmpeqb (%rcx),%xmm2
+660f7411|223344556677885f5f5f5f5f 64 intel pcmpeqb xmm2, xmmword ptr [rcx]
+660f7411|223344556677885f5f5f5f5f 64 plan9 PCMPEQB 0(CX), X2
+660f7511|223344556677885f5f5f5f5f 32 intel pcmpeqw xmm2, xmmword ptr [ecx]
+660f7511|223344556677885f5f5f5f5f 32 plan9 PCMPEQW 0(CX), X2
+660f7511|223344556677885f5f5f5f5f 64 gnu pcmpeqw (%rcx),%xmm2
+660f7511|223344556677885f5f5f5f5f 64 intel pcmpeqw xmm2, xmmword ptr [rcx]
+660f7511|223344556677885f5f5f5f5f 64 plan9 PCMPEQW 0(CX), X2
+660f7611|223344556677885f5f5f5f5f 32 intel pcmpeqd xmm2, xmmword ptr [ecx]
+660f7611|223344556677885f5f5f5f5f 32 plan9 PCMPEQD 0(CX), X2
+660f7611|223344556677885f5f5f5f5f 64 gnu pcmpeqd (%rcx),%xmm2
+660f7611|223344556677885f5f5f5f5f 64 intel pcmpeqd xmm2, xmmword ptr [rcx]
+660f7611|223344556677885f5f5f5f5f 64 plan9 PCMPEQD 0(CX), X2
+660f7c11|223344556677885f5f5f5f5f 32 intel haddpd xmm2, xmmword ptr [ecx]
+660f7c11|223344556677885f5f5f5f5f 32 plan9 HADDPD 0(CX), X2
+660f7c11|223344556677885f5f5f5f5f 64 gnu haddpd (%rcx),%xmm2
+660f7c11|223344556677885f5f5f5f5f 64 intel haddpd xmm2, xmmword ptr [rcx]
+660f7c11|223344556677885f5f5f5f5f 64 plan9 HADDPD 0(CX), X2
+660f7d11|223344556677885f5f5f5f5f 32 intel hsubpd xmm2, xmmword ptr [ecx]
+660f7d11|223344556677885f5f5f5f5f 32 plan9 HSUBPD 0(CX), X2
+660f7d11|223344556677885f5f5f5f5f 64 gnu hsubpd (%rcx),%xmm2
+660f7d11|223344556677885f5f5f5f5f 64 intel hsubpd xmm2, xmmword ptr [rcx]
+660f7d11|223344556677885f5f5f5f5f 64 plan9 HSUBPD 0(CX), X2
+660f7e11|223344556677885f5f5f5f5f 32 intel movd dword ptr [ecx], xmm2
+660f7e11|223344556677885f5f5f5f5f 32 plan9 MOVD X2, 0(CX)
+660f7e11|223344556677885f5f5f5f5f 64 gnu movd %xmm2,(%rcx)
+660f7e11|223344556677885f5f5f5f5f 64 intel movd dword ptr [rcx], xmm2
+660f7e11|223344556677885f5f5f5f5f 64 plan9 MOVD X2, 0(CX)
+660f7f11|223344556677885f5f5f5f5f 32 intel movdqa xmmword ptr [ecx], xmm2
+660f7f11|223344556677885f5f5f5f5f 32 plan9 MOVDQA X2, 0(CX)
+660f7f11|223344556677885f5f5f5f5f 64 gnu movdqa %xmm2,(%rcx)
+660f7f11|223344556677885f5f5f5f5f 64 intel movdqa xmmword ptr [rcx], xmm2
+660f7f11|223344556677885f5f5f5f5f 64 plan9 MOVDQA X2, 0(CX)
+660f8011223344|556677885f5f5f5f5f 64 gnu jo .+0x44332211
+660f8011223344|556677885f5f5f5f5f 64 intel jo .+0x44332211
+660f8011223344|556677885f5f5f5f5f 64 plan9 JO .+1144201745
+660f801122|3344556677885f5f5f5f5f 32 intel jo .+0x2211
+660f801122|3344556677885f5f5f5f5f 32 plan9 JO .+8721
+660f8111223344|556677885f5f5f5f5f 64 gnu jno .+0x44332211
+660f8111223344|556677885f5f5f5f5f 64 intel jno .+0x44332211
+660f8111223344|556677885f5f5f5f5f 64 plan9 JNO .+1144201745
+660f811122|3344556677885f5f5f5f5f 32 intel jno .+0x2211
+660f811122|3344556677885f5f5f5f5f 32 plan9 JNO .+8721
+660f8211223344|556677885f5f5f5f5f 64 gnu jb .+0x44332211
+660f8211223344|556677885f5f5f5f5f 64 intel jb .+0x44332211
+660f8211223344|556677885f5f5f5f5f 64 plan9 JB .+1144201745
+660f821122|3344556677885f5f5f5f5f 32 intel jb .+0x2211
+660f821122|3344556677885f5f5f5f5f 32 plan9 JB .+8721
+660f8311223344|556677885f5f5f5f5f 64 gnu jae .+0x44332211
+660f8311223344|556677885f5f5f5f5f 64 intel jnb .+0x44332211
+660f8311223344|556677885f5f5f5f5f 64 plan9 JAE .+1144201745
+660f831122|3344556677885f5f5f5f5f 32 intel jnb .+0x2211
+660f831122|3344556677885f5f5f5f5f 32 plan9 JAE .+8721
+660f8411223344|556677885f5f5f5f5f 64 gnu je .+0x44332211
+660f8411223344|556677885f5f5f5f5f 64 intel jz .+0x44332211
+660f8411223344|556677885f5f5f5f5f 64 plan9 JE .+1144201745
+660f841122|3344556677885f5f5f5f5f 32 intel jz .+0x2211
+660f841122|3344556677885f5f5f5f5f 32 plan9 JE .+8721
+660f8511223344|556677885f5f5f5f5f 64 gnu jne .+0x44332211
+660f8511223344|556677885f5f5f5f5f 64 intel jnz .+0x44332211
+660f8511223344|556677885f5f5f5f5f 64 plan9 JNE .+1144201745
+660f851122|3344556677885f5f5f5f5f 32 intel jnz .+0x2211
+660f851122|3344556677885f5f5f5f5f 32 plan9 JNE .+8721
+660f8611223344|556677885f5f5f5f5f 64 gnu jbe .+0x44332211
+660f8611223344|556677885f5f5f5f5f 64 intel jbe .+0x44332211
+660f8611223344|556677885f5f5f5f5f 64 plan9 JBE .+1144201745
+660f861122|3344556677885f5f5f5f5f 32 intel jbe .+0x2211
+660f861122|3344556677885f5f5f5f5f 32 plan9 JBE .+8721
+660f8711223344|556677885f5f5f5f5f 64 gnu ja .+0x44332211
+660f8711223344|556677885f5f5f5f5f 64 intel jnbe .+0x44332211
+660f8711223344|556677885f5f5f5f5f 64 plan9 JA .+1144201745
+660f871122|3344556677885f5f5f5f5f 32 intel jnbe .+0x2211
+660f871122|3344556677885f5f5f5f5f 32 plan9 JA .+8721
+660f8811223344|556677885f5f5f5f5f 64 gnu js .+0x44332211
+660f8811223344|556677885f5f5f5f5f 64 intel js .+0x44332211
+660f8811223344|556677885f5f5f5f5f 64 plan9 JS .+1144201745
+660f881122|3344556677885f5f5f5f5f 32 intel js .+0x2211
+660f881122|3344556677885f5f5f5f5f 32 plan9 JS .+8721
+660f8911223344|556677885f5f5f5f5f 64 gnu jns .+0x44332211
+660f8911223344|556677885f5f5f5f5f 64 intel jns .+0x44332211
+660f8911223344|556677885f5f5f5f5f 64 plan9 JNS .+1144201745
+660f891122|3344556677885f5f5f5f5f 32 intel jns .+0x2211
+660f891122|3344556677885f5f5f5f5f 32 plan9 JNS .+8721
+660f8a11223344|556677885f5f5f5f5f 64 gnu jp .+0x44332211
+660f8a11223344|556677885f5f5f5f5f 64 intel jp .+0x44332211
+660f8a11223344|556677885f5f5f5f5f 64 plan9 JP .+1144201745
+660f8a1122|3344556677885f5f5f5f5f 32 intel jp .+0x2211
+660f8a1122|3344556677885f5f5f5f5f 32 plan9 JP .+8721
+660f8b11223344|556677885f5f5f5f5f 64 gnu jnp .+0x44332211
+660f8b11223344|556677885f5f5f5f5f 64 intel jnp .+0x44332211
+660f8b11223344|556677885f5f5f5f5f 64 plan9 JNP .+1144201745
+660f8b1122|3344556677885f5f5f5f5f 32 intel jnp .+0x2211
+660f8b1122|3344556677885f5f5f5f5f 32 plan9 JNP .+8721
+660f8c11223344|556677885f5f5f5f5f 64 gnu jl .+0x44332211
+660f8c11223344|556677885f5f5f5f5f 64 intel jl .+0x44332211
+660f8c11223344|556677885f5f5f5f5f 64 plan9 JL .+1144201745
+660f8c1122|3344556677885f5f5f5f5f 32 intel jl .+0x2211
+660f8c1122|3344556677885f5f5f5f5f 32 plan9 JL .+8721
+660f8d11223344|556677885f5f5f5f5f 64 gnu jge .+0x44332211
+660f8d11223344|556677885f5f5f5f5f 64 intel jnl .+0x44332211
+660f8d11223344|556677885f5f5f5f5f 64 plan9 JGE .+1144201745
+660f8d1122|3344556677885f5f5f5f5f 32 intel jnl .+0x2211
+660f8d1122|3344556677885f5f5f5f5f 32 plan9 JGE .+8721
+660f8e11223344|556677885f5f5f5f5f 64 gnu jle .+0x44332211
+660f8e11223344|556677885f5f5f5f5f 64 intel jle .+0x44332211
+660f8e11223344|556677885f5f5f5f5f 64 plan9 JLE .+1144201745
+660f8e1122|3344556677885f5f5f5f5f 32 intel jle .+0x2211
+660f8e1122|3344556677885f5f5f5f5f 32 plan9 JLE .+8721
+660f8f11223344|556677885f5f5f5f5f 64 gnu jg .+0x44332211
+660f8f11223344|556677885f5f5f5f5f 64 intel jnle .+0x44332211
+660f8f11223344|556677885f5f5f5f5f 64 plan9 JG .+1144201745
+660f8f1122|3344556677885f5f5f5f5f 32 intel jnle .+0x2211
+660f8f1122|3344556677885f5f5f5f5f 32 plan9 JG .+8721
+660fa1|11223344556677885f5f5f5f5f 32 intel pop fs
+660fa1|11223344556677885f5f5f5f5f 32 plan9 POPW FS
+660fa1|11223344556677885f5f5f5f5f 64 gnu popw %fs
+660fa1|11223344556677885f5f5f5f5f 64 intel pop fs
+660fa1|11223344556677885f5f5f5f5f 64 plan9 POPW FS
+660fa311|223344556677885f5f5f5f5f 32 intel bt word ptr [ecx], dx
+660fa311|223344556677885f5f5f5f5f 32 plan9 BTW DX, 0(CX)
+660fa311|223344556677885f5f5f5f5f 64 gnu bt %dx,(%rcx)
+660fa311|223344556677885f5f5f5f5f 64 intel bt word ptr [rcx], dx
+660fa311|223344556677885f5f5f5f5f 64 plan9 BTW DX, 0(CX)
+660fa41122|3344556677885f5f5f5f5f 32 intel shld word ptr [ecx], dx, 0x22
+660fa41122|3344556677885f5f5f5f5f 32 plan9 SHLDW $0x22, DX, 0(CX)
+660fa41122|3344556677885f5f5f5f5f 64 gnu shld $0x22,%dx,(%rcx)
+660fa41122|3344556677885f5f5f5f5f 64 intel shld word ptr [rcx], dx, 0x22
+660fa41122|3344556677885f5f5f5f5f 64 plan9 SHLDW $0x22, DX, 0(CX)
+660fa511|223344556677885f5f5f5f5f 32 intel shld word ptr [ecx], dx, cl
+660fa511|223344556677885f5f5f5f5f 32 plan9 SHLDW CL, DX, 0(CX)
+660fa511|223344556677885f5f5f5f5f 64 gnu shld %cl,%dx,(%rcx)
+660fa511|223344556677885f5f5f5f5f 64 intel shld word ptr [rcx], dx, cl
+660fa511|223344556677885f5f5f5f5f 64 plan9 SHLDW CL, DX, 0(CX)
+660fa9|11223344556677885f5f5f5f5f 32 intel pop gs
+660fa9|11223344556677885f5f5f5f5f 32 plan9 POPW GS
+660fa9|11223344556677885f5f5f5f5f 64 gnu popw %gs
+660fa9|11223344556677885f5f5f5f5f 64 intel pop gs
+660fa9|11223344556677885f5f5f5f5f 64 plan9 POPW GS
+660fab11|223344556677885f5f5f5f5f 32 intel bts word ptr [ecx], dx
+660fab11|223344556677885f5f5f5f5f 32 plan9 BTSW DX, 0(CX)
+660fab11|223344556677885f5f5f5f5f 64 gnu bts %dx,(%rcx)
+660fab11|223344556677885f5f5f5f5f 64 intel bts word ptr [rcx], dx
+660fab11|223344556677885f5f5f5f5f 64 plan9 BTSW DX, 0(CX)
+660fac1122|3344556677885f5f5f5f5f 32 intel shrd word ptr [ecx], dx, 0x22
+660fac1122|3344556677885f5f5f5f5f 32 plan9 SHRDW $0x22, DX, 0(CX)
+660fac1122|3344556677885f5f5f5f5f 64 gnu shrd $0x22,%dx,(%rcx)
+660fac1122|3344556677885f5f5f5f5f 64 intel shrd word ptr [rcx], dx, 0x22
+660fac1122|3344556677885f5f5f5f5f 64 plan9 SHRDW $0x22, DX, 0(CX)
+660fad11|223344556677885f5f5f5f5f 32 intel shrd word ptr [ecx], dx, cl
+660fad11|223344556677885f5f5f5f5f 32 plan9 SHRDW CL, DX, 0(CX)
+660fad11|223344556677885f5f5f5f5f 64 gnu shrd %cl,%dx,(%rcx)
+660fad11|223344556677885f5f5f5f5f 64 intel shrd word ptr [rcx], dx, cl
+660fad11|223344556677885f5f5f5f5f 64 plan9 SHRDW CL, DX, 0(CX)
+660fae00|11223344556677885f5f5f5f 32 intel fxsave ptr [eax]
+660fae00|11223344556677885f5f5f5f 32 plan9 FXSAVE 0(AX)
+660fae00|11223344556677885f5f5f5f 64 gnu fxsave (%rax)
+660fae00|11223344556677885f5f5f5f 64 intel fxsave ptr [rax]
+660fae00|11223344556677885f5f5f5f 64 plan9 FXSAVE 0(AX)
+660fae08|11223344556677885f5f5f5f 32 intel fxrstor ptr [eax]
+660fae08|11223344556677885f5f5f5f 32 plan9 FXRSTOR 0(AX)
+660fae08|11223344556677885f5f5f5f 64 gnu data16 fxrstor (%rax)
+660fae08|11223344556677885f5f5f5f 64 intel fxrstor ptr [rax]
+660fae08|11223344556677885f5f5f5f 64 plan9 FXRSTOR 0(AX)
+660fae20|11223344556677885f5f5f5f 32 intel xsave ptr [eax]
+660fae20|11223344556677885f5f5f5f 32 plan9 XSAVE 0(AX)
+660fae20|11223344556677885f5f5f5f 64 gnu data16 xsave (%rax)
+660fae20|11223344556677885f5f5f5f 64 intel xsave ptr [rax]
+660fae20|11223344556677885f5f5f5f 64 plan9 XSAVE 0(AX)
+660fae28|11223344556677885f5f5f5f 32 intel xrstor ptr [eax]
+660fae28|11223344556677885f5f5f5f 32 plan9 XRSTOR 0(AX)
+660fae28|11223344556677885f5f5f5f 64 gnu data16 xrstor (%rax)
+660fae28|11223344556677885f5f5f5f 64 intel xrstor ptr [rax]
+660fae28|11223344556677885f5f5f5f 64 plan9 XRSTOR 0(AX)
+660fae30|11223344556677885f5f5f5f 32 intel xsaveopt ptr [eax]
+660fae30|11223344556677885f5f5f5f 32 plan9 XSAVEOPT 0(AX)
+660fae30|11223344556677885f5f5f5f 64 gnu data16 xsaveopt (%rax)
+660fae30|11223344556677885f5f5f5f 64 intel xsaveopt ptr [rax]
+660fae30|11223344556677885f5f5f5f 64 plan9 XSAVEOPT 0(AX)
+660faf11|223344556677885f5f5f5f5f 32 intel imul dx, word ptr [ecx]
+660faf11|223344556677885f5f5f5f5f 32 plan9 IMULW 0(CX), DX
+660faf11|223344556677885f5f5f5f5f 64 gnu imul (%rcx),%dx
+660faf11|223344556677885f5f5f5f5f 64 intel imul dx, word ptr [rcx]
+660faf11|223344556677885f5f5f5f5f 64 plan9 IMULW 0(CX), DX
+660fb111|223344556677885f5f5f5f5f 32 intel cmpxchg word ptr [ecx], dx
+660fb111|223344556677885f5f5f5f5f 32 plan9 CMPXCHGW DX, 0(CX)
+660fb111|223344556677885f5f5f5f5f 64 gnu cmpxchg %dx,(%rcx)
+660fb111|223344556677885f5f5f5f5f 64 intel cmpxchg word ptr [rcx], dx
+660fb111|223344556677885f5f5f5f5f 64 plan9 CMPXCHGW DX, 0(CX)
+660fb211|223344556677885f5f5f5f5f 32 intel lss dx, dword ptr [ecx]
+660fb211|223344556677885f5f5f5f5f 32 plan9 LSS 0(CX), DX
+660fb211|223344556677885f5f5f5f5f 64 gnu lss (%rcx),%dx
+660fb211|223344556677885f5f5f5f5f 64 intel lss dx, dword ptr [rcx]
+660fb211|223344556677885f5f5f5f5f 64 plan9 LSS 0(CX), DX
+660fb311|223344556677885f5f5f5f5f 32 intel btr word ptr [ecx], dx
+660fb311|223344556677885f5f5f5f5f 32 plan9 BTRW DX, 0(CX)
+660fb311|223344556677885f5f5f5f5f 64 gnu btr %dx,(%rcx)
+660fb311|223344556677885f5f5f5f5f 64 intel btr word ptr [rcx], dx
+660fb311|223344556677885f5f5f5f5f 64 plan9 BTRW DX, 0(CX)
+660fb411|223344556677885f5f5f5f5f 32 intel lfs dx, dword ptr [ecx]
+660fb411|223344556677885f5f5f5f5f 32 plan9 LFS 0(CX), DX
+660fb411|223344556677885f5f5f5f5f 64 gnu lfs (%rcx),%dx
+660fb411|223344556677885f5f5f5f5f 64 intel lfs dx, dword ptr [rcx]
+660fb411|223344556677885f5f5f5f5f 64 plan9 LFS 0(CX), DX
+660fb511|223344556677885f5f5f5f5f 32 intel lgs dx, dword ptr [ecx]
+660fb511|223344556677885f5f5f5f5f 32 plan9 LGS 0(CX), DX
+660fb511|223344556677885f5f5f5f5f 64 gnu lgs (%rcx),%dx
+660fb511|223344556677885f5f5f5f5f 64 intel lgs dx, dword ptr [rcx]
+660fb511|223344556677885f5f5f5f5f 64 plan9 LGS 0(CX), DX
+660fb611|223344556677885f5f5f5f5f 32 intel movzx dx, byte ptr [ecx]
+660fb611|223344556677885f5f5f5f5f 32 plan9 MOVZX 0(CX), DX
+660fb611|223344556677885f5f5f5f5f 64 gnu movzbw (%rcx),%dx
+660fb611|223344556677885f5f5f5f5f 64 intel movzx dx, byte ptr [rcx]
+660fb611|223344556677885f5f5f5f5f 64 plan9 MOVZX 0(CX), DX
+660fb711|223344556677885f5f5f5f5f 32 intel movzx dx, word ptr [ecx]
+660fb711|223344556677885f5f5f5f5f 32 plan9 MOVZX 0(CX), DX
+660fb711|223344556677885f5f5f5f5f 64 gnu movzww (%rcx),%dx
+660fb711|223344556677885f5f5f5f5f 64 intel movzx dx, word ptr [rcx]
+660fb711|223344556677885f5f5f5f5f 64 plan9 MOVZX 0(CX), DX
+660fba2011|223344556677885f5f5f5f 32 intel bt word ptr [eax], 0x11
+660fba2011|223344556677885f5f5f5f 32 plan9 BTW $0x11, 0(AX)
+660fba2011|223344556677885f5f5f5f 64 gnu btw $0x11,(%rax)
+660fba2011|223344556677885f5f5f5f 64 intel bt word ptr [rax], 0x11
+660fba2011|223344556677885f5f5f5f 64 plan9 BTW $0x11, 0(AX)
+660fba2811|223344556677885f5f5f5f 32 intel bts word ptr [eax], 0x11
+660fba2811|223344556677885f5f5f5f 32 plan9 BTSW $0x11, 0(AX)
+660fba2811|223344556677885f5f5f5f 64 gnu btsw $0x11,(%rax)
+660fba2811|223344556677885f5f5f5f 64 intel bts word ptr [rax], 0x11
+660fba2811|223344556677885f5f5f5f 64 plan9 BTSW $0x11, 0(AX)
+660fba3011|223344556677885f5f5f5f 32 intel btr word ptr [eax], 0x11
+660fba3011|223344556677885f5f5f5f 32 plan9 BTRW $0x11, 0(AX)
+660fba3011|223344556677885f5f5f5f 64 gnu btrw $0x11,(%rax)
+660fba3011|223344556677885f5f5f5f 64 intel btr word ptr [rax], 0x11
+660fba3011|223344556677885f5f5f5f 64 plan9 BTRW $0x11, 0(AX)
+660fba3811|223344556677885f5f5f5f 32 intel btc word ptr [eax], 0x11
+660fba3811|223344556677885f5f5f5f 32 plan9 BTCW $0x11, 0(AX)
+660fba3811|223344556677885f5f5f5f 64 gnu btcw $0x11,(%rax)
+660fba3811|223344556677885f5f5f5f 64 intel btc word ptr [rax], 0x11
+660fba3811|223344556677885f5f5f5f 64 plan9 BTCW $0x11, 0(AX)
+660fbb11|223344556677885f5f5f5f5f 32 intel btc word ptr [ecx], dx
+660fbb11|223344556677885f5f5f5f5f 32 plan9 BTCW DX, 0(CX)
+660fbb11|223344556677885f5f5f5f5f 64 gnu btc %dx,(%rcx)
+660fbb11|223344556677885f5f5f5f5f 64 intel btc word ptr [rcx], dx
+660fbb11|223344556677885f5f5f5f5f 64 plan9 BTCW DX, 0(CX)
+660fbc11|223344556677885f5f5f5f5f 32 intel bsf dx, word ptr [ecx]
+660fbc11|223344556677885f5f5f5f5f 32 plan9 BSFW 0(CX), DX
+660fbc11|223344556677885f5f5f5f5f 64 gnu bsf (%rcx),%dx
+660fbc11|223344556677885f5f5f5f5f 64 intel bsf dx, word ptr [rcx]
+660fbc11|223344556677885f5f5f5f5f 64 plan9 BSFW 0(CX), DX
+660fbd11|223344556677885f5f5f5f5f 32 intel bsr dx, word ptr [ecx]
+660fbd11|223344556677885f5f5f5f5f 32 plan9 BSRW 0(CX), DX
+660fbd11|223344556677885f5f5f5f5f 64 gnu bsr (%rcx),%dx
+660fbd11|223344556677885f5f5f5f5f 64 intel bsr dx, word ptr [rcx]
+660fbd11|223344556677885f5f5f5f5f 64 plan9 BSRW 0(CX), DX
+660fbe11|223344556677885f5f5f5f5f 32 intel movsx dx, byte ptr [ecx]
+660fbe11|223344556677885f5f5f5f5f 32 plan9 MOVSX 0(CX), DX
+660fbe11|223344556677885f5f5f5f5f 64 gnu movsbw (%rcx),%dx
+660fbe11|223344556677885f5f5f5f5f 64 intel movsx dx, byte ptr [rcx]
+660fbe11|223344556677885f5f5f5f5f 64 plan9 MOVSX 0(CX), DX
+660fbf11|223344556677885f5f5f5f5f 32 intel movsx dx, word ptr [ecx]
+660fbf11|223344556677885f5f5f5f5f 32 plan9 MOVSX 0(CX), DX
+660fbf11|223344556677885f5f5f5f5f 64 gnu movsww (%rcx),%dx
+660fbf11|223344556677885f5f5f5f5f 64 intel movsx dx, word ptr [rcx]
+660fbf11|223344556677885f5f5f5f5f 64 plan9 MOVSX 0(CX), DX
+660fc111|223344556677885f5f5f5f5f 32 intel xadd word ptr [ecx], dx
+660fc111|223344556677885f5f5f5f5f 32 plan9 XADDW DX, 0(CX)
+660fc111|223344556677885f5f5f5f5f 64 gnu xadd %dx,(%rcx)
+660fc111|223344556677885f5f5f5f5f 64 intel xadd word ptr [rcx], dx
+660fc111|223344556677885f5f5f5f5f 64 plan9 XADDW DX, 0(CX)
+660fc21122|3344556677885f5f5f5f5f 32 intel cmppd xmm2, xmmword ptr [ecx], 0x22
+660fc21122|3344556677885f5f5f5f5f 32 plan9 CMPPD $0x22, 0(CX), X2
+660fc21122|3344556677885f5f5f5f5f 64 gnu cmppd $0x22,(%rcx),%xmm2
+660fc21122|3344556677885f5f5f5f5f 64 intel cmppd xmm2, xmmword ptr [rcx], 0x22
+660fc21122|3344556677885f5f5f5f5f 64 plan9 CMPPD $0x22, 0(CX), X2
+660fc311|223344556677885f5f5f5f5f 32 intel movnti dword ptr [ecx], edx
+660fc311|223344556677885f5f5f5f5f 32 plan9 MOVNTIW DX, 0(CX)
+660fc311|223344556677885f5f5f5f5f 64 gnu movnti %edx,(%rcx)
+660fc311|223344556677885f5f5f5f5f 64 intel movnti dword ptr [rcx], edx
+660fc311|223344556677885f5f5f5f5f 64 plan9 MOVNTIW DX, 0(CX)
+660fc41122|3344556677885f5f5f5f5f 32 intel pinsrw xmm2, word ptr [ecx], 0x22
+660fc41122|3344556677885f5f5f5f5f 32 plan9 PINSRW $0x22, 0(CX), X2
+660fc41122|3344556677885f5f5f5f5f 64 gnu pinsrw $0x22,(%rcx),%xmm2
+660fc41122|3344556677885f5f5f5f5f 64 intel pinsrw xmm2, word ptr [rcx], 0x22
+660fc41122|3344556677885f5f5f5f5f 64 plan9 PINSRW $0x22, 0(CX), X2
+660fc5c011|223344556677885f5f5f5f 32 intel pextrw eax, xmm0, 0x11
+660fc5c011|223344556677885f5f5f5f 32 plan9 PEXTRW $0x11, X0, AX
+660fc5c011|223344556677885f5f5f5f 64 gnu pextrw $0x11,%xmm0,%eax
+660fc5c011|223344556677885f5f5f5f 64 intel pextrw eax, xmm0, 0x11
+660fc5c011|223344556677885f5f5f5f 64 plan9 PEXTRW $0x11, X0, AX
+660fc61122|3344556677885f5f5f5f5f 32 intel shufpd xmm2, xmmword ptr [ecx], 0x22
+660fc61122|3344556677885f5f5f5f5f 32 plan9 SHUFPD $0x22, 0(CX), X2
+660fc61122|3344556677885f5f5f5f5f 64 gnu shufpd $0x22,(%rcx),%xmm2
+660fc61122|3344556677885f5f5f5f5f 64 intel shufpd xmm2, xmmword ptr [rcx], 0x22
+660fc61122|3344556677885f5f5f5f5f 64 plan9 SHUFPD $0x22, 0(CX), X2
+660fc708|11223344556677885f5f5f5f 32 intel cmpxchg8b qword ptr [eax]
+660fc708|11223344556677885f5f5f5f 32 plan9 CMPXCHG8B 0(AX)
+660fc708|11223344556677885f5f5f5f 64 gnu data16 cmpxchg8b (%rax)
+660fc708|11223344556677885f5f5f5f 64 intel cmpxchg8b qword ptr [rax]
+660fc708|11223344556677885f5f5f5f 64 plan9 CMPXCHG8B 0(AX)
+660fc718|11223344556677885f5f5f5f 32 intel xrstors ptr [eax]
+660fc718|11223344556677885f5f5f5f 32 plan9 XRSTORS 0(AX)
+660fc718|11223344556677885f5f5f5f 64 gnu xrstors (%rax)
+660fc718|11223344556677885f5f5f5f 64 intel xrstors ptr [rax]
+660fc718|11223344556677885f5f5f5f 64 plan9 XRSTORS 0(AX)
+660fc720|11223344556677885f5f5f5f 32 intel xsavec ptr [eax]
+660fc720|11223344556677885f5f5f5f 32 plan9 XSAVEC 0(AX)
+660fc720|11223344556677885f5f5f5f 64 gnu xsavec (%rax)
+660fc720|11223344556677885f5f5f5f 64 intel xsavec ptr [rax]
+660fc720|11223344556677885f5f5f5f 64 plan9 XSAVEC 0(AX)
+660fc728|11223344556677885f5f5f5f 32 intel xsaves ptr [eax]
+660fc728|11223344556677885f5f5f5f 32 plan9 XSAVES 0(AX)
+660fc728|11223344556677885f5f5f5f 64 gnu xsaves (%rax)
+660fc728|11223344556677885f5f5f5f 64 intel xsaves ptr [rax]
+660fc728|11223344556677885f5f5f5f 64 plan9 XSAVES 0(AX)
+660fc7f2|11223344556677885f5f5f5f 32 intel rdrand dx
+660fc7f2|11223344556677885f5f5f5f 32 plan9 RDRAND DX
+660fc7f2|11223344556677885f5f5f5f 64 gnu rdrand %dx
+660fc7f2|11223344556677885f5f5f5f 64 intel rdrand dx
+660fc7f2|11223344556677885f5f5f5f 64 plan9 RDRAND DX
+660fc8|11223344556677885f5f5f5f5f 32 intel bswap ax
+660fc8|11223344556677885f5f5f5f5f 32 plan9 BSWAP AX
+660fc8|11223344556677885f5f5f5f5f 64 gnu bswap %ax
+660fc8|11223344556677885f5f5f5f5f 64 intel bswap ax
+660fc8|11223344556677885f5f5f5f5f 64 plan9 BSWAP AX
+660fd011|223344556677885f5f5f5f5f 32 intel addsubpd xmm2, xmmword ptr [ecx]
+660fd011|223344556677885f5f5f5f5f 32 plan9 ADDSUBPD 0(CX), X2
+660fd011|223344556677885f5f5f5f5f 64 gnu addsubpd (%rcx),%xmm2
+660fd011|223344556677885f5f5f5f5f 64 intel addsubpd xmm2, xmmword ptr [rcx]
+660fd011|223344556677885f5f5f5f5f 64 plan9 ADDSUBPD 0(CX), X2
+660fd111|223344556677885f5f5f5f5f 32 intel psrlw xmm2, xmmword ptr [ecx]
+660fd111|223344556677885f5f5f5f5f 32 plan9 PSRLW 0(CX), X2
+660fd111|223344556677885f5f5f5f5f 64 gnu psrlw (%rcx),%xmm2
+660fd111|223344556677885f5f5f5f5f 64 intel psrlw xmm2, xmmword ptr [rcx]
+660fd111|223344556677885f5f5f5f5f 64 plan9 PSRLW 0(CX), X2
+660fd211|223344556677885f5f5f5f5f 32 intel psrld xmm2, xmmword ptr [ecx]
+660fd211|223344556677885f5f5f5f5f 32 plan9 PSRLD 0(CX), X2
+660fd211|223344556677885f5f5f5f5f 64 gnu psrld (%rcx),%xmm2
+660fd211|223344556677885f5f5f5f5f 64 intel psrld xmm2, xmmword ptr [rcx]
+660fd211|223344556677885f5f5f5f5f 64 plan9 PSRLD 0(CX), X2
+660fd311|223344556677885f5f5f5f5f 32 intel psrlq xmm2, xmmword ptr [ecx]
+660fd311|223344556677885f5f5f5f5f 32 plan9 PSRLQ 0(CX), X2
+660fd311|223344556677885f5f5f5f5f 64 gnu psrlq (%rcx),%xmm2
+660fd311|223344556677885f5f5f5f5f 64 intel psrlq xmm2, xmmword ptr [rcx]
+660fd311|223344556677885f5f5f5f5f 64 plan9 PSRLQ 0(CX), X2
+660fd411|223344556677885f5f5f5f5f 32 intel paddq xmm2, xmmword ptr [ecx]
+660fd411|223344556677885f5f5f5f5f 32 plan9 PADDQ 0(CX), X2
+660fd411|223344556677885f5f5f5f5f 64 gnu paddq (%rcx),%xmm2
+660fd411|223344556677885f5f5f5f5f 64 intel paddq xmm2, xmmword ptr [rcx]
+660fd411|223344556677885f5f5f5f5f 64 plan9 PADDQ 0(CX), X2
+660fd511|223344556677885f5f5f5f5f 32 intel pmullw xmm2, xmmword ptr [ecx]
+660fd511|223344556677885f5f5f5f5f 32 plan9 PMULLW 0(CX), X2
+660fd511|223344556677885f5f5f5f5f 64 gnu pmullw (%rcx),%xmm2
+660fd511|223344556677885f5f5f5f5f 64 intel pmullw xmm2, xmmword ptr [rcx]
+660fd511|223344556677885f5f5f5f5f 64 plan9 PMULLW 0(CX), X2
+660fd611|223344556677885f5f5f5f5f 32 intel movq qword ptr [ecx], xmm2
+660fd611|223344556677885f5f5f5f5f 32 plan9 MOVQ X2, 0(CX)
+660fd611|223344556677885f5f5f5f5f 64 gnu movq %xmm2,(%rcx)
+660fd611|223344556677885f5f5f5f5f 64 intel movq qword ptr [rcx], xmm2
+660fd611|223344556677885f5f5f5f5f 64 plan9 MOVQ X2, 0(CX)
+660fd7c0|11223344556677885f5f5f5f 32 intel pmovmskb eax, xmm0
+660fd7c0|11223344556677885f5f5f5f 32 plan9 PMOVMSKB X0, AX
+660fd7c0|11223344556677885f5f5f5f 64 gnu pmovmskb %xmm0,%eax
+660fd7c0|11223344556677885f5f5f5f 64 intel pmovmskb eax, xmm0
+660fd7c0|11223344556677885f5f5f5f 64 plan9 PMOVMSKB X0, AX
+660fd811|223344556677885f5f5f5f5f 32 intel psubusb xmm2, xmmword ptr [ecx]
+660fd811|223344556677885f5f5f5f5f 32 plan9 PSUBUSB 0(CX), X2
+660fd811|223344556677885f5f5f5f5f 64 gnu psubusb (%rcx),%xmm2
+660fd811|223344556677885f5f5f5f5f 64 intel psubusb xmm2, xmmword ptr [rcx]
+660fd811|223344556677885f5f5f5f5f 64 plan9 PSUBUSB 0(CX), X2
+660fd911|223344556677885f5f5f5f5f 32 intel psubusw xmm2, xmmword ptr [ecx]
+660fd911|223344556677885f5f5f5f5f 32 plan9 PSUBUSW 0(CX), X2
+660fd911|223344556677885f5f5f5f5f 64 gnu psubusw (%rcx),%xmm2
+660fd911|223344556677885f5f5f5f5f 64 intel psubusw xmm2, xmmword ptr [rcx]
+660fd911|223344556677885f5f5f5f5f 64 plan9 PSUBUSW 0(CX), X2
+660fda11|223344556677885f5f5f5f5f 32 intel pminub xmm2, xmmword ptr [ecx]
+660fda11|223344556677885f5f5f5f5f 32 plan9 PMINUB 0(CX), X2
+660fda11|223344556677885f5f5f5f5f 64 gnu pminub (%rcx),%xmm2
+660fda11|223344556677885f5f5f5f5f 64 intel pminub xmm2, xmmword ptr [rcx]
+660fda11|223344556677885f5f5f5f5f 64 plan9 PMINUB 0(CX), X2
+660fdb11|223344556677885f5f5f5f5f 32 intel pand xmm2, xmmword ptr [ecx]
+660fdb11|223344556677885f5f5f5f5f 32 plan9 PAND 0(CX), X2
+660fdb11|223344556677885f5f5f5f5f 64 gnu pand (%rcx),%xmm2
+660fdb11|223344556677885f5f5f5f5f 64 intel pand xmm2, xmmword ptr [rcx]
+660fdb11|223344556677885f5f5f5f5f 64 plan9 PAND 0(CX), X2
+660fdc11|223344556677885f5f5f5f5f 32 intel paddusb xmm2, xmmword ptr [ecx]
+660fdc11|223344556677885f5f5f5f5f 32 plan9 PADDUSB 0(CX), X2
+660fdc11|223344556677885f5f5f5f5f 64 gnu paddusb (%rcx),%xmm2
+660fdc11|223344556677885f5f5f5f5f 64 intel paddusb xmm2, xmmword ptr [rcx]
+660fdc11|223344556677885f5f5f5f5f 64 plan9 PADDUSB 0(CX), X2
+660fdd11|223344556677885f5f5f5f5f 32 intel paddusw xmm2, xmmword ptr [ecx]
+660fdd11|223344556677885f5f5f5f5f 32 plan9 PADDUSW 0(CX), X2
+660fdd11|223344556677885f5f5f5f5f 64 gnu paddusw (%rcx),%xmm2
+660fdd11|223344556677885f5f5f5f5f 64 intel paddusw xmm2, xmmword ptr [rcx]
+660fdd11|223344556677885f5f5f5f5f 64 plan9 PADDUSW 0(CX), X2
+660fde11|223344556677885f5f5f5f5f 32 intel pmaxub xmm2, xmmword ptr [ecx]
+660fde11|223344556677885f5f5f5f5f 32 plan9 PMAXUB 0(CX), X2
+660fde11|223344556677885f5f5f5f5f 64 gnu pmaxub (%rcx),%xmm2
+660fde11|223344556677885f5f5f5f5f 64 intel pmaxub xmm2, xmmword ptr [rcx]
+660fde11|223344556677885f5f5f5f5f 64 plan9 PMAXUB 0(CX), X2
+660fdf11|223344556677885f5f5f5f5f 32 intel pandn xmm2, xmmword ptr [ecx]
+660fdf11|223344556677885f5f5f5f5f 32 plan9 PANDN 0(CX), X2
+660fdf11|223344556677885f5f5f5f5f 64 gnu pandn (%rcx),%xmm2
+660fdf11|223344556677885f5f5f5f5f 64 intel pandn xmm2, xmmword ptr [rcx]
+660fdf11|223344556677885f5f5f5f5f 64 plan9 PANDN 0(CX), X2
+660fe011|223344556677885f5f5f5f5f 32 intel pavgb xmm2, xmmword ptr [ecx]
+660fe011|223344556677885f5f5f5f5f 32 plan9 PAVGB 0(CX), X2
+660fe011|223344556677885f5f5f5f5f 64 gnu pavgb (%rcx),%xmm2
+660fe011|223344556677885f5f5f5f5f 64 intel pavgb xmm2, xmmword ptr [rcx]
+660fe011|223344556677885f5f5f5f5f 64 plan9 PAVGB 0(CX), X2
+660fe111|223344556677885f5f5f5f5f 32 intel psraw xmm2, xmmword ptr [ecx]
+660fe111|223344556677885f5f5f5f5f 32 plan9 PSRAW 0(CX), X2
+660fe111|223344556677885f5f5f5f5f 64 gnu psraw (%rcx),%xmm2
+660fe111|223344556677885f5f5f5f5f 64 intel psraw xmm2, xmmword ptr [rcx]
+660fe111|223344556677885f5f5f5f5f 64 plan9 PSRAW 0(CX), X2
+660fe211|223344556677885f5f5f5f5f 32 intel psrad xmm2, xmmword ptr [ecx]
+660fe211|223344556677885f5f5f5f5f 32 plan9 PSRAD 0(CX), X2
+660fe211|223344556677885f5f5f5f5f 64 gnu psrad (%rcx),%xmm2
+660fe211|223344556677885f5f5f5f5f 64 intel psrad xmm2, xmmword ptr [rcx]
+660fe211|223344556677885f5f5f5f5f 64 plan9 PSRAD 0(CX), X2
+660fe311|223344556677885f5f5f5f5f 32 intel pavgw xmm2, xmmword ptr [ecx]
+660fe311|223344556677885f5f5f5f5f 32 plan9 PAVGW 0(CX), X2
+660fe311|223344556677885f5f5f5f5f 64 gnu pavgw (%rcx),%xmm2
+660fe311|223344556677885f5f5f5f5f 64 intel pavgw xmm2, xmmword ptr [rcx]
+660fe311|223344556677885f5f5f5f5f 64 plan9 PAVGW 0(CX), X2
+660fe411|223344556677885f5f5f5f5f 32 intel pmulhuw xmm2, xmmword ptr [ecx]
+660fe411|223344556677885f5f5f5f5f 32 plan9 PMULHUW 0(CX), X2
+660fe411|223344556677885f5f5f5f5f 64 gnu pmulhuw (%rcx),%xmm2
+660fe411|223344556677885f5f5f5f5f 64 intel pmulhuw xmm2, xmmword ptr [rcx]
+660fe411|223344556677885f5f5f5f5f 64 plan9 PMULHUW 0(CX), X2
+660fe511|223344556677885f5f5f5f5f 32 intel pmulhw xmm2, xmmword ptr [ecx]
+660fe511|223344556677885f5f5f5f5f 32 plan9 PMULHW 0(CX), X2
+660fe511|223344556677885f5f5f5f5f 64 gnu pmulhw (%rcx),%xmm2
+660fe511|223344556677885f5f5f5f5f 64 intel pmulhw xmm2, xmmword ptr [rcx]
+660fe511|223344556677885f5f5f5f5f 64 plan9 PMULHW 0(CX), X2
+660fe611|223344556677885f5f5f5f5f 32 intel cvttpd2dq xmm2, xmmword ptr [ecx]
+660fe611|223344556677885f5f5f5f5f 32 plan9 CVTTPD2DQ 0(CX), X2
+660fe611|223344556677885f5f5f5f5f 64 gnu cvttpd2dq (%rcx),%xmm2
+660fe611|223344556677885f5f5f5f5f 64 intel cvttpd2dq xmm2, xmmword ptr [rcx]
+660fe611|223344556677885f5f5f5f5f 64 plan9 CVTTPD2DQ 0(CX), X2
+660fe711|223344556677885f5f5f5f5f 32 intel movntdq xmmword ptr [ecx], xmm2
+660fe711|223344556677885f5f5f5f5f 32 plan9 MOVNTDQ X2, 0(CX)
+660fe711|223344556677885f5f5f5f5f 64 gnu movntdq %xmm2,(%rcx)
+660fe711|223344556677885f5f5f5f5f 64 intel movntdq xmmword ptr [rcx], xmm2
+660fe711|223344556677885f5f5f5f5f 64 plan9 MOVNTDQ X2, 0(CX)
+660fe811|223344556677885f5f5f5f5f 32 intel psubsb xmm2, xmmword ptr [ecx]
+660fe811|223344556677885f5f5f5f5f 32 plan9 PSUBSB 0(CX), X2
+660fe811|223344556677885f5f5f5f5f 64 gnu psubsb (%rcx),%xmm2
+660fe811|223344556677885f5f5f5f5f 64 intel psubsb xmm2, xmmword ptr [rcx]
+660fe811|223344556677885f5f5f5f5f 64 plan9 PSUBSB 0(CX), X2
+660fe911|223344556677885f5f5f5f5f 32 intel psubsw xmm2, xmmword ptr [ecx]
+660fe911|223344556677885f5f5f5f5f 32 plan9 PSUBSW 0(CX), X2
+660fe911|223344556677885f5f5f5f5f 64 gnu psubsw (%rcx),%xmm2
+660fe911|223344556677885f5f5f5f5f 64 intel psubsw xmm2, xmmword ptr [rcx]
+660fe911|223344556677885f5f5f5f5f 64 plan9 PSUBSW 0(CX), X2
+660fea11|223344556677885f5f5f5f5f 32 intel pminsw xmm2, xmmword ptr [ecx]
+660fea11|223344556677885f5f5f5f5f 32 plan9 PMINSW 0(CX), X2
+660fea11|223344556677885f5f5f5f5f 64 gnu pminsw (%rcx),%xmm2
+660fea11|223344556677885f5f5f5f5f 64 intel pminsw xmm2, xmmword ptr [rcx]
+660fea11|223344556677885f5f5f5f5f 64 plan9 PMINSW 0(CX), X2
+660feb11|223344556677885f5f5f5f5f 32 intel por xmm2, xmmword ptr [ecx]
+660feb11|223344556677885f5f5f5f5f 32 plan9 POR 0(CX), X2
+660feb11|223344556677885f5f5f5f5f 64 gnu por (%rcx),%xmm2
+660feb11|223344556677885f5f5f5f5f 64 intel por xmm2, xmmword ptr [rcx]
+660feb11|223344556677885f5f5f5f5f 64 plan9 POR 0(CX), X2
+660fec11|223344556677885f5f5f5f5f 32 intel paddsb xmm2, xmmword ptr [ecx]
+660fec11|223344556677885f5f5f5f5f 32 plan9 PADDSB 0(CX), X2
+660fec11|223344556677885f5f5f5f5f 64 gnu paddsb (%rcx),%xmm2
+660fec11|223344556677885f5f5f5f5f 64 intel paddsb xmm2, xmmword ptr [rcx]
+660fec11|223344556677885f5f5f5f5f 64 plan9 PADDSB 0(CX), X2
+660fed11|223344556677885f5f5f5f5f 32 intel paddsw xmm2, xmmword ptr [ecx]
+660fed11|223344556677885f5f5f5f5f 32 plan9 PADDSW 0(CX), X2
+660fed11|223344556677885f5f5f5f5f 64 gnu paddsw (%rcx),%xmm2
+660fed11|223344556677885f5f5f5f5f 64 intel paddsw xmm2, xmmword ptr [rcx]
+660fed11|223344556677885f5f5f5f5f 64 plan9 PADDSW 0(CX), X2
+660fee11|223344556677885f5f5f5f5f 32 intel pmaxsw xmm2, xmmword ptr [ecx]
+660fee11|223344556677885f5f5f5f5f 32 plan9 PMAXSW 0(CX), X2
+660fee11|223344556677885f5f5f5f5f 64 gnu pmaxsw (%rcx),%xmm2
+660fee11|223344556677885f5f5f5f5f 64 intel pmaxsw xmm2, xmmword ptr [rcx]
+660fee11|223344556677885f5f5f5f5f 64 plan9 PMAXSW 0(CX), X2
+660fef11|223344556677885f5f5f5f5f 32 intel pxor xmm2, xmmword ptr [ecx]
+660fef11|223344556677885f5f5f5f5f 32 plan9 PXOR 0(CX), X2
+660fef11|223344556677885f5f5f5f5f 64 gnu pxor (%rcx),%xmm2
+660fef11|223344556677885f5f5f5f5f 64 intel pxor xmm2, xmmword ptr [rcx]
+660fef11|223344556677885f5f5f5f5f 64 plan9 PXOR 0(CX), X2
+660ff111|223344556677885f5f5f5f5f 32 intel psllw xmm2, xmmword ptr [ecx]
+660ff111|223344556677885f5f5f5f5f 32 plan9 PSLLW 0(CX), X2
+660ff111|223344556677885f5f5f5f5f 64 gnu psllw (%rcx),%xmm2
+660ff111|223344556677885f5f5f5f5f 64 intel psllw xmm2, xmmword ptr [rcx]
+660ff111|223344556677885f5f5f5f5f 64 plan9 PSLLW 0(CX), X2
+660ff211|223344556677885f5f5f5f5f 32 intel pslld xmm2, xmmword ptr [ecx]
+660ff211|223344556677885f5f5f5f5f 32 plan9 PSLLD 0(CX), X2
+660ff211|223344556677885f5f5f5f5f 64 gnu pslld (%rcx),%xmm2
+660ff211|223344556677885f5f5f5f5f 64 intel pslld xmm2, xmmword ptr [rcx]
+660ff211|223344556677885f5f5f5f5f 64 plan9 PSLLD 0(CX), X2
+660ff311|223344556677885f5f5f5f5f 32 intel psllq xmm2, xmmword ptr [ecx]
+660ff311|223344556677885f5f5f5f5f 32 plan9 PSLLQ 0(CX), X2
+660ff311|223344556677885f5f5f5f5f 64 gnu psllq (%rcx),%xmm2
+660ff311|223344556677885f5f5f5f5f 64 intel psllq xmm2, xmmword ptr [rcx]
+660ff311|223344556677885f5f5f5f5f 64 plan9 PSLLQ 0(CX), X2
+660ff411|223344556677885f5f5f5f5f 32 intel pmuludq xmm2, xmmword ptr [ecx]
+660ff411|223344556677885f5f5f5f5f 32 plan9 PMULUDQ 0(CX), X2
+660ff411|223344556677885f5f5f5f5f 64 gnu pmuludq (%rcx),%xmm2
+660ff411|223344556677885f5f5f5f5f 64 intel pmuludq xmm2, xmmword ptr [rcx]
+660ff411|223344556677885f5f5f5f5f 64 plan9 PMULUDQ 0(CX), X2
+660ff511|223344556677885f5f5f5f5f 32 intel pmaddwd xmm2, xmmword ptr [ecx]
+660ff511|223344556677885f5f5f5f5f 32 plan9 PMADDWD 0(CX), X2
+660ff511|223344556677885f5f5f5f5f 64 gnu pmaddwd (%rcx),%xmm2
+660ff511|223344556677885f5f5f5f5f 64 intel pmaddwd xmm2, xmmword ptr [rcx]
+660ff511|223344556677885f5f5f5f5f 64 plan9 PMADDWD 0(CX), X2
+660ff611|223344556677885f5f5f5f5f 32 intel psadbw xmm2, xmmword ptr [ecx]
+660ff611|223344556677885f5f5f5f5f 32 plan9 PSADBW 0(CX), X2
+660ff611|223344556677885f5f5f5f5f 64 gnu psadbw (%rcx),%xmm2
+660ff611|223344556677885f5f5f5f5f 64 intel psadbw xmm2, xmmword ptr [rcx]
+660ff611|223344556677885f5f5f5f5f 64 plan9 PSADBW 0(CX), X2
+660ff7c0|11223344556677885f5f5f5f 32 intel maskmovdqu xmm0, xmm0
+660ff7c0|11223344556677885f5f5f5f 32 plan9 MASKMOVDQU X0, X0
+660ff7c0|11223344556677885f5f5f5f 64 intel maskmovdqu xmm0, xmm0
+660ff7c0|11223344556677885f5f5f5f 64 plan9 MASKMOVDQU X0, X0
+660ff811|223344556677885f5f5f5f5f 32 intel psubb xmm2, xmmword ptr [ecx]
+660ff811|223344556677885f5f5f5f5f 32 plan9 PSUBB 0(CX), X2
+660ff811|223344556677885f5f5f5f5f 64 gnu psubb (%rcx),%xmm2
+660ff811|223344556677885f5f5f5f5f 64 intel psubb xmm2, xmmword ptr [rcx]
+660ff811|223344556677885f5f5f5f5f 64 plan9 PSUBB 0(CX), X2
+660ff911|223344556677885f5f5f5f5f 32 intel psubw xmm2, xmmword ptr [ecx]
+660ff911|223344556677885f5f5f5f5f 32 plan9 PSUBW 0(CX), X2
+660ff911|223344556677885f5f5f5f5f 64 gnu psubw (%rcx),%xmm2
+660ff911|223344556677885f5f5f5f5f 64 intel psubw xmm2, xmmword ptr [rcx]
+660ff911|223344556677885f5f5f5f5f 64 plan9 PSUBW 0(CX), X2
+660ffa11|223344556677885f5f5f5f5f 32 intel psubd xmm2, xmmword ptr [ecx]
+660ffa11|223344556677885f5f5f5f5f 32 plan9 PSUBD 0(CX), X2
+660ffa11|223344556677885f5f5f5f5f 64 gnu psubd (%rcx),%xmm2
+660ffa11|223344556677885f5f5f5f5f 64 intel psubd xmm2, xmmword ptr [rcx]
+660ffa11|223344556677885f5f5f5f5f 64 plan9 PSUBD 0(CX), X2
+660ffb11|223344556677885f5f5f5f5f 32 intel psubq xmm2, xmmword ptr [ecx]
+660ffb11|223344556677885f5f5f5f5f 32 plan9 PSUBQ 0(CX), X2
+660ffb11|223344556677885f5f5f5f5f 64 gnu psubq (%rcx),%xmm2
+660ffb11|223344556677885f5f5f5f5f 64 intel psubq xmm2, xmmword ptr [rcx]
+660ffb11|223344556677885f5f5f5f5f 64 plan9 PSUBQ 0(CX), X2
+660ffc11|223344556677885f5f5f5f5f 32 intel paddb xmm2, xmmword ptr [ecx]
+660ffc11|223344556677885f5f5f5f5f 32 plan9 PADDB 0(CX), X2
+660ffc11|223344556677885f5f5f5f5f 64 gnu paddb (%rcx),%xmm2
+660ffc11|223344556677885f5f5f5f5f 64 intel paddb xmm2, xmmword ptr [rcx]
+660ffc11|223344556677885f5f5f5f5f 64 plan9 PADDB 0(CX), X2
+660ffd11|223344556677885f5f5f5f5f 32 intel paddw xmm2, xmmword ptr [ecx]
+660ffd11|223344556677885f5f5f5f5f 32 plan9 PADDW 0(CX), X2
+660ffd11|223344556677885f5f5f5f5f 64 gnu paddw (%rcx),%xmm2
+660ffd11|223344556677885f5f5f5f5f 64 intel paddw xmm2, xmmword ptr [rcx]
+660ffd11|223344556677885f5f5f5f5f 64 plan9 PADDW 0(CX), X2
+660ffe11|223344556677885f5f5f5f5f 32 intel paddd xmm2, xmmword ptr [ecx]
+660ffe11|223344556677885f5f5f5f5f 32 plan9 PADDD 0(CX), X2
+660ffe11|223344556677885f5f5f5f5f 64 gnu paddd (%rcx),%xmm2
+660ffe11|223344556677885f5f5f5f5f 64 intel paddd xmm2, xmmword ptr [rcx]
+660ffe11|223344556677885f5f5f5f5f 64 plan9 PADDD 0(CX), X2
+661122|3344556677885f5f5f5f5f5f5f 32 intel adc word ptr [edx], sp
+661122|3344556677885f5f5f5f5f5f5f 32 plan9 ADCW SP, 0(DX)
+661122|3344556677885f5f5f5f5f5f5f 64 gnu adc %sp,(%rdx)
+661122|3344556677885f5f5f5f5f5f5f 64 intel adc word ptr [rdx], sp
+661122|3344556677885f5f5f5f5f5f5f 64 plan9 ADCW SP, 0(DX)
+661311|223344556677885f5f5f5f5f5f 32 intel adc dx, word ptr [ecx]
+661311|223344556677885f5f5f5f5f5f 32 plan9 ADCW 0(CX), DX
+661311|223344556677885f5f5f5f5f5f 64 gnu adc (%rcx),%dx
+661311|223344556677885f5f5f5f5f5f 64 intel adc dx, word ptr [rcx]
+661311|223344556677885f5f5f5f5f5f 64 plan9 ADCW 0(CX), DX
+66151122|3344556677885f5f5f5f5f5f 32 intel adc ax, 0x2211
+66151122|3344556677885f5f5f5f5f5f 32 plan9 ADCW $0x2211, AX
+66151122|3344556677885f5f5f5f5f5f 64 gnu adc $0x2211,%ax
+66151122|3344556677885f5f5f5f5f5f 64 intel adc ax, 0x2211
+66151122|3344556677885f5f5f5f5f5f 64 plan9 ADCW $0x2211, AX
+661911|223344556677885f5f5f5f5f5f 32 intel sbb word ptr [ecx], dx
+661911|223344556677885f5f5f5f5f5f 32 plan9 SBBW DX, 0(CX)
+661911|223344556677885f5f5f5f5f5f 64 gnu sbb %dx,(%rcx)
+661911|223344556677885f5f5f5f5f5f 64 intel sbb word ptr [rcx], dx
+661911|223344556677885f5f5f5f5f5f 64 plan9 SBBW DX, 0(CX)
+661b11|223344556677885f5f5f5f5f5f 32 intel sbb dx, word ptr [ecx]
+661b11|223344556677885f5f5f5f5f5f 32 plan9 SBBW 0(CX), DX
+661b11|223344556677885f5f5f5f5f5f 64 gnu sbb (%rcx),%dx
+661b11|223344556677885f5f5f5f5f5f 64 intel sbb dx, word ptr [rcx]
+661b11|223344556677885f5f5f5f5f5f 64 plan9 SBBW 0(CX), DX
+661d1122|3344556677885f5f5f5f5f5f 32 intel sbb ax, 0x2211
+661d1122|3344556677885f5f5f5f5f5f 32 plan9 SBBW $0x2211, AX
+661d1122|3344556677885f5f5f5f5f5f 64 gnu sbb $0x2211,%ax
+661d1122|3344556677885f5f5f5f5f5f 64 intel sbb ax, 0x2211
+661d1122|3344556677885f5f5f5f5f5f 64 plan9 SBBW $0x2211, AX
+662111|223344556677885f5f5f5f5f5f 32 intel and word ptr [ecx], dx
+662111|223344556677885f5f5f5f5f5f 32 plan9 ANDW DX, 0(CX)
+662111|223344556677885f5f5f5f5f5f 64 gnu and %dx,(%rcx)
+662111|223344556677885f5f5f5f5f5f 64 intel and word ptr [rcx], dx
+662111|223344556677885f5f5f5f5f5f 64 plan9 ANDW DX, 0(CX)
+662311|223344556677885f5f5f5f5f5f 32 intel and dx, word ptr [ecx]
+662311|223344556677885f5f5f5f5f5f 32 plan9 ANDW 0(CX), DX
+662311|223344556677885f5f5f5f5f5f 64 gnu and (%rcx),%dx
+662311|223344556677885f5f5f5f5f5f 64 intel and dx, word ptr [rcx]
+662311|223344556677885f5f5f5f5f5f 64 plan9 ANDW 0(CX), DX
+66251122|3344556677885f5f5f5f5f5f 32 intel and ax, 0x2211
+66251122|3344556677885f5f5f5f5f5f 32 plan9 ANDW $0x2211, AX
+66251122|3344556677885f5f5f5f5f5f 64 gnu and $0x2211,%ax
+66251122|3344556677885f5f5f5f5f5f 64 intel and ax, 0x2211
+66251122|3344556677885f5f5f5f5f5f 64 plan9 ANDW $0x2211, AX
+662911|223344556677885f5f5f5f5f5f 32 intel sub word ptr [ecx], dx
+662911|223344556677885f5f5f5f5f5f 32 plan9 SUBW DX, 0(CX)
+662911|223344556677885f5f5f5f5f5f 64 gnu sub %dx,(%rcx)
+662911|223344556677885f5f5f5f5f5f 64 intel sub word ptr [rcx], dx
+662911|223344556677885f5f5f5f5f5f 64 plan9 SUBW DX, 0(CX)
+662b11|223344556677885f5f5f5f5f5f 32 intel sub dx, word ptr [ecx]
+662b11|223344556677885f5f5f5f5f5f 32 plan9 SUBW 0(CX), DX
+662b11|223344556677885f5f5f5f5f5f 64 gnu sub (%rcx),%dx
+662b11|223344556677885f5f5f5f5f5f 64 intel sub dx, word ptr [rcx]
+662b11|223344556677885f5f5f5f5f5f 64 plan9 SUBW 0(CX), DX
+662d1122|3344556677885f5f5f5f5f5f 32 intel sub ax, 0x2211
+662d1122|3344556677885f5f5f5f5f5f 32 plan9 SUBW $0x2211, AX
+662d1122|3344556677885f5f5f5f5f5f 64 gnu sub $0x2211,%ax
+662d1122|3344556677885f5f5f5f5f5f 64 intel sub ax, 0x2211
+662d1122|3344556677885f5f5f5f5f5f 64 plan9 SUBW $0x2211, AX
+663111|223344556677885f5f5f5f5f5f 32 intel xor word ptr [ecx], dx
+663111|223344556677885f5f5f5f5f5f 32 plan9 XORW DX, 0(CX)
+663111|223344556677885f5f5f5f5f5f 64 gnu xor %dx,(%rcx)
+663111|223344556677885f5f5f5f5f5f 64 intel xor word ptr [rcx], dx
+663111|223344556677885f5f5f5f5f5f 64 plan9 XORW DX, 0(CX)
+663311|223344556677885f5f5f5f5f5f 32 intel xor dx, word ptr [ecx]
+663311|223344556677885f5f5f5f5f5f 32 plan9 XORW 0(CX), DX
+663311|223344556677885f5f5f5f5f5f 64 gnu xor (%rcx),%dx
+663311|223344556677885f5f5f5f5f5f 64 intel xor dx, word ptr [rcx]
+663311|223344556677885f5f5f5f5f5f 64 plan9 XORW 0(CX), DX
+66351122|3344556677885f5f5f5f5f5f 32 intel xor ax, 0x2211
+66351122|3344556677885f5f5f5f5f5f 32 plan9 XORW $0x2211, AX
+66351122|3344556677885f5f5f5f5f5f 64 gnu xor $0x2211,%ax
+66351122|3344556677885f5f5f5f5f5f 64 intel xor ax, 0x2211
+66351122|3344556677885f5f5f5f5f5f 64 plan9 XORW $0x2211, AX
+663911|223344556677885f5f5f5f5f5f 32 intel cmp word ptr [ecx], dx
+663911|223344556677885f5f5f5f5f5f 32 plan9 CMPW DX, 0(CX)
+663911|223344556677885f5f5f5f5f5f 64 gnu cmp %dx,(%rcx)
+663911|223344556677885f5f5f5f5f5f 64 intel cmp word ptr [rcx], dx
+663911|223344556677885f5f5f5f5f5f 64 plan9 CMPW DX, 0(CX)
+663b11|223344556677885f5f5f5f5f5f 32 intel cmp dx, word ptr [ecx]
+663b11|223344556677885f5f5f5f5f5f 32 plan9 CMPW 0(CX), DX
+663b11|223344556677885f5f5f5f5f5f 64 gnu cmp (%rcx),%dx
+663b11|223344556677885f5f5f5f5f5f 64 intel cmp dx, word ptr [rcx]
+663b11|223344556677885f5f5f5f5f5f 64 plan9 CMPW 0(CX), DX
+663d1122|3344556677885f5f5f5f5f5f 32 intel cmp ax, 0x2211
+663d1122|3344556677885f5f5f5f5f5f 32 plan9 CMPW $0x2211, AX
+663d1122|3344556677885f5f5f5f5f5f 64 gnu cmp $0x2211,%ax
+663d1122|3344556677885f5f5f5f5f5f 64 intel cmp ax, 0x2211
+663d1122|3344556677885f5f5f5f5f5f 64 plan9 CMPW $0x2211, AX
+6640|11223344556677885f5f5f5f5f5f 32 intel inc ax
+6640|11223344556677885f5f5f5f5f5f 32 plan9 INCW AX
+66480f3a161122|3344556677885f5f5f 64 gnu pextrq $0x22,%xmm2,(%rcx)
+66480f3a161122|3344556677885f5f5f 64 intel pextrq qword ptr [rcx], xmm2, 0x22
+66480f3a161122|3344556677885f5f5f 64 plan9 PEXTRQ $0x22, X2, 0(CX)
+66480f3a221122|3344556677885f5f5f 64 gnu pinsrq $0x22,(%rcx),%xmm2
+66480f3a221122|3344556677885f5f5f 64 intel pinsrq xmm2, qword ptr [rcx], 0x22
+66480f3a221122|3344556677885f5f5f 64 plan9 PINSRQ $0x22, 0(CX), X2
+66480f6e11|223344556677885f5f5f5f 64 gnu movq (%rcx),%xmm2
+66480f6e11|223344556677885f5f5f5f 64 intel movq xmm2, qword ptr [rcx]
+66480f6e11|223344556677885f5f5f5f 64 plan9 MOVQ 0(CX), X2
+66480f7e11|223344556677885f5f5f5f 64 gnu movq %xmm2,(%rcx)
+66480f7e11|223344556677885f5f5f5f 64 intel movq qword ptr [rcx], xmm2
+66480f7e11|223344556677885f5f5f5f 64 plan9 MOVQ X2, 0(CX)
+6648|0f3a1611223344556677885f5f5f 32 intel dec ax
+6648|0f3a1611223344556677885f5f5f 32 plan9 DECW AX
+6650|11223344556677885f5f5f5f5f5f 32 intel push ax
+6650|11223344556677885f5f5f5f5f5f 32 plan9 PUSHW AX
+6650|11223344556677885f5f5f5f5f5f 64 gnu push %ax
+6650|11223344556677885f5f5f5f5f5f 64 intel push ax
+6650|11223344556677885f5f5f5f5f5f 64 plan9 PUSHW AX
+6658|11223344556677885f5f5f5f5f5f 32 intel pop ax
+6658|11223344556677885f5f5f5f5f5f 32 plan9 POPW AX
+6658|11223344556677885f5f5f5f5f5f 64 gnu pop %ax
+6658|11223344556677885f5f5f5f5f5f 64 intel pop ax
+6658|11223344556677885f5f5f5f5f5f 64 plan9 POPW AX
+6660|11223344556677885f5f5f5f5f5f 32 intel data16 pusha
+6660|11223344556677885f5f5f5f5f5f 32 plan9 PUSHAW
+6661|11223344556677885f5f5f5f5f5f 32 intel data16 popa
+6661|11223344556677885f5f5f5f5f5f 32 plan9 POPAW
+666211|223344556677885f5f5f5f5f5f 32 intel bound dx, qword ptr [ecx]
+666211|223344556677885f5f5f5f5f5f 32 plan9 BOUND 0(CX), DX
+666311|223344556677885f5f5f5f5f5f 64 gnu movsxd (%rcx),%dx
+666311|223344556677885f5f5f5f5f5f 64 intel movsxd dx, dword ptr [rcx]
+666311|223344556677885f5f5f5f5f5f 64 plan9 MOVSXD 0(CX), DX
+66681122|3344556677885f5f5f5f5f5f 32 intel push 0x2211
+66681122|3344556677885f5f5f5f5f5f 32 plan9 PUSHW $0x2211
+66681122|3344556677885f5f5f5f5f5f 64 gnu pushw $0x2211
+66681122|3344556677885f5f5f5f5f5f 64 intel push 0x2211
+66681122|3344556677885f5f5f5f5f5f 64 plan9 PUSHW $0x2211
+6669112233|44556677885f5f5f5f5f5f 32 intel imul dx, word ptr [ecx], 0x3322
+6669112233|44556677885f5f5f5f5f5f 32 plan9 IMULW $0x3322, 0(CX), DX
+6669112233|44556677885f5f5f5f5f5f 64 gnu imul $0x3322,(%rcx),%dx
+6669112233|44556677885f5f5f5f5f5f 64 intel imul dx, word ptr [rcx], 0x3322
+6669112233|44556677885f5f5f5f5f5f 64 plan9 IMULW $0x3322, 0(CX), DX
+666b1122|3344556677885f5f5f5f5f5f 32 intel imul dx, word ptr [ecx], 0x22
+666b1122|3344556677885f5f5f5f5f5f 32 plan9 IMULW $0x22, 0(CX), DX
+666b1122|3344556677885f5f5f5f5f5f 64 gnu imul $0x22,(%rcx),%dx
+666b1122|3344556677885f5f5f5f5f5f 64 intel imul dx, word ptr [rcx], 0x22
+666b1122|3344556677885f5f5f5f5f5f 64 plan9 IMULW $0x22, 0(CX), DX
+666d|11223344556677885f5f5f5f5f5f 32 intel data16 insw
+666d|11223344556677885f5f5f5f5f5f 32 plan9 INSW DX, ES:0(DI)
+666d|11223344556677885f5f5f5f5f5f 64 gnu insw (%dx),%es:(%rdi)
+666d|11223344556677885f5f5f5f5f5f 64 intel data16 insw
+666d|11223344556677885f5f5f5f5f5f 64 plan9 INSW DX, ES:0(DI)
+666f|11223344556677885f5f5f5f5f5f 32 intel data16 outsw
+666f|11223344556677885f5f5f5f5f5f 32 plan9 OUTSW DS:0(SI), DX
+666f|11223344556677885f5f5f5f5f5f 64 gnu outsw %ds:(%rsi),(%dx)
+666f|11223344556677885f5f5f5f5f5f 64 intel data16 outsw
+666f|11223344556677885f5f5f5f5f5f 64 plan9 OUTSW DS:0(SI), DX
+6681001122|3344556677885f5f5f5f5f 32 intel add word ptr [eax], 0x2211
+6681001122|3344556677885f5f5f5f5f 32 plan9 ADDW $0x2211, 0(AX)
+6681001122|3344556677885f5f5f5f5f 64 gnu addw $0x2211,(%rax)
+6681001122|3344556677885f5f5f5f5f 64 intel add word ptr [rax], 0x2211
+6681001122|3344556677885f5f5f5f5f 64 plan9 ADDW $0x2211, 0(AX)
+6681081122|3344556677885f5f5f5f5f 32 intel or word ptr [eax], 0x2211
+6681081122|3344556677885f5f5f5f5f 32 plan9 ORW $0x2211, 0(AX)
+6681081122|3344556677885f5f5f5f5f 64 gnu orw $0x2211,(%rax)
+6681081122|3344556677885f5f5f5f5f 64 intel or word ptr [rax], 0x2211
+6681081122|3344556677885f5f5f5f5f 64 plan9 ORW $0x2211, 0(AX)
+6681112233|44556677885f5f5f5f5f5f 32 intel adc word ptr [ecx], 0x3322
+6681112233|44556677885f5f5f5f5f5f 32 plan9 ADCW $0x3322, 0(CX)
+6681112233|44556677885f5f5f5f5f5f 64 gnu adcw $0x3322,(%rcx)
+6681112233|44556677885f5f5f5f5f5f 64 intel adc word ptr [rcx], 0x3322
+6681112233|44556677885f5f5f5f5f5f 64 plan9 ADCW $0x3322, 0(CX)
+6681181122|3344556677885f5f5f5f5f 32 intel sbb word ptr [eax], 0x2211
+6681181122|3344556677885f5f5f5f5f 32 plan9 SBBW $0x2211, 0(AX)
+6681181122|3344556677885f5f5f5f5f 64 gnu sbbw $0x2211,(%rax)
+6681181122|3344556677885f5f5f5f5f 64 intel sbb word ptr [rax], 0x2211
+6681181122|3344556677885f5f5f5f5f 64 plan9 SBBW $0x2211, 0(AX)
+6681201122|3344556677885f5f5f5f5f 32 intel and word ptr [eax], 0x2211
+6681201122|3344556677885f5f5f5f5f 32 plan9 ANDW $0x2211, 0(AX)
+6681201122|3344556677885f5f5f5f5f 64 gnu andw $0x2211,(%rax)
+6681201122|3344556677885f5f5f5f5f 64 intel and word ptr [rax], 0x2211
+6681201122|3344556677885f5f5f5f5f 64 plan9 ANDW $0x2211, 0(AX)
+6681281122|3344556677885f5f5f5f5f 32 intel sub word ptr [eax], 0x2211
+6681281122|3344556677885f5f5f5f5f 32 plan9 SUBW $0x2211, 0(AX)
+6681281122|3344556677885f5f5f5f5f 64 gnu subw $0x2211,(%rax)
+6681281122|3344556677885f5f5f5f5f 64 intel sub word ptr [rax], 0x2211
+6681281122|3344556677885f5f5f5f5f 64 plan9 SUBW $0x2211, 0(AX)
+6681301122|3344556677885f5f5f5f5f 32 intel xor word ptr [eax], 0x2211
+6681301122|3344556677885f5f5f5f5f 32 plan9 XORW $0x2211, 0(AX)
+6681301122|3344556677885f5f5f5f5f 64 gnu xorw $0x2211,(%rax)
+6681301122|3344556677885f5f5f5f5f 64 intel xor word ptr [rax], 0x2211
+6681301122|3344556677885f5f5f5f5f 64 plan9 XORW $0x2211, 0(AX)
+6681381122|3344556677885f5f5f5f5f 32 intel cmp word ptr [eax], 0x2211
+6681381122|3344556677885f5f5f5f5f 32 plan9 CMPW $0x2211, 0(AX)
+6681381122|3344556677885f5f5f5f5f 64 gnu cmpw $0x2211,(%rax)
+6681381122|3344556677885f5f5f5f5f 64 intel cmp word ptr [rax], 0x2211
+6681381122|3344556677885f5f5f5f5f 64 plan9 CMPW $0x2211, 0(AX)
+66830011|223344556677885f5f5f5f5f 32 intel add word ptr [eax], 0x11
+66830011|223344556677885f5f5f5f5f 32 plan9 ADDW $0x11, 0(AX)
+66830011|223344556677885f5f5f5f5f 64 gnu addw $0x11,(%rax)
+66830011|223344556677885f5f5f5f5f 64 intel add word ptr [rax], 0x11
+66830011|223344556677885f5f5f5f5f 64 plan9 ADDW $0x11, 0(AX)
+66830811|223344556677885f5f5f5f5f 32 intel or word ptr [eax], 0x11
+66830811|223344556677885f5f5f5f5f 32 plan9 ORW $0x11, 0(AX)
+66830811|223344556677885f5f5f5f5f 64 gnu orw $0x11,(%rax)
+66830811|223344556677885f5f5f5f5f 64 intel or word ptr [rax], 0x11
+66830811|223344556677885f5f5f5f5f 64 plan9 ORW $0x11, 0(AX)
+66831122|3344556677885f5f5f5f5f5f 32 intel adc word ptr [ecx], 0x22
+66831122|3344556677885f5f5f5f5f5f 32 plan9 ADCW $0x22, 0(CX)
+66831122|3344556677885f5f5f5f5f5f 64 gnu adcw $0x22,(%rcx)
+66831122|3344556677885f5f5f5f5f5f 64 intel adc word ptr [rcx], 0x22
+66831122|3344556677885f5f5f5f5f5f 64 plan9 ADCW $0x22, 0(CX)
+66831811|223344556677885f5f5f5f5f 32 intel sbb word ptr [eax], 0x11
+66831811|223344556677885f5f5f5f5f 32 plan9 SBBW $0x11, 0(AX)
+66831811|223344556677885f5f5f5f5f 64 gnu sbbw $0x11,(%rax)
+66831811|223344556677885f5f5f5f5f 64 intel sbb word ptr [rax], 0x11
+66831811|223344556677885f5f5f5f5f 64 plan9 SBBW $0x11, 0(AX)
+66832011|223344556677885f5f5f5f5f 32 intel and word ptr [eax], 0x11
+66832011|223344556677885f5f5f5f5f 32 plan9 ANDW $0x11, 0(AX)
+66832011|223344556677885f5f5f5f5f 64 gnu andw $0x11,(%rax)
+66832011|223344556677885f5f5f5f5f 64 intel and word ptr [rax], 0x11
+66832011|223344556677885f5f5f5f5f 64 plan9 ANDW $0x11, 0(AX)
+66832811|223344556677885f5f5f5f5f 32 intel sub word ptr [eax], 0x11
+66832811|223344556677885f5f5f5f5f 32 plan9 SUBW $0x11, 0(AX)
+66832811|223344556677885f5f5f5f5f 64 gnu subw $0x11,(%rax)
+66832811|223344556677885f5f5f5f5f 64 intel sub word ptr [rax], 0x11
+66832811|223344556677885f5f5f5f5f 64 plan9 SUBW $0x11, 0(AX)
+66833011|223344556677885f5f5f5f5f 32 intel xor word ptr [eax], 0x11
+66833011|223344556677885f5f5f5f5f 32 plan9 XORW $0x11, 0(AX)
+66833011|223344556677885f5f5f5f5f 64 gnu xorw $0x11,(%rax)
+66833011|223344556677885f5f5f5f5f 64 intel xor word ptr [rax], 0x11
+66833011|223344556677885f5f5f5f5f 64 plan9 XORW $0x11, 0(AX)
+66833811|223344556677885f5f5f5f5f 32 intel cmp word ptr [eax], 0x11
+66833811|223344556677885f5f5f5f5f 32 plan9 CMPW $0x11, 0(AX)
+66833811|223344556677885f5f5f5f5f 64 gnu cmpw $0x11,(%rax)
+66833811|223344556677885f5f5f5f5f 64 intel cmp word ptr [rax], 0x11
+66833811|223344556677885f5f5f5f5f 64 plan9 CMPW $0x11, 0(AX)
+668511|223344556677885f5f5f5f5f5f 32 intel test word ptr [ecx], dx
+668511|223344556677885f5f5f5f5f5f 32 plan9 TESTW DX, 0(CX)
+668511|223344556677885f5f5f5f5f5f 64 gnu test %dx,(%rcx)
+668511|223344556677885f5f5f5f5f5f 64 intel test word ptr [rcx], dx
+668511|223344556677885f5f5f5f5f5f 64 plan9 TESTW DX, 0(CX)
+668711|223344556677885f5f5f5f5f5f 32 intel xchg word ptr [ecx], dx
+668711|223344556677885f5f5f5f5f5f 32 plan9 XCHGW DX, 0(CX)
+668711|223344556677885f5f5f5f5f5f 64 gnu xchg %dx,(%rcx)
+668711|223344556677885f5f5f5f5f5f 64 intel xchg word ptr [rcx], dx
+668711|223344556677885f5f5f5f5f5f 64 plan9 XCHGW DX, 0(CX)
+668911|223344556677885f5f5f5f5f5f 32 intel mov word ptr [ecx], dx
+668911|223344556677885f5f5f5f5f5f 32 plan9 MOVW DX, 0(CX)
+668911|223344556677885f5f5f5f5f5f 64 gnu mov %dx,(%rcx)
+668911|223344556677885f5f5f5f5f5f 64 intel mov word ptr [rcx], dx
+668911|223344556677885f5f5f5f5f5f 64 plan9 MOVW DX, 0(CX)
+668b11|223344556677885f5f5f5f5f5f 32 intel mov dx, word ptr [ecx]
+668b11|223344556677885f5f5f5f5f5f 32 plan9 MOVW 0(CX), DX
+668b11|223344556677885f5f5f5f5f5f 64 gnu mov (%rcx),%dx
+668b11|223344556677885f5f5f5f5f5f 64 intel mov dx, word ptr [rcx]
+668b11|223344556677885f5f5f5f5f5f 64 plan9 MOVW 0(CX), DX
+668c11|223344556677885f5f5f5f5f5f 32 intel mov word ptr [ecx], ss
+668c11|223344556677885f5f5f5f5f5f 32 plan9 MOVW SS, 0(CX)
+668c11|223344556677885f5f5f5f5f5f 64 gnu data16 mov %ss,(%rcx)
+668c11|223344556677885f5f5f5f5f5f 64 intel mov word ptr [rcx], ss
+668c11|223344556677885f5f5f5f5f5f 64 plan9 MOVW SS, 0(CX)
+668d11|223344556677885f5f5f5f5f5f 32 intel lea dx, ptr [ecx]
+668d11|223344556677885f5f5f5f5f5f 32 plan9 LEAW 0(CX), DX
+668d11|223344556677885f5f5f5f5f5f 64 gnu lea (%rcx),%dx
+668d11|223344556677885f5f5f5f5f5f 64 intel lea dx, ptr [rcx]
+668d11|223344556677885f5f5f5f5f5f 64 plan9 LEAW 0(CX), DX
+668ec0|11223344556677885f5f5f5f5f 32 intel mov es, ax
+668ec0|11223344556677885f5f5f5f5f 32 plan9 MOVW AX, ES
+668ec0|11223344556677885f5f5f5f5f 64 gnu mov %ax,%es
+668ec0|11223344556677885f5f5f5f5f 64 intel mov es, ax
+668ec0|11223344556677885f5f5f5f5f 64 plan9 MOVW AX, ES
+668f00|11223344556677885f5f5f5f5f 32 intel pop word ptr [eax]
+668f00|11223344556677885f5f5f5f5f 32 plan9 POPW 0(AX)
+668f00|11223344556677885f5f5f5f5f 64 gnu popw (%rax)
+668f00|11223344556677885f5f5f5f5f 64 intel pop word ptr [rax]
+668f00|11223344556677885f5f5f5f5f 64 plan9 POPW 0(AX)
+6690|11223344556677885f5f5f5f5f5f 32 plan9 NOPW
+6690|11223344556677885f5f5f5f5f5f 64 gnu data16 nop
+6690|11223344556677885f5f5f5f5f5f 64 plan9 NOPW
+6698|11223344556677885f5f5f5f5f5f 32 intel data16 cbw
+6698|11223344556677885f5f5f5f5f5f 32 plan9 CBW
+6698|11223344556677885f5f5f5f5f5f 64 gnu cbtw
+6698|11223344556677885f5f5f5f5f5f 64 intel data16 cbw
+6698|11223344556677885f5f5f5f5f5f 64 plan9 CBW
+6699|11223344556677885f5f5f5f5f5f 32 intel data16 cwd
+6699|11223344556677885f5f5f5f5f5f 32 plan9 CWD
+6699|11223344556677885f5f5f5f5f5f 64 gnu cwtd
+6699|11223344556677885f5f5f5f5f5f 64 intel data16 cwd
+6699|11223344556677885f5f5f5f5f5f 64 plan9 CWD
+669a11223344|556677885f5f5f5f5f5f 32 intel call far 0x2211, 0x4433
+669a11223344|556677885f5f5f5f5f5f 32 plan9 LCALL $0x2211, $0x4433
+669c|11223344556677885f5f5f5f5f5f 32 intel data16 pushf
+669c|11223344556677885f5f5f5f5f5f 32 plan9 PUSHF
+669c|11223344556677885f5f5f5f5f5f 64 gnu pushfw
+669c|11223344556677885f5f5f5f5f5f 64 intel data16 pushf
+669c|11223344556677885f5f5f5f5f5f 64 plan9 PUSHF
+669d|11223344556677885f5f5f5f5f5f 32 intel data16 popf
+669d|11223344556677885f5f5f5f5f5f 32 plan9 POPF
+669d|11223344556677885f5f5f5f5f5f 64 gnu popfw
+669d|11223344556677885f5f5f5f5f5f 64 intel data16 popf
+669d|11223344556677885f5f5f5f5f5f 64 plan9 POPF
+66a11122334455667788|5f5f5f5f5f5f 64 gnu mov -0x778899aabbccddef,%ax
+66a11122334455667788|5f5f5f5f5f5f 64 intel mov ax, word ptr [0x8877665544332211]
+66a11122334455667788|5f5f5f5f5f5f 64 plan9 MOVW -0x778899aabbccddef, AX
+66a111223344|556677885f5f5f5f5f5f 32 intel mov ax, word ptr [0x44332211]
+66a111223344|556677885f5f5f5f5f5f 32 plan9 MOVW 0x44332211, AX
+66a31122334455667788|5f5f5f5f5f5f 64 gnu mov %ax,-0x778899aabbccddef
+66a31122334455667788|5f5f5f5f5f5f 64 intel mov word ptr [0x8877665544332211], ax
+66a31122334455667788|5f5f5f5f5f5f 64 plan9 MOVW AX, -0x778899aabbccddef
+66a311223344|556677885f5f5f5f5f5f 32 intel mov word ptr [0x44332211], ax
+66a311223344|556677885f5f5f5f5f5f 32 plan9 MOVW AX, 0x44332211
+66a5|11223344556677885f5f5f5f5f5f 32 intel movsw word ptr [edi], word ptr [esi]
+66a5|11223344556677885f5f5f5f5f5f 32 plan9 MOVSW DS:0(SI), ES:0(DI)
+66a5|11223344556677885f5f5f5f5f5f 64 gnu movsw %ds:(%rsi),%es:(%rdi)
+66a5|11223344556677885f5f5f5f5f5f 64 intel movsw word ptr [rdi], word ptr [rsi]
+66a5|11223344556677885f5f5f5f5f5f 64 plan9 MOVSW DS:0(SI), ES:0(DI)
+66a7|11223344556677885f5f5f5f5f5f 32 intel cmpsw word ptr [esi], word ptr [edi]
+66a7|11223344556677885f5f5f5f5f5f 32 plan9 CMPSW ES:0(DI), DS:0(SI)
+66a7|11223344556677885f5f5f5f5f5f 64 gnu cmpsw %es:(%rdi),%ds:(%rsi)
+66a7|11223344556677885f5f5f5f5f5f 64 intel cmpsw word ptr [rsi], word ptr [rdi]
+66a7|11223344556677885f5f5f5f5f5f 64 plan9 CMPSW ES:0(DI), DS:0(SI)
+66a91122|3344556677885f5f5f5f5f5f 32 intel test ax, 0x2211
+66a91122|3344556677885f5f5f5f5f5f 32 plan9 TESTW $0x2211, AX
+66a91122|3344556677885f5f5f5f5f5f 64 gnu test $0x2211,%ax
+66a91122|3344556677885f5f5f5f5f5f 64 intel test ax, 0x2211
+66a91122|3344556677885f5f5f5f5f5f 64 plan9 TESTW $0x2211, AX
+66ab|11223344556677885f5f5f5f5f5f 32 intel stosw word ptr [edi]
+66ab|11223344556677885f5f5f5f5f5f 32 plan9 STOSW AX, ES:0(DI)
+66ab|11223344556677885f5f5f5f5f5f 64 gnu stos %ax,%es:(%rdi)
+66ab|11223344556677885f5f5f5f5f5f 64 intel stosw word ptr [rdi]
+66ab|11223344556677885f5f5f5f5f5f 64 plan9 STOSW AX, ES:0(DI)
+66ad|11223344556677885f5f5f5f5f5f 32 intel lodsw word ptr [esi]
+66ad|11223344556677885f5f5f5f5f5f 32 plan9 LODSW DS:0(SI), AX
+66ad|11223344556677885f5f5f5f5f5f 64 gnu lods %ds:(%rsi),%ax
+66ad|11223344556677885f5f5f5f5f5f 64 intel lodsw word ptr [rsi]
+66ad|11223344556677885f5f5f5f5f5f 64 plan9 LODSW DS:0(SI), AX
+66af|11223344556677885f5f5f5f5f5f 32 intel scasw word ptr [edi]
+66af|11223344556677885f5f5f5f5f5f 32 plan9 SCASW ES:0(DI), AX
+66af|11223344556677885f5f5f5f5f5f 64 gnu scas %es:(%rdi),%ax
+66af|11223344556677885f5f5f5f5f5f 64 intel scasw word ptr [rdi]
+66af|11223344556677885f5f5f5f5f5f 64 plan9 SCASW ES:0(DI), AX
+66b81122|3344556677885f5f5f5f5f5f 32 intel mov ax, 0x2211
+66b81122|3344556677885f5f5f5f5f5f 32 plan9 MOVW $0x2211, AX
+66b81122|3344556677885f5f5f5f5f5f 64 gnu mov $0x2211,%ax
+66b81122|3344556677885f5f5f5f5f5f 64 intel mov ax, 0x2211
+66b81122|3344556677885f5f5f5f5f5f 64 plan9 MOVW $0x2211, AX
+66c10011|223344556677885f5f5f5f5f 32 intel rol word ptr [eax], 0x11
+66c10011|223344556677885f5f5f5f5f 32 plan9 ROLW $0x11, 0(AX)
+66c10011|223344556677885f5f5f5f5f 64 gnu rolw $0x11,(%rax)
+66c10011|223344556677885f5f5f5f5f 64 intel rol word ptr [rax], 0x11
+66c10011|223344556677885f5f5f5f5f 64 plan9 ROLW $0x11, 0(AX)
+66c10811|223344556677885f5f5f5f5f 32 intel ror word ptr [eax], 0x11
+66c10811|223344556677885f5f5f5f5f 32 plan9 RORW $0x11, 0(AX)
+66c10811|223344556677885f5f5f5f5f 64 gnu rorw $0x11,(%rax)
+66c10811|223344556677885f5f5f5f5f 64 intel ror word ptr [rax], 0x11
+66c10811|223344556677885f5f5f5f5f 64 plan9 RORW $0x11, 0(AX)
+66c11122|3344556677885f5f5f5f5f5f 32 intel rcl word ptr [ecx], 0x22
+66c11122|3344556677885f5f5f5f5f5f 32 plan9 RCLW $0x22, 0(CX)
+66c11122|3344556677885f5f5f5f5f5f 64 gnu rclw $0x22,(%rcx)
+66c11122|3344556677885f5f5f5f5f5f 64 intel rcl word ptr [rcx], 0x22
+66c11122|3344556677885f5f5f5f5f5f 64 plan9 RCLW $0x22, 0(CX)
+66c11811|223344556677885f5f5f5f5f 32 intel rcr word ptr [eax], 0x11
+66c11811|223344556677885f5f5f5f5f 32 plan9 RCRW $0x11, 0(AX)
+66c11811|223344556677885f5f5f5f5f 64 gnu rcrw $0x11,(%rax)
+66c11811|223344556677885f5f5f5f5f 64 intel rcr word ptr [rax], 0x11
+66c11811|223344556677885f5f5f5f5f 64 plan9 RCRW $0x11, 0(AX)
+66c12011|223344556677885f5f5f5f5f 32 intel shl word ptr [eax], 0x11
+66c12011|223344556677885f5f5f5f5f 32 plan9 SHLW $0x11, 0(AX)
+66c12011|223344556677885f5f5f5f5f 64 gnu shlw $0x11,(%rax)
+66c12011|223344556677885f5f5f5f5f 64 intel shl word ptr [rax], 0x11
+66c12011|223344556677885f5f5f5f5f 64 plan9 SHLW $0x11, 0(AX)
+66c12811|223344556677885f5f5f5f5f 32 intel shr word ptr [eax], 0x11
+66c12811|223344556677885f5f5f5f5f 32 plan9 SHRW $0x11, 0(AX)
+66c12811|223344556677885f5f5f5f5f 64 gnu shrw $0x11,(%rax)
+66c12811|223344556677885f5f5f5f5f 64 intel shr word ptr [rax], 0x11
+66c12811|223344556677885f5f5f5f5f 64 plan9 SHRW $0x11, 0(AX)
+66c13811|223344556677885f5f5f5f5f 32 intel sar word ptr [eax], 0x11
+66c13811|223344556677885f5f5f5f5f 32 plan9 SARW $0x11, 0(AX)
+66c13811|223344556677885f5f5f5f5f 64 gnu sarw $0x11,(%rax)
+66c13811|223344556677885f5f5f5f5f 64 intel sar word ptr [rax], 0x11
+66c13811|223344556677885f5f5f5f5f 64 plan9 SARW $0x11, 0(AX)
+66c21122|3344556677885f5f5f5f5f5f 32 intel ret 0x2211
+66c21122|3344556677885f5f5f5f5f5f 32 plan9 RET $0x2211
+66c21122|3344556677885f5f5f5f5f5f 64 gnu retw $0x2211
+66c21122|3344556677885f5f5f5f5f5f 64 intel ret 0x2211
+66c21122|3344556677885f5f5f5f5f5f 64 plan9 RET $0x2211
+66c411|223344556677885f5f5f5f5f5f 32 intel les dx, dword ptr [ecx]
+66c411|223344556677885f5f5f5f5f5f 32 plan9 LES 0(CX), DX
+66c511|223344556677885f5f5f5f5f5f 32 intel lds dx, dword ptr [ecx]
+66c511|223344556677885f5f5f5f5f5f 32 plan9 LDS 0(CX), DX
+66c7001122|3344556677885f5f5f5f5f 32 intel mov word ptr [eax], 0x2211
+66c7001122|3344556677885f5f5f5f5f 32 plan9 MOVW $0x2211, 0(AX)
+66c7001122|3344556677885f5f5f5f5f 64 gnu movw $0x2211,(%rax)
+66c7001122|3344556677885f5f5f5f5f 64 intel mov word ptr [rax], 0x2211
+66c7001122|3344556677885f5f5f5f5f 64 plan9 MOVW $0x2211, 0(AX)
+66c7f81122|3344556677885f5f5f5f5f 32 intel xbegin .+0x2211
+66c7f81122|3344556677885f5f5f5f5f 32 plan9 XBEGIN .+8721
+66c7f81122|3344556677885f5f5f5f5f 64 gnu xbeginw .+0x2211
+66c7f81122|3344556677885f5f5f5f5f 64 intel xbegin .+0x2211
+66c7f81122|3344556677885f5f5f5f5f 64 plan9 XBEGIN .+8721
+66c9|11223344556677885f5f5f5f5f5f 32 intel data16 leave
+66c9|11223344556677885f5f5f5f5f5f 32 plan9 LEAVE
+66c9|11223344556677885f5f5f5f5f5f 64 gnu leavew
+66c9|11223344556677885f5f5f5f5f5f 64 intel data16 leave
+66c9|11223344556677885f5f5f5f5f5f 64 plan9 LEAVE
+66cf|11223344556677885f5f5f5f5f5f 32 intel data16 iret
+66cf|11223344556677885f5f5f5f5f5f 32 plan9 IRET
+66cf|11223344556677885f5f5f5f5f5f 64 gnu iretw
+66cf|11223344556677885f5f5f5f5f5f 64 intel data16 iret
+66cf|11223344556677885f5f5f5f5f5f 64 plan9 IRET
+66d100|11223344556677885f5f5f5f5f 32 intel rol word ptr [eax], 0x1
+66d100|11223344556677885f5f5f5f5f 32 plan9 ROLW $0x1, 0(AX)
+66d100|11223344556677885f5f5f5f5f 64 gnu rolw (%rax)
+66d100|11223344556677885f5f5f5f5f 64 intel rol word ptr [rax], 0x1
+66d100|11223344556677885f5f5f5f5f 64 plan9 ROLW $0x1, 0(AX)
+66d108|11223344556677885f5f5f5f5f 32 intel ror word ptr [eax], 0x1
+66d108|11223344556677885f5f5f5f5f 32 plan9 RORW $0x1, 0(AX)
+66d108|11223344556677885f5f5f5f5f 64 gnu rorw (%rax)
+66d108|11223344556677885f5f5f5f5f 64 intel ror word ptr [rax], 0x1
+66d108|11223344556677885f5f5f5f5f 64 plan9 RORW $0x1, 0(AX)
+66d111|223344556677885f5f5f5f5f5f 32 intel rcl word ptr [ecx], 0x1
+66d111|223344556677885f5f5f5f5f5f 32 plan9 RCLW $0x1, 0(CX)
+66d111|223344556677885f5f5f5f5f5f 64 gnu rclw (%rcx)
+66d111|223344556677885f5f5f5f5f5f 64 intel rcl word ptr [rcx], 0x1
+66d111|223344556677885f5f5f5f5f5f 64 plan9 RCLW $0x1, 0(CX)
+66d118|11223344556677885f5f5f5f5f 32 intel rcr word ptr [eax], 0x1
+66d118|11223344556677885f5f5f5f5f 32 plan9 RCRW $0x1, 0(AX)
+66d118|11223344556677885f5f5f5f5f 64 gnu rcrw (%rax)
+66d118|11223344556677885f5f5f5f5f 64 intel rcr word ptr [rax], 0x1
+66d118|11223344556677885f5f5f5f5f 64 plan9 RCRW $0x1, 0(AX)
+66d120|11223344556677885f5f5f5f5f 32 intel shl word ptr [eax], 0x1
+66d120|11223344556677885f5f5f5f5f 32 plan9 SHLW $0x1, 0(AX)
+66d120|11223344556677885f5f5f5f5f 64 gnu shlw (%rax)
+66d120|11223344556677885f5f5f5f5f 64 intel shl word ptr [rax], 0x1
+66d120|11223344556677885f5f5f5f5f 64 plan9 SHLW $0x1, 0(AX)
+66d128|11223344556677885f5f5f5f5f 32 intel shr word ptr [eax], 0x1
+66d128|11223344556677885f5f5f5f5f 32 plan9 SHRW $0x1, 0(AX)
+66d128|11223344556677885f5f5f5f5f 64 gnu shrw (%rax)
+66d128|11223344556677885f5f5f5f5f 64 intel shr word ptr [rax], 0x1
+66d128|11223344556677885f5f5f5f5f 64 plan9 SHRW $0x1, 0(AX)
+66d138|11223344556677885f5f5f5f5f 32 intel sar word ptr [eax], 0x1
+66d138|11223344556677885f5f5f5f5f 32 plan9 SARW $0x1, 0(AX)
+66d138|11223344556677885f5f5f5f5f 64 gnu sarw (%rax)
+66d138|11223344556677885f5f5f5f5f 64 intel sar word ptr [rax], 0x1
+66d138|11223344556677885f5f5f5f5f 64 plan9 SARW $0x1, 0(AX)
+66d300|11223344556677885f5f5f5f5f 32 intel rol word ptr [eax], cl
+66d300|11223344556677885f5f5f5f5f 32 plan9 ROLW CL, 0(AX)
+66d300|11223344556677885f5f5f5f5f 64 gnu rolw %cl,(%rax)
+66d300|11223344556677885f5f5f5f5f 64 intel rol word ptr [rax], cl
+66d300|11223344556677885f5f5f5f5f 64 plan9 ROLW CL, 0(AX)
+66d308|11223344556677885f5f5f5f5f 32 intel ror word ptr [eax], cl
+66d308|11223344556677885f5f5f5f5f 32 plan9 RORW CL, 0(AX)
+66d308|11223344556677885f5f5f5f5f 64 gnu rorw %cl,(%rax)
+66d308|11223344556677885f5f5f5f5f 64 intel ror word ptr [rax], cl
+66d308|11223344556677885f5f5f5f5f 64 plan9 RORW CL, 0(AX)
+66d311|223344556677885f5f5f5f5f5f 32 intel rcl word ptr [ecx], cl
+66d311|223344556677885f5f5f5f5f5f 32 plan9 RCLW CL, 0(CX)
+66d311|223344556677885f5f5f5f5f5f 64 gnu rclw %cl,(%rcx)
+66d311|223344556677885f5f5f5f5f5f 64 intel rcl word ptr [rcx], cl
+66d311|223344556677885f5f5f5f5f5f 64 plan9 RCLW CL, 0(CX)
+66d318|11223344556677885f5f5f5f5f 32 intel rcr word ptr [eax], cl
+66d318|11223344556677885f5f5f5f5f 32 plan9 RCRW CL, 0(AX)
+66d318|11223344556677885f5f5f5f5f 64 gnu rcrw %cl,(%rax)
+66d318|11223344556677885f5f5f5f5f 64 intel rcr word ptr [rax], cl
+66d318|11223344556677885f5f5f5f5f 64 plan9 RCRW CL, 0(AX)
+66d320|11223344556677885f5f5f5f5f 32 intel shl word ptr [eax], cl
+66d320|11223344556677885f5f5f5f5f 32 plan9 SHLW CL, 0(AX)
+66d320|11223344556677885f5f5f5f5f 64 gnu shlw %cl,(%rax)
+66d320|11223344556677885f5f5f5f5f 64 intel shl word ptr [rax], cl
+66d320|11223344556677885f5f5f5f5f 64 plan9 SHLW CL, 0(AX)
+66d328|11223344556677885f5f5f5f5f 32 intel shr word ptr [eax], cl
+66d328|11223344556677885f5f5f5f5f 32 plan9 SHRW CL, 0(AX)
+66d328|11223344556677885f5f5f5f5f 64 gnu shrw %cl,(%rax)
+66d328|11223344556677885f5f5f5f5f 64 intel shr word ptr [rax], cl
+66d328|11223344556677885f5f5f5f5f 64 plan9 SHRW CL, 0(AX)
+66d338|11223344556677885f5f5f5f5f 32 intel sar word ptr [eax], cl
+66d338|11223344556677885f5f5f5f5f 32 plan9 SARW CL, 0(AX)
+66d338|11223344556677885f5f5f5f5f 64 gnu sarw %cl,(%rax)
+66d338|11223344556677885f5f5f5f5f 64 intel sar word ptr [rax], cl
+66d338|11223344556677885f5f5f5f5f 64 plan9 SARW CL, 0(AX)
+66d411|223344556677885f5f5f5f5f5f 32 intel aam 0x11
+66d411|223344556677885f5f5f5f5f5f 32 plan9 AAM $0x11
+66d920|11223344556677885f5f5f5f5f 32 intel fldenv ptr [eax]
+66d920|11223344556677885f5f5f5f5f 32 plan9 FLDENVW 0(AX)
+66d920|11223344556677885f5f5f5f5f 64 gnu fldenvs (%rax)
+66d920|11223344556677885f5f5f5f5f 64 intel fldenv ptr [rax]
+66d920|11223344556677885f5f5f5f5f 64 plan9 FLDENVW 0(AX)
+66e511|223344556677885f5f5f5f5f5f 32 intel in ax, 0x11
+66e511|223344556677885f5f5f5f5f5f 32 plan9 INW $0x11, AX
+66e511|223344556677885f5f5f5f5f5f 64 gnu in $0x11,%ax
+66e511|223344556677885f5f5f5f5f5f 64 intel in ax, 0x11
+66e511|223344556677885f5f5f5f5f5f 64 plan9 INW $0x11, AX
+66e711|223344556677885f5f5f5f5f5f 32 intel out 0x11, ax
+66e711|223344556677885f5f5f5f5f5f 32 plan9 OUTW AX, $0x11
+66e711|223344556677885f5f5f5f5f5f 64 gnu out %ax,$0x11
+66e711|223344556677885f5f5f5f5f5f 64 intel out 0x11, ax
+66e711|223344556677885f5f5f5f5f5f 64 plan9 OUTW AX, $0x11
+66e811223344|556677885f5f5f5f5f5f 64 gnu callw .+0x44332211
+66e811223344|556677885f5f5f5f5f5f 64 intel call .+0x44332211
+66e811223344|556677885f5f5f5f5f5f 64 plan9 CALL .+1144201745
+66e81122|3344556677885f5f5f5f5f5f 32 intel call .+0x2211
+66e81122|3344556677885f5f5f5f5f5f 32 plan9 CALL .+8721
+66e911223344|556677885f5f5f5f5f5f 64 gnu jmpw .+0x44332211
+66e911223344|556677885f5f5f5f5f5f 64 intel jmp .+0x44332211
+66e911223344|556677885f5f5f5f5f5f 64 plan9 JMP .+1144201745
+66e91122|3344556677885f5f5f5f5f5f 32 intel jmp .+0x2211
+66e91122|3344556677885f5f5f5f5f5f 32 plan9 JMP .+8721
+66ea11223344|556677885f5f5f5f5f5f 32 intel jmp far 0x2211, 0x4433
+66ea11223344|556677885f5f5f5f5f5f 32 plan9 LJMP $0x2211, $0x4433
+66ed|11223344556677885f5f5f5f5f5f 32 intel in ax, dx
+66ed|11223344556677885f5f5f5f5f5f 32 plan9 INW DX, AX
+66ed|11223344556677885f5f5f5f5f5f 64 gnu in (%dx),%ax
+66ed|11223344556677885f5f5f5f5f5f 64 intel in ax, dx
+66ed|11223344556677885f5f5f5f5f5f 64 plan9 INW DX, AX
+66ef|11223344556677885f5f5f5f5f5f 32 intel out dx, ax
+66ef|11223344556677885f5f5f5f5f5f 32 plan9 OUTW AX, DX
+66ef|11223344556677885f5f5f5f5f5f 64 gnu out %ax,(%dx)
+66ef|11223344556677885f5f5f5f5f5f 64 intel out dx, ax
+66ef|11223344556677885f5f5f5f5f5f 64 plan9 OUTW AX, DX
+66f20f2a11|223344556677885f5f5f5f 32 intel cvtsi2sd xmm2, dword ptr [ecx]
+66f20f2a11|223344556677885f5f5f5f 32 plan9 REPNE CVTSI2SDW 0(CX), X2
+66f20f2a11|223344556677885f5f5f5f 64 gnu cvtsi2sdl (%rcx),%xmm2
+66f20f2a11|223344556677885f5f5f5f 64 intel cvtsi2sd xmm2, dword ptr [rcx]
+66f20f2a11|223344556677885f5f5f5f 64 plan9 REPNE CVTSI2SDW 0(CX), X2
+66f20f2c11|223344556677885f5f5f5f 32 intel cvttsd2si edx, qword ptr [ecx]
+66f20f2c11|223344556677885f5f5f5f 32 plan9 REPNE CVTTSD2SIW 0(CX), DX
+66f20f2c11|223344556677885f5f5f5f 64 gnu cvttsd2si (%rcx),%dx
+66f20f2c11|223344556677885f5f5f5f 64 intel cvttsd2si edx, qword ptr [rcx]
+66f20f2c11|223344556677885f5f5f5f 64 plan9 REPNE CVTTSD2SIW 0(CX), DX
+66f20f2d11|223344556677885f5f5f5f 32 intel cvtsd2si edx, qword ptr [ecx]
+66f20f2d11|223344556677885f5f5f5f 32 plan9 REPNE CVTSD2SIW 0(CX), DX
+66f20f2d11|223344556677885f5f5f5f 64 gnu cvtsd2si (%rcx),%dx
+66f20f2d11|223344556677885f5f5f5f 64 intel cvtsd2si edx, qword ptr [rcx]
+66f20f2d11|223344556677885f5f5f5f 64 plan9 REPNE CVTSD2SIW 0(CX), DX
+66f20f38f011|223344556677885f5f5f 32 intel crc32 edx, byte ptr [ecx]
+66f20f38f011|223344556677885f5f5f 32 plan9 REPNE CRC32 0(CX), DX
+66f20f38f011|223344556677885f5f5f 64 gnu crc32b (%rcx),%edx
+66f20f38f011|223344556677885f5f5f 64 intel crc32 edx, byte ptr [rcx]
+66f20f38f011|223344556677885f5f5f 64 plan9 REPNE CRC32 0(CX), DX
+66f30f2c11|223344556677885f5f5f5f 32 intel cvttss2si edx, dword ptr [ecx]
+66f30f2c11|223344556677885f5f5f5f 32 plan9 REP CVTTSS2SIW 0(CX), DX
+66f30f2c11|223344556677885f5f5f5f 64 gnu cvttss2si (%rcx),%dx
+66f30f2c11|223344556677885f5f5f5f 64 intel cvttss2si edx, dword ptr [rcx]
+66f30f2c11|223344556677885f5f5f5f 64 plan9 REP CVTTSS2SIW 0(CX), DX
+66f30f2d11|223344556677885f5f5f5f 32 intel cvtss2si edx, dword ptr [ecx]
+66f30f2d11|223344556677885f5f5f5f 32 plan9 REP CVTSS2SIW 0(CX), DX
+66f30f2d11|223344556677885f5f5f5f 64 gnu cvtss2si (%rcx),%dx
+66f30f2d11|223344556677885f5f5f5f 64 intel cvtss2si edx, dword ptr [rcx]
+66f30f2d11|223344556677885f5f5f5f 64 plan9 REP CVTSS2SIW 0(CX), DX
+66f30fae11|223344556677885f5f5f5f 64 gnu wrfsbasel (%rcx)
+66f30fae11|223344556677885f5f5f5f 64 intel wrfsbase dword ptr [rcx]
+66f30fae11|223344556677885f5f5f5f 64 plan9 REP WRFSBASE 0(CX)
+66f30fae18|11223344556677885f5f5f 64 gnu wrgsbasel (%rax)
+66f30fae18|11223344556677885f5f5f 64 intel wrgsbase dword ptr [rax]
+66f30fae18|11223344556677885f5f5f 64 plan9 REP WRGSBASE 0(AX)
+66f30faec0|11223344556677885f5f5f 64 gnu rdfsbase %eax
+66f30faec0|11223344556677885f5f5f 64 intel rdfsbase eax
+66f30faec0|11223344556677885f5f5f 64 plan9 REP RDFSBASE AX
+66f30faec8|11223344556677885f5f5f 64 gnu rdgsbase %eax
+66f30faec8|11223344556677885f5f5f 64 intel rdgsbase eax
+66f30faec8|11223344556677885f5f5f 64 plan9 REP RDGSBASE AX
+66f30fd6c5|11223344556677885f5f5f 32 intel movq2dq xmm0, mmx5
+66f30fd6c5|11223344556677885f5f5f 32 plan9 REP MOVQ2DQ M5, X0
+66f30fd6c5|11223344556677885f5f5f 64 gnu movq2dq %mm5,%xmm0
+66f30fd6c5|11223344556677885f5f5f 64 intel movq2dq xmm0, mmx5
+66f30fd6c5|11223344556677885f5f5f 64 plan9 REP MOVQ2DQ M5, X0
+66f7001122|3344556677885f5f5f5f5f 32 intel test word ptr [eax], 0x2211
+66f7001122|3344556677885f5f5f5f5f 32 plan9 TESTW $0x2211, 0(AX)
+66f7001122|3344556677885f5f5f5f5f 64 gnu testw $0x2211,(%rax)
+66f7001122|3344556677885f5f5f5f5f 64 intel test word ptr [rax], 0x2211
+66f7001122|3344556677885f5f5f5f5f 64 plan9 TESTW $0x2211, 0(AX)
+66f711|223344556677885f5f5f5f5f5f 32 intel not word ptr [ecx]
+66f711|223344556677885f5f5f5f5f5f 32 plan9 NOTW 0(CX)
+66f711|223344556677885f5f5f5f5f5f 64 gnu notw (%rcx)
+66f711|223344556677885f5f5f5f5f5f 64 intel not word ptr [rcx]
+66f711|223344556677885f5f5f5f5f5f 64 plan9 NOTW 0(CX)
+66f718|11223344556677885f5f5f5f5f 32 intel neg word ptr [eax]
+66f718|11223344556677885f5f5f5f5f 32 plan9 NEGW 0(AX)
+66f718|11223344556677885f5f5f5f5f 64 gnu negw (%rax)
+66f718|11223344556677885f5f5f5f5f 64 intel neg word ptr [rax]
+66f718|11223344556677885f5f5f5f5f 64 plan9 NEGW 0(AX)
+66f720|11223344556677885f5f5f5f5f 32 intel mul word ptr [eax]
+66f720|11223344556677885f5f5f5f5f 32 plan9 MULW 0(AX)
+66f720|11223344556677885f5f5f5f5f 64 gnu mulw (%rax)
+66f720|11223344556677885f5f5f5f5f 64 intel mul word ptr [rax]
+66f720|11223344556677885f5f5f5f5f 64 plan9 MULW 0(AX)
+66f728|11223344556677885f5f5f5f5f 32 intel imul word ptr [eax]
+66f728|11223344556677885f5f5f5f5f 32 plan9 IMULW 0(AX)
+66f728|11223344556677885f5f5f5f5f 64 gnu imulw (%rax)
+66f728|11223344556677885f5f5f5f5f 64 intel imul word ptr [rax]
+66f728|11223344556677885f5f5f5f5f 64 plan9 IMULW 0(AX)
+66f730|11223344556677885f5f5f5f5f 32 intel div word ptr [eax]
+66f730|11223344556677885f5f5f5f5f 32 plan9 DIVW 0(AX)
+66f730|11223344556677885f5f5f5f5f 64 gnu divw (%rax)
+66f730|11223344556677885f5f5f5f5f 64 intel div word ptr [rax]
+66f730|11223344556677885f5f5f5f5f 64 plan9 DIVW 0(AX)
+66f738|11223344556677885f5f5f5f5f 32 intel idiv word ptr [eax]
+66f738|11223344556677885f5f5f5f5f 32 plan9 IDIVW 0(AX)
+66f738|11223344556677885f5f5f5f5f 64 gnu idivw (%rax)
+66f738|11223344556677885f5f5f5f5f 64 intel idiv word ptr [rax]
+66f738|11223344556677885f5f5f5f5f 64 plan9 IDIVW 0(AX)
+66ff00|11223344556677885f5f5f5f5f 32 intel inc word ptr [eax]
+66ff00|11223344556677885f5f5f5f5f 32 plan9 INCW 0(AX)
+66ff00|11223344556677885f5f5f5f5f 64 gnu incw (%rax)
+66ff00|11223344556677885f5f5f5f5f 64 intel inc word ptr [rax]
+66ff00|11223344556677885f5f5f5f5f 64 plan9 INCW 0(AX)
+66ff08|11223344556677885f5f5f5f5f 32 intel dec word ptr [eax]
+66ff08|11223344556677885f5f5f5f5f 32 plan9 DECW 0(AX)
+66ff08|11223344556677885f5f5f5f5f 64 gnu decw (%rax)
+66ff08|11223344556677885f5f5f5f5f 64 intel dec word ptr [rax]
+66ff08|11223344556677885f5f5f5f5f 64 plan9 DECW 0(AX)
+66ff11|223344556677885f5f5f5f5f5f 32 intel call word ptr [ecx]
+66ff11|223344556677885f5f5f5f5f5f 32 plan9 CALL 0(CX)
+66ff11|223344556677885f5f5f5f5f5f 64 gnu callw *(%rcx)
+66ff11|223344556677885f5f5f5f5f5f 64 intel call qword ptr [rcx]
+66ff11|223344556677885f5f5f5f5f5f 64 plan9 CALL 0(CX)
+66ff18|11223344556677885f5f5f5f5f 32 intel call far dword ptr [eax]
+66ff18|11223344556677885f5f5f5f5f 32 plan9 LCALL 0(AX)
+66ff18|11223344556677885f5f5f5f5f 64 gnu lcallw *(%rax)
+66ff18|11223344556677885f5f5f5f5f 64 intel call far dword ptr [rax]
+66ff18|11223344556677885f5f5f5f5f 64 plan9 LCALL 0(AX)
+66ff20|11223344556677885f5f5f5f5f 32 intel jmp word ptr [eax]
+66ff20|11223344556677885f5f5f5f5f 32 plan9 JMP 0(AX)
+66ff20|11223344556677885f5f5f5f5f 64 gnu jmpw *(%rax)
+66ff20|11223344556677885f5f5f5f5f 64 intel jmp qword ptr [rax]
+66ff20|11223344556677885f5f5f5f5f 64 plan9 JMP 0(AX)
+66ff28|11223344556677885f5f5f5f5f 32 intel jmp far dword ptr [eax]
+66ff28|11223344556677885f5f5f5f5f 32 plan9 LJMP 0(AX)
+66ff28|11223344556677885f5f5f5f5f 64 gnu ljmpw *(%rax)
+66ff28|11223344556677885f5f5f5f5f 64 intel jmp far dword ptr [rax]
+66ff28|11223344556677885f5f5f5f5f 64 plan9 LJMP 0(AX)
+66ff30|11223344556677885f5f5f5f5f 32 intel push word ptr [eax]
+66ff30|11223344556677885f5f5f5f5f 32 plan9 PUSHW 0(AX)
+66ff30|11223344556677885f5f5f5f5f 64 gnu pushw (%rax)
+66ff30|11223344556677885f5f5f5f5f 64 intel push word ptr [rax]
+66ff30|11223344556677885f5f5f5f5f 64 plan9 PUSHW 0(AX)
+66|9a11223344556677885f5f5f5f5f5f 64 gnu data16
+66|9a11223344556677885f5f5f5f5f5f 64 intel data16
+66|9a11223344556677885f5f5f5f5f5f 64 plan9 Op(0)
+66|c411223344556677885f5f5f5f5f5f 64 gnu data16
+66|c411223344556677885f5f5f5f5f5f 64 intel data16
+66|c411223344556677885f5f5f5f5f5f 64 plan9 Op(0)
+66|c511223344556677885f5f5f5f5f5f 64 gnu data16
+66|c511223344556677885f5f5f5f5f5f 64 intel data16
+66|c511223344556677885f5f5f5f5f5f 64 plan9 Op(0)
+66|d411223344556677885f5f5f5f5f5f 64 gnu data16
+66|d411223344556677885f5f5f5f5f5f 64 intel data16
+66|d411223344556677885f5f5f5f5f5f 64 plan9 Op(0)
+66|ea11223344556677885f5f5f5f5f5f 64 gnu data16
+66|ea11223344556677885f5f5f5f5f5f 64 intel data16
+66|ea11223344556677885f5f5f5f5f5f 64 plan9 Op(0)
+676c|11223344556677885f5f5f5f5f5f 32 intel addr16 insb
+676c|11223344556677885f5f5f5f5f5f 32 plan9 INSB DX, ES:0(DI)
+676c|11223344556677885f5f5f5f5f5f 64 gnu insb (%dx),%es:(%edi)
+676c|11223344556677885f5f5f5f5f5f 64 intel addr32 insb
+676c|11223344556677885f5f5f5f5f5f 64 plan9 INSB DX, ES:0(DI)
+67d7|11223344556677885f5f5f5f5f5f 32 intel addr16 xlat
+67d7|11223344556677885f5f5f5f5f5f 32 plan9 XLATB DS:0(BX)
+67d7|11223344556677885f5f5f5f5f5f 64 gnu xlat %ds:(%ebx)
+67d7|11223344556677885f5f5f5f5f5f 64 intel addr32 xlat
+67d7|11223344556677885f5f5f5f5f5f 64 plan9 XLATB DS:0(BX)
+67e311|223344556677885f5f5f5f5f5f 32 intel addr16 jcxz .+0x11
+67e311|223344556677885f5f5f5f5f5f 32 plan9 JCXZ .+17
+67e311|223344556677885f5f5f5f5f5f 64 gnu jecxz .+0x11
+67e311|223344556677885f5f5f5f5f5f 64 intel addr32 jecxz .+0x11
+67e311|223344556677885f5f5f5f5f5f 64 plan9 JECXZ .+17
+6811223344|556677885f5f5f5f5f5f5f 32 intel push 0x44332211
+6811223344|556677885f5f5f5f5f5f5f 32 plan9 PUSHL $0x44332211
+6811223344|556677885f5f5f5f5f5f5f 64 gnu pushq $0x44332211
+6811223344|556677885f5f5f5f5f5f5f 64 intel push 0x44332211
+6811223344|556677885f5f5f5f5f5f5f 64 plan9 PUSHL $0x44332211
+691122334455|6677885f5f5f5f5f5f5f 32 intel imul edx, dword ptr [ecx], 0x55443322
+691122334455|6677885f5f5f5f5f5f5f 32 plan9 IMULL $0x55443322, 0(CX), DX
+691122334455|6677885f5f5f5f5f5f5f 64 gnu imul $0x55443322,(%rcx),%edx
+691122334455|6677885f5f5f5f5f5f5f 64 intel imul edx, dword ptr [rcx], 0x55443322
+691122334455|6677885f5f5f5f5f5f5f 64 plan9 IMULL $0x55443322, 0(CX), DX
+6a11|223344556677885f5f5f5f5f5f5f 32 intel push 0x11
+6a11|223344556677885f5f5f5f5f5f5f 32 plan9 PUSHL $0x11
+6a11|223344556677885f5f5f5f5f5f5f 64 gnu pushq $0x11
+6a11|223344556677885f5f5f5f5f5f5f 64 intel push 0x11
+6a11|223344556677885f5f5f5f5f5f5f 64 plan9 PUSHL $0x11
+6b1122|3344556677885f5f5f5f5f5f5f 32 intel imul edx, dword ptr [ecx], 0x22
+6b1122|3344556677885f5f5f5f5f5f5f 32 plan9 IMULL $0x22, 0(CX), DX
+6b1122|3344556677885f5f5f5f5f5f5f 64 gnu imul $0x22,(%rcx),%edx
+6b1122|3344556677885f5f5f5f5f5f5f 64 intel imul edx, dword ptr [rcx], 0x22
+6b1122|3344556677885f5f5f5f5f5f5f 64 plan9 IMULL $0x22, 0(CX), DX
+6d|11223344556677885f5f5f5f5f5f5f 32 intel insd
+6d|11223344556677885f5f5f5f5f5f5f 32 plan9 INSD DX, ES:0(DI)
+6d|11223344556677885f5f5f5f5f5f5f 64 gnu insl (%dx),%es:(%rdi)
+6d|11223344556677885f5f5f5f5f5f5f 64 intel insd
+6d|11223344556677885f5f5f5f5f5f5f 64 plan9 INSD DX, ES:0(DI)
+6f|11223344556677885f5f5f5f5f5f5f 32 intel outsd
+6f|11223344556677885f5f5f5f5f5f5f 32 plan9 OUTSD DS:0(SI), DX
+6f|11223344556677885f5f5f5f5f5f5f 64 gnu outsl %ds:(%rsi),(%dx)
+6f|11223344556677885f5f5f5f5f5f5f 64 intel outsd
+6f|11223344556677885f5f5f5f5f5f5f 64 plan9 OUTSD DS:0(SI), DX
+7111|223344556677885f5f5f5f5f5f5f 32 intel jno .+0x11
+7111|223344556677885f5f5f5f5f5f5f 32 plan9 JNO .+17
+7111|223344556677885f5f5f5f5f5f5f 64 gnu jno .+0x11
+7111|223344556677885f5f5f5f5f5f5f 64 intel jno .+0x11
+7111|223344556677885f5f5f5f5f5f5f 64 plan9 JNO .+17
+7211|223344556677885f5f5f5f5f5f5f 32 intel jb .+0x11
+7211|223344556677885f5f5f5f5f5f5f 32 plan9 JB .+17
+7211|223344556677885f5f5f5f5f5f5f 64 gnu jb .+0x11
+7211|223344556677885f5f5f5f5f5f5f 64 intel jb .+0x11
+7211|223344556677885f5f5f5f5f5f5f 64 plan9 JB .+17
+7311|223344556677885f5f5f5f5f5f5f 32 intel jnb .+0x11
+7311|223344556677885f5f5f5f5f5f5f 32 plan9 JAE .+17
+7311|223344556677885f5f5f5f5f5f5f 64 gnu jae .+0x11
+7311|223344556677885f5f5f5f5f5f5f 64 intel jnb .+0x11
+7311|223344556677885f5f5f5f5f5f5f 64 plan9 JAE .+17
+7411|223344556677885f5f5f5f5f5f5f 32 intel jz .+0x11
+7411|223344556677885f5f5f5f5f5f5f 32 plan9 JE .+17
+7411|223344556677885f5f5f5f5f5f5f 64 gnu je .+0x11
+7411|223344556677885f5f5f5f5f5f5f 64 intel jz .+0x11
+7411|223344556677885f5f5f5f5f5f5f 64 plan9 JE .+17
+7511|223344556677885f5f5f5f5f5f5f 32 intel jnz .+0x11
+7511|223344556677885f5f5f5f5f5f5f 32 plan9 JNE .+17
+7511|223344556677885f5f5f5f5f5f5f 64 gnu jne .+0x11
+7511|223344556677885f5f5f5f5f5f5f 64 intel jnz .+0x11
+7511|223344556677885f5f5f5f5f5f5f 64 plan9 JNE .+17
+7611|223344556677885f5f5f5f5f5f5f 32 intel jbe .+0x11
+7611|223344556677885f5f5f5f5f5f5f 32 plan9 JBE .+17
+7611|223344556677885f5f5f5f5f5f5f 64 gnu jbe .+0x11
+7611|223344556677885f5f5f5f5f5f5f 64 intel jbe .+0x11
+7611|223344556677885f5f5f5f5f5f5f 64 plan9 JBE .+17
+7711|223344556677885f5f5f5f5f5f5f 32 intel jnbe .+0x11
+7711|223344556677885f5f5f5f5f5f5f 32 plan9 JA .+17
+7711|223344556677885f5f5f5f5f5f5f 64 gnu ja .+0x11
+7711|223344556677885f5f5f5f5f5f5f 64 intel jnbe .+0x11
+7711|223344556677885f5f5f5f5f5f5f 64 plan9 JA .+17
+7811|223344556677885f5f5f5f5f5f5f 32 intel js .+0x11
+7811|223344556677885f5f5f5f5f5f5f 32 plan9 JS .+17
+7811|223344556677885f5f5f5f5f5f5f 64 gnu js .+0x11
+7811|223344556677885f5f5f5f5f5f5f 64 intel js .+0x11
+7811|223344556677885f5f5f5f5f5f5f 64 plan9 JS .+17
+7911|223344556677885f5f5f5f5f5f5f 32 intel jns .+0x11
+7911|223344556677885f5f5f5f5f5f5f 32 plan9 JNS .+17
+7911|223344556677885f5f5f5f5f5f5f 64 gnu jns .+0x11
+7911|223344556677885f5f5f5f5f5f5f 64 intel jns .+0x11
+7911|223344556677885f5f5f5f5f5f5f 64 plan9 JNS .+17
+7a11|223344556677885f5f5f5f5f5f5f 32 intel jp .+0x11
+7a11|223344556677885f5f5f5f5f5f5f 32 plan9 JP .+17
+7a11|223344556677885f5f5f5f5f5f5f 64 gnu jp .+0x11
+7a11|223344556677885f5f5f5f5f5f5f 64 intel jp .+0x11
+7a11|223344556677885f5f5f5f5f5f5f 64 plan9 JP .+17
+7b11|223344556677885f5f5f5f5f5f5f 32 intel jnp .+0x11
+7b11|223344556677885f5f5f5f5f5f5f 32 plan9 JNP .+17
+7b11|223344556677885f5f5f5f5f5f5f 64 gnu jnp .+0x11
+7b11|223344556677885f5f5f5f5f5f5f 64 intel jnp .+0x11
+7b11|223344556677885f5f5f5f5f5f5f 64 plan9 JNP .+17
+7c11|223344556677885f5f5f5f5f5f5f 32 intel jl .+0x11
+7c11|223344556677885f5f5f5f5f5f5f 32 plan9 JL .+17
+7c11|223344556677885f5f5f5f5f5f5f 64 gnu jl .+0x11
+7c11|223344556677885f5f5f5f5f5f5f 64 intel jl .+0x11
+7c11|223344556677885f5f5f5f5f5f5f 64 plan9 JL .+17
+7d11|223344556677885f5f5f5f5f5f5f 32 intel jnl .+0x11
+7d11|223344556677885f5f5f5f5f5f5f 32 plan9 JGE .+17
+7d11|223344556677885f5f5f5f5f5f5f 64 gnu jge .+0x11
+7d11|223344556677885f5f5f5f5f5f5f 64 intel jnl .+0x11
+7d11|223344556677885f5f5f5f5f5f5f 64 plan9 JGE .+17
+7e11|223344556677885f5f5f5f5f5f5f 32 intel jle .+0x11
+7e11|223344556677885f5f5f5f5f5f5f 32 plan9 JLE .+17
+7e11|223344556677885f5f5f5f5f5f5f 64 gnu jle .+0x11
+7e11|223344556677885f5f5f5f5f5f5f 64 intel jle .+0x11
+7e11|223344556677885f5f5f5f5f5f5f 64 plan9 JLE .+17
+7f11|223344556677885f5f5f5f5f5f5f 32 intel jnle .+0x11
+7f11|223344556677885f5f5f5f5f5f5f 32 plan9 JG .+17
+7f11|223344556677885f5f5f5f5f5f5f 64 gnu jg .+0x11
+7f11|223344556677885f5f5f5f5f5f5f 64 intel jnle .+0x11
+7f11|223344556677885f5f5f5f5f5f5f 64 plan9 JG .+17
+800011|223344556677885f5f5f5f5f5f 32 intel add byte ptr [eax], 0x11
+800011|223344556677885f5f5f5f5f5f 32 plan9 ADDL $0x11, 0(AX)
+800011|223344556677885f5f5f5f5f5f 64 gnu addb $0x11,(%rax)
+800011|223344556677885f5f5f5f5f5f 64 intel add byte ptr [rax], 0x11
+800011|223344556677885f5f5f5f5f5f 64 plan9 ADDL $0x11, 0(AX)
+800811|223344556677885f5f5f5f5f5f 32 intel or byte ptr [eax], 0x11
+800811|223344556677885f5f5f5f5f5f 32 plan9 ORL $0x11, 0(AX)
+800811|223344556677885f5f5f5f5f5f 64 gnu orb $0x11,(%rax)
+800811|223344556677885f5f5f5f5f5f 64 intel or byte ptr [rax], 0x11
+800811|223344556677885f5f5f5f5f5f 64 plan9 ORL $0x11, 0(AX)
+801122|3344556677885f5f5f5f5f5f5f 32 intel adc byte ptr [ecx], 0x22
+801122|3344556677885f5f5f5f5f5f5f 32 plan9 ADCL $0x22, 0(CX)
+801122|3344556677885f5f5f5f5f5f5f 64 gnu adcb $0x22,(%rcx)
+801122|3344556677885f5f5f5f5f5f5f 64 intel adc byte ptr [rcx], 0x22
+801122|3344556677885f5f5f5f5f5f5f 64 plan9 ADCL $0x22, 0(CX)
+801811|223344556677885f5f5f5f5f5f 32 intel sbb byte ptr [eax], 0x11
+801811|223344556677885f5f5f5f5f5f 32 plan9 SBBL $0x11, 0(AX)
+801811|223344556677885f5f5f5f5f5f 64 gnu sbbb $0x11,(%rax)
+801811|223344556677885f5f5f5f5f5f 64 intel sbb byte ptr [rax], 0x11
+801811|223344556677885f5f5f5f5f5f 64 plan9 SBBL $0x11, 0(AX)
+802011|223344556677885f5f5f5f5f5f 32 intel and byte ptr [eax], 0x11
+802011|223344556677885f5f5f5f5f5f 32 plan9 ANDL $0x11, 0(AX)
+802011|223344556677885f5f5f5f5f5f 64 gnu andb $0x11,(%rax)
+802011|223344556677885f5f5f5f5f5f 64 intel and byte ptr [rax], 0x11
+802011|223344556677885f5f5f5f5f5f 64 plan9 ANDL $0x11, 0(AX)
+802811|223344556677885f5f5f5f5f5f 32 intel sub byte ptr [eax], 0x11
+802811|223344556677885f5f5f5f5f5f 32 plan9 SUBL $0x11, 0(AX)
+802811|223344556677885f5f5f5f5f5f 64 gnu subb $0x11,(%rax)
+802811|223344556677885f5f5f5f5f5f 64 intel sub byte ptr [rax], 0x11
+802811|223344556677885f5f5f5f5f5f 64 plan9 SUBL $0x11, 0(AX)
+803011|223344556677885f5f5f5f5f5f 32 intel xor byte ptr [eax], 0x11
+803011|223344556677885f5f5f5f5f5f 32 plan9 XORL $0x11, 0(AX)
+803011|223344556677885f5f5f5f5f5f 64 gnu xorb $0x11,(%rax)
+803011|223344556677885f5f5f5f5f5f 64 intel xor byte ptr [rax], 0x11
+803011|223344556677885f5f5f5f5f5f 64 plan9 XORL $0x11, 0(AX)
+803811|223344556677885f5f5f5f5f5f 32 intel cmp byte ptr [eax], 0x11
+803811|223344556677885f5f5f5f5f5f 32 plan9 CMPL $0x11, 0(AX)
+803811|223344556677885f5f5f5f5f5f 64 gnu cmpb $0x11,(%rax)
+803811|223344556677885f5f5f5f5f5f 64 intel cmp byte ptr [rax], 0x11
+803811|223344556677885f5f5f5f5f5f 64 plan9 CMPL $0x11, 0(AX)
+810011223344|556677885f5f5f5f5f5f 32 intel add dword ptr [eax], 0x44332211
+810011223344|556677885f5f5f5f5f5f 32 plan9 ADDL $0x44332211, 0(AX)
+810011223344|556677885f5f5f5f5f5f 64 gnu addl $0x44332211,(%rax)
+810011223344|556677885f5f5f5f5f5f 64 intel add dword ptr [rax], 0x44332211
+810011223344|556677885f5f5f5f5f5f 64 plan9 ADDL $0x44332211, 0(AX)
+810811223344|556677885f5f5f5f5f5f 32 intel or dword ptr [eax], 0x44332211
+810811223344|556677885f5f5f5f5f5f 32 plan9 ORL $0x44332211, 0(AX)
+810811223344|556677885f5f5f5f5f5f 64 gnu orl $0x44332211,(%rax)
+810811223344|556677885f5f5f5f5f5f 64 intel or dword ptr [rax], 0x44332211
+810811223344|556677885f5f5f5f5f5f 64 plan9 ORL $0x44332211, 0(AX)
+811122334455|6677885f5f5f5f5f5f5f 32 intel adc dword ptr [ecx], 0x55443322
+811122334455|6677885f5f5f5f5f5f5f 32 plan9 ADCL $0x55443322, 0(CX)
+811122334455|6677885f5f5f5f5f5f5f 64 gnu adcl $0x55443322,(%rcx)
+811122334455|6677885f5f5f5f5f5f5f 64 intel adc dword ptr [rcx], 0x55443322
+811122334455|6677885f5f5f5f5f5f5f 64 plan9 ADCL $0x55443322, 0(CX)
+811811223344|556677885f5f5f5f5f5f 32 intel sbb dword ptr [eax], 0x44332211
+811811223344|556677885f5f5f5f5f5f 32 plan9 SBBL $0x44332211, 0(AX)
+811811223344|556677885f5f5f5f5f5f 64 gnu sbbl $0x44332211,(%rax)
+811811223344|556677885f5f5f5f5f5f 64 intel sbb dword ptr [rax], 0x44332211
+811811223344|556677885f5f5f5f5f5f 64 plan9 SBBL $0x44332211, 0(AX)
+812011223344|556677885f5f5f5f5f5f 32 intel and dword ptr [eax], 0x44332211
+812011223344|556677885f5f5f5f5f5f 32 plan9 ANDL $0x44332211, 0(AX)
+812011223344|556677885f5f5f5f5f5f 64 gnu andl $0x44332211,(%rax)
+812011223344|556677885f5f5f5f5f5f 64 intel and dword ptr [rax], 0x44332211
+812011223344|556677885f5f5f5f5f5f 64 plan9 ANDL $0x44332211, 0(AX)
+812811223344|556677885f5f5f5f5f5f 32 intel sub dword ptr [eax], 0x44332211
+812811223344|556677885f5f5f5f5f5f 32 plan9 SUBL $0x44332211, 0(AX)
+812811223344|556677885f5f5f5f5f5f 64 gnu subl $0x44332211,(%rax)
+812811223344|556677885f5f5f5f5f5f 64 intel sub dword ptr [rax], 0x44332211
+812811223344|556677885f5f5f5f5f5f 64 plan9 SUBL $0x44332211, 0(AX)
+813011223344|556677885f5f5f5f5f5f 32 intel xor dword ptr [eax], 0x44332211
+813011223344|556677885f5f5f5f5f5f 32 plan9 XORL $0x44332211, 0(AX)
+813011223344|556677885f5f5f5f5f5f 64 gnu xorl $0x44332211,(%rax)
+813011223344|556677885f5f5f5f5f5f 64 intel xor dword ptr [rax], 0x44332211
+813011223344|556677885f5f5f5f5f5f 64 plan9 XORL $0x44332211, 0(AX)
+813811223344|556677885f5f5f5f5f5f 32 intel cmp dword ptr [eax], 0x44332211
+813811223344|556677885f5f5f5f5f5f 32 plan9 CMPL $0x44332211, 0(AX)
+813811223344|556677885f5f5f5f5f5f 64 gnu cmpl $0x44332211,(%rax)
+813811223344|556677885f5f5f5f5f5f 64 intel cmp dword ptr [rax], 0x44332211
+813811223344|556677885f5f5f5f5f5f 64 plan9 CMPL $0x44332211, 0(AX)
+830011|223344556677885f5f5f5f5f5f 32 intel add dword ptr [eax], 0x11
+830011|223344556677885f5f5f5f5f5f 32 plan9 ADDL $0x11, 0(AX)
+830011|223344556677885f5f5f5f5f5f 64 gnu addl $0x11,(%rax)
+830011|223344556677885f5f5f5f5f5f 64 intel add dword ptr [rax], 0x11
+830011|223344556677885f5f5f5f5f5f 64 plan9 ADDL $0x11, 0(AX)
+830811|223344556677885f5f5f5f5f5f 32 intel or dword ptr [eax], 0x11
+830811|223344556677885f5f5f5f5f5f 32 plan9 ORL $0x11, 0(AX)
+830811|223344556677885f5f5f5f5f5f 64 gnu orl $0x11,(%rax)
+830811|223344556677885f5f5f5f5f5f 64 intel or dword ptr [rax], 0x11
+830811|223344556677885f5f5f5f5f5f 64 plan9 ORL $0x11, 0(AX)
+831122|3344556677885f5f5f5f5f5f5f 32 intel adc dword ptr [ecx], 0x22
+831122|3344556677885f5f5f5f5f5f5f 32 plan9 ADCL $0x22, 0(CX)
+831122|3344556677885f5f5f5f5f5f5f 64 gnu adcl $0x22,(%rcx)
+831122|3344556677885f5f5f5f5f5f5f 64 intel adc dword ptr [rcx], 0x22
+831122|3344556677885f5f5f5f5f5f5f 64 plan9 ADCL $0x22, 0(CX)
+831811|223344556677885f5f5f5f5f5f 32 intel sbb dword ptr [eax], 0x11
+831811|223344556677885f5f5f5f5f5f 32 plan9 SBBL $0x11, 0(AX)
+831811|223344556677885f5f5f5f5f5f 64 gnu sbbl $0x11,(%rax)
+831811|223344556677885f5f5f5f5f5f 64 intel sbb dword ptr [rax], 0x11
+831811|223344556677885f5f5f5f5f5f 64 plan9 SBBL $0x11, 0(AX)
+832011|223344556677885f5f5f5f5f5f 32 intel and dword ptr [eax], 0x11
+832011|223344556677885f5f5f5f5f5f 32 plan9 ANDL $0x11, 0(AX)
+832011|223344556677885f5f5f5f5f5f 64 gnu andl $0x11,(%rax)
+832011|223344556677885f5f5f5f5f5f 64 intel and dword ptr [rax], 0x11
+832011|223344556677885f5f5f5f5f5f 64 plan9 ANDL $0x11, 0(AX)
+832811|223344556677885f5f5f5f5f5f 32 intel sub dword ptr [eax], 0x11
+832811|223344556677885f5f5f5f5f5f 32 plan9 SUBL $0x11, 0(AX)
+832811|223344556677885f5f5f5f5f5f 64 gnu subl $0x11,(%rax)
+832811|223344556677885f5f5f5f5f5f 64 intel sub dword ptr [rax], 0x11
+832811|223344556677885f5f5f5f5f5f 64 plan9 SUBL $0x11, 0(AX)
+833011|223344556677885f5f5f5f5f5f 32 intel xor dword ptr [eax], 0x11
+833011|223344556677885f5f5f5f5f5f 32 plan9 XORL $0x11, 0(AX)
+833011|223344556677885f5f5f5f5f5f 64 gnu xorl $0x11,(%rax)
+833011|223344556677885f5f5f5f5f5f 64 intel xor dword ptr [rax], 0x11
+833011|223344556677885f5f5f5f5f5f 64 plan9 XORL $0x11, 0(AX)
+833811|223344556677885f5f5f5f5f5f 32 intel cmp dword ptr [eax], 0x11
+833811|223344556677885f5f5f5f5f5f 32 plan9 CMPL $0x11, 0(AX)
+833811|223344556677885f5f5f5f5f5f 64 gnu cmpl $0x11,(%rax)
+833811|223344556677885f5f5f5f5f5f 64 intel cmp dword ptr [rax], 0x11
+833811|223344556677885f5f5f5f5f5f 64 plan9 CMPL $0x11, 0(AX)
+8411|223344556677885f5f5f5f5f5f5f 32 intel test byte ptr [ecx], dl
+8411|223344556677885f5f5f5f5f5f5f 32 plan9 TESTL DL, 0(CX)
+8411|223344556677885f5f5f5f5f5f5f 64 gnu test %dl,(%rcx)
+8411|223344556677885f5f5f5f5f5f5f 64 intel test byte ptr [rcx], dl
+8411|223344556677885f5f5f5f5f5f5f 64 plan9 TESTL DL, 0(CX)
+8511|223344556677885f5f5f5f5f5f5f 32 intel test dword ptr [ecx], edx
+8511|223344556677885f5f5f5f5f5f5f 32 plan9 TESTL DX, 0(CX)
+8511|223344556677885f5f5f5f5f5f5f 64 gnu test %edx,(%rcx)
+8511|223344556677885f5f5f5f5f5f5f 64 intel test dword ptr [rcx], edx
+8511|223344556677885f5f5f5f5f5f5f 64 plan9 TESTL DX, 0(CX)
+8611|223344556677885f5f5f5f5f5f5f 32 intel xchg byte ptr [ecx], dl
+8611|223344556677885f5f5f5f5f5f5f 32 plan9 XCHGL DL, 0(CX)
+8611|223344556677885f5f5f5f5f5f5f 64 gnu xchg %dl,(%rcx)
+8611|223344556677885f5f5f5f5f5f5f 64 intel xchg byte ptr [rcx], dl
+8611|223344556677885f5f5f5f5f5f5f 64 plan9 XCHGL DL, 0(CX)
+8711|223344556677885f5f5f5f5f5f5f 32 intel xchg dword ptr [ecx], edx
+8711|223344556677885f5f5f5f5f5f5f 32 plan9 XCHGL DX, 0(CX)
+8711|223344556677885f5f5f5f5f5f5f 64 gnu xchg %edx,(%rcx)
+8711|223344556677885f5f5f5f5f5f5f 64 intel xchg dword ptr [rcx], edx
+8711|223344556677885f5f5f5f5f5f5f 64 plan9 XCHGL DX, 0(CX)
+8811|223344556677885f5f5f5f5f5f5f 32 intel mov byte ptr [ecx], dl
+8811|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL DL, 0(CX)
+8811|223344556677885f5f5f5f5f5f5f 64 gnu mov %dl,(%rcx)
+8811|223344556677885f5f5f5f5f5f5f 64 intel mov byte ptr [rcx], dl
+8811|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL DL, 0(CX)
+8911|223344556677885f5f5f5f5f5f5f 32 intel mov dword ptr [ecx], edx
+8911|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL DX, 0(CX)
+8911|223344556677885f5f5f5f5f5f5f 64 gnu mov %edx,(%rcx)
+8911|223344556677885f5f5f5f5f5f5f 64 intel mov dword ptr [rcx], edx
+8911|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL DX, 0(CX)
+8a11|223344556677885f5f5f5f5f5f5f 32 intel mov dl, byte ptr [ecx]
+8a11|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL 0(CX), DL
+8a11|223344556677885f5f5f5f5f5f5f 64 gnu mov (%rcx),%dl
+8a11|223344556677885f5f5f5f5f5f5f 64 intel mov dl, byte ptr [rcx]
+8a11|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL 0(CX), DL
+8b11|223344556677885f5f5f5f5f5f5f 32 intel mov edx, dword ptr [ecx]
+8b11|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL 0(CX), DX
+8b11|223344556677885f5f5f5f5f5f5f 64 gnu mov (%rcx),%edx
+8b11|223344556677885f5f5f5f5f5f5f 64 intel mov edx, dword ptr [rcx]
+8b11|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL 0(CX), DX
+8c11|223344556677885f5f5f5f5f5f5f 32 intel mov word ptr [ecx], ss
+8c11|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL SS, 0(CX)
+8c11|223344556677885f5f5f5f5f5f5f 64 gnu mov %ss,(%rcx)
+8c11|223344556677885f5f5f5f5f5f5f 64 intel mov word ptr [rcx], ss
+8c11|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL SS, 0(CX)
+8d11|223344556677885f5f5f5f5f5f5f 32 intel lea edx, ptr [ecx]
+8d11|223344556677885f5f5f5f5f5f5f 32 plan9 LEAL 0(CX), DX
+8d11|223344556677885f5f5f5f5f5f5f 64 gnu lea (%rcx),%edx
+8d11|223344556677885f5f5f5f5f5f5f 64 intel lea edx, ptr [rcx]
+8d11|223344556677885f5f5f5f5f5f5f 64 plan9 LEAL 0(CX), DX
+8e11|223344556677885f5f5f5f5f5f5f 32 intel mov ss, word ptr [ecx]
+8e11|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL 0(CX), SS
+8e11|223344556677885f5f5f5f5f5f5f 64 gnu mov (%rcx),%ss
+8e11|223344556677885f5f5f5f5f5f5f 64 intel mov ss, word ptr [rcx]
+8e11|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL 0(CX), SS
+8f00|11223344556677885f5f5f5f5f5f 32 intel pop dword ptr [eax]
+8f00|11223344556677885f5f5f5f5f5f 32 plan9 POPL 0(AX)
+8f00|11223344556677885f5f5f5f5f5f 64 gnu popq (%rax)
+8f00|11223344556677885f5f5f5f5f5f 64 intel pop qword ptr [rax]
+8f00|11223344556677885f5f5f5f5f5f 64 plan9 POPL 0(AX)
+91|11223344556677885f5f5f5f5f5f5f 32 intel xchg ecx, eax
+91|11223344556677885f5f5f5f5f5f5f 32 plan9 XCHGL AX, CX
+91|11223344556677885f5f5f5f5f5f5f 64 intel xchg ecx, eax
+91|11223344556677885f5f5f5f5f5f5f 64 plan9 XCHGL AX, CX
+98|11223344556677885f5f5f5f5f5f5f 32 intel cwde
+98|11223344556677885f5f5f5f5f5f5f 32 plan9 CWDE
+98|11223344556677885f5f5f5f5f5f5f 64 gnu cwtl
+98|11223344556677885f5f5f5f5f5f5f 64 intel cwde
+98|11223344556677885f5f5f5f5f5f5f 64 plan9 CWDE
+99|11223344556677885f5f5f5f5f5f5f 32 intel cdq
+99|11223344556677885f5f5f5f5f5f5f 32 plan9 CDQ
+99|11223344556677885f5f5f5f5f5f5f 64 gnu cltd
+99|11223344556677885f5f5f5f5f5f5f 64 intel cdq
+99|11223344556677885f5f5f5f5f5f5f 64 plan9 CDQ
+9a112233445566|77885f5f5f5f5f5f5f 32 intel call far 0x44332211, 0x6655
+9a112233445566|77885f5f5f5f5f5f5f 32 plan9 LCALL $0x44332211, $0x6655
+9b|11223344556677885f5f5f5f5f5f5f 32 intel fwait
+9b|11223344556677885f5f5f5f5f5f5f 32 plan9 FWAIT
+9b|11223344556677885f5f5f5f5f5f5f 64 gnu fwait
+9b|11223344556677885f5f5f5f5f5f5f 64 intel fwait
+9b|11223344556677885f5f5f5f5f5f5f 64 plan9 FWAIT
+9c|11223344556677885f5f5f5f5f5f5f 32 intel pushfd
+9c|11223344556677885f5f5f5f5f5f5f 32 plan9 PUSHFD
+9c|11223344556677885f5f5f5f5f5f5f 64 gnu pushfq
+9c|11223344556677885f5f5f5f5f5f5f 64 intel pushfq
+9c|11223344556677885f5f5f5f5f5f5f 64 plan9 PUSHFQ
+9d|11223344556677885f5f5f5f5f5f5f 32 intel popfd
+9d|11223344556677885f5f5f5f5f5f5f 32 plan9 POPFD
+9d|11223344556677885f5f5f5f5f5f5f 64 gnu popfq
+9d|11223344556677885f5f5f5f5f5f5f 64 intel popfq
+9d|11223344556677885f5f5f5f5f5f5f 64 plan9 POPFQ
+9e|11223344556677885f5f5f5f5f5f5f 32 intel sahf
+9e|11223344556677885f5f5f5f5f5f5f 32 plan9 SAHF
+9e|11223344556677885f5f5f5f5f5f5f 64 gnu sahf
+9e|11223344556677885f5f5f5f5f5f5f 64 intel sahf
+9e|11223344556677885f5f5f5f5f5f5f 64 plan9 SAHF
+9f|11223344556677885f5f5f5f5f5f5f 32 intel lahf
+9f|11223344556677885f5f5f5f5f5f5f 32 plan9 LAHF
+9f|11223344556677885f5f5f5f5f5f5f 64 gnu lahf
+9f|11223344556677885f5f5f5f5f5f5f 64 intel lahf
+9f|11223344556677885f5f5f5f5f5f5f 64 plan9 LAHF
+a11122334455667788|5f5f5f5f5f5f5f 64 gnu mov -0x778899aabbccddef,%eax
+a11122334455667788|5f5f5f5f5f5f5f 64 intel mov eax, dword ptr [0x8877665544332211]
+a11122334455667788|5f5f5f5f5f5f5f 64 plan9 MOVL -0x778899aabbccddef, AX
+a111223344|556677885f5f5f5f5f5f5f 32 intel mov eax, dword ptr [0x44332211]
+a111223344|556677885f5f5f5f5f5f5f 32 plan9 MOVL 0x44332211, AX
+a21122334455667788|5f5f5f5f5f5f5f 64 gnu mov %al,-0x778899aabbccddef
+a21122334455667788|5f5f5f5f5f5f5f 64 intel mov byte ptr [0x8877665544332211], al
+a21122334455667788|5f5f5f5f5f5f5f 64 plan9 MOVL AL, -0x778899aabbccddef
+a211223344|556677885f5f5f5f5f5f5f 32 intel mov byte ptr [0x44332211], al
+a211223344|556677885f5f5f5f5f5f5f 32 plan9 MOVL AL, 0x44332211
+a31122334455667788|5f5f5f5f5f5f5f 64 gnu mov %eax,-0x778899aabbccddef
+a31122334455667788|5f5f5f5f5f5f5f 64 intel mov dword ptr [0x8877665544332211], eax
+a31122334455667788|5f5f5f5f5f5f5f 64 plan9 MOVL AX, -0x778899aabbccddef
+a311223344|556677885f5f5f5f5f5f5f 32 intel mov dword ptr [0x44332211], eax
+a311223344|556677885f5f5f5f5f5f5f 32 plan9 MOVL AX, 0x44332211
+a4|11223344556677885f5f5f5f5f5f5f 32 intel movsb byte ptr [edi], byte ptr [esi]
+a4|11223344556677885f5f5f5f5f5f5f 32 plan9 MOVSB DS:0(SI), ES:0(DI)
+a4|11223344556677885f5f5f5f5f5f5f 64 gnu movsb %ds:(%rsi),%es:(%rdi)
+a4|11223344556677885f5f5f5f5f5f5f 64 intel movsb byte ptr [rdi], byte ptr [rsi]
+a4|11223344556677885f5f5f5f5f5f5f 64 plan9 MOVSB DS:0(SI), ES:0(DI)
+a5|11223344556677885f5f5f5f5f5f5f 32 intel movsd dword ptr [edi], dword ptr [esi]
+a5|11223344556677885f5f5f5f5f5f5f 32 plan9 MOVSD DS:0(SI), ES:0(DI)
+a5|11223344556677885f5f5f5f5f5f5f 64 gnu movsl %ds:(%rsi),%es:(%rdi)
+a5|11223344556677885f5f5f5f5f5f5f 64 intel movsd dword ptr [rdi], dword ptr [rsi]
+a5|11223344556677885f5f5f5f5f5f5f 64 plan9 MOVSD DS:0(SI), ES:0(DI)
+a6|11223344556677885f5f5f5f5f5f5f 32 intel cmpsb byte ptr [esi], byte ptr [edi]
+a6|11223344556677885f5f5f5f5f5f5f 32 plan9 CMPSB ES:0(DI), DS:0(SI)
+a6|11223344556677885f5f5f5f5f5f5f 64 gnu cmpsb %es:(%rdi),%ds:(%rsi)
+a6|11223344556677885f5f5f5f5f5f5f 64 intel cmpsb byte ptr [rsi], byte ptr [rdi]
+a6|11223344556677885f5f5f5f5f5f5f 64 plan9 CMPSB ES:0(DI), DS:0(SI)
+a7|11223344556677885f5f5f5f5f5f5f 32 intel cmpsd dword ptr [esi], dword ptr [edi]
+a7|11223344556677885f5f5f5f5f5f5f 32 plan9 CMPSD ES:0(DI), DS:0(SI)
+a7|11223344556677885f5f5f5f5f5f5f 64 gnu cmpsl %es:(%rdi),%ds:(%rsi)
+a7|11223344556677885f5f5f5f5f5f5f 64 intel cmpsd dword ptr [rsi], dword ptr [rdi]
+a7|11223344556677885f5f5f5f5f5f5f 64 plan9 CMPSD ES:0(DI), DS:0(SI)
+a811|223344556677885f5f5f5f5f5f5f 32 intel test al, 0x11
+a811|223344556677885f5f5f5f5f5f5f 32 plan9 TESTL $0x11, AL
+a811|223344556677885f5f5f5f5f5f5f 64 gnu test $0x11,%al
+a811|223344556677885f5f5f5f5f5f5f 64 intel test al, 0x11
+a811|223344556677885f5f5f5f5f5f5f 64 plan9 TESTL $0x11, AL
+a911223344|556677885f5f5f5f5f5f5f 32 intel test eax, 0x44332211
+a911223344|556677885f5f5f5f5f5f5f 32 plan9 TESTL $0x44332211, AX
+a911223344|556677885f5f5f5f5f5f5f 64 gnu test $0x44332211,%eax
+a911223344|556677885f5f5f5f5f5f5f 64 intel test eax, 0x44332211
+a911223344|556677885f5f5f5f5f5f5f 64 plan9 TESTL $0x44332211, AX
+aa|11223344556677885f5f5f5f5f5f5f 32 intel stosb byte ptr [edi]
+aa|11223344556677885f5f5f5f5f5f5f 32 plan9 STOSB AL, ES:0(DI)
+aa|11223344556677885f5f5f5f5f5f5f 64 gnu stos %al,%es:(%rdi)
+aa|11223344556677885f5f5f5f5f5f5f 64 intel stosb byte ptr [rdi]
+aa|11223344556677885f5f5f5f5f5f5f 64 plan9 STOSB AL, ES:0(DI)
+ab|11223344556677885f5f5f5f5f5f5f 32 intel stosd dword ptr [edi]
+ab|11223344556677885f5f5f5f5f5f5f 32 plan9 STOSD AX, ES:0(DI)
+ab|11223344556677885f5f5f5f5f5f5f 64 gnu stos %eax,%es:(%rdi)
+ab|11223344556677885f5f5f5f5f5f5f 64 intel stosd dword ptr [rdi]
+ab|11223344556677885f5f5f5f5f5f5f 64 plan9 STOSD AX, ES:0(DI)
+ac|11223344556677885f5f5f5f5f5f5f 32 intel lodsb byte ptr [esi]
+ac|11223344556677885f5f5f5f5f5f5f 32 plan9 LODSB DS:0(SI), AL
+ac|11223344556677885f5f5f5f5f5f5f 64 gnu lods %ds:(%rsi),%al
+ac|11223344556677885f5f5f5f5f5f5f 64 intel lodsb byte ptr [rsi]
+ac|11223344556677885f5f5f5f5f5f5f 64 plan9 LODSB DS:0(SI), AL
+ad|11223344556677885f5f5f5f5f5f5f 32 intel lodsd dword ptr [esi]
+ad|11223344556677885f5f5f5f5f5f5f 32 plan9 LODSD DS:0(SI), AX
+ad|11223344556677885f5f5f5f5f5f5f 64 gnu lods %ds:(%rsi),%eax
+ad|11223344556677885f5f5f5f5f5f5f 64 intel lodsd dword ptr [rsi]
+ad|11223344556677885f5f5f5f5f5f5f 64 plan9 LODSD DS:0(SI), AX
+ae|11223344556677885f5f5f5f5f5f5f 32 intel scasb byte ptr [edi]
+ae|11223344556677885f5f5f5f5f5f5f 32 plan9 SCASB ES:0(DI), AL
+ae|11223344556677885f5f5f5f5f5f5f 64 gnu scas %es:(%rdi),%al
+ae|11223344556677885f5f5f5f5f5f5f 64 intel scasb byte ptr [rdi]
+ae|11223344556677885f5f5f5f5f5f5f 64 plan9 SCASB ES:0(DI), AL
+af|11223344556677885f5f5f5f5f5f5f 32 intel scasd dword ptr [edi]
+af|11223344556677885f5f5f5f5f5f5f 32 plan9 SCASD ES:0(DI), AX
+af|11223344556677885f5f5f5f5f5f5f 64 gnu scas %es:(%rdi),%eax
+af|11223344556677885f5f5f5f5f5f5f 64 intel scasd dword ptr [rdi]
+af|11223344556677885f5f5f5f5f5f5f 64 plan9 SCASD ES:0(DI), AX
+b011|223344556677885f5f5f5f5f5f5f 32 intel mov al, 0x11
+b011|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL $0x11, AL
+b011|223344556677885f5f5f5f5f5f5f 64 gnu mov $0x11,%al
+b011|223344556677885f5f5f5f5f5f5f 64 intel mov al, 0x11
+b011|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL $0x11, AL
+b811223344|556677885f5f5f5f5f5f5f 32 intel mov eax, 0x44332211
+b811223344|556677885f5f5f5f5f5f5f 32 plan9 MOVL $0x44332211, AX
+b811223344|556677885f5f5f5f5f5f5f 64 gnu mov $0x44332211,%eax
+b811223344|556677885f5f5f5f5f5f5f 64 intel mov eax, 0x44332211
+b811223344|556677885f5f5f5f5f5f5f 64 plan9 MOVL $0x44332211, AX
+c00011|223344556677885f5f5f5f5f5f 32 intel rol byte ptr [eax], 0x11
+c00011|223344556677885f5f5f5f5f5f 32 plan9 ROLL $0x11, 0(AX)
+c00011|223344556677885f5f5f5f5f5f 64 gnu rolb $0x11,(%rax)
+c00011|223344556677885f5f5f5f5f5f 64 intel rol byte ptr [rax], 0x11
+c00011|223344556677885f5f5f5f5f5f 64 plan9 ROLL $0x11, 0(AX)
+c00811|223344556677885f5f5f5f5f5f 32 intel ror byte ptr [eax], 0x11
+c00811|223344556677885f5f5f5f5f5f 32 plan9 RORL $0x11, 0(AX)
+c00811|223344556677885f5f5f5f5f5f 64 gnu rorb $0x11,(%rax)
+c00811|223344556677885f5f5f5f5f5f 64 intel ror byte ptr [rax], 0x11
+c00811|223344556677885f5f5f5f5f5f 64 plan9 RORL $0x11, 0(AX)
+c01122|3344556677885f5f5f5f5f5f5f 32 intel rcl byte ptr [ecx], 0x22
+c01122|3344556677885f5f5f5f5f5f5f 32 plan9 RCLL $0x22, 0(CX)
+c01122|3344556677885f5f5f5f5f5f5f 64 gnu rclb $0x22,(%rcx)
+c01122|3344556677885f5f5f5f5f5f5f 64 intel rcl byte ptr [rcx], 0x22
+c01122|3344556677885f5f5f5f5f5f5f 64 plan9 RCLL $0x22, 0(CX)
+c01811|223344556677885f5f5f5f5f5f 32 intel rcr byte ptr [eax], 0x11
+c01811|223344556677885f5f5f5f5f5f 32 plan9 RCRL $0x11, 0(AX)
+c01811|223344556677885f5f5f5f5f5f 64 gnu rcrb $0x11,(%rax)
+c01811|223344556677885f5f5f5f5f5f 64 intel rcr byte ptr [rax], 0x11
+c01811|223344556677885f5f5f5f5f5f 64 plan9 RCRL $0x11, 0(AX)
+c02011|223344556677885f5f5f5f5f5f 32 intel shl byte ptr [eax], 0x11
+c02011|223344556677885f5f5f5f5f5f 32 plan9 SHLL $0x11, 0(AX)
+c02011|223344556677885f5f5f5f5f5f 64 gnu shlb $0x11,(%rax)
+c02011|223344556677885f5f5f5f5f5f 64 intel shl byte ptr [rax], 0x11
+c02011|223344556677885f5f5f5f5f5f 64 plan9 SHLL $0x11, 0(AX)
+c02811|223344556677885f5f5f5f5f5f 32 intel shr byte ptr [eax], 0x11
+c02811|223344556677885f5f5f5f5f5f 32 plan9 SHRL $0x11, 0(AX)
+c02811|223344556677885f5f5f5f5f5f 64 gnu shrb $0x11,(%rax)
+c02811|223344556677885f5f5f5f5f5f 64 intel shr byte ptr [rax], 0x11
+c02811|223344556677885f5f5f5f5f5f 64 plan9 SHRL $0x11, 0(AX)
+c03811|223344556677885f5f5f5f5f5f 32 intel sar byte ptr [eax], 0x11
+c03811|223344556677885f5f5f5f5f5f 32 plan9 SARL $0x11, 0(AX)
+c03811|223344556677885f5f5f5f5f5f 64 gnu sarb $0x11,(%rax)
+c03811|223344556677885f5f5f5f5f5f 64 intel sar byte ptr [rax], 0x11
+c03811|223344556677885f5f5f5f5f5f 64 plan9 SARL $0x11, 0(AX)
+c10011|223344556677885f5f5f5f5f5f 32 intel rol dword ptr [eax], 0x11
+c10011|223344556677885f5f5f5f5f5f 32 plan9 ROLL $0x11, 0(AX)
+c10011|223344556677885f5f5f5f5f5f 64 gnu roll $0x11,(%rax)
+c10011|223344556677885f5f5f5f5f5f 64 intel rol dword ptr [rax], 0x11
+c10011|223344556677885f5f5f5f5f5f 64 plan9 ROLL $0x11, 0(AX)
+c10811|223344556677885f5f5f5f5f5f 32 intel ror dword ptr [eax], 0x11
+c10811|223344556677885f5f5f5f5f5f 32 plan9 RORL $0x11, 0(AX)
+c10811|223344556677885f5f5f5f5f5f 64 gnu rorl $0x11,(%rax)
+c10811|223344556677885f5f5f5f5f5f 64 intel ror dword ptr [rax], 0x11
+c10811|223344556677885f5f5f5f5f5f 64 plan9 RORL $0x11, 0(AX)
+c11122|3344556677885f5f5f5f5f5f5f 32 intel rcl dword ptr [ecx], 0x22
+c11122|3344556677885f5f5f5f5f5f5f 32 plan9 RCLL $0x22, 0(CX)
+c11122|3344556677885f5f5f5f5f5f5f 64 gnu rcll $0x22,(%rcx)
+c11122|3344556677885f5f5f5f5f5f5f 64 intel rcl dword ptr [rcx], 0x22
+c11122|3344556677885f5f5f5f5f5f5f 64 plan9 RCLL $0x22, 0(CX)
+c11811|223344556677885f5f5f5f5f5f 32 intel rcr dword ptr [eax], 0x11
+c11811|223344556677885f5f5f5f5f5f 32 plan9 RCRL $0x11, 0(AX)
+c11811|223344556677885f5f5f5f5f5f 64 gnu rcrl $0x11,(%rax)
+c11811|223344556677885f5f5f5f5f5f 64 intel rcr dword ptr [rax], 0x11
+c11811|223344556677885f5f5f5f5f5f 64 plan9 RCRL $0x11, 0(AX)
+c12011|223344556677885f5f5f5f5f5f 32 intel shl dword ptr [eax], 0x11
+c12011|223344556677885f5f5f5f5f5f 32 plan9 SHLL $0x11, 0(AX)
+c12011|223344556677885f5f5f5f5f5f 64 gnu shll $0x11,(%rax)
+c12011|223344556677885f5f5f5f5f5f 64 intel shl dword ptr [rax], 0x11
+c12011|223344556677885f5f5f5f5f5f 64 plan9 SHLL $0x11, 0(AX)
+c12811|223344556677885f5f5f5f5f5f 32 intel shr dword ptr [eax], 0x11
+c12811|223344556677885f5f5f5f5f5f 32 plan9 SHRL $0x11, 0(AX)
+c12811|223344556677885f5f5f5f5f5f 64 gnu shrl $0x11,(%rax)
+c12811|223344556677885f5f5f5f5f5f 64 intel shr dword ptr [rax], 0x11
+c12811|223344556677885f5f5f5f5f5f 64 plan9 SHRL $0x11, 0(AX)
+c13811|223344556677885f5f5f5f5f5f 32 intel sar dword ptr [eax], 0x11
+c13811|223344556677885f5f5f5f5f5f 32 plan9 SARL $0x11, 0(AX)
+c13811|223344556677885f5f5f5f5f5f 64 gnu sarl $0x11,(%rax)
+c13811|223344556677885f5f5f5f5f5f 64 intel sar dword ptr [rax], 0x11
+c13811|223344556677885f5f5f5f5f5f 64 plan9 SARL $0x11, 0(AX)
+c3|11223344556677885f5f5f5f5f5f5f 32 intel ret
+c3|11223344556677885f5f5f5f5f5f5f 32 plan9 RET
+c3|11223344556677885f5f5f5f5f5f5f 64 gnu retq
+c3|11223344556677885f5f5f5f5f5f5f 64 intel ret
+c3|11223344556677885f5f5f5f5f5f5f 64 plan9 RET
+c411|223344556677885f5f5f5f5f5f5f 32 intel les edx, ptr [ecx]
+c411|223344556677885f5f5f5f5f5f5f 32 plan9 LES 0(CX), DX
+c511|223344556677885f5f5f5f5f5f5f 32 intel lds edx, ptr [ecx]
+c511|223344556677885f5f5f5f5f5f5f 32 plan9 LDS 0(CX), DX
+c60011|223344556677885f5f5f5f5f5f 32 intel mov byte ptr [eax], 0x11
+c60011|223344556677885f5f5f5f5f5f 32 plan9 MOVL $0x11, 0(AX)
+c60011|223344556677885f5f5f5f5f5f 64 gnu movb $0x11,(%rax)
+c60011|223344556677885f5f5f5f5f5f 64 intel mov byte ptr [rax], 0x11
+c60011|223344556677885f5f5f5f5f5f 64 plan9 MOVL $0x11, 0(AX)
+c6f811|223344556677885f5f5f5f5f5f 32 intel xabort 0x11
+c6f811|223344556677885f5f5f5f5f5f 32 plan9 XABORT $0x11
+c6f811|223344556677885f5f5f5f5f5f 64 gnu xabort $0x11
+c6f811|223344556677885f5f5f5f5f5f 64 intel xabort 0x11
+c6f811|223344556677885f5f5f5f5f5f 64 plan9 XABORT $0x11
+c70011223344|556677885f5f5f5f5f5f 32 intel mov dword ptr [eax], 0x44332211
+c70011223344|556677885f5f5f5f5f5f 32 plan9 MOVL $0x44332211, 0(AX)
+c70011223344|556677885f5f5f5f5f5f 64 gnu movl $0x44332211,(%rax)
+c70011223344|556677885f5f5f5f5f5f 64 intel mov dword ptr [rax], 0x44332211
+c70011223344|556677885f5f5f5f5f5f 64 plan9 MOVL $0x44332211, 0(AX)
+c7f811223344|556677885f5f5f5f5f5f 32 intel xbegin .+0x44332211
+c7f811223344|556677885f5f5f5f5f5f 32 plan9 XBEGIN .+1144201745
+c7f811223344|556677885f5f5f5f5f5f 64 gnu xbeginq .+0x44332211
+c7f811223344|556677885f5f5f5f5f5f 64 intel xbegin .+0x44332211
+c7f811223344|556677885f5f5f5f5f5f 64 plan9 XBEGIN .+1144201745
+c8112233|44556677885f5f5f5f5f5f5f 32 intel enter 0x2211, 0x33
+c8112233|44556677885f5f5f5f5f5f5f 32 plan9 ENTER $0x33, $0x2211
+c8112233|44556677885f5f5f5f5f5f5f 64 gnu enterq $0x2211,$0x33
+c8112233|44556677885f5f5f5f5f5f5f 64 intel enter 0x2211, 0x33
+c8112233|44556677885f5f5f5f5f5f5f 64 plan9 ENTER $0x33, $0x2211
+c9|11223344556677885f5f5f5f5f5f5f 32 intel leave
+c9|11223344556677885f5f5f5f5f5f5f 32 plan9 LEAVE
+c9|11223344556677885f5f5f5f5f5f5f 64 gnu leaveq
+c9|11223344556677885f5f5f5f5f5f5f 64 intel leave
+c9|11223344556677885f5f5f5f5f5f5f 64 plan9 LEAVE
+ca1122|3344556677885f5f5f5f5f5f5f 32 intel ret far 0x2211
+ca1122|3344556677885f5f5f5f5f5f5f 32 plan9 LRET $0x2211
+ca1122|3344556677885f5f5f5f5f5f5f 64 gnu lretq $0x2211
+ca1122|3344556677885f5f5f5f5f5f5f 64 intel ret far 0x2211
+ca1122|3344556677885f5f5f5f5f5f5f 64 plan9 LRET $0x2211
+cb|11223344556677885f5f5f5f5f5f5f 32 intel ret far
+cb|11223344556677885f5f5f5f5f5f5f 32 plan9 LRET
+cb|11223344556677885f5f5f5f5f5f5f 64 gnu lretq
+cb|11223344556677885f5f5f5f5f5f5f 64 intel ret far
+cb|11223344556677885f5f5f5f5f5f5f 64 plan9 LRET
+cc|11223344556677885f5f5f5f5f5f5f 32 intel int3
+cc|11223344556677885f5f5f5f5f5f5f 32 plan9 INT $0x3
+cc|11223344556677885f5f5f5f5f5f5f 64 gnu int3
+cc|11223344556677885f5f5f5f5f5f5f 64 intel int3
+cc|11223344556677885f5f5f5f5f5f5f 64 plan9 INT $0x3
+cd11|223344556677885f5f5f5f5f5f5f 32 intel int 0x11
+cd11|223344556677885f5f5f5f5f5f5f 32 plan9 INT $0x11
+cd11|223344556677885f5f5f5f5f5f5f 64 gnu int $0x11
+cd11|223344556677885f5f5f5f5f5f5f 64 intel int 0x11
+cd11|223344556677885f5f5f5f5f5f5f 64 plan9 INT $0x11
+ce|11223344556677885f5f5f5f5f5f5f 32 intel into
+ce|11223344556677885f5f5f5f5f5f5f 32 plan9 INTO
+ce|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+ce|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+ce|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+cf|11223344556677885f5f5f5f5f5f5f 32 intel iretd
+cf|11223344556677885f5f5f5f5f5f5f 32 plan9 IRETD
+cf|11223344556677885f5f5f5f5f5f5f 64 gnu iret
+cf|11223344556677885f5f5f5f5f5f5f 64 intel iretd
+cf|11223344556677885f5f5f5f5f5f5f 64 plan9 IRETD
+d000|11223344556677885f5f5f5f5f5f 32 intel rol byte ptr [eax], 0x1
+d000|11223344556677885f5f5f5f5f5f 32 plan9 ROLL $0x1, 0(AX)
+d000|11223344556677885f5f5f5f5f5f 64 gnu rolb (%rax)
+d000|11223344556677885f5f5f5f5f5f 64 intel rol byte ptr [rax], 0x1
+d000|11223344556677885f5f5f5f5f5f 64 plan9 ROLL $0x1, 0(AX)
+d008|11223344556677885f5f5f5f5f5f 32 intel ror byte ptr [eax], 0x1
+d008|11223344556677885f5f5f5f5f5f 32 plan9 RORL $0x1, 0(AX)
+d008|11223344556677885f5f5f5f5f5f 64 gnu rorb (%rax)
+d008|11223344556677885f5f5f5f5f5f 64 intel ror byte ptr [rax], 0x1
+d008|11223344556677885f5f5f5f5f5f 64 plan9 RORL $0x1, 0(AX)
+d011|223344556677885f5f5f5f5f5f5f 32 intel rcl byte ptr [ecx], 0x1
+d011|223344556677885f5f5f5f5f5f5f 32 plan9 RCLL $0x1, 0(CX)
+d011|223344556677885f5f5f5f5f5f5f 64 gnu rclb (%rcx)
+d011|223344556677885f5f5f5f5f5f5f 64 intel rcl byte ptr [rcx], 0x1
+d011|223344556677885f5f5f5f5f5f5f 64 plan9 RCLL $0x1, 0(CX)
+d018|11223344556677885f5f5f5f5f5f 32 intel rcr byte ptr [eax], 0x1
+d018|11223344556677885f5f5f5f5f5f 32 plan9 RCRL $0x1, 0(AX)
+d018|11223344556677885f5f5f5f5f5f 64 gnu rcrb (%rax)
+d018|11223344556677885f5f5f5f5f5f 64 intel rcr byte ptr [rax], 0x1
+d018|11223344556677885f5f5f5f5f5f 64 plan9 RCRL $0x1, 0(AX)
+d020|11223344556677885f5f5f5f5f5f 32 intel shl byte ptr [eax], 0x1
+d020|11223344556677885f5f5f5f5f5f 32 plan9 SHLL $0x1, 0(AX)
+d020|11223344556677885f5f5f5f5f5f 64 gnu shlb (%rax)
+d020|11223344556677885f5f5f5f5f5f 64 intel shl byte ptr [rax], 0x1
+d020|11223344556677885f5f5f5f5f5f 64 plan9 SHLL $0x1, 0(AX)
+d028|11223344556677885f5f5f5f5f5f 32 intel shr byte ptr [eax], 0x1
+d028|11223344556677885f5f5f5f5f5f 32 plan9 SHRL $0x1, 0(AX)
+d028|11223344556677885f5f5f5f5f5f 64 gnu shrb (%rax)
+d028|11223344556677885f5f5f5f5f5f 64 intel shr byte ptr [rax], 0x1
+d028|11223344556677885f5f5f5f5f5f 64 plan9 SHRL $0x1, 0(AX)
+d038|11223344556677885f5f5f5f5f5f 32 intel sar byte ptr [eax], 0x1
+d038|11223344556677885f5f5f5f5f5f 32 plan9 SARL $0x1, 0(AX)
+d038|11223344556677885f5f5f5f5f5f 64 gnu sarb (%rax)
+d038|11223344556677885f5f5f5f5f5f 64 intel sar byte ptr [rax], 0x1
+d038|11223344556677885f5f5f5f5f5f 64 plan9 SARL $0x1, 0(AX)
+d100|11223344556677885f5f5f5f5f5f 32 intel rol dword ptr [eax], 0x1
+d100|11223344556677885f5f5f5f5f5f 32 plan9 ROLL $0x1, 0(AX)
+d100|11223344556677885f5f5f5f5f5f 64 gnu roll (%rax)
+d100|11223344556677885f5f5f5f5f5f 64 intel rol dword ptr [rax], 0x1
+d100|11223344556677885f5f5f5f5f5f 64 plan9 ROLL $0x1, 0(AX)
+d108|11223344556677885f5f5f5f5f5f 32 intel ror dword ptr [eax], 0x1
+d108|11223344556677885f5f5f5f5f5f 32 plan9 RORL $0x1, 0(AX)
+d108|11223344556677885f5f5f5f5f5f 64 gnu rorl (%rax)
+d108|11223344556677885f5f5f5f5f5f 64 intel ror dword ptr [rax], 0x1
+d108|11223344556677885f5f5f5f5f5f 64 plan9 RORL $0x1, 0(AX)
+d111|223344556677885f5f5f5f5f5f5f 32 intel rcl dword ptr [ecx], 0x1
+d111|223344556677885f5f5f5f5f5f5f 32 plan9 RCLL $0x1, 0(CX)
+d111|223344556677885f5f5f5f5f5f5f 64 gnu rcll (%rcx)
+d111|223344556677885f5f5f5f5f5f5f 64 intel rcl dword ptr [rcx], 0x1
+d111|223344556677885f5f5f5f5f5f5f 64 plan9 RCLL $0x1, 0(CX)
+d118|11223344556677885f5f5f5f5f5f 32 intel rcr dword ptr [eax], 0x1
+d118|11223344556677885f5f5f5f5f5f 32 plan9 RCRL $0x1, 0(AX)
+d118|11223344556677885f5f5f5f5f5f 64 gnu rcrl (%rax)
+d118|11223344556677885f5f5f5f5f5f 64 intel rcr dword ptr [rax], 0x1
+d118|11223344556677885f5f5f5f5f5f 64 plan9 RCRL $0x1, 0(AX)
+d120|11223344556677885f5f5f5f5f5f 32 intel shl dword ptr [eax], 0x1
+d120|11223344556677885f5f5f5f5f5f 32 plan9 SHLL $0x1, 0(AX)
+d120|11223344556677885f5f5f5f5f5f 64 gnu shll (%rax)
+d120|11223344556677885f5f5f5f5f5f 64 intel shl dword ptr [rax], 0x1
+d120|11223344556677885f5f5f5f5f5f 64 plan9 SHLL $0x1, 0(AX)
+d128|11223344556677885f5f5f5f5f5f 32 intel shr dword ptr [eax], 0x1
+d128|11223344556677885f5f5f5f5f5f 32 plan9 SHRL $0x1, 0(AX)
+d128|11223344556677885f5f5f5f5f5f 64 gnu shrl (%rax)
+d128|11223344556677885f5f5f5f5f5f 64 intel shr dword ptr [rax], 0x1
+d128|11223344556677885f5f5f5f5f5f 64 plan9 SHRL $0x1, 0(AX)
+d138|11223344556677885f5f5f5f5f5f 32 intel sar dword ptr [eax], 0x1
+d138|11223344556677885f5f5f5f5f5f 32 plan9 SARL $0x1, 0(AX)
+d138|11223344556677885f5f5f5f5f5f 64 gnu sarl (%rax)
+d138|11223344556677885f5f5f5f5f5f 64 intel sar dword ptr [rax], 0x1
+d138|11223344556677885f5f5f5f5f5f 64 plan9 SARL $0x1, 0(AX)
+d200|11223344556677885f5f5f5f5f5f 32 intel rol byte ptr [eax], cl
+d200|11223344556677885f5f5f5f5f5f 32 plan9 ROLL CL, 0(AX)
+d200|11223344556677885f5f5f5f5f5f 64 gnu rolb %cl,(%rax)
+d200|11223344556677885f5f5f5f5f5f 64 intel rol byte ptr [rax], cl
+d200|11223344556677885f5f5f5f5f5f 64 plan9 ROLL CL, 0(AX)
+d208|11223344556677885f5f5f5f5f5f 32 intel ror byte ptr [eax], cl
+d208|11223344556677885f5f5f5f5f5f 32 plan9 RORL CL, 0(AX)
+d208|11223344556677885f5f5f5f5f5f 64 gnu rorb %cl,(%rax)
+d208|11223344556677885f5f5f5f5f5f 64 intel ror byte ptr [rax], cl
+d208|11223344556677885f5f5f5f5f5f 64 plan9 RORL CL, 0(AX)
+d211|223344556677885f5f5f5f5f5f5f 32 intel rcl byte ptr [ecx], cl
+d211|223344556677885f5f5f5f5f5f5f 32 plan9 RCLL CL, 0(CX)
+d211|223344556677885f5f5f5f5f5f5f 64 gnu rclb %cl,(%rcx)
+d211|223344556677885f5f5f5f5f5f5f 64 intel rcl byte ptr [rcx], cl
+d211|223344556677885f5f5f5f5f5f5f 64 plan9 RCLL CL, 0(CX)
+d218|11223344556677885f5f5f5f5f5f 32 intel rcr byte ptr [eax], cl
+d218|11223344556677885f5f5f5f5f5f 32 plan9 RCRL CL, 0(AX)
+d218|11223344556677885f5f5f5f5f5f 64 gnu rcrb %cl,(%rax)
+d218|11223344556677885f5f5f5f5f5f 64 intel rcr byte ptr [rax], cl
+d218|11223344556677885f5f5f5f5f5f 64 plan9 RCRL CL, 0(AX)
+d220|11223344556677885f5f5f5f5f5f 32 intel shl byte ptr [eax], cl
+d220|11223344556677885f5f5f5f5f5f 32 plan9 SHLL CL, 0(AX)
+d220|11223344556677885f5f5f5f5f5f 64 gnu shlb %cl,(%rax)
+d220|11223344556677885f5f5f5f5f5f 64 intel shl byte ptr [rax], cl
+d220|11223344556677885f5f5f5f5f5f 64 plan9 SHLL CL, 0(AX)
+d228|11223344556677885f5f5f5f5f5f 32 intel shr byte ptr [eax], cl
+d228|11223344556677885f5f5f5f5f5f 32 plan9 SHRL CL, 0(AX)
+d228|11223344556677885f5f5f5f5f5f 64 gnu shrb %cl,(%rax)
+d228|11223344556677885f5f5f5f5f5f 64 intel shr byte ptr [rax], cl
+d228|11223344556677885f5f5f5f5f5f 64 plan9 SHRL CL, 0(AX)
+d238|11223344556677885f5f5f5f5f5f 32 intel sar byte ptr [eax], cl
+d238|11223344556677885f5f5f5f5f5f 32 plan9 SARL CL, 0(AX)
+d238|11223344556677885f5f5f5f5f5f 64 gnu sarb %cl,(%rax)
+d238|11223344556677885f5f5f5f5f5f 64 intel sar byte ptr [rax], cl
+d238|11223344556677885f5f5f5f5f5f 64 plan9 SARL CL, 0(AX)
+d300|11223344556677885f5f5f5f5f5f 32 intel rol dword ptr [eax], cl
+d300|11223344556677885f5f5f5f5f5f 32 plan9 ROLL CL, 0(AX)
+d300|11223344556677885f5f5f5f5f5f 64 gnu roll %cl,(%rax)
+d300|11223344556677885f5f5f5f5f5f 64 intel rol dword ptr [rax], cl
+d300|11223344556677885f5f5f5f5f5f 64 plan9 ROLL CL, 0(AX)
+d308|11223344556677885f5f5f5f5f5f 32 intel ror dword ptr [eax], cl
+d308|11223344556677885f5f5f5f5f5f 32 plan9 RORL CL, 0(AX)
+d308|11223344556677885f5f5f5f5f5f 64 gnu rorl %cl,(%rax)
+d308|11223344556677885f5f5f5f5f5f 64 intel ror dword ptr [rax], cl
+d308|11223344556677885f5f5f5f5f5f 64 plan9 RORL CL, 0(AX)
+d311|223344556677885f5f5f5f5f5f5f 32 intel rcl dword ptr [ecx], cl
+d311|223344556677885f5f5f5f5f5f5f 32 plan9 RCLL CL, 0(CX)
+d311|223344556677885f5f5f5f5f5f5f 64 gnu rcll %cl,(%rcx)
+d311|223344556677885f5f5f5f5f5f5f 64 intel rcl dword ptr [rcx], cl
+d311|223344556677885f5f5f5f5f5f5f 64 plan9 RCLL CL, 0(CX)
+d318|11223344556677885f5f5f5f5f5f 32 intel rcr dword ptr [eax], cl
+d318|11223344556677885f5f5f5f5f5f 32 plan9 RCRL CL, 0(AX)
+d318|11223344556677885f5f5f5f5f5f 64 gnu rcrl %cl,(%rax)
+d318|11223344556677885f5f5f5f5f5f 64 intel rcr dword ptr [rax], cl
+d318|11223344556677885f5f5f5f5f5f 64 plan9 RCRL CL, 0(AX)
+d320|11223344556677885f5f5f5f5f5f 32 intel shl dword ptr [eax], cl
+d320|11223344556677885f5f5f5f5f5f 32 plan9 SHLL CL, 0(AX)
+d320|11223344556677885f5f5f5f5f5f 64 gnu shll %cl,(%rax)
+d320|11223344556677885f5f5f5f5f5f 64 intel shl dword ptr [rax], cl
+d320|11223344556677885f5f5f5f5f5f 64 plan9 SHLL CL, 0(AX)
+d328|11223344556677885f5f5f5f5f5f 32 intel shr dword ptr [eax], cl
+d328|11223344556677885f5f5f5f5f5f 32 plan9 SHRL CL, 0(AX)
+d328|11223344556677885f5f5f5f5f5f 64 gnu shrl %cl,(%rax)
+d328|11223344556677885f5f5f5f5f5f 64 intel shr dword ptr [rax], cl
+d328|11223344556677885f5f5f5f5f5f 64 plan9 SHRL CL, 0(AX)
+d338|11223344556677885f5f5f5f5f5f 32 intel sar dword ptr [eax], cl
+d338|11223344556677885f5f5f5f5f5f 32 plan9 SARL CL, 0(AX)
+d338|11223344556677885f5f5f5f5f5f 64 gnu sarl %cl,(%rax)
+d338|11223344556677885f5f5f5f5f5f 64 intel sar dword ptr [rax], cl
+d338|11223344556677885f5f5f5f5f5f 64 plan9 SARL CL, 0(AX)
+d511|223344556677885f5f5f5f5f5f5f 32 intel aad 0x11
+d511|223344556677885f5f5f5f5f5f5f 32 plan9 AAD $0x11
+d5|11223344556677885f5f5f5f5f5f5f 64 gnu error: unrecognized instruction
+d5|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
+d5|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
+d800|11223344556677885f5f5f5f5f5f 32 intel fadd st0, dword ptr [eax]
+d800|11223344556677885f5f5f5f5f5f 32 plan9 FADD 0(AX)
+d800|11223344556677885f5f5f5f5f5f 64 gnu fadds (%rax)
+d800|11223344556677885f5f5f5f5f5f 64 intel fadd st0, dword ptr [rax]
+d800|11223344556677885f5f5f5f5f5f 64 plan9 FADD 0(AX)
+d808|11223344556677885f5f5f5f5f5f 32 intel fmul st0, dword ptr [eax]
+d808|11223344556677885f5f5f5f5f5f 32 plan9 FMUL 0(AX)
+d808|11223344556677885f5f5f5f5f5f 64 gnu fmuls (%rax)
+d808|11223344556677885f5f5f5f5f5f 64 intel fmul st0, dword ptr [rax]
+d808|11223344556677885f5f5f5f5f5f 64 plan9 FMUL 0(AX)
+d811|223344556677885f5f5f5f5f5f5f 32 intel fcom st0, dword ptr [ecx]
+d811|223344556677885f5f5f5f5f5f5f 32 plan9 FCOM 0(CX)
+d811|223344556677885f5f5f5f5f5f5f 64 gnu fcoms (%rcx)
+d811|223344556677885f5f5f5f5f5f5f 64 intel fcom st0, dword ptr [rcx]
+d811|223344556677885f5f5f5f5f5f5f 64 plan9 FCOM 0(CX)
+d818|11223344556677885f5f5f5f5f5f 32 intel fcomp st0, dword ptr [eax]
+d818|11223344556677885f5f5f5f5f5f 32 plan9 FCOMP 0(AX)
+d818|11223344556677885f5f5f5f5f5f 64 gnu fcomps (%rax)
+d818|11223344556677885f5f5f5f5f5f 64 intel fcomp st0, dword ptr [rax]
+d818|11223344556677885f5f5f5f5f5f 64 plan9 FCOMP 0(AX)
+d820|11223344556677885f5f5f5f5f5f 32 intel fsub st0, dword ptr [eax]
+d820|11223344556677885f5f5f5f5f5f 32 plan9 FSUB 0(AX)
+d820|11223344556677885f5f5f5f5f5f 64 gnu fsubs (%rax)
+d820|11223344556677885f5f5f5f5f5f 64 intel fsub st0, dword ptr [rax]
+d820|11223344556677885f5f5f5f5f5f 64 plan9 FSUB 0(AX)
+d828|11223344556677885f5f5f5f5f5f 32 intel fsubr st0, dword ptr [eax]
+d828|11223344556677885f5f5f5f5f5f 32 plan9 FSUBR 0(AX)
+d828|11223344556677885f5f5f5f5f5f 64 gnu fsubrs (%rax)
+d828|11223344556677885f5f5f5f5f5f 64 intel fsubr st0, dword ptr [rax]
+d828|11223344556677885f5f5f5f5f5f 64 plan9 FSUBR 0(AX)
+d830|11223344556677885f5f5f5f5f5f 32 intel fdiv st0, dword ptr [eax]
+d830|11223344556677885f5f5f5f5f5f 32 plan9 FDIV 0(AX)
+d830|11223344556677885f5f5f5f5f5f 64 gnu fdivs (%rax)
+d830|11223344556677885f5f5f5f5f5f 64 intel fdiv st0, dword ptr [rax]
+d830|11223344556677885f5f5f5f5f5f 64 plan9 FDIV 0(AX)
+d838|11223344556677885f5f5f5f5f5f 32 intel fdivr st0, dword ptr [eax]
+d838|11223344556677885f5f5f5f5f5f 32 plan9 FDIVR 0(AX)
+d838|11223344556677885f5f5f5f5f5f 64 gnu fdivrs (%rax)
+d838|11223344556677885f5f5f5f5f5f 64 intel fdivr st0, dword ptr [rax]
+d838|11223344556677885f5f5f5f5f5f 64 plan9 FDIVR 0(AX)
+d8c0|11223344556677885f5f5f5f5f5f 32 intel fadd st0, st0
+d8c0|11223344556677885f5f5f5f5f5f 32 plan9 FADD F0, F0
+d8c0|11223344556677885f5f5f5f5f5f 64 gnu fadd %st,%st
+d8c0|11223344556677885f5f5f5f5f5f 64 intel fadd st0, st0
+d8c0|11223344556677885f5f5f5f5f5f 64 plan9 FADD F0, F0
+d8c8|11223344556677885f5f5f5f5f5f 32 intel fmul st0, st0
+d8c8|11223344556677885f5f5f5f5f5f 32 plan9 FMUL F0, F0
+d8c8|11223344556677885f5f5f5f5f5f 64 gnu fmul %st,%st
+d8c8|11223344556677885f5f5f5f5f5f 64 intel fmul st0, st0
+d8c8|11223344556677885f5f5f5f5f5f 64 plan9 FMUL F0, F0
+d8d0|11223344556677885f5f5f5f5f5f 32 intel fcom st0, st0
+d8d0|11223344556677885f5f5f5f5f5f 32 plan9 FCOM F0
+d8d0|11223344556677885f5f5f5f5f5f 64 gnu fcom %st
+d8d0|11223344556677885f5f5f5f5f5f 64 intel fcom st0, st0
+d8d0|11223344556677885f5f5f5f5f5f 64 plan9 FCOM F0
+d8d8|11223344556677885f5f5f5f5f5f 32 intel fcomp st0, st0
+d8d8|11223344556677885f5f5f5f5f5f 32 plan9 FCOMP F0
+d8d8|11223344556677885f5f5f5f5f5f 64 gnu fcomp %st
+d8d8|11223344556677885f5f5f5f5f5f 64 intel fcomp st0, st0
+d8d8|11223344556677885f5f5f5f5f5f 64 plan9 FCOMP F0
+d8e0|11223344556677885f5f5f5f5f5f 32 intel fsub st0, st0
+d8e0|11223344556677885f5f5f5f5f5f 32 plan9 FSUB F0, F0
+d8e0|11223344556677885f5f5f5f5f5f 64 gnu fsub %st,%st
+d8e0|11223344556677885f5f5f5f5f5f 64 intel fsub st0, st0
+d8e0|11223344556677885f5f5f5f5f5f 64 plan9 FSUB F0, F0
+d8e8|11223344556677885f5f5f5f5f5f 32 intel fsubr st0, st0
+d8e8|11223344556677885f5f5f5f5f5f 32 plan9 FSUBR F0, F0
+d8e8|11223344556677885f5f5f5f5f5f 64 gnu fsubr %st,%st
+d8e8|11223344556677885f5f5f5f5f5f 64 intel fsubr st0, st0
+d8e8|11223344556677885f5f5f5f5f5f 64 plan9 FSUBR F0, F0
+d8f0|11223344556677885f5f5f5f5f5f 32 intel fdiv st0, st0
+d8f0|11223344556677885f5f5f5f5f5f 32 plan9 FDIV F0, F0
+d8f0|11223344556677885f5f5f5f5f5f 64 gnu fdiv %st,%st
+d8f0|11223344556677885f5f5f5f5f5f 64 intel fdiv st0, st0
+d8f0|11223344556677885f5f5f5f5f5f 64 plan9 FDIV F0, F0
+d8f8|11223344556677885f5f5f5f5f5f 32 intel fdivr st0, st0
+d8f8|11223344556677885f5f5f5f5f5f 32 plan9 FDIVR F0, F0
+d8f8|11223344556677885f5f5f5f5f5f 64 gnu fdivr %st,%st
+d8f8|11223344556677885f5f5f5f5f5f 64 intel fdivr st0, st0
+d8f8|11223344556677885f5f5f5f5f5f 64 plan9 FDIVR F0, F0
+d900|11223344556677885f5f5f5f5f5f 32 intel fld st0, dword ptr [eax]
+d900|11223344556677885f5f5f5f5f5f 32 plan9 FLD 0(AX)
+d900|11223344556677885f5f5f5f5f5f 64 gnu flds (%rax)
+d900|11223344556677885f5f5f5f5f5f 64 intel fld st0, dword ptr [rax]
+d900|11223344556677885f5f5f5f5f5f 64 plan9 FLD 0(AX)
+d911|223344556677885f5f5f5f5f5f5f 32 intel fst dword ptr [ecx], st0
+d911|223344556677885f5f5f5f5f5f5f 32 plan9 FST 0(CX)
+d911|223344556677885f5f5f5f5f5f5f 64 gnu fsts (%rcx)
+d911|223344556677885f5f5f5f5f5f5f 64 intel fst dword ptr [rcx], st0
+d911|223344556677885f5f5f5f5f5f5f 64 plan9 FST 0(CX)
+d918|11223344556677885f5f5f5f5f5f 32 intel fstp dword ptr [eax], st0
+d918|11223344556677885f5f5f5f5f5f 32 plan9 FSTP 0(AX)
+d918|11223344556677885f5f5f5f5f5f 64 gnu fstps (%rax)
+d918|11223344556677885f5f5f5f5f5f 64 intel fstp dword ptr [rax], st0
+d918|11223344556677885f5f5f5f5f5f 64 plan9 FSTP 0(AX)
+d928|11223344556677885f5f5f5f5f5f 32 intel fldcw word ptr [eax]
+d928|11223344556677885f5f5f5f5f5f 32 plan9 FLDCW 0(AX)
+d928|11223344556677885f5f5f5f5f5f 64 gnu fldcw (%rax)
+d928|11223344556677885f5f5f5f5f5f 64 intel fldcw word ptr [rax]
+d928|11223344556677885f5f5f5f5f5f 64 plan9 FLDCW 0(AX)
+d930|11223344556677885f5f5f5f5f5f 32 intel fnstenv ptr [eax]
+d930|11223344556677885f5f5f5f5f5f 32 plan9 FNSTENV 0(AX)
+d930|11223344556677885f5f5f5f5f5f 64 gnu fnstenv (%rax)
+d930|11223344556677885f5f5f5f5f5f 64 intel fnstenv ptr [rax]
+d930|11223344556677885f5f5f5f5f5f 64 plan9 FNSTENV 0(AX)
+d938|11223344556677885f5f5f5f5f5f 32 intel fnstcw word ptr [eax]
+d938|11223344556677885f5f5f5f5f5f 32 plan9 FNSTCW 0(AX)
+d938|11223344556677885f5f5f5f5f5f 64 gnu fnstcw (%rax)
+d938|11223344556677885f5f5f5f5f5f 64 intel fnstcw word ptr [rax]
+d938|11223344556677885f5f5f5f5f5f 64 plan9 FNSTCW 0(AX)
+d9c0|11223344556677885f5f5f5f5f5f 32 intel fld st0, st0
+d9c0|11223344556677885f5f5f5f5f5f 32 plan9 FLD F0
+d9c0|11223344556677885f5f5f5f5f5f 64 gnu fld %st
+d9c0|11223344556677885f5f5f5f5f5f 64 intel fld st0, st0
+d9c0|11223344556677885f5f5f5f5f5f 64 plan9 FLD F0
+d9c8|11223344556677885f5f5f5f5f5f 32 intel fxch st0, st0
+d9c8|11223344556677885f5f5f5f5f5f 32 plan9 FXCH F0
+d9c8|11223344556677885f5f5f5f5f5f 64 gnu fxch %st
+d9c8|11223344556677885f5f5f5f5f5f 64 intel fxch st0, st0
+d9c8|11223344556677885f5f5f5f5f5f 64 plan9 FXCH F0
+d9d0|11223344556677885f5f5f5f5f5f 32 intel fnop
+d9d0|11223344556677885f5f5f5f5f5f 32 plan9 FNOP
+d9d0|11223344556677885f5f5f5f5f5f 64 gnu fnop
+d9d0|11223344556677885f5f5f5f5f5f 64 intel fnop
+d9d0|11223344556677885f5f5f5f5f5f 64 plan9 FNOP
+d9e0|11223344556677885f5f5f5f5f5f 32 intel fchs st0
+d9e0|11223344556677885f5f5f5f5f5f 32 plan9 FCHS
+d9e0|11223344556677885f5f5f5f5f5f 64 gnu fchs
+d9e0|11223344556677885f5f5f5f5f5f 64 intel fchs st0
+d9e0|11223344556677885f5f5f5f5f5f 64 plan9 FCHS
+d9e1|11223344556677885f5f5f5f5f5f 32 intel fabs st0
+d9e1|11223344556677885f5f5f5f5f5f 32 plan9 FABS
+d9e1|11223344556677885f5f5f5f5f5f 64 gnu fabs
+d9e1|11223344556677885f5f5f5f5f5f 64 intel fabs st0
+d9e1|11223344556677885f5f5f5f5f5f 64 plan9 FABS
+d9e4|11223344556677885f5f5f5f5f5f 32 intel ftst st0
+d9e4|11223344556677885f5f5f5f5f5f 32 plan9 FTST
+d9e4|11223344556677885f5f5f5f5f5f 64 gnu ftst
+d9e4|11223344556677885f5f5f5f5f5f 64 intel ftst st0
+d9e4|11223344556677885f5f5f5f5f5f 64 plan9 FTST
+d9e5|11223344556677885f5f5f5f5f5f 32 intel fxam st0
+d9e5|11223344556677885f5f5f5f5f5f 32 plan9 FXAM
+d9e5|11223344556677885f5f5f5f5f5f 64 gnu fxam
+d9e5|11223344556677885f5f5f5f5f5f 64 intel fxam st0
+d9e5|11223344556677885f5f5f5f5f5f 64 plan9 FXAM
+d9e8|11223344556677885f5f5f5f5f5f 32 intel fld1 st0
+d9e8|11223344556677885f5f5f5f5f5f 32 plan9 FLD1
+d9e8|11223344556677885f5f5f5f5f5f 64 gnu fld1
+d9e8|11223344556677885f5f5f5f5f5f 64 intel fld1 st0
+d9e8|11223344556677885f5f5f5f5f5f 64 plan9 FLD1
+d9e9|11223344556677885f5f5f5f5f5f 32 intel fldl2t st0
+d9e9|11223344556677885f5f5f5f5f5f 32 plan9 FLDL2T
+d9e9|11223344556677885f5f5f5f5f5f 64 gnu fldl2t
+d9e9|11223344556677885f5f5f5f5f5f 64 intel fldl2t st0
+d9e9|11223344556677885f5f5f5f5f5f 64 plan9 FLDL2T
+d9ea|11223344556677885f5f5f5f5f5f 32 intel fldl2e st0
+d9ea|11223344556677885f5f5f5f5f5f 32 plan9 FLDL2E
+d9ea|11223344556677885f5f5f5f5f5f 64 gnu fldl2e
+d9ea|11223344556677885f5f5f5f5f5f 64 intel fldl2e st0
+d9ea|11223344556677885f5f5f5f5f5f 64 plan9 FLDL2E
+d9eb|11223344556677885f5f5f5f5f5f 32 intel fldpi st0
+d9eb|11223344556677885f5f5f5f5f5f 32 plan9 FLDPI
+d9eb|11223344556677885f5f5f5f5f5f 64 gnu fldpi
+d9eb|11223344556677885f5f5f5f5f5f 64 intel fldpi st0
+d9eb|11223344556677885f5f5f5f5f5f 64 plan9 FLDPI
+d9ec|11223344556677885f5f5f5f5f5f 32 intel fldlg2 st0
+d9ec|11223344556677885f5f5f5f5f5f 32 plan9 FLDLG2
+d9ec|11223344556677885f5f5f5f5f5f 64 gnu fldlg2
+d9ec|11223344556677885f5f5f5f5f5f 64 intel fldlg2 st0
+d9ec|11223344556677885f5f5f5f5f5f 64 plan9 FLDLG2
+d9f0|11223344556677885f5f5f5f5f5f 32 intel f2xm1 st0
+d9f0|11223344556677885f5f5f5f5f5f 32 plan9 F2XM1
+d9f0|11223344556677885f5f5f5f5f5f 64 gnu f2xm1
+d9f0|11223344556677885f5f5f5f5f5f 64 intel f2xm1 st0
+d9f0|11223344556677885f5f5f5f5f5f 64 plan9 F2XM1
+d9f1|11223344556677885f5f5f5f5f5f 32 intel fyl2x st0, st1
+d9f1|11223344556677885f5f5f5f5f5f 32 plan9 FYL2X
+d9f1|11223344556677885f5f5f5f5f5f 64 gnu fyl2x
+d9f1|11223344556677885f5f5f5f5f5f 64 intel fyl2x st0, st1
+d9f1|11223344556677885f5f5f5f5f5f 64 plan9 FYL2X
+d9f2|11223344556677885f5f5f5f5f5f 32 intel fptan st0, st1
+d9f2|11223344556677885f5f5f5f5f5f 32 plan9 FPTAN
+d9f2|11223344556677885f5f5f5f5f5f 64 gnu fptan
+d9f2|11223344556677885f5f5f5f5f5f 64 intel fptan st0, st1
+d9f2|11223344556677885f5f5f5f5f5f 64 plan9 FPTAN
+d9f3|11223344556677885f5f5f5f5f5f 32 intel fpatan st0, st1
+d9f3|11223344556677885f5f5f5f5f5f 32 plan9 FPATAN
+d9f3|11223344556677885f5f5f5f5f5f 64 gnu fpatan
+d9f3|11223344556677885f5f5f5f5f5f 64 intel fpatan st0, st1
+d9f3|11223344556677885f5f5f5f5f5f 64 plan9 FPATAN
+d9f4|11223344556677885f5f5f5f5f5f 32 intel fxtract st0, st1
+d9f4|11223344556677885f5f5f5f5f5f 32 plan9 FXTRACT
+d9f4|11223344556677885f5f5f5f5f5f 64 gnu fxtract
+d9f4|11223344556677885f5f5f5f5f5f 64 intel fxtract st0, st1
+d9f4|11223344556677885f5f5f5f5f5f 64 plan9 FXTRACT
+d9f5|11223344556677885f5f5f5f5f5f 32 intel fprem1 st0, st1
+d9f5|11223344556677885f5f5f5f5f5f 32 plan9 FPREM1
+d9f5|11223344556677885f5f5f5f5f5f 64 gnu fprem1
+d9f5|11223344556677885f5f5f5f5f5f 64 intel fprem1 st0, st1
+d9f5|11223344556677885f5f5f5f5f5f 64 plan9 FPREM1
+d9f6|11223344556677885f5f5f5f5f5f 32 intel fdecstp
+d9f6|11223344556677885f5f5f5f5f5f 32 plan9 FDECSTP
+d9f6|11223344556677885f5f5f5f5f5f 64 gnu fdecstp
+d9f6|11223344556677885f5f5f5f5f5f 64 intel fdecstp
+d9f6|11223344556677885f5f5f5f5f5f 64 plan9 FDECSTP
+d9f7|11223344556677885f5f5f5f5f5f 32 intel fincstp
+d9f7|11223344556677885f5f5f5f5f5f 32 plan9 FINCSTP
+d9f7|11223344556677885f5f5f5f5f5f 64 gnu fincstp
+d9f7|11223344556677885f5f5f5f5f5f 64 intel fincstp
+d9f7|11223344556677885f5f5f5f5f5f 64 plan9 FINCSTP
+d9f8|11223344556677885f5f5f5f5f5f 32 intel fprem st0, st1
+d9f8|11223344556677885f5f5f5f5f5f 32 plan9 FPREM
+d9f8|11223344556677885f5f5f5f5f5f 64 gnu fprem
+d9f8|11223344556677885f5f5f5f5f5f 64 intel fprem st0, st1
+d9f8|11223344556677885f5f5f5f5f5f 64 plan9 FPREM
+d9f9|11223344556677885f5f5f5f5f5f 32 intel fyl2xp1 st0, st1
+d9f9|11223344556677885f5f5f5f5f5f 32 plan9 FYL2XP1
+d9f9|11223344556677885f5f5f5f5f5f 64 gnu fyl2xp1
+d9f9|11223344556677885f5f5f5f5f5f 64 intel fyl2xp1 st0, st1
+d9f9|11223344556677885f5f5f5f5f5f 64 plan9 FYL2XP1
+d9fa|11223344556677885f5f5f5f5f5f 32 intel fsqrt st0
+d9fa|11223344556677885f5f5f5f5f5f 32 plan9 FSQRT
+d9fa|11223344556677885f5f5f5f5f5f 64 gnu fsqrt
+d9fa|11223344556677885f5f5f5f5f5f 64 intel fsqrt st0
+d9fa|11223344556677885f5f5f5f5f5f 64 plan9 FSQRT
+d9fb|11223344556677885f5f5f5f5f5f 32 intel fsincos st0, st1
+d9fb|11223344556677885f5f5f5f5f5f 32 plan9 FSINCOS
+d9fb|11223344556677885f5f5f5f5f5f 64 gnu fsincos
+d9fb|11223344556677885f5f5f5f5f5f 64 intel fsincos st0, st1
+d9fb|11223344556677885f5f5f5f5f5f 64 plan9 FSINCOS
+d9fc|11223344556677885f5f5f5f5f5f 32 intel frndint st0
+d9fc|11223344556677885f5f5f5f5f5f 32 plan9 FRNDINT
+d9fc|11223344556677885f5f5f5f5f5f 64 gnu frndint
+d9fc|11223344556677885f5f5f5f5f5f 64 intel frndint st0
+d9fc|11223344556677885f5f5f5f5f5f 64 plan9 FRNDINT
+d9fd|11223344556677885f5f5f5f5f5f 32 intel fscale st0, st1
+d9fd|11223344556677885f5f5f5f5f5f 32 plan9 FSCALE
+d9fd|11223344556677885f5f5f5f5f5f 64 gnu fscale
+d9fd|11223344556677885f5f5f5f5f5f 64 intel fscale st0, st1
+d9fd|11223344556677885f5f5f5f5f5f 64 plan9 FSCALE
+d9fe|11223344556677885f5f5f5f5f5f 32 intel fsin st0
+d9fe|11223344556677885f5f5f5f5f5f 32 plan9 FSIN
+d9fe|11223344556677885f5f5f5f5f5f 64 gnu fsin
+d9fe|11223344556677885f5f5f5f5f5f 64 intel fsin st0
+d9fe|11223344556677885f5f5f5f5f5f 64 plan9 FSIN
+d9ff|11223344556677885f5f5f5f5f5f 32 intel fcos st0
+d9ff|11223344556677885f5f5f5f5f5f 32 plan9 FCOS
+d9ff|11223344556677885f5f5f5f5f5f 64 gnu fcos
+d9ff|11223344556677885f5f5f5f5f5f 64 intel fcos st0
+d9ff|11223344556677885f5f5f5f5f5f 64 plan9 FCOS
+da00|11223344556677885f5f5f5f5f5f 32 intel fiadd st0, dword ptr [eax]
+da00|11223344556677885f5f5f5f5f5f 32 plan9 FIADD 0(AX)
+da00|11223344556677885f5f5f5f5f5f 64 gnu fiaddl (%rax)
+da00|11223344556677885f5f5f5f5f5f 64 intel fiadd st0, dword ptr [rax]
+da00|11223344556677885f5f5f5f5f5f 64 plan9 FIADD 0(AX)
+da08|11223344556677885f5f5f5f5f5f 32 intel fimul st0, dword ptr [eax]
+da08|11223344556677885f5f5f5f5f5f 32 plan9 FIMUL 0(AX)
+da08|11223344556677885f5f5f5f5f5f 64 gnu fimull (%rax)
+da08|11223344556677885f5f5f5f5f5f 64 intel fimul st0, dword ptr [rax]
+da08|11223344556677885f5f5f5f5f5f 64 plan9 FIMUL 0(AX)
+da11|223344556677885f5f5f5f5f5f5f 32 intel ficom st0, dword ptr [ecx]
+da11|223344556677885f5f5f5f5f5f5f 32 plan9 FICOM 0(CX)
+da11|223344556677885f5f5f5f5f5f5f 64 gnu ficoml (%rcx)
+da11|223344556677885f5f5f5f5f5f5f 64 intel ficom st0, dword ptr [rcx]
+da11|223344556677885f5f5f5f5f5f5f 64 plan9 FICOM 0(CX)
+da18|11223344556677885f5f5f5f5f5f 32 intel ficomp st0, dword ptr [eax]
+da18|11223344556677885f5f5f5f5f5f 32 plan9 FICOMP 0(AX)
+da18|11223344556677885f5f5f5f5f5f 64 gnu ficompl (%rax)
+da18|11223344556677885f5f5f5f5f5f 64 intel ficomp st0, dword ptr [rax]
+da18|11223344556677885f5f5f5f5f5f 64 plan9 FICOMP 0(AX)
+da20|11223344556677885f5f5f5f5f5f 32 intel fisub st0, dword ptr [eax]
+da20|11223344556677885f5f5f5f5f5f 32 plan9 FISUB 0(AX)
+da20|11223344556677885f5f5f5f5f5f 64 gnu fisubl (%rax)
+da20|11223344556677885f5f5f5f5f5f 64 intel fisub st0, dword ptr [rax]
+da20|11223344556677885f5f5f5f5f5f 64 plan9 FISUB 0(AX)
+da28|11223344556677885f5f5f5f5f5f 32 intel fisubr st0, dword ptr [eax]
+da28|11223344556677885f5f5f5f5f5f 32 plan9 FISUBR 0(AX)
+da28|11223344556677885f5f5f5f5f5f 64 gnu fisubrl (%rax)
+da28|11223344556677885f5f5f5f5f5f 64 intel fisubr st0, dword ptr [rax]
+da28|11223344556677885f5f5f5f5f5f 64 plan9 FISUBR 0(AX)
+da30|11223344556677885f5f5f5f5f5f 32 intel fidiv st0, dword ptr [eax]
+da30|11223344556677885f5f5f5f5f5f 32 plan9 FIDIV 0(AX)
+da30|11223344556677885f5f5f5f5f5f 64 gnu fidivl (%rax)
+da30|11223344556677885f5f5f5f5f5f 64 intel fidiv st0, dword ptr [rax]
+da30|11223344556677885f5f5f5f5f5f 64 plan9 FIDIV 0(AX)
+da38|11223344556677885f5f5f5f5f5f 32 intel fidivr st0, dword ptr [eax]
+da38|11223344556677885f5f5f5f5f5f 32 plan9 FIDIVR 0(AX)
+da38|11223344556677885f5f5f5f5f5f 64 gnu fidivrl (%rax)
+da38|11223344556677885f5f5f5f5f5f 64 intel fidivr st0, dword ptr [rax]
+da38|11223344556677885f5f5f5f5f5f 64 plan9 FIDIVR 0(AX)
+dac0|11223344556677885f5f5f5f5f5f 32 intel fcmovb st0, st0
+dac0|11223344556677885f5f5f5f5f5f 32 plan9 FCMOVB F0, F0
+dac0|11223344556677885f5f5f5f5f5f 64 gnu fcmovb %st,%st
+dac0|11223344556677885f5f5f5f5f5f 64 intel fcmovb st0, st0
+dac0|11223344556677885f5f5f5f5f5f 64 plan9 FCMOVB F0, F0
+dac8|11223344556677885f5f5f5f5f5f 32 intel fcmove st0, st0
+dac8|11223344556677885f5f5f5f5f5f 32 plan9 FCMOVE F0, F0
+dac8|11223344556677885f5f5f5f5f5f 64 gnu fcmove %st,%st
+dac8|11223344556677885f5f5f5f5f5f 64 intel fcmove st0, st0
+dac8|11223344556677885f5f5f5f5f5f 64 plan9 FCMOVE F0, F0
+dad0|11223344556677885f5f5f5f5f5f 32 intel fcmovbe st0, st0
+dad0|11223344556677885f5f5f5f5f5f 32 plan9 FCMOVBE F0, F0
+dad0|11223344556677885f5f5f5f5f5f 64 gnu fcmovbe %st,%st
+dad0|11223344556677885f5f5f5f5f5f 64 intel fcmovbe st0, st0
+dad0|11223344556677885f5f5f5f5f5f 64 plan9 FCMOVBE F0, F0
+dad8|11223344556677885f5f5f5f5f5f 32 intel fcmovu st0, st0
+dad8|11223344556677885f5f5f5f5f5f 32 plan9 FCMOVU F0, F0
+dad8|11223344556677885f5f5f5f5f5f 64 gnu fcmovu %st,%st
+dad8|11223344556677885f5f5f5f5f5f 64 intel fcmovu st0, st0
+dad8|11223344556677885f5f5f5f5f5f 64 plan9 FCMOVU F0, F0
+dae9|11223344556677885f5f5f5f5f5f 32 intel fucompp st0, st1
+dae9|11223344556677885f5f5f5f5f5f 32 plan9 FUCOMPP
+dae9|11223344556677885f5f5f5f5f5f 64 gnu fucompp
+dae9|11223344556677885f5f5f5f5f5f 64 intel fucompp st0, st1
+dae9|11223344556677885f5f5f5f5f5f 64 plan9 FUCOMPP
+db00|11223344556677885f5f5f5f5f5f 32 intel fild st0, dword ptr [eax]
+db00|11223344556677885f5f5f5f5f5f 32 plan9 FILD 0(AX)
+db00|11223344556677885f5f5f5f5f5f 64 gnu fildl (%rax)
+db00|11223344556677885f5f5f5f5f5f 64 intel fild st0, dword ptr [rax]
+db00|11223344556677885f5f5f5f5f5f 64 plan9 FILD 0(AX)
+db08|11223344556677885f5f5f5f5f5f 32 intel fisttp dword ptr [eax], st0
+db08|11223344556677885f5f5f5f5f5f 32 plan9 FISTTP 0(AX)
+db08|11223344556677885f5f5f5f5f5f 64 gnu fisttpl (%rax)
+db08|11223344556677885f5f5f5f5f5f 64 intel fisttp dword ptr [rax], st0
+db08|11223344556677885f5f5f5f5f5f 64 plan9 FISTTP 0(AX)
+db11|223344556677885f5f5f5f5f5f5f 32 intel fist dword ptr [ecx], st0
+db11|223344556677885f5f5f5f5f5f5f 32 plan9 FIST 0(CX)
+db11|223344556677885f5f5f5f5f5f5f 64 gnu fistl (%rcx)
+db11|223344556677885f5f5f5f5f5f5f 64 intel fist dword ptr [rcx], st0
+db11|223344556677885f5f5f5f5f5f5f 64 plan9 FIST 0(CX)
+db18|11223344556677885f5f5f5f5f5f 32 intel fistp dword ptr [eax], st0
+db18|11223344556677885f5f5f5f5f5f 32 plan9 FISTP 0(AX)
+db18|11223344556677885f5f5f5f5f5f 64 gnu fistpl (%rax)
+db18|11223344556677885f5f5f5f5f5f 64 intel fistp dword ptr [rax], st0
+db18|11223344556677885f5f5f5f5f5f 64 plan9 FISTP 0(AX)
+db28|11223344556677885f5f5f5f5f5f 32 intel fld st0, ptr [eax]
+db28|11223344556677885f5f5f5f5f5f 32 plan9 FLD 0(AX)
+db28|11223344556677885f5f5f5f5f5f 64 gnu fldt (%rax)
+db28|11223344556677885f5f5f5f5f5f 64 intel fld st0, ptr [rax]
+db28|11223344556677885f5f5f5f5f5f 64 plan9 FLD 0(AX)
+db38|11223344556677885f5f5f5f5f5f 32 intel fstp ptr [eax], st0
+db38|11223344556677885f5f5f5f5f5f 32 plan9 FSTP 0(AX)
+db38|11223344556677885f5f5f5f5f5f 64 gnu fstpt (%rax)
+db38|11223344556677885f5f5f5f5f5f 64 intel fstp ptr [rax], st0
+db38|11223344556677885f5f5f5f5f5f 64 plan9 FSTP 0(AX)
+dbc0|11223344556677885f5f5f5f5f5f 32 intel fcmovnb st0, st0
+dbc0|11223344556677885f5f5f5f5f5f 32 plan9 FCMOVNB F0, F0
+dbc0|11223344556677885f5f5f5f5f5f 64 gnu fcmovnb %st,%st
+dbc0|11223344556677885f5f5f5f5f5f 64 intel fcmovnb st0, st0
+dbc0|11223344556677885f5f5f5f5f5f 64 plan9 FCMOVNB F0, F0
+dbc8|11223344556677885f5f5f5f5f5f 32 intel fcmovne st0, st0
+dbc8|11223344556677885f5f5f5f5f5f 32 plan9 FCMOVNE F0, F0
+dbc8|11223344556677885f5f5f5f5f5f 64 gnu fcmovne %st,%st
+dbc8|11223344556677885f5f5f5f5f5f 64 intel fcmovne st0, st0
+dbc8|11223344556677885f5f5f5f5f5f 64 plan9 FCMOVNE F0, F0
+dbd0|11223344556677885f5f5f5f5f5f 32 intel fcmovnbe st0, st0
+dbd0|11223344556677885f5f5f5f5f5f 32 plan9 FCMOVNBE F0, F0
+dbd0|11223344556677885f5f5f5f5f5f 64 gnu fcmovnbe %st,%st
+dbd0|11223344556677885f5f5f5f5f5f 64 intel fcmovnbe st0, st0
+dbd0|11223344556677885f5f5f5f5f5f 64 plan9 FCMOVNBE F0, F0
+dbd8|11223344556677885f5f5f5f5f5f 32 intel fcmovnu st0, st0
+dbd8|11223344556677885f5f5f5f5f5f 32 plan9 FCMOVNU F0, F0
+dbd8|11223344556677885f5f5f5f5f5f 64 gnu fcmovnu %st,%st
+dbd8|11223344556677885f5f5f5f5f5f 64 intel fcmovnu st0, st0
+dbd8|11223344556677885f5f5f5f5f5f 64 plan9 FCMOVNU F0, F0
+dbe2|11223344556677885f5f5f5f5f5f 32 intel fnclex
+dbe2|11223344556677885f5f5f5f5f5f 32 plan9 FNCLEX
+dbe2|11223344556677885f5f5f5f5f5f 64 gnu fnclex
+dbe2|11223344556677885f5f5f5f5f5f 64 intel fnclex
+dbe2|11223344556677885f5f5f5f5f5f 64 plan9 FNCLEX
+dbe3|11223344556677885f5f5f5f5f5f 32 intel fninit
+dbe3|11223344556677885f5f5f5f5f5f 32 plan9 FNINIT
+dbe3|11223344556677885f5f5f5f5f5f 64 gnu fninit
+dbe3|11223344556677885f5f5f5f5f5f 64 intel fninit
+dbe3|11223344556677885f5f5f5f5f5f 64 plan9 FNINIT
+dbe8|11223344556677885f5f5f5f5f5f 32 intel fucomi st0, st0
+dbe8|11223344556677885f5f5f5f5f5f 32 plan9 FUCOMI F0, F0
+dbe8|11223344556677885f5f5f5f5f5f 64 gnu fucomi %st,%st
+dbe8|11223344556677885f5f5f5f5f5f 64 intel fucomi st0, st0
+dbe8|11223344556677885f5f5f5f5f5f 64 plan9 FUCOMI F0, F0
+dbf0|11223344556677885f5f5f5f5f5f 32 intel fcomi st0, st0
+dbf0|11223344556677885f5f5f5f5f5f 32 plan9 FCOMI F0, F0
+dbf0|11223344556677885f5f5f5f5f5f 64 gnu fcomi %st,%st
+dbf0|11223344556677885f5f5f5f5f5f 64 intel fcomi st0, st0
+dbf0|11223344556677885f5f5f5f5f5f 64 plan9 FCOMI F0, F0
+dc00|11223344556677885f5f5f5f5f5f 32 intel fadd st0, qword ptr [eax]
+dc00|11223344556677885f5f5f5f5f5f 32 plan9 FADD 0(AX)
+dc00|11223344556677885f5f5f5f5f5f 64 gnu faddl (%rax)
+dc00|11223344556677885f5f5f5f5f5f 64 intel fadd st0, qword ptr [rax]
+dc00|11223344556677885f5f5f5f5f5f 64 plan9 FADD 0(AX)
+dc08|11223344556677885f5f5f5f5f5f 32 intel fmul st0, qword ptr [eax]
+dc08|11223344556677885f5f5f5f5f5f 32 plan9 FMUL 0(AX)
+dc08|11223344556677885f5f5f5f5f5f 64 gnu fmull (%rax)
+dc08|11223344556677885f5f5f5f5f5f 64 intel fmul st0, qword ptr [rax]
+dc08|11223344556677885f5f5f5f5f5f 64 plan9 FMUL 0(AX)
+dc11|223344556677885f5f5f5f5f5f5f 32 intel fcom st0, qword ptr [ecx]
+dc11|223344556677885f5f5f5f5f5f5f 32 plan9 FCOM 0(CX)
+dc11|223344556677885f5f5f5f5f5f5f 64 gnu fcoml (%rcx)
+dc11|223344556677885f5f5f5f5f5f5f 64 intel fcom st0, qword ptr [rcx]
+dc11|223344556677885f5f5f5f5f5f5f 64 plan9 FCOM 0(CX)
+dc18|11223344556677885f5f5f5f5f5f 32 intel fcomp st0, qword ptr [eax]
+dc18|11223344556677885f5f5f5f5f5f 32 plan9 FCOMP 0(AX)
+dc18|11223344556677885f5f5f5f5f5f 64 gnu fcompl (%rax)
+dc18|11223344556677885f5f5f5f5f5f 64 intel fcomp st0, qword ptr [rax]
+dc18|11223344556677885f5f5f5f5f5f 64 plan9 FCOMP 0(AX)
+dc20|11223344556677885f5f5f5f5f5f 32 intel fsub st0, qword ptr [eax]
+dc20|11223344556677885f5f5f5f5f5f 32 plan9 FSUB 0(AX)
+dc20|11223344556677885f5f5f5f5f5f 64 gnu fsubl (%rax)
+dc20|11223344556677885f5f5f5f5f5f 64 intel fsub st0, qword ptr [rax]
+dc20|11223344556677885f5f5f5f5f5f 64 plan9 FSUB 0(AX)
+dc28|11223344556677885f5f5f5f5f5f 32 intel fsubr st0, qword ptr [eax]
+dc28|11223344556677885f5f5f5f5f5f 32 plan9 FSUBR 0(AX)
+dc28|11223344556677885f5f5f5f5f5f 64 gnu fsubrl (%rax)
+dc28|11223344556677885f5f5f5f5f5f 64 intel fsubr st0, qword ptr [rax]
+dc28|11223344556677885f5f5f5f5f5f 64 plan9 FSUBR 0(AX)
+dc30|11223344556677885f5f5f5f5f5f 32 intel fdiv st0, qword ptr [eax]
+dc30|11223344556677885f5f5f5f5f5f 32 plan9 FDIV 0(AX)
+dc30|11223344556677885f5f5f5f5f5f 64 gnu fdivl (%rax)
+dc30|11223344556677885f5f5f5f5f5f 64 intel fdiv st0, qword ptr [rax]
+dc30|11223344556677885f5f5f5f5f5f 64 plan9 FDIV 0(AX)
+dc38|11223344556677885f5f5f5f5f5f 32 intel fdivr st0, qword ptr [eax]
+dc38|11223344556677885f5f5f5f5f5f 32 plan9 FDIVR 0(AX)
+dc38|11223344556677885f5f5f5f5f5f 64 gnu fdivrl (%rax)
+dc38|11223344556677885f5f5f5f5f5f 64 intel fdivr st0, qword ptr [rax]
+dc38|11223344556677885f5f5f5f5f5f 64 plan9 FDIVR 0(AX)
+dcc0|11223344556677885f5f5f5f5f5f 32 intel fadd st0, st0
+dcc0|11223344556677885f5f5f5f5f5f 32 plan9 FADD F0, F0
+dcc0|11223344556677885f5f5f5f5f5f 64 gnu fadd %st,%st
+dcc0|11223344556677885f5f5f5f5f5f 64 intel fadd st0, st0
+dcc0|11223344556677885f5f5f5f5f5f 64 plan9 FADD F0, F0
+dcc8|11223344556677885f5f5f5f5f5f 32 intel fmul st0, st0
+dcc8|11223344556677885f5f5f5f5f5f 32 plan9 FMUL F0, F0
+dcc8|11223344556677885f5f5f5f5f5f 64 gnu fmul %st,%st
+dcc8|11223344556677885f5f5f5f5f5f 64 intel fmul st0, st0
+dcc8|11223344556677885f5f5f5f5f5f 64 plan9 FMUL F0, F0
+dce0|11223344556677885f5f5f5f5f5f 32 intel fsubr st0, st0
+dce0|11223344556677885f5f5f5f5f5f 32 plan9 FSUBR F0, F0
+dce0|11223344556677885f5f5f5f5f5f 64 gnu fsub %st,%st
+dce0|11223344556677885f5f5f5f5f5f 64 intel fsubr st0, st0
+dce0|11223344556677885f5f5f5f5f5f 64 plan9 FSUBR F0, F0
+dce8|11223344556677885f5f5f5f5f5f 32 intel fsub st0, st0
+dce8|11223344556677885f5f5f5f5f5f 32 plan9 FSUB F0, F0
+dce8|11223344556677885f5f5f5f5f5f 64 gnu fsubr %st,%st
+dce8|11223344556677885f5f5f5f5f5f 64 intel fsub st0, st0
+dce8|11223344556677885f5f5f5f5f5f 64 plan9 FSUB F0, F0
+dcf0|11223344556677885f5f5f5f5f5f 32 intel fdivr st0, st0
+dcf0|11223344556677885f5f5f5f5f5f 32 plan9 FDIVR F0, F0
+dcf0|11223344556677885f5f5f5f5f5f 64 gnu fdiv %st,%st
+dcf0|11223344556677885f5f5f5f5f5f 64 intel fdivr st0, st0
+dcf0|11223344556677885f5f5f5f5f5f 64 plan9 FDIVR F0, F0
+dcf8|11223344556677885f5f5f5f5f5f 32 intel fdiv st0, st0
+dcf8|11223344556677885f5f5f5f5f5f 32 plan9 FDIV F0, F0
+dcf8|11223344556677885f5f5f5f5f5f 64 gnu fdivr %st,%st
+dcf8|11223344556677885f5f5f5f5f5f 64 intel fdiv st0, st0
+dcf8|11223344556677885f5f5f5f5f5f 64 plan9 FDIV F0, F0
+dd00|11223344556677885f5f5f5f5f5f 32 intel fld st0, qword ptr [eax]
+dd00|11223344556677885f5f5f5f5f5f 32 plan9 FLD 0(AX)
+dd00|11223344556677885f5f5f5f5f5f 64 gnu fldl (%rax)
+dd00|11223344556677885f5f5f5f5f5f 64 intel fld st0, qword ptr [rax]
+dd00|11223344556677885f5f5f5f5f5f 64 plan9 FLD 0(AX)
+dd08|11223344556677885f5f5f5f5f5f 32 intel fisttp qword ptr [eax], st0
+dd08|11223344556677885f5f5f5f5f5f 32 plan9 FISTTP 0(AX)
+dd08|11223344556677885f5f5f5f5f5f 64 gnu fisttpll (%rax)
+dd08|11223344556677885f5f5f5f5f5f 64 intel fisttp qword ptr [rax], st0
+dd08|11223344556677885f5f5f5f5f5f 64 plan9 FISTTP 0(AX)
+dd11|223344556677885f5f5f5f5f5f5f 32 intel fst qword ptr [ecx], st0
+dd11|223344556677885f5f5f5f5f5f5f 32 plan9 FST 0(CX)
+dd11|223344556677885f5f5f5f5f5f5f 64 gnu fstl (%rcx)
+dd11|223344556677885f5f5f5f5f5f5f 64 intel fst qword ptr [rcx], st0
+dd11|223344556677885f5f5f5f5f5f5f 64 plan9 FST 0(CX)
+dd18|11223344556677885f5f5f5f5f5f 32 intel fstp qword ptr [eax], st0
+dd18|11223344556677885f5f5f5f5f5f 32 plan9 FSTP 0(AX)
+dd18|11223344556677885f5f5f5f5f5f 64 gnu fstpl (%rax)
+dd18|11223344556677885f5f5f5f5f5f 64 intel fstp qword ptr [rax], st0
+dd18|11223344556677885f5f5f5f5f5f 64 plan9 FSTP 0(AX)
+dd20|11223344556677885f5f5f5f5f5f 32 intel frstor ptr [eax]
+dd20|11223344556677885f5f5f5f5f5f 32 plan9 FRSTORL 0(AX)
+dd20|11223344556677885f5f5f5f5f5f 64 gnu frstor (%rax)
+dd20|11223344556677885f5f5f5f5f5f 64 intel frstor ptr [rax]
+dd20|11223344556677885f5f5f5f5f5f 64 plan9 FRSTORL 0(AX)
+dd30|11223344556677885f5f5f5f5f5f 32 intel fnsave ptr [eax]
+dd30|11223344556677885f5f5f5f5f5f 32 plan9 FNSAVE 0(AX)
+dd30|11223344556677885f5f5f5f5f5f 64 gnu fnsave (%rax)
+dd30|11223344556677885f5f5f5f5f5f 64 intel fnsave ptr [rax]
+dd30|11223344556677885f5f5f5f5f5f 64 plan9 FNSAVE 0(AX)
+dd38|11223344556677885f5f5f5f5f5f 32 intel fnstsw word ptr [eax]
+dd38|11223344556677885f5f5f5f5f5f 32 plan9 FNSTSW 0(AX)
+dd38|11223344556677885f5f5f5f5f5f 64 gnu fnstsw (%rax)
+dd38|11223344556677885f5f5f5f5f5f 64 intel fnstsw word ptr [rax]
+dd38|11223344556677885f5f5f5f5f5f 64 plan9 FNSTSW 0(AX)
+ddc0|11223344556677885f5f5f5f5f5f 32 intel ffree st0
+ddc0|11223344556677885f5f5f5f5f5f 32 plan9 FFREE F0
+ddc0|11223344556677885f5f5f5f5f5f 64 gnu ffree %st
+ddc0|11223344556677885f5f5f5f5f5f 64 intel ffree st0
+ddc0|11223344556677885f5f5f5f5f5f 64 plan9 FFREE F0
+ddd0|11223344556677885f5f5f5f5f5f 32 intel fst st0, st0
+ddd0|11223344556677885f5f5f5f5f5f 32 plan9 FST F0
+ddd0|11223344556677885f5f5f5f5f5f 64 gnu fst %st
+ddd0|11223344556677885f5f5f5f5f5f 64 intel fst st0, st0
+ddd0|11223344556677885f5f5f5f5f5f 64 plan9 FST F0
+ddd8|11223344556677885f5f5f5f5f5f 32 intel fstp st0, st0
+ddd8|11223344556677885f5f5f5f5f5f 32 plan9 FSTP F0
+ddd8|11223344556677885f5f5f5f5f5f 64 gnu fstp %st
+ddd8|11223344556677885f5f5f5f5f5f 64 intel fstp st0, st0
+ddd8|11223344556677885f5f5f5f5f5f 64 plan9 FSTP F0
+dde0|11223344556677885f5f5f5f5f5f 32 intel fucom st0, st0
+dde0|11223344556677885f5f5f5f5f5f 32 plan9 FUCOM F0
+dde0|11223344556677885f5f5f5f5f5f 64 gnu fucom %st
+dde0|11223344556677885f5f5f5f5f5f 64 intel fucom st0, st0
+dde0|11223344556677885f5f5f5f5f5f 64 plan9 FUCOM F0
+dde8|11223344556677885f5f5f5f5f5f 32 intel fucomp st0, st0
+dde8|11223344556677885f5f5f5f5f5f 32 plan9 FUCOMP F0
+dde8|11223344556677885f5f5f5f5f5f 64 gnu fucomp %st
+dde8|11223344556677885f5f5f5f5f5f 64 intel fucomp st0, st0
+dde8|11223344556677885f5f5f5f5f5f 64 plan9 FUCOMP F0
+de00|11223344556677885f5f5f5f5f5f 32 intel fiadd st0, word ptr [eax]
+de00|11223344556677885f5f5f5f5f5f 32 plan9 FIADD 0(AX)
+de00|11223344556677885f5f5f5f5f5f 64 gnu fiadd (%rax)
+de00|11223344556677885f5f5f5f5f5f 64 intel fiadd st0, word ptr [rax]
+de00|11223344556677885f5f5f5f5f5f 64 plan9 FIADD 0(AX)
+de08|11223344556677885f5f5f5f5f5f 32 intel fimul st0, word ptr [eax]
+de08|11223344556677885f5f5f5f5f5f 32 plan9 FIMUL 0(AX)
+de08|11223344556677885f5f5f5f5f5f 64 gnu fimul (%rax)
+de08|11223344556677885f5f5f5f5f5f 64 intel fimul st0, word ptr [rax]
+de08|11223344556677885f5f5f5f5f5f 64 plan9 FIMUL 0(AX)
+de11|223344556677885f5f5f5f5f5f5f 32 intel ficom st0, word ptr [ecx]
+de11|223344556677885f5f5f5f5f5f5f 32 plan9 FICOM 0(CX)
+de11|223344556677885f5f5f5f5f5f5f 64 gnu ficom (%rcx)
+de11|223344556677885f5f5f5f5f5f5f 64 intel ficom st0, word ptr [rcx]
+de11|223344556677885f5f5f5f5f5f5f 64 plan9 FICOM 0(CX)
+de18|11223344556677885f5f5f5f5f5f 32 intel ficomp st0, word ptr [eax]
+de18|11223344556677885f5f5f5f5f5f 32 plan9 FICOMP 0(AX)
+de18|11223344556677885f5f5f5f5f5f 64 gnu ficomp (%rax)
+de18|11223344556677885f5f5f5f5f5f 64 intel ficomp st0, word ptr [rax]
+de18|11223344556677885f5f5f5f5f5f 64 plan9 FICOMP 0(AX)
+de20|11223344556677885f5f5f5f5f5f 32 intel fisub st0, word ptr [eax]
+de20|11223344556677885f5f5f5f5f5f 32 plan9 FISUB 0(AX)
+de20|11223344556677885f5f5f5f5f5f 64 gnu fisub (%rax)
+de20|11223344556677885f5f5f5f5f5f 64 intel fisub st0, word ptr [rax]
+de20|11223344556677885f5f5f5f5f5f 64 plan9 FISUB 0(AX)
+de28|11223344556677885f5f5f5f5f5f 32 intel fisubr st0, word ptr [eax]
+de28|11223344556677885f5f5f5f5f5f 32 plan9 FISUBR 0(AX)
+de28|11223344556677885f5f5f5f5f5f 64 gnu fisubr (%rax)
+de28|11223344556677885f5f5f5f5f5f 64 intel fisubr st0, word ptr [rax]
+de28|11223344556677885f5f5f5f5f5f 64 plan9 FISUBR 0(AX)
+de30|11223344556677885f5f5f5f5f5f 32 intel fidiv st0, word ptr [eax]
+de30|11223344556677885f5f5f5f5f5f 32 plan9 FIDIV 0(AX)
+de30|11223344556677885f5f5f5f5f5f 64 gnu fidiv (%rax)
+de30|11223344556677885f5f5f5f5f5f 64 intel fidiv st0, word ptr [rax]
+de30|11223344556677885f5f5f5f5f5f 64 plan9 FIDIV 0(AX)
+de38|11223344556677885f5f5f5f5f5f 32 intel fidivr st0, word ptr [eax]
+de38|11223344556677885f5f5f5f5f5f 32 plan9 FIDIVR 0(AX)
+de38|11223344556677885f5f5f5f5f5f 64 gnu fidivr (%rax)
+de38|11223344556677885f5f5f5f5f5f 64 intel fidivr st0, word ptr [rax]
+de38|11223344556677885f5f5f5f5f5f 64 plan9 FIDIVR 0(AX)
+dec0|11223344556677885f5f5f5f5f5f 32 intel faddp st0, st0
+dec0|11223344556677885f5f5f5f5f5f 32 plan9 FADDP F0, F0
+dec0|11223344556677885f5f5f5f5f5f 64 gnu faddp %st,%st
+dec0|11223344556677885f5f5f5f5f5f 64 intel faddp st0, st0
+dec0|11223344556677885f5f5f5f5f5f 64 plan9 FADDP F0, F0
+dec8|11223344556677885f5f5f5f5f5f 32 intel fmulp st0, st0
+dec8|11223344556677885f5f5f5f5f5f 32 plan9 FMULP F0, F0
+dec8|11223344556677885f5f5f5f5f5f 64 gnu fmulp %st,%st
+dec8|11223344556677885f5f5f5f5f5f 64 intel fmulp st0, st0
+dec8|11223344556677885f5f5f5f5f5f 64 plan9 FMULP F0, F0
+ded9|11223344556677885f5f5f5f5f5f 32 intel fcompp st0, st1
+ded9|11223344556677885f5f5f5f5f5f 32 plan9 FCOMPP
+ded9|11223344556677885f5f5f5f5f5f 64 gnu fcompp
+ded9|11223344556677885f5f5f5f5f5f 64 intel fcompp st0, st1
+ded9|11223344556677885f5f5f5f5f5f 64 plan9 FCOMPP
+dee0|11223344556677885f5f5f5f5f5f 32 intel fsubrp st0, st0
+dee0|11223344556677885f5f5f5f5f5f 32 plan9 FSUBRP F0, F0
+dee0|11223344556677885f5f5f5f5f5f 64 gnu fsubp %st,%st
+dee0|11223344556677885f5f5f5f5f5f 64 intel fsubrp st0, st0
+dee0|11223344556677885f5f5f5f5f5f 64 plan9 FSUBRP F0, F0
+dee8|11223344556677885f5f5f5f5f5f 32 intel fsubp st0, st0
+dee8|11223344556677885f5f5f5f5f5f 32 plan9 FSUBP F0, F0
+dee8|11223344556677885f5f5f5f5f5f 64 gnu fsubrp %st,%st
+dee8|11223344556677885f5f5f5f5f5f 64 intel fsubp st0, st0
+dee8|11223344556677885f5f5f5f5f5f 64 plan9 FSUBP F0, F0
+def0|11223344556677885f5f5f5f5f5f 32 intel fdivrp st0, st0
+def0|11223344556677885f5f5f5f5f5f 32 plan9 FDIVRP F0, F0
+def0|11223344556677885f5f5f5f5f5f 64 gnu fdivp %st,%st
+def0|11223344556677885f5f5f5f5f5f 64 intel fdivrp st0, st0
+def0|11223344556677885f5f5f5f5f5f 64 plan9 FDIVRP F0, F0
+def8|11223344556677885f5f5f5f5f5f 32 intel fdivp st0, st0
+def8|11223344556677885f5f5f5f5f5f 32 plan9 FDIVP F0, F0
+def8|11223344556677885f5f5f5f5f5f 64 gnu fdivrp %st,%st
+def8|11223344556677885f5f5f5f5f5f 64 intel fdivp st0, st0
+def8|11223344556677885f5f5f5f5f5f 64 plan9 FDIVP F0, F0
+df00|11223344556677885f5f5f5f5f5f 32 intel fild st0, word ptr [eax]
+df00|11223344556677885f5f5f5f5f5f 32 plan9 FILD 0(AX)
+df00|11223344556677885f5f5f5f5f5f 64 gnu fild (%rax)
+df00|11223344556677885f5f5f5f5f5f 64 intel fild st0, word ptr [rax]
+df00|11223344556677885f5f5f5f5f5f 64 plan9 FILD 0(AX)
+df08|11223344556677885f5f5f5f5f5f 32 intel fisttp word ptr [eax], st0
+df08|11223344556677885f5f5f5f5f5f 32 plan9 FISTTP 0(AX)
+df08|11223344556677885f5f5f5f5f5f 64 gnu fisttp (%rax)
+df08|11223344556677885f5f5f5f5f5f 64 intel fisttp word ptr [rax], st0
+df08|11223344556677885f5f5f5f5f5f 64 plan9 FISTTP 0(AX)
+df11|223344556677885f5f5f5f5f5f5f 32 intel fist word ptr [ecx], st0
+df11|223344556677885f5f5f5f5f5f5f 32 plan9 FIST 0(CX)
+df11|223344556677885f5f5f5f5f5f5f 64 gnu fist (%rcx)
+df11|223344556677885f5f5f5f5f5f5f 64 intel fist word ptr [rcx], st0
+df11|223344556677885f5f5f5f5f5f5f 64 plan9 FIST 0(CX)
+df18|11223344556677885f5f5f5f5f5f 32 intel fistp word ptr [eax], st0
+df18|11223344556677885f5f5f5f5f5f 32 plan9 FISTP 0(AX)
+df18|11223344556677885f5f5f5f5f5f 64 gnu fistp (%rax)
+df18|11223344556677885f5f5f5f5f5f 64 intel fistp word ptr [rax], st0
+df18|11223344556677885f5f5f5f5f5f 64 plan9 FISTP 0(AX)
+df20|11223344556677885f5f5f5f5f5f 32 intel fbld st0, ptr [eax]
+df20|11223344556677885f5f5f5f5f5f 32 plan9 FBLD 0(AX)
+df20|11223344556677885f5f5f5f5f5f 64 gnu fbld (%rax)
+df20|11223344556677885f5f5f5f5f5f 64 intel fbld st0, ptr [rax]
+df20|11223344556677885f5f5f5f5f5f 64 plan9 FBLD 0(AX)
+df28|11223344556677885f5f5f5f5f5f 32 intel fild st0, qword ptr [eax]
+df28|11223344556677885f5f5f5f5f5f 32 plan9 FILD 0(AX)
+df28|11223344556677885f5f5f5f5f5f 64 gnu fildll (%rax)
+df28|11223344556677885f5f5f5f5f5f 64 intel fild st0, qword ptr [rax]
+df28|11223344556677885f5f5f5f5f5f 64 plan9 FILD 0(AX)
+df30|11223344556677885f5f5f5f5f5f 32 intel fbstp ptr [eax], st0
+df30|11223344556677885f5f5f5f5f5f 32 plan9 FBSTP 0(AX)
+df30|11223344556677885f5f5f5f5f5f 64 gnu fbstp (%rax)
+df30|11223344556677885f5f5f5f5f5f 64 intel fbstp ptr [rax], st0
+df30|11223344556677885f5f5f5f5f5f 64 plan9 FBSTP 0(AX)
+df38|11223344556677885f5f5f5f5f5f 32 intel fistp qword ptr [eax], st0
+df38|11223344556677885f5f5f5f5f5f 32 plan9 FISTP 0(AX)
+df38|11223344556677885f5f5f5f5f5f 64 gnu fistpll (%rax)
+df38|11223344556677885f5f5f5f5f5f 64 intel fistp qword ptr [rax], st0
+df38|11223344556677885f5f5f5f5f5f 64 plan9 FISTP 0(AX)
+dfc0|11223344556677885f5f5f5f5f5f 32 intel ffreep st0
+dfc0|11223344556677885f5f5f5f5f5f 32 plan9 FFREEP F0
+dfc0|11223344556677885f5f5f5f5f5f 64 gnu ffreep %st
+dfc0|11223344556677885f5f5f5f5f5f 64 intel ffreep st0
+dfc0|11223344556677885f5f5f5f5f5f 64 plan9 FFREEP F0
+dfe0|11223344556677885f5f5f5f5f5f 32 intel fnstsw ax
+dfe0|11223344556677885f5f5f5f5f5f 32 plan9 FNSTSW AX
+dfe0|11223344556677885f5f5f5f5f5f 64 gnu fnstsw %ax
+dfe0|11223344556677885f5f5f5f5f5f 64 intel fnstsw ax
+dfe0|11223344556677885f5f5f5f5f5f 64 plan9 FNSTSW AX
+dfe8|11223344556677885f5f5f5f5f5f 32 intel fucomip st0, st0
+dfe8|11223344556677885f5f5f5f5f5f 32 plan9 FUCOMIP F0, F0
+dfe8|11223344556677885f5f5f5f5f5f 64 gnu fucomip %st,%st
+dfe8|11223344556677885f5f5f5f5f5f 64 intel fucomip st0, st0
+dfe8|11223344556677885f5f5f5f5f5f 64 plan9 FUCOMIP F0, F0
+dff0|11223344556677885f5f5f5f5f5f 32 intel fcomip st0, st0
+dff0|11223344556677885f5f5f5f5f5f 32 plan9 FCOMIP F0, F0
+dff0|11223344556677885f5f5f5f5f5f 64 gnu fcomip %st,%st
+dff0|11223344556677885f5f5f5f5f5f 64 intel fcomip st0, st0
+dff0|11223344556677885f5f5f5f5f5f 64 plan9 FCOMIP F0, F0
+e111|223344556677885f5f5f5f5f5f5f 32 intel loope .+0x11
+e111|223344556677885f5f5f5f5f5f5f 32 plan9 LOOPE .+17
+e111|223344556677885f5f5f5f5f5f5f 64 gnu loope .+0x11
+e111|223344556677885f5f5f5f5f5f5f 64 intel loope .+0x11
+e111|223344556677885f5f5f5f5f5f5f 64 plan9 LOOPE .+17
+e211|223344556677885f5f5f5f5f5f5f 32 intel loop .+0x11
+e211|223344556677885f5f5f5f5f5f5f 32 plan9 LOOP .+17
+e211|223344556677885f5f5f5f5f5f5f 64 gnu loop .+0x11
+e211|223344556677885f5f5f5f5f5f5f 64 intel loop .+0x11
+e211|223344556677885f5f5f5f5f5f5f 64 plan9 LOOP .+17
+e311|223344556677885f5f5f5f5f5f5f 32 intel jecxz .+0x11
+e311|223344556677885f5f5f5f5f5f5f 32 plan9 JECXZ .+17
+e311|223344556677885f5f5f5f5f5f5f 64 gnu jrcxz .+0x11
+e311|223344556677885f5f5f5f5f5f5f 64 intel jrcxz .+0x11
+e311|223344556677885f5f5f5f5f5f5f 64 plan9 JRCXZ .+17
+e411|223344556677885f5f5f5f5f5f5f 32 intel in al, 0x11
+e411|223344556677885f5f5f5f5f5f5f 32 plan9 INL $0x11, AL
+e411|223344556677885f5f5f5f5f5f5f 64 gnu in $0x11,%al
+e411|223344556677885f5f5f5f5f5f5f 64 intel in al, 0x11
+e411|223344556677885f5f5f5f5f5f5f 64 plan9 INL $0x11, AL
+e511|223344556677885f5f5f5f5f5f5f 32 intel in eax, 0x11
+e511|223344556677885f5f5f5f5f5f5f 32 plan9 INL $0x11, AX
+e511|223344556677885f5f5f5f5f5f5f 64 gnu in $0x11,%eax
+e511|223344556677885f5f5f5f5f5f5f 64 intel in eax, 0x11
+e511|223344556677885f5f5f5f5f5f5f 64 plan9 INL $0x11, AX
+e611|223344556677885f5f5f5f5f5f5f 32 intel out 0x11, al
+e611|223344556677885f5f5f5f5f5f5f 32 plan9 OUTL AL, $0x11
+e611|223344556677885f5f5f5f5f5f5f 64 gnu out %al,$0x11
+e611|223344556677885f5f5f5f5f5f5f 64 intel out 0x11, al
+e611|223344556677885f5f5f5f5f5f5f 64 plan9 OUTL AL, $0x11
+e711|223344556677885f5f5f5f5f5f5f 32 intel out 0x11, eax
+e711|223344556677885f5f5f5f5f5f5f 32 plan9 OUTL AX, $0x11
+e711|223344556677885f5f5f5f5f5f5f 64 gnu out %eax,$0x11
+e711|223344556677885f5f5f5f5f5f5f 64 intel out 0x11, eax
+e711|223344556677885f5f5f5f5f5f5f 64 plan9 OUTL AX, $0x11
+e811223344|556677885f5f5f5f5f5f5f 32 intel call .+0x44332211
+e811223344|556677885f5f5f5f5f5f5f 32 plan9 CALL .+1144201745
+e811223344|556677885f5f5f5f5f5f5f 64 gnu callq .+0x44332211
+e811223344|556677885f5f5f5f5f5f5f 64 intel call .+0x44332211
+e811223344|556677885f5f5f5f5f5f5f 64 plan9 CALL .+1144201745
+e911223344|556677885f5f5f5f5f5f5f 32 intel jmp .+0x44332211
+e911223344|556677885f5f5f5f5f5f5f 32 plan9 JMP .+1144201745
+e911223344|556677885f5f5f5f5f5f5f 64 gnu jmpq .+0x44332211
+e911223344|556677885f5f5f5f5f5f5f 64 intel jmp .+0x44332211
+e911223344|556677885f5f5f5f5f5f5f 64 plan9 JMP .+1144201745
+ea112233445566|77885f5f5f5f5f5f5f 32 intel jmp far 0x44332211, 0x6655
+ea112233445566|77885f5f5f5f5f5f5f 32 plan9 LJMP $0x44332211, $0x6655
+eb11|223344556677885f5f5f5f5f5f5f 32 intel jmp .+0x11
+eb11|223344556677885f5f5f5f5f5f5f 32 plan9 JMP .+17
+eb11|223344556677885f5f5f5f5f5f5f 64 gnu jmp .+0x11
+eb11|223344556677885f5f5f5f5f5f5f 64 intel jmp .+0x11
+eb11|223344556677885f5f5f5f5f5f5f 64 plan9 JMP .+17
+ec|11223344556677885f5f5f5f5f5f5f 32 intel in al, dx
+ec|11223344556677885f5f5f5f5f5f5f 32 plan9 INL DX, AL
+ec|11223344556677885f5f5f5f5f5f5f 64 gnu in (%dx),%al
+ec|11223344556677885f5f5f5f5f5f5f 64 intel in al, dx
+ec|11223344556677885f5f5f5f5f5f5f 64 plan9 INL DX, AL
+ed|11223344556677885f5f5f5f5f5f5f 32 intel in eax, dx
+ed|11223344556677885f5f5f5f5f5f5f 32 plan9 INL DX, AX
+ed|11223344556677885f5f5f5f5f5f5f 64 gnu in (%dx),%eax
+ed|11223344556677885f5f5f5f5f5f5f 64 intel in eax, dx
+ed|11223344556677885f5f5f5f5f5f5f 64 plan9 INL DX, AX
+ee|11223344556677885f5f5f5f5f5f5f 32 intel out dx, al
+ee|11223344556677885f5f5f5f5f5f5f 32 plan9 OUTL AL, DX
+ee|11223344556677885f5f5f5f5f5f5f 64 gnu out %al,(%dx)
+ee|11223344556677885f5f5f5f5f5f5f 64 intel out dx, al
+ee|11223344556677885f5f5f5f5f5f5f 64 plan9 OUTL AL, DX
+ef|11223344556677885f5f5f5f5f5f5f 32 intel out dx, eax
+ef|11223344556677885f5f5f5f5f5f5f 32 plan9 OUTL AX, DX
+ef|11223344556677885f5f5f5f5f5f5f 64 gnu out %eax,(%dx)
+ef|11223344556677885f5f5f5f5f5f5f 64 intel out dx, eax
+ef|11223344556677885f5f5f5f5f5f5f 64 plan9 OUTL AX, DX
+f1|11223344556677885f5f5f5f5f5f5f 32 intel int1
+f1|11223344556677885f5f5f5f5f5f5f 32 plan9 ICEBP
+f1|11223344556677885f5f5f5f5f5f5f 64 gnu icebp
+f1|11223344556677885f5f5f5f5f5f5f 64 intel int1
+f1|11223344556677885f5f5f5f5f5f5f 64 plan9 ICEBP
+f20f1011|223344556677885f5f5f5f5f 32 intel movsd xmm2, qword ptr [ecx]
+f20f1011|223344556677885f5f5f5f5f 32 plan9 REPNE MOVSD_XMM 0(CX), X2
+f20f1011|223344556677885f5f5f5f5f 64 gnu movsd (%rcx),%xmm2
+f20f1011|223344556677885f5f5f5f5f 64 intel movsd xmm2, qword ptr [rcx]
+f20f1011|223344556677885f5f5f5f5f 64 plan9 REPNE MOVSD_XMM 0(CX), X2
+f20f1122|3344556677885f5f5f5f5f5f 32 intel movsd qword ptr [edx], xmm4
+f20f1122|3344556677885f5f5f5f5f5f 32 plan9 REPNE MOVSD_XMM X4, 0(DX)
+f20f1122|3344556677885f5f5f5f5f5f 64 gnu movsd %xmm4,(%rdx)
+f20f1122|3344556677885f5f5f5f5f5f 64 intel movsd qword ptr [rdx], xmm4
+f20f1122|3344556677885f5f5f5f5f5f 64 plan9 REPNE MOVSD_XMM X4, 0(DX)
+f20f1211|223344556677885f5f5f5f5f 32 intel movddup xmm2, qword ptr [ecx]
+f20f1211|223344556677885f5f5f5f5f 32 plan9 REPNE MOVDDUP 0(CX), X2
+f20f1211|223344556677885f5f5f5f5f 64 gnu movddup (%rcx),%xmm2
+f20f1211|223344556677885f5f5f5f5f 64 intel movddup xmm2, qword ptr [rcx]
+f20f1211|223344556677885f5f5f5f5f 64 plan9 REPNE MOVDDUP 0(CX), X2
+f20f2a11|223344556677885f5f5f5f5f 32 intel cvtsi2sd xmm2, dword ptr [ecx]
+f20f2a11|223344556677885f5f5f5f5f 32 plan9 REPNE CVTSI2SDL 0(CX), X2
+f20f2a11|223344556677885f5f5f5f5f 64 gnu cvtsi2sdl (%rcx),%xmm2
+f20f2a11|223344556677885f5f5f5f5f 64 intel cvtsi2sd xmm2, dword ptr [rcx]
+f20f2a11|223344556677885f5f5f5f5f 64 plan9 REPNE CVTSI2SDL 0(CX), X2
+f20f2c11|223344556677885f5f5f5f5f 32 intel cvttsd2si edx, qword ptr [ecx]
+f20f2c11|223344556677885f5f5f5f5f 32 plan9 REPNE CVTTSD2SIL 0(CX), DX
+f20f2c11|223344556677885f5f5f5f5f 64 gnu cvttsd2si (%rcx),%edx
+f20f2c11|223344556677885f5f5f5f5f 64 intel cvttsd2si edx, qword ptr [rcx]
+f20f2c11|223344556677885f5f5f5f5f 64 plan9 REPNE CVTTSD2SIL 0(CX), DX
+f20f2d11|223344556677885f5f5f5f5f 32 intel cvtsd2si edx, qword ptr [ecx]
+f20f2d11|223344556677885f5f5f5f5f 32 plan9 REPNE CVTSD2SIL 0(CX), DX
+f20f2d11|223344556677885f5f5f5f5f 64 gnu cvtsd2si (%rcx),%edx
+f20f2d11|223344556677885f5f5f5f5f 64 intel cvtsd2si edx, qword ptr [rcx]
+f20f2d11|223344556677885f5f5f5f5f 64 plan9 REPNE CVTSD2SIL 0(CX), DX
+f20f38f011|223344556677885f5f5f5f 32 intel crc32 edx, byte ptr [ecx]
+f20f38f011|223344556677885f5f5f5f 32 plan9 REPNE CRC32 0(CX), DX
+f20f38f011|223344556677885f5f5f5f 64 gnu crc32b (%rcx),%edx
+f20f38f011|223344556677885f5f5f5f 64 intel crc32 edx, byte ptr [rcx]
+f20f38f011|223344556677885f5f5f5f 64 plan9 REPNE CRC32 0(CX), DX
+f20f38f111|223344556677885f5f5f5f 32 intel crc32 edx, dword ptr [ecx]
+f20f38f111|223344556677885f5f5f5f 32 plan9 REPNE CRC32 0(CX), DX
+f20f38f111|223344556677885f5f5f5f 64 gnu crc32l (%rcx),%edx
+f20f38f111|223344556677885f5f5f5f 64 intel crc32 edx, dword ptr [rcx]
+f20f38f111|223344556677885f5f5f5f 64 plan9 REPNE CRC32 0(CX), DX
+f20f5111|223344556677885f5f5f5f5f 32 intel sqrtsd xmm2, qword ptr [ecx]
+f20f5111|223344556677885f5f5f5f5f 32 plan9 REPNE SQRTSD 0(CX), X2
+f20f5111|223344556677885f5f5f5f5f 64 gnu sqrtsd (%rcx),%xmm2
+f20f5111|223344556677885f5f5f5f5f 64 intel sqrtsd xmm2, qword ptr [rcx]
+f20f5111|223344556677885f5f5f5f5f 64 plan9 REPNE SQRTSD 0(CX), X2
+f20f5811|223344556677885f5f5f5f5f 32 intel addsd xmm2, qword ptr [ecx]
+f20f5811|223344556677885f5f5f5f5f 32 plan9 REPNE ADDSD 0(CX), X2
+f20f5811|223344556677885f5f5f5f5f 64 gnu addsd (%rcx),%xmm2
+f20f5811|223344556677885f5f5f5f5f 64 intel addsd xmm2, qword ptr [rcx]
+f20f5811|223344556677885f5f5f5f5f 64 plan9 REPNE ADDSD 0(CX), X2
+f20f5911|223344556677885f5f5f5f5f 32 intel mulsd xmm2, qword ptr [ecx]
+f20f5911|223344556677885f5f5f5f5f 32 plan9 REPNE MULSD 0(CX), X2
+f20f5911|223344556677885f5f5f5f5f 64 gnu mulsd (%rcx),%xmm2
+f20f5911|223344556677885f5f5f5f5f 64 intel mulsd xmm2, qword ptr [rcx]
+f20f5911|223344556677885f5f5f5f5f 64 plan9 REPNE MULSD 0(CX), X2
+f20f5a11|223344556677885f5f5f5f5f 32 intel cvtsd2ss xmm2, qword ptr [ecx]
+f20f5a11|223344556677885f5f5f5f5f 32 plan9 REPNE CVTSD2SS 0(CX), X2
+f20f5a11|223344556677885f5f5f5f5f 64 gnu cvtsd2ss (%rcx),%xmm2
+f20f5a11|223344556677885f5f5f5f5f 64 intel cvtsd2ss xmm2, qword ptr [rcx]
+f20f5a11|223344556677885f5f5f5f5f 64 plan9 REPNE CVTSD2SS 0(CX), X2
+f20f5c11|223344556677885f5f5f5f5f 32 intel subsd xmm2, qword ptr [ecx]
+f20f5c11|223344556677885f5f5f5f5f 32 plan9 REPNE SUBSD 0(CX), X2
+f20f5c11|223344556677885f5f5f5f5f 64 gnu subsd (%rcx),%xmm2
+f20f5c11|223344556677885f5f5f5f5f 64 intel subsd xmm2, qword ptr [rcx]
+f20f5c11|223344556677885f5f5f5f5f 64 plan9 REPNE SUBSD 0(CX), X2
+f20f5d11|223344556677885f5f5f5f5f 32 intel minsd xmm2, qword ptr [ecx]
+f20f5d11|223344556677885f5f5f5f5f 32 plan9 REPNE MINSD 0(CX), X2
+f20f5d11|223344556677885f5f5f5f5f 64 gnu minsd (%rcx),%xmm2
+f20f5d11|223344556677885f5f5f5f5f 64 intel minsd xmm2, qword ptr [rcx]
+f20f5d11|223344556677885f5f5f5f5f 64 plan9 REPNE MINSD 0(CX), X2
+f20f5e11|223344556677885f5f5f5f5f 32 intel divsd xmm2, qword ptr [ecx]
+f20f5e11|223344556677885f5f5f5f5f 32 plan9 REPNE DIVSD 0(CX), X2
+f20f5e11|223344556677885f5f5f5f5f 64 gnu divsd (%rcx),%xmm2
+f20f5e11|223344556677885f5f5f5f5f 64 intel divsd xmm2, qword ptr [rcx]
+f20f5e11|223344556677885f5f5f5f5f 64 plan9 REPNE DIVSD 0(CX), X2
+f20f5f11|223344556677885f5f5f5f5f 32 intel maxsd xmm2, qword ptr [ecx]
+f20f5f11|223344556677885f5f5f5f5f 32 plan9 REPNE MAXSD 0(CX), X2
+f20f5f11|223344556677885f5f5f5f5f 64 gnu maxsd (%rcx),%xmm2
+f20f5f11|223344556677885f5f5f5f5f 64 intel maxsd xmm2, qword ptr [rcx]
+f20f5f11|223344556677885f5f5f5f5f 64 plan9 REPNE MAXSD 0(CX), X2
+f20f701122|3344556677885f5f5f5f5f 32 intel pshuflw xmm2, xmmword ptr [ecx], 0x22
+f20f701122|3344556677885f5f5f5f5f 32 plan9 REPNE PSHUFLW $0x22, 0(CX), X2
+f20f701122|3344556677885f5f5f5f5f 64 gnu pshuflw $0x22,(%rcx),%xmm2
+f20f701122|3344556677885f5f5f5f5f 64 intel pshuflw xmm2, xmmword ptr [rcx], 0x22
+f20f701122|3344556677885f5f5f5f5f 64 plan9 REPNE PSHUFLW $0x22, 0(CX), X2
+f20f7c11|223344556677885f5f5f5f5f 32 intel haddps xmm2, xmmword ptr [ecx]
+f20f7c11|223344556677885f5f5f5f5f 32 plan9 REPNE HADDPS 0(CX), X2
+f20f7c11|223344556677885f5f5f5f5f 64 gnu haddps (%rcx),%xmm2
+f20f7c11|223344556677885f5f5f5f5f 64 intel haddps xmm2, xmmword ptr [rcx]
+f20f7c11|223344556677885f5f5f5f5f 64 plan9 REPNE HADDPS 0(CX), X2
+f20f7d11|223344556677885f5f5f5f5f 32 intel hsubps xmm2, xmmword ptr [ecx]
+f20f7d11|223344556677885f5f5f5f5f 32 plan9 REPNE HSUBPS 0(CX), X2
+f20f7d11|223344556677885f5f5f5f5f 64 gnu hsubps (%rcx),%xmm2
+f20f7d11|223344556677885f5f5f5f5f 64 intel hsubps xmm2, xmmword ptr [rcx]
+f20f7d11|223344556677885f5f5f5f5f 64 plan9 REPNE HSUBPS 0(CX), X2
+f20fc21122|3344556677885f5f5f5f5f 32 intel cmpsd_xmm xmm2, qword ptr [ecx], 0x22
+f20fc21122|3344556677885f5f5f5f5f 32 plan9 REPNE CMPSD_XMM $0x22, 0(CX), X2
+f20fc21122|3344556677885f5f5f5f5f 64 gnu cmpsd $0x22,(%rcx),%xmm2
+f20fc21122|3344556677885f5f5f5f5f 64 intel cmpsd_xmm xmm2, qword ptr [rcx], 0x22
+f20fc21122|3344556677885f5f5f5f5f 64 plan9 REPNE CMPSD_XMM $0x22, 0(CX), X2
+f20fd011|223344556677885f5f5f5f5f 32 intel addsubps xmm2, xmmword ptr [ecx]
+f20fd011|223344556677885f5f5f5f5f 32 plan9 REPNE ADDSUBPS 0(CX), X2
+f20fd011|223344556677885f5f5f5f5f 64 gnu addsubps (%rcx),%xmm2
+f20fd011|223344556677885f5f5f5f5f 64 intel addsubps xmm2, xmmword ptr [rcx]
+f20fd011|223344556677885f5f5f5f5f 64 plan9 REPNE ADDSUBPS 0(CX), X2
+f20fd6c0|11223344556677885f5f5f5f 32 intel movdq2q mmx0, xmm0
+f20fd6c0|11223344556677885f5f5f5f 32 plan9 REPNE MOVDQ2Q X0, M0
+f20fd6c0|11223344556677885f5f5f5f 64 gnu movdq2q %xmm0,%mm0
+f20fd6c0|11223344556677885f5f5f5f 64 intel movdq2q mmx0, xmm0
+f20fd6c0|11223344556677885f5f5f5f 64 plan9 REPNE MOVDQ2Q X0, M0
+f20fe611|223344556677885f5f5f5f5f 32 intel cvtpd2dq xmm2, xmmword ptr [ecx]
+f20fe611|223344556677885f5f5f5f5f 32 plan9 REPNE CVTPD2DQ 0(CX), X2
+f20fe611|223344556677885f5f5f5f5f 64 gnu cvtpd2dq (%rcx),%xmm2
+f20fe611|223344556677885f5f5f5f5f 64 intel cvtpd2dq xmm2, xmmword ptr [rcx]
+f20fe611|223344556677885f5f5f5f5f 64 plan9 REPNE CVTPD2DQ 0(CX), X2
+f20ff011|223344556677885f5f5f5f5f 32 intel lddqu xmm2, xmmword ptr [ecx]
+f20ff011|223344556677885f5f5f5f5f 32 plan9 REPNE LDDQU 0(CX), X2
+f20ff011|223344556677885f5f5f5f5f 64 gnu lddqu (%rcx),%xmm2
+f20ff011|223344556677885f5f5f5f5f 64 intel lddqu xmm2, xmmword ptr [rcx]
+f20ff011|223344556677885f5f5f5f5f 64 plan9 REPNE LDDQU 0(CX), X2
+f2480f2a11|223344556677885f5f5f5f 64 gnu cvtsi2sdq (%rcx),%xmm2
+f2480f2a11|223344556677885f5f5f5f 64 intel cvtsi2sd xmm2, qword ptr [rcx]
+f2480f2a11|223344556677885f5f5f5f 64 plan9 REPNE CVTSI2SDQ 0(CX), X2
+f2480f2c11|223344556677885f5f5f5f 64 gnu cvttsd2si (%rcx),%rdx
+f2480f2c11|223344556677885f5f5f5f 64 intel cvttsd2si rdx, qword ptr [rcx]
+f2480f2c11|223344556677885f5f5f5f 64 plan9 REPNE CVTTSD2SIQ 0(CX), DX
+f2480f2d11|223344556677885f5f5f5f 64 gnu cvtsd2si (%rcx),%rdx
+f2480f2d11|223344556677885f5f5f5f 64 intel cvtsd2si rdx, qword ptr [rcx]
+f2480f2d11|223344556677885f5f5f5f 64 plan9 REPNE CVTSD2SIQ 0(CX), DX
+f2480f38f011|223344556677885f5f5f 64 gnu crc32b (%rcx),%rdx
+f2480f38f011|223344556677885f5f5f 64 intel crc32 rdx, byte ptr [rcx]
+f2480f38f011|223344556677885f5f5f 64 plan9 REPNE CRC32 0(CX), DX
+f2480f38f111|223344556677885f5f5f 64 gnu crc32q (%rcx),%rdx
+f2480f38f111|223344556677885f5f5f 64 intel crc32 rdx, qword ptr [rcx]
+f2480f38f111|223344556677885f5f5f 64 plan9 REPNE CRC32 0(CX), DX
+f267f0663e360f38f111|223344556677 32 intel lock crc32 edx, word ptr ss:[bx+di*1]
+f267f0663e360f38f111|223344556677 32 plan9 SS CRC32 SS:0(BX)(DI*1), DX
+f267f0663e360f38f111|223344556677 64 gnu lock crc32w %ds:%ss:(%ecx),%edx
+f267f0663e360f38f111|223344556677 64 intel lock crc32 edx, word ptr [ecx]
+f267f0663e360f38f111|223344556677 64 plan9 SS CRC32 0(CX), DX
+f2f30f2b11|5f5f5f5f5f5f5f5f5f5f5f 32 intel movntss dword ptr [ecx], xmm2
+f2f30f2b11|5f5f5f5f5f5f5f5f5f5f5f 32 plan9 REP MOVNTSS X2, 0(CX)
+f2f30f2b11|5f5f5f5f5f5f5f5f5f5f5f 64 gnu repn movntss %xmm2,(%rcx)
+f2f30f2b11|5f5f5f5f5f5f5f5f5f5f5f 64 intel movntss dword ptr [rcx], xmm2
+f2f30f2b11|5f5f5f5f5f5f5f5f5f5f5f 64 plan9 REP MOVNTSS X2, 0(CX)
+f30f1011|223344556677885f5f5f5f5f 32 intel movss xmm2, dword ptr [ecx]
+f30f1011|223344556677885f5f5f5f5f 32 plan9 REP MOVSS 0(CX), X2
+f30f1011|223344556677885f5f5f5f5f 64 gnu movss (%rcx),%xmm2
+f30f1011|223344556677885f5f5f5f5f 64 intel movss xmm2, dword ptr [rcx]
+f30f1011|223344556677885f5f5f5f5f 64 plan9 REP MOVSS 0(CX), X2
+f30f1122|3344556677885f5f5f5f5f5f 32 intel movss dword ptr [edx], xmm4
+f30f1122|3344556677885f5f5f5f5f5f 32 plan9 REP MOVSS X4, 0(DX)
+f30f1122|3344556677885f5f5f5f5f5f 64 gnu movss %xmm4,(%rdx)
+f30f1122|3344556677885f5f5f5f5f5f 64 intel movss dword ptr [rdx], xmm4
+f30f1122|3344556677885f5f5f5f5f5f 64 plan9 REP MOVSS X4, 0(DX)
+f30f1211|223344556677885f5f5f5f5f 32 intel movsldup xmm2, xmmword ptr [ecx]
+f30f1211|223344556677885f5f5f5f5f 32 plan9 REP MOVSLDUP 0(CX), X2
+f30f1211|223344556677885f5f5f5f5f 64 gnu movsldup (%rcx),%xmm2
+f30f1211|223344556677885f5f5f5f5f 64 intel movsldup xmm2, xmmword ptr [rcx]
+f30f1211|223344556677885f5f5f5f5f 64 plan9 REP MOVSLDUP 0(CX), X2
+f30f1611|223344556677885f5f5f5f5f 32 intel movshdup xmm2, xmmword ptr [ecx]
+f30f1611|223344556677885f5f5f5f5f 32 plan9 REP MOVSHDUP 0(CX), X2
+f30f1611|223344556677885f5f5f5f5f 64 gnu movshdup (%rcx),%xmm2
+f30f1611|223344556677885f5f5f5f5f 64 intel movshdup xmm2, xmmword ptr [rcx]
+f30f1611|223344556677885f5f5f5f5f 64 plan9 REP MOVSHDUP 0(CX), X2
+f30f2a11|223344556677885f5f5f5f5f 32 intel cvtsi2ss xmm2, dword ptr [ecx]
+f30f2a11|223344556677885f5f5f5f5f 32 plan9 REP CVTSI2SSL 0(CX), X2
+f30f2a11|223344556677885f5f5f5f5f 64 gnu cvtsi2ssl (%rcx),%xmm2
+f30f2a11|223344556677885f5f5f5f5f 64 intel cvtsi2ss xmm2, dword ptr [rcx]
+f30f2a11|223344556677885f5f5f5f5f 64 plan9 REP CVTSI2SSL 0(CX), X2
+f30f2c11|223344556677885f5f5f5f5f 32 intel cvttss2si edx, dword ptr [ecx]
+f30f2c11|223344556677885f5f5f5f5f 32 plan9 REP CVTTSS2SIL 0(CX), DX
+f30f2c11|223344556677885f5f5f5f5f 64 gnu cvttss2si (%rcx),%edx
+f30f2c11|223344556677885f5f5f5f5f 64 intel cvttss2si edx, dword ptr [rcx]
+f30f2c11|223344556677885f5f5f5f5f 64 plan9 REP CVTTSS2SIL 0(CX), DX
+f30f2d11|223344556677885f5f5f5f5f 32 intel cvtss2si edx, dword ptr [ecx]
+f30f2d11|223344556677885f5f5f5f5f 32 plan9 REP CVTSS2SIL 0(CX), DX
+f30f2d11|223344556677885f5f5f5f5f 64 gnu cvtss2si (%rcx),%edx
+f30f2d11|223344556677885f5f5f5f5f 64 intel cvtss2si edx, dword ptr [rcx]
+f30f2d11|223344556677885f5f5f5f5f 64 plan9 REP CVTSS2SIL 0(CX), DX
+f30f5111|223344556677885f5f5f5f5f 32 intel sqrtss xmm2, dword ptr [ecx]
+f30f5111|223344556677885f5f5f5f5f 32 plan9 REP SQRTSS 0(CX), X2
+f30f5111|223344556677885f5f5f5f5f 64 gnu sqrtss (%rcx),%xmm2
+f30f5111|223344556677885f5f5f5f5f 64 intel sqrtss xmm2, dword ptr [rcx]
+f30f5111|223344556677885f5f5f5f5f 64 plan9 REP SQRTSS 0(CX), X2
+f30f5211|223344556677885f5f5f5f5f 32 intel rsqrtss xmm2, dword ptr [ecx]
+f30f5211|223344556677885f5f5f5f5f 32 plan9 REP RSQRTSS 0(CX), X2
+f30f5211|223344556677885f5f5f5f5f 64 gnu rsqrtss (%rcx),%xmm2
+f30f5211|223344556677885f5f5f5f5f 64 intel rsqrtss xmm2, dword ptr [rcx]
+f30f5211|223344556677885f5f5f5f5f 64 plan9 REP RSQRTSS 0(CX), X2
+f30f5311|223344556677885f5f5f5f5f 32 intel rcpss xmm2, dword ptr [ecx]
+f30f5311|223344556677885f5f5f5f5f 32 plan9 REP RCPSS 0(CX), X2
+f30f5311|223344556677885f5f5f5f5f 64 gnu rcpss (%rcx),%xmm2
+f30f5311|223344556677885f5f5f5f5f 64 intel rcpss xmm2, dword ptr [rcx]
+f30f5311|223344556677885f5f5f5f5f 64 plan9 REP RCPSS 0(CX), X2
+f30f5811|223344556677885f5f5f5f5f 32 intel addss xmm2, dword ptr [ecx]
+f30f5811|223344556677885f5f5f5f5f 32 plan9 REP ADDSS 0(CX), X2
+f30f5811|223344556677885f5f5f5f5f 64 gnu addss (%rcx),%xmm2
+f30f5811|223344556677885f5f5f5f5f 64 intel addss xmm2, dword ptr [rcx]
+f30f5811|223344556677885f5f5f5f5f 64 plan9 REP ADDSS 0(CX), X2
+f30f5911|223344556677885f5f5f5f5f 32 intel mulss xmm2, dword ptr [ecx]
+f30f5911|223344556677885f5f5f5f5f 32 plan9 REP MULSS 0(CX), X2
+f30f5911|223344556677885f5f5f5f5f 64 gnu mulss (%rcx),%xmm2
+f30f5911|223344556677885f5f5f5f5f 64 intel mulss xmm2, dword ptr [rcx]
+f30f5911|223344556677885f5f5f5f5f 64 plan9 REP MULSS 0(CX), X2
+f30f5a11|223344556677885f5f5f5f5f 32 intel cvtss2sd xmm2, dword ptr [ecx]
+f30f5a11|223344556677885f5f5f5f5f 32 plan9 REP CVTSS2SD 0(CX), X2
+f30f5a11|223344556677885f5f5f5f5f 64 gnu cvtss2sd (%rcx),%xmm2
+f30f5a11|223344556677885f5f5f5f5f 64 intel cvtss2sd xmm2, dword ptr [rcx]
+f30f5a11|223344556677885f5f5f5f5f 64 plan9 REP CVTSS2SD 0(CX), X2
+f30f5b11|223344556677885f5f5f5f5f 32 intel cvttps2dq xmm2, xmmword ptr [ecx]
+f30f5b11|223344556677885f5f5f5f5f 32 plan9 REP CVTTPS2DQ 0(CX), X2
+f30f5b11|223344556677885f5f5f5f5f 64 gnu cvttps2dq (%rcx),%xmm2
+f30f5b11|223344556677885f5f5f5f5f 64 intel cvttps2dq xmm2, xmmword ptr [rcx]
+f30f5b11|223344556677885f5f5f5f5f 64 plan9 REP CVTTPS2DQ 0(CX), X2
+f30f5c11|223344556677885f5f5f5f5f 32 intel subss xmm2, dword ptr [ecx]
+f30f5c11|223344556677885f5f5f5f5f 32 plan9 REP SUBSS 0(CX), X2
+f30f5c11|223344556677885f5f5f5f5f 64 gnu subss (%rcx),%xmm2
+f30f5c11|223344556677885f5f5f5f5f 64 intel subss xmm2, dword ptr [rcx]
+f30f5c11|223344556677885f5f5f5f5f 64 plan9 REP SUBSS 0(CX), X2
+f30f5d11|223344556677885f5f5f5f5f 32 intel minss xmm2, dword ptr [ecx]
+f30f5d11|223344556677885f5f5f5f5f 32 plan9 REP MINSS 0(CX), X2
+f30f5d11|223344556677885f5f5f5f5f 64 gnu minss (%rcx),%xmm2
+f30f5d11|223344556677885f5f5f5f5f 64 intel minss xmm2, dword ptr [rcx]
+f30f5d11|223344556677885f5f5f5f5f 64 plan9 REP MINSS 0(CX), X2
+f30f5e11|223344556677885f5f5f5f5f 32 intel divss xmm2, dword ptr [ecx]
+f30f5e11|223344556677885f5f5f5f5f 32 plan9 REP DIVSS 0(CX), X2
+f30f5e11|223344556677885f5f5f5f5f 64 gnu divss (%rcx),%xmm2
+f30f5e11|223344556677885f5f5f5f5f 64 intel divss xmm2, dword ptr [rcx]
+f30f5e11|223344556677885f5f5f5f5f 64 plan9 REP DIVSS 0(CX), X2
+f30f5f11|223344556677885f5f5f5f5f 32 intel maxss xmm2, dword ptr [ecx]
+f30f5f11|223344556677885f5f5f5f5f 32 plan9 REP MAXSS 0(CX), X2
+f30f5f11|223344556677885f5f5f5f5f 64 gnu maxss (%rcx),%xmm2
+f30f5f11|223344556677885f5f5f5f5f 64 intel maxss xmm2, dword ptr [rcx]
+f30f5f11|223344556677885f5f5f5f5f 64 plan9 REP MAXSS 0(CX), X2
+f30f6f11|223344556677885f5f5f5f5f 32 intel movdqu xmm2, xmmword ptr [ecx]
+f30f6f11|223344556677885f5f5f5f5f 32 plan9 REP MOVDQU 0(CX), X2
+f30f6f11|223344556677885f5f5f5f5f 64 gnu movdqu (%rcx),%xmm2
+f30f6f11|223344556677885f5f5f5f5f 64 intel movdqu xmm2, xmmword ptr [rcx]
+f30f6f11|223344556677885f5f5f5f5f 64 plan9 REP MOVDQU 0(CX), X2
+f30f701122|3344556677885f5f5f5f5f 32 intel pshufhw xmm2, xmmword ptr [ecx], 0x22
+f30f701122|3344556677885f5f5f5f5f 32 plan9 REP PSHUFHW $0x22, 0(CX), X2
+f30f701122|3344556677885f5f5f5f5f 64 gnu pshufhw $0x22,(%rcx),%xmm2
+f30f701122|3344556677885f5f5f5f5f 64 intel pshufhw xmm2, xmmword ptr [rcx], 0x22
+f30f701122|3344556677885f5f5f5f5f 64 plan9 REP PSHUFHW $0x22, 0(CX), X2
+f30f7e11|223344556677885f5f5f5f5f 32 intel movq xmm2, qword ptr [ecx]
+f30f7e11|223344556677885f5f5f5f5f 32 plan9 REP MOVQ 0(CX), X2
+f30f7e11|223344556677885f5f5f5f5f 64 gnu movq (%rcx),%xmm2
+f30f7e11|223344556677885f5f5f5f5f 64 intel movq xmm2, qword ptr [rcx]
+f30f7e11|223344556677885f5f5f5f5f 64 plan9 REP MOVQ 0(CX), X2
+f30f7f11|223344556677885f5f5f5f5f 32 intel movdqu xmmword ptr [ecx], xmm2
+f30f7f11|223344556677885f5f5f5f5f 32 plan9 REP MOVDQU X2, 0(CX)
+f30f7f11|223344556677885f5f5f5f5f 64 gnu movdqu %xmm2,(%rcx)
+f30f7f11|223344556677885f5f5f5f5f 64 intel movdqu xmmword ptr [rcx], xmm2
+f30f7f11|223344556677885f5f5f5f5f 64 plan9 REP MOVDQU X2, 0(CX)
+f30fae11|223344556677885f5f5f5f5f 64 gnu wrfsbasel (%rcx)
+f30fae11|223344556677885f5f5f5f5f 64 intel wrfsbase dword ptr [rcx]
+f30fae11|223344556677885f5f5f5f5f 64 plan9 REP WRFSBASE 0(CX)
+f30fae18|11223344556677885f5f5f5f 64 gnu wrgsbasel (%rax)
+f30fae18|11223344556677885f5f5f5f 64 intel wrgsbase dword ptr [rax]
+f30fae18|11223344556677885f5f5f5f 64 plan9 REP WRGSBASE 0(AX)
+f30faec0|11223344556677885f5f5f5f 64 gnu rdfsbase %eax
+f30faec0|11223344556677885f5f5f5f 64 intel rdfsbase eax
+f30faec0|11223344556677885f5f5f5f 64 plan9 REP RDFSBASE AX
+f30faec8|11223344556677885f5f5f5f 64 gnu rdgsbase %eax
+f30faec8|11223344556677885f5f5f5f 64 intel rdgsbase eax
+f30faec8|11223344556677885f5f5f5f 64 plan9 REP RDGSBASE AX
+f30fb811|223344556677885f5f5f5f5f 32 intel popcnt edx, dword ptr [ecx]
+f30fb811|223344556677885f5f5f5f5f 32 plan9 REP POPCNT 0(CX), DX
+f30fb811|223344556677885f5f5f5f5f 64 gnu popcnt (%rcx),%edx
+f30fb811|223344556677885f5f5f5f5f 64 intel popcnt edx, dword ptr [rcx]
+f30fb811|223344556677885f5f5f5f5f 64 plan9 REP POPCNT 0(CX), DX
+f30fbc11|223344556677885f5f5f5f5f 32 intel tzcnt edx, dword ptr [ecx]
+f30fbc11|223344556677885f5f5f5f5f 32 plan9 REP TZCNT 0(CX), DX
+f30fbc11|223344556677885f5f5f5f5f 64 gnu tzcnt (%rcx),%edx
+f30fbc11|223344556677885f5f5f5f5f 64 intel tzcnt edx, dword ptr [rcx]
+f30fbc11|223344556677885f5f5f5f5f 64 plan9 REP TZCNT 0(CX), DX
+f30fbd11|223344556677885f5f5f5f5f 32 intel lzcnt edx, dword ptr [ecx]
+f30fbd11|223344556677885f5f5f5f5f 32 plan9 REP LZCNT 0(CX), DX
+f30fbd11|223344556677885f5f5f5f5f 64 gnu lzcnt (%rcx),%edx
+f30fbd11|223344556677885f5f5f5f5f 64 intel lzcnt edx, dword ptr [rcx]
+f30fbd11|223344556677885f5f5f5f5f 64 plan9 REP LZCNT 0(CX), DX
+f30fc21122|3344556677885f5f5f5f5f 32 intel cmpss xmm2, dword ptr [ecx], 0x22
+f30fc21122|3344556677885f5f5f5f5f 32 plan9 REP CMPSS $0x22, 0(CX), X2
+f30fc21122|3344556677885f5f5f5f5f 64 gnu cmpss $0x22,(%rcx),%xmm2
+f30fc21122|3344556677885f5f5f5f5f 64 intel cmpss xmm2, dword ptr [rcx], 0x22
+f30fc21122|3344556677885f5f5f5f5f 64 plan9 REP CMPSS $0x22, 0(CX), X2
+f30fe611|223344556677885f5f5f5f5f 32 intel cvtdq2pd xmm2, qword ptr [ecx]
+f30fe611|223344556677885f5f5f5f5f 32 plan9 REP CVTDQ2PD 0(CX), X2
+f30fe611|223344556677885f5f5f5f5f 64 gnu cvtdq2pd (%rcx),%xmm2
+f30fe611|223344556677885f5f5f5f5f 64 intel cvtdq2pd xmm2, qword ptr [rcx]
+f30fe611|223344556677885f5f5f5f5f 64 plan9 REP CVTDQ2PD 0(CX), X2
+f3480f2a11|223344556677885f5f5f5f 64 gnu cvtsi2ssq (%rcx),%xmm2
+f3480f2a11|223344556677885f5f5f5f 64 intel cvtsi2ss xmm2, qword ptr [rcx]
+f3480f2a11|223344556677885f5f5f5f 64 plan9 REP CVTSI2SSQ 0(CX), X2
+f3480f2c11|223344556677885f5f5f5f 64 gnu cvttss2si (%rcx),%rdx
+f3480f2c11|223344556677885f5f5f5f 64 intel cvttss2si rdx, dword ptr [rcx]
+f3480f2c11|223344556677885f5f5f5f 64 plan9 REP CVTTSS2SIQ 0(CX), DX
+f3480f2d11|223344556677885f5f5f5f 64 gnu cvtss2si (%rcx),%rdx
+f3480f2d11|223344556677885f5f5f5f 64 intel cvtss2si rdx, dword ptr [rcx]
+f3480f2d11|223344556677885f5f5f5f 64 plan9 REP CVTSS2SIQ 0(CX), DX
+f3480fae11|223344556677885f5f5f5f 64 gnu wrfsbaseq (%rcx)
+f3480fae11|223344556677885f5f5f5f 64 intel wrfsbase qword ptr [rcx]
+f3480fae11|223344556677885f5f5f5f 64 plan9 REP WRFSBASE 0(CX)
+f3480fae18|11223344556677885f5f5f 64 gnu wrgsbaseq (%rax)
+f3480fae18|11223344556677885f5f5f 64 intel wrgsbase qword ptr [rax]
+f3480fae18|11223344556677885f5f5f 64 plan9 REP WRGSBASE 0(AX)
+f3480faec0|11223344556677885f5f5f 64 gnu rdfsbase %rax
+f3480faec0|11223344556677885f5f5f 64 intel rdfsbase rax
+f3480faec0|11223344556677885f5f5f 64 plan9 REP RDFSBASE AX
+f3480faec8|11223344556677885f5f5f 64 gnu rdgsbase %rax
+f3480faec8|11223344556677885f5f5f 64 intel rdgsbase rax
+f3480faec8|11223344556677885f5f5f 64 plan9 REP RDGSBASE AX
+f3480fb811|223344556677885f5f5f5f 64 gnu popcnt (%rcx),%rdx
+f3480fb811|223344556677885f5f5f5f 64 intel popcnt rdx, qword ptr [rcx]
+f3480fb811|223344556677885f5f5f5f 64 plan9 REP POPCNT 0(CX), DX
+f3480fbc11|223344556677885f5f5f5f 64 gnu tzcnt (%rcx),%rdx
+f3480fbc11|223344556677885f5f5f5f 64 intel tzcnt rdx, qword ptr [rcx]
+f3480fbc11|223344556677885f5f5f5f 64 plan9 REP TZCNT 0(CX), DX
+f3480fbd11|223344556677885f5f5f5f 64 gnu lzcnt (%rcx),%rdx
+f3480fbd11|223344556677885f5f5f5f 64 intel lzcnt rdx, qword ptr [rcx]
+f3480fbd11|223344556677885f5f5f5f 64 plan9 REP LZCNT 0(CX), DX
+f3660fb811|223344556677885f5f5f5f 32 intel popcnt dx, word ptr [ecx]
+f3660fb811|223344556677885f5f5f5f 32 plan9 POPCNT 0(CX), DX
+f3660fb811|223344556677885f5f5f5f 64 gnu popcnt (%rcx),%dx
+f3660fb811|223344556677885f5f5f5f 64 intel popcnt dx, word ptr [rcx]
+f3660fb811|223344556677885f5f5f5f 64 plan9 POPCNT 0(CX), DX
+f3660fbc11|223344556677885f5f5f5f 32 intel tzcnt dx, word ptr [ecx]
+f3660fbc11|223344556677885f5f5f5f 32 plan9 TZCNT 0(CX), DX
+f3660fbc11|223344556677885f5f5f5f 64 gnu tzcnt (%rcx),%dx
+f3660fbc11|223344556677885f5f5f5f 64 intel tzcnt dx, word ptr [rcx]
+f3660fbc11|223344556677885f5f5f5f 64 plan9 TZCNT 0(CX), DX
+f3660fbd11|223344556677885f5f5f5f 32 intel lzcnt dx, word ptr [ecx]
+f3660fbd11|223344556677885f5f5f5f 32 plan9 LZCNT 0(CX), DX
+f3660fbd11|223344556677885f5f5f5f 64 gnu lzcnt (%rcx),%dx
+f3660fbd11|223344556677885f5f5f5f 64 intel lzcnt dx, word ptr [rcx]
+f3660fbd11|223344556677885f5f5f5f 64 plan9 LZCNT 0(CX), DX
+f3f0673e660f38f111|22334455667788 32 intel lock movbe word ptr [bx+di*1], dx
+f3f0673e660f38f111|22334455667788 32 plan9 MOVBE DX, DS:0(BX)(DI*1)
+f3f0673e660f38f111|22334455667788 64 gnu rep lock movbe %dx,%ds:(%ecx)
+f3f0673e660f38f111|22334455667788 64 intel lock movbe word ptr [ecx], dx
+f3f0673e660f38f111|22334455667788 64 plan9 MOVBE DX, 0(CX)
+f3f20f2b11|5f5f5f5f5f5f5f5f5f5f5f 32 intel movntsd qword ptr [ecx], xmm2
+f3f20f2b11|5f5f5f5f5f5f5f5f5f5f5f 32 plan9 REPNE MOVNTSD X2, 0(CX)
+f3f20f2b11|5f5f5f5f5f5f5f5f5f5f5f 64 gnu repn movntss %xmm2,(%rcx)
+f3f20f2b11|5f5f5f5f5f5f5f5f5f5f5f 64 intel movntsd qword ptr [rcx], xmm2
+f3f20f2b11|5f5f5f5f5f5f5f5f5f5f5f 64 plan9 REPNE MOVNTSD X2, 0(CX)
+f4|11223344556677885f5f5f5f5f5f5f 32 intel hlt
+f4|11223344556677885f5f5f5f5f5f5f 32 plan9 HLT
+f4|11223344556677885f5f5f5f5f5f5f 64 gnu hlt
+f4|11223344556677885f5f5f5f5f5f5f 64 intel hlt
+f4|11223344556677885f5f5f5f5f5f5f 64 plan9 HLT
+f5|11223344556677885f5f5f5f5f5f5f 32 intel cmc
+f5|11223344556677885f5f5f5f5f5f5f 32 plan9 CMC
+f5|11223344556677885f5f5f5f5f5f5f 64 gnu cmc
+f5|11223344556677885f5f5f5f5f5f5f 64 intel cmc
+f5|11223344556677885f5f5f5f5f5f5f 64 plan9 CMC
+f60011|223344556677885f5f5f5f5f5f 32 intel test byte ptr [eax], 0x11
+f60011|223344556677885f5f5f5f5f5f 32 plan9 TESTL $0x11, 0(AX)
+f60011|223344556677885f5f5f5f5f5f 64 gnu testb $0x11,(%rax)
+f60011|223344556677885f5f5f5f5f5f 64 intel test byte ptr [rax], 0x11
+f60011|223344556677885f5f5f5f5f5f 64 plan9 TESTL $0x11, 0(AX)
+f611|223344556677885f5f5f5f5f5f5f 32 intel not byte ptr [ecx]
+f611|223344556677885f5f5f5f5f5f5f 32 plan9 NOTL 0(CX)
+f611|223344556677885f5f5f5f5f5f5f 64 gnu notb (%rcx)
+f611|223344556677885f5f5f5f5f5f5f 64 intel not byte ptr [rcx]
+f611|223344556677885f5f5f5f5f5f5f 64 plan9 NOTL 0(CX)
+f618|11223344556677885f5f5f5f5f5f 32 intel neg byte ptr [eax]
+f618|11223344556677885f5f5f5f5f5f 32 plan9 NEGL 0(AX)
+f618|11223344556677885f5f5f5f5f5f 64 gnu negb (%rax)
+f618|11223344556677885f5f5f5f5f5f 64 intel neg byte ptr [rax]
+f618|11223344556677885f5f5f5f5f5f 64 plan9 NEGL 0(AX)
+f620|11223344556677885f5f5f5f5f5f 32 intel mul byte ptr [eax]
+f620|11223344556677885f5f5f5f5f5f 32 plan9 MULL 0(AX)
+f620|11223344556677885f5f5f5f5f5f 64 gnu mulb (%rax)
+f620|11223344556677885f5f5f5f5f5f 64 intel mul byte ptr [rax]
+f620|11223344556677885f5f5f5f5f5f 64 plan9 MULL 0(AX)
+f628|11223344556677885f5f5f5f5f5f 32 intel imul byte ptr [eax]
+f628|11223344556677885f5f5f5f5f5f 32 plan9 IMULL 0(AX)
+f628|11223344556677885f5f5f5f5f5f 64 gnu imulb (%rax)
+f628|11223344556677885f5f5f5f5f5f 64 intel imul byte ptr [rax]
+f628|11223344556677885f5f5f5f5f5f 64 plan9 IMULL 0(AX)
+f630|11223344556677885f5f5f5f5f5f 32 intel div byte ptr [eax]
+f630|11223344556677885f5f5f5f5f5f 32 plan9 DIVL 0(AX)
+f630|11223344556677885f5f5f5f5f5f 64 gnu divb (%rax)
+f630|11223344556677885f5f5f5f5f5f 64 intel div byte ptr [rax]
+f630|11223344556677885f5f5f5f5f5f 64 plan9 DIVL 0(AX)
+f638|11223344556677885f5f5f5f5f5f 32 intel idiv byte ptr [eax]
+f638|11223344556677885f5f5f5f5f5f 32 plan9 IDIVL 0(AX)
+f638|11223344556677885f5f5f5f5f5f 64 gnu idivb (%rax)
+f638|11223344556677885f5f5f5f5f5f 64 intel idiv byte ptr [rax]
+f638|11223344556677885f5f5f5f5f5f 64 plan9 IDIVL 0(AX)
+f70011223344|556677885f5f5f5f5f5f 32 intel test dword ptr [eax], 0x44332211
+f70011223344|556677885f5f5f5f5f5f 32 plan9 TESTL $0x44332211, 0(AX)
+f70011223344|556677885f5f5f5f5f5f 64 gnu testl $0x44332211,(%rax)
+f70011223344|556677885f5f5f5f5f5f 64 intel test dword ptr [rax], 0x44332211
+f70011223344|556677885f5f5f5f5f5f 64 plan9 TESTL $0x44332211, 0(AX)
+f711|223344556677885f5f5f5f5f5f5f 32 intel not dword ptr [ecx]
+f711|223344556677885f5f5f5f5f5f5f 32 plan9 NOTL 0(CX)
+f711|223344556677885f5f5f5f5f5f5f 64 gnu notl (%rcx)
+f711|223344556677885f5f5f5f5f5f5f 64 intel not dword ptr [rcx]
+f711|223344556677885f5f5f5f5f5f5f 64 plan9 NOTL 0(CX)
+f718|11223344556677885f5f5f5f5f5f 32 intel neg dword ptr [eax]
+f718|11223344556677885f5f5f5f5f5f 32 plan9 NEGL 0(AX)
+f718|11223344556677885f5f5f5f5f5f 64 gnu negl (%rax)
+f718|11223344556677885f5f5f5f5f5f 64 intel neg dword ptr [rax]
+f718|11223344556677885f5f5f5f5f5f 64 plan9 NEGL 0(AX)
+f720|11223344556677885f5f5f5f5f5f 32 intel mul dword ptr [eax]
+f720|11223344556677885f5f5f5f5f5f 32 plan9 MULL 0(AX)
+f720|11223344556677885f5f5f5f5f5f 64 gnu mull (%rax)
+f720|11223344556677885f5f5f5f5f5f 64 intel mul dword ptr [rax]
+f720|11223344556677885f5f5f5f5f5f 64 plan9 MULL 0(AX)
+f728|11223344556677885f5f5f5f5f5f 32 intel imul dword ptr [eax]
+f728|11223344556677885f5f5f5f5f5f 32 plan9 IMULL 0(AX)
+f728|11223344556677885f5f5f5f5f5f 64 gnu imull (%rax)
+f728|11223344556677885f5f5f5f5f5f 64 intel imul dword ptr [rax]
+f728|11223344556677885f5f5f5f5f5f 64 plan9 IMULL 0(AX)
+f730|11223344556677885f5f5f5f5f5f 32 intel div dword ptr [eax]
+f730|11223344556677885f5f5f5f5f5f 32 plan9 DIVL 0(AX)
+f730|11223344556677885f5f5f5f5f5f 64 gnu divl (%rax)
+f730|11223344556677885f5f5f5f5f5f 64 intel div dword ptr [rax]
+f730|11223344556677885f5f5f5f5f5f 64 plan9 DIVL 0(AX)
+f738|11223344556677885f5f5f5f5f5f 32 intel idiv dword ptr [eax]
+f738|11223344556677885f5f5f5f5f5f 32 plan9 IDIVL 0(AX)
+f738|11223344556677885f5f5f5f5f5f 64 gnu idivl (%rax)
+f738|11223344556677885f5f5f5f5f5f 64 intel idiv dword ptr [rax]
+f738|11223344556677885f5f5f5f5f5f 64 plan9 IDIVL 0(AX)
+f8|11223344556677885f5f5f5f5f5f5f 32 intel clc
+f8|11223344556677885f5f5f5f5f5f5f 32 plan9 CLC
+f8|11223344556677885f5f5f5f5f5f5f 64 gnu clc
+f8|11223344556677885f5f5f5f5f5f5f 64 intel clc
+f8|11223344556677885f5f5f5f5f5f5f 64 plan9 CLC
+f9|11223344556677885f5f5f5f5f5f5f 32 intel stc
+f9|11223344556677885f5f5f5f5f5f5f 32 plan9 STC
+f9|11223344556677885f5f5f5f5f5f5f 64 gnu stc
+f9|11223344556677885f5f5f5f5f5f5f 64 intel stc
+f9|11223344556677885f5f5f5f5f5f5f 64 plan9 STC
+fa|11223344556677885f5f5f5f5f5f5f 32 intel cli
+fa|11223344556677885f5f5f5f5f5f5f 32 plan9 CLI
+fa|11223344556677885f5f5f5f5f5f5f 64 gnu cli
+fa|11223344556677885f5f5f5f5f5f5f 64 intel cli
+fa|11223344556677885f5f5f5f5f5f5f 64 plan9 CLI
+fb|11223344556677885f5f5f5f5f5f5f 32 intel sti
+fb|11223344556677885f5f5f5f5f5f5f 32 plan9 STI
+fb|11223344556677885f5f5f5f5f5f5f 64 gnu sti
+fb|11223344556677885f5f5f5f5f5f5f 64 intel sti
+fb|11223344556677885f5f5f5f5f5f5f 64 plan9 STI
+fc|11223344556677885f5f5f5f5f5f5f 32 intel cld
+fc|11223344556677885f5f5f5f5f5f5f 32 plan9 CLD
+fc|11223344556677885f5f5f5f5f5f5f 64 gnu cld
+fc|11223344556677885f5f5f5f5f5f5f 64 intel cld
+fc|11223344556677885f5f5f5f5f5f5f 64 plan9 CLD
+fd|11223344556677885f5f5f5f5f5f5f 32 intel std
+fd|11223344556677885f5f5f5f5f5f5f 32 plan9 STD
+fd|11223344556677885f5f5f5f5f5f5f 64 gnu std
+fd|11223344556677885f5f5f5f5f5f5f 64 intel std
+fd|11223344556677885f5f5f5f5f5f5f 64 plan9 STD
+fe00|11223344556677885f5f5f5f5f5f 32 intel inc byte ptr [eax]
+fe00|11223344556677885f5f5f5f5f5f 32 plan9 INCL 0(AX)
+fe00|11223344556677885f5f5f5f5f5f 64 gnu incb (%rax)
+fe00|11223344556677885f5f5f5f5f5f 64 intel inc byte ptr [rax]
+fe00|11223344556677885f5f5f5f5f5f 64 plan9 INCL 0(AX)
+fe08|11223344556677885f5f5f5f5f5f 32 intel dec byte ptr [eax]
+fe08|11223344556677885f5f5f5f5f5f 32 plan9 DECL 0(AX)
+fe08|11223344556677885f5f5f5f5f5f 64 gnu decb (%rax)
+fe08|11223344556677885f5f5f5f5f5f 64 intel dec byte ptr [rax]
+fe08|11223344556677885f5f5f5f5f5f 64 plan9 DECL 0(AX)
+ff00|11223344556677885f5f5f5f5f5f 32 intel inc dword ptr [eax]
+ff00|11223344556677885f5f5f5f5f5f 32 plan9 INCL 0(AX)
+ff00|11223344556677885f5f5f5f5f5f 64 gnu incl (%rax)
+ff00|11223344556677885f5f5f5f5f5f 64 intel inc dword ptr [rax]
+ff00|11223344556677885f5f5f5f5f5f 64 plan9 INCL 0(AX)
+ff08|11223344556677885f5f5f5f5f5f 32 intel dec dword ptr [eax]
+ff08|11223344556677885f5f5f5f5f5f 32 plan9 DECL 0(AX)
+ff08|11223344556677885f5f5f5f5f5f 64 gnu decl (%rax)
+ff08|11223344556677885f5f5f5f5f5f 64 intel dec dword ptr [rax]
+ff08|11223344556677885f5f5f5f5f5f 64 plan9 DECL 0(AX)
+ff11|223344556677885f5f5f5f5f5f5f 32 intel call dword ptr [ecx]
+ff11|223344556677885f5f5f5f5f5f5f 32 plan9 CALL 0(CX)
+ff18|11223344556677885f5f5f5f5f5f 32 intel call far ptr [eax]
+ff18|11223344556677885f5f5f5f5f5f 32 plan9 LCALL 0(AX)
+ff18|11223344556677885f5f5f5f5f5f 64 gnu lcallq *(%rax)
+ff18|11223344556677885f5f5f5f5f5f 64 intel call far ptr [rax]
+ff18|11223344556677885f5f5f5f5f5f 64 plan9 LCALL 0(AX)
+ff20|11223344556677885f5f5f5f5f5f 32 intel jmp dword ptr [eax]
+ff20|11223344556677885f5f5f5f5f5f 32 plan9 JMP 0(AX)
+ff28|11223344556677885f5f5f5f5f5f 32 intel jmp far ptr [eax]
+ff28|11223344556677885f5f5f5f5f5f 32 plan9 LJMP 0(AX)
+ff28|11223344556677885f5f5f5f5f5f 64 gnu ljmpq *(%rax)
+ff28|11223344556677885f5f5f5f5f5f 64 intel jmp far ptr [rax]
+ff28|11223344556677885f5f5f5f5f5f 64 plan9 LJMP 0(AX)
+ff30|11223344556677885f5f5f5f5f5f 32 intel push dword ptr [eax]
+ff30|11223344556677885f5f5f5f5f5f 32 plan9 PUSHL 0(AX)
+ff30|11223344556677885f5f5f5f5f5f 64 gnu pushq (%rax)
+ff30|11223344556677885f5f5f5f5f5f 64 intel push qword ptr [rax]
+ff30|11223344556677885f5f5f5f5f5f 64 plan9 PUSHL 0(AX)
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/xed_test.go b/src/cmd/internal/rsc.io/x86/x86asm/xed_test.go
new file mode 100644
index 000000000..91cf82272
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/xed_test.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 x86asm
+
+import (
+ "bytes"
+ "strings"
+ "testing"
+)
+
+func TestXed32Manual(t *testing.T) { testXed32(t, hexCases(t, xedManualTests)) }
+func TestXed32Testdata(t *testing.T) { testXed32(t, concat(basicPrefixes, testdataCases(t))) }
+func TestXed32ModRM(t *testing.T) { testXed32(t, concat(basicPrefixes, enumModRM)) }
+func TestXed32OneByte(t *testing.T) { testBasic(t, testXed32) }
+func TestXed320F(t *testing.T) { testBasic(t, testXed32, 0x0F) }
+func TestXed320F38(t *testing.T) { testBasic(t, testXed32, 0x0F, 0x38) }
+func TestXed320F3A(t *testing.T) { testBasic(t, testXed32, 0x0F, 0x3A) }
+func TestXed32Prefix(t *testing.T) { testPrefix(t, testXed32) }
+
+func TestXed64Manual(t *testing.T) { testXed64(t, hexCases(t, xedManualTests)) }
+func TestXed64Testdata(t *testing.T) { testXed64(t, concat(basicPrefixes, testdataCases(t))) }
+func TestXed64ModRM(t *testing.T) { testXed64(t, concat(basicPrefixes, enumModRM)) }
+func TestXed64OneByte(t *testing.T) { testBasic(t, testXed64) }
+func TestXed640F(t *testing.T) { testBasic(t, testXed64, 0x0F) }
+func TestXed640F38(t *testing.T) { testBasic(t, testXed64, 0x0F, 0x38) }
+func TestXed640F3A(t *testing.T) { testBasic(t, testXed64, 0x0F, 0x3A) }
+func TestXed64Prefix(t *testing.T) { testPrefix(t, testXed64) }
+
+func TestXed64REXTestdata(t *testing.T) {
+ testXed64(t, filter(concat3(basicPrefixes, rexPrefixes, testdataCases(t)), isValidREX))
+}
+func TestXed64REXModRM(t *testing.T) { testXed64(t, concat3(basicPrefixes, rexPrefixes, enumModRM)) }
+func TestXed64REXOneByte(t *testing.T) { testBasicREX(t, testXed64) }
+func TestXed64REX0F(t *testing.T) { testBasicREX(t, testXed64, 0x0F) }
+func TestXed64REX0F38(t *testing.T) { testBasicREX(t, testXed64, 0x0F, 0x38) }
+func TestXed64REX0F3A(t *testing.T) { testBasicREX(t, testXed64, 0x0F, 0x3A) }
+func TestXed64REXPrefix(t *testing.T) { testPrefixREX(t, testXed64) }
+
+// xedManualTests holds test cases that will be run by TestXedManual32 and TestXedManual64.
+// 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=XedManual, particularly with tracing enabled.
+var xedManualTests = `
+6690
+`
+
+// allowedMismatchXed reports whether the mismatch between text and dec
+// should be allowed by the test.
+func allowedMismatchXed(text string, size int, inst *Inst, dec ExtInst) bool {
+ if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "GENERAL_ERROR", "INSTR_TOO_LONG", "BAD_LOCK_PREFIX") {
+ return true
+ }
+
+ if contains(dec.text, "BAD_LOCK_PREFIX") && countExactPrefix(inst, PrefixLOCK|PrefixInvalid) > 0 {
+ return true
+ }
+
+ if contains(dec.text, "BAD_LOCK_PREFIX", "GENERAL_ERROR") && countExactPrefix(inst, PrefixLOCK|PrefixImplicit) > 0 {
+ return true
+ }
+
+ if text == "lock" && size == 1 && contains(dec.text, "BAD_LOCK_PREFIX") {
+ return true
+ }
+
+ // Instructions not known to us.
+ if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, unsupported...) {
+ return true
+ }
+
+ // Instructions not known to xed.
+ if contains(text, xedUnsupported...) && contains(dec.text, "ERROR") {
+ return true
+ }
+
+ if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "shl ") && (inst.Opcode>>16)&0xEC38 == 0xC030 {
+ return true
+ }
+
+ // 82 11 22: xed says 'adc byte ptr [ecx], 0x22' but there is no justification in the manuals for that.
+ // C0 30 11: xed says 'shl byte ptr [eax], 0x11' but there is no justification in the manuals for that.
+ // F6 08 11: xed says 'test byte ptr [eax], 0x11' but there is no justification in the manuals for that.
+ if (contains(text, "error:") || isPrefix(text) && size == 1) && hasByte(dec.enc[:dec.nenc], 0x82, 0xC0, 0xC1, 0xD0, 0xD1, 0xD2, 0xD3, 0xF6, 0xF7) {
+ return true
+ }
+
+ // F3 11 22 and many others: xed allows and drops misused rep/repn prefix.
+ if (text == "rep" && dec.enc[0] == 0xF3 || (text == "repn" || text == "repne") && dec.enc[0] == 0xF2) && (!contains(dec.text, "ins", "outs", "movs", "lods", "cmps", "scas") || contains(dec.text, "xmm")) {
+ return true
+ }
+
+ // 0F C7 30: xed says vmptrld qword ptr [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
+ }
+
+ // F3 0F AE 00: we say 'rdfsbase dword ptr [eax]' but RDFSBASE needs a register.
+ // Also, this is a 64-bit only instruction.
+ // TODO(rsc): Fix to reject this encoding.
+ if contains(text, "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase") && contains(dec.text, "ERROR") {
+ return true
+ }
+
+ // 0F 01 F8: we say swapgs but that's only valid in 64-bit mode.
+ // TODO(rsc): Fix.
+ if contains(text, "swapgs") {
+ return true
+ }
+
+ // 0F 24 11: 'mov ecx, tr2' except there is no TR2.
+ // Or maybe the MOV to TR registers doesn't use RMF.
+ if contains(text, "cr1", "cr5", "cr6", "cr7", "tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7") && contains(dec.text, "ERROR") {
+ return true
+ }
+
+ // 0F 19 11, 0F 1C 11, 0F 1D 11, 0F 1E 11, 0F 1F 11: xed says nop,
+ // but the Intel manuals say that the only NOP there is 0F 1F /0.
+ // Perhaps xed is reporting an older encoding.
+ if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "nop ") && (inst.Opcode>>8)&0xFFFF38 != 0x0F1F00 {
+ return true
+ }
+
+ // 66 0F AE 38: clflushopt but we only know clflush
+ if contains(text, "clflush") && contains(dec.text, "clflushopt") {
+ return true
+ }
+
+ // 0F 20 04 11: MOV SP, CR0 but has mod!=3 despite register argument.
+ // (This encoding ignores the mod bits.) The decoder sees the non-register
+ // mod and reads farther ahead to decode the memory reference that
+ // isn't really there, causing the size to be too large.
+ // TODO(rsc): Fix.
+ if text == dec.text && size > dec.nenc && contains(text, " cr", " dr", " tr") {
+ return true
+ }
+
+ // 0F AE E9: xed says lfence, which is wrong (only 0F AE E8 is lfence). And so on.
+ if contains(dec.text, "fence") && hasByte(dec.enc[:dec.nenc], 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF) {
+ return true
+ }
+
+ // DD C9, DF C9: xed says 'fxch st0, st1' but that instruction is D9 C9.
+ if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fxch ") && hasByte(dec.enc[:dec.nenc], 0xDD, 0xDF) {
+ return true
+ }
+
+ // DC D4: xed says 'fcom st0, st4' but that instruction is D8 D4.
+ if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fcom ") && hasByte(dec.enc[:dec.nenc], 0xD8, 0xDC) {
+ return true
+ }
+
+ // DE D4: xed says 'fcomp st0, st4' but that instruction is D8 D4.
+ if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fcomp ") && hasByte(dec.enc[:dec.nenc], 0xDC, 0xDE) {
+ return true
+ }
+
+ // DF D4: xed says 'fstp st4, st0' but that instruction is DD D4.
+ if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fstp ") && hasByte(dec.enc[:dec.nenc], 0xDF) {
+ return true
+ }
+
+ return false
+}
+
+func countExactPrefix(inst *Inst, target Prefix) int {
+ n := 0
+ for _, p := range inst.Prefix {
+ if p == target {
+ n++
+ }
+ }
+ return n
+}
+
+func hasByte(src []byte, target ...byte) bool {
+ for _, b := range target {
+ if bytes.IndexByte(src, b) >= 0 {
+ return true
+ }
+ }
+ return false
+}
+
+// Instructions known to us but not to xed.
+var xedUnsupported = strings.Fields(`
+ xrstor
+ xsave
+ xsave
+ ud1
+ xgetbv
+ xsetbv
+ fxsave
+ fxrstor
+ clflush
+ lfence
+ mfence
+ sfence
+ rsqrtps
+ rcpps
+ emms
+ ldmxcsr
+ stmxcsr
+ movhpd
+ movnti
+ rdrand
+ movbe
+ movlpd
+ sysret
+`)
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go b/src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go
new file mode 100644
index 000000000..d7aa8e3e2
--- /dev/null
+++ b/src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go
@@ -0,0 +1,206 @@
+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/ld/data.c b/src/cmd/ld/data.c
index 55d020710..61847546a 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -35,7 +35,7 @@
#include "../ld/elf.h"
#include "../ld/macho.h"
#include "../ld/pe.h"
-#include "../../pkg/runtime/mgc0.h"
+#include "../../runtime/mgc0.h"
void dynreloc(void);
@@ -145,7 +145,7 @@ relocsym(LSym *s)
diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz, 0, s->np);
continue;
}
- if(r->sym != S && (r->sym->type & SMASK == 0 || r->sym->type & SMASK == SXREF)) {
+ if(r->sym != S && ((r->sym->type & (SMASK | SHIDDEN)) == 0 || (r->sym->type & SMASK) == SXREF)) {
diag("%s: not defined", r->sym->name);
continue;
}
@@ -160,6 +160,10 @@ relocsym(LSym *s)
if(r->sym != S && r->sym->type != 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 == R_TLS && strcmp(goos, "android") == 0)
+ r->type = R_ADDR;
+
switch(r->type) {
default:
o = 0;
@@ -186,8 +190,8 @@ relocsym(LSym *s)
case R_TLS_LE:
if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) {
r->done = 0;
- r->sym = ctxt->gmsym;
- r->xsym = ctxt->gmsym;
+ r->sym = ctxt->tlsg;
+ r->xsym = ctxt->tlsg;
r->xadd = r->add;
o = 0;
if(thechar != '6')
@@ -200,8 +204,8 @@ relocsym(LSym *s)
case R_TLS_IE:
if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) {
r->done = 0;
- r->sym = ctxt->gmsym;
- r->xsym = ctxt->gmsym;
+ r->sym = ctxt->tlsg;
+ r->xsym = ctxt->tlsg;
r->xadd = r->add;
o = 0;
if(thechar != '6')
@@ -277,9 +281,13 @@ relocsym(LSym *s)
if(thechar == '6')
o = 0;
} else if(HEADTYPE == Hdarwin) {
- if(rs->type != SHOSTOBJ)
- o += symaddr(rs) - rs->sect->vaddr;
- o -= r->off; // WTF?
+ if(r->type == R_CALL) {
+ if(rs->type != SHOSTOBJ)
+ o += symaddr(rs) - rs->sect->vaddr;
+ o -= r->off; // relative to section offset, not symbol
+ } else {
+ o += r->siz;
+ }
} else {
diag("unhandled pcrel relocation for %s", headstring);
}
@@ -421,10 +429,10 @@ dynreloc(void)
}
static void
-blk(LSym *start, int32 addr, int32 size)
+blk(LSym *start, int64 addr, int64 size)
{
LSym *sym;
- int32 eaddr;
+ int64 eaddr;
uchar *p, *ep;
for(sym = start; sym != nil; sym = sym->next)
@@ -463,10 +471,10 @@ blk(LSym *start, int32 addr, int32 size)
}
void
-codeblk(int32 addr, int32 size)
+codeblk(int64 addr, int64 size)
{
LSym *sym;
- int32 eaddr, n;
+ int64 eaddr, n;
uchar *q;
if(debug['a'])
@@ -523,10 +531,10 @@ codeblk(int32 addr, int32 size)
}
void
-datblk(int32 addr, int32 size)
+datblk(int64 addr, int64 size)
{
LSym *sym;
- int32 i, eaddr;
+ int64 i, eaddr;
uchar *p, *ep;
char *typ, *rsname;
Reloc *r;
@@ -612,22 +620,26 @@ addstrdata(char *name, char *value)
{
LSym *s, *sp;
char *p;
+ uchar reachable;
p = smprint("%s.str", name);
sp = linklookup(ctxt, p, 0);
free(p);
addstring(sp, value);
+ sp->type = SRODATA;
s = linklookup(ctxt, name, 0);
s->size = 0;
s->dupok = 1;
+ reachable = s->reachable;
addaddr(ctxt, s, sp);
- adduint32(ctxt, s, strlen(value));
- if(PtrSize == 8)
- adduint32(ctxt, s, 0); // round struct to pointer width
+ adduintxx(ctxt, s, strlen(value), PtrSize);
- // in case reachability has already been computed
- sp->reachable = s->reachable;
+ // addstring, addaddr, etc., mark the symbols as reachable.
+ // In this case that is not necessarily true, so stick to what
+ // we know before entering this function.
+ s->reachable = reachable;
+ sp->reachable = reachable;
}
vlong
@@ -702,31 +714,176 @@ maxalign(LSym *s, int type)
return max;
}
+// Helper object for building GC type programs.
+typedef struct ProgGen ProgGen;
+struct ProgGen
+{
+ LSym* s;
+ int32 datasize;
+ uint8 data[256/PointersPerByte];
+ vlong pos;
+};
+
static void
-gcaddsym(LSym *gc, LSym *s, vlong off)
+proggeninit(ProgGen *g, LSym *s)
{
- vlong a;
- LSym *gotype;
+ g->s = s;
+ g->datasize = 0;
+ g->pos = 0;
+ memset(g->data, 0, sizeof(g->data));
+}
- if(s->size < PtrSize)
+static void
+proggenemit(ProgGen *g, uint8 v)
+{
+ adduint8(ctxt, g->s, v);
+}
+
+// Writes insData block from g->data.
+static void
+proggendataflush(ProgGen *g)
+{
+ int32 i, s;
+
+ if(g->datasize == 0)
return;
- if(strcmp(s->name, ".string") == 0)
+ proggenemit(g, insData);
+ proggenemit(g, g->datasize);
+ s = (g->datasize + PointersPerByte - 1)/PointersPerByte;
+ for(i = 0; i < s; i++)
+ proggenemit(g, g->data[i]);
+ g->datasize = 0;
+ memset(g->data, 0, sizeof(g->data));
+}
+
+static void
+proggendata(ProgGen *g, uint8 d)
+{
+ g->data[g->datasize/PointersPerByte] |= d << ((g->datasize%PointersPerByte)*BitsPerPointer);
+ g->datasize++;
+ if(g->datasize == 255)
+ proggendataflush(g);
+}
+
+// Skip v bytes due to alignment, etc.
+static void
+proggenskip(ProgGen *g, vlong off, vlong v)
+{
+ vlong i;
+
+ for(i = off; i < off+v; i++) {
+ if((i%PtrSize) == 0)
+ proggendata(g, BitsScalar);
+ }
+}
+
+// Emit insArray instruction.
+static void
+proggenarray(ProgGen *g, vlong len)
+{
+ int32 i;
+
+ proggendataflush(g);
+ proggenemit(g, insArray);
+ for(i = 0; i < PtrSize; i++, len >>= 8)
+ proggenemit(g, len);
+}
+
+static void
+proggenarrayend(ProgGen *g)
+{
+ proggendataflush(g);
+ proggenemit(g, insArrayEnd);
+}
+
+static void
+proggenfini(ProgGen *g, vlong size)
+{
+ proggenskip(g, g->pos, size - g->pos);
+ proggendataflush(g);
+ proggenemit(g, insEnd);
+}
+
+
+// This function generates GC pointer info for global variables.
+static void
+proggenaddsym(ProgGen *g, LSym *s)
+{
+ LSym *gcprog;
+ uint8 *mask;
+ vlong i, size;
+
+ if(s->size == 0)
return;
- gotype = s->gotype;
- if(gotype != nil) {
- //print("gcaddsym: %s %d %s\n", s->name, s->size, gotype->name);
- adduintxx(ctxt, gc, GC_CALL, PtrSize);
- adduintxx(ctxt, gc, off, PtrSize);
- addpcrelplus(ctxt, gc, decodetype_gc(gotype), 3*PtrSize+4);
- if(PtrSize == 8)
- adduintxx(ctxt, gc, 0, 4);
- } else {
- //print("gcaddsym: %s %d <unknown type>\n", s->name, s->size);
- for(a = -off&(PtrSize-1); a+PtrSize<=s->size; a+=PtrSize) {
- adduintxx(ctxt, gc, GC_APTR, PtrSize);
- adduintxx(ctxt, gc, off+a, PtrSize);
+ // Skip alignment hole from the previous symbol.
+ proggenskip(g, g->pos, s->value - g->pos);
+ g->pos += s->value - g->pos;
+
+ // The test for names beginning with . here is meant
+ // to keep .dynamic and .dynsym from turning up as
+ // conservative symbols. They should be marked SELFSECT
+ // and not SDATA, but sometimes that doesn't happen.
+ // Leave debugging the SDATA issue for the Go rewrite.
+
+ if(s->gotype == nil && s->size >= PtrSize && s->name[0] != '.') {
+ // conservative scan
+ diag("missing Go type information for global symbol: %s size %d", s->name, (int)s->size);
+ if((s->size%PtrSize) || (g->pos%PtrSize))
+ diag("proggenaddsym: unaligned conservative symbol %s: size=%lld pos=%lld",
+ s->name, s->size, g->pos);
+ size = (s->size+PtrSize-1)/PtrSize*PtrSize;
+ if(size < 32*PtrSize) {
+ // Emit small symbols as data.
+ for(i = 0; i < size/PtrSize; i++)
+ proggendata(g, BitsPointer);
+ } else {
+ // Emit large symbols as array.
+ proggenarray(g, size/PtrSize);
+ proggendata(g, BitsPointer);
+ proggenarrayend(g);
+ }
+ g->pos = s->value + size;
+ } else if(s->gotype == nil || decodetype_noptr(s->gotype) || s->size < PtrSize || s->name[0] == '.') {
+ // no scan
+ if(s->size < 32*PtrSize) {
+ // Emit small symbols as data.
+ // This case also handles unaligned and tiny symbols, so tread carefully.
+ for(i = s->value; i < s->value+s->size; i++) {
+ if((i%PtrSize) == 0)
+ proggendata(g, BitsScalar);
+ }
+ } else {
+ // Emit large symbols as array.
+ if((s->size%PtrSize) || (g->pos%PtrSize))
+ diag("proggenaddsym: unaligned noscan symbol %s: size=%lld pos=%lld",
+ s->name, s->size, g->pos);
+ proggenarray(g, s->size/PtrSize);
+ proggendata(g, BitsScalar);
+ proggenarrayend(g);
}
+ g->pos = s->value + s->size;
+ } else if(decodetype_usegcprog(s->gotype)) {
+ // gc program, copy directly
+ proggendataflush(g);
+ gcprog = decodetype_gcprog(s->gotype);
+ size = decodetype_size(s->gotype);
+ if((size%PtrSize) || (g->pos%PtrSize))
+ diag("proggenaddsym: unaligned gcprog symbol %s: size=%lld pos=%lld",
+ s->name, s->size, g->pos);
+ for(i = 0; i < gcprog->np-1; i++)
+ proggenemit(g, gcprog->p[i]);
+ g->pos = s->value + size;
+ } else {
+ // gc mask, it's small so emit as data
+ mask = decodetype_gcmask(s->gotype);
+ size = decodetype_size(s->gotype);
+ if((size%PtrSize) || (g->pos%PtrSize))
+ diag("proggenaddsym: unaligned gcmask symbol %s: size=%lld pos=%lld",
+ s->name, s->size, g->pos);
+ for(i = 0; i < size; i += PtrSize)
+ proggendata(g, (mask[i/PtrSize/2]>>((i/PtrSize%2)*4+2))&BitsMask);
+ g->pos = s->value + size;
}
}
@@ -751,19 +908,13 @@ dodata(void)
Section *sect;
Segment *segro;
LSym *s, *last, **l;
- LSym *gcdata1, *gcbss1;
+ LSym *gcdata, *gcbss;
+ ProgGen gen;
if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso);
- gcdata1 = linklookup(ctxt, "gcdata", 0);
- gcbss1 = linklookup(ctxt, "gcbss", 0);
-
- // size of .data and .bss section. the zero value is later replaced by the actual size of the section.
- adduintxx(ctxt, gcdata1, 0, PtrSize);
- adduintxx(ctxt, gcbss1, 0, PtrSize);
-
last = nil;
datap = nil;
@@ -847,8 +998,8 @@ dodata(void)
sect->align = maxalign(s, SINITARR-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "noptrdata", 0)->sect = sect;
- linklookup(ctxt, "enoptrdata", 0)->sect = sect;
+ linklookup(ctxt, "runtime.noptrdata", 0)->sect = sect;
+ linklookup(ctxt, "runtime.enoptrdata", 0)->sect = sect;
for(; s != nil && s->type < SINITARR; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -878,8 +1029,10 @@ dodata(void)
sect->align = maxalign(s, SBSS-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "data", 0)->sect = sect;
- linklookup(ctxt, "edata", 0)->sect = sect;
+ linklookup(ctxt, "runtime.data", 0)->sect = sect;
+ linklookup(ctxt, "runtime.edata", 0)->sect = sect;
+ gcdata = linklookup(ctxt, "runtime.gcdata", 0);
+ proggeninit(&gen, gcdata);
for(; s != nil && s->type < SBSS; s = s->next) {
if(s->type == SINITARR) {
ctxt->cursym = s;
@@ -889,40 +1042,38 @@ dodata(void)
s->type = SDATA;
datsize = aligndatsize(datsize, s);
s->value = datsize - sect->vaddr;
- gcaddsym(gcdata1, s, datsize - sect->vaddr); // gc
+ proggenaddsym(&gen, s); // gc
growdatsize(&datsize, s);
}
sect->len = datsize - sect->vaddr;
-
- adduintxx(ctxt, gcdata1, GC_END, PtrSize);
- setuintxx(ctxt, gcdata1, 0, sect->len, PtrSize);
+ proggenfini(&gen, sect->len); // gc
/* bss */
sect = addsection(&segdata, ".bss", 06);
sect->align = maxalign(s, SNOPTRBSS-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "bss", 0)->sect = sect;
- linklookup(ctxt, "ebss", 0)->sect = sect;
+ linklookup(ctxt, "runtime.bss", 0)->sect = sect;
+ linklookup(ctxt, "runtime.ebss", 0)->sect = sect;
+ gcbss = linklookup(ctxt, "runtime.gcbss", 0);
+ proggeninit(&gen, gcbss);
for(; s != nil && s->type < SNOPTRBSS; s = s->next) {
s->sect = sect;
datsize = aligndatsize(datsize, s);
s->value = datsize - sect->vaddr;
- gcaddsym(gcbss1, s, datsize - sect->vaddr); // gc
+ proggenaddsym(&gen, s); // gc
growdatsize(&datsize, s);
}
sect->len = datsize - sect->vaddr;
-
- adduintxx(ctxt, gcbss1, GC_END, PtrSize);
- setuintxx(ctxt, gcbss1, 0, sect->len, PtrSize);
+ proggenfini(&gen, sect->len); // gc
/* pointer-free bss */
sect = addsection(&segdata, ".noptrbss", 06);
sect->align = maxalign(s, SNOPTRBSS);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "noptrbss", 0)->sect = sect;
- linklookup(ctxt, "enoptrbss", 0)->sect = sect;
+ linklookup(ctxt, "runtime.noptrbss", 0)->sect = sect;
+ linklookup(ctxt, "runtime.enoptrbss", 0)->sect = sect;
for(; s != nil && s->type == SNOPTRBSS; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -930,7 +1081,7 @@ dodata(void)
growdatsize(&datsize, s);
}
sect->len = datsize - sect->vaddr;
- linklookup(ctxt, "end", 0)->sect = sect;
+ linklookup(ctxt, "runtime.end", 0)->sect = sect;
// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
if(datsize != (uint32)datsize) {
@@ -951,9 +1102,9 @@ dodata(void)
sect->len = datsize;
} else {
// Might be internal linking but still using cgo.
- // In that case, the only possible STLSBSS symbol is tlsgm.
+ // 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 == STLSBSS && strcmp(s->name, "runtime.tlsgm") == 0) {
+ if(s != nil && s->type == STLSBSS && strcmp(s->name, "runtime.tlsg") == 0) {
s->value = 0;
s = s->next;
}
@@ -1001,8 +1152,8 @@ dodata(void)
sect->align = maxalign(s, STYPELINK-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = 0;
- linklookup(ctxt, "rodata", 0)->sect = sect;
- linklookup(ctxt, "erodata", 0)->sect = sect;
+ linklookup(ctxt, "runtime.rodata", 0)->sect = sect;
+ linklookup(ctxt, "runtime.erodata", 0)->sect = sect;
for(; s != nil && s->type < STYPELINK; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -1017,8 +1168,8 @@ dodata(void)
sect->align = maxalign(s, STYPELINK);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "typelink", 0)->sect = sect;
- linklookup(ctxt, "etypelink", 0)->sect = sect;
+ linklookup(ctxt, "runtime.typelink", 0)->sect = sect;
+ linklookup(ctxt, "runtime.etypelink", 0)->sect = sect;
for(; s != nil && s->type == STYPELINK; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -1033,8 +1184,8 @@ dodata(void)
sect->align = maxalign(s, SPCLNTAB-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "symtab", 0)->sect = sect;
- linklookup(ctxt, "esymtab", 0)->sect = sect;
+ linklookup(ctxt, "runtime.symtab", 0)->sect = sect;
+ linklookup(ctxt, "runtime.esymtab", 0)->sect = sect;
for(; s != nil && s->type < SPCLNTAB; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -1049,8 +1200,8 @@ dodata(void)
sect->align = maxalign(s, SELFROSECT-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "pclntab", 0)->sect = sect;
- linklookup(ctxt, "epclntab", 0)->sect = sect;
+ linklookup(ctxt, "runtime.pclntab", 0)->sect = sect;
+ linklookup(ctxt, "runtime.epclntab", 0)->sect = sect;
for(; s != nil && s->type < SELFROSECT; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -1103,8 +1254,8 @@ textaddress(void)
// and then letting threads copy down, but probably not worth it.
sect = segtext.sect;
sect->align = funcalign;
- linklookup(ctxt, "text", 0)->sect = sect;
- linklookup(ctxt, "etext", 0)->sect = sect;
+ linklookup(ctxt, "runtime.text", 0)->sect = sect;
+ linklookup(ctxt, "runtime.etext", 0)->sect = sect;
va = INITTEXT;
sect->vaddr = va;
for(sym = ctxt->textp; sym != nil; sym = sym->next) {
@@ -1215,32 +1366,32 @@ address(void)
sub->value += sym->value;
}
- xdefine("text", STEXT, text->vaddr);
- xdefine("etext", STEXT, text->vaddr + text->len);
- xdefine("rodata", SRODATA, rodata->vaddr);
- xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
- xdefine("typelink", SRODATA, typelink->vaddr);
- xdefine("etypelink", SRODATA, typelink->vaddr + typelink->len);
-
- sym = linklookup(ctxt, "gcdata", 0);
- xdefine("egcdata", SRODATA, symaddr(sym) + sym->size);
- linklookup(ctxt, "egcdata", 0)->sect = sym->sect;
-
- sym = linklookup(ctxt, "gcbss", 0);
- xdefine("egcbss", SRODATA, symaddr(sym) + sym->size);
- linklookup(ctxt, "egcbss", 0)->sect = sym->sect;
-
- xdefine("symtab", SRODATA, symtab->vaddr);
- xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
- xdefine("pclntab", SRODATA, pclntab->vaddr);
- xdefine("epclntab", SRODATA, pclntab->vaddr + pclntab->len);
- xdefine("noptrdata", SNOPTRDATA, noptr->vaddr);
- xdefine("enoptrdata", SNOPTRDATA, noptr->vaddr + noptr->len);
- xdefine("bss", SBSS, bss->vaddr);
- xdefine("ebss", SBSS, bss->vaddr + bss->len);
- xdefine("data", SDATA, data->vaddr);
- xdefine("edata", SDATA, data->vaddr + data->len);
- xdefine("noptrbss", SNOPTRBSS, noptrbss->vaddr);
- xdefine("enoptrbss", SNOPTRBSS, noptrbss->vaddr + noptrbss->len);
- xdefine("end", SBSS, segdata.vaddr + segdata.len);
+ xdefine("runtime.text", STEXT, text->vaddr);
+ xdefine("runtime.etext", STEXT, text->vaddr + text->len);
+ xdefine("runtime.rodata", SRODATA, rodata->vaddr);
+ xdefine("runtime.erodata", SRODATA, rodata->vaddr + rodata->len);
+ xdefine("runtime.typelink", SRODATA, typelink->vaddr);
+ xdefine("runtime.etypelink", SRODATA, typelink->vaddr + typelink->len);
+
+ sym = linklookup(ctxt, "runtime.gcdata", 0);
+ xdefine("runtime.egcdata", SRODATA, symaddr(sym) + sym->size);
+ linklookup(ctxt, "runtime.egcdata", 0)->sect = sym->sect;
+
+ sym = linklookup(ctxt, "runtime.gcbss", 0);
+ xdefine("runtime.egcbss", SRODATA, symaddr(sym) + sym->size);
+ linklookup(ctxt, "runtime.egcbss", 0)->sect = sym->sect;
+
+ xdefine("runtime.symtab", SRODATA, symtab->vaddr);
+ xdefine("runtime.esymtab", SRODATA, symtab->vaddr + symtab->len);
+ xdefine("runtime.pclntab", SRODATA, pclntab->vaddr);
+ xdefine("runtime.epclntab", SRODATA, pclntab->vaddr + pclntab->len);
+ xdefine("runtime.noptrdata", SNOPTRDATA, noptr->vaddr);
+ xdefine("runtime.enoptrdata", SNOPTRDATA, noptr->vaddr + noptr->len);
+ xdefine("runtime.bss", SBSS, bss->vaddr);
+ xdefine("runtime.ebss", SBSS, bss->vaddr + bss->len);
+ xdefine("runtime.data", SDATA, data->vaddr);
+ xdefine("runtime.edata", SDATA, data->vaddr + data->len);
+ xdefine("runtime.noptrbss", SNOPTRBSS, noptrbss->vaddr);
+ xdefine("runtime.enoptrbss", SNOPTRBSS, noptrbss->vaddr + noptrbss->len);
+ xdefine("runtime.end", SBSS, segdata.vaddr + segdata.len);
}
diff --git a/src/cmd/ld/decodesym.c b/src/cmd/ld/decodesym.c
index da48d3786..037263dce 100644
--- a/src/cmd/ld/decodesym.c
+++ b/src/cmd/ld/decodesym.c
@@ -4,10 +4,10 @@
#include "l.h"
#include "lib.h"
-#include "../../pkg/runtime/typekind.h"
+#include "../../runtime/typekind.h"
// Decoding the type.* symbols. This has to be in sync with
-// ../../pkg/runtime/type.go, or more specificaly, with what
+// ../../runtime/type.go, or more specificaly, with what
// ../gc/reflect.c stuffs in these.
static Reloc*
@@ -70,14 +70,28 @@ decode_inuxi(uchar* p, int sz)
static int
commonsize(void)
{
- return 7*PtrSize + 8;
+ return 8*PtrSize + 8;
}
// Type.commonType.kind
uint8
decodetype_kind(LSym *s)
{
- return s->p[1*PtrSize + 7] & ~KindNoPointers; // 0x13 / 0x1f
+ return s->p[1*PtrSize + 7] & KindMask; // 0x13 / 0x1f
+}
+
+// Type.commonType.kind
+uint8
+decodetype_noptr(LSym *s)
+{
+ return s->p[1*PtrSize + 7] & KindNoPointers; // 0x13 / 0x1f
+}
+
+// Type.commonType.kind
+uint8
+decodetype_usegcprog(LSym *s)
+{
+ return s->p[1*PtrSize + 7] & KindGCProg; // 0x13 / 0x1f
}
// Type.commonType.size
@@ -89,9 +103,18 @@ decodetype_size(LSym *s)
// Type.commonType.gc
LSym*
-decodetype_gc(LSym *s)
+decodetype_gcprog(LSym *s)
{
- return decode_reloc_sym(s, 1*PtrSize + 8 + 1*PtrSize);
+ return decode_reloc_sym(s, 1*PtrSize + 8 + 2*PtrSize);
+}
+
+uint8*
+decodetype_gcmask(LSym *s)
+{
+ LSym *mask;
+
+ mask = decode_reloc_sym(s, 1*PtrSize + 8 + 1*PtrSize);
+ return mask->p;
}
// Type.ArrayType.elem and Type.SliceType.Elem
@@ -104,7 +127,7 @@ decodetype_arrayelem(LSym *s)
vlong
decodetype_arraylen(LSym *s)
{
- return decode_inuxi(s->p + commonsize()+PtrSize, PtrSize);
+ return decode_inuxi(s->p + commonsize()+2*PtrSize, PtrSize);
}
// Type.PtrType.elem
@@ -120,6 +143,7 @@ decodetype_mapkey(LSym *s)
{
return decode_reloc_sym(s, commonsize()); // 0x1c / 0x30
}
+
LSym*
decodetype_mapvalue(LSym *s)
{
diff --git a/src/cmd/ld/doc.go b/src/cmd/ld/doc.go
index 8135bd549..5b5833db5 100644
--- a/src/cmd/ld/doc.go
+++ b/src/cmd/ld/doc.go
@@ -63,9 +63,9 @@ Options new in this version:
-w
Omit the DWARF symbol table.
-X symbol value
- Set the value of an otherwise uninitialized string variable.
- The symbol name should be of the form importpath.name,
- as displayed in the symbol table printed by "go tool nm".
+ Set the value of a string variable. The symbol name
+ should be of the form importpath.name, as displayed
+ in the symbol table printed by "go tool nm".
-race
Link with race detection libraries.
-B value
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index cc77b45cd..a3ba52325 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -19,7 +19,7 @@
#include "../ld/elf.h"
#include "../ld/macho.h"
#include "../ld/pe.h"
-#include "../../pkg/runtime/typekind.h"
+#include "../../runtime/typekind.h"
/*
* Offsets and sizes of the debug_* sections in the cout file.
@@ -141,16 +141,22 @@ sleb128put(vlong v)
* only a handful of them. The DWARF spec places no restriction on
* the ordering of attributes in the Abbrevs and DIEs, and we will
* always write them out in the order of declaration in the abbrev.
- * This implementation relies on tag, attr < 127, so they serialize as
- * a char. Higher numbered user-defined tags or attributes can be used
- * for storing internal data but won't be serialized.
*/
typedef struct DWAttrForm DWAttrForm;
struct DWAttrForm {
- uint8 attr;
+ uint16 attr;
uint8 form;
};
+// Go-specific type attributes.
+enum {
+ DW_AT_go_kind = 0x2900,
+ DW_AT_go_key = 0x2901,
+ DW_AT_go_elem = 0x2902,
+
+ DW_AT_internal_location = 253, // params and locals; not emitted
+};
+
// Index into the abbrevs table below.
// Keep in sync with ispubname() and ispubtype() below.
// ispubtype considers >= NULLTYPE public
@@ -260,7 +266,7 @@ static struct DWAbbrev {
DW_TAG_subrange_type, DW_CHILDREN_no,
// No name!
DW_AT_type, DW_FORM_ref_addr,
- DW_AT_upper_bound, DW_FORM_data1,
+ DW_AT_count, DW_FORM_udata,
0, 0
},
@@ -277,6 +283,7 @@ static struct DWAbbrev {
DW_AT_name, DW_FORM_string,
DW_AT_encoding, DW_FORM_data1,
DW_AT_byte_size, DW_FORM_data1,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
/* ARRAYTYPE */
@@ -286,6 +293,7 @@ static struct DWAbbrev {
DW_AT_name, DW_FORM_string,
DW_AT_type, DW_FORM_ref_addr,
DW_AT_byte_size, DW_FORM_udata,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
@@ -294,6 +302,8 @@ static struct DWAbbrev {
DW_TAG_typedef, DW_CHILDREN_no,
DW_AT_name, DW_FORM_string,
DW_AT_type, DW_FORM_ref_addr,
+ DW_AT_go_kind, DW_FORM_data1,
+ DW_AT_go_elem, DW_FORM_ref_addr,
0, 0
},
@@ -302,6 +312,7 @@ static struct DWAbbrev {
DW_TAG_subroutine_type, DW_CHILDREN_yes,
DW_AT_name, DW_FORM_string,
// DW_AT_type, DW_FORM_ref_addr,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
@@ -310,6 +321,7 @@ static struct DWAbbrev {
DW_TAG_typedef, DW_CHILDREN_yes,
DW_AT_name, DW_FORM_string,
DW_AT_type, DW_FORM_ref_addr,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
@@ -318,6 +330,9 @@ static struct DWAbbrev {
DW_TAG_typedef, DW_CHILDREN_no,
DW_AT_name, DW_FORM_string,
DW_AT_type, DW_FORM_ref_addr,
+ DW_AT_go_kind, DW_FORM_data1,
+ DW_AT_go_key, DW_FORM_ref_addr,
+ DW_AT_go_elem, DW_FORM_ref_addr,
0, 0
},
@@ -326,6 +341,7 @@ static struct DWAbbrev {
DW_TAG_pointer_type, DW_CHILDREN_no,
DW_AT_name, DW_FORM_string,
DW_AT_type, DW_FORM_ref_addr,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
/* BARE_PTRTYPE */
@@ -340,6 +356,8 @@ static struct DWAbbrev {
DW_TAG_structure_type, DW_CHILDREN_yes,
DW_AT_name, DW_FORM_string,
DW_AT_byte_size, DW_FORM_udata,
+ DW_AT_go_kind, DW_FORM_data1,
+ DW_AT_go_elem, DW_FORM_ref_addr,
0, 0
},
@@ -348,6 +366,7 @@ static struct DWAbbrev {
DW_TAG_structure_type, DW_CHILDREN_yes,
DW_AT_name, DW_FORM_string,
DW_AT_byte_size, DW_FORM_udata,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
@@ -356,6 +375,7 @@ static struct DWAbbrev {
DW_TAG_structure_type, DW_CHILDREN_yes,
DW_AT_name, DW_FORM_string,
DW_AT_byte_size, DW_FORM_udata,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
@@ -371,7 +391,8 @@ static struct DWAbbrev {
static void
writeabbrev(void)
{
- int i, n;
+ int i, j;
+ DWAttrForm *f;
abbrevo = cpos();
for (i = 1; i < DW_NABRV; i++) {
@@ -379,11 +400,13 @@ writeabbrev(void)
uleb128put(i);
uleb128put(abbrevs[i].tag);
cput(abbrevs[i].children);
- // 0 is not a valid attr or form, and DWAbbrev.attr is
- // 0-terminated, so we can treat it as a string
- n = strlen((char*)abbrevs[i].attr) / 2;
- strnput((char*)abbrevs[i].attr,
- (n+1) * sizeof(DWAttrForm));
+ for(j=0; j<nelem(abbrevs[i].attr); j++) {
+ f = &abbrevs[i].attr[j];
+ uleb128put(f->attr);
+ uleb128put(f->form);
+ if(f->attr == 0)
+ break;
+ }
}
cput(0);
abbrevsize = cpos() - abbrevo;
@@ -417,7 +440,7 @@ hashstr(char* s)
typedef struct DWAttr DWAttr;
struct DWAttr {
DWAttr *link;
- uint8 atr; // DW_AT_
+ uint16 atr; // DW_AT_
uint8 cls; // DW_CLS_
vlong value;
char *data;
@@ -445,7 +468,7 @@ static DWDie dwtypes;
static DWDie dwglobals;
static DWAttr*
-newattr(DWDie *die, uint8 attr, int cls, vlong value, char *data)
+newattr(DWDie *die, uint16 attr, int cls, vlong value, char *data)
{
DWAttr *a;
@@ -463,7 +486,7 @@ newattr(DWDie *die, uint8 attr, int cls, vlong value, char *data)
// name. getattr moves the desired one to the front so
// frequently searched ones are found faster.
static DWAttr*
-getattr(DWDie *die, uint8 attr)
+getattr(DWDie *die, uint16 attr)
{
DWAttr *a, *b;
@@ -622,7 +645,7 @@ adddwarfrel(LSym* sec, LSym* sym, vlong offsetbase, int siz, vlong addend)
}
static DWAttr*
-newrefattr(DWDie *die, uint8 attr, DWDie* ref)
+newrefattr(DWDie *die, uint16 attr, DWDie* ref)
{
if (ref == nil)
return nil;
@@ -762,22 +785,22 @@ putattr(int abbrev, int form, int cls, vlong value, char *data)
static void
putattrs(int abbrev, DWAttr* attr)
{
- DWAttr *attrs[DW_AT_recursive + 1];
DWAttrForm* af;
-
- memset(attrs, 0, sizeof attrs);
- for( ; attr; attr = attr->link)
- if (attr->atr < nelem(attrs))
- attrs[attr->atr] = attr;
-
- for(af = abbrevs[abbrev].attr; af->attr; af++)
- if (attrs[af->attr])
- putattr(abbrev, af->form,
- attrs[af->attr]->cls,
- attrs[af->attr]->value,
- attrs[af->attr]->data);
- else
- putattr(abbrev, af->form, 0, 0, nil);
+ DWAttr *ap;
+
+ for(af = abbrevs[abbrev].attr; af->attr; af++) {
+ for(ap=attr; ap; ap=ap->link) {
+ if(ap->atr == af->attr) {
+ putattr(abbrev, af->form,
+ ap->cls,
+ ap->value,
+ ap->data);
+ goto done;
+ }
+ }
+ putattr(abbrev, af->form, 0, 0, nil);
+ done:;
+ }
}
static void putdie(DWDie* die);
@@ -835,11 +858,8 @@ newmemberoffsetattr(DWDie *die, int32 offs)
int i;
i = 0;
- if (offs != 0) {
- block[i++] = DW_OP_consts;
- i += sleb128enc(offs, block+i);
- block[i++] = DW_OP_plus;
- }
+ block[i++] = DW_OP_plus_uconst;
+ i += uleb128enc(offs, block+i);
newattr(die, DW_AT_data_member_location, DW_CLS_BLOCK, i, mal(i));
memmove(die->attr->data, block, i);
}
@@ -852,15 +872,6 @@ newabslocexprattr(DWDie *die, vlong addr, LSym *sym)
newattr(die, DW_AT_location, DW_CLS_ADDRESS, addr, (char*)sym);
}
-
-// Fake attributes for slices, maps and channel
-enum {
- DW_AT_internal_elem_type = 250, // channels and slices
- DW_AT_internal_key_type = 251, // maps
- DW_AT_internal_val_type = 252, // maps
- DW_AT_internal_location = 253, // params and locals
-};
-
static DWDie* defptrto(DWDie *dwtype); // below
// Lookup predefined types
@@ -981,7 +992,8 @@ defgotype(LSym *gotype)
s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s));
fld = newdie(die, DW_ABRV_ARRAYRANGE, "range");
- newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, decodetype_arraylen(gotype), 0);
+ // use actual length not upper bound; correct for 0-length arrays.
+ newattr(fld, DW_AT_count, DW_CLS_CONSTANT, decodetype_arraylen(gotype), 0);
newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
break;
@@ -989,7 +1001,7 @@ defgotype(LSym *gotype)
die = newdie(&dwtypes, DW_ABRV_CHANTYPE, name);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_chanelem(gotype);
- newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
+ newrefattr(die, DW_AT_go_elem, defgotype(s));
break;
case KindFunc:
@@ -1027,9 +1039,9 @@ defgotype(LSym *gotype)
case KindMap:
die = newdie(&dwtypes, DW_ABRV_MAPTYPE, name);
s = decodetype_mapkey(gotype);
- newrefattr(die, DW_AT_internal_key_type, defgotype(s));
+ newrefattr(die, DW_AT_go_key, defgotype(s));
s = decodetype_mapvalue(gotype);
- newrefattr(die, DW_AT_internal_val_type, defgotype(s));
+ newrefattr(die, DW_AT_go_elem, defgotype(s));
break;
case KindPtr:
@@ -1044,7 +1056,7 @@ defgotype(LSym *gotype)
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype);
- newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
+ newrefattr(die, DW_AT_go_elem, defgotype(s));
break;
case KindString:
@@ -1076,7 +1088,9 @@ defgotype(LSym *gotype)
diag("dwarf: definition of unknown kind %d: %s", kind, gotype->name);
die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name);
newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "<unspecified>"));
- }
+ }
+
+ newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, kind, 0);
return die;
}
@@ -1171,7 +1185,7 @@ synthesizeslicetypes(DWDie *die)
if (die->abbrev != DW_ABRV_SLICETYPE)
continue;
copychildren(die, prototype);
- elem = (DWDie*) getattr(die, DW_AT_internal_elem_type)->data;
+ elem = (DWDie*) getattr(die, DW_AT_go_elem)->data;
substitutetype(die, "array", defptrto(elem));
}
}
@@ -1208,7 +1222,7 @@ synthesizemaptypes(DWDie *die)
DWAttr *a;
hash = walktypedef(defgotype(lookup_or_diag("type.runtime.hmap")));
- bucket = walktypedef(defgotype(lookup_or_diag("type.runtime.bucket")));
+ bucket = walktypedef(defgotype(lookup_or_diag("type.runtime.bmap")));
if (hash == nil)
return;
@@ -1217,8 +1231,8 @@ synthesizemaptypes(DWDie *die)
if (die->abbrev != DW_ABRV_MAPTYPE)
continue;
- keytype = walktypedef((DWDie*) getattr(die, DW_AT_internal_key_type)->data);
- valtype = walktypedef((DWDie*) getattr(die, DW_AT_internal_val_type)->data);
+ keytype = walktypedef((DWDie*) getattr(die, DW_AT_go_key)->data);
+ valtype = walktypedef((DWDie*) getattr(die, DW_AT_go_elem)->data);
// compute size info like hashmap.c does.
a = getattr(keytype, DW_AT_byte_size);
@@ -1243,7 +1257,7 @@ synthesizemaptypes(DWDie *die)
newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize * keysize, 0);
newrefattr(dwhk, DW_AT_type, indirect_key ? defptrto(keytype) : keytype);
fld = newdie(dwhk, DW_ABRV_ARRAYRANGE, "size");
- newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, BucketSize, 0);
+ newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0);
newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
// Construct type to represent an array of BucketSize values
@@ -1253,7 +1267,7 @@ synthesizemaptypes(DWDie *die)
newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize * valsize, 0);
newrefattr(dwhv, DW_AT_type, indirect_val ? defptrto(valtype) : valtype);
fld = newdie(dwhv, DW_ABRV_ARRAYRANGE, "size");
- newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, BucketSize, 0);
+ newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0);
newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
// Construct bucket<K,V>
@@ -1309,7 +1323,7 @@ synthesizechantypes(DWDie *die)
for (; die != nil; die = die->link) {
if (die->abbrev != DW_ABRV_CHANTYPE)
continue;
- elemtype = (DWDie*) getattr(die, DW_AT_internal_elem_type)->data;
+ elemtype = (DWDie*) getattr(die, DW_AT_go_elem)->data;
a = getattr(elemtype, DW_AT_byte_size);
elemsize = a ? a->value : PtrSize;
@@ -1696,6 +1710,9 @@ enum
static void
putpccfadelta(vlong deltapc, vlong cfa)
{
+ cput(DW_CFA_def_cfa_offset_sf);
+ sleb128put(cfa / DATAALIGNMENTFACTOR);
+
if (deltapc < 0x40) {
cput(DW_CFA_advance_loc + deltapc);
} else if (deltapc < 0x100) {
@@ -1708,9 +1725,6 @@ putpccfadelta(vlong deltapc, vlong cfa)
cput(DW_CFA_advance_loc4);
LPUT(deltapc);
}
-
- cput(DW_CFA_def_cfa_offset_sf);
- sleb128put(cfa / DATAALIGNMENTFACTOR);
}
static void
@@ -1719,6 +1733,7 @@ writeframes(void)
LSym *s;
vlong fdeo, fdesize, pad;
Pciter pcsp;
+ uint32 nextpc;
if(framesec == S)
framesec = linklookup(ctxt, ".dwarfframe", 0);
@@ -1761,8 +1776,17 @@ writeframes(void)
addrput(0); // initial location
addrput(0); // address range
- for(pciterinit(ctxt, &pcsp, &s->pcln->pcsp); !pcsp.done; pciternext(&pcsp))
- putpccfadelta(pcsp.nextpc - pcsp.pc, PtrSize + pcsp.value);
+ for(pciterinit(ctxt, &pcsp, &s->pcln->pcsp); !pcsp.done; pciternext(&pcsp)) {
+ nextpc = pcsp.nextpc;
+ // pciterinit goes up to the end of the function,
+ // but DWARF expects us to stop just before the end.
+ if(nextpc == s->size) {
+ nextpc--;
+ if(nextpc < pcsp.pc)
+ continue;
+ }
+ putpccfadelta(nextpc - pcsp.pc, PtrSize + pcsp.value);
+ }
fdesize = cpos() - fdeo - 4; // exclude the length field.
pad = rnd(fdesize, PtrSize) - fdesize;
@@ -2028,13 +2052,15 @@ dwarfemitdebugsections(void)
newdie(&dwtypes, DW_ABRV_NULLTYPE, "<unspecified>");
newdie(&dwtypes, DW_ABRV_NULLTYPE, "void");
newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer");
+
die = newdie(&dwtypes, DW_ABRV_BASETYPE, "uintptr"); // needed for array size
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, PtrSize, 0);
+ newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, KindUintptr, 0);
// Needed by the prettyprinter code for interface inspection.
- defgotype(lookup_or_diag("type.runtime.rtype"));
- defgotype(lookup_or_diag("type.runtime.interfaceType"));
+ defgotype(lookup_or_diag("type.runtime._type"));
+ defgotype(lookup_or_diag("type.runtime.interfacetype"));
defgotype(lookup_or_diag("type.runtime.itab"));
genasmsym(defdwsymb);
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index 0555cf46a..3196961f3 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -776,7 +776,8 @@ elfshbits(Section *sect)
if(sect->rwx & 2)
sh->flags |= SHF_WRITE;
if(strcmp(sect->name, ".tbss") == 0) {
- sh->flags |= SHF_TLS;
+ if(strcmp(goos, "android") != 0)
+ sh->flags |= SHF_TLS; // no TLS on android
sh->type = SHT_NOBITS;
}
if(linkmode != LinkExternal)
diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c
index 1d7c4c13e..b5d081949 100644
--- a/src/cmd/ld/ldelf.c
+++ b/src/cmd/ld/ldelf.c
@@ -539,7 +539,7 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
s->type = SRODATA;
break;
case ElfSectFlagAlloc + ElfSectFlagWrite:
- s->type = SDATA;
+ s->type = SNOPTRDATA;
break;
case ElfSectFlagAlloc + ElfSectFlagExec:
s->type = STEXT;
@@ -572,7 +572,7 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
if(s->size < sym.size)
s->size = sym.size;
if(s->type == 0 || s->type == SXREF)
- s->type = SBSS;
+ s->type = SNOPTRBSS;
continue;
}
if(sym.shndx >= obj->nsect || sym.shndx == 0)
@@ -582,6 +582,8 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
continue;
sect = obj->sect+sym.shndx;
if(sect->sym == nil) {
+ if(strncmp(sym.name, ".Linfo_string", 13) == 0) // clang does this
+ continue;
diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type);
continue;
}
@@ -817,7 +819,7 @@ readsym(ElfObj *obj, int i, ElfSym *sym, int needSym)
}
break;
case ElfSymBindLocal:
- if(!(thechar == '5' && (strcmp(sym->name, "$a") == 0 || strcmp(sym->name, "$d") == 0))) // binutils for arm generate these mapping symbols, ignore these
+ if(!(thechar == '5' && (strncmp(sym->name, "$a", 2) == 0 || strncmp(sym->name, "$d", 2) == 0))) // binutils for arm generate these mapping symbols, ignore these
if(needSym) {
// local names and hidden visiblity global names are unique
// and should only reference by its index, not name, so we
diff --git a/src/cmd/ld/ldmacho.c b/src/cmd/ld/ldmacho.c
index 413dedabd..71cfa63de 100644
--- a/src/cmd/ld/ldmacho.c
+++ b/src/cmd/ld/ldmacho.c
@@ -589,10 +589,10 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
s->type = SRODATA;
} else {
if (strcmp(sect->name, "__bss") == 0) {
- s->type = SBSS;
+ s->type = SNOPTRBSS;
s->np = 0;
} else
- s->type = SDATA;
+ s->type = SNOPTRDATA;
}
sect->sym = s;
}
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
index f6eda900d..4f5e51f2f 100644
--- a/src/cmd/ld/ldpe.c
+++ b/src/cmd/ld/ldpe.c
@@ -128,6 +128,7 @@ struct PeObj {
};
static int map(PeObj *obj, PeSect *sect);
+static int issect(PeSym *s);
static int readsym(PeObj *obj, int i, PeSym **sym);
void
@@ -179,6 +180,15 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*obj->fh.NumberOfSymbols, 0);
if(Bread(f, obj->snames, l) != l)
goto bad;
+ // rewrite section names if they start with /
+ for(i=0; i < obj->fh.NumberOfSections; i++) {
+ if(obj->sect[i].name == nil)
+ continue;
+ if(obj->sect[i].name[0] != '/')
+ continue;
+ l = atoi(obj->sect[i].name + 1);
+ obj->sect[i].name = (char*)&obj->snames[l];
+ }
// read symbols
obj->pesym = mal(obj->fh.NumberOfSymbols*sizeof obj->pesym[0]);
obj->npesym = obj->fh.NumberOfSymbols;
@@ -230,10 +240,10 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
s->type = SRODATA;
break;
case IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.bss
- s->type = SBSS;
+ s->type = SNOPTRBSS;
break;
case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.data
- s->type = SDATA;
+ s->type = SNOPTRDATA;
break;
case IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ: //.text
s->type = STEXT;
@@ -309,8 +319,8 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
// ld -r could generate multiple section symbols for the
// same section but with different values, we have to take
// that into account
- if (obj->pesym[symindex].name[0] == '.')
- rp->add += obj->pesym[symindex].value;
+ if(issect(&obj->pesym[symindex]))
+ rp->add += obj->pesym[symindex].value;
}
qsort(r, rsect->sh.NumberOfRelocations, sizeof r[0], rbyoff);
@@ -318,12 +328,12 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
s->r = r;
s->nr = rsect->sh.NumberOfRelocations;
}
-
+
// enter sub-symbols into symbol table.
for(i=0; i<obj->npesym; i++) {
if(obj->pesym[i].name == 0)
continue;
- if(obj->pesym[i].name[0] == '.') //skip section
+ if(issect(&obj->pesym[i]))
continue;
if(obj->pesym[i].sectnum > 0) {
sect = &obj->sect[obj->pesym[i].sectnum-1];
@@ -338,7 +348,7 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
if(s->type == SDYNIMPORT)
s->plt = -2; // flag for dynimport in PE object files.
if (s->type == SXREF && sym->value > 0) {// global data
- s->type = SDATA;
+ s->type = SNOPTRDATA;
s->size = sym->value;
}
continue;
@@ -422,6 +432,12 @@ map(PeObj *obj, PeSect *sect)
}
static int
+issect(PeSym *s)
+{
+ return s->sclass == IMAGE_SYM_CLASS_STATIC && s->type == 0 && s->name[0] == '.';
+}
+
+static int
readsym(PeObj *obj, int i, PeSym **y)
{
LSym *s;
@@ -436,7 +452,7 @@ readsym(PeObj *obj, int i, PeSym **y)
sym = &obj->pesym[i];
*y = sym;
- if(sym->name[0] == '.') // .section
+ if(issect(sym))
name = obj->sect[sym->sectnum-1].sym->name;
else {
name = sym->name;
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index da6194e4f..f889aba8a 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -33,8 +33,8 @@
#include "lib.h"
#include "../ld/elf.h"
#include "../ld/dwarf.h"
-#include "../../pkg/runtime/stack.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/stack.h"
+#include "../../runtime/funcdata.h"
#include <ar.h>
#if !(defined(_WIN32) || defined(PLAN9))
@@ -144,6 +144,10 @@ libinit(void)
void
errorexit(void)
{
+ if(cout >= 0) {
+ // For rmtemp run at atexit time on Windows.
+ close(cout);
+ }
if(nerrors) {
if(cout >= 0)
mayberemoveoutfile();
@@ -177,7 +181,7 @@ void
loadlib(void)
{
int i, w, x;
- LSym *s, *gmsym;
+ LSym *s, *tlsg;
char* cgostrsym;
if(flag_shared) {
@@ -217,8 +221,12 @@ loadlib(void)
// Provided by the code that imports the package.
// Since we are simulating the import, we have to provide this string.
cgostrsym = "go.string.\"runtime/cgo\"";
- if(linkrlookup(ctxt, cgostrsym, 0) == nil)
+ if(linkrlookup(ctxt, cgostrsym, 0) == nil) {
+ s = linklookup(ctxt, cgostrsym, 0);
+ s->type = SRODATA;
+ s->reachable = 1;
addstrdata(cgostrsym, "runtime/cgo");
+ }
}
if(linkmode == LinkAuto) {
@@ -226,6 +234,10 @@ loadlib(void)
linkmode = LinkExternal;
else
linkmode = LinkInternal;
+
+ // Force external linking for android.
+ if(strcmp(goos, "android") == 0)
+ linkmode = LinkExternal;
}
if(linkmode == LinkInternal) {
@@ -244,12 +256,12 @@ loadlib(void)
}
}
- gmsym = linklookup(ctxt, "runtime.tlsgm", 0);
- gmsym->type = STLSBSS;
- gmsym->size = 2*PtrSize;
- gmsym->hide = 1;
- gmsym->reachable = 1;
- ctxt->gmsym = gmsym;
+ tlsg = linklookup(ctxt, "runtime.tlsg", 0);
+ tlsg->type = STLSBSS;
+ tlsg->size = PtrSize;
+ tlsg->hide = 1;
+ tlsg->reachable = 1;
+ ctxt->tlsg = tlsg;
// Now that we know the link mode, trim the dynexp list.
x = CgoExportDynamic;
@@ -895,7 +907,7 @@ unmal(void *v, uint32 n)
* escaping are %, ., and ", but we escape all control characters too.
*
* If you edit this, edit ../gc/subr.c:/^pathtoprefix too.
- * If you edit this, edit ../../pkg/debug/goobj/read.go:/importPathToPrefix too.
+ * If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
*/
static char*
pathtoprefix(char *s)
@@ -1345,10 +1357,10 @@ genasmsym(void (*put)(LSym*, char*, int, vlong, vlong, int, LSym*))
// These symbols won't show up in the first loop below because we
// skip STEXT symbols. Normal STEXT symbols are emitted by walking textp.
- s = linklookup(ctxt, "text", 0);
+ s = linklookup(ctxt, "runtime.text", 0);
if(s->type == STEXT)
put(s, s->name, 'T', s->value, s->size, s->version, 0);
- s = linklookup(ctxt, "etext", 0);
+ s = linklookup(ctxt, "runtime.etext", 0);
if(s->type == STEXT)
put(s, s->name, 'T', s->value, s->size, s->version, 0);
@@ -1550,3 +1562,56 @@ diag(char *fmt, ...)
errorexit();
}
}
+
+void
+checkgo(void)
+{
+ LSym *s;
+ Reloc *r;
+ int i;
+ int changed;
+
+ if(!debug['C'])
+ return;
+
+ // TODO(rsc,khr): Eventually we want to get to no Go-called C functions at all,
+ // which would simplify this logic quite a bit.
+
+ // Mark every Go-called C function with cfunc=2, recursively.
+ do {
+ changed = 0;
+ for(s = ctxt->textp; s != nil; s = s->next) {
+ if(s->cfunc == 0 || (s->cfunc == 2 && s->nosplit)) {
+ for(i=0; i<s->nr; i++) {
+ r = &s->r[i];
+ if(r->sym == nil)
+ continue;
+ if((r->type == R_CALL || r->type == R_CALLARM) && r->sym->type == STEXT) {
+ if(r->sym->cfunc == 1) {
+ changed = 1;
+ r->sym->cfunc = 2;
+ }
+ }
+ }
+ }
+ }
+ }while(changed);
+
+ // Complain about Go-called C functions that can split the stack
+ // (that can be preempted for garbage collection or trigger a stack copy).
+ for(s = ctxt->textp; s != nil; s = s->next) {
+ if(s->cfunc == 0 || (s->cfunc == 2 && s->nosplit)) {
+ for(i=0; i<s->nr; i++) {
+ r = &s->r[i];
+ if(r->sym == nil)
+ continue;
+ if((r->type == R_CALL || r->type == R_CALLARM) && r->sym->type == STEXT) {
+ if(s->cfunc == 0 && r->sym->cfunc == 2 && !r->sym->nosplit)
+ print("Go %s calls C %s\n", s->name, r->sym->name);
+ else if(s->cfunc == 2 && s->nosplit && !r->sym->nosplit)
+ print("Go calls C %s calls %s\n", s->name, r->sym->name);
+ }
+ }
+ }
+ }
+}
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 7267c6371..067ffa0bc 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -33,6 +33,10 @@
// A section further describes the pieces of that block for
// use in debuggers and such.
+enum {
+ MAXIO = 8192,
+};
+
typedef struct Segment Segment;
typedef struct Section Section;
@@ -179,12 +183,13 @@ uint16 be16(uchar *b);
uint32 be32(uchar *b);
uint64 be64(uchar *b);
void callgraph(void);
+void checkgo(void);
void cflush(void);
-void codeblk(int32 addr, int32 size);
+void codeblk(int64 addr, int64 size);
vlong cpos(void);
void cseek(vlong p);
void cwrite(void *buf, int n);
-void datblk(int32 addr, int32 size);
+void datblk(int64 addr, int64 size);
int datcmp(LSym *s1, LSym *s2);
vlong datoff(vlong addr);
void deadcode(void);
@@ -196,9 +201,12 @@ int decodetype_funcincount(LSym *s);
LSym* decodetype_funcintype(LSym *s, int i);
int decodetype_funcoutcount(LSym *s);
LSym* decodetype_funcouttype(LSym *s, int i);
-LSym* decodetype_gc(LSym *s);
+LSym* decodetype_gcprog(LSym *s);
+uint8* decodetype_gcmask(LSym *s);
vlong decodetype_ifacemethodcount(LSym *s);
uint8 decodetype_kind(LSym *s);
+uint8 decodetype_noptr(LSym *s);
+uint8 decodetype_usegcprog(LSym *s);
LSym* decodetype_mapkey(LSym *s);
LSym* decodetype_mapvalue(LSym *s);
LSym* decodetype_ptrelem(LSym *s);
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index 61306bb7c..fe7e10e46 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -590,8 +590,7 @@ machosymtab(void)
if(strstr(s->extname, "·") == nil) {
addstring(symstr, s->extname);
} else {
- p = s->extname;
- while (*p++ != '\0') {
+ for(p = s->extname; *p; p++) {
if((uchar)*p == 0xc2 && (uchar)*(p+1) == 0xb7) {
adduint8(ctxt, symstr, '.');
p++;
diff --git a/src/cmd/ld/pass.c b/src/cmd/ld/pass.c
deleted file mode 100644
index 788b7c75a..000000000
--- a/src/cmd/ld/pass.c
+++ /dev/null
@@ -1,104 +0,0 @@
-// Inferno utils/6l/pass.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6l/pass.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@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@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.
-
-// Code and data passes.
-
-#include "l.h"
-#include "../ld/lib.h"
-#include "../../pkg/runtime/stack.h"
-
-void
-follow(void)
-{
- LSym *s;
-
- if(debug['v'])
- Bprint(&bso, "%5.2f follow\n", cputime());
- Bflush(&bso);
-
- for(s = ctxt->textp; s != nil; s = s->next)
- ctxt->arch->follow(ctxt, s);
-}
-
-void
-patch(void)
-{
- LSym *s;
-
- if(debug['v'])
- Bprint(&bso, "%5.2f mkfwd\n", cputime());
- Bflush(&bso);
- for(s = ctxt->textp; s != nil; s = s->next)
- mkfwd(s);
- if(debug['v'])
- Bprint(&bso, "%5.2f patch\n", cputime());
- Bflush(&bso);
-
- if(flag_shared) {
- s = linklookup(ctxt, "init_array", 0);
- s->type = SINITARR;
- s->reachable = 1;
- s->hide = 1;
- addaddr(ctxt, s, linklookup(ctxt, INITENTRY, 0));
- }
-
- for(s = ctxt->textp; s != nil; s = s->next)
- linkpatch(ctxt, s);
-}
-
-void
-dostkoff(void)
-{
- LSym *s;
-
- for(s = ctxt->textp; s != nil; s = s->next)
- ctxt->arch->addstacksplit(ctxt, s);
-}
-
-void
-span(void)
-{
- LSym *s;
-
- if(debug['v'])
- Bprint(&bso, "%5.2f span\n", cputime());
-
- for(s = ctxt->textp; s != nil; s = s->next)
- ctxt->arch->assemble(ctxt, s);
-}
-
-void
-pcln(void)
-{
- LSym *s;
-
- for(s = ctxt->textp; s != nil; s = s->next)
- linkpcln(ctxt, s);
-}
diff --git a/src/cmd/ld/pcln.c b/src/cmd/ld/pcln.c
index 4c2ffa78e..69671c0fc 100644
--- a/src/cmd/ld/pcln.c
+++ b/src/cmd/ld/pcln.c
@@ -4,7 +4,7 @@
#include "l.h"
#include "lib.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
static void
addvarint(Pcdata *d, uint32 val)
@@ -90,7 +90,7 @@ renumberfiles(Link *ctxt, LSym **files, int nfiles, Pcdata *d)
}
dv = val - newval;
newval = val;
- v = (uint32)(dv<<1) ^ (uint32)(int32)(dv>>31);
+ v = ((uint32)dv<<1) ^ (uint32)(int32)(dv>>31);
addvarint(&out, v);
// pc delta
@@ -119,7 +119,7 @@ pclntab(void)
static Pcln zpcln;
funcdata_bytes = 0;
- ftab = linklookup(ctxt, "pclntab", 0);
+ ftab = linklookup(ctxt, "runtime.pclntab", 0);
ftab->type = SPCLNTAB;
ftab->reachable = 1;
diff --git a/src/cmd/ld/pobj.c b/src/cmd/ld/pobj.c
index 819c37954..63460df30 100644
--- a/src/cmd/ld/pobj.c
+++ b/src/cmd/ld/pobj.c
@@ -45,6 +45,8 @@ char* paramspace = "FP";
void
main(int argc, char *argv[])
{
+ int i;
+
linkarchinit();
ctxt = linknew(thelinkarch);
ctxt->thechar = thechar;
@@ -63,7 +65,13 @@ main(int argc, char *argv[])
INITRND = -1;
INITENTRY = 0;
linkmode = LinkAuto;
- nuxiinit();
+
+ // For testing behavior of go command when tools crash.
+ // Undocumented, not in standard flag parser to avoid
+ // exposing in usage message.
+ for(i=1; i<argc; i++)
+ if(strcmp(argv[i], "-crash_for_testing") == 0)
+ *(volatile int*)0 = 0;
if(thechar == '5' && ctxt->goarm == 5)
debug['F'] = 1;
@@ -72,6 +80,7 @@ main(int argc, char *argv[])
if(thechar == '6')
flagcount("8", "assume 64-bit addresses", &debug['8']);
flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo);
+ flagcount("C", "check Go calls to C code", &debug['C']);
flagint64("D", "addr: data address", &INITDAT);
flagstr("E", "sym: entry symbol", &INITENTRY);
if(thechar == '5')
@@ -96,11 +105,11 @@ main(int argc, char *argv[])
flagcount("a", "disassemble output", &debug['a']);
flagcount("c", "dump call graph", &debug['c']);
flagcount("d", "disable dynamic executable", &debug['d']);
- flagstr("extld", "linker to run in external mode", &extld);
- flagstr("extldflags", "flags for external linker", &extldflags);
+ flagstr("extld", "ld: linker to run in external mode", &extld);
+ flagstr("extldflags", "ldflags: flags for external linker", &extldflags);
flagcount("f", "ignore version mismatch", &debug['f']);
flagcount("g", "disable go package data checks", &debug['g']);
- flagstr("installsuffix", "pkg directory suffix", &flag_installsuffix);
+ flagstr("installsuffix", "suffix: pkg directory suffix", &flag_installsuffix);
flagstr("k", "sym: set field tracking symbol", &tracksym);
flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
flagcount("n", "dump symbol table", &debug['n']);
@@ -110,7 +119,7 @@ main(int argc, char *argv[])
flagcount("s", "disable symbol table", &debug['s']);
if(thechar == '5' || thechar == '6')
flagcount("shared", "generate shared object (implies -linkmode external)", &flag_shared);
- flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
+ flagstr("tmpdir", "dir: leave temporary files in this directory", &tmpdir);
flagcount("u", "reject unsafe packages", &debug['u']);
flagcount("v", "print link trace", &debug['v']);
flagcount("w", "disable DWARF generation", &debug['w']);
@@ -139,7 +148,7 @@ main(int argc, char *argv[])
if(HEADTYPE == -1)
HEADTYPE = headtype(goos);
ctxt->headtype = HEADTYPE;
- if (headstring == nil)
+ if(headstring == nil)
headstring = headstr(HEADTYPE);
archinit();
@@ -163,6 +172,7 @@ main(int argc, char *argv[])
mark(linklookup(ctxt, "runtime.read_tls_fallback", 0));
}
+ checkgo();
deadcode();
callgraph();
paramspace = "SP"; /* (FP) now (SP) on output */
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index 6d321c0bb..156270c8f 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -198,13 +198,18 @@ asmelfsym(void)
genasmsym(putelfsym);
if(linkmode == LinkExternal && HEADTYPE != Hopenbsd) {
- s = linklookup(ctxt, "runtime.tlsgm", 0);
+ s = linklookup(ctxt, "runtime.tlsg", 0);
if(s->sect == nil) {
ctxt->cursym = nil;
diag("missing section for %s", s->name);
errorexit();
}
- putelfsyment(putelfstr(s->name), 0, 2*PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0);
+ if (strcmp(goos, "android") == 0) {
+ // Android emulates runtime.tlsg as a regular variable.
+ putelfsyment(putelfstr(s->name), 0, s->size, (STB_LOCAL<<4)|STT_OBJECT, s->sect->elfsect->shnum, 0);
+ } else {
+ putelfsyment(putelfstr(s->name), 0, s->size, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0);
+ }
s->elfsym = numelfsym++;
}
@@ -341,36 +346,36 @@ symtab(void)
// Define these so that they'll get put into the symbol table.
// data.c:/^address will provide the actual values.
- xdefine("text", STEXT, 0);
- xdefine("etext", STEXT, 0);
- xdefine("typelink", SRODATA, 0);
- xdefine("etypelink", SRODATA, 0);
- xdefine("rodata", SRODATA, 0);
- xdefine("erodata", SRODATA, 0);
- xdefine("noptrdata", SNOPTRDATA, 0);
- xdefine("enoptrdata", SNOPTRDATA, 0);
- xdefine("data", SDATA, 0);
- xdefine("edata", SDATA, 0);
- xdefine("bss", SBSS, 0);
- xdefine("ebss", SBSS, 0);
- xdefine("noptrbss", SNOPTRBSS, 0);
- xdefine("enoptrbss", SNOPTRBSS, 0);
- xdefine("end", SBSS, 0);
- xdefine("epclntab", SRODATA, 0);
- xdefine("esymtab", SRODATA, 0);
+ xdefine("runtime.text", STEXT, 0);
+ xdefine("runtime.etext", STEXT, 0);
+ xdefine("runtime.typelink", SRODATA, 0);
+ xdefine("runtime.etypelink", SRODATA, 0);
+ xdefine("runtime.rodata", SRODATA, 0);
+ xdefine("runtime.erodata", SRODATA, 0);
+ xdefine("runtime.noptrdata", SNOPTRDATA, 0);
+ xdefine("runtime.enoptrdata", SNOPTRDATA, 0);
+ xdefine("runtime.data", SDATA, 0);
+ xdefine("runtime.edata", SDATA, 0);
+ xdefine("runtime.bss", SBSS, 0);
+ xdefine("runtime.ebss", SBSS, 0);
+ xdefine("runtime.noptrbss", SNOPTRBSS, 0);
+ xdefine("runtime.enoptrbss", SNOPTRBSS, 0);
+ xdefine("runtime.end", SBSS, 0);
+ xdefine("runtime.epclntab", SRODATA, 0);
+ xdefine("runtime.esymtab", SRODATA, 0);
// garbage collection symbols
- s = linklookup(ctxt, "gcdata", 0);
+ s = linklookup(ctxt, "runtime.gcdata", 0);
s->type = SRODATA;
s->size = 0;
s->reachable = 1;
- xdefine("egcdata", SRODATA, 0);
+ xdefine("runtime.egcdata", SRODATA, 0);
- s = linklookup(ctxt, "gcbss", 0);
+ s = linklookup(ctxt, "runtime.gcbss", 0);
s->type = SRODATA;
s->size = 0;
s->reachable = 1;
- xdefine("egcbss", SRODATA, 0);
+ xdefine("runtime.egcbss", SRODATA, 0);
// pseudo-symbols to mark locations of type, string, and go string data.
s = linklookup(ctxt, "type.*", 0);
@@ -391,9 +396,9 @@ symtab(void)
s->reachable = 1;
symgofunc = s;
- symtypelink = linklookup(ctxt, "typelink", 0);
+ symtypelink = linklookup(ctxt, "runtime.typelink", 0);
- symt = linklookup(ctxt, "symtab", 0);
+ symt = linklookup(ctxt, "runtime.symtab", 0);
symt->type = SSYMTAB;
symt->size = 0;
symt->reachable = 1;
diff --git a/src/cmd/ld/textflag.h b/src/cmd/ld/textflag.h
index 2a76e76c2..0ee8b5f1c 100644
--- a/src/cmd/ld/textflag.h
+++ b/src/cmd/ld/textflag.h
@@ -21,3 +21,16 @@
#define WRAPPER 32
// This function uses its incoming context register.
#define NEEDCTXT 64
+
+/*c2go
+enum
+{
+ NOPROF = 1,
+ DUPOK = 2,
+ NOSPLIT = 4,
+ RODATA = 8,
+ NOPTR = 16,
+ WRAPPER = 32,
+ NEEDCTXT = 64,
+};
+*/
diff --git a/src/cmd/nm/elf.go b/src/cmd/nm/elf.go
deleted file mode 100644
index 5aaa194dd..000000000
--- a/src/cmd/nm/elf.go
+++ /dev/null
@@ -1,57 +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.
-
-// Parsing of ELF executables (Linux, FreeBSD, and so on).
-
-package main
-
-import (
- "debug/elf"
- "os"
-)
-
-func elfSymbols(f *os.File) []Sym {
- p, err := elf.NewFile(f)
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return nil
- }
-
- elfSyms, err := p.Symbols()
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return nil
- }
-
- var syms []Sym
- for _, s := range elfSyms {
- sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'}
- switch s.Section {
- case elf.SHN_UNDEF:
- sym.Code = 'U'
- case elf.SHN_COMMON:
- sym.Code = 'B'
- default:
- i := int(s.Section)
- if i < 0 || i >= len(p.Sections) {
- break
- }
- sect := p.Sections[i]
- switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) {
- case elf.SHF_ALLOC | elf.SHF_EXECINSTR:
- sym.Code = 'T'
- case elf.SHF_ALLOC:
- sym.Code = 'R'
- case elf.SHF_ALLOC | elf.SHF_WRITE:
- sym.Code = 'D'
- }
- }
- if elf.ST_BIND(s.Info) == elf.STB_LOCAL {
- sym.Code += 'a' - 'A'
- }
- syms = append(syms, sym)
- }
-
- return syms
-}
diff --git a/src/cmd/nm/goobj.go b/src/cmd/nm/goobj.go
deleted file mode 100644
index 5e0817d95..000000000
--- a/src/cmd/nm/goobj.go
+++ /dev/null
@@ -1,67 +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.
-
-// Parsing of Go intermediate object files and archives.
-
-package main
-
-import (
- "fmt"
- "os"
-)
-
-func goobjName(id goobj_SymID) string {
- if id.Version == 0 {
- return id.Name
- }
- return fmt.Sprintf("%s<%d>", id.Name, id.Version)
-}
-
-func goobjSymbols(f *os.File) []Sym {
- pkg, err := goobj_Parse(f, `""`)
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return nil
- }
-
- seen := make(map[goobj_SymID]bool)
-
- var syms []Sym
- for _, s := range pkg.Syms {
- seen[s.goobj_SymID] = true
- sym := Sym{Addr: uint64(s.Data.Offset), Name: goobjName(s.goobj_SymID), Size: int64(s.Size), Type: s.Type.Name, Code: '?'}
- switch s.Kind {
- case goobj_STEXT, goobj_SELFRXSECT:
- sym.Code = 'T'
- case goobj_STYPE, goobj_SSTRING, goobj_SGOSTRING, goobj_SGOFUNC, goobj_SRODATA, goobj_SFUNCTAB, goobj_STYPELINK, goobj_SSYMTAB, goobj_SPCLNTAB, goobj_SELFROSECT:
- sym.Code = 'R'
- case goobj_SMACHOPLT, goobj_SELFSECT, goobj_SMACHO, goobj_SMACHOGOT, goobj_SNOPTRDATA, goobj_SINITARR, goobj_SDATA, goobj_SWINDOWS:
- sym.Code = 'D'
- case goobj_SBSS, goobj_SNOPTRBSS, goobj_STLSBSS:
- sym.Code = 'B'
- case goobj_SXREF, goobj_SMACHOSYMSTR, goobj_SMACHOSYMTAB, goobj_SMACHOINDIRECTPLT, goobj_SMACHOINDIRECTGOT, goobj_SFILE, goobj_SFILEPATH, goobj_SCONST, goobj_SDYNIMPORT, goobj_SHOSTOBJ:
- sym.Code = 'X' // should not see
- }
- if s.Version != 0 {
- sym.Code += 'a' - 'A'
- }
- syms = append(syms, sym)
- }
-
- for _, s := range pkg.Syms {
- for _, r := range s.Reloc {
- if !seen[r.Sym] {
- seen[r.Sym] = true
- sym := Sym{Name: goobjName(r.Sym), Code: 'U'}
- if s.Version != 0 {
- // should not happen but handle anyway
- sym.Code = 'u'
- }
- syms = append(syms, sym)
- }
- }
- }
-
- return syms
-}
diff --git a/src/cmd/nm/macho.go b/src/cmd/nm/macho.go
deleted file mode 100644
index c60bde55b..000000000
--- a/src/cmd/nm/macho.go
+++ /dev/null
@@ -1,69 +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.
-
-// Parsing of Mach-O executables (OS X).
-
-package main
-
-import (
- "debug/macho"
- "os"
- "sort"
-)
-
-func machoSymbols(f *os.File) []Sym {
- p, err := macho.NewFile(f)
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return nil
- }
-
- if p.Symtab == nil {
- errorf("%s: no symbol table", f.Name())
- return nil
- }
-
- // Build sorted list of addresses of all symbols.
- // We infer the size of a symbol by looking at where the next symbol begins.
- var addrs []uint64
- for _, s := range p.Symtab.Syms {
- addrs = append(addrs, s.Value)
- }
- sort.Sort(uint64s(addrs))
-
- var syms []Sym
- for _, s := range p.Symtab.Syms {
- sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'}
- i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value })
- if i < len(addrs) {
- sym.Size = int64(addrs[i] - s.Value)
- }
- if s.Sect == 0 {
- sym.Code = 'U'
- } else if int(s.Sect) <= len(p.Sections) {
- sect := p.Sections[s.Sect-1]
- switch sect.Seg {
- case "__TEXT":
- sym.Code = 'R'
- case "__DATA":
- sym.Code = 'D'
- }
- switch sect.Seg + " " + sect.Name {
- case "__TEXT __text":
- sym.Code = 'T'
- case "__DATA __bss", "__DATA __noptrbss":
- sym.Code = 'B'
- }
- }
- syms = append(syms, sym)
- }
-
- return syms
-}
-
-type uint64s []uint64
-
-func (x uint64s) Len() int { return len(x) }
-func (x uint64s) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
-func (x uint64s) Less(i, j int) bool { return x[i] < x[j] }
diff --git a/src/cmd/nm/nm.go b/src/cmd/nm/nm.go
index a4036184e..3089e481b 100644
--- a/src/cmd/nm/nm.go
+++ b/src/cmd/nm/nm.go
@@ -6,13 +6,13 @@ package main
import (
"bufio"
- "bytes"
"flag"
"fmt"
- "io"
"log"
"os"
"sort"
+
+ "cmd/internal/objfile"
)
func usage() {
@@ -85,55 +85,22 @@ func errorf(format string, args ...interface{}) {
exitCode = 1
}
-type Sym struct {
- Addr uint64
- Size int64
- Code rune
- Name string
- Type string
-}
-
-var parsers = []struct {
- prefix []byte
- parse func(*os.File) []Sym
-}{
- {[]byte("!<arch>\n"), goobjSymbols},
- {[]byte("go object "), goobjSymbols},
- {[]byte("\x7FELF"), elfSymbols},
- {[]byte("\xFE\xED\xFA\xCE"), machoSymbols},
- {[]byte("\xFE\xED\xFA\xCF"), machoSymbols},
- {[]byte("\xCE\xFA\xED\xFE"), machoSymbols},
- {[]byte("\xCF\xFA\xED\xFE"), machoSymbols},
- {[]byte("MZ"), peSymbols},
- {[]byte("\x00\x00\x01\xEB"), plan9Symbols}, // 386
- {[]byte("\x00\x00\x04\x07"), plan9Symbols}, // mips
- {[]byte("\x00\x00\x06\x47"), plan9Symbols}, // arm
- {[]byte("\x00\x00\x8A\x97"), plan9Symbols}, // amd64
-}
-
func nm(file string) {
- f, err := os.Open(file)
+ f, err := objfile.Open(file)
if err != nil {
errorf("%v", err)
return
}
defer f.Close()
- buf := make([]byte, 16)
- io.ReadFull(f, buf)
- f.Seek(0, 0)
-
- var syms []Sym
- for _, p := range parsers {
- if bytes.HasPrefix(buf, p.prefix) {
- syms = p.parse(f)
- goto HaveSyms
- }
+ syms, err := f.Symbols()
+ if err != nil {
+ errorf("reading %s: %v", file, err)
+ }
+ if len(syms) == 0 {
+ errorf("reading %s: no symbols", file)
}
- errorf("%v: unknown file format", file)
- return
-HaveSyms:
switch *sortOrder {
case "address":
sort.Sort(byAddr(syms))
@@ -165,19 +132,19 @@ HaveSyms:
w.Flush()
}
-type byAddr []Sym
+type byAddr []objfile.Sym
func (x byAddr) Len() int { return len(x) }
func (x byAddr) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byAddr) Less(i, j int) bool { return x[i].Addr < x[j].Addr }
-type byName []Sym
+type byName []objfile.Sym
func (x byName) Len() int { return len(x) }
func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byName) Less(i, j int) bool { return x[i].Name < x[j].Name }
-type bySize []Sym
+type bySize []objfile.Sym
func (x bySize) Len() int { return len(x) }
func (x bySize) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
diff --git a/src/cmd/nm/nm_test.go b/src/cmd/nm/nm_test.go
index f4e47a42d..cb555d827 100644
--- a/src/cmd/nm/nm_test.go
+++ b/src/cmd/nm/nm_test.go
@@ -55,8 +55,9 @@ func checkSymbols(t *testing.T, nmoutput []byte) {
}
func TestNM(t *testing.T) {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
+ switch runtime.GOOS {
+ case "android", "nacl":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
tmpDir, err := ioutil.TempDir("", "TestNM")
@@ -76,17 +77,17 @@ func TestNM(t *testing.T) {
"elf/testdata/gcc-amd64-linux-exec",
"macho/testdata/gcc-386-darwin-exec",
"macho/testdata/gcc-amd64-darwin-exec",
- "pe/testdata/gcc-amd64-mingw-exec",
+ // "pe/testdata/gcc-amd64-mingw-exec", // no symbols!
"pe/testdata/gcc-386-mingw-exec",
"plan9obj/testdata/amd64-plan9-exec",
"plan9obj/testdata/386-plan9-exec",
}
for _, f := range testfiles {
- exepath := filepath.Join(runtime.GOROOT(), "src", "pkg", "debug", f)
+ exepath := filepath.Join(runtime.GOROOT(), "src", "debug", f)
cmd := exec.Command(testnmpath, exepath)
out, err := cmd.CombinedOutput()
if err != nil {
- t.Fatalf("go tool nm %v: %v\n%s", exepath, err, string(out))
+ t.Errorf("go tool nm %v: %v\n%s", exepath, err, string(out))
}
}
diff --git a/src/cmd/nm/pe.go b/src/cmd/nm/pe.go
deleted file mode 100644
index 52d05e51d..000000000
--- a/src/cmd/nm/pe.go
+++ /dev/null
@@ -1,98 +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.
-
-// Parsing of PE executables (Microsoft Windows).
-
-package main
-
-import (
- "debug/pe"
- "os"
- "sort"
-)
-
-func peSymbols(f *os.File) []Sym {
- p, err := pe.NewFile(f)
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return nil
- }
-
- // Build sorted list of addresses of all symbols.
- // We infer the size of a symbol by looking at where the next symbol begins.
- var addrs []uint64
-
- var imageBase uint64
- switch oh := p.OptionalHeader.(type) {
- case *pe.OptionalHeader32:
- imageBase = uint64(oh.ImageBase)
- case *pe.OptionalHeader64:
- imageBase = oh.ImageBase
- default:
- errorf("parsing %s: file format not recognized", f.Name())
- return nil
- }
-
- var syms []Sym
- for _, s := range p.Symbols {
- const (
- N_UNDEF = 0 // An undefined (extern) symbol
- N_ABS = -1 // An absolute symbol (e_value is a constant, not an address)
- N_DEBUG = -2 // A debugging symbol
- )
- sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'}
- switch s.SectionNumber {
- case N_UNDEF:
- sym.Code = 'U'
- case N_ABS:
- sym.Code = 'C'
- case N_DEBUG:
- sym.Code = '?'
- default:
- if s.SectionNumber < 0 {
- errorf("parsing %s: invalid section number %d", f.Name(), s.SectionNumber)
- return nil
- }
- if len(p.Sections) < int(s.SectionNumber) {
- errorf("parsing %s: section number %d is large then max %d", f.Name(), s.SectionNumber, len(p.Sections))
- return nil
- }
- sect := p.Sections[s.SectionNumber-1]
- const (
- text = 0x20
- data = 0x40
- bss = 0x80
- permX = 0x20000000
- permR = 0x40000000
- permW = 0x80000000
- )
- ch := sect.Characteristics
- switch {
- case ch&text != 0:
- sym.Code = 'T'
- case ch&data != 0:
- if ch&permW == 0 {
- sym.Code = 'R'
- } else {
- sym.Code = 'D'
- }
- case ch&bss != 0:
- sym.Code = 'B'
- }
- sym.Addr += imageBase + uint64(sect.VirtualAddress)
- }
- syms = append(syms, sym)
- addrs = append(addrs, sym.Addr)
- }
-
- sort.Sort(uint64s(addrs))
- for i := range syms {
- j := sort.Search(len(addrs), func(x int) bool { return addrs[x] > syms[i].Addr })
- if j < len(addrs) {
- syms[i].Size = int64(addrs[j] - syms[i].Addr)
- }
- }
-
- return syms
-}
diff --git a/src/cmd/nm/plan9obj.go b/src/cmd/nm/plan9obj.go
deleted file mode 100644
index 006c66ebf..000000000
--- a/src/cmd/nm/plan9obj.go
+++ /dev/null
@@ -1,48 +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.
-
-// Parsing of Plan 9 a.out executables.
-
-package main
-
-import (
- "debug/plan9obj"
- "os"
- "sort"
-)
-
-func plan9Symbols(f *os.File) []Sym {
- p, err := plan9obj.NewFile(f)
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return nil
- }
-
- plan9Syms, err := p.Symbols()
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return nil
- }
-
- // Build sorted list of addresses of all symbols.
- // We infer the size of a symbol by looking at where the next symbol begins.
- var addrs []uint64
- for _, s := range plan9Syms {
- addrs = append(addrs, s.Value)
- }
- sort.Sort(uint64s(addrs))
-
- var syms []Sym
-
- for _, s := range plan9Syms {
- sym := Sym{Addr: s.Value, Name: s.Name, Code: rune(s.Type)}
- i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value })
- if i < len(addrs) {
- sym.Size = int64(addrs[i] - s.Value)
- }
- syms = append(syms, sym)
- }
-
- return syms
-}
diff --git a/src/cmd/objdump/Makefile b/src/cmd/objdump/Makefile
deleted file mode 100644
index 1b66c26ba..000000000
--- a/src/cmd/objdump/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-all: x86.go armasm.go
-
-x86.go: bundle
- ./bundle -p main -x x86_ rsc.io/x86/x86asm | gofmt >x86.go
-
-armasm.go: bundle
- ./bundle -p main -x arm_ rsc.io/arm/armasm | gofmt >armasm.go
-
-bundle:
- go build -o bundle code.google.com/p/rsc/cmd/bundle
diff --git a/src/cmd/objdump/armasm.go b/src/cmd/objdump/armasm.go
deleted file mode 100644
index 764a3689e..000000000
--- a/src/cmd/objdump/armasm.go
+++ /dev/null
@@ -1,10821 +0,0 @@
-// DO NOT EDIT. Generated by code.google.com/p/rsc/cmd/bundle
-// bundle -p main -x arm_ rsc.io/arm/armasm
-
-/* decode.go */
-
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
- "bytes"
- "encoding/binary"
- "fmt"
- "io"
- "strings"
-)
-
-// An instFormat describes the format of an instruction encoding.
-// An instruction with 32-bit value x matches the format if x&mask == value
-// and the condition matches.
-// The condition matches if x>>28 == 0xF && value>>28==0xF
-// or if x>>28 != 0xF and value>>28 == 0.
-// If x matches the format, then the rest of the fields describe how to interpret x.
-// The opBits describe bits that should be extracted from x and added to the opcode.
-// For example opBits = 0x1234 means that the value
-// (2 bits at offset 1) followed by (4 bits at offset 3)
-// should be added to op.
-// Finally the args describe how to decode the instruction arguments.
-// args is stored as a fixed-size array; if there are fewer than len(args) arguments,
-// args[i] == 0 marks the end of the argument list.
-type arm_instFormat struct {
- mask uint32
- value uint32
- priority int8
- op arm_Op
- opBits uint64
- args arm_instArgs
-}
-
-type arm_instArgs [4]arm_instArg
-
-var (
- arm_errMode = fmt.Errorf("unsupported execution mode")
- arm_errShort = fmt.Errorf("truncated instruction")
- arm_errUnknown = fmt.Errorf("unknown instruction")
-)
-
-var arm_decoderCover []bool
-
-// Decode decodes the leading bytes in src as a single instruction.
-func arm_Decode(src []byte, mode arm_Mode) (inst arm_Inst, err error) {
- if mode != arm_ModeARM {
- return arm_Inst{}, arm_errMode
- }
- if len(src) < 4 {
- return arm_Inst{}, arm_errShort
- }
-
- if arm_decoderCover == nil {
- arm_decoderCover = make([]bool, len(arm_instFormats))
- }
-
- x := binary.LittleEndian.Uint32(src)
-
- // The instFormat table contains both conditional and unconditional instructions.
- // Considering only the top 4 bits, the conditional instructions use mask=0, value=0,
- // while the unconditional instructions use mask=f, value=f.
- // Prepare a version of x with the condition cleared to 0 in conditional instructions
- // and then assume mask=f during matching.
- const condMask = 0xf0000000
- xNoCond := x
- if x&condMask != condMask {
- xNoCond &^= condMask
- }
- var priority int8
-Search:
- for i := range arm_instFormats {
- f := &arm_instFormats[i]
- if xNoCond&(f.mask|condMask) != f.value || f.priority <= priority {
- continue
- }
- delta := uint32(0)
- deltaShift := uint(0)
- for opBits := f.opBits; opBits != 0; opBits >>= 16 {
- n := uint(opBits & 0xFF)
- off := uint((opBits >> 8) & 0xFF)
- delta |= (x >> off) & (1<<n - 1) << deltaShift
- deltaShift += n
- }
- op := f.op + arm_Op(delta)
-
- // Special case: BKPT encodes with condition but cannot have one.
- if op&^15 == arm_BKPT_EQ && op != arm_BKPT {
- continue Search
- }
-
- var args arm_Args
- for j, aop := range f.args {
- if aop == 0 {
- break
- }
- arg := arm_decodeArg(aop, x)
- if arg == nil { // cannot decode argument
- continue Search
- }
- args[j] = arg
- }
-
- arm_decoderCover[i] = true
-
- inst = arm_Inst{
- Op: op,
- Args: args,
- Enc: x,
- Len: 4,
- }
- priority = f.priority
- continue Search
- }
- if inst.Op != 0 {
- return inst, nil
- }
- return arm_Inst{}, arm_errUnknown
-}
-
-// An instArg describes the encoding of a single argument.
-// In the names used for arguments, _p_ means +, _m_ means -,
-// _pm_ means ± (usually keyed by the U bit).
-// The _W suffix indicates a general addressing mode based on the P and W bits.
-// The _offset and _postindex suffixes force the given addressing mode.
-// The rest should be somewhat self-explanatory, at least given
-// the decodeArg function.
-type arm_instArg uint8
-
-const (
- _ arm_instArg = iota
- arm_arg_APSR
- arm_arg_FPSCR
- arm_arg_Dn_half
- arm_arg_R1_0
- arm_arg_R1_12
- arm_arg_R2_0
- arm_arg_R2_12
- arm_arg_R_0
- arm_arg_R_12
- arm_arg_R_12_nzcv
- arm_arg_R_16
- arm_arg_R_16_WB
- arm_arg_R_8
- arm_arg_R_rotate
- arm_arg_R_shift_R
- arm_arg_R_shift_imm
- arm_arg_SP
- arm_arg_Sd
- arm_arg_Sd_Dd
- arm_arg_Dd_Sd
- arm_arg_Sm
- arm_arg_Sm_Dm
- arm_arg_Sn
- arm_arg_Sn_Dn
- arm_arg_const
- arm_arg_endian
- arm_arg_fbits
- arm_arg_fp_0
- arm_arg_imm24
- arm_arg_imm5
- arm_arg_imm5_32
- arm_arg_imm5_nz
- arm_arg_imm_12at8_4at0
- arm_arg_imm_4at16_12at0
- arm_arg_imm_vfp
- arm_arg_label24
- arm_arg_label24H
- arm_arg_label_m_12
- arm_arg_label_p_12
- arm_arg_label_pm_12
- arm_arg_label_pm_4_4
- arm_arg_lsb_width
- arm_arg_mem_R
- arm_arg_mem_R_pm_R_W
- arm_arg_mem_R_pm_R_postindex
- arm_arg_mem_R_pm_R_shift_imm_W
- arm_arg_mem_R_pm_R_shift_imm_offset
- arm_arg_mem_R_pm_R_shift_imm_postindex
- arm_arg_mem_R_pm_imm12_W
- arm_arg_mem_R_pm_imm12_offset
- arm_arg_mem_R_pm_imm12_postindex
- arm_arg_mem_R_pm_imm8_W
- arm_arg_mem_R_pm_imm8_postindex
- arm_arg_mem_R_pm_imm8at0_offset
- arm_arg_option
- arm_arg_registers
- arm_arg_registers1
- arm_arg_registers2
- arm_arg_satimm4
- arm_arg_satimm5
- arm_arg_satimm4m1
- arm_arg_satimm5m1
- arm_arg_widthm1
-)
-
-// decodeArg decodes the arg described by aop from the instruction bits x.
-// It returns nil if x cannot be decoded according to aop.
-func arm_decodeArg(aop arm_instArg, x uint32) arm_Arg {
- switch aop {
- default:
- return nil
-
- case arm_arg_APSR:
- return arm_APSR
- case arm_arg_FPSCR:
- return arm_FPSCR
-
- case arm_arg_R_0:
- return arm_Reg(x & (1<<4 - 1))
- case arm_arg_R_8:
- return arm_Reg((x >> 8) & (1<<4 - 1))
- case arm_arg_R_12:
- return arm_Reg((x >> 12) & (1<<4 - 1))
- case arm_arg_R_16:
- return arm_Reg((x >> 16) & (1<<4 - 1))
-
- case arm_arg_R_12_nzcv:
- r := arm_Reg((x >> 12) & (1<<4 - 1))
- if r == arm_R15 {
- return arm_APSR_nzcv
- }
- return r
-
- case arm_arg_R_16_WB:
- mode := arm_AddrLDM
- if (x>>21)&1 != 0 {
- mode = arm_AddrLDM_WB
- }
- return arm_Mem{Base: arm_Reg((x >> 16) & (1<<4 - 1)), Mode: mode}
-
- case arm_arg_R_rotate:
- Rm := arm_Reg(x & (1<<4 - 1))
- typ, count := arm_decodeShift(x)
- // ROR #0 here means ROR #0, but decodeShift rewrites to RRX #1.
- if typ == arm_RotateRightExt {
- return arm_Reg(Rm)
- }
- return arm_RegShift{Rm, typ, uint8(count)}
-
- case arm_arg_R_shift_R:
- Rm := arm_Reg(x & (1<<4 - 1))
- Rs := arm_Reg((x >> 8) & (1<<4 - 1))
- typ := arm_Shift((x >> 5) & (1<<2 - 1))
- return arm_RegShiftReg{Rm, typ, Rs}
-
- case arm_arg_R_shift_imm:
- Rm := arm_Reg(x & (1<<4 - 1))
- typ, count := arm_decodeShift(x)
- if typ == arm_ShiftLeft && count == 0 {
- return arm_Reg(Rm)
- }
- return arm_RegShift{Rm, typ, uint8(count)}
-
- case arm_arg_R1_0:
- return arm_Reg((x & (1<<4 - 1)))
- case arm_arg_R1_12:
- return arm_Reg(((x >> 12) & (1<<4 - 1)))
- case arm_arg_R2_0:
- return arm_Reg((x & (1<<4 - 1)) | 1)
- case arm_arg_R2_12:
- return arm_Reg(((x >> 12) & (1<<4 - 1)) | 1)
-
- case arm_arg_SP:
- return arm_SP
-
- case arm_arg_Sd_Dd:
- v := (x >> 12) & (1<<4 - 1)
- vx := (x >> 22) & 1
- sz := (x >> 8) & 1
- if sz != 0 {
- return arm_D0 + arm_Reg(vx<<4+v)
- } else {
- return arm_S0 + arm_Reg(v<<1+vx)
- }
-
- case arm_arg_Dd_Sd:
- return arm_decodeArg(arm_arg_Sd_Dd, x^(1<<8))
-
- case arm_arg_Sd:
- v := (x >> 12) & (1<<4 - 1)
- vx := (x >> 22) & 1
- return arm_S0 + arm_Reg(v<<1+vx)
-
- case arm_arg_Sm_Dm:
- v := (x >> 0) & (1<<4 - 1)
- vx := (x >> 5) & 1
- sz := (x >> 8) & 1
- if sz != 0 {
- return arm_D0 + arm_Reg(vx<<4+v)
- } else {
- return arm_S0 + arm_Reg(v<<1+vx)
- }
-
- case arm_arg_Sm:
- v := (x >> 0) & (1<<4 - 1)
- vx := (x >> 5) & 1
- return arm_S0 + arm_Reg(v<<1+vx)
-
- case arm_arg_Dn_half:
- v := (x >> 16) & (1<<4 - 1)
- vx := (x >> 7) & 1
- return arm_RegX{arm_D0 + arm_Reg(vx<<4+v), int((x >> 21) & 1)}
-
- case arm_arg_Sn_Dn:
- v := (x >> 16) & (1<<4 - 1)
- vx := (x >> 7) & 1
- sz := (x >> 8) & 1
- if sz != 0 {
- return arm_D0 + arm_Reg(vx<<4+v)
- } else {
- return arm_S0 + arm_Reg(v<<1+vx)
- }
-
- case arm_arg_Sn:
- v := (x >> 16) & (1<<4 - 1)
- vx := (x >> 7) & 1
- return arm_S0 + arm_Reg(v<<1+vx)
-
- case arm_arg_const:
- v := x & (1<<8 - 1)
- rot := (x >> 8) & (1<<4 - 1) * 2
- if rot > 0 && v&3 == 0 {
- // could rotate less
- return arm_ImmAlt{uint8(v), uint8(rot)}
- }
- if rot >= 24 && ((v<<(32-rot))&0xFF)>>(32-rot) == v {
- // could wrap around to rot==0.
- return arm_ImmAlt{uint8(v), uint8(rot)}
- }
- return arm_Imm(v>>rot | v<<(32-rot))
-
- case arm_arg_endian:
- return arm_Endian((x >> 9) & 1)
-
- case arm_arg_fbits:
- return arm_Imm((16 << ((x >> 7) & 1)) - ((x&(1<<4-1))<<1 | (x>>5)&1))
-
- case arm_arg_fp_0:
- return arm_Imm(0)
-
- case arm_arg_imm24:
- return arm_Imm(x & (1<<24 - 1))
-
- case arm_arg_imm5:
- return arm_Imm((x >> 7) & (1<<5 - 1))
-
- case arm_arg_imm5_32:
- x = (x >> 7) & (1<<5 - 1)
- if x == 0 {
- x = 32
- }
- return arm_Imm(x)
-
- case arm_arg_imm5_nz:
- x = (x >> 7) & (1<<5 - 1)
- if x == 0 {
- return nil
- }
- return arm_Imm(x)
-
- case arm_arg_imm_4at16_12at0:
- return arm_Imm((x>>16)&(1<<4-1)<<12 | x&(1<<12-1))
-
- case arm_arg_imm_12at8_4at0:
- return arm_Imm((x>>8)&(1<<12-1)<<4 | x&(1<<4-1))
-
- case arm_arg_imm_vfp:
- x = (x>>16)&(1<<4-1)<<4 | x&(1<<4-1)
- return arm_Imm(x)
-
- case arm_arg_label24:
- imm := (x & (1<<24 - 1)) << 2
- return arm_PCRel(int32(imm<<6) >> 6)
-
- case arm_arg_label24H:
- h := (x >> 24) & 1
- imm := (x&(1<<24-1))<<2 | h<<1
- return arm_PCRel(int32(imm<<6) >> 6)
-
- case arm_arg_label_m_12:
- d := int32(x & (1<<12 - 1))
- return arm_Mem{Base: arm_PC, Mode: arm_AddrOffset, Offset: int16(-d)}
-
- case arm_arg_label_p_12:
- d := int32(x & (1<<12 - 1))
- return arm_Mem{Base: arm_PC, Mode: arm_AddrOffset, Offset: int16(d)}
-
- case arm_arg_label_pm_12:
- d := int32(x & (1<<12 - 1))
- u := (x >> 23) & 1
- if u == 0 {
- d = -d
- }
- return arm_Mem{Base: arm_PC, Mode: arm_AddrOffset, Offset: int16(d)}
-
- case arm_arg_label_pm_4_4:
- d := int32((x>>8)&(1<<4-1)<<4 | x&(1<<4-1))
- u := (x >> 23) & 1
- if u == 0 {
- d = -d
- }
- return arm_PCRel(d)
-
- case arm_arg_lsb_width:
- lsb := (x >> 7) & (1<<5 - 1)
- msb := (x >> 16) & (1<<5 - 1)
- if msb < lsb || msb >= 32 {
- return nil
- }
- return arm_Imm(msb + 1 - lsb)
-
- case arm_arg_mem_R:
- Rn := arm_Reg((x >> 16) & (1<<4 - 1))
- return arm_Mem{Base: Rn, Mode: arm_AddrOffset}
-
- case arm_arg_mem_R_pm_R_postindex:
- // Treat [<Rn>],+/-<Rm> like [<Rn>,+/-<Rm>{,<shift>}]{!}
- // by forcing shift bits to <<0 and P=0, W=0 (postindex=true).
- return arm_decodeArg(arm_arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5|1<<24|1<<21))
-
- case arm_arg_mem_R_pm_R_W:
- // Treat [<Rn>,+/-<Rm>]{!} like [<Rn>,+/-<Rm>{,<shift>}]{!}
- // by forcing shift bits to <<0.
- return arm_decodeArg(arm_arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5))
-
- case arm_arg_mem_R_pm_R_shift_imm_offset:
- // Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!}
- // by forcing P=1, W=0 (index=false, wback=false).
- return arm_decodeArg(arm_arg_mem_R_pm_R_shift_imm_W, x&^(1<<21)|1<<24)
-
- case arm_arg_mem_R_pm_R_shift_imm_postindex:
- // Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!}
- // by forcing P=0, W=0 (postindex=true).
- return arm_decodeArg(arm_arg_mem_R_pm_R_shift_imm_W, x&^(1<<24|1<<21))
-
- case arm_arg_mem_R_pm_R_shift_imm_W:
- Rn := arm_Reg((x >> 16) & (1<<4 - 1))
- Rm := arm_Reg(x & (1<<4 - 1))
- typ, count := arm_decodeShift(x)
- u := (x >> 23) & 1
- w := (x >> 21) & 1
- p := (x >> 24) & 1
- if p == 0 && w == 1 {
- return nil
- }
- sign := int8(+1)
- if u == 0 {
- sign = -1
- }
- mode := arm_AddrMode(uint8(p<<1) | uint8(w^1))
- return arm_Mem{Base: Rn, Mode: mode, Sign: sign, Index: Rm, Shift: typ, Count: count}
-
- case arm_arg_mem_R_pm_imm12_offset:
- // Treat [<Rn>,#+/-<imm12>] like [<Rn>{,#+/-<imm12>}]{!}
- // by forcing P=1, W=0 (index=false, wback=false).
- return arm_decodeArg(arm_arg_mem_R_pm_imm12_W, x&^(1<<21)|1<<24)
-
- case arm_arg_mem_R_pm_imm12_postindex:
- // Treat [<Rn>],#+/-<imm12> like [<Rn>{,#+/-<imm12>}]{!}
- // by forcing P=0, W=0 (postindex=true).
- return arm_decodeArg(arm_arg_mem_R_pm_imm12_W, x&^(1<<24|1<<21))
-
- case arm_arg_mem_R_pm_imm12_W:
- Rn := arm_Reg((x >> 16) & (1<<4 - 1))
- u := (x >> 23) & 1
- w := (x >> 21) & 1
- p := (x >> 24) & 1
- if p == 0 && w == 1 {
- return nil
- }
- sign := int8(+1)
- if u == 0 {
- sign = -1
- }
- imm := int16(x & (1<<12 - 1))
- mode := arm_AddrMode(uint8(p<<1) | uint8(w^1))
- return arm_Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm}
-
- case arm_arg_mem_R_pm_imm8_postindex:
- // Treat [<Rn>],#+/-<imm8> like [<Rn>{,#+/-<imm8>}]{!}
- // by forcing P=0, W=0 (postindex=true).
- return arm_decodeArg(arm_arg_mem_R_pm_imm8_W, x&^(1<<24|1<<21))
-
- case arm_arg_mem_R_pm_imm8_W:
- Rn := arm_Reg((x >> 16) & (1<<4 - 1))
- u := (x >> 23) & 1
- w := (x >> 21) & 1
- p := (x >> 24) & 1
- if p == 0 && w == 1 {
- return nil
- }
- sign := int8(+1)
- if u == 0 {
- sign = -1
- }
- imm := int16((x>>8)&(1<<4-1)<<4 | x&(1<<4-1))
- mode := arm_AddrMode(uint8(p<<1) | uint8(w^1))
- return arm_Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm}
-
- case arm_arg_mem_R_pm_imm8at0_offset:
- Rn := arm_Reg((x >> 16) & (1<<4 - 1))
- u := (x >> 23) & 1
- sign := int8(+1)
- if u == 0 {
- sign = -1
- }
- imm := int16(x&(1<<8-1)) << 2
- return arm_Mem{Base: Rn, Mode: arm_AddrOffset, Offset: int16(sign) * imm}
-
- case arm_arg_option:
- return arm_Imm(x & (1<<4 - 1))
-
- case arm_arg_registers:
- return arm_RegList(x & (1<<16 - 1))
-
- case arm_arg_registers2:
- x &= 1<<16 - 1
- n := 0
- for i := 0; i < 16; i++ {
- if x>>uint(i)&1 != 0 {
- n++
- }
- }
- if n < 2 {
- return nil
- }
- return arm_RegList(x)
-
- case arm_arg_registers1:
- Rt := (x >> 12) & (1<<4 - 1)
- return arm_RegList(1 << Rt)
-
- case arm_arg_satimm4:
- return arm_Imm((x >> 16) & (1<<4 - 1))
-
- case arm_arg_satimm5:
- return arm_Imm((x >> 16) & (1<<5 - 1))
-
- case arm_arg_satimm4m1:
- return arm_Imm((x>>16)&(1<<4-1) + 1)
-
- case arm_arg_satimm5m1:
- return arm_Imm((x>>16)&(1<<5-1) + 1)
-
- case arm_arg_widthm1:
- return arm_Imm((x>>16)&(1<<5-1) + 1)
-
- }
-}
-
-// decodeShift decodes the shift-by-immediate encoded in x.
-func arm_decodeShift(x uint32) (arm_Shift, uint8) {
- count := (x >> 7) & (1<<5 - 1)
- typ := arm_Shift((x >> 5) & (1<<2 - 1))
- switch typ {
- case arm_ShiftRight, arm_ShiftRightSigned:
- if count == 0 {
- count = 32
- }
- case arm_RotateRight:
- if count == 0 {
- typ = arm_RotateRightExt
- count = 1
- }
- }
- return typ, uint8(count)
-}
-
-/* gnu.go */
-
-// 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.
-
-var arm_saveDot = strings.NewReplacer(
- ".F16", "_dot_F16",
- ".F32", "_dot_F32",
- ".F64", "_dot_F64",
- ".S32", "_dot_S32",
- ".U32", "_dot_U32",
- ".FXS", "_dot_S",
- ".FXU", "_dot_U",
- ".32", "_dot_32",
-)
-
-// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
-// This form typically matches the syntax defined in the ARM Reference Manual.
-func arm_GNUSyntax(inst arm_Inst) string {
- var buf bytes.Buffer
- op := inst.Op.String()
- op = arm_saveDot.Replace(op)
- op = strings.Replace(op, ".", "", -1)
- op = strings.Replace(op, "_dot_", ".", -1)
- op = strings.ToLower(op)
- buf.WriteString(op)
- sep := " "
- for i, arg := range inst.Args {
- if arg == nil {
- break
- }
- text := arm_gnuArg(&inst, i, arg)
- if text == "" {
- continue
- }
- buf.WriteString(sep)
- sep = ", "
- buf.WriteString(text)
- }
- return buf.String()
-}
-
-func arm_gnuArg(inst *arm_Inst, argIndex int, arg arm_Arg) string {
- switch inst.Op &^ 15 {
- case arm_LDRD_EQ, arm_LDREXD_EQ, arm_STRD_EQ:
- if argIndex == 1 {
- // second argument in consecutive pair not printed
- return ""
- }
- case arm_STREXD_EQ:
- if argIndex == 2 {
- // second argument in consecutive pair not printed
- return ""
- }
- }
-
- switch arg := arg.(type) {
- case arm_Imm:
- switch inst.Op &^ 15 {
- case arm_BKPT_EQ:
- return fmt.Sprintf("%#04x", uint32(arg))
- case arm_SVC_EQ:
- return fmt.Sprintf("%#08x", uint32(arg))
- }
- return fmt.Sprintf("#%d", int32(arg))
-
- case arm_ImmAlt:
- return fmt.Sprintf("#%d, %d", arg.Val, arg.Rot)
-
- case arm_Mem:
- R := arm_gnuArg(inst, -1, arg.Base)
- X := ""
- if arg.Sign != 0 {
- X = ""
- if arg.Sign < 0 {
- X = "-"
- }
- X += arm_gnuArg(inst, -1, arg.Index)
- if arg.Shift == arm_ShiftLeft && arg.Count == 0 {
- // nothing
- } else if arg.Shift == arm_RotateRightExt {
- X += ", rrx"
- } else {
- X += fmt.Sprintf(", %s #%d", strings.ToLower(arg.Shift.String()), arg.Count)
- }
- } else {
- X = fmt.Sprintf("#%d", arg.Offset)
- }
-
- switch arg.Mode {
- case arm_AddrOffset:
- if X == "#0" {
- return fmt.Sprintf("[%s]", R)
- }
- return fmt.Sprintf("[%s, %s]", R, X)
- case arm_AddrPreIndex:
- return fmt.Sprintf("[%s, %s]!", R, X)
- case arm_AddrPostIndex:
- return fmt.Sprintf("[%s], %s", R, X)
- case arm_AddrLDM:
- if X == "#0" {
- return R
- }
- case arm_AddrLDM_WB:
- if X == "#0" {
- return R + "!"
- }
- }
- return fmt.Sprintf("[%s Mode(%d) %s]", R, int(arg.Mode), X)
-
- case arm_PCRel:
- return fmt.Sprintf(".%+#x", int32(arg)+4)
-
- case arm_Reg:
- switch inst.Op &^ 15 {
- case arm_LDREX_EQ:
- if argIndex == 0 {
- return fmt.Sprintf("r%d", int32(arg))
- }
- }
- switch arg {
- case arm_R10:
- return "sl"
- case arm_R11:
- return "fp"
- case arm_R12:
- return "ip"
- }
-
- case arm_RegList:
- var buf bytes.Buffer
- fmt.Fprintf(&buf, "{")
- sep := ""
- for i := 0; i < 16; i++ {
- if arg&(1<<uint(i)) != 0 {
- fmt.Fprintf(&buf, "%s%s", sep, arm_gnuArg(inst, -1, arm_Reg(i)))
- sep = ", "
- }
- }
- fmt.Fprintf(&buf, "}")
- return buf.String()
-
- case arm_RegShift:
- if arg.Shift == arm_ShiftLeft && arg.Count == 0 {
- return arm_gnuArg(inst, -1, arg.Reg)
- }
- if arg.Shift == arm_RotateRightExt {
- return arm_gnuArg(inst, -1, arg.Reg) + ", rrx"
- }
- return fmt.Sprintf("%s, %s #%d", arm_gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), arg.Count)
-
- case arm_RegShiftReg:
- return fmt.Sprintf("%s, %s %s", arm_gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), arm_gnuArg(inst, -1, arg.RegCount))
-
- }
- return strings.ToLower(arg.String())
-}
-
-/* inst.go */
-
-// 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.
-
-// A Mode is an instruction execution mode.
-type arm_Mode int
-
-const (
- _ arm_Mode = iota
- arm_ModeARM
- arm_ModeThumb
-)
-
-func (m arm_Mode) String() string {
- switch m {
- case arm_ModeARM:
- return "ARM"
- case arm_ModeThumb:
- return "Thumb"
- }
- return fmt.Sprintf("Mode(%d)", int(m))
-}
-
-// An Op is an ARM opcode.
-type arm_Op uint16
-
-// NOTE: The actual Op values are defined in tables.go.
-// They are chosen to simplify instruction decoding and
-// are not a dense packing from 0 to N, although the
-// density is high, probably at least 90%.
-
-func (op arm_Op) String() string {
- if op >= arm_Op(len(arm_opstr)) || arm_opstr[op] == "" {
- return fmt.Sprintf("Op(%d)", int(op))
- }
- return arm_opstr[op]
-}
-
-// An Inst is a single instruction.
-type arm_Inst struct {
- Op arm_Op // Opcode mnemonic
- Enc uint32 // Raw encoding bits.
- Len int // Length of encoding in bytes.
- Args arm_Args // Instruction arguments, in ARM manual order.
-}
-
-func (i arm_Inst) String() string {
- var buf bytes.Buffer
- buf.WriteString(i.Op.String())
- for j, arg := range i.Args {
- if arg == nil {
- break
- }
- if j == 0 {
- buf.WriteString(" ")
- } else {
- buf.WriteString(", ")
- }
- buf.WriteString(arg.String())
- }
- return buf.String()
-}
-
-// An Args holds the instruction arguments.
-// If an instruction has fewer than 4 arguments,
-// the final elements in the array are nil.
-type arm_Args [4]arm_Arg
-
-// An Arg is a single instruction argument, one of these types:
-// Endian, Imm, Mem, PCRel, Reg, RegList, RegShift, RegShiftReg.
-type arm_Arg interface {
- IsArg()
- String() string
-}
-
-type arm_Float32Imm float32
-
-func (arm_Float32Imm) IsArg() {}
-
-func (f arm_Float32Imm) String() string {
- return fmt.Sprintf("#%v", float32(f))
-}
-
-type arm_Float64Imm float32
-
-func (arm_Float64Imm) IsArg() {}
-
-func (f arm_Float64Imm) String() string {
- return fmt.Sprintf("#%v", float64(f))
-}
-
-// An Imm is an integer constant.
-type arm_Imm uint32
-
-func (arm_Imm) IsArg() {}
-
-func (i arm_Imm) String() string {
- return fmt.Sprintf("#%#x", uint32(i))
-}
-
-// A ImmAlt is an alternate encoding of an integer constant.
-type arm_ImmAlt struct {
- Val uint8
- Rot uint8
-}
-
-func (arm_ImmAlt) IsArg() {}
-
-func (i arm_ImmAlt) Imm() arm_Imm {
- v := uint32(i.Val)
- r := uint(i.Rot)
- return arm_Imm(v>>r | v<<(32-r))
-}
-
-func (i arm_ImmAlt) String() string {
- return fmt.Sprintf("#%#x, %d", i.Val, i.Rot)
-}
-
-// A Label is a text (code) address.
-type arm_Label uint32
-
-func (arm_Label) IsArg() {}
-
-func (i arm_Label) String() string {
- return fmt.Sprintf("%#x", uint32(i))
-}
-
-// A Reg is a single register.
-// The zero value denotes R0, not the absence of a register.
-type arm_Reg uint8
-
-const (
- arm_R0 arm_Reg = iota
- arm_R1
- arm_R2
- arm_R3
- arm_R4
- arm_R5
- arm_R6
- arm_R7
- arm_R8
- arm_R9
- arm_R10
- arm_R11
- arm_R12
- arm_R13
- arm_R14
- arm_R15
-
- arm_S0
- arm_S1
- arm_S2
- arm_S3
- arm_S4
- arm_S5
- arm_S6
- arm_S7
- arm_S8
- arm_S9
- arm_S10
- arm_S11
- arm_S12
- arm_S13
- arm_S14
- arm_S15
- arm_S16
- arm_S17
- arm_S18
- arm_S19
- arm_S20
- arm_S21
- arm_S22
- arm_S23
- arm_S24
- arm_S25
- arm_S26
- arm_S27
- arm_S28
- arm_S29
- arm_S30
- arm_S31
-
- arm_D0
- arm_D1
- arm_D2
- arm_D3
- arm_D4
- arm_D5
- arm_D6
- arm_D7
- arm_D8
- arm_D9
- arm_D10
- arm_D11
- arm_D12
- arm_D13
- arm_D14
- arm_D15
- arm_D16
- arm_D17
- arm_D18
- arm_D19
- arm_D20
- arm_D21
- arm_D22
- arm_D23
- arm_D24
- arm_D25
- arm_D26
- arm_D27
- arm_D28
- arm_D29
- arm_D30
- arm_D31
-
- arm_APSR
- arm_APSR_nzcv
- arm_FPSCR
-
- arm_SP = arm_R13
- arm_LR = arm_R14
- arm_PC = arm_R15
-)
-
-func (arm_Reg) IsArg() {}
-
-func (r arm_Reg) String() string {
- switch r {
- case arm_APSR:
- return "APSR"
- case arm_APSR_nzcv:
- return "APSR_nzcv"
- case arm_FPSCR:
- return "FPSCR"
- case arm_SP:
- return "SP"
- case arm_PC:
- return "PC"
- case arm_LR:
- return "LR"
- }
- if arm_R0 <= r && r <= arm_R15 {
- return fmt.Sprintf("R%d", int(r-arm_R0))
- }
- if arm_S0 <= r && r <= arm_S31 {
- return fmt.Sprintf("S%d", int(r-arm_S0))
- }
- if arm_D0 <= r && r <= arm_D31 {
- return fmt.Sprintf("D%d", int(r-arm_D0))
- }
- return fmt.Sprintf("Reg(%d)", int(r))
-}
-
-// A RegX represents a fraction of a multi-value register.
-// The Index field specifies the index number,
-// but the size of the fraction is not specified.
-// It must be inferred from the instruction and the register type.
-// For example, in a VMOV instruction, RegX{D5, 1} represents
-// the top 32 bits of the 64-bit D5 register.
-type arm_RegX struct {
- Reg arm_Reg
- Index int
-}
-
-func (arm_RegX) IsArg() {}
-
-func (r arm_RegX) String() string {
- return fmt.Sprintf("%s[%d]", r.Reg, r.Index)
-}
-
-// A RegList is a register list.
-// Bits at indexes x = 0 through 15 indicate whether the corresponding Rx register is in the list.
-type arm_RegList uint16
-
-func (arm_RegList) IsArg() {}
-
-func (r arm_RegList) String() string {
- var buf bytes.Buffer
- fmt.Fprintf(&buf, "{")
- sep := ""
- for i := 0; i < 16; i++ {
- if r&(1<<uint(i)) != 0 {
- fmt.Fprintf(&buf, "%s%s", sep, arm_Reg(i).String())
- sep = ","
- }
- }
- fmt.Fprintf(&buf, "}")
- return buf.String()
-}
-
-// An Endian is the argument to the SETEND instruction.
-type arm_Endian uint8
-
-const (
- arm_LittleEndian arm_Endian = 0
- arm_BigEndian arm_Endian = 1
-)
-
-func (arm_Endian) IsArg() {}
-
-func (e arm_Endian) String() string {
- if e != 0 {
- return "BE"
- }
- return "LE"
-}
-
-// A Shift describes an ARM shift operation.
-type arm_Shift uint8
-
-const (
- arm_ShiftLeft arm_Shift = 0 // left shift
- arm_ShiftRight arm_Shift = 1 // logical (unsigned) right shift
- arm_ShiftRightSigned arm_Shift = 2 // arithmetic (signed) right shift
- arm_RotateRight arm_Shift = 3 // right rotate
- arm_RotateRightExt arm_Shift = 4 // right rotate through carry (Count will always be 1)
-)
-
-var arm_shiftName = [...]string{
- "LSL", "LSR", "ASR", "ROR", "RRX",
-}
-
-func (s arm_Shift) String() string {
- if s < 5 {
- return arm_shiftName[s]
- }
- return fmt.Sprintf("Shift(%d)", int(s))
-}
-
-// A RegShift is a register shifted by a constant.
-type arm_RegShift struct {
- Reg arm_Reg
- Shift arm_Shift
- Count uint8
-}
-
-func (arm_RegShift) IsArg() {}
-
-func (r arm_RegShift) String() string {
- return fmt.Sprintf("%s %s #%d", r.Reg, r.Shift, r.Count)
-}
-
-// A RegShiftReg is a register shifted by a register.
-type arm_RegShiftReg struct {
- Reg arm_Reg
- Shift arm_Shift
- RegCount arm_Reg
-}
-
-func (arm_RegShiftReg) IsArg() {}
-
-func (r arm_RegShiftReg) String() string {
- return fmt.Sprintf("%s %s %s", r.Reg, r.Shift, r.RegCount)
-}
-
-// A PCRel describes a memory address (usually a code label)
-// as a distance relative to the program counter.
-// TODO(rsc): Define which program counter (PC+4? PC+8? PC?).
-type arm_PCRel int32
-
-func (arm_PCRel) IsArg() {}
-
-func (r arm_PCRel) String() string {
- return fmt.Sprintf("PC%+#x", int32(r))
-}
-
-// An AddrMode is an ARM addressing mode.
-type arm_AddrMode uint8
-
-const (
- _ arm_AddrMode = iota
- arm_AddrPostIndex // [R], X – use address R, set R = R + X
- arm_AddrPreIndex // [R, X]! – use address R + X, set R = R + X
- arm_AddrOffset // [R, X] – use address R + X
- arm_AddrLDM // R – [R] but formats as R, for LDM/STM only
- arm_AddrLDM_WB // R! - [R], X where X is instruction-specific amount, for LDM/STM only
-)
-
-// A Mem is a memory reference made up of a base R and index expression X.
-// The effective memory address is R or R+X depending on AddrMode.
-// The index expression is X = Sign*(Index Shift Count) + Offset,
-// but in any instruction either Sign = 0 or Offset = 0.
-type arm_Mem struct {
- Base arm_Reg
- Mode arm_AddrMode
- Sign int8
- Index arm_Reg
- Shift arm_Shift
- Count uint8
- Offset int16
-}
-
-func (arm_Mem) IsArg() {}
-
-func (m arm_Mem) String() string {
- R := m.Base.String()
- X := ""
- if m.Sign != 0 {
- X = "+"
- if m.Sign < 0 {
- X = "-"
- }
- X += m.Index.String()
- if m.Shift != arm_ShiftLeft || m.Count != 0 {
- X += fmt.Sprintf(", %s #%d", m.Shift, m.Count)
- }
- } else {
- X = fmt.Sprintf("#%d", m.Offset)
- }
-
- switch m.Mode {
- case arm_AddrOffset:
- if X == "#0" {
- return fmt.Sprintf("[%s]", R)
- }
- return fmt.Sprintf("[%s, %s]", R, X)
- case arm_AddrPreIndex:
- return fmt.Sprintf("[%s, %s]!", R, X)
- case arm_AddrPostIndex:
- return fmt.Sprintf("[%s], %s", R, X)
- case arm_AddrLDM:
- if X == "#0" {
- return R
- }
- case arm_AddrLDM_WB:
- if X == "#0" {
- return R + "!"
- }
- }
- return fmt.Sprintf("[%s Mode(%d) %s]", R, int(m.Mode), X)
-}
-
-/* plan9x.go */
-
-// 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.
-
-// 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 arm_plan9Syntax(inst arm_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, arm_plan9Arg(&inst, pc, symname, a))
- }
-
- op := inst.Op.String()
-
- switch inst.Op &^ 15 {
- case arm_LDR_EQ, arm_LDRB_EQ, arm_LDRH_EQ:
- // Check for RET
- reg, _ := inst.Args[0].(arm_Reg)
- mem, _ := inst.Args[1].(arm_Mem)
- if inst.Op&^15 == arm_LDR_EQ && reg == arm_R15 && mem.Base == arm_SP && mem.Sign == 0 && mem.Mode == arm_AddrPostIndex {
- return fmt.Sprintf("RET%s #%d", op[3:], mem.Offset)
- }
-
- // Check for PC-relative load.
- if mem.Base == arm_PC && mem.Sign == 0 && mem.Mode == arm_AddrOffset && text != nil {
- addr := uint32(pc) + 8 + uint32(mem.Offset)
- buf := make([]byte, 4)
- switch inst.Op &^ 15 {
- case arm_LDRB_EQ:
- if _, err := text.ReadAt(buf[:1], int64(addr)); err != nil {
- break
- }
- args[1] = fmt.Sprintf("$%#x", buf[0])
-
- case arm_LDRH_EQ:
- if _, err := text.ReadAt(buf[:2], int64(addr)); err != nil {
- break
- }
- args[1] = fmt.Sprintf("$%#x", binary.LittleEndian.Uint16(buf))
-
- case arm_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 arm_LDR_EQ, arm_LDRB_EQ, arm_LDRH_EQ, arm_STR_EQ, arm_STRB_EQ, arm_STRH_EQ:
- mem, _ := inst.Args[1].(arm_Mem)
- switch mem.Mode {
- case arm_AddrOffset, arm_AddrLDM:
- // no suffix
- case arm_AddrPreIndex, arm_AddrLDM_WB:
- suffix = ".W"
- case arm_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", arm_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 arm_MOV_EQ:
- op = "MOVW" + op[3:]
-
- case arm_LDR_EQ:
- op = "MOVW" + op[3:] + suffix
- case arm_LDRB_EQ:
- op = "MOVB" + op[4:] + suffix
- case arm_LDRH_EQ:
- op = "MOVH" + op[4:] + suffix
-
- case arm_STR_EQ:
- op = "MOVW" + op[3:] + suffix
- args[0], args[1] = args[1], args[0]
- case arm_STRB_EQ:
- op = "MOVB" + op[4:] + suffix
- args[0], args[1] = args[1], args[0]
- case arm_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 arm_plan9Shift = []string{"<<", ">>", "->", "@>", "@x>"}
-
-func arm_plan9Arg(inst *arm_Inst, pc uint64, symname func(uint64) (string, uint64), arg arm_Arg) string {
- switch a := arg.(type) {
- case arm_Endian:
-
- case arm_Imm:
- return fmt.Sprintf("$%d", int(a))
-
- case arm_Mem:
-
- case arm_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 arm_Reg:
- if a < 16 {
- return fmt.Sprintf("R%d", int(a))
- }
-
- case arm_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 arm_RegShift:
- return fmt.Sprintf("R%d%s$%d", int(a.Reg), arm_plan9Shift[a.Shift], int(a.Count))
-
- case arm_RegShiftReg:
- return fmt.Sprintf("R%d%sR%d", int(a.Reg), arm_plan9Shift[a.Shift], int(a.RegCount))
- }
- return strings.ToUpper(arg.String())
-}
-
-/* tables.go */
-
-const (
- _ arm_Op = iota
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- arm_ADC_EQ
- arm_ADC_NE
- arm_ADC_CS
- arm_ADC_CC
- arm_ADC_MI
- arm_ADC_PL
- arm_ADC_VS
- arm_ADC_VC
- arm_ADC_HI
- arm_ADC_LS
- arm_ADC_GE
- arm_ADC_LT
- arm_ADC_GT
- arm_ADC_LE
- arm_ADC
- arm_ADC_ZZ
- arm_ADC_S_EQ
- arm_ADC_S_NE
- arm_ADC_S_CS
- arm_ADC_S_CC
- arm_ADC_S_MI
- arm_ADC_S_PL
- arm_ADC_S_VS
- arm_ADC_S_VC
- arm_ADC_S_HI
- arm_ADC_S_LS
- arm_ADC_S_GE
- arm_ADC_S_LT
- arm_ADC_S_GT
- arm_ADC_S_LE
- arm_ADC_S
- arm_ADC_S_ZZ
- arm_ADD_EQ
- arm_ADD_NE
- arm_ADD_CS
- arm_ADD_CC
- arm_ADD_MI
- arm_ADD_PL
- arm_ADD_VS
- arm_ADD_VC
- arm_ADD_HI
- arm_ADD_LS
- arm_ADD_GE
- arm_ADD_LT
- arm_ADD_GT
- arm_ADD_LE
- arm_ADD
- arm_ADD_ZZ
- arm_ADD_S_EQ
- arm_ADD_S_NE
- arm_ADD_S_CS
- arm_ADD_S_CC
- arm_ADD_S_MI
- arm_ADD_S_PL
- arm_ADD_S_VS
- arm_ADD_S_VC
- arm_ADD_S_HI
- arm_ADD_S_LS
- arm_ADD_S_GE
- arm_ADD_S_LT
- arm_ADD_S_GT
- arm_ADD_S_LE
- arm_ADD_S
- arm_ADD_S_ZZ
- arm_AND_EQ
- arm_AND_NE
- arm_AND_CS
- arm_AND_CC
- arm_AND_MI
- arm_AND_PL
- arm_AND_VS
- arm_AND_VC
- arm_AND_HI
- arm_AND_LS
- arm_AND_GE
- arm_AND_LT
- arm_AND_GT
- arm_AND_LE
- arm_AND
- arm_AND_ZZ
- arm_AND_S_EQ
- arm_AND_S_NE
- arm_AND_S_CS
- arm_AND_S_CC
- arm_AND_S_MI
- arm_AND_S_PL
- arm_AND_S_VS
- arm_AND_S_VC
- arm_AND_S_HI
- arm_AND_S_LS
- arm_AND_S_GE
- arm_AND_S_LT
- arm_AND_S_GT
- arm_AND_S_LE
- arm_AND_S
- arm_AND_S_ZZ
- arm_ASR_EQ
- arm_ASR_NE
- arm_ASR_CS
- arm_ASR_CC
- arm_ASR_MI
- arm_ASR_PL
- arm_ASR_VS
- arm_ASR_VC
- arm_ASR_HI
- arm_ASR_LS
- arm_ASR_GE
- arm_ASR_LT
- arm_ASR_GT
- arm_ASR_LE
- arm_ASR
- arm_ASR_ZZ
- arm_ASR_S_EQ
- arm_ASR_S_NE
- arm_ASR_S_CS
- arm_ASR_S_CC
- arm_ASR_S_MI
- arm_ASR_S_PL
- arm_ASR_S_VS
- arm_ASR_S_VC
- arm_ASR_S_HI
- arm_ASR_S_LS
- arm_ASR_S_GE
- arm_ASR_S_LT
- arm_ASR_S_GT
- arm_ASR_S_LE
- arm_ASR_S
- arm_ASR_S_ZZ
- arm_B_EQ
- arm_B_NE
- arm_B_CS
- arm_B_CC
- arm_B_MI
- arm_B_PL
- arm_B_VS
- arm_B_VC
- arm_B_HI
- arm_B_LS
- arm_B_GE
- arm_B_LT
- arm_B_GT
- arm_B_LE
- arm_B
- arm_B_ZZ
- arm_BFC_EQ
- arm_BFC_NE
- arm_BFC_CS
- arm_BFC_CC
- arm_BFC_MI
- arm_BFC_PL
- arm_BFC_VS
- arm_BFC_VC
- arm_BFC_HI
- arm_BFC_LS
- arm_BFC_GE
- arm_BFC_LT
- arm_BFC_GT
- arm_BFC_LE
- arm_BFC
- arm_BFC_ZZ
- arm_BFI_EQ
- arm_BFI_NE
- arm_BFI_CS
- arm_BFI_CC
- arm_BFI_MI
- arm_BFI_PL
- arm_BFI_VS
- arm_BFI_VC
- arm_BFI_HI
- arm_BFI_LS
- arm_BFI_GE
- arm_BFI_LT
- arm_BFI_GT
- arm_BFI_LE
- arm_BFI
- arm_BFI_ZZ
- arm_BIC_EQ
- arm_BIC_NE
- arm_BIC_CS
- arm_BIC_CC
- arm_BIC_MI
- arm_BIC_PL
- arm_BIC_VS
- arm_BIC_VC
- arm_BIC_HI
- arm_BIC_LS
- arm_BIC_GE
- arm_BIC_LT
- arm_BIC_GT
- arm_BIC_LE
- arm_BIC
- arm_BIC_ZZ
- arm_BIC_S_EQ
- arm_BIC_S_NE
- arm_BIC_S_CS
- arm_BIC_S_CC
- arm_BIC_S_MI
- arm_BIC_S_PL
- arm_BIC_S_VS
- arm_BIC_S_VC
- arm_BIC_S_HI
- arm_BIC_S_LS
- arm_BIC_S_GE
- arm_BIC_S_LT
- arm_BIC_S_GT
- arm_BIC_S_LE
- arm_BIC_S
- arm_BIC_S_ZZ
- arm_BKPT_EQ
- arm_BKPT_NE
- arm_BKPT_CS
- arm_BKPT_CC
- arm_BKPT_MI
- arm_BKPT_PL
- arm_BKPT_VS
- arm_BKPT_VC
- arm_BKPT_HI
- arm_BKPT_LS
- arm_BKPT_GE
- arm_BKPT_LT
- arm_BKPT_GT
- arm_BKPT_LE
- arm_BKPT
- arm_BKPT_ZZ
- arm_BL_EQ
- arm_BL_NE
- arm_BL_CS
- arm_BL_CC
- arm_BL_MI
- arm_BL_PL
- arm_BL_VS
- arm_BL_VC
- arm_BL_HI
- arm_BL_LS
- arm_BL_GE
- arm_BL_LT
- arm_BL_GT
- arm_BL_LE
- arm_BL
- arm_BL_ZZ
- arm_BLX_EQ
- arm_BLX_NE
- arm_BLX_CS
- arm_BLX_CC
- arm_BLX_MI
- arm_BLX_PL
- arm_BLX_VS
- arm_BLX_VC
- arm_BLX_HI
- arm_BLX_LS
- arm_BLX_GE
- arm_BLX_LT
- arm_BLX_GT
- arm_BLX_LE
- arm_BLX
- arm_BLX_ZZ
- arm_BX_EQ
- arm_BX_NE
- arm_BX_CS
- arm_BX_CC
- arm_BX_MI
- arm_BX_PL
- arm_BX_VS
- arm_BX_VC
- arm_BX_HI
- arm_BX_LS
- arm_BX_GE
- arm_BX_LT
- arm_BX_GT
- arm_BX_LE
- arm_BX
- arm_BX_ZZ
- arm_BXJ_EQ
- arm_BXJ_NE
- arm_BXJ_CS
- arm_BXJ_CC
- arm_BXJ_MI
- arm_BXJ_PL
- arm_BXJ_VS
- arm_BXJ_VC
- arm_BXJ_HI
- arm_BXJ_LS
- arm_BXJ_GE
- arm_BXJ_LT
- arm_BXJ_GT
- arm_BXJ_LE
- arm_BXJ
- arm_BXJ_ZZ
- arm_CLREX
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- arm_CLZ_EQ
- arm_CLZ_NE
- arm_CLZ_CS
- arm_CLZ_CC
- arm_CLZ_MI
- arm_CLZ_PL
- arm_CLZ_VS
- arm_CLZ_VC
- arm_CLZ_HI
- arm_CLZ_LS
- arm_CLZ_GE
- arm_CLZ_LT
- arm_CLZ_GT
- arm_CLZ_LE
- arm_CLZ
- arm_CLZ_ZZ
- arm_CMN_EQ
- arm_CMN_NE
- arm_CMN_CS
- arm_CMN_CC
- arm_CMN_MI
- arm_CMN_PL
- arm_CMN_VS
- arm_CMN_VC
- arm_CMN_HI
- arm_CMN_LS
- arm_CMN_GE
- arm_CMN_LT
- arm_CMN_GT
- arm_CMN_LE
- arm_CMN
- arm_CMN_ZZ
- arm_CMP_EQ
- arm_CMP_NE
- arm_CMP_CS
- arm_CMP_CC
- arm_CMP_MI
- arm_CMP_PL
- arm_CMP_VS
- arm_CMP_VC
- arm_CMP_HI
- arm_CMP_LS
- arm_CMP_GE
- arm_CMP_LT
- arm_CMP_GT
- arm_CMP_LE
- arm_CMP
- arm_CMP_ZZ
- arm_DBG_EQ
- arm_DBG_NE
- arm_DBG_CS
- arm_DBG_CC
- arm_DBG_MI
- arm_DBG_PL
- arm_DBG_VS
- arm_DBG_VC
- arm_DBG_HI
- arm_DBG_LS
- arm_DBG_GE
- arm_DBG_LT
- arm_DBG_GT
- arm_DBG_LE
- arm_DBG
- arm_DBG_ZZ
- arm_DMB
- arm_DSB
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- arm_EOR_EQ
- arm_EOR_NE
- arm_EOR_CS
- arm_EOR_CC
- arm_EOR_MI
- arm_EOR_PL
- arm_EOR_VS
- arm_EOR_VC
- arm_EOR_HI
- arm_EOR_LS
- arm_EOR_GE
- arm_EOR_LT
- arm_EOR_GT
- arm_EOR_LE
- arm_EOR
- arm_EOR_ZZ
- arm_EOR_S_EQ
- arm_EOR_S_NE
- arm_EOR_S_CS
- arm_EOR_S_CC
- arm_EOR_S_MI
- arm_EOR_S_PL
- arm_EOR_S_VS
- arm_EOR_S_VC
- arm_EOR_S_HI
- arm_EOR_S_LS
- arm_EOR_S_GE
- arm_EOR_S_LT
- arm_EOR_S_GT
- arm_EOR_S_LE
- arm_EOR_S
- arm_EOR_S_ZZ
- arm_ISB
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- arm_LDM_EQ
- arm_LDM_NE
- arm_LDM_CS
- arm_LDM_CC
- arm_LDM_MI
- arm_LDM_PL
- arm_LDM_VS
- arm_LDM_VC
- arm_LDM_HI
- arm_LDM_LS
- arm_LDM_GE
- arm_LDM_LT
- arm_LDM_GT
- arm_LDM_LE
- arm_LDM
- arm_LDM_ZZ
- arm_LDMDA_EQ
- arm_LDMDA_NE
- arm_LDMDA_CS
- arm_LDMDA_CC
- arm_LDMDA_MI
- arm_LDMDA_PL
- arm_LDMDA_VS
- arm_LDMDA_VC
- arm_LDMDA_HI
- arm_LDMDA_LS
- arm_LDMDA_GE
- arm_LDMDA_LT
- arm_LDMDA_GT
- arm_LDMDA_LE
- arm_LDMDA
- arm_LDMDA_ZZ
- arm_LDMDB_EQ
- arm_LDMDB_NE
- arm_LDMDB_CS
- arm_LDMDB_CC
- arm_LDMDB_MI
- arm_LDMDB_PL
- arm_LDMDB_VS
- arm_LDMDB_VC
- arm_LDMDB_HI
- arm_LDMDB_LS
- arm_LDMDB_GE
- arm_LDMDB_LT
- arm_LDMDB_GT
- arm_LDMDB_LE
- arm_LDMDB
- arm_LDMDB_ZZ
- arm_LDMIB_EQ
- arm_LDMIB_NE
- arm_LDMIB_CS
- arm_LDMIB_CC
- arm_LDMIB_MI
- arm_LDMIB_PL
- arm_LDMIB_VS
- arm_LDMIB_VC
- arm_LDMIB_HI
- arm_LDMIB_LS
- arm_LDMIB_GE
- arm_LDMIB_LT
- arm_LDMIB_GT
- arm_LDMIB_LE
- arm_LDMIB
- arm_LDMIB_ZZ
- arm_LDR_EQ
- arm_LDR_NE
- arm_LDR_CS
- arm_LDR_CC
- arm_LDR_MI
- arm_LDR_PL
- arm_LDR_VS
- arm_LDR_VC
- arm_LDR_HI
- arm_LDR_LS
- arm_LDR_GE
- arm_LDR_LT
- arm_LDR_GT
- arm_LDR_LE
- arm_LDR
- arm_LDR_ZZ
- arm_LDRB_EQ
- arm_LDRB_NE
- arm_LDRB_CS
- arm_LDRB_CC
- arm_LDRB_MI
- arm_LDRB_PL
- arm_LDRB_VS
- arm_LDRB_VC
- arm_LDRB_HI
- arm_LDRB_LS
- arm_LDRB_GE
- arm_LDRB_LT
- arm_LDRB_GT
- arm_LDRB_LE
- arm_LDRB
- arm_LDRB_ZZ
- arm_LDRBT_EQ
- arm_LDRBT_NE
- arm_LDRBT_CS
- arm_LDRBT_CC
- arm_LDRBT_MI
- arm_LDRBT_PL
- arm_LDRBT_VS
- arm_LDRBT_VC
- arm_LDRBT_HI
- arm_LDRBT_LS
- arm_LDRBT_GE
- arm_LDRBT_LT
- arm_LDRBT_GT
- arm_LDRBT_LE
- arm_LDRBT
- arm_LDRBT_ZZ
- arm_LDRD_EQ
- arm_LDRD_NE
- arm_LDRD_CS
- arm_LDRD_CC
- arm_LDRD_MI
- arm_LDRD_PL
- arm_LDRD_VS
- arm_LDRD_VC
- arm_LDRD_HI
- arm_LDRD_LS
- arm_LDRD_GE
- arm_LDRD_LT
- arm_LDRD_GT
- arm_LDRD_LE
- arm_LDRD
- arm_LDRD_ZZ
- arm_LDREX_EQ
- arm_LDREX_NE
- arm_LDREX_CS
- arm_LDREX_CC
- arm_LDREX_MI
- arm_LDREX_PL
- arm_LDREX_VS
- arm_LDREX_VC
- arm_LDREX_HI
- arm_LDREX_LS
- arm_LDREX_GE
- arm_LDREX_LT
- arm_LDREX_GT
- arm_LDREX_LE
- arm_LDREX
- arm_LDREX_ZZ
- arm_LDREXB_EQ
- arm_LDREXB_NE
- arm_LDREXB_CS
- arm_LDREXB_CC
- arm_LDREXB_MI
- arm_LDREXB_PL
- arm_LDREXB_VS
- arm_LDREXB_VC
- arm_LDREXB_HI
- arm_LDREXB_LS
- arm_LDREXB_GE
- arm_LDREXB_LT
- arm_LDREXB_GT
- arm_LDREXB_LE
- arm_LDREXB
- arm_LDREXB_ZZ
- arm_LDREXD_EQ
- arm_LDREXD_NE
- arm_LDREXD_CS
- arm_LDREXD_CC
- arm_LDREXD_MI
- arm_LDREXD_PL
- arm_LDREXD_VS
- arm_LDREXD_VC
- arm_LDREXD_HI
- arm_LDREXD_LS
- arm_LDREXD_GE
- arm_LDREXD_LT
- arm_LDREXD_GT
- arm_LDREXD_LE
- arm_LDREXD
- arm_LDREXD_ZZ
- arm_LDREXH_EQ
- arm_LDREXH_NE
- arm_LDREXH_CS
- arm_LDREXH_CC
- arm_LDREXH_MI
- arm_LDREXH_PL
- arm_LDREXH_VS
- arm_LDREXH_VC
- arm_LDREXH_HI
- arm_LDREXH_LS
- arm_LDREXH_GE
- arm_LDREXH_LT
- arm_LDREXH_GT
- arm_LDREXH_LE
- arm_LDREXH
- arm_LDREXH_ZZ
- arm_LDRH_EQ
- arm_LDRH_NE
- arm_LDRH_CS
- arm_LDRH_CC
- arm_LDRH_MI
- arm_LDRH_PL
- arm_LDRH_VS
- arm_LDRH_VC
- arm_LDRH_HI
- arm_LDRH_LS
- arm_LDRH_GE
- arm_LDRH_LT
- arm_LDRH_GT
- arm_LDRH_LE
- arm_LDRH
- arm_LDRH_ZZ
- arm_LDRHT_EQ
- arm_LDRHT_NE
- arm_LDRHT_CS
- arm_LDRHT_CC
- arm_LDRHT_MI
- arm_LDRHT_PL
- arm_LDRHT_VS
- arm_LDRHT_VC
- arm_LDRHT_HI
- arm_LDRHT_LS
- arm_LDRHT_GE
- arm_LDRHT_LT
- arm_LDRHT_GT
- arm_LDRHT_LE
- arm_LDRHT
- arm_LDRHT_ZZ
- arm_LDRSB_EQ
- arm_LDRSB_NE
- arm_LDRSB_CS
- arm_LDRSB_CC
- arm_LDRSB_MI
- arm_LDRSB_PL
- arm_LDRSB_VS
- arm_LDRSB_VC
- arm_LDRSB_HI
- arm_LDRSB_LS
- arm_LDRSB_GE
- arm_LDRSB_LT
- arm_LDRSB_GT
- arm_LDRSB_LE
- arm_LDRSB
- arm_LDRSB_ZZ
- arm_LDRSBT_EQ
- arm_LDRSBT_NE
- arm_LDRSBT_CS
- arm_LDRSBT_CC
- arm_LDRSBT_MI
- arm_LDRSBT_PL
- arm_LDRSBT_VS
- arm_LDRSBT_VC
- arm_LDRSBT_HI
- arm_LDRSBT_LS
- arm_LDRSBT_GE
- arm_LDRSBT_LT
- arm_LDRSBT_GT
- arm_LDRSBT_LE
- arm_LDRSBT
- arm_LDRSBT_ZZ
- arm_LDRSH_EQ
- arm_LDRSH_NE
- arm_LDRSH_CS
- arm_LDRSH_CC
- arm_LDRSH_MI
- arm_LDRSH_PL
- arm_LDRSH_VS
- arm_LDRSH_VC
- arm_LDRSH_HI
- arm_LDRSH_LS
- arm_LDRSH_GE
- arm_LDRSH_LT
- arm_LDRSH_GT
- arm_LDRSH_LE
- arm_LDRSH
- arm_LDRSH_ZZ
- arm_LDRSHT_EQ
- arm_LDRSHT_NE
- arm_LDRSHT_CS
- arm_LDRSHT_CC
- arm_LDRSHT_MI
- arm_LDRSHT_PL
- arm_LDRSHT_VS
- arm_LDRSHT_VC
- arm_LDRSHT_HI
- arm_LDRSHT_LS
- arm_LDRSHT_GE
- arm_LDRSHT_LT
- arm_LDRSHT_GT
- arm_LDRSHT_LE
- arm_LDRSHT
- arm_LDRSHT_ZZ
- arm_LDRT_EQ
- arm_LDRT_NE
- arm_LDRT_CS
- arm_LDRT_CC
- arm_LDRT_MI
- arm_LDRT_PL
- arm_LDRT_VS
- arm_LDRT_VC
- arm_LDRT_HI
- arm_LDRT_LS
- arm_LDRT_GE
- arm_LDRT_LT
- arm_LDRT_GT
- arm_LDRT_LE
- arm_LDRT
- arm_LDRT_ZZ
- arm_LSL_EQ
- arm_LSL_NE
- arm_LSL_CS
- arm_LSL_CC
- arm_LSL_MI
- arm_LSL_PL
- arm_LSL_VS
- arm_LSL_VC
- arm_LSL_HI
- arm_LSL_LS
- arm_LSL_GE
- arm_LSL_LT
- arm_LSL_GT
- arm_LSL_LE
- arm_LSL
- arm_LSL_ZZ
- arm_LSL_S_EQ
- arm_LSL_S_NE
- arm_LSL_S_CS
- arm_LSL_S_CC
- arm_LSL_S_MI
- arm_LSL_S_PL
- arm_LSL_S_VS
- arm_LSL_S_VC
- arm_LSL_S_HI
- arm_LSL_S_LS
- arm_LSL_S_GE
- arm_LSL_S_LT
- arm_LSL_S_GT
- arm_LSL_S_LE
- arm_LSL_S
- arm_LSL_S_ZZ
- arm_LSR_EQ
- arm_LSR_NE
- arm_LSR_CS
- arm_LSR_CC
- arm_LSR_MI
- arm_LSR_PL
- arm_LSR_VS
- arm_LSR_VC
- arm_LSR_HI
- arm_LSR_LS
- arm_LSR_GE
- arm_LSR_LT
- arm_LSR_GT
- arm_LSR_LE
- arm_LSR
- arm_LSR_ZZ
- arm_LSR_S_EQ
- arm_LSR_S_NE
- arm_LSR_S_CS
- arm_LSR_S_CC
- arm_LSR_S_MI
- arm_LSR_S_PL
- arm_LSR_S_VS
- arm_LSR_S_VC
- arm_LSR_S_HI
- arm_LSR_S_LS
- arm_LSR_S_GE
- arm_LSR_S_LT
- arm_LSR_S_GT
- arm_LSR_S_LE
- arm_LSR_S
- arm_LSR_S_ZZ
- arm_MLA_EQ
- arm_MLA_NE
- arm_MLA_CS
- arm_MLA_CC
- arm_MLA_MI
- arm_MLA_PL
- arm_MLA_VS
- arm_MLA_VC
- arm_MLA_HI
- arm_MLA_LS
- arm_MLA_GE
- arm_MLA_LT
- arm_MLA_GT
- arm_MLA_LE
- arm_MLA
- arm_MLA_ZZ
- arm_MLA_S_EQ
- arm_MLA_S_NE
- arm_MLA_S_CS
- arm_MLA_S_CC
- arm_MLA_S_MI
- arm_MLA_S_PL
- arm_MLA_S_VS
- arm_MLA_S_VC
- arm_MLA_S_HI
- arm_MLA_S_LS
- arm_MLA_S_GE
- arm_MLA_S_LT
- arm_MLA_S_GT
- arm_MLA_S_LE
- arm_MLA_S
- arm_MLA_S_ZZ
- arm_MLS_EQ
- arm_MLS_NE
- arm_MLS_CS
- arm_MLS_CC
- arm_MLS_MI
- arm_MLS_PL
- arm_MLS_VS
- arm_MLS_VC
- arm_MLS_HI
- arm_MLS_LS
- arm_MLS_GE
- arm_MLS_LT
- arm_MLS_GT
- arm_MLS_LE
- arm_MLS
- arm_MLS_ZZ
- arm_MOV_EQ
- arm_MOV_NE
- arm_MOV_CS
- arm_MOV_CC
- arm_MOV_MI
- arm_MOV_PL
- arm_MOV_VS
- arm_MOV_VC
- arm_MOV_HI
- arm_MOV_LS
- arm_MOV_GE
- arm_MOV_LT
- arm_MOV_GT
- arm_MOV_LE
- arm_MOV
- arm_MOV_ZZ
- arm_MOV_S_EQ
- arm_MOV_S_NE
- arm_MOV_S_CS
- arm_MOV_S_CC
- arm_MOV_S_MI
- arm_MOV_S_PL
- arm_MOV_S_VS
- arm_MOV_S_VC
- arm_MOV_S_HI
- arm_MOV_S_LS
- arm_MOV_S_GE
- arm_MOV_S_LT
- arm_MOV_S_GT
- arm_MOV_S_LE
- arm_MOV_S
- arm_MOV_S_ZZ
- arm_MOVT_EQ
- arm_MOVT_NE
- arm_MOVT_CS
- arm_MOVT_CC
- arm_MOVT_MI
- arm_MOVT_PL
- arm_MOVT_VS
- arm_MOVT_VC
- arm_MOVT_HI
- arm_MOVT_LS
- arm_MOVT_GE
- arm_MOVT_LT
- arm_MOVT_GT
- arm_MOVT_LE
- arm_MOVT
- arm_MOVT_ZZ
- arm_MOVW_EQ
- arm_MOVW_NE
- arm_MOVW_CS
- arm_MOVW_CC
- arm_MOVW_MI
- arm_MOVW_PL
- arm_MOVW_VS
- arm_MOVW_VC
- arm_MOVW_HI
- arm_MOVW_LS
- arm_MOVW_GE
- arm_MOVW_LT
- arm_MOVW_GT
- arm_MOVW_LE
- arm_MOVW
- arm_MOVW_ZZ
- arm_MRS_EQ
- arm_MRS_NE
- arm_MRS_CS
- arm_MRS_CC
- arm_MRS_MI
- arm_MRS_PL
- arm_MRS_VS
- arm_MRS_VC
- arm_MRS_HI
- arm_MRS_LS
- arm_MRS_GE
- arm_MRS_LT
- arm_MRS_GT
- arm_MRS_LE
- arm_MRS
- arm_MRS_ZZ
- arm_MUL_EQ
- arm_MUL_NE
- arm_MUL_CS
- arm_MUL_CC
- arm_MUL_MI
- arm_MUL_PL
- arm_MUL_VS
- arm_MUL_VC
- arm_MUL_HI
- arm_MUL_LS
- arm_MUL_GE
- arm_MUL_LT
- arm_MUL_GT
- arm_MUL_LE
- arm_MUL
- arm_MUL_ZZ
- arm_MUL_S_EQ
- arm_MUL_S_NE
- arm_MUL_S_CS
- arm_MUL_S_CC
- arm_MUL_S_MI
- arm_MUL_S_PL
- arm_MUL_S_VS
- arm_MUL_S_VC
- arm_MUL_S_HI
- arm_MUL_S_LS
- arm_MUL_S_GE
- arm_MUL_S_LT
- arm_MUL_S_GT
- arm_MUL_S_LE
- arm_MUL_S
- arm_MUL_S_ZZ
- arm_MVN_EQ
- arm_MVN_NE
- arm_MVN_CS
- arm_MVN_CC
- arm_MVN_MI
- arm_MVN_PL
- arm_MVN_VS
- arm_MVN_VC
- arm_MVN_HI
- arm_MVN_LS
- arm_MVN_GE
- arm_MVN_LT
- arm_MVN_GT
- arm_MVN_LE
- arm_MVN
- arm_MVN_ZZ
- arm_MVN_S_EQ
- arm_MVN_S_NE
- arm_MVN_S_CS
- arm_MVN_S_CC
- arm_MVN_S_MI
- arm_MVN_S_PL
- arm_MVN_S_VS
- arm_MVN_S_VC
- arm_MVN_S_HI
- arm_MVN_S_LS
- arm_MVN_S_GE
- arm_MVN_S_LT
- arm_MVN_S_GT
- arm_MVN_S_LE
- arm_MVN_S
- arm_MVN_S_ZZ
- arm_NOP_EQ
- arm_NOP_NE
- arm_NOP_CS
- arm_NOP_CC
- arm_NOP_MI
- arm_NOP_PL
- arm_NOP_VS
- arm_NOP_VC
- arm_NOP_HI
- arm_NOP_LS
- arm_NOP_GE
- arm_NOP_LT
- arm_NOP_GT
- arm_NOP_LE
- arm_NOP
- arm_NOP_ZZ
- arm_ORR_EQ
- arm_ORR_NE
- arm_ORR_CS
- arm_ORR_CC
- arm_ORR_MI
- arm_ORR_PL
- arm_ORR_VS
- arm_ORR_VC
- arm_ORR_HI
- arm_ORR_LS
- arm_ORR_GE
- arm_ORR_LT
- arm_ORR_GT
- arm_ORR_LE
- arm_ORR
- arm_ORR_ZZ
- arm_ORR_S_EQ
- arm_ORR_S_NE
- arm_ORR_S_CS
- arm_ORR_S_CC
- arm_ORR_S_MI
- arm_ORR_S_PL
- arm_ORR_S_VS
- arm_ORR_S_VC
- arm_ORR_S_HI
- arm_ORR_S_LS
- arm_ORR_S_GE
- arm_ORR_S_LT
- arm_ORR_S_GT
- arm_ORR_S_LE
- arm_ORR_S
- arm_ORR_S_ZZ
- arm_PKHBT_EQ
- arm_PKHBT_NE
- arm_PKHBT_CS
- arm_PKHBT_CC
- arm_PKHBT_MI
- arm_PKHBT_PL
- arm_PKHBT_VS
- arm_PKHBT_VC
- arm_PKHBT_HI
- arm_PKHBT_LS
- arm_PKHBT_GE
- arm_PKHBT_LT
- arm_PKHBT_GT
- arm_PKHBT_LE
- arm_PKHBT
- arm_PKHBT_ZZ
- arm_PKHTB_EQ
- arm_PKHTB_NE
- arm_PKHTB_CS
- arm_PKHTB_CC
- arm_PKHTB_MI
- arm_PKHTB_PL
- arm_PKHTB_VS
- arm_PKHTB_VC
- arm_PKHTB_HI
- arm_PKHTB_LS
- arm_PKHTB_GE
- arm_PKHTB_LT
- arm_PKHTB_GT
- arm_PKHTB_LE
- arm_PKHTB
- arm_PKHTB_ZZ
- arm_PLD_W
- arm_PLD
- arm_PLI
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- arm_POP_EQ
- arm_POP_NE
- arm_POP_CS
- arm_POP_CC
- arm_POP_MI
- arm_POP_PL
- arm_POP_VS
- arm_POP_VC
- arm_POP_HI
- arm_POP_LS
- arm_POP_GE
- arm_POP_LT
- arm_POP_GT
- arm_POP_LE
- arm_POP
- arm_POP_ZZ
- arm_PUSH_EQ
- arm_PUSH_NE
- arm_PUSH_CS
- arm_PUSH_CC
- arm_PUSH_MI
- arm_PUSH_PL
- arm_PUSH_VS
- arm_PUSH_VC
- arm_PUSH_HI
- arm_PUSH_LS
- arm_PUSH_GE
- arm_PUSH_LT
- arm_PUSH_GT
- arm_PUSH_LE
- arm_PUSH
- arm_PUSH_ZZ
- arm_QADD_EQ
- arm_QADD_NE
- arm_QADD_CS
- arm_QADD_CC
- arm_QADD_MI
- arm_QADD_PL
- arm_QADD_VS
- arm_QADD_VC
- arm_QADD_HI
- arm_QADD_LS
- arm_QADD_GE
- arm_QADD_LT
- arm_QADD_GT
- arm_QADD_LE
- arm_QADD
- arm_QADD_ZZ
- arm_QADD16_EQ
- arm_QADD16_NE
- arm_QADD16_CS
- arm_QADD16_CC
- arm_QADD16_MI
- arm_QADD16_PL
- arm_QADD16_VS
- arm_QADD16_VC
- arm_QADD16_HI
- arm_QADD16_LS
- arm_QADD16_GE
- arm_QADD16_LT
- arm_QADD16_GT
- arm_QADD16_LE
- arm_QADD16
- arm_QADD16_ZZ
- arm_QADD8_EQ
- arm_QADD8_NE
- arm_QADD8_CS
- arm_QADD8_CC
- arm_QADD8_MI
- arm_QADD8_PL
- arm_QADD8_VS
- arm_QADD8_VC
- arm_QADD8_HI
- arm_QADD8_LS
- arm_QADD8_GE
- arm_QADD8_LT
- arm_QADD8_GT
- arm_QADD8_LE
- arm_QADD8
- arm_QADD8_ZZ
- arm_QASX_EQ
- arm_QASX_NE
- arm_QASX_CS
- arm_QASX_CC
- arm_QASX_MI
- arm_QASX_PL
- arm_QASX_VS
- arm_QASX_VC
- arm_QASX_HI
- arm_QASX_LS
- arm_QASX_GE
- arm_QASX_LT
- arm_QASX_GT
- arm_QASX_LE
- arm_QASX
- arm_QASX_ZZ
- arm_QDADD_EQ
- arm_QDADD_NE
- arm_QDADD_CS
- arm_QDADD_CC
- arm_QDADD_MI
- arm_QDADD_PL
- arm_QDADD_VS
- arm_QDADD_VC
- arm_QDADD_HI
- arm_QDADD_LS
- arm_QDADD_GE
- arm_QDADD_LT
- arm_QDADD_GT
- arm_QDADD_LE
- arm_QDADD
- arm_QDADD_ZZ
- arm_QDSUB_EQ
- arm_QDSUB_NE
- arm_QDSUB_CS
- arm_QDSUB_CC
- arm_QDSUB_MI
- arm_QDSUB_PL
- arm_QDSUB_VS
- arm_QDSUB_VC
- arm_QDSUB_HI
- arm_QDSUB_LS
- arm_QDSUB_GE
- arm_QDSUB_LT
- arm_QDSUB_GT
- arm_QDSUB_LE
- arm_QDSUB
- arm_QDSUB_ZZ
- arm_QSAX_EQ
- arm_QSAX_NE
- arm_QSAX_CS
- arm_QSAX_CC
- arm_QSAX_MI
- arm_QSAX_PL
- arm_QSAX_VS
- arm_QSAX_VC
- arm_QSAX_HI
- arm_QSAX_LS
- arm_QSAX_GE
- arm_QSAX_LT
- arm_QSAX_GT
- arm_QSAX_LE
- arm_QSAX
- arm_QSAX_ZZ
- arm_QSUB_EQ
- arm_QSUB_NE
- arm_QSUB_CS
- arm_QSUB_CC
- arm_QSUB_MI
- arm_QSUB_PL
- arm_QSUB_VS
- arm_QSUB_VC
- arm_QSUB_HI
- arm_QSUB_LS
- arm_QSUB_GE
- arm_QSUB_LT
- arm_QSUB_GT
- arm_QSUB_LE
- arm_QSUB
- arm_QSUB_ZZ
- arm_QSUB16_EQ
- arm_QSUB16_NE
- arm_QSUB16_CS
- arm_QSUB16_CC
- arm_QSUB16_MI
- arm_QSUB16_PL
- arm_QSUB16_VS
- arm_QSUB16_VC
- arm_QSUB16_HI
- arm_QSUB16_LS
- arm_QSUB16_GE
- arm_QSUB16_LT
- arm_QSUB16_GT
- arm_QSUB16_LE
- arm_QSUB16
- arm_QSUB16_ZZ
- arm_QSUB8_EQ
- arm_QSUB8_NE
- arm_QSUB8_CS
- arm_QSUB8_CC
- arm_QSUB8_MI
- arm_QSUB8_PL
- arm_QSUB8_VS
- arm_QSUB8_VC
- arm_QSUB8_HI
- arm_QSUB8_LS
- arm_QSUB8_GE
- arm_QSUB8_LT
- arm_QSUB8_GT
- arm_QSUB8_LE
- arm_QSUB8
- arm_QSUB8_ZZ
- arm_RBIT_EQ
- arm_RBIT_NE
- arm_RBIT_CS
- arm_RBIT_CC
- arm_RBIT_MI
- arm_RBIT_PL
- arm_RBIT_VS
- arm_RBIT_VC
- arm_RBIT_HI
- arm_RBIT_LS
- arm_RBIT_GE
- arm_RBIT_LT
- arm_RBIT_GT
- arm_RBIT_LE
- arm_RBIT
- arm_RBIT_ZZ
- arm_REV_EQ
- arm_REV_NE
- arm_REV_CS
- arm_REV_CC
- arm_REV_MI
- arm_REV_PL
- arm_REV_VS
- arm_REV_VC
- arm_REV_HI
- arm_REV_LS
- arm_REV_GE
- arm_REV_LT
- arm_REV_GT
- arm_REV_LE
- arm_REV
- arm_REV_ZZ
- arm_REV16_EQ
- arm_REV16_NE
- arm_REV16_CS
- arm_REV16_CC
- arm_REV16_MI
- arm_REV16_PL
- arm_REV16_VS
- arm_REV16_VC
- arm_REV16_HI
- arm_REV16_LS
- arm_REV16_GE
- arm_REV16_LT
- arm_REV16_GT
- arm_REV16_LE
- arm_REV16
- arm_REV16_ZZ
- arm_REVSH_EQ
- arm_REVSH_NE
- arm_REVSH_CS
- arm_REVSH_CC
- arm_REVSH_MI
- arm_REVSH_PL
- arm_REVSH_VS
- arm_REVSH_VC
- arm_REVSH_HI
- arm_REVSH_LS
- arm_REVSH_GE
- arm_REVSH_LT
- arm_REVSH_GT
- arm_REVSH_LE
- arm_REVSH
- arm_REVSH_ZZ
- arm_ROR_EQ
- arm_ROR_NE
- arm_ROR_CS
- arm_ROR_CC
- arm_ROR_MI
- arm_ROR_PL
- arm_ROR_VS
- arm_ROR_VC
- arm_ROR_HI
- arm_ROR_LS
- arm_ROR_GE
- arm_ROR_LT
- arm_ROR_GT
- arm_ROR_LE
- arm_ROR
- arm_ROR_ZZ
- arm_ROR_S_EQ
- arm_ROR_S_NE
- arm_ROR_S_CS
- arm_ROR_S_CC
- arm_ROR_S_MI
- arm_ROR_S_PL
- arm_ROR_S_VS
- arm_ROR_S_VC
- arm_ROR_S_HI
- arm_ROR_S_LS
- arm_ROR_S_GE
- arm_ROR_S_LT
- arm_ROR_S_GT
- arm_ROR_S_LE
- arm_ROR_S
- arm_ROR_S_ZZ
- arm_RRX_EQ
- arm_RRX_NE
- arm_RRX_CS
- arm_RRX_CC
- arm_RRX_MI
- arm_RRX_PL
- arm_RRX_VS
- arm_RRX_VC
- arm_RRX_HI
- arm_RRX_LS
- arm_RRX_GE
- arm_RRX_LT
- arm_RRX_GT
- arm_RRX_LE
- arm_RRX
- arm_RRX_ZZ
- arm_RRX_S_EQ
- arm_RRX_S_NE
- arm_RRX_S_CS
- arm_RRX_S_CC
- arm_RRX_S_MI
- arm_RRX_S_PL
- arm_RRX_S_VS
- arm_RRX_S_VC
- arm_RRX_S_HI
- arm_RRX_S_LS
- arm_RRX_S_GE
- arm_RRX_S_LT
- arm_RRX_S_GT
- arm_RRX_S_LE
- arm_RRX_S
- arm_RRX_S_ZZ
- arm_RSB_EQ
- arm_RSB_NE
- arm_RSB_CS
- arm_RSB_CC
- arm_RSB_MI
- arm_RSB_PL
- arm_RSB_VS
- arm_RSB_VC
- arm_RSB_HI
- arm_RSB_LS
- arm_RSB_GE
- arm_RSB_LT
- arm_RSB_GT
- arm_RSB_LE
- arm_RSB
- arm_RSB_ZZ
- arm_RSB_S_EQ
- arm_RSB_S_NE
- arm_RSB_S_CS
- arm_RSB_S_CC
- arm_RSB_S_MI
- arm_RSB_S_PL
- arm_RSB_S_VS
- arm_RSB_S_VC
- arm_RSB_S_HI
- arm_RSB_S_LS
- arm_RSB_S_GE
- arm_RSB_S_LT
- arm_RSB_S_GT
- arm_RSB_S_LE
- arm_RSB_S
- arm_RSB_S_ZZ
- arm_RSC_EQ
- arm_RSC_NE
- arm_RSC_CS
- arm_RSC_CC
- arm_RSC_MI
- arm_RSC_PL
- arm_RSC_VS
- arm_RSC_VC
- arm_RSC_HI
- arm_RSC_LS
- arm_RSC_GE
- arm_RSC_LT
- arm_RSC_GT
- arm_RSC_LE
- arm_RSC
- arm_RSC_ZZ
- arm_RSC_S_EQ
- arm_RSC_S_NE
- arm_RSC_S_CS
- arm_RSC_S_CC
- arm_RSC_S_MI
- arm_RSC_S_PL
- arm_RSC_S_VS
- arm_RSC_S_VC
- arm_RSC_S_HI
- arm_RSC_S_LS
- arm_RSC_S_GE
- arm_RSC_S_LT
- arm_RSC_S_GT
- arm_RSC_S_LE
- arm_RSC_S
- arm_RSC_S_ZZ
- arm_SADD16_EQ
- arm_SADD16_NE
- arm_SADD16_CS
- arm_SADD16_CC
- arm_SADD16_MI
- arm_SADD16_PL
- arm_SADD16_VS
- arm_SADD16_VC
- arm_SADD16_HI
- arm_SADD16_LS
- arm_SADD16_GE
- arm_SADD16_LT
- arm_SADD16_GT
- arm_SADD16_LE
- arm_SADD16
- arm_SADD16_ZZ
- arm_SADD8_EQ
- arm_SADD8_NE
- arm_SADD8_CS
- arm_SADD8_CC
- arm_SADD8_MI
- arm_SADD8_PL
- arm_SADD8_VS
- arm_SADD8_VC
- arm_SADD8_HI
- arm_SADD8_LS
- arm_SADD8_GE
- arm_SADD8_LT
- arm_SADD8_GT
- arm_SADD8_LE
- arm_SADD8
- arm_SADD8_ZZ
- arm_SASX_EQ
- arm_SASX_NE
- arm_SASX_CS
- arm_SASX_CC
- arm_SASX_MI
- arm_SASX_PL
- arm_SASX_VS
- arm_SASX_VC
- arm_SASX_HI
- arm_SASX_LS
- arm_SASX_GE
- arm_SASX_LT
- arm_SASX_GT
- arm_SASX_LE
- arm_SASX
- arm_SASX_ZZ
- arm_SBC_EQ
- arm_SBC_NE
- arm_SBC_CS
- arm_SBC_CC
- arm_SBC_MI
- arm_SBC_PL
- arm_SBC_VS
- arm_SBC_VC
- arm_SBC_HI
- arm_SBC_LS
- arm_SBC_GE
- arm_SBC_LT
- arm_SBC_GT
- arm_SBC_LE
- arm_SBC
- arm_SBC_ZZ
- arm_SBC_S_EQ
- arm_SBC_S_NE
- arm_SBC_S_CS
- arm_SBC_S_CC
- arm_SBC_S_MI
- arm_SBC_S_PL
- arm_SBC_S_VS
- arm_SBC_S_VC
- arm_SBC_S_HI
- arm_SBC_S_LS
- arm_SBC_S_GE
- arm_SBC_S_LT
- arm_SBC_S_GT
- arm_SBC_S_LE
- arm_SBC_S
- arm_SBC_S_ZZ
- arm_SBFX_EQ
- arm_SBFX_NE
- arm_SBFX_CS
- arm_SBFX_CC
- arm_SBFX_MI
- arm_SBFX_PL
- arm_SBFX_VS
- arm_SBFX_VC
- arm_SBFX_HI
- arm_SBFX_LS
- arm_SBFX_GE
- arm_SBFX_LT
- arm_SBFX_GT
- arm_SBFX_LE
- arm_SBFX
- arm_SBFX_ZZ
- arm_SEL_EQ
- arm_SEL_NE
- arm_SEL_CS
- arm_SEL_CC
- arm_SEL_MI
- arm_SEL_PL
- arm_SEL_VS
- arm_SEL_VC
- arm_SEL_HI
- arm_SEL_LS
- arm_SEL_GE
- arm_SEL_LT
- arm_SEL_GT
- arm_SEL_LE
- arm_SEL
- arm_SEL_ZZ
- arm_SETEND
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- arm_SEV_EQ
- arm_SEV_NE
- arm_SEV_CS
- arm_SEV_CC
- arm_SEV_MI
- arm_SEV_PL
- arm_SEV_VS
- arm_SEV_VC
- arm_SEV_HI
- arm_SEV_LS
- arm_SEV_GE
- arm_SEV_LT
- arm_SEV_GT
- arm_SEV_LE
- arm_SEV
- arm_SEV_ZZ
- arm_SHADD16_EQ
- arm_SHADD16_NE
- arm_SHADD16_CS
- arm_SHADD16_CC
- arm_SHADD16_MI
- arm_SHADD16_PL
- arm_SHADD16_VS
- arm_SHADD16_VC
- arm_SHADD16_HI
- arm_SHADD16_LS
- arm_SHADD16_GE
- arm_SHADD16_LT
- arm_SHADD16_GT
- arm_SHADD16_LE
- arm_SHADD16
- arm_SHADD16_ZZ
- arm_SHADD8_EQ
- arm_SHADD8_NE
- arm_SHADD8_CS
- arm_SHADD8_CC
- arm_SHADD8_MI
- arm_SHADD8_PL
- arm_SHADD8_VS
- arm_SHADD8_VC
- arm_SHADD8_HI
- arm_SHADD8_LS
- arm_SHADD8_GE
- arm_SHADD8_LT
- arm_SHADD8_GT
- arm_SHADD8_LE
- arm_SHADD8
- arm_SHADD8_ZZ
- arm_SHASX_EQ
- arm_SHASX_NE
- arm_SHASX_CS
- arm_SHASX_CC
- arm_SHASX_MI
- arm_SHASX_PL
- arm_SHASX_VS
- arm_SHASX_VC
- arm_SHASX_HI
- arm_SHASX_LS
- arm_SHASX_GE
- arm_SHASX_LT
- arm_SHASX_GT
- arm_SHASX_LE
- arm_SHASX
- arm_SHASX_ZZ
- arm_SHSAX_EQ
- arm_SHSAX_NE
- arm_SHSAX_CS
- arm_SHSAX_CC
- arm_SHSAX_MI
- arm_SHSAX_PL
- arm_SHSAX_VS
- arm_SHSAX_VC
- arm_SHSAX_HI
- arm_SHSAX_LS
- arm_SHSAX_GE
- arm_SHSAX_LT
- arm_SHSAX_GT
- arm_SHSAX_LE
- arm_SHSAX
- arm_SHSAX_ZZ
- arm_SHSUB16_EQ
- arm_SHSUB16_NE
- arm_SHSUB16_CS
- arm_SHSUB16_CC
- arm_SHSUB16_MI
- arm_SHSUB16_PL
- arm_SHSUB16_VS
- arm_SHSUB16_VC
- arm_SHSUB16_HI
- arm_SHSUB16_LS
- arm_SHSUB16_GE
- arm_SHSUB16_LT
- arm_SHSUB16_GT
- arm_SHSUB16_LE
- arm_SHSUB16
- arm_SHSUB16_ZZ
- arm_SHSUB8_EQ
- arm_SHSUB8_NE
- arm_SHSUB8_CS
- arm_SHSUB8_CC
- arm_SHSUB8_MI
- arm_SHSUB8_PL
- arm_SHSUB8_VS
- arm_SHSUB8_VC
- arm_SHSUB8_HI
- arm_SHSUB8_LS
- arm_SHSUB8_GE
- arm_SHSUB8_LT
- arm_SHSUB8_GT
- arm_SHSUB8_LE
- arm_SHSUB8
- arm_SHSUB8_ZZ
- arm_SMLABB_EQ
- arm_SMLABB_NE
- arm_SMLABB_CS
- arm_SMLABB_CC
- arm_SMLABB_MI
- arm_SMLABB_PL
- arm_SMLABB_VS
- arm_SMLABB_VC
- arm_SMLABB_HI
- arm_SMLABB_LS
- arm_SMLABB_GE
- arm_SMLABB_LT
- arm_SMLABB_GT
- arm_SMLABB_LE
- arm_SMLABB
- arm_SMLABB_ZZ
- arm_SMLABT_EQ
- arm_SMLABT_NE
- arm_SMLABT_CS
- arm_SMLABT_CC
- arm_SMLABT_MI
- arm_SMLABT_PL
- arm_SMLABT_VS
- arm_SMLABT_VC
- arm_SMLABT_HI
- arm_SMLABT_LS
- arm_SMLABT_GE
- arm_SMLABT_LT
- arm_SMLABT_GT
- arm_SMLABT_LE
- arm_SMLABT
- arm_SMLABT_ZZ
- arm_SMLATB_EQ
- arm_SMLATB_NE
- arm_SMLATB_CS
- arm_SMLATB_CC
- arm_SMLATB_MI
- arm_SMLATB_PL
- arm_SMLATB_VS
- arm_SMLATB_VC
- arm_SMLATB_HI
- arm_SMLATB_LS
- arm_SMLATB_GE
- arm_SMLATB_LT
- arm_SMLATB_GT
- arm_SMLATB_LE
- arm_SMLATB
- arm_SMLATB_ZZ
- arm_SMLATT_EQ
- arm_SMLATT_NE
- arm_SMLATT_CS
- arm_SMLATT_CC
- arm_SMLATT_MI
- arm_SMLATT_PL
- arm_SMLATT_VS
- arm_SMLATT_VC
- arm_SMLATT_HI
- arm_SMLATT_LS
- arm_SMLATT_GE
- arm_SMLATT_LT
- arm_SMLATT_GT
- arm_SMLATT_LE
- arm_SMLATT
- arm_SMLATT_ZZ
- arm_SMLAD_EQ
- arm_SMLAD_NE
- arm_SMLAD_CS
- arm_SMLAD_CC
- arm_SMLAD_MI
- arm_SMLAD_PL
- arm_SMLAD_VS
- arm_SMLAD_VC
- arm_SMLAD_HI
- arm_SMLAD_LS
- arm_SMLAD_GE
- arm_SMLAD_LT
- arm_SMLAD_GT
- arm_SMLAD_LE
- arm_SMLAD
- arm_SMLAD_ZZ
- arm_SMLAD_X_EQ
- arm_SMLAD_X_NE
- arm_SMLAD_X_CS
- arm_SMLAD_X_CC
- arm_SMLAD_X_MI
- arm_SMLAD_X_PL
- arm_SMLAD_X_VS
- arm_SMLAD_X_VC
- arm_SMLAD_X_HI
- arm_SMLAD_X_LS
- arm_SMLAD_X_GE
- arm_SMLAD_X_LT
- arm_SMLAD_X_GT
- arm_SMLAD_X_LE
- arm_SMLAD_X
- arm_SMLAD_X_ZZ
- arm_SMLAL_EQ
- arm_SMLAL_NE
- arm_SMLAL_CS
- arm_SMLAL_CC
- arm_SMLAL_MI
- arm_SMLAL_PL
- arm_SMLAL_VS
- arm_SMLAL_VC
- arm_SMLAL_HI
- arm_SMLAL_LS
- arm_SMLAL_GE
- arm_SMLAL_LT
- arm_SMLAL_GT
- arm_SMLAL_LE
- arm_SMLAL
- arm_SMLAL_ZZ
- arm_SMLAL_S_EQ
- arm_SMLAL_S_NE
- arm_SMLAL_S_CS
- arm_SMLAL_S_CC
- arm_SMLAL_S_MI
- arm_SMLAL_S_PL
- arm_SMLAL_S_VS
- arm_SMLAL_S_VC
- arm_SMLAL_S_HI
- arm_SMLAL_S_LS
- arm_SMLAL_S_GE
- arm_SMLAL_S_LT
- arm_SMLAL_S_GT
- arm_SMLAL_S_LE
- arm_SMLAL_S
- arm_SMLAL_S_ZZ
- arm_SMLALBB_EQ
- arm_SMLALBB_NE
- arm_SMLALBB_CS
- arm_SMLALBB_CC
- arm_SMLALBB_MI
- arm_SMLALBB_PL
- arm_SMLALBB_VS
- arm_SMLALBB_VC
- arm_SMLALBB_HI
- arm_SMLALBB_LS
- arm_SMLALBB_GE
- arm_SMLALBB_LT
- arm_SMLALBB_GT
- arm_SMLALBB_LE
- arm_SMLALBB
- arm_SMLALBB_ZZ
- arm_SMLALBT_EQ
- arm_SMLALBT_NE
- arm_SMLALBT_CS
- arm_SMLALBT_CC
- arm_SMLALBT_MI
- arm_SMLALBT_PL
- arm_SMLALBT_VS
- arm_SMLALBT_VC
- arm_SMLALBT_HI
- arm_SMLALBT_LS
- arm_SMLALBT_GE
- arm_SMLALBT_LT
- arm_SMLALBT_GT
- arm_SMLALBT_LE
- arm_SMLALBT
- arm_SMLALBT_ZZ
- arm_SMLALTB_EQ
- arm_SMLALTB_NE
- arm_SMLALTB_CS
- arm_SMLALTB_CC
- arm_SMLALTB_MI
- arm_SMLALTB_PL
- arm_SMLALTB_VS
- arm_SMLALTB_VC
- arm_SMLALTB_HI
- arm_SMLALTB_LS
- arm_SMLALTB_GE
- arm_SMLALTB_LT
- arm_SMLALTB_GT
- arm_SMLALTB_LE
- arm_SMLALTB
- arm_SMLALTB_ZZ
- arm_SMLALTT_EQ
- arm_SMLALTT_NE
- arm_SMLALTT_CS
- arm_SMLALTT_CC
- arm_SMLALTT_MI
- arm_SMLALTT_PL
- arm_SMLALTT_VS
- arm_SMLALTT_VC
- arm_SMLALTT_HI
- arm_SMLALTT_LS
- arm_SMLALTT_GE
- arm_SMLALTT_LT
- arm_SMLALTT_GT
- arm_SMLALTT_LE
- arm_SMLALTT
- arm_SMLALTT_ZZ
- arm_SMLALD_EQ
- arm_SMLALD_NE
- arm_SMLALD_CS
- arm_SMLALD_CC
- arm_SMLALD_MI
- arm_SMLALD_PL
- arm_SMLALD_VS
- arm_SMLALD_VC
- arm_SMLALD_HI
- arm_SMLALD_LS
- arm_SMLALD_GE
- arm_SMLALD_LT
- arm_SMLALD_GT
- arm_SMLALD_LE
- arm_SMLALD
- arm_SMLALD_ZZ
- arm_SMLALD_X_EQ
- arm_SMLALD_X_NE
- arm_SMLALD_X_CS
- arm_SMLALD_X_CC
- arm_SMLALD_X_MI
- arm_SMLALD_X_PL
- arm_SMLALD_X_VS
- arm_SMLALD_X_VC
- arm_SMLALD_X_HI
- arm_SMLALD_X_LS
- arm_SMLALD_X_GE
- arm_SMLALD_X_LT
- arm_SMLALD_X_GT
- arm_SMLALD_X_LE
- arm_SMLALD_X
- arm_SMLALD_X_ZZ
- arm_SMLAWB_EQ
- arm_SMLAWB_NE
- arm_SMLAWB_CS
- arm_SMLAWB_CC
- arm_SMLAWB_MI
- arm_SMLAWB_PL
- arm_SMLAWB_VS
- arm_SMLAWB_VC
- arm_SMLAWB_HI
- arm_SMLAWB_LS
- arm_SMLAWB_GE
- arm_SMLAWB_LT
- arm_SMLAWB_GT
- arm_SMLAWB_LE
- arm_SMLAWB
- arm_SMLAWB_ZZ
- arm_SMLAWT_EQ
- arm_SMLAWT_NE
- arm_SMLAWT_CS
- arm_SMLAWT_CC
- arm_SMLAWT_MI
- arm_SMLAWT_PL
- arm_SMLAWT_VS
- arm_SMLAWT_VC
- arm_SMLAWT_HI
- arm_SMLAWT_LS
- arm_SMLAWT_GE
- arm_SMLAWT_LT
- arm_SMLAWT_GT
- arm_SMLAWT_LE
- arm_SMLAWT
- arm_SMLAWT_ZZ
- arm_SMLSD_EQ
- arm_SMLSD_NE
- arm_SMLSD_CS
- arm_SMLSD_CC
- arm_SMLSD_MI
- arm_SMLSD_PL
- arm_SMLSD_VS
- arm_SMLSD_VC
- arm_SMLSD_HI
- arm_SMLSD_LS
- arm_SMLSD_GE
- arm_SMLSD_LT
- arm_SMLSD_GT
- arm_SMLSD_LE
- arm_SMLSD
- arm_SMLSD_ZZ
- arm_SMLSD_X_EQ
- arm_SMLSD_X_NE
- arm_SMLSD_X_CS
- arm_SMLSD_X_CC
- arm_SMLSD_X_MI
- arm_SMLSD_X_PL
- arm_SMLSD_X_VS
- arm_SMLSD_X_VC
- arm_SMLSD_X_HI
- arm_SMLSD_X_LS
- arm_SMLSD_X_GE
- arm_SMLSD_X_LT
- arm_SMLSD_X_GT
- arm_SMLSD_X_LE
- arm_SMLSD_X
- arm_SMLSD_X_ZZ
- arm_SMLSLD_EQ
- arm_SMLSLD_NE
- arm_SMLSLD_CS
- arm_SMLSLD_CC
- arm_SMLSLD_MI
- arm_SMLSLD_PL
- arm_SMLSLD_VS
- arm_SMLSLD_VC
- arm_SMLSLD_HI
- arm_SMLSLD_LS
- arm_SMLSLD_GE
- arm_SMLSLD_LT
- arm_SMLSLD_GT
- arm_SMLSLD_LE
- arm_SMLSLD
- arm_SMLSLD_ZZ
- arm_SMLSLD_X_EQ
- arm_SMLSLD_X_NE
- arm_SMLSLD_X_CS
- arm_SMLSLD_X_CC
- arm_SMLSLD_X_MI
- arm_SMLSLD_X_PL
- arm_SMLSLD_X_VS
- arm_SMLSLD_X_VC
- arm_SMLSLD_X_HI
- arm_SMLSLD_X_LS
- arm_SMLSLD_X_GE
- arm_SMLSLD_X_LT
- arm_SMLSLD_X_GT
- arm_SMLSLD_X_LE
- arm_SMLSLD_X
- arm_SMLSLD_X_ZZ
- arm_SMMLA_EQ
- arm_SMMLA_NE
- arm_SMMLA_CS
- arm_SMMLA_CC
- arm_SMMLA_MI
- arm_SMMLA_PL
- arm_SMMLA_VS
- arm_SMMLA_VC
- arm_SMMLA_HI
- arm_SMMLA_LS
- arm_SMMLA_GE
- arm_SMMLA_LT
- arm_SMMLA_GT
- arm_SMMLA_LE
- arm_SMMLA
- arm_SMMLA_ZZ
- arm_SMMLA_R_EQ
- arm_SMMLA_R_NE
- arm_SMMLA_R_CS
- arm_SMMLA_R_CC
- arm_SMMLA_R_MI
- arm_SMMLA_R_PL
- arm_SMMLA_R_VS
- arm_SMMLA_R_VC
- arm_SMMLA_R_HI
- arm_SMMLA_R_LS
- arm_SMMLA_R_GE
- arm_SMMLA_R_LT
- arm_SMMLA_R_GT
- arm_SMMLA_R_LE
- arm_SMMLA_R
- arm_SMMLA_R_ZZ
- arm_SMMLS_EQ
- arm_SMMLS_NE
- arm_SMMLS_CS
- arm_SMMLS_CC
- arm_SMMLS_MI
- arm_SMMLS_PL
- arm_SMMLS_VS
- arm_SMMLS_VC
- arm_SMMLS_HI
- arm_SMMLS_LS
- arm_SMMLS_GE
- arm_SMMLS_LT
- arm_SMMLS_GT
- arm_SMMLS_LE
- arm_SMMLS
- arm_SMMLS_ZZ
- arm_SMMLS_R_EQ
- arm_SMMLS_R_NE
- arm_SMMLS_R_CS
- arm_SMMLS_R_CC
- arm_SMMLS_R_MI
- arm_SMMLS_R_PL
- arm_SMMLS_R_VS
- arm_SMMLS_R_VC
- arm_SMMLS_R_HI
- arm_SMMLS_R_LS
- arm_SMMLS_R_GE
- arm_SMMLS_R_LT
- arm_SMMLS_R_GT
- arm_SMMLS_R_LE
- arm_SMMLS_R
- arm_SMMLS_R_ZZ
- arm_SMMUL_EQ
- arm_SMMUL_NE
- arm_SMMUL_CS
- arm_SMMUL_CC
- arm_SMMUL_MI
- arm_SMMUL_PL
- arm_SMMUL_VS
- arm_SMMUL_VC
- arm_SMMUL_HI
- arm_SMMUL_LS
- arm_SMMUL_GE
- arm_SMMUL_LT
- arm_SMMUL_GT
- arm_SMMUL_LE
- arm_SMMUL
- arm_SMMUL_ZZ
- arm_SMMUL_R_EQ
- arm_SMMUL_R_NE
- arm_SMMUL_R_CS
- arm_SMMUL_R_CC
- arm_SMMUL_R_MI
- arm_SMMUL_R_PL
- arm_SMMUL_R_VS
- arm_SMMUL_R_VC
- arm_SMMUL_R_HI
- arm_SMMUL_R_LS
- arm_SMMUL_R_GE
- arm_SMMUL_R_LT
- arm_SMMUL_R_GT
- arm_SMMUL_R_LE
- arm_SMMUL_R
- arm_SMMUL_R_ZZ
- arm_SMUAD_EQ
- arm_SMUAD_NE
- arm_SMUAD_CS
- arm_SMUAD_CC
- arm_SMUAD_MI
- arm_SMUAD_PL
- arm_SMUAD_VS
- arm_SMUAD_VC
- arm_SMUAD_HI
- arm_SMUAD_LS
- arm_SMUAD_GE
- arm_SMUAD_LT
- arm_SMUAD_GT
- arm_SMUAD_LE
- arm_SMUAD
- arm_SMUAD_ZZ
- arm_SMUAD_X_EQ
- arm_SMUAD_X_NE
- arm_SMUAD_X_CS
- arm_SMUAD_X_CC
- arm_SMUAD_X_MI
- arm_SMUAD_X_PL
- arm_SMUAD_X_VS
- arm_SMUAD_X_VC
- arm_SMUAD_X_HI
- arm_SMUAD_X_LS
- arm_SMUAD_X_GE
- arm_SMUAD_X_LT
- arm_SMUAD_X_GT
- arm_SMUAD_X_LE
- arm_SMUAD_X
- arm_SMUAD_X_ZZ
- arm_SMULBB_EQ
- arm_SMULBB_NE
- arm_SMULBB_CS
- arm_SMULBB_CC
- arm_SMULBB_MI
- arm_SMULBB_PL
- arm_SMULBB_VS
- arm_SMULBB_VC
- arm_SMULBB_HI
- arm_SMULBB_LS
- arm_SMULBB_GE
- arm_SMULBB_LT
- arm_SMULBB_GT
- arm_SMULBB_LE
- arm_SMULBB
- arm_SMULBB_ZZ
- arm_SMULBT_EQ
- arm_SMULBT_NE
- arm_SMULBT_CS
- arm_SMULBT_CC
- arm_SMULBT_MI
- arm_SMULBT_PL
- arm_SMULBT_VS
- arm_SMULBT_VC
- arm_SMULBT_HI
- arm_SMULBT_LS
- arm_SMULBT_GE
- arm_SMULBT_LT
- arm_SMULBT_GT
- arm_SMULBT_LE
- arm_SMULBT
- arm_SMULBT_ZZ
- arm_SMULTB_EQ
- arm_SMULTB_NE
- arm_SMULTB_CS
- arm_SMULTB_CC
- arm_SMULTB_MI
- arm_SMULTB_PL
- arm_SMULTB_VS
- arm_SMULTB_VC
- arm_SMULTB_HI
- arm_SMULTB_LS
- arm_SMULTB_GE
- arm_SMULTB_LT
- arm_SMULTB_GT
- arm_SMULTB_LE
- arm_SMULTB
- arm_SMULTB_ZZ
- arm_SMULTT_EQ
- arm_SMULTT_NE
- arm_SMULTT_CS
- arm_SMULTT_CC
- arm_SMULTT_MI
- arm_SMULTT_PL
- arm_SMULTT_VS
- arm_SMULTT_VC
- arm_SMULTT_HI
- arm_SMULTT_LS
- arm_SMULTT_GE
- arm_SMULTT_LT
- arm_SMULTT_GT
- arm_SMULTT_LE
- arm_SMULTT
- arm_SMULTT_ZZ
- arm_SMULL_EQ
- arm_SMULL_NE
- arm_SMULL_CS
- arm_SMULL_CC
- arm_SMULL_MI
- arm_SMULL_PL
- arm_SMULL_VS
- arm_SMULL_VC
- arm_SMULL_HI
- arm_SMULL_LS
- arm_SMULL_GE
- arm_SMULL_LT
- arm_SMULL_GT
- arm_SMULL_LE
- arm_SMULL
- arm_SMULL_ZZ
- arm_SMULL_S_EQ
- arm_SMULL_S_NE
- arm_SMULL_S_CS
- arm_SMULL_S_CC
- arm_SMULL_S_MI
- arm_SMULL_S_PL
- arm_SMULL_S_VS
- arm_SMULL_S_VC
- arm_SMULL_S_HI
- arm_SMULL_S_LS
- arm_SMULL_S_GE
- arm_SMULL_S_LT
- arm_SMULL_S_GT
- arm_SMULL_S_LE
- arm_SMULL_S
- arm_SMULL_S_ZZ
- arm_SMULWB_EQ
- arm_SMULWB_NE
- arm_SMULWB_CS
- arm_SMULWB_CC
- arm_SMULWB_MI
- arm_SMULWB_PL
- arm_SMULWB_VS
- arm_SMULWB_VC
- arm_SMULWB_HI
- arm_SMULWB_LS
- arm_SMULWB_GE
- arm_SMULWB_LT
- arm_SMULWB_GT
- arm_SMULWB_LE
- arm_SMULWB
- arm_SMULWB_ZZ
- arm_SMULWT_EQ
- arm_SMULWT_NE
- arm_SMULWT_CS
- arm_SMULWT_CC
- arm_SMULWT_MI
- arm_SMULWT_PL
- arm_SMULWT_VS
- arm_SMULWT_VC
- arm_SMULWT_HI
- arm_SMULWT_LS
- arm_SMULWT_GE
- arm_SMULWT_LT
- arm_SMULWT_GT
- arm_SMULWT_LE
- arm_SMULWT
- arm_SMULWT_ZZ
- arm_SMUSD_EQ
- arm_SMUSD_NE
- arm_SMUSD_CS
- arm_SMUSD_CC
- arm_SMUSD_MI
- arm_SMUSD_PL
- arm_SMUSD_VS
- arm_SMUSD_VC
- arm_SMUSD_HI
- arm_SMUSD_LS
- arm_SMUSD_GE
- arm_SMUSD_LT
- arm_SMUSD_GT
- arm_SMUSD_LE
- arm_SMUSD
- arm_SMUSD_ZZ
- arm_SMUSD_X_EQ
- arm_SMUSD_X_NE
- arm_SMUSD_X_CS
- arm_SMUSD_X_CC
- arm_SMUSD_X_MI
- arm_SMUSD_X_PL
- arm_SMUSD_X_VS
- arm_SMUSD_X_VC
- arm_SMUSD_X_HI
- arm_SMUSD_X_LS
- arm_SMUSD_X_GE
- arm_SMUSD_X_LT
- arm_SMUSD_X_GT
- arm_SMUSD_X_LE
- arm_SMUSD_X
- arm_SMUSD_X_ZZ
- arm_SSAT_EQ
- arm_SSAT_NE
- arm_SSAT_CS
- arm_SSAT_CC
- arm_SSAT_MI
- arm_SSAT_PL
- arm_SSAT_VS
- arm_SSAT_VC
- arm_SSAT_HI
- arm_SSAT_LS
- arm_SSAT_GE
- arm_SSAT_LT
- arm_SSAT_GT
- arm_SSAT_LE
- arm_SSAT
- arm_SSAT_ZZ
- arm_SSAT16_EQ
- arm_SSAT16_NE
- arm_SSAT16_CS
- arm_SSAT16_CC
- arm_SSAT16_MI
- arm_SSAT16_PL
- arm_SSAT16_VS
- arm_SSAT16_VC
- arm_SSAT16_HI
- arm_SSAT16_LS
- arm_SSAT16_GE
- arm_SSAT16_LT
- arm_SSAT16_GT
- arm_SSAT16_LE
- arm_SSAT16
- arm_SSAT16_ZZ
- arm_SSAX_EQ
- arm_SSAX_NE
- arm_SSAX_CS
- arm_SSAX_CC
- arm_SSAX_MI
- arm_SSAX_PL
- arm_SSAX_VS
- arm_SSAX_VC
- arm_SSAX_HI
- arm_SSAX_LS
- arm_SSAX_GE
- arm_SSAX_LT
- arm_SSAX_GT
- arm_SSAX_LE
- arm_SSAX
- arm_SSAX_ZZ
- arm_SSUB16_EQ
- arm_SSUB16_NE
- arm_SSUB16_CS
- arm_SSUB16_CC
- arm_SSUB16_MI
- arm_SSUB16_PL
- arm_SSUB16_VS
- arm_SSUB16_VC
- arm_SSUB16_HI
- arm_SSUB16_LS
- arm_SSUB16_GE
- arm_SSUB16_LT
- arm_SSUB16_GT
- arm_SSUB16_LE
- arm_SSUB16
- arm_SSUB16_ZZ
- arm_SSUB8_EQ
- arm_SSUB8_NE
- arm_SSUB8_CS
- arm_SSUB8_CC
- arm_SSUB8_MI
- arm_SSUB8_PL
- arm_SSUB8_VS
- arm_SSUB8_VC
- arm_SSUB8_HI
- arm_SSUB8_LS
- arm_SSUB8_GE
- arm_SSUB8_LT
- arm_SSUB8_GT
- arm_SSUB8_LE
- arm_SSUB8
- arm_SSUB8_ZZ
- arm_STM_EQ
- arm_STM_NE
- arm_STM_CS
- arm_STM_CC
- arm_STM_MI
- arm_STM_PL
- arm_STM_VS
- arm_STM_VC
- arm_STM_HI
- arm_STM_LS
- arm_STM_GE
- arm_STM_LT
- arm_STM_GT
- arm_STM_LE
- arm_STM
- arm_STM_ZZ
- arm_STMDA_EQ
- arm_STMDA_NE
- arm_STMDA_CS
- arm_STMDA_CC
- arm_STMDA_MI
- arm_STMDA_PL
- arm_STMDA_VS
- arm_STMDA_VC
- arm_STMDA_HI
- arm_STMDA_LS
- arm_STMDA_GE
- arm_STMDA_LT
- arm_STMDA_GT
- arm_STMDA_LE
- arm_STMDA
- arm_STMDA_ZZ
- arm_STMDB_EQ
- arm_STMDB_NE
- arm_STMDB_CS
- arm_STMDB_CC
- arm_STMDB_MI
- arm_STMDB_PL
- arm_STMDB_VS
- arm_STMDB_VC
- arm_STMDB_HI
- arm_STMDB_LS
- arm_STMDB_GE
- arm_STMDB_LT
- arm_STMDB_GT
- arm_STMDB_LE
- arm_STMDB
- arm_STMDB_ZZ
- arm_STMIB_EQ
- arm_STMIB_NE
- arm_STMIB_CS
- arm_STMIB_CC
- arm_STMIB_MI
- arm_STMIB_PL
- arm_STMIB_VS
- arm_STMIB_VC
- arm_STMIB_HI
- arm_STMIB_LS
- arm_STMIB_GE
- arm_STMIB_LT
- arm_STMIB_GT
- arm_STMIB_LE
- arm_STMIB
- arm_STMIB_ZZ
- arm_STR_EQ
- arm_STR_NE
- arm_STR_CS
- arm_STR_CC
- arm_STR_MI
- arm_STR_PL
- arm_STR_VS
- arm_STR_VC
- arm_STR_HI
- arm_STR_LS
- arm_STR_GE
- arm_STR_LT
- arm_STR_GT
- arm_STR_LE
- arm_STR
- arm_STR_ZZ
- arm_STRB_EQ
- arm_STRB_NE
- arm_STRB_CS
- arm_STRB_CC
- arm_STRB_MI
- arm_STRB_PL
- arm_STRB_VS
- arm_STRB_VC
- arm_STRB_HI
- arm_STRB_LS
- arm_STRB_GE
- arm_STRB_LT
- arm_STRB_GT
- arm_STRB_LE
- arm_STRB
- arm_STRB_ZZ
- arm_STRBT_EQ
- arm_STRBT_NE
- arm_STRBT_CS
- arm_STRBT_CC
- arm_STRBT_MI
- arm_STRBT_PL
- arm_STRBT_VS
- arm_STRBT_VC
- arm_STRBT_HI
- arm_STRBT_LS
- arm_STRBT_GE
- arm_STRBT_LT
- arm_STRBT_GT
- arm_STRBT_LE
- arm_STRBT
- arm_STRBT_ZZ
- arm_STRD_EQ
- arm_STRD_NE
- arm_STRD_CS
- arm_STRD_CC
- arm_STRD_MI
- arm_STRD_PL
- arm_STRD_VS
- arm_STRD_VC
- arm_STRD_HI
- arm_STRD_LS
- arm_STRD_GE
- arm_STRD_LT
- arm_STRD_GT
- arm_STRD_LE
- arm_STRD
- arm_STRD_ZZ
- arm_STREX_EQ
- arm_STREX_NE
- arm_STREX_CS
- arm_STREX_CC
- arm_STREX_MI
- arm_STREX_PL
- arm_STREX_VS
- arm_STREX_VC
- arm_STREX_HI
- arm_STREX_LS
- arm_STREX_GE
- arm_STREX_LT
- arm_STREX_GT
- arm_STREX_LE
- arm_STREX
- arm_STREX_ZZ
- arm_STREXB_EQ
- arm_STREXB_NE
- arm_STREXB_CS
- arm_STREXB_CC
- arm_STREXB_MI
- arm_STREXB_PL
- arm_STREXB_VS
- arm_STREXB_VC
- arm_STREXB_HI
- arm_STREXB_LS
- arm_STREXB_GE
- arm_STREXB_LT
- arm_STREXB_GT
- arm_STREXB_LE
- arm_STREXB
- arm_STREXB_ZZ
- arm_STREXD_EQ
- arm_STREXD_NE
- arm_STREXD_CS
- arm_STREXD_CC
- arm_STREXD_MI
- arm_STREXD_PL
- arm_STREXD_VS
- arm_STREXD_VC
- arm_STREXD_HI
- arm_STREXD_LS
- arm_STREXD_GE
- arm_STREXD_LT
- arm_STREXD_GT
- arm_STREXD_LE
- arm_STREXD
- arm_STREXD_ZZ
- arm_STREXH_EQ
- arm_STREXH_NE
- arm_STREXH_CS
- arm_STREXH_CC
- arm_STREXH_MI
- arm_STREXH_PL
- arm_STREXH_VS
- arm_STREXH_VC
- arm_STREXH_HI
- arm_STREXH_LS
- arm_STREXH_GE
- arm_STREXH_LT
- arm_STREXH_GT
- arm_STREXH_LE
- arm_STREXH
- arm_STREXH_ZZ
- arm_STRH_EQ
- arm_STRH_NE
- arm_STRH_CS
- arm_STRH_CC
- arm_STRH_MI
- arm_STRH_PL
- arm_STRH_VS
- arm_STRH_VC
- arm_STRH_HI
- arm_STRH_LS
- arm_STRH_GE
- arm_STRH_LT
- arm_STRH_GT
- arm_STRH_LE
- arm_STRH
- arm_STRH_ZZ
- arm_STRHT_EQ
- arm_STRHT_NE
- arm_STRHT_CS
- arm_STRHT_CC
- arm_STRHT_MI
- arm_STRHT_PL
- arm_STRHT_VS
- arm_STRHT_VC
- arm_STRHT_HI
- arm_STRHT_LS
- arm_STRHT_GE
- arm_STRHT_LT
- arm_STRHT_GT
- arm_STRHT_LE
- arm_STRHT
- arm_STRHT_ZZ
- arm_STRT_EQ
- arm_STRT_NE
- arm_STRT_CS
- arm_STRT_CC
- arm_STRT_MI
- arm_STRT_PL
- arm_STRT_VS
- arm_STRT_VC
- arm_STRT_HI
- arm_STRT_LS
- arm_STRT_GE
- arm_STRT_LT
- arm_STRT_GT
- arm_STRT_LE
- arm_STRT
- arm_STRT_ZZ
- arm_SUB_EQ
- arm_SUB_NE
- arm_SUB_CS
- arm_SUB_CC
- arm_SUB_MI
- arm_SUB_PL
- arm_SUB_VS
- arm_SUB_VC
- arm_SUB_HI
- arm_SUB_LS
- arm_SUB_GE
- arm_SUB_LT
- arm_SUB_GT
- arm_SUB_LE
- arm_SUB
- arm_SUB_ZZ
- arm_SUB_S_EQ
- arm_SUB_S_NE
- arm_SUB_S_CS
- arm_SUB_S_CC
- arm_SUB_S_MI
- arm_SUB_S_PL
- arm_SUB_S_VS
- arm_SUB_S_VC
- arm_SUB_S_HI
- arm_SUB_S_LS
- arm_SUB_S_GE
- arm_SUB_S_LT
- arm_SUB_S_GT
- arm_SUB_S_LE
- arm_SUB_S
- arm_SUB_S_ZZ
- arm_SVC_EQ
- arm_SVC_NE
- arm_SVC_CS
- arm_SVC_CC
- arm_SVC_MI
- arm_SVC_PL
- arm_SVC_VS
- arm_SVC_VC
- arm_SVC_HI
- arm_SVC_LS
- arm_SVC_GE
- arm_SVC_LT
- arm_SVC_GT
- arm_SVC_LE
- arm_SVC
- arm_SVC_ZZ
- arm_SWP_EQ
- arm_SWP_NE
- arm_SWP_CS
- arm_SWP_CC
- arm_SWP_MI
- arm_SWP_PL
- arm_SWP_VS
- arm_SWP_VC
- arm_SWP_HI
- arm_SWP_LS
- arm_SWP_GE
- arm_SWP_LT
- arm_SWP_GT
- arm_SWP_LE
- arm_SWP
- arm_SWP_ZZ
- arm_SWP_B_EQ
- arm_SWP_B_NE
- arm_SWP_B_CS
- arm_SWP_B_CC
- arm_SWP_B_MI
- arm_SWP_B_PL
- arm_SWP_B_VS
- arm_SWP_B_VC
- arm_SWP_B_HI
- arm_SWP_B_LS
- arm_SWP_B_GE
- arm_SWP_B_LT
- arm_SWP_B_GT
- arm_SWP_B_LE
- arm_SWP_B
- arm_SWP_B_ZZ
- arm_SXTAB_EQ
- arm_SXTAB_NE
- arm_SXTAB_CS
- arm_SXTAB_CC
- arm_SXTAB_MI
- arm_SXTAB_PL
- arm_SXTAB_VS
- arm_SXTAB_VC
- arm_SXTAB_HI
- arm_SXTAB_LS
- arm_SXTAB_GE
- arm_SXTAB_LT
- arm_SXTAB_GT
- arm_SXTAB_LE
- arm_SXTAB
- arm_SXTAB_ZZ
- arm_SXTAB16_EQ
- arm_SXTAB16_NE
- arm_SXTAB16_CS
- arm_SXTAB16_CC
- arm_SXTAB16_MI
- arm_SXTAB16_PL
- arm_SXTAB16_VS
- arm_SXTAB16_VC
- arm_SXTAB16_HI
- arm_SXTAB16_LS
- arm_SXTAB16_GE
- arm_SXTAB16_LT
- arm_SXTAB16_GT
- arm_SXTAB16_LE
- arm_SXTAB16
- arm_SXTAB16_ZZ
- arm_SXTAH_EQ
- arm_SXTAH_NE
- arm_SXTAH_CS
- arm_SXTAH_CC
- arm_SXTAH_MI
- arm_SXTAH_PL
- arm_SXTAH_VS
- arm_SXTAH_VC
- arm_SXTAH_HI
- arm_SXTAH_LS
- arm_SXTAH_GE
- arm_SXTAH_LT
- arm_SXTAH_GT
- arm_SXTAH_LE
- arm_SXTAH
- arm_SXTAH_ZZ
- arm_SXTB_EQ
- arm_SXTB_NE
- arm_SXTB_CS
- arm_SXTB_CC
- arm_SXTB_MI
- arm_SXTB_PL
- arm_SXTB_VS
- arm_SXTB_VC
- arm_SXTB_HI
- arm_SXTB_LS
- arm_SXTB_GE
- arm_SXTB_LT
- arm_SXTB_GT
- arm_SXTB_LE
- arm_SXTB
- arm_SXTB_ZZ
- arm_SXTB16_EQ
- arm_SXTB16_NE
- arm_SXTB16_CS
- arm_SXTB16_CC
- arm_SXTB16_MI
- arm_SXTB16_PL
- arm_SXTB16_VS
- arm_SXTB16_VC
- arm_SXTB16_HI
- arm_SXTB16_LS
- arm_SXTB16_GE
- arm_SXTB16_LT
- arm_SXTB16_GT
- arm_SXTB16_LE
- arm_SXTB16
- arm_SXTB16_ZZ
- arm_SXTH_EQ
- arm_SXTH_NE
- arm_SXTH_CS
- arm_SXTH_CC
- arm_SXTH_MI
- arm_SXTH_PL
- arm_SXTH_VS
- arm_SXTH_VC
- arm_SXTH_HI
- arm_SXTH_LS
- arm_SXTH_GE
- arm_SXTH_LT
- arm_SXTH_GT
- arm_SXTH_LE
- arm_SXTH
- arm_SXTH_ZZ
- arm_TEQ_EQ
- arm_TEQ_NE
- arm_TEQ_CS
- arm_TEQ_CC
- arm_TEQ_MI
- arm_TEQ_PL
- arm_TEQ_VS
- arm_TEQ_VC
- arm_TEQ_HI
- arm_TEQ_LS
- arm_TEQ_GE
- arm_TEQ_LT
- arm_TEQ_GT
- arm_TEQ_LE
- arm_TEQ
- arm_TEQ_ZZ
- arm_TST_EQ
- arm_TST_NE
- arm_TST_CS
- arm_TST_CC
- arm_TST_MI
- arm_TST_PL
- arm_TST_VS
- arm_TST_VC
- arm_TST_HI
- arm_TST_LS
- arm_TST_GE
- arm_TST_LT
- arm_TST_GT
- arm_TST_LE
- arm_TST
- arm_TST_ZZ
- arm_UADD16_EQ
- arm_UADD16_NE
- arm_UADD16_CS
- arm_UADD16_CC
- arm_UADD16_MI
- arm_UADD16_PL
- arm_UADD16_VS
- arm_UADD16_VC
- arm_UADD16_HI
- arm_UADD16_LS
- arm_UADD16_GE
- arm_UADD16_LT
- arm_UADD16_GT
- arm_UADD16_LE
- arm_UADD16
- arm_UADD16_ZZ
- arm_UADD8_EQ
- arm_UADD8_NE
- arm_UADD8_CS
- arm_UADD8_CC
- arm_UADD8_MI
- arm_UADD8_PL
- arm_UADD8_VS
- arm_UADD8_VC
- arm_UADD8_HI
- arm_UADD8_LS
- arm_UADD8_GE
- arm_UADD8_LT
- arm_UADD8_GT
- arm_UADD8_LE
- arm_UADD8
- arm_UADD8_ZZ
- arm_UASX_EQ
- arm_UASX_NE
- arm_UASX_CS
- arm_UASX_CC
- arm_UASX_MI
- arm_UASX_PL
- arm_UASX_VS
- arm_UASX_VC
- arm_UASX_HI
- arm_UASX_LS
- arm_UASX_GE
- arm_UASX_LT
- arm_UASX_GT
- arm_UASX_LE
- arm_UASX
- arm_UASX_ZZ
- arm_UBFX_EQ
- arm_UBFX_NE
- arm_UBFX_CS
- arm_UBFX_CC
- arm_UBFX_MI
- arm_UBFX_PL
- arm_UBFX_VS
- arm_UBFX_VC
- arm_UBFX_HI
- arm_UBFX_LS
- arm_UBFX_GE
- arm_UBFX_LT
- arm_UBFX_GT
- arm_UBFX_LE
- arm_UBFX
- arm_UBFX_ZZ
- arm_UHADD16_EQ
- arm_UHADD16_NE
- arm_UHADD16_CS
- arm_UHADD16_CC
- arm_UHADD16_MI
- arm_UHADD16_PL
- arm_UHADD16_VS
- arm_UHADD16_VC
- arm_UHADD16_HI
- arm_UHADD16_LS
- arm_UHADD16_GE
- arm_UHADD16_LT
- arm_UHADD16_GT
- arm_UHADD16_LE
- arm_UHADD16
- arm_UHADD16_ZZ
- arm_UHADD8_EQ
- arm_UHADD8_NE
- arm_UHADD8_CS
- arm_UHADD8_CC
- arm_UHADD8_MI
- arm_UHADD8_PL
- arm_UHADD8_VS
- arm_UHADD8_VC
- arm_UHADD8_HI
- arm_UHADD8_LS
- arm_UHADD8_GE
- arm_UHADD8_LT
- arm_UHADD8_GT
- arm_UHADD8_LE
- arm_UHADD8
- arm_UHADD8_ZZ
- arm_UHASX_EQ
- arm_UHASX_NE
- arm_UHASX_CS
- arm_UHASX_CC
- arm_UHASX_MI
- arm_UHASX_PL
- arm_UHASX_VS
- arm_UHASX_VC
- arm_UHASX_HI
- arm_UHASX_LS
- arm_UHASX_GE
- arm_UHASX_LT
- arm_UHASX_GT
- arm_UHASX_LE
- arm_UHASX
- arm_UHASX_ZZ
- arm_UHSAX_EQ
- arm_UHSAX_NE
- arm_UHSAX_CS
- arm_UHSAX_CC
- arm_UHSAX_MI
- arm_UHSAX_PL
- arm_UHSAX_VS
- arm_UHSAX_VC
- arm_UHSAX_HI
- arm_UHSAX_LS
- arm_UHSAX_GE
- arm_UHSAX_LT
- arm_UHSAX_GT
- arm_UHSAX_LE
- arm_UHSAX
- arm_UHSAX_ZZ
- arm_UHSUB16_EQ
- arm_UHSUB16_NE
- arm_UHSUB16_CS
- arm_UHSUB16_CC
- arm_UHSUB16_MI
- arm_UHSUB16_PL
- arm_UHSUB16_VS
- arm_UHSUB16_VC
- arm_UHSUB16_HI
- arm_UHSUB16_LS
- arm_UHSUB16_GE
- arm_UHSUB16_LT
- arm_UHSUB16_GT
- arm_UHSUB16_LE
- arm_UHSUB16
- arm_UHSUB16_ZZ
- arm_UHSUB8_EQ
- arm_UHSUB8_NE
- arm_UHSUB8_CS
- arm_UHSUB8_CC
- arm_UHSUB8_MI
- arm_UHSUB8_PL
- arm_UHSUB8_VS
- arm_UHSUB8_VC
- arm_UHSUB8_HI
- arm_UHSUB8_LS
- arm_UHSUB8_GE
- arm_UHSUB8_LT
- arm_UHSUB8_GT
- arm_UHSUB8_LE
- arm_UHSUB8
- arm_UHSUB8_ZZ
- arm_UMAAL_EQ
- arm_UMAAL_NE
- arm_UMAAL_CS
- arm_UMAAL_CC
- arm_UMAAL_MI
- arm_UMAAL_PL
- arm_UMAAL_VS
- arm_UMAAL_VC
- arm_UMAAL_HI
- arm_UMAAL_LS
- arm_UMAAL_GE
- arm_UMAAL_LT
- arm_UMAAL_GT
- arm_UMAAL_LE
- arm_UMAAL
- arm_UMAAL_ZZ
- arm_UMLAL_EQ
- arm_UMLAL_NE
- arm_UMLAL_CS
- arm_UMLAL_CC
- arm_UMLAL_MI
- arm_UMLAL_PL
- arm_UMLAL_VS
- arm_UMLAL_VC
- arm_UMLAL_HI
- arm_UMLAL_LS
- arm_UMLAL_GE
- arm_UMLAL_LT
- arm_UMLAL_GT
- arm_UMLAL_LE
- arm_UMLAL
- arm_UMLAL_ZZ
- arm_UMLAL_S_EQ
- arm_UMLAL_S_NE
- arm_UMLAL_S_CS
- arm_UMLAL_S_CC
- arm_UMLAL_S_MI
- arm_UMLAL_S_PL
- arm_UMLAL_S_VS
- arm_UMLAL_S_VC
- arm_UMLAL_S_HI
- arm_UMLAL_S_LS
- arm_UMLAL_S_GE
- arm_UMLAL_S_LT
- arm_UMLAL_S_GT
- arm_UMLAL_S_LE
- arm_UMLAL_S
- arm_UMLAL_S_ZZ
- arm_UMULL_EQ
- arm_UMULL_NE
- arm_UMULL_CS
- arm_UMULL_CC
- arm_UMULL_MI
- arm_UMULL_PL
- arm_UMULL_VS
- arm_UMULL_VC
- arm_UMULL_HI
- arm_UMULL_LS
- arm_UMULL_GE
- arm_UMULL_LT
- arm_UMULL_GT
- arm_UMULL_LE
- arm_UMULL
- arm_UMULL_ZZ
- arm_UMULL_S_EQ
- arm_UMULL_S_NE
- arm_UMULL_S_CS
- arm_UMULL_S_CC
- arm_UMULL_S_MI
- arm_UMULL_S_PL
- arm_UMULL_S_VS
- arm_UMULL_S_VC
- arm_UMULL_S_HI
- arm_UMULL_S_LS
- arm_UMULL_S_GE
- arm_UMULL_S_LT
- arm_UMULL_S_GT
- arm_UMULL_S_LE
- arm_UMULL_S
- arm_UMULL_S_ZZ
- arm_UNDEF
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- _
- arm_UQADD16_EQ
- arm_UQADD16_NE
- arm_UQADD16_CS
- arm_UQADD16_CC
- arm_UQADD16_MI
- arm_UQADD16_PL
- arm_UQADD16_VS
- arm_UQADD16_VC
- arm_UQADD16_HI
- arm_UQADD16_LS
- arm_UQADD16_GE
- arm_UQADD16_LT
- arm_UQADD16_GT
- arm_UQADD16_LE
- arm_UQADD16
- arm_UQADD16_ZZ
- arm_UQADD8_EQ
- arm_UQADD8_NE
- arm_UQADD8_CS
- arm_UQADD8_CC
- arm_UQADD8_MI
- arm_UQADD8_PL
- arm_UQADD8_VS
- arm_UQADD8_VC
- arm_UQADD8_HI
- arm_UQADD8_LS
- arm_UQADD8_GE
- arm_UQADD8_LT
- arm_UQADD8_GT
- arm_UQADD8_LE
- arm_UQADD8
- arm_UQADD8_ZZ
- arm_UQASX_EQ
- arm_UQASX_NE
- arm_UQASX_CS
- arm_UQASX_CC
- arm_UQASX_MI
- arm_UQASX_PL
- arm_UQASX_VS
- arm_UQASX_VC
- arm_UQASX_HI
- arm_UQASX_LS
- arm_UQASX_GE
- arm_UQASX_LT
- arm_UQASX_GT
- arm_UQASX_LE
- arm_UQASX
- arm_UQASX_ZZ
- arm_UQSAX_EQ
- arm_UQSAX_NE
- arm_UQSAX_CS
- arm_UQSAX_CC
- arm_UQSAX_MI
- arm_UQSAX_PL
- arm_UQSAX_VS
- arm_UQSAX_VC
- arm_UQSAX_HI
- arm_UQSAX_LS
- arm_UQSAX_GE
- arm_UQSAX_LT
- arm_UQSAX_GT
- arm_UQSAX_LE
- arm_UQSAX
- arm_UQSAX_ZZ
- arm_UQSUB16_EQ
- arm_UQSUB16_NE
- arm_UQSUB16_CS
- arm_UQSUB16_CC
- arm_UQSUB16_MI
- arm_UQSUB16_PL
- arm_UQSUB16_VS
- arm_UQSUB16_VC
- arm_UQSUB16_HI
- arm_UQSUB16_LS
- arm_UQSUB16_GE
- arm_UQSUB16_LT
- arm_UQSUB16_GT
- arm_UQSUB16_LE
- arm_UQSUB16
- arm_UQSUB16_ZZ
- arm_UQSUB8_EQ
- arm_UQSUB8_NE
- arm_UQSUB8_CS
- arm_UQSUB8_CC
- arm_UQSUB8_MI
- arm_UQSUB8_PL
- arm_UQSUB8_VS
- arm_UQSUB8_VC
- arm_UQSUB8_HI
- arm_UQSUB8_LS
- arm_UQSUB8_GE
- arm_UQSUB8_LT
- arm_UQSUB8_GT
- arm_UQSUB8_LE
- arm_UQSUB8
- arm_UQSUB8_ZZ
- arm_USAD8_EQ
- arm_USAD8_NE
- arm_USAD8_CS
- arm_USAD8_CC
- arm_USAD8_MI
- arm_USAD8_PL
- arm_USAD8_VS
- arm_USAD8_VC
- arm_USAD8_HI
- arm_USAD8_LS
- arm_USAD8_GE
- arm_USAD8_LT
- arm_USAD8_GT
- arm_USAD8_LE
- arm_USAD8
- arm_USAD8_ZZ
- arm_USADA8_EQ
- arm_USADA8_NE
- arm_USADA8_CS
- arm_USADA8_CC
- arm_USADA8_MI
- arm_USADA8_PL
- arm_USADA8_VS
- arm_USADA8_VC
- arm_USADA8_HI
- arm_USADA8_LS
- arm_USADA8_GE
- arm_USADA8_LT
- arm_USADA8_GT
- arm_USADA8_LE
- arm_USADA8
- arm_USADA8_ZZ
- arm_USAT_EQ
- arm_USAT_NE
- arm_USAT_CS
- arm_USAT_CC
- arm_USAT_MI
- arm_USAT_PL
- arm_USAT_VS
- arm_USAT_VC
- arm_USAT_HI
- arm_USAT_LS
- arm_USAT_GE
- arm_USAT_LT
- arm_USAT_GT
- arm_USAT_LE
- arm_USAT
- arm_USAT_ZZ
- arm_USAT16_EQ
- arm_USAT16_NE
- arm_USAT16_CS
- arm_USAT16_CC
- arm_USAT16_MI
- arm_USAT16_PL
- arm_USAT16_VS
- arm_USAT16_VC
- arm_USAT16_HI
- arm_USAT16_LS
- arm_USAT16_GE
- arm_USAT16_LT
- arm_USAT16_GT
- arm_USAT16_LE
- arm_USAT16
- arm_USAT16_ZZ
- arm_USAX_EQ
- arm_USAX_NE
- arm_USAX_CS
- arm_USAX_CC
- arm_USAX_MI
- arm_USAX_PL
- arm_USAX_VS
- arm_USAX_VC
- arm_USAX_HI
- arm_USAX_LS
- arm_USAX_GE
- arm_USAX_LT
- arm_USAX_GT
- arm_USAX_LE
- arm_USAX
- arm_USAX_ZZ
- arm_USUB16_EQ
- arm_USUB16_NE
- arm_USUB16_CS
- arm_USUB16_CC
- arm_USUB16_MI
- arm_USUB16_PL
- arm_USUB16_VS
- arm_USUB16_VC
- arm_USUB16_HI
- arm_USUB16_LS
- arm_USUB16_GE
- arm_USUB16_LT
- arm_USUB16_GT
- arm_USUB16_LE
- arm_USUB16
- arm_USUB16_ZZ
- arm_USUB8_EQ
- arm_USUB8_NE
- arm_USUB8_CS
- arm_USUB8_CC
- arm_USUB8_MI
- arm_USUB8_PL
- arm_USUB8_VS
- arm_USUB8_VC
- arm_USUB8_HI
- arm_USUB8_LS
- arm_USUB8_GE
- arm_USUB8_LT
- arm_USUB8_GT
- arm_USUB8_LE
- arm_USUB8
- arm_USUB8_ZZ
- arm_UXTAB_EQ
- arm_UXTAB_NE
- arm_UXTAB_CS
- arm_UXTAB_CC
- arm_UXTAB_MI
- arm_UXTAB_PL
- arm_UXTAB_VS
- arm_UXTAB_VC
- arm_UXTAB_HI
- arm_UXTAB_LS
- arm_UXTAB_GE
- arm_UXTAB_LT
- arm_UXTAB_GT
- arm_UXTAB_LE
- arm_UXTAB
- arm_UXTAB_ZZ
- arm_UXTAB16_EQ
- arm_UXTAB16_NE
- arm_UXTAB16_CS
- arm_UXTAB16_CC
- arm_UXTAB16_MI
- arm_UXTAB16_PL
- arm_UXTAB16_VS
- arm_UXTAB16_VC
- arm_UXTAB16_HI
- arm_UXTAB16_LS
- arm_UXTAB16_GE
- arm_UXTAB16_LT
- arm_UXTAB16_GT
- arm_UXTAB16_LE
- arm_UXTAB16
- arm_UXTAB16_ZZ
- arm_UXTAH_EQ
- arm_UXTAH_NE
- arm_UXTAH_CS
- arm_UXTAH_CC
- arm_UXTAH_MI
- arm_UXTAH_PL
- arm_UXTAH_VS
- arm_UXTAH_VC
- arm_UXTAH_HI
- arm_UXTAH_LS
- arm_UXTAH_GE
- arm_UXTAH_LT
- arm_UXTAH_GT
- arm_UXTAH_LE
- arm_UXTAH
- arm_UXTAH_ZZ
- arm_UXTB_EQ
- arm_UXTB_NE
- arm_UXTB_CS
- arm_UXTB_CC
- arm_UXTB_MI
- arm_UXTB_PL
- arm_UXTB_VS
- arm_UXTB_VC
- arm_UXTB_HI
- arm_UXTB_LS
- arm_UXTB_GE
- arm_UXTB_LT
- arm_UXTB_GT
- arm_UXTB_LE
- arm_UXTB
- arm_UXTB_ZZ
- arm_UXTB16_EQ
- arm_UXTB16_NE
- arm_UXTB16_CS
- arm_UXTB16_CC
- arm_UXTB16_MI
- arm_UXTB16_PL
- arm_UXTB16_VS
- arm_UXTB16_VC
- arm_UXTB16_HI
- arm_UXTB16_LS
- arm_UXTB16_GE
- arm_UXTB16_LT
- arm_UXTB16_GT
- arm_UXTB16_LE
- arm_UXTB16
- arm_UXTB16_ZZ
- arm_UXTH_EQ
- arm_UXTH_NE
- arm_UXTH_CS
- arm_UXTH_CC
- arm_UXTH_MI
- arm_UXTH_PL
- arm_UXTH_VS
- arm_UXTH_VC
- arm_UXTH_HI
- arm_UXTH_LS
- arm_UXTH_GE
- arm_UXTH_LT
- arm_UXTH_GT
- arm_UXTH_LE
- arm_UXTH
- arm_UXTH_ZZ
- arm_VABS_EQ_F32
- arm_VABS_NE_F32
- arm_VABS_CS_F32
- arm_VABS_CC_F32
- arm_VABS_MI_F32
- arm_VABS_PL_F32
- arm_VABS_VS_F32
- arm_VABS_VC_F32
- arm_VABS_HI_F32
- arm_VABS_LS_F32
- arm_VABS_GE_F32
- arm_VABS_LT_F32
- arm_VABS_GT_F32
- arm_VABS_LE_F32
- arm_VABS_F32
- arm_VABS_ZZ_F32
- arm_VABS_EQ_F64
- arm_VABS_NE_F64
- arm_VABS_CS_F64
- arm_VABS_CC_F64
- arm_VABS_MI_F64
- arm_VABS_PL_F64
- arm_VABS_VS_F64
- arm_VABS_VC_F64
- arm_VABS_HI_F64
- arm_VABS_LS_F64
- arm_VABS_GE_F64
- arm_VABS_LT_F64
- arm_VABS_GT_F64
- arm_VABS_LE_F64
- arm_VABS_F64
- arm_VABS_ZZ_F64
- arm_VADD_EQ_F32
- arm_VADD_NE_F32
- arm_VADD_CS_F32
- arm_VADD_CC_F32
- arm_VADD_MI_F32
- arm_VADD_PL_F32
- arm_VADD_VS_F32
- arm_VADD_VC_F32
- arm_VADD_HI_F32
- arm_VADD_LS_F32
- arm_VADD_GE_F32
- arm_VADD_LT_F32
- arm_VADD_GT_F32
- arm_VADD_LE_F32
- arm_VADD_F32
- arm_VADD_ZZ_F32
- arm_VADD_EQ_F64
- arm_VADD_NE_F64
- arm_VADD_CS_F64
- arm_VADD_CC_F64
- arm_VADD_MI_F64
- arm_VADD_PL_F64
- arm_VADD_VS_F64
- arm_VADD_VC_F64
- arm_VADD_HI_F64
- arm_VADD_LS_F64
- arm_VADD_GE_F64
- arm_VADD_LT_F64
- arm_VADD_GT_F64
- arm_VADD_LE_F64
- arm_VADD_F64
- arm_VADD_ZZ_F64
- arm_VCMP_EQ_F32
- arm_VCMP_NE_F32
- arm_VCMP_CS_F32
- arm_VCMP_CC_F32
- arm_VCMP_MI_F32
- arm_VCMP_PL_F32
- arm_VCMP_VS_F32
- arm_VCMP_VC_F32
- arm_VCMP_HI_F32
- arm_VCMP_LS_F32
- arm_VCMP_GE_F32
- arm_VCMP_LT_F32
- arm_VCMP_GT_F32
- arm_VCMP_LE_F32
- arm_VCMP_F32
- arm_VCMP_ZZ_F32
- arm_VCMP_EQ_F64
- arm_VCMP_NE_F64
- arm_VCMP_CS_F64
- arm_VCMP_CC_F64
- arm_VCMP_MI_F64
- arm_VCMP_PL_F64
- arm_VCMP_VS_F64
- arm_VCMP_VC_F64
- arm_VCMP_HI_F64
- arm_VCMP_LS_F64
- arm_VCMP_GE_F64
- arm_VCMP_LT_F64
- arm_VCMP_GT_F64
- arm_VCMP_LE_F64
- arm_VCMP_F64
- arm_VCMP_ZZ_F64
- arm_VCMP_E_EQ_F32
- arm_VCMP_E_NE_F32
- arm_VCMP_E_CS_F32
- arm_VCMP_E_CC_F32
- arm_VCMP_E_MI_F32
- arm_VCMP_E_PL_F32
- arm_VCMP_E_VS_F32
- arm_VCMP_E_VC_F32
- arm_VCMP_E_HI_F32
- arm_VCMP_E_LS_F32
- arm_VCMP_E_GE_F32
- arm_VCMP_E_LT_F32
- arm_VCMP_E_GT_F32
- arm_VCMP_E_LE_F32
- arm_VCMP_E_F32
- arm_VCMP_E_ZZ_F32
- arm_VCMP_E_EQ_F64
- arm_VCMP_E_NE_F64
- arm_VCMP_E_CS_F64
- arm_VCMP_E_CC_F64
- arm_VCMP_E_MI_F64
- arm_VCMP_E_PL_F64
- arm_VCMP_E_VS_F64
- arm_VCMP_E_VC_F64
- arm_VCMP_E_HI_F64
- arm_VCMP_E_LS_F64
- arm_VCMP_E_GE_F64
- arm_VCMP_E_LT_F64
- arm_VCMP_E_GT_F64
- arm_VCMP_E_LE_F64
- arm_VCMP_E_F64
- arm_VCMP_E_ZZ_F64
- arm_VCVT_EQ_F32_FXS16
- arm_VCVT_NE_F32_FXS16
- arm_VCVT_CS_F32_FXS16
- arm_VCVT_CC_F32_FXS16
- arm_VCVT_MI_F32_FXS16
- arm_VCVT_PL_F32_FXS16
- arm_VCVT_VS_F32_FXS16
- arm_VCVT_VC_F32_FXS16
- arm_VCVT_HI_F32_FXS16
- arm_VCVT_LS_F32_FXS16
- arm_VCVT_GE_F32_FXS16
- arm_VCVT_LT_F32_FXS16
- arm_VCVT_GT_F32_FXS16
- arm_VCVT_LE_F32_FXS16
- arm_VCVT_F32_FXS16
- arm_VCVT_ZZ_F32_FXS16
- arm_VCVT_EQ_F32_FXS32
- arm_VCVT_NE_F32_FXS32
- arm_VCVT_CS_F32_FXS32
- arm_VCVT_CC_F32_FXS32
- arm_VCVT_MI_F32_FXS32
- arm_VCVT_PL_F32_FXS32
- arm_VCVT_VS_F32_FXS32
- arm_VCVT_VC_F32_FXS32
- arm_VCVT_HI_F32_FXS32
- arm_VCVT_LS_F32_FXS32
- arm_VCVT_GE_F32_FXS32
- arm_VCVT_LT_F32_FXS32
- arm_VCVT_GT_F32_FXS32
- arm_VCVT_LE_F32_FXS32
- arm_VCVT_F32_FXS32
- arm_VCVT_ZZ_F32_FXS32
- arm_VCVT_EQ_F32_FXU16
- arm_VCVT_NE_F32_FXU16
- arm_VCVT_CS_F32_FXU16
- arm_VCVT_CC_F32_FXU16
- arm_VCVT_MI_F32_FXU16
- arm_VCVT_PL_F32_FXU16
- arm_VCVT_VS_F32_FXU16
- arm_VCVT_VC_F32_FXU16
- arm_VCVT_HI_F32_FXU16
- arm_VCVT_LS_F32_FXU16
- arm_VCVT_GE_F32_FXU16
- arm_VCVT_LT_F32_FXU16
- arm_VCVT_GT_F32_FXU16
- arm_VCVT_LE_F32_FXU16
- arm_VCVT_F32_FXU16
- arm_VCVT_ZZ_F32_FXU16
- arm_VCVT_EQ_F32_FXU32
- arm_VCVT_NE_F32_FXU32
- arm_VCVT_CS_F32_FXU32
- arm_VCVT_CC_F32_FXU32
- arm_VCVT_MI_F32_FXU32
- arm_VCVT_PL_F32_FXU32
- arm_VCVT_VS_F32_FXU32
- arm_VCVT_VC_F32_FXU32
- arm_VCVT_HI_F32_FXU32
- arm_VCVT_LS_F32_FXU32
- arm_VCVT_GE_F32_FXU32
- arm_VCVT_LT_F32_FXU32
- arm_VCVT_GT_F32_FXU32
- arm_VCVT_LE_F32_FXU32
- arm_VCVT_F32_FXU32
- arm_VCVT_ZZ_F32_FXU32
- arm_VCVT_EQ_F64_FXS16
- arm_VCVT_NE_F64_FXS16
- arm_VCVT_CS_F64_FXS16
- arm_VCVT_CC_F64_FXS16
- arm_VCVT_MI_F64_FXS16
- arm_VCVT_PL_F64_FXS16
- arm_VCVT_VS_F64_FXS16
- arm_VCVT_VC_F64_FXS16
- arm_VCVT_HI_F64_FXS16
- arm_VCVT_LS_F64_FXS16
- arm_VCVT_GE_F64_FXS16
- arm_VCVT_LT_F64_FXS16
- arm_VCVT_GT_F64_FXS16
- arm_VCVT_LE_F64_FXS16
- arm_VCVT_F64_FXS16
- arm_VCVT_ZZ_F64_FXS16
- arm_VCVT_EQ_F64_FXS32
- arm_VCVT_NE_F64_FXS32
- arm_VCVT_CS_F64_FXS32
- arm_VCVT_CC_F64_FXS32
- arm_VCVT_MI_F64_FXS32
- arm_VCVT_PL_F64_FXS32
- arm_VCVT_VS_F64_FXS32
- arm_VCVT_VC_F64_FXS32
- arm_VCVT_HI_F64_FXS32
- arm_VCVT_LS_F64_FXS32
- arm_VCVT_GE_F64_FXS32
- arm_VCVT_LT_F64_FXS32
- arm_VCVT_GT_F64_FXS32
- arm_VCVT_LE_F64_FXS32
- arm_VCVT_F64_FXS32
- arm_VCVT_ZZ_F64_FXS32
- arm_VCVT_EQ_F64_FXU16
- arm_VCVT_NE_F64_FXU16
- arm_VCVT_CS_F64_FXU16
- arm_VCVT_CC_F64_FXU16
- arm_VCVT_MI_F64_FXU16
- arm_VCVT_PL_F64_FXU16
- arm_VCVT_VS_F64_FXU16
- arm_VCVT_VC_F64_FXU16
- arm_VCVT_HI_F64_FXU16
- arm_VCVT_LS_F64_FXU16
- arm_VCVT_GE_F64_FXU16
- arm_VCVT_LT_F64_FXU16
- arm_VCVT_GT_F64_FXU16
- arm_VCVT_LE_F64_FXU16
- arm_VCVT_F64_FXU16
- arm_VCVT_ZZ_F64_FXU16
- arm_VCVT_EQ_F64_FXU32
- arm_VCVT_NE_F64_FXU32
- arm_VCVT_CS_F64_FXU32
- arm_VCVT_CC_F64_FXU32
- arm_VCVT_MI_F64_FXU32
- arm_VCVT_PL_F64_FXU32
- arm_VCVT_VS_F64_FXU32
- arm_VCVT_VC_F64_FXU32
- arm_VCVT_HI_F64_FXU32
- arm_VCVT_LS_F64_FXU32
- arm_VCVT_GE_F64_FXU32
- arm_VCVT_LT_F64_FXU32
- arm_VCVT_GT_F64_FXU32
- arm_VCVT_LE_F64_FXU32
- arm_VCVT_F64_FXU32
- arm_VCVT_ZZ_F64_FXU32
- arm_VCVT_EQ_F32_U32
- arm_VCVT_NE_F32_U32
- arm_VCVT_CS_F32_U32
- arm_VCVT_CC_F32_U32
- arm_VCVT_MI_F32_U32
- arm_VCVT_PL_F32_U32
- arm_VCVT_VS_F32_U32
- arm_VCVT_VC_F32_U32
- arm_VCVT_HI_F32_U32
- arm_VCVT_LS_F32_U32
- arm_VCVT_GE_F32_U32
- arm_VCVT_LT_F32_U32
- arm_VCVT_GT_F32_U32
- arm_VCVT_LE_F32_U32
- arm_VCVT_F32_U32
- arm_VCVT_ZZ_F32_U32
- arm_VCVT_EQ_F32_S32
- arm_VCVT_NE_F32_S32
- arm_VCVT_CS_F32_S32
- arm_VCVT_CC_F32_S32
- arm_VCVT_MI_F32_S32
- arm_VCVT_PL_F32_S32
- arm_VCVT_VS_F32_S32
- arm_VCVT_VC_F32_S32
- arm_VCVT_HI_F32_S32
- arm_VCVT_LS_F32_S32
- arm_VCVT_GE_F32_S32
- arm_VCVT_LT_F32_S32
- arm_VCVT_GT_F32_S32
- arm_VCVT_LE_F32_S32
- arm_VCVT_F32_S32
- arm_VCVT_ZZ_F32_S32
- arm_VCVT_EQ_F64_U32
- arm_VCVT_NE_F64_U32
- arm_VCVT_CS_F64_U32
- arm_VCVT_CC_F64_U32
- arm_VCVT_MI_F64_U32
- arm_VCVT_PL_F64_U32
- arm_VCVT_VS_F64_U32
- arm_VCVT_VC_F64_U32
- arm_VCVT_HI_F64_U32
- arm_VCVT_LS_F64_U32
- arm_VCVT_GE_F64_U32
- arm_VCVT_LT_F64_U32
- arm_VCVT_GT_F64_U32
- arm_VCVT_LE_F64_U32
- arm_VCVT_F64_U32
- arm_VCVT_ZZ_F64_U32
- arm_VCVT_EQ_F64_S32
- arm_VCVT_NE_F64_S32
- arm_VCVT_CS_F64_S32
- arm_VCVT_CC_F64_S32
- arm_VCVT_MI_F64_S32
- arm_VCVT_PL_F64_S32
- arm_VCVT_VS_F64_S32
- arm_VCVT_VC_F64_S32
- arm_VCVT_HI_F64_S32
- arm_VCVT_LS_F64_S32
- arm_VCVT_GE_F64_S32
- arm_VCVT_LT_F64_S32
- arm_VCVT_GT_F64_S32
- arm_VCVT_LE_F64_S32
- arm_VCVT_F64_S32
- arm_VCVT_ZZ_F64_S32
- arm_VCVT_EQ_F64_F32
- arm_VCVT_NE_F64_F32
- arm_VCVT_CS_F64_F32
- arm_VCVT_CC_F64_F32
- arm_VCVT_MI_F64_F32
- arm_VCVT_PL_F64_F32
- arm_VCVT_VS_F64_F32
- arm_VCVT_VC_F64_F32
- arm_VCVT_HI_F64_F32
- arm_VCVT_LS_F64_F32
- arm_VCVT_GE_F64_F32
- arm_VCVT_LT_F64_F32
- arm_VCVT_GT_F64_F32
- arm_VCVT_LE_F64_F32
- arm_VCVT_F64_F32
- arm_VCVT_ZZ_F64_F32
- arm_VCVT_EQ_F32_F64
- arm_VCVT_NE_F32_F64
- arm_VCVT_CS_F32_F64
- arm_VCVT_CC_F32_F64
- arm_VCVT_MI_F32_F64
- arm_VCVT_PL_F32_F64
- arm_VCVT_VS_F32_F64
- arm_VCVT_VC_F32_F64
- arm_VCVT_HI_F32_F64
- arm_VCVT_LS_F32_F64
- arm_VCVT_GE_F32_F64
- arm_VCVT_LT_F32_F64
- arm_VCVT_GT_F32_F64
- arm_VCVT_LE_F32_F64
- arm_VCVT_F32_F64
- arm_VCVT_ZZ_F32_F64
- arm_VCVT_EQ_FXS16_F32
- arm_VCVT_NE_FXS16_F32
- arm_VCVT_CS_FXS16_F32
- arm_VCVT_CC_FXS16_F32
- arm_VCVT_MI_FXS16_F32
- arm_VCVT_PL_FXS16_F32
- arm_VCVT_VS_FXS16_F32
- arm_VCVT_VC_FXS16_F32
- arm_VCVT_HI_FXS16_F32
- arm_VCVT_LS_FXS16_F32
- arm_VCVT_GE_FXS16_F32
- arm_VCVT_LT_FXS16_F32
- arm_VCVT_GT_FXS16_F32
- arm_VCVT_LE_FXS16_F32
- arm_VCVT_FXS16_F32
- arm_VCVT_ZZ_FXS16_F32
- arm_VCVT_EQ_FXS16_F64
- arm_VCVT_NE_FXS16_F64
- arm_VCVT_CS_FXS16_F64
- arm_VCVT_CC_FXS16_F64
- arm_VCVT_MI_FXS16_F64
- arm_VCVT_PL_FXS16_F64
- arm_VCVT_VS_FXS16_F64
- arm_VCVT_VC_FXS16_F64
- arm_VCVT_HI_FXS16_F64
- arm_VCVT_LS_FXS16_F64
- arm_VCVT_GE_FXS16_F64
- arm_VCVT_LT_FXS16_F64
- arm_VCVT_GT_FXS16_F64
- arm_VCVT_LE_FXS16_F64
- arm_VCVT_FXS16_F64
- arm_VCVT_ZZ_FXS16_F64
- arm_VCVT_EQ_FXS32_F32
- arm_VCVT_NE_FXS32_F32
- arm_VCVT_CS_FXS32_F32
- arm_VCVT_CC_FXS32_F32
- arm_VCVT_MI_FXS32_F32
- arm_VCVT_PL_FXS32_F32
- arm_VCVT_VS_FXS32_F32
- arm_VCVT_VC_FXS32_F32
- arm_VCVT_HI_FXS32_F32
- arm_VCVT_LS_FXS32_F32
- arm_VCVT_GE_FXS32_F32
- arm_VCVT_LT_FXS32_F32
- arm_VCVT_GT_FXS32_F32
- arm_VCVT_LE_FXS32_F32
- arm_VCVT_FXS32_F32
- arm_VCVT_ZZ_FXS32_F32
- arm_VCVT_EQ_FXS32_F64
- arm_VCVT_NE_FXS32_F64
- arm_VCVT_CS_FXS32_F64
- arm_VCVT_CC_FXS32_F64
- arm_VCVT_MI_FXS32_F64
- arm_VCVT_PL_FXS32_F64
- arm_VCVT_VS_FXS32_F64
- arm_VCVT_VC_FXS32_F64
- arm_VCVT_HI_FXS32_F64
- arm_VCVT_LS_FXS32_F64
- arm_VCVT_GE_FXS32_F64
- arm_VCVT_LT_FXS32_F64
- arm_VCVT_GT_FXS32_F64
- arm_VCVT_LE_FXS32_F64
- arm_VCVT_FXS32_F64
- arm_VCVT_ZZ_FXS32_F64
- arm_VCVT_EQ_FXU16_F32
- arm_VCVT_NE_FXU16_F32
- arm_VCVT_CS_FXU16_F32
- arm_VCVT_CC_FXU16_F32
- arm_VCVT_MI_FXU16_F32
- arm_VCVT_PL_FXU16_F32
- arm_VCVT_VS_FXU16_F32
- arm_VCVT_VC_FXU16_F32
- arm_VCVT_HI_FXU16_F32
- arm_VCVT_LS_FXU16_F32
- arm_VCVT_GE_FXU16_F32
- arm_VCVT_LT_FXU16_F32
- arm_VCVT_GT_FXU16_F32
- arm_VCVT_LE_FXU16_F32
- arm_VCVT_FXU16_F32
- arm_VCVT_ZZ_FXU16_F32
- arm_VCVT_EQ_FXU16_F64
- arm_VCVT_NE_FXU16_F64
- arm_VCVT_CS_FXU16_F64
- arm_VCVT_CC_FXU16_F64
- arm_VCVT_MI_FXU16_F64
- arm_VCVT_PL_FXU16_F64
- arm_VCVT_VS_FXU16_F64
- arm_VCVT_VC_FXU16_F64
- arm_VCVT_HI_FXU16_F64
- arm_VCVT_LS_FXU16_F64
- arm_VCVT_GE_FXU16_F64
- arm_VCVT_LT_FXU16_F64
- arm_VCVT_GT_FXU16_F64
- arm_VCVT_LE_FXU16_F64
- arm_VCVT_FXU16_F64
- arm_VCVT_ZZ_FXU16_F64
- arm_VCVT_EQ_FXU32_F32
- arm_VCVT_NE_FXU32_F32
- arm_VCVT_CS_FXU32_F32
- arm_VCVT_CC_FXU32_F32
- arm_VCVT_MI_FXU32_F32
- arm_VCVT_PL_FXU32_F32
- arm_VCVT_VS_FXU32_F32
- arm_VCVT_VC_FXU32_F32
- arm_VCVT_HI_FXU32_F32
- arm_VCVT_LS_FXU32_F32
- arm_VCVT_GE_FXU32_F32
- arm_VCVT_LT_FXU32_F32
- arm_VCVT_GT_FXU32_F32
- arm_VCVT_LE_FXU32_F32
- arm_VCVT_FXU32_F32
- arm_VCVT_ZZ_FXU32_F32
- arm_VCVT_EQ_FXU32_F64
- arm_VCVT_NE_FXU32_F64
- arm_VCVT_CS_FXU32_F64
- arm_VCVT_CC_FXU32_F64
- arm_VCVT_MI_FXU32_F64
- arm_VCVT_PL_FXU32_F64
- arm_VCVT_VS_FXU32_F64
- arm_VCVT_VC_FXU32_F64
- arm_VCVT_HI_FXU32_F64
- arm_VCVT_LS_FXU32_F64
- arm_VCVT_GE_FXU32_F64
- arm_VCVT_LT_FXU32_F64
- arm_VCVT_GT_FXU32_F64
- arm_VCVT_LE_FXU32_F64
- arm_VCVT_FXU32_F64
- arm_VCVT_ZZ_FXU32_F64
- arm_VCVTB_EQ_F32_F16
- arm_VCVTB_NE_F32_F16
- arm_VCVTB_CS_F32_F16
- arm_VCVTB_CC_F32_F16
- arm_VCVTB_MI_F32_F16
- arm_VCVTB_PL_F32_F16
- arm_VCVTB_VS_F32_F16
- arm_VCVTB_VC_F32_F16
- arm_VCVTB_HI_F32_F16
- arm_VCVTB_LS_F32_F16
- arm_VCVTB_GE_F32_F16
- arm_VCVTB_LT_F32_F16
- arm_VCVTB_GT_F32_F16
- arm_VCVTB_LE_F32_F16
- arm_VCVTB_F32_F16
- arm_VCVTB_ZZ_F32_F16
- arm_VCVTB_EQ_F16_F32
- arm_VCVTB_NE_F16_F32
- arm_VCVTB_CS_F16_F32
- arm_VCVTB_CC_F16_F32
- arm_VCVTB_MI_F16_F32
- arm_VCVTB_PL_F16_F32
- arm_VCVTB_VS_F16_F32
- arm_VCVTB_VC_F16_F32
- arm_VCVTB_HI_F16_F32
- arm_VCVTB_LS_F16_F32
- arm_VCVTB_GE_F16_F32
- arm_VCVTB_LT_F16_F32
- arm_VCVTB_GT_F16_F32
- arm_VCVTB_LE_F16_F32
- arm_VCVTB_F16_F32
- arm_VCVTB_ZZ_F16_F32
- arm_VCVTT_EQ_F32_F16
- arm_VCVTT_NE_F32_F16
- arm_VCVTT_CS_F32_F16
- arm_VCVTT_CC_F32_F16
- arm_VCVTT_MI_F32_F16
- arm_VCVTT_PL_F32_F16
- arm_VCVTT_VS_F32_F16
- arm_VCVTT_VC_F32_F16
- arm_VCVTT_HI_F32_F16
- arm_VCVTT_LS_F32_F16
- arm_VCVTT_GE_F32_F16
- arm_VCVTT_LT_F32_F16
- arm_VCVTT_GT_F32_F16
- arm_VCVTT_LE_F32_F16
- arm_VCVTT_F32_F16
- arm_VCVTT_ZZ_F32_F16
- arm_VCVTT_EQ_F16_F32
- arm_VCVTT_NE_F16_F32
- arm_VCVTT_CS_F16_F32
- arm_VCVTT_CC_F16_F32
- arm_VCVTT_MI_F16_F32
- arm_VCVTT_PL_F16_F32
- arm_VCVTT_VS_F16_F32
- arm_VCVTT_VC_F16_F32
- arm_VCVTT_HI_F16_F32
- arm_VCVTT_LS_F16_F32
- arm_VCVTT_GE_F16_F32
- arm_VCVTT_LT_F16_F32
- arm_VCVTT_GT_F16_F32
- arm_VCVTT_LE_F16_F32
- arm_VCVTT_F16_F32
- arm_VCVTT_ZZ_F16_F32
- arm_VCVTR_EQ_U32_F32
- arm_VCVTR_NE_U32_F32
- arm_VCVTR_CS_U32_F32
- arm_VCVTR_CC_U32_F32
- arm_VCVTR_MI_U32_F32
- arm_VCVTR_PL_U32_F32
- arm_VCVTR_VS_U32_F32
- arm_VCVTR_VC_U32_F32
- arm_VCVTR_HI_U32_F32
- arm_VCVTR_LS_U32_F32
- arm_VCVTR_GE_U32_F32
- arm_VCVTR_LT_U32_F32
- arm_VCVTR_GT_U32_F32
- arm_VCVTR_LE_U32_F32
- arm_VCVTR_U32_F32
- arm_VCVTR_ZZ_U32_F32
- arm_VCVTR_EQ_U32_F64
- arm_VCVTR_NE_U32_F64
- arm_VCVTR_CS_U32_F64
- arm_VCVTR_CC_U32_F64
- arm_VCVTR_MI_U32_F64
- arm_VCVTR_PL_U32_F64
- arm_VCVTR_VS_U32_F64
- arm_VCVTR_VC_U32_F64
- arm_VCVTR_HI_U32_F64
- arm_VCVTR_LS_U32_F64
- arm_VCVTR_GE_U32_F64
- arm_VCVTR_LT_U32_F64
- arm_VCVTR_GT_U32_F64
- arm_VCVTR_LE_U32_F64
- arm_VCVTR_U32_F64
- arm_VCVTR_ZZ_U32_F64
- arm_VCVTR_EQ_S32_F32
- arm_VCVTR_NE_S32_F32
- arm_VCVTR_CS_S32_F32
- arm_VCVTR_CC_S32_F32
- arm_VCVTR_MI_S32_F32
- arm_VCVTR_PL_S32_F32
- arm_VCVTR_VS_S32_F32
- arm_VCVTR_VC_S32_F32
- arm_VCVTR_HI_S32_F32
- arm_VCVTR_LS_S32_F32
- arm_VCVTR_GE_S32_F32
- arm_VCVTR_LT_S32_F32
- arm_VCVTR_GT_S32_F32
- arm_VCVTR_LE_S32_F32
- arm_VCVTR_S32_F32
- arm_VCVTR_ZZ_S32_F32
- arm_VCVTR_EQ_S32_F64
- arm_VCVTR_NE_S32_F64
- arm_VCVTR_CS_S32_F64
- arm_VCVTR_CC_S32_F64
- arm_VCVTR_MI_S32_F64
- arm_VCVTR_PL_S32_F64
- arm_VCVTR_VS_S32_F64
- arm_VCVTR_VC_S32_F64
- arm_VCVTR_HI_S32_F64
- arm_VCVTR_LS_S32_F64
- arm_VCVTR_GE_S32_F64
- arm_VCVTR_LT_S32_F64
- arm_VCVTR_GT_S32_F64
- arm_VCVTR_LE_S32_F64
- arm_VCVTR_S32_F64
- arm_VCVTR_ZZ_S32_F64
- arm_VCVT_EQ_U32_F32
- arm_VCVT_NE_U32_F32
- arm_VCVT_CS_U32_F32
- arm_VCVT_CC_U32_F32
- arm_VCVT_MI_U32_F32
- arm_VCVT_PL_U32_F32
- arm_VCVT_VS_U32_F32
- arm_VCVT_VC_U32_F32
- arm_VCVT_HI_U32_F32
- arm_VCVT_LS_U32_F32
- arm_VCVT_GE_U32_F32
- arm_VCVT_LT_U32_F32
- arm_VCVT_GT_U32_F32
- arm_VCVT_LE_U32_F32
- arm_VCVT_U32_F32
- arm_VCVT_ZZ_U32_F32
- arm_VCVT_EQ_U32_F64
- arm_VCVT_NE_U32_F64
- arm_VCVT_CS_U32_F64
- arm_VCVT_CC_U32_F64
- arm_VCVT_MI_U32_F64
- arm_VCVT_PL_U32_F64
- arm_VCVT_VS_U32_F64
- arm_VCVT_VC_U32_F64
- arm_VCVT_HI_U32_F64
- arm_VCVT_LS_U32_F64
- arm_VCVT_GE_U32_F64
- arm_VCVT_LT_U32_F64
- arm_VCVT_GT_U32_F64
- arm_VCVT_LE_U32_F64
- arm_VCVT_U32_F64
- arm_VCVT_ZZ_U32_F64
- arm_VCVT_EQ_S32_F32
- arm_VCVT_NE_S32_F32
- arm_VCVT_CS_S32_F32
- arm_VCVT_CC_S32_F32
- arm_VCVT_MI_S32_F32
- arm_VCVT_PL_S32_F32
- arm_VCVT_VS_S32_F32
- arm_VCVT_VC_S32_F32
- arm_VCVT_HI_S32_F32
- arm_VCVT_LS_S32_F32
- arm_VCVT_GE_S32_F32
- arm_VCVT_LT_S32_F32
- arm_VCVT_GT_S32_F32
- arm_VCVT_LE_S32_F32
- arm_VCVT_S32_F32
- arm_VCVT_ZZ_S32_F32
- arm_VCVT_EQ_S32_F64
- arm_VCVT_NE_S32_F64
- arm_VCVT_CS_S32_F64
- arm_VCVT_CC_S32_F64
- arm_VCVT_MI_S32_F64
- arm_VCVT_PL_S32_F64
- arm_VCVT_VS_S32_F64
- arm_VCVT_VC_S32_F64
- arm_VCVT_HI_S32_F64
- arm_VCVT_LS_S32_F64
- arm_VCVT_GE_S32_F64
- arm_VCVT_LT_S32_F64
- arm_VCVT_GT_S32_F64
- arm_VCVT_LE_S32_F64
- arm_VCVT_S32_F64
- arm_VCVT_ZZ_S32_F64
- arm_VDIV_EQ_F32
- arm_VDIV_NE_F32
- arm_VDIV_CS_F32
- arm_VDIV_CC_F32
- arm_VDIV_MI_F32
- arm_VDIV_PL_F32
- arm_VDIV_VS_F32
- arm_VDIV_VC_F32
- arm_VDIV_HI_F32
- arm_VDIV_LS_F32
- arm_VDIV_GE_F32
- arm_VDIV_LT_F32
- arm_VDIV_GT_F32
- arm_VDIV_LE_F32
- arm_VDIV_F32
- arm_VDIV_ZZ_F32
- arm_VDIV_EQ_F64
- arm_VDIV_NE_F64
- arm_VDIV_CS_F64
- arm_VDIV_CC_F64
- arm_VDIV_MI_F64
- arm_VDIV_PL_F64
- arm_VDIV_VS_F64
- arm_VDIV_VC_F64
- arm_VDIV_HI_F64
- arm_VDIV_LS_F64
- arm_VDIV_GE_F64
- arm_VDIV_LT_F64
- arm_VDIV_GT_F64
- arm_VDIV_LE_F64
- arm_VDIV_F64
- arm_VDIV_ZZ_F64
- arm_VLDR_EQ
- arm_VLDR_NE
- arm_VLDR_CS
- arm_VLDR_CC
- arm_VLDR_MI
- arm_VLDR_PL
- arm_VLDR_VS
- arm_VLDR_VC
- arm_VLDR_HI
- arm_VLDR_LS
- arm_VLDR_GE
- arm_VLDR_LT
- arm_VLDR_GT
- arm_VLDR_LE
- arm_VLDR
- arm_VLDR_ZZ
- arm_VMLA_EQ_F32
- arm_VMLA_NE_F32
- arm_VMLA_CS_F32
- arm_VMLA_CC_F32
- arm_VMLA_MI_F32
- arm_VMLA_PL_F32
- arm_VMLA_VS_F32
- arm_VMLA_VC_F32
- arm_VMLA_HI_F32
- arm_VMLA_LS_F32
- arm_VMLA_GE_F32
- arm_VMLA_LT_F32
- arm_VMLA_GT_F32
- arm_VMLA_LE_F32
- arm_VMLA_F32
- arm_VMLA_ZZ_F32
- arm_VMLA_EQ_F64
- arm_VMLA_NE_F64
- arm_VMLA_CS_F64
- arm_VMLA_CC_F64
- arm_VMLA_MI_F64
- arm_VMLA_PL_F64
- arm_VMLA_VS_F64
- arm_VMLA_VC_F64
- arm_VMLA_HI_F64
- arm_VMLA_LS_F64
- arm_VMLA_GE_F64
- arm_VMLA_LT_F64
- arm_VMLA_GT_F64
- arm_VMLA_LE_F64
- arm_VMLA_F64
- arm_VMLA_ZZ_F64
- arm_VMLS_EQ_F32
- arm_VMLS_NE_F32
- arm_VMLS_CS_F32
- arm_VMLS_CC_F32
- arm_VMLS_MI_F32
- arm_VMLS_PL_F32
- arm_VMLS_VS_F32
- arm_VMLS_VC_F32
- arm_VMLS_HI_F32
- arm_VMLS_LS_F32
- arm_VMLS_GE_F32
- arm_VMLS_LT_F32
- arm_VMLS_GT_F32
- arm_VMLS_LE_F32
- arm_VMLS_F32
- arm_VMLS_ZZ_F32
- arm_VMLS_EQ_F64
- arm_VMLS_NE_F64
- arm_VMLS_CS_F64
- arm_VMLS_CC_F64
- arm_VMLS_MI_F64
- arm_VMLS_PL_F64
- arm_VMLS_VS_F64
- arm_VMLS_VC_F64
- arm_VMLS_HI_F64
- arm_VMLS_LS_F64
- arm_VMLS_GE_F64
- arm_VMLS_LT_F64
- arm_VMLS_GT_F64
- arm_VMLS_LE_F64
- arm_VMLS_F64
- arm_VMLS_ZZ_F64
- arm_VMOV_EQ
- arm_VMOV_NE
- arm_VMOV_CS
- arm_VMOV_CC
- arm_VMOV_MI
- arm_VMOV_PL
- arm_VMOV_VS
- arm_VMOV_VC
- arm_VMOV_HI
- arm_VMOV_LS
- arm_VMOV_GE
- arm_VMOV_LT
- arm_VMOV_GT
- arm_VMOV_LE
- arm_VMOV
- arm_VMOV_ZZ
- arm_VMOV_EQ_32
- arm_VMOV_NE_32
- arm_VMOV_CS_32
- arm_VMOV_CC_32
- arm_VMOV_MI_32
- arm_VMOV_PL_32
- arm_VMOV_VS_32
- arm_VMOV_VC_32
- arm_VMOV_HI_32
- arm_VMOV_LS_32
- arm_VMOV_GE_32
- arm_VMOV_LT_32
- arm_VMOV_GT_32
- arm_VMOV_LE_32
- arm_VMOV_32
- arm_VMOV_ZZ_32
- arm_VMOV_EQ_F32
- arm_VMOV_NE_F32
- arm_VMOV_CS_F32
- arm_VMOV_CC_F32
- arm_VMOV_MI_F32
- arm_VMOV_PL_F32
- arm_VMOV_VS_F32
- arm_VMOV_VC_F32
- arm_VMOV_HI_F32
- arm_VMOV_LS_F32
- arm_VMOV_GE_F32
- arm_VMOV_LT_F32
- arm_VMOV_GT_F32
- arm_VMOV_LE_F32
- arm_VMOV_F32
- arm_VMOV_ZZ_F32
- arm_VMOV_EQ_F64
- arm_VMOV_NE_F64
- arm_VMOV_CS_F64
- arm_VMOV_CC_F64
- arm_VMOV_MI_F64
- arm_VMOV_PL_F64
- arm_VMOV_VS_F64
- arm_VMOV_VC_F64
- arm_VMOV_HI_F64
- arm_VMOV_LS_F64
- arm_VMOV_GE_F64
- arm_VMOV_LT_F64
- arm_VMOV_GT_F64
- arm_VMOV_LE_F64
- arm_VMOV_F64
- arm_VMOV_ZZ_F64
- arm_VMRS_EQ
- arm_VMRS_NE
- arm_VMRS_CS
- arm_VMRS_CC
- arm_VMRS_MI
- arm_VMRS_PL
- arm_VMRS_VS
- arm_VMRS_VC
- arm_VMRS_HI
- arm_VMRS_LS
- arm_VMRS_GE
- arm_VMRS_LT
- arm_VMRS_GT
- arm_VMRS_LE
- arm_VMRS
- arm_VMRS_ZZ
- arm_VMSR_EQ
- arm_VMSR_NE
- arm_VMSR_CS
- arm_VMSR_CC
- arm_VMSR_MI
- arm_VMSR_PL
- arm_VMSR_VS
- arm_VMSR_VC
- arm_VMSR_HI
- arm_VMSR_LS
- arm_VMSR_GE
- arm_VMSR_LT
- arm_VMSR_GT
- arm_VMSR_LE
- arm_VMSR
- arm_VMSR_ZZ
- arm_VMUL_EQ_F32
- arm_VMUL_NE_F32
- arm_VMUL_CS_F32
- arm_VMUL_CC_F32
- arm_VMUL_MI_F32
- arm_VMUL_PL_F32
- arm_VMUL_VS_F32
- arm_VMUL_VC_F32
- arm_VMUL_HI_F32
- arm_VMUL_LS_F32
- arm_VMUL_GE_F32
- arm_VMUL_LT_F32
- arm_VMUL_GT_F32
- arm_VMUL_LE_F32
- arm_VMUL_F32
- arm_VMUL_ZZ_F32
- arm_VMUL_EQ_F64
- arm_VMUL_NE_F64
- arm_VMUL_CS_F64
- arm_VMUL_CC_F64
- arm_VMUL_MI_F64
- arm_VMUL_PL_F64
- arm_VMUL_VS_F64
- arm_VMUL_VC_F64
- arm_VMUL_HI_F64
- arm_VMUL_LS_F64
- arm_VMUL_GE_F64
- arm_VMUL_LT_F64
- arm_VMUL_GT_F64
- arm_VMUL_LE_F64
- arm_VMUL_F64
- arm_VMUL_ZZ_F64
- arm_VNEG_EQ_F32
- arm_VNEG_NE_F32
- arm_VNEG_CS_F32
- arm_VNEG_CC_F32
- arm_VNEG_MI_F32
- arm_VNEG_PL_F32
- arm_VNEG_VS_F32
- arm_VNEG_VC_F32
- arm_VNEG_HI_F32
- arm_VNEG_LS_F32
- arm_VNEG_GE_F32
- arm_VNEG_LT_F32
- arm_VNEG_GT_F32
- arm_VNEG_LE_F32
- arm_VNEG_F32
- arm_VNEG_ZZ_F32
- arm_VNEG_EQ_F64
- arm_VNEG_NE_F64
- arm_VNEG_CS_F64
- arm_VNEG_CC_F64
- arm_VNEG_MI_F64
- arm_VNEG_PL_F64
- arm_VNEG_VS_F64
- arm_VNEG_VC_F64
- arm_VNEG_HI_F64
- arm_VNEG_LS_F64
- arm_VNEG_GE_F64
- arm_VNEG_LT_F64
- arm_VNEG_GT_F64
- arm_VNEG_LE_F64
- arm_VNEG_F64
- arm_VNEG_ZZ_F64
- arm_VNMLS_EQ_F32
- arm_VNMLS_NE_F32
- arm_VNMLS_CS_F32
- arm_VNMLS_CC_F32
- arm_VNMLS_MI_F32
- arm_VNMLS_PL_F32
- arm_VNMLS_VS_F32
- arm_VNMLS_VC_F32
- arm_VNMLS_HI_F32
- arm_VNMLS_LS_F32
- arm_VNMLS_GE_F32
- arm_VNMLS_LT_F32
- arm_VNMLS_GT_F32
- arm_VNMLS_LE_F32
- arm_VNMLS_F32
- arm_VNMLS_ZZ_F32
- arm_VNMLS_EQ_F64
- arm_VNMLS_NE_F64
- arm_VNMLS_CS_F64
- arm_VNMLS_CC_F64
- arm_VNMLS_MI_F64
- arm_VNMLS_PL_F64
- arm_VNMLS_VS_F64
- arm_VNMLS_VC_F64
- arm_VNMLS_HI_F64
- arm_VNMLS_LS_F64
- arm_VNMLS_GE_F64
- arm_VNMLS_LT_F64
- arm_VNMLS_GT_F64
- arm_VNMLS_LE_F64
- arm_VNMLS_F64
- arm_VNMLS_ZZ_F64
- arm_VNMLA_EQ_F32
- arm_VNMLA_NE_F32
- arm_VNMLA_CS_F32
- arm_VNMLA_CC_F32
- arm_VNMLA_MI_F32
- arm_VNMLA_PL_F32
- arm_VNMLA_VS_F32
- arm_VNMLA_VC_F32
- arm_VNMLA_HI_F32
- arm_VNMLA_LS_F32
- arm_VNMLA_GE_F32
- arm_VNMLA_LT_F32
- arm_VNMLA_GT_F32
- arm_VNMLA_LE_F32
- arm_VNMLA_F32
- arm_VNMLA_ZZ_F32
- arm_VNMLA_EQ_F64
- arm_VNMLA_NE_F64
- arm_VNMLA_CS_F64
- arm_VNMLA_CC_F64
- arm_VNMLA_MI_F64
- arm_VNMLA_PL_F64
- arm_VNMLA_VS_F64
- arm_VNMLA_VC_F64
- arm_VNMLA_HI_F64
- arm_VNMLA_LS_F64
- arm_VNMLA_GE_F64
- arm_VNMLA_LT_F64
- arm_VNMLA_GT_F64
- arm_VNMLA_LE_F64
- arm_VNMLA_F64
- arm_VNMLA_ZZ_F64
- arm_VNMUL_EQ_F32
- arm_VNMUL_NE_F32
- arm_VNMUL_CS_F32
- arm_VNMUL_CC_F32
- arm_VNMUL_MI_F32
- arm_VNMUL_PL_F32
- arm_VNMUL_VS_F32
- arm_VNMUL_VC_F32
- arm_VNMUL_HI_F32
- arm_VNMUL_LS_F32
- arm_VNMUL_GE_F32
- arm_VNMUL_LT_F32
- arm_VNMUL_GT_F32
- arm_VNMUL_LE_F32
- arm_VNMUL_F32
- arm_VNMUL_ZZ_F32
- arm_VNMUL_EQ_F64
- arm_VNMUL_NE_F64
- arm_VNMUL_CS_F64
- arm_VNMUL_CC_F64
- arm_VNMUL_MI_F64
- arm_VNMUL_PL_F64
- arm_VNMUL_VS_F64
- arm_VNMUL_VC_F64
- arm_VNMUL_HI_F64
- arm_VNMUL_LS_F64
- arm_VNMUL_GE_F64
- arm_VNMUL_LT_F64
- arm_VNMUL_GT_F64
- arm_VNMUL_LE_F64
- arm_VNMUL_F64
- arm_VNMUL_ZZ_F64
- arm_VSQRT_EQ_F32
- arm_VSQRT_NE_F32
- arm_VSQRT_CS_F32
- arm_VSQRT_CC_F32
- arm_VSQRT_MI_F32
- arm_VSQRT_PL_F32
- arm_VSQRT_VS_F32
- arm_VSQRT_VC_F32
- arm_VSQRT_HI_F32
- arm_VSQRT_LS_F32
- arm_VSQRT_GE_F32
- arm_VSQRT_LT_F32
- arm_VSQRT_GT_F32
- arm_VSQRT_LE_F32
- arm_VSQRT_F32
- arm_VSQRT_ZZ_F32
- arm_VSQRT_EQ_F64
- arm_VSQRT_NE_F64
- arm_VSQRT_CS_F64
- arm_VSQRT_CC_F64
- arm_VSQRT_MI_F64
- arm_VSQRT_PL_F64
- arm_VSQRT_VS_F64
- arm_VSQRT_VC_F64
- arm_VSQRT_HI_F64
- arm_VSQRT_LS_F64
- arm_VSQRT_GE_F64
- arm_VSQRT_LT_F64
- arm_VSQRT_GT_F64
- arm_VSQRT_LE_F64
- arm_VSQRT_F64
- arm_VSQRT_ZZ_F64
- arm_VSTR_EQ
- arm_VSTR_NE
- arm_VSTR_CS
- arm_VSTR_CC
- arm_VSTR_MI
- arm_VSTR_PL
- arm_VSTR_VS
- arm_VSTR_VC
- arm_VSTR_HI
- arm_VSTR_LS
- arm_VSTR_GE
- arm_VSTR_LT
- arm_VSTR_GT
- arm_VSTR_LE
- arm_VSTR
- arm_VSTR_ZZ
- arm_VSUB_EQ_F32
- arm_VSUB_NE_F32
- arm_VSUB_CS_F32
- arm_VSUB_CC_F32
- arm_VSUB_MI_F32
- arm_VSUB_PL_F32
- arm_VSUB_VS_F32
- arm_VSUB_VC_F32
- arm_VSUB_HI_F32
- arm_VSUB_LS_F32
- arm_VSUB_GE_F32
- arm_VSUB_LT_F32
- arm_VSUB_GT_F32
- arm_VSUB_LE_F32
- arm_VSUB_F32
- arm_VSUB_ZZ_F32
- arm_VSUB_EQ_F64
- arm_VSUB_NE_F64
- arm_VSUB_CS_F64
- arm_VSUB_CC_F64
- arm_VSUB_MI_F64
- arm_VSUB_PL_F64
- arm_VSUB_VS_F64
- arm_VSUB_VC_F64
- arm_VSUB_HI_F64
- arm_VSUB_LS_F64
- arm_VSUB_GE_F64
- arm_VSUB_LT_F64
- arm_VSUB_GT_F64
- arm_VSUB_LE_F64
- arm_VSUB_F64
- arm_VSUB_ZZ_F64
- arm_WFE_EQ
- arm_WFE_NE
- arm_WFE_CS
- arm_WFE_CC
- arm_WFE_MI
- arm_WFE_PL
- arm_WFE_VS
- arm_WFE_VC
- arm_WFE_HI
- arm_WFE_LS
- arm_WFE_GE
- arm_WFE_LT
- arm_WFE_GT
- arm_WFE_LE
- arm_WFE
- arm_WFE_ZZ
- arm_WFI_EQ
- arm_WFI_NE
- arm_WFI_CS
- arm_WFI_CC
- arm_WFI_MI
- arm_WFI_PL
- arm_WFI_VS
- arm_WFI_VC
- arm_WFI_HI
- arm_WFI_LS
- arm_WFI_GE
- arm_WFI_LT
- arm_WFI_GT
- arm_WFI_LE
- arm_WFI
- arm_WFI_ZZ
- arm_YIELD_EQ
- arm_YIELD_NE
- arm_YIELD_CS
- arm_YIELD_CC
- arm_YIELD_MI
- arm_YIELD_PL
- arm_YIELD_VS
- arm_YIELD_VC
- arm_YIELD_HI
- arm_YIELD_LS
- arm_YIELD_GE
- arm_YIELD_LT
- arm_YIELD_GT
- arm_YIELD_LE
- arm_YIELD
- arm_YIELD_ZZ
-)
-
-var arm_opstr = [...]string{
- arm_ADC_EQ: "ADC.EQ",
- arm_ADC_NE: "ADC.NE",
- arm_ADC_CS: "ADC.CS",
- arm_ADC_CC: "ADC.CC",
- arm_ADC_MI: "ADC.MI",
- arm_ADC_PL: "ADC.PL",
- arm_ADC_VS: "ADC.VS",
- arm_ADC_VC: "ADC.VC",
- arm_ADC_HI: "ADC.HI",
- arm_ADC_LS: "ADC.LS",
- arm_ADC_GE: "ADC.GE",
- arm_ADC_LT: "ADC.LT",
- arm_ADC_GT: "ADC.GT",
- arm_ADC_LE: "ADC.LE",
- arm_ADC: "ADC",
- arm_ADC_ZZ: "ADC.ZZ",
- arm_ADC_S_EQ: "ADC.S.EQ",
- arm_ADC_S_NE: "ADC.S.NE",
- arm_ADC_S_CS: "ADC.S.CS",
- arm_ADC_S_CC: "ADC.S.CC",
- arm_ADC_S_MI: "ADC.S.MI",
- arm_ADC_S_PL: "ADC.S.PL",
- arm_ADC_S_VS: "ADC.S.VS",
- arm_ADC_S_VC: "ADC.S.VC",
- arm_ADC_S_HI: "ADC.S.HI",
- arm_ADC_S_LS: "ADC.S.LS",
- arm_ADC_S_GE: "ADC.S.GE",
- arm_ADC_S_LT: "ADC.S.LT",
- arm_ADC_S_GT: "ADC.S.GT",
- arm_ADC_S_LE: "ADC.S.LE",
- arm_ADC_S: "ADC.S",
- arm_ADC_S_ZZ: "ADC.S.ZZ",
- arm_ADD_EQ: "ADD.EQ",
- arm_ADD_NE: "ADD.NE",
- arm_ADD_CS: "ADD.CS",
- arm_ADD_CC: "ADD.CC",
- arm_ADD_MI: "ADD.MI",
- arm_ADD_PL: "ADD.PL",
- arm_ADD_VS: "ADD.VS",
- arm_ADD_VC: "ADD.VC",
- arm_ADD_HI: "ADD.HI",
- arm_ADD_LS: "ADD.LS",
- arm_ADD_GE: "ADD.GE",
- arm_ADD_LT: "ADD.LT",
- arm_ADD_GT: "ADD.GT",
- arm_ADD_LE: "ADD.LE",
- arm_ADD: "ADD",
- arm_ADD_ZZ: "ADD.ZZ",
- arm_ADD_S_EQ: "ADD.S.EQ",
- arm_ADD_S_NE: "ADD.S.NE",
- arm_ADD_S_CS: "ADD.S.CS",
- arm_ADD_S_CC: "ADD.S.CC",
- arm_ADD_S_MI: "ADD.S.MI",
- arm_ADD_S_PL: "ADD.S.PL",
- arm_ADD_S_VS: "ADD.S.VS",
- arm_ADD_S_VC: "ADD.S.VC",
- arm_ADD_S_HI: "ADD.S.HI",
- arm_ADD_S_LS: "ADD.S.LS",
- arm_ADD_S_GE: "ADD.S.GE",
- arm_ADD_S_LT: "ADD.S.LT",
- arm_ADD_S_GT: "ADD.S.GT",
- arm_ADD_S_LE: "ADD.S.LE",
- arm_ADD_S: "ADD.S",
- arm_ADD_S_ZZ: "ADD.S.ZZ",
- arm_AND_EQ: "AND.EQ",
- arm_AND_NE: "AND.NE",
- arm_AND_CS: "AND.CS",
- arm_AND_CC: "AND.CC",
- arm_AND_MI: "AND.MI",
- arm_AND_PL: "AND.PL",
- arm_AND_VS: "AND.VS",
- arm_AND_VC: "AND.VC",
- arm_AND_HI: "AND.HI",
- arm_AND_LS: "AND.LS",
- arm_AND_GE: "AND.GE",
- arm_AND_LT: "AND.LT",
- arm_AND_GT: "AND.GT",
- arm_AND_LE: "AND.LE",
- arm_AND: "AND",
- arm_AND_ZZ: "AND.ZZ",
- arm_AND_S_EQ: "AND.S.EQ",
- arm_AND_S_NE: "AND.S.NE",
- arm_AND_S_CS: "AND.S.CS",
- arm_AND_S_CC: "AND.S.CC",
- arm_AND_S_MI: "AND.S.MI",
- arm_AND_S_PL: "AND.S.PL",
- arm_AND_S_VS: "AND.S.VS",
- arm_AND_S_VC: "AND.S.VC",
- arm_AND_S_HI: "AND.S.HI",
- arm_AND_S_LS: "AND.S.LS",
- arm_AND_S_GE: "AND.S.GE",
- arm_AND_S_LT: "AND.S.LT",
- arm_AND_S_GT: "AND.S.GT",
- arm_AND_S_LE: "AND.S.LE",
- arm_AND_S: "AND.S",
- arm_AND_S_ZZ: "AND.S.ZZ",
- arm_ASR_EQ: "ASR.EQ",
- arm_ASR_NE: "ASR.NE",
- arm_ASR_CS: "ASR.CS",
- arm_ASR_CC: "ASR.CC",
- arm_ASR_MI: "ASR.MI",
- arm_ASR_PL: "ASR.PL",
- arm_ASR_VS: "ASR.VS",
- arm_ASR_VC: "ASR.VC",
- arm_ASR_HI: "ASR.HI",
- arm_ASR_LS: "ASR.LS",
- arm_ASR_GE: "ASR.GE",
- arm_ASR_LT: "ASR.LT",
- arm_ASR_GT: "ASR.GT",
- arm_ASR_LE: "ASR.LE",
- arm_ASR: "ASR",
- arm_ASR_ZZ: "ASR.ZZ",
- arm_ASR_S_EQ: "ASR.S.EQ",
- arm_ASR_S_NE: "ASR.S.NE",
- arm_ASR_S_CS: "ASR.S.CS",
- arm_ASR_S_CC: "ASR.S.CC",
- arm_ASR_S_MI: "ASR.S.MI",
- arm_ASR_S_PL: "ASR.S.PL",
- arm_ASR_S_VS: "ASR.S.VS",
- arm_ASR_S_VC: "ASR.S.VC",
- arm_ASR_S_HI: "ASR.S.HI",
- arm_ASR_S_LS: "ASR.S.LS",
- arm_ASR_S_GE: "ASR.S.GE",
- arm_ASR_S_LT: "ASR.S.LT",
- arm_ASR_S_GT: "ASR.S.GT",
- arm_ASR_S_LE: "ASR.S.LE",
- arm_ASR_S: "ASR.S",
- arm_ASR_S_ZZ: "ASR.S.ZZ",
- arm_B_EQ: "B.EQ",
- arm_B_NE: "B.NE",
- arm_B_CS: "B.CS",
- arm_B_CC: "B.CC",
- arm_B_MI: "B.MI",
- arm_B_PL: "B.PL",
- arm_B_VS: "B.VS",
- arm_B_VC: "B.VC",
- arm_B_HI: "B.HI",
- arm_B_LS: "B.LS",
- arm_B_GE: "B.GE",
- arm_B_LT: "B.LT",
- arm_B_GT: "B.GT",
- arm_B_LE: "B.LE",
- arm_B: "B",
- arm_B_ZZ: "B.ZZ",
- arm_BFC_EQ: "BFC.EQ",
- arm_BFC_NE: "BFC.NE",
- arm_BFC_CS: "BFC.CS",
- arm_BFC_CC: "BFC.CC",
- arm_BFC_MI: "BFC.MI",
- arm_BFC_PL: "BFC.PL",
- arm_BFC_VS: "BFC.VS",
- arm_BFC_VC: "BFC.VC",
- arm_BFC_HI: "BFC.HI",
- arm_BFC_LS: "BFC.LS",
- arm_BFC_GE: "BFC.GE",
- arm_BFC_LT: "BFC.LT",
- arm_BFC_GT: "BFC.GT",
- arm_BFC_LE: "BFC.LE",
- arm_BFC: "BFC",
- arm_BFC_ZZ: "BFC.ZZ",
- arm_BFI_EQ: "BFI.EQ",
- arm_BFI_NE: "BFI.NE",
- arm_BFI_CS: "BFI.CS",
- arm_BFI_CC: "BFI.CC",
- arm_BFI_MI: "BFI.MI",
- arm_BFI_PL: "BFI.PL",
- arm_BFI_VS: "BFI.VS",
- arm_BFI_VC: "BFI.VC",
- arm_BFI_HI: "BFI.HI",
- arm_BFI_LS: "BFI.LS",
- arm_BFI_GE: "BFI.GE",
- arm_BFI_LT: "BFI.LT",
- arm_BFI_GT: "BFI.GT",
- arm_BFI_LE: "BFI.LE",
- arm_BFI: "BFI",
- arm_BFI_ZZ: "BFI.ZZ",
- arm_BIC_EQ: "BIC.EQ",
- arm_BIC_NE: "BIC.NE",
- arm_BIC_CS: "BIC.CS",
- arm_BIC_CC: "BIC.CC",
- arm_BIC_MI: "BIC.MI",
- arm_BIC_PL: "BIC.PL",
- arm_BIC_VS: "BIC.VS",
- arm_BIC_VC: "BIC.VC",
- arm_BIC_HI: "BIC.HI",
- arm_BIC_LS: "BIC.LS",
- arm_BIC_GE: "BIC.GE",
- arm_BIC_LT: "BIC.LT",
- arm_BIC_GT: "BIC.GT",
- arm_BIC_LE: "BIC.LE",
- arm_BIC: "BIC",
- arm_BIC_ZZ: "BIC.ZZ",
- arm_BIC_S_EQ: "BIC.S.EQ",
- arm_BIC_S_NE: "BIC.S.NE",
- arm_BIC_S_CS: "BIC.S.CS",
- arm_BIC_S_CC: "BIC.S.CC",
- arm_BIC_S_MI: "BIC.S.MI",
- arm_BIC_S_PL: "BIC.S.PL",
- arm_BIC_S_VS: "BIC.S.VS",
- arm_BIC_S_VC: "BIC.S.VC",
- arm_BIC_S_HI: "BIC.S.HI",
- arm_BIC_S_LS: "BIC.S.LS",
- arm_BIC_S_GE: "BIC.S.GE",
- arm_BIC_S_LT: "BIC.S.LT",
- arm_BIC_S_GT: "BIC.S.GT",
- arm_BIC_S_LE: "BIC.S.LE",
- arm_BIC_S: "BIC.S",
- arm_BIC_S_ZZ: "BIC.S.ZZ",
- arm_BKPT_EQ: "BKPT.EQ",
- arm_BKPT_NE: "BKPT.NE",
- arm_BKPT_CS: "BKPT.CS",
- arm_BKPT_CC: "BKPT.CC",
- arm_BKPT_MI: "BKPT.MI",
- arm_BKPT_PL: "BKPT.PL",
- arm_BKPT_VS: "BKPT.VS",
- arm_BKPT_VC: "BKPT.VC",
- arm_BKPT_HI: "BKPT.HI",
- arm_BKPT_LS: "BKPT.LS",
- arm_BKPT_GE: "BKPT.GE",
- arm_BKPT_LT: "BKPT.LT",
- arm_BKPT_GT: "BKPT.GT",
- arm_BKPT_LE: "BKPT.LE",
- arm_BKPT: "BKPT",
- arm_BKPT_ZZ: "BKPT.ZZ",
- arm_BL_EQ: "BL.EQ",
- arm_BL_NE: "BL.NE",
- arm_BL_CS: "BL.CS",
- arm_BL_CC: "BL.CC",
- arm_BL_MI: "BL.MI",
- arm_BL_PL: "BL.PL",
- arm_BL_VS: "BL.VS",
- arm_BL_VC: "BL.VC",
- arm_BL_HI: "BL.HI",
- arm_BL_LS: "BL.LS",
- arm_BL_GE: "BL.GE",
- arm_BL_LT: "BL.LT",
- arm_BL_GT: "BL.GT",
- arm_BL_LE: "BL.LE",
- arm_BL: "BL",
- arm_BL_ZZ: "BL.ZZ",
- arm_BLX_EQ: "BLX.EQ",
- arm_BLX_NE: "BLX.NE",
- arm_BLX_CS: "BLX.CS",
- arm_BLX_CC: "BLX.CC",
- arm_BLX_MI: "BLX.MI",
- arm_BLX_PL: "BLX.PL",
- arm_BLX_VS: "BLX.VS",
- arm_BLX_VC: "BLX.VC",
- arm_BLX_HI: "BLX.HI",
- arm_BLX_LS: "BLX.LS",
- arm_BLX_GE: "BLX.GE",
- arm_BLX_LT: "BLX.LT",
- arm_BLX_GT: "BLX.GT",
- arm_BLX_LE: "BLX.LE",
- arm_BLX: "BLX",
- arm_BLX_ZZ: "BLX.ZZ",
- arm_BX_EQ: "BX.EQ",
- arm_BX_NE: "BX.NE",
- arm_BX_CS: "BX.CS",
- arm_BX_CC: "BX.CC",
- arm_BX_MI: "BX.MI",
- arm_BX_PL: "BX.PL",
- arm_BX_VS: "BX.VS",
- arm_BX_VC: "BX.VC",
- arm_BX_HI: "BX.HI",
- arm_BX_LS: "BX.LS",
- arm_BX_GE: "BX.GE",
- arm_BX_LT: "BX.LT",
- arm_BX_GT: "BX.GT",
- arm_BX_LE: "BX.LE",
- arm_BX: "BX",
- arm_BX_ZZ: "BX.ZZ",
- arm_BXJ_EQ: "BXJ.EQ",
- arm_BXJ_NE: "BXJ.NE",
- arm_BXJ_CS: "BXJ.CS",
- arm_BXJ_CC: "BXJ.CC",
- arm_BXJ_MI: "BXJ.MI",
- arm_BXJ_PL: "BXJ.PL",
- arm_BXJ_VS: "BXJ.VS",
- arm_BXJ_VC: "BXJ.VC",
- arm_BXJ_HI: "BXJ.HI",
- arm_BXJ_LS: "BXJ.LS",
- arm_BXJ_GE: "BXJ.GE",
- arm_BXJ_LT: "BXJ.LT",
- arm_BXJ_GT: "BXJ.GT",
- arm_BXJ_LE: "BXJ.LE",
- arm_BXJ: "BXJ",
- arm_BXJ_ZZ: "BXJ.ZZ",
- arm_CLREX: "CLREX",
- arm_CLZ_EQ: "CLZ.EQ",
- arm_CLZ_NE: "CLZ.NE",
- arm_CLZ_CS: "CLZ.CS",
- arm_CLZ_CC: "CLZ.CC",
- arm_CLZ_MI: "CLZ.MI",
- arm_CLZ_PL: "CLZ.PL",
- arm_CLZ_VS: "CLZ.VS",
- arm_CLZ_VC: "CLZ.VC",
- arm_CLZ_HI: "CLZ.HI",
- arm_CLZ_LS: "CLZ.LS",
- arm_CLZ_GE: "CLZ.GE",
- arm_CLZ_LT: "CLZ.LT",
- arm_CLZ_GT: "CLZ.GT",
- arm_CLZ_LE: "CLZ.LE",
- arm_CLZ: "CLZ",
- arm_CLZ_ZZ: "CLZ.ZZ",
- arm_CMN_EQ: "CMN.EQ",
- arm_CMN_NE: "CMN.NE",
- arm_CMN_CS: "CMN.CS",
- arm_CMN_CC: "CMN.CC",
- arm_CMN_MI: "CMN.MI",
- arm_CMN_PL: "CMN.PL",
- arm_CMN_VS: "CMN.VS",
- arm_CMN_VC: "CMN.VC",
- arm_CMN_HI: "CMN.HI",
- arm_CMN_LS: "CMN.LS",
- arm_CMN_GE: "CMN.GE",
- arm_CMN_LT: "CMN.LT",
- arm_CMN_GT: "CMN.GT",
- arm_CMN_LE: "CMN.LE",
- arm_CMN: "CMN",
- arm_CMN_ZZ: "CMN.ZZ",
- arm_CMP_EQ: "CMP.EQ",
- arm_CMP_NE: "CMP.NE",
- arm_CMP_CS: "CMP.CS",
- arm_CMP_CC: "CMP.CC",
- arm_CMP_MI: "CMP.MI",
- arm_CMP_PL: "CMP.PL",
- arm_CMP_VS: "CMP.VS",
- arm_CMP_VC: "CMP.VC",
- arm_CMP_HI: "CMP.HI",
- arm_CMP_LS: "CMP.LS",
- arm_CMP_GE: "CMP.GE",
- arm_CMP_LT: "CMP.LT",
- arm_CMP_GT: "CMP.GT",
- arm_CMP_LE: "CMP.LE",
- arm_CMP: "CMP",
- arm_CMP_ZZ: "CMP.ZZ",
- arm_DBG_EQ: "DBG.EQ",
- arm_DBG_NE: "DBG.NE",
- arm_DBG_CS: "DBG.CS",
- arm_DBG_CC: "DBG.CC",
- arm_DBG_MI: "DBG.MI",
- arm_DBG_PL: "DBG.PL",
- arm_DBG_VS: "DBG.VS",
- arm_DBG_VC: "DBG.VC",
- arm_DBG_HI: "DBG.HI",
- arm_DBG_LS: "DBG.LS",
- arm_DBG_GE: "DBG.GE",
- arm_DBG_LT: "DBG.LT",
- arm_DBG_GT: "DBG.GT",
- arm_DBG_LE: "DBG.LE",
- arm_DBG: "DBG",
- arm_DBG_ZZ: "DBG.ZZ",
- arm_DMB: "DMB",
- arm_DSB: "DSB",
- arm_EOR_EQ: "EOR.EQ",
- arm_EOR_NE: "EOR.NE",
- arm_EOR_CS: "EOR.CS",
- arm_EOR_CC: "EOR.CC",
- arm_EOR_MI: "EOR.MI",
- arm_EOR_PL: "EOR.PL",
- arm_EOR_VS: "EOR.VS",
- arm_EOR_VC: "EOR.VC",
- arm_EOR_HI: "EOR.HI",
- arm_EOR_LS: "EOR.LS",
- arm_EOR_GE: "EOR.GE",
- arm_EOR_LT: "EOR.LT",
- arm_EOR_GT: "EOR.GT",
- arm_EOR_LE: "EOR.LE",
- arm_EOR: "EOR",
- arm_EOR_ZZ: "EOR.ZZ",
- arm_EOR_S_EQ: "EOR.S.EQ",
- arm_EOR_S_NE: "EOR.S.NE",
- arm_EOR_S_CS: "EOR.S.CS",
- arm_EOR_S_CC: "EOR.S.CC",
- arm_EOR_S_MI: "EOR.S.MI",
- arm_EOR_S_PL: "EOR.S.PL",
- arm_EOR_S_VS: "EOR.S.VS",
- arm_EOR_S_VC: "EOR.S.VC",
- arm_EOR_S_HI: "EOR.S.HI",
- arm_EOR_S_LS: "EOR.S.LS",
- arm_EOR_S_GE: "EOR.S.GE",
- arm_EOR_S_LT: "EOR.S.LT",
- arm_EOR_S_GT: "EOR.S.GT",
- arm_EOR_S_LE: "EOR.S.LE",
- arm_EOR_S: "EOR.S",
- arm_EOR_S_ZZ: "EOR.S.ZZ",
- arm_ISB: "ISB",
- arm_LDM_EQ: "LDM.EQ",
- arm_LDM_NE: "LDM.NE",
- arm_LDM_CS: "LDM.CS",
- arm_LDM_CC: "LDM.CC",
- arm_LDM_MI: "LDM.MI",
- arm_LDM_PL: "LDM.PL",
- arm_LDM_VS: "LDM.VS",
- arm_LDM_VC: "LDM.VC",
- arm_LDM_HI: "LDM.HI",
- arm_LDM_LS: "LDM.LS",
- arm_LDM_GE: "LDM.GE",
- arm_LDM_LT: "LDM.LT",
- arm_LDM_GT: "LDM.GT",
- arm_LDM_LE: "LDM.LE",
- arm_LDM: "LDM",
- arm_LDM_ZZ: "LDM.ZZ",
- arm_LDMDA_EQ: "LDMDA.EQ",
- arm_LDMDA_NE: "LDMDA.NE",
- arm_LDMDA_CS: "LDMDA.CS",
- arm_LDMDA_CC: "LDMDA.CC",
- arm_LDMDA_MI: "LDMDA.MI",
- arm_LDMDA_PL: "LDMDA.PL",
- arm_LDMDA_VS: "LDMDA.VS",
- arm_LDMDA_VC: "LDMDA.VC",
- arm_LDMDA_HI: "LDMDA.HI",
- arm_LDMDA_LS: "LDMDA.LS",
- arm_LDMDA_GE: "LDMDA.GE",
- arm_LDMDA_LT: "LDMDA.LT",
- arm_LDMDA_GT: "LDMDA.GT",
- arm_LDMDA_LE: "LDMDA.LE",
- arm_LDMDA: "LDMDA",
- arm_LDMDA_ZZ: "LDMDA.ZZ",
- arm_LDMDB_EQ: "LDMDB.EQ",
- arm_LDMDB_NE: "LDMDB.NE",
- arm_LDMDB_CS: "LDMDB.CS",
- arm_LDMDB_CC: "LDMDB.CC",
- arm_LDMDB_MI: "LDMDB.MI",
- arm_LDMDB_PL: "LDMDB.PL",
- arm_LDMDB_VS: "LDMDB.VS",
- arm_LDMDB_VC: "LDMDB.VC",
- arm_LDMDB_HI: "LDMDB.HI",
- arm_LDMDB_LS: "LDMDB.LS",
- arm_LDMDB_GE: "LDMDB.GE",
- arm_LDMDB_LT: "LDMDB.LT",
- arm_LDMDB_GT: "LDMDB.GT",
- arm_LDMDB_LE: "LDMDB.LE",
- arm_LDMDB: "LDMDB",
- arm_LDMDB_ZZ: "LDMDB.ZZ",
- arm_LDMIB_EQ: "LDMIB.EQ",
- arm_LDMIB_NE: "LDMIB.NE",
- arm_LDMIB_CS: "LDMIB.CS",
- arm_LDMIB_CC: "LDMIB.CC",
- arm_LDMIB_MI: "LDMIB.MI",
- arm_LDMIB_PL: "LDMIB.PL",
- arm_LDMIB_VS: "LDMIB.VS",
- arm_LDMIB_VC: "LDMIB.VC",
- arm_LDMIB_HI: "LDMIB.HI",
- arm_LDMIB_LS: "LDMIB.LS",
- arm_LDMIB_GE: "LDMIB.GE",
- arm_LDMIB_LT: "LDMIB.LT",
- arm_LDMIB_GT: "LDMIB.GT",
- arm_LDMIB_LE: "LDMIB.LE",
- arm_LDMIB: "LDMIB",
- arm_LDMIB_ZZ: "LDMIB.ZZ",
- arm_LDR_EQ: "LDR.EQ",
- arm_LDR_NE: "LDR.NE",
- arm_LDR_CS: "LDR.CS",
- arm_LDR_CC: "LDR.CC",
- arm_LDR_MI: "LDR.MI",
- arm_LDR_PL: "LDR.PL",
- arm_LDR_VS: "LDR.VS",
- arm_LDR_VC: "LDR.VC",
- arm_LDR_HI: "LDR.HI",
- arm_LDR_LS: "LDR.LS",
- arm_LDR_GE: "LDR.GE",
- arm_LDR_LT: "LDR.LT",
- arm_LDR_GT: "LDR.GT",
- arm_LDR_LE: "LDR.LE",
- arm_LDR: "LDR",
- arm_LDR_ZZ: "LDR.ZZ",
- arm_LDRB_EQ: "LDRB.EQ",
- arm_LDRB_NE: "LDRB.NE",
- arm_LDRB_CS: "LDRB.CS",
- arm_LDRB_CC: "LDRB.CC",
- arm_LDRB_MI: "LDRB.MI",
- arm_LDRB_PL: "LDRB.PL",
- arm_LDRB_VS: "LDRB.VS",
- arm_LDRB_VC: "LDRB.VC",
- arm_LDRB_HI: "LDRB.HI",
- arm_LDRB_LS: "LDRB.LS",
- arm_LDRB_GE: "LDRB.GE",
- arm_LDRB_LT: "LDRB.LT",
- arm_LDRB_GT: "LDRB.GT",
- arm_LDRB_LE: "LDRB.LE",
- arm_LDRB: "LDRB",
- arm_LDRB_ZZ: "LDRB.ZZ",
- arm_LDRBT_EQ: "LDRBT.EQ",
- arm_LDRBT_NE: "LDRBT.NE",
- arm_LDRBT_CS: "LDRBT.CS",
- arm_LDRBT_CC: "LDRBT.CC",
- arm_LDRBT_MI: "LDRBT.MI",
- arm_LDRBT_PL: "LDRBT.PL",
- arm_LDRBT_VS: "LDRBT.VS",
- arm_LDRBT_VC: "LDRBT.VC",
- arm_LDRBT_HI: "LDRBT.HI",
- arm_LDRBT_LS: "LDRBT.LS",
- arm_LDRBT_GE: "LDRBT.GE",
- arm_LDRBT_LT: "LDRBT.LT",
- arm_LDRBT_GT: "LDRBT.GT",
- arm_LDRBT_LE: "LDRBT.LE",
- arm_LDRBT: "LDRBT",
- arm_LDRBT_ZZ: "LDRBT.ZZ",
- arm_LDRD_EQ: "LDRD.EQ",
- arm_LDRD_NE: "LDRD.NE",
- arm_LDRD_CS: "LDRD.CS",
- arm_LDRD_CC: "LDRD.CC",
- arm_LDRD_MI: "LDRD.MI",
- arm_LDRD_PL: "LDRD.PL",
- arm_LDRD_VS: "LDRD.VS",
- arm_LDRD_VC: "LDRD.VC",
- arm_LDRD_HI: "LDRD.HI",
- arm_LDRD_LS: "LDRD.LS",
- arm_LDRD_GE: "LDRD.GE",
- arm_LDRD_LT: "LDRD.LT",
- arm_LDRD_GT: "LDRD.GT",
- arm_LDRD_LE: "LDRD.LE",
- arm_LDRD: "LDRD",
- arm_LDRD_ZZ: "LDRD.ZZ",
- arm_LDREX_EQ: "LDREX.EQ",
- arm_LDREX_NE: "LDREX.NE",
- arm_LDREX_CS: "LDREX.CS",
- arm_LDREX_CC: "LDREX.CC",
- arm_LDREX_MI: "LDREX.MI",
- arm_LDREX_PL: "LDREX.PL",
- arm_LDREX_VS: "LDREX.VS",
- arm_LDREX_VC: "LDREX.VC",
- arm_LDREX_HI: "LDREX.HI",
- arm_LDREX_LS: "LDREX.LS",
- arm_LDREX_GE: "LDREX.GE",
- arm_LDREX_LT: "LDREX.LT",
- arm_LDREX_GT: "LDREX.GT",
- arm_LDREX_LE: "LDREX.LE",
- arm_LDREX: "LDREX",
- arm_LDREX_ZZ: "LDREX.ZZ",
- arm_LDREXB_EQ: "LDREXB.EQ",
- arm_LDREXB_NE: "LDREXB.NE",
- arm_LDREXB_CS: "LDREXB.CS",
- arm_LDREXB_CC: "LDREXB.CC",
- arm_LDREXB_MI: "LDREXB.MI",
- arm_LDREXB_PL: "LDREXB.PL",
- arm_LDREXB_VS: "LDREXB.VS",
- arm_LDREXB_VC: "LDREXB.VC",
- arm_LDREXB_HI: "LDREXB.HI",
- arm_LDREXB_LS: "LDREXB.LS",
- arm_LDREXB_GE: "LDREXB.GE",
- arm_LDREXB_LT: "LDREXB.LT",
- arm_LDREXB_GT: "LDREXB.GT",
- arm_LDREXB_LE: "LDREXB.LE",
- arm_LDREXB: "LDREXB",
- arm_LDREXB_ZZ: "LDREXB.ZZ",
- arm_LDREXD_EQ: "LDREXD.EQ",
- arm_LDREXD_NE: "LDREXD.NE",
- arm_LDREXD_CS: "LDREXD.CS",
- arm_LDREXD_CC: "LDREXD.CC",
- arm_LDREXD_MI: "LDREXD.MI",
- arm_LDREXD_PL: "LDREXD.PL",
- arm_LDREXD_VS: "LDREXD.VS",
- arm_LDREXD_VC: "LDREXD.VC",
- arm_LDREXD_HI: "LDREXD.HI",
- arm_LDREXD_LS: "LDREXD.LS",
- arm_LDREXD_GE: "LDREXD.GE",
- arm_LDREXD_LT: "LDREXD.LT",
- arm_LDREXD_GT: "LDREXD.GT",
- arm_LDREXD_LE: "LDREXD.LE",
- arm_LDREXD: "LDREXD",
- arm_LDREXD_ZZ: "LDREXD.ZZ",
- arm_LDREXH_EQ: "LDREXH.EQ",
- arm_LDREXH_NE: "LDREXH.NE",
- arm_LDREXH_CS: "LDREXH.CS",
- arm_LDREXH_CC: "LDREXH.CC",
- arm_LDREXH_MI: "LDREXH.MI",
- arm_LDREXH_PL: "LDREXH.PL",
- arm_LDREXH_VS: "LDREXH.VS",
- arm_LDREXH_VC: "LDREXH.VC",
- arm_LDREXH_HI: "LDREXH.HI",
- arm_LDREXH_LS: "LDREXH.LS",
- arm_LDREXH_GE: "LDREXH.GE",
- arm_LDREXH_LT: "LDREXH.LT",
- arm_LDREXH_GT: "LDREXH.GT",
- arm_LDREXH_LE: "LDREXH.LE",
- arm_LDREXH: "LDREXH",
- arm_LDREXH_ZZ: "LDREXH.ZZ",
- arm_LDRH_EQ: "LDRH.EQ",
- arm_LDRH_NE: "LDRH.NE",
- arm_LDRH_CS: "LDRH.CS",
- arm_LDRH_CC: "LDRH.CC",
- arm_LDRH_MI: "LDRH.MI",
- arm_LDRH_PL: "LDRH.PL",
- arm_LDRH_VS: "LDRH.VS",
- arm_LDRH_VC: "LDRH.VC",
- arm_LDRH_HI: "LDRH.HI",
- arm_LDRH_LS: "LDRH.LS",
- arm_LDRH_GE: "LDRH.GE",
- arm_LDRH_LT: "LDRH.LT",
- arm_LDRH_GT: "LDRH.GT",
- arm_LDRH_LE: "LDRH.LE",
- arm_LDRH: "LDRH",
- arm_LDRH_ZZ: "LDRH.ZZ",
- arm_LDRHT_EQ: "LDRHT.EQ",
- arm_LDRHT_NE: "LDRHT.NE",
- arm_LDRHT_CS: "LDRHT.CS",
- arm_LDRHT_CC: "LDRHT.CC",
- arm_LDRHT_MI: "LDRHT.MI",
- arm_LDRHT_PL: "LDRHT.PL",
- arm_LDRHT_VS: "LDRHT.VS",
- arm_LDRHT_VC: "LDRHT.VC",
- arm_LDRHT_HI: "LDRHT.HI",
- arm_LDRHT_LS: "LDRHT.LS",
- arm_LDRHT_GE: "LDRHT.GE",
- arm_LDRHT_LT: "LDRHT.LT",
- arm_LDRHT_GT: "LDRHT.GT",
- arm_LDRHT_LE: "LDRHT.LE",
- arm_LDRHT: "LDRHT",
- arm_LDRHT_ZZ: "LDRHT.ZZ",
- arm_LDRSB_EQ: "LDRSB.EQ",
- arm_LDRSB_NE: "LDRSB.NE",
- arm_LDRSB_CS: "LDRSB.CS",
- arm_LDRSB_CC: "LDRSB.CC",
- arm_LDRSB_MI: "LDRSB.MI",
- arm_LDRSB_PL: "LDRSB.PL",
- arm_LDRSB_VS: "LDRSB.VS",
- arm_LDRSB_VC: "LDRSB.VC",
- arm_LDRSB_HI: "LDRSB.HI",
- arm_LDRSB_LS: "LDRSB.LS",
- arm_LDRSB_GE: "LDRSB.GE",
- arm_LDRSB_LT: "LDRSB.LT",
- arm_LDRSB_GT: "LDRSB.GT",
- arm_LDRSB_LE: "LDRSB.LE",
- arm_LDRSB: "LDRSB",
- arm_LDRSB_ZZ: "LDRSB.ZZ",
- arm_LDRSBT_EQ: "LDRSBT.EQ",
- arm_LDRSBT_NE: "LDRSBT.NE",
- arm_LDRSBT_CS: "LDRSBT.CS",
- arm_LDRSBT_CC: "LDRSBT.CC",
- arm_LDRSBT_MI: "LDRSBT.MI",
- arm_LDRSBT_PL: "LDRSBT.PL",
- arm_LDRSBT_VS: "LDRSBT.VS",
- arm_LDRSBT_VC: "LDRSBT.VC",
- arm_LDRSBT_HI: "LDRSBT.HI",
- arm_LDRSBT_LS: "LDRSBT.LS",
- arm_LDRSBT_GE: "LDRSBT.GE",
- arm_LDRSBT_LT: "LDRSBT.LT",
- arm_LDRSBT_GT: "LDRSBT.GT",
- arm_LDRSBT_LE: "LDRSBT.LE",
- arm_LDRSBT: "LDRSBT",
- arm_LDRSBT_ZZ: "LDRSBT.ZZ",
- arm_LDRSH_EQ: "LDRSH.EQ",
- arm_LDRSH_NE: "LDRSH.NE",
- arm_LDRSH_CS: "LDRSH.CS",
- arm_LDRSH_CC: "LDRSH.CC",
- arm_LDRSH_MI: "LDRSH.MI",
- arm_LDRSH_PL: "LDRSH.PL",
- arm_LDRSH_VS: "LDRSH.VS",
- arm_LDRSH_VC: "LDRSH.VC",
- arm_LDRSH_HI: "LDRSH.HI",
- arm_LDRSH_LS: "LDRSH.LS",
- arm_LDRSH_GE: "LDRSH.GE",
- arm_LDRSH_LT: "LDRSH.LT",
- arm_LDRSH_GT: "LDRSH.GT",
- arm_LDRSH_LE: "LDRSH.LE",
- arm_LDRSH: "LDRSH",
- arm_LDRSH_ZZ: "LDRSH.ZZ",
- arm_LDRSHT_EQ: "LDRSHT.EQ",
- arm_LDRSHT_NE: "LDRSHT.NE",
- arm_LDRSHT_CS: "LDRSHT.CS",
- arm_LDRSHT_CC: "LDRSHT.CC",
- arm_LDRSHT_MI: "LDRSHT.MI",
- arm_LDRSHT_PL: "LDRSHT.PL",
- arm_LDRSHT_VS: "LDRSHT.VS",
- arm_LDRSHT_VC: "LDRSHT.VC",
- arm_LDRSHT_HI: "LDRSHT.HI",
- arm_LDRSHT_LS: "LDRSHT.LS",
- arm_LDRSHT_GE: "LDRSHT.GE",
- arm_LDRSHT_LT: "LDRSHT.LT",
- arm_LDRSHT_GT: "LDRSHT.GT",
- arm_LDRSHT_LE: "LDRSHT.LE",
- arm_LDRSHT: "LDRSHT",
- arm_LDRSHT_ZZ: "LDRSHT.ZZ",
- arm_LDRT_EQ: "LDRT.EQ",
- arm_LDRT_NE: "LDRT.NE",
- arm_LDRT_CS: "LDRT.CS",
- arm_LDRT_CC: "LDRT.CC",
- arm_LDRT_MI: "LDRT.MI",
- arm_LDRT_PL: "LDRT.PL",
- arm_LDRT_VS: "LDRT.VS",
- arm_LDRT_VC: "LDRT.VC",
- arm_LDRT_HI: "LDRT.HI",
- arm_LDRT_LS: "LDRT.LS",
- arm_LDRT_GE: "LDRT.GE",
- arm_LDRT_LT: "LDRT.LT",
- arm_LDRT_GT: "LDRT.GT",
- arm_LDRT_LE: "LDRT.LE",
- arm_LDRT: "LDRT",
- arm_LDRT_ZZ: "LDRT.ZZ",
- arm_LSL_EQ: "LSL.EQ",
- arm_LSL_NE: "LSL.NE",
- arm_LSL_CS: "LSL.CS",
- arm_LSL_CC: "LSL.CC",
- arm_LSL_MI: "LSL.MI",
- arm_LSL_PL: "LSL.PL",
- arm_LSL_VS: "LSL.VS",
- arm_LSL_VC: "LSL.VC",
- arm_LSL_HI: "LSL.HI",
- arm_LSL_LS: "LSL.LS",
- arm_LSL_GE: "LSL.GE",
- arm_LSL_LT: "LSL.LT",
- arm_LSL_GT: "LSL.GT",
- arm_LSL_LE: "LSL.LE",
- arm_LSL: "LSL",
- arm_LSL_ZZ: "LSL.ZZ",
- arm_LSL_S_EQ: "LSL.S.EQ",
- arm_LSL_S_NE: "LSL.S.NE",
- arm_LSL_S_CS: "LSL.S.CS",
- arm_LSL_S_CC: "LSL.S.CC",
- arm_LSL_S_MI: "LSL.S.MI",
- arm_LSL_S_PL: "LSL.S.PL",
- arm_LSL_S_VS: "LSL.S.VS",
- arm_LSL_S_VC: "LSL.S.VC",
- arm_LSL_S_HI: "LSL.S.HI",
- arm_LSL_S_LS: "LSL.S.LS",
- arm_LSL_S_GE: "LSL.S.GE",
- arm_LSL_S_LT: "LSL.S.LT",
- arm_LSL_S_GT: "LSL.S.GT",
- arm_LSL_S_LE: "LSL.S.LE",
- arm_LSL_S: "LSL.S",
- arm_LSL_S_ZZ: "LSL.S.ZZ",
- arm_LSR_EQ: "LSR.EQ",
- arm_LSR_NE: "LSR.NE",
- arm_LSR_CS: "LSR.CS",
- arm_LSR_CC: "LSR.CC",
- arm_LSR_MI: "LSR.MI",
- arm_LSR_PL: "LSR.PL",
- arm_LSR_VS: "LSR.VS",
- arm_LSR_VC: "LSR.VC",
- arm_LSR_HI: "LSR.HI",
- arm_LSR_LS: "LSR.LS",
- arm_LSR_GE: "LSR.GE",
- arm_LSR_LT: "LSR.LT",
- arm_LSR_GT: "LSR.GT",
- arm_LSR_LE: "LSR.LE",
- arm_LSR: "LSR",
- arm_LSR_ZZ: "LSR.ZZ",
- arm_LSR_S_EQ: "LSR.S.EQ",
- arm_LSR_S_NE: "LSR.S.NE",
- arm_LSR_S_CS: "LSR.S.CS",
- arm_LSR_S_CC: "LSR.S.CC",
- arm_LSR_S_MI: "LSR.S.MI",
- arm_LSR_S_PL: "LSR.S.PL",
- arm_LSR_S_VS: "LSR.S.VS",
- arm_LSR_S_VC: "LSR.S.VC",
- arm_LSR_S_HI: "LSR.S.HI",
- arm_LSR_S_LS: "LSR.S.LS",
- arm_LSR_S_GE: "LSR.S.GE",
- arm_LSR_S_LT: "LSR.S.LT",
- arm_LSR_S_GT: "LSR.S.GT",
- arm_LSR_S_LE: "LSR.S.LE",
- arm_LSR_S: "LSR.S",
- arm_LSR_S_ZZ: "LSR.S.ZZ",
- arm_MLA_EQ: "MLA.EQ",
- arm_MLA_NE: "MLA.NE",
- arm_MLA_CS: "MLA.CS",
- arm_MLA_CC: "MLA.CC",
- arm_MLA_MI: "MLA.MI",
- arm_MLA_PL: "MLA.PL",
- arm_MLA_VS: "MLA.VS",
- arm_MLA_VC: "MLA.VC",
- arm_MLA_HI: "MLA.HI",
- arm_MLA_LS: "MLA.LS",
- arm_MLA_GE: "MLA.GE",
- arm_MLA_LT: "MLA.LT",
- arm_MLA_GT: "MLA.GT",
- arm_MLA_LE: "MLA.LE",
- arm_MLA: "MLA",
- arm_MLA_ZZ: "MLA.ZZ",
- arm_MLA_S_EQ: "MLA.S.EQ",
- arm_MLA_S_NE: "MLA.S.NE",
- arm_MLA_S_CS: "MLA.S.CS",
- arm_MLA_S_CC: "MLA.S.CC",
- arm_MLA_S_MI: "MLA.S.MI",
- arm_MLA_S_PL: "MLA.S.PL",
- arm_MLA_S_VS: "MLA.S.VS",
- arm_MLA_S_VC: "MLA.S.VC",
- arm_MLA_S_HI: "MLA.S.HI",
- arm_MLA_S_LS: "MLA.S.LS",
- arm_MLA_S_GE: "MLA.S.GE",
- arm_MLA_S_LT: "MLA.S.LT",
- arm_MLA_S_GT: "MLA.S.GT",
- arm_MLA_S_LE: "MLA.S.LE",
- arm_MLA_S: "MLA.S",
- arm_MLA_S_ZZ: "MLA.S.ZZ",
- arm_MLS_EQ: "MLS.EQ",
- arm_MLS_NE: "MLS.NE",
- arm_MLS_CS: "MLS.CS",
- arm_MLS_CC: "MLS.CC",
- arm_MLS_MI: "MLS.MI",
- arm_MLS_PL: "MLS.PL",
- arm_MLS_VS: "MLS.VS",
- arm_MLS_VC: "MLS.VC",
- arm_MLS_HI: "MLS.HI",
- arm_MLS_LS: "MLS.LS",
- arm_MLS_GE: "MLS.GE",
- arm_MLS_LT: "MLS.LT",
- arm_MLS_GT: "MLS.GT",
- arm_MLS_LE: "MLS.LE",
- arm_MLS: "MLS",
- arm_MLS_ZZ: "MLS.ZZ",
- arm_MOV_EQ: "MOV.EQ",
- arm_MOV_NE: "MOV.NE",
- arm_MOV_CS: "MOV.CS",
- arm_MOV_CC: "MOV.CC",
- arm_MOV_MI: "MOV.MI",
- arm_MOV_PL: "MOV.PL",
- arm_MOV_VS: "MOV.VS",
- arm_MOV_VC: "MOV.VC",
- arm_MOV_HI: "MOV.HI",
- arm_MOV_LS: "MOV.LS",
- arm_MOV_GE: "MOV.GE",
- arm_MOV_LT: "MOV.LT",
- arm_MOV_GT: "MOV.GT",
- arm_MOV_LE: "MOV.LE",
- arm_MOV: "MOV",
- arm_MOV_ZZ: "MOV.ZZ",
- arm_MOV_S_EQ: "MOV.S.EQ",
- arm_MOV_S_NE: "MOV.S.NE",
- arm_MOV_S_CS: "MOV.S.CS",
- arm_MOV_S_CC: "MOV.S.CC",
- arm_MOV_S_MI: "MOV.S.MI",
- arm_MOV_S_PL: "MOV.S.PL",
- arm_MOV_S_VS: "MOV.S.VS",
- arm_MOV_S_VC: "MOV.S.VC",
- arm_MOV_S_HI: "MOV.S.HI",
- arm_MOV_S_LS: "MOV.S.LS",
- arm_MOV_S_GE: "MOV.S.GE",
- arm_MOV_S_LT: "MOV.S.LT",
- arm_MOV_S_GT: "MOV.S.GT",
- arm_MOV_S_LE: "MOV.S.LE",
- arm_MOV_S: "MOV.S",
- arm_MOV_S_ZZ: "MOV.S.ZZ",
- arm_MOVT_EQ: "MOVT.EQ",
- arm_MOVT_NE: "MOVT.NE",
- arm_MOVT_CS: "MOVT.CS",
- arm_MOVT_CC: "MOVT.CC",
- arm_MOVT_MI: "MOVT.MI",
- arm_MOVT_PL: "MOVT.PL",
- arm_MOVT_VS: "MOVT.VS",
- arm_MOVT_VC: "MOVT.VC",
- arm_MOVT_HI: "MOVT.HI",
- arm_MOVT_LS: "MOVT.LS",
- arm_MOVT_GE: "MOVT.GE",
- arm_MOVT_LT: "MOVT.LT",
- arm_MOVT_GT: "MOVT.GT",
- arm_MOVT_LE: "MOVT.LE",
- arm_MOVT: "MOVT",
- arm_MOVT_ZZ: "MOVT.ZZ",
- arm_MOVW_EQ: "MOVW.EQ",
- arm_MOVW_NE: "MOVW.NE",
- arm_MOVW_CS: "MOVW.CS",
- arm_MOVW_CC: "MOVW.CC",
- arm_MOVW_MI: "MOVW.MI",
- arm_MOVW_PL: "MOVW.PL",
- arm_MOVW_VS: "MOVW.VS",
- arm_MOVW_VC: "MOVW.VC",
- arm_MOVW_HI: "MOVW.HI",
- arm_MOVW_LS: "MOVW.LS",
- arm_MOVW_GE: "MOVW.GE",
- arm_MOVW_LT: "MOVW.LT",
- arm_MOVW_GT: "MOVW.GT",
- arm_MOVW_LE: "MOVW.LE",
- arm_MOVW: "MOVW",
- arm_MOVW_ZZ: "MOVW.ZZ",
- arm_MRS_EQ: "MRS.EQ",
- arm_MRS_NE: "MRS.NE",
- arm_MRS_CS: "MRS.CS",
- arm_MRS_CC: "MRS.CC",
- arm_MRS_MI: "MRS.MI",
- arm_MRS_PL: "MRS.PL",
- arm_MRS_VS: "MRS.VS",
- arm_MRS_VC: "MRS.VC",
- arm_MRS_HI: "MRS.HI",
- arm_MRS_LS: "MRS.LS",
- arm_MRS_GE: "MRS.GE",
- arm_MRS_LT: "MRS.LT",
- arm_MRS_GT: "MRS.GT",
- arm_MRS_LE: "MRS.LE",
- arm_MRS: "MRS",
- arm_MRS_ZZ: "MRS.ZZ",
- arm_MUL_EQ: "MUL.EQ",
- arm_MUL_NE: "MUL.NE",
- arm_MUL_CS: "MUL.CS",
- arm_MUL_CC: "MUL.CC",
- arm_MUL_MI: "MUL.MI",
- arm_MUL_PL: "MUL.PL",
- arm_MUL_VS: "MUL.VS",
- arm_MUL_VC: "MUL.VC",
- arm_MUL_HI: "MUL.HI",
- arm_MUL_LS: "MUL.LS",
- arm_MUL_GE: "MUL.GE",
- arm_MUL_LT: "MUL.LT",
- arm_MUL_GT: "MUL.GT",
- arm_MUL_LE: "MUL.LE",
- arm_MUL: "MUL",
- arm_MUL_ZZ: "MUL.ZZ",
- arm_MUL_S_EQ: "MUL.S.EQ",
- arm_MUL_S_NE: "MUL.S.NE",
- arm_MUL_S_CS: "MUL.S.CS",
- arm_MUL_S_CC: "MUL.S.CC",
- arm_MUL_S_MI: "MUL.S.MI",
- arm_MUL_S_PL: "MUL.S.PL",
- arm_MUL_S_VS: "MUL.S.VS",
- arm_MUL_S_VC: "MUL.S.VC",
- arm_MUL_S_HI: "MUL.S.HI",
- arm_MUL_S_LS: "MUL.S.LS",
- arm_MUL_S_GE: "MUL.S.GE",
- arm_MUL_S_LT: "MUL.S.LT",
- arm_MUL_S_GT: "MUL.S.GT",
- arm_MUL_S_LE: "MUL.S.LE",
- arm_MUL_S: "MUL.S",
- arm_MUL_S_ZZ: "MUL.S.ZZ",
- arm_MVN_EQ: "MVN.EQ",
- arm_MVN_NE: "MVN.NE",
- arm_MVN_CS: "MVN.CS",
- arm_MVN_CC: "MVN.CC",
- arm_MVN_MI: "MVN.MI",
- arm_MVN_PL: "MVN.PL",
- arm_MVN_VS: "MVN.VS",
- arm_MVN_VC: "MVN.VC",
- arm_MVN_HI: "MVN.HI",
- arm_MVN_LS: "MVN.LS",
- arm_MVN_GE: "MVN.GE",
- arm_MVN_LT: "MVN.LT",
- arm_MVN_GT: "MVN.GT",
- arm_MVN_LE: "MVN.LE",
- arm_MVN: "MVN",
- arm_MVN_ZZ: "MVN.ZZ",
- arm_MVN_S_EQ: "MVN.S.EQ",
- arm_MVN_S_NE: "MVN.S.NE",
- arm_MVN_S_CS: "MVN.S.CS",
- arm_MVN_S_CC: "MVN.S.CC",
- arm_MVN_S_MI: "MVN.S.MI",
- arm_MVN_S_PL: "MVN.S.PL",
- arm_MVN_S_VS: "MVN.S.VS",
- arm_MVN_S_VC: "MVN.S.VC",
- arm_MVN_S_HI: "MVN.S.HI",
- arm_MVN_S_LS: "MVN.S.LS",
- arm_MVN_S_GE: "MVN.S.GE",
- arm_MVN_S_LT: "MVN.S.LT",
- arm_MVN_S_GT: "MVN.S.GT",
- arm_MVN_S_LE: "MVN.S.LE",
- arm_MVN_S: "MVN.S",
- arm_MVN_S_ZZ: "MVN.S.ZZ",
- arm_NOP_EQ: "NOP.EQ",
- arm_NOP_NE: "NOP.NE",
- arm_NOP_CS: "NOP.CS",
- arm_NOP_CC: "NOP.CC",
- arm_NOP_MI: "NOP.MI",
- arm_NOP_PL: "NOP.PL",
- arm_NOP_VS: "NOP.VS",
- arm_NOP_VC: "NOP.VC",
- arm_NOP_HI: "NOP.HI",
- arm_NOP_LS: "NOP.LS",
- arm_NOP_GE: "NOP.GE",
- arm_NOP_LT: "NOP.LT",
- arm_NOP_GT: "NOP.GT",
- arm_NOP_LE: "NOP.LE",
- arm_NOP: "NOP",
- arm_NOP_ZZ: "NOP.ZZ",
- arm_ORR_EQ: "ORR.EQ",
- arm_ORR_NE: "ORR.NE",
- arm_ORR_CS: "ORR.CS",
- arm_ORR_CC: "ORR.CC",
- arm_ORR_MI: "ORR.MI",
- arm_ORR_PL: "ORR.PL",
- arm_ORR_VS: "ORR.VS",
- arm_ORR_VC: "ORR.VC",
- arm_ORR_HI: "ORR.HI",
- arm_ORR_LS: "ORR.LS",
- arm_ORR_GE: "ORR.GE",
- arm_ORR_LT: "ORR.LT",
- arm_ORR_GT: "ORR.GT",
- arm_ORR_LE: "ORR.LE",
- arm_ORR: "ORR",
- arm_ORR_ZZ: "ORR.ZZ",
- arm_ORR_S_EQ: "ORR.S.EQ",
- arm_ORR_S_NE: "ORR.S.NE",
- arm_ORR_S_CS: "ORR.S.CS",
- arm_ORR_S_CC: "ORR.S.CC",
- arm_ORR_S_MI: "ORR.S.MI",
- arm_ORR_S_PL: "ORR.S.PL",
- arm_ORR_S_VS: "ORR.S.VS",
- arm_ORR_S_VC: "ORR.S.VC",
- arm_ORR_S_HI: "ORR.S.HI",
- arm_ORR_S_LS: "ORR.S.LS",
- arm_ORR_S_GE: "ORR.S.GE",
- arm_ORR_S_LT: "ORR.S.LT",
- arm_ORR_S_GT: "ORR.S.GT",
- arm_ORR_S_LE: "ORR.S.LE",
- arm_ORR_S: "ORR.S",
- arm_ORR_S_ZZ: "ORR.S.ZZ",
- arm_PKHBT_EQ: "PKHBT.EQ",
- arm_PKHBT_NE: "PKHBT.NE",
- arm_PKHBT_CS: "PKHBT.CS",
- arm_PKHBT_CC: "PKHBT.CC",
- arm_PKHBT_MI: "PKHBT.MI",
- arm_PKHBT_PL: "PKHBT.PL",
- arm_PKHBT_VS: "PKHBT.VS",
- arm_PKHBT_VC: "PKHBT.VC",
- arm_PKHBT_HI: "PKHBT.HI",
- arm_PKHBT_LS: "PKHBT.LS",
- arm_PKHBT_GE: "PKHBT.GE",
- arm_PKHBT_LT: "PKHBT.LT",
- arm_PKHBT_GT: "PKHBT.GT",
- arm_PKHBT_LE: "PKHBT.LE",
- arm_PKHBT: "PKHBT",
- arm_PKHBT_ZZ: "PKHBT.ZZ",
- arm_PKHTB_EQ: "PKHTB.EQ",
- arm_PKHTB_NE: "PKHTB.NE",
- arm_PKHTB_CS: "PKHTB.CS",
- arm_PKHTB_CC: "PKHTB.CC",
- arm_PKHTB_MI: "PKHTB.MI",
- arm_PKHTB_PL: "PKHTB.PL",
- arm_PKHTB_VS: "PKHTB.VS",
- arm_PKHTB_VC: "PKHTB.VC",
- arm_PKHTB_HI: "PKHTB.HI",
- arm_PKHTB_LS: "PKHTB.LS",
- arm_PKHTB_GE: "PKHTB.GE",
- arm_PKHTB_LT: "PKHTB.LT",
- arm_PKHTB_GT: "PKHTB.GT",
- arm_PKHTB_LE: "PKHTB.LE",
- arm_PKHTB: "PKHTB",
- arm_PKHTB_ZZ: "PKHTB.ZZ",
- arm_PLD_W: "PLD.W",
- arm_PLD: "PLD",
- arm_PLI: "PLI",
- arm_POP_EQ: "POP.EQ",
- arm_POP_NE: "POP.NE",
- arm_POP_CS: "POP.CS",
- arm_POP_CC: "POP.CC",
- arm_POP_MI: "POP.MI",
- arm_POP_PL: "POP.PL",
- arm_POP_VS: "POP.VS",
- arm_POP_VC: "POP.VC",
- arm_POP_HI: "POP.HI",
- arm_POP_LS: "POP.LS",
- arm_POP_GE: "POP.GE",
- arm_POP_LT: "POP.LT",
- arm_POP_GT: "POP.GT",
- arm_POP_LE: "POP.LE",
- arm_POP: "POP",
- arm_POP_ZZ: "POP.ZZ",
- arm_PUSH_EQ: "PUSH.EQ",
- arm_PUSH_NE: "PUSH.NE",
- arm_PUSH_CS: "PUSH.CS",
- arm_PUSH_CC: "PUSH.CC",
- arm_PUSH_MI: "PUSH.MI",
- arm_PUSH_PL: "PUSH.PL",
- arm_PUSH_VS: "PUSH.VS",
- arm_PUSH_VC: "PUSH.VC",
- arm_PUSH_HI: "PUSH.HI",
- arm_PUSH_LS: "PUSH.LS",
- arm_PUSH_GE: "PUSH.GE",
- arm_PUSH_LT: "PUSH.LT",
- arm_PUSH_GT: "PUSH.GT",
- arm_PUSH_LE: "PUSH.LE",
- arm_PUSH: "PUSH",
- arm_PUSH_ZZ: "PUSH.ZZ",
- arm_QADD_EQ: "QADD.EQ",
- arm_QADD_NE: "QADD.NE",
- arm_QADD_CS: "QADD.CS",
- arm_QADD_CC: "QADD.CC",
- arm_QADD_MI: "QADD.MI",
- arm_QADD_PL: "QADD.PL",
- arm_QADD_VS: "QADD.VS",
- arm_QADD_VC: "QADD.VC",
- arm_QADD_HI: "QADD.HI",
- arm_QADD_LS: "QADD.LS",
- arm_QADD_GE: "QADD.GE",
- arm_QADD_LT: "QADD.LT",
- arm_QADD_GT: "QADD.GT",
- arm_QADD_LE: "QADD.LE",
- arm_QADD: "QADD",
- arm_QADD_ZZ: "QADD.ZZ",
- arm_QADD16_EQ: "QADD16.EQ",
- arm_QADD16_NE: "QADD16.NE",
- arm_QADD16_CS: "QADD16.CS",
- arm_QADD16_CC: "QADD16.CC",
- arm_QADD16_MI: "QADD16.MI",
- arm_QADD16_PL: "QADD16.PL",
- arm_QADD16_VS: "QADD16.VS",
- arm_QADD16_VC: "QADD16.VC",
- arm_QADD16_HI: "QADD16.HI",
- arm_QADD16_LS: "QADD16.LS",
- arm_QADD16_GE: "QADD16.GE",
- arm_QADD16_LT: "QADD16.LT",
- arm_QADD16_GT: "QADD16.GT",
- arm_QADD16_LE: "QADD16.LE",
- arm_QADD16: "QADD16",
- arm_QADD16_ZZ: "QADD16.ZZ",
- arm_QADD8_EQ: "QADD8.EQ",
- arm_QADD8_NE: "QADD8.NE",
- arm_QADD8_CS: "QADD8.CS",
- arm_QADD8_CC: "QADD8.CC",
- arm_QADD8_MI: "QADD8.MI",
- arm_QADD8_PL: "QADD8.PL",
- arm_QADD8_VS: "QADD8.VS",
- arm_QADD8_VC: "QADD8.VC",
- arm_QADD8_HI: "QADD8.HI",
- arm_QADD8_LS: "QADD8.LS",
- arm_QADD8_GE: "QADD8.GE",
- arm_QADD8_LT: "QADD8.LT",
- arm_QADD8_GT: "QADD8.GT",
- arm_QADD8_LE: "QADD8.LE",
- arm_QADD8: "QADD8",
- arm_QADD8_ZZ: "QADD8.ZZ",
- arm_QASX_EQ: "QASX.EQ",
- arm_QASX_NE: "QASX.NE",
- arm_QASX_CS: "QASX.CS",
- arm_QASX_CC: "QASX.CC",
- arm_QASX_MI: "QASX.MI",
- arm_QASX_PL: "QASX.PL",
- arm_QASX_VS: "QASX.VS",
- arm_QASX_VC: "QASX.VC",
- arm_QASX_HI: "QASX.HI",
- arm_QASX_LS: "QASX.LS",
- arm_QASX_GE: "QASX.GE",
- arm_QASX_LT: "QASX.LT",
- arm_QASX_GT: "QASX.GT",
- arm_QASX_LE: "QASX.LE",
- arm_QASX: "QASX",
- arm_QASX_ZZ: "QASX.ZZ",
- arm_QDADD_EQ: "QDADD.EQ",
- arm_QDADD_NE: "QDADD.NE",
- arm_QDADD_CS: "QDADD.CS",
- arm_QDADD_CC: "QDADD.CC",
- arm_QDADD_MI: "QDADD.MI",
- arm_QDADD_PL: "QDADD.PL",
- arm_QDADD_VS: "QDADD.VS",
- arm_QDADD_VC: "QDADD.VC",
- arm_QDADD_HI: "QDADD.HI",
- arm_QDADD_LS: "QDADD.LS",
- arm_QDADD_GE: "QDADD.GE",
- arm_QDADD_LT: "QDADD.LT",
- arm_QDADD_GT: "QDADD.GT",
- arm_QDADD_LE: "QDADD.LE",
- arm_QDADD: "QDADD",
- arm_QDADD_ZZ: "QDADD.ZZ",
- arm_QDSUB_EQ: "QDSUB.EQ",
- arm_QDSUB_NE: "QDSUB.NE",
- arm_QDSUB_CS: "QDSUB.CS",
- arm_QDSUB_CC: "QDSUB.CC",
- arm_QDSUB_MI: "QDSUB.MI",
- arm_QDSUB_PL: "QDSUB.PL",
- arm_QDSUB_VS: "QDSUB.VS",
- arm_QDSUB_VC: "QDSUB.VC",
- arm_QDSUB_HI: "QDSUB.HI",
- arm_QDSUB_LS: "QDSUB.LS",
- arm_QDSUB_GE: "QDSUB.GE",
- arm_QDSUB_LT: "QDSUB.LT",
- arm_QDSUB_GT: "QDSUB.GT",
- arm_QDSUB_LE: "QDSUB.LE",
- arm_QDSUB: "QDSUB",
- arm_QDSUB_ZZ: "QDSUB.ZZ",
- arm_QSAX_EQ: "QSAX.EQ",
- arm_QSAX_NE: "QSAX.NE",
- arm_QSAX_CS: "QSAX.CS",
- arm_QSAX_CC: "QSAX.CC",
- arm_QSAX_MI: "QSAX.MI",
- arm_QSAX_PL: "QSAX.PL",
- arm_QSAX_VS: "QSAX.VS",
- arm_QSAX_VC: "QSAX.VC",
- arm_QSAX_HI: "QSAX.HI",
- arm_QSAX_LS: "QSAX.LS",
- arm_QSAX_GE: "QSAX.GE",
- arm_QSAX_LT: "QSAX.LT",
- arm_QSAX_GT: "QSAX.GT",
- arm_QSAX_LE: "QSAX.LE",
- arm_QSAX: "QSAX",
- arm_QSAX_ZZ: "QSAX.ZZ",
- arm_QSUB_EQ: "QSUB.EQ",
- arm_QSUB_NE: "QSUB.NE",
- arm_QSUB_CS: "QSUB.CS",
- arm_QSUB_CC: "QSUB.CC",
- arm_QSUB_MI: "QSUB.MI",
- arm_QSUB_PL: "QSUB.PL",
- arm_QSUB_VS: "QSUB.VS",
- arm_QSUB_VC: "QSUB.VC",
- arm_QSUB_HI: "QSUB.HI",
- arm_QSUB_LS: "QSUB.LS",
- arm_QSUB_GE: "QSUB.GE",
- arm_QSUB_LT: "QSUB.LT",
- arm_QSUB_GT: "QSUB.GT",
- arm_QSUB_LE: "QSUB.LE",
- arm_QSUB: "QSUB",
- arm_QSUB_ZZ: "QSUB.ZZ",
- arm_QSUB16_EQ: "QSUB16.EQ",
- arm_QSUB16_NE: "QSUB16.NE",
- arm_QSUB16_CS: "QSUB16.CS",
- arm_QSUB16_CC: "QSUB16.CC",
- arm_QSUB16_MI: "QSUB16.MI",
- arm_QSUB16_PL: "QSUB16.PL",
- arm_QSUB16_VS: "QSUB16.VS",
- arm_QSUB16_VC: "QSUB16.VC",
- arm_QSUB16_HI: "QSUB16.HI",
- arm_QSUB16_LS: "QSUB16.LS",
- arm_QSUB16_GE: "QSUB16.GE",
- arm_QSUB16_LT: "QSUB16.LT",
- arm_QSUB16_GT: "QSUB16.GT",
- arm_QSUB16_LE: "QSUB16.LE",
- arm_QSUB16: "QSUB16",
- arm_QSUB16_ZZ: "QSUB16.ZZ",
- arm_QSUB8_EQ: "QSUB8.EQ",
- arm_QSUB8_NE: "QSUB8.NE",
- arm_QSUB8_CS: "QSUB8.CS",
- arm_QSUB8_CC: "QSUB8.CC",
- arm_QSUB8_MI: "QSUB8.MI",
- arm_QSUB8_PL: "QSUB8.PL",
- arm_QSUB8_VS: "QSUB8.VS",
- arm_QSUB8_VC: "QSUB8.VC",
- arm_QSUB8_HI: "QSUB8.HI",
- arm_QSUB8_LS: "QSUB8.LS",
- arm_QSUB8_GE: "QSUB8.GE",
- arm_QSUB8_LT: "QSUB8.LT",
- arm_QSUB8_GT: "QSUB8.GT",
- arm_QSUB8_LE: "QSUB8.LE",
- arm_QSUB8: "QSUB8",
- arm_QSUB8_ZZ: "QSUB8.ZZ",
- arm_RBIT_EQ: "RBIT.EQ",
- arm_RBIT_NE: "RBIT.NE",
- arm_RBIT_CS: "RBIT.CS",
- arm_RBIT_CC: "RBIT.CC",
- arm_RBIT_MI: "RBIT.MI",
- arm_RBIT_PL: "RBIT.PL",
- arm_RBIT_VS: "RBIT.VS",
- arm_RBIT_VC: "RBIT.VC",
- arm_RBIT_HI: "RBIT.HI",
- arm_RBIT_LS: "RBIT.LS",
- arm_RBIT_GE: "RBIT.GE",
- arm_RBIT_LT: "RBIT.LT",
- arm_RBIT_GT: "RBIT.GT",
- arm_RBIT_LE: "RBIT.LE",
- arm_RBIT: "RBIT",
- arm_RBIT_ZZ: "RBIT.ZZ",
- arm_REV_EQ: "REV.EQ",
- arm_REV_NE: "REV.NE",
- arm_REV_CS: "REV.CS",
- arm_REV_CC: "REV.CC",
- arm_REV_MI: "REV.MI",
- arm_REV_PL: "REV.PL",
- arm_REV_VS: "REV.VS",
- arm_REV_VC: "REV.VC",
- arm_REV_HI: "REV.HI",
- arm_REV_LS: "REV.LS",
- arm_REV_GE: "REV.GE",
- arm_REV_LT: "REV.LT",
- arm_REV_GT: "REV.GT",
- arm_REV_LE: "REV.LE",
- arm_REV: "REV",
- arm_REV_ZZ: "REV.ZZ",
- arm_REV16_EQ: "REV16.EQ",
- arm_REV16_NE: "REV16.NE",
- arm_REV16_CS: "REV16.CS",
- arm_REV16_CC: "REV16.CC",
- arm_REV16_MI: "REV16.MI",
- arm_REV16_PL: "REV16.PL",
- arm_REV16_VS: "REV16.VS",
- arm_REV16_VC: "REV16.VC",
- arm_REV16_HI: "REV16.HI",
- arm_REV16_LS: "REV16.LS",
- arm_REV16_GE: "REV16.GE",
- arm_REV16_LT: "REV16.LT",
- arm_REV16_GT: "REV16.GT",
- arm_REV16_LE: "REV16.LE",
- arm_REV16: "REV16",
- arm_REV16_ZZ: "REV16.ZZ",
- arm_REVSH_EQ: "REVSH.EQ",
- arm_REVSH_NE: "REVSH.NE",
- arm_REVSH_CS: "REVSH.CS",
- arm_REVSH_CC: "REVSH.CC",
- arm_REVSH_MI: "REVSH.MI",
- arm_REVSH_PL: "REVSH.PL",
- arm_REVSH_VS: "REVSH.VS",
- arm_REVSH_VC: "REVSH.VC",
- arm_REVSH_HI: "REVSH.HI",
- arm_REVSH_LS: "REVSH.LS",
- arm_REVSH_GE: "REVSH.GE",
- arm_REVSH_LT: "REVSH.LT",
- arm_REVSH_GT: "REVSH.GT",
- arm_REVSH_LE: "REVSH.LE",
- arm_REVSH: "REVSH",
- arm_REVSH_ZZ: "REVSH.ZZ",
- arm_ROR_EQ: "ROR.EQ",
- arm_ROR_NE: "ROR.NE",
- arm_ROR_CS: "ROR.CS",
- arm_ROR_CC: "ROR.CC",
- arm_ROR_MI: "ROR.MI",
- arm_ROR_PL: "ROR.PL",
- arm_ROR_VS: "ROR.VS",
- arm_ROR_VC: "ROR.VC",
- arm_ROR_HI: "ROR.HI",
- arm_ROR_LS: "ROR.LS",
- arm_ROR_GE: "ROR.GE",
- arm_ROR_LT: "ROR.LT",
- arm_ROR_GT: "ROR.GT",
- arm_ROR_LE: "ROR.LE",
- arm_ROR: "ROR",
- arm_ROR_ZZ: "ROR.ZZ",
- arm_ROR_S_EQ: "ROR.S.EQ",
- arm_ROR_S_NE: "ROR.S.NE",
- arm_ROR_S_CS: "ROR.S.CS",
- arm_ROR_S_CC: "ROR.S.CC",
- arm_ROR_S_MI: "ROR.S.MI",
- arm_ROR_S_PL: "ROR.S.PL",
- arm_ROR_S_VS: "ROR.S.VS",
- arm_ROR_S_VC: "ROR.S.VC",
- arm_ROR_S_HI: "ROR.S.HI",
- arm_ROR_S_LS: "ROR.S.LS",
- arm_ROR_S_GE: "ROR.S.GE",
- arm_ROR_S_LT: "ROR.S.LT",
- arm_ROR_S_GT: "ROR.S.GT",
- arm_ROR_S_LE: "ROR.S.LE",
- arm_ROR_S: "ROR.S",
- arm_ROR_S_ZZ: "ROR.S.ZZ",
- arm_RRX_EQ: "RRX.EQ",
- arm_RRX_NE: "RRX.NE",
- arm_RRX_CS: "RRX.CS",
- arm_RRX_CC: "RRX.CC",
- arm_RRX_MI: "RRX.MI",
- arm_RRX_PL: "RRX.PL",
- arm_RRX_VS: "RRX.VS",
- arm_RRX_VC: "RRX.VC",
- arm_RRX_HI: "RRX.HI",
- arm_RRX_LS: "RRX.LS",
- arm_RRX_GE: "RRX.GE",
- arm_RRX_LT: "RRX.LT",
- arm_RRX_GT: "RRX.GT",
- arm_RRX_LE: "RRX.LE",
- arm_RRX: "RRX",
- arm_RRX_ZZ: "RRX.ZZ",
- arm_RRX_S_EQ: "RRX.S.EQ",
- arm_RRX_S_NE: "RRX.S.NE",
- arm_RRX_S_CS: "RRX.S.CS",
- arm_RRX_S_CC: "RRX.S.CC",
- arm_RRX_S_MI: "RRX.S.MI",
- arm_RRX_S_PL: "RRX.S.PL",
- arm_RRX_S_VS: "RRX.S.VS",
- arm_RRX_S_VC: "RRX.S.VC",
- arm_RRX_S_HI: "RRX.S.HI",
- arm_RRX_S_LS: "RRX.S.LS",
- arm_RRX_S_GE: "RRX.S.GE",
- arm_RRX_S_LT: "RRX.S.LT",
- arm_RRX_S_GT: "RRX.S.GT",
- arm_RRX_S_LE: "RRX.S.LE",
- arm_RRX_S: "RRX.S",
- arm_RRX_S_ZZ: "RRX.S.ZZ",
- arm_RSB_EQ: "RSB.EQ",
- arm_RSB_NE: "RSB.NE",
- arm_RSB_CS: "RSB.CS",
- arm_RSB_CC: "RSB.CC",
- arm_RSB_MI: "RSB.MI",
- arm_RSB_PL: "RSB.PL",
- arm_RSB_VS: "RSB.VS",
- arm_RSB_VC: "RSB.VC",
- arm_RSB_HI: "RSB.HI",
- arm_RSB_LS: "RSB.LS",
- arm_RSB_GE: "RSB.GE",
- arm_RSB_LT: "RSB.LT",
- arm_RSB_GT: "RSB.GT",
- arm_RSB_LE: "RSB.LE",
- arm_RSB: "RSB",
- arm_RSB_ZZ: "RSB.ZZ",
- arm_RSB_S_EQ: "RSB.S.EQ",
- arm_RSB_S_NE: "RSB.S.NE",
- arm_RSB_S_CS: "RSB.S.CS",
- arm_RSB_S_CC: "RSB.S.CC",
- arm_RSB_S_MI: "RSB.S.MI",
- arm_RSB_S_PL: "RSB.S.PL",
- arm_RSB_S_VS: "RSB.S.VS",
- arm_RSB_S_VC: "RSB.S.VC",
- arm_RSB_S_HI: "RSB.S.HI",
- arm_RSB_S_LS: "RSB.S.LS",
- arm_RSB_S_GE: "RSB.S.GE",
- arm_RSB_S_LT: "RSB.S.LT",
- arm_RSB_S_GT: "RSB.S.GT",
- arm_RSB_S_LE: "RSB.S.LE",
- arm_RSB_S: "RSB.S",
- arm_RSB_S_ZZ: "RSB.S.ZZ",
- arm_RSC_EQ: "RSC.EQ",
- arm_RSC_NE: "RSC.NE",
- arm_RSC_CS: "RSC.CS",
- arm_RSC_CC: "RSC.CC",
- arm_RSC_MI: "RSC.MI",
- arm_RSC_PL: "RSC.PL",
- arm_RSC_VS: "RSC.VS",
- arm_RSC_VC: "RSC.VC",
- arm_RSC_HI: "RSC.HI",
- arm_RSC_LS: "RSC.LS",
- arm_RSC_GE: "RSC.GE",
- arm_RSC_LT: "RSC.LT",
- arm_RSC_GT: "RSC.GT",
- arm_RSC_LE: "RSC.LE",
- arm_RSC: "RSC",
- arm_RSC_ZZ: "RSC.ZZ",
- arm_RSC_S_EQ: "RSC.S.EQ",
- arm_RSC_S_NE: "RSC.S.NE",
- arm_RSC_S_CS: "RSC.S.CS",
- arm_RSC_S_CC: "RSC.S.CC",
- arm_RSC_S_MI: "RSC.S.MI",
- arm_RSC_S_PL: "RSC.S.PL",
- arm_RSC_S_VS: "RSC.S.VS",
- arm_RSC_S_VC: "RSC.S.VC",
- arm_RSC_S_HI: "RSC.S.HI",
- arm_RSC_S_LS: "RSC.S.LS",
- arm_RSC_S_GE: "RSC.S.GE",
- arm_RSC_S_LT: "RSC.S.LT",
- arm_RSC_S_GT: "RSC.S.GT",
- arm_RSC_S_LE: "RSC.S.LE",
- arm_RSC_S: "RSC.S",
- arm_RSC_S_ZZ: "RSC.S.ZZ",
- arm_SADD16_EQ: "SADD16.EQ",
- arm_SADD16_NE: "SADD16.NE",
- arm_SADD16_CS: "SADD16.CS",
- arm_SADD16_CC: "SADD16.CC",
- arm_SADD16_MI: "SADD16.MI",
- arm_SADD16_PL: "SADD16.PL",
- arm_SADD16_VS: "SADD16.VS",
- arm_SADD16_VC: "SADD16.VC",
- arm_SADD16_HI: "SADD16.HI",
- arm_SADD16_LS: "SADD16.LS",
- arm_SADD16_GE: "SADD16.GE",
- arm_SADD16_LT: "SADD16.LT",
- arm_SADD16_GT: "SADD16.GT",
- arm_SADD16_LE: "SADD16.LE",
- arm_SADD16: "SADD16",
- arm_SADD16_ZZ: "SADD16.ZZ",
- arm_SADD8_EQ: "SADD8.EQ",
- arm_SADD8_NE: "SADD8.NE",
- arm_SADD8_CS: "SADD8.CS",
- arm_SADD8_CC: "SADD8.CC",
- arm_SADD8_MI: "SADD8.MI",
- arm_SADD8_PL: "SADD8.PL",
- arm_SADD8_VS: "SADD8.VS",
- arm_SADD8_VC: "SADD8.VC",
- arm_SADD8_HI: "SADD8.HI",
- arm_SADD8_LS: "SADD8.LS",
- arm_SADD8_GE: "SADD8.GE",
- arm_SADD8_LT: "SADD8.LT",
- arm_SADD8_GT: "SADD8.GT",
- arm_SADD8_LE: "SADD8.LE",
- arm_SADD8: "SADD8",
- arm_SADD8_ZZ: "SADD8.ZZ",
- arm_SASX_EQ: "SASX.EQ",
- arm_SASX_NE: "SASX.NE",
- arm_SASX_CS: "SASX.CS",
- arm_SASX_CC: "SASX.CC",
- arm_SASX_MI: "SASX.MI",
- arm_SASX_PL: "SASX.PL",
- arm_SASX_VS: "SASX.VS",
- arm_SASX_VC: "SASX.VC",
- arm_SASX_HI: "SASX.HI",
- arm_SASX_LS: "SASX.LS",
- arm_SASX_GE: "SASX.GE",
- arm_SASX_LT: "SASX.LT",
- arm_SASX_GT: "SASX.GT",
- arm_SASX_LE: "SASX.LE",
- arm_SASX: "SASX",
- arm_SASX_ZZ: "SASX.ZZ",
- arm_SBC_EQ: "SBC.EQ",
- arm_SBC_NE: "SBC.NE",
- arm_SBC_CS: "SBC.CS",
- arm_SBC_CC: "SBC.CC",
- arm_SBC_MI: "SBC.MI",
- arm_SBC_PL: "SBC.PL",
- arm_SBC_VS: "SBC.VS",
- arm_SBC_VC: "SBC.VC",
- arm_SBC_HI: "SBC.HI",
- arm_SBC_LS: "SBC.LS",
- arm_SBC_GE: "SBC.GE",
- arm_SBC_LT: "SBC.LT",
- arm_SBC_GT: "SBC.GT",
- arm_SBC_LE: "SBC.LE",
- arm_SBC: "SBC",
- arm_SBC_ZZ: "SBC.ZZ",
- arm_SBC_S_EQ: "SBC.S.EQ",
- arm_SBC_S_NE: "SBC.S.NE",
- arm_SBC_S_CS: "SBC.S.CS",
- arm_SBC_S_CC: "SBC.S.CC",
- arm_SBC_S_MI: "SBC.S.MI",
- arm_SBC_S_PL: "SBC.S.PL",
- arm_SBC_S_VS: "SBC.S.VS",
- arm_SBC_S_VC: "SBC.S.VC",
- arm_SBC_S_HI: "SBC.S.HI",
- arm_SBC_S_LS: "SBC.S.LS",
- arm_SBC_S_GE: "SBC.S.GE",
- arm_SBC_S_LT: "SBC.S.LT",
- arm_SBC_S_GT: "SBC.S.GT",
- arm_SBC_S_LE: "SBC.S.LE",
- arm_SBC_S: "SBC.S",
- arm_SBC_S_ZZ: "SBC.S.ZZ",
- arm_SBFX_EQ: "SBFX.EQ",
- arm_SBFX_NE: "SBFX.NE",
- arm_SBFX_CS: "SBFX.CS",
- arm_SBFX_CC: "SBFX.CC",
- arm_SBFX_MI: "SBFX.MI",
- arm_SBFX_PL: "SBFX.PL",
- arm_SBFX_VS: "SBFX.VS",
- arm_SBFX_VC: "SBFX.VC",
- arm_SBFX_HI: "SBFX.HI",
- arm_SBFX_LS: "SBFX.LS",
- arm_SBFX_GE: "SBFX.GE",
- arm_SBFX_LT: "SBFX.LT",
- arm_SBFX_GT: "SBFX.GT",
- arm_SBFX_LE: "SBFX.LE",
- arm_SBFX: "SBFX",
- arm_SBFX_ZZ: "SBFX.ZZ",
- arm_SEL_EQ: "SEL.EQ",
- arm_SEL_NE: "SEL.NE",
- arm_SEL_CS: "SEL.CS",
- arm_SEL_CC: "SEL.CC",
- arm_SEL_MI: "SEL.MI",
- arm_SEL_PL: "SEL.PL",
- arm_SEL_VS: "SEL.VS",
- arm_SEL_VC: "SEL.VC",
- arm_SEL_HI: "SEL.HI",
- arm_SEL_LS: "SEL.LS",
- arm_SEL_GE: "SEL.GE",
- arm_SEL_LT: "SEL.LT",
- arm_SEL_GT: "SEL.GT",
- arm_SEL_LE: "SEL.LE",
- arm_SEL: "SEL",
- arm_SEL_ZZ: "SEL.ZZ",
- arm_SETEND: "SETEND",
- arm_SEV_EQ: "SEV.EQ",
- arm_SEV_NE: "SEV.NE",
- arm_SEV_CS: "SEV.CS",
- arm_SEV_CC: "SEV.CC",
- arm_SEV_MI: "SEV.MI",
- arm_SEV_PL: "SEV.PL",
- arm_SEV_VS: "SEV.VS",
- arm_SEV_VC: "SEV.VC",
- arm_SEV_HI: "SEV.HI",
- arm_SEV_LS: "SEV.LS",
- arm_SEV_GE: "SEV.GE",
- arm_SEV_LT: "SEV.LT",
- arm_SEV_GT: "SEV.GT",
- arm_SEV_LE: "SEV.LE",
- arm_SEV: "SEV",
- arm_SEV_ZZ: "SEV.ZZ",
- arm_SHADD16_EQ: "SHADD16.EQ",
- arm_SHADD16_NE: "SHADD16.NE",
- arm_SHADD16_CS: "SHADD16.CS",
- arm_SHADD16_CC: "SHADD16.CC",
- arm_SHADD16_MI: "SHADD16.MI",
- arm_SHADD16_PL: "SHADD16.PL",
- arm_SHADD16_VS: "SHADD16.VS",
- arm_SHADD16_VC: "SHADD16.VC",
- arm_SHADD16_HI: "SHADD16.HI",
- arm_SHADD16_LS: "SHADD16.LS",
- arm_SHADD16_GE: "SHADD16.GE",
- arm_SHADD16_LT: "SHADD16.LT",
- arm_SHADD16_GT: "SHADD16.GT",
- arm_SHADD16_LE: "SHADD16.LE",
- arm_SHADD16: "SHADD16",
- arm_SHADD16_ZZ: "SHADD16.ZZ",
- arm_SHADD8_EQ: "SHADD8.EQ",
- arm_SHADD8_NE: "SHADD8.NE",
- arm_SHADD8_CS: "SHADD8.CS",
- arm_SHADD8_CC: "SHADD8.CC",
- arm_SHADD8_MI: "SHADD8.MI",
- arm_SHADD8_PL: "SHADD8.PL",
- arm_SHADD8_VS: "SHADD8.VS",
- arm_SHADD8_VC: "SHADD8.VC",
- arm_SHADD8_HI: "SHADD8.HI",
- arm_SHADD8_LS: "SHADD8.LS",
- arm_SHADD8_GE: "SHADD8.GE",
- arm_SHADD8_LT: "SHADD8.LT",
- arm_SHADD8_GT: "SHADD8.GT",
- arm_SHADD8_LE: "SHADD8.LE",
- arm_SHADD8: "SHADD8",
- arm_SHADD8_ZZ: "SHADD8.ZZ",
- arm_SHASX_EQ: "SHASX.EQ",
- arm_SHASX_NE: "SHASX.NE",
- arm_SHASX_CS: "SHASX.CS",
- arm_SHASX_CC: "SHASX.CC",
- arm_SHASX_MI: "SHASX.MI",
- arm_SHASX_PL: "SHASX.PL",
- arm_SHASX_VS: "SHASX.VS",
- arm_SHASX_VC: "SHASX.VC",
- arm_SHASX_HI: "SHASX.HI",
- arm_SHASX_LS: "SHASX.LS",
- arm_SHASX_GE: "SHASX.GE",
- arm_SHASX_LT: "SHASX.LT",
- arm_SHASX_GT: "SHASX.GT",
- arm_SHASX_LE: "SHASX.LE",
- arm_SHASX: "SHASX",
- arm_SHASX_ZZ: "SHASX.ZZ",
- arm_SHSAX_EQ: "SHSAX.EQ",
- arm_SHSAX_NE: "SHSAX.NE",
- arm_SHSAX_CS: "SHSAX.CS",
- arm_SHSAX_CC: "SHSAX.CC",
- arm_SHSAX_MI: "SHSAX.MI",
- arm_SHSAX_PL: "SHSAX.PL",
- arm_SHSAX_VS: "SHSAX.VS",
- arm_SHSAX_VC: "SHSAX.VC",
- arm_SHSAX_HI: "SHSAX.HI",
- arm_SHSAX_LS: "SHSAX.LS",
- arm_SHSAX_GE: "SHSAX.GE",
- arm_SHSAX_LT: "SHSAX.LT",
- arm_SHSAX_GT: "SHSAX.GT",
- arm_SHSAX_LE: "SHSAX.LE",
- arm_SHSAX: "SHSAX",
- arm_SHSAX_ZZ: "SHSAX.ZZ",
- arm_SHSUB16_EQ: "SHSUB16.EQ",
- arm_SHSUB16_NE: "SHSUB16.NE",
- arm_SHSUB16_CS: "SHSUB16.CS",
- arm_SHSUB16_CC: "SHSUB16.CC",
- arm_SHSUB16_MI: "SHSUB16.MI",
- arm_SHSUB16_PL: "SHSUB16.PL",
- arm_SHSUB16_VS: "SHSUB16.VS",
- arm_SHSUB16_VC: "SHSUB16.VC",
- arm_SHSUB16_HI: "SHSUB16.HI",
- arm_SHSUB16_LS: "SHSUB16.LS",
- arm_SHSUB16_GE: "SHSUB16.GE",
- arm_SHSUB16_LT: "SHSUB16.LT",
- arm_SHSUB16_GT: "SHSUB16.GT",
- arm_SHSUB16_LE: "SHSUB16.LE",
- arm_SHSUB16: "SHSUB16",
- arm_SHSUB16_ZZ: "SHSUB16.ZZ",
- arm_SHSUB8_EQ: "SHSUB8.EQ",
- arm_SHSUB8_NE: "SHSUB8.NE",
- arm_SHSUB8_CS: "SHSUB8.CS",
- arm_SHSUB8_CC: "SHSUB8.CC",
- arm_SHSUB8_MI: "SHSUB8.MI",
- arm_SHSUB8_PL: "SHSUB8.PL",
- arm_SHSUB8_VS: "SHSUB8.VS",
- arm_SHSUB8_VC: "SHSUB8.VC",
- arm_SHSUB8_HI: "SHSUB8.HI",
- arm_SHSUB8_LS: "SHSUB8.LS",
- arm_SHSUB8_GE: "SHSUB8.GE",
- arm_SHSUB8_LT: "SHSUB8.LT",
- arm_SHSUB8_GT: "SHSUB8.GT",
- arm_SHSUB8_LE: "SHSUB8.LE",
- arm_SHSUB8: "SHSUB8",
- arm_SHSUB8_ZZ: "SHSUB8.ZZ",
- arm_SMLABB_EQ: "SMLABB.EQ",
- arm_SMLABB_NE: "SMLABB.NE",
- arm_SMLABB_CS: "SMLABB.CS",
- arm_SMLABB_CC: "SMLABB.CC",
- arm_SMLABB_MI: "SMLABB.MI",
- arm_SMLABB_PL: "SMLABB.PL",
- arm_SMLABB_VS: "SMLABB.VS",
- arm_SMLABB_VC: "SMLABB.VC",
- arm_SMLABB_HI: "SMLABB.HI",
- arm_SMLABB_LS: "SMLABB.LS",
- arm_SMLABB_GE: "SMLABB.GE",
- arm_SMLABB_LT: "SMLABB.LT",
- arm_SMLABB_GT: "SMLABB.GT",
- arm_SMLABB_LE: "SMLABB.LE",
- arm_SMLABB: "SMLABB",
- arm_SMLABB_ZZ: "SMLABB.ZZ",
- arm_SMLABT_EQ: "SMLABT.EQ",
- arm_SMLABT_NE: "SMLABT.NE",
- arm_SMLABT_CS: "SMLABT.CS",
- arm_SMLABT_CC: "SMLABT.CC",
- arm_SMLABT_MI: "SMLABT.MI",
- arm_SMLABT_PL: "SMLABT.PL",
- arm_SMLABT_VS: "SMLABT.VS",
- arm_SMLABT_VC: "SMLABT.VC",
- arm_SMLABT_HI: "SMLABT.HI",
- arm_SMLABT_LS: "SMLABT.LS",
- arm_SMLABT_GE: "SMLABT.GE",
- arm_SMLABT_LT: "SMLABT.LT",
- arm_SMLABT_GT: "SMLABT.GT",
- arm_SMLABT_LE: "SMLABT.LE",
- arm_SMLABT: "SMLABT",
- arm_SMLABT_ZZ: "SMLABT.ZZ",
- arm_SMLATB_EQ: "SMLATB.EQ",
- arm_SMLATB_NE: "SMLATB.NE",
- arm_SMLATB_CS: "SMLATB.CS",
- arm_SMLATB_CC: "SMLATB.CC",
- arm_SMLATB_MI: "SMLATB.MI",
- arm_SMLATB_PL: "SMLATB.PL",
- arm_SMLATB_VS: "SMLATB.VS",
- arm_SMLATB_VC: "SMLATB.VC",
- arm_SMLATB_HI: "SMLATB.HI",
- arm_SMLATB_LS: "SMLATB.LS",
- arm_SMLATB_GE: "SMLATB.GE",
- arm_SMLATB_LT: "SMLATB.LT",
- arm_SMLATB_GT: "SMLATB.GT",
- arm_SMLATB_LE: "SMLATB.LE",
- arm_SMLATB: "SMLATB",
- arm_SMLATB_ZZ: "SMLATB.ZZ",
- arm_SMLATT_EQ: "SMLATT.EQ",
- arm_SMLATT_NE: "SMLATT.NE",
- arm_SMLATT_CS: "SMLATT.CS",
- arm_SMLATT_CC: "SMLATT.CC",
- arm_SMLATT_MI: "SMLATT.MI",
- arm_SMLATT_PL: "SMLATT.PL",
- arm_SMLATT_VS: "SMLATT.VS",
- arm_SMLATT_VC: "SMLATT.VC",
- arm_SMLATT_HI: "SMLATT.HI",
- arm_SMLATT_LS: "SMLATT.LS",
- arm_SMLATT_GE: "SMLATT.GE",
- arm_SMLATT_LT: "SMLATT.LT",
- arm_SMLATT_GT: "SMLATT.GT",
- arm_SMLATT_LE: "SMLATT.LE",
- arm_SMLATT: "SMLATT",
- arm_SMLATT_ZZ: "SMLATT.ZZ",
- arm_SMLAD_EQ: "SMLAD.EQ",
- arm_SMLAD_NE: "SMLAD.NE",
- arm_SMLAD_CS: "SMLAD.CS",
- arm_SMLAD_CC: "SMLAD.CC",
- arm_SMLAD_MI: "SMLAD.MI",
- arm_SMLAD_PL: "SMLAD.PL",
- arm_SMLAD_VS: "SMLAD.VS",
- arm_SMLAD_VC: "SMLAD.VC",
- arm_SMLAD_HI: "SMLAD.HI",
- arm_SMLAD_LS: "SMLAD.LS",
- arm_SMLAD_GE: "SMLAD.GE",
- arm_SMLAD_LT: "SMLAD.LT",
- arm_SMLAD_GT: "SMLAD.GT",
- arm_SMLAD_LE: "SMLAD.LE",
- arm_SMLAD: "SMLAD",
- arm_SMLAD_ZZ: "SMLAD.ZZ",
- arm_SMLAD_X_EQ: "SMLAD.X.EQ",
- arm_SMLAD_X_NE: "SMLAD.X.NE",
- arm_SMLAD_X_CS: "SMLAD.X.CS",
- arm_SMLAD_X_CC: "SMLAD.X.CC",
- arm_SMLAD_X_MI: "SMLAD.X.MI",
- arm_SMLAD_X_PL: "SMLAD.X.PL",
- arm_SMLAD_X_VS: "SMLAD.X.VS",
- arm_SMLAD_X_VC: "SMLAD.X.VC",
- arm_SMLAD_X_HI: "SMLAD.X.HI",
- arm_SMLAD_X_LS: "SMLAD.X.LS",
- arm_SMLAD_X_GE: "SMLAD.X.GE",
- arm_SMLAD_X_LT: "SMLAD.X.LT",
- arm_SMLAD_X_GT: "SMLAD.X.GT",
- arm_SMLAD_X_LE: "SMLAD.X.LE",
- arm_SMLAD_X: "SMLAD.X",
- arm_SMLAD_X_ZZ: "SMLAD.X.ZZ",
- arm_SMLAL_EQ: "SMLAL.EQ",
- arm_SMLAL_NE: "SMLAL.NE",
- arm_SMLAL_CS: "SMLAL.CS",
- arm_SMLAL_CC: "SMLAL.CC",
- arm_SMLAL_MI: "SMLAL.MI",
- arm_SMLAL_PL: "SMLAL.PL",
- arm_SMLAL_VS: "SMLAL.VS",
- arm_SMLAL_VC: "SMLAL.VC",
- arm_SMLAL_HI: "SMLAL.HI",
- arm_SMLAL_LS: "SMLAL.LS",
- arm_SMLAL_GE: "SMLAL.GE",
- arm_SMLAL_LT: "SMLAL.LT",
- arm_SMLAL_GT: "SMLAL.GT",
- arm_SMLAL_LE: "SMLAL.LE",
- arm_SMLAL: "SMLAL",
- arm_SMLAL_ZZ: "SMLAL.ZZ",
- arm_SMLAL_S_EQ: "SMLAL.S.EQ",
- arm_SMLAL_S_NE: "SMLAL.S.NE",
- arm_SMLAL_S_CS: "SMLAL.S.CS",
- arm_SMLAL_S_CC: "SMLAL.S.CC",
- arm_SMLAL_S_MI: "SMLAL.S.MI",
- arm_SMLAL_S_PL: "SMLAL.S.PL",
- arm_SMLAL_S_VS: "SMLAL.S.VS",
- arm_SMLAL_S_VC: "SMLAL.S.VC",
- arm_SMLAL_S_HI: "SMLAL.S.HI",
- arm_SMLAL_S_LS: "SMLAL.S.LS",
- arm_SMLAL_S_GE: "SMLAL.S.GE",
- arm_SMLAL_S_LT: "SMLAL.S.LT",
- arm_SMLAL_S_GT: "SMLAL.S.GT",
- arm_SMLAL_S_LE: "SMLAL.S.LE",
- arm_SMLAL_S: "SMLAL.S",
- arm_SMLAL_S_ZZ: "SMLAL.S.ZZ",
- arm_SMLALBB_EQ: "SMLALBB.EQ",
- arm_SMLALBB_NE: "SMLALBB.NE",
- arm_SMLALBB_CS: "SMLALBB.CS",
- arm_SMLALBB_CC: "SMLALBB.CC",
- arm_SMLALBB_MI: "SMLALBB.MI",
- arm_SMLALBB_PL: "SMLALBB.PL",
- arm_SMLALBB_VS: "SMLALBB.VS",
- arm_SMLALBB_VC: "SMLALBB.VC",
- arm_SMLALBB_HI: "SMLALBB.HI",
- arm_SMLALBB_LS: "SMLALBB.LS",
- arm_SMLALBB_GE: "SMLALBB.GE",
- arm_SMLALBB_LT: "SMLALBB.LT",
- arm_SMLALBB_GT: "SMLALBB.GT",
- arm_SMLALBB_LE: "SMLALBB.LE",
- arm_SMLALBB: "SMLALBB",
- arm_SMLALBB_ZZ: "SMLALBB.ZZ",
- arm_SMLALBT_EQ: "SMLALBT.EQ",
- arm_SMLALBT_NE: "SMLALBT.NE",
- arm_SMLALBT_CS: "SMLALBT.CS",
- arm_SMLALBT_CC: "SMLALBT.CC",
- arm_SMLALBT_MI: "SMLALBT.MI",
- arm_SMLALBT_PL: "SMLALBT.PL",
- arm_SMLALBT_VS: "SMLALBT.VS",
- arm_SMLALBT_VC: "SMLALBT.VC",
- arm_SMLALBT_HI: "SMLALBT.HI",
- arm_SMLALBT_LS: "SMLALBT.LS",
- arm_SMLALBT_GE: "SMLALBT.GE",
- arm_SMLALBT_LT: "SMLALBT.LT",
- arm_SMLALBT_GT: "SMLALBT.GT",
- arm_SMLALBT_LE: "SMLALBT.LE",
- arm_SMLALBT: "SMLALBT",
- arm_SMLALBT_ZZ: "SMLALBT.ZZ",
- arm_SMLALTB_EQ: "SMLALTB.EQ",
- arm_SMLALTB_NE: "SMLALTB.NE",
- arm_SMLALTB_CS: "SMLALTB.CS",
- arm_SMLALTB_CC: "SMLALTB.CC",
- arm_SMLALTB_MI: "SMLALTB.MI",
- arm_SMLALTB_PL: "SMLALTB.PL",
- arm_SMLALTB_VS: "SMLALTB.VS",
- arm_SMLALTB_VC: "SMLALTB.VC",
- arm_SMLALTB_HI: "SMLALTB.HI",
- arm_SMLALTB_LS: "SMLALTB.LS",
- arm_SMLALTB_GE: "SMLALTB.GE",
- arm_SMLALTB_LT: "SMLALTB.LT",
- arm_SMLALTB_GT: "SMLALTB.GT",
- arm_SMLALTB_LE: "SMLALTB.LE",
- arm_SMLALTB: "SMLALTB",
- arm_SMLALTB_ZZ: "SMLALTB.ZZ",
- arm_SMLALTT_EQ: "SMLALTT.EQ",
- arm_SMLALTT_NE: "SMLALTT.NE",
- arm_SMLALTT_CS: "SMLALTT.CS",
- arm_SMLALTT_CC: "SMLALTT.CC",
- arm_SMLALTT_MI: "SMLALTT.MI",
- arm_SMLALTT_PL: "SMLALTT.PL",
- arm_SMLALTT_VS: "SMLALTT.VS",
- arm_SMLALTT_VC: "SMLALTT.VC",
- arm_SMLALTT_HI: "SMLALTT.HI",
- arm_SMLALTT_LS: "SMLALTT.LS",
- arm_SMLALTT_GE: "SMLALTT.GE",
- arm_SMLALTT_LT: "SMLALTT.LT",
- arm_SMLALTT_GT: "SMLALTT.GT",
- arm_SMLALTT_LE: "SMLALTT.LE",
- arm_SMLALTT: "SMLALTT",
- arm_SMLALTT_ZZ: "SMLALTT.ZZ",
- arm_SMLALD_EQ: "SMLALD.EQ",
- arm_SMLALD_NE: "SMLALD.NE",
- arm_SMLALD_CS: "SMLALD.CS",
- arm_SMLALD_CC: "SMLALD.CC",
- arm_SMLALD_MI: "SMLALD.MI",
- arm_SMLALD_PL: "SMLALD.PL",
- arm_SMLALD_VS: "SMLALD.VS",
- arm_SMLALD_VC: "SMLALD.VC",
- arm_SMLALD_HI: "SMLALD.HI",
- arm_SMLALD_LS: "SMLALD.LS",
- arm_SMLALD_GE: "SMLALD.GE",
- arm_SMLALD_LT: "SMLALD.LT",
- arm_SMLALD_GT: "SMLALD.GT",
- arm_SMLALD_LE: "SMLALD.LE",
- arm_SMLALD: "SMLALD",
- arm_SMLALD_ZZ: "SMLALD.ZZ",
- arm_SMLALD_X_EQ: "SMLALD.X.EQ",
- arm_SMLALD_X_NE: "SMLALD.X.NE",
- arm_SMLALD_X_CS: "SMLALD.X.CS",
- arm_SMLALD_X_CC: "SMLALD.X.CC",
- arm_SMLALD_X_MI: "SMLALD.X.MI",
- arm_SMLALD_X_PL: "SMLALD.X.PL",
- arm_SMLALD_X_VS: "SMLALD.X.VS",
- arm_SMLALD_X_VC: "SMLALD.X.VC",
- arm_SMLALD_X_HI: "SMLALD.X.HI",
- arm_SMLALD_X_LS: "SMLALD.X.LS",
- arm_SMLALD_X_GE: "SMLALD.X.GE",
- arm_SMLALD_X_LT: "SMLALD.X.LT",
- arm_SMLALD_X_GT: "SMLALD.X.GT",
- arm_SMLALD_X_LE: "SMLALD.X.LE",
- arm_SMLALD_X: "SMLALD.X",
- arm_SMLALD_X_ZZ: "SMLALD.X.ZZ",
- arm_SMLAWB_EQ: "SMLAWB.EQ",
- arm_SMLAWB_NE: "SMLAWB.NE",
- arm_SMLAWB_CS: "SMLAWB.CS",
- arm_SMLAWB_CC: "SMLAWB.CC",
- arm_SMLAWB_MI: "SMLAWB.MI",
- arm_SMLAWB_PL: "SMLAWB.PL",
- arm_SMLAWB_VS: "SMLAWB.VS",
- arm_SMLAWB_VC: "SMLAWB.VC",
- arm_SMLAWB_HI: "SMLAWB.HI",
- arm_SMLAWB_LS: "SMLAWB.LS",
- arm_SMLAWB_GE: "SMLAWB.GE",
- arm_SMLAWB_LT: "SMLAWB.LT",
- arm_SMLAWB_GT: "SMLAWB.GT",
- arm_SMLAWB_LE: "SMLAWB.LE",
- arm_SMLAWB: "SMLAWB",
- arm_SMLAWB_ZZ: "SMLAWB.ZZ",
- arm_SMLAWT_EQ: "SMLAWT.EQ",
- arm_SMLAWT_NE: "SMLAWT.NE",
- arm_SMLAWT_CS: "SMLAWT.CS",
- arm_SMLAWT_CC: "SMLAWT.CC",
- arm_SMLAWT_MI: "SMLAWT.MI",
- arm_SMLAWT_PL: "SMLAWT.PL",
- arm_SMLAWT_VS: "SMLAWT.VS",
- arm_SMLAWT_VC: "SMLAWT.VC",
- arm_SMLAWT_HI: "SMLAWT.HI",
- arm_SMLAWT_LS: "SMLAWT.LS",
- arm_SMLAWT_GE: "SMLAWT.GE",
- arm_SMLAWT_LT: "SMLAWT.LT",
- arm_SMLAWT_GT: "SMLAWT.GT",
- arm_SMLAWT_LE: "SMLAWT.LE",
- arm_SMLAWT: "SMLAWT",
- arm_SMLAWT_ZZ: "SMLAWT.ZZ",
- arm_SMLSD_EQ: "SMLSD.EQ",
- arm_SMLSD_NE: "SMLSD.NE",
- arm_SMLSD_CS: "SMLSD.CS",
- arm_SMLSD_CC: "SMLSD.CC",
- arm_SMLSD_MI: "SMLSD.MI",
- arm_SMLSD_PL: "SMLSD.PL",
- arm_SMLSD_VS: "SMLSD.VS",
- arm_SMLSD_VC: "SMLSD.VC",
- arm_SMLSD_HI: "SMLSD.HI",
- arm_SMLSD_LS: "SMLSD.LS",
- arm_SMLSD_GE: "SMLSD.GE",
- arm_SMLSD_LT: "SMLSD.LT",
- arm_SMLSD_GT: "SMLSD.GT",
- arm_SMLSD_LE: "SMLSD.LE",
- arm_SMLSD: "SMLSD",
- arm_SMLSD_ZZ: "SMLSD.ZZ",
- arm_SMLSD_X_EQ: "SMLSD.X.EQ",
- arm_SMLSD_X_NE: "SMLSD.X.NE",
- arm_SMLSD_X_CS: "SMLSD.X.CS",
- arm_SMLSD_X_CC: "SMLSD.X.CC",
- arm_SMLSD_X_MI: "SMLSD.X.MI",
- arm_SMLSD_X_PL: "SMLSD.X.PL",
- arm_SMLSD_X_VS: "SMLSD.X.VS",
- arm_SMLSD_X_VC: "SMLSD.X.VC",
- arm_SMLSD_X_HI: "SMLSD.X.HI",
- arm_SMLSD_X_LS: "SMLSD.X.LS",
- arm_SMLSD_X_GE: "SMLSD.X.GE",
- arm_SMLSD_X_LT: "SMLSD.X.LT",
- arm_SMLSD_X_GT: "SMLSD.X.GT",
- arm_SMLSD_X_LE: "SMLSD.X.LE",
- arm_SMLSD_X: "SMLSD.X",
- arm_SMLSD_X_ZZ: "SMLSD.X.ZZ",
- arm_SMLSLD_EQ: "SMLSLD.EQ",
- arm_SMLSLD_NE: "SMLSLD.NE",
- arm_SMLSLD_CS: "SMLSLD.CS",
- arm_SMLSLD_CC: "SMLSLD.CC",
- arm_SMLSLD_MI: "SMLSLD.MI",
- arm_SMLSLD_PL: "SMLSLD.PL",
- arm_SMLSLD_VS: "SMLSLD.VS",
- arm_SMLSLD_VC: "SMLSLD.VC",
- arm_SMLSLD_HI: "SMLSLD.HI",
- arm_SMLSLD_LS: "SMLSLD.LS",
- arm_SMLSLD_GE: "SMLSLD.GE",
- arm_SMLSLD_LT: "SMLSLD.LT",
- arm_SMLSLD_GT: "SMLSLD.GT",
- arm_SMLSLD_LE: "SMLSLD.LE",
- arm_SMLSLD: "SMLSLD",
- arm_SMLSLD_ZZ: "SMLSLD.ZZ",
- arm_SMLSLD_X_EQ: "SMLSLD.X.EQ",
- arm_SMLSLD_X_NE: "SMLSLD.X.NE",
- arm_SMLSLD_X_CS: "SMLSLD.X.CS",
- arm_SMLSLD_X_CC: "SMLSLD.X.CC",
- arm_SMLSLD_X_MI: "SMLSLD.X.MI",
- arm_SMLSLD_X_PL: "SMLSLD.X.PL",
- arm_SMLSLD_X_VS: "SMLSLD.X.VS",
- arm_SMLSLD_X_VC: "SMLSLD.X.VC",
- arm_SMLSLD_X_HI: "SMLSLD.X.HI",
- arm_SMLSLD_X_LS: "SMLSLD.X.LS",
- arm_SMLSLD_X_GE: "SMLSLD.X.GE",
- arm_SMLSLD_X_LT: "SMLSLD.X.LT",
- arm_SMLSLD_X_GT: "SMLSLD.X.GT",
- arm_SMLSLD_X_LE: "SMLSLD.X.LE",
- arm_SMLSLD_X: "SMLSLD.X",
- arm_SMLSLD_X_ZZ: "SMLSLD.X.ZZ",
- arm_SMMLA_EQ: "SMMLA.EQ",
- arm_SMMLA_NE: "SMMLA.NE",
- arm_SMMLA_CS: "SMMLA.CS",
- arm_SMMLA_CC: "SMMLA.CC",
- arm_SMMLA_MI: "SMMLA.MI",
- arm_SMMLA_PL: "SMMLA.PL",
- arm_SMMLA_VS: "SMMLA.VS",
- arm_SMMLA_VC: "SMMLA.VC",
- arm_SMMLA_HI: "SMMLA.HI",
- arm_SMMLA_LS: "SMMLA.LS",
- arm_SMMLA_GE: "SMMLA.GE",
- arm_SMMLA_LT: "SMMLA.LT",
- arm_SMMLA_GT: "SMMLA.GT",
- arm_SMMLA_LE: "SMMLA.LE",
- arm_SMMLA: "SMMLA",
- arm_SMMLA_ZZ: "SMMLA.ZZ",
- arm_SMMLA_R_EQ: "SMMLA.R.EQ",
- arm_SMMLA_R_NE: "SMMLA.R.NE",
- arm_SMMLA_R_CS: "SMMLA.R.CS",
- arm_SMMLA_R_CC: "SMMLA.R.CC",
- arm_SMMLA_R_MI: "SMMLA.R.MI",
- arm_SMMLA_R_PL: "SMMLA.R.PL",
- arm_SMMLA_R_VS: "SMMLA.R.VS",
- arm_SMMLA_R_VC: "SMMLA.R.VC",
- arm_SMMLA_R_HI: "SMMLA.R.HI",
- arm_SMMLA_R_LS: "SMMLA.R.LS",
- arm_SMMLA_R_GE: "SMMLA.R.GE",
- arm_SMMLA_R_LT: "SMMLA.R.LT",
- arm_SMMLA_R_GT: "SMMLA.R.GT",
- arm_SMMLA_R_LE: "SMMLA.R.LE",
- arm_SMMLA_R: "SMMLA.R",
- arm_SMMLA_R_ZZ: "SMMLA.R.ZZ",
- arm_SMMLS_EQ: "SMMLS.EQ",
- arm_SMMLS_NE: "SMMLS.NE",
- arm_SMMLS_CS: "SMMLS.CS",
- arm_SMMLS_CC: "SMMLS.CC",
- arm_SMMLS_MI: "SMMLS.MI",
- arm_SMMLS_PL: "SMMLS.PL",
- arm_SMMLS_VS: "SMMLS.VS",
- arm_SMMLS_VC: "SMMLS.VC",
- arm_SMMLS_HI: "SMMLS.HI",
- arm_SMMLS_LS: "SMMLS.LS",
- arm_SMMLS_GE: "SMMLS.GE",
- arm_SMMLS_LT: "SMMLS.LT",
- arm_SMMLS_GT: "SMMLS.GT",
- arm_SMMLS_LE: "SMMLS.LE",
- arm_SMMLS: "SMMLS",
- arm_SMMLS_ZZ: "SMMLS.ZZ",
- arm_SMMLS_R_EQ: "SMMLS.R.EQ",
- arm_SMMLS_R_NE: "SMMLS.R.NE",
- arm_SMMLS_R_CS: "SMMLS.R.CS",
- arm_SMMLS_R_CC: "SMMLS.R.CC",
- arm_SMMLS_R_MI: "SMMLS.R.MI",
- arm_SMMLS_R_PL: "SMMLS.R.PL",
- arm_SMMLS_R_VS: "SMMLS.R.VS",
- arm_SMMLS_R_VC: "SMMLS.R.VC",
- arm_SMMLS_R_HI: "SMMLS.R.HI",
- arm_SMMLS_R_LS: "SMMLS.R.LS",
- arm_SMMLS_R_GE: "SMMLS.R.GE",
- arm_SMMLS_R_LT: "SMMLS.R.LT",
- arm_SMMLS_R_GT: "SMMLS.R.GT",
- arm_SMMLS_R_LE: "SMMLS.R.LE",
- arm_SMMLS_R: "SMMLS.R",
- arm_SMMLS_R_ZZ: "SMMLS.R.ZZ",
- arm_SMMUL_EQ: "SMMUL.EQ",
- arm_SMMUL_NE: "SMMUL.NE",
- arm_SMMUL_CS: "SMMUL.CS",
- arm_SMMUL_CC: "SMMUL.CC",
- arm_SMMUL_MI: "SMMUL.MI",
- arm_SMMUL_PL: "SMMUL.PL",
- arm_SMMUL_VS: "SMMUL.VS",
- arm_SMMUL_VC: "SMMUL.VC",
- arm_SMMUL_HI: "SMMUL.HI",
- arm_SMMUL_LS: "SMMUL.LS",
- arm_SMMUL_GE: "SMMUL.GE",
- arm_SMMUL_LT: "SMMUL.LT",
- arm_SMMUL_GT: "SMMUL.GT",
- arm_SMMUL_LE: "SMMUL.LE",
- arm_SMMUL: "SMMUL",
- arm_SMMUL_ZZ: "SMMUL.ZZ",
- arm_SMMUL_R_EQ: "SMMUL.R.EQ",
- arm_SMMUL_R_NE: "SMMUL.R.NE",
- arm_SMMUL_R_CS: "SMMUL.R.CS",
- arm_SMMUL_R_CC: "SMMUL.R.CC",
- arm_SMMUL_R_MI: "SMMUL.R.MI",
- arm_SMMUL_R_PL: "SMMUL.R.PL",
- arm_SMMUL_R_VS: "SMMUL.R.VS",
- arm_SMMUL_R_VC: "SMMUL.R.VC",
- arm_SMMUL_R_HI: "SMMUL.R.HI",
- arm_SMMUL_R_LS: "SMMUL.R.LS",
- arm_SMMUL_R_GE: "SMMUL.R.GE",
- arm_SMMUL_R_LT: "SMMUL.R.LT",
- arm_SMMUL_R_GT: "SMMUL.R.GT",
- arm_SMMUL_R_LE: "SMMUL.R.LE",
- arm_SMMUL_R: "SMMUL.R",
- arm_SMMUL_R_ZZ: "SMMUL.R.ZZ",
- arm_SMUAD_EQ: "SMUAD.EQ",
- arm_SMUAD_NE: "SMUAD.NE",
- arm_SMUAD_CS: "SMUAD.CS",
- arm_SMUAD_CC: "SMUAD.CC",
- arm_SMUAD_MI: "SMUAD.MI",
- arm_SMUAD_PL: "SMUAD.PL",
- arm_SMUAD_VS: "SMUAD.VS",
- arm_SMUAD_VC: "SMUAD.VC",
- arm_SMUAD_HI: "SMUAD.HI",
- arm_SMUAD_LS: "SMUAD.LS",
- arm_SMUAD_GE: "SMUAD.GE",
- arm_SMUAD_LT: "SMUAD.LT",
- arm_SMUAD_GT: "SMUAD.GT",
- arm_SMUAD_LE: "SMUAD.LE",
- arm_SMUAD: "SMUAD",
- arm_SMUAD_ZZ: "SMUAD.ZZ",
- arm_SMUAD_X_EQ: "SMUAD.X.EQ",
- arm_SMUAD_X_NE: "SMUAD.X.NE",
- arm_SMUAD_X_CS: "SMUAD.X.CS",
- arm_SMUAD_X_CC: "SMUAD.X.CC",
- arm_SMUAD_X_MI: "SMUAD.X.MI",
- arm_SMUAD_X_PL: "SMUAD.X.PL",
- arm_SMUAD_X_VS: "SMUAD.X.VS",
- arm_SMUAD_X_VC: "SMUAD.X.VC",
- arm_SMUAD_X_HI: "SMUAD.X.HI",
- arm_SMUAD_X_LS: "SMUAD.X.LS",
- arm_SMUAD_X_GE: "SMUAD.X.GE",
- arm_SMUAD_X_LT: "SMUAD.X.LT",
- arm_SMUAD_X_GT: "SMUAD.X.GT",
- arm_SMUAD_X_LE: "SMUAD.X.LE",
- arm_SMUAD_X: "SMUAD.X",
- arm_SMUAD_X_ZZ: "SMUAD.X.ZZ",
- arm_SMULBB_EQ: "SMULBB.EQ",
- arm_SMULBB_NE: "SMULBB.NE",
- arm_SMULBB_CS: "SMULBB.CS",
- arm_SMULBB_CC: "SMULBB.CC",
- arm_SMULBB_MI: "SMULBB.MI",
- arm_SMULBB_PL: "SMULBB.PL",
- arm_SMULBB_VS: "SMULBB.VS",
- arm_SMULBB_VC: "SMULBB.VC",
- arm_SMULBB_HI: "SMULBB.HI",
- arm_SMULBB_LS: "SMULBB.LS",
- arm_SMULBB_GE: "SMULBB.GE",
- arm_SMULBB_LT: "SMULBB.LT",
- arm_SMULBB_GT: "SMULBB.GT",
- arm_SMULBB_LE: "SMULBB.LE",
- arm_SMULBB: "SMULBB",
- arm_SMULBB_ZZ: "SMULBB.ZZ",
- arm_SMULBT_EQ: "SMULBT.EQ",
- arm_SMULBT_NE: "SMULBT.NE",
- arm_SMULBT_CS: "SMULBT.CS",
- arm_SMULBT_CC: "SMULBT.CC",
- arm_SMULBT_MI: "SMULBT.MI",
- arm_SMULBT_PL: "SMULBT.PL",
- arm_SMULBT_VS: "SMULBT.VS",
- arm_SMULBT_VC: "SMULBT.VC",
- arm_SMULBT_HI: "SMULBT.HI",
- arm_SMULBT_LS: "SMULBT.LS",
- arm_SMULBT_GE: "SMULBT.GE",
- arm_SMULBT_LT: "SMULBT.LT",
- arm_SMULBT_GT: "SMULBT.GT",
- arm_SMULBT_LE: "SMULBT.LE",
- arm_SMULBT: "SMULBT",
- arm_SMULBT_ZZ: "SMULBT.ZZ",
- arm_SMULTB_EQ: "SMULTB.EQ",
- arm_SMULTB_NE: "SMULTB.NE",
- arm_SMULTB_CS: "SMULTB.CS",
- arm_SMULTB_CC: "SMULTB.CC",
- arm_SMULTB_MI: "SMULTB.MI",
- arm_SMULTB_PL: "SMULTB.PL",
- arm_SMULTB_VS: "SMULTB.VS",
- arm_SMULTB_VC: "SMULTB.VC",
- arm_SMULTB_HI: "SMULTB.HI",
- arm_SMULTB_LS: "SMULTB.LS",
- arm_SMULTB_GE: "SMULTB.GE",
- arm_SMULTB_LT: "SMULTB.LT",
- arm_SMULTB_GT: "SMULTB.GT",
- arm_SMULTB_LE: "SMULTB.LE",
- arm_SMULTB: "SMULTB",
- arm_SMULTB_ZZ: "SMULTB.ZZ",
- arm_SMULTT_EQ: "SMULTT.EQ",
- arm_SMULTT_NE: "SMULTT.NE",
- arm_SMULTT_CS: "SMULTT.CS",
- arm_SMULTT_CC: "SMULTT.CC",
- arm_SMULTT_MI: "SMULTT.MI",
- arm_SMULTT_PL: "SMULTT.PL",
- arm_SMULTT_VS: "SMULTT.VS",
- arm_SMULTT_VC: "SMULTT.VC",
- arm_SMULTT_HI: "SMULTT.HI",
- arm_SMULTT_LS: "SMULTT.LS",
- arm_SMULTT_GE: "SMULTT.GE",
- arm_SMULTT_LT: "SMULTT.LT",
- arm_SMULTT_GT: "SMULTT.GT",
- arm_SMULTT_LE: "SMULTT.LE",
- arm_SMULTT: "SMULTT",
- arm_SMULTT_ZZ: "SMULTT.ZZ",
- arm_SMULL_EQ: "SMULL.EQ",
- arm_SMULL_NE: "SMULL.NE",
- arm_SMULL_CS: "SMULL.CS",
- arm_SMULL_CC: "SMULL.CC",
- arm_SMULL_MI: "SMULL.MI",
- arm_SMULL_PL: "SMULL.PL",
- arm_SMULL_VS: "SMULL.VS",
- arm_SMULL_VC: "SMULL.VC",
- arm_SMULL_HI: "SMULL.HI",
- arm_SMULL_LS: "SMULL.LS",
- arm_SMULL_GE: "SMULL.GE",
- arm_SMULL_LT: "SMULL.LT",
- arm_SMULL_GT: "SMULL.GT",
- arm_SMULL_LE: "SMULL.LE",
- arm_SMULL: "SMULL",
- arm_SMULL_ZZ: "SMULL.ZZ",
- arm_SMULL_S_EQ: "SMULL.S.EQ",
- arm_SMULL_S_NE: "SMULL.S.NE",
- arm_SMULL_S_CS: "SMULL.S.CS",
- arm_SMULL_S_CC: "SMULL.S.CC",
- arm_SMULL_S_MI: "SMULL.S.MI",
- arm_SMULL_S_PL: "SMULL.S.PL",
- arm_SMULL_S_VS: "SMULL.S.VS",
- arm_SMULL_S_VC: "SMULL.S.VC",
- arm_SMULL_S_HI: "SMULL.S.HI",
- arm_SMULL_S_LS: "SMULL.S.LS",
- arm_SMULL_S_GE: "SMULL.S.GE",
- arm_SMULL_S_LT: "SMULL.S.LT",
- arm_SMULL_S_GT: "SMULL.S.GT",
- arm_SMULL_S_LE: "SMULL.S.LE",
- arm_SMULL_S: "SMULL.S",
- arm_SMULL_S_ZZ: "SMULL.S.ZZ",
- arm_SMULWB_EQ: "SMULWB.EQ",
- arm_SMULWB_NE: "SMULWB.NE",
- arm_SMULWB_CS: "SMULWB.CS",
- arm_SMULWB_CC: "SMULWB.CC",
- arm_SMULWB_MI: "SMULWB.MI",
- arm_SMULWB_PL: "SMULWB.PL",
- arm_SMULWB_VS: "SMULWB.VS",
- arm_SMULWB_VC: "SMULWB.VC",
- arm_SMULWB_HI: "SMULWB.HI",
- arm_SMULWB_LS: "SMULWB.LS",
- arm_SMULWB_GE: "SMULWB.GE",
- arm_SMULWB_LT: "SMULWB.LT",
- arm_SMULWB_GT: "SMULWB.GT",
- arm_SMULWB_LE: "SMULWB.LE",
- arm_SMULWB: "SMULWB",
- arm_SMULWB_ZZ: "SMULWB.ZZ",
- arm_SMULWT_EQ: "SMULWT.EQ",
- arm_SMULWT_NE: "SMULWT.NE",
- arm_SMULWT_CS: "SMULWT.CS",
- arm_SMULWT_CC: "SMULWT.CC",
- arm_SMULWT_MI: "SMULWT.MI",
- arm_SMULWT_PL: "SMULWT.PL",
- arm_SMULWT_VS: "SMULWT.VS",
- arm_SMULWT_VC: "SMULWT.VC",
- arm_SMULWT_HI: "SMULWT.HI",
- arm_SMULWT_LS: "SMULWT.LS",
- arm_SMULWT_GE: "SMULWT.GE",
- arm_SMULWT_LT: "SMULWT.LT",
- arm_SMULWT_GT: "SMULWT.GT",
- arm_SMULWT_LE: "SMULWT.LE",
- arm_SMULWT: "SMULWT",
- arm_SMULWT_ZZ: "SMULWT.ZZ",
- arm_SMUSD_EQ: "SMUSD.EQ",
- arm_SMUSD_NE: "SMUSD.NE",
- arm_SMUSD_CS: "SMUSD.CS",
- arm_SMUSD_CC: "SMUSD.CC",
- arm_SMUSD_MI: "SMUSD.MI",
- arm_SMUSD_PL: "SMUSD.PL",
- arm_SMUSD_VS: "SMUSD.VS",
- arm_SMUSD_VC: "SMUSD.VC",
- arm_SMUSD_HI: "SMUSD.HI",
- arm_SMUSD_LS: "SMUSD.LS",
- arm_SMUSD_GE: "SMUSD.GE",
- arm_SMUSD_LT: "SMUSD.LT",
- arm_SMUSD_GT: "SMUSD.GT",
- arm_SMUSD_LE: "SMUSD.LE",
- arm_SMUSD: "SMUSD",
- arm_SMUSD_ZZ: "SMUSD.ZZ",
- arm_SMUSD_X_EQ: "SMUSD.X.EQ",
- arm_SMUSD_X_NE: "SMUSD.X.NE",
- arm_SMUSD_X_CS: "SMUSD.X.CS",
- arm_SMUSD_X_CC: "SMUSD.X.CC",
- arm_SMUSD_X_MI: "SMUSD.X.MI",
- arm_SMUSD_X_PL: "SMUSD.X.PL",
- arm_SMUSD_X_VS: "SMUSD.X.VS",
- arm_SMUSD_X_VC: "SMUSD.X.VC",
- arm_SMUSD_X_HI: "SMUSD.X.HI",
- arm_SMUSD_X_LS: "SMUSD.X.LS",
- arm_SMUSD_X_GE: "SMUSD.X.GE",
- arm_SMUSD_X_LT: "SMUSD.X.LT",
- arm_SMUSD_X_GT: "SMUSD.X.GT",
- arm_SMUSD_X_LE: "SMUSD.X.LE",
- arm_SMUSD_X: "SMUSD.X",
- arm_SMUSD_X_ZZ: "SMUSD.X.ZZ",
- arm_SSAT_EQ: "SSAT.EQ",
- arm_SSAT_NE: "SSAT.NE",
- arm_SSAT_CS: "SSAT.CS",
- arm_SSAT_CC: "SSAT.CC",
- arm_SSAT_MI: "SSAT.MI",
- arm_SSAT_PL: "SSAT.PL",
- arm_SSAT_VS: "SSAT.VS",
- arm_SSAT_VC: "SSAT.VC",
- arm_SSAT_HI: "SSAT.HI",
- arm_SSAT_LS: "SSAT.LS",
- arm_SSAT_GE: "SSAT.GE",
- arm_SSAT_LT: "SSAT.LT",
- arm_SSAT_GT: "SSAT.GT",
- arm_SSAT_LE: "SSAT.LE",
- arm_SSAT: "SSAT",
- arm_SSAT_ZZ: "SSAT.ZZ",
- arm_SSAT16_EQ: "SSAT16.EQ",
- arm_SSAT16_NE: "SSAT16.NE",
- arm_SSAT16_CS: "SSAT16.CS",
- arm_SSAT16_CC: "SSAT16.CC",
- arm_SSAT16_MI: "SSAT16.MI",
- arm_SSAT16_PL: "SSAT16.PL",
- arm_SSAT16_VS: "SSAT16.VS",
- arm_SSAT16_VC: "SSAT16.VC",
- arm_SSAT16_HI: "SSAT16.HI",
- arm_SSAT16_LS: "SSAT16.LS",
- arm_SSAT16_GE: "SSAT16.GE",
- arm_SSAT16_LT: "SSAT16.LT",
- arm_SSAT16_GT: "SSAT16.GT",
- arm_SSAT16_LE: "SSAT16.LE",
- arm_SSAT16: "SSAT16",
- arm_SSAT16_ZZ: "SSAT16.ZZ",
- arm_SSAX_EQ: "SSAX.EQ",
- arm_SSAX_NE: "SSAX.NE",
- arm_SSAX_CS: "SSAX.CS",
- arm_SSAX_CC: "SSAX.CC",
- arm_SSAX_MI: "SSAX.MI",
- arm_SSAX_PL: "SSAX.PL",
- arm_SSAX_VS: "SSAX.VS",
- arm_SSAX_VC: "SSAX.VC",
- arm_SSAX_HI: "SSAX.HI",
- arm_SSAX_LS: "SSAX.LS",
- arm_SSAX_GE: "SSAX.GE",
- arm_SSAX_LT: "SSAX.LT",
- arm_SSAX_GT: "SSAX.GT",
- arm_SSAX_LE: "SSAX.LE",
- arm_SSAX: "SSAX",
- arm_SSAX_ZZ: "SSAX.ZZ",
- arm_SSUB16_EQ: "SSUB16.EQ",
- arm_SSUB16_NE: "SSUB16.NE",
- arm_SSUB16_CS: "SSUB16.CS",
- arm_SSUB16_CC: "SSUB16.CC",
- arm_SSUB16_MI: "SSUB16.MI",
- arm_SSUB16_PL: "SSUB16.PL",
- arm_SSUB16_VS: "SSUB16.VS",
- arm_SSUB16_VC: "SSUB16.VC",
- arm_SSUB16_HI: "SSUB16.HI",
- arm_SSUB16_LS: "SSUB16.LS",
- arm_SSUB16_GE: "SSUB16.GE",
- arm_SSUB16_LT: "SSUB16.LT",
- arm_SSUB16_GT: "SSUB16.GT",
- arm_SSUB16_LE: "SSUB16.LE",
- arm_SSUB16: "SSUB16",
- arm_SSUB16_ZZ: "SSUB16.ZZ",
- arm_SSUB8_EQ: "SSUB8.EQ",
- arm_SSUB8_NE: "SSUB8.NE",
- arm_SSUB8_CS: "SSUB8.CS",
- arm_SSUB8_CC: "SSUB8.CC",
- arm_SSUB8_MI: "SSUB8.MI",
- arm_SSUB8_PL: "SSUB8.PL",
- arm_SSUB8_VS: "SSUB8.VS",
- arm_SSUB8_VC: "SSUB8.VC",
- arm_SSUB8_HI: "SSUB8.HI",
- arm_SSUB8_LS: "SSUB8.LS",
- arm_SSUB8_GE: "SSUB8.GE",
- arm_SSUB8_LT: "SSUB8.LT",
- arm_SSUB8_GT: "SSUB8.GT",
- arm_SSUB8_LE: "SSUB8.LE",
- arm_SSUB8: "SSUB8",
- arm_SSUB8_ZZ: "SSUB8.ZZ",
- arm_STM_EQ: "STM.EQ",
- arm_STM_NE: "STM.NE",
- arm_STM_CS: "STM.CS",
- arm_STM_CC: "STM.CC",
- arm_STM_MI: "STM.MI",
- arm_STM_PL: "STM.PL",
- arm_STM_VS: "STM.VS",
- arm_STM_VC: "STM.VC",
- arm_STM_HI: "STM.HI",
- arm_STM_LS: "STM.LS",
- arm_STM_GE: "STM.GE",
- arm_STM_LT: "STM.LT",
- arm_STM_GT: "STM.GT",
- arm_STM_LE: "STM.LE",
- arm_STM: "STM",
- arm_STM_ZZ: "STM.ZZ",
- arm_STMDA_EQ: "STMDA.EQ",
- arm_STMDA_NE: "STMDA.NE",
- arm_STMDA_CS: "STMDA.CS",
- arm_STMDA_CC: "STMDA.CC",
- arm_STMDA_MI: "STMDA.MI",
- arm_STMDA_PL: "STMDA.PL",
- arm_STMDA_VS: "STMDA.VS",
- arm_STMDA_VC: "STMDA.VC",
- arm_STMDA_HI: "STMDA.HI",
- arm_STMDA_LS: "STMDA.LS",
- arm_STMDA_GE: "STMDA.GE",
- arm_STMDA_LT: "STMDA.LT",
- arm_STMDA_GT: "STMDA.GT",
- arm_STMDA_LE: "STMDA.LE",
- arm_STMDA: "STMDA",
- arm_STMDA_ZZ: "STMDA.ZZ",
- arm_STMDB_EQ: "STMDB.EQ",
- arm_STMDB_NE: "STMDB.NE",
- arm_STMDB_CS: "STMDB.CS",
- arm_STMDB_CC: "STMDB.CC",
- arm_STMDB_MI: "STMDB.MI",
- arm_STMDB_PL: "STMDB.PL",
- arm_STMDB_VS: "STMDB.VS",
- arm_STMDB_VC: "STMDB.VC",
- arm_STMDB_HI: "STMDB.HI",
- arm_STMDB_LS: "STMDB.LS",
- arm_STMDB_GE: "STMDB.GE",
- arm_STMDB_LT: "STMDB.LT",
- arm_STMDB_GT: "STMDB.GT",
- arm_STMDB_LE: "STMDB.LE",
- arm_STMDB: "STMDB",
- arm_STMDB_ZZ: "STMDB.ZZ",
- arm_STMIB_EQ: "STMIB.EQ",
- arm_STMIB_NE: "STMIB.NE",
- arm_STMIB_CS: "STMIB.CS",
- arm_STMIB_CC: "STMIB.CC",
- arm_STMIB_MI: "STMIB.MI",
- arm_STMIB_PL: "STMIB.PL",
- arm_STMIB_VS: "STMIB.VS",
- arm_STMIB_VC: "STMIB.VC",
- arm_STMIB_HI: "STMIB.HI",
- arm_STMIB_LS: "STMIB.LS",
- arm_STMIB_GE: "STMIB.GE",
- arm_STMIB_LT: "STMIB.LT",
- arm_STMIB_GT: "STMIB.GT",
- arm_STMIB_LE: "STMIB.LE",
- arm_STMIB: "STMIB",
- arm_STMIB_ZZ: "STMIB.ZZ",
- arm_STR_EQ: "STR.EQ",
- arm_STR_NE: "STR.NE",
- arm_STR_CS: "STR.CS",
- arm_STR_CC: "STR.CC",
- arm_STR_MI: "STR.MI",
- arm_STR_PL: "STR.PL",
- arm_STR_VS: "STR.VS",
- arm_STR_VC: "STR.VC",
- arm_STR_HI: "STR.HI",
- arm_STR_LS: "STR.LS",
- arm_STR_GE: "STR.GE",
- arm_STR_LT: "STR.LT",
- arm_STR_GT: "STR.GT",
- arm_STR_LE: "STR.LE",
- arm_STR: "STR",
- arm_STR_ZZ: "STR.ZZ",
- arm_STRB_EQ: "STRB.EQ",
- arm_STRB_NE: "STRB.NE",
- arm_STRB_CS: "STRB.CS",
- arm_STRB_CC: "STRB.CC",
- arm_STRB_MI: "STRB.MI",
- arm_STRB_PL: "STRB.PL",
- arm_STRB_VS: "STRB.VS",
- arm_STRB_VC: "STRB.VC",
- arm_STRB_HI: "STRB.HI",
- arm_STRB_LS: "STRB.LS",
- arm_STRB_GE: "STRB.GE",
- arm_STRB_LT: "STRB.LT",
- arm_STRB_GT: "STRB.GT",
- arm_STRB_LE: "STRB.LE",
- arm_STRB: "STRB",
- arm_STRB_ZZ: "STRB.ZZ",
- arm_STRBT_EQ: "STRBT.EQ",
- arm_STRBT_NE: "STRBT.NE",
- arm_STRBT_CS: "STRBT.CS",
- arm_STRBT_CC: "STRBT.CC",
- arm_STRBT_MI: "STRBT.MI",
- arm_STRBT_PL: "STRBT.PL",
- arm_STRBT_VS: "STRBT.VS",
- arm_STRBT_VC: "STRBT.VC",
- arm_STRBT_HI: "STRBT.HI",
- arm_STRBT_LS: "STRBT.LS",
- arm_STRBT_GE: "STRBT.GE",
- arm_STRBT_LT: "STRBT.LT",
- arm_STRBT_GT: "STRBT.GT",
- arm_STRBT_LE: "STRBT.LE",
- arm_STRBT: "STRBT",
- arm_STRBT_ZZ: "STRBT.ZZ",
- arm_STRD_EQ: "STRD.EQ",
- arm_STRD_NE: "STRD.NE",
- arm_STRD_CS: "STRD.CS",
- arm_STRD_CC: "STRD.CC",
- arm_STRD_MI: "STRD.MI",
- arm_STRD_PL: "STRD.PL",
- arm_STRD_VS: "STRD.VS",
- arm_STRD_VC: "STRD.VC",
- arm_STRD_HI: "STRD.HI",
- arm_STRD_LS: "STRD.LS",
- arm_STRD_GE: "STRD.GE",
- arm_STRD_LT: "STRD.LT",
- arm_STRD_GT: "STRD.GT",
- arm_STRD_LE: "STRD.LE",
- arm_STRD: "STRD",
- arm_STRD_ZZ: "STRD.ZZ",
- arm_STREX_EQ: "STREX.EQ",
- arm_STREX_NE: "STREX.NE",
- arm_STREX_CS: "STREX.CS",
- arm_STREX_CC: "STREX.CC",
- arm_STREX_MI: "STREX.MI",
- arm_STREX_PL: "STREX.PL",
- arm_STREX_VS: "STREX.VS",
- arm_STREX_VC: "STREX.VC",
- arm_STREX_HI: "STREX.HI",
- arm_STREX_LS: "STREX.LS",
- arm_STREX_GE: "STREX.GE",
- arm_STREX_LT: "STREX.LT",
- arm_STREX_GT: "STREX.GT",
- arm_STREX_LE: "STREX.LE",
- arm_STREX: "STREX",
- arm_STREX_ZZ: "STREX.ZZ",
- arm_STREXB_EQ: "STREXB.EQ",
- arm_STREXB_NE: "STREXB.NE",
- arm_STREXB_CS: "STREXB.CS",
- arm_STREXB_CC: "STREXB.CC",
- arm_STREXB_MI: "STREXB.MI",
- arm_STREXB_PL: "STREXB.PL",
- arm_STREXB_VS: "STREXB.VS",
- arm_STREXB_VC: "STREXB.VC",
- arm_STREXB_HI: "STREXB.HI",
- arm_STREXB_LS: "STREXB.LS",
- arm_STREXB_GE: "STREXB.GE",
- arm_STREXB_LT: "STREXB.LT",
- arm_STREXB_GT: "STREXB.GT",
- arm_STREXB_LE: "STREXB.LE",
- arm_STREXB: "STREXB",
- arm_STREXB_ZZ: "STREXB.ZZ",
- arm_STREXD_EQ: "STREXD.EQ",
- arm_STREXD_NE: "STREXD.NE",
- arm_STREXD_CS: "STREXD.CS",
- arm_STREXD_CC: "STREXD.CC",
- arm_STREXD_MI: "STREXD.MI",
- arm_STREXD_PL: "STREXD.PL",
- arm_STREXD_VS: "STREXD.VS",
- arm_STREXD_VC: "STREXD.VC",
- arm_STREXD_HI: "STREXD.HI",
- arm_STREXD_LS: "STREXD.LS",
- arm_STREXD_GE: "STREXD.GE",
- arm_STREXD_LT: "STREXD.LT",
- arm_STREXD_GT: "STREXD.GT",
- arm_STREXD_LE: "STREXD.LE",
- arm_STREXD: "STREXD",
- arm_STREXD_ZZ: "STREXD.ZZ",
- arm_STREXH_EQ: "STREXH.EQ",
- arm_STREXH_NE: "STREXH.NE",
- arm_STREXH_CS: "STREXH.CS",
- arm_STREXH_CC: "STREXH.CC",
- arm_STREXH_MI: "STREXH.MI",
- arm_STREXH_PL: "STREXH.PL",
- arm_STREXH_VS: "STREXH.VS",
- arm_STREXH_VC: "STREXH.VC",
- arm_STREXH_HI: "STREXH.HI",
- arm_STREXH_LS: "STREXH.LS",
- arm_STREXH_GE: "STREXH.GE",
- arm_STREXH_LT: "STREXH.LT",
- arm_STREXH_GT: "STREXH.GT",
- arm_STREXH_LE: "STREXH.LE",
- arm_STREXH: "STREXH",
- arm_STREXH_ZZ: "STREXH.ZZ",
- arm_STRH_EQ: "STRH.EQ",
- arm_STRH_NE: "STRH.NE",
- arm_STRH_CS: "STRH.CS",
- arm_STRH_CC: "STRH.CC",
- arm_STRH_MI: "STRH.MI",
- arm_STRH_PL: "STRH.PL",
- arm_STRH_VS: "STRH.VS",
- arm_STRH_VC: "STRH.VC",
- arm_STRH_HI: "STRH.HI",
- arm_STRH_LS: "STRH.LS",
- arm_STRH_GE: "STRH.GE",
- arm_STRH_LT: "STRH.LT",
- arm_STRH_GT: "STRH.GT",
- arm_STRH_LE: "STRH.LE",
- arm_STRH: "STRH",
- arm_STRH_ZZ: "STRH.ZZ",
- arm_STRHT_EQ: "STRHT.EQ",
- arm_STRHT_NE: "STRHT.NE",
- arm_STRHT_CS: "STRHT.CS",
- arm_STRHT_CC: "STRHT.CC",
- arm_STRHT_MI: "STRHT.MI",
- arm_STRHT_PL: "STRHT.PL",
- arm_STRHT_VS: "STRHT.VS",
- arm_STRHT_VC: "STRHT.VC",
- arm_STRHT_HI: "STRHT.HI",
- arm_STRHT_LS: "STRHT.LS",
- arm_STRHT_GE: "STRHT.GE",
- arm_STRHT_LT: "STRHT.LT",
- arm_STRHT_GT: "STRHT.GT",
- arm_STRHT_LE: "STRHT.LE",
- arm_STRHT: "STRHT",
- arm_STRHT_ZZ: "STRHT.ZZ",
- arm_STRT_EQ: "STRT.EQ",
- arm_STRT_NE: "STRT.NE",
- arm_STRT_CS: "STRT.CS",
- arm_STRT_CC: "STRT.CC",
- arm_STRT_MI: "STRT.MI",
- arm_STRT_PL: "STRT.PL",
- arm_STRT_VS: "STRT.VS",
- arm_STRT_VC: "STRT.VC",
- arm_STRT_HI: "STRT.HI",
- arm_STRT_LS: "STRT.LS",
- arm_STRT_GE: "STRT.GE",
- arm_STRT_LT: "STRT.LT",
- arm_STRT_GT: "STRT.GT",
- arm_STRT_LE: "STRT.LE",
- arm_STRT: "STRT",
- arm_STRT_ZZ: "STRT.ZZ",
- arm_SUB_EQ: "SUB.EQ",
- arm_SUB_NE: "SUB.NE",
- arm_SUB_CS: "SUB.CS",
- arm_SUB_CC: "SUB.CC",
- arm_SUB_MI: "SUB.MI",
- arm_SUB_PL: "SUB.PL",
- arm_SUB_VS: "SUB.VS",
- arm_SUB_VC: "SUB.VC",
- arm_SUB_HI: "SUB.HI",
- arm_SUB_LS: "SUB.LS",
- arm_SUB_GE: "SUB.GE",
- arm_SUB_LT: "SUB.LT",
- arm_SUB_GT: "SUB.GT",
- arm_SUB_LE: "SUB.LE",
- arm_SUB: "SUB",
- arm_SUB_ZZ: "SUB.ZZ",
- arm_SUB_S_EQ: "SUB.S.EQ",
- arm_SUB_S_NE: "SUB.S.NE",
- arm_SUB_S_CS: "SUB.S.CS",
- arm_SUB_S_CC: "SUB.S.CC",
- arm_SUB_S_MI: "SUB.S.MI",
- arm_SUB_S_PL: "SUB.S.PL",
- arm_SUB_S_VS: "SUB.S.VS",
- arm_SUB_S_VC: "SUB.S.VC",
- arm_SUB_S_HI: "SUB.S.HI",
- arm_SUB_S_LS: "SUB.S.LS",
- arm_SUB_S_GE: "SUB.S.GE",
- arm_SUB_S_LT: "SUB.S.LT",
- arm_SUB_S_GT: "SUB.S.GT",
- arm_SUB_S_LE: "SUB.S.LE",
- arm_SUB_S: "SUB.S",
- arm_SUB_S_ZZ: "SUB.S.ZZ",
- arm_SVC_EQ: "SVC.EQ",
- arm_SVC_NE: "SVC.NE",
- arm_SVC_CS: "SVC.CS",
- arm_SVC_CC: "SVC.CC",
- arm_SVC_MI: "SVC.MI",
- arm_SVC_PL: "SVC.PL",
- arm_SVC_VS: "SVC.VS",
- arm_SVC_VC: "SVC.VC",
- arm_SVC_HI: "SVC.HI",
- arm_SVC_LS: "SVC.LS",
- arm_SVC_GE: "SVC.GE",
- arm_SVC_LT: "SVC.LT",
- arm_SVC_GT: "SVC.GT",
- arm_SVC_LE: "SVC.LE",
- arm_SVC: "SVC",
- arm_SVC_ZZ: "SVC.ZZ",
- arm_SWP_EQ: "SWP.EQ",
- arm_SWP_NE: "SWP.NE",
- arm_SWP_CS: "SWP.CS",
- arm_SWP_CC: "SWP.CC",
- arm_SWP_MI: "SWP.MI",
- arm_SWP_PL: "SWP.PL",
- arm_SWP_VS: "SWP.VS",
- arm_SWP_VC: "SWP.VC",
- arm_SWP_HI: "SWP.HI",
- arm_SWP_LS: "SWP.LS",
- arm_SWP_GE: "SWP.GE",
- arm_SWP_LT: "SWP.LT",
- arm_SWP_GT: "SWP.GT",
- arm_SWP_LE: "SWP.LE",
- arm_SWP: "SWP",
- arm_SWP_ZZ: "SWP.ZZ",
- arm_SWP_B_EQ: "SWP.B.EQ",
- arm_SWP_B_NE: "SWP.B.NE",
- arm_SWP_B_CS: "SWP.B.CS",
- arm_SWP_B_CC: "SWP.B.CC",
- arm_SWP_B_MI: "SWP.B.MI",
- arm_SWP_B_PL: "SWP.B.PL",
- arm_SWP_B_VS: "SWP.B.VS",
- arm_SWP_B_VC: "SWP.B.VC",
- arm_SWP_B_HI: "SWP.B.HI",
- arm_SWP_B_LS: "SWP.B.LS",
- arm_SWP_B_GE: "SWP.B.GE",
- arm_SWP_B_LT: "SWP.B.LT",
- arm_SWP_B_GT: "SWP.B.GT",
- arm_SWP_B_LE: "SWP.B.LE",
- arm_SWP_B: "SWP.B",
- arm_SWP_B_ZZ: "SWP.B.ZZ",
- arm_SXTAB_EQ: "SXTAB.EQ",
- arm_SXTAB_NE: "SXTAB.NE",
- arm_SXTAB_CS: "SXTAB.CS",
- arm_SXTAB_CC: "SXTAB.CC",
- arm_SXTAB_MI: "SXTAB.MI",
- arm_SXTAB_PL: "SXTAB.PL",
- arm_SXTAB_VS: "SXTAB.VS",
- arm_SXTAB_VC: "SXTAB.VC",
- arm_SXTAB_HI: "SXTAB.HI",
- arm_SXTAB_LS: "SXTAB.LS",
- arm_SXTAB_GE: "SXTAB.GE",
- arm_SXTAB_LT: "SXTAB.LT",
- arm_SXTAB_GT: "SXTAB.GT",
- arm_SXTAB_LE: "SXTAB.LE",
- arm_SXTAB: "SXTAB",
- arm_SXTAB_ZZ: "SXTAB.ZZ",
- arm_SXTAB16_EQ: "SXTAB16.EQ",
- arm_SXTAB16_NE: "SXTAB16.NE",
- arm_SXTAB16_CS: "SXTAB16.CS",
- arm_SXTAB16_CC: "SXTAB16.CC",
- arm_SXTAB16_MI: "SXTAB16.MI",
- arm_SXTAB16_PL: "SXTAB16.PL",
- arm_SXTAB16_VS: "SXTAB16.VS",
- arm_SXTAB16_VC: "SXTAB16.VC",
- arm_SXTAB16_HI: "SXTAB16.HI",
- arm_SXTAB16_LS: "SXTAB16.LS",
- arm_SXTAB16_GE: "SXTAB16.GE",
- arm_SXTAB16_LT: "SXTAB16.LT",
- arm_SXTAB16_GT: "SXTAB16.GT",
- arm_SXTAB16_LE: "SXTAB16.LE",
- arm_SXTAB16: "SXTAB16",
- arm_SXTAB16_ZZ: "SXTAB16.ZZ",
- arm_SXTAH_EQ: "SXTAH.EQ",
- arm_SXTAH_NE: "SXTAH.NE",
- arm_SXTAH_CS: "SXTAH.CS",
- arm_SXTAH_CC: "SXTAH.CC",
- arm_SXTAH_MI: "SXTAH.MI",
- arm_SXTAH_PL: "SXTAH.PL",
- arm_SXTAH_VS: "SXTAH.VS",
- arm_SXTAH_VC: "SXTAH.VC",
- arm_SXTAH_HI: "SXTAH.HI",
- arm_SXTAH_LS: "SXTAH.LS",
- arm_SXTAH_GE: "SXTAH.GE",
- arm_SXTAH_LT: "SXTAH.LT",
- arm_SXTAH_GT: "SXTAH.GT",
- arm_SXTAH_LE: "SXTAH.LE",
- arm_SXTAH: "SXTAH",
- arm_SXTAH_ZZ: "SXTAH.ZZ",
- arm_SXTB_EQ: "SXTB.EQ",
- arm_SXTB_NE: "SXTB.NE",
- arm_SXTB_CS: "SXTB.CS",
- arm_SXTB_CC: "SXTB.CC",
- arm_SXTB_MI: "SXTB.MI",
- arm_SXTB_PL: "SXTB.PL",
- arm_SXTB_VS: "SXTB.VS",
- arm_SXTB_VC: "SXTB.VC",
- arm_SXTB_HI: "SXTB.HI",
- arm_SXTB_LS: "SXTB.LS",
- arm_SXTB_GE: "SXTB.GE",
- arm_SXTB_LT: "SXTB.LT",
- arm_SXTB_GT: "SXTB.GT",
- arm_SXTB_LE: "SXTB.LE",
- arm_SXTB: "SXTB",
- arm_SXTB_ZZ: "SXTB.ZZ",
- arm_SXTB16_EQ: "SXTB16.EQ",
- arm_SXTB16_NE: "SXTB16.NE",
- arm_SXTB16_CS: "SXTB16.CS",
- arm_SXTB16_CC: "SXTB16.CC",
- arm_SXTB16_MI: "SXTB16.MI",
- arm_SXTB16_PL: "SXTB16.PL",
- arm_SXTB16_VS: "SXTB16.VS",
- arm_SXTB16_VC: "SXTB16.VC",
- arm_SXTB16_HI: "SXTB16.HI",
- arm_SXTB16_LS: "SXTB16.LS",
- arm_SXTB16_GE: "SXTB16.GE",
- arm_SXTB16_LT: "SXTB16.LT",
- arm_SXTB16_GT: "SXTB16.GT",
- arm_SXTB16_LE: "SXTB16.LE",
- arm_SXTB16: "SXTB16",
- arm_SXTB16_ZZ: "SXTB16.ZZ",
- arm_SXTH_EQ: "SXTH.EQ",
- arm_SXTH_NE: "SXTH.NE",
- arm_SXTH_CS: "SXTH.CS",
- arm_SXTH_CC: "SXTH.CC",
- arm_SXTH_MI: "SXTH.MI",
- arm_SXTH_PL: "SXTH.PL",
- arm_SXTH_VS: "SXTH.VS",
- arm_SXTH_VC: "SXTH.VC",
- arm_SXTH_HI: "SXTH.HI",
- arm_SXTH_LS: "SXTH.LS",
- arm_SXTH_GE: "SXTH.GE",
- arm_SXTH_LT: "SXTH.LT",
- arm_SXTH_GT: "SXTH.GT",
- arm_SXTH_LE: "SXTH.LE",
- arm_SXTH: "SXTH",
- arm_SXTH_ZZ: "SXTH.ZZ",
- arm_TEQ_EQ: "TEQ.EQ",
- arm_TEQ_NE: "TEQ.NE",
- arm_TEQ_CS: "TEQ.CS",
- arm_TEQ_CC: "TEQ.CC",
- arm_TEQ_MI: "TEQ.MI",
- arm_TEQ_PL: "TEQ.PL",
- arm_TEQ_VS: "TEQ.VS",
- arm_TEQ_VC: "TEQ.VC",
- arm_TEQ_HI: "TEQ.HI",
- arm_TEQ_LS: "TEQ.LS",
- arm_TEQ_GE: "TEQ.GE",
- arm_TEQ_LT: "TEQ.LT",
- arm_TEQ_GT: "TEQ.GT",
- arm_TEQ_LE: "TEQ.LE",
- arm_TEQ: "TEQ",
- arm_TEQ_ZZ: "TEQ.ZZ",
- arm_TST_EQ: "TST.EQ",
- arm_TST_NE: "TST.NE",
- arm_TST_CS: "TST.CS",
- arm_TST_CC: "TST.CC",
- arm_TST_MI: "TST.MI",
- arm_TST_PL: "TST.PL",
- arm_TST_VS: "TST.VS",
- arm_TST_VC: "TST.VC",
- arm_TST_HI: "TST.HI",
- arm_TST_LS: "TST.LS",
- arm_TST_GE: "TST.GE",
- arm_TST_LT: "TST.LT",
- arm_TST_GT: "TST.GT",
- arm_TST_LE: "TST.LE",
- arm_TST: "TST",
- arm_TST_ZZ: "TST.ZZ",
- arm_UADD16_EQ: "UADD16.EQ",
- arm_UADD16_NE: "UADD16.NE",
- arm_UADD16_CS: "UADD16.CS",
- arm_UADD16_CC: "UADD16.CC",
- arm_UADD16_MI: "UADD16.MI",
- arm_UADD16_PL: "UADD16.PL",
- arm_UADD16_VS: "UADD16.VS",
- arm_UADD16_VC: "UADD16.VC",
- arm_UADD16_HI: "UADD16.HI",
- arm_UADD16_LS: "UADD16.LS",
- arm_UADD16_GE: "UADD16.GE",
- arm_UADD16_LT: "UADD16.LT",
- arm_UADD16_GT: "UADD16.GT",
- arm_UADD16_LE: "UADD16.LE",
- arm_UADD16: "UADD16",
- arm_UADD16_ZZ: "UADD16.ZZ",
- arm_UADD8_EQ: "UADD8.EQ",
- arm_UADD8_NE: "UADD8.NE",
- arm_UADD8_CS: "UADD8.CS",
- arm_UADD8_CC: "UADD8.CC",
- arm_UADD8_MI: "UADD8.MI",
- arm_UADD8_PL: "UADD8.PL",
- arm_UADD8_VS: "UADD8.VS",
- arm_UADD8_VC: "UADD8.VC",
- arm_UADD8_HI: "UADD8.HI",
- arm_UADD8_LS: "UADD8.LS",
- arm_UADD8_GE: "UADD8.GE",
- arm_UADD8_LT: "UADD8.LT",
- arm_UADD8_GT: "UADD8.GT",
- arm_UADD8_LE: "UADD8.LE",
- arm_UADD8: "UADD8",
- arm_UADD8_ZZ: "UADD8.ZZ",
- arm_UASX_EQ: "UASX.EQ",
- arm_UASX_NE: "UASX.NE",
- arm_UASX_CS: "UASX.CS",
- arm_UASX_CC: "UASX.CC",
- arm_UASX_MI: "UASX.MI",
- arm_UASX_PL: "UASX.PL",
- arm_UASX_VS: "UASX.VS",
- arm_UASX_VC: "UASX.VC",
- arm_UASX_HI: "UASX.HI",
- arm_UASX_LS: "UASX.LS",
- arm_UASX_GE: "UASX.GE",
- arm_UASX_LT: "UASX.LT",
- arm_UASX_GT: "UASX.GT",
- arm_UASX_LE: "UASX.LE",
- arm_UASX: "UASX",
- arm_UASX_ZZ: "UASX.ZZ",
- arm_UBFX_EQ: "UBFX.EQ",
- arm_UBFX_NE: "UBFX.NE",
- arm_UBFX_CS: "UBFX.CS",
- arm_UBFX_CC: "UBFX.CC",
- arm_UBFX_MI: "UBFX.MI",
- arm_UBFX_PL: "UBFX.PL",
- arm_UBFX_VS: "UBFX.VS",
- arm_UBFX_VC: "UBFX.VC",
- arm_UBFX_HI: "UBFX.HI",
- arm_UBFX_LS: "UBFX.LS",
- arm_UBFX_GE: "UBFX.GE",
- arm_UBFX_LT: "UBFX.LT",
- arm_UBFX_GT: "UBFX.GT",
- arm_UBFX_LE: "UBFX.LE",
- arm_UBFX: "UBFX",
- arm_UBFX_ZZ: "UBFX.ZZ",
- arm_UHADD16_EQ: "UHADD16.EQ",
- arm_UHADD16_NE: "UHADD16.NE",
- arm_UHADD16_CS: "UHADD16.CS",
- arm_UHADD16_CC: "UHADD16.CC",
- arm_UHADD16_MI: "UHADD16.MI",
- arm_UHADD16_PL: "UHADD16.PL",
- arm_UHADD16_VS: "UHADD16.VS",
- arm_UHADD16_VC: "UHADD16.VC",
- arm_UHADD16_HI: "UHADD16.HI",
- arm_UHADD16_LS: "UHADD16.LS",
- arm_UHADD16_GE: "UHADD16.GE",
- arm_UHADD16_LT: "UHADD16.LT",
- arm_UHADD16_GT: "UHADD16.GT",
- arm_UHADD16_LE: "UHADD16.LE",
- arm_UHADD16: "UHADD16",
- arm_UHADD16_ZZ: "UHADD16.ZZ",
- arm_UHADD8_EQ: "UHADD8.EQ",
- arm_UHADD8_NE: "UHADD8.NE",
- arm_UHADD8_CS: "UHADD8.CS",
- arm_UHADD8_CC: "UHADD8.CC",
- arm_UHADD8_MI: "UHADD8.MI",
- arm_UHADD8_PL: "UHADD8.PL",
- arm_UHADD8_VS: "UHADD8.VS",
- arm_UHADD8_VC: "UHADD8.VC",
- arm_UHADD8_HI: "UHADD8.HI",
- arm_UHADD8_LS: "UHADD8.LS",
- arm_UHADD8_GE: "UHADD8.GE",
- arm_UHADD8_LT: "UHADD8.LT",
- arm_UHADD8_GT: "UHADD8.GT",
- arm_UHADD8_LE: "UHADD8.LE",
- arm_UHADD8: "UHADD8",
- arm_UHADD8_ZZ: "UHADD8.ZZ",
- arm_UHASX_EQ: "UHASX.EQ",
- arm_UHASX_NE: "UHASX.NE",
- arm_UHASX_CS: "UHASX.CS",
- arm_UHASX_CC: "UHASX.CC",
- arm_UHASX_MI: "UHASX.MI",
- arm_UHASX_PL: "UHASX.PL",
- arm_UHASX_VS: "UHASX.VS",
- arm_UHASX_VC: "UHASX.VC",
- arm_UHASX_HI: "UHASX.HI",
- arm_UHASX_LS: "UHASX.LS",
- arm_UHASX_GE: "UHASX.GE",
- arm_UHASX_LT: "UHASX.LT",
- arm_UHASX_GT: "UHASX.GT",
- arm_UHASX_LE: "UHASX.LE",
- arm_UHASX: "UHASX",
- arm_UHASX_ZZ: "UHASX.ZZ",
- arm_UHSAX_EQ: "UHSAX.EQ",
- arm_UHSAX_NE: "UHSAX.NE",
- arm_UHSAX_CS: "UHSAX.CS",
- arm_UHSAX_CC: "UHSAX.CC",
- arm_UHSAX_MI: "UHSAX.MI",
- arm_UHSAX_PL: "UHSAX.PL",
- arm_UHSAX_VS: "UHSAX.VS",
- arm_UHSAX_VC: "UHSAX.VC",
- arm_UHSAX_HI: "UHSAX.HI",
- arm_UHSAX_LS: "UHSAX.LS",
- arm_UHSAX_GE: "UHSAX.GE",
- arm_UHSAX_LT: "UHSAX.LT",
- arm_UHSAX_GT: "UHSAX.GT",
- arm_UHSAX_LE: "UHSAX.LE",
- arm_UHSAX: "UHSAX",
- arm_UHSAX_ZZ: "UHSAX.ZZ",
- arm_UHSUB16_EQ: "UHSUB16.EQ",
- arm_UHSUB16_NE: "UHSUB16.NE",
- arm_UHSUB16_CS: "UHSUB16.CS",
- arm_UHSUB16_CC: "UHSUB16.CC",
- arm_UHSUB16_MI: "UHSUB16.MI",
- arm_UHSUB16_PL: "UHSUB16.PL",
- arm_UHSUB16_VS: "UHSUB16.VS",
- arm_UHSUB16_VC: "UHSUB16.VC",
- arm_UHSUB16_HI: "UHSUB16.HI",
- arm_UHSUB16_LS: "UHSUB16.LS",
- arm_UHSUB16_GE: "UHSUB16.GE",
- arm_UHSUB16_LT: "UHSUB16.LT",
- arm_UHSUB16_GT: "UHSUB16.GT",
- arm_UHSUB16_LE: "UHSUB16.LE",
- arm_UHSUB16: "UHSUB16",
- arm_UHSUB16_ZZ: "UHSUB16.ZZ",
- arm_UHSUB8_EQ: "UHSUB8.EQ",
- arm_UHSUB8_NE: "UHSUB8.NE",
- arm_UHSUB8_CS: "UHSUB8.CS",
- arm_UHSUB8_CC: "UHSUB8.CC",
- arm_UHSUB8_MI: "UHSUB8.MI",
- arm_UHSUB8_PL: "UHSUB8.PL",
- arm_UHSUB8_VS: "UHSUB8.VS",
- arm_UHSUB8_VC: "UHSUB8.VC",
- arm_UHSUB8_HI: "UHSUB8.HI",
- arm_UHSUB8_LS: "UHSUB8.LS",
- arm_UHSUB8_GE: "UHSUB8.GE",
- arm_UHSUB8_LT: "UHSUB8.LT",
- arm_UHSUB8_GT: "UHSUB8.GT",
- arm_UHSUB8_LE: "UHSUB8.LE",
- arm_UHSUB8: "UHSUB8",
- arm_UHSUB8_ZZ: "UHSUB8.ZZ",
- arm_UMAAL_EQ: "UMAAL.EQ",
- arm_UMAAL_NE: "UMAAL.NE",
- arm_UMAAL_CS: "UMAAL.CS",
- arm_UMAAL_CC: "UMAAL.CC",
- arm_UMAAL_MI: "UMAAL.MI",
- arm_UMAAL_PL: "UMAAL.PL",
- arm_UMAAL_VS: "UMAAL.VS",
- arm_UMAAL_VC: "UMAAL.VC",
- arm_UMAAL_HI: "UMAAL.HI",
- arm_UMAAL_LS: "UMAAL.LS",
- arm_UMAAL_GE: "UMAAL.GE",
- arm_UMAAL_LT: "UMAAL.LT",
- arm_UMAAL_GT: "UMAAL.GT",
- arm_UMAAL_LE: "UMAAL.LE",
- arm_UMAAL: "UMAAL",
- arm_UMAAL_ZZ: "UMAAL.ZZ",
- arm_UMLAL_EQ: "UMLAL.EQ",
- arm_UMLAL_NE: "UMLAL.NE",
- arm_UMLAL_CS: "UMLAL.CS",
- arm_UMLAL_CC: "UMLAL.CC",
- arm_UMLAL_MI: "UMLAL.MI",
- arm_UMLAL_PL: "UMLAL.PL",
- arm_UMLAL_VS: "UMLAL.VS",
- arm_UMLAL_VC: "UMLAL.VC",
- arm_UMLAL_HI: "UMLAL.HI",
- arm_UMLAL_LS: "UMLAL.LS",
- arm_UMLAL_GE: "UMLAL.GE",
- arm_UMLAL_LT: "UMLAL.LT",
- arm_UMLAL_GT: "UMLAL.GT",
- arm_UMLAL_LE: "UMLAL.LE",
- arm_UMLAL: "UMLAL",
- arm_UMLAL_ZZ: "UMLAL.ZZ",
- arm_UMLAL_S_EQ: "UMLAL.S.EQ",
- arm_UMLAL_S_NE: "UMLAL.S.NE",
- arm_UMLAL_S_CS: "UMLAL.S.CS",
- arm_UMLAL_S_CC: "UMLAL.S.CC",
- arm_UMLAL_S_MI: "UMLAL.S.MI",
- arm_UMLAL_S_PL: "UMLAL.S.PL",
- arm_UMLAL_S_VS: "UMLAL.S.VS",
- arm_UMLAL_S_VC: "UMLAL.S.VC",
- arm_UMLAL_S_HI: "UMLAL.S.HI",
- arm_UMLAL_S_LS: "UMLAL.S.LS",
- arm_UMLAL_S_GE: "UMLAL.S.GE",
- arm_UMLAL_S_LT: "UMLAL.S.LT",
- arm_UMLAL_S_GT: "UMLAL.S.GT",
- arm_UMLAL_S_LE: "UMLAL.S.LE",
- arm_UMLAL_S: "UMLAL.S",
- arm_UMLAL_S_ZZ: "UMLAL.S.ZZ",
- arm_UMULL_EQ: "UMULL.EQ",
- arm_UMULL_NE: "UMULL.NE",
- arm_UMULL_CS: "UMULL.CS",
- arm_UMULL_CC: "UMULL.CC",
- arm_UMULL_MI: "UMULL.MI",
- arm_UMULL_PL: "UMULL.PL",
- arm_UMULL_VS: "UMULL.VS",
- arm_UMULL_VC: "UMULL.VC",
- arm_UMULL_HI: "UMULL.HI",
- arm_UMULL_LS: "UMULL.LS",
- arm_UMULL_GE: "UMULL.GE",
- arm_UMULL_LT: "UMULL.LT",
- arm_UMULL_GT: "UMULL.GT",
- arm_UMULL_LE: "UMULL.LE",
- arm_UMULL: "UMULL",
- arm_UMULL_ZZ: "UMULL.ZZ",
- arm_UMULL_S_EQ: "UMULL.S.EQ",
- arm_UMULL_S_NE: "UMULL.S.NE",
- arm_UMULL_S_CS: "UMULL.S.CS",
- arm_UMULL_S_CC: "UMULL.S.CC",
- arm_UMULL_S_MI: "UMULL.S.MI",
- arm_UMULL_S_PL: "UMULL.S.PL",
- arm_UMULL_S_VS: "UMULL.S.VS",
- arm_UMULL_S_VC: "UMULL.S.VC",
- arm_UMULL_S_HI: "UMULL.S.HI",
- arm_UMULL_S_LS: "UMULL.S.LS",
- arm_UMULL_S_GE: "UMULL.S.GE",
- arm_UMULL_S_LT: "UMULL.S.LT",
- arm_UMULL_S_GT: "UMULL.S.GT",
- arm_UMULL_S_LE: "UMULL.S.LE",
- arm_UMULL_S: "UMULL.S",
- arm_UMULL_S_ZZ: "UMULL.S.ZZ",
- arm_UNDEF: "UNDEF",
- arm_UQADD16_EQ: "UQADD16.EQ",
- arm_UQADD16_NE: "UQADD16.NE",
- arm_UQADD16_CS: "UQADD16.CS",
- arm_UQADD16_CC: "UQADD16.CC",
- arm_UQADD16_MI: "UQADD16.MI",
- arm_UQADD16_PL: "UQADD16.PL",
- arm_UQADD16_VS: "UQADD16.VS",
- arm_UQADD16_VC: "UQADD16.VC",
- arm_UQADD16_HI: "UQADD16.HI",
- arm_UQADD16_LS: "UQADD16.LS",
- arm_UQADD16_GE: "UQADD16.GE",
- arm_UQADD16_LT: "UQADD16.LT",
- arm_UQADD16_GT: "UQADD16.GT",
- arm_UQADD16_LE: "UQADD16.LE",
- arm_UQADD16: "UQADD16",
- arm_UQADD16_ZZ: "UQADD16.ZZ",
- arm_UQADD8_EQ: "UQADD8.EQ",
- arm_UQADD8_NE: "UQADD8.NE",
- arm_UQADD8_CS: "UQADD8.CS",
- arm_UQADD8_CC: "UQADD8.CC",
- arm_UQADD8_MI: "UQADD8.MI",
- arm_UQADD8_PL: "UQADD8.PL",
- arm_UQADD8_VS: "UQADD8.VS",
- arm_UQADD8_VC: "UQADD8.VC",
- arm_UQADD8_HI: "UQADD8.HI",
- arm_UQADD8_LS: "UQADD8.LS",
- arm_UQADD8_GE: "UQADD8.GE",
- arm_UQADD8_LT: "UQADD8.LT",
- arm_UQADD8_GT: "UQADD8.GT",
- arm_UQADD8_LE: "UQADD8.LE",
- arm_UQADD8: "UQADD8",
- arm_UQADD8_ZZ: "UQADD8.ZZ",
- arm_UQASX_EQ: "UQASX.EQ",
- arm_UQASX_NE: "UQASX.NE",
- arm_UQASX_CS: "UQASX.CS",
- arm_UQASX_CC: "UQASX.CC",
- arm_UQASX_MI: "UQASX.MI",
- arm_UQASX_PL: "UQASX.PL",
- arm_UQASX_VS: "UQASX.VS",
- arm_UQASX_VC: "UQASX.VC",
- arm_UQASX_HI: "UQASX.HI",
- arm_UQASX_LS: "UQASX.LS",
- arm_UQASX_GE: "UQASX.GE",
- arm_UQASX_LT: "UQASX.LT",
- arm_UQASX_GT: "UQASX.GT",
- arm_UQASX_LE: "UQASX.LE",
- arm_UQASX: "UQASX",
- arm_UQASX_ZZ: "UQASX.ZZ",
- arm_UQSAX_EQ: "UQSAX.EQ",
- arm_UQSAX_NE: "UQSAX.NE",
- arm_UQSAX_CS: "UQSAX.CS",
- arm_UQSAX_CC: "UQSAX.CC",
- arm_UQSAX_MI: "UQSAX.MI",
- arm_UQSAX_PL: "UQSAX.PL",
- arm_UQSAX_VS: "UQSAX.VS",
- arm_UQSAX_VC: "UQSAX.VC",
- arm_UQSAX_HI: "UQSAX.HI",
- arm_UQSAX_LS: "UQSAX.LS",
- arm_UQSAX_GE: "UQSAX.GE",
- arm_UQSAX_LT: "UQSAX.LT",
- arm_UQSAX_GT: "UQSAX.GT",
- arm_UQSAX_LE: "UQSAX.LE",
- arm_UQSAX: "UQSAX",
- arm_UQSAX_ZZ: "UQSAX.ZZ",
- arm_UQSUB16_EQ: "UQSUB16.EQ",
- arm_UQSUB16_NE: "UQSUB16.NE",
- arm_UQSUB16_CS: "UQSUB16.CS",
- arm_UQSUB16_CC: "UQSUB16.CC",
- arm_UQSUB16_MI: "UQSUB16.MI",
- arm_UQSUB16_PL: "UQSUB16.PL",
- arm_UQSUB16_VS: "UQSUB16.VS",
- arm_UQSUB16_VC: "UQSUB16.VC",
- arm_UQSUB16_HI: "UQSUB16.HI",
- arm_UQSUB16_LS: "UQSUB16.LS",
- arm_UQSUB16_GE: "UQSUB16.GE",
- arm_UQSUB16_LT: "UQSUB16.LT",
- arm_UQSUB16_GT: "UQSUB16.GT",
- arm_UQSUB16_LE: "UQSUB16.LE",
- arm_UQSUB16: "UQSUB16",
- arm_UQSUB16_ZZ: "UQSUB16.ZZ",
- arm_UQSUB8_EQ: "UQSUB8.EQ",
- arm_UQSUB8_NE: "UQSUB8.NE",
- arm_UQSUB8_CS: "UQSUB8.CS",
- arm_UQSUB8_CC: "UQSUB8.CC",
- arm_UQSUB8_MI: "UQSUB8.MI",
- arm_UQSUB8_PL: "UQSUB8.PL",
- arm_UQSUB8_VS: "UQSUB8.VS",
- arm_UQSUB8_VC: "UQSUB8.VC",
- arm_UQSUB8_HI: "UQSUB8.HI",
- arm_UQSUB8_LS: "UQSUB8.LS",
- arm_UQSUB8_GE: "UQSUB8.GE",
- arm_UQSUB8_LT: "UQSUB8.LT",
- arm_UQSUB8_GT: "UQSUB8.GT",
- arm_UQSUB8_LE: "UQSUB8.LE",
- arm_UQSUB8: "UQSUB8",
- arm_UQSUB8_ZZ: "UQSUB8.ZZ",
- arm_USAD8_EQ: "USAD8.EQ",
- arm_USAD8_NE: "USAD8.NE",
- arm_USAD8_CS: "USAD8.CS",
- arm_USAD8_CC: "USAD8.CC",
- arm_USAD8_MI: "USAD8.MI",
- arm_USAD8_PL: "USAD8.PL",
- arm_USAD8_VS: "USAD8.VS",
- arm_USAD8_VC: "USAD8.VC",
- arm_USAD8_HI: "USAD8.HI",
- arm_USAD8_LS: "USAD8.LS",
- arm_USAD8_GE: "USAD8.GE",
- arm_USAD8_LT: "USAD8.LT",
- arm_USAD8_GT: "USAD8.GT",
- arm_USAD8_LE: "USAD8.LE",
- arm_USAD8: "USAD8",
- arm_USAD8_ZZ: "USAD8.ZZ",
- arm_USADA8_EQ: "USADA8.EQ",
- arm_USADA8_NE: "USADA8.NE",
- arm_USADA8_CS: "USADA8.CS",
- arm_USADA8_CC: "USADA8.CC",
- arm_USADA8_MI: "USADA8.MI",
- arm_USADA8_PL: "USADA8.PL",
- arm_USADA8_VS: "USADA8.VS",
- arm_USADA8_VC: "USADA8.VC",
- arm_USADA8_HI: "USADA8.HI",
- arm_USADA8_LS: "USADA8.LS",
- arm_USADA8_GE: "USADA8.GE",
- arm_USADA8_LT: "USADA8.LT",
- arm_USADA8_GT: "USADA8.GT",
- arm_USADA8_LE: "USADA8.LE",
- arm_USADA8: "USADA8",
- arm_USADA8_ZZ: "USADA8.ZZ",
- arm_USAT_EQ: "USAT.EQ",
- arm_USAT_NE: "USAT.NE",
- arm_USAT_CS: "USAT.CS",
- arm_USAT_CC: "USAT.CC",
- arm_USAT_MI: "USAT.MI",
- arm_USAT_PL: "USAT.PL",
- arm_USAT_VS: "USAT.VS",
- arm_USAT_VC: "USAT.VC",
- arm_USAT_HI: "USAT.HI",
- arm_USAT_LS: "USAT.LS",
- arm_USAT_GE: "USAT.GE",
- arm_USAT_LT: "USAT.LT",
- arm_USAT_GT: "USAT.GT",
- arm_USAT_LE: "USAT.LE",
- arm_USAT: "USAT",
- arm_USAT_ZZ: "USAT.ZZ",
- arm_USAT16_EQ: "USAT16.EQ",
- arm_USAT16_NE: "USAT16.NE",
- arm_USAT16_CS: "USAT16.CS",
- arm_USAT16_CC: "USAT16.CC",
- arm_USAT16_MI: "USAT16.MI",
- arm_USAT16_PL: "USAT16.PL",
- arm_USAT16_VS: "USAT16.VS",
- arm_USAT16_VC: "USAT16.VC",
- arm_USAT16_HI: "USAT16.HI",
- arm_USAT16_LS: "USAT16.LS",
- arm_USAT16_GE: "USAT16.GE",
- arm_USAT16_LT: "USAT16.LT",
- arm_USAT16_GT: "USAT16.GT",
- arm_USAT16_LE: "USAT16.LE",
- arm_USAT16: "USAT16",
- arm_USAT16_ZZ: "USAT16.ZZ",
- arm_USAX_EQ: "USAX.EQ",
- arm_USAX_NE: "USAX.NE",
- arm_USAX_CS: "USAX.CS",
- arm_USAX_CC: "USAX.CC",
- arm_USAX_MI: "USAX.MI",
- arm_USAX_PL: "USAX.PL",
- arm_USAX_VS: "USAX.VS",
- arm_USAX_VC: "USAX.VC",
- arm_USAX_HI: "USAX.HI",
- arm_USAX_LS: "USAX.LS",
- arm_USAX_GE: "USAX.GE",
- arm_USAX_LT: "USAX.LT",
- arm_USAX_GT: "USAX.GT",
- arm_USAX_LE: "USAX.LE",
- arm_USAX: "USAX",
- arm_USAX_ZZ: "USAX.ZZ",
- arm_USUB16_EQ: "USUB16.EQ",
- arm_USUB16_NE: "USUB16.NE",
- arm_USUB16_CS: "USUB16.CS",
- arm_USUB16_CC: "USUB16.CC",
- arm_USUB16_MI: "USUB16.MI",
- arm_USUB16_PL: "USUB16.PL",
- arm_USUB16_VS: "USUB16.VS",
- arm_USUB16_VC: "USUB16.VC",
- arm_USUB16_HI: "USUB16.HI",
- arm_USUB16_LS: "USUB16.LS",
- arm_USUB16_GE: "USUB16.GE",
- arm_USUB16_LT: "USUB16.LT",
- arm_USUB16_GT: "USUB16.GT",
- arm_USUB16_LE: "USUB16.LE",
- arm_USUB16: "USUB16",
- arm_USUB16_ZZ: "USUB16.ZZ",
- arm_USUB8_EQ: "USUB8.EQ",
- arm_USUB8_NE: "USUB8.NE",
- arm_USUB8_CS: "USUB8.CS",
- arm_USUB8_CC: "USUB8.CC",
- arm_USUB8_MI: "USUB8.MI",
- arm_USUB8_PL: "USUB8.PL",
- arm_USUB8_VS: "USUB8.VS",
- arm_USUB8_VC: "USUB8.VC",
- arm_USUB8_HI: "USUB8.HI",
- arm_USUB8_LS: "USUB8.LS",
- arm_USUB8_GE: "USUB8.GE",
- arm_USUB8_LT: "USUB8.LT",
- arm_USUB8_GT: "USUB8.GT",
- arm_USUB8_LE: "USUB8.LE",
- arm_USUB8: "USUB8",
- arm_USUB8_ZZ: "USUB8.ZZ",
- arm_UXTAB_EQ: "UXTAB.EQ",
- arm_UXTAB_NE: "UXTAB.NE",
- arm_UXTAB_CS: "UXTAB.CS",
- arm_UXTAB_CC: "UXTAB.CC",
- arm_UXTAB_MI: "UXTAB.MI",
- arm_UXTAB_PL: "UXTAB.PL",
- arm_UXTAB_VS: "UXTAB.VS",
- arm_UXTAB_VC: "UXTAB.VC",
- arm_UXTAB_HI: "UXTAB.HI",
- arm_UXTAB_LS: "UXTAB.LS",
- arm_UXTAB_GE: "UXTAB.GE",
- arm_UXTAB_LT: "UXTAB.LT",
- arm_UXTAB_GT: "UXTAB.GT",
- arm_UXTAB_LE: "UXTAB.LE",
- arm_UXTAB: "UXTAB",
- arm_UXTAB_ZZ: "UXTAB.ZZ",
- arm_UXTAB16_EQ: "UXTAB16.EQ",
- arm_UXTAB16_NE: "UXTAB16.NE",
- arm_UXTAB16_CS: "UXTAB16.CS",
- arm_UXTAB16_CC: "UXTAB16.CC",
- arm_UXTAB16_MI: "UXTAB16.MI",
- arm_UXTAB16_PL: "UXTAB16.PL",
- arm_UXTAB16_VS: "UXTAB16.VS",
- arm_UXTAB16_VC: "UXTAB16.VC",
- arm_UXTAB16_HI: "UXTAB16.HI",
- arm_UXTAB16_LS: "UXTAB16.LS",
- arm_UXTAB16_GE: "UXTAB16.GE",
- arm_UXTAB16_LT: "UXTAB16.LT",
- arm_UXTAB16_GT: "UXTAB16.GT",
- arm_UXTAB16_LE: "UXTAB16.LE",
- arm_UXTAB16: "UXTAB16",
- arm_UXTAB16_ZZ: "UXTAB16.ZZ",
- arm_UXTAH_EQ: "UXTAH.EQ",
- arm_UXTAH_NE: "UXTAH.NE",
- arm_UXTAH_CS: "UXTAH.CS",
- arm_UXTAH_CC: "UXTAH.CC",
- arm_UXTAH_MI: "UXTAH.MI",
- arm_UXTAH_PL: "UXTAH.PL",
- arm_UXTAH_VS: "UXTAH.VS",
- arm_UXTAH_VC: "UXTAH.VC",
- arm_UXTAH_HI: "UXTAH.HI",
- arm_UXTAH_LS: "UXTAH.LS",
- arm_UXTAH_GE: "UXTAH.GE",
- arm_UXTAH_LT: "UXTAH.LT",
- arm_UXTAH_GT: "UXTAH.GT",
- arm_UXTAH_LE: "UXTAH.LE",
- arm_UXTAH: "UXTAH",
- arm_UXTAH_ZZ: "UXTAH.ZZ",
- arm_UXTB_EQ: "UXTB.EQ",
- arm_UXTB_NE: "UXTB.NE",
- arm_UXTB_CS: "UXTB.CS",
- arm_UXTB_CC: "UXTB.CC",
- arm_UXTB_MI: "UXTB.MI",
- arm_UXTB_PL: "UXTB.PL",
- arm_UXTB_VS: "UXTB.VS",
- arm_UXTB_VC: "UXTB.VC",
- arm_UXTB_HI: "UXTB.HI",
- arm_UXTB_LS: "UXTB.LS",
- arm_UXTB_GE: "UXTB.GE",
- arm_UXTB_LT: "UXTB.LT",
- arm_UXTB_GT: "UXTB.GT",
- arm_UXTB_LE: "UXTB.LE",
- arm_UXTB: "UXTB",
- arm_UXTB_ZZ: "UXTB.ZZ",
- arm_UXTB16_EQ: "UXTB16.EQ",
- arm_UXTB16_NE: "UXTB16.NE",
- arm_UXTB16_CS: "UXTB16.CS",
- arm_UXTB16_CC: "UXTB16.CC",
- arm_UXTB16_MI: "UXTB16.MI",
- arm_UXTB16_PL: "UXTB16.PL",
- arm_UXTB16_VS: "UXTB16.VS",
- arm_UXTB16_VC: "UXTB16.VC",
- arm_UXTB16_HI: "UXTB16.HI",
- arm_UXTB16_LS: "UXTB16.LS",
- arm_UXTB16_GE: "UXTB16.GE",
- arm_UXTB16_LT: "UXTB16.LT",
- arm_UXTB16_GT: "UXTB16.GT",
- arm_UXTB16_LE: "UXTB16.LE",
- arm_UXTB16: "UXTB16",
- arm_UXTB16_ZZ: "UXTB16.ZZ",
- arm_UXTH_EQ: "UXTH.EQ",
- arm_UXTH_NE: "UXTH.NE",
- arm_UXTH_CS: "UXTH.CS",
- arm_UXTH_CC: "UXTH.CC",
- arm_UXTH_MI: "UXTH.MI",
- arm_UXTH_PL: "UXTH.PL",
- arm_UXTH_VS: "UXTH.VS",
- arm_UXTH_VC: "UXTH.VC",
- arm_UXTH_HI: "UXTH.HI",
- arm_UXTH_LS: "UXTH.LS",
- arm_UXTH_GE: "UXTH.GE",
- arm_UXTH_LT: "UXTH.LT",
- arm_UXTH_GT: "UXTH.GT",
- arm_UXTH_LE: "UXTH.LE",
- arm_UXTH: "UXTH",
- arm_UXTH_ZZ: "UXTH.ZZ",
- arm_VABS_EQ_F32: "VABS.EQ.F32",
- arm_VABS_NE_F32: "VABS.NE.F32",
- arm_VABS_CS_F32: "VABS.CS.F32",
- arm_VABS_CC_F32: "VABS.CC.F32",
- arm_VABS_MI_F32: "VABS.MI.F32",
- arm_VABS_PL_F32: "VABS.PL.F32",
- arm_VABS_VS_F32: "VABS.VS.F32",
- arm_VABS_VC_F32: "VABS.VC.F32",
- arm_VABS_HI_F32: "VABS.HI.F32",
- arm_VABS_LS_F32: "VABS.LS.F32",
- arm_VABS_GE_F32: "VABS.GE.F32",
- arm_VABS_LT_F32: "VABS.LT.F32",
- arm_VABS_GT_F32: "VABS.GT.F32",
- arm_VABS_LE_F32: "VABS.LE.F32",
- arm_VABS_F32: "VABS.F32",
- arm_VABS_ZZ_F32: "VABS.ZZ.F32",
- arm_VABS_EQ_F64: "VABS.EQ.F64",
- arm_VABS_NE_F64: "VABS.NE.F64",
- arm_VABS_CS_F64: "VABS.CS.F64",
- arm_VABS_CC_F64: "VABS.CC.F64",
- arm_VABS_MI_F64: "VABS.MI.F64",
- arm_VABS_PL_F64: "VABS.PL.F64",
- arm_VABS_VS_F64: "VABS.VS.F64",
- arm_VABS_VC_F64: "VABS.VC.F64",
- arm_VABS_HI_F64: "VABS.HI.F64",
- arm_VABS_LS_F64: "VABS.LS.F64",
- arm_VABS_GE_F64: "VABS.GE.F64",
- arm_VABS_LT_F64: "VABS.LT.F64",
- arm_VABS_GT_F64: "VABS.GT.F64",
- arm_VABS_LE_F64: "VABS.LE.F64",
- arm_VABS_F64: "VABS.F64",
- arm_VABS_ZZ_F64: "VABS.ZZ.F64",
- arm_VADD_EQ_F32: "VADD.EQ.F32",
- arm_VADD_NE_F32: "VADD.NE.F32",
- arm_VADD_CS_F32: "VADD.CS.F32",
- arm_VADD_CC_F32: "VADD.CC.F32",
- arm_VADD_MI_F32: "VADD.MI.F32",
- arm_VADD_PL_F32: "VADD.PL.F32",
- arm_VADD_VS_F32: "VADD.VS.F32",
- arm_VADD_VC_F32: "VADD.VC.F32",
- arm_VADD_HI_F32: "VADD.HI.F32",
- arm_VADD_LS_F32: "VADD.LS.F32",
- arm_VADD_GE_F32: "VADD.GE.F32",
- arm_VADD_LT_F32: "VADD.LT.F32",
- arm_VADD_GT_F32: "VADD.GT.F32",
- arm_VADD_LE_F32: "VADD.LE.F32",
- arm_VADD_F32: "VADD.F32",
- arm_VADD_ZZ_F32: "VADD.ZZ.F32",
- arm_VADD_EQ_F64: "VADD.EQ.F64",
- arm_VADD_NE_F64: "VADD.NE.F64",
- arm_VADD_CS_F64: "VADD.CS.F64",
- arm_VADD_CC_F64: "VADD.CC.F64",
- arm_VADD_MI_F64: "VADD.MI.F64",
- arm_VADD_PL_F64: "VADD.PL.F64",
- arm_VADD_VS_F64: "VADD.VS.F64",
- arm_VADD_VC_F64: "VADD.VC.F64",
- arm_VADD_HI_F64: "VADD.HI.F64",
- arm_VADD_LS_F64: "VADD.LS.F64",
- arm_VADD_GE_F64: "VADD.GE.F64",
- arm_VADD_LT_F64: "VADD.LT.F64",
- arm_VADD_GT_F64: "VADD.GT.F64",
- arm_VADD_LE_F64: "VADD.LE.F64",
- arm_VADD_F64: "VADD.F64",
- arm_VADD_ZZ_F64: "VADD.ZZ.F64",
- arm_VCMP_EQ_F32: "VCMP.EQ.F32",
- arm_VCMP_NE_F32: "VCMP.NE.F32",
- arm_VCMP_CS_F32: "VCMP.CS.F32",
- arm_VCMP_CC_F32: "VCMP.CC.F32",
- arm_VCMP_MI_F32: "VCMP.MI.F32",
- arm_VCMP_PL_F32: "VCMP.PL.F32",
- arm_VCMP_VS_F32: "VCMP.VS.F32",
- arm_VCMP_VC_F32: "VCMP.VC.F32",
- arm_VCMP_HI_F32: "VCMP.HI.F32",
- arm_VCMP_LS_F32: "VCMP.LS.F32",
- arm_VCMP_GE_F32: "VCMP.GE.F32",
- arm_VCMP_LT_F32: "VCMP.LT.F32",
- arm_VCMP_GT_F32: "VCMP.GT.F32",
- arm_VCMP_LE_F32: "VCMP.LE.F32",
- arm_VCMP_F32: "VCMP.F32",
- arm_VCMP_ZZ_F32: "VCMP.ZZ.F32",
- arm_VCMP_EQ_F64: "VCMP.EQ.F64",
- arm_VCMP_NE_F64: "VCMP.NE.F64",
- arm_VCMP_CS_F64: "VCMP.CS.F64",
- arm_VCMP_CC_F64: "VCMP.CC.F64",
- arm_VCMP_MI_F64: "VCMP.MI.F64",
- arm_VCMP_PL_F64: "VCMP.PL.F64",
- arm_VCMP_VS_F64: "VCMP.VS.F64",
- arm_VCMP_VC_F64: "VCMP.VC.F64",
- arm_VCMP_HI_F64: "VCMP.HI.F64",
- arm_VCMP_LS_F64: "VCMP.LS.F64",
- arm_VCMP_GE_F64: "VCMP.GE.F64",
- arm_VCMP_LT_F64: "VCMP.LT.F64",
- arm_VCMP_GT_F64: "VCMP.GT.F64",
- arm_VCMP_LE_F64: "VCMP.LE.F64",
- arm_VCMP_F64: "VCMP.F64",
- arm_VCMP_ZZ_F64: "VCMP.ZZ.F64",
- arm_VCMP_E_EQ_F32: "VCMP.E.EQ.F32",
- arm_VCMP_E_NE_F32: "VCMP.E.NE.F32",
- arm_VCMP_E_CS_F32: "VCMP.E.CS.F32",
- arm_VCMP_E_CC_F32: "VCMP.E.CC.F32",
- arm_VCMP_E_MI_F32: "VCMP.E.MI.F32",
- arm_VCMP_E_PL_F32: "VCMP.E.PL.F32",
- arm_VCMP_E_VS_F32: "VCMP.E.VS.F32",
- arm_VCMP_E_VC_F32: "VCMP.E.VC.F32",
- arm_VCMP_E_HI_F32: "VCMP.E.HI.F32",
- arm_VCMP_E_LS_F32: "VCMP.E.LS.F32",
- arm_VCMP_E_GE_F32: "VCMP.E.GE.F32",
- arm_VCMP_E_LT_F32: "VCMP.E.LT.F32",
- arm_VCMP_E_GT_F32: "VCMP.E.GT.F32",
- arm_VCMP_E_LE_F32: "VCMP.E.LE.F32",
- arm_VCMP_E_F32: "VCMP.E.F32",
- arm_VCMP_E_ZZ_F32: "VCMP.E.ZZ.F32",
- arm_VCMP_E_EQ_F64: "VCMP.E.EQ.F64",
- arm_VCMP_E_NE_F64: "VCMP.E.NE.F64",
- arm_VCMP_E_CS_F64: "VCMP.E.CS.F64",
- arm_VCMP_E_CC_F64: "VCMP.E.CC.F64",
- arm_VCMP_E_MI_F64: "VCMP.E.MI.F64",
- arm_VCMP_E_PL_F64: "VCMP.E.PL.F64",
- arm_VCMP_E_VS_F64: "VCMP.E.VS.F64",
- arm_VCMP_E_VC_F64: "VCMP.E.VC.F64",
- arm_VCMP_E_HI_F64: "VCMP.E.HI.F64",
- arm_VCMP_E_LS_F64: "VCMP.E.LS.F64",
- arm_VCMP_E_GE_F64: "VCMP.E.GE.F64",
- arm_VCMP_E_LT_F64: "VCMP.E.LT.F64",
- arm_VCMP_E_GT_F64: "VCMP.E.GT.F64",
- arm_VCMP_E_LE_F64: "VCMP.E.LE.F64",
- arm_VCMP_E_F64: "VCMP.E.F64",
- arm_VCMP_E_ZZ_F64: "VCMP.E.ZZ.F64",
- arm_VCVT_EQ_F32_FXS16: "VCVT.EQ.F32.FXS16",
- arm_VCVT_NE_F32_FXS16: "VCVT.NE.F32.FXS16",
- arm_VCVT_CS_F32_FXS16: "VCVT.CS.F32.FXS16",
- arm_VCVT_CC_F32_FXS16: "VCVT.CC.F32.FXS16",
- arm_VCVT_MI_F32_FXS16: "VCVT.MI.F32.FXS16",
- arm_VCVT_PL_F32_FXS16: "VCVT.PL.F32.FXS16",
- arm_VCVT_VS_F32_FXS16: "VCVT.VS.F32.FXS16",
- arm_VCVT_VC_F32_FXS16: "VCVT.VC.F32.FXS16",
- arm_VCVT_HI_F32_FXS16: "VCVT.HI.F32.FXS16",
- arm_VCVT_LS_F32_FXS16: "VCVT.LS.F32.FXS16",
- arm_VCVT_GE_F32_FXS16: "VCVT.GE.F32.FXS16",
- arm_VCVT_LT_F32_FXS16: "VCVT.LT.F32.FXS16",
- arm_VCVT_GT_F32_FXS16: "VCVT.GT.F32.FXS16",
- arm_VCVT_LE_F32_FXS16: "VCVT.LE.F32.FXS16",
- arm_VCVT_F32_FXS16: "VCVT.F32.FXS16",
- arm_VCVT_ZZ_F32_FXS16: "VCVT.ZZ.F32.FXS16",
- arm_VCVT_EQ_F32_FXS32: "VCVT.EQ.F32.FXS32",
- arm_VCVT_NE_F32_FXS32: "VCVT.NE.F32.FXS32",
- arm_VCVT_CS_F32_FXS32: "VCVT.CS.F32.FXS32",
- arm_VCVT_CC_F32_FXS32: "VCVT.CC.F32.FXS32",
- arm_VCVT_MI_F32_FXS32: "VCVT.MI.F32.FXS32",
- arm_VCVT_PL_F32_FXS32: "VCVT.PL.F32.FXS32",
- arm_VCVT_VS_F32_FXS32: "VCVT.VS.F32.FXS32",
- arm_VCVT_VC_F32_FXS32: "VCVT.VC.F32.FXS32",
- arm_VCVT_HI_F32_FXS32: "VCVT.HI.F32.FXS32",
- arm_VCVT_LS_F32_FXS32: "VCVT.LS.F32.FXS32",
- arm_VCVT_GE_F32_FXS32: "VCVT.GE.F32.FXS32",
- arm_VCVT_LT_F32_FXS32: "VCVT.LT.F32.FXS32",
- arm_VCVT_GT_F32_FXS32: "VCVT.GT.F32.FXS32",
- arm_VCVT_LE_F32_FXS32: "VCVT.LE.F32.FXS32",
- arm_VCVT_F32_FXS32: "VCVT.F32.FXS32",
- arm_VCVT_ZZ_F32_FXS32: "VCVT.ZZ.F32.FXS32",
- arm_VCVT_EQ_F32_FXU16: "VCVT.EQ.F32.FXU16",
- arm_VCVT_NE_F32_FXU16: "VCVT.NE.F32.FXU16",
- arm_VCVT_CS_F32_FXU16: "VCVT.CS.F32.FXU16",
- arm_VCVT_CC_F32_FXU16: "VCVT.CC.F32.FXU16",
- arm_VCVT_MI_F32_FXU16: "VCVT.MI.F32.FXU16",
- arm_VCVT_PL_F32_FXU16: "VCVT.PL.F32.FXU16",
- arm_VCVT_VS_F32_FXU16: "VCVT.VS.F32.FXU16",
- arm_VCVT_VC_F32_FXU16: "VCVT.VC.F32.FXU16",
- arm_VCVT_HI_F32_FXU16: "VCVT.HI.F32.FXU16",
- arm_VCVT_LS_F32_FXU16: "VCVT.LS.F32.FXU16",
- arm_VCVT_GE_F32_FXU16: "VCVT.GE.F32.FXU16",
- arm_VCVT_LT_F32_FXU16: "VCVT.LT.F32.FXU16",
- arm_VCVT_GT_F32_FXU16: "VCVT.GT.F32.FXU16",
- arm_VCVT_LE_F32_FXU16: "VCVT.LE.F32.FXU16",
- arm_VCVT_F32_FXU16: "VCVT.F32.FXU16",
- arm_VCVT_ZZ_F32_FXU16: "VCVT.ZZ.F32.FXU16",
- arm_VCVT_EQ_F32_FXU32: "VCVT.EQ.F32.FXU32",
- arm_VCVT_NE_F32_FXU32: "VCVT.NE.F32.FXU32",
- arm_VCVT_CS_F32_FXU32: "VCVT.CS.F32.FXU32",
- arm_VCVT_CC_F32_FXU32: "VCVT.CC.F32.FXU32",
- arm_VCVT_MI_F32_FXU32: "VCVT.MI.F32.FXU32",
- arm_VCVT_PL_F32_FXU32: "VCVT.PL.F32.FXU32",
- arm_VCVT_VS_F32_FXU32: "VCVT.VS.F32.FXU32",
- arm_VCVT_VC_F32_FXU32: "VCVT.VC.F32.FXU32",
- arm_VCVT_HI_F32_FXU32: "VCVT.HI.F32.FXU32",
- arm_VCVT_LS_F32_FXU32: "VCVT.LS.F32.FXU32",
- arm_VCVT_GE_F32_FXU32: "VCVT.GE.F32.FXU32",
- arm_VCVT_LT_F32_FXU32: "VCVT.LT.F32.FXU32",
- arm_VCVT_GT_F32_FXU32: "VCVT.GT.F32.FXU32",
- arm_VCVT_LE_F32_FXU32: "VCVT.LE.F32.FXU32",
- arm_VCVT_F32_FXU32: "VCVT.F32.FXU32",
- arm_VCVT_ZZ_F32_FXU32: "VCVT.ZZ.F32.FXU32",
- arm_VCVT_EQ_F64_FXS16: "VCVT.EQ.F64.FXS16",
- arm_VCVT_NE_F64_FXS16: "VCVT.NE.F64.FXS16",
- arm_VCVT_CS_F64_FXS16: "VCVT.CS.F64.FXS16",
- arm_VCVT_CC_F64_FXS16: "VCVT.CC.F64.FXS16",
- arm_VCVT_MI_F64_FXS16: "VCVT.MI.F64.FXS16",
- arm_VCVT_PL_F64_FXS16: "VCVT.PL.F64.FXS16",
- arm_VCVT_VS_F64_FXS16: "VCVT.VS.F64.FXS16",
- arm_VCVT_VC_F64_FXS16: "VCVT.VC.F64.FXS16",
- arm_VCVT_HI_F64_FXS16: "VCVT.HI.F64.FXS16",
- arm_VCVT_LS_F64_FXS16: "VCVT.LS.F64.FXS16",
- arm_VCVT_GE_F64_FXS16: "VCVT.GE.F64.FXS16",
- arm_VCVT_LT_F64_FXS16: "VCVT.LT.F64.FXS16",
- arm_VCVT_GT_F64_FXS16: "VCVT.GT.F64.FXS16",
- arm_VCVT_LE_F64_FXS16: "VCVT.LE.F64.FXS16",
- arm_VCVT_F64_FXS16: "VCVT.F64.FXS16",
- arm_VCVT_ZZ_F64_FXS16: "VCVT.ZZ.F64.FXS16",
- arm_VCVT_EQ_F64_FXS32: "VCVT.EQ.F64.FXS32",
- arm_VCVT_NE_F64_FXS32: "VCVT.NE.F64.FXS32",
- arm_VCVT_CS_F64_FXS32: "VCVT.CS.F64.FXS32",
- arm_VCVT_CC_F64_FXS32: "VCVT.CC.F64.FXS32",
- arm_VCVT_MI_F64_FXS32: "VCVT.MI.F64.FXS32",
- arm_VCVT_PL_F64_FXS32: "VCVT.PL.F64.FXS32",
- arm_VCVT_VS_F64_FXS32: "VCVT.VS.F64.FXS32",
- arm_VCVT_VC_F64_FXS32: "VCVT.VC.F64.FXS32",
- arm_VCVT_HI_F64_FXS32: "VCVT.HI.F64.FXS32",
- arm_VCVT_LS_F64_FXS32: "VCVT.LS.F64.FXS32",
- arm_VCVT_GE_F64_FXS32: "VCVT.GE.F64.FXS32",
- arm_VCVT_LT_F64_FXS32: "VCVT.LT.F64.FXS32",
- arm_VCVT_GT_F64_FXS32: "VCVT.GT.F64.FXS32",
- arm_VCVT_LE_F64_FXS32: "VCVT.LE.F64.FXS32",
- arm_VCVT_F64_FXS32: "VCVT.F64.FXS32",
- arm_VCVT_ZZ_F64_FXS32: "VCVT.ZZ.F64.FXS32",
- arm_VCVT_EQ_F64_FXU16: "VCVT.EQ.F64.FXU16",
- arm_VCVT_NE_F64_FXU16: "VCVT.NE.F64.FXU16",
- arm_VCVT_CS_F64_FXU16: "VCVT.CS.F64.FXU16",
- arm_VCVT_CC_F64_FXU16: "VCVT.CC.F64.FXU16",
- arm_VCVT_MI_F64_FXU16: "VCVT.MI.F64.FXU16",
- arm_VCVT_PL_F64_FXU16: "VCVT.PL.F64.FXU16",
- arm_VCVT_VS_F64_FXU16: "VCVT.VS.F64.FXU16",
- arm_VCVT_VC_F64_FXU16: "VCVT.VC.F64.FXU16",
- arm_VCVT_HI_F64_FXU16: "VCVT.HI.F64.FXU16",
- arm_VCVT_LS_F64_FXU16: "VCVT.LS.F64.FXU16",
- arm_VCVT_GE_F64_FXU16: "VCVT.GE.F64.FXU16",
- arm_VCVT_LT_F64_FXU16: "VCVT.LT.F64.FXU16",
- arm_VCVT_GT_F64_FXU16: "VCVT.GT.F64.FXU16",
- arm_VCVT_LE_F64_FXU16: "VCVT.LE.F64.FXU16",
- arm_VCVT_F64_FXU16: "VCVT.F64.FXU16",
- arm_VCVT_ZZ_F64_FXU16: "VCVT.ZZ.F64.FXU16",
- arm_VCVT_EQ_F64_FXU32: "VCVT.EQ.F64.FXU32",
- arm_VCVT_NE_F64_FXU32: "VCVT.NE.F64.FXU32",
- arm_VCVT_CS_F64_FXU32: "VCVT.CS.F64.FXU32",
- arm_VCVT_CC_F64_FXU32: "VCVT.CC.F64.FXU32",
- arm_VCVT_MI_F64_FXU32: "VCVT.MI.F64.FXU32",
- arm_VCVT_PL_F64_FXU32: "VCVT.PL.F64.FXU32",
- arm_VCVT_VS_F64_FXU32: "VCVT.VS.F64.FXU32",
- arm_VCVT_VC_F64_FXU32: "VCVT.VC.F64.FXU32",
- arm_VCVT_HI_F64_FXU32: "VCVT.HI.F64.FXU32",
- arm_VCVT_LS_F64_FXU32: "VCVT.LS.F64.FXU32",
- arm_VCVT_GE_F64_FXU32: "VCVT.GE.F64.FXU32",
- arm_VCVT_LT_F64_FXU32: "VCVT.LT.F64.FXU32",
- arm_VCVT_GT_F64_FXU32: "VCVT.GT.F64.FXU32",
- arm_VCVT_LE_F64_FXU32: "VCVT.LE.F64.FXU32",
- arm_VCVT_F64_FXU32: "VCVT.F64.FXU32",
- arm_VCVT_ZZ_F64_FXU32: "VCVT.ZZ.F64.FXU32",
- arm_VCVT_EQ_F32_U32: "VCVT.EQ.F32.U32",
- arm_VCVT_NE_F32_U32: "VCVT.NE.F32.U32",
- arm_VCVT_CS_F32_U32: "VCVT.CS.F32.U32",
- arm_VCVT_CC_F32_U32: "VCVT.CC.F32.U32",
- arm_VCVT_MI_F32_U32: "VCVT.MI.F32.U32",
- arm_VCVT_PL_F32_U32: "VCVT.PL.F32.U32",
- arm_VCVT_VS_F32_U32: "VCVT.VS.F32.U32",
- arm_VCVT_VC_F32_U32: "VCVT.VC.F32.U32",
- arm_VCVT_HI_F32_U32: "VCVT.HI.F32.U32",
- arm_VCVT_LS_F32_U32: "VCVT.LS.F32.U32",
- arm_VCVT_GE_F32_U32: "VCVT.GE.F32.U32",
- arm_VCVT_LT_F32_U32: "VCVT.LT.F32.U32",
- arm_VCVT_GT_F32_U32: "VCVT.GT.F32.U32",
- arm_VCVT_LE_F32_U32: "VCVT.LE.F32.U32",
- arm_VCVT_F32_U32: "VCVT.F32.U32",
- arm_VCVT_ZZ_F32_U32: "VCVT.ZZ.F32.U32",
- arm_VCVT_EQ_F32_S32: "VCVT.EQ.F32.S32",
- arm_VCVT_NE_F32_S32: "VCVT.NE.F32.S32",
- arm_VCVT_CS_F32_S32: "VCVT.CS.F32.S32",
- arm_VCVT_CC_F32_S32: "VCVT.CC.F32.S32",
- arm_VCVT_MI_F32_S32: "VCVT.MI.F32.S32",
- arm_VCVT_PL_F32_S32: "VCVT.PL.F32.S32",
- arm_VCVT_VS_F32_S32: "VCVT.VS.F32.S32",
- arm_VCVT_VC_F32_S32: "VCVT.VC.F32.S32",
- arm_VCVT_HI_F32_S32: "VCVT.HI.F32.S32",
- arm_VCVT_LS_F32_S32: "VCVT.LS.F32.S32",
- arm_VCVT_GE_F32_S32: "VCVT.GE.F32.S32",
- arm_VCVT_LT_F32_S32: "VCVT.LT.F32.S32",
- arm_VCVT_GT_F32_S32: "VCVT.GT.F32.S32",
- arm_VCVT_LE_F32_S32: "VCVT.LE.F32.S32",
- arm_VCVT_F32_S32: "VCVT.F32.S32",
- arm_VCVT_ZZ_F32_S32: "VCVT.ZZ.F32.S32",
- arm_VCVT_EQ_F64_U32: "VCVT.EQ.F64.U32",
- arm_VCVT_NE_F64_U32: "VCVT.NE.F64.U32",
- arm_VCVT_CS_F64_U32: "VCVT.CS.F64.U32",
- arm_VCVT_CC_F64_U32: "VCVT.CC.F64.U32",
- arm_VCVT_MI_F64_U32: "VCVT.MI.F64.U32",
- arm_VCVT_PL_F64_U32: "VCVT.PL.F64.U32",
- arm_VCVT_VS_F64_U32: "VCVT.VS.F64.U32",
- arm_VCVT_VC_F64_U32: "VCVT.VC.F64.U32",
- arm_VCVT_HI_F64_U32: "VCVT.HI.F64.U32",
- arm_VCVT_LS_F64_U32: "VCVT.LS.F64.U32",
- arm_VCVT_GE_F64_U32: "VCVT.GE.F64.U32",
- arm_VCVT_LT_F64_U32: "VCVT.LT.F64.U32",
- arm_VCVT_GT_F64_U32: "VCVT.GT.F64.U32",
- arm_VCVT_LE_F64_U32: "VCVT.LE.F64.U32",
- arm_VCVT_F64_U32: "VCVT.F64.U32",
- arm_VCVT_ZZ_F64_U32: "VCVT.ZZ.F64.U32",
- arm_VCVT_EQ_F64_S32: "VCVT.EQ.F64.S32",
- arm_VCVT_NE_F64_S32: "VCVT.NE.F64.S32",
- arm_VCVT_CS_F64_S32: "VCVT.CS.F64.S32",
- arm_VCVT_CC_F64_S32: "VCVT.CC.F64.S32",
- arm_VCVT_MI_F64_S32: "VCVT.MI.F64.S32",
- arm_VCVT_PL_F64_S32: "VCVT.PL.F64.S32",
- arm_VCVT_VS_F64_S32: "VCVT.VS.F64.S32",
- arm_VCVT_VC_F64_S32: "VCVT.VC.F64.S32",
- arm_VCVT_HI_F64_S32: "VCVT.HI.F64.S32",
- arm_VCVT_LS_F64_S32: "VCVT.LS.F64.S32",
- arm_VCVT_GE_F64_S32: "VCVT.GE.F64.S32",
- arm_VCVT_LT_F64_S32: "VCVT.LT.F64.S32",
- arm_VCVT_GT_F64_S32: "VCVT.GT.F64.S32",
- arm_VCVT_LE_F64_S32: "VCVT.LE.F64.S32",
- arm_VCVT_F64_S32: "VCVT.F64.S32",
- arm_VCVT_ZZ_F64_S32: "VCVT.ZZ.F64.S32",
- arm_VCVT_EQ_F64_F32: "VCVT.EQ.F64.F32",
- arm_VCVT_NE_F64_F32: "VCVT.NE.F64.F32",
- arm_VCVT_CS_F64_F32: "VCVT.CS.F64.F32",
- arm_VCVT_CC_F64_F32: "VCVT.CC.F64.F32",
- arm_VCVT_MI_F64_F32: "VCVT.MI.F64.F32",
- arm_VCVT_PL_F64_F32: "VCVT.PL.F64.F32",
- arm_VCVT_VS_F64_F32: "VCVT.VS.F64.F32",
- arm_VCVT_VC_F64_F32: "VCVT.VC.F64.F32",
- arm_VCVT_HI_F64_F32: "VCVT.HI.F64.F32",
- arm_VCVT_LS_F64_F32: "VCVT.LS.F64.F32",
- arm_VCVT_GE_F64_F32: "VCVT.GE.F64.F32",
- arm_VCVT_LT_F64_F32: "VCVT.LT.F64.F32",
- arm_VCVT_GT_F64_F32: "VCVT.GT.F64.F32",
- arm_VCVT_LE_F64_F32: "VCVT.LE.F64.F32",
- arm_VCVT_F64_F32: "VCVT.F64.F32",
- arm_VCVT_ZZ_F64_F32: "VCVT.ZZ.F64.F32",
- arm_VCVT_EQ_F32_F64: "VCVT.EQ.F32.F64",
- arm_VCVT_NE_F32_F64: "VCVT.NE.F32.F64",
- arm_VCVT_CS_F32_F64: "VCVT.CS.F32.F64",
- arm_VCVT_CC_F32_F64: "VCVT.CC.F32.F64",
- arm_VCVT_MI_F32_F64: "VCVT.MI.F32.F64",
- arm_VCVT_PL_F32_F64: "VCVT.PL.F32.F64",
- arm_VCVT_VS_F32_F64: "VCVT.VS.F32.F64",
- arm_VCVT_VC_F32_F64: "VCVT.VC.F32.F64",
- arm_VCVT_HI_F32_F64: "VCVT.HI.F32.F64",
- arm_VCVT_LS_F32_F64: "VCVT.LS.F32.F64",
- arm_VCVT_GE_F32_F64: "VCVT.GE.F32.F64",
- arm_VCVT_LT_F32_F64: "VCVT.LT.F32.F64",
- arm_VCVT_GT_F32_F64: "VCVT.GT.F32.F64",
- arm_VCVT_LE_F32_F64: "VCVT.LE.F32.F64",
- arm_VCVT_F32_F64: "VCVT.F32.F64",
- arm_VCVT_ZZ_F32_F64: "VCVT.ZZ.F32.F64",
- arm_VCVT_EQ_FXS16_F32: "VCVT.EQ.FXS16.F32",
- arm_VCVT_NE_FXS16_F32: "VCVT.NE.FXS16.F32",
- arm_VCVT_CS_FXS16_F32: "VCVT.CS.FXS16.F32",
- arm_VCVT_CC_FXS16_F32: "VCVT.CC.FXS16.F32",
- arm_VCVT_MI_FXS16_F32: "VCVT.MI.FXS16.F32",
- arm_VCVT_PL_FXS16_F32: "VCVT.PL.FXS16.F32",
- arm_VCVT_VS_FXS16_F32: "VCVT.VS.FXS16.F32",
- arm_VCVT_VC_FXS16_F32: "VCVT.VC.FXS16.F32",
- arm_VCVT_HI_FXS16_F32: "VCVT.HI.FXS16.F32",
- arm_VCVT_LS_FXS16_F32: "VCVT.LS.FXS16.F32",
- arm_VCVT_GE_FXS16_F32: "VCVT.GE.FXS16.F32",
- arm_VCVT_LT_FXS16_F32: "VCVT.LT.FXS16.F32",
- arm_VCVT_GT_FXS16_F32: "VCVT.GT.FXS16.F32",
- arm_VCVT_LE_FXS16_F32: "VCVT.LE.FXS16.F32",
- arm_VCVT_FXS16_F32: "VCVT.FXS16.F32",
- arm_VCVT_ZZ_FXS16_F32: "VCVT.ZZ.FXS16.F32",
- arm_VCVT_EQ_FXS16_F64: "VCVT.EQ.FXS16.F64",
- arm_VCVT_NE_FXS16_F64: "VCVT.NE.FXS16.F64",
- arm_VCVT_CS_FXS16_F64: "VCVT.CS.FXS16.F64",
- arm_VCVT_CC_FXS16_F64: "VCVT.CC.FXS16.F64",
- arm_VCVT_MI_FXS16_F64: "VCVT.MI.FXS16.F64",
- arm_VCVT_PL_FXS16_F64: "VCVT.PL.FXS16.F64",
- arm_VCVT_VS_FXS16_F64: "VCVT.VS.FXS16.F64",
- arm_VCVT_VC_FXS16_F64: "VCVT.VC.FXS16.F64",
- arm_VCVT_HI_FXS16_F64: "VCVT.HI.FXS16.F64",
- arm_VCVT_LS_FXS16_F64: "VCVT.LS.FXS16.F64",
- arm_VCVT_GE_FXS16_F64: "VCVT.GE.FXS16.F64",
- arm_VCVT_LT_FXS16_F64: "VCVT.LT.FXS16.F64",
- arm_VCVT_GT_FXS16_F64: "VCVT.GT.FXS16.F64",
- arm_VCVT_LE_FXS16_F64: "VCVT.LE.FXS16.F64",
- arm_VCVT_FXS16_F64: "VCVT.FXS16.F64",
- arm_VCVT_ZZ_FXS16_F64: "VCVT.ZZ.FXS16.F64",
- arm_VCVT_EQ_FXS32_F32: "VCVT.EQ.FXS32.F32",
- arm_VCVT_NE_FXS32_F32: "VCVT.NE.FXS32.F32",
- arm_VCVT_CS_FXS32_F32: "VCVT.CS.FXS32.F32",
- arm_VCVT_CC_FXS32_F32: "VCVT.CC.FXS32.F32",
- arm_VCVT_MI_FXS32_F32: "VCVT.MI.FXS32.F32",
- arm_VCVT_PL_FXS32_F32: "VCVT.PL.FXS32.F32",
- arm_VCVT_VS_FXS32_F32: "VCVT.VS.FXS32.F32",
- arm_VCVT_VC_FXS32_F32: "VCVT.VC.FXS32.F32",
- arm_VCVT_HI_FXS32_F32: "VCVT.HI.FXS32.F32",
- arm_VCVT_LS_FXS32_F32: "VCVT.LS.FXS32.F32",
- arm_VCVT_GE_FXS32_F32: "VCVT.GE.FXS32.F32",
- arm_VCVT_LT_FXS32_F32: "VCVT.LT.FXS32.F32",
- arm_VCVT_GT_FXS32_F32: "VCVT.GT.FXS32.F32",
- arm_VCVT_LE_FXS32_F32: "VCVT.LE.FXS32.F32",
- arm_VCVT_FXS32_F32: "VCVT.FXS32.F32",
- arm_VCVT_ZZ_FXS32_F32: "VCVT.ZZ.FXS32.F32",
- arm_VCVT_EQ_FXS32_F64: "VCVT.EQ.FXS32.F64",
- arm_VCVT_NE_FXS32_F64: "VCVT.NE.FXS32.F64",
- arm_VCVT_CS_FXS32_F64: "VCVT.CS.FXS32.F64",
- arm_VCVT_CC_FXS32_F64: "VCVT.CC.FXS32.F64",
- arm_VCVT_MI_FXS32_F64: "VCVT.MI.FXS32.F64",
- arm_VCVT_PL_FXS32_F64: "VCVT.PL.FXS32.F64",
- arm_VCVT_VS_FXS32_F64: "VCVT.VS.FXS32.F64",
- arm_VCVT_VC_FXS32_F64: "VCVT.VC.FXS32.F64",
- arm_VCVT_HI_FXS32_F64: "VCVT.HI.FXS32.F64",
- arm_VCVT_LS_FXS32_F64: "VCVT.LS.FXS32.F64",
- arm_VCVT_GE_FXS32_F64: "VCVT.GE.FXS32.F64",
- arm_VCVT_LT_FXS32_F64: "VCVT.LT.FXS32.F64",
- arm_VCVT_GT_FXS32_F64: "VCVT.GT.FXS32.F64",
- arm_VCVT_LE_FXS32_F64: "VCVT.LE.FXS32.F64",
- arm_VCVT_FXS32_F64: "VCVT.FXS32.F64",
- arm_VCVT_ZZ_FXS32_F64: "VCVT.ZZ.FXS32.F64",
- arm_VCVT_EQ_FXU16_F32: "VCVT.EQ.FXU16.F32",
- arm_VCVT_NE_FXU16_F32: "VCVT.NE.FXU16.F32",
- arm_VCVT_CS_FXU16_F32: "VCVT.CS.FXU16.F32",
- arm_VCVT_CC_FXU16_F32: "VCVT.CC.FXU16.F32",
- arm_VCVT_MI_FXU16_F32: "VCVT.MI.FXU16.F32",
- arm_VCVT_PL_FXU16_F32: "VCVT.PL.FXU16.F32",
- arm_VCVT_VS_FXU16_F32: "VCVT.VS.FXU16.F32",
- arm_VCVT_VC_FXU16_F32: "VCVT.VC.FXU16.F32",
- arm_VCVT_HI_FXU16_F32: "VCVT.HI.FXU16.F32",
- arm_VCVT_LS_FXU16_F32: "VCVT.LS.FXU16.F32",
- arm_VCVT_GE_FXU16_F32: "VCVT.GE.FXU16.F32",
- arm_VCVT_LT_FXU16_F32: "VCVT.LT.FXU16.F32",
- arm_VCVT_GT_FXU16_F32: "VCVT.GT.FXU16.F32",
- arm_VCVT_LE_FXU16_F32: "VCVT.LE.FXU16.F32",
- arm_VCVT_FXU16_F32: "VCVT.FXU16.F32",
- arm_VCVT_ZZ_FXU16_F32: "VCVT.ZZ.FXU16.F32",
- arm_VCVT_EQ_FXU16_F64: "VCVT.EQ.FXU16.F64",
- arm_VCVT_NE_FXU16_F64: "VCVT.NE.FXU16.F64",
- arm_VCVT_CS_FXU16_F64: "VCVT.CS.FXU16.F64",
- arm_VCVT_CC_FXU16_F64: "VCVT.CC.FXU16.F64",
- arm_VCVT_MI_FXU16_F64: "VCVT.MI.FXU16.F64",
- arm_VCVT_PL_FXU16_F64: "VCVT.PL.FXU16.F64",
- arm_VCVT_VS_FXU16_F64: "VCVT.VS.FXU16.F64",
- arm_VCVT_VC_FXU16_F64: "VCVT.VC.FXU16.F64",
- arm_VCVT_HI_FXU16_F64: "VCVT.HI.FXU16.F64",
- arm_VCVT_LS_FXU16_F64: "VCVT.LS.FXU16.F64",
- arm_VCVT_GE_FXU16_F64: "VCVT.GE.FXU16.F64",
- arm_VCVT_LT_FXU16_F64: "VCVT.LT.FXU16.F64",
- arm_VCVT_GT_FXU16_F64: "VCVT.GT.FXU16.F64",
- arm_VCVT_LE_FXU16_F64: "VCVT.LE.FXU16.F64",
- arm_VCVT_FXU16_F64: "VCVT.FXU16.F64",
- arm_VCVT_ZZ_FXU16_F64: "VCVT.ZZ.FXU16.F64",
- arm_VCVT_EQ_FXU32_F32: "VCVT.EQ.FXU32.F32",
- arm_VCVT_NE_FXU32_F32: "VCVT.NE.FXU32.F32",
- arm_VCVT_CS_FXU32_F32: "VCVT.CS.FXU32.F32",
- arm_VCVT_CC_FXU32_F32: "VCVT.CC.FXU32.F32",
- arm_VCVT_MI_FXU32_F32: "VCVT.MI.FXU32.F32",
- arm_VCVT_PL_FXU32_F32: "VCVT.PL.FXU32.F32",
- arm_VCVT_VS_FXU32_F32: "VCVT.VS.FXU32.F32",
- arm_VCVT_VC_FXU32_F32: "VCVT.VC.FXU32.F32",
- arm_VCVT_HI_FXU32_F32: "VCVT.HI.FXU32.F32",
- arm_VCVT_LS_FXU32_F32: "VCVT.LS.FXU32.F32",
- arm_VCVT_GE_FXU32_F32: "VCVT.GE.FXU32.F32",
- arm_VCVT_LT_FXU32_F32: "VCVT.LT.FXU32.F32",
- arm_VCVT_GT_FXU32_F32: "VCVT.GT.FXU32.F32",
- arm_VCVT_LE_FXU32_F32: "VCVT.LE.FXU32.F32",
- arm_VCVT_FXU32_F32: "VCVT.FXU32.F32",
- arm_VCVT_ZZ_FXU32_F32: "VCVT.ZZ.FXU32.F32",
- arm_VCVT_EQ_FXU32_F64: "VCVT.EQ.FXU32.F64",
- arm_VCVT_NE_FXU32_F64: "VCVT.NE.FXU32.F64",
- arm_VCVT_CS_FXU32_F64: "VCVT.CS.FXU32.F64",
- arm_VCVT_CC_FXU32_F64: "VCVT.CC.FXU32.F64",
- arm_VCVT_MI_FXU32_F64: "VCVT.MI.FXU32.F64",
- arm_VCVT_PL_FXU32_F64: "VCVT.PL.FXU32.F64",
- arm_VCVT_VS_FXU32_F64: "VCVT.VS.FXU32.F64",
- arm_VCVT_VC_FXU32_F64: "VCVT.VC.FXU32.F64",
- arm_VCVT_HI_FXU32_F64: "VCVT.HI.FXU32.F64",
- arm_VCVT_LS_FXU32_F64: "VCVT.LS.FXU32.F64",
- arm_VCVT_GE_FXU32_F64: "VCVT.GE.FXU32.F64",
- arm_VCVT_LT_FXU32_F64: "VCVT.LT.FXU32.F64",
- arm_VCVT_GT_FXU32_F64: "VCVT.GT.FXU32.F64",
- arm_VCVT_LE_FXU32_F64: "VCVT.LE.FXU32.F64",
- arm_VCVT_FXU32_F64: "VCVT.FXU32.F64",
- arm_VCVT_ZZ_FXU32_F64: "VCVT.ZZ.FXU32.F64",
- arm_VCVTB_EQ_F32_F16: "VCVTB.EQ.F32.F16",
- arm_VCVTB_NE_F32_F16: "VCVTB.NE.F32.F16",
- arm_VCVTB_CS_F32_F16: "VCVTB.CS.F32.F16",
- arm_VCVTB_CC_F32_F16: "VCVTB.CC.F32.F16",
- arm_VCVTB_MI_F32_F16: "VCVTB.MI.F32.F16",
- arm_VCVTB_PL_F32_F16: "VCVTB.PL.F32.F16",
- arm_VCVTB_VS_F32_F16: "VCVTB.VS.F32.F16",
- arm_VCVTB_VC_F32_F16: "VCVTB.VC.F32.F16",
- arm_VCVTB_HI_F32_F16: "VCVTB.HI.F32.F16",
- arm_VCVTB_LS_F32_F16: "VCVTB.LS.F32.F16",
- arm_VCVTB_GE_F32_F16: "VCVTB.GE.F32.F16",
- arm_VCVTB_LT_F32_F16: "VCVTB.LT.F32.F16",
- arm_VCVTB_GT_F32_F16: "VCVTB.GT.F32.F16",
- arm_VCVTB_LE_F32_F16: "VCVTB.LE.F32.F16",
- arm_VCVTB_F32_F16: "VCVTB.F32.F16",
- arm_VCVTB_ZZ_F32_F16: "VCVTB.ZZ.F32.F16",
- arm_VCVTB_EQ_F16_F32: "VCVTB.EQ.F16.F32",
- arm_VCVTB_NE_F16_F32: "VCVTB.NE.F16.F32",
- arm_VCVTB_CS_F16_F32: "VCVTB.CS.F16.F32",
- arm_VCVTB_CC_F16_F32: "VCVTB.CC.F16.F32",
- arm_VCVTB_MI_F16_F32: "VCVTB.MI.F16.F32",
- arm_VCVTB_PL_F16_F32: "VCVTB.PL.F16.F32",
- arm_VCVTB_VS_F16_F32: "VCVTB.VS.F16.F32",
- arm_VCVTB_VC_F16_F32: "VCVTB.VC.F16.F32",
- arm_VCVTB_HI_F16_F32: "VCVTB.HI.F16.F32",
- arm_VCVTB_LS_F16_F32: "VCVTB.LS.F16.F32",
- arm_VCVTB_GE_F16_F32: "VCVTB.GE.F16.F32",
- arm_VCVTB_LT_F16_F32: "VCVTB.LT.F16.F32",
- arm_VCVTB_GT_F16_F32: "VCVTB.GT.F16.F32",
- arm_VCVTB_LE_F16_F32: "VCVTB.LE.F16.F32",
- arm_VCVTB_F16_F32: "VCVTB.F16.F32",
- arm_VCVTB_ZZ_F16_F32: "VCVTB.ZZ.F16.F32",
- arm_VCVTT_EQ_F32_F16: "VCVTT.EQ.F32.F16",
- arm_VCVTT_NE_F32_F16: "VCVTT.NE.F32.F16",
- arm_VCVTT_CS_F32_F16: "VCVTT.CS.F32.F16",
- arm_VCVTT_CC_F32_F16: "VCVTT.CC.F32.F16",
- arm_VCVTT_MI_F32_F16: "VCVTT.MI.F32.F16",
- arm_VCVTT_PL_F32_F16: "VCVTT.PL.F32.F16",
- arm_VCVTT_VS_F32_F16: "VCVTT.VS.F32.F16",
- arm_VCVTT_VC_F32_F16: "VCVTT.VC.F32.F16",
- arm_VCVTT_HI_F32_F16: "VCVTT.HI.F32.F16",
- arm_VCVTT_LS_F32_F16: "VCVTT.LS.F32.F16",
- arm_VCVTT_GE_F32_F16: "VCVTT.GE.F32.F16",
- arm_VCVTT_LT_F32_F16: "VCVTT.LT.F32.F16",
- arm_VCVTT_GT_F32_F16: "VCVTT.GT.F32.F16",
- arm_VCVTT_LE_F32_F16: "VCVTT.LE.F32.F16",
- arm_VCVTT_F32_F16: "VCVTT.F32.F16",
- arm_VCVTT_ZZ_F32_F16: "VCVTT.ZZ.F32.F16",
- arm_VCVTT_EQ_F16_F32: "VCVTT.EQ.F16.F32",
- arm_VCVTT_NE_F16_F32: "VCVTT.NE.F16.F32",
- arm_VCVTT_CS_F16_F32: "VCVTT.CS.F16.F32",
- arm_VCVTT_CC_F16_F32: "VCVTT.CC.F16.F32",
- arm_VCVTT_MI_F16_F32: "VCVTT.MI.F16.F32",
- arm_VCVTT_PL_F16_F32: "VCVTT.PL.F16.F32",
- arm_VCVTT_VS_F16_F32: "VCVTT.VS.F16.F32",
- arm_VCVTT_VC_F16_F32: "VCVTT.VC.F16.F32",
- arm_VCVTT_HI_F16_F32: "VCVTT.HI.F16.F32",
- arm_VCVTT_LS_F16_F32: "VCVTT.LS.F16.F32",
- arm_VCVTT_GE_F16_F32: "VCVTT.GE.F16.F32",
- arm_VCVTT_LT_F16_F32: "VCVTT.LT.F16.F32",
- arm_VCVTT_GT_F16_F32: "VCVTT.GT.F16.F32",
- arm_VCVTT_LE_F16_F32: "VCVTT.LE.F16.F32",
- arm_VCVTT_F16_F32: "VCVTT.F16.F32",
- arm_VCVTT_ZZ_F16_F32: "VCVTT.ZZ.F16.F32",
- arm_VCVTR_EQ_U32_F32: "VCVTR.EQ.U32.F32",
- arm_VCVTR_NE_U32_F32: "VCVTR.NE.U32.F32",
- arm_VCVTR_CS_U32_F32: "VCVTR.CS.U32.F32",
- arm_VCVTR_CC_U32_F32: "VCVTR.CC.U32.F32",
- arm_VCVTR_MI_U32_F32: "VCVTR.MI.U32.F32",
- arm_VCVTR_PL_U32_F32: "VCVTR.PL.U32.F32",
- arm_VCVTR_VS_U32_F32: "VCVTR.VS.U32.F32",
- arm_VCVTR_VC_U32_F32: "VCVTR.VC.U32.F32",
- arm_VCVTR_HI_U32_F32: "VCVTR.HI.U32.F32",
- arm_VCVTR_LS_U32_F32: "VCVTR.LS.U32.F32",
- arm_VCVTR_GE_U32_F32: "VCVTR.GE.U32.F32",
- arm_VCVTR_LT_U32_F32: "VCVTR.LT.U32.F32",
- arm_VCVTR_GT_U32_F32: "VCVTR.GT.U32.F32",
- arm_VCVTR_LE_U32_F32: "VCVTR.LE.U32.F32",
- arm_VCVTR_U32_F32: "VCVTR.U32.F32",
- arm_VCVTR_ZZ_U32_F32: "VCVTR.ZZ.U32.F32",
- arm_VCVTR_EQ_U32_F64: "VCVTR.EQ.U32.F64",
- arm_VCVTR_NE_U32_F64: "VCVTR.NE.U32.F64",
- arm_VCVTR_CS_U32_F64: "VCVTR.CS.U32.F64",
- arm_VCVTR_CC_U32_F64: "VCVTR.CC.U32.F64",
- arm_VCVTR_MI_U32_F64: "VCVTR.MI.U32.F64",
- arm_VCVTR_PL_U32_F64: "VCVTR.PL.U32.F64",
- arm_VCVTR_VS_U32_F64: "VCVTR.VS.U32.F64",
- arm_VCVTR_VC_U32_F64: "VCVTR.VC.U32.F64",
- arm_VCVTR_HI_U32_F64: "VCVTR.HI.U32.F64",
- arm_VCVTR_LS_U32_F64: "VCVTR.LS.U32.F64",
- arm_VCVTR_GE_U32_F64: "VCVTR.GE.U32.F64",
- arm_VCVTR_LT_U32_F64: "VCVTR.LT.U32.F64",
- arm_VCVTR_GT_U32_F64: "VCVTR.GT.U32.F64",
- arm_VCVTR_LE_U32_F64: "VCVTR.LE.U32.F64",
- arm_VCVTR_U32_F64: "VCVTR.U32.F64",
- arm_VCVTR_ZZ_U32_F64: "VCVTR.ZZ.U32.F64",
- arm_VCVTR_EQ_S32_F32: "VCVTR.EQ.S32.F32",
- arm_VCVTR_NE_S32_F32: "VCVTR.NE.S32.F32",
- arm_VCVTR_CS_S32_F32: "VCVTR.CS.S32.F32",
- arm_VCVTR_CC_S32_F32: "VCVTR.CC.S32.F32",
- arm_VCVTR_MI_S32_F32: "VCVTR.MI.S32.F32",
- arm_VCVTR_PL_S32_F32: "VCVTR.PL.S32.F32",
- arm_VCVTR_VS_S32_F32: "VCVTR.VS.S32.F32",
- arm_VCVTR_VC_S32_F32: "VCVTR.VC.S32.F32",
- arm_VCVTR_HI_S32_F32: "VCVTR.HI.S32.F32",
- arm_VCVTR_LS_S32_F32: "VCVTR.LS.S32.F32",
- arm_VCVTR_GE_S32_F32: "VCVTR.GE.S32.F32",
- arm_VCVTR_LT_S32_F32: "VCVTR.LT.S32.F32",
- arm_VCVTR_GT_S32_F32: "VCVTR.GT.S32.F32",
- arm_VCVTR_LE_S32_F32: "VCVTR.LE.S32.F32",
- arm_VCVTR_S32_F32: "VCVTR.S32.F32",
- arm_VCVTR_ZZ_S32_F32: "VCVTR.ZZ.S32.F32",
- arm_VCVTR_EQ_S32_F64: "VCVTR.EQ.S32.F64",
- arm_VCVTR_NE_S32_F64: "VCVTR.NE.S32.F64",
- arm_VCVTR_CS_S32_F64: "VCVTR.CS.S32.F64",
- arm_VCVTR_CC_S32_F64: "VCVTR.CC.S32.F64",
- arm_VCVTR_MI_S32_F64: "VCVTR.MI.S32.F64",
- arm_VCVTR_PL_S32_F64: "VCVTR.PL.S32.F64",
- arm_VCVTR_VS_S32_F64: "VCVTR.VS.S32.F64",
- arm_VCVTR_VC_S32_F64: "VCVTR.VC.S32.F64",
- arm_VCVTR_HI_S32_F64: "VCVTR.HI.S32.F64",
- arm_VCVTR_LS_S32_F64: "VCVTR.LS.S32.F64",
- arm_VCVTR_GE_S32_F64: "VCVTR.GE.S32.F64",
- arm_VCVTR_LT_S32_F64: "VCVTR.LT.S32.F64",
- arm_VCVTR_GT_S32_F64: "VCVTR.GT.S32.F64",
- arm_VCVTR_LE_S32_F64: "VCVTR.LE.S32.F64",
- arm_VCVTR_S32_F64: "VCVTR.S32.F64",
- arm_VCVTR_ZZ_S32_F64: "VCVTR.ZZ.S32.F64",
- arm_VCVT_EQ_U32_F32: "VCVT.EQ.U32.F32",
- arm_VCVT_NE_U32_F32: "VCVT.NE.U32.F32",
- arm_VCVT_CS_U32_F32: "VCVT.CS.U32.F32",
- arm_VCVT_CC_U32_F32: "VCVT.CC.U32.F32",
- arm_VCVT_MI_U32_F32: "VCVT.MI.U32.F32",
- arm_VCVT_PL_U32_F32: "VCVT.PL.U32.F32",
- arm_VCVT_VS_U32_F32: "VCVT.VS.U32.F32",
- arm_VCVT_VC_U32_F32: "VCVT.VC.U32.F32",
- arm_VCVT_HI_U32_F32: "VCVT.HI.U32.F32",
- arm_VCVT_LS_U32_F32: "VCVT.LS.U32.F32",
- arm_VCVT_GE_U32_F32: "VCVT.GE.U32.F32",
- arm_VCVT_LT_U32_F32: "VCVT.LT.U32.F32",
- arm_VCVT_GT_U32_F32: "VCVT.GT.U32.F32",
- arm_VCVT_LE_U32_F32: "VCVT.LE.U32.F32",
- arm_VCVT_U32_F32: "VCVT.U32.F32",
- arm_VCVT_ZZ_U32_F32: "VCVT.ZZ.U32.F32",
- arm_VCVT_EQ_U32_F64: "VCVT.EQ.U32.F64",
- arm_VCVT_NE_U32_F64: "VCVT.NE.U32.F64",
- arm_VCVT_CS_U32_F64: "VCVT.CS.U32.F64",
- arm_VCVT_CC_U32_F64: "VCVT.CC.U32.F64",
- arm_VCVT_MI_U32_F64: "VCVT.MI.U32.F64",
- arm_VCVT_PL_U32_F64: "VCVT.PL.U32.F64",
- arm_VCVT_VS_U32_F64: "VCVT.VS.U32.F64",
- arm_VCVT_VC_U32_F64: "VCVT.VC.U32.F64",
- arm_VCVT_HI_U32_F64: "VCVT.HI.U32.F64",
- arm_VCVT_LS_U32_F64: "VCVT.LS.U32.F64",
- arm_VCVT_GE_U32_F64: "VCVT.GE.U32.F64",
- arm_VCVT_LT_U32_F64: "VCVT.LT.U32.F64",
- arm_VCVT_GT_U32_F64: "VCVT.GT.U32.F64",
- arm_VCVT_LE_U32_F64: "VCVT.LE.U32.F64",
- arm_VCVT_U32_F64: "VCVT.U32.F64",
- arm_VCVT_ZZ_U32_F64: "VCVT.ZZ.U32.F64",
- arm_VCVT_EQ_S32_F32: "VCVT.EQ.S32.F32",
- arm_VCVT_NE_S32_F32: "VCVT.NE.S32.F32",
- arm_VCVT_CS_S32_F32: "VCVT.CS.S32.F32",
- arm_VCVT_CC_S32_F32: "VCVT.CC.S32.F32",
- arm_VCVT_MI_S32_F32: "VCVT.MI.S32.F32",
- arm_VCVT_PL_S32_F32: "VCVT.PL.S32.F32",
- arm_VCVT_VS_S32_F32: "VCVT.VS.S32.F32",
- arm_VCVT_VC_S32_F32: "VCVT.VC.S32.F32",
- arm_VCVT_HI_S32_F32: "VCVT.HI.S32.F32",
- arm_VCVT_LS_S32_F32: "VCVT.LS.S32.F32",
- arm_VCVT_GE_S32_F32: "VCVT.GE.S32.F32",
- arm_VCVT_LT_S32_F32: "VCVT.LT.S32.F32",
- arm_VCVT_GT_S32_F32: "VCVT.GT.S32.F32",
- arm_VCVT_LE_S32_F32: "VCVT.LE.S32.F32",
- arm_VCVT_S32_F32: "VCVT.S32.F32",
- arm_VCVT_ZZ_S32_F32: "VCVT.ZZ.S32.F32",
- arm_VCVT_EQ_S32_F64: "VCVT.EQ.S32.F64",
- arm_VCVT_NE_S32_F64: "VCVT.NE.S32.F64",
- arm_VCVT_CS_S32_F64: "VCVT.CS.S32.F64",
- arm_VCVT_CC_S32_F64: "VCVT.CC.S32.F64",
- arm_VCVT_MI_S32_F64: "VCVT.MI.S32.F64",
- arm_VCVT_PL_S32_F64: "VCVT.PL.S32.F64",
- arm_VCVT_VS_S32_F64: "VCVT.VS.S32.F64",
- arm_VCVT_VC_S32_F64: "VCVT.VC.S32.F64",
- arm_VCVT_HI_S32_F64: "VCVT.HI.S32.F64",
- arm_VCVT_LS_S32_F64: "VCVT.LS.S32.F64",
- arm_VCVT_GE_S32_F64: "VCVT.GE.S32.F64",
- arm_VCVT_LT_S32_F64: "VCVT.LT.S32.F64",
- arm_VCVT_GT_S32_F64: "VCVT.GT.S32.F64",
- arm_VCVT_LE_S32_F64: "VCVT.LE.S32.F64",
- arm_VCVT_S32_F64: "VCVT.S32.F64",
- arm_VCVT_ZZ_S32_F64: "VCVT.ZZ.S32.F64",
- arm_VDIV_EQ_F32: "VDIV.EQ.F32",
- arm_VDIV_NE_F32: "VDIV.NE.F32",
- arm_VDIV_CS_F32: "VDIV.CS.F32",
- arm_VDIV_CC_F32: "VDIV.CC.F32",
- arm_VDIV_MI_F32: "VDIV.MI.F32",
- arm_VDIV_PL_F32: "VDIV.PL.F32",
- arm_VDIV_VS_F32: "VDIV.VS.F32",
- arm_VDIV_VC_F32: "VDIV.VC.F32",
- arm_VDIV_HI_F32: "VDIV.HI.F32",
- arm_VDIV_LS_F32: "VDIV.LS.F32",
- arm_VDIV_GE_F32: "VDIV.GE.F32",
- arm_VDIV_LT_F32: "VDIV.LT.F32",
- arm_VDIV_GT_F32: "VDIV.GT.F32",
- arm_VDIV_LE_F32: "VDIV.LE.F32",
- arm_VDIV_F32: "VDIV.F32",
- arm_VDIV_ZZ_F32: "VDIV.ZZ.F32",
- arm_VDIV_EQ_F64: "VDIV.EQ.F64",
- arm_VDIV_NE_F64: "VDIV.NE.F64",
- arm_VDIV_CS_F64: "VDIV.CS.F64",
- arm_VDIV_CC_F64: "VDIV.CC.F64",
- arm_VDIV_MI_F64: "VDIV.MI.F64",
- arm_VDIV_PL_F64: "VDIV.PL.F64",
- arm_VDIV_VS_F64: "VDIV.VS.F64",
- arm_VDIV_VC_F64: "VDIV.VC.F64",
- arm_VDIV_HI_F64: "VDIV.HI.F64",
- arm_VDIV_LS_F64: "VDIV.LS.F64",
- arm_VDIV_GE_F64: "VDIV.GE.F64",
- arm_VDIV_LT_F64: "VDIV.LT.F64",
- arm_VDIV_GT_F64: "VDIV.GT.F64",
- arm_VDIV_LE_F64: "VDIV.LE.F64",
- arm_VDIV_F64: "VDIV.F64",
- arm_VDIV_ZZ_F64: "VDIV.ZZ.F64",
- arm_VLDR_EQ: "VLDR.EQ",
- arm_VLDR_NE: "VLDR.NE",
- arm_VLDR_CS: "VLDR.CS",
- arm_VLDR_CC: "VLDR.CC",
- arm_VLDR_MI: "VLDR.MI",
- arm_VLDR_PL: "VLDR.PL",
- arm_VLDR_VS: "VLDR.VS",
- arm_VLDR_VC: "VLDR.VC",
- arm_VLDR_HI: "VLDR.HI",
- arm_VLDR_LS: "VLDR.LS",
- arm_VLDR_GE: "VLDR.GE",
- arm_VLDR_LT: "VLDR.LT",
- arm_VLDR_GT: "VLDR.GT",
- arm_VLDR_LE: "VLDR.LE",
- arm_VLDR: "VLDR",
- arm_VLDR_ZZ: "VLDR.ZZ",
- arm_VMLA_EQ_F32: "VMLA.EQ.F32",
- arm_VMLA_NE_F32: "VMLA.NE.F32",
- arm_VMLA_CS_F32: "VMLA.CS.F32",
- arm_VMLA_CC_F32: "VMLA.CC.F32",
- arm_VMLA_MI_F32: "VMLA.MI.F32",
- arm_VMLA_PL_F32: "VMLA.PL.F32",
- arm_VMLA_VS_F32: "VMLA.VS.F32",
- arm_VMLA_VC_F32: "VMLA.VC.F32",
- arm_VMLA_HI_F32: "VMLA.HI.F32",
- arm_VMLA_LS_F32: "VMLA.LS.F32",
- arm_VMLA_GE_F32: "VMLA.GE.F32",
- arm_VMLA_LT_F32: "VMLA.LT.F32",
- arm_VMLA_GT_F32: "VMLA.GT.F32",
- arm_VMLA_LE_F32: "VMLA.LE.F32",
- arm_VMLA_F32: "VMLA.F32",
- arm_VMLA_ZZ_F32: "VMLA.ZZ.F32",
- arm_VMLA_EQ_F64: "VMLA.EQ.F64",
- arm_VMLA_NE_F64: "VMLA.NE.F64",
- arm_VMLA_CS_F64: "VMLA.CS.F64",
- arm_VMLA_CC_F64: "VMLA.CC.F64",
- arm_VMLA_MI_F64: "VMLA.MI.F64",
- arm_VMLA_PL_F64: "VMLA.PL.F64",
- arm_VMLA_VS_F64: "VMLA.VS.F64",
- arm_VMLA_VC_F64: "VMLA.VC.F64",
- arm_VMLA_HI_F64: "VMLA.HI.F64",
- arm_VMLA_LS_F64: "VMLA.LS.F64",
- arm_VMLA_GE_F64: "VMLA.GE.F64",
- arm_VMLA_LT_F64: "VMLA.LT.F64",
- arm_VMLA_GT_F64: "VMLA.GT.F64",
- arm_VMLA_LE_F64: "VMLA.LE.F64",
- arm_VMLA_F64: "VMLA.F64",
- arm_VMLA_ZZ_F64: "VMLA.ZZ.F64",
- arm_VMLS_EQ_F32: "VMLS.EQ.F32",
- arm_VMLS_NE_F32: "VMLS.NE.F32",
- arm_VMLS_CS_F32: "VMLS.CS.F32",
- arm_VMLS_CC_F32: "VMLS.CC.F32",
- arm_VMLS_MI_F32: "VMLS.MI.F32",
- arm_VMLS_PL_F32: "VMLS.PL.F32",
- arm_VMLS_VS_F32: "VMLS.VS.F32",
- arm_VMLS_VC_F32: "VMLS.VC.F32",
- arm_VMLS_HI_F32: "VMLS.HI.F32",
- arm_VMLS_LS_F32: "VMLS.LS.F32",
- arm_VMLS_GE_F32: "VMLS.GE.F32",
- arm_VMLS_LT_F32: "VMLS.LT.F32",
- arm_VMLS_GT_F32: "VMLS.GT.F32",
- arm_VMLS_LE_F32: "VMLS.LE.F32",
- arm_VMLS_F32: "VMLS.F32",
- arm_VMLS_ZZ_F32: "VMLS.ZZ.F32",
- arm_VMLS_EQ_F64: "VMLS.EQ.F64",
- arm_VMLS_NE_F64: "VMLS.NE.F64",
- arm_VMLS_CS_F64: "VMLS.CS.F64",
- arm_VMLS_CC_F64: "VMLS.CC.F64",
- arm_VMLS_MI_F64: "VMLS.MI.F64",
- arm_VMLS_PL_F64: "VMLS.PL.F64",
- arm_VMLS_VS_F64: "VMLS.VS.F64",
- arm_VMLS_VC_F64: "VMLS.VC.F64",
- arm_VMLS_HI_F64: "VMLS.HI.F64",
- arm_VMLS_LS_F64: "VMLS.LS.F64",
- arm_VMLS_GE_F64: "VMLS.GE.F64",
- arm_VMLS_LT_F64: "VMLS.LT.F64",
- arm_VMLS_GT_F64: "VMLS.GT.F64",
- arm_VMLS_LE_F64: "VMLS.LE.F64",
- arm_VMLS_F64: "VMLS.F64",
- arm_VMLS_ZZ_F64: "VMLS.ZZ.F64",
- arm_VMOV_EQ: "VMOV.EQ",
- arm_VMOV_NE: "VMOV.NE",
- arm_VMOV_CS: "VMOV.CS",
- arm_VMOV_CC: "VMOV.CC",
- arm_VMOV_MI: "VMOV.MI",
- arm_VMOV_PL: "VMOV.PL",
- arm_VMOV_VS: "VMOV.VS",
- arm_VMOV_VC: "VMOV.VC",
- arm_VMOV_HI: "VMOV.HI",
- arm_VMOV_LS: "VMOV.LS",
- arm_VMOV_GE: "VMOV.GE",
- arm_VMOV_LT: "VMOV.LT",
- arm_VMOV_GT: "VMOV.GT",
- arm_VMOV_LE: "VMOV.LE",
- arm_VMOV: "VMOV",
- arm_VMOV_ZZ: "VMOV.ZZ",
- arm_VMOV_EQ_32: "VMOV.EQ.32",
- arm_VMOV_NE_32: "VMOV.NE.32",
- arm_VMOV_CS_32: "VMOV.CS.32",
- arm_VMOV_CC_32: "VMOV.CC.32",
- arm_VMOV_MI_32: "VMOV.MI.32",
- arm_VMOV_PL_32: "VMOV.PL.32",
- arm_VMOV_VS_32: "VMOV.VS.32",
- arm_VMOV_VC_32: "VMOV.VC.32",
- arm_VMOV_HI_32: "VMOV.HI.32",
- arm_VMOV_LS_32: "VMOV.LS.32",
- arm_VMOV_GE_32: "VMOV.GE.32",
- arm_VMOV_LT_32: "VMOV.LT.32",
- arm_VMOV_GT_32: "VMOV.GT.32",
- arm_VMOV_LE_32: "VMOV.LE.32",
- arm_VMOV_32: "VMOV.32",
- arm_VMOV_ZZ_32: "VMOV.ZZ.32",
- arm_VMOV_EQ_F32: "VMOV.EQ.F32",
- arm_VMOV_NE_F32: "VMOV.NE.F32",
- arm_VMOV_CS_F32: "VMOV.CS.F32",
- arm_VMOV_CC_F32: "VMOV.CC.F32",
- arm_VMOV_MI_F32: "VMOV.MI.F32",
- arm_VMOV_PL_F32: "VMOV.PL.F32",
- arm_VMOV_VS_F32: "VMOV.VS.F32",
- arm_VMOV_VC_F32: "VMOV.VC.F32",
- arm_VMOV_HI_F32: "VMOV.HI.F32",
- arm_VMOV_LS_F32: "VMOV.LS.F32",
- arm_VMOV_GE_F32: "VMOV.GE.F32",
- arm_VMOV_LT_F32: "VMOV.LT.F32",
- arm_VMOV_GT_F32: "VMOV.GT.F32",
- arm_VMOV_LE_F32: "VMOV.LE.F32",
- arm_VMOV_F32: "VMOV.F32",
- arm_VMOV_ZZ_F32: "VMOV.ZZ.F32",
- arm_VMOV_EQ_F64: "VMOV.EQ.F64",
- arm_VMOV_NE_F64: "VMOV.NE.F64",
- arm_VMOV_CS_F64: "VMOV.CS.F64",
- arm_VMOV_CC_F64: "VMOV.CC.F64",
- arm_VMOV_MI_F64: "VMOV.MI.F64",
- arm_VMOV_PL_F64: "VMOV.PL.F64",
- arm_VMOV_VS_F64: "VMOV.VS.F64",
- arm_VMOV_VC_F64: "VMOV.VC.F64",
- arm_VMOV_HI_F64: "VMOV.HI.F64",
- arm_VMOV_LS_F64: "VMOV.LS.F64",
- arm_VMOV_GE_F64: "VMOV.GE.F64",
- arm_VMOV_LT_F64: "VMOV.LT.F64",
- arm_VMOV_GT_F64: "VMOV.GT.F64",
- arm_VMOV_LE_F64: "VMOV.LE.F64",
- arm_VMOV_F64: "VMOV.F64",
- arm_VMOV_ZZ_F64: "VMOV.ZZ.F64",
- arm_VMRS_EQ: "VMRS.EQ",
- arm_VMRS_NE: "VMRS.NE",
- arm_VMRS_CS: "VMRS.CS",
- arm_VMRS_CC: "VMRS.CC",
- arm_VMRS_MI: "VMRS.MI",
- arm_VMRS_PL: "VMRS.PL",
- arm_VMRS_VS: "VMRS.VS",
- arm_VMRS_VC: "VMRS.VC",
- arm_VMRS_HI: "VMRS.HI",
- arm_VMRS_LS: "VMRS.LS",
- arm_VMRS_GE: "VMRS.GE",
- arm_VMRS_LT: "VMRS.LT",
- arm_VMRS_GT: "VMRS.GT",
- arm_VMRS_LE: "VMRS.LE",
- arm_VMRS: "VMRS",
- arm_VMRS_ZZ: "VMRS.ZZ",
- arm_VMSR_EQ: "VMSR.EQ",
- arm_VMSR_NE: "VMSR.NE",
- arm_VMSR_CS: "VMSR.CS",
- arm_VMSR_CC: "VMSR.CC",
- arm_VMSR_MI: "VMSR.MI",
- arm_VMSR_PL: "VMSR.PL",
- arm_VMSR_VS: "VMSR.VS",
- arm_VMSR_VC: "VMSR.VC",
- arm_VMSR_HI: "VMSR.HI",
- arm_VMSR_LS: "VMSR.LS",
- arm_VMSR_GE: "VMSR.GE",
- arm_VMSR_LT: "VMSR.LT",
- arm_VMSR_GT: "VMSR.GT",
- arm_VMSR_LE: "VMSR.LE",
- arm_VMSR: "VMSR",
- arm_VMSR_ZZ: "VMSR.ZZ",
- arm_VMUL_EQ_F32: "VMUL.EQ.F32",
- arm_VMUL_NE_F32: "VMUL.NE.F32",
- arm_VMUL_CS_F32: "VMUL.CS.F32",
- arm_VMUL_CC_F32: "VMUL.CC.F32",
- arm_VMUL_MI_F32: "VMUL.MI.F32",
- arm_VMUL_PL_F32: "VMUL.PL.F32",
- arm_VMUL_VS_F32: "VMUL.VS.F32",
- arm_VMUL_VC_F32: "VMUL.VC.F32",
- arm_VMUL_HI_F32: "VMUL.HI.F32",
- arm_VMUL_LS_F32: "VMUL.LS.F32",
- arm_VMUL_GE_F32: "VMUL.GE.F32",
- arm_VMUL_LT_F32: "VMUL.LT.F32",
- arm_VMUL_GT_F32: "VMUL.GT.F32",
- arm_VMUL_LE_F32: "VMUL.LE.F32",
- arm_VMUL_F32: "VMUL.F32",
- arm_VMUL_ZZ_F32: "VMUL.ZZ.F32",
- arm_VMUL_EQ_F64: "VMUL.EQ.F64",
- arm_VMUL_NE_F64: "VMUL.NE.F64",
- arm_VMUL_CS_F64: "VMUL.CS.F64",
- arm_VMUL_CC_F64: "VMUL.CC.F64",
- arm_VMUL_MI_F64: "VMUL.MI.F64",
- arm_VMUL_PL_F64: "VMUL.PL.F64",
- arm_VMUL_VS_F64: "VMUL.VS.F64",
- arm_VMUL_VC_F64: "VMUL.VC.F64",
- arm_VMUL_HI_F64: "VMUL.HI.F64",
- arm_VMUL_LS_F64: "VMUL.LS.F64",
- arm_VMUL_GE_F64: "VMUL.GE.F64",
- arm_VMUL_LT_F64: "VMUL.LT.F64",
- arm_VMUL_GT_F64: "VMUL.GT.F64",
- arm_VMUL_LE_F64: "VMUL.LE.F64",
- arm_VMUL_F64: "VMUL.F64",
- arm_VMUL_ZZ_F64: "VMUL.ZZ.F64",
- arm_VNEG_EQ_F32: "VNEG.EQ.F32",
- arm_VNEG_NE_F32: "VNEG.NE.F32",
- arm_VNEG_CS_F32: "VNEG.CS.F32",
- arm_VNEG_CC_F32: "VNEG.CC.F32",
- arm_VNEG_MI_F32: "VNEG.MI.F32",
- arm_VNEG_PL_F32: "VNEG.PL.F32",
- arm_VNEG_VS_F32: "VNEG.VS.F32",
- arm_VNEG_VC_F32: "VNEG.VC.F32",
- arm_VNEG_HI_F32: "VNEG.HI.F32",
- arm_VNEG_LS_F32: "VNEG.LS.F32",
- arm_VNEG_GE_F32: "VNEG.GE.F32",
- arm_VNEG_LT_F32: "VNEG.LT.F32",
- arm_VNEG_GT_F32: "VNEG.GT.F32",
- arm_VNEG_LE_F32: "VNEG.LE.F32",
- arm_VNEG_F32: "VNEG.F32",
- arm_VNEG_ZZ_F32: "VNEG.ZZ.F32",
- arm_VNEG_EQ_F64: "VNEG.EQ.F64",
- arm_VNEG_NE_F64: "VNEG.NE.F64",
- arm_VNEG_CS_F64: "VNEG.CS.F64",
- arm_VNEG_CC_F64: "VNEG.CC.F64",
- arm_VNEG_MI_F64: "VNEG.MI.F64",
- arm_VNEG_PL_F64: "VNEG.PL.F64",
- arm_VNEG_VS_F64: "VNEG.VS.F64",
- arm_VNEG_VC_F64: "VNEG.VC.F64",
- arm_VNEG_HI_F64: "VNEG.HI.F64",
- arm_VNEG_LS_F64: "VNEG.LS.F64",
- arm_VNEG_GE_F64: "VNEG.GE.F64",
- arm_VNEG_LT_F64: "VNEG.LT.F64",
- arm_VNEG_GT_F64: "VNEG.GT.F64",
- arm_VNEG_LE_F64: "VNEG.LE.F64",
- arm_VNEG_F64: "VNEG.F64",
- arm_VNEG_ZZ_F64: "VNEG.ZZ.F64",
- arm_VNMLS_EQ_F32: "VNMLS.EQ.F32",
- arm_VNMLS_NE_F32: "VNMLS.NE.F32",
- arm_VNMLS_CS_F32: "VNMLS.CS.F32",
- arm_VNMLS_CC_F32: "VNMLS.CC.F32",
- arm_VNMLS_MI_F32: "VNMLS.MI.F32",
- arm_VNMLS_PL_F32: "VNMLS.PL.F32",
- arm_VNMLS_VS_F32: "VNMLS.VS.F32",
- arm_VNMLS_VC_F32: "VNMLS.VC.F32",
- arm_VNMLS_HI_F32: "VNMLS.HI.F32",
- arm_VNMLS_LS_F32: "VNMLS.LS.F32",
- arm_VNMLS_GE_F32: "VNMLS.GE.F32",
- arm_VNMLS_LT_F32: "VNMLS.LT.F32",
- arm_VNMLS_GT_F32: "VNMLS.GT.F32",
- arm_VNMLS_LE_F32: "VNMLS.LE.F32",
- arm_VNMLS_F32: "VNMLS.F32",
- arm_VNMLS_ZZ_F32: "VNMLS.ZZ.F32",
- arm_VNMLS_EQ_F64: "VNMLS.EQ.F64",
- arm_VNMLS_NE_F64: "VNMLS.NE.F64",
- arm_VNMLS_CS_F64: "VNMLS.CS.F64",
- arm_VNMLS_CC_F64: "VNMLS.CC.F64",
- arm_VNMLS_MI_F64: "VNMLS.MI.F64",
- arm_VNMLS_PL_F64: "VNMLS.PL.F64",
- arm_VNMLS_VS_F64: "VNMLS.VS.F64",
- arm_VNMLS_VC_F64: "VNMLS.VC.F64",
- arm_VNMLS_HI_F64: "VNMLS.HI.F64",
- arm_VNMLS_LS_F64: "VNMLS.LS.F64",
- arm_VNMLS_GE_F64: "VNMLS.GE.F64",
- arm_VNMLS_LT_F64: "VNMLS.LT.F64",
- arm_VNMLS_GT_F64: "VNMLS.GT.F64",
- arm_VNMLS_LE_F64: "VNMLS.LE.F64",
- arm_VNMLS_F64: "VNMLS.F64",
- arm_VNMLS_ZZ_F64: "VNMLS.ZZ.F64",
- arm_VNMLA_EQ_F32: "VNMLA.EQ.F32",
- arm_VNMLA_NE_F32: "VNMLA.NE.F32",
- arm_VNMLA_CS_F32: "VNMLA.CS.F32",
- arm_VNMLA_CC_F32: "VNMLA.CC.F32",
- arm_VNMLA_MI_F32: "VNMLA.MI.F32",
- arm_VNMLA_PL_F32: "VNMLA.PL.F32",
- arm_VNMLA_VS_F32: "VNMLA.VS.F32",
- arm_VNMLA_VC_F32: "VNMLA.VC.F32",
- arm_VNMLA_HI_F32: "VNMLA.HI.F32",
- arm_VNMLA_LS_F32: "VNMLA.LS.F32",
- arm_VNMLA_GE_F32: "VNMLA.GE.F32",
- arm_VNMLA_LT_F32: "VNMLA.LT.F32",
- arm_VNMLA_GT_F32: "VNMLA.GT.F32",
- arm_VNMLA_LE_F32: "VNMLA.LE.F32",
- arm_VNMLA_F32: "VNMLA.F32",
- arm_VNMLA_ZZ_F32: "VNMLA.ZZ.F32",
- arm_VNMLA_EQ_F64: "VNMLA.EQ.F64",
- arm_VNMLA_NE_F64: "VNMLA.NE.F64",
- arm_VNMLA_CS_F64: "VNMLA.CS.F64",
- arm_VNMLA_CC_F64: "VNMLA.CC.F64",
- arm_VNMLA_MI_F64: "VNMLA.MI.F64",
- arm_VNMLA_PL_F64: "VNMLA.PL.F64",
- arm_VNMLA_VS_F64: "VNMLA.VS.F64",
- arm_VNMLA_VC_F64: "VNMLA.VC.F64",
- arm_VNMLA_HI_F64: "VNMLA.HI.F64",
- arm_VNMLA_LS_F64: "VNMLA.LS.F64",
- arm_VNMLA_GE_F64: "VNMLA.GE.F64",
- arm_VNMLA_LT_F64: "VNMLA.LT.F64",
- arm_VNMLA_GT_F64: "VNMLA.GT.F64",
- arm_VNMLA_LE_F64: "VNMLA.LE.F64",
- arm_VNMLA_F64: "VNMLA.F64",
- arm_VNMLA_ZZ_F64: "VNMLA.ZZ.F64",
- arm_VNMUL_EQ_F32: "VNMUL.EQ.F32",
- arm_VNMUL_NE_F32: "VNMUL.NE.F32",
- arm_VNMUL_CS_F32: "VNMUL.CS.F32",
- arm_VNMUL_CC_F32: "VNMUL.CC.F32",
- arm_VNMUL_MI_F32: "VNMUL.MI.F32",
- arm_VNMUL_PL_F32: "VNMUL.PL.F32",
- arm_VNMUL_VS_F32: "VNMUL.VS.F32",
- arm_VNMUL_VC_F32: "VNMUL.VC.F32",
- arm_VNMUL_HI_F32: "VNMUL.HI.F32",
- arm_VNMUL_LS_F32: "VNMUL.LS.F32",
- arm_VNMUL_GE_F32: "VNMUL.GE.F32",
- arm_VNMUL_LT_F32: "VNMUL.LT.F32",
- arm_VNMUL_GT_F32: "VNMUL.GT.F32",
- arm_VNMUL_LE_F32: "VNMUL.LE.F32",
- arm_VNMUL_F32: "VNMUL.F32",
- arm_VNMUL_ZZ_F32: "VNMUL.ZZ.F32",
- arm_VNMUL_EQ_F64: "VNMUL.EQ.F64",
- arm_VNMUL_NE_F64: "VNMUL.NE.F64",
- arm_VNMUL_CS_F64: "VNMUL.CS.F64",
- arm_VNMUL_CC_F64: "VNMUL.CC.F64",
- arm_VNMUL_MI_F64: "VNMUL.MI.F64",
- arm_VNMUL_PL_F64: "VNMUL.PL.F64",
- arm_VNMUL_VS_F64: "VNMUL.VS.F64",
- arm_VNMUL_VC_F64: "VNMUL.VC.F64",
- arm_VNMUL_HI_F64: "VNMUL.HI.F64",
- arm_VNMUL_LS_F64: "VNMUL.LS.F64",
- arm_VNMUL_GE_F64: "VNMUL.GE.F64",
- arm_VNMUL_LT_F64: "VNMUL.LT.F64",
- arm_VNMUL_GT_F64: "VNMUL.GT.F64",
- arm_VNMUL_LE_F64: "VNMUL.LE.F64",
- arm_VNMUL_F64: "VNMUL.F64",
- arm_VNMUL_ZZ_F64: "VNMUL.ZZ.F64",
- arm_VSQRT_EQ_F32: "VSQRT.EQ.F32",
- arm_VSQRT_NE_F32: "VSQRT.NE.F32",
- arm_VSQRT_CS_F32: "VSQRT.CS.F32",
- arm_VSQRT_CC_F32: "VSQRT.CC.F32",
- arm_VSQRT_MI_F32: "VSQRT.MI.F32",
- arm_VSQRT_PL_F32: "VSQRT.PL.F32",
- arm_VSQRT_VS_F32: "VSQRT.VS.F32",
- arm_VSQRT_VC_F32: "VSQRT.VC.F32",
- arm_VSQRT_HI_F32: "VSQRT.HI.F32",
- arm_VSQRT_LS_F32: "VSQRT.LS.F32",
- arm_VSQRT_GE_F32: "VSQRT.GE.F32",
- arm_VSQRT_LT_F32: "VSQRT.LT.F32",
- arm_VSQRT_GT_F32: "VSQRT.GT.F32",
- arm_VSQRT_LE_F32: "VSQRT.LE.F32",
- arm_VSQRT_F32: "VSQRT.F32",
- arm_VSQRT_ZZ_F32: "VSQRT.ZZ.F32",
- arm_VSQRT_EQ_F64: "VSQRT.EQ.F64",
- arm_VSQRT_NE_F64: "VSQRT.NE.F64",
- arm_VSQRT_CS_F64: "VSQRT.CS.F64",
- arm_VSQRT_CC_F64: "VSQRT.CC.F64",
- arm_VSQRT_MI_F64: "VSQRT.MI.F64",
- arm_VSQRT_PL_F64: "VSQRT.PL.F64",
- arm_VSQRT_VS_F64: "VSQRT.VS.F64",
- arm_VSQRT_VC_F64: "VSQRT.VC.F64",
- arm_VSQRT_HI_F64: "VSQRT.HI.F64",
- arm_VSQRT_LS_F64: "VSQRT.LS.F64",
- arm_VSQRT_GE_F64: "VSQRT.GE.F64",
- arm_VSQRT_LT_F64: "VSQRT.LT.F64",
- arm_VSQRT_GT_F64: "VSQRT.GT.F64",
- arm_VSQRT_LE_F64: "VSQRT.LE.F64",
- arm_VSQRT_F64: "VSQRT.F64",
- arm_VSQRT_ZZ_F64: "VSQRT.ZZ.F64",
- arm_VSTR_EQ: "VSTR.EQ",
- arm_VSTR_NE: "VSTR.NE",
- arm_VSTR_CS: "VSTR.CS",
- arm_VSTR_CC: "VSTR.CC",
- arm_VSTR_MI: "VSTR.MI",
- arm_VSTR_PL: "VSTR.PL",
- arm_VSTR_VS: "VSTR.VS",
- arm_VSTR_VC: "VSTR.VC",
- arm_VSTR_HI: "VSTR.HI",
- arm_VSTR_LS: "VSTR.LS",
- arm_VSTR_GE: "VSTR.GE",
- arm_VSTR_LT: "VSTR.LT",
- arm_VSTR_GT: "VSTR.GT",
- arm_VSTR_LE: "VSTR.LE",
- arm_VSTR: "VSTR",
- arm_VSTR_ZZ: "VSTR.ZZ",
- arm_VSUB_EQ_F32: "VSUB.EQ.F32",
- arm_VSUB_NE_F32: "VSUB.NE.F32",
- arm_VSUB_CS_F32: "VSUB.CS.F32",
- arm_VSUB_CC_F32: "VSUB.CC.F32",
- arm_VSUB_MI_F32: "VSUB.MI.F32",
- arm_VSUB_PL_F32: "VSUB.PL.F32",
- arm_VSUB_VS_F32: "VSUB.VS.F32",
- arm_VSUB_VC_F32: "VSUB.VC.F32",
- arm_VSUB_HI_F32: "VSUB.HI.F32",
- arm_VSUB_LS_F32: "VSUB.LS.F32",
- arm_VSUB_GE_F32: "VSUB.GE.F32",
- arm_VSUB_LT_F32: "VSUB.LT.F32",
- arm_VSUB_GT_F32: "VSUB.GT.F32",
- arm_VSUB_LE_F32: "VSUB.LE.F32",
- arm_VSUB_F32: "VSUB.F32",
- arm_VSUB_ZZ_F32: "VSUB.ZZ.F32",
- arm_VSUB_EQ_F64: "VSUB.EQ.F64",
- arm_VSUB_NE_F64: "VSUB.NE.F64",
- arm_VSUB_CS_F64: "VSUB.CS.F64",
- arm_VSUB_CC_F64: "VSUB.CC.F64",
- arm_VSUB_MI_F64: "VSUB.MI.F64",
- arm_VSUB_PL_F64: "VSUB.PL.F64",
- arm_VSUB_VS_F64: "VSUB.VS.F64",
- arm_VSUB_VC_F64: "VSUB.VC.F64",
- arm_VSUB_HI_F64: "VSUB.HI.F64",
- arm_VSUB_LS_F64: "VSUB.LS.F64",
- arm_VSUB_GE_F64: "VSUB.GE.F64",
- arm_VSUB_LT_F64: "VSUB.LT.F64",
- arm_VSUB_GT_F64: "VSUB.GT.F64",
- arm_VSUB_LE_F64: "VSUB.LE.F64",
- arm_VSUB_F64: "VSUB.F64",
- arm_VSUB_ZZ_F64: "VSUB.ZZ.F64",
- arm_WFE_EQ: "WFE.EQ",
- arm_WFE_NE: "WFE.NE",
- arm_WFE_CS: "WFE.CS",
- arm_WFE_CC: "WFE.CC",
- arm_WFE_MI: "WFE.MI",
- arm_WFE_PL: "WFE.PL",
- arm_WFE_VS: "WFE.VS",
- arm_WFE_VC: "WFE.VC",
- arm_WFE_HI: "WFE.HI",
- arm_WFE_LS: "WFE.LS",
- arm_WFE_GE: "WFE.GE",
- arm_WFE_LT: "WFE.LT",
- arm_WFE_GT: "WFE.GT",
- arm_WFE_LE: "WFE.LE",
- arm_WFE: "WFE",
- arm_WFE_ZZ: "WFE.ZZ",
- arm_WFI_EQ: "WFI.EQ",
- arm_WFI_NE: "WFI.NE",
- arm_WFI_CS: "WFI.CS",
- arm_WFI_CC: "WFI.CC",
- arm_WFI_MI: "WFI.MI",
- arm_WFI_PL: "WFI.PL",
- arm_WFI_VS: "WFI.VS",
- arm_WFI_VC: "WFI.VC",
- arm_WFI_HI: "WFI.HI",
- arm_WFI_LS: "WFI.LS",
- arm_WFI_GE: "WFI.GE",
- arm_WFI_LT: "WFI.LT",
- arm_WFI_GT: "WFI.GT",
- arm_WFI_LE: "WFI.LE",
- arm_WFI: "WFI",
- arm_WFI_ZZ: "WFI.ZZ",
- arm_YIELD_EQ: "YIELD.EQ",
- arm_YIELD_NE: "YIELD.NE",
- arm_YIELD_CS: "YIELD.CS",
- arm_YIELD_CC: "YIELD.CC",
- arm_YIELD_MI: "YIELD.MI",
- arm_YIELD_PL: "YIELD.PL",
- arm_YIELD_VS: "YIELD.VS",
- arm_YIELD_VC: "YIELD.VC",
- arm_YIELD_HI: "YIELD.HI",
- arm_YIELD_LS: "YIELD.LS",
- arm_YIELD_GE: "YIELD.GE",
- arm_YIELD_LT: "YIELD.LT",
- arm_YIELD_GT: "YIELD.GT",
- arm_YIELD_LE: "YIELD.LE",
- arm_YIELD: "YIELD",
- arm_YIELD_ZZ: "YIELD.ZZ",
-}
-
-var arm_instFormats = [...]arm_instFormat{
- {0x0fe00000, 0x02a00000, 2, arm_ADC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_const}}, // ADC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|0|1|S|Rn:4|Rd:4|imm12:12
- {0x0fe00090, 0x00a00010, 4, arm_ADC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_R}}, // ADC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fe00010, 0x00a00000, 2, arm_ADC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_imm}}, // ADC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0fe00000, 0x02800000, 2, arm_ADD_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_const}}, // ADD{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|0|0|S|Rn:4|Rd:4|imm12:12
- {0x0fe00090, 0x00800010, 4, arm_ADD_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_R}}, // ADD{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fe00010, 0x00800000, 2, arm_ADD_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_imm}}, // ADD{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0fef0000, 0x028d0000, 2, arm_ADD_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_SP, arm_arg_const}}, // ADD{S}<c> <Rd>,SP,#<const> cond:4|0|0|1|0|1|0|0|S|1|1|0|1|Rd:4|imm12:12
- {0x0fef0010, 0x008d0000, 2, arm_ADD_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_SP, arm_arg_R_shift_imm}}, // ADD{S}<c> <Rd>,SP,<Rm>{,<shift>} cond:4|0|0|0|0|1|0|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0fe00000, 0x02000000, 2, arm_AND_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_const}}, // AND{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|0|0|S|Rn:4|Rd:4|imm12:12
- {0x0fe00090, 0x00000010, 4, arm_AND_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_R}}, // AND{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fe00010, 0x00000000, 2, arm_AND_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_imm}}, // AND{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0fef0070, 0x01a00040, 4, arm_ASR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_imm5_32}}, // ASR{S}<c> <Rd>,<Rm>,#<imm5_32> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|0|0|Rm:4
- {0x0fef00f0, 0x01a00050, 4, arm_ASR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_R_8}}, // ASR{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|0|1|Rn:4
- {0x0f000000, 0x0a000000, 4, arm_B_EQ, 0x1c04, arm_instArgs{arm_arg_label24}}, // B<c> <label24> cond:4|1|0|1|0|imm24:24
- {0x0fe0007f, 0x07c0001f, 4, arm_BFC_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_imm5, arm_arg_lsb_width}}, // BFC<c> <Rd>,#<lsb>,#<width> cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|1|1|1|1
- {0x0fe00070, 0x07c00010, 2, arm_BFI_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_imm5, arm_arg_lsb_width}}, // BFI<c> <Rd>,<Rn>,#<lsb>,#<width> cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|Rn:4
- {0x0fe00000, 0x03c00000, 2, arm_BIC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_const}}, // BIC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|1|1|1|0|S|Rn:4|Rd:4|imm12:12
- {0x0fe00090, 0x01c00010, 4, arm_BIC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_R}}, // BIC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fe00010, 0x01c00000, 2, arm_BIC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_imm}}, // BIC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0ff000f0, 0x01200070, 4, arm_BKPT_EQ, 0x1c04, arm_instArgs{arm_arg_imm_12at8_4at0}}, // BKPT<c> #<imm12+4> cond:4|0|0|0|1|0|0|1|0|imm12:12|0|1|1|1|imm4:4
- {0x0f000000, 0x0b000000, 4, arm_BL_EQ, 0x1c04, arm_instArgs{arm_arg_label24}}, // BL<c> <label24> cond:4|1|0|1|1|imm24:24
- {0xfe000000, 0xfa000000, 4, arm_BLX, 0x0, arm_instArgs{arm_arg_label24H}}, // BLX <label24H> 1|1|1|1|1|0|1|H|imm24:24
- {0x0ffffff0, 0x012fff30, 4, arm_BLX_EQ, 0x1c04, arm_instArgs{arm_arg_R_0}}, // BLX<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff000f0, 0x012fff30, 3, arm_BLX_EQ, 0x1c04, arm_instArgs{arm_arg_R_0}}, // BLX<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ffffff0, 0x012fff10, 4, arm_BX_EQ, 0x1c04, arm_instArgs{arm_arg_R_0}}, // BX<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff000f0, 0x012fff10, 3, arm_BX_EQ, 0x1c04, arm_instArgs{arm_arg_R_0}}, // BX<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ffffff0, 0x012fff20, 4, arm_BXJ_EQ, 0x1c04, arm_instArgs{arm_arg_R_0}}, // BXJ<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4
- {0x0ff000f0, 0x012fff20, 3, arm_BXJ_EQ, 0x1c04, arm_instArgs{arm_arg_R_0}}, // BXJ<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4
- {0xffffffff, 0xf57ff01f, 4, arm_CLREX, 0x0, arm_instArgs{}}, // CLREX 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1)
- {0xfff000f0, 0xf57ff01f, 3, arm_CLREX, 0x0, arm_instArgs{}}, // CLREX 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1)
- {0x0fff0ff0, 0x016f0f10, 4, arm_CLZ_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // CLZ<c> <Rd>,<Rm> cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff000f0, 0x016f0f10, 3, arm_CLZ_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // CLZ<c> <Rd>,<Rm> cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff0f000, 0x03700000, 4, arm_CMN_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_const}}, // CMN<c> <Rn>,#<const> cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
- {0x0ff00000, 0x03700000, 3, arm_CMN_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_const}}, // CMN<c> <Rn>,#<const> cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
- {0x0ff0f090, 0x01700010, 4, arm_CMN_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_R}}, // CMN<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
- {0x0ff00090, 0x01700010, 3, arm_CMN_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_R}}, // CMN<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
- {0x0ff0f010, 0x01700000, 4, arm_CMN_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_imm}}, // CMN<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
- {0x0ff00010, 0x01700000, 3, arm_CMN_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_imm}}, // CMN<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
- {0x0ff0f000, 0x03500000, 4, arm_CMP_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_const}}, // CMP<c> <Rn>,#<const> cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
- {0x0ff00000, 0x03500000, 3, arm_CMP_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_const}}, // CMP<c> <Rn>,#<const> cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
- {0x0ff0f090, 0x01500010, 4, arm_CMP_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_R}}, // CMP<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
- {0x0ff00090, 0x01500010, 3, arm_CMP_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_R}}, // CMP<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
- {0x0ff0f010, 0x01500000, 4, arm_CMP_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_imm}}, // CMP<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
- {0x0ff00010, 0x01500000, 3, arm_CMP_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_imm}}, // CMP<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
- {0x0ffffff0, 0x0320f0f0, 4, arm_DBG_EQ, 0x1c04, arm_instArgs{arm_arg_option}}, // DBG<c> #<option> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|1|1|1|1|option:4
- {0x0fff00f0, 0x0320f0f0, 3, arm_DBG_EQ, 0x1c04, arm_instArgs{arm_arg_option}}, // DBG<c> #<option> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|1|1|1|1|option:4
- {0xfffffff0, 0xf57ff050, 4, arm_DMB, 0x0, arm_instArgs{arm_arg_option}}, // DMB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|1|option:4
- {0xfff000f0, 0xf57ff050, 3, arm_DMB, 0x0, arm_instArgs{arm_arg_option}}, // DMB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|1|option:4
- {0xfffffff0, 0xf57ff040, 4, arm_DSB, 0x0, arm_instArgs{arm_arg_option}}, // DSB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|0|option:4
- {0xfff000f0, 0xf57ff040, 3, arm_DSB, 0x0, arm_instArgs{arm_arg_option}}, // DSB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|0|option:4
- {0x0fe00000, 0x02200000, 2, arm_EOR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_const}}, // EOR{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|0|1|S|Rn:4|Rd:4|imm12:12
- {0x0fe00090, 0x00200010, 4, arm_EOR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_R}}, // EOR{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fe00010, 0x00200000, 2, arm_EOR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_imm}}, // EOR{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
- {0xfffffff0, 0xf57ff060, 4, arm_ISB, 0x0, arm_instArgs{arm_arg_option}}, // ISB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|1|0|option:4
- {0xfff000f0, 0xf57ff060, 3, arm_ISB, 0x0, arm_instArgs{arm_arg_option}}, // ISB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|1|0|option:4
- {0x0fd00000, 0x08900000, 2, arm_LDM_EQ, 0x1c04, arm_instArgs{arm_arg_R_16_WB, arm_arg_registers}}, // LDM<c> <Rn>{!},<registers> cond:4|1|0|0|0|1|0|W|1|Rn:4|register_list:16
- {0x0fd00000, 0x08100000, 4, arm_LDMDA_EQ, 0x1c04, arm_instArgs{arm_arg_R_16_WB, arm_arg_registers}}, // LDMDA<c> <Rn>{!},<registers> cond:4|1|0|0|0|0|0|W|1|Rn:4|register_list:16
- {0x0fd00000, 0x09100000, 4, arm_LDMDB_EQ, 0x1c04, arm_instArgs{arm_arg_R_16_WB, arm_arg_registers}}, // LDMDB<c> <Rn>{!},<registers> cond:4|1|0|0|1|0|0|W|1|Rn:4|register_list:16
- {0x0fd00000, 0x09900000, 4, arm_LDMIB_EQ, 0x1c04, arm_instArgs{arm_arg_R_16_WB, arm_arg_registers}}, // LDMIB<c> <Rn>{!},<registers> cond:4|1|0|0|1|1|0|W|1|Rn:4|register_list:16
- {0x0f7f0000, 0x051f0000, 4, arm_LDR_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_label_pm_12}}, // LDR<c> <Rt>,<label+/-12> cond:4|0|1|0|(1)|U|0|(0)|1|1|1|1|1|Rt:4|imm12:12
- {0x0e5f0000, 0x051f0000, 3, arm_LDR_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_label_pm_12}}, // LDR<c> <Rt>,<label+/-12> cond:4|0|1|0|(1)|U|0|(0)|1|1|1|1|1|Rt:4|imm12:12
- {0x0e500010, 0x06100000, 2, arm_LDR_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_shift_imm_W}}, // LDR<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|0|W|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
- {0x0e500000, 0x04100000, 2, arm_LDR_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm12_W}}, // LDR<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|0|W|1|Rn:4|Rt:4|imm12:12
- {0x0f7f0000, 0x055f0000, 4, arm_LDRB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_label_pm_12}}, // LDRB<c> <Rt>,<label+/-12> cond:4|0|1|0|(1)|U|1|(0)|1|1|1|1|1|Rt:4|imm12:12
- {0x0e5f0000, 0x055f0000, 3, arm_LDRB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_label_pm_12}}, // LDRB<c> <Rt>,<label+/-12> cond:4|0|1|0|(1)|U|1|(0)|1|1|1|1|1|Rt:4|imm12:12
- {0x0e500010, 0x06500000, 2, arm_LDRB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_shift_imm_W}}, // LDRB<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|1|W|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
- {0x0e500000, 0x04500000, 2, arm_LDRB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm12_W}}, // LDRB<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|1|W|1|Rn:4|Rt:4|imm12:12
- {0x0f700000, 0x04700000, 4, arm_LDRBT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm12_postindex}}, // LDRBT<c> <Rt>,[<Rn>],#+/-<imm12> cond:4|0|1|0|0|U|1|1|1|Rn:4|Rt:4|imm12:12
- {0x0f700010, 0x06700000, 4, arm_LDRBT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_shift_imm_postindex}}, // LDRBT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|1|1|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
- {0x0e500ff0, 0x000000d0, 4, arm_LDRD_EQ, 0x1c04, arm_instArgs{arm_arg_R1_12, arm_arg_R2_12, arm_arg_mem_R_pm_R_W}}, // LDRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|0|1|Rm:4
- {0x0e5000f0, 0x000000d0, 3, arm_LDRD_EQ, 0x1c04, arm_instArgs{arm_arg_R1_12, arm_arg_R2_12, arm_arg_mem_R_pm_R_W}}, // LDRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|0|1|Rm:4
- {0x0e5000f0, 0x004000d0, 2, arm_LDRD_EQ, 0x1c04, arm_instArgs{arm_arg_R1_12, arm_arg_R2_12, arm_arg_mem_R_pm_imm8_W}}, // LDRD<c> <Rt1>,<Rt2>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4
- {0x0ff00fff, 0x01900f9f, 4, arm_LDREX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R}}, // LDREX<c> <Rt>,[<Rn>] cond:4|0|0|0|1|1|0|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
- {0x0ff000f0, 0x01900f9f, 3, arm_LDREX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R}}, // LDREX<c> <Rt>,[<Rn>] cond:4|0|0|0|1|1|0|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
- {0x0ff00fff, 0x01d00f9f, 4, arm_LDREXB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R}}, // LDREXB<c> <Rt>, [<Rn>] cond:4|0|0|0|1|1|1|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
- {0x0ff000f0, 0x01d00f9f, 3, arm_LDREXB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R}}, // LDREXB<c> <Rt>, [<Rn>] cond:4|0|0|0|1|1|1|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
- {0x0ff00fff, 0x01b00f9f, 4, arm_LDREXD_EQ, 0x1c04, arm_instArgs{arm_arg_R1_12, arm_arg_R2_12, arm_arg_mem_R}}, // LDREXD<c> <Rt1>,<Rt2>,[<Rn>] cond:4|0|0|0|1|1|0|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
- {0x0ff000f0, 0x01b00f9f, 3, arm_LDREXD_EQ, 0x1c04, arm_instArgs{arm_arg_R1_12, arm_arg_R2_12, arm_arg_mem_R}}, // LDREXD<c> <Rt1>,<Rt2>,[<Rn>] cond:4|0|0|0|1|1|0|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
- {0x0ff00fff, 0x01f00f9f, 4, arm_LDREXH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R}}, // LDREXH<c> <Rt>, [<Rn>] cond:4|0|0|0|1|1|1|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
- {0x0ff000f0, 0x01f00f9f, 3, arm_LDREXH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R}}, // LDREXH<c> <Rt>, [<Rn>] cond:4|0|0|0|1|1|1|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
- {0x0e500ff0, 0x001000b0, 2, arm_LDRH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_W}}, // LDRH<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4
- {0x0e5000f0, 0x005000b0, 2, arm_LDRH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm8_W}}, // LDRH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4
- {0x0f7000f0, 0x007000b0, 4, arm_LDRHT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm8_postindex}}, // LDRHT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4
- {0x0f700ff0, 0x003000b0, 4, arm_LDRHT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_postindex}}, // LDRHT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4
- {0x0e500ff0, 0x001000d0, 2, arm_LDRSB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_W}}, // LDRSB<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|1|0|1|Rm:4
- {0x0e5000f0, 0x005000d0, 2, arm_LDRSB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm8_W}}, // LDRSB<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4
- {0x0f7000f0, 0x007000d0, 4, arm_LDRSBT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm8_postindex}}, // LDRSBT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4
- {0x0f700ff0, 0x003000d0, 4, arm_LDRSBT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_postindex}}, // LDRSBT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|1|0|1|Rm:4
- {0x0e500ff0, 0x001000f0, 2, arm_LDRSH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_W}}, // LDRSH<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|1|1|1|Rm:4
- {0x0e5000f0, 0x005000f0, 2, arm_LDRSH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm8_W}}, // LDRSH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4
- {0x0f7000f0, 0x007000f0, 4, arm_LDRSHT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm8_postindex}}, // LDRSHT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4
- {0x0f700ff0, 0x003000f0, 4, arm_LDRSHT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_postindex}}, // LDRSHT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|1|1|1|Rm:4
- {0x0f700000, 0x04300000, 4, arm_LDRT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm12_postindex}}, // LDRT<c> <Rt>, [<Rn>] {,#+/-<imm12>} cond:4|0|1|0|0|U|0|1|1|Rn:4|Rt:4|imm12:12
- {0x0f700010, 0x06300000, 4, arm_LDRT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_shift_imm_postindex}}, // LDRT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|0|1|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
- {0x0fef0070, 0x01a00000, 2, arm_LSL_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_imm5_nz}}, // LSL{S}<c> <Rd>,<Rm>,#<imm5_nz> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|0|0|0|Rm:4
- {0x0fef00f0, 0x01a00010, 4, arm_LSL_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_R_8}}, // LSL{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|0|0|1|Rn:4
- {0x0fef0070, 0x01a00020, 4, arm_LSR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_imm5_32}}, // LSR{S}<c> <Rd>,<Rm>,#<imm5_32> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|0|1|0|Rm:4
- {0x0fef00f0, 0x01a00030, 4, arm_LSR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_R_8}}, // LSR{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|0|1|1|Rn:4
- {0x0fe000f0, 0x00200090, 4, arm_MLA_EQ, 0x14011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8, arm_arg_R_12}}, // MLA{S}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|0|0|0|1|S|Rd:4|Ra:4|Rm:4|1|0|0|1|Rn:4
- {0x0ff000f0, 0x00600090, 4, arm_MLS_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8, arm_arg_R_12}}, // MLS<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|0|0|1|1|0|Rd:4|Ra:4|Rm:4|1|0|0|1|Rn:4
- {0x0ff00000, 0x03400000, 4, arm_MOVT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_imm_4at16_12at0}}, // MOVT<c> <Rd>,#<imm12+4> cond:4|0|0|1|1|0|1|0|0|imm4:4|Rd:4|imm12:12
- {0x0ff00000, 0x03000000, 4, arm_MOVW_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_imm_4at16_12at0}}, // MOVW<c> <Rd>,#<imm12+4> cond:4|0|0|1|1|0|0|0|0|imm4:4|Rd:4|imm12:12
- {0x0fef0000, 0x03a00000, 2, arm_MOV_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_const}}, // MOV{S}<c> <Rd>,#<const> cond:4|0|0|1|1|1|0|1|S|0|0|0|0|Rd:4|imm12:12
- {0x0fef0ff0, 0x01a00000, 2, arm_MOV_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // MOV{S}<c> <Rd>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|0|0|0|0|0|0|0|0|Rm:4
- {0x0fff0fff, 0x010f0000, 4, arm_MRS_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_APSR}}, // MRS<c> <Rd>,APSR cond:4|0|0|0|1|0|0|0|0|(1)|(1)|(1)|(1)|Rd:4|(0)|(0)|(0)|(0)|0|0|0|0|(0)|(0)|(0)|(0)
- {0x0ff000f0, 0x010f0000, 3, arm_MRS_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_APSR}}, // MRS<c> <Rd>,APSR cond:4|0|0|0|1|0|0|0|0|(1)|(1)|(1)|(1)|Rd:4|(0)|(0)|(0)|(0)|0|0|0|0|(0)|(0)|(0)|(0)
- {0x0fe0f0f0, 0x00000090, 4, arm_MUL_EQ, 0x14011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // MUL{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|0|0|0|0|S|Rd:4|(0)|(0)|(0)|(0)|Rm:4|1|0|0|1|Rn:4
- {0x0fe000f0, 0x00000090, 3, arm_MUL_EQ, 0x14011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // MUL{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|0|0|0|0|S|Rd:4|(0)|(0)|(0)|(0)|Rm:4|1|0|0|1|Rn:4
- {0x0fef0000, 0x03e00000, 2, arm_MVN_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_const}}, // MVN{S}<c> <Rd>,#<const> cond:4|0|0|1|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm12:12
- {0x0fe00000, 0x03e00000, 1, arm_MVN_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_const}}, // MVN{S}<c> <Rd>,#<const> cond:4|0|0|1|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm12:12
- {0x0fef0090, 0x01e00010, 4, arm_MVN_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_shift_R}}, // MVN{S}<c> <Rd>,<Rm>,<type> <Rs> cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fe00090, 0x01e00010, 3, arm_MVN_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_shift_R}}, // MVN{S}<c> <Rd>,<Rm>,<type> <Rs> cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fef0010, 0x01e00000, 2, arm_MVN_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_shift_imm}}, // MVN{S}<c> <Rd>,<Rm>{,<shift>} cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0fe00010, 0x01e00000, 1, arm_MVN_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_shift_imm}}, // MVN{S}<c> <Rd>,<Rm>{,<shift>} cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0fffffff, 0x0320f000, 4, arm_NOP_EQ, 0x1c04, arm_instArgs{}}, // NOP<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|0
- {0x0fff00ff, 0x0320f000, 3, arm_NOP_EQ, 0x1c04, arm_instArgs{}}, // NOP<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|0
- {0x0fe00000, 0x03800000, 2, arm_ORR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_const}}, // ORR{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|1|1|0|0|S|Rn:4|Rd:4|imm12:12
- {0x0fe00090, 0x01800010, 4, arm_ORR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_R}}, // ORR{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fe00010, 0x01800000, 2, arm_ORR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_imm}}, // ORR{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0ff00030, 0x06800010, 4, arm_PKHBT_EQ, 0x6011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_imm}}, // PKH<BT,TB><c> <Rd>,<Rn>,<Rm>{,LSL #<imm5>} cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|imm5:5|tb|0|1|Rm:4
- {0xff7ff000, 0xf55ff000, 4, arm_PLD, 0x0, arm_instArgs{arm_arg_label_pm_12}}, // PLD <label+/-12> 1|1|1|1|0|1|0|1|U|(1)|0|1|1|1|1|1|(1)|(1)|(1)|(1)|imm12:12
- {0xff3f0000, 0xf55ff000, 3, arm_PLD, 0x0, arm_instArgs{arm_arg_label_pm_12}}, // PLD <label+/-12> 1|1|1|1|0|1|0|1|U|(1)|0|1|1|1|1|1|(1)|(1)|(1)|(1)|imm12:12
- {0xff30f000, 0xf510f000, 2, arm_PLD_W, 0x1601, arm_instArgs{arm_arg_mem_R_pm_imm12_offset}}, // PLD{W} [<Rn>,#+/-<imm12>] 1|1|1|1|0|1|0|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12
- {0xff300000, 0xf510f000, 1, arm_PLD_W, 0x1601, arm_instArgs{arm_arg_mem_R_pm_imm12_offset}}, // PLD{W} [<Rn>,#+/-<imm12>] 1|1|1|1|0|1|0|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12
- {0xff30f010, 0xf710f000, 4, arm_PLD_W, 0x1601, arm_instArgs{arm_arg_mem_R_pm_R_shift_imm_offset}}, // PLD{W} [<Rn>,+/-<Rm>{, <shift>}] 1|1|1|1|0|1|1|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4
- {0xff300010, 0xf710f000, 3, arm_PLD_W, 0x1601, arm_instArgs{arm_arg_mem_R_pm_R_shift_imm_offset}}, // PLD{W} [<Rn>,+/-<Rm>{, <shift>}] 1|1|1|1|0|1|1|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4
- {0xff70f000, 0xf450f000, 4, arm_PLI, 0x0, arm_instArgs{arm_arg_mem_R_pm_imm12_offset}}, // PLI [<Rn>,#+/-<imm12>] 1|1|1|1|0|1|0|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12
- {0xff700000, 0xf450f000, 3, arm_PLI, 0x0, arm_instArgs{arm_arg_mem_R_pm_imm12_offset}}, // PLI [<Rn>,#+/-<imm12>] 1|1|1|1|0|1|0|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12
- {0xff70f010, 0xf650f000, 4, arm_PLI, 0x0, arm_instArgs{arm_arg_mem_R_pm_R_shift_imm_offset}}, // PLI [<Rn>,+/-<Rm>{, <shift>}] 1|1|1|1|0|1|1|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4
- {0xff700010, 0xf650f000, 3, arm_PLI, 0x0, arm_instArgs{arm_arg_mem_R_pm_R_shift_imm_offset}}, // PLI [<Rn>,+/-<Rm>{, <shift>}] 1|1|1|1|0|1|1|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4
- {0x0fff0000, 0x08bd0000, 4, arm_POP_EQ, 0x1c04, arm_instArgs{arm_arg_registers2}}, // POP<c> <registers2> cond:4|1|0|0|0|1|0|1|1|1|1|0|1|register_list:16
- {0x0fff0fff, 0x049d0004, 4, arm_POP_EQ, 0x1c04, arm_instArgs{arm_arg_registers1}}, // POP<c> <registers1> cond:4|0|1|0|0|1|0|0|1|1|1|0|1|Rt:4|0|0|0|0|0|0|0|0|0|1|0|0
- {0x0fff0000, 0x092d0000, 4, arm_PUSH_EQ, 0x1c04, arm_instArgs{arm_arg_registers2}}, // PUSH<c> <registers2> cond:4|1|0|0|1|0|0|1|0|1|1|0|1|register_list:16
- {0x0fff0fff, 0x052d0004, 4, arm_PUSH_EQ, 0x1c04, arm_instArgs{arm_arg_registers1}}, // PUSH<c> <registers1> cond:4|0|1|0|1|0|0|1|0|1|1|0|1|Rt:4|0|0|0|0|0|0|0|0|0|1|0|0
- {0x0ff00ff0, 0x06200f10, 4, arm_QADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff000f0, 0x06200f10, 3, arm_QADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff00ff0, 0x06200f90, 4, arm_QADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff000f0, 0x06200f90, 3, arm_QADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff00ff0, 0x01000050, 4, arm_QADD_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_R_16}}, // QADD<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|0|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4
- {0x0ff000f0, 0x01000050, 3, arm_QADD_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_R_16}}, // QADD<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|0|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4
- {0x0ff00ff0, 0x06200f30, 4, arm_QASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff000f0, 0x06200f30, 3, arm_QASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff00ff0, 0x01400050, 4, arm_QDADD_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_R_16}}, // QDADD<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|1|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4
- {0x0ff000f0, 0x01400050, 3, arm_QDADD_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_R_16}}, // QDADD<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|1|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4
- {0x0ff00ff0, 0x01600050, 4, arm_QDSUB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_R_16}}, // QDSUB<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|1|1|0|Rn:4|Rd:4|0|0|0|0|0|1|0|1|Rm:4
- {0x0ff00ff0, 0x06200f50, 4, arm_QSAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff000f0, 0x06200f50, 3, arm_QSAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff00ff0, 0x06200f70, 4, arm_QSUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff000f0, 0x06200f70, 3, arm_QSUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff00ff0, 0x06200ff0, 4, arm_QSUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0ff000f0, 0x06200ff0, 3, arm_QSUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // QSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0ff00ff0, 0x01200050, 4, arm_QSUB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_R_16}}, // QSUB<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|0|1|0|Rn:4|Rd:4|0|0|0|0|0|1|0|1|Rm:4
- {0x0fff0ff0, 0x06ff0f30, 4, arm_RBIT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // RBIT<c> <Rd>,<Rm> cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff000f0, 0x06ff0f30, 3, arm_RBIT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // RBIT<c> <Rd>,<Rm> cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0fff0ff0, 0x06bf0fb0, 4, arm_REV16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // REV16<c> <Rd>,<Rm> cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
- {0x0ff000f0, 0x06bf0fb0, 3, arm_REV16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // REV16<c> <Rd>,<Rm> cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
- {0x0fff0ff0, 0x06bf0f30, 4, arm_REV_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // REV<c> <Rd>,<Rm> cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff000f0, 0x06bf0f30, 3, arm_REV_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // REV<c> <Rd>,<Rm> cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0fff0ff0, 0x06ff0fb0, 4, arm_REVSH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // REVSH<c> <Rd>,<Rm> cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
- {0x0ff000f0, 0x06ff0fb0, 3, arm_REVSH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // REVSH<c> <Rd>,<Rm> cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
- {0x0fef0070, 0x01a00060, 2, arm_ROR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_imm5}}, // ROR{S}<c> <Rd>,<Rm>,#<imm5> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|1|0|Rm:4
- {0x0fef00f0, 0x01a00070, 4, arm_ROR_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_R_8}}, // ROR{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|1|1|Rn:4
- {0x0fef0ff0, 0x01a00060, 4, arm_RRX_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0}}, // RRX{S}<c> <Rd>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|0|0|0|0|0|1|1|0|Rm:4
- {0x0fe00000, 0x02600000, 2, arm_RSB_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_const}}, // RSB{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|1|1|S|Rn:4|Rd:4|imm12:12
- {0x0fe00090, 0x00600010, 4, arm_RSB_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_R}}, // RSB{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|1|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fe00010, 0x00600000, 2, arm_RSB_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_imm}}, // RSB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|1|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0fe00000, 0x02e00000, 2, arm_RSC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_const}}, // RSC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|1|1|S|Rn:4|Rd:4|imm12:12
- {0x0fe00090, 0x00e00010, 4, arm_RSC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_R}}, // RSC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|1|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fe00010, 0x00e00000, 2, arm_RSC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_imm}}, // RSC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|1|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0ff00ff0, 0x06100f10, 4, arm_SADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff000f0, 0x06100f10, 3, arm_SADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff00ff0, 0x06100f90, 4, arm_SADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff000f0, 0x06100f90, 3, arm_SADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff00ff0, 0x06100f30, 4, arm_SASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff000f0, 0x06100f30, 3, arm_SASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0fe00000, 0x02c00000, 2, arm_SBC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_const}}, // SBC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|1|0|S|Rn:4|Rd:4|imm12:12
- {0x0fe00090, 0x00c00010, 4, arm_SBC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_R}}, // SBC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fe00010, 0x00c00000, 2, arm_SBC_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_imm}}, // SBC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0fe00070, 0x07a00050, 4, arm_SBFX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_imm5, arm_arg_widthm1}}, // SBFX<c> <Rd>,<Rn>,#<lsb>,#<widthm1> cond:4|0|1|1|1|1|0|1|widthm1:5|Rd:4|lsb:5|1|0|1|Rn:4
- {0x0ff00ff0, 0x06800fb0, 4, arm_SEL_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SEL<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
- {0x0ff000f0, 0x06800fb0, 3, arm_SEL_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SEL<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
- {0xfffffdff, 0xf1010000, 4, arm_SETEND, 0x0, arm_instArgs{arm_arg_endian}}, // SETEND <endian_specifier> 1|1|1|1|0|0|0|1|0|0|0|0|0|0|0|1|0|0|0|0|0|0|E|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)
- {0xfffffc00, 0xf1010000, 3, arm_SETEND, 0x0, arm_instArgs{arm_arg_endian}}, // SETEND <endian_specifier> 1|1|1|1|0|0|0|1|0|0|0|0|0|0|0|1|0|0|0|0|0|0|E|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)
- {0x0fffffff, 0x0320f004, 4, arm_SEV_EQ, 0x1c04, arm_instArgs{}}, // SEV<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|1|0|0
- {0x0fff00ff, 0x0320f004, 3, arm_SEV_EQ, 0x1c04, arm_instArgs{}}, // SEV<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|1|0|0
- {0x0ff00ff0, 0x06300f10, 4, arm_SHADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff000f0, 0x06300f10, 3, arm_SHADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff00ff0, 0x06300f90, 4, arm_SHADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff000f0, 0x06300f90, 3, arm_SHADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff00ff0, 0x06300f30, 4, arm_SHASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff000f0, 0x06300f30, 3, arm_SHASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff00ff0, 0x06300f50, 4, arm_SHSAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff000f0, 0x06300f50, 3, arm_SHSAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff00ff0, 0x06300f70, 4, arm_SHSUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff000f0, 0x06300f70, 3, arm_SHSUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff00ff0, 0x06300ff0, 4, arm_SHSUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0ff000f0, 0x06300ff0, 3, arm_SHSUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SHSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0ff00090, 0x01000080, 4, arm_SMLABB_EQ, 0x50106011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8, arm_arg_R_12}}, // SMLA<x><y><c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|1|0|0|0|0|Rd:4|Ra:4|Rm:4|1|M|N|0|Rn:4
- {0x0ff000d0, 0x07000010, 2, arm_SMLAD_EQ, 0x5011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8, arm_arg_R_12}}, // SMLAD{X}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|0|0|0|Rd:4|Ra:4|Rm:4|0|0|M|1|Rn:4
- {0x0ff00090, 0x01400080, 4, arm_SMLALBB_EQ, 0x50106011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // SMLAL<x><y><c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|1|M|N|0|Rn:4
- {0x0ff000d0, 0x07400010, 4, arm_SMLALD_EQ, 0x5011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // SMLALD{X}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|1|1|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|0|0|M|1|Rn:4
- {0x0fe000f0, 0x00e00090, 4, arm_SMLAL_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // SMLAL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|1|1|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
- {0x0ff000b0, 0x01200080, 4, arm_SMLAWB_EQ, 0x6011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8, arm_arg_R_12}}, // SMLAW<y><c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|1|0|0|1|0|Rd:4|Ra:4|Rm:4|1|M|0|0|Rn:4
- {0x0ff000d0, 0x07000050, 2, arm_SMLSD_EQ, 0x5011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8, arm_arg_R_12}}, // SMLSD{X}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|0|0|0|Rd:4|Ra:4|Rm:4|0|1|M|1|Rn:4
- {0x0ff000d0, 0x07400050, 4, arm_SMLSLD_EQ, 0x5011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // SMLSLD{X}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|1|1|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|0|1|M|1|Rn:4
- {0x0ff000d0, 0x07500010, 2, arm_SMMLA_EQ, 0x5011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8, arm_arg_R_12}}, // SMMLA{R}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|1|0|1|Rd:4|Ra:4|Rm:4|0|0|R|1|Rn:4
- {0x0ff000d0, 0x075000d0, 4, arm_SMMLS_EQ, 0x5011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8, arm_arg_R_12}}, // SMMLS{R}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|1|0|1|Rd:4|Ra:4|Rm:4|1|1|R|1|Rn:4
- {0x0ff0f0d0, 0x0750f010, 4, arm_SMMUL_EQ, 0x5011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // SMMUL{R}<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|0|1|0|1|Rd:4|1|1|1|1|Rm:4|0|0|R|1|Rn:4
- {0x0ff0f0d0, 0x0700f010, 4, arm_SMUAD_EQ, 0x5011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // SMUAD{X}<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|0|0|0|0|Rd:4|1|1|1|1|Rm:4|0|0|M|1|Rn:4
- {0x0ff0f090, 0x01600080, 4, arm_SMULBB_EQ, 0x50106011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // SMUL<x><y><c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|0|1|1|0|Rd:4|0|0|0|0|Rm:4|1|M|N|0|Rn:4
- {0x0fe000f0, 0x00c00090, 4, arm_SMULL_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // SMULL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|1|0|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
- {0x0ff0f0b0, 0x012000a0, 4, arm_SMULWB_EQ, 0x6011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // SMULW<y><c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|0|0|1|0|Rd:4|0|0|0|0|Rm:4|1|M|1|0|Rn:4
- {0x0ff0f0d0, 0x0700f050, 4, arm_SMUSD_EQ, 0x5011c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // SMUSD{X}<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|0|0|0|0|Rd:4|1|1|1|1|Rm:4|0|1|M|1|Rn:4
- {0x0ff00ff0, 0x06a00f30, 4, arm_SSAT16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_satimm4m1, arm_arg_R_0}}, // SSAT16<c> <Rd>,#<sat_imm4m1>,<Rn> cond:4|0|1|1|0|1|0|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4
- {0x0ff000f0, 0x06a00f30, 3, arm_SSAT16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_satimm4m1, arm_arg_R_0}}, // SSAT16<c> <Rd>,#<sat_imm4m1>,<Rn> cond:4|0|1|1|0|1|0|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4
- {0x0fe00030, 0x06a00010, 4, arm_SSAT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_satimm5m1, arm_arg_R_shift_imm}}, // SSAT<c> <Rd>,#<sat_imm5m1>,<Rn>{,<shift>} cond:4|0|1|1|0|1|0|1|sat_imm:5|Rd:4|imm5:5|sh|0|1|Rn:4
- {0x0ff00ff0, 0x06100f50, 4, arm_SSAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff000f0, 0x06100f50, 3, arm_SSAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff00ff0, 0x06100f70, 4, arm_SSUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff000f0, 0x06100f70, 3, arm_SSUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff00ff0, 0x06100ff0, 4, arm_SSUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0ff000f0, 0x06100ff0, 3, arm_SSUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // SSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0fd00000, 0x08800000, 4, arm_STM_EQ, 0x1c04, arm_instArgs{arm_arg_R_16_WB, arm_arg_registers}}, // STM<c> <Rn>{!},<registers> cond:4|1|0|0|0|1|0|W|0|Rn:4|register_list:16
- {0x0fd00000, 0x08000000, 4, arm_STMDA_EQ, 0x1c04, arm_instArgs{arm_arg_R_16_WB, arm_arg_registers}}, // STMDA<c> <Rn>{!},<registers> cond:4|1|0|0|0|0|0|W|0|Rn:4|register_list:16
- {0x0fd00000, 0x09000000, 2, arm_STMDB_EQ, 0x1c04, arm_instArgs{arm_arg_R_16_WB, arm_arg_registers}}, // STMDB<c> <Rn>{!},<registers> cond:4|1|0|0|1|0|0|W|0|Rn:4|register_list:16
- {0x0fd00000, 0x09800000, 4, arm_STMIB_EQ, 0x1c04, arm_instArgs{arm_arg_R_16_WB, arm_arg_registers}}, // STMIB<c> <Rn>{!},<registers> cond:4|1|0|0|1|1|0|W|0|Rn:4|register_list:16
- {0x0e500018, 0x06000000, 2, arm_STR_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_shift_imm_W}}, // STR<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|0|W|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
- {0x0e500000, 0x04000000, 2, arm_STR_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm12_W}}, // STR<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|0|W|0|Rn:4|Rt:4|imm12:12
- {0x0e500010, 0x06400000, 2, arm_STRB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_shift_imm_W}}, // STRB<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|1|W|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
- {0x0e500000, 0x04400000, 2, arm_STRB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm12_W}}, // STRB<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|1|W|0|Rn:4|Rt:4|imm12:12
- {0x0f700000, 0x04600000, 4, arm_STRBT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm12_postindex}}, // STRBT<c> <Rt>,[<Rn>],#+/-<imm12> cond:4|0|1|0|0|U|1|1|0|Rn:4|Rt:4|imm12:12
- {0x0f700010, 0x06600000, 4, arm_STRBT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_shift_imm_postindex}}, // STRBT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|1|1|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
- {0x0e500ff0, 0x000000f0, 4, arm_STRD_EQ, 0x1c04, arm_instArgs{arm_arg_R1_12, arm_arg_R2_12, arm_arg_mem_R_pm_R_W}}, // STRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|1|1|Rm:4
- {0x0e5000f0, 0x000000f0, 3, arm_STRD_EQ, 0x1c04, arm_instArgs{arm_arg_R1_12, arm_arg_R2_12, arm_arg_mem_R_pm_R_W}}, // STRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|1|1|Rm:4
- {0x0e5000f0, 0x004000f0, 4, arm_STRD_EQ, 0x1c04, arm_instArgs{arm_arg_R1_12, arm_arg_R2_12, arm_arg_mem_R_pm_imm8_W}}, // STRD<c> <Rt1>,<Rt2>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4
- {0x0ff00ff0, 0x01800f90, 4, arm_STREX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_mem_R}}, // STREX<c> <Rd>,<Rt>,[<Rn>] cond:4|0|0|0|1|1|0|0|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
- {0x0ff00ff0, 0x01c00f90, 4, arm_STREXB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_mem_R}}, // STREXB<c> <Rd>,<Rt>,[<Rn>] cond:4|0|0|0|1|1|1|0|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
- {0x0ff00ff0, 0x01a00f90, 4, arm_STREXD_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R1_0, arm_arg_R2_0, arm_arg_mem_R}}, // STREXD<c> <Rd>,<Rt1>,<Rt2>,[<Rn>] cond:4|0|0|0|1|1|0|1|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
- {0x0ff00ff0, 0x01e00f90, 4, arm_STREXH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_mem_R}}, // STREXH<c> <Rd>,<Rt>,[<Rn>] cond:4|0|0|0|1|1|1|1|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
- {0x0e500ff0, 0x000000b0, 2, arm_STRH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_W}}, // STRH<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4
- {0x0e5000f0, 0x004000b0, 2, arm_STRH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm8_W}}, // STRH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4
- {0x0f7000f0, 0x006000b0, 4, arm_STRHT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm8_postindex}}, // STRHT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|0|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4
- {0x0f700ff0, 0x002000b0, 4, arm_STRHT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_postindex}}, // STRHT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|0|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4
- {0x0f700000, 0x04200000, 4, arm_STRT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_imm12_postindex}}, // STRT<c> <Rt>, [<Rn>] {,#+/-<imm12>} cond:4|0|1|0|0|U|0|1|0|Rn:4|Rt:4|imm12:12
- {0x0f700010, 0x06200000, 4, arm_STRT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_mem_R_pm_R_shift_imm_postindex}}, // STRT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|0|1|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
- {0x0fe00000, 0x02400000, 2, arm_SUB_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_const}}, // SUB{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|1|0|S|Rn:4|Rd:4|imm12:12
- {0x0fe00090, 0x00400010, 4, arm_SUB_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_R}}, // SUB{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
- {0x0fe00010, 0x00400000, 2, arm_SUB_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_shift_imm}}, // SUB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0fef0000, 0x024d0000, 2, arm_SUB_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_SP, arm_arg_const}}, // SUB{S}<c> <Rd>,SP,#<const> cond:4|0|0|1|0|0|1|0|S|1|1|0|1|Rd:4|imm12:12
- {0x0fef0010, 0x004d0000, 2, arm_SUB_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_SP, arm_arg_R_shift_imm}}, // SUB{S}<c> <Rd>,SP,<Rm>{,<shift>} cond:4|0|0|0|0|0|1|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4
- {0x0f000000, 0x0f000000, 4, arm_SVC_EQ, 0x1c04, arm_instArgs{arm_arg_imm24}}, // SVC<c> #<imm24> cond:4|1|1|1|1|imm24:24
- {0x0fb00ff0, 0x01000090, 4, arm_SWP_EQ, 0x16011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_mem_R}}, // SWP{B}<c> <Rt>,<Rm>,[<Rn>] cond:4|0|0|0|1|0|B|0|0|Rn:4|Rt:4|0|0|0|0|1|0|0|1|Rm:4
- {0x0ff003f0, 0x06800070, 2, arm_SXTAB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_rotate}}, // SXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0ff003f0, 0x06a00070, 2, arm_SXTAB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_rotate}}, // SXTAB<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0ff003f0, 0x06b00070, 2, arm_SXTAH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_rotate}}, // SXTAH<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|1|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0fff03f0, 0x068f0070, 4, arm_SXTB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_rotate}}, // SXTB16<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|0|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0fff03f0, 0x06af0070, 4, arm_SXTB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_rotate}}, // SXTB<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0fff03f0, 0x06bf0070, 4, arm_SXTH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_rotate}}, // SXTH<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|1|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0ff0f000, 0x03300000, 4, arm_TEQ_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_const}}, // TEQ<c> <Rn>,#<const> cond:4|0|0|1|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
- {0x0ff00000, 0x03300000, 3, arm_TEQ_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_const}}, // TEQ<c> <Rn>,#<const> cond:4|0|0|1|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
- {0x0ff0f090, 0x01300010, 4, arm_TEQ_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_R}}, // TEQ<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
- {0x0ff00090, 0x01300010, 3, arm_TEQ_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_R}}, // TEQ<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
- {0x0ff0f010, 0x01300000, 4, arm_TEQ_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_imm}}, // TEQ<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
- {0x0ff00010, 0x01300000, 3, arm_TEQ_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_imm}}, // TEQ<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
- {0x0ff0f000, 0x03100000, 4, arm_TST_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_const}}, // TST<c> <Rn>,#<const> cond:4|0|0|1|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
- {0x0ff00000, 0x03100000, 3, arm_TST_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_const}}, // TST<c> <Rn>,#<const> cond:4|0|0|1|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
- {0x0ff0f090, 0x01100010, 4, arm_TST_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_R}}, // TST<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
- {0x0ff00090, 0x01100010, 3, arm_TST_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_R}}, // TST<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
- {0x0ff0f010, 0x01100000, 4, arm_TST_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_imm}}, // TST<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
- {0x0ff00010, 0x01100000, 3, arm_TST_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_shift_imm}}, // TST<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
- {0x0ff00ff0, 0x06500f10, 4, arm_UADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff000f0, 0x06500f10, 3, arm_UADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff00ff0, 0x06500f90, 4, arm_UADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff000f0, 0x06500f90, 3, arm_UADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff00ff0, 0x06500f30, 4, arm_UASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff000f0, 0x06500f30, 3, arm_UASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0fe00070, 0x07e00050, 4, arm_UBFX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_0, arm_arg_imm5, arm_arg_widthm1}}, // UBFX<c> <Rd>,<Rn>,#<lsb>,#<widthm1> cond:4|0|1|1|1|1|1|1|widthm1:5|Rd:4|lsb:5|1|0|1|Rn:4
- {0x0ff00ff0, 0x06700f10, 4, arm_UHADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff000f0, 0x06700f10, 3, arm_UHADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff00ff0, 0x06700f90, 4, arm_UHADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff000f0, 0x06700f90, 3, arm_UHADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff00ff0, 0x06700f30, 4, arm_UHASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff000f0, 0x06700f30, 3, arm_UHASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff00ff0, 0x06700f50, 4, arm_UHSAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff000f0, 0x06700f50, 3, arm_UHSAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff00ff0, 0x06700f70, 4, arm_UHSUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff000f0, 0x06700f70, 3, arm_UHSUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff00ff0, 0x06700ff0, 4, arm_UHSUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0ff000f0, 0x06700ff0, 3, arm_UHSUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UHSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0ff000f0, 0x00400090, 4, arm_UMAAL_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // UMAAL<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|0|1|0|0|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
- {0x0fe000f0, 0x00a00090, 4, arm_UMLAL_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // UMLAL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|0|1|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
- {0x0fe000f0, 0x00800090, 4, arm_UMULL_EQ, 0x14011c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // UMULL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|0|0|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
- {0x0ff00ff0, 0x06600f10, 4, arm_UQADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff000f0, 0x06600f10, 3, arm_UQADD16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
- {0x0ff00ff0, 0x06600f90, 4, arm_UQADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff000f0, 0x06600f90, 3, arm_UQADD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
- {0x0ff00ff0, 0x06600f30, 4, arm_UQASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff000f0, 0x06600f30, 3, arm_UQASX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
- {0x0ff00ff0, 0x06600f50, 4, arm_UQSAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff000f0, 0x06600f50, 3, arm_UQSAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff00ff0, 0x06600f70, 4, arm_UQSUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff000f0, 0x06600f70, 3, arm_UQSUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff00ff0, 0x06600ff0, 4, arm_UQSUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0ff000f0, 0x06600ff0, 3, arm_UQSUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // UQSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0ff0f0f0, 0x0780f010, 4, arm_USAD8_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8}}, // USAD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|1|0|0|0|Rd:4|1|1|1|1|Rm:4|0|0|0|1|Rn:4
- {0x0ff000f0, 0x07800010, 2, arm_USADA8_EQ, 0x1c04, arm_instArgs{arm_arg_R_16, arm_arg_R_0, arm_arg_R_8, arm_arg_R_12}}, // USADA8<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|1|0|0|0|Rd:4|Ra:4|Rm:4|0|0|0|1|Rn:4
- {0x0ff00ff0, 0x06e00f30, 4, arm_USAT16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_satimm4, arm_arg_R_0}}, // USAT16<c> <Rd>,#<sat_imm4>,<Rn> cond:4|0|1|1|0|1|1|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4
- {0x0ff000f0, 0x06e00f30, 3, arm_USAT16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_satimm4, arm_arg_R_0}}, // USAT16<c> <Rd>,#<sat_imm4>,<Rn> cond:4|0|1|1|0|1|1|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4
- {0x0fe00030, 0x06e00010, 4, arm_USAT_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_satimm5, arm_arg_R_shift_imm}}, // USAT<c> <Rd>,#<sat_imm5>,<Rn>{,<shift>} cond:4|0|1|1|0|1|1|1|sat_imm:5|Rd:4|imm5:5|sh|0|1|Rn:4
- {0x0ff00ff0, 0x06500f50, 4, arm_USAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // USAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff000f0, 0x06500f50, 3, arm_USAX_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // USAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
- {0x0ff00ff0, 0x06500f70, 4, arm_USUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // USUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff000f0, 0x06500f70, 3, arm_USUB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // USUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
- {0x0ff00ff0, 0x06500ff0, 4, arm_USUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // USUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0ff000f0, 0x06500ff0, 3, arm_USUB8_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_0}}, // USUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
- {0x0ff003f0, 0x06c00070, 2, arm_UXTAB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_rotate}}, // UXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|0|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0ff003f0, 0x06e00070, 2, arm_UXTAB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_rotate}}, // UXTAB<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0ff003f0, 0x06f00070, 2, arm_UXTAH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_16, arm_arg_R_rotate}}, // UXTAH<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|1|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0fff03f0, 0x06cf0070, 4, arm_UXTB16_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_rotate}}, // UXTB16<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|0|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0fff03f0, 0x06ef0070, 4, arm_UXTB_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_rotate}}, // UXTB<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0fff03f0, 0x06ff0070, 4, arm_UXTH_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_R_rotate}}, // UXTH<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|1|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
- {0x0fb00e10, 0x0e000a00, 4, arm_VMLA_EQ_F32, 0x60108011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sn_Dn, arm_arg_Sm_Dm}}, // V<MLA,MLS><c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|0|0|Vn:4|Vd:4|1|0|1|sz|N|op|M|0|Vm:4
- {0x0fbf0ed0, 0x0eb00ac0, 4, arm_VABS_EQ_F32, 0x8011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sm_Dm}}, // VABS<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|0|Vd:4|1|0|1|sz|1|1|M|0|Vm:4
- {0x0fb00e50, 0x0e300a00, 4, arm_VADD_EQ_F32, 0x8011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sn_Dn, arm_arg_Sm_Dm}}, // VADD<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|1|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4
- {0x0fbf0e7f, 0x0eb50a40, 4, arm_VCMP_EQ_F32, 0x70108011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_fp_0}}, // VCMP{E}<c>.F<32,64> <Sd,Dd>, #0.0 cond:4|1|1|1|0|1|D|1|1|0|1|0|1|Vd:4|1|0|1|sz|E|1|0|0|(0)|(0)|(0)|(0)
- {0x0fbf0e70, 0x0eb50a40, 3, arm_VCMP_EQ_F32, 0x70108011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_fp_0}}, // VCMP{E}<c>.F<32,64> <Sd,Dd>, #0.0 cond:4|1|1|1|0|1|D|1|1|0|1|0|1|Vd:4|1|0|1|sz|E|1|0|0|(0)|(0)|(0)|(0)
- {0x0fbf0e50, 0x0eb40a40, 4, arm_VCMP_EQ_F32, 0x70108011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sm_Dm}}, // VCMP{E}<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|1|0|0|Vd:4|1|0|1|sz|E|1|M|0|Vm:4
- {0x0fbe0e50, 0x0eba0a40, 4, arm_VCVT_EQ_F32_FXS16, 0x801100107011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sd_Dd, arm_arg_fbits}}, // VCVT<c>.F<32,64>.FX<S,U><16,32> <Sd,Dd>, <Sd,Dd>, #<fbits> cond:4|1|1|1|0|1|D|1|1|1|0|1|U|Vd:4|1|0|1|sz|sx|1|i|0|imm4:4
- {0x0fbe0e50, 0x0ebe0a40, 4, arm_VCVT_EQ_FXS16_F32, 0x1001070108011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sd_Dd, arm_arg_fbits}}, // VCVT<c>.FX<S,U><16,32>.F<32,64> <Sd,Dd>, <Sd,Dd>, #<fbits> cond:4|1|1|1|0|1|D|1|1|1|1|1|U|Vd:4|1|0|1|sz|sx|1|i|0|imm4:4
- {0x0fbf0ed0, 0x0eb70ac0, 4, arm_VCVT_EQ_F64_F32, 0x8011c04, arm_instArgs{arm_arg_Dd_Sd, arm_arg_Sm_Dm}}, // VCVT<c>.<F64.F32,F32.F64> <Dd,Sd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|1|1|1|Vd:4|1|0|1|sz|1|1|M|0|Vm:4
- {0x0fbe0f50, 0x0eb20a40, 4, arm_VCVTB_EQ_F32_F16, 0x70110011c04, arm_instArgs{arm_arg_Sd, arm_arg_Sm}}, // VCVT<B,T><c>.<F32.F16,F16.F32> <Sd>, <Sm> cond:4|1|1|1|0|1|D|1|1|0|0|1|op|Vd:4|1|0|1|0|T|1|M|0|Vm:4
- {0x0fbf0e50, 0x0eb80a40, 4, arm_VCVT_EQ_F32_U32, 0x80107011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sm}}, // VCVT<c>.F<32,64>.<U,S>32 <Sd,Dd>, <Sm> cond:4|1|1|1|0|1|D|1|1|1|0|0|0|Vd:4|1|0|1|sz|op|1|M|0|Vm:4
- {0x0fbe0e50, 0x0ebc0a40, 4, arm_VCVTR_EQ_U32_F32, 0x701100108011c04, arm_instArgs{arm_arg_Sd, arm_arg_Sm_Dm}}, // VCVT<R,><c>.<U,S>32.F<32,64> <Sd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|1|1|0|signed|Vd:4|1|0|1|sz|op|1|M|0|Vm:4
- {0x0fb00e50, 0x0e800a00, 4, arm_VDIV_EQ_F32, 0x8011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sn_Dn, arm_arg_Sm_Dm}}, // VDIV<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|1|D|0|0|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4
- {0x0f300e00, 0x0d100a00, 4, arm_VLDR_EQ, 0x1c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_mem_R_pm_imm8at0_offset}}, // VLDR<c> <Sd,Dd>, [<Rn>{,#+/-<imm8>}] cond:4|1|1|0|1|U|D|0|1|Rn:4|Vd:4|1|0|1|sz|imm8:8
- {0x0ff00f7f, 0x0e000a10, 4, arm_VMOV_EQ, 0x1c04, arm_instArgs{arm_arg_Sn, arm_arg_R_12}}, // VMOV<c> <Sn>, <Rt> cond:4|1|1|1|0|0|0|0|0|Vn:4|Rt:4|1|0|1|0|N|0|0|1|0|0|0|0
- {0x0ff00f7f, 0x0e100a10, 4, arm_VMOV_EQ, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_Sn}}, // VMOV<c> <Rt>, <Sn> cond:4|1|1|1|0|0|0|0|1|Vn:4|Rt:4|1|0|1|0|N|0|0|1|0|0|0|0
- {0x0fd00f7f, 0x0e100b10, 4, arm_VMOV_EQ_32, 0x1c04, arm_instArgs{arm_arg_R_12, arm_arg_Dn_half}}, // VMOV<c>.32 <Rt>, <Dn[x]> cond:4|1|1|1|0|0|0|opc1|1|Vn:4|Rt:4|1|0|1|1|N|0|0|1|0|0|0|0
- {0x0fd00f7f, 0x0e000b10, 4, arm_VMOV_EQ_32, 0x1c04, arm_instArgs{arm_arg_Dn_half, arm_arg_R_12}}, // VMOV<c>.32 <Dd[x]>, <Rt> cond:4|1|1|1|0|0|0|opc1|0|Vd:4|Rt:4|1|0|1|1|D|0|0|1|0|0|0|0
- {0x0fb00ef0, 0x0eb00a00, 4, arm_VMOV_EQ_F32, 0x8011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_imm_vfp}}, // VMOV<c>.F<32,64> <Sd,Dd>, #<imm_vfp> cond:4|1|1|1|0|1|D|1|1|imm4H:4|Vd:4|1|0|1|sz|0|0|0|0|imm4L:4
- {0x0fbf0ed0, 0x0eb00a40, 4, arm_VMOV_EQ_F32, 0x8011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sm_Dm}}, // VMOV<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|0|Vd:4|1|0|1|sz|0|1|M|0|Vm:4
- {0x0fff0fff, 0x0ef10a10, 4, arm_VMRS_EQ, 0x1c04, arm_instArgs{arm_arg_R_12_nzcv, arm_arg_FPSCR}}, // VMRS<c> <Rt_nzcv>, FPSCR cond:4|1|1|1|0|1|1|1|1|0|0|0|1|Rt:4|1|0|1|0|0|0|0|1|0|0|0|0
- {0x0fff0fff, 0x0ee10a10, 4, arm_VMSR_EQ, 0x1c04, arm_instArgs{arm_arg_FPSCR, arm_arg_R_12}}, // VMSR<c> FPSCR, <Rt> cond:4|1|1|1|0|1|1|1|0|0|0|0|1|Rt:4|1|0|1|0|0|0|0|1|0|0|0|0
- {0x0fb00e50, 0x0e200a00, 4, arm_VMUL_EQ_F32, 0x8011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sn_Dn, arm_arg_Sm_Dm}}, // VMUL<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|0|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4
- {0x0fbf0ed0, 0x0eb10a40, 4, arm_VNEG_EQ_F32, 0x8011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sm_Dm}}, // VNEG<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|1|Vd:4|1|0|1|sz|0|1|M|0|Vm:4
- {0x0fb00e10, 0x0e100a00, 4, arm_VNMLS_EQ_F32, 0x60108011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sn_Dn, arm_arg_Sm_Dm}}, // VN<MLS,MLA><c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|0|1|Vn:4|Vd:4|1|0|1|sz|N|op|M|0|Vm:4
- {0x0fb00e50, 0x0e200a40, 4, arm_VNMUL_EQ_F32, 0x8011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sn_Dn, arm_arg_Sm_Dm}}, // VNMUL<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|0|Vn:4|Vd:4|1|0|1|sz|N|1|M|0|Vm:4
- {0x0fbf0ed0, 0x0eb10ac0, 4, arm_VSQRT_EQ_F32, 0x8011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sm_Dm}}, // VSQRT<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|1|Vd:4|1|0|1|sz|1|1|M|0|Vm:4
- {0x0f300e00, 0x0d000a00, 4, arm_VSTR_EQ, 0x1c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_mem_R_pm_imm8at0_offset}}, // VSTR<c> <Sd,Dd>, [<Rn>{,#+/-<imm8>}] cond:4|1|1|0|1|U|D|0|0|Rn:4|Vd:4|1|0|1|sz|imm8:8
- {0x0fb00e50, 0x0e300a40, 4, arm_VSUB_EQ_F32, 0x8011c04, arm_instArgs{arm_arg_Sd_Dd, arm_arg_Sn_Dn, arm_arg_Sm_Dm}}, // VSUB<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|1|Vn:4|Vd:4|1|0|1|sz|N|1|M|0|Vm:4
- {0x0fffffff, 0x0320f002, 4, arm_WFE_EQ, 0x1c04, arm_instArgs{}}, // WFE<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|0
- {0x0fff00ff, 0x0320f002, 3, arm_WFE_EQ, 0x1c04, arm_instArgs{}}, // WFE<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|0
- {0x0fffffff, 0x0320f003, 4, arm_WFI_EQ, 0x1c04, arm_instArgs{}}, // WFI<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|1
- {0x0fff00ff, 0x0320f003, 3, arm_WFI_EQ, 0x1c04, arm_instArgs{}}, // WFI<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|1
- {0x0fffffff, 0x0320f001, 4, arm_YIELD_EQ, 0x1c04, arm_instArgs{}}, // YIELD<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|1
- {0x0fff00ff, 0x0320f001, 3, arm_YIELD_EQ, 0x1c04, arm_instArgs{}}, // YIELD<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|1
- {0xffffffff, 0xf7fabcfd, 4, arm_UNDEF, 0x0, arm_instArgs{}}, // UNDEF 1|1|1|1|0|1|1|1|1|1|1|1|1|0|1|0|1|0|1|1|1|1|0|0|1|1|1|1|1|1|0|1
-}
diff --git a/src/cmd/objdump/elf.go b/src/cmd/objdump/elf.go
deleted file mode 100644
index 906e90353..000000000
--- a/src/cmd/objdump/elf.go
+++ /dev/null
@@ -1,65 +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.
-
-// Parsing of ELF executables (Linux, FreeBSD, and so on).
-
-package main
-
-import (
- "debug/elf"
- "os"
-)
-
-func elfSymbols(f *os.File) (syms []Sym, goarch string) {
- p, err := elf.NewFile(f)
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return
- }
-
- elfSyms, err := p.Symbols()
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return
- }
-
- switch p.Machine {
- case elf.EM_X86_64:
- goarch = "amd64"
- case elf.EM_386:
- goarch = "386"
- case elf.EM_ARM:
- goarch = "arm"
- }
-
- for _, s := range elfSyms {
- sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'}
- switch s.Section {
- case elf.SHN_UNDEF:
- sym.Code = 'U'
- case elf.SHN_COMMON:
- sym.Code = 'B'
- default:
- i := int(s.Section)
- if i < 0 || i >= len(p.Sections) {
- break
- }
- sect := p.Sections[i]
- switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) {
- case elf.SHF_ALLOC | elf.SHF_EXECINSTR:
- sym.Code = 'T'
- case elf.SHF_ALLOC:
- sym.Code = 'R'
- case elf.SHF_ALLOC | elf.SHF_WRITE:
- sym.Code = 'D'
- }
- }
- if elf.ST_BIND(s.Info) == elf.STB_LOCAL {
- sym.Code += 'a' - 'A'
- }
- syms = append(syms, sym)
- }
-
- return
-}
diff --git a/src/cmd/objdump/macho.go b/src/cmd/objdump/macho.go
deleted file mode 100644
index 6e0ad223d..000000000
--- a/src/cmd/objdump/macho.go
+++ /dev/null
@@ -1,77 +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.
-
-// Parsing of Mach-O executables (OS X).
-
-package main
-
-import (
- "debug/macho"
- "os"
- "sort"
-)
-
-func machoSymbols(f *os.File) (syms []Sym, goarch string) {
- p, err := macho.NewFile(f)
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return
- }
-
- if p.Symtab == nil {
- errorf("%s: no symbol table", f.Name())
- return
- }
-
- switch p.Cpu {
- case macho.Cpu386:
- goarch = "386"
- case macho.CpuAmd64:
- goarch = "amd64"
- case macho.CpuArm:
- goarch = "arm"
- }
-
- // Build sorted list of addresses of all symbols.
- // We infer the size of a symbol by looking at where the next symbol begins.
- var addrs []uint64
- for _, s := range p.Symtab.Syms {
- addrs = append(addrs, s.Value)
- }
- sort.Sort(uint64s(addrs))
-
- for _, s := range p.Symtab.Syms {
- sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'}
- i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value })
- if i < len(addrs) {
- sym.Size = int64(addrs[i] - s.Value)
- }
- if s.Sect == 0 {
- sym.Code = 'U'
- } else if int(s.Sect) <= len(p.Sections) {
- sect := p.Sections[s.Sect-1]
- switch sect.Seg {
- case "__TEXT":
- sym.Code = 'R'
- case "__DATA":
- sym.Code = 'D'
- }
- switch sect.Seg + " " + sect.Name {
- case "__TEXT __text":
- sym.Code = 'T'
- case "__DATA __bss", "__DATA __noptrbss":
- sym.Code = 'B'
- }
- }
- syms = append(syms, sym)
- }
-
- return
-}
-
-type uint64s []uint64
-
-func (x uint64s) Len() int { return len(x) }
-func (x uint64s) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
-func (x uint64s) Less(i, j int) bool { return x[i] < x[j] }
diff --git a/src/cmd/objdump/main.go b/src/cmd/objdump/main.go
index ade54366e..708a85370 100644
--- a/src/cmd/objdump/main.go
+++ b/src/cmd/objdump/main.go
@@ -29,30 +29,18 @@
// Each stanza gives the disassembly for a contiguous range of addresses
// all mapped to the same original source file and line number.
// This mode is intended for use by pprof.
-//
-// The ARM disassembler is missing (golang.org/issue/7452) but will be added
-// before the Go 1.3 release.
package main
import (
- "bufio"
- "bytes"
- "debug/elf"
- "debug/gosym"
- "debug/macho"
- "debug/pe"
- "debug/plan9obj"
- "encoding/binary"
"flag"
"fmt"
- "io"
"log"
"os"
"regexp"
- "sort"
"strconv"
"strings"
- "text/tabwriter"
+
+ "cmd/internal/objfile"
)
var symregexp = flag.String("s", "", "only dump symbols matching this regexp")
@@ -85,435 +73,35 @@ func main() {
symRE = re
}
- f, err := os.Open(flag.Arg(0))
+ f, err := objfile.Open(flag.Arg(0))
if err != nil {
log.Fatal(err)
}
- textStart, textData, symtab, pclntab, err := loadTables(f)
- if err != nil {
- log.Fatalf("reading %s: %v", flag.Arg(0), err)
- }
-
- syms, goarch, err := loadSymbols(f)
- if err != nil {
- log.Fatalf("reading %s: %v", flag.Arg(0), err)
- }
-
- // Filter out section symbols, overwriting syms in place.
- keep := syms[:0]
- for _, sym := range syms {
- switch sym.Name {
- case "text", "_text", "etext", "_etext":
- // drop
- default:
- keep = append(keep, sym)
- }
- }
- syms = keep
-
- disasm := disasms[goarch]
- if disasm == nil {
- log.Fatalf("reading %s: unknown architecture", flag.Arg(0))
- }
-
- lookup := func(addr uint64) (string, uint64) {
- i := sort.Search(len(syms), func(i int) bool { return syms[i].Addr > addr })
- if i > 0 {
- s := syms[i-1]
- if s.Addr <= addr && addr < s.Addr+uint64(s.Size) && s.Name != "etext" && s.Name != "_etext" {
- return s.Name, s.Addr
- }
- }
- return "", 0
- }
-
- pcln := gosym.NewLineTable(pclntab, textStart)
- tab, err := gosym.NewTable(symtab, pcln)
- if err != nil {
- log.Fatalf("reading %s: %v", flag.Arg(0), err)
- }
-
- if flag.NArg() == 1 {
- // disassembly of entire object - our format
- dump(tab, lookup, disasm, goarch, syms, textData, textStart)
- os.Exit(exitCode)
- }
-
- // disassembly of specific piece of object - gnu objdump format for pprof
- gnuDump(tab, lookup, disasm, textData, textStart)
- os.Exit(exitCode)
-}
-
-// base returns the final element in the path.
-// It works on both Windows and Unix paths.
-func base(path string) string {
- path = path[strings.LastIndex(path, "/")+1:]
- path = path[strings.LastIndex(path, `\`)+1:]
- return path
-}
-
-func dump(tab *gosym.Table, lookup lookupFunc, disasm disasmFunc, goarch string, syms []Sym, textData []byte, textStart uint64) {
- stdout := bufio.NewWriter(os.Stdout)
- defer stdout.Flush()
-
- printed := false
- for _, sym := range syms {
- if sym.Code != 'T' || sym.Size == 0 || sym.Name == "_text" || sym.Name == "text" || sym.Addr < textStart || symRE != nil && !symRE.MatchString(sym.Name) {
- continue
- }
- if sym.Addr >= textStart+uint64(len(textData)) || sym.Addr+uint64(sym.Size) > textStart+uint64(len(textData)) {
- break
- }
- if printed {
- fmt.Fprintf(stdout, "\n")
- } else {
- printed = true
- }
- file, _, _ := tab.PCToLine(sym.Addr)
- fmt.Fprintf(stdout, "TEXT %s(SB) %s\n", sym.Name, file)
- tw := tabwriter.NewWriter(stdout, 1, 8, 1, '\t', 0)
- start := sym.Addr
- end := sym.Addr + uint64(sym.Size)
- for pc := start; pc < end; {
- i := pc - textStart
- text, size := disasm(textData[i:end-textStart], pc, lookup)
- file, line, _ := tab.PCToLine(pc)
-
- // ARM is word-based, so show actual word hex, not byte hex.
- // Since ARM is little endian, they're different.
- if goarch == "arm" && size == 4 {
- fmt.Fprintf(tw, "\t%s:%d\t%#x\t%08x\t%s\n", base(file), line, pc, binary.LittleEndian.Uint32(textData[i:i+uint64(size)]), text)
- } else {
- fmt.Fprintf(tw, "\t%s:%d\t%#x\t%x\t%s\n", base(file), line, pc, textData[i:i+uint64(size)], text)
- }
- pc += uint64(size)
- }
- tw.Flush()
- }
-}
-
-func disasm_386(code []byte, pc uint64, lookup lookupFunc) (string, int) {
- return disasm_x86(code, pc, lookup, 32)
-}
-
-func disasm_amd64(code []byte, pc uint64, lookup lookupFunc) (string, int) {
- return disasm_x86(code, pc, lookup, 64)
-}
-
-func disasm_x86(code []byte, pc uint64, lookup lookupFunc, arch int) (string, int) {
- inst, err := x86_Decode(code, 64)
- var text string
- size := inst.Len
- if err != nil || size == 0 || inst.Op == 0 {
- size = 1
- text = "?"
- } else {
- text = x86_plan9Syntax(inst, pc, lookup)
- }
- return text, size
-}
-
-type textReader struct {
- code []byte
- pc uint64
-}
-
-func (r textReader) ReadAt(data []byte, off int64) (n int, err error) {
- if off < 0 || uint64(off) < r.pc {
- return 0, io.EOF
- }
- d := uint64(off) - r.pc
- if d >= uint64(len(r.code)) {
- return 0, io.EOF
- }
- n = copy(data, r.code[d:])
- if n < len(data) {
- err = io.ErrUnexpectedEOF
- }
- return
-}
-
-func disasm_arm(code []byte, pc uint64, lookup lookupFunc) (string, int) {
- inst, err := arm_Decode(code, arm_ModeARM)
- var text string
- size := inst.Len
- if err != nil || size == 0 || inst.Op == 0 {
- size = 4
- text = "?"
- } else {
- text = arm_plan9Syntax(inst, pc, lookup, textReader{code, pc})
- }
- return text, size
-}
-
-var disasms = map[string]disasmFunc{
- "386": disasm_386,
- "amd64": disasm_amd64,
- "arm": disasm_arm,
-}
-
-func gnuDump(tab *gosym.Table, lookup lookupFunc, disasm disasmFunc, textData []byte, textStart uint64) {
- start, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(1), "0x"), 16, 64)
+ dis, err := f.Disasm()
if err != nil {
- log.Fatalf("invalid start PC: %v", err)
- }
- end, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(2), "0x"), 16, 64)
- if err != nil {
- log.Fatalf("invalid end PC: %v", err)
- }
- if start < textStart {
- start = textStart
- }
- if end < start {
- end = start
- }
- if end > textStart+uint64(len(textData)) {
- end = textStart + uint64(len(textData))
- }
-
- stdout := bufio.NewWriter(os.Stdout)
- defer stdout.Flush()
-
- // For now, find spans of same PC/line/fn and
- // emit them as having dummy instructions.
- var (
- spanPC uint64
- spanFile string
- spanLine int
- spanFn *gosym.Func
- )
-
- flush := func(endPC uint64) {
- if spanPC == 0 {
- return
- }
- fmt.Fprintf(stdout, "%s:%d\n", spanFile, spanLine)
- for pc := spanPC; pc < endPC; {
- text, size := disasm(textData[pc-textStart:], pc, lookup)
- fmt.Fprintf(stdout, " %x: %s\n", pc, text)
- pc += uint64(size)
- }
- spanPC = 0
- }
-
- for pc := start; pc < end; pc++ {
- file, line, fn := tab.PCToLine(pc)
- if file != spanFile || line != spanLine || fn != spanFn {
- flush(pc)
- spanPC, spanFile, spanLine, spanFn = pc, file, line, fn
- }
- }
- flush(end)
-}
-
-func loadTables(f *os.File) (textStart uint64, textData, symtab, pclntab []byte, err error) {
- if obj, err := elf.NewFile(f); err == nil {
- if sect := obj.Section(".text"); sect != nil {
- textStart = sect.Addr
- textData, _ = sect.Data()
- }
- if sect := obj.Section(".gosymtab"); sect != nil {
- if symtab, err = sect.Data(); err != nil {
- return 0, nil, nil, nil, err
- }
- }
- if sect := obj.Section(".gopclntab"); sect != nil {
- if pclntab, err = sect.Data(); err != nil {
- return 0, nil, nil, nil, err
- }
- }
- return textStart, textData, symtab, pclntab, nil
+ log.Fatal("disassemble %s: %v", flag.Arg(0), err)
}
- if obj, err := macho.NewFile(f); err == nil {
- if sect := obj.Section("__text"); sect != nil {
- textStart = sect.Addr
- textData, _ = sect.Data()
- }
- if sect := obj.Section("__gosymtab"); sect != nil {
- if symtab, err = sect.Data(); err != nil {
- return 0, nil, nil, nil, err
- }
- }
- if sect := obj.Section("__gopclntab"); sect != nil {
- if pclntab, err = sect.Data(); err != nil {
- return 0, nil, nil, nil, err
- }
- }
- return textStart, textData, symtab, pclntab, nil
- }
-
- if obj, err := pe.NewFile(f); err == nil {
- var imageBase uint64
- switch oh := obj.OptionalHeader.(type) {
- case *pe.OptionalHeader32:
- imageBase = uint64(oh.ImageBase)
- case *pe.OptionalHeader64:
- imageBase = oh.ImageBase
- default:
- return 0, nil, nil, nil, fmt.Errorf("pe file format not recognized")
- }
- if sect := obj.Section(".text"); sect != nil {
- textStart = imageBase + uint64(sect.VirtualAddress)
- textData, _ = sect.Data()
- }
- if pclntab, err = loadPETable(obj, "pclntab", "epclntab"); err != nil {
- return 0, nil, nil, nil, err
- }
- if symtab, err = loadPETable(obj, "symtab", "esymtab"); err != nil {
- return 0, nil, nil, nil, err
- }
- return textStart, textData, symtab, pclntab, nil
- }
-
- if obj, err := plan9obj.NewFile(f); err == nil {
- sym, err := findPlan9Symbol(obj, "text")
+ switch flag.NArg() {
+ default:
+ usage()
+ case 1:
+ // disassembly of entire object
+ dis.Print(os.Stdout, symRE, 0, ^uint64(0))
+ os.Exit(0)
+
+ case 3:
+ // disassembly of PC range
+ start, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(1), "0x"), 16, 64)
if err != nil {
- return 0, nil, nil, nil, err
- }
- textStart = sym.Value
- if sect := obj.Section("text"); sect != nil {
- textData, _ = sect.Data()
- }
- if pclntab, err = loadPlan9Table(obj, "pclntab", "epclntab"); err != nil {
- return 0, nil, nil, nil, err
- }
- if symtab, err = loadPlan9Table(obj, "symtab", "esymtab"); err != nil {
- return 0, nil, nil, nil, err
- }
- return textStart, textData, symtab, pclntab, nil
- }
-
- return 0, nil, nil, nil, fmt.Errorf("unrecognized binary format")
-}
-
-func findPESymbol(f *pe.File, name string) (*pe.Symbol, error) {
- for _, s := range f.Symbols {
- if s.Name != name {
- continue
- }
- if s.SectionNumber <= 0 {
- return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber)
- }
- if len(f.Sections) < int(s.SectionNumber) {
- return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections))
- }
- return s, nil
- }
- return nil, fmt.Errorf("no %s symbol found", name)
-}
-
-func loadPETable(f *pe.File, sname, ename string) ([]byte, error) {
- ssym, err := findPESymbol(f, sname)
- if err != nil {
- return nil, err
- }
- esym, err := findPESymbol(f, ename)
- if err != nil {
- return nil, err
- }
- if ssym.SectionNumber != esym.SectionNumber {
- return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename)
- }
- sect := f.Sections[ssym.SectionNumber-1]
- data, err := sect.Data()
- if err != nil {
- return nil, err
- }
- return data[ssym.Value:esym.Value], nil
-}
-
-func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) {
- syms, err := f.Symbols()
- if err != nil {
- return nil, err
- }
- for _, s := range syms {
- if s.Name != name {
- continue
+ log.Fatalf("invalid start PC: %v", err)
}
- return &s, nil
- }
- return nil, fmt.Errorf("no %s symbol found", name)
-}
-
-func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) {
- ssym, err := findPlan9Symbol(f, sname)
- if err != nil {
- return nil, err
- }
- esym, err := findPlan9Symbol(f, ename)
- if err != nil {
- return nil, err
- }
- text, err := findPlan9Symbol(f, "text")
- if err != nil {
- return nil, err
- }
- sect := f.Section("text")
- if sect == nil {
- return nil, err
- }
- data, err := sect.Data()
- if err != nil {
- return nil, err
- }
- return data[ssym.Value-text.Value : esym.Value-text.Value], nil
-}
-
-// TODO(rsc): This code is taken from cmd/nm. Arrange some way to share the code.
-
-var exitCode = 0
-
-func errorf(format string, args ...interface{}) {
- log.Printf(format, args...)
- exitCode = 1
-}
-
-func loadSymbols(f *os.File) (syms []Sym, goarch string, err error) {
- f.Seek(0, 0)
- buf := make([]byte, 16)
- io.ReadFull(f, buf)
- f.Seek(0, 0)
-
- for _, p := range parsers {
- if bytes.HasPrefix(buf, p.prefix) {
- syms, goarch = p.parse(f)
- sort.Sort(byAddr(syms))
- return
+ end, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(2), "0x"), 16, 64)
+ if err != nil {
+ log.Fatalf("invalid end PC: %v", err)
}
+ dis.Print(os.Stdout, symRE, start, end)
+ os.Exit(0)
}
- err = fmt.Errorf("unknown file format")
- return
-}
-
-type Sym struct {
- Addr uint64
- Size int64
- Code rune
- Name string
- Type string
}
-
-var parsers = []struct {
- prefix []byte
- parse func(*os.File) ([]Sym, string)
-}{
- {[]byte("\x7FELF"), elfSymbols},
- {[]byte("\xFE\xED\xFA\xCE"), machoSymbols},
- {[]byte("\xFE\xED\xFA\xCF"), machoSymbols},
- {[]byte("\xCE\xFA\xED\xFE"), machoSymbols},
- {[]byte("\xCF\xFA\xED\xFE"), machoSymbols},
- {[]byte("MZ"), peSymbols},
- {[]byte("\x00\x00\x01\xEB"), plan9Symbols}, // 386
- {[]byte("\x00\x00\x04\x07"), plan9Symbols}, // mips
- {[]byte("\x00\x00\x06\x47"), plan9Symbols}, // arm
- {[]byte("\x00\x00\x8A\x97"), plan9Symbols}, // amd64
-}
-
-type byAddr []Sym
-
-func (x byAddr) Len() int { return len(x) }
-func (x byAddr) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
-func (x byAddr) Less(i, j int) bool { return x[i].Addr < x[j].Addr }
diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go
index 82311bb1f..2bb74663c 100644
--- a/src/cmd/objdump/objdump_test.go
+++ b/src/cmd/objdump/objdump_test.go
@@ -5,114 +5,19 @@
package main
import (
- "bufio"
- "bytes"
- "fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
- "strconv"
"strings"
"testing"
)
-func loadSyms(t *testing.T) map[string]string {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
- }
-
- cmd := exec.Command("go", "tool", "nm", os.Args[0])
- out, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("go tool nm %v: %v\n%s", os.Args[0], err, string(out))
- }
- syms := make(map[string]string)
- scanner := bufio.NewScanner(bytes.NewReader(out))
- for scanner.Scan() {
- f := strings.Fields(scanner.Text())
- if len(f) < 3 {
- continue
- }
- syms[f[2]] = f[0]
- }
- if err := scanner.Err(); err != nil {
- t.Fatalf("error reading symbols: %v", err)
- }
- return syms
-}
-
-func runObjDump(t *testing.T, exe, startaddr, endaddr string) (path, lineno string) {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
- }
-
- cmd := exec.Command(exe, os.Args[0], startaddr, endaddr)
- out, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("go tool objdump %v: %v\n%s", os.Args[0], err, string(out))
- }
- f := strings.Split(string(out), "\n")
- if len(f) < 1 {
- t.Fatal("objdump output must have at least one line")
- }
- pathAndLineNo := f[0]
- f = strings.Split(pathAndLineNo, ":")
- if runtime.GOOS == "windows" {
- switch len(f) {
- case 2:
- return f[0], f[1]
- case 3:
- return f[0] + ":" + f[1], f[2]
- default:
- t.Fatalf("no line number found in %q", pathAndLineNo)
- }
- }
- if len(f) != 2 {
- t.Fatalf("no line number found in %q", pathAndLineNo)
- }
- return f[0], f[1]
-}
-
-func testObjDump(t *testing.T, exe, startaddr, endaddr string, line int) {
- srcPath, srcLineNo := runObjDump(t, exe, startaddr, endaddr)
- fi1, err := os.Stat("objdump_test.go")
- if err != nil {
- t.Fatalf("Stat failed: %v", err)
- }
- fi2, err := os.Stat(srcPath)
- if err != nil {
- t.Fatalf("Stat failed: %v", err)
- }
- if !os.SameFile(fi1, fi2) {
- t.Fatalf("objdump_test.go and %s are not same file", srcPath)
- }
- if srcLineNo != fmt.Sprint(line) {
- t.Fatalf("line number = %v; want %d", srcLineNo, line)
- }
-}
-
-func TestObjDump(t *testing.T) {
- _, _, line, _ := runtime.Caller(0)
- syms := loadSyms(t)
-
- tmp, exe := buildObjdump(t)
- defer os.RemoveAll(tmp)
-
- startaddr := syms["cmd/objdump.TestObjDump"]
- addr, err := strconv.ParseUint(startaddr, 16, 64)
- if err != nil {
- t.Fatalf("invalid start address %v: %v", startaddr, err)
- }
- endaddr := fmt.Sprintf("%x", addr+10)
- testObjDump(t, exe, startaddr, endaddr, line-1)
- testObjDump(t, exe, "0x"+startaddr, "0x"+endaddr, line-1)
-}
-
func buildObjdump(t *testing.T) (tmp, exe string) {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
+ switch runtime.GOOS {
+ case "android", "nacl":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
tmp, err := ioutil.TempDir("", "TestObjDump")
@@ -140,7 +45,7 @@ var x86Need = []string{
var armNeed = []string{
"fmthello.go:6",
"TEXT main.main(SB)",
- "B.LS main.main(SB)",
+ //"B.LS main.main(SB)", // TODO(rsc): restore; golang.org/issue/9021
"BL fmt.Println(SB)",
"RET",
}
@@ -154,12 +59,15 @@ var armNeed = []string{
// binary for the current system (only) and test that objdump
// can handle that one.
-func TestDisasm(t *testing.T) {
+func testDisasm(t *testing.T, flags ...string) {
tmp, exe := buildObjdump(t)
defer os.RemoveAll(tmp)
hello := filepath.Join(tmp, "hello.exe")
- out, err := exec.Command("go", "build", "-o", hello, "testdata/fmthello.go").CombinedOutput()
+ args := []string{"build", "-o", hello}
+ args = append(args, flags...)
+ args = append(args, "testdata/fmthello.go")
+ out, err := exec.Command("go", args...).CombinedOutput()
if err != nil {
t.Fatalf("go build fmthello.go: %v\n%s", err, out)
}
@@ -191,3 +99,15 @@ func TestDisasm(t *testing.T) {
t.Logf("full disassembly:\n%s", text)
}
}
+
+func TestDisasm(t *testing.T) {
+ testDisasm(t)
+}
+
+func TestDisasmExtld(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9", "windows":
+ t.Skipf("skipping on %s", runtime.GOOS)
+ }
+ testDisasm(t, "-ldflags=-linkmode=external")
+}
diff --git a/src/cmd/objdump/pe.go b/src/cmd/objdump/pe.go
deleted file mode 100644
index 38190095a..000000000
--- a/src/cmd/objdump/pe.go
+++ /dev/null
@@ -1,99 +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.
-
-// Parsing of PE executables (Microsoft Windows).
-
-package main
-
-import (
- "debug/pe"
- "os"
- "sort"
-)
-
-func peSymbols(f *os.File) (syms []Sym, goarch string) {
- p, err := pe.NewFile(f)
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return
- }
-
- // Build sorted list of addresses of all symbols.
- // We infer the size of a symbol by looking at where the next symbol begins.
- var addrs []uint64
-
- var imageBase uint64
- switch oh := p.OptionalHeader.(type) {
- case *pe.OptionalHeader32:
- imageBase = uint64(oh.ImageBase)
- goarch = "386"
- case *pe.OptionalHeader64:
- imageBase = oh.ImageBase
- goarch = "amd64"
- default:
- errorf("parsing %s: file format not recognized", f.Name())
- return
- }
-
- for _, s := range p.Symbols {
- const (
- N_UNDEF = 0 // An undefined (extern) symbol
- N_ABS = -1 // An absolute symbol (e_value is a constant, not an address)
- N_DEBUG = -2 // A debugging symbol
- )
- sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'}
- switch s.SectionNumber {
- case N_UNDEF:
- sym.Code = 'U'
- case N_ABS:
- sym.Code = 'C'
- case N_DEBUG:
- sym.Code = '?'
- default:
- if s.SectionNumber < 0 {
- errorf("parsing %s: invalid section number %d", f.Name(), s.SectionNumber)
- return
- }
- if len(p.Sections) < int(s.SectionNumber) {
- errorf("parsing %s: section number %d is large then max %d", f.Name(), s.SectionNumber, len(p.Sections))
- return
- }
- sect := p.Sections[s.SectionNumber-1]
- const (
- text = 0x20
- data = 0x40
- bss = 0x80
- permX = 0x20000000
- permR = 0x40000000
- permW = 0x80000000
- )
- ch := sect.Characteristics
- switch {
- case ch&text != 0:
- sym.Code = 'T'
- case ch&data != 0:
- if ch&permW == 0 {
- sym.Code = 'R'
- } else {
- sym.Code = 'D'
- }
- case ch&bss != 0:
- sym.Code = 'B'
- }
- sym.Addr += imageBase + uint64(sect.VirtualAddress)
- }
- syms = append(syms, sym)
- addrs = append(addrs, sym.Addr)
- }
-
- sort.Sort(uint64s(addrs))
- for i := range syms {
- j := sort.Search(len(addrs), func(x int) bool { return addrs[x] > syms[i].Addr })
- if j < len(addrs) {
- syms[i].Size = int64(addrs[j] - syms[i].Addr)
- }
- }
-
- return
-}
diff --git a/src/cmd/objdump/plan9obj.go b/src/cmd/objdump/plan9obj.go
deleted file mode 100644
index 34462f31c..000000000
--- a/src/cmd/objdump/plan9obj.go
+++ /dev/null
@@ -1,63 +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.
-
-// Parsing of Plan 9 a.out executables.
-
-package main
-
-import (
- "debug/plan9obj"
- "os"
- "sort"
-)
-
-var validSymType = map[rune]bool{
- 'T': true,
- 't': true,
- 'D': true,
- 'd': true,
- 'B': true,
- 'b': true,
-}
-
-func plan9Symbols(f *os.File) (syms []Sym, goarch string) {
- p, err := plan9obj.NewFile(f)
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return
- }
-
- plan9Syms, err := p.Symbols()
- if err != nil {
- errorf("parsing %s: %v", f.Name(), err)
- return
- }
-
- goarch = "386"
-
- // Build sorted list of addresses of all symbols.
- // We infer the size of a symbol by looking at where the next symbol begins.
- var addrs []uint64
- for _, s := range plan9Syms {
- if !validSymType[s.Type] {
- continue
- }
- addrs = append(addrs, s.Value)
- }
- sort.Sort(uint64s(addrs))
-
- for _, s := range plan9Syms {
- if !validSymType[s.Type] {
- continue
- }
- sym := Sym{Addr: s.Value, Name: s.Name, Code: rune(s.Type)}
- i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value })
- if i < len(addrs) {
- sym.Size = int64(addrs[i] - s.Value)
- }
- syms = append(syms, sym)
- }
-
- return
-}
diff --git a/src/cmd/objdump/x86.go b/src/cmd/objdump/x86.go
deleted file mode 100644
index 8e741331f..000000000
--- a/src/cmd/objdump/x86.go
+++ /dev/null
@@ -1,13800 +0,0 @@
-// DO NOT EDIT. Generated by code.google.com/p/rsc/cmd/bundle
-// bundle -p main -x x86_ rsc.io/x86/x86asm
-
-/* decode.go */
-
-// 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 main
-
-import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "runtime"
- "strings"
-)
-
-// 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 x86_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 x86_decodeOp uint16
-
-const (
- x86_xFail x86_decodeOp = iota // invalid instruction (return)
- x86_xMatch // completed match
- x86_xJump // jump to pc
-
- x86_xCondByte // switch on instruction byte value
- x86_xCondSlashR // read and switch on instruction /r value
- x86_xCondPrefix // switch on presence of instruction prefix
- x86_xCondIs64 // switch on 64-bit processor mode
- x86_xCondDataSize // switch on operand size
- x86_xCondAddrSize // switch on address size
- x86_xCondIsMem // switch on memory vs register argument
-
- x86_xSetOp // set instruction opcode
-
- x86_xReadSlashR // read /r
- x86_xReadIb // read ib
- x86_xReadIw // read iw
- x86_xReadId // read id
- x86_xReadIo // read io
- x86_xReadCb // read cb
- x86_xReadCw // read cw
- x86_xReadCd // read cd
- x86_xReadCp // read cp
- x86_xReadCm // read cm
-
- x86_xArg1 // arg 1
- x86_xArg3 // arg 3
- x86_xArgAL // arg AL
- x86_xArgAX // arg AX
- x86_xArgCL // arg CL
- x86_xArgCR0dashCR7 // arg CR0-CR7
- x86_xArgCS // arg CS
- x86_xArgDR0dashDR7 // arg DR0-DR7
- x86_xArgDS // arg DS
- x86_xArgDX // arg DX
- x86_xArgEAX // arg EAX
- x86_xArgEDX // arg EDX
- x86_xArgES // arg ES
- x86_xArgFS // arg FS
- x86_xArgGS // arg GS
- x86_xArgImm16 // arg imm16
- x86_xArgImm32 // arg imm32
- x86_xArgImm64 // arg imm64
- x86_xArgImm8 // arg imm8
- x86_xArgImm8u // arg imm8 but record as unsigned
- x86_xArgImm16u // arg imm8 but record as unsigned
- x86_xArgM // arg m
- x86_xArgM128 // arg m128
- x86_xArgM1428byte // arg m14/28byte
- x86_xArgM16 // arg m16
- x86_xArgM16and16 // arg m16&16
- x86_xArgM16and32 // arg m16&32
- x86_xArgM16and64 // arg m16&64
- x86_xArgM16colon16 // arg m16:16
- x86_xArgM16colon32 // arg m16:32
- x86_xArgM16colon64 // arg m16:64
- x86_xArgM16int // arg m16int
- x86_xArgM2byte // arg m2byte
- x86_xArgM32 // arg m32
- x86_xArgM32and32 // arg m32&32
- x86_xArgM32fp // arg m32fp
- x86_xArgM32int // arg m32int
- x86_xArgM512byte // arg m512byte
- x86_xArgM64 // arg m64
- x86_xArgM64fp // arg m64fp
- x86_xArgM64int // arg m64int
- x86_xArgM8 // arg m8
- x86_xArgM80bcd // arg m80bcd
- x86_xArgM80dec // arg m80dec
- x86_xArgM80fp // arg m80fp
- x86_xArgM94108byte // arg m94/108byte
- x86_xArgMm // arg mm
- x86_xArgMm1 // arg mm1
- x86_xArgMm2 // arg mm2
- x86_xArgMm2M64 // arg mm2/m64
- x86_xArgMmM32 // arg mm/m32
- x86_xArgMmM64 // arg mm/m64
- x86_xArgMem // arg mem
- x86_xArgMoffs16 // arg moffs16
- x86_xArgMoffs32 // arg moffs32
- x86_xArgMoffs64 // arg moffs64
- x86_xArgMoffs8 // arg moffs8
- x86_xArgPtr16colon16 // arg ptr16:16
- x86_xArgPtr16colon32 // arg ptr16:32
- x86_xArgR16 // arg r16
- x86_xArgR16op // arg r16 with +rw in opcode
- x86_xArgR32 // arg r32
- x86_xArgR32M16 // arg r32/m16
- x86_xArgR32M8 // arg r32/m8
- x86_xArgR32op // arg r32 with +rd in opcode
- x86_xArgR64 // arg r64
- x86_xArgR64M16 // arg r64/m16
- x86_xArgR64op // arg r64 with +rd in opcode
- x86_xArgR8 // arg r8
- x86_xArgR8op // arg r8 with +rb in opcode
- x86_xArgRAX // arg RAX
- x86_xArgRDX // arg RDX
- x86_xArgRM // arg r/m
- x86_xArgRM16 // arg r/m16
- x86_xArgRM32 // arg r/m32
- x86_xArgRM64 // arg r/m64
- x86_xArgRM8 // arg r/m8
- x86_xArgReg // arg reg
- x86_xArgRegM16 // arg reg/m16
- x86_xArgRegM32 // arg reg/m32
- x86_xArgRegM8 // arg reg/m8
- x86_xArgRel16 // arg rel16
- x86_xArgRel32 // arg rel32
- x86_xArgRel8 // arg rel8
- x86_xArgSS // arg SS
- x86_xArgST // arg ST, aka ST(0)
- x86_xArgSTi // arg ST(i) with +i in opcode
- x86_xArgSreg // arg Sreg
- x86_xArgTR0dashTR7 // arg TR0-TR7
- x86_xArgXmm // arg xmm
- x86_xArgXMM0 // arg <XMM0>
- x86_xArgXmm1 // arg xmm1
- x86_xArgXmm2 // arg xmm2
- x86_xArgXmm2M128 // arg xmm2/m128
- x86_xArgXmm2M16 // arg xmm2/m16
- x86_xArgXmm2M32 // arg xmm2/m32
- x86_xArgXmm2M64 // arg xmm2/m64
- x86_xArgXmmM128 // arg xmm/m128
- x86_xArgXmmM32 // arg xmm/m32
- x86_xArgXmmM64 // arg xmm/m64
- x86_xArgRmf16 // arg r/m16 but force mod=3
- x86_xArgRmf32 // arg r/m32 but force mod=3
- x86_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 x86_instPrefix(b byte, mode int) (x86_Inst, error) {
- // When tracing it is useful to see what called instPrefix to report an error.
- if x86_trace {
- _, file, line, _ := runtime.Caller(1)
- fmt.Printf("%s:%d\n", file, line)
- }
- p := x86_Prefix(b)
- switch p {
- case x86_PrefixDataSize:
- if mode == 16 {
- p = x86_PrefixData32
- } else {
- p = x86_PrefixData16
- }
- case x86_PrefixAddrSize:
- if mode == 32 {
- p = x86_PrefixAddr16
- } else {
- p = x86_PrefixAddr32
- }
- }
- // Note: using composite literal with Prefix key confuses 'bundle' tool.
- inst := x86_Inst{Len: 1}
- inst.Prefix = x86_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 x86_truncated(src []byte, mode int) (x86_Inst, error) {
- // return Inst{}, len(src), ErrTruncated
- return x86_instPrefix(src[0], mode) // too long
-}
-
-// These are the errors returned by Decode.
-var (
- x86_ErrInvalidMode = errors.New("invalid x86 mode in Decode")
- x86_ErrTruncated = errors.New("truncated instruction")
- x86_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 x86_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 x86_Decode(src []byte, mode int) (inst x86_Inst, err error) {
- return x86_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 x86_decode1(src []byte, mode int, gnuCompat bool) (x86_Inst, error) {
- switch mode {
- case 16, 32, 64:
- // ok
- // TODO(rsc): 64-bit mode not tested, probably not working.
- default:
- return x86_Inst{}, x86_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 x86_Prefix // rex byte if present (or 0)
- rexUsed x86_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 x86_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 x86_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 := x86_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] |= x86_PrefixIgnored
- }
- lockIndex = pos
- case 0xF2, 0xF3:
- if repIndex >= 0 {
- inst.Prefix[repIndex] |= x86_PrefixIgnored
- }
- repIndex = pos
-
- // Group 2 - segment override / branch hints
- case 0x26, 0x2E, 0x36, 0x3E:
- if mode == 64 {
- p |= x86_PrefixIgnored
- break
- }
- fallthrough
- case 0x64, 0x65:
- if segIndex >= 0 {
- inst.Prefix[segIndex] |= x86_PrefixIgnored
- }
- segIndex = pos
-
- // Group 3 - operand size override
- case 0x66:
- if mode == 16 {
- dataMode = 32
- p = x86_PrefixData32
- } else {
- dataMode = 16
- p = x86_PrefixData16
- }
- if dataSizeIndex >= 0 {
- inst.Prefix[dataSizeIndex] |= x86_PrefixIgnored
- }
- dataSizeIndex = pos
-
- // Group 4 - address size override
- case 0x67:
- if mode == 32 {
- addrMode = 16
- p = x86_PrefixAddr16
- } else {
- addrMode = 32
- p = x86_PrefixAddr32
- }
- if addrSizeIndex >= 0 {
- inst.Prefix[addrSizeIndex] |= x86_PrefixIgnored
- }
- addrSizeIndex = pos
- }
-
- if pos >= len(inst.Prefix) {
- return x86_instPrefix(src[0], mode) // too long
- }
-
- inst.Prefix[pos] = p
- }
-
- // Read REX prefix.
- if pos < len(src) && mode == 64 && x86_Prefix(src[pos]).IsREX() {
- rex = x86_Prefix(src[pos])
- rexIndex = pos
- if pos >= len(inst.Prefix) {
- return x86_instPrefix(src[0], mode) // too long
- }
- inst.Prefix[pos] = rex
- pos++
- if rex&x86_PrefixREXW != 0 {
- dataMode = 64
- if dataSizeIndex >= 0 {
- inst.Prefix[dataSizeIndex] |= x86_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 x86_decoderCover == nil {
- x86_decoderCover = make([]bool, len(x86_decoder))
- }
-
- // Decode loop, executing decoder program.
- var oldPC, prevPC int
-Decode:
- for pc := 1; ; { // TODO uint
- oldPC = prevPC
- prevPC = pc
- if x86_trace {
- println("run", pc)
- }
- x := x86_decoder[pc]
- x86_decoderCover[pc] = true
- pc++
-
- // Read and decode ModR/M if needed by opcode.
- switch x86_decodeOp(x) {
- case x86_xCondSlashR, x86_xReadSlashR:
- if haveModrm {
- return x86_Inst{Len: pos}, x86_errInternal
- }
- haveModrm = true
- if pos >= len(src) {
- return x86_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&x86_PrefixREXR != 0 {
- rexUsed |= x86_PrefixREXR
- regop |= 8
- }
- if addrMode == 16 {
- // 16-bit modrm form
- if mod != 3 {
- haveMem = true
- mem = x86_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 x86_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 x86_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 x86_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&x86_PrefixREXB != 0 {
- rexUsed |= x86_PrefixREXB
- base |= 8
- }
- if rex&x86_PrefixREXX != 0 {
- rexUsed |= x86_PrefixREXX
- index |= 8
- }
-
- mem.Scale = 1 << uint(scale)
- if index == 4 {
- // no mem.Index
- } else {
- mem.Index = x86_baseRegForBits(addrMode) + x86_Reg(index)
- }
- if base&7 == 5 && mod == 0 {
- // no mem.Base
- } else {
- mem.Base = x86_baseRegForBits(addrMode) + x86_Reg(base)
- }
- } else {
- if rex&x86_PrefixREXB != 0 {
- rexUsed |= x86_PrefixREXB
- rm |= 8
- }
- if mod == 0 && rm&7 == 5 || rm&7 == 4 {
- // base omitted
- } else if mod != 3 {
- mem.Base = x86_baseRegForBits(addrMode) + x86_Reg(rm)
- }
- }
-
- // Consume disp32 if present.
- if mod == 0 && (rm&7 == 5 || haveSIB && base&7 == 5) || mod == 2 {
- if pos+4 > len(src) {
- return x86_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 x86_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 = x86_EIP
- } else {
- mem.Base = x86_RIP
- }
- }
- }
-
- if segIndex >= 0 {
- mem.Segment = x86_prefixToSegment(inst.Prefix[segIndex])
- }
- }
-
- // Execute single opcode.
- switch x86_decodeOp(x) {
- default:
- println("bad op", x, "at", pc-1, "from", oldPC)
- return x86_Inst{Len: pos}, x86_errInternal
-
- case x86_xFail:
- inst.Op = 0
- break Decode
-
- case x86_xMatch:
- break Decode
-
- case x86_xJump:
- pc = int(x86_decoder[pc])
-
- // Conditional branches.
-
- case x86_xCondByte:
- if pos >= len(src) {
- return x86_truncated(src, mode)
- }
- b := src[pos]
- n := int(x86_decoder[pc])
- pc++
- for i := 0; i < n; i++ {
- xb, xpc := x86_decoder[pc], int(x86_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 x86_decodeOp(x86_decoder[pc]) == x86_xJump {
- pc = int(x86_decoder[pc+1])
- }
- if x86_decodeOp(x86_decoder[pc]) == x86_xFail {
- pos++
- }
-
- case x86_xCondIs64:
- if mode == 64 {
- pc = int(x86_decoder[pc+1])
- } else {
- pc = int(x86_decoder[pc])
- }
-
- case x86_xCondIsMem:
- mem := haveMem
- if !haveModrm {
- if pos >= len(src) {
- return x86_instPrefix(src[0], mode) // too long
- }
- mem = src[pos]>>6 != 3
- }
- if mem {
- pc = int(x86_decoder[pc+1])
- } else {
- pc = int(x86_decoder[pc])
- }
-
- case x86_xCondDataSize:
- switch dataMode {
- case 16:
- if dataSizeIndex >= 0 {
- inst.Prefix[dataSizeIndex] |= x86_PrefixImplicit
- }
- pc = int(x86_decoder[pc])
- case 32:
- if dataSizeIndex >= 0 {
- inst.Prefix[dataSizeIndex] |= x86_PrefixImplicit
- }
- pc = int(x86_decoder[pc+1])
- case 64:
- rexUsed |= x86_PrefixREXW
- pc = int(x86_decoder[pc+2])
- }
-
- case x86_xCondAddrSize:
- switch addrMode {
- case 16:
- if addrSizeIndex >= 0 {
- inst.Prefix[addrSizeIndex] |= x86_PrefixImplicit
- }
- pc = int(x86_decoder[pc])
- case 32:
- if addrSizeIndex >= 0 {
- inst.Prefix[addrSizeIndex] |= x86_PrefixImplicit
- }
- pc = int(x86_decoder[pc+1])
- case 64:
- pc = int(x86_decoder[pc+2])
- }
-
- case x86_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(x86_decoder[pc])
- pc++
- sawF3 := false
- for j := 0; j < n; j++ {
- prefix := x86_Prefix(x86_decoder[pc+2*j])
- if prefix.IsREX() {
- rexUsed |= prefix
- if rex&prefix == prefix {
- pc = int(x86_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 x86_PrefixLOCK:
- if lockIndex >= 0 {
- inst.Prefix[lockIndex] |= x86_PrefixImplicit
- ok = true
- }
- case x86_PrefixREP, x86_PrefixREPN:
- if repIndex >= 0 && inst.Prefix[repIndex]&0xFF == prefix {
- inst.Prefix[repIndex] |= x86_PrefixImplicit
- ok = true
- }
- if gnuCompat && !ok && prefix == 0xF3 && repIndex >= 0 && (j+1 >= n || x86_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] |= x86_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] |= x86_PrefixImplicit
- ok = true
- }
- }
- }
- case x86_PrefixCS, x86_PrefixDS, x86_PrefixES, x86_PrefixFS, x86_PrefixGS, x86_PrefixSS:
- if segIndex >= 0 && inst.Prefix[segIndex]&0xFF == prefix {
- inst.Prefix[segIndex] |= x86_PrefixImplicit
- ok = true
- }
- case x86_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] |= x86_PrefixImplicit
- ok = true
- }
- case x86_PrefixAddrSize:
- if addrSizeIndex >= 0 {
- inst.Prefix[addrSizeIndex] |= x86_PrefixImplicit
- ok = true
- }
- }
- }
- if ok {
- pc = int(x86_decoder[pc+2*j+1])
- continue Decode
- }
- }
- inst.Op = 0
- break Decode
-
- case x86_xCondSlashR:
- pc = int(x86_decoder[pc+regop&7])
-
- // Input.
-
- case x86_xReadSlashR:
- // done above
-
- case x86_xReadIb:
- if pos >= len(src) {
- return x86_truncated(src, mode)
- }
- imm8 = int8(src[pos])
- pos++
-
- case x86_xReadIw:
- if pos+2 > len(src) {
- return x86_truncated(src, mode)
- }
- imm = int64(binary.LittleEndian.Uint16(src[pos:]))
- pos += 2
-
- case x86_xReadId:
- if pos+4 > len(src) {
- return x86_truncated(src, mode)
- }
- imm = int64(binary.LittleEndian.Uint32(src[pos:]))
- pos += 4
-
- case x86_xReadIo:
- if pos+8 > len(src) {
- return x86_truncated(src, mode)
- }
- imm = int64(binary.LittleEndian.Uint64(src[pos:]))
- pos += 8
-
- case x86_xReadCb:
- if pos >= len(src) {
- return x86_truncated(src, mode)
- }
- immc = int64(src[pos])
- pos++
-
- case x86_xReadCw:
- if pos+2 > len(src) {
- return x86_truncated(src, mode)
- }
- immc = int64(binary.LittleEndian.Uint16(src[pos:]))
- pos += 2
-
- case x86_xReadCm:
- if addrMode == 16 {
- if pos+2 > len(src) {
- return x86_truncated(src, mode)
- }
- immc = int64(binary.LittleEndian.Uint16(src[pos:]))
- pos += 2
- } else if addrMode == 32 {
- if pos+4 > len(src) {
- return x86_truncated(src, mode)
- }
- immc = int64(binary.LittleEndian.Uint32(src[pos:]))
- pos += 4
- } else {
- if pos+8 > len(src) {
- return x86_truncated(src, mode)
- }
- immc = int64(binary.LittleEndian.Uint64(src[pos:]))
- pos += 8
- }
- case x86_xReadCd:
- if pos+4 > len(src) {
- return x86_truncated(src, mode)
- }
- immc = int64(binary.LittleEndian.Uint32(src[pos:]))
- pos += 4
-
- case x86_xReadCp:
- if pos+6 > len(src) {
- return x86_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 x86_xSetOp:
- inst.Op = x86_Op(x86_decoder[pc])
- pc++
-
- case x86_xArg1,
- x86_xArg3,
- x86_xArgAL,
- x86_xArgAX,
- x86_xArgCL,
- x86_xArgCS,
- x86_xArgDS,
- x86_xArgDX,
- x86_xArgEAX,
- x86_xArgEDX,
- x86_xArgES,
- x86_xArgFS,
- x86_xArgGS,
- x86_xArgRAX,
- x86_xArgRDX,
- x86_xArgSS,
- x86_xArgST,
- x86_xArgXMM0:
- inst.Args[narg] = x86_fixedArg[x]
- narg++
-
- case x86_xArgImm8:
- inst.Args[narg] = x86_Imm(imm8)
- narg++
-
- case x86_xArgImm8u:
- inst.Args[narg] = x86_Imm(uint8(imm8))
- narg++
-
- case x86_xArgImm16:
- inst.Args[narg] = x86_Imm(int16(imm))
- narg++
-
- case x86_xArgImm16u:
- inst.Args[narg] = x86_Imm(uint16(imm))
- narg++
-
- case x86_xArgImm32:
- inst.Args[narg] = x86_Imm(int32(imm))
- narg++
-
- case x86_xArgImm64:
- inst.Args[narg] = x86_Imm(imm)
- narg++
-
- case x86_xArgM,
- x86_xArgM128,
- x86_xArgM1428byte,
- x86_xArgM16,
- x86_xArgM16and16,
- x86_xArgM16and32,
- x86_xArgM16and64,
- x86_xArgM16colon16,
- x86_xArgM16colon32,
- x86_xArgM16colon64,
- x86_xArgM16int,
- x86_xArgM2byte,
- x86_xArgM32,
- x86_xArgM32and32,
- x86_xArgM32fp,
- x86_xArgM32int,
- x86_xArgM512byte,
- x86_xArgM64,
- x86_xArgM64fp,
- x86_xArgM64int,
- x86_xArgM8,
- x86_xArgM80bcd,
- x86_xArgM80dec,
- x86_xArgM80fp,
- x86_xArgM94108byte,
- x86_xArgMem:
- if !haveMem {
- inst.Op = 0
- break Decode
- }
- inst.Args[narg] = mem
- inst.MemBytes = int(x86_memBytes[x86_decodeOp(x)])
- narg++
-
- case x86_xArgPtr16colon16:
- inst.Args[narg] = x86_Imm(immc >> 16)
- inst.Args[narg+1] = x86_Imm(immc & (1<<16 - 1))
- narg += 2
-
- case x86_xArgPtr16colon32:
- inst.Args[narg] = x86_Imm(immc >> 32)
- inst.Args[narg+1] = x86_Imm(immc & (1<<32 - 1))
- narg += 2
-
- case x86_xArgMoffs8, x86_xArgMoffs16, x86_xArgMoffs32, x86_xArgMoffs64:
- // TODO(rsc): Can address be 64 bits?
- mem = x86_Mem{Disp: int64(immc)}
- if segIndex >= 0 {
- mem.Segment = x86_prefixToSegment(inst.Prefix[segIndex])
- inst.Prefix[segIndex] |= x86_PrefixImplicit
- }
- inst.Args[narg] = mem
- inst.MemBytes = int(x86_memBytes[x86_decodeOp(x)])
- narg++
-
- case x86_xArgR8, x86_xArgR16, x86_xArgR32, x86_xArgR64, x86_xArgXmm, x86_xArgXmm1, x86_xArgDR0dashDR7:
- base := x86_baseReg[x]
- index := x86_Reg(regop)
- if rex != 0 && base == x86_AL && index >= 4 {
- rexUsed |= x86_PrefixREX
- index -= 4
- base = x86_SPB
- }
- inst.Args[narg] = base + index
- narg++
-
- case x86_xArgMm, x86_xArgMm1, x86_xArgTR0dashTR7:
- inst.Args[narg] = x86_baseReg[x] + x86_Reg(regop&7)
- narg++
-
- case x86_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] |= x86_PrefixImplicit
- regop += 8
- }
- inst.Args[narg] = x86_CR0 + x86_Reg(regop)
- narg++
-
- case x86_xArgSreg:
- regop &= 7
- if regop >= 6 {
- inst.Op = 0
- break Decode
- }
- inst.Args[narg] = x86_ES + x86_Reg(regop)
- narg++
-
- case x86_xArgRmf16, x86_xArgRmf32, x86_xArgRmf64:
- base := x86_baseReg[x]
- index := x86_Reg(modrm & 07)
- if rex&x86_PrefixREXB != 0 {
- rexUsed |= x86_PrefixREXB
- index += 8
- }
- inst.Args[narg] = base + index
- narg++
-
- case x86_xArgR8op, x86_xArgR16op, x86_xArgR32op, x86_xArgR64op, x86_xArgSTi:
- n := inst.Opcode >> uint(opshift+8) & 07
- base := x86_baseReg[x]
- index := x86_Reg(n)
- if rex&x86_PrefixREXB != 0 && x86_decodeOp(x) != x86_xArgSTi {
- rexUsed |= x86_PrefixREXB
- index += 8
- }
- if rex != 0 && base == x86_AL && index >= 4 {
- rexUsed |= x86_PrefixREX
- index -= 4
- base = x86_SPB
- }
- inst.Args[narg] = base + index
- narg++
-
- case x86_xArgRM8, x86_xArgRM16, x86_xArgRM32, x86_xArgRM64, x86_xArgR32M16, x86_xArgR32M8, x86_xArgR64M16,
- x86_xArgMmM32, x86_xArgMmM64, x86_xArgMm2M64,
- x86_xArgXmm2M16, x86_xArgXmm2M32, x86_xArgXmm2M64, x86_xArgXmmM64, x86_xArgXmmM128, x86_xArgXmmM32, x86_xArgXmm2M128:
- if haveMem {
- inst.Args[narg] = mem
- inst.MemBytes = int(x86_memBytes[x86_decodeOp(x)])
- } else {
- base := x86_baseReg[x]
- index := x86_Reg(rm)
- switch x86_decodeOp(x) {
- case x86_xArgMmM32, x86_xArgMmM64, x86_xArgMm2M64:
- // There are only 8 MMX registers, so these ignore the REX.X bit.
- index &= 7
- case x86_xArgRM8:
- if rex != 0 && index >= 4 {
- rexUsed |= x86_PrefixREX
- index -= 4
- base = x86_SPB
- }
- }
- inst.Args[narg] = base + index
- }
- narg++
-
- case x86_xArgMm2: // register only; TODO(rsc): Handle with tag modrm_regonly tag
- if haveMem {
- inst.Op = 0
- break Decode
- }
- inst.Args[narg] = x86_baseReg[x] + x86_Reg(rm&7)
- narg++
-
- case x86_xArgXmm2: // register only; TODO(rsc): Handle with tag modrm_regonly tag
- if haveMem {
- inst.Op = 0
- break Decode
- }
- inst.Args[narg] = x86_baseReg[x] + x86_Reg(rm)
- narg++
-
- case x86_xArgRel8:
- inst.Args[narg] = x86_Rel(int8(immc))
- narg++
-
- case x86_xArgRel16:
- inst.Args[narg] = x86_Rel(int16(immc))
- narg++
-
- case x86_xArgRel32:
- inst.Args[narg] = x86_Rel(int32(immc))
- narg++
- }
- }
-
- if inst.Op == 0 {
- // Invalid instruction.
- if nprefix > 0 {
- return x86_instPrefix(src[0], mode) // invalid instruction
- }
- return x86_Inst{Len: pos}, x86_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 == x86_XCHG && inst.Opcode>>24 == 0x90 {
- if inst.Args[0] == x86_RAX || inst.Args[0] == x86_EAX || inst.Args[0] == x86_AX {
- inst.Op = x86_NOP
- if dataSizeIndex >= 0 {
- inst.Prefix[dataSizeIndex] &^= x86_PrefixImplicit
- }
- inst.Args[0] = nil
- inst.Args[1] = nil
- }
- if repIndex >= 0 && inst.Prefix[repIndex] == 0xF3 {
- inst.Prefix[repIndex] |= x86_PrefixImplicit
- inst.Op = x86_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] |= x86_PrefixImplicit
- inst.Op = x86_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() x86_Reg {
- if segIndex >= 0 {
- inst.Prefix[segIndex] |= x86_PrefixImplicit
- return x86_prefixToSegment(inst.Prefix[segIndex])
- }
- return x86_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 x86_INSB, x86_INSW, x86_INSD:
- inst.Args[0] = x86_Mem{Segment: x86_ES, Base: x86_baseRegForBits(addrMode) + x86_DI - x86_AX}
- inst.Args[1] = x86_DX
- usedAddrSize = true
-
- case x86_OUTSB, x86_OUTSW, x86_OUTSD:
- inst.Args[0] = x86_DX
- inst.Args[1] = x86_Mem{Segment: defaultSeg(), Base: x86_baseRegForBits(addrMode) + x86_SI - x86_AX}
- usedAddrSize = true
-
- case x86_MOVSB, x86_MOVSW, x86_MOVSD, x86_MOVSQ:
- inst.Args[0] = x86_Mem{Segment: x86_ES, Base: x86_baseRegForBits(addrMode) + x86_DI - x86_AX}
- inst.Args[1] = x86_Mem{Segment: defaultSeg(), Base: x86_baseRegForBits(addrMode) + x86_SI - x86_AX}
- usedAddrSize = true
-
- case x86_CMPSB, x86_CMPSW, x86_CMPSD, x86_CMPSQ:
- inst.Args[0] = x86_Mem{Segment: defaultSeg(), Base: x86_baseRegForBits(addrMode) + x86_SI - x86_AX}
- inst.Args[1] = x86_Mem{Segment: x86_ES, Base: x86_baseRegForBits(addrMode) + x86_DI - x86_AX}
- usedAddrSize = true
-
- case x86_LODSB, x86_LODSW, x86_LODSD, x86_LODSQ:
- switch inst.Op {
- case x86_LODSB:
- inst.Args[0] = x86_AL
- case x86_LODSW:
- inst.Args[0] = x86_AX
- case x86_LODSD:
- inst.Args[0] = x86_EAX
- case x86_LODSQ:
- inst.Args[0] = x86_RAX
- }
- inst.Args[1] = x86_Mem{Segment: defaultSeg(), Base: x86_baseRegForBits(addrMode) + x86_SI - x86_AX}
- usedAddrSize = true
-
- case x86_STOSB, x86_STOSW, x86_STOSD, x86_STOSQ:
- inst.Args[0] = x86_Mem{Segment: x86_ES, Base: x86_baseRegForBits(addrMode) + x86_DI - x86_AX}
- switch inst.Op {
- case x86_STOSB:
- inst.Args[1] = x86_AL
- case x86_STOSW:
- inst.Args[1] = x86_AX
- case x86_STOSD:
- inst.Args[1] = x86_EAX
- case x86_STOSQ:
- inst.Args[1] = x86_RAX
- }
- usedAddrSize = true
-
- case x86_SCASB, x86_SCASW, x86_SCASD, x86_SCASQ:
- inst.Args[1] = x86_Mem{Segment: x86_ES, Base: x86_baseRegForBits(addrMode) + x86_DI - x86_AX}
- switch inst.Op {
- case x86_SCASB:
- inst.Args[0] = x86_AL
- case x86_SCASW:
- inst.Args[0] = x86_AX
- case x86_SCASD:
- inst.Args[0] = x86_EAX
- case x86_SCASQ:
- inst.Args[0] = x86_RAX
- }
- usedAddrSize = true
-
- case x86_XLATB:
- inst.Args[0] = x86_Mem{Segment: defaultSeg(), Base: x86_baseRegForBits(addrMode) + x86_BX - x86_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] |= x86_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] |= x86_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 x86_isCondJmp[inst.Op] || x86_isLoop[inst.Op] || inst.Op == x86_JCXZ || inst.Op == x86_JECXZ || inst.Op == x86_JRCXZ {
- PredictLoop:
- for i := nprefix - 1; i >= 0; i-- {
- p := inst.Prefix[i]
- switch p & 0xFF {
- case x86_PrefixCS:
- inst.Prefix[i] = x86_PrefixPN
- break PredictLoop
- case x86_PrefixDS:
- inst.Prefix[i] = x86_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 x86_isCondJmp[inst.Op] || inst.Op == x86_JMP || inst.Op == x86_CALL || inst.Op == x86_RET {
- for i := nprefix - 1; i >= 0; i-- {
- p := inst.Prefix[i]
- if p&^x86_PrefixIgnored == x86_PrefixREPN {
- inst.Prefix[i] = x86_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]&x86_PrefixImplicit == 0 {
- switch inst.Op {
- // TODO(rsc): Perhaps this instruction class should be derived from the CSV.
- case x86_ADD, x86_ADC, x86_AND, x86_BTC, x86_BTR, x86_BTS, x86_CMPXCHG, x86_CMPXCHG8B, x86_CMPXCHG16B, x86_DEC, x86_INC, x86_NEG, x86_NOT, x86_OR, x86_SBB, x86_SUB, x86_XOR, x86_XADD, x86_XCHG:
- if x86_isMem(inst.Args[0]) {
- hasLock = true
- break
- }
- fallthrough
- default:
- inst.Prefix[lockIndex] |= x86_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 x86_isMem(inst.Args[0]) {
- if inst.Op == x86_XCHG {
- hasLock = true
- }
-
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- p := inst.Prefix[i] &^ x86_PrefixIgnored
- switch p {
- case x86_PrefixREPN:
- if hasLock {
- inst.Prefix[i] = inst.Prefix[i]&x86_PrefixIgnored | x86_PrefixXACQUIRE
- }
-
- case x86_PrefixREP:
- if hasLock {
- inst.Prefix[i] = inst.Prefix[i]&x86_PrefixIgnored | x86_PrefixXRELEASE
- }
-
- if inst.Op == x86_MOV {
- op := (inst.Opcode >> 24) &^ 1
- if op == 0x88 || op == 0xC6 {
- inst.Prefix[i] = inst.Prefix[i]&x86_PrefixIgnored | x86_PrefixXRELEASE
- }
- }
- }
- }
- }
-
- // If REP is used on a non-REP-able instruction, mark the prefix as ignored.
- if repIndex >= 0 {
- switch inst.Prefix[repIndex] {
- case x86_PrefixREP, x86_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 x86_INSB, x86_INSW, x86_INSD,
- x86_MOVSB, x86_MOVSW, x86_MOVSD, x86_MOVSQ,
- x86_OUTSB, x86_OUTSW, x86_OUTSD,
- x86_LODSB, x86_LODSW, x86_LODSD, x86_LODSQ,
- x86_CMPSB, x86_CMPSW, x86_CMPSD, x86_CMPSQ,
- x86_SCASB, x86_SCASW, x86_SCASD, x86_SCASQ,
- x86_STOSB, x86_STOSW, x86_STOSD, x86_STOSQ:
- // ok
- default:
- inst.Prefix[repIndex] |= x86_PrefixIgnored
- }
- }
- }
-
- // If REX was present, mark implicit if all the 1 bits were consumed.
- if rexIndex >= 0 {
- if rexUsed != 0 {
- rexUsed |= x86_PrefixREX
- }
- if rex&^rexUsed == 0 {
- inst.Prefix[rexIndex] |= x86_PrefixImplicit
- }
- }
-
- inst.DataSize = dataMode
- inst.AddrSize = addrMode
- inst.Mode = mode
- inst.Len = pos
- return inst, nil
-}
-
-var x86_errInternal = errors.New("internal error")
-
-// addr16 records the eight 16-bit addressing modes.
-var x86_addr16 = [8]x86_Mem{
- {Base: x86_BX, Scale: 1, Index: x86_SI},
- {Base: x86_BX, Scale: 1, Index: x86_DI},
- {Base: x86_BP, Scale: 1, Index: x86_SI},
- {Base: x86_BP, Scale: 1, Index: x86_DI},
- {Base: x86_SI},
- {Base: x86_DI},
- {Base: x86_BP},
- {Base: x86_BX},
-}
-
-// baseReg returns the base register for a given register size in bits.
-func x86_baseRegForBits(bits int) x86_Reg {
- switch bits {
- case 8:
- return x86_AL
- case 16:
- return x86_AX
- case 32:
- return x86_EAX
- case 64:
- return x86_RAX
- }
- return 0
-}
-
-// baseReg records the base register for argument types that specify
-// a range of registers indexed by op, regop, or rm.
-var x86_baseReg = [...]x86_Reg{
- x86_xArgDR0dashDR7: x86_DR0,
- x86_xArgMm1: x86_M0,
- x86_xArgMm2: x86_M0,
- x86_xArgMm2M64: x86_M0,
- x86_xArgMm: x86_M0,
- x86_xArgMmM32: x86_M0,
- x86_xArgMmM64: x86_M0,
- x86_xArgR16: x86_AX,
- x86_xArgR16op: x86_AX,
- x86_xArgR32: x86_EAX,
- x86_xArgR32M16: x86_EAX,
- x86_xArgR32M8: x86_EAX,
- x86_xArgR32op: x86_EAX,
- x86_xArgR64: x86_RAX,
- x86_xArgR64M16: x86_RAX,
- x86_xArgR64op: x86_RAX,
- x86_xArgR8: x86_AL,
- x86_xArgR8op: x86_AL,
- x86_xArgRM16: x86_AX,
- x86_xArgRM32: x86_EAX,
- x86_xArgRM64: x86_RAX,
- x86_xArgRM8: x86_AL,
- x86_xArgRmf16: x86_AX,
- x86_xArgRmf32: x86_EAX,
- x86_xArgRmf64: x86_RAX,
- x86_xArgSTi: x86_F0,
- x86_xArgTR0dashTR7: x86_TR0,
- x86_xArgXmm1: x86_X0,
- x86_xArgXmm2: x86_X0,
- x86_xArgXmm2M128: x86_X0,
- x86_xArgXmm2M16: x86_X0,
- x86_xArgXmm2M32: x86_X0,
- x86_xArgXmm2M64: x86_X0,
- x86_xArgXmm: x86_X0,
- x86_xArgXmmM128: x86_X0,
- x86_xArgXmmM32: x86_X0,
- x86_xArgXmmM64: x86_X0,
-}
-
-// prefixToSegment returns the segment register
-// corresponding to a particular segment prefix.
-func x86_prefixToSegment(p x86_Prefix) x86_Reg {
- switch p &^ x86_PrefixImplicit {
- case x86_PrefixCS:
- return x86_CS
- case x86_PrefixDS:
- return x86_DS
- case x86_PrefixES:
- return x86_ES
- case x86_PrefixFS:
- return x86_FS
- case x86_PrefixGS:
- return x86_GS
- case x86_PrefixSS:
- return x86_SS
- }
- return 0
-}
-
-// fixedArg records the fixed arguments corresponding to the given bytecodes.
-var x86_fixedArg = [...]x86_Arg{
- x86_xArg1: x86_Imm(1),
- x86_xArg3: x86_Imm(3),
- x86_xArgAL: x86_AL,
- x86_xArgAX: x86_AX,
- x86_xArgDX: x86_DX,
- x86_xArgEAX: x86_EAX,
- x86_xArgEDX: x86_EDX,
- x86_xArgRAX: x86_RAX,
- x86_xArgRDX: x86_RDX,
- x86_xArgCL: x86_CL,
- x86_xArgCS: x86_CS,
- x86_xArgDS: x86_DS,
- x86_xArgES: x86_ES,
- x86_xArgFS: x86_FS,
- x86_xArgGS: x86_GS,
- x86_xArgSS: x86_SS,
- x86_xArgST: x86_F0,
- x86_xArgXMM0: x86_X0,
-}
-
-// memBytes records the size of the memory pointed at
-// by a memory argument of the given form.
-var x86_memBytes = [...]int8{
- x86_xArgM128: 128 / 8,
- x86_xArgM16: 16 / 8,
- x86_xArgM16and16: (16 + 16) / 8,
- x86_xArgM16colon16: (16 + 16) / 8,
- x86_xArgM16colon32: (16 + 32) / 8,
- x86_xArgM16int: 16 / 8,
- x86_xArgM2byte: 2,
- x86_xArgM32: 32 / 8,
- x86_xArgM32and32: (32 + 32) / 8,
- x86_xArgM32fp: 32 / 8,
- x86_xArgM32int: 32 / 8,
- x86_xArgM64: 64 / 8,
- x86_xArgM64fp: 64 / 8,
- x86_xArgM64int: 64 / 8,
- x86_xArgMm2M64: 64 / 8,
- x86_xArgMmM32: 32 / 8,
- x86_xArgMmM64: 64 / 8,
- x86_xArgMoffs16: 16 / 8,
- x86_xArgMoffs32: 32 / 8,
- x86_xArgMoffs64: 64 / 8,
- x86_xArgMoffs8: 8 / 8,
- x86_xArgR32M16: 16 / 8,
- x86_xArgR32M8: 8 / 8,
- x86_xArgR64M16: 16 / 8,
- x86_xArgRM16: 16 / 8,
- x86_xArgRM32: 32 / 8,
- x86_xArgRM64: 64 / 8,
- x86_xArgRM8: 8 / 8,
- x86_xArgXmm2M128: 128 / 8,
- x86_xArgXmm2M16: 16 / 8,
- x86_xArgXmm2M32: 32 / 8,
- x86_xArgXmm2M64: 64 / 8,
- x86_xArgXmm: 128 / 8,
- x86_xArgXmmM128: 128 / 8,
- x86_xArgXmmM32: 32 / 8,
- x86_xArgXmmM64: 64 / 8,
-}
-
-// isCondJmp records the conditional jumps.
-var x86_isCondJmp = [x86_maxOp + 1]bool{
- x86_JA: true,
- x86_JAE: true,
- x86_JB: true,
- x86_JBE: true,
- x86_JE: true,
- x86_JG: true,
- x86_JGE: true,
- x86_JL: true,
- x86_JLE: true,
- x86_JNE: true,
- x86_JNO: true,
- x86_JNP: true,
- x86_JNS: true,
- x86_JO: true,
- x86_JP: true,
- x86_JS: true,
-}
-
-// isLoop records the loop operators.
-var x86_isLoop = [x86_maxOp + 1]bool{
- x86_LOOP: true,
- x86_LOOPE: true,
- x86_LOOPNE: true,
- x86_JECXZ: true,
- x86_JRCXZ: true,
-}
-
-/* gnu.go */
-
-// 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.
-
-// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
-// This general form is often called ``AT&T syntax'' as a reference to AT&T System V Unix.
-func x86_GNUSyntax(inst x86_Inst) string {
- // Rewrite instruction to mimic GNU peculiarities.
- // Note that inst has been passed by value and contains
- // no pointers, so any changes we make here are local
- // and will not propagate back out to the caller.
-
- // Adjust opcode [sic].
- switch inst.Op {
- case x86_FDIV, x86_FDIVR, x86_FSUB, x86_FSUBR, x86_FDIVP, x86_FDIVRP, x86_FSUBP, x86_FSUBRP:
- // DC E0, DC F0: libopcodes swaps FSUBR/FSUB and FDIVR/FDIV, at least
- // if you believe the Intel manual is correct (the encoding is irregular as given;
- // libopcodes uses the more regular expected encoding).
- // TODO(rsc): Test to ensure Intel manuals are correct and report to libopcodes maintainers?
- // NOTE: iant thinks this is deliberate, but we can't find the history.
- _, reg1 := inst.Args[0].(x86_Reg)
- _, reg2 := inst.Args[1].(x86_Reg)
- if reg1 && reg2 && (inst.Opcode>>24 == 0xDC || inst.Opcode>>24 == 0xDE) {
- switch inst.Op {
- case x86_FDIV:
- inst.Op = x86_FDIVR
- case x86_FDIVR:
- inst.Op = x86_FDIV
- case x86_FSUB:
- inst.Op = x86_FSUBR
- case x86_FSUBR:
- inst.Op = x86_FSUB
- case x86_FDIVP:
- inst.Op = x86_FDIVRP
- case x86_FDIVRP:
- inst.Op = x86_FDIVP
- case x86_FSUBP:
- inst.Op = x86_FSUBRP
- case x86_FSUBRP:
- inst.Op = x86_FSUBP
- }
- }
-
- case x86_MOVNTSD:
- // MOVNTSD is F2 0F 2B /r.
- // MOVNTSS is F3 0F 2B /r (supposedly; not in manuals).
- // Usually inner prefixes win for display,
- // so that F3 F2 0F 2B 11 is REP MOVNTSD
- // and F2 F3 0F 2B 11 is REPN MOVNTSS.
- // Libopcodes always prefers MOVNTSS regardless of prefix order.
- if x86_countPrefix(&inst, 0xF3) > 0 {
- found := false
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- switch inst.Prefix[i] & 0xFF {
- case 0xF3:
- if !found {
- found = true
- inst.Prefix[i] |= x86_PrefixImplicit
- }
- case 0xF2:
- inst.Prefix[i] &^= x86_PrefixImplicit
- }
- }
- inst.Op = x86_MOVNTSS
- }
- }
-
- // Add implicit arguments.
- switch inst.Op {
- case x86_MONITOR:
- inst.Args[0] = x86_EDX
- inst.Args[1] = x86_ECX
- inst.Args[2] = x86_EAX
- if inst.AddrSize == 16 {
- inst.Args[2] = x86_AX
- }
-
- case x86_MWAIT:
- if inst.Mode == 64 {
- inst.Args[0] = x86_RCX
- inst.Args[1] = x86_RAX
- } else {
- inst.Args[0] = x86_ECX
- inst.Args[1] = x86_EAX
- }
- }
-
- // Adjust which prefixes will be displayed.
- // The rule is to display all the prefixes not implied by
- // the usual instruction display, that is, all the prefixes
- // except the ones with PrefixImplicit set.
- // However, of course, there are exceptions to the rule.
- switch inst.Op {
- case x86_CRC32:
- // CRC32 has a mandatory F2 prefix.
- // If there are multiple F2s and no F3s, the extra F2s do not print.
- // (And Decode has already marked them implicit.)
- // However, if there is an F3 anywhere, then the extra F2s do print.
- // If there are multiple F2 prefixes *and* an (ignored) F3,
- // then libopcodes prints the extra F2s as REPNs.
- if x86_countPrefix(&inst, 0xF2) > 1 {
- x86_unmarkImplicit(&inst, 0xF2)
- x86_markLastImplicit(&inst, 0xF2)
- }
-
- // An unused data size override should probably be shown,
- // to distinguish DATA16 CRC32B from plain CRC32B,
- // but libopcodes always treats the final override as implicit
- // and the others as explicit.
- x86_unmarkImplicit(&inst, x86_PrefixDataSize)
- x86_markLastImplicit(&inst, x86_PrefixDataSize)
-
- case x86_CVTSI2SD, x86_CVTSI2SS:
- if !x86_isMem(inst.Args[1]) {
- x86_markLastImplicit(&inst, x86_PrefixDataSize)
- }
-
- case x86_CVTSD2SI, x86_CVTSS2SI, x86_CVTTSD2SI, x86_CVTTSS2SI,
- x86_ENTER, x86_FLDENV, x86_FNSAVE, x86_FNSTENV, x86_FRSTOR, x86_LGDT, x86_LIDT, x86_LRET,
- x86_POP, x86_PUSH, x86_RET, x86_SGDT, x86_SIDT, x86_SYSRET, x86_XBEGIN:
- x86_markLastImplicit(&inst, x86_PrefixDataSize)
-
- case x86_LOOP, x86_LOOPE, x86_LOOPNE, x86_MONITOR:
- x86_markLastImplicit(&inst, x86_PrefixAddrSize)
-
- case x86_MOV:
- // The 16-bit and 32-bit forms of MOV Sreg, dst and MOV src, Sreg
- // cannot be distinguished when src or dst refers to memory, because
- // Sreg is always a 16-bit value, even when we're doing a 32-bit
- // instruction. Because the instruction tables distinguished these two,
- // any operand size prefix has been marked as used (to decide which
- // branch to take). Unmark it, so that it will show up in disassembly,
- // so that the reader can tell the size of memory operand.
- // up with the same arguments
- dst, _ := inst.Args[0].(x86_Reg)
- src, _ := inst.Args[1].(x86_Reg)
- if x86_ES <= src && src <= x86_GS && x86_isMem(inst.Args[0]) || x86_ES <= dst && dst <= x86_GS && x86_isMem(inst.Args[1]) {
- x86_unmarkImplicit(&inst, x86_PrefixDataSize)
- }
-
- case x86_MOVDQU:
- if x86_countPrefix(&inst, 0xF3) > 1 {
- x86_unmarkImplicit(&inst, 0xF3)
- x86_markLastImplicit(&inst, 0xF3)
- }
-
- case x86_MOVQ2DQ:
- x86_markLastImplicit(&inst, x86_PrefixDataSize)
-
- case x86_SLDT, x86_SMSW, x86_STR, x86_FXRSTOR, x86_XRSTOR, x86_XSAVE, x86_XSAVEOPT, x86_CMPXCHG8B:
- if x86_isMem(inst.Args[0]) {
- x86_unmarkImplicit(&inst, x86_PrefixDataSize)
- }
-
- case x86_SYSEXIT:
- x86_unmarkImplicit(&inst, x86_PrefixDataSize)
- }
-
- if x86_isCondJmp[inst.Op] || x86_isLoop[inst.Op] || inst.Op == x86_JCXZ || inst.Op == x86_JECXZ || inst.Op == x86_JRCXZ {
- if x86_countPrefix(&inst, x86_PrefixCS) > 0 && x86_countPrefix(&inst, x86_PrefixDS) > 0 {
- for i, p := range inst.Prefix {
- switch p & 0xFFF {
- case x86_PrefixPN, x86_PrefixPT:
- inst.Prefix[i] &= 0xF0FF // cut interpretation bits, producing original segment prefix
- }
- }
- }
- }
-
- // XACQUIRE/XRELEASE adjustment.
- if inst.Op == x86_MOV {
- // MOV into memory is a candidate for turning REP into XRELEASE.
- // However, if the REP is followed by a REPN, that REPN blocks the
- // conversion.
- haveREPN := false
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- switch inst.Prefix[i] &^ x86_PrefixIgnored {
- case x86_PrefixREPN:
- haveREPN = true
- case x86_PrefixXRELEASE:
- if haveREPN {
- inst.Prefix[i] = x86_PrefixREP
- }
- }
- }
- }
-
- // We only format the final F2/F3 as XRELEASE/XACQUIRE.
- haveXA := false
- haveXR := false
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- switch inst.Prefix[i] &^ x86_PrefixIgnored {
- case x86_PrefixXRELEASE:
- if !haveXR {
- haveXR = true
- } else {
- inst.Prefix[i] = x86_PrefixREP
- }
-
- case x86_PrefixXACQUIRE:
- if !haveXA {
- haveXA = true
- } else {
- inst.Prefix[i] = x86_PrefixREPN
- }
- }
- }
-
- // Determine opcode.
- op := strings.ToLower(inst.Op.String())
- if alt := x86_gnuOp[inst.Op]; alt != "" {
- op = alt
- }
-
- // Determine opcode suffix.
- // Libopcodes omits the suffix if the width of the operation
- // can be inferred from a register arguments. For example,
- // add $1, %ebx has no suffix because you can tell from the
- // 32-bit register destination that it is a 32-bit add,
- // but in addl $1, (%ebx), the destination is memory, so the
- // size is not evident without the l suffix.
- needSuffix := true
-SuffixLoop:
- for i, a := range inst.Args {
- if a == nil {
- break
- }
- switch a := a.(type) {
- case x86_Reg:
- switch inst.Op {
- case x86_MOVSX, x86_MOVZX:
- continue
-
- case x86_SHL, x86_SHR, x86_RCL, x86_RCR, x86_ROL, x86_ROR, x86_SAR:
- if i == 1 {
- // shift count does not tell us operand size
- continue
- }
-
- case x86_CRC32:
- // The source argument does tell us operand size,
- // but libopcodes still always puts a suffix on crc32.
- continue
-
- case x86_PUSH, x86_POP:
- // Even though segment registers are 16-bit, push and pop
- // can save/restore them from 32-bit slots, so they
- // do not imply operand size.
- if x86_ES <= a && a <= x86_GS {
- continue
- }
-
- case x86_CVTSI2SD, x86_CVTSI2SS:
- // The integer register argument takes priority.
- if x86_X0 <= a && a <= x86_X15 {
- continue
- }
- }
-
- if x86_AL <= a && a <= x86_R15 || x86_ES <= a && a <= x86_GS || x86_X0 <= a && a <= x86_X15 || x86_M0 <= a && a <= x86_M7 {
- needSuffix = false
- break SuffixLoop
- }
- }
- }
-
- if needSuffix {
- switch inst.Op {
- case x86_CMPXCHG8B, x86_FLDCW, x86_FNSTCW, x86_FNSTSW, x86_LDMXCSR, x86_LLDT, x86_LMSW, x86_LTR, x86_PCLMULQDQ,
- x86_SETA, x86_SETAE, x86_SETB, x86_SETBE, x86_SETE, x86_SETG, x86_SETGE, x86_SETL, x86_SETLE, x86_SETNE, x86_SETNO, x86_SETNP, x86_SETNS, x86_SETO, x86_SETP, x86_SETS,
- x86_SLDT, x86_SMSW, x86_STMXCSR, x86_STR, x86_VERR, x86_VERW:
- // For various reasons, libopcodes emits no suffix for these instructions.
-
- case x86_CRC32:
- op += x86_byteSizeSuffix(x86_argBytes(&inst, inst.Args[1]))
-
- case x86_LGDT, x86_LIDT, x86_SGDT, x86_SIDT:
- op += x86_byteSizeSuffix(inst.DataSize / 8)
-
- case x86_MOVZX, x86_MOVSX:
- // Integer size conversions get two suffixes.
- op = op[:4] + x86_byteSizeSuffix(x86_argBytes(&inst, inst.Args[1])) + x86_byteSizeSuffix(x86_argBytes(&inst, inst.Args[0]))
-
- case x86_LOOP, x86_LOOPE, x86_LOOPNE:
- // Add w suffix to indicate use of CX register instead of ECX.
- if inst.AddrSize == 16 {
- op += "w"
- }
-
- case x86_CALL, x86_ENTER, x86_JMP, x86_LCALL, x86_LEAVE, x86_LJMP, x86_LRET, x86_RET, x86_SYSRET, x86_XBEGIN:
- // Add w suffix to indicate use of 16-bit target.
- // Exclude JMP rel8.
- if inst.Opcode>>24 == 0xEB {
- break
- }
- if inst.DataSize == 16 && inst.Mode != 16 {
- x86_markLastImplicit(&inst, x86_PrefixDataSize)
- op += "w"
- } else if inst.Mode == 64 {
- op += "q"
- }
-
- case x86_FRSTOR, x86_FNSAVE, x86_FNSTENV, x86_FLDENV:
- // Add s suffix to indicate shortened FPU state (I guess).
- if inst.DataSize == 16 {
- op += "s"
- }
-
- case x86_PUSH, x86_POP:
- if x86_markLastImplicit(&inst, x86_PrefixDataSize) {
- op += x86_byteSizeSuffix(inst.DataSize / 8)
- } else if inst.Mode == 64 {
- op += "q"
- } else {
- op += x86_byteSizeSuffix(inst.MemBytes)
- }
-
- default:
- if x86_isFloat(inst.Op) {
- // I can't explain any of this, but it's what libopcodes does.
- switch inst.MemBytes {
- default:
- if (inst.Op == x86_FLD || inst.Op == x86_FSTP) && x86_isMem(inst.Args[0]) {
- op += "t"
- }
- case 4:
- if x86_isFloatInt(inst.Op) {
- op += "l"
- } else {
- op += "s"
- }
- case 8:
- if x86_isFloatInt(inst.Op) {
- op += "ll"
- } else {
- op += "l"
- }
- }
- break
- }
-
- op += x86_byteSizeSuffix(inst.MemBytes)
- }
- }
-
- // Adjust special case opcodes.
- switch inst.Op {
- case 0:
- if inst.Prefix[0] != 0 {
- return strings.ToLower(inst.Prefix[0].String())
- }
-
- case x86_INT:
- if inst.Opcode>>24 == 0xCC {
- inst.Args[0] = nil
- op = "int3"
- }
-
- case x86_CMPPS, x86_CMPPD, x86_CMPSD_XMM, x86_CMPSS:
- imm, ok := inst.Args[2].(x86_Imm)
- if ok && 0 <= imm && imm < 8 {
- inst.Args[2] = nil
- op = x86_cmppsOps[imm] + op[3:]
- }
-
- case x86_PCLMULQDQ:
- imm, ok := inst.Args[2].(x86_Imm)
- if ok && imm&^0x11 == 0 {
- inst.Args[2] = nil
- op = x86_pclmulqOps[(imm&0x10)>>3|(imm&1)]
- }
-
- case x86_XLATB:
- if x86_markLastImplicit(&inst, x86_PrefixAddrSize) {
- op = "xlat" // not xlatb
- }
- }
-
- // Build list of argument strings.
- var (
- usedPrefixes bool // segment prefixes consumed by Mem formatting
- args []string // formatted arguments
- )
- for i, a := range inst.Args {
- if a == nil {
- break
- }
- switch inst.Op {
- case x86_MOVSB, x86_MOVSW, x86_MOVSD, x86_MOVSQ, x86_OUTSB, x86_OUTSW, x86_OUTSD:
- if i == 0 {
- usedPrefixes = true // disable use of prefixes for first argument
- } else {
- usedPrefixes = false
- }
- }
- if a == x86_Imm(1) && (inst.Opcode>>24)&^1 == 0xD0 {
- continue
- }
- args = append(args, x86_gnuArg(&inst, a, &usedPrefixes))
- }
-
- // The default is to print the arguments in reverse Intel order.
- // A few instructions inhibit this behavior.
- switch inst.Op {
- case x86_BOUND, x86_LCALL, x86_ENTER, x86_LJMP:
- // no reverse
- default:
- // reverse args
- for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
- args[i], args[j] = args[j], args[i]
- }
- }
-
- // Build prefix string.
- // Must be after argument formatting, which can turn off segment prefixes.
- var (
- prefix = "" // output string
- numAddr = 0
- numData = 0
- implicitData = false
- )
- for _, p := range inst.Prefix {
- if p&0xFF == x86_PrefixDataSize && p&x86_PrefixImplicit != 0 {
- implicitData = true
- }
- }
- for _, p := range inst.Prefix {
- if p == 0 {
- break
- }
- if p&x86_PrefixImplicit != 0 {
- continue
- }
- switch p &^ (x86_PrefixIgnored | x86_PrefixInvalid) {
- default:
- if p.IsREX() {
- if p&0xFF == x86_PrefixREX {
- prefix += "rex "
- } else {
- prefix += "rex." + p.String()[4:] + " "
- }
- break
- }
- prefix += strings.ToLower(p.String()) + " "
-
- case x86_PrefixPN:
- op += ",pn"
- continue
-
- case x86_PrefixPT:
- op += ",pt"
- continue
-
- case x86_PrefixAddrSize, x86_PrefixAddr16, x86_PrefixAddr32:
- // For unknown reasons, if the addr16 prefix is repeated,
- // libopcodes displays all but the last as addr32, even though
- // the addressing form used in a memory reference is clearly
- // still 16-bit.
- n := 32
- if inst.Mode == 32 {
- n = 16
- }
- numAddr++
- if x86_countPrefix(&inst, x86_PrefixAddrSize) > numAddr {
- n = inst.Mode
- }
- prefix += fmt.Sprintf("addr%d ", n)
- continue
-
- case x86_PrefixData16, x86_PrefixData32:
- if implicitData && x86_countPrefix(&inst, x86_PrefixDataSize) > 1 {
- // Similar to the addr32 logic above, but it only kicks in
- // when something used the data size prefix (one is implicit).
- n := 16
- if inst.Mode == 16 {
- n = 32
- }
- numData++
- if x86_countPrefix(&inst, x86_PrefixDataSize) > numData {
- if inst.Mode == 16 {
- n = 16
- } else {
- n = 32
- }
- }
- prefix += fmt.Sprintf("data%d ", n)
- continue
- }
- prefix += strings.ToLower(p.String()) + " "
- }
- }
-
- // Finally! Put it all together.
- text := prefix + op
- if args != nil {
- text += " "
- // Indirect call/jmp gets a star to distinguish from direct jump address.
- if (inst.Op == x86_CALL || inst.Op == x86_JMP || inst.Op == x86_LJMP || inst.Op == x86_LCALL) && (x86_isMem(inst.Args[0]) || x86_isReg(inst.Args[0])) {
- text += "*"
- }
- text += strings.Join(args, ",")
- }
- return text
-}
-
-// gnuArg returns the GNU syntax for the argument x from the instruction inst.
-// If *usedPrefixes is false and x is a Mem, then the formatting
-// includes any segment prefixes and sets *usedPrefixes to true.
-func x86_gnuArg(inst *x86_Inst, x x86_Arg, usedPrefixes *bool) string {
- if x == nil {
- return "<nil>"
- }
- switch x := x.(type) {
- case x86_Reg:
- switch inst.Op {
- case x86_CVTSI2SS, x86_CVTSI2SD, x86_CVTSS2SI, x86_CVTSD2SI, x86_CVTTSD2SI, x86_CVTTSS2SI:
- if inst.DataSize == 16 && x86_EAX <= x && x <= x86_R15L {
- x -= x86_EAX - x86_AX
- }
-
- case x86_IN, x86_INSB, x86_INSW, x86_INSD, x86_OUT, x86_OUTSB, x86_OUTSW, x86_OUTSD:
- // DX is the port, but libopcodes prints it as if it were a memory reference.
- if x == x86_DX {
- return "(%dx)"
- }
- }
- return x86_gccRegName[x]
- case x86_Mem:
- seg := ""
- var haveCS, haveDS, haveES, haveFS, haveGS, haveSS bool
- switch x.Segment {
- case x86_CS:
- haveCS = true
- case x86_DS:
- haveDS = true
- case x86_ES:
- haveES = true
- case x86_FS:
- haveFS = true
- case x86_GS:
- haveGS = true
- case x86_SS:
- haveSS = true
- }
- switch inst.Op {
- case x86_INSB, x86_INSW, x86_INSD, x86_STOSB, x86_STOSW, x86_STOSD, x86_STOSQ, x86_SCASB, x86_SCASW, x86_SCASD, x86_SCASQ:
- // These do not accept segment prefixes, at least in the GNU rendering.
- default:
- if *usedPrefixes {
- break
- }
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- p := inst.Prefix[i] &^ x86_PrefixIgnored
- if p == 0 {
- continue
- }
- switch p {
- case x86_PrefixCS:
- if !haveCS {
- haveCS = true
- inst.Prefix[i] |= x86_PrefixImplicit
- }
- case x86_PrefixDS:
- if !haveDS {
- haveDS = true
- inst.Prefix[i] |= x86_PrefixImplicit
- }
- case x86_PrefixES:
- if !haveES {
- haveES = true
- inst.Prefix[i] |= x86_PrefixImplicit
- }
- case x86_PrefixFS:
- if !haveFS {
- haveFS = true
- inst.Prefix[i] |= x86_PrefixImplicit
- }
- case x86_PrefixGS:
- if !haveGS {
- haveGS = true
- inst.Prefix[i] |= x86_PrefixImplicit
- }
- case x86_PrefixSS:
- if !haveSS {
- haveSS = true
- inst.Prefix[i] |= x86_PrefixImplicit
- }
- }
- }
- *usedPrefixes = true
- }
- if haveCS {
- seg += "%cs:"
- }
- if haveDS {
- seg += "%ds:"
- }
- if haveSS {
- seg += "%ss:"
- }
- if haveES {
- seg += "%es:"
- }
- if haveFS {
- seg += "%fs:"
- }
- if haveGS {
- seg += "%gs:"
- }
- disp := ""
- if x.Disp != 0 {
- disp = fmt.Sprintf("%#x", x.Disp)
- }
- if x.Scale == 0 || x.Index == 0 && x.Scale == 1 && (x.Base == x86_ESP || x.Base == x86_RSP || x.Base == 0 && inst.Mode == 64) {
- if x.Base == 0 {
- return seg + disp
- }
- return fmt.Sprintf("%s%s(%s)", seg, disp, x86_gccRegName[x.Base])
- }
- base := x86_gccRegName[x.Base]
- if x.Base == 0 {
- base = ""
- }
- index := x86_gccRegName[x.Index]
- if x.Index == 0 {
- if inst.AddrSize == 64 {
- index = "%riz"
- } else {
- index = "%eiz"
- }
- }
- if x86_AX <= x.Base && x.Base <= x86_DI {
- // 16-bit addressing - no scale
- return fmt.Sprintf("%s%s(%s,%s)", seg, disp, base, index)
- }
- return fmt.Sprintf("%s%s(%s,%s,%d)", seg, disp, base, index, x.Scale)
- case x86_Rel:
- return fmt.Sprintf(".%+#x", int32(x))
- case x86_Imm:
- if inst.Mode == 32 {
- return fmt.Sprintf("$%#x", uint32(x))
- }
- return fmt.Sprintf("$%#x", int64(x))
- }
- return x.String()
-}
-
-var x86_gccRegName = [...]string{
- 0: "REG0",
- x86_AL: "%al",
- x86_CL: "%cl",
- x86_BL: "%bl",
- x86_DL: "%dl",
- x86_AH: "%ah",
- x86_CH: "%ch",
- x86_BH: "%bh",
- x86_DH: "%dh",
- x86_SPB: "%spl",
- x86_BPB: "%bpl",
- x86_SIB: "%sil",
- x86_DIB: "%dil",
- x86_R8B: "%r8b",
- x86_R9B: "%r9b",
- x86_R10B: "%r10b",
- x86_R11B: "%r11b",
- x86_R12B: "%r12b",
- x86_R13B: "%r13b",
- x86_R14B: "%r14b",
- x86_R15B: "%r15b",
- x86_AX: "%ax",
- x86_CX: "%cx",
- x86_BX: "%bx",
- x86_DX: "%dx",
- x86_SP: "%sp",
- x86_BP: "%bp",
- x86_SI: "%si",
- x86_DI: "%di",
- x86_R8W: "%r8w",
- x86_R9W: "%r9w",
- x86_R10W: "%r10w",
- x86_R11W: "%r11w",
- x86_R12W: "%r12w",
- x86_R13W: "%r13w",
- x86_R14W: "%r14w",
- x86_R15W: "%r15w",
- x86_EAX: "%eax",
- x86_ECX: "%ecx",
- x86_EDX: "%edx",
- x86_EBX: "%ebx",
- x86_ESP: "%esp",
- x86_EBP: "%ebp",
- x86_ESI: "%esi",
- x86_EDI: "%edi",
- x86_R8L: "%r8d",
- x86_R9L: "%r9d",
- x86_R10L: "%r10d",
- x86_R11L: "%r11d",
- x86_R12L: "%r12d",
- x86_R13L: "%r13d",
- x86_R14L: "%r14d",
- x86_R15L: "%r15d",
- x86_RAX: "%rax",
- x86_RCX: "%rcx",
- x86_RDX: "%rdx",
- x86_RBX: "%rbx",
- x86_RSP: "%rsp",
- x86_RBP: "%rbp",
- x86_RSI: "%rsi",
- x86_RDI: "%rdi",
- x86_R8: "%r8",
- x86_R9: "%r9",
- x86_R10: "%r10",
- x86_R11: "%r11",
- x86_R12: "%r12",
- x86_R13: "%r13",
- x86_R14: "%r14",
- x86_R15: "%r15",
- x86_IP: "%ip",
- x86_EIP: "%eip",
- x86_RIP: "%rip",
- x86_F0: "%st",
- x86_F1: "%st(1)",
- x86_F2: "%st(2)",
- x86_F3: "%st(3)",
- x86_F4: "%st(4)",
- x86_F5: "%st(5)",
- x86_F6: "%st(6)",
- x86_F7: "%st(7)",
- x86_M0: "%mm0",
- x86_M1: "%mm1",
- x86_M2: "%mm2",
- x86_M3: "%mm3",
- x86_M4: "%mm4",
- x86_M5: "%mm5",
- x86_M6: "%mm6",
- x86_M7: "%mm7",
- x86_X0: "%xmm0",
- x86_X1: "%xmm1",
- x86_X2: "%xmm2",
- x86_X3: "%xmm3",
- x86_X4: "%xmm4",
- x86_X5: "%xmm5",
- x86_X6: "%xmm6",
- x86_X7: "%xmm7",
- x86_X8: "%xmm8",
- x86_X9: "%xmm9",
- x86_X10: "%xmm10",
- x86_X11: "%xmm11",
- x86_X12: "%xmm12",
- x86_X13: "%xmm13",
- x86_X14: "%xmm14",
- x86_X15: "%xmm15",
- x86_CS: "%cs",
- x86_SS: "%ss",
- x86_DS: "%ds",
- x86_ES: "%es",
- x86_FS: "%fs",
- x86_GS: "%gs",
- x86_GDTR: "%gdtr",
- x86_IDTR: "%idtr",
- x86_LDTR: "%ldtr",
- x86_MSW: "%msw",
- x86_TASK: "%task",
- x86_CR0: "%cr0",
- x86_CR1: "%cr1",
- x86_CR2: "%cr2",
- x86_CR3: "%cr3",
- x86_CR4: "%cr4",
- x86_CR5: "%cr5",
- x86_CR6: "%cr6",
- x86_CR7: "%cr7",
- x86_CR8: "%cr8",
- x86_CR9: "%cr9",
- x86_CR10: "%cr10",
- x86_CR11: "%cr11",
- x86_CR12: "%cr12",
- x86_CR13: "%cr13",
- x86_CR14: "%cr14",
- x86_CR15: "%cr15",
- x86_DR0: "%db0",
- x86_DR1: "%db1",
- x86_DR2: "%db2",
- x86_DR3: "%db3",
- x86_DR4: "%db4",
- x86_DR5: "%db5",
- x86_DR6: "%db6",
- x86_DR7: "%db7",
- x86_TR0: "%tr0",
- x86_TR1: "%tr1",
- x86_TR2: "%tr2",
- x86_TR3: "%tr3",
- x86_TR4: "%tr4",
- x86_TR5: "%tr5",
- x86_TR6: "%tr6",
- x86_TR7: "%tr7",
-}
-
-var x86_gnuOp = map[x86_Op]string{
- x86_CBW: "cbtw",
- x86_CDQ: "cltd",
- x86_CMPSD: "cmpsl",
- x86_CMPSD_XMM: "cmpsd",
- x86_CWD: "cwtd",
- x86_CWDE: "cwtl",
- x86_CQO: "cqto",
- x86_INSD: "insl",
- x86_IRET: "iretw",
- x86_IRETD: "iret",
- x86_IRETQ: "iretq",
- x86_LODSB: "lods",
- x86_LODSD: "lods",
- x86_LODSQ: "lods",
- x86_LODSW: "lods",
- x86_MOVSD: "movsl",
- x86_MOVSD_XMM: "movsd",
- x86_OUTSD: "outsl",
- x86_POPA: "popaw",
- x86_POPAD: "popa",
- x86_POPF: "popfw",
- x86_POPFD: "popf",
- x86_PUSHA: "pushaw",
- x86_PUSHAD: "pusha",
- x86_PUSHF: "pushfw",
- x86_PUSHFD: "pushf",
- x86_SCASB: "scas",
- x86_SCASD: "scas",
- x86_SCASQ: "scas",
- x86_SCASW: "scas",
- x86_STOSB: "stos",
- x86_STOSD: "stos",
- x86_STOSQ: "stos",
- x86_STOSW: "stos",
- x86_XLATB: "xlat",
-}
-
-var x86_cmppsOps = []string{
- "cmpeq",
- "cmplt",
- "cmple",
- "cmpunord",
- "cmpneq",
- "cmpnlt",
- "cmpnle",
- "cmpord",
-}
-
-var x86_pclmulqOps = []string{
- "pclmullqlqdq",
- "pclmulhqlqdq",
- "pclmullqhqdq",
- "pclmulhqhqdq",
-}
-
-func x86_countPrefix(inst *x86_Inst, target x86_Prefix) int {
- n := 0
- for _, p := range inst.Prefix {
- if p&0xFF == target&0xFF {
- n++
- }
- }
- return n
-}
-
-func x86_markLastImplicit(inst *x86_Inst, prefix x86_Prefix) bool {
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- p := inst.Prefix[i]
- if p&0xFF == prefix {
- inst.Prefix[i] |= x86_PrefixImplicit
- return true
- }
- }
- return false
-}
-
-func x86_unmarkImplicit(inst *x86_Inst, prefix x86_Prefix) {
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- p := inst.Prefix[i]
- if p&0xFF == prefix {
- inst.Prefix[i] &^= x86_PrefixImplicit
- }
- }
-}
-
-func x86_byteSizeSuffix(b int) string {
- switch b {
- case 1:
- return "b"
- case 2:
- return "w"
- case 4:
- return "l"
- case 8:
- return "q"
- }
- return ""
-}
-
-func x86_argBytes(inst *x86_Inst, arg x86_Arg) int {
- if x86_isMem(arg) {
- return inst.MemBytes
- }
- return x86_regBytes(arg)
-}
-
-func x86_isFloat(op x86_Op) bool {
- switch op {
- case x86_FADD, x86_FCOM, x86_FCOMP, x86_FDIV, x86_FDIVR, x86_FIADD, x86_FICOM, x86_FICOMP, x86_FIDIV, x86_FIDIVR, x86_FILD, x86_FIMUL, x86_FIST, x86_FISTP, x86_FISTTP, x86_FISUB, x86_FISUBR, x86_FLD, x86_FMUL, x86_FST, x86_FSTP, x86_FSUB, x86_FSUBR:
- return true
- }
- return false
-}
-
-func x86_isFloatInt(op x86_Op) bool {
- switch op {
- case x86_FIADD, x86_FICOM, x86_FICOMP, x86_FIDIV, x86_FIDIVR, x86_FILD, x86_FIMUL, x86_FIST, x86_FISTP, x86_FISTTP, x86_FISUB, x86_FISUBR:
- return true
- }
- return false
-}
-
-/* inst.go */
-
-// 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.
-
-// An Inst is a single instruction.
-type x86_Inst struct {
- Prefix x86_Prefixes // Prefixes applied to the instruction.
- Op x86_Op // Opcode mnemonic
- Opcode uint32 // Encoded opcode bits, left aligned (first byte is Opcode>>24, etc)
- Args x86_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 x86_Prefixes [14]x86_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 x86_Prefix uint16
-
-const (
- // Metadata about the role of a prefix in an instruction.
- x86_PrefixImplicit x86_Prefix = 0x8000 // prefix is implied by instruction text
- x86_PrefixIgnored x86_Prefix = 0x4000 // prefix is ignored: either irrelevant or overridden by a later prefix
- x86_PrefixInvalid x86_Prefix = 0x2000 // prefix makes entire instruction invalid (bad LOCK)
-
- // Memory segment overrides.
- x86_PrefixES x86_Prefix = 0x26 // ES segment override
- x86_PrefixCS x86_Prefix = 0x2E // CS segment override
- x86_PrefixSS x86_Prefix = 0x36 // SS segment override
- x86_PrefixDS x86_Prefix = 0x3E // DS segment override
- x86_PrefixFS x86_Prefix = 0x64 // FS segment override
- x86_PrefixGS x86_Prefix = 0x65 // GS segment override
-
- // Branch prediction.
- x86_PrefixPN x86_Prefix = 0x12E // predict not taken (conditional branch only)
- x86_PrefixPT x86_Prefix = 0x13E // predict taken (conditional branch only)
-
- // Size attributes.
- x86_PrefixDataSize x86_Prefix = 0x66 // operand size override
- x86_PrefixData16 x86_Prefix = 0x166
- x86_PrefixData32 x86_Prefix = 0x266
- x86_PrefixAddrSize x86_Prefix = 0x67 // address size override
- x86_PrefixAddr16 x86_Prefix = 0x167
- x86_PrefixAddr32 x86_Prefix = 0x267
-
- // One of a kind.
- x86_PrefixLOCK x86_Prefix = 0xF0 // lock
- x86_PrefixREPN x86_Prefix = 0xF2 // repeat not zero
- x86_PrefixXACQUIRE x86_Prefix = 0x1F2
- x86_PrefixBND x86_Prefix = 0x2F2
- x86_PrefixREP x86_Prefix = 0xF3 // repeat
- x86_PrefixXRELEASE x86_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.
- x86_PrefixREX x86_Prefix = 0x40 // REX 64-bit extension prefix
- x86_PrefixREXW x86_Prefix = 0x08 // extension bit W (64-bit instruction width)
- x86_PrefixREXR x86_Prefix = 0x04 // extension bit R (r field in modrm)
- x86_PrefixREXX x86_Prefix = 0x02 // extension bit X (index field in sib)
- x86_PrefixREXB x86_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 x86_Prefix) IsREX() bool {
- return p&0xF0 == x86_PrefixREX
-}
-
-func (p x86_Prefix) String() string {
- p &^= x86_PrefixImplicit | x86_PrefixIgnored | x86_PrefixInvalid
- if s := x86_prefixNames[p]; s != "" {
- return s
- }
-
- if p.IsREX() {
- s := "REX."
- if p&x86_PrefixREXW != 0 {
- s += "W"
- }
- if p&x86_PrefixREXR != 0 {
- s += "R"
- }
- if p&x86_PrefixREXX != 0 {
- s += "X"
- }
- if p&x86_PrefixREXB != 0 {
- s += "B"
- }
- return s
- }
-
- return fmt.Sprintf("Prefix(%#x)", int(p))
-}
-
-// An Op is an x86 opcode.
-type x86_Op uint32
-
-func (op x86_Op) String() string {
- i := int(op)
- if i < 0 || i >= len(x86_opNames) || x86_opNames[i] == "" {
- return fmt.Sprintf("Op(%d)", i)
- }
- return x86_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 x86_Args [4]x86_Arg
-
-// An Arg is a single instruction argument,
-// one of these types: Reg, Mem, Imm, Rel.
-type x86_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 x86_Reg uint8
-
-const (
- _ x86_Reg = iota
-
- // 8-bit
- x86_AL
- x86_CL
- x86_DL
- x86_BL
- x86_AH
- x86_CH
- x86_DH
- x86_BH
- x86_SPB
- x86_BPB
- x86_SIB
- x86_DIB
- x86_R8B
- x86_R9B
- x86_R10B
- x86_R11B
- x86_R12B
- x86_R13B
- x86_R14B
- x86_R15B
-
- // 16-bit
- x86_AX
- x86_CX
- x86_DX
- x86_BX
- x86_SP
- x86_BP
- x86_SI
- x86_DI
- x86_R8W
- x86_R9W
- x86_R10W
- x86_R11W
- x86_R12W
- x86_R13W
- x86_R14W
- x86_R15W
-
- // 32-bit
- x86_EAX
- x86_ECX
- x86_EDX
- x86_EBX
- x86_ESP
- x86_EBP
- x86_ESI
- x86_EDI
- x86_R8L
- x86_R9L
- x86_R10L
- x86_R11L
- x86_R12L
- x86_R13L
- x86_R14L
- x86_R15L
-
- // 64-bit
- x86_RAX
- x86_RCX
- x86_RDX
- x86_RBX
- x86_RSP
- x86_RBP
- x86_RSI
- x86_RDI
- x86_R8
- x86_R9
- x86_R10
- x86_R11
- x86_R12
- x86_R13
- x86_R14
- x86_R15
-
- // Instruction pointer.
- x86_IP // 16-bit
- x86_EIP // 32-bit
- x86_RIP // 64-bit
-
- // 387 floating point registers.
- x86_F0
- x86_F1
- x86_F2
- x86_F3
- x86_F4
- x86_F5
- x86_F6
- x86_F7
-
- // MMX registers.
- x86_M0
- x86_M1
- x86_M2
- x86_M3
- x86_M4
- x86_M5
- x86_M6
- x86_M7
-
- // XMM registers.
- x86_X0
- x86_X1
- x86_X2
- x86_X3
- x86_X4
- x86_X5
- x86_X6
- x86_X7
- x86_X8
- x86_X9
- x86_X10
- x86_X11
- x86_X12
- x86_X13
- x86_X14
- x86_X15
-
- // Segment registers.
- x86_ES
- x86_CS
- x86_SS
- x86_DS
- x86_FS
- x86_GS
-
- // System registers.
- x86_GDTR
- x86_IDTR
- x86_LDTR
- x86_MSW
- x86_TASK
-
- // Control registers.
- x86_CR0
- x86_CR1
- x86_CR2
- x86_CR3
- x86_CR4
- x86_CR5
- x86_CR6
- x86_CR7
- x86_CR8
- x86_CR9
- x86_CR10
- x86_CR11
- x86_CR12
- x86_CR13
- x86_CR14
- x86_CR15
-
- // Debug registers.
- x86_DR0
- x86_DR1
- x86_DR2
- x86_DR3
- x86_DR4
- x86_DR5
- x86_DR6
- x86_DR7
- x86_DR8
- x86_DR9
- x86_DR10
- x86_DR11
- x86_DR12
- x86_DR13
- x86_DR14
- x86_DR15
-
- // Task registers.
- x86_TR0
- x86_TR1
- x86_TR2
- x86_TR3
- x86_TR4
- x86_TR5
- x86_TR6
- x86_TR7
-)
-
-const x86_regMax = x86_TR7
-
-func (x86_Reg) isArg() {}
-
-func (r x86_Reg) String() string {
- i := int(r)
- if i < 0 || i >= len(x86_regNames) || x86_regNames[i] == "" {
- return fmt.Sprintf("Reg(%d)", i)
- }
- return x86_regNames[i]
-}
-
-// A Mem is a memory reference.
-// The general form is Segment:[Base+Scale*Index+Disp].
-type x86_Mem struct {
- Segment x86_Reg
- Base x86_Reg
- Scale uint8
- Index x86_Reg
- Disp int64
-}
-
-func (x86_Mem) isArg() {}
-
-func (m x86_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 x86_Rel int32
-
-func (x86_Rel) isArg() {}
-
-func (r x86_Rel) String() string {
- return fmt.Sprintf(".%+d", r)
-}
-
-// An Imm is an integer constant.
-type x86_Imm int64
-
-func (x86_Imm) isArg() {}
-
-func (i x86_Imm) String() string {
- return fmt.Sprintf("%#x", int64(i))
-}
-
-func (i x86_Inst) String() string {
- var buf bytes.Buffer
- for _, p := range i.Prefix {
- if p == 0 {
- break
- }
- if p&x86_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 x86_isReg(a x86_Arg) bool {
- _, ok := a.(x86_Reg)
- return ok
-}
-
-func x86_isSegReg(a x86_Arg) bool {
- r, ok := a.(x86_Reg)
- return ok && x86_ES <= r && r <= x86_GS
-}
-
-func x86_isMem(a x86_Arg) bool {
- _, ok := a.(x86_Mem)
- return ok
-}
-
-func x86_isImm(a x86_Arg) bool {
- _, ok := a.(x86_Imm)
- return ok
-}
-
-func x86_regBytes(a x86_Arg) int {
- r, ok := a.(x86_Reg)
- if !ok {
- return 0
- }
- if x86_AL <= r && r <= x86_R15B {
- return 1
- }
- if x86_AX <= r && r <= x86_R15W {
- return 2
- }
- if x86_EAX <= r && r <= x86_R15L {
- return 4
- }
- if x86_RAX <= r && r <= x86_R15 {
- return 8
- }
- return 0
-}
-
-func x86_isSegment(p x86_Prefix) bool {
- switch p {
- case x86_PrefixCS, x86_PrefixDS, x86_PrefixES, x86_PrefixFS, x86_PrefixGS, x86_PrefixSS:
- return true
- }
- return false
-}
-
-// The Op definitions and string list are in tables.go.
-
-var x86_prefixNames = map[x86_Prefix]string{
- x86_PrefixCS: "CS",
- x86_PrefixDS: "DS",
- x86_PrefixES: "ES",
- x86_PrefixFS: "FS",
- x86_PrefixGS: "GS",
- x86_PrefixSS: "SS",
- x86_PrefixLOCK: "LOCK",
- x86_PrefixREP: "REP",
- x86_PrefixREPN: "REPN",
- x86_PrefixAddrSize: "ADDRSIZE",
- x86_PrefixDataSize: "DATASIZE",
- x86_PrefixAddr16: "ADDR16",
- x86_PrefixData16: "DATA16",
- x86_PrefixAddr32: "ADDR32",
- x86_PrefixData32: "DATA32",
- x86_PrefixBND: "BND",
- x86_PrefixXACQUIRE: "XACQUIRE",
- x86_PrefixXRELEASE: "XRELEASE",
- x86_PrefixREX: "REX",
- x86_PrefixPT: "PT",
- x86_PrefixPN: "PN",
-}
-
-var x86_regNames = [...]string{
- x86_AL: "AL",
- x86_CL: "CL",
- x86_BL: "BL",
- x86_DL: "DL",
- x86_AH: "AH",
- x86_CH: "CH",
- x86_BH: "BH",
- x86_DH: "DH",
- x86_SPB: "SPB",
- x86_BPB: "BPB",
- x86_SIB: "SIB",
- x86_DIB: "DIB",
- x86_R8B: "R8B",
- x86_R9B: "R9B",
- x86_R10B: "R10B",
- x86_R11B: "R11B",
- x86_R12B: "R12B",
- x86_R13B: "R13B",
- x86_R14B: "R14B",
- x86_R15B: "R15B",
- x86_AX: "AX",
- x86_CX: "CX",
- x86_BX: "BX",
- x86_DX: "DX",
- x86_SP: "SP",
- x86_BP: "BP",
- x86_SI: "SI",
- x86_DI: "DI",
- x86_R8W: "R8W",
- x86_R9W: "R9W",
- x86_R10W: "R10W",
- x86_R11W: "R11W",
- x86_R12W: "R12W",
- x86_R13W: "R13W",
- x86_R14W: "R14W",
- x86_R15W: "R15W",
- x86_EAX: "EAX",
- x86_ECX: "ECX",
- x86_EDX: "EDX",
- x86_EBX: "EBX",
- x86_ESP: "ESP",
- x86_EBP: "EBP",
- x86_ESI: "ESI",
- x86_EDI: "EDI",
- x86_R8L: "R8L",
- x86_R9L: "R9L",
- x86_R10L: "R10L",
- x86_R11L: "R11L",
- x86_R12L: "R12L",
- x86_R13L: "R13L",
- x86_R14L: "R14L",
- x86_R15L: "R15L",
- x86_RAX: "RAX",
- x86_RCX: "RCX",
- x86_RDX: "RDX",
- x86_RBX: "RBX",
- x86_RSP: "RSP",
- x86_RBP: "RBP",
- x86_RSI: "RSI",
- x86_RDI: "RDI",
- x86_R8: "R8",
- x86_R9: "R9",
- x86_R10: "R10",
- x86_R11: "R11",
- x86_R12: "R12",
- x86_R13: "R13",
- x86_R14: "R14",
- x86_R15: "R15",
- x86_IP: "IP",
- x86_EIP: "EIP",
- x86_RIP: "RIP",
- x86_F0: "F0",
- x86_F1: "F1",
- x86_F2: "F2",
- x86_F3: "F3",
- x86_F4: "F4",
- x86_F5: "F5",
- x86_F6: "F6",
- x86_F7: "F7",
- x86_M0: "M0",
- x86_M1: "M1",
- x86_M2: "M2",
- x86_M3: "M3",
- x86_M4: "M4",
- x86_M5: "M5",
- x86_M6: "M6",
- x86_M7: "M7",
- x86_X0: "X0",
- x86_X1: "X1",
- x86_X2: "X2",
- x86_X3: "X3",
- x86_X4: "X4",
- x86_X5: "X5",
- x86_X6: "X6",
- x86_X7: "X7",
- x86_X8: "X8",
- x86_X9: "X9",
- x86_X10: "X10",
- x86_X11: "X11",
- x86_X12: "X12",
- x86_X13: "X13",
- x86_X14: "X14",
- x86_X15: "X15",
- x86_CS: "CS",
- x86_SS: "SS",
- x86_DS: "DS",
- x86_ES: "ES",
- x86_FS: "FS",
- x86_GS: "GS",
- x86_GDTR: "GDTR",
- x86_IDTR: "IDTR",
- x86_LDTR: "LDTR",
- x86_MSW: "MSW",
- x86_TASK: "TASK",
- x86_CR0: "CR0",
- x86_CR1: "CR1",
- x86_CR2: "CR2",
- x86_CR3: "CR3",
- x86_CR4: "CR4",
- x86_CR5: "CR5",
- x86_CR6: "CR6",
- x86_CR7: "CR7",
- x86_CR8: "CR8",
- x86_CR9: "CR9",
- x86_CR10: "CR10",
- x86_CR11: "CR11",
- x86_CR12: "CR12",
- x86_CR13: "CR13",
- x86_CR14: "CR14",
- x86_CR15: "CR15",
- x86_DR0: "DR0",
- x86_DR1: "DR1",
- x86_DR2: "DR2",
- x86_DR3: "DR3",
- x86_DR4: "DR4",
- x86_DR5: "DR5",
- x86_DR6: "DR6",
- x86_DR7: "DR7",
- x86_DR8: "DR8",
- x86_DR9: "DR9",
- x86_DR10: "DR10",
- x86_DR11: "DR11",
- x86_DR12: "DR12",
- x86_DR13: "DR13",
- x86_DR14: "DR14",
- x86_DR15: "DR15",
- x86_TR0: "TR0",
- x86_TR1: "TR1",
- x86_TR2: "TR2",
- x86_TR3: "TR3",
- x86_TR4: "TR4",
- x86_TR5: "TR5",
- x86_TR6: "TR6",
- x86_TR7: "TR7",
-}
-
-/* intel.go */
-
-// 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.
-
-// IntelSyntax returns the Intel assembler syntax for the instruction, as defined by Intel's XED tool.
-func x86_IntelSyntax(inst x86_Inst) string {
- var iargs []x86_Arg
- for _, a := range inst.Args {
- if a == nil {
- break
- }
- iargs = append(iargs, a)
- }
-
- switch inst.Op {
- case x86_INSB, x86_INSD, x86_INSW, x86_OUTSB, x86_OUTSD, x86_OUTSW, x86_LOOPNE, x86_JCXZ, x86_JECXZ, x86_JRCXZ, x86_LOOP, x86_LOOPE, x86_MOV, x86_XLATB:
- if inst.Op == x86_MOV && (inst.Opcode>>16)&0xFFFC != 0x0F20 {
- break
- }
- for i, p := range inst.Prefix {
- if p&0xFF == x86_PrefixAddrSize {
- inst.Prefix[i] &^= x86_PrefixImplicit
- }
- }
- }
-
- switch inst.Op {
- case x86_MOV:
- dst, _ := inst.Args[0].(x86_Reg)
- src, _ := inst.Args[1].(x86_Reg)
- if x86_ES <= dst && dst <= x86_GS && x86_EAX <= src && src <= x86_R15L {
- src -= x86_EAX - x86_AX
- iargs[1] = src
- }
- if x86_ES <= dst && dst <= x86_GS && x86_RAX <= src && src <= x86_R15 {
- src -= x86_RAX - x86_AX
- iargs[1] = src
- }
-
- if inst.Opcode>>24&^3 == 0xA0 {
- for i, p := range inst.Prefix {
- if p&0xFF == x86_PrefixAddrSize {
- inst.Prefix[i] |= x86_PrefixImplicit
- }
- }
- }
- }
-
- switch inst.Op {
- case x86_AAM, x86_AAD:
- if imm, ok := iargs[0].(x86_Imm); ok {
- if inst.DataSize == 32 {
- iargs[0] = x86_Imm(uint32(int8(imm)))
- } else if inst.DataSize == 16 {
- iargs[0] = x86_Imm(uint16(int8(imm)))
- }
- }
-
- case x86_PUSH:
- if imm, ok := iargs[0].(x86_Imm); ok {
- iargs[0] = x86_Imm(uint32(imm))
- }
- }
-
- for _, p := range inst.Prefix {
- if p&x86_PrefixImplicit != 0 {
- for j, pj := range inst.Prefix {
- if pj&0xFF == p&0xFF {
- inst.Prefix[j] |= x86_PrefixImplicit
- }
- }
- }
- }
-
- if inst.Op != 0 {
- for i, p := range inst.Prefix {
- switch p &^ x86_PrefixIgnored {
- case x86_PrefixData16, x86_PrefixData32, x86_PrefixCS, x86_PrefixDS, x86_PrefixES, x86_PrefixSS:
- inst.Prefix[i] |= x86_PrefixImplicit
- }
- if p.IsREX() {
- inst.Prefix[i] |= x86_PrefixImplicit
- }
- }
- }
-
- if x86_isLoop[inst.Op] || inst.Op == x86_JCXZ || inst.Op == x86_JECXZ || inst.Op == x86_JRCXZ {
- for i, p := range inst.Prefix {
- if p == x86_PrefixPT || p == x86_PrefixPN {
- inst.Prefix[i] |= x86_PrefixImplicit
- }
- }
- }
-
- switch inst.Op {
- case x86_AAA, x86_AAS, x86_CBW, x86_CDQE, x86_CLC, x86_CLD, x86_CLI, x86_CLTS, x86_CMC, x86_CPUID, x86_CQO, x86_CWD, x86_DAA, x86_DAS,
- x86_FDECSTP, x86_FINCSTP, x86_FNCLEX, x86_FNINIT, x86_FNOP, x86_FWAIT, x86_HLT,
- x86_ICEBP, x86_INSB, x86_INSD, x86_INSW, x86_INT, x86_INTO, x86_INVD, x86_IRET, x86_IRETQ,
- x86_LAHF, x86_LEAVE, x86_LRET, x86_MONITOR, x86_MWAIT, x86_NOP, x86_OUTSB, x86_OUTSD, x86_OUTSW,
- x86_PAUSE, x86_POPA, x86_POPF, x86_POPFQ, x86_PUSHA, x86_PUSHF, x86_PUSHFQ,
- x86_RDMSR, x86_RDPMC, x86_RDTSC, x86_RDTSCP, x86_RET, x86_RSM,
- x86_SAHF, x86_STC, x86_STD, x86_STI, x86_SYSENTER, x86_SYSEXIT, x86_SYSRET,
- x86_UD2, x86_WBINVD, x86_WRMSR, x86_XEND, x86_XLATB, x86_XTEST:
-
- if inst.Op == x86_NOP && inst.Opcode>>24 != 0x90 {
- break
- }
- if inst.Op == x86_RET && inst.Opcode>>24 != 0xC3 {
- break
- }
- if inst.Op == x86_INT && inst.Opcode>>24 != 0xCC {
- break
- }
- if inst.Op == x86_LRET && inst.Opcode>>24 != 0xcb {
- break
- }
- for i, p := range inst.Prefix {
- if p&0xFF == x86_PrefixDataSize {
- inst.Prefix[i] &^= x86_PrefixImplicit | x86_PrefixIgnored
- }
- }
-
- case 0:
- // ok
- }
-
- switch inst.Op {
- case x86_INSB, x86_INSD, x86_INSW, x86_OUTSB, x86_OUTSD, x86_OUTSW, x86_MONITOR, x86_MWAIT, x86_XLATB:
- iargs = nil
-
- case x86_STOSB, x86_STOSW, x86_STOSD, x86_STOSQ:
- iargs = iargs[:1]
-
- case x86_LODSB, x86_LODSW, x86_LODSD, x86_LODSQ, x86_SCASB, x86_SCASW, x86_SCASD, x86_SCASQ:
- iargs = iargs[1:]
- }
-
- const (
- haveData16 = 1 << iota
- haveData32
- haveAddr16
- haveAddr32
- haveXacquire
- haveXrelease
- haveLock
- haveHintTaken
- haveHintNotTaken
- haveBnd
- )
- var prefixBits uint32
- prefix := ""
- for _, p := range inst.Prefix {
- if p == 0 {
- break
- }
- if p&0xFF == 0xF3 {
- prefixBits &^= haveBnd
- }
- if p&(x86_PrefixImplicit|x86_PrefixIgnored) != 0 {
- continue
- }
- switch p {
- default:
- prefix += strings.ToLower(p.String()) + " "
- case x86_PrefixCS, x86_PrefixDS, x86_PrefixES, x86_PrefixFS, x86_PrefixGS, x86_PrefixSS:
- if inst.Op == 0 {
- prefix += strings.ToLower(p.String()) + " "
- }
- case x86_PrefixREPN:
- prefix += "repne "
- case x86_PrefixLOCK:
- prefixBits |= haveLock
- case x86_PrefixData16, x86_PrefixDataSize:
- prefixBits |= haveData16
- case x86_PrefixData32:
- prefixBits |= haveData32
- case x86_PrefixAddrSize, x86_PrefixAddr16:
- prefixBits |= haveAddr16
- case x86_PrefixAddr32:
- prefixBits |= haveAddr32
- case x86_PrefixXACQUIRE:
- prefixBits |= haveXacquire
- case x86_PrefixXRELEASE:
- prefixBits |= haveXrelease
- case x86_PrefixPT:
- prefixBits |= haveHintTaken
- case x86_PrefixPN:
- prefixBits |= haveHintNotTaken
- case x86_PrefixBND:
- prefixBits |= haveBnd
- }
- }
- switch inst.Op {
- case x86_JMP:
- if inst.Opcode>>24 == 0xEB {
- prefixBits &^= haveBnd
- }
- case x86_RET, x86_LRET:
- prefixBits &^= haveData16 | haveData32
- }
-
- if prefixBits&haveXacquire != 0 {
- prefix += "xacquire "
- }
- if prefixBits&haveXrelease != 0 {
- prefix += "xrelease "
- }
- if prefixBits&haveLock != 0 {
- prefix += "lock "
- }
- if prefixBits&haveBnd != 0 {
- prefix += "bnd "
- }
- if prefixBits&haveHintTaken != 0 {
- prefix += "hint-taken "
- }
- if prefixBits&haveHintNotTaken != 0 {
- prefix += "hint-not-taken "
- }
- if prefixBits&haveAddr16 != 0 {
- prefix += "addr16 "
- }
- if prefixBits&haveAddr32 != 0 {
- prefix += "addr32 "
- }
- if prefixBits&haveData16 != 0 {
- prefix += "data16 "
- }
- if prefixBits&haveData32 != 0 {
- prefix += "data32 "
- }
-
- if inst.Op == 0 {
- if prefix == "" {
- return "<no instruction>"
- }
- return prefix[:len(prefix)-1]
- }
-
- var args []string
- for _, a := range iargs {
- if a == nil {
- break
- }
- args = append(args, x86_intelArg(&inst, a))
- }
-
- var op string
- switch inst.Op {
- case x86_NOP:
- if inst.Opcode>>24 == 0x0F {
- if inst.DataSize == 16 {
- args = append(args, "ax")
- } else {
- args = append(args, "eax")
- }
- }
-
- case x86_BLENDVPD, x86_BLENDVPS, x86_PBLENDVB:
- args = args[:2]
-
- case x86_INT:
- if inst.Opcode>>24 == 0xCC {
- args = nil
- op = "int3"
- }
-
- case x86_LCALL, x86_LJMP:
- if len(args) == 2 {
- args[0], args[1] = args[1], args[0]
- }
-
- case x86_FCHS, x86_FABS, x86_FTST, x86_FLDPI, x86_FLDL2E, x86_FLDLG2, x86_F2XM1, x86_FXAM, x86_FLD1, x86_FLDL2T, x86_FSQRT, x86_FRNDINT, x86_FCOS, x86_FSIN:
- if len(args) == 0 {
- args = append(args, "st0")
- }
-
- case x86_FPTAN, x86_FSINCOS, x86_FUCOMPP, x86_FCOMPP, x86_FYL2X, x86_FPATAN, x86_FXTRACT, x86_FPREM1, x86_FPREM, x86_FYL2XP1, x86_FSCALE:
- if len(args) == 0 {
- args = []string{"st0", "st1"}
- }
-
- case x86_FST, x86_FSTP, x86_FISTTP, x86_FIST, x86_FISTP, x86_FBSTP:
- if len(args) == 1 {
- args = append(args, "st0")
- }
-
- case x86_FLD, x86_FXCH, x86_FCOM, x86_FCOMP, x86_FIADD, x86_FIMUL, x86_FICOM, x86_FICOMP, x86_FISUBR, x86_FIDIV, x86_FUCOM, x86_FUCOMP, x86_FILD, x86_FBLD, x86_FADD, x86_FMUL, x86_FSUB, x86_FSUBR, x86_FISUB, x86_FDIV, x86_FDIVR, x86_FIDIVR:
- if len(args) == 1 {
- args = []string{"st0", args[0]}
- }
-
- case x86_MASKMOVDQU, x86_MASKMOVQ, x86_XLATB, x86_OUTSB, x86_OUTSW, x86_OUTSD:
- FixSegment:
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- p := inst.Prefix[i] & 0xFF
- switch p {
- case x86_PrefixCS, x86_PrefixES, x86_PrefixFS, x86_PrefixGS, x86_PrefixSS:
- if inst.Mode != 64 || p == x86_PrefixFS || p == x86_PrefixGS {
- args = append(args, strings.ToLower((inst.Prefix[i] & 0xFF).String()))
- break FixSegment
- }
- case x86_PrefixDS:
- if inst.Mode != 64 {
- break FixSegment
- }
- }
- }
- }
-
- if op == "" {
- op = x86_intelOp[inst.Op]
- }
- if op == "" {
- op = strings.ToLower(inst.Op.String())
- }
- if args != nil {
- op += " " + strings.Join(args, ", ")
- }
- return prefix + op
-}
-
-func x86_intelArg(inst *x86_Inst, arg x86_Arg) string {
- switch a := arg.(type) {
- case x86_Imm:
- if inst.Mode == 32 {
- return fmt.Sprintf("%#x", uint32(a))
- }
- if x86_Imm(int32(a)) == a {
- return fmt.Sprintf("%#x", int64(a))
- }
- return fmt.Sprintf("%#x", uint64(a))
- case x86_Mem:
- if a.Base == x86_EIP {
- a.Base = x86_RIP
- }
- prefix := ""
- switch inst.MemBytes {
- case 1:
- prefix = "byte "
- case 2:
- prefix = "word "
- case 4:
- prefix = "dword "
- case 8:
- prefix = "qword "
- case 16:
- prefix = "xmmword "
- }
- switch inst.Op {
- case x86_INVLPG:
- prefix = "byte "
- case x86_STOSB, x86_MOVSB, x86_CMPSB, x86_LODSB, x86_SCASB:
- prefix = "byte "
- case x86_STOSW, x86_MOVSW, x86_CMPSW, x86_LODSW, x86_SCASW:
- prefix = "word "
- case x86_STOSD, x86_MOVSD, x86_CMPSD, x86_LODSD, x86_SCASD:
- prefix = "dword "
- case x86_STOSQ, x86_MOVSQ, x86_CMPSQ, x86_LODSQ, x86_SCASQ:
- prefix = "qword "
- case x86_LAR:
- prefix = "word "
- case x86_BOUND:
- if inst.Mode == 32 {
- prefix = "qword "
- } else {
- prefix = "dword "
- }
- case x86_PREFETCHW, x86_PREFETCHNTA, x86_PREFETCHT0, x86_PREFETCHT1, x86_PREFETCHT2, x86_CLFLUSH:
- prefix = "zmmword "
- }
- switch inst.Op {
- case x86_MOVSB, x86_MOVSW, x86_MOVSD, x86_MOVSQ, x86_CMPSB, x86_CMPSW, x86_CMPSD, x86_CMPSQ, x86_STOSB, x86_STOSW, x86_STOSD, x86_STOSQ, x86_SCASB, x86_SCASW, x86_SCASD, x86_SCASQ, x86_LODSB, x86_LODSW, x86_LODSD, x86_LODSQ:
- switch a.Base {
- case x86_DI, x86_EDI, x86_RDI:
- if a.Segment == x86_ES {
- a.Segment = 0
- }
- case x86_SI, x86_ESI, x86_RSI:
- if a.Segment == x86_DS {
- a.Segment = 0
- }
- }
- case x86_LEA:
- a.Segment = 0
- default:
- switch a.Base {
- case x86_SP, x86_ESP, x86_RSP, x86_BP, x86_EBP, x86_RBP:
- if a.Segment == x86_SS {
- a.Segment = 0
- }
- default:
- if a.Segment == x86_DS {
- a.Segment = 0
- }
- }
- }
-
- if inst.Mode == 64 && a.Segment != x86_FS && a.Segment != x86_GS {
- a.Segment = 0
- }
-
- prefix += "ptr "
- if a.Segment != 0 {
- prefix += strings.ToLower(a.Segment.String()) + ":"
- }
- prefix += "["
- if a.Base != 0 {
- prefix += x86_intelArg(inst, a.Base)
- }
- if a.Scale != 0 && a.Index != 0 {
- if a.Base != 0 {
- prefix += "+"
- }
- prefix += fmt.Sprintf("%s*%d", x86_intelArg(inst, a.Index), a.Scale)
- }
- if a.Disp != 0 {
- if prefix[len(prefix)-1] == '[' && (a.Disp >= 0 || int64(int32(a.Disp)) != a.Disp) {
- prefix += fmt.Sprintf("%#x", uint64(a.Disp))
- } else {
- prefix += fmt.Sprintf("%+#x", a.Disp)
- }
- }
- prefix += "]"
- return prefix
- case x86_Rel:
- return fmt.Sprintf(".%+#x", int64(a))
- case x86_Reg:
- if int(a) < len(x86_intelReg) && x86_intelReg[a] != "" {
- return x86_intelReg[a]
- }
- }
- return strings.ToLower(arg.String())
-}
-
-var x86_intelOp = map[x86_Op]string{
- x86_JAE: "jnb",
- x86_JA: "jnbe",
- x86_JGE: "jnl",
- x86_JNE: "jnz",
- x86_JG: "jnle",
- x86_JE: "jz",
- x86_SETAE: "setnb",
- x86_SETA: "setnbe",
- x86_SETGE: "setnl",
- x86_SETNE: "setnz",
- x86_SETG: "setnle",
- x86_SETE: "setz",
- x86_CMOVAE: "cmovnb",
- x86_CMOVA: "cmovnbe",
- x86_CMOVGE: "cmovnl",
- x86_CMOVNE: "cmovnz",
- x86_CMOVG: "cmovnle",
- x86_CMOVE: "cmovz",
- x86_LCALL: "call far",
- x86_LJMP: "jmp far",
- x86_LRET: "ret far",
- x86_ICEBP: "int1",
- x86_MOVSD_XMM: "movsd",
- x86_XLATB: "xlat",
-}
-
-var x86_intelReg = [...]string{
- x86_F0: "st0",
- x86_F1: "st1",
- x86_F2: "st2",
- x86_F3: "st3",
- x86_F4: "st4",
- x86_F5: "st5",
- x86_F6: "st6",
- x86_F7: "st7",
- x86_M0: "mmx0",
- x86_M1: "mmx1",
- x86_M2: "mmx2",
- x86_M3: "mmx3",
- x86_M4: "mmx4",
- x86_M5: "mmx5",
- x86_M6: "mmx6",
- x86_M7: "mmx7",
- x86_X0: "xmm0",
- x86_X1: "xmm1",
- x86_X2: "xmm2",
- x86_X3: "xmm3",
- x86_X4: "xmm4",
- x86_X5: "xmm5",
- x86_X6: "xmm6",
- x86_X7: "xmm7",
- x86_X8: "xmm8",
- x86_X9: "xmm9",
- x86_X10: "xmm10",
- x86_X11: "xmm11",
- x86_X12: "xmm12",
- x86_X13: "xmm13",
- x86_X14: "xmm14",
- x86_X15: "xmm15",
-
- // TODO: Maybe the constants are named wrong.
- x86_SPB: "spl",
- x86_BPB: "bpl",
- x86_SIB: "sil",
- x86_DIB: "dil",
-
- x86_R8L: "r8d",
- x86_R9L: "r9d",
- x86_R10L: "r10d",
- x86_R11L: "r11d",
- x86_R12L: "r12d",
- x86_R13L: "r13d",
- x86_R14L: "r14d",
- x86_R15L: "r15d",
-}
-
-/* plan9x.go */
-
-// 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.
-
-// 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 x86_plan9Syntax(inst x86_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, x86_plan9Arg(&inst, pc, symname, a))
- }
-
- var last x86_Prefix
- for _, p := range inst.Prefix {
- if p == 0 || p.IsREX() {
- break
- }
- last = p
- }
-
- prefix := ""
- switch last & 0xFF {
- case 0, 0x66, 0x67:
- // ignore
- case x86_PrefixREPN:
- prefix += "REPNE "
- default:
- prefix += last.String() + " "
- }
-
- op := inst.Op.String()
- if x86_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 x86_plan9Arg(inst *x86_Inst, pc uint64, symname func(uint64) (string, uint64), arg x86_Arg) string {
- switch a := arg.(type) {
- case x86_Reg:
- return x86_plan9Reg[a]
- case x86_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 x86_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 x86_Imm(int32(a)) == a {
- return fmt.Sprintf("$%#x", int64(a))
- }
- return fmt.Sprintf("$%#x", uint64(a))
- case x86_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:", x86_plan9Reg[a.Segment])
- }
- if a.Disp != 0 {
- s += fmt.Sprintf("%#x", a.Disp)
- } else {
- s += "0"
- }
- if a.Base != 0 {
- s += fmt.Sprintf("(%s)", x86_plan9Reg[a.Base])
- }
- if a.Index != 0 && a.Scale != 0 {
- s += fmt.Sprintf("(%s*%d)", x86_plan9Reg[a.Index], a.Scale)
- }
- return s
- }
- return arg.String()
-}
-
-var x86_plan9Suffix = [x86_maxOp + 1]bool{
- x86_ADC: true,
- x86_ADD: true,
- x86_AND: true,
- x86_BSF: true,
- x86_BSR: true,
- x86_BT: true,
- x86_BTC: true,
- x86_BTR: true,
- x86_BTS: true,
- x86_CMP: true,
- x86_CMPXCHG: true,
- x86_CVTSI2SD: true,
- x86_CVTSI2SS: true,
- x86_CVTSD2SI: true,
- x86_CVTSS2SI: true,
- x86_CVTTSD2SI: true,
- x86_CVTTSS2SI: true,
- x86_DEC: true,
- x86_DIV: true,
- x86_FLDENV: true,
- x86_FRSTOR: true,
- x86_IDIV: true,
- x86_IMUL: true,
- x86_IN: true,
- x86_INC: true,
- x86_LEA: true,
- x86_MOV: true,
- x86_MOVNTI: true,
- x86_MUL: true,
- x86_NEG: true,
- x86_NOP: true,
- x86_NOT: true,
- x86_OR: true,
- x86_OUT: true,
- x86_POP: true,
- x86_POPA: true,
- x86_PUSH: true,
- x86_PUSHA: true,
- x86_RCL: true,
- x86_RCR: true,
- x86_ROL: true,
- x86_ROR: true,
- x86_SAR: true,
- x86_SBB: true,
- x86_SHL: true,
- x86_SHLD: true,
- x86_SHR: true,
- x86_SHRD: true,
- x86_SUB: true,
- x86_TEST: true,
- x86_XADD: true,
- x86_XCHG: true,
- x86_XOR: true,
-}
-
-var x86_plan9Reg = [...]string{
- x86_AL: "AL",
- x86_CL: "CL",
- x86_BL: "BL",
- x86_DL: "DL",
- x86_AH: "AH",
- x86_CH: "CH",
- x86_BH: "BH",
- x86_DH: "DH",
- x86_SPB: "SP",
- x86_BPB: "BP",
- x86_SIB: "SI",
- x86_DIB: "DI",
- x86_R8B: "R8",
- x86_R9B: "R9",
- x86_R10B: "R10",
- x86_R11B: "R11",
- x86_R12B: "R12",
- x86_R13B: "R13",
- x86_R14B: "R14",
- x86_R15B: "R15",
- x86_AX: "AX",
- x86_CX: "CX",
- x86_BX: "BX",
- x86_DX: "DX",
- x86_SP: "SP",
- x86_BP: "BP",
- x86_SI: "SI",
- x86_DI: "DI",
- x86_R8W: "R8",
- x86_R9W: "R9",
- x86_R10W: "R10",
- x86_R11W: "R11",
- x86_R12W: "R12",
- x86_R13W: "R13",
- x86_R14W: "R14",
- x86_R15W: "R15",
- x86_EAX: "AX",
- x86_ECX: "CX",
- x86_EDX: "DX",
- x86_EBX: "BX",
- x86_ESP: "SP",
- x86_EBP: "BP",
- x86_ESI: "SI",
- x86_EDI: "DI",
- x86_R8L: "R8",
- x86_R9L: "R9",
- x86_R10L: "R10",
- x86_R11L: "R11",
- x86_R12L: "R12",
- x86_R13L: "R13",
- x86_R14L: "R14",
- x86_R15L: "R15",
- x86_RAX: "AX",
- x86_RCX: "CX",
- x86_RDX: "DX",
- x86_RBX: "BX",
- x86_RSP: "SP",
- x86_RBP: "BP",
- x86_RSI: "SI",
- x86_RDI: "DI",
- x86_R8: "R8",
- x86_R9: "R9",
- x86_R10: "R10",
- x86_R11: "R11",
- x86_R12: "R12",
- x86_R13: "R13",
- x86_R14: "R14",
- x86_R15: "R15",
- x86_IP: "IP",
- x86_EIP: "IP",
- x86_RIP: "IP",
- x86_F0: "F0",
- x86_F1: "F1",
- x86_F2: "F2",
- x86_F3: "F3",
- x86_F4: "F4",
- x86_F5: "F5",
- x86_F6: "F6",
- x86_F7: "F7",
- x86_M0: "M0",
- x86_M1: "M1",
- x86_M2: "M2",
- x86_M3: "M3",
- x86_M4: "M4",
- x86_M5: "M5",
- x86_M6: "M6",
- x86_M7: "M7",
- x86_X0: "X0",
- x86_X1: "X1",
- x86_X2: "X2",
- x86_X3: "X3",
- x86_X4: "X4",
- x86_X5: "X5",
- x86_X6: "X6",
- x86_X7: "X7",
- x86_X8: "X8",
- x86_X9: "X9",
- x86_X10: "X10",
- x86_X11: "X11",
- x86_X12: "X12",
- x86_X13: "X13",
- x86_X14: "X14",
- x86_X15: "X15",
- x86_CS: "CS",
- x86_SS: "SS",
- x86_DS: "DS",
- x86_ES: "ES",
- x86_FS: "FS",
- x86_GS: "GS",
- x86_GDTR: "GDTR",
- x86_IDTR: "IDTR",
- x86_LDTR: "LDTR",
- x86_MSW: "MSW",
- x86_TASK: "TASK",
- x86_CR0: "CR0",
- x86_CR1: "CR1",
- x86_CR2: "CR2",
- x86_CR3: "CR3",
- x86_CR4: "CR4",
- x86_CR5: "CR5",
- x86_CR6: "CR6",
- x86_CR7: "CR7",
- x86_CR8: "CR8",
- x86_CR9: "CR9",
- x86_CR10: "CR10",
- x86_CR11: "CR11",
- x86_CR12: "CR12",
- x86_CR13: "CR13",
- x86_CR14: "CR14",
- x86_CR15: "CR15",
- x86_DR0: "DR0",
- x86_DR1: "DR1",
- x86_DR2: "DR2",
- x86_DR3: "DR3",
- x86_DR4: "DR4",
- x86_DR5: "DR5",
- x86_DR6: "DR6",
- x86_DR7: "DR7",
- x86_DR8: "DR8",
- x86_DR9: "DR9",
- x86_DR10: "DR10",
- x86_DR11: "DR11",
- x86_DR12: "DR12",
- x86_DR13: "DR13",
- x86_DR14: "DR14",
- x86_DR15: "DR15",
- x86_TR0: "TR0",
- x86_TR1: "TR1",
- x86_TR2: "TR2",
- x86_TR3: "TR3",
- x86_TR4: "TR4",
- x86_TR5: "TR5",
- x86_TR6: "TR6",
- x86_TR7: "TR7",
-}
-
-/* tables.go */
-
-// DO NOT EDIT
-// generated by: x86map -fmt=decoder ../x86.csv
-
-var x86_decoder = [...]uint16{
- uint16(x86_xFail),
- /*1*/ uint16(x86_xCondByte), 243,
- 0x00, 490,
- 0x01, 496,
- 0x02, 525,
- 0x03, 531,
- 0x04, 560,
- 0x05, 566,
- 0x06, 595,
- 0x07, 602,
- 0x08, 609,
- 0x09, 615,
- 0x0A, 644,
- 0x0B, 650,
- 0x0C, 679,
- 0x0D, 685,
- 0x0E, 714,
- 0x0F, 721,
- 0x10, 8026,
- 0x11, 8032,
- 0x12, 8061,
- 0x13, 8067,
- 0x14, 8096,
- 0x15, 8102,
- 0x16, 8131,
- 0x17, 8138,
- 0x18, 8145,
- 0x19, 8151,
- 0x1A, 8180,
- 0x1B, 8186,
- 0x1C, 8215,
- 0x1D, 8221,
- 0x1E, 8250,
- 0x1F, 8257,
- 0x20, 8264,
- 0x21, 8270,
- 0x22, 8299,
- 0x23, 8305,
- 0x24, 8334,
- 0x25, 8340,
- 0x27, 8369,
- 0x28, 8375,
- 0x29, 8381,
- 0x2A, 8410,
- 0x2B, 8416,
- 0x2C, 8445,
- 0x2D, 8451,
- 0x2F, 8480,
- 0x30, 8486,
- 0x31, 8492,
- 0x32, 8521,
- 0x33, 8527,
- 0x34, 8556,
- 0x35, 8562,
- 0x37, 8591,
- 0x38, 8597,
- 0x39, 8603,
- 0x3A, 8632,
- 0x3B, 8638,
- 0x3C, 8667,
- 0x3D, 8673,
- 0x3F, 8702,
- 0x40, 8708,
- 0x41, 8708,
- 0x42, 8708,
- 0x43, 8708,
- 0x44, 8708,
- 0x45, 8708,
- 0x46, 8708,
- 0x47, 8708,
- 0x48, 8723,
- 0x49, 8723,
- 0x4a, 8723,
- 0x4b, 8723,
- 0x4c, 8723,
- 0x4d, 8723,
- 0x4e, 8723,
- 0x4f, 8723,
- 0x50, 8738,
- 0x51, 8738,
- 0x52, 8738,
- 0x53, 8738,
- 0x54, 8738,
- 0x55, 8738,
- 0x56, 8738,
- 0x57, 8738,
- 0x58, 8765,
- 0x59, 8765,
- 0x5a, 8765,
- 0x5b, 8765,
- 0x5c, 8765,
- 0x5d, 8765,
- 0x5e, 8765,
- 0x5f, 8765,
- 0x60, 8792,
- 0x61, 8805,
- 0x62, 8818,
- 0x63, 8837,
- 0x68, 8868,
- 0x69, 8887,
- 0x6A, 8922,
- 0x6B, 8927,
- 0x6C, 8962,
- 0x6D, 8965,
- 0x6E, 8978,
- 0x6F, 8981,
- 0x70, 8994,
- 0x71, 8999,
- 0x72, 9004,
- 0x73, 9009,
- 0x74, 9014,
- 0x75, 9019,
- 0x76, 9024,
- 0x77, 9029,
- 0x78, 9034,
- 0x79, 9039,
- 0x7A, 9044,
- 0x7B, 9049,
- 0x7C, 9054,
- 0x7D, 9059,
- 0x7E, 9064,
- 0x7F, 9069,
- 0x80, 9074,
- 0x81, 9131,
- 0x83, 9372,
- 0x84, 9613,
- 0x85, 9619,
- 0x86, 9648,
- 0x87, 9654,
- 0x88, 9683,
- 0x89, 9689,
- 0x8A, 9711,
- 0x8B, 9717,
- 0x8C, 9739,
- 0x8D, 9768,
- 0x8E, 9797,
- 0x8F, 9826,
- 0x90, 9862,
- 0x91, 9862,
- 0x92, 9862,
- 0x93, 9862,
- 0x94, 9862,
- 0x95, 9862,
- 0x96, 9862,
- 0x97, 9862,
- 0x98, 9888,
- 0x99, 9908,
- 0x9A, 9928,
- 0x9B, 9945,
- 0x9C, 9948,
- 0x9D, 9971,
- 0x9E, 9994,
- 0x9F, 9997,
- 0xA0, 10000,
- 0xA1, 10019,
- 0xA2, 10041,
- 0xA3, 10060,
- 0xA4, 10082,
- 0xA5, 10085,
- 0xA6, 10105,
- 0xA7, 10108,
- 0xA8, 10128,
- 0xA9, 10134,
- 0xAA, 10163,
- 0xAB, 10166,
- 0xAC, 10186,
- 0xAD, 10189,
- 0xAE, 10209,
- 0xAF, 10212,
- 0xb0, 10232,
- 0xb1, 10232,
- 0xb2, 10232,
- 0xb3, 10232,
- 0xb4, 10232,
- 0xb5, 10232,
- 0xb6, 10232,
- 0xb7, 10232,
- 0xb8, 10238,
- 0xb9, 10238,
- 0xba, 10238,
- 0xbb, 10238,
- 0xbc, 10238,
- 0xbd, 10238,
- 0xbe, 10238,
- 0xbf, 10238,
- 0xC0, 10267,
- 0xC1, 10318,
- 0xC2, 10516,
- 0xC3, 10521,
- 0xC4, 10524,
- 0xC5, 10543,
- 0xC6, 10562,
- 0xC7, 10586,
- 0xC8, 10647,
- 0xC9, 10654,
- 0xCA, 10677,
- 0xCB, 10682,
- 0xCC, 10685,
- 0xCD, 10689,
- 0xCE, 10694,
- 0xCF, 10700,
- 0xD0, 10720,
- 0xD1, 10764,
- 0xD2, 10955,
- 0xD3, 10999,
- 0xD4, 11190,
- 0xD5, 11198,
- 0xD7, 11206,
- 0xD8, 11219,
- 0xD9, 11428,
- 0xDA, 11637,
- 0xDB, 11769,
- 0xDC, 11940,
- 0xDD, 12109,
- 0xDE, 12248,
- 0xDF, 12422,
- 0xE0, 12533,
- 0xE1, 12538,
- 0xE2, 12543,
- 0xE3, 12548,
- 0xE4, 12574,
- 0xE5, 12580,
- 0xE6, 12602,
- 0xE7, 12608,
- 0xE8, 12630,
- 0xE9, 12661,
- 0xEA, 12692,
- 0xEB, 12709,
- 0xEC, 12714,
- 0xED, 12719,
- 0xEE, 12738,
- 0xEF, 12743,
- 0xF1, 12762,
- 0xF4, 12765,
- 0xF5, 12768,
- 0xF6, 12771,
- 0xF7, 12810,
- 0xF8, 12986,
- 0xF9, 12989,
- 0xFA, 12992,
- 0xFB, 12995,
- 0xFC, 12998,
- 0xFD, 13001,
- 0xFE, 13004,
- 0xFF, 13021,
- uint16(x86_xFail),
- /*490*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*492*/ uint16(x86_xReadSlashR),
- /*493*/ uint16(x86_xArgRM8),
- /*494*/ uint16(x86_xArgR8),
- /*495*/ uint16(x86_xMatch),
- /*496*/ uint16(x86_xCondIs64), 499, 515,
- /*499*/ uint16(x86_xCondDataSize), 503, 509, 0,
- /*503*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*505*/ uint16(x86_xReadSlashR),
- /*506*/ uint16(x86_xArgRM16),
- /*507*/ uint16(x86_xArgR16),
- /*508*/ uint16(x86_xMatch),
- /*509*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*511*/ uint16(x86_xReadSlashR),
- /*512*/ uint16(x86_xArgRM32),
- /*513*/ uint16(x86_xArgR32),
- /*514*/ uint16(x86_xMatch),
- /*515*/ uint16(x86_xCondDataSize), 503, 509, 519,
- /*519*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*521*/ uint16(x86_xReadSlashR),
- /*522*/ uint16(x86_xArgRM64),
- /*523*/ uint16(x86_xArgR64),
- /*524*/ uint16(x86_xMatch),
- /*525*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*527*/ uint16(x86_xReadSlashR),
- /*528*/ uint16(x86_xArgR8),
- /*529*/ uint16(x86_xArgRM8),
- /*530*/ uint16(x86_xMatch),
- /*531*/ uint16(x86_xCondIs64), 534, 550,
- /*534*/ uint16(x86_xCondDataSize), 538, 544, 0,
- /*538*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*540*/ uint16(x86_xReadSlashR),
- /*541*/ uint16(x86_xArgR16),
- /*542*/ uint16(x86_xArgRM16),
- /*543*/ uint16(x86_xMatch),
- /*544*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*546*/ uint16(x86_xReadSlashR),
- /*547*/ uint16(x86_xArgR32),
- /*548*/ uint16(x86_xArgRM32),
- /*549*/ uint16(x86_xMatch),
- /*550*/ uint16(x86_xCondDataSize), 538, 544, 554,
- /*554*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*556*/ uint16(x86_xReadSlashR),
- /*557*/ uint16(x86_xArgR64),
- /*558*/ uint16(x86_xArgRM64),
- /*559*/ uint16(x86_xMatch),
- /*560*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*562*/ uint16(x86_xReadIb),
- /*563*/ uint16(x86_xArgAL),
- /*564*/ uint16(x86_xArgImm8u),
- /*565*/ uint16(x86_xMatch),
- /*566*/ uint16(x86_xCondIs64), 569, 585,
- /*569*/ uint16(x86_xCondDataSize), 573, 579, 0,
- /*573*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*575*/ uint16(x86_xReadIw),
- /*576*/ uint16(x86_xArgAX),
- /*577*/ uint16(x86_xArgImm16),
- /*578*/ uint16(x86_xMatch),
- /*579*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*581*/ uint16(x86_xReadId),
- /*582*/ uint16(x86_xArgEAX),
- /*583*/ uint16(x86_xArgImm32),
- /*584*/ uint16(x86_xMatch),
- /*585*/ uint16(x86_xCondDataSize), 573, 579, 589,
- /*589*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*591*/ uint16(x86_xReadId),
- /*592*/ uint16(x86_xArgRAX),
- /*593*/ uint16(x86_xArgImm32),
- /*594*/ uint16(x86_xMatch),
- /*595*/ uint16(x86_xCondIs64), 598, 0,
- /*598*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*600*/ uint16(x86_xArgES),
- /*601*/ uint16(x86_xMatch),
- /*602*/ uint16(x86_xCondIs64), 605, 0,
- /*605*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*607*/ uint16(x86_xArgES),
- /*608*/ uint16(x86_xMatch),
- /*609*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*611*/ uint16(x86_xReadSlashR),
- /*612*/ uint16(x86_xArgRM8),
- /*613*/ uint16(x86_xArgR8),
- /*614*/ uint16(x86_xMatch),
- /*615*/ uint16(x86_xCondIs64), 618, 634,
- /*618*/ uint16(x86_xCondDataSize), 622, 628, 0,
- /*622*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*624*/ uint16(x86_xReadSlashR),
- /*625*/ uint16(x86_xArgRM16),
- /*626*/ uint16(x86_xArgR16),
- /*627*/ uint16(x86_xMatch),
- /*628*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*630*/ uint16(x86_xReadSlashR),
- /*631*/ uint16(x86_xArgRM32),
- /*632*/ uint16(x86_xArgR32),
- /*633*/ uint16(x86_xMatch),
- /*634*/ uint16(x86_xCondDataSize), 622, 628, 638,
- /*638*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*640*/ uint16(x86_xReadSlashR),
- /*641*/ uint16(x86_xArgRM64),
- /*642*/ uint16(x86_xArgR64),
- /*643*/ uint16(x86_xMatch),
- /*644*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*646*/ uint16(x86_xReadSlashR),
- /*647*/ uint16(x86_xArgR8),
- /*648*/ uint16(x86_xArgRM8),
- /*649*/ uint16(x86_xMatch),
- /*650*/ uint16(x86_xCondIs64), 653, 669,
- /*653*/ uint16(x86_xCondDataSize), 657, 663, 0,
- /*657*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*659*/ uint16(x86_xReadSlashR),
- /*660*/ uint16(x86_xArgR16),
- /*661*/ uint16(x86_xArgRM16),
- /*662*/ uint16(x86_xMatch),
- /*663*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*665*/ uint16(x86_xReadSlashR),
- /*666*/ uint16(x86_xArgR32),
- /*667*/ uint16(x86_xArgRM32),
- /*668*/ uint16(x86_xMatch),
- /*669*/ uint16(x86_xCondDataSize), 657, 663, 673,
- /*673*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*675*/ uint16(x86_xReadSlashR),
- /*676*/ uint16(x86_xArgR64),
- /*677*/ uint16(x86_xArgRM64),
- /*678*/ uint16(x86_xMatch),
- /*679*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*681*/ uint16(x86_xReadIb),
- /*682*/ uint16(x86_xArgAL),
- /*683*/ uint16(x86_xArgImm8u),
- /*684*/ uint16(x86_xMatch),
- /*685*/ uint16(x86_xCondIs64), 688, 704,
- /*688*/ uint16(x86_xCondDataSize), 692, 698, 0,
- /*692*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*694*/ uint16(x86_xReadIw),
- /*695*/ uint16(x86_xArgAX),
- /*696*/ uint16(x86_xArgImm16),
- /*697*/ uint16(x86_xMatch),
- /*698*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*700*/ uint16(x86_xReadId),
- /*701*/ uint16(x86_xArgEAX),
- /*702*/ uint16(x86_xArgImm32),
- /*703*/ uint16(x86_xMatch),
- /*704*/ uint16(x86_xCondDataSize), 692, 698, 708,
- /*708*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*710*/ uint16(x86_xReadId),
- /*711*/ uint16(x86_xArgRAX),
- /*712*/ uint16(x86_xArgImm32),
- /*713*/ uint16(x86_xMatch),
- /*714*/ uint16(x86_xCondIs64), 717, 0,
- /*717*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*719*/ uint16(x86_xArgCS),
- /*720*/ uint16(x86_xMatch),
- /*721*/ uint16(x86_xCondByte), 228,
- 0x00, 1180,
- 0x01, 1237,
- 0x02, 1345,
- 0x03, 1367,
- 0x05, 1389,
- 0x06, 1395,
- 0x07, 1398,
- 0x08, 1404,
- 0x09, 1407,
- 0x0B, 1410,
- 0x0D, 1413,
- 0x10, 1426,
- 0x11, 1460,
- 0x12, 1494,
- 0x13, 1537,
- 0x14, 1555,
- 0x15, 1573,
- 0x16, 1591,
- 0x17, 1626,
- 0x18, 1644,
- 0x1F, 1669,
- 0x20, 1690,
- 0x21, 1705,
- 0x22, 1720,
- 0x23, 1735,
- 0x24, 1750,
- 0x26, 1765,
- 0x28, 1780,
- 0x29, 1798,
- 0x2A, 1816,
- 0x2B, 1903,
- 0x2C, 1937,
- 0x2D, 2024,
- 0x2E, 2111,
- 0x2F, 2129,
- 0x30, 2147,
- 0x31, 2150,
- 0x32, 2153,
- 0x33, 2156,
- 0x34, 2159,
- 0x35, 2162,
- 0x38, 2172,
- 0x3A, 3073,
- 0x40, 3484,
- 0x41, 3513,
- 0x42, 3542,
- 0x43, 3571,
- 0x44, 3600,
- 0x45, 3629,
- 0x46, 3658,
- 0x47, 3687,
- 0x48, 3716,
- 0x49, 3745,
- 0x4A, 3774,
- 0x4B, 3803,
- 0x4C, 3832,
- 0x4D, 3861,
- 0x4E, 3890,
- 0x4F, 3919,
- 0x50, 3948,
- 0x51, 3966,
- 0x52, 4000,
- 0x53, 4018,
- 0x54, 4036,
- 0x55, 4054,
- 0x56, 4072,
- 0x57, 4090,
- 0x58, 4108,
- 0x59, 4142,
- 0x5A, 4176,
- 0x5B, 4210,
- 0x5C, 4236,
- 0x5D, 4270,
- 0x5E, 4304,
- 0x5F, 4338,
- 0x60, 4372,
- 0x61, 4390,
- 0x62, 4408,
- 0x63, 4426,
- 0x64, 4444,
- 0x65, 4462,
- 0x66, 4480,
- 0x67, 4498,
- 0x68, 4516,
- 0x69, 4534,
- 0x6A, 4552,
- 0x6B, 4570,
- 0x6C, 4588,
- 0x6D, 4598,
- 0x6E, 4608,
- 0x6F, 4675,
- 0x70, 4701,
- 0x71, 4743,
- 0x72, 4806,
- 0x73, 4869,
- 0x74, 4934,
- 0x75, 4952,
- 0x76, 4970,
- 0x77, 4988,
- 0x7C, 4991,
- 0x7D, 5009,
- 0x7E, 5027,
- 0x7F, 5104,
- 0x80, 5130,
- 0x81, 5161,
- 0x82, 5192,
- 0x83, 5223,
- 0x84, 5254,
- 0x85, 5285,
- 0x86, 5316,
- 0x87, 5347,
- 0x88, 5378,
- 0x89, 5409,
- 0x8A, 5440,
- 0x8B, 5471,
- 0x8C, 5502,
- 0x8D, 5533,
- 0x8E, 5564,
- 0x8F, 5595,
- 0x90, 5626,
- 0x91, 5631,
- 0x92, 5636,
- 0x93, 5641,
- 0x94, 5646,
- 0x95, 5651,
- 0x96, 5656,
- 0x97, 5661,
- 0x98, 5666,
- 0x99, 5671,
- 0x9A, 5676,
- 0x9B, 5681,
- 0x9C, 5686,
- 0x9D, 5691,
- 0x9E, 5696,
- 0x9F, 5701,
- 0xA0, 5706,
- 0xA1, 5710,
- 0xA2, 5737,
- 0xA3, 5740,
- 0xA4, 5769,
- 0xA5, 5804,
- 0xA8, 5836,
- 0xA9, 5840,
- 0xAA, 5867,
- 0xAB, 5870,
- 0xAC, 5899,
- 0xAD, 5934,
- 0xAE, 5966,
- 0xAF, 6224,
- 0xB0, 6253,
- 0xB1, 6259,
- 0xB2, 6288,
- 0xB3, 6317,
- 0xB4, 6346,
- 0xB5, 6375,
- 0xB6, 6404,
- 0xB7, 6433,
- 0xB8, 6462,
- 0xB9, 6499,
- 0xBA, 6502,
- 0xBB, 6627,
- 0xBC, 6656,
- 0xBD, 6723,
- 0xBE, 6790,
- 0xBF, 6819,
- 0xC0, 6848,
- 0xC1, 6854,
- 0xC2, 6883,
- 0xC3, 6925,
- 0xC4, 6954,
- 0xC5, 6976,
- 0xC6, 6998,
- 0xC7, 7020,
- 0xc8, 7149,
- 0xc9, 7149,
- 0xca, 7149,
- 0xcb, 7149,
- 0xcc, 7149,
- 0xcd, 7149,
- 0xce, 7149,
- 0xcf, 7149,
- 0xD0, 7172,
- 0xD1, 7190,
- 0xD2, 7208,
- 0xD3, 7226,
- 0xD4, 7244,
- 0xD5, 7262,
- 0xD6, 7280,
- 0xD7, 7306,
- 0xD8, 7324,
- 0xD9, 7342,
- 0xDA, 7360,
- 0xDB, 7378,
- 0xDC, 7396,
- 0xDD, 7414,
- 0xDE, 7432,
- 0xDF, 7450,
- 0xE0, 7468,
- 0xE1, 7486,
- 0xE2, 7504,
- 0xE3, 7522,
- 0xE4, 7540,
- 0xE5, 7558,
- 0xE6, 7576,
- 0xE7, 7602,
- 0xE8, 7620,
- 0xE9, 7638,
- 0xEA, 7656,
- 0xEB, 7674,
- 0xEC, 7692,
- 0xED, 7710,
- 0xEE, 7728,
- 0xEF, 7746,
- 0xF0, 7764,
- 0xF1, 7774,
- 0xF2, 7792,
- 0xF3, 7810,
- 0xF4, 7828,
- 0xF5, 7846,
- 0xF6, 7864,
- 0xF7, 7882,
- 0xF8, 7900,
- 0xF9, 7918,
- 0xFA, 7936,
- 0xFB, 7954,
- 0xFC, 7972,
- 0xFD, 7990,
- 0xFE, 8008,
- uint16(x86_xFail),
- /*1180*/ uint16(x86_xCondSlashR),
- 1189, // 0
- 1205, // 1
- 1221, // 2
- 1225, // 3
- 1229, // 4
- 1233, // 5
- 0, // 6
- 0, // 7
- /*1189*/ uint16(x86_xCondDataSize), 1193, 1197, 1201,
- /*1193*/ uint16(x86_xSetOp), uint16(x86_SLDT),
- /*1195*/ uint16(x86_xArgRM16),
- /*1196*/ uint16(x86_xMatch),
- /*1197*/ uint16(x86_xSetOp), uint16(x86_SLDT),
- /*1199*/ uint16(x86_xArgR32M16),
- /*1200*/ uint16(x86_xMatch),
- /*1201*/ uint16(x86_xSetOp), uint16(x86_SLDT),
- /*1203*/ uint16(x86_xArgR64M16),
- /*1204*/ uint16(x86_xMatch),
- /*1205*/ uint16(x86_xCondDataSize), 1209, 1213, 1217,
- /*1209*/ uint16(x86_xSetOp), uint16(x86_STR),
- /*1211*/ uint16(x86_xArgRM16),
- /*1212*/ uint16(x86_xMatch),
- /*1213*/ uint16(x86_xSetOp), uint16(x86_STR),
- /*1215*/ uint16(x86_xArgR32M16),
- /*1216*/ uint16(x86_xMatch),
- /*1217*/ uint16(x86_xSetOp), uint16(x86_STR),
- /*1219*/ uint16(x86_xArgR64M16),
- /*1220*/ uint16(x86_xMatch),
- /*1221*/ uint16(x86_xSetOp), uint16(x86_LLDT),
- /*1223*/ uint16(x86_xArgRM16),
- /*1224*/ uint16(x86_xMatch),
- /*1225*/ uint16(x86_xSetOp), uint16(x86_LTR),
- /*1227*/ uint16(x86_xArgRM16),
- /*1228*/ uint16(x86_xMatch),
- /*1229*/ uint16(x86_xSetOp), uint16(x86_VERR),
- /*1231*/ uint16(x86_xArgRM16),
- /*1232*/ uint16(x86_xMatch),
- /*1233*/ uint16(x86_xSetOp), uint16(x86_VERW),
- /*1235*/ uint16(x86_xArgRM16),
- /*1236*/ uint16(x86_xMatch),
- /*1237*/ uint16(x86_xCondByte), 8,
- 0xC8, 1318,
- 0xC9, 1321,
- 0xD0, 1324,
- 0xD1, 1327,
- 0xD5, 1330,
- 0xD6, 1333,
- 0xF8, 1336,
- 0xF9, 1342,
- /*1255*/ uint16(x86_xCondSlashR),
- 1264, // 0
- 1268, // 1
- 1272, // 2
- 1283, // 3
- 1294, // 4
- 0, // 5
- 1310, // 6
- 1314, // 7
- /*1264*/ uint16(x86_xSetOp), uint16(x86_SGDT),
- /*1266*/ uint16(x86_xArgM),
- /*1267*/ uint16(x86_xMatch),
- /*1268*/ uint16(x86_xSetOp), uint16(x86_SIDT),
- /*1270*/ uint16(x86_xArgM),
- /*1271*/ uint16(x86_xMatch),
- /*1272*/ uint16(x86_xCondIs64), 1275, 1279,
- /*1275*/ uint16(x86_xSetOp), uint16(x86_LGDT),
- /*1277*/ uint16(x86_xArgM16and32),
- /*1278*/ uint16(x86_xMatch),
- /*1279*/ uint16(x86_xSetOp), uint16(x86_LGDT),
- /*1281*/ uint16(x86_xArgM16and64),
- /*1282*/ uint16(x86_xMatch),
- /*1283*/ uint16(x86_xCondIs64), 1286, 1290,
- /*1286*/ uint16(x86_xSetOp), uint16(x86_LIDT),
- /*1288*/ uint16(x86_xArgM16and32),
- /*1289*/ uint16(x86_xMatch),
- /*1290*/ uint16(x86_xSetOp), uint16(x86_LIDT),
- /*1292*/ uint16(x86_xArgM16and64),
- /*1293*/ uint16(x86_xMatch),
- /*1294*/ uint16(x86_xCondDataSize), 1298, 1302, 1306,
- /*1298*/ uint16(x86_xSetOp), uint16(x86_SMSW),
- /*1300*/ uint16(x86_xArgRM16),
- /*1301*/ uint16(x86_xMatch),
- /*1302*/ uint16(x86_xSetOp), uint16(x86_SMSW),
- /*1304*/ uint16(x86_xArgR32M16),
- /*1305*/ uint16(x86_xMatch),
- /*1306*/ uint16(x86_xSetOp), uint16(x86_SMSW),
- /*1308*/ uint16(x86_xArgR64M16),
- /*1309*/ uint16(x86_xMatch),
- /*1310*/ uint16(x86_xSetOp), uint16(x86_LMSW),
- /*1312*/ uint16(x86_xArgRM16),
- /*1313*/ uint16(x86_xMatch),
- /*1314*/ uint16(x86_xSetOp), uint16(x86_INVLPG),
- /*1316*/ uint16(x86_xArgM),
- /*1317*/ uint16(x86_xMatch),
- /*1318*/ uint16(x86_xSetOp), uint16(x86_MONITOR),
- /*1320*/ uint16(x86_xMatch),
- /*1321*/ uint16(x86_xSetOp), uint16(x86_MWAIT),
- /*1323*/ uint16(x86_xMatch),
- /*1324*/ uint16(x86_xSetOp), uint16(x86_XGETBV),
- /*1326*/ uint16(x86_xMatch),
- /*1327*/ uint16(x86_xSetOp), uint16(x86_XSETBV),
- /*1329*/ uint16(x86_xMatch),
- /*1330*/ uint16(x86_xSetOp), uint16(x86_XEND),
- /*1332*/ uint16(x86_xMatch),
- /*1333*/ uint16(x86_xSetOp), uint16(x86_XTEST),
- /*1335*/ uint16(x86_xMatch),
- /*1336*/ uint16(x86_xCondIs64), 0, 1339,
- /*1339*/ uint16(x86_xSetOp), uint16(x86_SWAPGS),
- /*1341*/ uint16(x86_xMatch),
- /*1342*/ uint16(x86_xSetOp), uint16(x86_RDTSCP),
- /*1344*/ uint16(x86_xMatch),
- /*1345*/ uint16(x86_xCondDataSize), 1349, 1355, 1361,
- /*1349*/ uint16(x86_xSetOp), uint16(x86_LAR),
- /*1351*/ uint16(x86_xReadSlashR),
- /*1352*/ uint16(x86_xArgR16),
- /*1353*/ uint16(x86_xArgRM16),
- /*1354*/ uint16(x86_xMatch),
- /*1355*/ uint16(x86_xSetOp), uint16(x86_LAR),
- /*1357*/ uint16(x86_xReadSlashR),
- /*1358*/ uint16(x86_xArgR32),
- /*1359*/ uint16(x86_xArgR32M16),
- /*1360*/ uint16(x86_xMatch),
- /*1361*/ uint16(x86_xSetOp), uint16(x86_LAR),
- /*1363*/ uint16(x86_xReadSlashR),
- /*1364*/ uint16(x86_xArgR64),
- /*1365*/ uint16(x86_xArgR64M16),
- /*1366*/ uint16(x86_xMatch),
- /*1367*/ uint16(x86_xCondDataSize), 1371, 1377, 1383,
- /*1371*/ uint16(x86_xSetOp), uint16(x86_LSL),
- /*1373*/ uint16(x86_xReadSlashR),
- /*1374*/ uint16(x86_xArgR16),
- /*1375*/ uint16(x86_xArgRM16),
- /*1376*/ uint16(x86_xMatch),
- /*1377*/ uint16(x86_xSetOp), uint16(x86_LSL),
- /*1379*/ uint16(x86_xReadSlashR),
- /*1380*/ uint16(x86_xArgR32),
- /*1381*/ uint16(x86_xArgR32M16),
- /*1382*/ uint16(x86_xMatch),
- /*1383*/ uint16(x86_xSetOp), uint16(x86_LSL),
- /*1385*/ uint16(x86_xReadSlashR),
- /*1386*/ uint16(x86_xArgR64),
- /*1387*/ uint16(x86_xArgR32M16),
- /*1388*/ uint16(x86_xMatch),
- /*1389*/ uint16(x86_xCondIs64), 0, 1392,
- /*1392*/ uint16(x86_xSetOp), uint16(x86_SYSCALL),
- /*1394*/ uint16(x86_xMatch),
- /*1395*/ uint16(x86_xSetOp), uint16(x86_CLTS),
- /*1397*/ uint16(x86_xMatch),
- /*1398*/ uint16(x86_xCondIs64), 0, 1401,
- /*1401*/ uint16(x86_xSetOp), uint16(x86_SYSRET),
- /*1403*/ uint16(x86_xMatch),
- /*1404*/ uint16(x86_xSetOp), uint16(x86_INVD),
- /*1406*/ uint16(x86_xMatch),
- /*1407*/ uint16(x86_xSetOp), uint16(x86_WBINVD),
- /*1409*/ uint16(x86_xMatch),
- /*1410*/ uint16(x86_xSetOp), uint16(x86_UD2),
- /*1412*/ uint16(x86_xMatch),
- /*1413*/ uint16(x86_xCondSlashR),
- 0, // 0
- 1422, // 1
- 0, // 2
- 0, // 3
- 0, // 4
- 0, // 5
- 0, // 6
- 0, // 7
- /*1422*/ uint16(x86_xSetOp), uint16(x86_PREFETCHW),
- /*1424*/ uint16(x86_xArgM8),
- /*1425*/ uint16(x86_xMatch),
- /*1426*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 1454,
- 0xF2, 1448,
- 0x66, 1442,
- 0x0, 1436,
- /*1436*/ uint16(x86_xSetOp), uint16(x86_MOVUPS),
- /*1438*/ uint16(x86_xReadSlashR),
- /*1439*/ uint16(x86_xArgXmm1),
- /*1440*/ uint16(x86_xArgXmm2M128),
- /*1441*/ uint16(x86_xMatch),
- /*1442*/ uint16(x86_xSetOp), uint16(x86_MOVUPD),
- /*1444*/ uint16(x86_xReadSlashR),
- /*1445*/ uint16(x86_xArgXmm1),
- /*1446*/ uint16(x86_xArgXmm2M128),
- /*1447*/ uint16(x86_xMatch),
- /*1448*/ uint16(x86_xSetOp), uint16(x86_MOVSD_XMM),
- /*1450*/ uint16(x86_xReadSlashR),
- /*1451*/ uint16(x86_xArgXmm1),
- /*1452*/ uint16(x86_xArgXmm2M64),
- /*1453*/ uint16(x86_xMatch),
- /*1454*/ uint16(x86_xSetOp), uint16(x86_MOVSS),
- /*1456*/ uint16(x86_xReadSlashR),
- /*1457*/ uint16(x86_xArgXmm1),
- /*1458*/ uint16(x86_xArgXmm2M32),
- /*1459*/ uint16(x86_xMatch),
- /*1460*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 1488,
- 0xF2, 1482,
- 0x66, 1476,
- 0x0, 1470,
- /*1470*/ uint16(x86_xSetOp), uint16(x86_MOVUPS),
- /*1472*/ uint16(x86_xReadSlashR),
- /*1473*/ uint16(x86_xArgXmm2M128),
- /*1474*/ uint16(x86_xArgXmm1),
- /*1475*/ uint16(x86_xMatch),
- /*1476*/ uint16(x86_xSetOp), uint16(x86_MOVUPD),
- /*1478*/ uint16(x86_xReadSlashR),
- /*1479*/ uint16(x86_xArgXmm2M128),
- /*1480*/ uint16(x86_xArgXmm),
- /*1481*/ uint16(x86_xMatch),
- /*1482*/ uint16(x86_xSetOp), uint16(x86_MOVSD_XMM),
- /*1484*/ uint16(x86_xReadSlashR),
- /*1485*/ uint16(x86_xArgXmm2M64),
- /*1486*/ uint16(x86_xArgXmm1),
- /*1487*/ uint16(x86_xMatch),
- /*1488*/ uint16(x86_xSetOp), uint16(x86_MOVSS),
- /*1490*/ uint16(x86_xReadSlashR),
- /*1491*/ uint16(x86_xArgXmm2M32),
- /*1492*/ uint16(x86_xArgXmm),
- /*1493*/ uint16(x86_xMatch),
- /*1494*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 1531,
- 0xF2, 1525,
- 0x66, 1519,
- 0x0, 1504,
- /*1504*/ uint16(x86_xCondIsMem), 1507, 1513,
- /*1507*/ uint16(x86_xSetOp), uint16(x86_MOVHLPS),
- /*1509*/ uint16(x86_xReadSlashR),
- /*1510*/ uint16(x86_xArgXmm1),
- /*1511*/ uint16(x86_xArgXmm2),
- /*1512*/ uint16(x86_xMatch),
- /*1513*/ uint16(x86_xSetOp), uint16(x86_MOVLPS),
- /*1515*/ uint16(x86_xReadSlashR),
- /*1516*/ uint16(x86_xArgXmm),
- /*1517*/ uint16(x86_xArgM64),
- /*1518*/ uint16(x86_xMatch),
- /*1519*/ uint16(x86_xSetOp), uint16(x86_MOVLPD),
- /*1521*/ uint16(x86_xReadSlashR),
- /*1522*/ uint16(x86_xArgXmm),
- /*1523*/ uint16(x86_xArgXmm2M64),
- /*1524*/ uint16(x86_xMatch),
- /*1525*/ uint16(x86_xSetOp), uint16(x86_MOVDDUP),
- /*1527*/ uint16(x86_xReadSlashR),
- /*1528*/ uint16(x86_xArgXmm1),
- /*1529*/ uint16(x86_xArgXmm2M64),
- /*1530*/ uint16(x86_xMatch),
- /*1531*/ uint16(x86_xSetOp), uint16(x86_MOVSLDUP),
- /*1533*/ uint16(x86_xReadSlashR),
- /*1534*/ uint16(x86_xArgXmm1),
- /*1535*/ uint16(x86_xArgXmm2M128),
- /*1536*/ uint16(x86_xMatch),
- /*1537*/ uint16(x86_xCondPrefix), 2,
- 0x66, 1549,
- 0x0, 1543,
- /*1543*/ uint16(x86_xSetOp), uint16(x86_MOVLPS),
- /*1545*/ uint16(x86_xReadSlashR),
- /*1546*/ uint16(x86_xArgM64),
- /*1547*/ uint16(x86_xArgXmm),
- /*1548*/ uint16(x86_xMatch),
- /*1549*/ uint16(x86_xSetOp), uint16(x86_MOVLPD),
- /*1551*/ uint16(x86_xReadSlashR),
- /*1552*/ uint16(x86_xArgXmm2M64),
- /*1553*/ uint16(x86_xArgXmm),
- /*1554*/ uint16(x86_xMatch),
- /*1555*/ uint16(x86_xCondPrefix), 2,
- 0x66, 1567,
- 0x0, 1561,
- /*1561*/ uint16(x86_xSetOp), uint16(x86_UNPCKLPS),
- /*1563*/ uint16(x86_xReadSlashR),
- /*1564*/ uint16(x86_xArgXmm1),
- /*1565*/ uint16(x86_xArgXmm2M128),
- /*1566*/ uint16(x86_xMatch),
- /*1567*/ uint16(x86_xSetOp), uint16(x86_UNPCKLPD),
- /*1569*/ uint16(x86_xReadSlashR),
- /*1570*/ uint16(x86_xArgXmm1),
- /*1571*/ uint16(x86_xArgXmm2M128),
- /*1572*/ uint16(x86_xMatch),
- /*1573*/ uint16(x86_xCondPrefix), 2,
- 0x66, 1585,
- 0x0, 1579,
- /*1579*/ uint16(x86_xSetOp), uint16(x86_UNPCKHPS),
- /*1581*/ uint16(x86_xReadSlashR),
- /*1582*/ uint16(x86_xArgXmm1),
- /*1583*/ uint16(x86_xArgXmm2M128),
- /*1584*/ uint16(x86_xMatch),
- /*1585*/ uint16(x86_xSetOp), uint16(x86_UNPCKHPD),
- /*1587*/ uint16(x86_xReadSlashR),
- /*1588*/ uint16(x86_xArgXmm1),
- /*1589*/ uint16(x86_xArgXmm2M128),
- /*1590*/ uint16(x86_xMatch),
- /*1591*/ uint16(x86_xCondPrefix), 3,
- 0xF3, 1620,
- 0x66, 1614,
- 0x0, 1599,
- /*1599*/ uint16(x86_xCondIsMem), 1602, 1608,
- /*1602*/ uint16(x86_xSetOp), uint16(x86_MOVLHPS),
- /*1604*/ uint16(x86_xReadSlashR),
- /*1605*/ uint16(x86_xArgXmm1),
- /*1606*/ uint16(x86_xArgXmm2),
- /*1607*/ uint16(x86_xMatch),
- /*1608*/ uint16(x86_xSetOp), uint16(x86_MOVHPS),
- /*1610*/ uint16(x86_xReadSlashR),
- /*1611*/ uint16(x86_xArgXmm),
- /*1612*/ uint16(x86_xArgM64),
- /*1613*/ uint16(x86_xMatch),
- /*1614*/ uint16(x86_xSetOp), uint16(x86_MOVHPD),
- /*1616*/ uint16(x86_xReadSlashR),
- /*1617*/ uint16(x86_xArgXmm),
- /*1618*/ uint16(x86_xArgXmm2M64),
- /*1619*/ uint16(x86_xMatch),
- /*1620*/ uint16(x86_xSetOp), uint16(x86_MOVSHDUP),
- /*1622*/ uint16(x86_xReadSlashR),
- /*1623*/ uint16(x86_xArgXmm1),
- /*1624*/ uint16(x86_xArgXmm2M128),
- /*1625*/ uint16(x86_xMatch),
- /*1626*/ uint16(x86_xCondPrefix), 2,
- 0x66, 1638,
- 0x0, 1632,
- /*1632*/ uint16(x86_xSetOp), uint16(x86_MOVHPS),
- /*1634*/ uint16(x86_xReadSlashR),
- /*1635*/ uint16(x86_xArgM64),
- /*1636*/ uint16(x86_xArgXmm),
- /*1637*/ uint16(x86_xMatch),
- /*1638*/ uint16(x86_xSetOp), uint16(x86_MOVHPD),
- /*1640*/ uint16(x86_xReadSlashR),
- /*1641*/ uint16(x86_xArgXmm2M64),
- /*1642*/ uint16(x86_xArgXmm),
- /*1643*/ uint16(x86_xMatch),
- /*1644*/ uint16(x86_xCondSlashR),
- 1653, // 0
- 1657, // 1
- 1661, // 2
- 1665, // 3
- 0, // 4
- 0, // 5
- 0, // 6
- 0, // 7
- /*1653*/ uint16(x86_xSetOp), uint16(x86_PREFETCHNTA),
- /*1655*/ uint16(x86_xArgM8),
- /*1656*/ uint16(x86_xMatch),
- /*1657*/ uint16(x86_xSetOp), uint16(x86_PREFETCHT0),
- /*1659*/ uint16(x86_xArgM8),
- /*1660*/ uint16(x86_xMatch),
- /*1661*/ uint16(x86_xSetOp), uint16(x86_PREFETCHT1),
- /*1663*/ uint16(x86_xArgM8),
- /*1664*/ uint16(x86_xMatch),
- /*1665*/ uint16(x86_xSetOp), uint16(x86_PREFETCHT2),
- /*1667*/ uint16(x86_xArgM8),
- /*1668*/ uint16(x86_xMatch),
- /*1669*/ uint16(x86_xCondSlashR),
- 1678, // 0
- 0, // 1
- 0, // 2
- 0, // 3
- 0, // 4
- 0, // 5
- 0, // 6
- 0, // 7
- /*1678*/ uint16(x86_xCondDataSize), 1682, 1686, 0,
- /*1682*/ uint16(x86_xSetOp), uint16(x86_NOP),
- /*1684*/ uint16(x86_xArgRM16),
- /*1685*/ uint16(x86_xMatch),
- /*1686*/ uint16(x86_xSetOp), uint16(x86_NOP),
- /*1688*/ uint16(x86_xArgRM32),
- /*1689*/ uint16(x86_xMatch),
- /*1690*/ uint16(x86_xCondIs64), 1693, 1699,
- /*1693*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1695*/ uint16(x86_xReadSlashR),
- /*1696*/ uint16(x86_xArgRmf32),
- /*1697*/ uint16(x86_xArgCR0dashCR7),
- /*1698*/ uint16(x86_xMatch),
- /*1699*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1701*/ uint16(x86_xReadSlashR),
- /*1702*/ uint16(x86_xArgRmf64),
- /*1703*/ uint16(x86_xArgCR0dashCR7),
- /*1704*/ uint16(x86_xMatch),
- /*1705*/ uint16(x86_xCondIs64), 1708, 1714,
- /*1708*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1710*/ uint16(x86_xReadSlashR),
- /*1711*/ uint16(x86_xArgRmf32),
- /*1712*/ uint16(x86_xArgDR0dashDR7),
- /*1713*/ uint16(x86_xMatch),
- /*1714*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1716*/ uint16(x86_xReadSlashR),
- /*1717*/ uint16(x86_xArgRmf64),
- /*1718*/ uint16(x86_xArgDR0dashDR7),
- /*1719*/ uint16(x86_xMatch),
- /*1720*/ uint16(x86_xCondIs64), 1723, 1729,
- /*1723*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1725*/ uint16(x86_xReadSlashR),
- /*1726*/ uint16(x86_xArgCR0dashCR7),
- /*1727*/ uint16(x86_xArgRmf32),
- /*1728*/ uint16(x86_xMatch),
- /*1729*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1731*/ uint16(x86_xReadSlashR),
- /*1732*/ uint16(x86_xArgCR0dashCR7),
- /*1733*/ uint16(x86_xArgRmf64),
- /*1734*/ uint16(x86_xMatch),
- /*1735*/ uint16(x86_xCondIs64), 1738, 1744,
- /*1738*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1740*/ uint16(x86_xReadSlashR),
- /*1741*/ uint16(x86_xArgDR0dashDR7),
- /*1742*/ uint16(x86_xArgRmf32),
- /*1743*/ uint16(x86_xMatch),
- /*1744*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1746*/ uint16(x86_xReadSlashR),
- /*1747*/ uint16(x86_xArgDR0dashDR7),
- /*1748*/ uint16(x86_xArgRmf64),
- /*1749*/ uint16(x86_xMatch),
- /*1750*/ uint16(x86_xCondIs64), 1753, 1759,
- /*1753*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1755*/ uint16(x86_xReadSlashR),
- /*1756*/ uint16(x86_xArgRmf32),
- /*1757*/ uint16(x86_xArgTR0dashTR7),
- /*1758*/ uint16(x86_xMatch),
- /*1759*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1761*/ uint16(x86_xReadSlashR),
- /*1762*/ uint16(x86_xArgRmf64),
- /*1763*/ uint16(x86_xArgTR0dashTR7),
- /*1764*/ uint16(x86_xMatch),
- /*1765*/ uint16(x86_xCondIs64), 1768, 1774,
- /*1768*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1770*/ uint16(x86_xReadSlashR),
- /*1771*/ uint16(x86_xArgTR0dashTR7),
- /*1772*/ uint16(x86_xArgRmf32),
- /*1773*/ uint16(x86_xMatch),
- /*1774*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*1776*/ uint16(x86_xReadSlashR),
- /*1777*/ uint16(x86_xArgTR0dashTR7),
- /*1778*/ uint16(x86_xArgRmf64),
- /*1779*/ uint16(x86_xMatch),
- /*1780*/ uint16(x86_xCondPrefix), 2,
- 0x66, 1792,
- 0x0, 1786,
- /*1786*/ uint16(x86_xSetOp), uint16(x86_MOVAPS),
- /*1788*/ uint16(x86_xReadSlashR),
- /*1789*/ uint16(x86_xArgXmm1),
- /*1790*/ uint16(x86_xArgXmm2M128),
- /*1791*/ uint16(x86_xMatch),
- /*1792*/ uint16(x86_xSetOp), uint16(x86_MOVAPD),
- /*1794*/ uint16(x86_xReadSlashR),
- /*1795*/ uint16(x86_xArgXmm1),
- /*1796*/ uint16(x86_xArgXmm2M128),
- /*1797*/ uint16(x86_xMatch),
- /*1798*/ uint16(x86_xCondPrefix), 2,
- 0x66, 1810,
- 0x0, 1804,
- /*1804*/ uint16(x86_xSetOp), uint16(x86_MOVAPS),
- /*1806*/ uint16(x86_xReadSlashR),
- /*1807*/ uint16(x86_xArgXmm2M128),
- /*1808*/ uint16(x86_xArgXmm1),
- /*1809*/ uint16(x86_xMatch),
- /*1810*/ uint16(x86_xSetOp), uint16(x86_MOVAPD),
- /*1812*/ uint16(x86_xReadSlashR),
- /*1813*/ uint16(x86_xArgXmm2M128),
- /*1814*/ uint16(x86_xArgXmm1),
- /*1815*/ uint16(x86_xMatch),
- /*1816*/ uint16(x86_xCondIs64), 1819, 1873,
- /*1819*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 1857,
- 0xF2, 1841,
- 0x66, 1835,
- 0x0, 1829,
- /*1829*/ uint16(x86_xSetOp), uint16(x86_CVTPI2PS),
- /*1831*/ uint16(x86_xReadSlashR),
- /*1832*/ uint16(x86_xArgXmm),
- /*1833*/ uint16(x86_xArgMmM64),
- /*1834*/ uint16(x86_xMatch),
- /*1835*/ uint16(x86_xSetOp), uint16(x86_CVTPI2PD),
- /*1837*/ uint16(x86_xReadSlashR),
- /*1838*/ uint16(x86_xArgXmm),
- /*1839*/ uint16(x86_xArgMmM64),
- /*1840*/ uint16(x86_xMatch),
- /*1841*/ uint16(x86_xCondDataSize), 1845, 1851, 0,
- /*1845*/ uint16(x86_xSetOp), uint16(x86_CVTSI2SD),
- /*1847*/ uint16(x86_xReadSlashR),
- /*1848*/ uint16(x86_xArgXmm),
- /*1849*/ uint16(x86_xArgRM32),
- /*1850*/ uint16(x86_xMatch),
- /*1851*/ uint16(x86_xSetOp), uint16(x86_CVTSI2SD),
- /*1853*/ uint16(x86_xReadSlashR),
- /*1854*/ uint16(x86_xArgXmm),
- /*1855*/ uint16(x86_xArgRM32),
- /*1856*/ uint16(x86_xMatch),
- /*1857*/ uint16(x86_xCondDataSize), 1861, 1867, 0,
- /*1861*/ uint16(x86_xSetOp), uint16(x86_CVTSI2SS),
- /*1863*/ uint16(x86_xReadSlashR),
- /*1864*/ uint16(x86_xArgXmm),
- /*1865*/ uint16(x86_xArgRM32),
- /*1866*/ uint16(x86_xMatch),
- /*1867*/ uint16(x86_xSetOp), uint16(x86_CVTSI2SS),
- /*1869*/ uint16(x86_xReadSlashR),
- /*1870*/ uint16(x86_xArgXmm),
- /*1871*/ uint16(x86_xArgRM32),
- /*1872*/ uint16(x86_xMatch),
- /*1873*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 1893,
- 0xF2, 1883,
- 0x66, 1835,
- 0x0, 1829,
- /*1883*/ uint16(x86_xCondDataSize), 1845, 1851, 1887,
- /*1887*/ uint16(x86_xSetOp), uint16(x86_CVTSI2SD),
- /*1889*/ uint16(x86_xReadSlashR),
- /*1890*/ uint16(x86_xArgXmm),
- /*1891*/ uint16(x86_xArgRM64),
- /*1892*/ uint16(x86_xMatch),
- /*1893*/ uint16(x86_xCondDataSize), 1861, 1867, 1897,
- /*1897*/ uint16(x86_xSetOp), uint16(x86_CVTSI2SS),
- /*1899*/ uint16(x86_xReadSlashR),
- /*1900*/ uint16(x86_xArgXmm),
- /*1901*/ uint16(x86_xArgRM64),
- /*1902*/ uint16(x86_xMatch),
- /*1903*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 1931,
- 0xF2, 1925,
- 0x66, 1919,
- 0x0, 1913,
- /*1913*/ uint16(x86_xSetOp), uint16(x86_MOVNTPS),
- /*1915*/ uint16(x86_xReadSlashR),
- /*1916*/ uint16(x86_xArgM128),
- /*1917*/ uint16(x86_xArgXmm),
- /*1918*/ uint16(x86_xMatch),
- /*1919*/ uint16(x86_xSetOp), uint16(x86_MOVNTPD),
- /*1921*/ uint16(x86_xReadSlashR),
- /*1922*/ uint16(x86_xArgM128),
- /*1923*/ uint16(x86_xArgXmm),
- /*1924*/ uint16(x86_xMatch),
- /*1925*/ uint16(x86_xSetOp), uint16(x86_MOVNTSD),
- /*1927*/ uint16(x86_xReadSlashR),
- /*1928*/ uint16(x86_xArgM64),
- /*1929*/ uint16(x86_xArgXmm),
- /*1930*/ uint16(x86_xMatch),
- /*1931*/ uint16(x86_xSetOp), uint16(x86_MOVNTSS),
- /*1933*/ uint16(x86_xReadSlashR),
- /*1934*/ uint16(x86_xArgM32),
- /*1935*/ uint16(x86_xArgXmm),
- /*1936*/ uint16(x86_xMatch),
- /*1937*/ uint16(x86_xCondIs64), 1940, 1994,
- /*1940*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 1978,
- 0xF2, 1962,
- 0x66, 1956,
- 0x0, 1950,
- /*1950*/ uint16(x86_xSetOp), uint16(x86_CVTTPS2PI),
- /*1952*/ uint16(x86_xReadSlashR),
- /*1953*/ uint16(x86_xArgMm),
- /*1954*/ uint16(x86_xArgXmmM64),
- /*1955*/ uint16(x86_xMatch),
- /*1956*/ uint16(x86_xSetOp), uint16(x86_CVTTPD2PI),
- /*1958*/ uint16(x86_xReadSlashR),
- /*1959*/ uint16(x86_xArgMm),
- /*1960*/ uint16(x86_xArgXmmM128),
- /*1961*/ uint16(x86_xMatch),
- /*1962*/ uint16(x86_xCondDataSize), 1966, 1972, 0,
- /*1966*/ uint16(x86_xSetOp), uint16(x86_CVTTSD2SI),
- /*1968*/ uint16(x86_xReadSlashR),
- /*1969*/ uint16(x86_xArgR32),
- /*1970*/ uint16(x86_xArgXmmM64),
- /*1971*/ uint16(x86_xMatch),
- /*1972*/ uint16(x86_xSetOp), uint16(x86_CVTTSD2SI),
- /*1974*/ uint16(x86_xReadSlashR),
- /*1975*/ uint16(x86_xArgR32),
- /*1976*/ uint16(x86_xArgXmmM64),
- /*1977*/ uint16(x86_xMatch),
- /*1978*/ uint16(x86_xCondDataSize), 1982, 1988, 0,
- /*1982*/ uint16(x86_xSetOp), uint16(x86_CVTTSS2SI),
- /*1984*/ uint16(x86_xReadSlashR),
- /*1985*/ uint16(x86_xArgR32),
- /*1986*/ uint16(x86_xArgXmmM32),
- /*1987*/ uint16(x86_xMatch),
- /*1988*/ uint16(x86_xSetOp), uint16(x86_CVTTSS2SI),
- /*1990*/ uint16(x86_xReadSlashR),
- /*1991*/ uint16(x86_xArgR32),
- /*1992*/ uint16(x86_xArgXmmM32),
- /*1993*/ uint16(x86_xMatch),
- /*1994*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 2014,
- 0xF2, 2004,
- 0x66, 1956,
- 0x0, 1950,
- /*2004*/ uint16(x86_xCondDataSize), 1966, 1972, 2008,
- /*2008*/ uint16(x86_xSetOp), uint16(x86_CVTTSD2SI),
- /*2010*/ uint16(x86_xReadSlashR),
- /*2011*/ uint16(x86_xArgR64),
- /*2012*/ uint16(x86_xArgXmmM64),
- /*2013*/ uint16(x86_xMatch),
- /*2014*/ uint16(x86_xCondDataSize), 1982, 1988, 2018,
- /*2018*/ uint16(x86_xSetOp), uint16(x86_CVTTSS2SI),
- /*2020*/ uint16(x86_xReadSlashR),
- /*2021*/ uint16(x86_xArgR64),
- /*2022*/ uint16(x86_xArgXmmM32),
- /*2023*/ uint16(x86_xMatch),
- /*2024*/ uint16(x86_xCondIs64), 2027, 2081,
- /*2027*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 2065,
- 0xF2, 2049,
- 0x66, 2043,
- 0x0, 2037,
- /*2037*/ uint16(x86_xSetOp), uint16(x86_CVTPS2PI),
- /*2039*/ uint16(x86_xReadSlashR),
- /*2040*/ uint16(x86_xArgMm),
- /*2041*/ uint16(x86_xArgXmmM64),
- /*2042*/ uint16(x86_xMatch),
- /*2043*/ uint16(x86_xSetOp), uint16(x86_CVTPD2PI),
- /*2045*/ uint16(x86_xReadSlashR),
- /*2046*/ uint16(x86_xArgMm),
- /*2047*/ uint16(x86_xArgXmmM128),
- /*2048*/ uint16(x86_xMatch),
- /*2049*/ uint16(x86_xCondDataSize), 2053, 2059, 0,
- /*2053*/ uint16(x86_xSetOp), uint16(x86_CVTSD2SI),
- /*2055*/ uint16(x86_xReadSlashR),
- /*2056*/ uint16(x86_xArgR32),
- /*2057*/ uint16(x86_xArgXmmM64),
- /*2058*/ uint16(x86_xMatch),
- /*2059*/ uint16(x86_xSetOp), uint16(x86_CVTSD2SI),
- /*2061*/ uint16(x86_xReadSlashR),
- /*2062*/ uint16(x86_xArgR32),
- /*2063*/ uint16(x86_xArgXmmM64),
- /*2064*/ uint16(x86_xMatch),
- /*2065*/ uint16(x86_xCondDataSize), 2069, 2075, 0,
- /*2069*/ uint16(x86_xSetOp), uint16(x86_CVTSS2SI),
- /*2071*/ uint16(x86_xReadSlashR),
- /*2072*/ uint16(x86_xArgR32),
- /*2073*/ uint16(x86_xArgXmmM32),
- /*2074*/ uint16(x86_xMatch),
- /*2075*/ uint16(x86_xSetOp), uint16(x86_CVTSS2SI),
- /*2077*/ uint16(x86_xReadSlashR),
- /*2078*/ uint16(x86_xArgR32),
- /*2079*/ uint16(x86_xArgXmmM32),
- /*2080*/ uint16(x86_xMatch),
- /*2081*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 2101,
- 0xF2, 2091,
- 0x66, 2043,
- 0x0, 2037,
- /*2091*/ uint16(x86_xCondDataSize), 2053, 2059, 2095,
- /*2095*/ uint16(x86_xSetOp), uint16(x86_CVTSD2SI),
- /*2097*/ uint16(x86_xReadSlashR),
- /*2098*/ uint16(x86_xArgR64),
- /*2099*/ uint16(x86_xArgXmmM64),
- /*2100*/ uint16(x86_xMatch),
- /*2101*/ uint16(x86_xCondDataSize), 2069, 2075, 2105,
- /*2105*/ uint16(x86_xSetOp), uint16(x86_CVTSS2SI),
- /*2107*/ uint16(x86_xReadSlashR),
- /*2108*/ uint16(x86_xArgR64),
- /*2109*/ uint16(x86_xArgXmmM32),
- /*2110*/ uint16(x86_xMatch),
- /*2111*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2123,
- 0x0, 2117,
- /*2117*/ uint16(x86_xSetOp), uint16(x86_UCOMISS),
- /*2119*/ uint16(x86_xReadSlashR),
- /*2120*/ uint16(x86_xArgXmm1),
- /*2121*/ uint16(x86_xArgXmm2M32),
- /*2122*/ uint16(x86_xMatch),
- /*2123*/ uint16(x86_xSetOp), uint16(x86_UCOMISD),
- /*2125*/ uint16(x86_xReadSlashR),
- /*2126*/ uint16(x86_xArgXmm1),
- /*2127*/ uint16(x86_xArgXmm2M64),
- /*2128*/ uint16(x86_xMatch),
- /*2129*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2141,
- 0x0, 2135,
- /*2135*/ uint16(x86_xSetOp), uint16(x86_COMISS),
- /*2137*/ uint16(x86_xReadSlashR),
- /*2138*/ uint16(x86_xArgXmm1),
- /*2139*/ uint16(x86_xArgXmm2M32),
- /*2140*/ uint16(x86_xMatch),
- /*2141*/ uint16(x86_xSetOp), uint16(x86_COMISD),
- /*2143*/ uint16(x86_xReadSlashR),
- /*2144*/ uint16(x86_xArgXmm1),
- /*2145*/ uint16(x86_xArgXmm2M64),
- /*2146*/ uint16(x86_xMatch),
- /*2147*/ uint16(x86_xSetOp), uint16(x86_WRMSR),
- /*2149*/ uint16(x86_xMatch),
- /*2150*/ uint16(x86_xSetOp), uint16(x86_RDTSC),
- /*2152*/ uint16(x86_xMatch),
- /*2153*/ uint16(x86_xSetOp), uint16(x86_RDMSR),
- /*2155*/ uint16(x86_xMatch),
- /*2156*/ uint16(x86_xSetOp), uint16(x86_RDPMC),
- /*2158*/ uint16(x86_xMatch),
- /*2159*/ uint16(x86_xSetOp), uint16(x86_SYSENTER),
- /*2161*/ uint16(x86_xMatch),
- /*2162*/ uint16(x86_xCondDataSize), 2166, 2166, 2169,
- /*2166*/ uint16(x86_xSetOp), uint16(x86_SYSEXIT),
- /*2168*/ uint16(x86_xMatch),
- /*2169*/ uint16(x86_xSetOp), uint16(x86_SYSEXIT),
- /*2171*/ uint16(x86_xMatch),
- /*2172*/ uint16(x86_xCondByte), 54,
- 0x00, 2283,
- 0x01, 2301,
- 0x02, 2319,
- 0x03, 2337,
- 0x04, 2355,
- 0x05, 2373,
- 0x06, 2391,
- 0x07, 2409,
- 0x08, 2427,
- 0x09, 2445,
- 0x0A, 2463,
- 0x0B, 2481,
- 0x10, 2499,
- 0x14, 2510,
- 0x15, 2521,
- 0x17, 2532,
- 0x1C, 2542,
- 0x1D, 2560,
- 0x1E, 2578,
- 0x20, 2596,
- 0x21, 2606,
- 0x22, 2616,
- 0x23, 2626,
- 0x24, 2636,
- 0x25, 2646,
- 0x28, 2656,
- 0x29, 2666,
- 0x2A, 2676,
- 0x2B, 2686,
- 0x30, 2696,
- 0x31, 2706,
- 0x32, 2716,
- 0x33, 2726,
- 0x34, 2736,
- 0x35, 2746,
- 0x37, 2756,
- 0x38, 2766,
- 0x39, 2776,
- 0x3A, 2786,
- 0x3B, 2796,
- 0x3C, 2806,
- 0x3D, 2816,
- 0x3E, 2826,
- 0x3F, 2836,
- 0x40, 2846,
- 0x41, 2856,
- 0x82, 2866,
- 0xDB, 2889,
- 0xDC, 2899,
- 0xDD, 2909,
- 0xDE, 2919,
- 0xDF, 2929,
- 0xF0, 2939,
- 0xF1, 3006,
- uint16(x86_xFail),
- /*2283*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2295,
- 0x0, 2289,
- /*2289*/ uint16(x86_xSetOp), uint16(x86_PSHUFB),
- /*2291*/ uint16(x86_xReadSlashR),
- /*2292*/ uint16(x86_xArgMm1),
- /*2293*/ uint16(x86_xArgMm2M64),
- /*2294*/ uint16(x86_xMatch),
- /*2295*/ uint16(x86_xSetOp), uint16(x86_PSHUFB),
- /*2297*/ uint16(x86_xReadSlashR),
- /*2298*/ uint16(x86_xArgXmm1),
- /*2299*/ uint16(x86_xArgXmm2M128),
- /*2300*/ uint16(x86_xMatch),
- /*2301*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2313,
- 0x0, 2307,
- /*2307*/ uint16(x86_xSetOp), uint16(x86_PHADDW),
- /*2309*/ uint16(x86_xReadSlashR),
- /*2310*/ uint16(x86_xArgMm1),
- /*2311*/ uint16(x86_xArgMm2M64),
- /*2312*/ uint16(x86_xMatch),
- /*2313*/ uint16(x86_xSetOp), uint16(x86_PHADDW),
- /*2315*/ uint16(x86_xReadSlashR),
- /*2316*/ uint16(x86_xArgXmm1),
- /*2317*/ uint16(x86_xArgXmm2M128),
- /*2318*/ uint16(x86_xMatch),
- /*2319*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2331,
- 0x0, 2325,
- /*2325*/ uint16(x86_xSetOp), uint16(x86_PHADDD),
- /*2327*/ uint16(x86_xReadSlashR),
- /*2328*/ uint16(x86_xArgMm1),
- /*2329*/ uint16(x86_xArgMm2M64),
- /*2330*/ uint16(x86_xMatch),
- /*2331*/ uint16(x86_xSetOp), uint16(x86_PHADDD),
- /*2333*/ uint16(x86_xReadSlashR),
- /*2334*/ uint16(x86_xArgXmm1),
- /*2335*/ uint16(x86_xArgXmm2M128),
- /*2336*/ uint16(x86_xMatch),
- /*2337*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2349,
- 0x0, 2343,
- /*2343*/ uint16(x86_xSetOp), uint16(x86_PHADDSW),
- /*2345*/ uint16(x86_xReadSlashR),
- /*2346*/ uint16(x86_xArgMm1),
- /*2347*/ uint16(x86_xArgMm2M64),
- /*2348*/ uint16(x86_xMatch),
- /*2349*/ uint16(x86_xSetOp), uint16(x86_PHADDSW),
- /*2351*/ uint16(x86_xReadSlashR),
- /*2352*/ uint16(x86_xArgXmm1),
- /*2353*/ uint16(x86_xArgXmm2M128),
- /*2354*/ uint16(x86_xMatch),
- /*2355*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2367,
- 0x0, 2361,
- /*2361*/ uint16(x86_xSetOp), uint16(x86_PMADDUBSW),
- /*2363*/ uint16(x86_xReadSlashR),
- /*2364*/ uint16(x86_xArgMm1),
- /*2365*/ uint16(x86_xArgMm2M64),
- /*2366*/ uint16(x86_xMatch),
- /*2367*/ uint16(x86_xSetOp), uint16(x86_PMADDUBSW),
- /*2369*/ uint16(x86_xReadSlashR),
- /*2370*/ uint16(x86_xArgXmm1),
- /*2371*/ uint16(x86_xArgXmm2M128),
- /*2372*/ uint16(x86_xMatch),
- /*2373*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2385,
- 0x0, 2379,
- /*2379*/ uint16(x86_xSetOp), uint16(x86_PHSUBW),
- /*2381*/ uint16(x86_xReadSlashR),
- /*2382*/ uint16(x86_xArgMm1),
- /*2383*/ uint16(x86_xArgMm2M64),
- /*2384*/ uint16(x86_xMatch),
- /*2385*/ uint16(x86_xSetOp), uint16(x86_PHSUBW),
- /*2387*/ uint16(x86_xReadSlashR),
- /*2388*/ uint16(x86_xArgXmm1),
- /*2389*/ uint16(x86_xArgXmm2M128),
- /*2390*/ uint16(x86_xMatch),
- /*2391*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2403,
- 0x0, 2397,
- /*2397*/ uint16(x86_xSetOp), uint16(x86_PHSUBD),
- /*2399*/ uint16(x86_xReadSlashR),
- /*2400*/ uint16(x86_xArgMm1),
- /*2401*/ uint16(x86_xArgMm2M64),
- /*2402*/ uint16(x86_xMatch),
- /*2403*/ uint16(x86_xSetOp), uint16(x86_PHSUBD),
- /*2405*/ uint16(x86_xReadSlashR),
- /*2406*/ uint16(x86_xArgXmm1),
- /*2407*/ uint16(x86_xArgXmm2M128),
- /*2408*/ uint16(x86_xMatch),
- /*2409*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2421,
- 0x0, 2415,
- /*2415*/ uint16(x86_xSetOp), uint16(x86_PHSUBSW),
- /*2417*/ uint16(x86_xReadSlashR),
- /*2418*/ uint16(x86_xArgMm1),
- /*2419*/ uint16(x86_xArgMm2M64),
- /*2420*/ uint16(x86_xMatch),
- /*2421*/ uint16(x86_xSetOp), uint16(x86_PHSUBSW),
- /*2423*/ uint16(x86_xReadSlashR),
- /*2424*/ uint16(x86_xArgXmm1),
- /*2425*/ uint16(x86_xArgXmm2M128),
- /*2426*/ uint16(x86_xMatch),
- /*2427*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2439,
- 0x0, 2433,
- /*2433*/ uint16(x86_xSetOp), uint16(x86_PSIGNB),
- /*2435*/ uint16(x86_xReadSlashR),
- /*2436*/ uint16(x86_xArgMm1),
- /*2437*/ uint16(x86_xArgMm2M64),
- /*2438*/ uint16(x86_xMatch),
- /*2439*/ uint16(x86_xSetOp), uint16(x86_PSIGNB),
- /*2441*/ uint16(x86_xReadSlashR),
- /*2442*/ uint16(x86_xArgXmm1),
- /*2443*/ uint16(x86_xArgXmm2M128),
- /*2444*/ uint16(x86_xMatch),
- /*2445*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2457,
- 0x0, 2451,
- /*2451*/ uint16(x86_xSetOp), uint16(x86_PSIGNW),
- /*2453*/ uint16(x86_xReadSlashR),
- /*2454*/ uint16(x86_xArgMm1),
- /*2455*/ uint16(x86_xArgMm2M64),
- /*2456*/ uint16(x86_xMatch),
- /*2457*/ uint16(x86_xSetOp), uint16(x86_PSIGNW),
- /*2459*/ uint16(x86_xReadSlashR),
- /*2460*/ uint16(x86_xArgXmm1),
- /*2461*/ uint16(x86_xArgXmm2M128),
- /*2462*/ uint16(x86_xMatch),
- /*2463*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2475,
- 0x0, 2469,
- /*2469*/ uint16(x86_xSetOp), uint16(x86_PSIGND),
- /*2471*/ uint16(x86_xReadSlashR),
- /*2472*/ uint16(x86_xArgMm1),
- /*2473*/ uint16(x86_xArgMm2M64),
- /*2474*/ uint16(x86_xMatch),
- /*2475*/ uint16(x86_xSetOp), uint16(x86_PSIGND),
- /*2477*/ uint16(x86_xReadSlashR),
- /*2478*/ uint16(x86_xArgXmm1),
- /*2479*/ uint16(x86_xArgXmm2M128),
- /*2480*/ uint16(x86_xMatch),
- /*2481*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2493,
- 0x0, 2487,
- /*2487*/ uint16(x86_xSetOp), uint16(x86_PMULHRSW),
- /*2489*/ uint16(x86_xReadSlashR),
- /*2490*/ uint16(x86_xArgMm1),
- /*2491*/ uint16(x86_xArgMm2M64),
- /*2492*/ uint16(x86_xMatch),
- /*2493*/ uint16(x86_xSetOp), uint16(x86_PMULHRSW),
- /*2495*/ uint16(x86_xReadSlashR),
- /*2496*/ uint16(x86_xArgXmm1),
- /*2497*/ uint16(x86_xArgXmm2M128),
- /*2498*/ uint16(x86_xMatch),
- /*2499*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2503,
- /*2503*/ uint16(x86_xSetOp), uint16(x86_PBLENDVB),
- /*2505*/ uint16(x86_xReadSlashR),
- /*2506*/ uint16(x86_xArgXmm1),
- /*2507*/ uint16(x86_xArgXmm2M128),
- /*2508*/ uint16(x86_xArgXMM0),
- /*2509*/ uint16(x86_xMatch),
- /*2510*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2514,
- /*2514*/ uint16(x86_xSetOp), uint16(x86_BLENDVPS),
- /*2516*/ uint16(x86_xReadSlashR),
- /*2517*/ uint16(x86_xArgXmm1),
- /*2518*/ uint16(x86_xArgXmm2M128),
- /*2519*/ uint16(x86_xArgXMM0),
- /*2520*/ uint16(x86_xMatch),
- /*2521*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2525,
- /*2525*/ uint16(x86_xSetOp), uint16(x86_BLENDVPD),
- /*2527*/ uint16(x86_xReadSlashR),
- /*2528*/ uint16(x86_xArgXmm1),
- /*2529*/ uint16(x86_xArgXmm2M128),
- /*2530*/ uint16(x86_xArgXMM0),
- /*2531*/ uint16(x86_xMatch),
- /*2532*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2536,
- /*2536*/ uint16(x86_xSetOp), uint16(x86_PTEST),
- /*2538*/ uint16(x86_xReadSlashR),
- /*2539*/ uint16(x86_xArgXmm1),
- /*2540*/ uint16(x86_xArgXmm2M128),
- /*2541*/ uint16(x86_xMatch),
- /*2542*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2554,
- 0x0, 2548,
- /*2548*/ uint16(x86_xSetOp), uint16(x86_PABSB),
- /*2550*/ uint16(x86_xReadSlashR),
- /*2551*/ uint16(x86_xArgMm1),
- /*2552*/ uint16(x86_xArgMm2M64),
- /*2553*/ uint16(x86_xMatch),
- /*2554*/ uint16(x86_xSetOp), uint16(x86_PABSB),
- /*2556*/ uint16(x86_xReadSlashR),
- /*2557*/ uint16(x86_xArgXmm1),
- /*2558*/ uint16(x86_xArgXmm2M128),
- /*2559*/ uint16(x86_xMatch),
- /*2560*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2572,
- 0x0, 2566,
- /*2566*/ uint16(x86_xSetOp), uint16(x86_PABSW),
- /*2568*/ uint16(x86_xReadSlashR),
- /*2569*/ uint16(x86_xArgMm1),
- /*2570*/ uint16(x86_xArgMm2M64),
- /*2571*/ uint16(x86_xMatch),
- /*2572*/ uint16(x86_xSetOp), uint16(x86_PABSW),
- /*2574*/ uint16(x86_xReadSlashR),
- /*2575*/ uint16(x86_xArgXmm1),
- /*2576*/ uint16(x86_xArgXmm2M128),
- /*2577*/ uint16(x86_xMatch),
- /*2578*/ uint16(x86_xCondPrefix), 2,
- 0x66, 2590,
- 0x0, 2584,
- /*2584*/ uint16(x86_xSetOp), uint16(x86_PABSD),
- /*2586*/ uint16(x86_xReadSlashR),
- /*2587*/ uint16(x86_xArgMm1),
- /*2588*/ uint16(x86_xArgMm2M64),
- /*2589*/ uint16(x86_xMatch),
- /*2590*/ uint16(x86_xSetOp), uint16(x86_PABSD),
- /*2592*/ uint16(x86_xReadSlashR),
- /*2593*/ uint16(x86_xArgXmm1),
- /*2594*/ uint16(x86_xArgXmm2M128),
- /*2595*/ uint16(x86_xMatch),
- /*2596*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2600,
- /*2600*/ uint16(x86_xSetOp), uint16(x86_PMOVSXBW),
- /*2602*/ uint16(x86_xReadSlashR),
- /*2603*/ uint16(x86_xArgXmm1),
- /*2604*/ uint16(x86_xArgXmm2M64),
- /*2605*/ uint16(x86_xMatch),
- /*2606*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2610,
- /*2610*/ uint16(x86_xSetOp), uint16(x86_PMOVSXBD),
- /*2612*/ uint16(x86_xReadSlashR),
- /*2613*/ uint16(x86_xArgXmm1),
- /*2614*/ uint16(x86_xArgXmm2M32),
- /*2615*/ uint16(x86_xMatch),
- /*2616*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2620,
- /*2620*/ uint16(x86_xSetOp), uint16(x86_PMOVSXBQ),
- /*2622*/ uint16(x86_xReadSlashR),
- /*2623*/ uint16(x86_xArgXmm1),
- /*2624*/ uint16(x86_xArgXmm2M16),
- /*2625*/ uint16(x86_xMatch),
- /*2626*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2630,
- /*2630*/ uint16(x86_xSetOp), uint16(x86_PMOVSXWD),
- /*2632*/ uint16(x86_xReadSlashR),
- /*2633*/ uint16(x86_xArgXmm1),
- /*2634*/ uint16(x86_xArgXmm2M64),
- /*2635*/ uint16(x86_xMatch),
- /*2636*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2640,
- /*2640*/ uint16(x86_xSetOp), uint16(x86_PMOVSXWQ),
- /*2642*/ uint16(x86_xReadSlashR),
- /*2643*/ uint16(x86_xArgXmm1),
- /*2644*/ uint16(x86_xArgXmm2M32),
- /*2645*/ uint16(x86_xMatch),
- /*2646*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2650,
- /*2650*/ uint16(x86_xSetOp), uint16(x86_PMOVSXDQ),
- /*2652*/ uint16(x86_xReadSlashR),
- /*2653*/ uint16(x86_xArgXmm1),
- /*2654*/ uint16(x86_xArgXmm2M64),
- /*2655*/ uint16(x86_xMatch),
- /*2656*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2660,
- /*2660*/ uint16(x86_xSetOp), uint16(x86_PMULDQ),
- /*2662*/ uint16(x86_xReadSlashR),
- /*2663*/ uint16(x86_xArgXmm1),
- /*2664*/ uint16(x86_xArgXmm2M128),
- /*2665*/ uint16(x86_xMatch),
- /*2666*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2670,
- /*2670*/ uint16(x86_xSetOp), uint16(x86_PCMPEQQ),
- /*2672*/ uint16(x86_xReadSlashR),
- /*2673*/ uint16(x86_xArgXmm1),
- /*2674*/ uint16(x86_xArgXmm2M128),
- /*2675*/ uint16(x86_xMatch),
- /*2676*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2680,
- /*2680*/ uint16(x86_xSetOp), uint16(x86_MOVNTDQA),
- /*2682*/ uint16(x86_xReadSlashR),
- /*2683*/ uint16(x86_xArgXmm1),
- /*2684*/ uint16(x86_xArgM128),
- /*2685*/ uint16(x86_xMatch),
- /*2686*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2690,
- /*2690*/ uint16(x86_xSetOp), uint16(x86_PACKUSDW),
- /*2692*/ uint16(x86_xReadSlashR),
- /*2693*/ uint16(x86_xArgXmm1),
- /*2694*/ uint16(x86_xArgXmm2M128),
- /*2695*/ uint16(x86_xMatch),
- /*2696*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2700,
- /*2700*/ uint16(x86_xSetOp), uint16(x86_PMOVZXBW),
- /*2702*/ uint16(x86_xReadSlashR),
- /*2703*/ uint16(x86_xArgXmm1),
- /*2704*/ uint16(x86_xArgXmm2M64),
- /*2705*/ uint16(x86_xMatch),
- /*2706*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2710,
- /*2710*/ uint16(x86_xSetOp), uint16(x86_PMOVZXBD),
- /*2712*/ uint16(x86_xReadSlashR),
- /*2713*/ uint16(x86_xArgXmm1),
- /*2714*/ uint16(x86_xArgXmm2M32),
- /*2715*/ uint16(x86_xMatch),
- /*2716*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2720,
- /*2720*/ uint16(x86_xSetOp), uint16(x86_PMOVZXBQ),
- /*2722*/ uint16(x86_xReadSlashR),
- /*2723*/ uint16(x86_xArgXmm1),
- /*2724*/ uint16(x86_xArgXmm2M16),
- /*2725*/ uint16(x86_xMatch),
- /*2726*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2730,
- /*2730*/ uint16(x86_xSetOp), uint16(x86_PMOVZXWD),
- /*2732*/ uint16(x86_xReadSlashR),
- /*2733*/ uint16(x86_xArgXmm1),
- /*2734*/ uint16(x86_xArgXmm2M64),
- /*2735*/ uint16(x86_xMatch),
- /*2736*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2740,
- /*2740*/ uint16(x86_xSetOp), uint16(x86_PMOVZXWQ),
- /*2742*/ uint16(x86_xReadSlashR),
- /*2743*/ uint16(x86_xArgXmm1),
- /*2744*/ uint16(x86_xArgXmm2M32),
- /*2745*/ uint16(x86_xMatch),
- /*2746*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2750,
- /*2750*/ uint16(x86_xSetOp), uint16(x86_PMOVZXDQ),
- /*2752*/ uint16(x86_xReadSlashR),
- /*2753*/ uint16(x86_xArgXmm1),
- /*2754*/ uint16(x86_xArgXmm2M64),
- /*2755*/ uint16(x86_xMatch),
- /*2756*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2760,
- /*2760*/ uint16(x86_xSetOp), uint16(x86_PCMPGTQ),
- /*2762*/ uint16(x86_xReadSlashR),
- /*2763*/ uint16(x86_xArgXmm1),
- /*2764*/ uint16(x86_xArgXmm2M128),
- /*2765*/ uint16(x86_xMatch),
- /*2766*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2770,
- /*2770*/ uint16(x86_xSetOp), uint16(x86_PMINSB),
- /*2772*/ uint16(x86_xReadSlashR),
- /*2773*/ uint16(x86_xArgXmm1),
- /*2774*/ uint16(x86_xArgXmm2M128),
- /*2775*/ uint16(x86_xMatch),
- /*2776*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2780,
- /*2780*/ uint16(x86_xSetOp), uint16(x86_PMINSD),
- /*2782*/ uint16(x86_xReadSlashR),
- /*2783*/ uint16(x86_xArgXmm1),
- /*2784*/ uint16(x86_xArgXmm2M128),
- /*2785*/ uint16(x86_xMatch),
- /*2786*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2790,
- /*2790*/ uint16(x86_xSetOp), uint16(x86_PMINUW),
- /*2792*/ uint16(x86_xReadSlashR),
- /*2793*/ uint16(x86_xArgXmm1),
- /*2794*/ uint16(x86_xArgXmm2M128),
- /*2795*/ uint16(x86_xMatch),
- /*2796*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2800,
- /*2800*/ uint16(x86_xSetOp), uint16(x86_PMINUD),
- /*2802*/ uint16(x86_xReadSlashR),
- /*2803*/ uint16(x86_xArgXmm1),
- /*2804*/ uint16(x86_xArgXmm2M128),
- /*2805*/ uint16(x86_xMatch),
- /*2806*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2810,
- /*2810*/ uint16(x86_xSetOp), uint16(x86_PMAXSB),
- /*2812*/ uint16(x86_xReadSlashR),
- /*2813*/ uint16(x86_xArgXmm1),
- /*2814*/ uint16(x86_xArgXmm2M128),
- /*2815*/ uint16(x86_xMatch),
- /*2816*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2820,
- /*2820*/ uint16(x86_xSetOp), uint16(x86_PMAXSD),
- /*2822*/ uint16(x86_xReadSlashR),
- /*2823*/ uint16(x86_xArgXmm1),
- /*2824*/ uint16(x86_xArgXmm2M128),
- /*2825*/ uint16(x86_xMatch),
- /*2826*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2830,
- /*2830*/ uint16(x86_xSetOp), uint16(x86_PMAXUW),
- /*2832*/ uint16(x86_xReadSlashR),
- /*2833*/ uint16(x86_xArgXmm1),
- /*2834*/ uint16(x86_xArgXmm2M128),
- /*2835*/ uint16(x86_xMatch),
- /*2836*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2840,
- /*2840*/ uint16(x86_xSetOp), uint16(x86_PMAXUD),
- /*2842*/ uint16(x86_xReadSlashR),
- /*2843*/ uint16(x86_xArgXmm1),
- /*2844*/ uint16(x86_xArgXmm2M128),
- /*2845*/ uint16(x86_xMatch),
- /*2846*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2850,
- /*2850*/ uint16(x86_xSetOp), uint16(x86_PMULLD),
- /*2852*/ uint16(x86_xReadSlashR),
- /*2853*/ uint16(x86_xArgXmm1),
- /*2854*/ uint16(x86_xArgXmm2M128),
- /*2855*/ uint16(x86_xMatch),
- /*2856*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2860,
- /*2860*/ uint16(x86_xSetOp), uint16(x86_PHMINPOSUW),
- /*2862*/ uint16(x86_xReadSlashR),
- /*2863*/ uint16(x86_xArgXmm1),
- /*2864*/ uint16(x86_xArgXmm2M128),
- /*2865*/ uint16(x86_xMatch),
- /*2866*/ uint16(x86_xCondIs64), 2869, 2879,
- /*2869*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2873,
- /*2873*/ uint16(x86_xSetOp), uint16(x86_INVPCID),
- /*2875*/ uint16(x86_xReadSlashR),
- /*2876*/ uint16(x86_xArgR32),
- /*2877*/ uint16(x86_xArgM128),
- /*2878*/ uint16(x86_xMatch),
- /*2879*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2883,
- /*2883*/ uint16(x86_xSetOp), uint16(x86_INVPCID),
- /*2885*/ uint16(x86_xReadSlashR),
- /*2886*/ uint16(x86_xArgR64),
- /*2887*/ uint16(x86_xArgM128),
- /*2888*/ uint16(x86_xMatch),
- /*2889*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2893,
- /*2893*/ uint16(x86_xSetOp), uint16(x86_AESIMC),
- /*2895*/ uint16(x86_xReadSlashR),
- /*2896*/ uint16(x86_xArgXmm1),
- /*2897*/ uint16(x86_xArgXmm2M128),
- /*2898*/ uint16(x86_xMatch),
- /*2899*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2903,
- /*2903*/ uint16(x86_xSetOp), uint16(x86_AESENC),
- /*2905*/ uint16(x86_xReadSlashR),
- /*2906*/ uint16(x86_xArgXmm1),
- /*2907*/ uint16(x86_xArgXmm2M128),
- /*2908*/ uint16(x86_xMatch),
- /*2909*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2913,
- /*2913*/ uint16(x86_xSetOp), uint16(x86_AESENCLAST),
- /*2915*/ uint16(x86_xReadSlashR),
- /*2916*/ uint16(x86_xArgXmm1),
- /*2917*/ uint16(x86_xArgXmm2M128),
- /*2918*/ uint16(x86_xMatch),
- /*2919*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2923,
- /*2923*/ uint16(x86_xSetOp), uint16(x86_AESDEC),
- /*2925*/ uint16(x86_xReadSlashR),
- /*2926*/ uint16(x86_xArgXmm1),
- /*2927*/ uint16(x86_xArgXmm2M128),
- /*2928*/ uint16(x86_xMatch),
- /*2929*/ uint16(x86_xCondPrefix), 1,
- 0x66, 2933,
- /*2933*/ uint16(x86_xSetOp), uint16(x86_AESDECLAST),
- /*2935*/ uint16(x86_xReadSlashR),
- /*2936*/ uint16(x86_xArgXmm1),
- /*2937*/ uint16(x86_xArgXmm2M128),
- /*2938*/ uint16(x86_xMatch),
- /*2939*/ uint16(x86_xCondIs64), 2942, 2980,
- /*2942*/ uint16(x86_xCondPrefix), 2,
- 0xF2, 2964,
- 0x0, 2948,
- /*2948*/ uint16(x86_xCondDataSize), 2952, 2958, 0,
- /*2952*/ uint16(x86_xSetOp), uint16(x86_MOVBE),
- /*2954*/ uint16(x86_xReadSlashR),
- /*2955*/ uint16(x86_xArgR16),
- /*2956*/ uint16(x86_xArgM16),
- /*2957*/ uint16(x86_xMatch),
- /*2958*/ uint16(x86_xSetOp), uint16(x86_MOVBE),
- /*2960*/ uint16(x86_xReadSlashR),
- /*2961*/ uint16(x86_xArgR32),
- /*2962*/ uint16(x86_xArgM32),
- /*2963*/ uint16(x86_xMatch),
- /*2964*/ uint16(x86_xCondDataSize), 2968, 2974, 0,
- /*2968*/ uint16(x86_xSetOp), uint16(x86_CRC32),
- /*2970*/ uint16(x86_xReadSlashR),
- /*2971*/ uint16(x86_xArgR32),
- /*2972*/ uint16(x86_xArgRM8),
- /*2973*/ uint16(x86_xMatch),
- /*2974*/ uint16(x86_xSetOp), uint16(x86_CRC32),
- /*2976*/ uint16(x86_xReadSlashR),
- /*2977*/ uint16(x86_xArgR32),
- /*2978*/ uint16(x86_xArgRM8),
- /*2979*/ uint16(x86_xMatch),
- /*2980*/ uint16(x86_xCondPrefix), 2,
- 0xF2, 2996,
- 0x0, 2986,
- /*2986*/ uint16(x86_xCondDataSize), 2952, 2958, 2990,
- /*2990*/ uint16(x86_xSetOp), uint16(x86_MOVBE),
- /*2992*/ uint16(x86_xReadSlashR),
- /*2993*/ uint16(x86_xArgR64),
- /*2994*/ uint16(x86_xArgM64),
- /*2995*/ uint16(x86_xMatch),
- /*2996*/ uint16(x86_xCondDataSize), 2968, 2974, 3000,
- /*3000*/ uint16(x86_xSetOp), uint16(x86_CRC32),
- /*3002*/ uint16(x86_xReadSlashR),
- /*3003*/ uint16(x86_xArgR64),
- /*3004*/ uint16(x86_xArgRM8),
- /*3005*/ uint16(x86_xMatch),
- /*3006*/ uint16(x86_xCondIs64), 3009, 3047,
- /*3009*/ uint16(x86_xCondPrefix), 2,
- 0xF2, 3031,
- 0x0, 3015,
- /*3015*/ uint16(x86_xCondDataSize), 3019, 3025, 0,
- /*3019*/ uint16(x86_xSetOp), uint16(x86_MOVBE),
- /*3021*/ uint16(x86_xReadSlashR),
- /*3022*/ uint16(x86_xArgM16),
- /*3023*/ uint16(x86_xArgR16),
- /*3024*/ uint16(x86_xMatch),
- /*3025*/ uint16(x86_xSetOp), uint16(x86_MOVBE),
- /*3027*/ uint16(x86_xReadSlashR),
- /*3028*/ uint16(x86_xArgM32),
- /*3029*/ uint16(x86_xArgR32),
- /*3030*/ uint16(x86_xMatch),
- /*3031*/ uint16(x86_xCondDataSize), 3035, 3041, 0,
- /*3035*/ uint16(x86_xSetOp), uint16(x86_CRC32),
- /*3037*/ uint16(x86_xReadSlashR),
- /*3038*/ uint16(x86_xArgR32),
- /*3039*/ uint16(x86_xArgRM16),
- /*3040*/ uint16(x86_xMatch),
- /*3041*/ uint16(x86_xSetOp), uint16(x86_CRC32),
- /*3043*/ uint16(x86_xReadSlashR),
- /*3044*/ uint16(x86_xArgR32),
- /*3045*/ uint16(x86_xArgRM32),
- /*3046*/ uint16(x86_xMatch),
- /*3047*/ uint16(x86_xCondPrefix), 2,
- 0xF2, 3063,
- 0x0, 3053,
- /*3053*/ uint16(x86_xCondDataSize), 3019, 3025, 3057,
- /*3057*/ uint16(x86_xSetOp), uint16(x86_MOVBE),
- /*3059*/ uint16(x86_xReadSlashR),
- /*3060*/ uint16(x86_xArgM64),
- /*3061*/ uint16(x86_xArgR64),
- /*3062*/ uint16(x86_xMatch),
- /*3063*/ uint16(x86_xCondDataSize), 3035, 3041, 3067,
- /*3067*/ uint16(x86_xSetOp), uint16(x86_CRC32),
- /*3069*/ uint16(x86_xReadSlashR),
- /*3070*/ uint16(x86_xArgR64),
- /*3071*/ uint16(x86_xArgRM64),
- /*3072*/ uint16(x86_xMatch),
- /*3073*/ uint16(x86_xCondByte), 24,
- 0x08, 3124,
- 0x09, 3136,
- 0x0A, 3148,
- 0x0B, 3160,
- 0x0C, 3172,
- 0x0D, 3184,
- 0x0E, 3196,
- 0x0F, 3208,
- 0x14, 3230,
- 0x15, 3242,
- 0x16, 3254,
- 0x17, 3297,
- 0x20, 3309,
- 0x21, 3321,
- 0x22, 3333,
- 0x40, 3376,
- 0x41, 3388,
- 0x42, 3400,
- 0x44, 3412,
- 0x60, 3424,
- 0x61, 3436,
- 0x62, 3448,
- 0x63, 3460,
- 0xDF, 3472,
- uint16(x86_xFail),
- /*3124*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3128,
- /*3128*/ uint16(x86_xSetOp), uint16(x86_ROUNDPS),
- /*3130*/ uint16(x86_xReadSlashR),
- /*3131*/ uint16(x86_xReadIb),
- /*3132*/ uint16(x86_xArgXmm1),
- /*3133*/ uint16(x86_xArgXmm2M128),
- /*3134*/ uint16(x86_xArgImm8u),
- /*3135*/ uint16(x86_xMatch),
- /*3136*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3140,
- /*3140*/ uint16(x86_xSetOp), uint16(x86_ROUNDPD),
- /*3142*/ uint16(x86_xReadSlashR),
- /*3143*/ uint16(x86_xReadIb),
- /*3144*/ uint16(x86_xArgXmm1),
- /*3145*/ uint16(x86_xArgXmm2M128),
- /*3146*/ uint16(x86_xArgImm8u),
- /*3147*/ uint16(x86_xMatch),
- /*3148*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3152,
- /*3152*/ uint16(x86_xSetOp), uint16(x86_ROUNDSS),
- /*3154*/ uint16(x86_xReadSlashR),
- /*3155*/ uint16(x86_xReadIb),
- /*3156*/ uint16(x86_xArgXmm1),
- /*3157*/ uint16(x86_xArgXmm2M32),
- /*3158*/ uint16(x86_xArgImm8u),
- /*3159*/ uint16(x86_xMatch),
- /*3160*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3164,
- /*3164*/ uint16(x86_xSetOp), uint16(x86_ROUNDSD),
- /*3166*/ uint16(x86_xReadSlashR),
- /*3167*/ uint16(x86_xReadIb),
- /*3168*/ uint16(x86_xArgXmm1),
- /*3169*/ uint16(x86_xArgXmm2M64),
- /*3170*/ uint16(x86_xArgImm8u),
- /*3171*/ uint16(x86_xMatch),
- /*3172*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3176,
- /*3176*/ uint16(x86_xSetOp), uint16(x86_BLENDPS),
- /*3178*/ uint16(x86_xReadSlashR),
- /*3179*/ uint16(x86_xReadIb),
- /*3180*/ uint16(x86_xArgXmm1),
- /*3181*/ uint16(x86_xArgXmm2M128),
- /*3182*/ uint16(x86_xArgImm8u),
- /*3183*/ uint16(x86_xMatch),
- /*3184*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3188,
- /*3188*/ uint16(x86_xSetOp), uint16(x86_BLENDPD),
- /*3190*/ uint16(x86_xReadSlashR),
- /*3191*/ uint16(x86_xReadIb),
- /*3192*/ uint16(x86_xArgXmm1),
- /*3193*/ uint16(x86_xArgXmm2M128),
- /*3194*/ uint16(x86_xArgImm8u),
- /*3195*/ uint16(x86_xMatch),
- /*3196*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3200,
- /*3200*/ uint16(x86_xSetOp), uint16(x86_PBLENDW),
- /*3202*/ uint16(x86_xReadSlashR),
- /*3203*/ uint16(x86_xReadIb),
- /*3204*/ uint16(x86_xArgXmm1),
- /*3205*/ uint16(x86_xArgXmm2M128),
- /*3206*/ uint16(x86_xArgImm8u),
- /*3207*/ uint16(x86_xMatch),
- /*3208*/ uint16(x86_xCondPrefix), 2,
- 0x66, 3222,
- 0x0, 3214,
- /*3214*/ uint16(x86_xSetOp), uint16(x86_PALIGNR),
- /*3216*/ uint16(x86_xReadSlashR),
- /*3217*/ uint16(x86_xReadIb),
- /*3218*/ uint16(x86_xArgMm1),
- /*3219*/ uint16(x86_xArgMm2M64),
- /*3220*/ uint16(x86_xArgImm8u),
- /*3221*/ uint16(x86_xMatch),
- /*3222*/ uint16(x86_xSetOp), uint16(x86_PALIGNR),
- /*3224*/ uint16(x86_xReadSlashR),
- /*3225*/ uint16(x86_xReadIb),
- /*3226*/ uint16(x86_xArgXmm1),
- /*3227*/ uint16(x86_xArgXmm2M128),
- /*3228*/ uint16(x86_xArgImm8u),
- /*3229*/ uint16(x86_xMatch),
- /*3230*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3234,
- /*3234*/ uint16(x86_xSetOp), uint16(x86_PEXTRB),
- /*3236*/ uint16(x86_xReadSlashR),
- /*3237*/ uint16(x86_xReadIb),
- /*3238*/ uint16(x86_xArgR32M8),
- /*3239*/ uint16(x86_xArgXmm1),
- /*3240*/ uint16(x86_xArgImm8u),
- /*3241*/ uint16(x86_xMatch),
- /*3242*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3246,
- /*3246*/ uint16(x86_xSetOp), uint16(x86_PEXTRW),
- /*3248*/ uint16(x86_xReadSlashR),
- /*3249*/ uint16(x86_xReadIb),
- /*3250*/ uint16(x86_xArgR32M16),
- /*3251*/ uint16(x86_xArgXmm1),
- /*3252*/ uint16(x86_xArgImm8u),
- /*3253*/ uint16(x86_xMatch),
- /*3254*/ uint16(x86_xCondIs64), 3257, 3281,
- /*3257*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3261,
- /*3261*/ uint16(x86_xCondDataSize), 3265, 3273, 0,
- /*3265*/ uint16(x86_xSetOp), uint16(x86_PEXTRD),
- /*3267*/ uint16(x86_xReadSlashR),
- /*3268*/ uint16(x86_xReadIb),
- /*3269*/ uint16(x86_xArgRM32),
- /*3270*/ uint16(x86_xArgXmm1),
- /*3271*/ uint16(x86_xArgImm8u),
- /*3272*/ uint16(x86_xMatch),
- /*3273*/ uint16(x86_xSetOp), uint16(x86_PEXTRD),
- /*3275*/ uint16(x86_xReadSlashR),
- /*3276*/ uint16(x86_xReadIb),
- /*3277*/ uint16(x86_xArgRM32),
- /*3278*/ uint16(x86_xArgXmm1),
- /*3279*/ uint16(x86_xArgImm8u),
- /*3280*/ uint16(x86_xMatch),
- /*3281*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3285,
- /*3285*/ uint16(x86_xCondDataSize), 3265, 3273, 3289,
- /*3289*/ uint16(x86_xSetOp), uint16(x86_PEXTRQ),
- /*3291*/ uint16(x86_xReadSlashR),
- /*3292*/ uint16(x86_xReadIb),
- /*3293*/ uint16(x86_xArgRM64),
- /*3294*/ uint16(x86_xArgXmm1),
- /*3295*/ uint16(x86_xArgImm8u),
- /*3296*/ uint16(x86_xMatch),
- /*3297*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3301,
- /*3301*/ uint16(x86_xSetOp), uint16(x86_EXTRACTPS),
- /*3303*/ uint16(x86_xReadSlashR),
- /*3304*/ uint16(x86_xReadIb),
- /*3305*/ uint16(x86_xArgRM32),
- /*3306*/ uint16(x86_xArgXmm1),
- /*3307*/ uint16(x86_xArgImm8u),
- /*3308*/ uint16(x86_xMatch),
- /*3309*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3313,
- /*3313*/ uint16(x86_xSetOp), uint16(x86_PINSRB),
- /*3315*/ uint16(x86_xReadSlashR),
- /*3316*/ uint16(x86_xReadIb),
- /*3317*/ uint16(x86_xArgXmm1),
- /*3318*/ uint16(x86_xArgR32M8),
- /*3319*/ uint16(x86_xArgImm8u),
- /*3320*/ uint16(x86_xMatch),
- /*3321*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3325,
- /*3325*/ uint16(x86_xSetOp), uint16(x86_INSERTPS),
- /*3327*/ uint16(x86_xReadSlashR),
- /*3328*/ uint16(x86_xReadIb),
- /*3329*/ uint16(x86_xArgXmm1),
- /*3330*/ uint16(x86_xArgXmm2M32),
- /*3331*/ uint16(x86_xArgImm8u),
- /*3332*/ uint16(x86_xMatch),
- /*3333*/ uint16(x86_xCondIs64), 3336, 3360,
- /*3336*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3340,
- /*3340*/ uint16(x86_xCondDataSize), 3344, 3352, 0,
- /*3344*/ uint16(x86_xSetOp), uint16(x86_PINSRD),
- /*3346*/ uint16(x86_xReadSlashR),
- /*3347*/ uint16(x86_xReadIb),
- /*3348*/ uint16(x86_xArgXmm1),
- /*3349*/ uint16(x86_xArgRM32),
- /*3350*/ uint16(x86_xArgImm8u),
- /*3351*/ uint16(x86_xMatch),
- /*3352*/ uint16(x86_xSetOp), uint16(x86_PINSRD),
- /*3354*/ uint16(x86_xReadSlashR),
- /*3355*/ uint16(x86_xReadIb),
- /*3356*/ uint16(x86_xArgXmm1),
- /*3357*/ uint16(x86_xArgRM32),
- /*3358*/ uint16(x86_xArgImm8u),
- /*3359*/ uint16(x86_xMatch),
- /*3360*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3364,
- /*3364*/ uint16(x86_xCondDataSize), 3344, 3352, 3368,
- /*3368*/ uint16(x86_xSetOp), uint16(x86_PINSRQ),
- /*3370*/ uint16(x86_xReadSlashR),
- /*3371*/ uint16(x86_xReadIb),
- /*3372*/ uint16(x86_xArgXmm1),
- /*3373*/ uint16(x86_xArgRM64),
- /*3374*/ uint16(x86_xArgImm8u),
- /*3375*/ uint16(x86_xMatch),
- /*3376*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3380,
- /*3380*/ uint16(x86_xSetOp), uint16(x86_DPPS),
- /*3382*/ uint16(x86_xReadSlashR),
- /*3383*/ uint16(x86_xReadIb),
- /*3384*/ uint16(x86_xArgXmm1),
- /*3385*/ uint16(x86_xArgXmm2M128),
- /*3386*/ uint16(x86_xArgImm8u),
- /*3387*/ uint16(x86_xMatch),
- /*3388*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3392,
- /*3392*/ uint16(x86_xSetOp), uint16(x86_DPPD),
- /*3394*/ uint16(x86_xReadSlashR),
- /*3395*/ uint16(x86_xReadIb),
- /*3396*/ uint16(x86_xArgXmm1),
- /*3397*/ uint16(x86_xArgXmm2M128),
- /*3398*/ uint16(x86_xArgImm8u),
- /*3399*/ uint16(x86_xMatch),
- /*3400*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3404,
- /*3404*/ uint16(x86_xSetOp), uint16(x86_MPSADBW),
- /*3406*/ uint16(x86_xReadSlashR),
- /*3407*/ uint16(x86_xReadIb),
- /*3408*/ uint16(x86_xArgXmm1),
- /*3409*/ uint16(x86_xArgXmm2M128),
- /*3410*/ uint16(x86_xArgImm8u),
- /*3411*/ uint16(x86_xMatch),
- /*3412*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3416,
- /*3416*/ uint16(x86_xSetOp), uint16(x86_PCLMULQDQ),
- /*3418*/ uint16(x86_xReadSlashR),
- /*3419*/ uint16(x86_xReadIb),
- /*3420*/ uint16(x86_xArgXmm1),
- /*3421*/ uint16(x86_xArgXmm2M128),
- /*3422*/ uint16(x86_xArgImm8u),
- /*3423*/ uint16(x86_xMatch),
- /*3424*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3428,
- /*3428*/ uint16(x86_xSetOp), uint16(x86_PCMPESTRM),
- /*3430*/ uint16(x86_xReadSlashR),
- /*3431*/ uint16(x86_xReadIb),
- /*3432*/ uint16(x86_xArgXmm1),
- /*3433*/ uint16(x86_xArgXmm2M128),
- /*3434*/ uint16(x86_xArgImm8u),
- /*3435*/ uint16(x86_xMatch),
- /*3436*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3440,
- /*3440*/ uint16(x86_xSetOp), uint16(x86_PCMPESTRI),
- /*3442*/ uint16(x86_xReadSlashR),
- /*3443*/ uint16(x86_xReadIb),
- /*3444*/ uint16(x86_xArgXmm1),
- /*3445*/ uint16(x86_xArgXmm2M128),
- /*3446*/ uint16(x86_xArgImm8u),
- /*3447*/ uint16(x86_xMatch),
- /*3448*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3452,
- /*3452*/ uint16(x86_xSetOp), uint16(x86_PCMPISTRM),
- /*3454*/ uint16(x86_xReadSlashR),
- /*3455*/ uint16(x86_xReadIb),
- /*3456*/ uint16(x86_xArgXmm1),
- /*3457*/ uint16(x86_xArgXmm2M128),
- /*3458*/ uint16(x86_xArgImm8u),
- /*3459*/ uint16(x86_xMatch),
- /*3460*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3464,
- /*3464*/ uint16(x86_xSetOp), uint16(x86_PCMPISTRI),
- /*3466*/ uint16(x86_xReadSlashR),
- /*3467*/ uint16(x86_xReadIb),
- /*3468*/ uint16(x86_xArgXmm1),
- /*3469*/ uint16(x86_xArgXmm2M128),
- /*3470*/ uint16(x86_xArgImm8u),
- /*3471*/ uint16(x86_xMatch),
- /*3472*/ uint16(x86_xCondPrefix), 1,
- 0x66, 3476,
- /*3476*/ uint16(x86_xSetOp), uint16(x86_AESKEYGENASSIST),
- /*3478*/ uint16(x86_xReadSlashR),
- /*3479*/ uint16(x86_xReadIb),
- /*3480*/ uint16(x86_xArgXmm1),
- /*3481*/ uint16(x86_xArgXmm2M128),
- /*3482*/ uint16(x86_xArgImm8u),
- /*3483*/ uint16(x86_xMatch),
- /*3484*/ uint16(x86_xCondIs64), 3487, 3503,
- /*3487*/ uint16(x86_xCondDataSize), 3491, 3497, 0,
- /*3491*/ uint16(x86_xSetOp), uint16(x86_CMOVO),
- /*3493*/ uint16(x86_xReadSlashR),
- /*3494*/ uint16(x86_xArgR16),
- /*3495*/ uint16(x86_xArgRM16),
- /*3496*/ uint16(x86_xMatch),
- /*3497*/ uint16(x86_xSetOp), uint16(x86_CMOVO),
- /*3499*/ uint16(x86_xReadSlashR),
- /*3500*/ uint16(x86_xArgR32),
- /*3501*/ uint16(x86_xArgRM32),
- /*3502*/ uint16(x86_xMatch),
- /*3503*/ uint16(x86_xCondDataSize), 3491, 3497, 3507,
- /*3507*/ uint16(x86_xSetOp), uint16(x86_CMOVO),
- /*3509*/ uint16(x86_xReadSlashR),
- /*3510*/ uint16(x86_xArgR64),
- /*3511*/ uint16(x86_xArgRM64),
- /*3512*/ uint16(x86_xMatch),
- /*3513*/ uint16(x86_xCondIs64), 3516, 3532,
- /*3516*/ uint16(x86_xCondDataSize), 3520, 3526, 0,
- /*3520*/ uint16(x86_xSetOp), uint16(x86_CMOVNO),
- /*3522*/ uint16(x86_xReadSlashR),
- /*3523*/ uint16(x86_xArgR16),
- /*3524*/ uint16(x86_xArgRM16),
- /*3525*/ uint16(x86_xMatch),
- /*3526*/ uint16(x86_xSetOp), uint16(x86_CMOVNO),
- /*3528*/ uint16(x86_xReadSlashR),
- /*3529*/ uint16(x86_xArgR32),
- /*3530*/ uint16(x86_xArgRM32),
- /*3531*/ uint16(x86_xMatch),
- /*3532*/ uint16(x86_xCondDataSize), 3520, 3526, 3536,
- /*3536*/ uint16(x86_xSetOp), uint16(x86_CMOVNO),
- /*3538*/ uint16(x86_xReadSlashR),
- /*3539*/ uint16(x86_xArgR64),
- /*3540*/ uint16(x86_xArgRM64),
- /*3541*/ uint16(x86_xMatch),
- /*3542*/ uint16(x86_xCondIs64), 3545, 3561,
- /*3545*/ uint16(x86_xCondDataSize), 3549, 3555, 0,
- /*3549*/ uint16(x86_xSetOp), uint16(x86_CMOVB),
- /*3551*/ uint16(x86_xReadSlashR),
- /*3552*/ uint16(x86_xArgR16),
- /*3553*/ uint16(x86_xArgRM16),
- /*3554*/ uint16(x86_xMatch),
- /*3555*/ uint16(x86_xSetOp), uint16(x86_CMOVB),
- /*3557*/ uint16(x86_xReadSlashR),
- /*3558*/ uint16(x86_xArgR32),
- /*3559*/ uint16(x86_xArgRM32),
- /*3560*/ uint16(x86_xMatch),
- /*3561*/ uint16(x86_xCondDataSize), 3549, 3555, 3565,
- /*3565*/ uint16(x86_xSetOp), uint16(x86_CMOVB),
- /*3567*/ uint16(x86_xReadSlashR),
- /*3568*/ uint16(x86_xArgR64),
- /*3569*/ uint16(x86_xArgRM64),
- /*3570*/ uint16(x86_xMatch),
- /*3571*/ uint16(x86_xCondIs64), 3574, 3590,
- /*3574*/ uint16(x86_xCondDataSize), 3578, 3584, 0,
- /*3578*/ uint16(x86_xSetOp), uint16(x86_CMOVAE),
- /*3580*/ uint16(x86_xReadSlashR),
- /*3581*/ uint16(x86_xArgR16),
- /*3582*/ uint16(x86_xArgRM16),
- /*3583*/ uint16(x86_xMatch),
- /*3584*/ uint16(x86_xSetOp), uint16(x86_CMOVAE),
- /*3586*/ uint16(x86_xReadSlashR),
- /*3587*/ uint16(x86_xArgR32),
- /*3588*/ uint16(x86_xArgRM32),
- /*3589*/ uint16(x86_xMatch),
- /*3590*/ uint16(x86_xCondDataSize), 3578, 3584, 3594,
- /*3594*/ uint16(x86_xSetOp), uint16(x86_CMOVAE),
- /*3596*/ uint16(x86_xReadSlashR),
- /*3597*/ uint16(x86_xArgR64),
- /*3598*/ uint16(x86_xArgRM64),
- /*3599*/ uint16(x86_xMatch),
- /*3600*/ uint16(x86_xCondIs64), 3603, 3619,
- /*3603*/ uint16(x86_xCondDataSize), 3607, 3613, 0,
- /*3607*/ uint16(x86_xSetOp), uint16(x86_CMOVE),
- /*3609*/ uint16(x86_xReadSlashR),
- /*3610*/ uint16(x86_xArgR16),
- /*3611*/ uint16(x86_xArgRM16),
- /*3612*/ uint16(x86_xMatch),
- /*3613*/ uint16(x86_xSetOp), uint16(x86_CMOVE),
- /*3615*/ uint16(x86_xReadSlashR),
- /*3616*/ uint16(x86_xArgR32),
- /*3617*/ uint16(x86_xArgRM32),
- /*3618*/ uint16(x86_xMatch),
- /*3619*/ uint16(x86_xCondDataSize), 3607, 3613, 3623,
- /*3623*/ uint16(x86_xSetOp), uint16(x86_CMOVE),
- /*3625*/ uint16(x86_xReadSlashR),
- /*3626*/ uint16(x86_xArgR64),
- /*3627*/ uint16(x86_xArgRM64),
- /*3628*/ uint16(x86_xMatch),
- /*3629*/ uint16(x86_xCondIs64), 3632, 3648,
- /*3632*/ uint16(x86_xCondDataSize), 3636, 3642, 0,
- /*3636*/ uint16(x86_xSetOp), uint16(x86_CMOVNE),
- /*3638*/ uint16(x86_xReadSlashR),
- /*3639*/ uint16(x86_xArgR16),
- /*3640*/ uint16(x86_xArgRM16),
- /*3641*/ uint16(x86_xMatch),
- /*3642*/ uint16(x86_xSetOp), uint16(x86_CMOVNE),
- /*3644*/ uint16(x86_xReadSlashR),
- /*3645*/ uint16(x86_xArgR32),
- /*3646*/ uint16(x86_xArgRM32),
- /*3647*/ uint16(x86_xMatch),
- /*3648*/ uint16(x86_xCondDataSize), 3636, 3642, 3652,
- /*3652*/ uint16(x86_xSetOp), uint16(x86_CMOVNE),
- /*3654*/ uint16(x86_xReadSlashR),
- /*3655*/ uint16(x86_xArgR64),
- /*3656*/ uint16(x86_xArgRM64),
- /*3657*/ uint16(x86_xMatch),
- /*3658*/ uint16(x86_xCondIs64), 3661, 3677,
- /*3661*/ uint16(x86_xCondDataSize), 3665, 3671, 0,
- /*3665*/ uint16(x86_xSetOp), uint16(x86_CMOVBE),
- /*3667*/ uint16(x86_xReadSlashR),
- /*3668*/ uint16(x86_xArgR16),
- /*3669*/ uint16(x86_xArgRM16),
- /*3670*/ uint16(x86_xMatch),
- /*3671*/ uint16(x86_xSetOp), uint16(x86_CMOVBE),
- /*3673*/ uint16(x86_xReadSlashR),
- /*3674*/ uint16(x86_xArgR32),
- /*3675*/ uint16(x86_xArgRM32),
- /*3676*/ uint16(x86_xMatch),
- /*3677*/ uint16(x86_xCondDataSize), 3665, 3671, 3681,
- /*3681*/ uint16(x86_xSetOp), uint16(x86_CMOVBE),
- /*3683*/ uint16(x86_xReadSlashR),
- /*3684*/ uint16(x86_xArgR64),
- /*3685*/ uint16(x86_xArgRM64),
- /*3686*/ uint16(x86_xMatch),
- /*3687*/ uint16(x86_xCondIs64), 3690, 3706,
- /*3690*/ uint16(x86_xCondDataSize), 3694, 3700, 0,
- /*3694*/ uint16(x86_xSetOp), uint16(x86_CMOVA),
- /*3696*/ uint16(x86_xReadSlashR),
- /*3697*/ uint16(x86_xArgR16),
- /*3698*/ uint16(x86_xArgRM16),
- /*3699*/ uint16(x86_xMatch),
- /*3700*/ uint16(x86_xSetOp), uint16(x86_CMOVA),
- /*3702*/ uint16(x86_xReadSlashR),
- /*3703*/ uint16(x86_xArgR32),
- /*3704*/ uint16(x86_xArgRM32),
- /*3705*/ uint16(x86_xMatch),
- /*3706*/ uint16(x86_xCondDataSize), 3694, 3700, 3710,
- /*3710*/ uint16(x86_xSetOp), uint16(x86_CMOVA),
- /*3712*/ uint16(x86_xReadSlashR),
- /*3713*/ uint16(x86_xArgR64),
- /*3714*/ uint16(x86_xArgRM64),
- /*3715*/ uint16(x86_xMatch),
- /*3716*/ uint16(x86_xCondIs64), 3719, 3735,
- /*3719*/ uint16(x86_xCondDataSize), 3723, 3729, 0,
- /*3723*/ uint16(x86_xSetOp), uint16(x86_CMOVS),
- /*3725*/ uint16(x86_xReadSlashR),
- /*3726*/ uint16(x86_xArgR16),
- /*3727*/ uint16(x86_xArgRM16),
- /*3728*/ uint16(x86_xMatch),
- /*3729*/ uint16(x86_xSetOp), uint16(x86_CMOVS),
- /*3731*/ uint16(x86_xReadSlashR),
- /*3732*/ uint16(x86_xArgR32),
- /*3733*/ uint16(x86_xArgRM32),
- /*3734*/ uint16(x86_xMatch),
- /*3735*/ uint16(x86_xCondDataSize), 3723, 3729, 3739,
- /*3739*/ uint16(x86_xSetOp), uint16(x86_CMOVS),
- /*3741*/ uint16(x86_xReadSlashR),
- /*3742*/ uint16(x86_xArgR64),
- /*3743*/ uint16(x86_xArgRM64),
- /*3744*/ uint16(x86_xMatch),
- /*3745*/ uint16(x86_xCondIs64), 3748, 3764,
- /*3748*/ uint16(x86_xCondDataSize), 3752, 3758, 0,
- /*3752*/ uint16(x86_xSetOp), uint16(x86_CMOVNS),
- /*3754*/ uint16(x86_xReadSlashR),
- /*3755*/ uint16(x86_xArgR16),
- /*3756*/ uint16(x86_xArgRM16),
- /*3757*/ uint16(x86_xMatch),
- /*3758*/ uint16(x86_xSetOp), uint16(x86_CMOVNS),
- /*3760*/ uint16(x86_xReadSlashR),
- /*3761*/ uint16(x86_xArgR32),
- /*3762*/ uint16(x86_xArgRM32),
- /*3763*/ uint16(x86_xMatch),
- /*3764*/ uint16(x86_xCondDataSize), 3752, 3758, 3768,
- /*3768*/ uint16(x86_xSetOp), uint16(x86_CMOVNS),
- /*3770*/ uint16(x86_xReadSlashR),
- /*3771*/ uint16(x86_xArgR64),
- /*3772*/ uint16(x86_xArgRM64),
- /*3773*/ uint16(x86_xMatch),
- /*3774*/ uint16(x86_xCondIs64), 3777, 3793,
- /*3777*/ uint16(x86_xCondDataSize), 3781, 3787, 0,
- /*3781*/ uint16(x86_xSetOp), uint16(x86_CMOVP),
- /*3783*/ uint16(x86_xReadSlashR),
- /*3784*/ uint16(x86_xArgR16),
- /*3785*/ uint16(x86_xArgRM16),
- /*3786*/ uint16(x86_xMatch),
- /*3787*/ uint16(x86_xSetOp), uint16(x86_CMOVP),
- /*3789*/ uint16(x86_xReadSlashR),
- /*3790*/ uint16(x86_xArgR32),
- /*3791*/ uint16(x86_xArgRM32),
- /*3792*/ uint16(x86_xMatch),
- /*3793*/ uint16(x86_xCondDataSize), 3781, 3787, 3797,
- /*3797*/ uint16(x86_xSetOp), uint16(x86_CMOVP),
- /*3799*/ uint16(x86_xReadSlashR),
- /*3800*/ uint16(x86_xArgR64),
- /*3801*/ uint16(x86_xArgRM64),
- /*3802*/ uint16(x86_xMatch),
- /*3803*/ uint16(x86_xCondIs64), 3806, 3822,
- /*3806*/ uint16(x86_xCondDataSize), 3810, 3816, 0,
- /*3810*/ uint16(x86_xSetOp), uint16(x86_CMOVNP),
- /*3812*/ uint16(x86_xReadSlashR),
- /*3813*/ uint16(x86_xArgR16),
- /*3814*/ uint16(x86_xArgRM16),
- /*3815*/ uint16(x86_xMatch),
- /*3816*/ uint16(x86_xSetOp), uint16(x86_CMOVNP),
- /*3818*/ uint16(x86_xReadSlashR),
- /*3819*/ uint16(x86_xArgR32),
- /*3820*/ uint16(x86_xArgRM32),
- /*3821*/ uint16(x86_xMatch),
- /*3822*/ uint16(x86_xCondDataSize), 3810, 3816, 3826,
- /*3826*/ uint16(x86_xSetOp), uint16(x86_CMOVNP),
- /*3828*/ uint16(x86_xReadSlashR),
- /*3829*/ uint16(x86_xArgR64),
- /*3830*/ uint16(x86_xArgRM64),
- /*3831*/ uint16(x86_xMatch),
- /*3832*/ uint16(x86_xCondIs64), 3835, 3851,
- /*3835*/ uint16(x86_xCondDataSize), 3839, 3845, 0,
- /*3839*/ uint16(x86_xSetOp), uint16(x86_CMOVL),
- /*3841*/ uint16(x86_xReadSlashR),
- /*3842*/ uint16(x86_xArgR16),
- /*3843*/ uint16(x86_xArgRM16),
- /*3844*/ uint16(x86_xMatch),
- /*3845*/ uint16(x86_xSetOp), uint16(x86_CMOVL),
- /*3847*/ uint16(x86_xReadSlashR),
- /*3848*/ uint16(x86_xArgR32),
- /*3849*/ uint16(x86_xArgRM32),
- /*3850*/ uint16(x86_xMatch),
- /*3851*/ uint16(x86_xCondDataSize), 3839, 3845, 3855,
- /*3855*/ uint16(x86_xSetOp), uint16(x86_CMOVL),
- /*3857*/ uint16(x86_xReadSlashR),
- /*3858*/ uint16(x86_xArgR64),
- /*3859*/ uint16(x86_xArgRM64),
- /*3860*/ uint16(x86_xMatch),
- /*3861*/ uint16(x86_xCondIs64), 3864, 3880,
- /*3864*/ uint16(x86_xCondDataSize), 3868, 3874, 0,
- /*3868*/ uint16(x86_xSetOp), uint16(x86_CMOVGE),
- /*3870*/ uint16(x86_xReadSlashR),
- /*3871*/ uint16(x86_xArgR16),
- /*3872*/ uint16(x86_xArgRM16),
- /*3873*/ uint16(x86_xMatch),
- /*3874*/ uint16(x86_xSetOp), uint16(x86_CMOVGE),
- /*3876*/ uint16(x86_xReadSlashR),
- /*3877*/ uint16(x86_xArgR32),
- /*3878*/ uint16(x86_xArgRM32),
- /*3879*/ uint16(x86_xMatch),
- /*3880*/ uint16(x86_xCondDataSize), 3868, 3874, 3884,
- /*3884*/ uint16(x86_xSetOp), uint16(x86_CMOVGE),
- /*3886*/ uint16(x86_xReadSlashR),
- /*3887*/ uint16(x86_xArgR64),
- /*3888*/ uint16(x86_xArgRM64),
- /*3889*/ uint16(x86_xMatch),
- /*3890*/ uint16(x86_xCondIs64), 3893, 3909,
- /*3893*/ uint16(x86_xCondDataSize), 3897, 3903, 0,
- /*3897*/ uint16(x86_xSetOp), uint16(x86_CMOVLE),
- /*3899*/ uint16(x86_xReadSlashR),
- /*3900*/ uint16(x86_xArgR16),
- /*3901*/ uint16(x86_xArgRM16),
- /*3902*/ uint16(x86_xMatch),
- /*3903*/ uint16(x86_xSetOp), uint16(x86_CMOVLE),
- /*3905*/ uint16(x86_xReadSlashR),
- /*3906*/ uint16(x86_xArgR32),
- /*3907*/ uint16(x86_xArgRM32),
- /*3908*/ uint16(x86_xMatch),
- /*3909*/ uint16(x86_xCondDataSize), 3897, 3903, 3913,
- /*3913*/ uint16(x86_xSetOp), uint16(x86_CMOVLE),
- /*3915*/ uint16(x86_xReadSlashR),
- /*3916*/ uint16(x86_xArgR64),
- /*3917*/ uint16(x86_xArgRM64),
- /*3918*/ uint16(x86_xMatch),
- /*3919*/ uint16(x86_xCondIs64), 3922, 3938,
- /*3922*/ uint16(x86_xCondDataSize), 3926, 3932, 0,
- /*3926*/ uint16(x86_xSetOp), uint16(x86_CMOVG),
- /*3928*/ uint16(x86_xReadSlashR),
- /*3929*/ uint16(x86_xArgR16),
- /*3930*/ uint16(x86_xArgRM16),
- /*3931*/ uint16(x86_xMatch),
- /*3932*/ uint16(x86_xSetOp), uint16(x86_CMOVG),
- /*3934*/ uint16(x86_xReadSlashR),
- /*3935*/ uint16(x86_xArgR32),
- /*3936*/ uint16(x86_xArgRM32),
- /*3937*/ uint16(x86_xMatch),
- /*3938*/ uint16(x86_xCondDataSize), 3926, 3932, 3942,
- /*3942*/ uint16(x86_xSetOp), uint16(x86_CMOVG),
- /*3944*/ uint16(x86_xReadSlashR),
- /*3945*/ uint16(x86_xArgR64),
- /*3946*/ uint16(x86_xArgRM64),
- /*3947*/ uint16(x86_xMatch),
- /*3948*/ uint16(x86_xCondPrefix), 2,
- 0x66, 3960,
- 0x0, 3954,
- /*3954*/ uint16(x86_xSetOp), uint16(x86_MOVMSKPS),
- /*3956*/ uint16(x86_xReadSlashR),
- /*3957*/ uint16(x86_xArgR32),
- /*3958*/ uint16(x86_xArgXmm2),
- /*3959*/ uint16(x86_xMatch),
- /*3960*/ uint16(x86_xSetOp), uint16(x86_MOVMSKPD),
- /*3962*/ uint16(x86_xReadSlashR),
- /*3963*/ uint16(x86_xArgR32),
- /*3964*/ uint16(x86_xArgXmm2),
- /*3965*/ uint16(x86_xMatch),
- /*3966*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 3994,
- 0xF2, 3988,
- 0x66, 3982,
- 0x0, 3976,
- /*3976*/ uint16(x86_xSetOp), uint16(x86_SQRTPS),
- /*3978*/ uint16(x86_xReadSlashR),
- /*3979*/ uint16(x86_xArgXmm1),
- /*3980*/ uint16(x86_xArgXmm2M128),
- /*3981*/ uint16(x86_xMatch),
- /*3982*/ uint16(x86_xSetOp), uint16(x86_SQRTPD),
- /*3984*/ uint16(x86_xReadSlashR),
- /*3985*/ uint16(x86_xArgXmm1),
- /*3986*/ uint16(x86_xArgXmm2M128),
- /*3987*/ uint16(x86_xMatch),
- /*3988*/ uint16(x86_xSetOp), uint16(x86_SQRTSD),
- /*3990*/ uint16(x86_xReadSlashR),
- /*3991*/ uint16(x86_xArgXmm1),
- /*3992*/ uint16(x86_xArgXmm2M64),
- /*3993*/ uint16(x86_xMatch),
- /*3994*/ uint16(x86_xSetOp), uint16(x86_SQRTSS),
- /*3996*/ uint16(x86_xReadSlashR),
- /*3997*/ uint16(x86_xArgXmm1),
- /*3998*/ uint16(x86_xArgXmm2M32),
- /*3999*/ uint16(x86_xMatch),
- /*4000*/ uint16(x86_xCondPrefix), 2,
- 0xF3, 4012,
- 0x0, 4006,
- /*4006*/ uint16(x86_xSetOp), uint16(x86_RSQRTPS),
- /*4008*/ uint16(x86_xReadSlashR),
- /*4009*/ uint16(x86_xArgXmm1),
- /*4010*/ uint16(x86_xArgXmm2M128),
- /*4011*/ uint16(x86_xMatch),
- /*4012*/ uint16(x86_xSetOp), uint16(x86_RSQRTSS),
- /*4014*/ uint16(x86_xReadSlashR),
- /*4015*/ uint16(x86_xArgXmm1),
- /*4016*/ uint16(x86_xArgXmm2M32),
- /*4017*/ uint16(x86_xMatch),
- /*4018*/ uint16(x86_xCondPrefix), 2,
- 0xF3, 4030,
- 0x0, 4024,
- /*4024*/ uint16(x86_xSetOp), uint16(x86_RCPPS),
- /*4026*/ uint16(x86_xReadSlashR),
- /*4027*/ uint16(x86_xArgXmm1),
- /*4028*/ uint16(x86_xArgXmm2M128),
- /*4029*/ uint16(x86_xMatch),
- /*4030*/ uint16(x86_xSetOp), uint16(x86_RCPSS),
- /*4032*/ uint16(x86_xReadSlashR),
- /*4033*/ uint16(x86_xArgXmm1),
- /*4034*/ uint16(x86_xArgXmm2M32),
- /*4035*/ uint16(x86_xMatch),
- /*4036*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4048,
- 0x0, 4042,
- /*4042*/ uint16(x86_xSetOp), uint16(x86_ANDPS),
- /*4044*/ uint16(x86_xReadSlashR),
- /*4045*/ uint16(x86_xArgXmm1),
- /*4046*/ uint16(x86_xArgXmm2M128),
- /*4047*/ uint16(x86_xMatch),
- /*4048*/ uint16(x86_xSetOp), uint16(x86_ANDPD),
- /*4050*/ uint16(x86_xReadSlashR),
- /*4051*/ uint16(x86_xArgXmm1),
- /*4052*/ uint16(x86_xArgXmm2M128),
- /*4053*/ uint16(x86_xMatch),
- /*4054*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4066,
- 0x0, 4060,
- /*4060*/ uint16(x86_xSetOp), uint16(x86_ANDNPS),
- /*4062*/ uint16(x86_xReadSlashR),
- /*4063*/ uint16(x86_xArgXmm1),
- /*4064*/ uint16(x86_xArgXmm2M128),
- /*4065*/ uint16(x86_xMatch),
- /*4066*/ uint16(x86_xSetOp), uint16(x86_ANDNPD),
- /*4068*/ uint16(x86_xReadSlashR),
- /*4069*/ uint16(x86_xArgXmm1),
- /*4070*/ uint16(x86_xArgXmm2M128),
- /*4071*/ uint16(x86_xMatch),
- /*4072*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4084,
- 0x0, 4078,
- /*4078*/ uint16(x86_xSetOp), uint16(x86_ORPS),
- /*4080*/ uint16(x86_xReadSlashR),
- /*4081*/ uint16(x86_xArgXmm1),
- /*4082*/ uint16(x86_xArgXmm2M128),
- /*4083*/ uint16(x86_xMatch),
- /*4084*/ uint16(x86_xSetOp), uint16(x86_ORPD),
- /*4086*/ uint16(x86_xReadSlashR),
- /*4087*/ uint16(x86_xArgXmm1),
- /*4088*/ uint16(x86_xArgXmm2M128),
- /*4089*/ uint16(x86_xMatch),
- /*4090*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4102,
- 0x0, 4096,
- /*4096*/ uint16(x86_xSetOp), uint16(x86_XORPS),
- /*4098*/ uint16(x86_xReadSlashR),
- /*4099*/ uint16(x86_xArgXmm1),
- /*4100*/ uint16(x86_xArgXmm2M128),
- /*4101*/ uint16(x86_xMatch),
- /*4102*/ uint16(x86_xSetOp), uint16(x86_XORPD),
- /*4104*/ uint16(x86_xReadSlashR),
- /*4105*/ uint16(x86_xArgXmm1),
- /*4106*/ uint16(x86_xArgXmm2M128),
- /*4107*/ uint16(x86_xMatch),
- /*4108*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 4136,
- 0xF2, 4130,
- 0x66, 4124,
- 0x0, 4118,
- /*4118*/ uint16(x86_xSetOp), uint16(x86_ADDPS),
- /*4120*/ uint16(x86_xReadSlashR),
- /*4121*/ uint16(x86_xArgXmm1),
- /*4122*/ uint16(x86_xArgXmm2M128),
- /*4123*/ uint16(x86_xMatch),
- /*4124*/ uint16(x86_xSetOp), uint16(x86_ADDPD),
- /*4126*/ uint16(x86_xReadSlashR),
- /*4127*/ uint16(x86_xArgXmm1),
- /*4128*/ uint16(x86_xArgXmm2M128),
- /*4129*/ uint16(x86_xMatch),
- /*4130*/ uint16(x86_xSetOp), uint16(x86_ADDSD),
- /*4132*/ uint16(x86_xReadSlashR),
- /*4133*/ uint16(x86_xArgXmm1),
- /*4134*/ uint16(x86_xArgXmm2M64),
- /*4135*/ uint16(x86_xMatch),
- /*4136*/ uint16(x86_xSetOp), uint16(x86_ADDSS),
- /*4138*/ uint16(x86_xReadSlashR),
- /*4139*/ uint16(x86_xArgXmm1),
- /*4140*/ uint16(x86_xArgXmm2M32),
- /*4141*/ uint16(x86_xMatch),
- /*4142*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 4170,
- 0xF2, 4164,
- 0x66, 4158,
- 0x0, 4152,
- /*4152*/ uint16(x86_xSetOp), uint16(x86_MULPS),
- /*4154*/ uint16(x86_xReadSlashR),
- /*4155*/ uint16(x86_xArgXmm1),
- /*4156*/ uint16(x86_xArgXmm2M128),
- /*4157*/ uint16(x86_xMatch),
- /*4158*/ uint16(x86_xSetOp), uint16(x86_MULPD),
- /*4160*/ uint16(x86_xReadSlashR),
- /*4161*/ uint16(x86_xArgXmm1),
- /*4162*/ uint16(x86_xArgXmm2M128),
- /*4163*/ uint16(x86_xMatch),
- /*4164*/ uint16(x86_xSetOp), uint16(x86_MULSD),
- /*4166*/ uint16(x86_xReadSlashR),
- /*4167*/ uint16(x86_xArgXmm1),
- /*4168*/ uint16(x86_xArgXmm2M64),
- /*4169*/ uint16(x86_xMatch),
- /*4170*/ uint16(x86_xSetOp), uint16(x86_MULSS),
- /*4172*/ uint16(x86_xReadSlashR),
- /*4173*/ uint16(x86_xArgXmm1),
- /*4174*/ uint16(x86_xArgXmm2M32),
- /*4175*/ uint16(x86_xMatch),
- /*4176*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 4204,
- 0xF2, 4198,
- 0x66, 4192,
- 0x0, 4186,
- /*4186*/ uint16(x86_xSetOp), uint16(x86_CVTPS2PD),
- /*4188*/ uint16(x86_xReadSlashR),
- /*4189*/ uint16(x86_xArgXmm1),
- /*4190*/ uint16(x86_xArgXmm2M64),
- /*4191*/ uint16(x86_xMatch),
- /*4192*/ uint16(x86_xSetOp), uint16(x86_CVTPD2PS),
- /*4194*/ uint16(x86_xReadSlashR),
- /*4195*/ uint16(x86_xArgXmm1),
- /*4196*/ uint16(x86_xArgXmm2M128),
- /*4197*/ uint16(x86_xMatch),
- /*4198*/ uint16(x86_xSetOp), uint16(x86_CVTSD2SS),
- /*4200*/ uint16(x86_xReadSlashR),
- /*4201*/ uint16(x86_xArgXmm1),
- /*4202*/ uint16(x86_xArgXmm2M64),
- /*4203*/ uint16(x86_xMatch),
- /*4204*/ uint16(x86_xSetOp), uint16(x86_CVTSS2SD),
- /*4206*/ uint16(x86_xReadSlashR),
- /*4207*/ uint16(x86_xArgXmm1),
- /*4208*/ uint16(x86_xArgXmm2M32),
- /*4209*/ uint16(x86_xMatch),
- /*4210*/ uint16(x86_xCondPrefix), 3,
- 0xF3, 4230,
- 0x66, 4224,
- 0x0, 4218,
- /*4218*/ uint16(x86_xSetOp), uint16(x86_CVTDQ2PS),
- /*4220*/ uint16(x86_xReadSlashR),
- /*4221*/ uint16(x86_xArgXmm1),
- /*4222*/ uint16(x86_xArgXmm2M128),
- /*4223*/ uint16(x86_xMatch),
- /*4224*/ uint16(x86_xSetOp), uint16(x86_CVTPS2DQ),
- /*4226*/ uint16(x86_xReadSlashR),
- /*4227*/ uint16(x86_xArgXmm1),
- /*4228*/ uint16(x86_xArgXmm2M128),
- /*4229*/ uint16(x86_xMatch),
- /*4230*/ uint16(x86_xSetOp), uint16(x86_CVTTPS2DQ),
- /*4232*/ uint16(x86_xReadSlashR),
- /*4233*/ uint16(x86_xArgXmm1),
- /*4234*/ uint16(x86_xArgXmm2M128),
- /*4235*/ uint16(x86_xMatch),
- /*4236*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 4264,
- 0xF2, 4258,
- 0x66, 4252,
- 0x0, 4246,
- /*4246*/ uint16(x86_xSetOp), uint16(x86_SUBPS),
- /*4248*/ uint16(x86_xReadSlashR),
- /*4249*/ uint16(x86_xArgXmm1),
- /*4250*/ uint16(x86_xArgXmm2M128),
- /*4251*/ uint16(x86_xMatch),
- /*4252*/ uint16(x86_xSetOp), uint16(x86_SUBPD),
- /*4254*/ uint16(x86_xReadSlashR),
- /*4255*/ uint16(x86_xArgXmm1),
- /*4256*/ uint16(x86_xArgXmm2M128),
- /*4257*/ uint16(x86_xMatch),
- /*4258*/ uint16(x86_xSetOp), uint16(x86_SUBSD),
- /*4260*/ uint16(x86_xReadSlashR),
- /*4261*/ uint16(x86_xArgXmm1),
- /*4262*/ uint16(x86_xArgXmm2M64),
- /*4263*/ uint16(x86_xMatch),
- /*4264*/ uint16(x86_xSetOp), uint16(x86_SUBSS),
- /*4266*/ uint16(x86_xReadSlashR),
- /*4267*/ uint16(x86_xArgXmm1),
- /*4268*/ uint16(x86_xArgXmm2M32),
- /*4269*/ uint16(x86_xMatch),
- /*4270*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 4298,
- 0xF2, 4292,
- 0x66, 4286,
- 0x0, 4280,
- /*4280*/ uint16(x86_xSetOp), uint16(x86_MINPS),
- /*4282*/ uint16(x86_xReadSlashR),
- /*4283*/ uint16(x86_xArgXmm1),
- /*4284*/ uint16(x86_xArgXmm2M128),
- /*4285*/ uint16(x86_xMatch),
- /*4286*/ uint16(x86_xSetOp), uint16(x86_MINPD),
- /*4288*/ uint16(x86_xReadSlashR),
- /*4289*/ uint16(x86_xArgXmm1),
- /*4290*/ uint16(x86_xArgXmm2M128),
- /*4291*/ uint16(x86_xMatch),
- /*4292*/ uint16(x86_xSetOp), uint16(x86_MINSD),
- /*4294*/ uint16(x86_xReadSlashR),
- /*4295*/ uint16(x86_xArgXmm1),
- /*4296*/ uint16(x86_xArgXmm2M64),
- /*4297*/ uint16(x86_xMatch),
- /*4298*/ uint16(x86_xSetOp), uint16(x86_MINSS),
- /*4300*/ uint16(x86_xReadSlashR),
- /*4301*/ uint16(x86_xArgXmm1),
- /*4302*/ uint16(x86_xArgXmm2M32),
- /*4303*/ uint16(x86_xMatch),
- /*4304*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 4332,
- 0xF2, 4326,
- 0x66, 4320,
- 0x0, 4314,
- /*4314*/ uint16(x86_xSetOp), uint16(x86_DIVPS),
- /*4316*/ uint16(x86_xReadSlashR),
- /*4317*/ uint16(x86_xArgXmm1),
- /*4318*/ uint16(x86_xArgXmm2M128),
- /*4319*/ uint16(x86_xMatch),
- /*4320*/ uint16(x86_xSetOp), uint16(x86_DIVPD),
- /*4322*/ uint16(x86_xReadSlashR),
- /*4323*/ uint16(x86_xArgXmm1),
- /*4324*/ uint16(x86_xArgXmm2M128),
- /*4325*/ uint16(x86_xMatch),
- /*4326*/ uint16(x86_xSetOp), uint16(x86_DIVSD),
- /*4328*/ uint16(x86_xReadSlashR),
- /*4329*/ uint16(x86_xArgXmm1),
- /*4330*/ uint16(x86_xArgXmm2M64),
- /*4331*/ uint16(x86_xMatch),
- /*4332*/ uint16(x86_xSetOp), uint16(x86_DIVSS),
- /*4334*/ uint16(x86_xReadSlashR),
- /*4335*/ uint16(x86_xArgXmm1),
- /*4336*/ uint16(x86_xArgXmm2M32),
- /*4337*/ uint16(x86_xMatch),
- /*4338*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 4366,
- 0xF2, 4360,
- 0x66, 4354,
- 0x0, 4348,
- /*4348*/ uint16(x86_xSetOp), uint16(x86_MAXPS),
- /*4350*/ uint16(x86_xReadSlashR),
- /*4351*/ uint16(x86_xArgXmm1),
- /*4352*/ uint16(x86_xArgXmm2M128),
- /*4353*/ uint16(x86_xMatch),
- /*4354*/ uint16(x86_xSetOp), uint16(x86_MAXPD),
- /*4356*/ uint16(x86_xReadSlashR),
- /*4357*/ uint16(x86_xArgXmm1),
- /*4358*/ uint16(x86_xArgXmm2M128),
- /*4359*/ uint16(x86_xMatch),
- /*4360*/ uint16(x86_xSetOp), uint16(x86_MAXSD),
- /*4362*/ uint16(x86_xReadSlashR),
- /*4363*/ uint16(x86_xArgXmm1),
- /*4364*/ uint16(x86_xArgXmm2M64),
- /*4365*/ uint16(x86_xMatch),
- /*4366*/ uint16(x86_xSetOp), uint16(x86_MAXSS),
- /*4368*/ uint16(x86_xReadSlashR),
- /*4369*/ uint16(x86_xArgXmm1),
- /*4370*/ uint16(x86_xArgXmm2M32),
- /*4371*/ uint16(x86_xMatch),
- /*4372*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4384,
- 0x0, 4378,
- /*4378*/ uint16(x86_xSetOp), uint16(x86_PUNPCKLBW),
- /*4380*/ uint16(x86_xReadSlashR),
- /*4381*/ uint16(x86_xArgMm),
- /*4382*/ uint16(x86_xArgMmM32),
- /*4383*/ uint16(x86_xMatch),
- /*4384*/ uint16(x86_xSetOp), uint16(x86_PUNPCKLBW),
- /*4386*/ uint16(x86_xReadSlashR),
- /*4387*/ uint16(x86_xArgXmm1),
- /*4388*/ uint16(x86_xArgXmm2M128),
- /*4389*/ uint16(x86_xMatch),
- /*4390*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4402,
- 0x0, 4396,
- /*4396*/ uint16(x86_xSetOp), uint16(x86_PUNPCKLWD),
- /*4398*/ uint16(x86_xReadSlashR),
- /*4399*/ uint16(x86_xArgMm),
- /*4400*/ uint16(x86_xArgMmM32),
- /*4401*/ uint16(x86_xMatch),
- /*4402*/ uint16(x86_xSetOp), uint16(x86_PUNPCKLWD),
- /*4404*/ uint16(x86_xReadSlashR),
- /*4405*/ uint16(x86_xArgXmm1),
- /*4406*/ uint16(x86_xArgXmm2M128),
- /*4407*/ uint16(x86_xMatch),
- /*4408*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4420,
- 0x0, 4414,
- /*4414*/ uint16(x86_xSetOp), uint16(x86_PUNPCKLDQ),
- /*4416*/ uint16(x86_xReadSlashR),
- /*4417*/ uint16(x86_xArgMm),
- /*4418*/ uint16(x86_xArgMmM32),
- /*4419*/ uint16(x86_xMatch),
- /*4420*/ uint16(x86_xSetOp), uint16(x86_PUNPCKLDQ),
- /*4422*/ uint16(x86_xReadSlashR),
- /*4423*/ uint16(x86_xArgXmm1),
- /*4424*/ uint16(x86_xArgXmm2M128),
- /*4425*/ uint16(x86_xMatch),
- /*4426*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4438,
- 0x0, 4432,
- /*4432*/ uint16(x86_xSetOp), uint16(x86_PACKSSWB),
- /*4434*/ uint16(x86_xReadSlashR),
- /*4435*/ uint16(x86_xArgMm1),
- /*4436*/ uint16(x86_xArgMm2M64),
- /*4437*/ uint16(x86_xMatch),
- /*4438*/ uint16(x86_xSetOp), uint16(x86_PACKSSWB),
- /*4440*/ uint16(x86_xReadSlashR),
- /*4441*/ uint16(x86_xArgXmm1),
- /*4442*/ uint16(x86_xArgXmm2M128),
- /*4443*/ uint16(x86_xMatch),
- /*4444*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4456,
- 0x0, 4450,
- /*4450*/ uint16(x86_xSetOp), uint16(x86_PCMPGTB),
- /*4452*/ uint16(x86_xReadSlashR),
- /*4453*/ uint16(x86_xArgMm),
- /*4454*/ uint16(x86_xArgMmM64),
- /*4455*/ uint16(x86_xMatch),
- /*4456*/ uint16(x86_xSetOp), uint16(x86_PCMPGTB),
- /*4458*/ uint16(x86_xReadSlashR),
- /*4459*/ uint16(x86_xArgXmm1),
- /*4460*/ uint16(x86_xArgXmm2M128),
- /*4461*/ uint16(x86_xMatch),
- /*4462*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4474,
- 0x0, 4468,
- /*4468*/ uint16(x86_xSetOp), uint16(x86_PCMPGTW),
- /*4470*/ uint16(x86_xReadSlashR),
- /*4471*/ uint16(x86_xArgMm),
- /*4472*/ uint16(x86_xArgMmM64),
- /*4473*/ uint16(x86_xMatch),
- /*4474*/ uint16(x86_xSetOp), uint16(x86_PCMPGTW),
- /*4476*/ uint16(x86_xReadSlashR),
- /*4477*/ uint16(x86_xArgXmm1),
- /*4478*/ uint16(x86_xArgXmm2M128),
- /*4479*/ uint16(x86_xMatch),
- /*4480*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4492,
- 0x0, 4486,
- /*4486*/ uint16(x86_xSetOp), uint16(x86_PCMPGTD),
- /*4488*/ uint16(x86_xReadSlashR),
- /*4489*/ uint16(x86_xArgMm),
- /*4490*/ uint16(x86_xArgMmM64),
- /*4491*/ uint16(x86_xMatch),
- /*4492*/ uint16(x86_xSetOp), uint16(x86_PCMPGTD),
- /*4494*/ uint16(x86_xReadSlashR),
- /*4495*/ uint16(x86_xArgXmm1),
- /*4496*/ uint16(x86_xArgXmm2M128),
- /*4497*/ uint16(x86_xMatch),
- /*4498*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4510,
- 0x0, 4504,
- /*4504*/ uint16(x86_xSetOp), uint16(x86_PACKUSWB),
- /*4506*/ uint16(x86_xReadSlashR),
- /*4507*/ uint16(x86_xArgMm),
- /*4508*/ uint16(x86_xArgMmM64),
- /*4509*/ uint16(x86_xMatch),
- /*4510*/ uint16(x86_xSetOp), uint16(x86_PACKUSWB),
- /*4512*/ uint16(x86_xReadSlashR),
- /*4513*/ uint16(x86_xArgXmm1),
- /*4514*/ uint16(x86_xArgXmm2M128),
- /*4515*/ uint16(x86_xMatch),
- /*4516*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4528,
- 0x0, 4522,
- /*4522*/ uint16(x86_xSetOp), uint16(x86_PUNPCKHBW),
- /*4524*/ uint16(x86_xReadSlashR),
- /*4525*/ uint16(x86_xArgMm),
- /*4526*/ uint16(x86_xArgMmM64),
- /*4527*/ uint16(x86_xMatch),
- /*4528*/ uint16(x86_xSetOp), uint16(x86_PUNPCKHBW),
- /*4530*/ uint16(x86_xReadSlashR),
- /*4531*/ uint16(x86_xArgXmm1),
- /*4532*/ uint16(x86_xArgXmm2M128),
- /*4533*/ uint16(x86_xMatch),
- /*4534*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4546,
- 0x0, 4540,
- /*4540*/ uint16(x86_xSetOp), uint16(x86_PUNPCKHWD),
- /*4542*/ uint16(x86_xReadSlashR),
- /*4543*/ uint16(x86_xArgMm),
- /*4544*/ uint16(x86_xArgMmM64),
- /*4545*/ uint16(x86_xMatch),
- /*4546*/ uint16(x86_xSetOp), uint16(x86_PUNPCKHWD),
- /*4548*/ uint16(x86_xReadSlashR),
- /*4549*/ uint16(x86_xArgXmm1),
- /*4550*/ uint16(x86_xArgXmm2M128),
- /*4551*/ uint16(x86_xMatch),
- /*4552*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4564,
- 0x0, 4558,
- /*4558*/ uint16(x86_xSetOp), uint16(x86_PUNPCKHDQ),
- /*4560*/ uint16(x86_xReadSlashR),
- /*4561*/ uint16(x86_xArgMm),
- /*4562*/ uint16(x86_xArgMmM64),
- /*4563*/ uint16(x86_xMatch),
- /*4564*/ uint16(x86_xSetOp), uint16(x86_PUNPCKHDQ),
- /*4566*/ uint16(x86_xReadSlashR),
- /*4567*/ uint16(x86_xArgXmm1),
- /*4568*/ uint16(x86_xArgXmm2M128),
- /*4569*/ uint16(x86_xMatch),
- /*4570*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4582,
- 0x0, 4576,
- /*4576*/ uint16(x86_xSetOp), uint16(x86_PACKSSDW),
- /*4578*/ uint16(x86_xReadSlashR),
- /*4579*/ uint16(x86_xArgMm1),
- /*4580*/ uint16(x86_xArgMm2M64),
- /*4581*/ uint16(x86_xMatch),
- /*4582*/ uint16(x86_xSetOp), uint16(x86_PACKSSDW),
- /*4584*/ uint16(x86_xReadSlashR),
- /*4585*/ uint16(x86_xArgXmm1),
- /*4586*/ uint16(x86_xArgXmm2M128),
- /*4587*/ uint16(x86_xMatch),
- /*4588*/ uint16(x86_xCondPrefix), 1,
- 0x66, 4592,
- /*4592*/ uint16(x86_xSetOp), uint16(x86_PUNPCKLQDQ),
- /*4594*/ uint16(x86_xReadSlashR),
- /*4595*/ uint16(x86_xArgXmm1),
- /*4596*/ uint16(x86_xArgXmm2M128),
- /*4597*/ uint16(x86_xMatch),
- /*4598*/ uint16(x86_xCondPrefix), 1,
- 0x66, 4602,
- /*4602*/ uint16(x86_xSetOp), uint16(x86_PUNPCKHQDQ),
- /*4604*/ uint16(x86_xReadSlashR),
- /*4605*/ uint16(x86_xArgXmm1),
- /*4606*/ uint16(x86_xArgXmm2M128),
- /*4607*/ uint16(x86_xMatch),
- /*4608*/ uint16(x86_xCondIs64), 4611, 4649,
- /*4611*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4633,
- 0x0, 4617,
- /*4617*/ uint16(x86_xCondDataSize), 4621, 4627, 0,
- /*4621*/ uint16(x86_xSetOp), uint16(x86_MOVD),
- /*4623*/ uint16(x86_xReadSlashR),
- /*4624*/ uint16(x86_xArgMm),
- /*4625*/ uint16(x86_xArgRM32),
- /*4626*/ uint16(x86_xMatch),
- /*4627*/ uint16(x86_xSetOp), uint16(x86_MOVD),
- /*4629*/ uint16(x86_xReadSlashR),
- /*4630*/ uint16(x86_xArgMm),
- /*4631*/ uint16(x86_xArgRM32),
- /*4632*/ uint16(x86_xMatch),
- /*4633*/ uint16(x86_xCondDataSize), 4637, 4643, 0,
- /*4637*/ uint16(x86_xSetOp), uint16(x86_MOVD),
- /*4639*/ uint16(x86_xReadSlashR),
- /*4640*/ uint16(x86_xArgXmm),
- /*4641*/ uint16(x86_xArgRM32),
- /*4642*/ uint16(x86_xMatch),
- /*4643*/ uint16(x86_xSetOp), uint16(x86_MOVD),
- /*4645*/ uint16(x86_xReadSlashR),
- /*4646*/ uint16(x86_xArgXmm),
- /*4647*/ uint16(x86_xArgRM32),
- /*4648*/ uint16(x86_xMatch),
- /*4649*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4665,
- 0x0, 4655,
- /*4655*/ uint16(x86_xCondDataSize), 4621, 4627, 4659,
- /*4659*/ uint16(x86_xSetOp), uint16(x86_MOVQ),
- /*4661*/ uint16(x86_xReadSlashR),
- /*4662*/ uint16(x86_xArgMm),
- /*4663*/ uint16(x86_xArgRM64),
- /*4664*/ uint16(x86_xMatch),
- /*4665*/ uint16(x86_xCondDataSize), 4637, 4643, 4669,
- /*4669*/ uint16(x86_xSetOp), uint16(x86_MOVQ),
- /*4671*/ uint16(x86_xReadSlashR),
- /*4672*/ uint16(x86_xArgXmm),
- /*4673*/ uint16(x86_xArgRM64),
- /*4674*/ uint16(x86_xMatch),
- /*4675*/ uint16(x86_xCondPrefix), 3,
- 0xF3, 4695,
- 0x66, 4689,
- 0x0, 4683,
- /*4683*/ uint16(x86_xSetOp), uint16(x86_MOVQ),
- /*4685*/ uint16(x86_xReadSlashR),
- /*4686*/ uint16(x86_xArgMm),
- /*4687*/ uint16(x86_xArgMmM64),
- /*4688*/ uint16(x86_xMatch),
- /*4689*/ uint16(x86_xSetOp), uint16(x86_MOVDQA),
- /*4691*/ uint16(x86_xReadSlashR),
- /*4692*/ uint16(x86_xArgXmm1),
- /*4693*/ uint16(x86_xArgXmm2M128),
- /*4694*/ uint16(x86_xMatch),
- /*4695*/ uint16(x86_xSetOp), uint16(x86_MOVDQU),
- /*4697*/ uint16(x86_xReadSlashR),
- /*4698*/ uint16(x86_xArgXmm1),
- /*4699*/ uint16(x86_xArgXmm2M128),
- /*4700*/ uint16(x86_xMatch),
- /*4701*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 4735,
- 0xF2, 4727,
- 0x66, 4719,
- 0x0, 4711,
- /*4711*/ uint16(x86_xSetOp), uint16(x86_PSHUFW),
- /*4713*/ uint16(x86_xReadSlashR),
- /*4714*/ uint16(x86_xReadIb),
- /*4715*/ uint16(x86_xArgMm1),
- /*4716*/ uint16(x86_xArgMm2M64),
- /*4717*/ uint16(x86_xArgImm8u),
- /*4718*/ uint16(x86_xMatch),
- /*4719*/ uint16(x86_xSetOp), uint16(x86_PSHUFD),
- /*4721*/ uint16(x86_xReadSlashR),
- /*4722*/ uint16(x86_xReadIb),
- /*4723*/ uint16(x86_xArgXmm1),
- /*4724*/ uint16(x86_xArgXmm2M128),
- /*4725*/ uint16(x86_xArgImm8u),
- /*4726*/ uint16(x86_xMatch),
- /*4727*/ uint16(x86_xSetOp), uint16(x86_PSHUFLW),
- /*4729*/ uint16(x86_xReadSlashR),
- /*4730*/ uint16(x86_xReadIb),
- /*4731*/ uint16(x86_xArgXmm1),
- /*4732*/ uint16(x86_xArgXmm2M128),
- /*4733*/ uint16(x86_xArgImm8u),
- /*4734*/ uint16(x86_xMatch),
- /*4735*/ uint16(x86_xSetOp), uint16(x86_PSHUFHW),
- /*4737*/ uint16(x86_xReadSlashR),
- /*4738*/ uint16(x86_xReadIb),
- /*4739*/ uint16(x86_xArgXmm1),
- /*4740*/ uint16(x86_xArgXmm2M128),
- /*4741*/ uint16(x86_xArgImm8u),
- /*4742*/ uint16(x86_xMatch),
- /*4743*/ uint16(x86_xCondSlashR),
- 0, // 0
- 0, // 1
- 4752, // 2
- 0, // 3
- 4770, // 4
- 0, // 5
- 4788, // 6
- 0, // 7
- /*4752*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4764,
- 0x0, 4758,
- /*4758*/ uint16(x86_xSetOp), uint16(x86_PSRLW),
- /*4760*/ uint16(x86_xReadIb),
- /*4761*/ uint16(x86_xArgMm2),
- /*4762*/ uint16(x86_xArgImm8u),
- /*4763*/ uint16(x86_xMatch),
- /*4764*/ uint16(x86_xSetOp), uint16(x86_PSRLW),
- /*4766*/ uint16(x86_xReadIb),
- /*4767*/ uint16(x86_xArgXmm2),
- /*4768*/ uint16(x86_xArgImm8u),
- /*4769*/ uint16(x86_xMatch),
- /*4770*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4782,
- 0x0, 4776,
- /*4776*/ uint16(x86_xSetOp), uint16(x86_PSRAW),
- /*4778*/ uint16(x86_xReadIb),
- /*4779*/ uint16(x86_xArgMm2),
- /*4780*/ uint16(x86_xArgImm8u),
- /*4781*/ uint16(x86_xMatch),
- /*4782*/ uint16(x86_xSetOp), uint16(x86_PSRAW),
- /*4784*/ uint16(x86_xReadIb),
- /*4785*/ uint16(x86_xArgXmm2),
- /*4786*/ uint16(x86_xArgImm8u),
- /*4787*/ uint16(x86_xMatch),
- /*4788*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4800,
- 0x0, 4794,
- /*4794*/ uint16(x86_xSetOp), uint16(x86_PSLLW),
- /*4796*/ uint16(x86_xReadIb),
- /*4797*/ uint16(x86_xArgMm2),
- /*4798*/ uint16(x86_xArgImm8u),
- /*4799*/ uint16(x86_xMatch),
- /*4800*/ uint16(x86_xSetOp), uint16(x86_PSLLW),
- /*4802*/ uint16(x86_xReadIb),
- /*4803*/ uint16(x86_xArgXmm2),
- /*4804*/ uint16(x86_xArgImm8u),
- /*4805*/ uint16(x86_xMatch),
- /*4806*/ uint16(x86_xCondSlashR),
- 0, // 0
- 0, // 1
- 4815, // 2
- 0, // 3
- 4833, // 4
- 0, // 5
- 4851, // 6
- 0, // 7
- /*4815*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4827,
- 0x0, 4821,
- /*4821*/ uint16(x86_xSetOp), uint16(x86_PSRLD),
- /*4823*/ uint16(x86_xReadIb),
- /*4824*/ uint16(x86_xArgMm2),
- /*4825*/ uint16(x86_xArgImm8u),
- /*4826*/ uint16(x86_xMatch),
- /*4827*/ uint16(x86_xSetOp), uint16(x86_PSRLD),
- /*4829*/ uint16(x86_xReadIb),
- /*4830*/ uint16(x86_xArgXmm2),
- /*4831*/ uint16(x86_xArgImm8u),
- /*4832*/ uint16(x86_xMatch),
- /*4833*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4845,
- 0x0, 4839,
- /*4839*/ uint16(x86_xSetOp), uint16(x86_PSRAD),
- /*4841*/ uint16(x86_xReadIb),
- /*4842*/ uint16(x86_xArgMm2),
- /*4843*/ uint16(x86_xArgImm8u),
- /*4844*/ uint16(x86_xMatch),
- /*4845*/ uint16(x86_xSetOp), uint16(x86_PSRAD),
- /*4847*/ uint16(x86_xReadIb),
- /*4848*/ uint16(x86_xArgXmm2),
- /*4849*/ uint16(x86_xArgImm8u),
- /*4850*/ uint16(x86_xMatch),
- /*4851*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4863,
- 0x0, 4857,
- /*4857*/ uint16(x86_xSetOp), uint16(x86_PSLLD),
- /*4859*/ uint16(x86_xReadIb),
- /*4860*/ uint16(x86_xArgMm2),
- /*4861*/ uint16(x86_xArgImm8u),
- /*4862*/ uint16(x86_xMatch),
- /*4863*/ uint16(x86_xSetOp), uint16(x86_PSLLD),
- /*4865*/ uint16(x86_xReadIb),
- /*4866*/ uint16(x86_xArgXmm2),
- /*4867*/ uint16(x86_xArgImm8u),
- /*4868*/ uint16(x86_xMatch),
- /*4869*/ uint16(x86_xCondSlashR),
- 0, // 0
- 0, // 1
- 4878, // 2
- 4896, // 3
- 0, // 4
- 0, // 5
- 4906, // 6
- 4924, // 7
- /*4878*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4890,
- 0x0, 4884,
- /*4884*/ uint16(x86_xSetOp), uint16(x86_PSRLQ),
- /*4886*/ uint16(x86_xReadIb),
- /*4887*/ uint16(x86_xArgMm2),
- /*4888*/ uint16(x86_xArgImm8u),
- /*4889*/ uint16(x86_xMatch),
- /*4890*/ uint16(x86_xSetOp), uint16(x86_PSRLQ),
- /*4892*/ uint16(x86_xReadIb),
- /*4893*/ uint16(x86_xArgXmm2),
- /*4894*/ uint16(x86_xArgImm8u),
- /*4895*/ uint16(x86_xMatch),
- /*4896*/ uint16(x86_xCondPrefix), 1,
- 0x66, 4900,
- /*4900*/ uint16(x86_xSetOp), uint16(x86_PSRLDQ),
- /*4902*/ uint16(x86_xReadIb),
- /*4903*/ uint16(x86_xArgXmm2),
- /*4904*/ uint16(x86_xArgImm8u),
- /*4905*/ uint16(x86_xMatch),
- /*4906*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4918,
- 0x0, 4912,
- /*4912*/ uint16(x86_xSetOp), uint16(x86_PSLLQ),
- /*4914*/ uint16(x86_xReadIb),
- /*4915*/ uint16(x86_xArgMm2),
- /*4916*/ uint16(x86_xArgImm8u),
- /*4917*/ uint16(x86_xMatch),
- /*4918*/ uint16(x86_xSetOp), uint16(x86_PSLLQ),
- /*4920*/ uint16(x86_xReadIb),
- /*4921*/ uint16(x86_xArgXmm2),
- /*4922*/ uint16(x86_xArgImm8u),
- /*4923*/ uint16(x86_xMatch),
- /*4924*/ uint16(x86_xCondPrefix), 1,
- 0x66, 4928,
- /*4928*/ uint16(x86_xSetOp), uint16(x86_PSLLDQ),
- /*4930*/ uint16(x86_xReadIb),
- /*4931*/ uint16(x86_xArgXmm2),
- /*4932*/ uint16(x86_xArgImm8u),
- /*4933*/ uint16(x86_xMatch),
- /*4934*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4946,
- 0x0, 4940,
- /*4940*/ uint16(x86_xSetOp), uint16(x86_PCMPEQB),
- /*4942*/ uint16(x86_xReadSlashR),
- /*4943*/ uint16(x86_xArgMm),
- /*4944*/ uint16(x86_xArgMmM64),
- /*4945*/ uint16(x86_xMatch),
- /*4946*/ uint16(x86_xSetOp), uint16(x86_PCMPEQB),
- /*4948*/ uint16(x86_xReadSlashR),
- /*4949*/ uint16(x86_xArgXmm1),
- /*4950*/ uint16(x86_xArgXmm2M128),
- /*4951*/ uint16(x86_xMatch),
- /*4952*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4964,
- 0x0, 4958,
- /*4958*/ uint16(x86_xSetOp), uint16(x86_PCMPEQW),
- /*4960*/ uint16(x86_xReadSlashR),
- /*4961*/ uint16(x86_xArgMm),
- /*4962*/ uint16(x86_xArgMmM64),
- /*4963*/ uint16(x86_xMatch),
- /*4964*/ uint16(x86_xSetOp), uint16(x86_PCMPEQW),
- /*4966*/ uint16(x86_xReadSlashR),
- /*4967*/ uint16(x86_xArgXmm1),
- /*4968*/ uint16(x86_xArgXmm2M128),
- /*4969*/ uint16(x86_xMatch),
- /*4970*/ uint16(x86_xCondPrefix), 2,
- 0x66, 4982,
- 0x0, 4976,
- /*4976*/ uint16(x86_xSetOp), uint16(x86_PCMPEQD),
- /*4978*/ uint16(x86_xReadSlashR),
- /*4979*/ uint16(x86_xArgMm),
- /*4980*/ uint16(x86_xArgMmM64),
- /*4981*/ uint16(x86_xMatch),
- /*4982*/ uint16(x86_xSetOp), uint16(x86_PCMPEQD),
- /*4984*/ uint16(x86_xReadSlashR),
- /*4985*/ uint16(x86_xArgXmm1),
- /*4986*/ uint16(x86_xArgXmm2M128),
- /*4987*/ uint16(x86_xMatch),
- /*4988*/ uint16(x86_xSetOp), uint16(x86_EMMS),
- /*4990*/ uint16(x86_xMatch),
- /*4991*/ uint16(x86_xCondPrefix), 2,
- 0xF2, 5003,
- 0x66, 4997,
- /*4997*/ uint16(x86_xSetOp), uint16(x86_HADDPD),
- /*4999*/ uint16(x86_xReadSlashR),
- /*5000*/ uint16(x86_xArgXmm1),
- /*5001*/ uint16(x86_xArgXmm2M128),
- /*5002*/ uint16(x86_xMatch),
- /*5003*/ uint16(x86_xSetOp), uint16(x86_HADDPS),
- /*5005*/ uint16(x86_xReadSlashR),
- /*5006*/ uint16(x86_xArgXmm1),
- /*5007*/ uint16(x86_xArgXmm2M128),
- /*5008*/ uint16(x86_xMatch),
- /*5009*/ uint16(x86_xCondPrefix), 2,
- 0xF2, 5021,
- 0x66, 5015,
- /*5015*/ uint16(x86_xSetOp), uint16(x86_HSUBPD),
- /*5017*/ uint16(x86_xReadSlashR),
- /*5018*/ uint16(x86_xArgXmm1),
- /*5019*/ uint16(x86_xArgXmm2M128),
- /*5020*/ uint16(x86_xMatch),
- /*5021*/ uint16(x86_xSetOp), uint16(x86_HSUBPS),
- /*5023*/ uint16(x86_xReadSlashR),
- /*5024*/ uint16(x86_xArgXmm1),
- /*5025*/ uint16(x86_xArgXmm2M128),
- /*5026*/ uint16(x86_xMatch),
- /*5027*/ uint16(x86_xCondIs64), 5030, 5076,
- /*5030*/ uint16(x86_xCondPrefix), 3,
- 0xF3, 5070,
- 0x66, 5054,
- 0x0, 5038,
- /*5038*/ uint16(x86_xCondDataSize), 5042, 5048, 0,
- /*5042*/ uint16(x86_xSetOp), uint16(x86_MOVD),
- /*5044*/ uint16(x86_xReadSlashR),
- /*5045*/ uint16(x86_xArgRM32),
- /*5046*/ uint16(x86_xArgMm),
- /*5047*/ uint16(x86_xMatch),
- /*5048*/ uint16(x86_xSetOp), uint16(x86_MOVD),
- /*5050*/ uint16(x86_xReadSlashR),
- /*5051*/ uint16(x86_xArgRM32),
- /*5052*/ uint16(x86_xArgMm),
- /*5053*/ uint16(x86_xMatch),
- /*5054*/ uint16(x86_xCondDataSize), 5058, 5064, 0,
- /*5058*/ uint16(x86_xSetOp), uint16(x86_MOVD),
- /*5060*/ uint16(x86_xReadSlashR),
- /*5061*/ uint16(x86_xArgRM32),
- /*5062*/ uint16(x86_xArgXmm),
- /*5063*/ uint16(x86_xMatch),
- /*5064*/ uint16(x86_xSetOp), uint16(x86_MOVD),
- /*5066*/ uint16(x86_xReadSlashR),
- /*5067*/ uint16(x86_xArgRM32),
- /*5068*/ uint16(x86_xArgXmm),
- /*5069*/ uint16(x86_xMatch),
- /*5070*/ uint16(x86_xSetOp), uint16(x86_MOVQ),
- /*5072*/ uint16(x86_xReadSlashR),
- /*5073*/ uint16(x86_xArgXmm1),
- /*5074*/ uint16(x86_xArgXmm2M64),
- /*5075*/ uint16(x86_xMatch),
- /*5076*/ uint16(x86_xCondPrefix), 3,
- 0xF3, 5070,
- 0x66, 5094,
- 0x0, 5084,
- /*5084*/ uint16(x86_xCondDataSize), 5042, 5048, 5088,
- /*5088*/ uint16(x86_xSetOp), uint16(x86_MOVQ),
- /*5090*/ uint16(x86_xReadSlashR),
- /*5091*/ uint16(x86_xArgRM64),
- /*5092*/ uint16(x86_xArgMm),
- /*5093*/ uint16(x86_xMatch),
- /*5094*/ uint16(x86_xCondDataSize), 5058, 5064, 5098,
- /*5098*/ uint16(x86_xSetOp), uint16(x86_MOVQ),
- /*5100*/ uint16(x86_xReadSlashR),
- /*5101*/ uint16(x86_xArgRM64),
- /*5102*/ uint16(x86_xArgXmm),
- /*5103*/ uint16(x86_xMatch),
- /*5104*/ uint16(x86_xCondPrefix), 3,
- 0xF3, 5124,
- 0x66, 5118,
- 0x0, 5112,
- /*5112*/ uint16(x86_xSetOp), uint16(x86_MOVQ),
- /*5114*/ uint16(x86_xReadSlashR),
- /*5115*/ uint16(x86_xArgMmM64),
- /*5116*/ uint16(x86_xArgMm),
- /*5117*/ uint16(x86_xMatch),
- /*5118*/ uint16(x86_xSetOp), uint16(x86_MOVDQA),
- /*5120*/ uint16(x86_xReadSlashR),
- /*5121*/ uint16(x86_xArgXmm2M128),
- /*5122*/ uint16(x86_xArgXmm1),
- /*5123*/ uint16(x86_xMatch),
- /*5124*/ uint16(x86_xSetOp), uint16(x86_MOVDQU),
- /*5126*/ uint16(x86_xReadSlashR),
- /*5127*/ uint16(x86_xArgXmm2M128),
- /*5128*/ uint16(x86_xArgXmm1),
- /*5129*/ uint16(x86_xMatch),
- /*5130*/ uint16(x86_xCondIs64), 5133, 5147,
- /*5133*/ uint16(x86_xCondDataSize), 5137, 5142, 0,
- /*5137*/ uint16(x86_xSetOp), uint16(x86_JO),
- /*5139*/ uint16(x86_xReadCw),
- /*5140*/ uint16(x86_xArgRel16),
- /*5141*/ uint16(x86_xMatch),
- /*5142*/ uint16(x86_xSetOp), uint16(x86_JO),
- /*5144*/ uint16(x86_xReadCd),
- /*5145*/ uint16(x86_xArgRel32),
- /*5146*/ uint16(x86_xMatch),
- /*5147*/ uint16(x86_xCondDataSize), 5151, 5142, 5156,
- /*5151*/ uint16(x86_xSetOp), uint16(x86_JO),
- /*5153*/ uint16(x86_xReadCd),
- /*5154*/ uint16(x86_xArgRel32),
- /*5155*/ uint16(x86_xMatch),
- /*5156*/ uint16(x86_xSetOp), uint16(x86_JO),
- /*5158*/ uint16(x86_xReadCd),
- /*5159*/ uint16(x86_xArgRel32),
- /*5160*/ uint16(x86_xMatch),
- /*5161*/ uint16(x86_xCondIs64), 5164, 5178,
- /*5164*/ uint16(x86_xCondDataSize), 5168, 5173, 0,
- /*5168*/ uint16(x86_xSetOp), uint16(x86_JNO),
- /*5170*/ uint16(x86_xReadCw),
- /*5171*/ uint16(x86_xArgRel16),
- /*5172*/ uint16(x86_xMatch),
- /*5173*/ uint16(x86_xSetOp), uint16(x86_JNO),
- /*5175*/ uint16(x86_xReadCd),
- /*5176*/ uint16(x86_xArgRel32),
- /*5177*/ uint16(x86_xMatch),
- /*5178*/ uint16(x86_xCondDataSize), 5182, 5173, 5187,
- /*5182*/ uint16(x86_xSetOp), uint16(x86_JNO),
- /*5184*/ uint16(x86_xReadCd),
- /*5185*/ uint16(x86_xArgRel32),
- /*5186*/ uint16(x86_xMatch),
- /*5187*/ uint16(x86_xSetOp), uint16(x86_JNO),
- /*5189*/ uint16(x86_xReadCd),
- /*5190*/ uint16(x86_xArgRel32),
- /*5191*/ uint16(x86_xMatch),
- /*5192*/ uint16(x86_xCondIs64), 5195, 5209,
- /*5195*/ uint16(x86_xCondDataSize), 5199, 5204, 0,
- /*5199*/ uint16(x86_xSetOp), uint16(x86_JB),
- /*5201*/ uint16(x86_xReadCw),
- /*5202*/ uint16(x86_xArgRel16),
- /*5203*/ uint16(x86_xMatch),
- /*5204*/ uint16(x86_xSetOp), uint16(x86_JB),
- /*5206*/ uint16(x86_xReadCd),
- /*5207*/ uint16(x86_xArgRel32),
- /*5208*/ uint16(x86_xMatch),
- /*5209*/ uint16(x86_xCondDataSize), 5213, 5204, 5218,
- /*5213*/ uint16(x86_xSetOp), uint16(x86_JB),
- /*5215*/ uint16(x86_xReadCd),
- /*5216*/ uint16(x86_xArgRel32),
- /*5217*/ uint16(x86_xMatch),
- /*5218*/ uint16(x86_xSetOp), uint16(x86_JB),
- /*5220*/ uint16(x86_xReadCd),
- /*5221*/ uint16(x86_xArgRel32),
- /*5222*/ uint16(x86_xMatch),
- /*5223*/ uint16(x86_xCondIs64), 5226, 5240,
- /*5226*/ uint16(x86_xCondDataSize), 5230, 5235, 0,
- /*5230*/ uint16(x86_xSetOp), uint16(x86_JAE),
- /*5232*/ uint16(x86_xReadCw),
- /*5233*/ uint16(x86_xArgRel16),
- /*5234*/ uint16(x86_xMatch),
- /*5235*/ uint16(x86_xSetOp), uint16(x86_JAE),
- /*5237*/ uint16(x86_xReadCd),
- /*5238*/ uint16(x86_xArgRel32),
- /*5239*/ uint16(x86_xMatch),
- /*5240*/ uint16(x86_xCondDataSize), 5244, 5235, 5249,
- /*5244*/ uint16(x86_xSetOp), uint16(x86_JAE),
- /*5246*/ uint16(x86_xReadCd),
- /*5247*/ uint16(x86_xArgRel32),
- /*5248*/ uint16(x86_xMatch),
- /*5249*/ uint16(x86_xSetOp), uint16(x86_JAE),
- /*5251*/ uint16(x86_xReadCd),
- /*5252*/ uint16(x86_xArgRel32),
- /*5253*/ uint16(x86_xMatch),
- /*5254*/ uint16(x86_xCondIs64), 5257, 5271,
- /*5257*/ uint16(x86_xCondDataSize), 5261, 5266, 0,
- /*5261*/ uint16(x86_xSetOp), uint16(x86_JE),
- /*5263*/ uint16(x86_xReadCw),
- /*5264*/ uint16(x86_xArgRel16),
- /*5265*/ uint16(x86_xMatch),
- /*5266*/ uint16(x86_xSetOp), uint16(x86_JE),
- /*5268*/ uint16(x86_xReadCd),
- /*5269*/ uint16(x86_xArgRel32),
- /*5270*/ uint16(x86_xMatch),
- /*5271*/ uint16(x86_xCondDataSize), 5275, 5266, 5280,
- /*5275*/ uint16(x86_xSetOp), uint16(x86_JE),
- /*5277*/ uint16(x86_xReadCd),
- /*5278*/ uint16(x86_xArgRel32),
- /*5279*/ uint16(x86_xMatch),
- /*5280*/ uint16(x86_xSetOp), uint16(x86_JE),
- /*5282*/ uint16(x86_xReadCd),
- /*5283*/ uint16(x86_xArgRel32),
- /*5284*/ uint16(x86_xMatch),
- /*5285*/ uint16(x86_xCondIs64), 5288, 5302,
- /*5288*/ uint16(x86_xCondDataSize), 5292, 5297, 0,
- /*5292*/ uint16(x86_xSetOp), uint16(x86_JNE),
- /*5294*/ uint16(x86_xReadCw),
- /*5295*/ uint16(x86_xArgRel16),
- /*5296*/ uint16(x86_xMatch),
- /*5297*/ uint16(x86_xSetOp), uint16(x86_JNE),
- /*5299*/ uint16(x86_xReadCd),
- /*5300*/ uint16(x86_xArgRel32),
- /*5301*/ uint16(x86_xMatch),
- /*5302*/ uint16(x86_xCondDataSize), 5306, 5297, 5311,
- /*5306*/ uint16(x86_xSetOp), uint16(x86_JNE),
- /*5308*/ uint16(x86_xReadCd),
- /*5309*/ uint16(x86_xArgRel32),
- /*5310*/ uint16(x86_xMatch),
- /*5311*/ uint16(x86_xSetOp), uint16(x86_JNE),
- /*5313*/ uint16(x86_xReadCd),
- /*5314*/ uint16(x86_xArgRel32),
- /*5315*/ uint16(x86_xMatch),
- /*5316*/ uint16(x86_xCondIs64), 5319, 5333,
- /*5319*/ uint16(x86_xCondDataSize), 5323, 5328, 0,
- /*5323*/ uint16(x86_xSetOp), uint16(x86_JBE),
- /*5325*/ uint16(x86_xReadCw),
- /*5326*/ uint16(x86_xArgRel16),
- /*5327*/ uint16(x86_xMatch),
- /*5328*/ uint16(x86_xSetOp), uint16(x86_JBE),
- /*5330*/ uint16(x86_xReadCd),
- /*5331*/ uint16(x86_xArgRel32),
- /*5332*/ uint16(x86_xMatch),
- /*5333*/ uint16(x86_xCondDataSize), 5337, 5328, 5342,
- /*5337*/ uint16(x86_xSetOp), uint16(x86_JBE),
- /*5339*/ uint16(x86_xReadCd),
- /*5340*/ uint16(x86_xArgRel32),
- /*5341*/ uint16(x86_xMatch),
- /*5342*/ uint16(x86_xSetOp), uint16(x86_JBE),
- /*5344*/ uint16(x86_xReadCd),
- /*5345*/ uint16(x86_xArgRel32),
- /*5346*/ uint16(x86_xMatch),
- /*5347*/ uint16(x86_xCondIs64), 5350, 5364,
- /*5350*/ uint16(x86_xCondDataSize), 5354, 5359, 0,
- /*5354*/ uint16(x86_xSetOp), uint16(x86_JA),
- /*5356*/ uint16(x86_xReadCw),
- /*5357*/ uint16(x86_xArgRel16),
- /*5358*/ uint16(x86_xMatch),
- /*5359*/ uint16(x86_xSetOp), uint16(x86_JA),
- /*5361*/ uint16(x86_xReadCd),
- /*5362*/ uint16(x86_xArgRel32),
- /*5363*/ uint16(x86_xMatch),
- /*5364*/ uint16(x86_xCondDataSize), 5368, 5359, 5373,
- /*5368*/ uint16(x86_xSetOp), uint16(x86_JA),
- /*5370*/ uint16(x86_xReadCd),
- /*5371*/ uint16(x86_xArgRel32),
- /*5372*/ uint16(x86_xMatch),
- /*5373*/ uint16(x86_xSetOp), uint16(x86_JA),
- /*5375*/ uint16(x86_xReadCd),
- /*5376*/ uint16(x86_xArgRel32),
- /*5377*/ uint16(x86_xMatch),
- /*5378*/ uint16(x86_xCondIs64), 5381, 5395,
- /*5381*/ uint16(x86_xCondDataSize), 5385, 5390, 0,
- /*5385*/ uint16(x86_xSetOp), uint16(x86_JS),
- /*5387*/ uint16(x86_xReadCw),
- /*5388*/ uint16(x86_xArgRel16),
- /*5389*/ uint16(x86_xMatch),
- /*5390*/ uint16(x86_xSetOp), uint16(x86_JS),
- /*5392*/ uint16(x86_xReadCd),
- /*5393*/ uint16(x86_xArgRel32),
- /*5394*/ uint16(x86_xMatch),
- /*5395*/ uint16(x86_xCondDataSize), 5399, 5390, 5404,
- /*5399*/ uint16(x86_xSetOp), uint16(x86_JS),
- /*5401*/ uint16(x86_xReadCd),
- /*5402*/ uint16(x86_xArgRel32),
- /*5403*/ uint16(x86_xMatch),
- /*5404*/ uint16(x86_xSetOp), uint16(x86_JS),
- /*5406*/ uint16(x86_xReadCd),
- /*5407*/ uint16(x86_xArgRel32),
- /*5408*/ uint16(x86_xMatch),
- /*5409*/ uint16(x86_xCondIs64), 5412, 5426,
- /*5412*/ uint16(x86_xCondDataSize), 5416, 5421, 0,
- /*5416*/ uint16(x86_xSetOp), uint16(x86_JNS),
- /*5418*/ uint16(x86_xReadCw),
- /*5419*/ uint16(x86_xArgRel16),
- /*5420*/ uint16(x86_xMatch),
- /*5421*/ uint16(x86_xSetOp), uint16(x86_JNS),
- /*5423*/ uint16(x86_xReadCd),
- /*5424*/ uint16(x86_xArgRel32),
- /*5425*/ uint16(x86_xMatch),
- /*5426*/ uint16(x86_xCondDataSize), 5430, 5421, 5435,
- /*5430*/ uint16(x86_xSetOp), uint16(x86_JNS),
- /*5432*/ uint16(x86_xReadCd),
- /*5433*/ uint16(x86_xArgRel32),
- /*5434*/ uint16(x86_xMatch),
- /*5435*/ uint16(x86_xSetOp), uint16(x86_JNS),
- /*5437*/ uint16(x86_xReadCd),
- /*5438*/ uint16(x86_xArgRel32),
- /*5439*/ uint16(x86_xMatch),
- /*5440*/ uint16(x86_xCondIs64), 5443, 5457,
- /*5443*/ uint16(x86_xCondDataSize), 5447, 5452, 0,
- /*5447*/ uint16(x86_xSetOp), uint16(x86_JP),
- /*5449*/ uint16(x86_xReadCw),
- /*5450*/ uint16(x86_xArgRel16),
- /*5451*/ uint16(x86_xMatch),
- /*5452*/ uint16(x86_xSetOp), uint16(x86_JP),
- /*5454*/ uint16(x86_xReadCd),
- /*5455*/ uint16(x86_xArgRel32),
- /*5456*/ uint16(x86_xMatch),
- /*5457*/ uint16(x86_xCondDataSize), 5461, 5452, 5466,
- /*5461*/ uint16(x86_xSetOp), uint16(x86_JP),
- /*5463*/ uint16(x86_xReadCd),
- /*5464*/ uint16(x86_xArgRel32),
- /*5465*/ uint16(x86_xMatch),
- /*5466*/ uint16(x86_xSetOp), uint16(x86_JP),
- /*5468*/ uint16(x86_xReadCd),
- /*5469*/ uint16(x86_xArgRel32),
- /*5470*/ uint16(x86_xMatch),
- /*5471*/ uint16(x86_xCondIs64), 5474, 5488,
- /*5474*/ uint16(x86_xCondDataSize), 5478, 5483, 0,
- /*5478*/ uint16(x86_xSetOp), uint16(x86_JNP),
- /*5480*/ uint16(x86_xReadCw),
- /*5481*/ uint16(x86_xArgRel16),
- /*5482*/ uint16(x86_xMatch),
- /*5483*/ uint16(x86_xSetOp), uint16(x86_JNP),
- /*5485*/ uint16(x86_xReadCd),
- /*5486*/ uint16(x86_xArgRel32),
- /*5487*/ uint16(x86_xMatch),
- /*5488*/ uint16(x86_xCondDataSize), 5492, 5483, 5497,
- /*5492*/ uint16(x86_xSetOp), uint16(x86_JNP),
- /*5494*/ uint16(x86_xReadCd),
- /*5495*/ uint16(x86_xArgRel32),
- /*5496*/ uint16(x86_xMatch),
- /*5497*/ uint16(x86_xSetOp), uint16(x86_JNP),
- /*5499*/ uint16(x86_xReadCd),
- /*5500*/ uint16(x86_xArgRel32),
- /*5501*/ uint16(x86_xMatch),
- /*5502*/ uint16(x86_xCondIs64), 5505, 5519,
- /*5505*/ uint16(x86_xCondDataSize), 5509, 5514, 0,
- /*5509*/ uint16(x86_xSetOp), uint16(x86_JL),
- /*5511*/ uint16(x86_xReadCw),
- /*5512*/ uint16(x86_xArgRel16),
- /*5513*/ uint16(x86_xMatch),
- /*5514*/ uint16(x86_xSetOp), uint16(x86_JL),
- /*5516*/ uint16(x86_xReadCd),
- /*5517*/ uint16(x86_xArgRel32),
- /*5518*/ uint16(x86_xMatch),
- /*5519*/ uint16(x86_xCondDataSize), 5523, 5514, 5528,
- /*5523*/ uint16(x86_xSetOp), uint16(x86_JL),
- /*5525*/ uint16(x86_xReadCd),
- /*5526*/ uint16(x86_xArgRel32),
- /*5527*/ uint16(x86_xMatch),
- /*5528*/ uint16(x86_xSetOp), uint16(x86_JL),
- /*5530*/ uint16(x86_xReadCd),
- /*5531*/ uint16(x86_xArgRel32),
- /*5532*/ uint16(x86_xMatch),
- /*5533*/ uint16(x86_xCondIs64), 5536, 5550,
- /*5536*/ uint16(x86_xCondDataSize), 5540, 5545, 0,
- /*5540*/ uint16(x86_xSetOp), uint16(x86_JGE),
- /*5542*/ uint16(x86_xReadCw),
- /*5543*/ uint16(x86_xArgRel16),
- /*5544*/ uint16(x86_xMatch),
- /*5545*/ uint16(x86_xSetOp), uint16(x86_JGE),
- /*5547*/ uint16(x86_xReadCd),
- /*5548*/ uint16(x86_xArgRel32),
- /*5549*/ uint16(x86_xMatch),
- /*5550*/ uint16(x86_xCondDataSize), 5554, 5545, 5559,
- /*5554*/ uint16(x86_xSetOp), uint16(x86_JGE),
- /*5556*/ uint16(x86_xReadCd),
- /*5557*/ uint16(x86_xArgRel32),
- /*5558*/ uint16(x86_xMatch),
- /*5559*/ uint16(x86_xSetOp), uint16(x86_JGE),
- /*5561*/ uint16(x86_xReadCd),
- /*5562*/ uint16(x86_xArgRel32),
- /*5563*/ uint16(x86_xMatch),
- /*5564*/ uint16(x86_xCondIs64), 5567, 5581,
- /*5567*/ uint16(x86_xCondDataSize), 5571, 5576, 0,
- /*5571*/ uint16(x86_xSetOp), uint16(x86_JLE),
- /*5573*/ uint16(x86_xReadCw),
- /*5574*/ uint16(x86_xArgRel16),
- /*5575*/ uint16(x86_xMatch),
- /*5576*/ uint16(x86_xSetOp), uint16(x86_JLE),
- /*5578*/ uint16(x86_xReadCd),
- /*5579*/ uint16(x86_xArgRel32),
- /*5580*/ uint16(x86_xMatch),
- /*5581*/ uint16(x86_xCondDataSize), 5585, 5576, 5590,
- /*5585*/ uint16(x86_xSetOp), uint16(x86_JLE),
- /*5587*/ uint16(x86_xReadCd),
- /*5588*/ uint16(x86_xArgRel32),
- /*5589*/ uint16(x86_xMatch),
- /*5590*/ uint16(x86_xSetOp), uint16(x86_JLE),
- /*5592*/ uint16(x86_xReadCd),
- /*5593*/ uint16(x86_xArgRel32),
- /*5594*/ uint16(x86_xMatch),
- /*5595*/ uint16(x86_xCondIs64), 5598, 5612,
- /*5598*/ uint16(x86_xCondDataSize), 5602, 5607, 0,
- /*5602*/ uint16(x86_xSetOp), uint16(x86_JG),
- /*5604*/ uint16(x86_xReadCw),
- /*5605*/ uint16(x86_xArgRel16),
- /*5606*/ uint16(x86_xMatch),
- /*5607*/ uint16(x86_xSetOp), uint16(x86_JG),
- /*5609*/ uint16(x86_xReadCd),
- /*5610*/ uint16(x86_xArgRel32),
- /*5611*/ uint16(x86_xMatch),
- /*5612*/ uint16(x86_xCondDataSize), 5616, 5607, 5621,
- /*5616*/ uint16(x86_xSetOp), uint16(x86_JG),
- /*5618*/ uint16(x86_xReadCd),
- /*5619*/ uint16(x86_xArgRel32),
- /*5620*/ uint16(x86_xMatch),
- /*5621*/ uint16(x86_xSetOp), uint16(x86_JG),
- /*5623*/ uint16(x86_xReadCd),
- /*5624*/ uint16(x86_xArgRel32),
- /*5625*/ uint16(x86_xMatch),
- /*5626*/ uint16(x86_xSetOp), uint16(x86_SETO),
- /*5628*/ uint16(x86_xReadSlashR),
- /*5629*/ uint16(x86_xArgRM8),
- /*5630*/ uint16(x86_xMatch),
- /*5631*/ uint16(x86_xSetOp), uint16(x86_SETNO),
- /*5633*/ uint16(x86_xReadSlashR),
- /*5634*/ uint16(x86_xArgRM8),
- /*5635*/ uint16(x86_xMatch),
- /*5636*/ uint16(x86_xSetOp), uint16(x86_SETB),
- /*5638*/ uint16(x86_xReadSlashR),
- /*5639*/ uint16(x86_xArgRM8),
- /*5640*/ uint16(x86_xMatch),
- /*5641*/ uint16(x86_xSetOp), uint16(x86_SETAE),
- /*5643*/ uint16(x86_xReadSlashR),
- /*5644*/ uint16(x86_xArgRM8),
- /*5645*/ uint16(x86_xMatch),
- /*5646*/ uint16(x86_xSetOp), uint16(x86_SETE),
- /*5648*/ uint16(x86_xReadSlashR),
- /*5649*/ uint16(x86_xArgRM8),
- /*5650*/ uint16(x86_xMatch),
- /*5651*/ uint16(x86_xSetOp), uint16(x86_SETNE),
- /*5653*/ uint16(x86_xReadSlashR),
- /*5654*/ uint16(x86_xArgRM8),
- /*5655*/ uint16(x86_xMatch),
- /*5656*/ uint16(x86_xSetOp), uint16(x86_SETBE),
- /*5658*/ uint16(x86_xReadSlashR),
- /*5659*/ uint16(x86_xArgRM8),
- /*5660*/ uint16(x86_xMatch),
- /*5661*/ uint16(x86_xSetOp), uint16(x86_SETA),
- /*5663*/ uint16(x86_xReadSlashR),
- /*5664*/ uint16(x86_xArgRM8),
- /*5665*/ uint16(x86_xMatch),
- /*5666*/ uint16(x86_xSetOp), uint16(x86_SETS),
- /*5668*/ uint16(x86_xReadSlashR),
- /*5669*/ uint16(x86_xArgRM8),
- /*5670*/ uint16(x86_xMatch),
- /*5671*/ uint16(x86_xSetOp), uint16(x86_SETNS),
- /*5673*/ uint16(x86_xReadSlashR),
- /*5674*/ uint16(x86_xArgRM8),
- /*5675*/ uint16(x86_xMatch),
- /*5676*/ uint16(x86_xSetOp), uint16(x86_SETP),
- /*5678*/ uint16(x86_xReadSlashR),
- /*5679*/ uint16(x86_xArgRM8),
- /*5680*/ uint16(x86_xMatch),
- /*5681*/ uint16(x86_xSetOp), uint16(x86_SETNP),
- /*5683*/ uint16(x86_xReadSlashR),
- /*5684*/ uint16(x86_xArgRM8),
- /*5685*/ uint16(x86_xMatch),
- /*5686*/ uint16(x86_xSetOp), uint16(x86_SETL),
- /*5688*/ uint16(x86_xReadSlashR),
- /*5689*/ uint16(x86_xArgRM8),
- /*5690*/ uint16(x86_xMatch),
- /*5691*/ uint16(x86_xSetOp), uint16(x86_SETGE),
- /*5693*/ uint16(x86_xReadSlashR),
- /*5694*/ uint16(x86_xArgRM8),
- /*5695*/ uint16(x86_xMatch),
- /*5696*/ uint16(x86_xSetOp), uint16(x86_SETLE),
- /*5698*/ uint16(x86_xReadSlashR),
- /*5699*/ uint16(x86_xArgRM8),
- /*5700*/ uint16(x86_xMatch),
- /*5701*/ uint16(x86_xSetOp), uint16(x86_SETG),
- /*5703*/ uint16(x86_xReadSlashR),
- /*5704*/ uint16(x86_xArgRM8),
- /*5705*/ uint16(x86_xMatch),
- /*5706*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*5708*/ uint16(x86_xArgFS),
- /*5709*/ uint16(x86_xMatch),
- /*5710*/ uint16(x86_xCondIs64), 5713, 5725,
- /*5713*/ uint16(x86_xCondDataSize), 5717, 5721, 0,
- /*5717*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*5719*/ uint16(x86_xArgFS),
- /*5720*/ uint16(x86_xMatch),
- /*5721*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*5723*/ uint16(x86_xArgFS),
- /*5724*/ uint16(x86_xMatch),
- /*5725*/ uint16(x86_xCondDataSize), 5717, 5729, 5733,
- /*5729*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*5731*/ uint16(x86_xArgFS),
- /*5732*/ uint16(x86_xMatch),
- /*5733*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*5735*/ uint16(x86_xArgFS),
- /*5736*/ uint16(x86_xMatch),
- /*5737*/ uint16(x86_xSetOp), uint16(x86_CPUID),
- /*5739*/ uint16(x86_xMatch),
- /*5740*/ uint16(x86_xCondIs64), 5743, 5759,
- /*5743*/ uint16(x86_xCondDataSize), 5747, 5753, 0,
- /*5747*/ uint16(x86_xSetOp), uint16(x86_BT),
- /*5749*/ uint16(x86_xReadSlashR),
- /*5750*/ uint16(x86_xArgRM16),
- /*5751*/ uint16(x86_xArgR16),
- /*5752*/ uint16(x86_xMatch),
- /*5753*/ uint16(x86_xSetOp), uint16(x86_BT),
- /*5755*/ uint16(x86_xReadSlashR),
- /*5756*/ uint16(x86_xArgRM32),
- /*5757*/ uint16(x86_xArgR32),
- /*5758*/ uint16(x86_xMatch),
- /*5759*/ uint16(x86_xCondDataSize), 5747, 5753, 5763,
- /*5763*/ uint16(x86_xSetOp), uint16(x86_BT),
- /*5765*/ uint16(x86_xReadSlashR),
- /*5766*/ uint16(x86_xArgRM64),
- /*5767*/ uint16(x86_xArgR64),
- /*5768*/ uint16(x86_xMatch),
- /*5769*/ uint16(x86_xCondIs64), 5772, 5792,
- /*5772*/ uint16(x86_xCondDataSize), 5776, 5784, 0,
- /*5776*/ uint16(x86_xSetOp), uint16(x86_SHLD),
- /*5778*/ uint16(x86_xReadSlashR),
- /*5779*/ uint16(x86_xReadIb),
- /*5780*/ uint16(x86_xArgRM16),
- /*5781*/ uint16(x86_xArgR16),
- /*5782*/ uint16(x86_xArgImm8u),
- /*5783*/ uint16(x86_xMatch),
- /*5784*/ uint16(x86_xSetOp), uint16(x86_SHLD),
- /*5786*/ uint16(x86_xReadSlashR),
- /*5787*/ uint16(x86_xReadIb),
- /*5788*/ uint16(x86_xArgRM32),
- /*5789*/ uint16(x86_xArgR32),
- /*5790*/ uint16(x86_xArgImm8u),
- /*5791*/ uint16(x86_xMatch),
- /*5792*/ uint16(x86_xCondDataSize), 5776, 5784, 5796,
- /*5796*/ uint16(x86_xSetOp), uint16(x86_SHLD),
- /*5798*/ uint16(x86_xReadSlashR),
- /*5799*/ uint16(x86_xReadIb),
- /*5800*/ uint16(x86_xArgRM64),
- /*5801*/ uint16(x86_xArgR64),
- /*5802*/ uint16(x86_xArgImm8u),
- /*5803*/ uint16(x86_xMatch),
- /*5804*/ uint16(x86_xCondIs64), 5807, 5825,
- /*5807*/ uint16(x86_xCondDataSize), 5811, 5818, 0,
- /*5811*/ uint16(x86_xSetOp), uint16(x86_SHLD),
- /*5813*/ uint16(x86_xReadSlashR),
- /*5814*/ uint16(x86_xArgRM16),
- /*5815*/ uint16(x86_xArgR16),
- /*5816*/ uint16(x86_xArgCL),
- /*5817*/ uint16(x86_xMatch),
- /*5818*/ uint16(x86_xSetOp), uint16(x86_SHLD),
- /*5820*/ uint16(x86_xReadSlashR),
- /*5821*/ uint16(x86_xArgRM32),
- /*5822*/ uint16(x86_xArgR32),
- /*5823*/ uint16(x86_xArgCL),
- /*5824*/ uint16(x86_xMatch),
- /*5825*/ uint16(x86_xCondDataSize), 5811, 5818, 5829,
- /*5829*/ uint16(x86_xSetOp), uint16(x86_SHLD),
- /*5831*/ uint16(x86_xReadSlashR),
- /*5832*/ uint16(x86_xArgRM64),
- /*5833*/ uint16(x86_xArgR64),
- /*5834*/ uint16(x86_xArgCL),
- /*5835*/ uint16(x86_xMatch),
- /*5836*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*5838*/ uint16(x86_xArgGS),
- /*5839*/ uint16(x86_xMatch),
- /*5840*/ uint16(x86_xCondIs64), 5843, 5855,
- /*5843*/ uint16(x86_xCondDataSize), 5847, 5851, 0,
- /*5847*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*5849*/ uint16(x86_xArgGS),
- /*5850*/ uint16(x86_xMatch),
- /*5851*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*5853*/ uint16(x86_xArgGS),
- /*5854*/ uint16(x86_xMatch),
- /*5855*/ uint16(x86_xCondDataSize), 5847, 5859, 5863,
- /*5859*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*5861*/ uint16(x86_xArgGS),
- /*5862*/ uint16(x86_xMatch),
- /*5863*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*5865*/ uint16(x86_xArgGS),
- /*5866*/ uint16(x86_xMatch),
- /*5867*/ uint16(x86_xSetOp), uint16(x86_RSM),
- /*5869*/ uint16(x86_xMatch),
- /*5870*/ uint16(x86_xCondIs64), 5873, 5889,
- /*5873*/ uint16(x86_xCondDataSize), 5877, 5883, 0,
- /*5877*/ uint16(x86_xSetOp), uint16(x86_BTS),
- /*5879*/ uint16(x86_xReadSlashR),
- /*5880*/ uint16(x86_xArgRM16),
- /*5881*/ uint16(x86_xArgR16),
- /*5882*/ uint16(x86_xMatch),
- /*5883*/ uint16(x86_xSetOp), uint16(x86_BTS),
- /*5885*/ uint16(x86_xReadSlashR),
- /*5886*/ uint16(x86_xArgRM32),
- /*5887*/ uint16(x86_xArgR32),
- /*5888*/ uint16(x86_xMatch),
- /*5889*/ uint16(x86_xCondDataSize), 5877, 5883, 5893,
- /*5893*/ uint16(x86_xSetOp), uint16(x86_BTS),
- /*5895*/ uint16(x86_xReadSlashR),
- /*5896*/ uint16(x86_xArgRM64),
- /*5897*/ uint16(x86_xArgR64),
- /*5898*/ uint16(x86_xMatch),
- /*5899*/ uint16(x86_xCondIs64), 5902, 5922,
- /*5902*/ uint16(x86_xCondDataSize), 5906, 5914, 0,
- /*5906*/ uint16(x86_xSetOp), uint16(x86_SHRD),
- /*5908*/ uint16(x86_xReadSlashR),
- /*5909*/ uint16(x86_xReadIb),
- /*5910*/ uint16(x86_xArgRM16),
- /*5911*/ uint16(x86_xArgR16),
- /*5912*/ uint16(x86_xArgImm8u),
- /*5913*/ uint16(x86_xMatch),
- /*5914*/ uint16(x86_xSetOp), uint16(x86_SHRD),
- /*5916*/ uint16(x86_xReadSlashR),
- /*5917*/ uint16(x86_xReadIb),
- /*5918*/ uint16(x86_xArgRM32),
- /*5919*/ uint16(x86_xArgR32),
- /*5920*/ uint16(x86_xArgImm8u),
- /*5921*/ uint16(x86_xMatch),
- /*5922*/ uint16(x86_xCondDataSize), 5906, 5914, 5926,
- /*5926*/ uint16(x86_xSetOp), uint16(x86_SHRD),
- /*5928*/ uint16(x86_xReadSlashR),
- /*5929*/ uint16(x86_xReadIb),
- /*5930*/ uint16(x86_xArgRM64),
- /*5931*/ uint16(x86_xArgR64),
- /*5932*/ uint16(x86_xArgImm8u),
- /*5933*/ uint16(x86_xMatch),
- /*5934*/ uint16(x86_xCondIs64), 5937, 5955,
- /*5937*/ uint16(x86_xCondDataSize), 5941, 5948, 0,
- /*5941*/ uint16(x86_xSetOp), uint16(x86_SHRD),
- /*5943*/ uint16(x86_xReadSlashR),
- /*5944*/ uint16(x86_xArgRM16),
- /*5945*/ uint16(x86_xArgR16),
- /*5946*/ uint16(x86_xArgCL),
- /*5947*/ uint16(x86_xMatch),
- /*5948*/ uint16(x86_xSetOp), uint16(x86_SHRD),
- /*5950*/ uint16(x86_xReadSlashR),
- /*5951*/ uint16(x86_xArgRM32),
- /*5952*/ uint16(x86_xArgR32),
- /*5953*/ uint16(x86_xArgCL),
- /*5954*/ uint16(x86_xMatch),
- /*5955*/ uint16(x86_xCondDataSize), 5941, 5948, 5959,
- /*5959*/ uint16(x86_xSetOp), uint16(x86_SHRD),
- /*5961*/ uint16(x86_xReadSlashR),
- /*5962*/ uint16(x86_xArgRM64),
- /*5963*/ uint16(x86_xArgR64),
- /*5964*/ uint16(x86_xArgCL),
- /*5965*/ uint16(x86_xMatch),
- /*5966*/ uint16(x86_xCondByte), 3,
- 0xE8, 6215,
- 0xF0, 6218,
- 0xF8, 6221,
- /*5974*/ uint16(x86_xCondSlashR),
- 5983, // 0
- 6037, // 1
- 6091, // 2
- 6120, // 3
- 6149, // 4
- 6172, // 5
- 6195, // 6
- 6211, // 7
- /*5983*/ uint16(x86_xCondIs64), 5986, 5998,
- /*5986*/ uint16(x86_xCondDataSize), 5990, 5994, 0,
- /*5990*/ uint16(x86_xSetOp), uint16(x86_FXSAVE),
- /*5992*/ uint16(x86_xArgM512byte),
- /*5993*/ uint16(x86_xMatch),
- /*5994*/ uint16(x86_xSetOp), uint16(x86_FXSAVE),
- /*5996*/ uint16(x86_xArgM512byte),
- /*5997*/ uint16(x86_xMatch),
- /*5998*/ uint16(x86_xCondPrefix), 2,
- 0xF3, 6012,
- 0x0, 6004,
- /*6004*/ uint16(x86_xCondDataSize), 5990, 5994, 6008,
- /*6008*/ uint16(x86_xSetOp), uint16(x86_FXSAVE64),
- /*6010*/ uint16(x86_xArgM512byte),
- /*6011*/ uint16(x86_xMatch),
- /*6012*/ uint16(x86_xCondDataSize), 6016, 6023, 6030,
- /*6016*/ uint16(x86_xCondIsMem), 6019, 0,
- /*6019*/ uint16(x86_xSetOp), uint16(x86_RDFSBASE),
- /*6021*/ uint16(x86_xArgRM32),
- /*6022*/ uint16(x86_xMatch),
- /*6023*/ uint16(x86_xCondIsMem), 6026, 0,
- /*6026*/ uint16(x86_xSetOp), uint16(x86_RDFSBASE),
- /*6028*/ uint16(x86_xArgRM32),
- /*6029*/ uint16(x86_xMatch),
- /*6030*/ uint16(x86_xCondIsMem), 6033, 0,
- /*6033*/ uint16(x86_xSetOp), uint16(x86_RDFSBASE),
- /*6035*/ uint16(x86_xArgRM64),
- /*6036*/ uint16(x86_xMatch),
- /*6037*/ uint16(x86_xCondIs64), 6040, 6052,
- /*6040*/ uint16(x86_xCondDataSize), 6044, 6048, 0,
- /*6044*/ uint16(x86_xSetOp), uint16(x86_FXRSTOR),
- /*6046*/ uint16(x86_xArgM512byte),
- /*6047*/ uint16(x86_xMatch),
- /*6048*/ uint16(x86_xSetOp), uint16(x86_FXRSTOR),
- /*6050*/ uint16(x86_xArgM512byte),
- /*6051*/ uint16(x86_xMatch),
- /*6052*/ uint16(x86_xCondPrefix), 2,
- 0xF3, 6066,
- 0x0, 6058,
- /*6058*/ uint16(x86_xCondDataSize), 6044, 6048, 6062,
- /*6062*/ uint16(x86_xSetOp), uint16(x86_FXRSTOR64),
- /*6064*/ uint16(x86_xArgM512byte),
- /*6065*/ uint16(x86_xMatch),
- /*6066*/ uint16(x86_xCondDataSize), 6070, 6077, 6084,
- /*6070*/ uint16(x86_xCondIsMem), 6073, 0,
- /*6073*/ uint16(x86_xSetOp), uint16(x86_RDGSBASE),
- /*6075*/ uint16(x86_xArgRM32),
- /*6076*/ uint16(x86_xMatch),
- /*6077*/ uint16(x86_xCondIsMem), 6080, 0,
- /*6080*/ uint16(x86_xSetOp), uint16(x86_RDGSBASE),
- /*6082*/ uint16(x86_xArgRM32),
- /*6083*/ uint16(x86_xMatch),
- /*6084*/ uint16(x86_xCondIsMem), 6087, 0,
- /*6087*/ uint16(x86_xSetOp), uint16(x86_RDGSBASE),
- /*6089*/ uint16(x86_xArgRM64),
- /*6090*/ uint16(x86_xMatch),
- /*6091*/ uint16(x86_xCondIs64), 6094, 6098,
- /*6094*/ uint16(x86_xSetOp), uint16(x86_LDMXCSR),
- /*6096*/ uint16(x86_xArgM32),
- /*6097*/ uint16(x86_xMatch),
- /*6098*/ uint16(x86_xCondPrefix), 2,
- 0xF3, 6104,
- 0x0, 6094,
- /*6104*/ uint16(x86_xCondDataSize), 6108, 6112, 6116,
- /*6108*/ uint16(x86_xSetOp), uint16(x86_WRFSBASE),
- /*6110*/ uint16(x86_xArgRM32),
- /*6111*/ uint16(x86_xMatch),
- /*6112*/ uint16(x86_xSetOp), uint16(x86_WRFSBASE),
- /*6114*/ uint16(x86_xArgRM32),
- /*6115*/ uint16(x86_xMatch),
- /*6116*/ uint16(x86_xSetOp), uint16(x86_WRFSBASE),
- /*6118*/ uint16(x86_xArgRM64),
- /*6119*/ uint16(x86_xMatch),
- /*6120*/ uint16(x86_xCondIs64), 6123, 6127,
- /*6123*/ uint16(x86_xSetOp), uint16(x86_STMXCSR),
- /*6125*/ uint16(x86_xArgM32),
- /*6126*/ uint16(x86_xMatch),
- /*6127*/ uint16(x86_xCondPrefix), 2,
- 0xF3, 6133,
- 0x0, 6123,
- /*6133*/ uint16(x86_xCondDataSize), 6137, 6141, 6145,
- /*6137*/ uint16(x86_xSetOp), uint16(x86_WRGSBASE),
- /*6139*/ uint16(x86_xArgRM32),
- /*6140*/ uint16(x86_xMatch),
- /*6141*/ uint16(x86_xSetOp), uint16(x86_WRGSBASE),
- /*6143*/ uint16(x86_xArgRM32),
- /*6144*/ uint16(x86_xMatch),
- /*6145*/ uint16(x86_xSetOp), uint16(x86_WRGSBASE),
- /*6147*/ uint16(x86_xArgRM64),
- /*6148*/ uint16(x86_xMatch),
- /*6149*/ uint16(x86_xCondIs64), 6152, 6164,
- /*6152*/ uint16(x86_xCondDataSize), 6156, 6160, 0,
- /*6156*/ uint16(x86_xSetOp), uint16(x86_XSAVE),
- /*6158*/ uint16(x86_xArgMem),
- /*6159*/ uint16(x86_xMatch),
- /*6160*/ uint16(x86_xSetOp), uint16(x86_XSAVE),
- /*6162*/ uint16(x86_xArgMem),
- /*6163*/ uint16(x86_xMatch),
- /*6164*/ uint16(x86_xCondDataSize), 6156, 6160, 6168,
- /*6168*/ uint16(x86_xSetOp), uint16(x86_XSAVE64),
- /*6170*/ uint16(x86_xArgMem),
- /*6171*/ uint16(x86_xMatch),
- /*6172*/ uint16(x86_xCondIs64), 6175, 6187,
- /*6175*/ uint16(x86_xCondDataSize), 6179, 6183, 0,
- /*6179*/ uint16(x86_xSetOp), uint16(x86_XRSTOR),
- /*6181*/ uint16(x86_xArgMem),
- /*6182*/ uint16(x86_xMatch),
- /*6183*/ uint16(x86_xSetOp), uint16(x86_XRSTOR),
- /*6185*/ uint16(x86_xArgMem),
- /*6186*/ uint16(x86_xMatch),
- /*6187*/ uint16(x86_xCondDataSize), 6179, 6183, 6191,
- /*6191*/ uint16(x86_xSetOp), uint16(x86_XRSTOR64),
- /*6193*/ uint16(x86_xArgMem),
- /*6194*/ uint16(x86_xMatch),
- /*6195*/ uint16(x86_xCondDataSize), 6199, 6203, 6207,
- /*6199*/ uint16(x86_xSetOp), uint16(x86_XSAVEOPT),
- /*6201*/ uint16(x86_xArgMem),
- /*6202*/ uint16(x86_xMatch),
- /*6203*/ uint16(x86_xSetOp), uint16(x86_XSAVEOPT),
- /*6205*/ uint16(x86_xArgMem),
- /*6206*/ uint16(x86_xMatch),
- /*6207*/ uint16(x86_xSetOp), uint16(x86_XSAVEOPT64),
- /*6209*/ uint16(x86_xArgMem),
- /*6210*/ uint16(x86_xMatch),
- /*6211*/ uint16(x86_xSetOp), uint16(x86_CLFLUSH),
- /*6213*/ uint16(x86_xArgM8),
- /*6214*/ uint16(x86_xMatch),
- /*6215*/ uint16(x86_xSetOp), uint16(x86_LFENCE),
- /*6217*/ uint16(x86_xMatch),
- /*6218*/ uint16(x86_xSetOp), uint16(x86_MFENCE),
- /*6220*/ uint16(x86_xMatch),
- /*6221*/ uint16(x86_xSetOp), uint16(x86_SFENCE),
- /*6223*/ uint16(x86_xMatch),
- /*6224*/ uint16(x86_xCondIs64), 6227, 6243,
- /*6227*/ uint16(x86_xCondDataSize), 6231, 6237, 0,
- /*6231*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*6233*/ uint16(x86_xReadSlashR),
- /*6234*/ uint16(x86_xArgR16),
- /*6235*/ uint16(x86_xArgRM16),
- /*6236*/ uint16(x86_xMatch),
- /*6237*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*6239*/ uint16(x86_xReadSlashR),
- /*6240*/ uint16(x86_xArgR32),
- /*6241*/ uint16(x86_xArgRM32),
- /*6242*/ uint16(x86_xMatch),
- /*6243*/ uint16(x86_xCondDataSize), 6231, 6237, 6247,
- /*6247*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*6249*/ uint16(x86_xReadSlashR),
- /*6250*/ uint16(x86_xArgR64),
- /*6251*/ uint16(x86_xArgRM64),
- /*6252*/ uint16(x86_xMatch),
- /*6253*/ uint16(x86_xSetOp), uint16(x86_CMPXCHG),
- /*6255*/ uint16(x86_xReadSlashR),
- /*6256*/ uint16(x86_xArgRM8),
- /*6257*/ uint16(x86_xArgR8),
- /*6258*/ uint16(x86_xMatch),
- /*6259*/ uint16(x86_xCondIs64), 6262, 6278,
- /*6262*/ uint16(x86_xCondDataSize), 6266, 6272, 0,
- /*6266*/ uint16(x86_xSetOp), uint16(x86_CMPXCHG),
- /*6268*/ uint16(x86_xReadSlashR),
- /*6269*/ uint16(x86_xArgRM16),
- /*6270*/ uint16(x86_xArgR16),
- /*6271*/ uint16(x86_xMatch),
- /*6272*/ uint16(x86_xSetOp), uint16(x86_CMPXCHG),
- /*6274*/ uint16(x86_xReadSlashR),
- /*6275*/ uint16(x86_xArgRM32),
- /*6276*/ uint16(x86_xArgR32),
- /*6277*/ uint16(x86_xMatch),
- /*6278*/ uint16(x86_xCondDataSize), 6266, 6272, 6282,
- /*6282*/ uint16(x86_xSetOp), uint16(x86_CMPXCHG),
- /*6284*/ uint16(x86_xReadSlashR),
- /*6285*/ uint16(x86_xArgRM64),
- /*6286*/ uint16(x86_xArgR64),
- /*6287*/ uint16(x86_xMatch),
- /*6288*/ uint16(x86_xCondIs64), 6291, 6307,
- /*6291*/ uint16(x86_xCondDataSize), 6295, 6301, 0,
- /*6295*/ uint16(x86_xSetOp), uint16(x86_LSS),
- /*6297*/ uint16(x86_xReadSlashR),
- /*6298*/ uint16(x86_xArgR16),
- /*6299*/ uint16(x86_xArgM16colon16),
- /*6300*/ uint16(x86_xMatch),
- /*6301*/ uint16(x86_xSetOp), uint16(x86_LSS),
- /*6303*/ uint16(x86_xReadSlashR),
- /*6304*/ uint16(x86_xArgR32),
- /*6305*/ uint16(x86_xArgM16colon32),
- /*6306*/ uint16(x86_xMatch),
- /*6307*/ uint16(x86_xCondDataSize), 6295, 6301, 6311,
- /*6311*/ uint16(x86_xSetOp), uint16(x86_LSS),
- /*6313*/ uint16(x86_xReadSlashR),
- /*6314*/ uint16(x86_xArgR64),
- /*6315*/ uint16(x86_xArgM16colon64),
- /*6316*/ uint16(x86_xMatch),
- /*6317*/ uint16(x86_xCondIs64), 6320, 6336,
- /*6320*/ uint16(x86_xCondDataSize), 6324, 6330, 0,
- /*6324*/ uint16(x86_xSetOp), uint16(x86_BTR),
- /*6326*/ uint16(x86_xReadSlashR),
- /*6327*/ uint16(x86_xArgRM16),
- /*6328*/ uint16(x86_xArgR16),
- /*6329*/ uint16(x86_xMatch),
- /*6330*/ uint16(x86_xSetOp), uint16(x86_BTR),
- /*6332*/ uint16(x86_xReadSlashR),
- /*6333*/ uint16(x86_xArgRM32),
- /*6334*/ uint16(x86_xArgR32),
- /*6335*/ uint16(x86_xMatch),
- /*6336*/ uint16(x86_xCondDataSize), 6324, 6330, 6340,
- /*6340*/ uint16(x86_xSetOp), uint16(x86_BTR),
- /*6342*/ uint16(x86_xReadSlashR),
- /*6343*/ uint16(x86_xArgRM64),
- /*6344*/ uint16(x86_xArgR64),
- /*6345*/ uint16(x86_xMatch),
- /*6346*/ uint16(x86_xCondIs64), 6349, 6365,
- /*6349*/ uint16(x86_xCondDataSize), 6353, 6359, 0,
- /*6353*/ uint16(x86_xSetOp), uint16(x86_LFS),
- /*6355*/ uint16(x86_xReadSlashR),
- /*6356*/ uint16(x86_xArgR16),
- /*6357*/ uint16(x86_xArgM16colon16),
- /*6358*/ uint16(x86_xMatch),
- /*6359*/ uint16(x86_xSetOp), uint16(x86_LFS),
- /*6361*/ uint16(x86_xReadSlashR),
- /*6362*/ uint16(x86_xArgR32),
- /*6363*/ uint16(x86_xArgM16colon32),
- /*6364*/ uint16(x86_xMatch),
- /*6365*/ uint16(x86_xCondDataSize), 6353, 6359, 6369,
- /*6369*/ uint16(x86_xSetOp), uint16(x86_LFS),
- /*6371*/ uint16(x86_xReadSlashR),
- /*6372*/ uint16(x86_xArgR64),
- /*6373*/ uint16(x86_xArgM16colon64),
- /*6374*/ uint16(x86_xMatch),
- /*6375*/ uint16(x86_xCondIs64), 6378, 6394,
- /*6378*/ uint16(x86_xCondDataSize), 6382, 6388, 0,
- /*6382*/ uint16(x86_xSetOp), uint16(x86_LGS),
- /*6384*/ uint16(x86_xReadSlashR),
- /*6385*/ uint16(x86_xArgR16),
- /*6386*/ uint16(x86_xArgM16colon16),
- /*6387*/ uint16(x86_xMatch),
- /*6388*/ uint16(x86_xSetOp), uint16(x86_LGS),
- /*6390*/ uint16(x86_xReadSlashR),
- /*6391*/ uint16(x86_xArgR32),
- /*6392*/ uint16(x86_xArgM16colon32),
- /*6393*/ uint16(x86_xMatch),
- /*6394*/ uint16(x86_xCondDataSize), 6382, 6388, 6398,
- /*6398*/ uint16(x86_xSetOp), uint16(x86_LGS),
- /*6400*/ uint16(x86_xReadSlashR),
- /*6401*/ uint16(x86_xArgR64),
- /*6402*/ uint16(x86_xArgM16colon64),
- /*6403*/ uint16(x86_xMatch),
- /*6404*/ uint16(x86_xCondIs64), 6407, 6423,
- /*6407*/ uint16(x86_xCondDataSize), 6411, 6417, 0,
- /*6411*/ uint16(x86_xSetOp), uint16(x86_MOVZX),
- /*6413*/ uint16(x86_xReadSlashR),
- /*6414*/ uint16(x86_xArgR16),
- /*6415*/ uint16(x86_xArgRM8),
- /*6416*/ uint16(x86_xMatch),
- /*6417*/ uint16(x86_xSetOp), uint16(x86_MOVZX),
- /*6419*/ uint16(x86_xReadSlashR),
- /*6420*/ uint16(x86_xArgR32),
- /*6421*/ uint16(x86_xArgRM8),
- /*6422*/ uint16(x86_xMatch),
- /*6423*/ uint16(x86_xCondDataSize), 6411, 6417, 6427,
- /*6427*/ uint16(x86_xSetOp), uint16(x86_MOVZX),
- /*6429*/ uint16(x86_xReadSlashR),
- /*6430*/ uint16(x86_xArgR64),
- /*6431*/ uint16(x86_xArgRM8),
- /*6432*/ uint16(x86_xMatch),
- /*6433*/ uint16(x86_xCondIs64), 6436, 6452,
- /*6436*/ uint16(x86_xCondDataSize), 6440, 6446, 0,
- /*6440*/ uint16(x86_xSetOp), uint16(x86_MOVZX),
- /*6442*/ uint16(x86_xReadSlashR),
- /*6443*/ uint16(x86_xArgR16),
- /*6444*/ uint16(x86_xArgRM16),
- /*6445*/ uint16(x86_xMatch),
- /*6446*/ uint16(x86_xSetOp), uint16(x86_MOVZX),
- /*6448*/ uint16(x86_xReadSlashR),
- /*6449*/ uint16(x86_xArgR32),
- /*6450*/ uint16(x86_xArgRM16),
- /*6451*/ uint16(x86_xMatch),
- /*6452*/ uint16(x86_xCondDataSize), 6440, 6446, 6456,
- /*6456*/ uint16(x86_xSetOp), uint16(x86_MOVZX),
- /*6458*/ uint16(x86_xReadSlashR),
- /*6459*/ uint16(x86_xArgR64),
- /*6460*/ uint16(x86_xArgRM16),
- /*6461*/ uint16(x86_xMatch),
- /*6462*/ uint16(x86_xCondIs64), 6465, 6485,
- /*6465*/ uint16(x86_xCondPrefix), 1,
- 0xF3, 6469,
- /*6469*/ uint16(x86_xCondDataSize), 6473, 6479, 0,
- /*6473*/ uint16(x86_xSetOp), uint16(x86_POPCNT),
- /*6475*/ uint16(x86_xReadSlashR),
- /*6476*/ uint16(x86_xArgR16),
- /*6477*/ uint16(x86_xArgRM16),
- /*6478*/ uint16(x86_xMatch),
- /*6479*/ uint16(x86_xSetOp), uint16(x86_POPCNT),
- /*6481*/ uint16(x86_xReadSlashR),
- /*6482*/ uint16(x86_xArgR32),
- /*6483*/ uint16(x86_xArgRM32),
- /*6484*/ uint16(x86_xMatch),
- /*6485*/ uint16(x86_xCondPrefix), 1,
- 0xF3, 6489,
- /*6489*/ uint16(x86_xCondDataSize), 6473, 6479, 6493,
- /*6493*/ uint16(x86_xSetOp), uint16(x86_POPCNT),
- /*6495*/ uint16(x86_xReadSlashR),
- /*6496*/ uint16(x86_xArgR64),
- /*6497*/ uint16(x86_xArgRM64),
- /*6498*/ uint16(x86_xMatch),
- /*6499*/ uint16(x86_xSetOp), uint16(x86_UD1),
- /*6501*/ uint16(x86_xMatch),
- /*6502*/ uint16(x86_xCondSlashR),
- 0, // 0
- 0, // 1
- 0, // 2
- 0, // 3
- 6511, // 4
- 6540, // 5
- 6569, // 6
- 6598, // 7
- /*6511*/ uint16(x86_xCondIs64), 6514, 6530,
- /*6514*/ uint16(x86_xCondDataSize), 6518, 6524, 0,
- /*6518*/ uint16(x86_xSetOp), uint16(x86_BT),
- /*6520*/ uint16(x86_xReadIb),
- /*6521*/ uint16(x86_xArgRM16),
- /*6522*/ uint16(x86_xArgImm8u),
- /*6523*/ uint16(x86_xMatch),
- /*6524*/ uint16(x86_xSetOp), uint16(x86_BT),
- /*6526*/ uint16(x86_xReadIb),
- /*6527*/ uint16(x86_xArgRM32),
- /*6528*/ uint16(x86_xArgImm8u),
- /*6529*/ uint16(x86_xMatch),
- /*6530*/ uint16(x86_xCondDataSize), 6518, 6524, 6534,
- /*6534*/ uint16(x86_xSetOp), uint16(x86_BT),
- /*6536*/ uint16(x86_xReadIb),
- /*6537*/ uint16(x86_xArgRM64),
- /*6538*/ uint16(x86_xArgImm8u),
- /*6539*/ uint16(x86_xMatch),
- /*6540*/ uint16(x86_xCondIs64), 6543, 6559,
- /*6543*/ uint16(x86_xCondDataSize), 6547, 6553, 0,
- /*6547*/ uint16(x86_xSetOp), uint16(x86_BTS),
- /*6549*/ uint16(x86_xReadIb),
- /*6550*/ uint16(x86_xArgRM16),
- /*6551*/ uint16(x86_xArgImm8u),
- /*6552*/ uint16(x86_xMatch),
- /*6553*/ uint16(x86_xSetOp), uint16(x86_BTS),
- /*6555*/ uint16(x86_xReadIb),
- /*6556*/ uint16(x86_xArgRM32),
- /*6557*/ uint16(x86_xArgImm8u),
- /*6558*/ uint16(x86_xMatch),
- /*6559*/ uint16(x86_xCondDataSize), 6547, 6553, 6563,
- /*6563*/ uint16(x86_xSetOp), uint16(x86_BTS),
- /*6565*/ uint16(x86_xReadIb),
- /*6566*/ uint16(x86_xArgRM64),
- /*6567*/ uint16(x86_xArgImm8u),
- /*6568*/ uint16(x86_xMatch),
- /*6569*/ uint16(x86_xCondIs64), 6572, 6588,
- /*6572*/ uint16(x86_xCondDataSize), 6576, 6582, 0,
- /*6576*/ uint16(x86_xSetOp), uint16(x86_BTR),
- /*6578*/ uint16(x86_xReadIb),
- /*6579*/ uint16(x86_xArgRM16),
- /*6580*/ uint16(x86_xArgImm8u),
- /*6581*/ uint16(x86_xMatch),
- /*6582*/ uint16(x86_xSetOp), uint16(x86_BTR),
- /*6584*/ uint16(x86_xReadIb),
- /*6585*/ uint16(x86_xArgRM32),
- /*6586*/ uint16(x86_xArgImm8u),
- /*6587*/ uint16(x86_xMatch),
- /*6588*/ uint16(x86_xCondDataSize), 6576, 6582, 6592,
- /*6592*/ uint16(x86_xSetOp), uint16(x86_BTR),
- /*6594*/ uint16(x86_xReadIb),
- /*6595*/ uint16(x86_xArgRM64),
- /*6596*/ uint16(x86_xArgImm8u),
- /*6597*/ uint16(x86_xMatch),
- /*6598*/ uint16(x86_xCondIs64), 6601, 6617,
- /*6601*/ uint16(x86_xCondDataSize), 6605, 6611, 0,
- /*6605*/ uint16(x86_xSetOp), uint16(x86_BTC),
- /*6607*/ uint16(x86_xReadIb),
- /*6608*/ uint16(x86_xArgRM16),
- /*6609*/ uint16(x86_xArgImm8u),
- /*6610*/ uint16(x86_xMatch),
- /*6611*/ uint16(x86_xSetOp), uint16(x86_BTC),
- /*6613*/ uint16(x86_xReadIb),
- /*6614*/ uint16(x86_xArgRM32),
- /*6615*/ uint16(x86_xArgImm8u),
- /*6616*/ uint16(x86_xMatch),
- /*6617*/ uint16(x86_xCondDataSize), 6605, 6611, 6621,
- /*6621*/ uint16(x86_xSetOp), uint16(x86_BTC),
- /*6623*/ uint16(x86_xReadIb),
- /*6624*/ uint16(x86_xArgRM64),
- /*6625*/ uint16(x86_xArgImm8u),
- /*6626*/ uint16(x86_xMatch),
- /*6627*/ uint16(x86_xCondIs64), 6630, 6646,
- /*6630*/ uint16(x86_xCondDataSize), 6634, 6640, 0,
- /*6634*/ uint16(x86_xSetOp), uint16(x86_BTC),
- /*6636*/ uint16(x86_xReadSlashR),
- /*6637*/ uint16(x86_xArgRM16),
- /*6638*/ uint16(x86_xArgR16),
- /*6639*/ uint16(x86_xMatch),
- /*6640*/ uint16(x86_xSetOp), uint16(x86_BTC),
- /*6642*/ uint16(x86_xReadSlashR),
- /*6643*/ uint16(x86_xArgRM32),
- /*6644*/ uint16(x86_xArgR32),
- /*6645*/ uint16(x86_xMatch),
- /*6646*/ uint16(x86_xCondDataSize), 6634, 6640, 6650,
- /*6650*/ uint16(x86_xSetOp), uint16(x86_BTC),
- /*6652*/ uint16(x86_xReadSlashR),
- /*6653*/ uint16(x86_xArgRM64),
- /*6654*/ uint16(x86_xArgR64),
- /*6655*/ uint16(x86_xMatch),
- /*6656*/ uint16(x86_xCondIs64), 6659, 6697,
- /*6659*/ uint16(x86_xCondPrefix), 2,
- 0xF3, 6681,
- 0x0, 6665,
- /*6665*/ uint16(x86_xCondDataSize), 6669, 6675, 0,
- /*6669*/ uint16(x86_xSetOp), uint16(x86_BSF),
- /*6671*/ uint16(x86_xReadSlashR),
- /*6672*/ uint16(x86_xArgR16),
- /*6673*/ uint16(x86_xArgRM16),
- /*6674*/ uint16(x86_xMatch),
- /*6675*/ uint16(x86_xSetOp), uint16(x86_BSF),
- /*6677*/ uint16(x86_xReadSlashR),
- /*6678*/ uint16(x86_xArgR32),
- /*6679*/ uint16(x86_xArgRM32),
- /*6680*/ uint16(x86_xMatch),
- /*6681*/ uint16(x86_xCondDataSize), 6685, 6691, 0,
- /*6685*/ uint16(x86_xSetOp), uint16(x86_TZCNT),
- /*6687*/ uint16(x86_xReadSlashR),
- /*6688*/ uint16(x86_xArgR16),
- /*6689*/ uint16(x86_xArgRM16),
- /*6690*/ uint16(x86_xMatch),
- /*6691*/ uint16(x86_xSetOp), uint16(x86_TZCNT),
- /*6693*/ uint16(x86_xReadSlashR),
- /*6694*/ uint16(x86_xArgR32),
- /*6695*/ uint16(x86_xArgRM32),
- /*6696*/ uint16(x86_xMatch),
- /*6697*/ uint16(x86_xCondPrefix), 2,
- 0xF3, 6713,
- 0x0, 6703,
- /*6703*/ uint16(x86_xCondDataSize), 6669, 6675, 6707,
- /*6707*/ uint16(x86_xSetOp), uint16(x86_BSF),
- /*6709*/ uint16(x86_xReadSlashR),
- /*6710*/ uint16(x86_xArgR64),
- /*6711*/ uint16(x86_xArgRM64),
- /*6712*/ uint16(x86_xMatch),
- /*6713*/ uint16(x86_xCondDataSize), 6685, 6691, 6717,
- /*6717*/ uint16(x86_xSetOp), uint16(x86_TZCNT),
- /*6719*/ uint16(x86_xReadSlashR),
- /*6720*/ uint16(x86_xArgR64),
- /*6721*/ uint16(x86_xArgRM64),
- /*6722*/ uint16(x86_xMatch),
- /*6723*/ uint16(x86_xCondIs64), 6726, 6764,
- /*6726*/ uint16(x86_xCondPrefix), 2,
- 0xF3, 6748,
- 0x0, 6732,
- /*6732*/ uint16(x86_xCondDataSize), 6736, 6742, 0,
- /*6736*/ uint16(x86_xSetOp), uint16(x86_BSR),
- /*6738*/ uint16(x86_xReadSlashR),
- /*6739*/ uint16(x86_xArgR16),
- /*6740*/ uint16(x86_xArgRM16),
- /*6741*/ uint16(x86_xMatch),
- /*6742*/ uint16(x86_xSetOp), uint16(x86_BSR),
- /*6744*/ uint16(x86_xReadSlashR),
- /*6745*/ uint16(x86_xArgR32),
- /*6746*/ uint16(x86_xArgRM32),
- /*6747*/ uint16(x86_xMatch),
- /*6748*/ uint16(x86_xCondDataSize), 6752, 6758, 0,
- /*6752*/ uint16(x86_xSetOp), uint16(x86_LZCNT),
- /*6754*/ uint16(x86_xReadSlashR),
- /*6755*/ uint16(x86_xArgR16),
- /*6756*/ uint16(x86_xArgRM16),
- /*6757*/ uint16(x86_xMatch),
- /*6758*/ uint16(x86_xSetOp), uint16(x86_LZCNT),
- /*6760*/ uint16(x86_xReadSlashR),
- /*6761*/ uint16(x86_xArgR32),
- /*6762*/ uint16(x86_xArgRM32),
- /*6763*/ uint16(x86_xMatch),
- /*6764*/ uint16(x86_xCondPrefix), 2,
- 0xF3, 6780,
- 0x0, 6770,
- /*6770*/ uint16(x86_xCondDataSize), 6736, 6742, 6774,
- /*6774*/ uint16(x86_xSetOp), uint16(x86_BSR),
- /*6776*/ uint16(x86_xReadSlashR),
- /*6777*/ uint16(x86_xArgR64),
- /*6778*/ uint16(x86_xArgRM64),
- /*6779*/ uint16(x86_xMatch),
- /*6780*/ uint16(x86_xCondDataSize), 6752, 6758, 6784,
- /*6784*/ uint16(x86_xSetOp), uint16(x86_LZCNT),
- /*6786*/ uint16(x86_xReadSlashR),
- /*6787*/ uint16(x86_xArgR64),
- /*6788*/ uint16(x86_xArgRM64),
- /*6789*/ uint16(x86_xMatch),
- /*6790*/ uint16(x86_xCondIs64), 6793, 6809,
- /*6793*/ uint16(x86_xCondDataSize), 6797, 6803, 0,
- /*6797*/ uint16(x86_xSetOp), uint16(x86_MOVSX),
- /*6799*/ uint16(x86_xReadSlashR),
- /*6800*/ uint16(x86_xArgR16),
- /*6801*/ uint16(x86_xArgRM8),
- /*6802*/ uint16(x86_xMatch),
- /*6803*/ uint16(x86_xSetOp), uint16(x86_MOVSX),
- /*6805*/ uint16(x86_xReadSlashR),
- /*6806*/ uint16(x86_xArgR32),
- /*6807*/ uint16(x86_xArgRM8),
- /*6808*/ uint16(x86_xMatch),
- /*6809*/ uint16(x86_xCondDataSize), 6797, 6803, 6813,
- /*6813*/ uint16(x86_xSetOp), uint16(x86_MOVSX),
- /*6815*/ uint16(x86_xReadSlashR),
- /*6816*/ uint16(x86_xArgR64),
- /*6817*/ uint16(x86_xArgRM8),
- /*6818*/ uint16(x86_xMatch),
- /*6819*/ uint16(x86_xCondIs64), 6822, 6838,
- /*6822*/ uint16(x86_xCondDataSize), 6826, 6832, 0,
- /*6826*/ uint16(x86_xSetOp), uint16(x86_MOVSX),
- /*6828*/ uint16(x86_xReadSlashR),
- /*6829*/ uint16(x86_xArgR16),
- /*6830*/ uint16(x86_xArgRM16),
- /*6831*/ uint16(x86_xMatch),
- /*6832*/ uint16(x86_xSetOp), uint16(x86_MOVSX),
- /*6834*/ uint16(x86_xReadSlashR),
- /*6835*/ uint16(x86_xArgR32),
- /*6836*/ uint16(x86_xArgRM16),
- /*6837*/ uint16(x86_xMatch),
- /*6838*/ uint16(x86_xCondDataSize), 6826, 6832, 6842,
- /*6842*/ uint16(x86_xSetOp), uint16(x86_MOVSX),
- /*6844*/ uint16(x86_xReadSlashR),
- /*6845*/ uint16(x86_xArgR64),
- /*6846*/ uint16(x86_xArgRM16),
- /*6847*/ uint16(x86_xMatch),
- /*6848*/ uint16(x86_xSetOp), uint16(x86_XADD),
- /*6850*/ uint16(x86_xReadSlashR),
- /*6851*/ uint16(x86_xArgRM8),
- /*6852*/ uint16(x86_xArgR8),
- /*6853*/ uint16(x86_xMatch),
- /*6854*/ uint16(x86_xCondIs64), 6857, 6873,
- /*6857*/ uint16(x86_xCondDataSize), 6861, 6867, 0,
- /*6861*/ uint16(x86_xSetOp), uint16(x86_XADD),
- /*6863*/ uint16(x86_xReadSlashR),
- /*6864*/ uint16(x86_xArgRM16),
- /*6865*/ uint16(x86_xArgR16),
- /*6866*/ uint16(x86_xMatch),
- /*6867*/ uint16(x86_xSetOp), uint16(x86_XADD),
- /*6869*/ uint16(x86_xReadSlashR),
- /*6870*/ uint16(x86_xArgRM32),
- /*6871*/ uint16(x86_xArgR32),
- /*6872*/ uint16(x86_xMatch),
- /*6873*/ uint16(x86_xCondDataSize), 6861, 6867, 6877,
- /*6877*/ uint16(x86_xSetOp), uint16(x86_XADD),
- /*6879*/ uint16(x86_xReadSlashR),
- /*6880*/ uint16(x86_xArgRM64),
- /*6881*/ uint16(x86_xArgR64),
- /*6882*/ uint16(x86_xMatch),
- /*6883*/ uint16(x86_xCondPrefix), 4,
- 0xF3, 6917,
- 0xF2, 6909,
- 0x66, 6901,
- 0x0, 6893,
- /*6893*/ uint16(x86_xSetOp), uint16(x86_CMPPS),
- /*6895*/ uint16(x86_xReadSlashR),
- /*6896*/ uint16(x86_xReadIb),
- /*6897*/ uint16(x86_xArgXmm1),
- /*6898*/ uint16(x86_xArgXmm2M128),
- /*6899*/ uint16(x86_xArgImm8u),
- /*6900*/ uint16(x86_xMatch),
- /*6901*/ uint16(x86_xSetOp), uint16(x86_CMPPD),
- /*6903*/ uint16(x86_xReadSlashR),
- /*6904*/ uint16(x86_xReadIb),
- /*6905*/ uint16(x86_xArgXmm1),
- /*6906*/ uint16(x86_xArgXmm2M128),
- /*6907*/ uint16(x86_xArgImm8u),
- /*6908*/ uint16(x86_xMatch),
- /*6909*/ uint16(x86_xSetOp), uint16(x86_CMPSD_XMM),
- /*6911*/ uint16(x86_xReadSlashR),
- /*6912*/ uint16(x86_xReadIb),
- /*6913*/ uint16(x86_xArgXmm1),
- /*6914*/ uint16(x86_xArgXmm2M64),
- /*6915*/ uint16(x86_xArgImm8u),
- /*6916*/ uint16(x86_xMatch),
- /*6917*/ uint16(x86_xSetOp), uint16(x86_CMPSS),
- /*6919*/ uint16(x86_xReadSlashR),
- /*6920*/ uint16(x86_xReadIb),
- /*6921*/ uint16(x86_xArgXmm1),
- /*6922*/ uint16(x86_xArgXmm2M32),
- /*6923*/ uint16(x86_xArgImm8u),
- /*6924*/ uint16(x86_xMatch),
- /*6925*/ uint16(x86_xCondIs64), 6928, 6944,
- /*6928*/ uint16(x86_xCondDataSize), 6932, 6938, 0,
- /*6932*/ uint16(x86_xSetOp), uint16(x86_MOVNTI),
- /*6934*/ uint16(x86_xReadSlashR),
- /*6935*/ uint16(x86_xArgM32),
- /*6936*/ uint16(x86_xArgR32),
- /*6937*/ uint16(x86_xMatch),
- /*6938*/ uint16(x86_xSetOp), uint16(x86_MOVNTI),
- /*6940*/ uint16(x86_xReadSlashR),
- /*6941*/ uint16(x86_xArgM32),
- /*6942*/ uint16(x86_xArgR32),
- /*6943*/ uint16(x86_xMatch),
- /*6944*/ uint16(x86_xCondDataSize), 6932, 6938, 6948,
- /*6948*/ uint16(x86_xSetOp), uint16(x86_MOVNTI),
- /*6950*/ uint16(x86_xReadSlashR),
- /*6951*/ uint16(x86_xArgM64),
- /*6952*/ uint16(x86_xArgR64),
- /*6953*/ uint16(x86_xMatch),
- /*6954*/ uint16(x86_xCondPrefix), 2,
- 0x66, 6968,
- 0x0, 6960,
- /*6960*/ uint16(x86_xSetOp), uint16(x86_PINSRW),
- /*6962*/ uint16(x86_xReadSlashR),
- /*6963*/ uint16(x86_xReadIb),
- /*6964*/ uint16(x86_xArgMm),
- /*6965*/ uint16(x86_xArgR32M16),
- /*6966*/ uint16(x86_xArgImm8u),
- /*6967*/ uint16(x86_xMatch),
- /*6968*/ uint16(x86_xSetOp), uint16(x86_PINSRW),
- /*6970*/ uint16(x86_xReadSlashR),
- /*6971*/ uint16(x86_xReadIb),
- /*6972*/ uint16(x86_xArgXmm),
- /*6973*/ uint16(x86_xArgR32M16),
- /*6974*/ uint16(x86_xArgImm8u),
- /*6975*/ uint16(x86_xMatch),
- /*6976*/ uint16(x86_xCondPrefix), 2,
- 0x66, 6990,
- 0x0, 6982,
- /*6982*/ uint16(x86_xSetOp), uint16(x86_PEXTRW),
- /*6984*/ uint16(x86_xReadSlashR),
- /*6985*/ uint16(x86_xReadIb),
- /*6986*/ uint16(x86_xArgR32),
- /*6987*/ uint16(x86_xArgMm2),
- /*6988*/ uint16(x86_xArgImm8u),
- /*6989*/ uint16(x86_xMatch),
- /*6990*/ uint16(x86_xSetOp), uint16(x86_PEXTRW),
- /*6992*/ uint16(x86_xReadSlashR),
- /*6993*/ uint16(x86_xReadIb),
- /*6994*/ uint16(x86_xArgR32),
- /*6995*/ uint16(x86_xArgXmm2),
- /*6996*/ uint16(x86_xArgImm8u),
- /*6997*/ uint16(x86_xMatch),
- /*6998*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7012,
- 0x0, 7004,
- /*7004*/ uint16(x86_xSetOp), uint16(x86_SHUFPS),
- /*7006*/ uint16(x86_xReadSlashR),
- /*7007*/ uint16(x86_xReadIb),
- /*7008*/ uint16(x86_xArgXmm1),
- /*7009*/ uint16(x86_xArgXmm2M128),
- /*7010*/ uint16(x86_xArgImm8u),
- /*7011*/ uint16(x86_xMatch),
- /*7012*/ uint16(x86_xSetOp), uint16(x86_SHUFPD),
- /*7014*/ uint16(x86_xReadSlashR),
- /*7015*/ uint16(x86_xReadIb),
- /*7016*/ uint16(x86_xArgXmm1),
- /*7017*/ uint16(x86_xArgXmm2M128),
- /*7018*/ uint16(x86_xArgImm8u),
- /*7019*/ uint16(x86_xMatch),
- /*7020*/ uint16(x86_xCondSlashR),
- 0, // 0
- 7029, // 1
- 0, // 2
- 7052, // 3
- 7075, // 4
- 7098, // 5
- 7121, // 6
- 0, // 7
- /*7029*/ uint16(x86_xCondIs64), 7032, 7044,
- /*7032*/ uint16(x86_xCondDataSize), 7036, 7040, 0,
- /*7036*/ uint16(x86_xSetOp), uint16(x86_CMPXCHG8B),
- /*7038*/ uint16(x86_xArgM64),
- /*7039*/ uint16(x86_xMatch),
- /*7040*/ uint16(x86_xSetOp), uint16(x86_CMPXCHG8B),
- /*7042*/ uint16(x86_xArgM64),
- /*7043*/ uint16(x86_xMatch),
- /*7044*/ uint16(x86_xCondDataSize), 7036, 7040, 7048,
- /*7048*/ uint16(x86_xSetOp), uint16(x86_CMPXCHG16B),
- /*7050*/ uint16(x86_xArgM128),
- /*7051*/ uint16(x86_xMatch),
- /*7052*/ uint16(x86_xCondIs64), 7055, 7067,
- /*7055*/ uint16(x86_xCondDataSize), 7059, 7063, 0,
- /*7059*/ uint16(x86_xSetOp), uint16(x86_XRSTORS),
- /*7061*/ uint16(x86_xArgMem),
- /*7062*/ uint16(x86_xMatch),
- /*7063*/ uint16(x86_xSetOp), uint16(x86_XRSTORS),
- /*7065*/ uint16(x86_xArgMem),
- /*7066*/ uint16(x86_xMatch),
- /*7067*/ uint16(x86_xCondDataSize), 7059, 7063, 7071,
- /*7071*/ uint16(x86_xSetOp), uint16(x86_XRSTORS64),
- /*7073*/ uint16(x86_xArgMem),
- /*7074*/ uint16(x86_xMatch),
- /*7075*/ uint16(x86_xCondIs64), 7078, 7090,
- /*7078*/ uint16(x86_xCondDataSize), 7082, 7086, 0,
- /*7082*/ uint16(x86_xSetOp), uint16(x86_XSAVEC),
- /*7084*/ uint16(x86_xArgMem),
- /*7085*/ uint16(x86_xMatch),
- /*7086*/ uint16(x86_xSetOp), uint16(x86_XSAVEC),
- /*7088*/ uint16(x86_xArgMem),
- /*7089*/ uint16(x86_xMatch),
- /*7090*/ uint16(x86_xCondDataSize), 7082, 7086, 7094,
- /*7094*/ uint16(x86_xSetOp), uint16(x86_XSAVEC64),
- /*7096*/ uint16(x86_xArgMem),
- /*7097*/ uint16(x86_xMatch),
- /*7098*/ uint16(x86_xCondIs64), 7101, 7113,
- /*7101*/ uint16(x86_xCondDataSize), 7105, 7109, 0,
- /*7105*/ uint16(x86_xSetOp), uint16(x86_XSAVES),
- /*7107*/ uint16(x86_xArgMem),
- /*7108*/ uint16(x86_xMatch),
- /*7109*/ uint16(x86_xSetOp), uint16(x86_XSAVES),
- /*7111*/ uint16(x86_xArgMem),
- /*7112*/ uint16(x86_xMatch),
- /*7113*/ uint16(x86_xCondDataSize), 7105, 7109, 7117,
- /*7117*/ uint16(x86_xSetOp), uint16(x86_XSAVES64),
- /*7119*/ uint16(x86_xArgMem),
- /*7120*/ uint16(x86_xMatch),
- /*7121*/ uint16(x86_xCondIs64), 7124, 7142,
- /*7124*/ uint16(x86_xCondDataSize), 7128, 7135, 0,
- /*7128*/ uint16(x86_xCondIsMem), 7131, 0,
- /*7131*/ uint16(x86_xSetOp), uint16(x86_RDRAND),
- /*7133*/ uint16(x86_xArgRmf16),
- /*7134*/ uint16(x86_xMatch),
- /*7135*/ uint16(x86_xCondIsMem), 7138, 0,
- /*7138*/ uint16(x86_xSetOp), uint16(x86_RDRAND),
- /*7140*/ uint16(x86_xArgRmf32),
- /*7141*/ uint16(x86_xMatch),
- /*7142*/ uint16(x86_xCondDataSize), 7128, 7135, 7146,
- /*7146*/ uint16(x86_xSetOp), uint16(x86_RDRAND),
- /*7148*/ uint16(x86_xMatch),
- /*7149*/ uint16(x86_xCondIs64), 7152, 7164,
- /*7152*/ uint16(x86_xCondDataSize), 7156, 7160, 0,
- /*7156*/ uint16(x86_xSetOp), uint16(x86_BSWAP),
- /*7158*/ uint16(x86_xArgR16op),
- /*7159*/ uint16(x86_xMatch),
- /*7160*/ uint16(x86_xSetOp), uint16(x86_BSWAP),
- /*7162*/ uint16(x86_xArgR32op),
- /*7163*/ uint16(x86_xMatch),
- /*7164*/ uint16(x86_xCondDataSize), 7156, 7160, 7168,
- /*7168*/ uint16(x86_xSetOp), uint16(x86_BSWAP),
- /*7170*/ uint16(x86_xArgR64op),
- /*7171*/ uint16(x86_xMatch),
- /*7172*/ uint16(x86_xCondPrefix), 2,
- 0xF2, 7184,
- 0x66, 7178,
- /*7178*/ uint16(x86_xSetOp), uint16(x86_ADDSUBPD),
- /*7180*/ uint16(x86_xReadSlashR),
- /*7181*/ uint16(x86_xArgXmm1),
- /*7182*/ uint16(x86_xArgXmm2M128),
- /*7183*/ uint16(x86_xMatch),
- /*7184*/ uint16(x86_xSetOp), uint16(x86_ADDSUBPS),
- /*7186*/ uint16(x86_xReadSlashR),
- /*7187*/ uint16(x86_xArgXmm1),
- /*7188*/ uint16(x86_xArgXmm2M128),
- /*7189*/ uint16(x86_xMatch),
- /*7190*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7202,
- 0x0, 7196,
- /*7196*/ uint16(x86_xSetOp), uint16(x86_PSRLW),
- /*7198*/ uint16(x86_xReadSlashR),
- /*7199*/ uint16(x86_xArgMm),
- /*7200*/ uint16(x86_xArgMmM64),
- /*7201*/ uint16(x86_xMatch),
- /*7202*/ uint16(x86_xSetOp), uint16(x86_PSRLW),
- /*7204*/ uint16(x86_xReadSlashR),
- /*7205*/ uint16(x86_xArgXmm1),
- /*7206*/ uint16(x86_xArgXmm2M128),
- /*7207*/ uint16(x86_xMatch),
- /*7208*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7220,
- 0x0, 7214,
- /*7214*/ uint16(x86_xSetOp), uint16(x86_PSRLD),
- /*7216*/ uint16(x86_xReadSlashR),
- /*7217*/ uint16(x86_xArgMm),
- /*7218*/ uint16(x86_xArgMmM64),
- /*7219*/ uint16(x86_xMatch),
- /*7220*/ uint16(x86_xSetOp), uint16(x86_PSRLD),
- /*7222*/ uint16(x86_xReadSlashR),
- /*7223*/ uint16(x86_xArgXmm1),
- /*7224*/ uint16(x86_xArgXmm2M128),
- /*7225*/ uint16(x86_xMatch),
- /*7226*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7238,
- 0x0, 7232,
- /*7232*/ uint16(x86_xSetOp), uint16(x86_PSRLQ),
- /*7234*/ uint16(x86_xReadSlashR),
- /*7235*/ uint16(x86_xArgMm),
- /*7236*/ uint16(x86_xArgMmM64),
- /*7237*/ uint16(x86_xMatch),
- /*7238*/ uint16(x86_xSetOp), uint16(x86_PSRLQ),
- /*7240*/ uint16(x86_xReadSlashR),
- /*7241*/ uint16(x86_xArgXmm1),
- /*7242*/ uint16(x86_xArgXmm2M128),
- /*7243*/ uint16(x86_xMatch),
- /*7244*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7256,
- 0x0, 7250,
- /*7250*/ uint16(x86_xSetOp), uint16(x86_PADDQ),
- /*7252*/ uint16(x86_xReadSlashR),
- /*7253*/ uint16(x86_xArgMm1),
- /*7254*/ uint16(x86_xArgMm2M64),
- /*7255*/ uint16(x86_xMatch),
- /*7256*/ uint16(x86_xSetOp), uint16(x86_PADDQ),
- /*7258*/ uint16(x86_xReadSlashR),
- /*7259*/ uint16(x86_xArgXmm1),
- /*7260*/ uint16(x86_xArgXmm2M128),
- /*7261*/ uint16(x86_xMatch),
- /*7262*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7274,
- 0x0, 7268,
- /*7268*/ uint16(x86_xSetOp), uint16(x86_PMULLW),
- /*7270*/ uint16(x86_xReadSlashR),
- /*7271*/ uint16(x86_xArgMm),
- /*7272*/ uint16(x86_xArgMmM64),
- /*7273*/ uint16(x86_xMatch),
- /*7274*/ uint16(x86_xSetOp), uint16(x86_PMULLW),
- /*7276*/ uint16(x86_xReadSlashR),
- /*7277*/ uint16(x86_xArgXmm1),
- /*7278*/ uint16(x86_xArgXmm2M128),
- /*7279*/ uint16(x86_xMatch),
- /*7280*/ uint16(x86_xCondPrefix), 3,
- 0xF3, 7300,
- 0xF2, 7294,
- 0x66, 7288,
- /*7288*/ uint16(x86_xSetOp), uint16(x86_MOVQ),
- /*7290*/ uint16(x86_xReadSlashR),
- /*7291*/ uint16(x86_xArgXmm2M64),
- /*7292*/ uint16(x86_xArgXmm1),
- /*7293*/ uint16(x86_xMatch),
- /*7294*/ uint16(x86_xSetOp), uint16(x86_MOVDQ2Q),
- /*7296*/ uint16(x86_xReadSlashR),
- /*7297*/ uint16(x86_xArgMm),
- /*7298*/ uint16(x86_xArgXmm2),
- /*7299*/ uint16(x86_xMatch),
- /*7300*/ uint16(x86_xSetOp), uint16(x86_MOVQ2DQ),
- /*7302*/ uint16(x86_xReadSlashR),
- /*7303*/ uint16(x86_xArgXmm1),
- /*7304*/ uint16(x86_xArgMm2),
- /*7305*/ uint16(x86_xMatch),
- /*7306*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7318,
- 0x0, 7312,
- /*7312*/ uint16(x86_xSetOp), uint16(x86_PMOVMSKB),
- /*7314*/ uint16(x86_xReadSlashR),
- /*7315*/ uint16(x86_xArgR32),
- /*7316*/ uint16(x86_xArgMm2),
- /*7317*/ uint16(x86_xMatch),
- /*7318*/ uint16(x86_xSetOp), uint16(x86_PMOVMSKB),
- /*7320*/ uint16(x86_xReadSlashR),
- /*7321*/ uint16(x86_xArgR32),
- /*7322*/ uint16(x86_xArgXmm2),
- /*7323*/ uint16(x86_xMatch),
- /*7324*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7336,
- 0x0, 7330,
- /*7330*/ uint16(x86_xSetOp), uint16(x86_PSUBUSB),
- /*7332*/ uint16(x86_xReadSlashR),
- /*7333*/ uint16(x86_xArgMm),
- /*7334*/ uint16(x86_xArgMmM64),
- /*7335*/ uint16(x86_xMatch),
- /*7336*/ uint16(x86_xSetOp), uint16(x86_PSUBUSB),
- /*7338*/ uint16(x86_xReadSlashR),
- /*7339*/ uint16(x86_xArgXmm1),
- /*7340*/ uint16(x86_xArgXmm2M128),
- /*7341*/ uint16(x86_xMatch),
- /*7342*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7354,
- 0x0, 7348,
- /*7348*/ uint16(x86_xSetOp), uint16(x86_PSUBUSW),
- /*7350*/ uint16(x86_xReadSlashR),
- /*7351*/ uint16(x86_xArgMm),
- /*7352*/ uint16(x86_xArgMmM64),
- /*7353*/ uint16(x86_xMatch),
- /*7354*/ uint16(x86_xSetOp), uint16(x86_PSUBUSW),
- /*7356*/ uint16(x86_xReadSlashR),
- /*7357*/ uint16(x86_xArgXmm1),
- /*7358*/ uint16(x86_xArgXmm2M128),
- /*7359*/ uint16(x86_xMatch),
- /*7360*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7372,
- 0x0, 7366,
- /*7366*/ uint16(x86_xSetOp), uint16(x86_PMINUB),
- /*7368*/ uint16(x86_xReadSlashR),
- /*7369*/ uint16(x86_xArgMm1),
- /*7370*/ uint16(x86_xArgMm2M64),
- /*7371*/ uint16(x86_xMatch),
- /*7372*/ uint16(x86_xSetOp), uint16(x86_PMINUB),
- /*7374*/ uint16(x86_xReadSlashR),
- /*7375*/ uint16(x86_xArgXmm1),
- /*7376*/ uint16(x86_xArgXmm2M128),
- /*7377*/ uint16(x86_xMatch),
- /*7378*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7390,
- 0x0, 7384,
- /*7384*/ uint16(x86_xSetOp), uint16(x86_PAND),
- /*7386*/ uint16(x86_xReadSlashR),
- /*7387*/ uint16(x86_xArgMm),
- /*7388*/ uint16(x86_xArgMmM64),
- /*7389*/ uint16(x86_xMatch),
- /*7390*/ uint16(x86_xSetOp), uint16(x86_PAND),
- /*7392*/ uint16(x86_xReadSlashR),
- /*7393*/ uint16(x86_xArgXmm1),
- /*7394*/ uint16(x86_xArgXmm2M128),
- /*7395*/ uint16(x86_xMatch),
- /*7396*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7408,
- 0x0, 7402,
- /*7402*/ uint16(x86_xSetOp), uint16(x86_PADDUSB),
- /*7404*/ uint16(x86_xReadSlashR),
- /*7405*/ uint16(x86_xArgMm),
- /*7406*/ uint16(x86_xArgMmM64),
- /*7407*/ uint16(x86_xMatch),
- /*7408*/ uint16(x86_xSetOp), uint16(x86_PADDUSB),
- /*7410*/ uint16(x86_xReadSlashR),
- /*7411*/ uint16(x86_xArgXmm1),
- /*7412*/ uint16(x86_xArgXmm2M128),
- /*7413*/ uint16(x86_xMatch),
- /*7414*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7426,
- 0x0, 7420,
- /*7420*/ uint16(x86_xSetOp), uint16(x86_PADDUSW),
- /*7422*/ uint16(x86_xReadSlashR),
- /*7423*/ uint16(x86_xArgMm),
- /*7424*/ uint16(x86_xArgMmM64),
- /*7425*/ uint16(x86_xMatch),
- /*7426*/ uint16(x86_xSetOp), uint16(x86_PADDUSW),
- /*7428*/ uint16(x86_xReadSlashR),
- /*7429*/ uint16(x86_xArgXmm1),
- /*7430*/ uint16(x86_xArgXmm2M128),
- /*7431*/ uint16(x86_xMatch),
- /*7432*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7444,
- 0x0, 7438,
- /*7438*/ uint16(x86_xSetOp), uint16(x86_PMAXUB),
- /*7440*/ uint16(x86_xReadSlashR),
- /*7441*/ uint16(x86_xArgMm1),
- /*7442*/ uint16(x86_xArgMm2M64),
- /*7443*/ uint16(x86_xMatch),
- /*7444*/ uint16(x86_xSetOp), uint16(x86_PMAXUB),
- /*7446*/ uint16(x86_xReadSlashR),
- /*7447*/ uint16(x86_xArgXmm1),
- /*7448*/ uint16(x86_xArgXmm2M128),
- /*7449*/ uint16(x86_xMatch),
- /*7450*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7462,
- 0x0, 7456,
- /*7456*/ uint16(x86_xSetOp), uint16(x86_PANDN),
- /*7458*/ uint16(x86_xReadSlashR),
- /*7459*/ uint16(x86_xArgMm),
- /*7460*/ uint16(x86_xArgMmM64),
- /*7461*/ uint16(x86_xMatch),
- /*7462*/ uint16(x86_xSetOp), uint16(x86_PANDN),
- /*7464*/ uint16(x86_xReadSlashR),
- /*7465*/ uint16(x86_xArgXmm1),
- /*7466*/ uint16(x86_xArgXmm2M128),
- /*7467*/ uint16(x86_xMatch),
- /*7468*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7480,
- 0x0, 7474,
- /*7474*/ uint16(x86_xSetOp), uint16(x86_PAVGB),
- /*7476*/ uint16(x86_xReadSlashR),
- /*7477*/ uint16(x86_xArgMm1),
- /*7478*/ uint16(x86_xArgMm2M64),
- /*7479*/ uint16(x86_xMatch),
- /*7480*/ uint16(x86_xSetOp), uint16(x86_PAVGB),
- /*7482*/ uint16(x86_xReadSlashR),
- /*7483*/ uint16(x86_xArgXmm1),
- /*7484*/ uint16(x86_xArgXmm2M128),
- /*7485*/ uint16(x86_xMatch),
- /*7486*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7498,
- 0x0, 7492,
- /*7492*/ uint16(x86_xSetOp), uint16(x86_PSRAW),
- /*7494*/ uint16(x86_xReadSlashR),
- /*7495*/ uint16(x86_xArgMm),
- /*7496*/ uint16(x86_xArgMmM64),
- /*7497*/ uint16(x86_xMatch),
- /*7498*/ uint16(x86_xSetOp), uint16(x86_PSRAW),
- /*7500*/ uint16(x86_xReadSlashR),
- /*7501*/ uint16(x86_xArgXmm1),
- /*7502*/ uint16(x86_xArgXmm2M128),
- /*7503*/ uint16(x86_xMatch),
- /*7504*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7516,
- 0x0, 7510,
- /*7510*/ uint16(x86_xSetOp), uint16(x86_PSRAD),
- /*7512*/ uint16(x86_xReadSlashR),
- /*7513*/ uint16(x86_xArgMm),
- /*7514*/ uint16(x86_xArgMmM64),
- /*7515*/ uint16(x86_xMatch),
- /*7516*/ uint16(x86_xSetOp), uint16(x86_PSRAD),
- /*7518*/ uint16(x86_xReadSlashR),
- /*7519*/ uint16(x86_xArgXmm1),
- /*7520*/ uint16(x86_xArgXmm2M128),
- /*7521*/ uint16(x86_xMatch),
- /*7522*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7534,
- 0x0, 7528,
- /*7528*/ uint16(x86_xSetOp), uint16(x86_PAVGW),
- /*7530*/ uint16(x86_xReadSlashR),
- /*7531*/ uint16(x86_xArgMm1),
- /*7532*/ uint16(x86_xArgMm2M64),
- /*7533*/ uint16(x86_xMatch),
- /*7534*/ uint16(x86_xSetOp), uint16(x86_PAVGW),
- /*7536*/ uint16(x86_xReadSlashR),
- /*7537*/ uint16(x86_xArgXmm1),
- /*7538*/ uint16(x86_xArgXmm2M128),
- /*7539*/ uint16(x86_xMatch),
- /*7540*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7552,
- 0x0, 7546,
- /*7546*/ uint16(x86_xSetOp), uint16(x86_PMULHUW),
- /*7548*/ uint16(x86_xReadSlashR),
- /*7549*/ uint16(x86_xArgMm1),
- /*7550*/ uint16(x86_xArgMm2M64),
- /*7551*/ uint16(x86_xMatch),
- /*7552*/ uint16(x86_xSetOp), uint16(x86_PMULHUW),
- /*7554*/ uint16(x86_xReadSlashR),
- /*7555*/ uint16(x86_xArgXmm1),
- /*7556*/ uint16(x86_xArgXmm2M128),
- /*7557*/ uint16(x86_xMatch),
- /*7558*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7570,
- 0x0, 7564,
- /*7564*/ uint16(x86_xSetOp), uint16(x86_PMULHW),
- /*7566*/ uint16(x86_xReadSlashR),
- /*7567*/ uint16(x86_xArgMm),
- /*7568*/ uint16(x86_xArgMmM64),
- /*7569*/ uint16(x86_xMatch),
- /*7570*/ uint16(x86_xSetOp), uint16(x86_PMULHW),
- /*7572*/ uint16(x86_xReadSlashR),
- /*7573*/ uint16(x86_xArgXmm1),
- /*7574*/ uint16(x86_xArgXmm2M128),
- /*7575*/ uint16(x86_xMatch),
- /*7576*/ uint16(x86_xCondPrefix), 3,
- 0xF3, 7596,
- 0xF2, 7590,
- 0x66, 7584,
- /*7584*/ uint16(x86_xSetOp), uint16(x86_CVTTPD2DQ),
- /*7586*/ uint16(x86_xReadSlashR),
- /*7587*/ uint16(x86_xArgXmm1),
- /*7588*/ uint16(x86_xArgXmm2M128),
- /*7589*/ uint16(x86_xMatch),
- /*7590*/ uint16(x86_xSetOp), uint16(x86_CVTPD2DQ),
- /*7592*/ uint16(x86_xReadSlashR),
- /*7593*/ uint16(x86_xArgXmm1),
- /*7594*/ uint16(x86_xArgXmm2M128),
- /*7595*/ uint16(x86_xMatch),
- /*7596*/ uint16(x86_xSetOp), uint16(x86_CVTDQ2PD),
- /*7598*/ uint16(x86_xReadSlashR),
- /*7599*/ uint16(x86_xArgXmm1),
- /*7600*/ uint16(x86_xArgXmm2M64),
- /*7601*/ uint16(x86_xMatch),
- /*7602*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7614,
- 0x0, 7608,
- /*7608*/ uint16(x86_xSetOp), uint16(x86_MOVNTQ),
- /*7610*/ uint16(x86_xReadSlashR),
- /*7611*/ uint16(x86_xArgM64),
- /*7612*/ uint16(x86_xArgMm),
- /*7613*/ uint16(x86_xMatch),
- /*7614*/ uint16(x86_xSetOp), uint16(x86_MOVNTDQ),
- /*7616*/ uint16(x86_xReadSlashR),
- /*7617*/ uint16(x86_xArgM128),
- /*7618*/ uint16(x86_xArgXmm),
- /*7619*/ uint16(x86_xMatch),
- /*7620*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7632,
- 0x0, 7626,
- /*7626*/ uint16(x86_xSetOp), uint16(x86_PSUBSB),
- /*7628*/ uint16(x86_xReadSlashR),
- /*7629*/ uint16(x86_xArgMm),
- /*7630*/ uint16(x86_xArgMmM64),
- /*7631*/ uint16(x86_xMatch),
- /*7632*/ uint16(x86_xSetOp), uint16(x86_PSUBSB),
- /*7634*/ uint16(x86_xReadSlashR),
- /*7635*/ uint16(x86_xArgXmm1),
- /*7636*/ uint16(x86_xArgXmm2M128),
- /*7637*/ uint16(x86_xMatch),
- /*7638*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7650,
- 0x0, 7644,
- /*7644*/ uint16(x86_xSetOp), uint16(x86_PSUBSW),
- /*7646*/ uint16(x86_xReadSlashR),
- /*7647*/ uint16(x86_xArgMm),
- /*7648*/ uint16(x86_xArgMmM64),
- /*7649*/ uint16(x86_xMatch),
- /*7650*/ uint16(x86_xSetOp), uint16(x86_PSUBSW),
- /*7652*/ uint16(x86_xReadSlashR),
- /*7653*/ uint16(x86_xArgXmm1),
- /*7654*/ uint16(x86_xArgXmm2M128),
- /*7655*/ uint16(x86_xMatch),
- /*7656*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7668,
- 0x0, 7662,
- /*7662*/ uint16(x86_xSetOp), uint16(x86_PMINSW),
- /*7664*/ uint16(x86_xReadSlashR),
- /*7665*/ uint16(x86_xArgMm1),
- /*7666*/ uint16(x86_xArgMm2M64),
- /*7667*/ uint16(x86_xMatch),
- /*7668*/ uint16(x86_xSetOp), uint16(x86_PMINSW),
- /*7670*/ uint16(x86_xReadSlashR),
- /*7671*/ uint16(x86_xArgXmm1),
- /*7672*/ uint16(x86_xArgXmm2M128),
- /*7673*/ uint16(x86_xMatch),
- /*7674*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7686,
- 0x0, 7680,
- /*7680*/ uint16(x86_xSetOp), uint16(x86_POR),
- /*7682*/ uint16(x86_xReadSlashR),
- /*7683*/ uint16(x86_xArgMm),
- /*7684*/ uint16(x86_xArgMmM64),
- /*7685*/ uint16(x86_xMatch),
- /*7686*/ uint16(x86_xSetOp), uint16(x86_POR),
- /*7688*/ uint16(x86_xReadSlashR),
- /*7689*/ uint16(x86_xArgXmm1),
- /*7690*/ uint16(x86_xArgXmm2M128),
- /*7691*/ uint16(x86_xMatch),
- /*7692*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7704,
- 0x0, 7698,
- /*7698*/ uint16(x86_xSetOp), uint16(x86_PADDSB),
- /*7700*/ uint16(x86_xReadSlashR),
- /*7701*/ uint16(x86_xArgMm),
- /*7702*/ uint16(x86_xArgMmM64),
- /*7703*/ uint16(x86_xMatch),
- /*7704*/ uint16(x86_xSetOp), uint16(x86_PADDSB),
- /*7706*/ uint16(x86_xReadSlashR),
- /*7707*/ uint16(x86_xArgXmm1),
- /*7708*/ uint16(x86_xArgXmm2M128),
- /*7709*/ uint16(x86_xMatch),
- /*7710*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7722,
- 0x0, 7716,
- /*7716*/ uint16(x86_xSetOp), uint16(x86_PADDSW),
- /*7718*/ uint16(x86_xReadSlashR),
- /*7719*/ uint16(x86_xArgMm),
- /*7720*/ uint16(x86_xArgMmM64),
- /*7721*/ uint16(x86_xMatch),
- /*7722*/ uint16(x86_xSetOp), uint16(x86_PADDSW),
- /*7724*/ uint16(x86_xReadSlashR),
- /*7725*/ uint16(x86_xArgXmm1),
- /*7726*/ uint16(x86_xArgXmm2M128),
- /*7727*/ uint16(x86_xMatch),
- /*7728*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7740,
- 0x0, 7734,
- /*7734*/ uint16(x86_xSetOp), uint16(x86_PMAXSW),
- /*7736*/ uint16(x86_xReadSlashR),
- /*7737*/ uint16(x86_xArgMm1),
- /*7738*/ uint16(x86_xArgMm2M64),
- /*7739*/ uint16(x86_xMatch),
- /*7740*/ uint16(x86_xSetOp), uint16(x86_PMAXSW),
- /*7742*/ uint16(x86_xReadSlashR),
- /*7743*/ uint16(x86_xArgXmm1),
- /*7744*/ uint16(x86_xArgXmm2M128),
- /*7745*/ uint16(x86_xMatch),
- /*7746*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7758,
- 0x0, 7752,
- /*7752*/ uint16(x86_xSetOp), uint16(x86_PXOR),
- /*7754*/ uint16(x86_xReadSlashR),
- /*7755*/ uint16(x86_xArgMm),
- /*7756*/ uint16(x86_xArgMmM64),
- /*7757*/ uint16(x86_xMatch),
- /*7758*/ uint16(x86_xSetOp), uint16(x86_PXOR),
- /*7760*/ uint16(x86_xReadSlashR),
- /*7761*/ uint16(x86_xArgXmm1),
- /*7762*/ uint16(x86_xArgXmm2M128),
- /*7763*/ uint16(x86_xMatch),
- /*7764*/ uint16(x86_xCondPrefix), 1,
- 0xF2, 7768,
- /*7768*/ uint16(x86_xSetOp), uint16(x86_LDDQU),
- /*7770*/ uint16(x86_xReadSlashR),
- /*7771*/ uint16(x86_xArgXmm1),
- /*7772*/ uint16(x86_xArgM128),
- /*7773*/ uint16(x86_xMatch),
- /*7774*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7786,
- 0x0, 7780,
- /*7780*/ uint16(x86_xSetOp), uint16(x86_PSLLW),
- /*7782*/ uint16(x86_xReadSlashR),
- /*7783*/ uint16(x86_xArgMm),
- /*7784*/ uint16(x86_xArgMmM64),
- /*7785*/ uint16(x86_xMatch),
- /*7786*/ uint16(x86_xSetOp), uint16(x86_PSLLW),
- /*7788*/ uint16(x86_xReadSlashR),
- /*7789*/ uint16(x86_xArgXmm1),
- /*7790*/ uint16(x86_xArgXmm2M128),
- /*7791*/ uint16(x86_xMatch),
- /*7792*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7804,
- 0x0, 7798,
- /*7798*/ uint16(x86_xSetOp), uint16(x86_PSLLD),
- /*7800*/ uint16(x86_xReadSlashR),
- /*7801*/ uint16(x86_xArgMm),
- /*7802*/ uint16(x86_xArgMmM64),
- /*7803*/ uint16(x86_xMatch),
- /*7804*/ uint16(x86_xSetOp), uint16(x86_PSLLD),
- /*7806*/ uint16(x86_xReadSlashR),
- /*7807*/ uint16(x86_xArgXmm1),
- /*7808*/ uint16(x86_xArgXmm2M128),
- /*7809*/ uint16(x86_xMatch),
- /*7810*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7822,
- 0x0, 7816,
- /*7816*/ uint16(x86_xSetOp), uint16(x86_PSLLQ),
- /*7818*/ uint16(x86_xReadSlashR),
- /*7819*/ uint16(x86_xArgMm),
- /*7820*/ uint16(x86_xArgMmM64),
- /*7821*/ uint16(x86_xMatch),
- /*7822*/ uint16(x86_xSetOp), uint16(x86_PSLLQ),
- /*7824*/ uint16(x86_xReadSlashR),
- /*7825*/ uint16(x86_xArgXmm1),
- /*7826*/ uint16(x86_xArgXmm2M128),
- /*7827*/ uint16(x86_xMatch),
- /*7828*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7840,
- 0x0, 7834,
- /*7834*/ uint16(x86_xSetOp), uint16(x86_PMULUDQ),
- /*7836*/ uint16(x86_xReadSlashR),
- /*7837*/ uint16(x86_xArgMm1),
- /*7838*/ uint16(x86_xArgMm2M64),
- /*7839*/ uint16(x86_xMatch),
- /*7840*/ uint16(x86_xSetOp), uint16(x86_PMULUDQ),
- /*7842*/ uint16(x86_xReadSlashR),
- /*7843*/ uint16(x86_xArgXmm1),
- /*7844*/ uint16(x86_xArgXmm2M128),
- /*7845*/ uint16(x86_xMatch),
- /*7846*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7858,
- 0x0, 7852,
- /*7852*/ uint16(x86_xSetOp), uint16(x86_PMADDWD),
- /*7854*/ uint16(x86_xReadSlashR),
- /*7855*/ uint16(x86_xArgMm),
- /*7856*/ uint16(x86_xArgMmM64),
- /*7857*/ uint16(x86_xMatch),
- /*7858*/ uint16(x86_xSetOp), uint16(x86_PMADDWD),
- /*7860*/ uint16(x86_xReadSlashR),
- /*7861*/ uint16(x86_xArgXmm1),
- /*7862*/ uint16(x86_xArgXmm2M128),
- /*7863*/ uint16(x86_xMatch),
- /*7864*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7876,
- 0x0, 7870,
- /*7870*/ uint16(x86_xSetOp), uint16(x86_PSADBW),
- /*7872*/ uint16(x86_xReadSlashR),
- /*7873*/ uint16(x86_xArgMm1),
- /*7874*/ uint16(x86_xArgMm2M64),
- /*7875*/ uint16(x86_xMatch),
- /*7876*/ uint16(x86_xSetOp), uint16(x86_PSADBW),
- /*7878*/ uint16(x86_xReadSlashR),
- /*7879*/ uint16(x86_xArgXmm1),
- /*7880*/ uint16(x86_xArgXmm2M128),
- /*7881*/ uint16(x86_xMatch),
- /*7882*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7894,
- 0x0, 7888,
- /*7888*/ uint16(x86_xSetOp), uint16(x86_MASKMOVQ),
- /*7890*/ uint16(x86_xReadSlashR),
- /*7891*/ uint16(x86_xArgMm1),
- /*7892*/ uint16(x86_xArgMm2),
- /*7893*/ uint16(x86_xMatch),
- /*7894*/ uint16(x86_xSetOp), uint16(x86_MASKMOVDQU),
- /*7896*/ uint16(x86_xReadSlashR),
- /*7897*/ uint16(x86_xArgXmm1),
- /*7898*/ uint16(x86_xArgXmm2),
- /*7899*/ uint16(x86_xMatch),
- /*7900*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7912,
- 0x0, 7906,
- /*7906*/ uint16(x86_xSetOp), uint16(x86_PSUBB),
- /*7908*/ uint16(x86_xReadSlashR),
- /*7909*/ uint16(x86_xArgMm),
- /*7910*/ uint16(x86_xArgMmM64),
- /*7911*/ uint16(x86_xMatch),
- /*7912*/ uint16(x86_xSetOp), uint16(x86_PSUBB),
- /*7914*/ uint16(x86_xReadSlashR),
- /*7915*/ uint16(x86_xArgXmm1),
- /*7916*/ uint16(x86_xArgXmm2M128),
- /*7917*/ uint16(x86_xMatch),
- /*7918*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7930,
- 0x0, 7924,
- /*7924*/ uint16(x86_xSetOp), uint16(x86_PSUBW),
- /*7926*/ uint16(x86_xReadSlashR),
- /*7927*/ uint16(x86_xArgMm),
- /*7928*/ uint16(x86_xArgMmM64),
- /*7929*/ uint16(x86_xMatch),
- /*7930*/ uint16(x86_xSetOp), uint16(x86_PSUBW),
- /*7932*/ uint16(x86_xReadSlashR),
- /*7933*/ uint16(x86_xArgXmm1),
- /*7934*/ uint16(x86_xArgXmm2M128),
- /*7935*/ uint16(x86_xMatch),
- /*7936*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7948,
- 0x0, 7942,
- /*7942*/ uint16(x86_xSetOp), uint16(x86_PSUBD),
- /*7944*/ uint16(x86_xReadSlashR),
- /*7945*/ uint16(x86_xArgMm),
- /*7946*/ uint16(x86_xArgMmM64),
- /*7947*/ uint16(x86_xMatch),
- /*7948*/ uint16(x86_xSetOp), uint16(x86_PSUBD),
- /*7950*/ uint16(x86_xReadSlashR),
- /*7951*/ uint16(x86_xArgXmm1),
- /*7952*/ uint16(x86_xArgXmm2M128),
- /*7953*/ uint16(x86_xMatch),
- /*7954*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7966,
- 0x0, 7960,
- /*7960*/ uint16(x86_xSetOp), uint16(x86_PSUBQ),
- /*7962*/ uint16(x86_xReadSlashR),
- /*7963*/ uint16(x86_xArgMm1),
- /*7964*/ uint16(x86_xArgMm2M64),
- /*7965*/ uint16(x86_xMatch),
- /*7966*/ uint16(x86_xSetOp), uint16(x86_PSUBQ),
- /*7968*/ uint16(x86_xReadSlashR),
- /*7969*/ uint16(x86_xArgXmm1),
- /*7970*/ uint16(x86_xArgXmm2M128),
- /*7971*/ uint16(x86_xMatch),
- /*7972*/ uint16(x86_xCondPrefix), 2,
- 0x66, 7984,
- 0x0, 7978,
- /*7978*/ uint16(x86_xSetOp), uint16(x86_PADDB),
- /*7980*/ uint16(x86_xReadSlashR),
- /*7981*/ uint16(x86_xArgMm),
- /*7982*/ uint16(x86_xArgMmM64),
- /*7983*/ uint16(x86_xMatch),
- /*7984*/ uint16(x86_xSetOp), uint16(x86_PADDB),
- /*7986*/ uint16(x86_xReadSlashR),
- /*7987*/ uint16(x86_xArgXmm1),
- /*7988*/ uint16(x86_xArgXmm2M128),
- /*7989*/ uint16(x86_xMatch),
- /*7990*/ uint16(x86_xCondPrefix), 2,
- 0x66, 8002,
- 0x0, 7996,
- /*7996*/ uint16(x86_xSetOp), uint16(x86_PADDW),
- /*7998*/ uint16(x86_xReadSlashR),
- /*7999*/ uint16(x86_xArgMm),
- /*8000*/ uint16(x86_xArgMmM64),
- /*8001*/ uint16(x86_xMatch),
- /*8002*/ uint16(x86_xSetOp), uint16(x86_PADDW),
- /*8004*/ uint16(x86_xReadSlashR),
- /*8005*/ uint16(x86_xArgXmm1),
- /*8006*/ uint16(x86_xArgXmm2M128),
- /*8007*/ uint16(x86_xMatch),
- /*8008*/ uint16(x86_xCondPrefix), 2,
- 0x66, 8020,
- 0x0, 8014,
- /*8014*/ uint16(x86_xSetOp), uint16(x86_PADDD),
- /*8016*/ uint16(x86_xReadSlashR),
- /*8017*/ uint16(x86_xArgMm),
- /*8018*/ uint16(x86_xArgMmM64),
- /*8019*/ uint16(x86_xMatch),
- /*8020*/ uint16(x86_xSetOp), uint16(x86_PADDD),
- /*8022*/ uint16(x86_xReadSlashR),
- /*8023*/ uint16(x86_xArgXmm1),
- /*8024*/ uint16(x86_xArgXmm2M128),
- /*8025*/ uint16(x86_xMatch),
- /*8026*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8028*/ uint16(x86_xReadSlashR),
- /*8029*/ uint16(x86_xArgRM8),
- /*8030*/ uint16(x86_xArgR8),
- /*8031*/ uint16(x86_xMatch),
- /*8032*/ uint16(x86_xCondIs64), 8035, 8051,
- /*8035*/ uint16(x86_xCondDataSize), 8039, 8045, 0,
- /*8039*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8041*/ uint16(x86_xReadSlashR),
- /*8042*/ uint16(x86_xArgRM16),
- /*8043*/ uint16(x86_xArgR16),
- /*8044*/ uint16(x86_xMatch),
- /*8045*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8047*/ uint16(x86_xReadSlashR),
- /*8048*/ uint16(x86_xArgRM32),
- /*8049*/ uint16(x86_xArgR32),
- /*8050*/ uint16(x86_xMatch),
- /*8051*/ uint16(x86_xCondDataSize), 8039, 8045, 8055,
- /*8055*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8057*/ uint16(x86_xReadSlashR),
- /*8058*/ uint16(x86_xArgRM64),
- /*8059*/ uint16(x86_xArgR64),
- /*8060*/ uint16(x86_xMatch),
- /*8061*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8063*/ uint16(x86_xReadSlashR),
- /*8064*/ uint16(x86_xArgR8),
- /*8065*/ uint16(x86_xArgRM8),
- /*8066*/ uint16(x86_xMatch),
- /*8067*/ uint16(x86_xCondIs64), 8070, 8086,
- /*8070*/ uint16(x86_xCondDataSize), 8074, 8080, 0,
- /*8074*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8076*/ uint16(x86_xReadSlashR),
- /*8077*/ uint16(x86_xArgR16),
- /*8078*/ uint16(x86_xArgRM16),
- /*8079*/ uint16(x86_xMatch),
- /*8080*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8082*/ uint16(x86_xReadSlashR),
- /*8083*/ uint16(x86_xArgR32),
- /*8084*/ uint16(x86_xArgRM32),
- /*8085*/ uint16(x86_xMatch),
- /*8086*/ uint16(x86_xCondDataSize), 8074, 8080, 8090,
- /*8090*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8092*/ uint16(x86_xReadSlashR),
- /*8093*/ uint16(x86_xArgR64),
- /*8094*/ uint16(x86_xArgRM64),
- /*8095*/ uint16(x86_xMatch),
- /*8096*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8098*/ uint16(x86_xReadIb),
- /*8099*/ uint16(x86_xArgAL),
- /*8100*/ uint16(x86_xArgImm8u),
- /*8101*/ uint16(x86_xMatch),
- /*8102*/ uint16(x86_xCondIs64), 8105, 8121,
- /*8105*/ uint16(x86_xCondDataSize), 8109, 8115, 0,
- /*8109*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8111*/ uint16(x86_xReadIw),
- /*8112*/ uint16(x86_xArgAX),
- /*8113*/ uint16(x86_xArgImm16),
- /*8114*/ uint16(x86_xMatch),
- /*8115*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8117*/ uint16(x86_xReadId),
- /*8118*/ uint16(x86_xArgEAX),
- /*8119*/ uint16(x86_xArgImm32),
- /*8120*/ uint16(x86_xMatch),
- /*8121*/ uint16(x86_xCondDataSize), 8109, 8115, 8125,
- /*8125*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*8127*/ uint16(x86_xReadId),
- /*8128*/ uint16(x86_xArgRAX),
- /*8129*/ uint16(x86_xArgImm32),
- /*8130*/ uint16(x86_xMatch),
- /*8131*/ uint16(x86_xCondIs64), 8134, 0,
- /*8134*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*8136*/ uint16(x86_xArgSS),
- /*8137*/ uint16(x86_xMatch),
- /*8138*/ uint16(x86_xCondIs64), 8141, 0,
- /*8141*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*8143*/ uint16(x86_xArgSS),
- /*8144*/ uint16(x86_xMatch),
- /*8145*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8147*/ uint16(x86_xReadSlashR),
- /*8148*/ uint16(x86_xArgRM8),
- /*8149*/ uint16(x86_xArgR8),
- /*8150*/ uint16(x86_xMatch),
- /*8151*/ uint16(x86_xCondIs64), 8154, 8170,
- /*8154*/ uint16(x86_xCondDataSize), 8158, 8164, 0,
- /*8158*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8160*/ uint16(x86_xReadSlashR),
- /*8161*/ uint16(x86_xArgRM16),
- /*8162*/ uint16(x86_xArgR16),
- /*8163*/ uint16(x86_xMatch),
- /*8164*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8166*/ uint16(x86_xReadSlashR),
- /*8167*/ uint16(x86_xArgRM32),
- /*8168*/ uint16(x86_xArgR32),
- /*8169*/ uint16(x86_xMatch),
- /*8170*/ uint16(x86_xCondDataSize), 8158, 8164, 8174,
- /*8174*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8176*/ uint16(x86_xReadSlashR),
- /*8177*/ uint16(x86_xArgRM64),
- /*8178*/ uint16(x86_xArgR64),
- /*8179*/ uint16(x86_xMatch),
- /*8180*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8182*/ uint16(x86_xReadSlashR),
- /*8183*/ uint16(x86_xArgR8),
- /*8184*/ uint16(x86_xArgRM8),
- /*8185*/ uint16(x86_xMatch),
- /*8186*/ uint16(x86_xCondIs64), 8189, 8205,
- /*8189*/ uint16(x86_xCondDataSize), 8193, 8199, 0,
- /*8193*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8195*/ uint16(x86_xReadSlashR),
- /*8196*/ uint16(x86_xArgR16),
- /*8197*/ uint16(x86_xArgRM16),
- /*8198*/ uint16(x86_xMatch),
- /*8199*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8201*/ uint16(x86_xReadSlashR),
- /*8202*/ uint16(x86_xArgR32),
- /*8203*/ uint16(x86_xArgRM32),
- /*8204*/ uint16(x86_xMatch),
- /*8205*/ uint16(x86_xCondDataSize), 8193, 8199, 8209,
- /*8209*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8211*/ uint16(x86_xReadSlashR),
- /*8212*/ uint16(x86_xArgR64),
- /*8213*/ uint16(x86_xArgRM64),
- /*8214*/ uint16(x86_xMatch),
- /*8215*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8217*/ uint16(x86_xReadIb),
- /*8218*/ uint16(x86_xArgAL),
- /*8219*/ uint16(x86_xArgImm8u),
- /*8220*/ uint16(x86_xMatch),
- /*8221*/ uint16(x86_xCondIs64), 8224, 8240,
- /*8224*/ uint16(x86_xCondDataSize), 8228, 8234, 0,
- /*8228*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8230*/ uint16(x86_xReadIw),
- /*8231*/ uint16(x86_xArgAX),
- /*8232*/ uint16(x86_xArgImm16),
- /*8233*/ uint16(x86_xMatch),
- /*8234*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8236*/ uint16(x86_xReadId),
- /*8237*/ uint16(x86_xArgEAX),
- /*8238*/ uint16(x86_xArgImm32),
- /*8239*/ uint16(x86_xMatch),
- /*8240*/ uint16(x86_xCondDataSize), 8228, 8234, 8244,
- /*8244*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*8246*/ uint16(x86_xReadId),
- /*8247*/ uint16(x86_xArgRAX),
- /*8248*/ uint16(x86_xArgImm32),
- /*8249*/ uint16(x86_xMatch),
- /*8250*/ uint16(x86_xCondIs64), 8253, 0,
- /*8253*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*8255*/ uint16(x86_xArgDS),
- /*8256*/ uint16(x86_xMatch),
- /*8257*/ uint16(x86_xCondIs64), 8260, 0,
- /*8260*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*8262*/ uint16(x86_xArgDS),
- /*8263*/ uint16(x86_xMatch),
- /*8264*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8266*/ uint16(x86_xReadSlashR),
- /*8267*/ uint16(x86_xArgRM8),
- /*8268*/ uint16(x86_xArgR8),
- /*8269*/ uint16(x86_xMatch),
- /*8270*/ uint16(x86_xCondIs64), 8273, 8289,
- /*8273*/ uint16(x86_xCondDataSize), 8277, 8283, 0,
- /*8277*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8279*/ uint16(x86_xReadSlashR),
- /*8280*/ uint16(x86_xArgRM16),
- /*8281*/ uint16(x86_xArgR16),
- /*8282*/ uint16(x86_xMatch),
- /*8283*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8285*/ uint16(x86_xReadSlashR),
- /*8286*/ uint16(x86_xArgRM32),
- /*8287*/ uint16(x86_xArgR32),
- /*8288*/ uint16(x86_xMatch),
- /*8289*/ uint16(x86_xCondDataSize), 8277, 8283, 8293,
- /*8293*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8295*/ uint16(x86_xReadSlashR),
- /*8296*/ uint16(x86_xArgRM64),
- /*8297*/ uint16(x86_xArgR64),
- /*8298*/ uint16(x86_xMatch),
- /*8299*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8301*/ uint16(x86_xReadSlashR),
- /*8302*/ uint16(x86_xArgR8),
- /*8303*/ uint16(x86_xArgRM8),
- /*8304*/ uint16(x86_xMatch),
- /*8305*/ uint16(x86_xCondIs64), 8308, 8324,
- /*8308*/ uint16(x86_xCondDataSize), 8312, 8318, 0,
- /*8312*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8314*/ uint16(x86_xReadSlashR),
- /*8315*/ uint16(x86_xArgR16),
- /*8316*/ uint16(x86_xArgRM16),
- /*8317*/ uint16(x86_xMatch),
- /*8318*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8320*/ uint16(x86_xReadSlashR),
- /*8321*/ uint16(x86_xArgR32),
- /*8322*/ uint16(x86_xArgRM32),
- /*8323*/ uint16(x86_xMatch),
- /*8324*/ uint16(x86_xCondDataSize), 8312, 8318, 8328,
- /*8328*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8330*/ uint16(x86_xReadSlashR),
- /*8331*/ uint16(x86_xArgR64),
- /*8332*/ uint16(x86_xArgRM64),
- /*8333*/ uint16(x86_xMatch),
- /*8334*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8336*/ uint16(x86_xReadIb),
- /*8337*/ uint16(x86_xArgAL),
- /*8338*/ uint16(x86_xArgImm8u),
- /*8339*/ uint16(x86_xMatch),
- /*8340*/ uint16(x86_xCondIs64), 8343, 8359,
- /*8343*/ uint16(x86_xCondDataSize), 8347, 8353, 0,
- /*8347*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8349*/ uint16(x86_xReadIw),
- /*8350*/ uint16(x86_xArgAX),
- /*8351*/ uint16(x86_xArgImm16),
- /*8352*/ uint16(x86_xMatch),
- /*8353*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8355*/ uint16(x86_xReadId),
- /*8356*/ uint16(x86_xArgEAX),
- /*8357*/ uint16(x86_xArgImm32),
- /*8358*/ uint16(x86_xMatch),
- /*8359*/ uint16(x86_xCondDataSize), 8347, 8353, 8363,
- /*8363*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*8365*/ uint16(x86_xReadId),
- /*8366*/ uint16(x86_xArgRAX),
- /*8367*/ uint16(x86_xArgImm32),
- /*8368*/ uint16(x86_xMatch),
- /*8369*/ uint16(x86_xCondIs64), 8372, 0,
- /*8372*/ uint16(x86_xSetOp), uint16(x86_DAA),
- /*8374*/ uint16(x86_xMatch),
- /*8375*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8377*/ uint16(x86_xReadSlashR),
- /*8378*/ uint16(x86_xArgRM8),
- /*8379*/ uint16(x86_xArgR8),
- /*8380*/ uint16(x86_xMatch),
- /*8381*/ uint16(x86_xCondIs64), 8384, 8400,
- /*8384*/ uint16(x86_xCondDataSize), 8388, 8394, 0,
- /*8388*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8390*/ uint16(x86_xReadSlashR),
- /*8391*/ uint16(x86_xArgRM16),
- /*8392*/ uint16(x86_xArgR16),
- /*8393*/ uint16(x86_xMatch),
- /*8394*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8396*/ uint16(x86_xReadSlashR),
- /*8397*/ uint16(x86_xArgRM32),
- /*8398*/ uint16(x86_xArgR32),
- /*8399*/ uint16(x86_xMatch),
- /*8400*/ uint16(x86_xCondDataSize), 8388, 8394, 8404,
- /*8404*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8406*/ uint16(x86_xReadSlashR),
- /*8407*/ uint16(x86_xArgRM64),
- /*8408*/ uint16(x86_xArgR64),
- /*8409*/ uint16(x86_xMatch),
- /*8410*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8412*/ uint16(x86_xReadSlashR),
- /*8413*/ uint16(x86_xArgR8),
- /*8414*/ uint16(x86_xArgRM8),
- /*8415*/ uint16(x86_xMatch),
- /*8416*/ uint16(x86_xCondIs64), 8419, 8435,
- /*8419*/ uint16(x86_xCondDataSize), 8423, 8429, 0,
- /*8423*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8425*/ uint16(x86_xReadSlashR),
- /*8426*/ uint16(x86_xArgR16),
- /*8427*/ uint16(x86_xArgRM16),
- /*8428*/ uint16(x86_xMatch),
- /*8429*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8431*/ uint16(x86_xReadSlashR),
- /*8432*/ uint16(x86_xArgR32),
- /*8433*/ uint16(x86_xArgRM32),
- /*8434*/ uint16(x86_xMatch),
- /*8435*/ uint16(x86_xCondDataSize), 8423, 8429, 8439,
- /*8439*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8441*/ uint16(x86_xReadSlashR),
- /*8442*/ uint16(x86_xArgR64),
- /*8443*/ uint16(x86_xArgRM64),
- /*8444*/ uint16(x86_xMatch),
- /*8445*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8447*/ uint16(x86_xReadIb),
- /*8448*/ uint16(x86_xArgAL),
- /*8449*/ uint16(x86_xArgImm8u),
- /*8450*/ uint16(x86_xMatch),
- /*8451*/ uint16(x86_xCondIs64), 8454, 8470,
- /*8454*/ uint16(x86_xCondDataSize), 8458, 8464, 0,
- /*8458*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8460*/ uint16(x86_xReadIw),
- /*8461*/ uint16(x86_xArgAX),
- /*8462*/ uint16(x86_xArgImm16),
- /*8463*/ uint16(x86_xMatch),
- /*8464*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8466*/ uint16(x86_xReadId),
- /*8467*/ uint16(x86_xArgEAX),
- /*8468*/ uint16(x86_xArgImm32),
- /*8469*/ uint16(x86_xMatch),
- /*8470*/ uint16(x86_xCondDataSize), 8458, 8464, 8474,
- /*8474*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*8476*/ uint16(x86_xReadId),
- /*8477*/ uint16(x86_xArgRAX),
- /*8478*/ uint16(x86_xArgImm32),
- /*8479*/ uint16(x86_xMatch),
- /*8480*/ uint16(x86_xCondIs64), 8483, 0,
- /*8483*/ uint16(x86_xSetOp), uint16(x86_DAS),
- /*8485*/ uint16(x86_xMatch),
- /*8486*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8488*/ uint16(x86_xReadSlashR),
- /*8489*/ uint16(x86_xArgRM8),
- /*8490*/ uint16(x86_xArgR8),
- /*8491*/ uint16(x86_xMatch),
- /*8492*/ uint16(x86_xCondIs64), 8495, 8511,
- /*8495*/ uint16(x86_xCondDataSize), 8499, 8505, 0,
- /*8499*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8501*/ uint16(x86_xReadSlashR),
- /*8502*/ uint16(x86_xArgRM16),
- /*8503*/ uint16(x86_xArgR16),
- /*8504*/ uint16(x86_xMatch),
- /*8505*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8507*/ uint16(x86_xReadSlashR),
- /*8508*/ uint16(x86_xArgRM32),
- /*8509*/ uint16(x86_xArgR32),
- /*8510*/ uint16(x86_xMatch),
- /*8511*/ uint16(x86_xCondDataSize), 8499, 8505, 8515,
- /*8515*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8517*/ uint16(x86_xReadSlashR),
- /*8518*/ uint16(x86_xArgRM64),
- /*8519*/ uint16(x86_xArgR64),
- /*8520*/ uint16(x86_xMatch),
- /*8521*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8523*/ uint16(x86_xReadSlashR),
- /*8524*/ uint16(x86_xArgR8),
- /*8525*/ uint16(x86_xArgRM8),
- /*8526*/ uint16(x86_xMatch),
- /*8527*/ uint16(x86_xCondIs64), 8530, 8546,
- /*8530*/ uint16(x86_xCondDataSize), 8534, 8540, 0,
- /*8534*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8536*/ uint16(x86_xReadSlashR),
- /*8537*/ uint16(x86_xArgR16),
- /*8538*/ uint16(x86_xArgRM16),
- /*8539*/ uint16(x86_xMatch),
- /*8540*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8542*/ uint16(x86_xReadSlashR),
- /*8543*/ uint16(x86_xArgR32),
- /*8544*/ uint16(x86_xArgRM32),
- /*8545*/ uint16(x86_xMatch),
- /*8546*/ uint16(x86_xCondDataSize), 8534, 8540, 8550,
- /*8550*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8552*/ uint16(x86_xReadSlashR),
- /*8553*/ uint16(x86_xArgR64),
- /*8554*/ uint16(x86_xArgRM64),
- /*8555*/ uint16(x86_xMatch),
- /*8556*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8558*/ uint16(x86_xReadIb),
- /*8559*/ uint16(x86_xArgAL),
- /*8560*/ uint16(x86_xArgImm8u),
- /*8561*/ uint16(x86_xMatch),
- /*8562*/ uint16(x86_xCondIs64), 8565, 8581,
- /*8565*/ uint16(x86_xCondDataSize), 8569, 8575, 0,
- /*8569*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8571*/ uint16(x86_xReadIw),
- /*8572*/ uint16(x86_xArgAX),
- /*8573*/ uint16(x86_xArgImm16),
- /*8574*/ uint16(x86_xMatch),
- /*8575*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8577*/ uint16(x86_xReadId),
- /*8578*/ uint16(x86_xArgEAX),
- /*8579*/ uint16(x86_xArgImm32),
- /*8580*/ uint16(x86_xMatch),
- /*8581*/ uint16(x86_xCondDataSize), 8569, 8575, 8585,
- /*8585*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*8587*/ uint16(x86_xReadId),
- /*8588*/ uint16(x86_xArgRAX),
- /*8589*/ uint16(x86_xArgImm32),
- /*8590*/ uint16(x86_xMatch),
- /*8591*/ uint16(x86_xCondIs64), 8594, 0,
- /*8594*/ uint16(x86_xSetOp), uint16(x86_AAA),
- /*8596*/ uint16(x86_xMatch),
- /*8597*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8599*/ uint16(x86_xReadSlashR),
- /*8600*/ uint16(x86_xArgRM8),
- /*8601*/ uint16(x86_xArgR8),
- /*8602*/ uint16(x86_xMatch),
- /*8603*/ uint16(x86_xCondIs64), 8606, 8622,
- /*8606*/ uint16(x86_xCondDataSize), 8610, 8616, 0,
- /*8610*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8612*/ uint16(x86_xReadSlashR),
- /*8613*/ uint16(x86_xArgRM16),
- /*8614*/ uint16(x86_xArgR16),
- /*8615*/ uint16(x86_xMatch),
- /*8616*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8618*/ uint16(x86_xReadSlashR),
- /*8619*/ uint16(x86_xArgRM32),
- /*8620*/ uint16(x86_xArgR32),
- /*8621*/ uint16(x86_xMatch),
- /*8622*/ uint16(x86_xCondDataSize), 8610, 8616, 8626,
- /*8626*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8628*/ uint16(x86_xReadSlashR),
- /*8629*/ uint16(x86_xArgRM64),
- /*8630*/ uint16(x86_xArgR64),
- /*8631*/ uint16(x86_xMatch),
- /*8632*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8634*/ uint16(x86_xReadSlashR),
- /*8635*/ uint16(x86_xArgR8),
- /*8636*/ uint16(x86_xArgRM8),
- /*8637*/ uint16(x86_xMatch),
- /*8638*/ uint16(x86_xCondIs64), 8641, 8657,
- /*8641*/ uint16(x86_xCondDataSize), 8645, 8651, 0,
- /*8645*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8647*/ uint16(x86_xReadSlashR),
- /*8648*/ uint16(x86_xArgR16),
- /*8649*/ uint16(x86_xArgRM16),
- /*8650*/ uint16(x86_xMatch),
- /*8651*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8653*/ uint16(x86_xReadSlashR),
- /*8654*/ uint16(x86_xArgR32),
- /*8655*/ uint16(x86_xArgRM32),
- /*8656*/ uint16(x86_xMatch),
- /*8657*/ uint16(x86_xCondDataSize), 8645, 8651, 8661,
- /*8661*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8663*/ uint16(x86_xReadSlashR),
- /*8664*/ uint16(x86_xArgR64),
- /*8665*/ uint16(x86_xArgRM64),
- /*8666*/ uint16(x86_xMatch),
- /*8667*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8669*/ uint16(x86_xReadIb),
- /*8670*/ uint16(x86_xArgAL),
- /*8671*/ uint16(x86_xArgImm8u),
- /*8672*/ uint16(x86_xMatch),
- /*8673*/ uint16(x86_xCondIs64), 8676, 8692,
- /*8676*/ uint16(x86_xCondDataSize), 8680, 8686, 0,
- /*8680*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8682*/ uint16(x86_xReadIw),
- /*8683*/ uint16(x86_xArgAX),
- /*8684*/ uint16(x86_xArgImm16),
- /*8685*/ uint16(x86_xMatch),
- /*8686*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8688*/ uint16(x86_xReadId),
- /*8689*/ uint16(x86_xArgEAX),
- /*8690*/ uint16(x86_xArgImm32),
- /*8691*/ uint16(x86_xMatch),
- /*8692*/ uint16(x86_xCondDataSize), 8680, 8686, 8696,
- /*8696*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*8698*/ uint16(x86_xReadId),
- /*8699*/ uint16(x86_xArgRAX),
- /*8700*/ uint16(x86_xArgImm32),
- /*8701*/ uint16(x86_xMatch),
- /*8702*/ uint16(x86_xCondIs64), 8705, 0,
- /*8705*/ uint16(x86_xSetOp), uint16(x86_AAS),
- /*8707*/ uint16(x86_xMatch),
- /*8708*/ uint16(x86_xCondIs64), 8711, 0,
- /*8711*/ uint16(x86_xCondDataSize), 8715, 8719, 0,
- /*8715*/ uint16(x86_xSetOp), uint16(x86_INC),
- /*8717*/ uint16(x86_xArgR16op),
- /*8718*/ uint16(x86_xMatch),
- /*8719*/ uint16(x86_xSetOp), uint16(x86_INC),
- /*8721*/ uint16(x86_xArgR32op),
- /*8722*/ uint16(x86_xMatch),
- /*8723*/ uint16(x86_xCondIs64), 8726, 0,
- /*8726*/ uint16(x86_xCondDataSize), 8730, 8734, 0,
- /*8730*/ uint16(x86_xSetOp), uint16(x86_DEC),
- /*8732*/ uint16(x86_xArgR16op),
- /*8733*/ uint16(x86_xMatch),
- /*8734*/ uint16(x86_xSetOp), uint16(x86_DEC),
- /*8736*/ uint16(x86_xArgR32op),
- /*8737*/ uint16(x86_xMatch),
- /*8738*/ uint16(x86_xCondIs64), 8741, 8753,
- /*8741*/ uint16(x86_xCondDataSize), 8745, 8749, 0,
- /*8745*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*8747*/ uint16(x86_xArgR16op),
- /*8748*/ uint16(x86_xMatch),
- /*8749*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*8751*/ uint16(x86_xArgR32op),
- /*8752*/ uint16(x86_xMatch),
- /*8753*/ uint16(x86_xCondDataSize), 8745, 8757, 8761,
- /*8757*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*8759*/ uint16(x86_xArgR64op),
- /*8760*/ uint16(x86_xMatch),
- /*8761*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*8763*/ uint16(x86_xArgR64op),
- /*8764*/ uint16(x86_xMatch),
- /*8765*/ uint16(x86_xCondIs64), 8768, 8780,
- /*8768*/ uint16(x86_xCondDataSize), 8772, 8776, 0,
- /*8772*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*8774*/ uint16(x86_xArgR16op),
- /*8775*/ uint16(x86_xMatch),
- /*8776*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*8778*/ uint16(x86_xArgR32op),
- /*8779*/ uint16(x86_xMatch),
- /*8780*/ uint16(x86_xCondDataSize), 8772, 8784, 8788,
- /*8784*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*8786*/ uint16(x86_xArgR64op),
- /*8787*/ uint16(x86_xMatch),
- /*8788*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*8790*/ uint16(x86_xArgR64op),
- /*8791*/ uint16(x86_xMatch),
- /*8792*/ uint16(x86_xCondIs64), 8795, 0,
- /*8795*/ uint16(x86_xCondDataSize), 8799, 8802, 0,
- /*8799*/ uint16(x86_xSetOp), uint16(x86_PUSHA),
- /*8801*/ uint16(x86_xMatch),
- /*8802*/ uint16(x86_xSetOp), uint16(x86_PUSHAD),
- /*8804*/ uint16(x86_xMatch),
- /*8805*/ uint16(x86_xCondIs64), 8808, 0,
- /*8808*/ uint16(x86_xCondDataSize), 8812, 8815, 0,
- /*8812*/ uint16(x86_xSetOp), uint16(x86_POPA),
- /*8814*/ uint16(x86_xMatch),
- /*8815*/ uint16(x86_xSetOp), uint16(x86_POPAD),
- /*8817*/ uint16(x86_xMatch),
- /*8818*/ uint16(x86_xCondIs64), 8821, 0,
- /*8821*/ uint16(x86_xCondDataSize), 8825, 8831, 0,
- /*8825*/ uint16(x86_xSetOp), uint16(x86_BOUND),
- /*8827*/ uint16(x86_xReadSlashR),
- /*8828*/ uint16(x86_xArgR16),
- /*8829*/ uint16(x86_xArgM16and16),
- /*8830*/ uint16(x86_xMatch),
- /*8831*/ uint16(x86_xSetOp), uint16(x86_BOUND),
- /*8833*/ uint16(x86_xReadSlashR),
- /*8834*/ uint16(x86_xArgR32),
- /*8835*/ uint16(x86_xArgM32and32),
- /*8836*/ uint16(x86_xMatch),
- /*8837*/ uint16(x86_xCondIs64), 8840, 8846,
- /*8840*/ uint16(x86_xSetOp), uint16(x86_ARPL),
- /*8842*/ uint16(x86_xReadSlashR),
- /*8843*/ uint16(x86_xArgRM16),
- /*8844*/ uint16(x86_xArgR16),
- /*8845*/ uint16(x86_xMatch),
- /*8846*/ uint16(x86_xCondDataSize), 8850, 8856, 8862,
- /*8850*/ uint16(x86_xSetOp), uint16(x86_MOVSXD),
- /*8852*/ uint16(x86_xReadSlashR),
- /*8853*/ uint16(x86_xArgR16),
- /*8854*/ uint16(x86_xArgRM32),
- /*8855*/ uint16(x86_xMatch),
- /*8856*/ uint16(x86_xSetOp), uint16(x86_MOVSXD),
- /*8858*/ uint16(x86_xReadSlashR),
- /*8859*/ uint16(x86_xArgR32),
- /*8860*/ uint16(x86_xArgRM32),
- /*8861*/ uint16(x86_xMatch),
- /*8862*/ uint16(x86_xSetOp), uint16(x86_MOVSXD),
- /*8864*/ uint16(x86_xReadSlashR),
- /*8865*/ uint16(x86_xArgR64),
- /*8866*/ uint16(x86_xArgRM32),
- /*8867*/ uint16(x86_xMatch),
- /*8868*/ uint16(x86_xCondDataSize), 8872, 8877, 8882,
- /*8872*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*8874*/ uint16(x86_xReadIw),
- /*8875*/ uint16(x86_xArgImm16),
- /*8876*/ uint16(x86_xMatch),
- /*8877*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*8879*/ uint16(x86_xReadId),
- /*8880*/ uint16(x86_xArgImm32),
- /*8881*/ uint16(x86_xMatch),
- /*8882*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*8884*/ uint16(x86_xReadId),
- /*8885*/ uint16(x86_xArgImm32),
- /*8886*/ uint16(x86_xMatch),
- /*8887*/ uint16(x86_xCondIs64), 8890, 8910,
- /*8890*/ uint16(x86_xCondDataSize), 8894, 8902, 0,
- /*8894*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*8896*/ uint16(x86_xReadSlashR),
- /*8897*/ uint16(x86_xReadIw),
- /*8898*/ uint16(x86_xArgR16),
- /*8899*/ uint16(x86_xArgRM16),
- /*8900*/ uint16(x86_xArgImm16),
- /*8901*/ uint16(x86_xMatch),
- /*8902*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*8904*/ uint16(x86_xReadSlashR),
- /*8905*/ uint16(x86_xReadId),
- /*8906*/ uint16(x86_xArgR32),
- /*8907*/ uint16(x86_xArgRM32),
- /*8908*/ uint16(x86_xArgImm32),
- /*8909*/ uint16(x86_xMatch),
- /*8910*/ uint16(x86_xCondDataSize), 8894, 8902, 8914,
- /*8914*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*8916*/ uint16(x86_xReadSlashR),
- /*8917*/ uint16(x86_xReadId),
- /*8918*/ uint16(x86_xArgR64),
- /*8919*/ uint16(x86_xArgRM64),
- /*8920*/ uint16(x86_xArgImm32),
- /*8921*/ uint16(x86_xMatch),
- /*8922*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*8924*/ uint16(x86_xReadIb),
- /*8925*/ uint16(x86_xArgImm8),
- /*8926*/ uint16(x86_xMatch),
- /*8927*/ uint16(x86_xCondIs64), 8930, 8950,
- /*8930*/ uint16(x86_xCondDataSize), 8934, 8942, 0,
- /*8934*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*8936*/ uint16(x86_xReadSlashR),
- /*8937*/ uint16(x86_xReadIb),
- /*8938*/ uint16(x86_xArgR16),
- /*8939*/ uint16(x86_xArgRM16),
- /*8940*/ uint16(x86_xArgImm8),
- /*8941*/ uint16(x86_xMatch),
- /*8942*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*8944*/ uint16(x86_xReadSlashR),
- /*8945*/ uint16(x86_xReadIb),
- /*8946*/ uint16(x86_xArgR32),
- /*8947*/ uint16(x86_xArgRM32),
- /*8948*/ uint16(x86_xArgImm8),
- /*8949*/ uint16(x86_xMatch),
- /*8950*/ uint16(x86_xCondDataSize), 8934, 8942, 8954,
- /*8954*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*8956*/ uint16(x86_xReadSlashR),
- /*8957*/ uint16(x86_xReadIb),
- /*8958*/ uint16(x86_xArgR64),
- /*8959*/ uint16(x86_xArgRM64),
- /*8960*/ uint16(x86_xArgImm8),
- /*8961*/ uint16(x86_xMatch),
- /*8962*/ uint16(x86_xSetOp), uint16(x86_INSB),
- /*8964*/ uint16(x86_xMatch),
- /*8965*/ uint16(x86_xCondDataSize), 8969, 8972, 8975,
- /*8969*/ uint16(x86_xSetOp), uint16(x86_INSW),
- /*8971*/ uint16(x86_xMatch),
- /*8972*/ uint16(x86_xSetOp), uint16(x86_INSD),
- /*8974*/ uint16(x86_xMatch),
- /*8975*/ uint16(x86_xSetOp), uint16(x86_INSD),
- /*8977*/ uint16(x86_xMatch),
- /*8978*/ uint16(x86_xSetOp), uint16(x86_OUTSB),
- /*8980*/ uint16(x86_xMatch),
- /*8981*/ uint16(x86_xCondDataSize), 8985, 8988, 8991,
- /*8985*/ uint16(x86_xSetOp), uint16(x86_OUTSW),
- /*8987*/ uint16(x86_xMatch),
- /*8988*/ uint16(x86_xSetOp), uint16(x86_OUTSD),
- /*8990*/ uint16(x86_xMatch),
- /*8991*/ uint16(x86_xSetOp), uint16(x86_OUTSD),
- /*8993*/ uint16(x86_xMatch),
- /*8994*/ uint16(x86_xSetOp), uint16(x86_JO),
- /*8996*/ uint16(x86_xReadCb),
- /*8997*/ uint16(x86_xArgRel8),
- /*8998*/ uint16(x86_xMatch),
- /*8999*/ uint16(x86_xSetOp), uint16(x86_JNO),
- /*9001*/ uint16(x86_xReadCb),
- /*9002*/ uint16(x86_xArgRel8),
- /*9003*/ uint16(x86_xMatch),
- /*9004*/ uint16(x86_xSetOp), uint16(x86_JB),
- /*9006*/ uint16(x86_xReadCb),
- /*9007*/ uint16(x86_xArgRel8),
- /*9008*/ uint16(x86_xMatch),
- /*9009*/ uint16(x86_xSetOp), uint16(x86_JAE),
- /*9011*/ uint16(x86_xReadCb),
- /*9012*/ uint16(x86_xArgRel8),
- /*9013*/ uint16(x86_xMatch),
- /*9014*/ uint16(x86_xSetOp), uint16(x86_JE),
- /*9016*/ uint16(x86_xReadCb),
- /*9017*/ uint16(x86_xArgRel8),
- /*9018*/ uint16(x86_xMatch),
- /*9019*/ uint16(x86_xSetOp), uint16(x86_JNE),
- /*9021*/ uint16(x86_xReadCb),
- /*9022*/ uint16(x86_xArgRel8),
- /*9023*/ uint16(x86_xMatch),
- /*9024*/ uint16(x86_xSetOp), uint16(x86_JBE),
- /*9026*/ uint16(x86_xReadCb),
- /*9027*/ uint16(x86_xArgRel8),
- /*9028*/ uint16(x86_xMatch),
- /*9029*/ uint16(x86_xSetOp), uint16(x86_JA),
- /*9031*/ uint16(x86_xReadCb),
- /*9032*/ uint16(x86_xArgRel8),
- /*9033*/ uint16(x86_xMatch),
- /*9034*/ uint16(x86_xSetOp), uint16(x86_JS),
- /*9036*/ uint16(x86_xReadCb),
- /*9037*/ uint16(x86_xArgRel8),
- /*9038*/ uint16(x86_xMatch),
- /*9039*/ uint16(x86_xSetOp), uint16(x86_JNS),
- /*9041*/ uint16(x86_xReadCb),
- /*9042*/ uint16(x86_xArgRel8),
- /*9043*/ uint16(x86_xMatch),
- /*9044*/ uint16(x86_xSetOp), uint16(x86_JP),
- /*9046*/ uint16(x86_xReadCb),
- /*9047*/ uint16(x86_xArgRel8),
- /*9048*/ uint16(x86_xMatch),
- /*9049*/ uint16(x86_xSetOp), uint16(x86_JNP),
- /*9051*/ uint16(x86_xReadCb),
- /*9052*/ uint16(x86_xArgRel8),
- /*9053*/ uint16(x86_xMatch),
- /*9054*/ uint16(x86_xSetOp), uint16(x86_JL),
- /*9056*/ uint16(x86_xReadCb),
- /*9057*/ uint16(x86_xArgRel8),
- /*9058*/ uint16(x86_xMatch),
- /*9059*/ uint16(x86_xSetOp), uint16(x86_JGE),
- /*9061*/ uint16(x86_xReadCb),
- /*9062*/ uint16(x86_xArgRel8),
- /*9063*/ uint16(x86_xMatch),
- /*9064*/ uint16(x86_xSetOp), uint16(x86_JLE),
- /*9066*/ uint16(x86_xReadCb),
- /*9067*/ uint16(x86_xArgRel8),
- /*9068*/ uint16(x86_xMatch),
- /*9069*/ uint16(x86_xSetOp), uint16(x86_JG),
- /*9071*/ uint16(x86_xReadCb),
- /*9072*/ uint16(x86_xArgRel8),
- /*9073*/ uint16(x86_xMatch),
- /*9074*/ uint16(x86_xCondSlashR),
- 9083, // 0
- 9089, // 1
- 9095, // 2
- 9101, // 3
- 9107, // 4
- 9113, // 5
- 9119, // 6
- 9125, // 7
- /*9083*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*9085*/ uint16(x86_xReadIb),
- /*9086*/ uint16(x86_xArgRM8),
- /*9087*/ uint16(x86_xArgImm8u),
- /*9088*/ uint16(x86_xMatch),
- /*9089*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*9091*/ uint16(x86_xReadIb),
- /*9092*/ uint16(x86_xArgRM8),
- /*9093*/ uint16(x86_xArgImm8u),
- /*9094*/ uint16(x86_xMatch),
- /*9095*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*9097*/ uint16(x86_xReadIb),
- /*9098*/ uint16(x86_xArgRM8),
- /*9099*/ uint16(x86_xArgImm8u),
- /*9100*/ uint16(x86_xMatch),
- /*9101*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*9103*/ uint16(x86_xReadIb),
- /*9104*/ uint16(x86_xArgRM8),
- /*9105*/ uint16(x86_xArgImm8u),
- /*9106*/ uint16(x86_xMatch),
- /*9107*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*9109*/ uint16(x86_xReadIb),
- /*9110*/ uint16(x86_xArgRM8),
- /*9111*/ uint16(x86_xArgImm8u),
- /*9112*/ uint16(x86_xMatch),
- /*9113*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*9115*/ uint16(x86_xReadIb),
- /*9116*/ uint16(x86_xArgRM8),
- /*9117*/ uint16(x86_xArgImm8u),
- /*9118*/ uint16(x86_xMatch),
- /*9119*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*9121*/ uint16(x86_xReadIb),
- /*9122*/ uint16(x86_xArgRM8),
- /*9123*/ uint16(x86_xArgImm8u),
- /*9124*/ uint16(x86_xMatch),
- /*9125*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*9127*/ uint16(x86_xReadIb),
- /*9128*/ uint16(x86_xArgRM8),
- /*9129*/ uint16(x86_xArgImm8u),
- /*9130*/ uint16(x86_xMatch),
- /*9131*/ uint16(x86_xCondSlashR),
- 9140, // 0
- 9169, // 1
- 9198, // 2
- 9227, // 3
- 9256, // 4
- 9285, // 5
- 9314, // 6
- 9343, // 7
- /*9140*/ uint16(x86_xCondIs64), 9143, 9159,
- /*9143*/ uint16(x86_xCondDataSize), 9147, 9153, 0,
- /*9147*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*9149*/ uint16(x86_xReadIw),
- /*9150*/ uint16(x86_xArgRM16),
- /*9151*/ uint16(x86_xArgImm16),
- /*9152*/ uint16(x86_xMatch),
- /*9153*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*9155*/ uint16(x86_xReadId),
- /*9156*/ uint16(x86_xArgRM32),
- /*9157*/ uint16(x86_xArgImm32),
- /*9158*/ uint16(x86_xMatch),
- /*9159*/ uint16(x86_xCondDataSize), 9147, 9153, 9163,
- /*9163*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*9165*/ uint16(x86_xReadId),
- /*9166*/ uint16(x86_xArgRM64),
- /*9167*/ uint16(x86_xArgImm32),
- /*9168*/ uint16(x86_xMatch),
- /*9169*/ uint16(x86_xCondIs64), 9172, 9188,
- /*9172*/ uint16(x86_xCondDataSize), 9176, 9182, 0,
- /*9176*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*9178*/ uint16(x86_xReadIw),
- /*9179*/ uint16(x86_xArgRM16),
- /*9180*/ uint16(x86_xArgImm16),
- /*9181*/ uint16(x86_xMatch),
- /*9182*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*9184*/ uint16(x86_xReadId),
- /*9185*/ uint16(x86_xArgRM32),
- /*9186*/ uint16(x86_xArgImm32),
- /*9187*/ uint16(x86_xMatch),
- /*9188*/ uint16(x86_xCondDataSize), 9176, 9182, 9192,
- /*9192*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*9194*/ uint16(x86_xReadId),
- /*9195*/ uint16(x86_xArgRM64),
- /*9196*/ uint16(x86_xArgImm32),
- /*9197*/ uint16(x86_xMatch),
- /*9198*/ uint16(x86_xCondIs64), 9201, 9217,
- /*9201*/ uint16(x86_xCondDataSize), 9205, 9211, 0,
- /*9205*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*9207*/ uint16(x86_xReadIw),
- /*9208*/ uint16(x86_xArgRM16),
- /*9209*/ uint16(x86_xArgImm16),
- /*9210*/ uint16(x86_xMatch),
- /*9211*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*9213*/ uint16(x86_xReadId),
- /*9214*/ uint16(x86_xArgRM32),
- /*9215*/ uint16(x86_xArgImm32),
- /*9216*/ uint16(x86_xMatch),
- /*9217*/ uint16(x86_xCondDataSize), 9205, 9211, 9221,
- /*9221*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*9223*/ uint16(x86_xReadId),
- /*9224*/ uint16(x86_xArgRM64),
- /*9225*/ uint16(x86_xArgImm32),
- /*9226*/ uint16(x86_xMatch),
- /*9227*/ uint16(x86_xCondIs64), 9230, 9246,
- /*9230*/ uint16(x86_xCondDataSize), 9234, 9240, 0,
- /*9234*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*9236*/ uint16(x86_xReadIw),
- /*9237*/ uint16(x86_xArgRM16),
- /*9238*/ uint16(x86_xArgImm16),
- /*9239*/ uint16(x86_xMatch),
- /*9240*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*9242*/ uint16(x86_xReadId),
- /*9243*/ uint16(x86_xArgRM32),
- /*9244*/ uint16(x86_xArgImm32),
- /*9245*/ uint16(x86_xMatch),
- /*9246*/ uint16(x86_xCondDataSize), 9234, 9240, 9250,
- /*9250*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*9252*/ uint16(x86_xReadId),
- /*9253*/ uint16(x86_xArgRM64),
- /*9254*/ uint16(x86_xArgImm32),
- /*9255*/ uint16(x86_xMatch),
- /*9256*/ uint16(x86_xCondIs64), 9259, 9275,
- /*9259*/ uint16(x86_xCondDataSize), 9263, 9269, 0,
- /*9263*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*9265*/ uint16(x86_xReadIw),
- /*9266*/ uint16(x86_xArgRM16),
- /*9267*/ uint16(x86_xArgImm16),
- /*9268*/ uint16(x86_xMatch),
- /*9269*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*9271*/ uint16(x86_xReadId),
- /*9272*/ uint16(x86_xArgRM32),
- /*9273*/ uint16(x86_xArgImm32),
- /*9274*/ uint16(x86_xMatch),
- /*9275*/ uint16(x86_xCondDataSize), 9263, 9269, 9279,
- /*9279*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*9281*/ uint16(x86_xReadId),
- /*9282*/ uint16(x86_xArgRM64),
- /*9283*/ uint16(x86_xArgImm32),
- /*9284*/ uint16(x86_xMatch),
- /*9285*/ uint16(x86_xCondIs64), 9288, 9304,
- /*9288*/ uint16(x86_xCondDataSize), 9292, 9298, 0,
- /*9292*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*9294*/ uint16(x86_xReadIw),
- /*9295*/ uint16(x86_xArgRM16),
- /*9296*/ uint16(x86_xArgImm16),
- /*9297*/ uint16(x86_xMatch),
- /*9298*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*9300*/ uint16(x86_xReadId),
- /*9301*/ uint16(x86_xArgRM32),
- /*9302*/ uint16(x86_xArgImm32),
- /*9303*/ uint16(x86_xMatch),
- /*9304*/ uint16(x86_xCondDataSize), 9292, 9298, 9308,
- /*9308*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*9310*/ uint16(x86_xReadId),
- /*9311*/ uint16(x86_xArgRM64),
- /*9312*/ uint16(x86_xArgImm32),
- /*9313*/ uint16(x86_xMatch),
- /*9314*/ uint16(x86_xCondIs64), 9317, 9333,
- /*9317*/ uint16(x86_xCondDataSize), 9321, 9327, 0,
- /*9321*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*9323*/ uint16(x86_xReadIw),
- /*9324*/ uint16(x86_xArgRM16),
- /*9325*/ uint16(x86_xArgImm16),
- /*9326*/ uint16(x86_xMatch),
- /*9327*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*9329*/ uint16(x86_xReadId),
- /*9330*/ uint16(x86_xArgRM32),
- /*9331*/ uint16(x86_xArgImm32),
- /*9332*/ uint16(x86_xMatch),
- /*9333*/ uint16(x86_xCondDataSize), 9321, 9327, 9337,
- /*9337*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*9339*/ uint16(x86_xReadId),
- /*9340*/ uint16(x86_xArgRM64),
- /*9341*/ uint16(x86_xArgImm32),
- /*9342*/ uint16(x86_xMatch),
- /*9343*/ uint16(x86_xCondIs64), 9346, 9362,
- /*9346*/ uint16(x86_xCondDataSize), 9350, 9356, 0,
- /*9350*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*9352*/ uint16(x86_xReadIw),
- /*9353*/ uint16(x86_xArgRM16),
- /*9354*/ uint16(x86_xArgImm16),
- /*9355*/ uint16(x86_xMatch),
- /*9356*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*9358*/ uint16(x86_xReadId),
- /*9359*/ uint16(x86_xArgRM32),
- /*9360*/ uint16(x86_xArgImm32),
- /*9361*/ uint16(x86_xMatch),
- /*9362*/ uint16(x86_xCondDataSize), 9350, 9356, 9366,
- /*9366*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*9368*/ uint16(x86_xReadId),
- /*9369*/ uint16(x86_xArgRM64),
- /*9370*/ uint16(x86_xArgImm32),
- /*9371*/ uint16(x86_xMatch),
- /*9372*/ uint16(x86_xCondSlashR),
- 9381, // 0
- 9410, // 1
- 9439, // 2
- 9468, // 3
- 9497, // 4
- 9526, // 5
- 9555, // 6
- 9584, // 7
- /*9381*/ uint16(x86_xCondIs64), 9384, 9400,
- /*9384*/ uint16(x86_xCondDataSize), 9388, 9394, 0,
- /*9388*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*9390*/ uint16(x86_xReadIb),
- /*9391*/ uint16(x86_xArgRM16),
- /*9392*/ uint16(x86_xArgImm8),
- /*9393*/ uint16(x86_xMatch),
- /*9394*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*9396*/ uint16(x86_xReadIb),
- /*9397*/ uint16(x86_xArgRM32),
- /*9398*/ uint16(x86_xArgImm8),
- /*9399*/ uint16(x86_xMatch),
- /*9400*/ uint16(x86_xCondDataSize), 9388, 9394, 9404,
- /*9404*/ uint16(x86_xSetOp), uint16(x86_ADD),
- /*9406*/ uint16(x86_xReadIb),
- /*9407*/ uint16(x86_xArgRM64),
- /*9408*/ uint16(x86_xArgImm8),
- /*9409*/ uint16(x86_xMatch),
- /*9410*/ uint16(x86_xCondIs64), 9413, 9429,
- /*9413*/ uint16(x86_xCondDataSize), 9417, 9423, 0,
- /*9417*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*9419*/ uint16(x86_xReadIb),
- /*9420*/ uint16(x86_xArgRM16),
- /*9421*/ uint16(x86_xArgImm8),
- /*9422*/ uint16(x86_xMatch),
- /*9423*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*9425*/ uint16(x86_xReadIb),
- /*9426*/ uint16(x86_xArgRM32),
- /*9427*/ uint16(x86_xArgImm8),
- /*9428*/ uint16(x86_xMatch),
- /*9429*/ uint16(x86_xCondDataSize), 9417, 9423, 9433,
- /*9433*/ uint16(x86_xSetOp), uint16(x86_OR),
- /*9435*/ uint16(x86_xReadIb),
- /*9436*/ uint16(x86_xArgRM64),
- /*9437*/ uint16(x86_xArgImm8),
- /*9438*/ uint16(x86_xMatch),
- /*9439*/ uint16(x86_xCondIs64), 9442, 9458,
- /*9442*/ uint16(x86_xCondDataSize), 9446, 9452, 0,
- /*9446*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*9448*/ uint16(x86_xReadIb),
- /*9449*/ uint16(x86_xArgRM16),
- /*9450*/ uint16(x86_xArgImm8),
- /*9451*/ uint16(x86_xMatch),
- /*9452*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*9454*/ uint16(x86_xReadIb),
- /*9455*/ uint16(x86_xArgRM32),
- /*9456*/ uint16(x86_xArgImm8),
- /*9457*/ uint16(x86_xMatch),
- /*9458*/ uint16(x86_xCondDataSize), 9446, 9452, 9462,
- /*9462*/ uint16(x86_xSetOp), uint16(x86_ADC),
- /*9464*/ uint16(x86_xReadIb),
- /*9465*/ uint16(x86_xArgRM64),
- /*9466*/ uint16(x86_xArgImm8),
- /*9467*/ uint16(x86_xMatch),
- /*9468*/ uint16(x86_xCondIs64), 9471, 9487,
- /*9471*/ uint16(x86_xCondDataSize), 9475, 9481, 0,
- /*9475*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*9477*/ uint16(x86_xReadIb),
- /*9478*/ uint16(x86_xArgRM16),
- /*9479*/ uint16(x86_xArgImm8),
- /*9480*/ uint16(x86_xMatch),
- /*9481*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*9483*/ uint16(x86_xReadIb),
- /*9484*/ uint16(x86_xArgRM32),
- /*9485*/ uint16(x86_xArgImm8),
- /*9486*/ uint16(x86_xMatch),
- /*9487*/ uint16(x86_xCondDataSize), 9475, 9481, 9491,
- /*9491*/ uint16(x86_xSetOp), uint16(x86_SBB),
- /*9493*/ uint16(x86_xReadIb),
- /*9494*/ uint16(x86_xArgRM64),
- /*9495*/ uint16(x86_xArgImm8),
- /*9496*/ uint16(x86_xMatch),
- /*9497*/ uint16(x86_xCondIs64), 9500, 9516,
- /*9500*/ uint16(x86_xCondDataSize), 9504, 9510, 0,
- /*9504*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*9506*/ uint16(x86_xReadIb),
- /*9507*/ uint16(x86_xArgRM16),
- /*9508*/ uint16(x86_xArgImm8),
- /*9509*/ uint16(x86_xMatch),
- /*9510*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*9512*/ uint16(x86_xReadIb),
- /*9513*/ uint16(x86_xArgRM32),
- /*9514*/ uint16(x86_xArgImm8),
- /*9515*/ uint16(x86_xMatch),
- /*9516*/ uint16(x86_xCondDataSize), 9504, 9510, 9520,
- /*9520*/ uint16(x86_xSetOp), uint16(x86_AND),
- /*9522*/ uint16(x86_xReadIb),
- /*9523*/ uint16(x86_xArgRM64),
- /*9524*/ uint16(x86_xArgImm8),
- /*9525*/ uint16(x86_xMatch),
- /*9526*/ uint16(x86_xCondIs64), 9529, 9545,
- /*9529*/ uint16(x86_xCondDataSize), 9533, 9539, 0,
- /*9533*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*9535*/ uint16(x86_xReadIb),
- /*9536*/ uint16(x86_xArgRM16),
- /*9537*/ uint16(x86_xArgImm8),
- /*9538*/ uint16(x86_xMatch),
- /*9539*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*9541*/ uint16(x86_xReadIb),
- /*9542*/ uint16(x86_xArgRM32),
- /*9543*/ uint16(x86_xArgImm8),
- /*9544*/ uint16(x86_xMatch),
- /*9545*/ uint16(x86_xCondDataSize), 9533, 9539, 9549,
- /*9549*/ uint16(x86_xSetOp), uint16(x86_SUB),
- /*9551*/ uint16(x86_xReadIb),
- /*9552*/ uint16(x86_xArgRM64),
- /*9553*/ uint16(x86_xArgImm8),
- /*9554*/ uint16(x86_xMatch),
- /*9555*/ uint16(x86_xCondIs64), 9558, 9574,
- /*9558*/ uint16(x86_xCondDataSize), 9562, 9568, 0,
- /*9562*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*9564*/ uint16(x86_xReadIb),
- /*9565*/ uint16(x86_xArgRM16),
- /*9566*/ uint16(x86_xArgImm8),
- /*9567*/ uint16(x86_xMatch),
- /*9568*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*9570*/ uint16(x86_xReadIb),
- /*9571*/ uint16(x86_xArgRM32),
- /*9572*/ uint16(x86_xArgImm8),
- /*9573*/ uint16(x86_xMatch),
- /*9574*/ uint16(x86_xCondDataSize), 9562, 9568, 9578,
- /*9578*/ uint16(x86_xSetOp), uint16(x86_XOR),
- /*9580*/ uint16(x86_xReadIb),
- /*9581*/ uint16(x86_xArgRM64),
- /*9582*/ uint16(x86_xArgImm8),
- /*9583*/ uint16(x86_xMatch),
- /*9584*/ uint16(x86_xCondIs64), 9587, 9603,
- /*9587*/ uint16(x86_xCondDataSize), 9591, 9597, 0,
- /*9591*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*9593*/ uint16(x86_xReadIb),
- /*9594*/ uint16(x86_xArgRM16),
- /*9595*/ uint16(x86_xArgImm8),
- /*9596*/ uint16(x86_xMatch),
- /*9597*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*9599*/ uint16(x86_xReadIb),
- /*9600*/ uint16(x86_xArgRM32),
- /*9601*/ uint16(x86_xArgImm8),
- /*9602*/ uint16(x86_xMatch),
- /*9603*/ uint16(x86_xCondDataSize), 9591, 9597, 9607,
- /*9607*/ uint16(x86_xSetOp), uint16(x86_CMP),
- /*9609*/ uint16(x86_xReadIb),
- /*9610*/ uint16(x86_xArgRM64),
- /*9611*/ uint16(x86_xArgImm8),
- /*9612*/ uint16(x86_xMatch),
- /*9613*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*9615*/ uint16(x86_xReadSlashR),
- /*9616*/ uint16(x86_xArgRM8),
- /*9617*/ uint16(x86_xArgR8),
- /*9618*/ uint16(x86_xMatch),
- /*9619*/ uint16(x86_xCondIs64), 9622, 9638,
- /*9622*/ uint16(x86_xCondDataSize), 9626, 9632, 0,
- /*9626*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*9628*/ uint16(x86_xReadSlashR),
- /*9629*/ uint16(x86_xArgRM16),
- /*9630*/ uint16(x86_xArgR16),
- /*9631*/ uint16(x86_xMatch),
- /*9632*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*9634*/ uint16(x86_xReadSlashR),
- /*9635*/ uint16(x86_xArgRM32),
- /*9636*/ uint16(x86_xArgR32),
- /*9637*/ uint16(x86_xMatch),
- /*9638*/ uint16(x86_xCondDataSize), 9626, 9632, 9642,
- /*9642*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*9644*/ uint16(x86_xReadSlashR),
- /*9645*/ uint16(x86_xArgRM64),
- /*9646*/ uint16(x86_xArgR64),
- /*9647*/ uint16(x86_xMatch),
- /*9648*/ uint16(x86_xSetOp), uint16(x86_XCHG),
- /*9650*/ uint16(x86_xReadSlashR),
- /*9651*/ uint16(x86_xArgRM8),
- /*9652*/ uint16(x86_xArgR8),
- /*9653*/ uint16(x86_xMatch),
- /*9654*/ uint16(x86_xCondIs64), 9657, 9673,
- /*9657*/ uint16(x86_xCondDataSize), 9661, 9667, 0,
- /*9661*/ uint16(x86_xSetOp), uint16(x86_XCHG),
- /*9663*/ uint16(x86_xReadSlashR),
- /*9664*/ uint16(x86_xArgRM16),
- /*9665*/ uint16(x86_xArgR16),
- /*9666*/ uint16(x86_xMatch),
- /*9667*/ uint16(x86_xSetOp), uint16(x86_XCHG),
- /*9669*/ uint16(x86_xReadSlashR),
- /*9670*/ uint16(x86_xArgRM32),
- /*9671*/ uint16(x86_xArgR32),
- /*9672*/ uint16(x86_xMatch),
- /*9673*/ uint16(x86_xCondDataSize), 9661, 9667, 9677,
- /*9677*/ uint16(x86_xSetOp), uint16(x86_XCHG),
- /*9679*/ uint16(x86_xReadSlashR),
- /*9680*/ uint16(x86_xArgRM64),
- /*9681*/ uint16(x86_xArgR64),
- /*9682*/ uint16(x86_xMatch),
- /*9683*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9685*/ uint16(x86_xReadSlashR),
- /*9686*/ uint16(x86_xArgRM8),
- /*9687*/ uint16(x86_xArgR8),
- /*9688*/ uint16(x86_xMatch),
- /*9689*/ uint16(x86_xCondDataSize), 9693, 9699, 9705,
- /*9693*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9695*/ uint16(x86_xReadSlashR),
- /*9696*/ uint16(x86_xArgRM16),
- /*9697*/ uint16(x86_xArgR16),
- /*9698*/ uint16(x86_xMatch),
- /*9699*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9701*/ uint16(x86_xReadSlashR),
- /*9702*/ uint16(x86_xArgRM32),
- /*9703*/ uint16(x86_xArgR32),
- /*9704*/ uint16(x86_xMatch),
- /*9705*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9707*/ uint16(x86_xReadSlashR),
- /*9708*/ uint16(x86_xArgRM64),
- /*9709*/ uint16(x86_xArgR64),
- /*9710*/ uint16(x86_xMatch),
- /*9711*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9713*/ uint16(x86_xReadSlashR),
- /*9714*/ uint16(x86_xArgR8),
- /*9715*/ uint16(x86_xArgRM8),
- /*9716*/ uint16(x86_xMatch),
- /*9717*/ uint16(x86_xCondDataSize), 9721, 9727, 9733,
- /*9721*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9723*/ uint16(x86_xReadSlashR),
- /*9724*/ uint16(x86_xArgR16),
- /*9725*/ uint16(x86_xArgRM16),
- /*9726*/ uint16(x86_xMatch),
- /*9727*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9729*/ uint16(x86_xReadSlashR),
- /*9730*/ uint16(x86_xArgR32),
- /*9731*/ uint16(x86_xArgRM32),
- /*9732*/ uint16(x86_xMatch),
- /*9733*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9735*/ uint16(x86_xReadSlashR),
- /*9736*/ uint16(x86_xArgR64),
- /*9737*/ uint16(x86_xArgRM64),
- /*9738*/ uint16(x86_xMatch),
- /*9739*/ uint16(x86_xCondIs64), 9742, 9758,
- /*9742*/ uint16(x86_xCondDataSize), 9746, 9752, 0,
- /*9746*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9748*/ uint16(x86_xReadSlashR),
- /*9749*/ uint16(x86_xArgRM16),
- /*9750*/ uint16(x86_xArgSreg),
- /*9751*/ uint16(x86_xMatch),
- /*9752*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9754*/ uint16(x86_xReadSlashR),
- /*9755*/ uint16(x86_xArgR32M16),
- /*9756*/ uint16(x86_xArgSreg),
- /*9757*/ uint16(x86_xMatch),
- /*9758*/ uint16(x86_xCondDataSize), 9746, 9752, 9762,
- /*9762*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9764*/ uint16(x86_xReadSlashR),
- /*9765*/ uint16(x86_xArgR64M16),
- /*9766*/ uint16(x86_xArgSreg),
- /*9767*/ uint16(x86_xMatch),
- /*9768*/ uint16(x86_xCondIs64), 9771, 9787,
- /*9771*/ uint16(x86_xCondDataSize), 9775, 9781, 0,
- /*9775*/ uint16(x86_xSetOp), uint16(x86_LEA),
- /*9777*/ uint16(x86_xReadSlashR),
- /*9778*/ uint16(x86_xArgR16),
- /*9779*/ uint16(x86_xArgM),
- /*9780*/ uint16(x86_xMatch),
- /*9781*/ uint16(x86_xSetOp), uint16(x86_LEA),
- /*9783*/ uint16(x86_xReadSlashR),
- /*9784*/ uint16(x86_xArgR32),
- /*9785*/ uint16(x86_xArgM),
- /*9786*/ uint16(x86_xMatch),
- /*9787*/ uint16(x86_xCondDataSize), 9775, 9781, 9791,
- /*9791*/ uint16(x86_xSetOp), uint16(x86_LEA),
- /*9793*/ uint16(x86_xReadSlashR),
- /*9794*/ uint16(x86_xArgR64),
- /*9795*/ uint16(x86_xArgM),
- /*9796*/ uint16(x86_xMatch),
- /*9797*/ uint16(x86_xCondIs64), 9800, 9816,
- /*9800*/ uint16(x86_xCondDataSize), 9804, 9810, 0,
- /*9804*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9806*/ uint16(x86_xReadSlashR),
- /*9807*/ uint16(x86_xArgSreg),
- /*9808*/ uint16(x86_xArgRM16),
- /*9809*/ uint16(x86_xMatch),
- /*9810*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9812*/ uint16(x86_xReadSlashR),
- /*9813*/ uint16(x86_xArgSreg),
- /*9814*/ uint16(x86_xArgR32M16),
- /*9815*/ uint16(x86_xMatch),
- /*9816*/ uint16(x86_xCondDataSize), 9804, 9810, 9820,
- /*9820*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*9822*/ uint16(x86_xReadSlashR),
- /*9823*/ uint16(x86_xArgSreg),
- /*9824*/ uint16(x86_xArgR64M16),
- /*9825*/ uint16(x86_xMatch),
- /*9826*/ uint16(x86_xCondSlashR),
- 9835, // 0
- 0, // 1
- 0, // 2
- 0, // 3
- 0, // 4
- 0, // 5
- 0, // 6
- 0, // 7
- /*9835*/ uint16(x86_xCondIs64), 9838, 9850,
- /*9838*/ uint16(x86_xCondDataSize), 9842, 9846, 0,
- /*9842*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*9844*/ uint16(x86_xArgRM16),
- /*9845*/ uint16(x86_xMatch),
- /*9846*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*9848*/ uint16(x86_xArgRM32),
- /*9849*/ uint16(x86_xMatch),
- /*9850*/ uint16(x86_xCondDataSize), 9842, 9854, 9858,
- /*9854*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*9856*/ uint16(x86_xArgRM64),
- /*9857*/ uint16(x86_xMatch),
- /*9858*/ uint16(x86_xSetOp), uint16(x86_POP),
- /*9860*/ uint16(x86_xArgRM64),
- /*9861*/ uint16(x86_xMatch),
- /*9862*/ uint16(x86_xCondIs64), 9865, 9879,
- /*9865*/ uint16(x86_xCondDataSize), 9869, 9874, 0,
- /*9869*/ uint16(x86_xSetOp), uint16(x86_XCHG),
- /*9871*/ uint16(x86_xArgR16op),
- /*9872*/ uint16(x86_xArgAX),
- /*9873*/ uint16(x86_xMatch),
- /*9874*/ uint16(x86_xSetOp), uint16(x86_XCHG),
- /*9876*/ uint16(x86_xArgR32op),
- /*9877*/ uint16(x86_xArgEAX),
- /*9878*/ uint16(x86_xMatch),
- /*9879*/ uint16(x86_xCondDataSize), 9869, 9874, 9883,
- /*9883*/ uint16(x86_xSetOp), uint16(x86_XCHG),
- /*9885*/ uint16(x86_xArgR64op),
- /*9886*/ uint16(x86_xArgRAX),
- /*9887*/ uint16(x86_xMatch),
- /*9888*/ uint16(x86_xCondIs64), 9891, 9901,
- /*9891*/ uint16(x86_xCondDataSize), 9895, 9898, 0,
- /*9895*/ uint16(x86_xSetOp), uint16(x86_CBW),
- /*9897*/ uint16(x86_xMatch),
- /*9898*/ uint16(x86_xSetOp), uint16(x86_CWDE),
- /*9900*/ uint16(x86_xMatch),
- /*9901*/ uint16(x86_xCondDataSize), 9895, 9898, 9905,
- /*9905*/ uint16(x86_xSetOp), uint16(x86_CDQE),
- /*9907*/ uint16(x86_xMatch),
- /*9908*/ uint16(x86_xCondIs64), 9911, 9921,
- /*9911*/ uint16(x86_xCondDataSize), 9915, 9918, 0,
- /*9915*/ uint16(x86_xSetOp), uint16(x86_CWD),
- /*9917*/ uint16(x86_xMatch),
- /*9918*/ uint16(x86_xSetOp), uint16(x86_CDQ),
- /*9920*/ uint16(x86_xMatch),
- /*9921*/ uint16(x86_xCondDataSize), 9915, 9918, 9925,
- /*9925*/ uint16(x86_xSetOp), uint16(x86_CQO),
- /*9927*/ uint16(x86_xMatch),
- /*9928*/ uint16(x86_xCondIs64), 9931, 0,
- /*9931*/ uint16(x86_xCondDataSize), 9935, 9940, 0,
- /*9935*/ uint16(x86_xSetOp), uint16(x86_LCALL),
- /*9937*/ uint16(x86_xReadCd),
- /*9938*/ uint16(x86_xArgPtr16colon16),
- /*9939*/ uint16(x86_xMatch),
- /*9940*/ uint16(x86_xSetOp), uint16(x86_LCALL),
- /*9942*/ uint16(x86_xReadCp),
- /*9943*/ uint16(x86_xArgPtr16colon32),
- /*9944*/ uint16(x86_xMatch),
- /*9945*/ uint16(x86_xSetOp), uint16(x86_FWAIT),
- /*9947*/ uint16(x86_xMatch),
- /*9948*/ uint16(x86_xCondIs64), 9951, 9961,
- /*9951*/ uint16(x86_xCondDataSize), 9955, 9958, 0,
- /*9955*/ uint16(x86_xSetOp), uint16(x86_PUSHF),
- /*9957*/ uint16(x86_xMatch),
- /*9958*/ uint16(x86_xSetOp), uint16(x86_PUSHFD),
- /*9960*/ uint16(x86_xMatch),
- /*9961*/ uint16(x86_xCondDataSize), 9955, 9965, 9968,
- /*9965*/ uint16(x86_xSetOp), uint16(x86_PUSHFQ),
- /*9967*/ uint16(x86_xMatch),
- /*9968*/ uint16(x86_xSetOp), uint16(x86_PUSHFQ),
- /*9970*/ uint16(x86_xMatch),
- /*9971*/ uint16(x86_xCondIs64), 9974, 9984,
- /*9974*/ uint16(x86_xCondDataSize), 9978, 9981, 0,
- /*9978*/ uint16(x86_xSetOp), uint16(x86_POPF),
- /*9980*/ uint16(x86_xMatch),
- /*9981*/ uint16(x86_xSetOp), uint16(x86_POPFD),
- /*9983*/ uint16(x86_xMatch),
- /*9984*/ uint16(x86_xCondDataSize), 9978, 9988, 9991,
- /*9988*/ uint16(x86_xSetOp), uint16(x86_POPFQ),
- /*9990*/ uint16(x86_xMatch),
- /*9991*/ uint16(x86_xSetOp), uint16(x86_POPFQ),
- /*9993*/ uint16(x86_xMatch),
- /*9994*/ uint16(x86_xSetOp), uint16(x86_SAHF),
- /*9996*/ uint16(x86_xMatch),
- /*9997*/ uint16(x86_xSetOp), uint16(x86_LAHF),
- /*9999*/ uint16(x86_xMatch),
- /*10000*/ uint16(x86_xCondIs64), 10003, 10009,
- /*10003*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10005*/ uint16(x86_xReadCm),
- /*10006*/ uint16(x86_xArgAL),
- /*10007*/ uint16(x86_xArgMoffs8),
- /*10008*/ uint16(x86_xMatch),
- /*10009*/ uint16(x86_xCondDataSize), 10003, 10003, 10013,
- /*10013*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10015*/ uint16(x86_xReadCm),
- /*10016*/ uint16(x86_xArgAL),
- /*10017*/ uint16(x86_xArgMoffs8),
- /*10018*/ uint16(x86_xMatch),
- /*10019*/ uint16(x86_xCondDataSize), 10023, 10029, 10035,
- /*10023*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10025*/ uint16(x86_xReadCm),
- /*10026*/ uint16(x86_xArgAX),
- /*10027*/ uint16(x86_xArgMoffs16),
- /*10028*/ uint16(x86_xMatch),
- /*10029*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10031*/ uint16(x86_xReadCm),
- /*10032*/ uint16(x86_xArgEAX),
- /*10033*/ uint16(x86_xArgMoffs32),
- /*10034*/ uint16(x86_xMatch),
- /*10035*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10037*/ uint16(x86_xReadCm),
- /*10038*/ uint16(x86_xArgRAX),
- /*10039*/ uint16(x86_xArgMoffs64),
- /*10040*/ uint16(x86_xMatch),
- /*10041*/ uint16(x86_xCondIs64), 10044, 10050,
- /*10044*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10046*/ uint16(x86_xReadCm),
- /*10047*/ uint16(x86_xArgMoffs8),
- /*10048*/ uint16(x86_xArgAL),
- /*10049*/ uint16(x86_xMatch),
- /*10050*/ uint16(x86_xCondDataSize), 10044, 10044, 10054,
- /*10054*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10056*/ uint16(x86_xReadCm),
- /*10057*/ uint16(x86_xArgMoffs8),
- /*10058*/ uint16(x86_xArgAL),
- /*10059*/ uint16(x86_xMatch),
- /*10060*/ uint16(x86_xCondDataSize), 10064, 10070, 10076,
- /*10064*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10066*/ uint16(x86_xReadCm),
- /*10067*/ uint16(x86_xArgMoffs16),
- /*10068*/ uint16(x86_xArgAX),
- /*10069*/ uint16(x86_xMatch),
- /*10070*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10072*/ uint16(x86_xReadCm),
- /*10073*/ uint16(x86_xArgMoffs32),
- /*10074*/ uint16(x86_xArgEAX),
- /*10075*/ uint16(x86_xMatch),
- /*10076*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10078*/ uint16(x86_xReadCm),
- /*10079*/ uint16(x86_xArgMoffs64),
- /*10080*/ uint16(x86_xArgRAX),
- /*10081*/ uint16(x86_xMatch),
- /*10082*/ uint16(x86_xSetOp), uint16(x86_MOVSB),
- /*10084*/ uint16(x86_xMatch),
- /*10085*/ uint16(x86_xCondIs64), 10088, 10098,
- /*10088*/ uint16(x86_xCondDataSize), 10092, 10095, 0,
- /*10092*/ uint16(x86_xSetOp), uint16(x86_MOVSW),
- /*10094*/ uint16(x86_xMatch),
- /*10095*/ uint16(x86_xSetOp), uint16(x86_MOVSD),
- /*10097*/ uint16(x86_xMatch),
- /*10098*/ uint16(x86_xCondDataSize), 10092, 10095, 10102,
- /*10102*/ uint16(x86_xSetOp), uint16(x86_MOVSQ),
- /*10104*/ uint16(x86_xMatch),
- /*10105*/ uint16(x86_xSetOp), uint16(x86_CMPSB),
- /*10107*/ uint16(x86_xMatch),
- /*10108*/ uint16(x86_xCondIs64), 10111, 10121,
- /*10111*/ uint16(x86_xCondDataSize), 10115, 10118, 0,
- /*10115*/ uint16(x86_xSetOp), uint16(x86_CMPSW),
- /*10117*/ uint16(x86_xMatch),
- /*10118*/ uint16(x86_xSetOp), uint16(x86_CMPSD),
- /*10120*/ uint16(x86_xMatch),
- /*10121*/ uint16(x86_xCondDataSize), 10115, 10118, 10125,
- /*10125*/ uint16(x86_xSetOp), uint16(x86_CMPSQ),
- /*10127*/ uint16(x86_xMatch),
- /*10128*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*10130*/ uint16(x86_xReadIb),
- /*10131*/ uint16(x86_xArgAL),
- /*10132*/ uint16(x86_xArgImm8u),
- /*10133*/ uint16(x86_xMatch),
- /*10134*/ uint16(x86_xCondIs64), 10137, 10153,
- /*10137*/ uint16(x86_xCondDataSize), 10141, 10147, 0,
- /*10141*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*10143*/ uint16(x86_xReadIw),
- /*10144*/ uint16(x86_xArgAX),
- /*10145*/ uint16(x86_xArgImm16),
- /*10146*/ uint16(x86_xMatch),
- /*10147*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*10149*/ uint16(x86_xReadId),
- /*10150*/ uint16(x86_xArgEAX),
- /*10151*/ uint16(x86_xArgImm32),
- /*10152*/ uint16(x86_xMatch),
- /*10153*/ uint16(x86_xCondDataSize), 10141, 10147, 10157,
- /*10157*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*10159*/ uint16(x86_xReadId),
- /*10160*/ uint16(x86_xArgRAX),
- /*10161*/ uint16(x86_xArgImm32),
- /*10162*/ uint16(x86_xMatch),
- /*10163*/ uint16(x86_xSetOp), uint16(x86_STOSB),
- /*10165*/ uint16(x86_xMatch),
- /*10166*/ uint16(x86_xCondIs64), 10169, 10179,
- /*10169*/ uint16(x86_xCondDataSize), 10173, 10176, 0,
- /*10173*/ uint16(x86_xSetOp), uint16(x86_STOSW),
- /*10175*/ uint16(x86_xMatch),
- /*10176*/ uint16(x86_xSetOp), uint16(x86_STOSD),
- /*10178*/ uint16(x86_xMatch),
- /*10179*/ uint16(x86_xCondDataSize), 10173, 10176, 10183,
- /*10183*/ uint16(x86_xSetOp), uint16(x86_STOSQ),
- /*10185*/ uint16(x86_xMatch),
- /*10186*/ uint16(x86_xSetOp), uint16(x86_LODSB),
- /*10188*/ uint16(x86_xMatch),
- /*10189*/ uint16(x86_xCondIs64), 10192, 10202,
- /*10192*/ uint16(x86_xCondDataSize), 10196, 10199, 0,
- /*10196*/ uint16(x86_xSetOp), uint16(x86_LODSW),
- /*10198*/ uint16(x86_xMatch),
- /*10199*/ uint16(x86_xSetOp), uint16(x86_LODSD),
- /*10201*/ uint16(x86_xMatch),
- /*10202*/ uint16(x86_xCondDataSize), 10196, 10199, 10206,
- /*10206*/ uint16(x86_xSetOp), uint16(x86_LODSQ),
- /*10208*/ uint16(x86_xMatch),
- /*10209*/ uint16(x86_xSetOp), uint16(x86_SCASB),
- /*10211*/ uint16(x86_xMatch),
- /*10212*/ uint16(x86_xCondIs64), 10215, 10225,
- /*10215*/ uint16(x86_xCondDataSize), 10219, 10222, 0,
- /*10219*/ uint16(x86_xSetOp), uint16(x86_SCASW),
- /*10221*/ uint16(x86_xMatch),
- /*10222*/ uint16(x86_xSetOp), uint16(x86_SCASD),
- /*10224*/ uint16(x86_xMatch),
- /*10225*/ uint16(x86_xCondDataSize), 10219, 10222, 10229,
- /*10229*/ uint16(x86_xSetOp), uint16(x86_SCASQ),
- /*10231*/ uint16(x86_xMatch),
- /*10232*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10234*/ uint16(x86_xReadIb),
- /*10235*/ uint16(x86_xArgR8op),
- /*10236*/ uint16(x86_xArgImm8u),
- /*10237*/ uint16(x86_xMatch),
- /*10238*/ uint16(x86_xCondIs64), 10241, 10257,
- /*10241*/ uint16(x86_xCondDataSize), 10245, 10251, 0,
- /*10245*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10247*/ uint16(x86_xReadIw),
- /*10248*/ uint16(x86_xArgR16op),
- /*10249*/ uint16(x86_xArgImm16),
- /*10250*/ uint16(x86_xMatch),
- /*10251*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10253*/ uint16(x86_xReadId),
- /*10254*/ uint16(x86_xArgR32op),
- /*10255*/ uint16(x86_xArgImm32),
- /*10256*/ uint16(x86_xMatch),
- /*10257*/ uint16(x86_xCondDataSize), 10245, 10251, 10261,
- /*10261*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10263*/ uint16(x86_xReadIo),
- /*10264*/ uint16(x86_xArgR64op),
- /*10265*/ uint16(x86_xArgImm64),
- /*10266*/ uint16(x86_xMatch),
- /*10267*/ uint16(x86_xCondSlashR),
- 10276, // 0
- 10282, // 1
- 10288, // 2
- 10294, // 3
- 10300, // 4
- 10306, // 5
- 0, // 6
- 10312, // 7
- /*10276*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*10278*/ uint16(x86_xReadIb),
- /*10279*/ uint16(x86_xArgRM8),
- /*10280*/ uint16(x86_xArgImm8u),
- /*10281*/ uint16(x86_xMatch),
- /*10282*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*10284*/ uint16(x86_xReadIb),
- /*10285*/ uint16(x86_xArgRM8),
- /*10286*/ uint16(x86_xArgImm8u),
- /*10287*/ uint16(x86_xMatch),
- /*10288*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*10290*/ uint16(x86_xReadIb),
- /*10291*/ uint16(x86_xArgRM8),
- /*10292*/ uint16(x86_xArgImm8u),
- /*10293*/ uint16(x86_xMatch),
- /*10294*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*10296*/ uint16(x86_xReadIb),
- /*10297*/ uint16(x86_xArgRM8),
- /*10298*/ uint16(x86_xArgImm8u),
- /*10299*/ uint16(x86_xMatch),
- /*10300*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*10302*/ uint16(x86_xReadIb),
- /*10303*/ uint16(x86_xArgRM8),
- /*10304*/ uint16(x86_xArgImm8u),
- /*10305*/ uint16(x86_xMatch),
- /*10306*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*10308*/ uint16(x86_xReadIb),
- /*10309*/ uint16(x86_xArgRM8),
- /*10310*/ uint16(x86_xArgImm8u),
- /*10311*/ uint16(x86_xMatch),
- /*10312*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*10314*/ uint16(x86_xReadIb),
- /*10315*/ uint16(x86_xArgRM8),
- /*10316*/ uint16(x86_xArgImm8u),
- /*10317*/ uint16(x86_xMatch),
- /*10318*/ uint16(x86_xCondSlashR),
- 10327, // 0
- 10349, // 1
- 10371, // 2
- 10400, // 3
- 10429, // 4
- 10458, // 5
- 0, // 6
- 10487, // 7
- /*10327*/ uint16(x86_xCondDataSize), 10331, 10337, 10343,
- /*10331*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*10333*/ uint16(x86_xReadIb),
- /*10334*/ uint16(x86_xArgRM16),
- /*10335*/ uint16(x86_xArgImm8u),
- /*10336*/ uint16(x86_xMatch),
- /*10337*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*10339*/ uint16(x86_xReadIb),
- /*10340*/ uint16(x86_xArgRM32),
- /*10341*/ uint16(x86_xArgImm8u),
- /*10342*/ uint16(x86_xMatch),
- /*10343*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*10345*/ uint16(x86_xReadIb),
- /*10346*/ uint16(x86_xArgRM64),
- /*10347*/ uint16(x86_xArgImm8u),
- /*10348*/ uint16(x86_xMatch),
- /*10349*/ uint16(x86_xCondDataSize), 10353, 10359, 10365,
- /*10353*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*10355*/ uint16(x86_xReadIb),
- /*10356*/ uint16(x86_xArgRM16),
- /*10357*/ uint16(x86_xArgImm8u),
- /*10358*/ uint16(x86_xMatch),
- /*10359*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*10361*/ uint16(x86_xReadIb),
- /*10362*/ uint16(x86_xArgRM32),
- /*10363*/ uint16(x86_xArgImm8u),
- /*10364*/ uint16(x86_xMatch),
- /*10365*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*10367*/ uint16(x86_xReadIb),
- /*10368*/ uint16(x86_xArgRM64),
- /*10369*/ uint16(x86_xArgImm8u),
- /*10370*/ uint16(x86_xMatch),
- /*10371*/ uint16(x86_xCondIs64), 10374, 10390,
- /*10374*/ uint16(x86_xCondDataSize), 10378, 10384, 0,
- /*10378*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*10380*/ uint16(x86_xReadIb),
- /*10381*/ uint16(x86_xArgRM16),
- /*10382*/ uint16(x86_xArgImm8u),
- /*10383*/ uint16(x86_xMatch),
- /*10384*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*10386*/ uint16(x86_xReadIb),
- /*10387*/ uint16(x86_xArgRM32),
- /*10388*/ uint16(x86_xArgImm8u),
- /*10389*/ uint16(x86_xMatch),
- /*10390*/ uint16(x86_xCondDataSize), 10378, 10384, 10394,
- /*10394*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*10396*/ uint16(x86_xReadIb),
- /*10397*/ uint16(x86_xArgRM64),
- /*10398*/ uint16(x86_xArgImm8u),
- /*10399*/ uint16(x86_xMatch),
- /*10400*/ uint16(x86_xCondIs64), 10403, 10419,
- /*10403*/ uint16(x86_xCondDataSize), 10407, 10413, 0,
- /*10407*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*10409*/ uint16(x86_xReadIb),
- /*10410*/ uint16(x86_xArgRM16),
- /*10411*/ uint16(x86_xArgImm8u),
- /*10412*/ uint16(x86_xMatch),
- /*10413*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*10415*/ uint16(x86_xReadIb),
- /*10416*/ uint16(x86_xArgRM32),
- /*10417*/ uint16(x86_xArgImm8u),
- /*10418*/ uint16(x86_xMatch),
- /*10419*/ uint16(x86_xCondDataSize), 10407, 10413, 10423,
- /*10423*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*10425*/ uint16(x86_xReadIb),
- /*10426*/ uint16(x86_xArgRM64),
- /*10427*/ uint16(x86_xArgImm8u),
- /*10428*/ uint16(x86_xMatch),
- /*10429*/ uint16(x86_xCondIs64), 10432, 10448,
- /*10432*/ uint16(x86_xCondDataSize), 10436, 10442, 0,
- /*10436*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*10438*/ uint16(x86_xReadIb),
- /*10439*/ uint16(x86_xArgRM16),
- /*10440*/ uint16(x86_xArgImm8u),
- /*10441*/ uint16(x86_xMatch),
- /*10442*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*10444*/ uint16(x86_xReadIb),
- /*10445*/ uint16(x86_xArgRM32),
- /*10446*/ uint16(x86_xArgImm8u),
- /*10447*/ uint16(x86_xMatch),
- /*10448*/ uint16(x86_xCondDataSize), 10436, 10442, 10452,
- /*10452*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*10454*/ uint16(x86_xReadIb),
- /*10455*/ uint16(x86_xArgRM64),
- /*10456*/ uint16(x86_xArgImm8u),
- /*10457*/ uint16(x86_xMatch),
- /*10458*/ uint16(x86_xCondIs64), 10461, 10477,
- /*10461*/ uint16(x86_xCondDataSize), 10465, 10471, 0,
- /*10465*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*10467*/ uint16(x86_xReadIb),
- /*10468*/ uint16(x86_xArgRM16),
- /*10469*/ uint16(x86_xArgImm8u),
- /*10470*/ uint16(x86_xMatch),
- /*10471*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*10473*/ uint16(x86_xReadIb),
- /*10474*/ uint16(x86_xArgRM32),
- /*10475*/ uint16(x86_xArgImm8u),
- /*10476*/ uint16(x86_xMatch),
- /*10477*/ uint16(x86_xCondDataSize), 10465, 10471, 10481,
- /*10481*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*10483*/ uint16(x86_xReadIb),
- /*10484*/ uint16(x86_xArgRM64),
- /*10485*/ uint16(x86_xArgImm8u),
- /*10486*/ uint16(x86_xMatch),
- /*10487*/ uint16(x86_xCondIs64), 10490, 10506,
- /*10490*/ uint16(x86_xCondDataSize), 10494, 10500, 0,
- /*10494*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*10496*/ uint16(x86_xReadIb),
- /*10497*/ uint16(x86_xArgRM16),
- /*10498*/ uint16(x86_xArgImm8u),
- /*10499*/ uint16(x86_xMatch),
- /*10500*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*10502*/ uint16(x86_xReadIb),
- /*10503*/ uint16(x86_xArgRM32),
- /*10504*/ uint16(x86_xArgImm8u),
- /*10505*/ uint16(x86_xMatch),
- /*10506*/ uint16(x86_xCondDataSize), 10494, 10500, 10510,
- /*10510*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*10512*/ uint16(x86_xReadIb),
- /*10513*/ uint16(x86_xArgRM64),
- /*10514*/ uint16(x86_xArgImm8u),
- /*10515*/ uint16(x86_xMatch),
- /*10516*/ uint16(x86_xSetOp), uint16(x86_RET),
- /*10518*/ uint16(x86_xReadIw),
- /*10519*/ uint16(x86_xArgImm16u),
- /*10520*/ uint16(x86_xMatch),
- /*10521*/ uint16(x86_xSetOp), uint16(x86_RET),
- /*10523*/ uint16(x86_xMatch),
- /*10524*/ uint16(x86_xCondIs64), 10527, 0,
- /*10527*/ uint16(x86_xCondDataSize), 10531, 10537, 0,
- /*10531*/ uint16(x86_xSetOp), uint16(x86_LES),
- /*10533*/ uint16(x86_xReadSlashR),
- /*10534*/ uint16(x86_xArgR16),
- /*10535*/ uint16(x86_xArgM16colon16),
- /*10536*/ uint16(x86_xMatch),
- /*10537*/ uint16(x86_xSetOp), uint16(x86_LES),
- /*10539*/ uint16(x86_xReadSlashR),
- /*10540*/ uint16(x86_xArgR32),
- /*10541*/ uint16(x86_xArgM16colon32),
- /*10542*/ uint16(x86_xMatch),
- /*10543*/ uint16(x86_xCondIs64), 10546, 0,
- /*10546*/ uint16(x86_xCondDataSize), 10550, 10556, 0,
- /*10550*/ uint16(x86_xSetOp), uint16(x86_LDS),
- /*10552*/ uint16(x86_xReadSlashR),
- /*10553*/ uint16(x86_xArgR16),
- /*10554*/ uint16(x86_xArgM16colon16),
- /*10555*/ uint16(x86_xMatch),
- /*10556*/ uint16(x86_xSetOp), uint16(x86_LDS),
- /*10558*/ uint16(x86_xReadSlashR),
- /*10559*/ uint16(x86_xArgR32),
- /*10560*/ uint16(x86_xArgM16colon32),
- /*10561*/ uint16(x86_xMatch),
- /*10562*/ uint16(x86_xCondByte), 1,
- 0xF8, 10581,
- /*10566*/ uint16(x86_xCondSlashR),
- 10575, // 0
- 0, // 1
- 0, // 2
- 0, // 3
- 0, // 4
- 0, // 5
- 0, // 6
- 0, // 7
- /*10575*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10577*/ uint16(x86_xReadIb),
- /*10578*/ uint16(x86_xArgRM8),
- /*10579*/ uint16(x86_xArgImm8u),
- /*10580*/ uint16(x86_xMatch),
- /*10581*/ uint16(x86_xSetOp), uint16(x86_XABORT),
- /*10583*/ uint16(x86_xReadIb),
- /*10584*/ uint16(x86_xArgImm8u),
- /*10585*/ uint16(x86_xMatch),
- /*10586*/ uint16(x86_xCondByte), 1,
- 0xF8, 10628,
- /*10590*/ uint16(x86_xCondSlashR),
- 10599, // 0
- 0, // 1
- 0, // 2
- 0, // 3
- 0, // 4
- 0, // 5
- 0, // 6
- 0, // 7
- /*10599*/ uint16(x86_xCondIs64), 10602, 10618,
- /*10602*/ uint16(x86_xCondDataSize), 10606, 10612, 0,
- /*10606*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10608*/ uint16(x86_xReadIw),
- /*10609*/ uint16(x86_xArgRM16),
- /*10610*/ uint16(x86_xArgImm16),
- /*10611*/ uint16(x86_xMatch),
- /*10612*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10614*/ uint16(x86_xReadId),
- /*10615*/ uint16(x86_xArgRM32),
- /*10616*/ uint16(x86_xArgImm32),
- /*10617*/ uint16(x86_xMatch),
- /*10618*/ uint16(x86_xCondDataSize), 10606, 10612, 10622,
- /*10622*/ uint16(x86_xSetOp), uint16(x86_MOV),
- /*10624*/ uint16(x86_xReadId),
- /*10625*/ uint16(x86_xArgRM64),
- /*10626*/ uint16(x86_xArgImm32),
- /*10627*/ uint16(x86_xMatch),
- /*10628*/ uint16(x86_xCondDataSize), 10632, 10637, 10642,
- /*10632*/ uint16(x86_xSetOp), uint16(x86_XBEGIN),
- /*10634*/ uint16(x86_xReadCw),
- /*10635*/ uint16(x86_xArgRel16),
- /*10636*/ uint16(x86_xMatch),
- /*10637*/ uint16(x86_xSetOp), uint16(x86_XBEGIN),
- /*10639*/ uint16(x86_xReadCd),
- /*10640*/ uint16(x86_xArgRel32),
- /*10641*/ uint16(x86_xMatch),
- /*10642*/ uint16(x86_xSetOp), uint16(x86_XBEGIN),
- /*10644*/ uint16(x86_xReadCd),
- /*10645*/ uint16(x86_xArgRel32),
- /*10646*/ uint16(x86_xMatch),
- /*10647*/ uint16(x86_xSetOp), uint16(x86_ENTER),
- /*10649*/ uint16(x86_xReadIw),
- /*10650*/ uint16(x86_xReadIb),
- /*10651*/ uint16(x86_xArgImm16u),
- /*10652*/ uint16(x86_xArgImm8u),
- /*10653*/ uint16(x86_xMatch),
- /*10654*/ uint16(x86_xCondIs64), 10657, 10667,
- /*10657*/ uint16(x86_xCondDataSize), 10661, 10664, 0,
- /*10661*/ uint16(x86_xSetOp), uint16(x86_LEAVE),
- /*10663*/ uint16(x86_xMatch),
- /*10664*/ uint16(x86_xSetOp), uint16(x86_LEAVE),
- /*10666*/ uint16(x86_xMatch),
- /*10667*/ uint16(x86_xCondDataSize), 10661, 10671, 10674,
- /*10671*/ uint16(x86_xSetOp), uint16(x86_LEAVE),
- /*10673*/ uint16(x86_xMatch),
- /*10674*/ uint16(x86_xSetOp), uint16(x86_LEAVE),
- /*10676*/ uint16(x86_xMatch),
- /*10677*/ uint16(x86_xSetOp), uint16(x86_LRET),
- /*10679*/ uint16(x86_xReadIw),
- /*10680*/ uint16(x86_xArgImm16u),
- /*10681*/ uint16(x86_xMatch),
- /*10682*/ uint16(x86_xSetOp), uint16(x86_LRET),
- /*10684*/ uint16(x86_xMatch),
- /*10685*/ uint16(x86_xSetOp), uint16(x86_INT),
- /*10687*/ uint16(x86_xArg3),
- /*10688*/ uint16(x86_xMatch),
- /*10689*/ uint16(x86_xSetOp), uint16(x86_INT),
- /*10691*/ uint16(x86_xReadIb),
- /*10692*/ uint16(x86_xArgImm8u),
- /*10693*/ uint16(x86_xMatch),
- /*10694*/ uint16(x86_xCondIs64), 10697, 0,
- /*10697*/ uint16(x86_xSetOp), uint16(x86_INTO),
- /*10699*/ uint16(x86_xMatch),
- /*10700*/ uint16(x86_xCondIs64), 10703, 10713,
- /*10703*/ uint16(x86_xCondDataSize), 10707, 10710, 0,
- /*10707*/ uint16(x86_xSetOp), uint16(x86_IRET),
- /*10709*/ uint16(x86_xMatch),
- /*10710*/ uint16(x86_xSetOp), uint16(x86_IRETD),
- /*10712*/ uint16(x86_xMatch),
- /*10713*/ uint16(x86_xCondDataSize), 10707, 10710, 10717,
- /*10717*/ uint16(x86_xSetOp), uint16(x86_IRETQ),
- /*10719*/ uint16(x86_xMatch),
- /*10720*/ uint16(x86_xCondSlashR),
- 10729, // 0
- 10734, // 1
- 10739, // 2
- 10744, // 3
- 10749, // 4
- 10754, // 5
- 0, // 6
- 10759, // 7
- /*10729*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*10731*/ uint16(x86_xArgRM8),
- /*10732*/ uint16(x86_xArg1),
- /*10733*/ uint16(x86_xMatch),
- /*10734*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*10736*/ uint16(x86_xArgRM8),
- /*10737*/ uint16(x86_xArg1),
- /*10738*/ uint16(x86_xMatch),
- /*10739*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*10741*/ uint16(x86_xArgRM8),
- /*10742*/ uint16(x86_xArg1),
- /*10743*/ uint16(x86_xMatch),
- /*10744*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*10746*/ uint16(x86_xArgRM8),
- /*10747*/ uint16(x86_xArg1),
- /*10748*/ uint16(x86_xMatch),
- /*10749*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*10751*/ uint16(x86_xArgRM8),
- /*10752*/ uint16(x86_xArg1),
- /*10753*/ uint16(x86_xMatch),
- /*10754*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*10756*/ uint16(x86_xArgRM8),
- /*10757*/ uint16(x86_xArg1),
- /*10758*/ uint16(x86_xMatch),
- /*10759*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*10761*/ uint16(x86_xArgRM8),
- /*10762*/ uint16(x86_xArg1),
- /*10763*/ uint16(x86_xMatch),
- /*10764*/ uint16(x86_xCondSlashR),
- 10773, // 0
- 10799, // 1
- 10825, // 2
- 10851, // 3
- 10877, // 4
- 10903, // 5
- 0, // 6
- 10929, // 7
- /*10773*/ uint16(x86_xCondIs64), 10776, 10790,
- /*10776*/ uint16(x86_xCondDataSize), 10780, 10785, 0,
- /*10780*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*10782*/ uint16(x86_xArgRM16),
- /*10783*/ uint16(x86_xArg1),
- /*10784*/ uint16(x86_xMatch),
- /*10785*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*10787*/ uint16(x86_xArgRM32),
- /*10788*/ uint16(x86_xArg1),
- /*10789*/ uint16(x86_xMatch),
- /*10790*/ uint16(x86_xCondDataSize), 10780, 10785, 10794,
- /*10794*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*10796*/ uint16(x86_xArgRM64),
- /*10797*/ uint16(x86_xArg1),
- /*10798*/ uint16(x86_xMatch),
- /*10799*/ uint16(x86_xCondIs64), 10802, 10816,
- /*10802*/ uint16(x86_xCondDataSize), 10806, 10811, 0,
- /*10806*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*10808*/ uint16(x86_xArgRM16),
- /*10809*/ uint16(x86_xArg1),
- /*10810*/ uint16(x86_xMatch),
- /*10811*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*10813*/ uint16(x86_xArgRM32),
- /*10814*/ uint16(x86_xArg1),
- /*10815*/ uint16(x86_xMatch),
- /*10816*/ uint16(x86_xCondDataSize), 10806, 10811, 10820,
- /*10820*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*10822*/ uint16(x86_xArgRM64),
- /*10823*/ uint16(x86_xArg1),
- /*10824*/ uint16(x86_xMatch),
- /*10825*/ uint16(x86_xCondIs64), 10828, 10842,
- /*10828*/ uint16(x86_xCondDataSize), 10832, 10837, 0,
- /*10832*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*10834*/ uint16(x86_xArgRM16),
- /*10835*/ uint16(x86_xArg1),
- /*10836*/ uint16(x86_xMatch),
- /*10837*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*10839*/ uint16(x86_xArgRM32),
- /*10840*/ uint16(x86_xArg1),
- /*10841*/ uint16(x86_xMatch),
- /*10842*/ uint16(x86_xCondDataSize), 10832, 10837, 10846,
- /*10846*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*10848*/ uint16(x86_xArgRM64),
- /*10849*/ uint16(x86_xArg1),
- /*10850*/ uint16(x86_xMatch),
- /*10851*/ uint16(x86_xCondIs64), 10854, 10868,
- /*10854*/ uint16(x86_xCondDataSize), 10858, 10863, 0,
- /*10858*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*10860*/ uint16(x86_xArgRM16),
- /*10861*/ uint16(x86_xArg1),
- /*10862*/ uint16(x86_xMatch),
- /*10863*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*10865*/ uint16(x86_xArgRM32),
- /*10866*/ uint16(x86_xArg1),
- /*10867*/ uint16(x86_xMatch),
- /*10868*/ uint16(x86_xCondDataSize), 10858, 10863, 10872,
- /*10872*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*10874*/ uint16(x86_xArgRM64),
- /*10875*/ uint16(x86_xArg1),
- /*10876*/ uint16(x86_xMatch),
- /*10877*/ uint16(x86_xCondIs64), 10880, 10894,
- /*10880*/ uint16(x86_xCondDataSize), 10884, 10889, 0,
- /*10884*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*10886*/ uint16(x86_xArgRM16),
- /*10887*/ uint16(x86_xArg1),
- /*10888*/ uint16(x86_xMatch),
- /*10889*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*10891*/ uint16(x86_xArgRM32),
- /*10892*/ uint16(x86_xArg1),
- /*10893*/ uint16(x86_xMatch),
- /*10894*/ uint16(x86_xCondDataSize), 10884, 10889, 10898,
- /*10898*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*10900*/ uint16(x86_xArgRM64),
- /*10901*/ uint16(x86_xArg1),
- /*10902*/ uint16(x86_xMatch),
- /*10903*/ uint16(x86_xCondIs64), 10906, 10920,
- /*10906*/ uint16(x86_xCondDataSize), 10910, 10915, 0,
- /*10910*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*10912*/ uint16(x86_xArgRM16),
- /*10913*/ uint16(x86_xArg1),
- /*10914*/ uint16(x86_xMatch),
- /*10915*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*10917*/ uint16(x86_xArgRM32),
- /*10918*/ uint16(x86_xArg1),
- /*10919*/ uint16(x86_xMatch),
- /*10920*/ uint16(x86_xCondDataSize), 10910, 10915, 10924,
- /*10924*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*10926*/ uint16(x86_xArgRM64),
- /*10927*/ uint16(x86_xArg1),
- /*10928*/ uint16(x86_xMatch),
- /*10929*/ uint16(x86_xCondIs64), 10932, 10946,
- /*10932*/ uint16(x86_xCondDataSize), 10936, 10941, 0,
- /*10936*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*10938*/ uint16(x86_xArgRM16),
- /*10939*/ uint16(x86_xArg1),
- /*10940*/ uint16(x86_xMatch),
- /*10941*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*10943*/ uint16(x86_xArgRM32),
- /*10944*/ uint16(x86_xArg1),
- /*10945*/ uint16(x86_xMatch),
- /*10946*/ uint16(x86_xCondDataSize), 10936, 10941, 10950,
- /*10950*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*10952*/ uint16(x86_xArgRM64),
- /*10953*/ uint16(x86_xArg1),
- /*10954*/ uint16(x86_xMatch),
- /*10955*/ uint16(x86_xCondSlashR),
- 10964, // 0
- 10969, // 1
- 10974, // 2
- 10979, // 3
- 10984, // 4
- 10989, // 5
- 0, // 6
- 10994, // 7
- /*10964*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*10966*/ uint16(x86_xArgRM8),
- /*10967*/ uint16(x86_xArgCL),
- /*10968*/ uint16(x86_xMatch),
- /*10969*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*10971*/ uint16(x86_xArgRM8),
- /*10972*/ uint16(x86_xArgCL),
- /*10973*/ uint16(x86_xMatch),
- /*10974*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*10976*/ uint16(x86_xArgRM8),
- /*10977*/ uint16(x86_xArgCL),
- /*10978*/ uint16(x86_xMatch),
- /*10979*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*10981*/ uint16(x86_xArgRM8),
- /*10982*/ uint16(x86_xArgCL),
- /*10983*/ uint16(x86_xMatch),
- /*10984*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*10986*/ uint16(x86_xArgRM8),
- /*10987*/ uint16(x86_xArgCL),
- /*10988*/ uint16(x86_xMatch),
- /*10989*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*10991*/ uint16(x86_xArgRM8),
- /*10992*/ uint16(x86_xArgCL),
- /*10993*/ uint16(x86_xMatch),
- /*10994*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*10996*/ uint16(x86_xArgRM8),
- /*10997*/ uint16(x86_xArgCL),
- /*10998*/ uint16(x86_xMatch),
- /*10999*/ uint16(x86_xCondSlashR),
- 11008, // 0
- 11034, // 1
- 11060, // 2
- 11086, // 3
- 11112, // 4
- 11138, // 5
- 0, // 6
- 11164, // 7
- /*11008*/ uint16(x86_xCondIs64), 11011, 11025,
- /*11011*/ uint16(x86_xCondDataSize), 11015, 11020, 0,
- /*11015*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*11017*/ uint16(x86_xArgRM16),
- /*11018*/ uint16(x86_xArgCL),
- /*11019*/ uint16(x86_xMatch),
- /*11020*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*11022*/ uint16(x86_xArgRM32),
- /*11023*/ uint16(x86_xArgCL),
- /*11024*/ uint16(x86_xMatch),
- /*11025*/ uint16(x86_xCondDataSize), 11015, 11020, 11029,
- /*11029*/ uint16(x86_xSetOp), uint16(x86_ROL),
- /*11031*/ uint16(x86_xArgRM64),
- /*11032*/ uint16(x86_xArgCL),
- /*11033*/ uint16(x86_xMatch),
- /*11034*/ uint16(x86_xCondIs64), 11037, 11051,
- /*11037*/ uint16(x86_xCondDataSize), 11041, 11046, 0,
- /*11041*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*11043*/ uint16(x86_xArgRM16),
- /*11044*/ uint16(x86_xArgCL),
- /*11045*/ uint16(x86_xMatch),
- /*11046*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*11048*/ uint16(x86_xArgRM32),
- /*11049*/ uint16(x86_xArgCL),
- /*11050*/ uint16(x86_xMatch),
- /*11051*/ uint16(x86_xCondDataSize), 11041, 11046, 11055,
- /*11055*/ uint16(x86_xSetOp), uint16(x86_ROR),
- /*11057*/ uint16(x86_xArgRM64),
- /*11058*/ uint16(x86_xArgCL),
- /*11059*/ uint16(x86_xMatch),
- /*11060*/ uint16(x86_xCondIs64), 11063, 11077,
- /*11063*/ uint16(x86_xCondDataSize), 11067, 11072, 0,
- /*11067*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*11069*/ uint16(x86_xArgRM16),
- /*11070*/ uint16(x86_xArgCL),
- /*11071*/ uint16(x86_xMatch),
- /*11072*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*11074*/ uint16(x86_xArgRM32),
- /*11075*/ uint16(x86_xArgCL),
- /*11076*/ uint16(x86_xMatch),
- /*11077*/ uint16(x86_xCondDataSize), 11067, 11072, 11081,
- /*11081*/ uint16(x86_xSetOp), uint16(x86_RCL),
- /*11083*/ uint16(x86_xArgRM64),
- /*11084*/ uint16(x86_xArgCL),
- /*11085*/ uint16(x86_xMatch),
- /*11086*/ uint16(x86_xCondIs64), 11089, 11103,
- /*11089*/ uint16(x86_xCondDataSize), 11093, 11098, 0,
- /*11093*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*11095*/ uint16(x86_xArgRM16),
- /*11096*/ uint16(x86_xArgCL),
- /*11097*/ uint16(x86_xMatch),
- /*11098*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*11100*/ uint16(x86_xArgRM32),
- /*11101*/ uint16(x86_xArgCL),
- /*11102*/ uint16(x86_xMatch),
- /*11103*/ uint16(x86_xCondDataSize), 11093, 11098, 11107,
- /*11107*/ uint16(x86_xSetOp), uint16(x86_RCR),
- /*11109*/ uint16(x86_xArgRM64),
- /*11110*/ uint16(x86_xArgCL),
- /*11111*/ uint16(x86_xMatch),
- /*11112*/ uint16(x86_xCondIs64), 11115, 11129,
- /*11115*/ uint16(x86_xCondDataSize), 11119, 11124, 0,
- /*11119*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*11121*/ uint16(x86_xArgRM16),
- /*11122*/ uint16(x86_xArgCL),
- /*11123*/ uint16(x86_xMatch),
- /*11124*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*11126*/ uint16(x86_xArgRM32),
- /*11127*/ uint16(x86_xArgCL),
- /*11128*/ uint16(x86_xMatch),
- /*11129*/ uint16(x86_xCondDataSize), 11119, 11124, 11133,
- /*11133*/ uint16(x86_xSetOp), uint16(x86_SHL),
- /*11135*/ uint16(x86_xArgRM64),
- /*11136*/ uint16(x86_xArgCL),
- /*11137*/ uint16(x86_xMatch),
- /*11138*/ uint16(x86_xCondIs64), 11141, 11155,
- /*11141*/ uint16(x86_xCondDataSize), 11145, 11150, 0,
- /*11145*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*11147*/ uint16(x86_xArgRM16),
- /*11148*/ uint16(x86_xArgCL),
- /*11149*/ uint16(x86_xMatch),
- /*11150*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*11152*/ uint16(x86_xArgRM32),
- /*11153*/ uint16(x86_xArgCL),
- /*11154*/ uint16(x86_xMatch),
- /*11155*/ uint16(x86_xCondDataSize), 11145, 11150, 11159,
- /*11159*/ uint16(x86_xSetOp), uint16(x86_SHR),
- /*11161*/ uint16(x86_xArgRM64),
- /*11162*/ uint16(x86_xArgCL),
- /*11163*/ uint16(x86_xMatch),
- /*11164*/ uint16(x86_xCondIs64), 11167, 11181,
- /*11167*/ uint16(x86_xCondDataSize), 11171, 11176, 0,
- /*11171*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*11173*/ uint16(x86_xArgRM16),
- /*11174*/ uint16(x86_xArgCL),
- /*11175*/ uint16(x86_xMatch),
- /*11176*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*11178*/ uint16(x86_xArgRM32),
- /*11179*/ uint16(x86_xArgCL),
- /*11180*/ uint16(x86_xMatch),
- /*11181*/ uint16(x86_xCondDataSize), 11171, 11176, 11185,
- /*11185*/ uint16(x86_xSetOp), uint16(x86_SAR),
- /*11187*/ uint16(x86_xArgRM64),
- /*11188*/ uint16(x86_xArgCL),
- /*11189*/ uint16(x86_xMatch),
- /*11190*/ uint16(x86_xCondIs64), 11193, 0,
- /*11193*/ uint16(x86_xSetOp), uint16(x86_AAM),
- /*11195*/ uint16(x86_xReadIb),
- /*11196*/ uint16(x86_xArgImm8u),
- /*11197*/ uint16(x86_xMatch),
- /*11198*/ uint16(x86_xCondIs64), 11201, 0,
- /*11201*/ uint16(x86_xSetOp), uint16(x86_AAD),
- /*11203*/ uint16(x86_xReadIb),
- /*11204*/ uint16(x86_xArgImm8u),
- /*11205*/ uint16(x86_xMatch),
- /*11206*/ uint16(x86_xCondIs64), 11209, 11212,
- /*11209*/ uint16(x86_xSetOp), uint16(x86_XLATB),
- /*11211*/ uint16(x86_xMatch),
- /*11212*/ uint16(x86_xCondDataSize), 11209, 11209, 11216,
- /*11216*/ uint16(x86_xSetOp), uint16(x86_XLATB),
- /*11218*/ uint16(x86_xMatch),
- /*11219*/ uint16(x86_xCondByte), 64,
- 0xc0, 11390,
- 0xc1, 11390,
- 0xc2, 11390,
- 0xc3, 11390,
- 0xc4, 11390,
- 0xc5, 11390,
- 0xc6, 11390,
- 0xc7, 11390,
- 0xc8, 11395,
- 0xc9, 11395,
- 0xca, 11395,
- 0xcb, 11395,
- 0xcc, 11395,
- 0xcd, 11395,
- 0xce, 11395,
- 0xcf, 11395,
- 0xd0, 11400,
- 0xd1, 11400,
- 0xd2, 11400,
- 0xd3, 11400,
- 0xd4, 11400,
- 0xd5, 11400,
- 0xd6, 11400,
- 0xd7, 11400,
- 0xd8, 11404,
- 0xd9, 11404,
- 0xda, 11404,
- 0xdb, 11404,
- 0xdc, 11404,
- 0xdd, 11404,
- 0xde, 11404,
- 0xdf, 11404,
- 0xe0, 11408,
- 0xe1, 11408,
- 0xe2, 11408,
- 0xe3, 11408,
- 0xe4, 11408,
- 0xe5, 11408,
- 0xe6, 11408,
- 0xe7, 11408,
- 0xe8, 11413,
- 0xe9, 11413,
- 0xea, 11413,
- 0xeb, 11413,
- 0xec, 11413,
- 0xed, 11413,
- 0xee, 11413,
- 0xef, 11413,
- 0xf0, 11418,
- 0xf1, 11418,
- 0xf2, 11418,
- 0xf3, 11418,
- 0xf4, 11418,
- 0xf5, 11418,
- 0xf6, 11418,
- 0xf7, 11418,
- 0xf8, 11423,
- 0xf9, 11423,
- 0xfa, 11423,
- 0xfb, 11423,
- 0xfc, 11423,
- 0xfd, 11423,
- 0xfe, 11423,
- 0xff, 11423,
- /*11349*/ uint16(x86_xCondSlashR),
- 11358, // 0
- 11362, // 1
- 11366, // 2
- 11370, // 3
- 11374, // 4
- 11378, // 5
- 11382, // 6
- 11386, // 7
- /*11358*/ uint16(x86_xSetOp), uint16(x86_FADD),
- /*11360*/ uint16(x86_xArgM32fp),
- /*11361*/ uint16(x86_xMatch),
- /*11362*/ uint16(x86_xSetOp), uint16(x86_FMUL),
- /*11364*/ uint16(x86_xArgM32fp),
- /*11365*/ uint16(x86_xMatch),
- /*11366*/ uint16(x86_xSetOp), uint16(x86_FCOM),
- /*11368*/ uint16(x86_xArgM32fp),
- /*11369*/ uint16(x86_xMatch),
- /*11370*/ uint16(x86_xSetOp), uint16(x86_FCOMP),
- /*11372*/ uint16(x86_xArgM32fp),
- /*11373*/ uint16(x86_xMatch),
- /*11374*/ uint16(x86_xSetOp), uint16(x86_FSUB),
- /*11376*/ uint16(x86_xArgM32fp),
- /*11377*/ uint16(x86_xMatch),
- /*11378*/ uint16(x86_xSetOp), uint16(x86_FSUBR),
- /*11380*/ uint16(x86_xArgM32fp),
- /*11381*/ uint16(x86_xMatch),
- /*11382*/ uint16(x86_xSetOp), uint16(x86_FDIV),
- /*11384*/ uint16(x86_xArgM32fp),
- /*11385*/ uint16(x86_xMatch),
- /*11386*/ uint16(x86_xSetOp), uint16(x86_FDIVR),
- /*11388*/ uint16(x86_xArgM32fp),
- /*11389*/ uint16(x86_xMatch),
- /*11390*/ uint16(x86_xSetOp), uint16(x86_FADD),
- /*11392*/ uint16(x86_xArgST),
- /*11393*/ uint16(x86_xArgSTi),
- /*11394*/ uint16(x86_xMatch),
- /*11395*/ uint16(x86_xSetOp), uint16(x86_FMUL),
- /*11397*/ uint16(x86_xArgST),
- /*11398*/ uint16(x86_xArgSTi),
- /*11399*/ uint16(x86_xMatch),
- /*11400*/ uint16(x86_xSetOp), uint16(x86_FCOM),
- /*11402*/ uint16(x86_xArgSTi),
- /*11403*/ uint16(x86_xMatch),
- /*11404*/ uint16(x86_xSetOp), uint16(x86_FCOMP),
- /*11406*/ uint16(x86_xArgSTi),
- /*11407*/ uint16(x86_xMatch),
- /*11408*/ uint16(x86_xSetOp), uint16(x86_FSUB),
- /*11410*/ uint16(x86_xArgST),
- /*11411*/ uint16(x86_xArgSTi),
- /*11412*/ uint16(x86_xMatch),
- /*11413*/ uint16(x86_xSetOp), uint16(x86_FSUBR),
- /*11415*/ uint16(x86_xArgST),
- /*11416*/ uint16(x86_xArgSTi),
- /*11417*/ uint16(x86_xMatch),
- /*11418*/ uint16(x86_xSetOp), uint16(x86_FDIV),
- /*11420*/ uint16(x86_xArgST),
- /*11421*/ uint16(x86_xArgSTi),
- /*11422*/ uint16(x86_xMatch),
- /*11423*/ uint16(x86_xSetOp), uint16(x86_FDIVR),
- /*11425*/ uint16(x86_xArgST),
- /*11426*/ uint16(x86_xArgSTi),
- /*11427*/ uint16(x86_xMatch),
- /*11428*/ uint16(x86_xCondByte), 42,
- 0xc0, 11551,
- 0xc1, 11551,
- 0xc2, 11551,
- 0xc3, 11551,
- 0xc4, 11551,
- 0xc5, 11551,
- 0xc6, 11551,
- 0xc7, 11551,
- 0xc8, 11555,
- 0xc9, 11555,
- 0xca, 11555,
- 0xcb, 11555,
- 0xcc, 11555,
- 0xcd, 11555,
- 0xce, 11555,
- 0xcf, 11555,
- 0xD0, 11559,
- 0xE0, 11562,
- 0xE1, 11565,
- 0xE4, 11568,
- 0xE5, 11571,
- 0xE8, 11574,
- 0xE9, 11577,
- 0xEA, 11580,
- 0xEB, 11583,
- 0xEC, 11586,
- 0xF0, 11589,
- 0xF1, 11592,
- 0xF2, 11595,
- 0xF3, 11598,
- 0xF4, 11601,
- 0xF5, 11604,
- 0xF6, 11607,
- 0xF7, 11610,
- 0xF8, 11613,
- 0xF9, 11616,
- 0xFA, 11619,
- 0xFB, 11622,
- 0xFC, 11625,
- 0xFD, 11628,
- 0xFE, 11631,
- 0xFF, 11634,
- /*11514*/ uint16(x86_xCondSlashR),
- 11523, // 0
- 0, // 1
- 11527, // 2
- 11531, // 3
- 11535, // 4
- 11539, // 5
- 11543, // 6
- 11547, // 7
- /*11523*/ uint16(x86_xSetOp), uint16(x86_FLD),
- /*11525*/ uint16(x86_xArgM32fp),
- /*11526*/ uint16(x86_xMatch),
- /*11527*/ uint16(x86_xSetOp), uint16(x86_FST),
- /*11529*/ uint16(x86_xArgM32fp),
- /*11530*/ uint16(x86_xMatch),
- /*11531*/ uint16(x86_xSetOp), uint16(x86_FSTP),
- /*11533*/ uint16(x86_xArgM32fp),
- /*11534*/ uint16(x86_xMatch),
- /*11535*/ uint16(x86_xSetOp), uint16(x86_FLDENV),
- /*11537*/ uint16(x86_xArgM1428byte),
- /*11538*/ uint16(x86_xMatch),
- /*11539*/ uint16(x86_xSetOp), uint16(x86_FLDCW),
- /*11541*/ uint16(x86_xArgM2byte),
- /*11542*/ uint16(x86_xMatch),
- /*11543*/ uint16(x86_xSetOp), uint16(x86_FNSTENV),
- /*11545*/ uint16(x86_xArgM1428byte),
- /*11546*/ uint16(x86_xMatch),
- /*11547*/ uint16(x86_xSetOp), uint16(x86_FNSTCW),
- /*11549*/ uint16(x86_xArgM2byte),
- /*11550*/ uint16(x86_xMatch),
- /*11551*/ uint16(x86_xSetOp), uint16(x86_FLD),
- /*11553*/ uint16(x86_xArgSTi),
- /*11554*/ uint16(x86_xMatch),
- /*11555*/ uint16(x86_xSetOp), uint16(x86_FXCH),
- /*11557*/ uint16(x86_xArgSTi),
- /*11558*/ uint16(x86_xMatch),
- /*11559*/ uint16(x86_xSetOp), uint16(x86_FNOP),
- /*11561*/ uint16(x86_xMatch),
- /*11562*/ uint16(x86_xSetOp), uint16(x86_FCHS),
- /*11564*/ uint16(x86_xMatch),
- /*11565*/ uint16(x86_xSetOp), uint16(x86_FABS),
- /*11567*/ uint16(x86_xMatch),
- /*11568*/ uint16(x86_xSetOp), uint16(x86_FTST),
- /*11570*/ uint16(x86_xMatch),
- /*11571*/ uint16(x86_xSetOp), uint16(x86_FXAM),
- /*11573*/ uint16(x86_xMatch),
- /*11574*/ uint16(x86_xSetOp), uint16(x86_FLD1),
- /*11576*/ uint16(x86_xMatch),
- /*11577*/ uint16(x86_xSetOp), uint16(x86_FLDL2T),
- /*11579*/ uint16(x86_xMatch),
- /*11580*/ uint16(x86_xSetOp), uint16(x86_FLDL2E),
- /*11582*/ uint16(x86_xMatch),
- /*11583*/ uint16(x86_xSetOp), uint16(x86_FLDPI),
- /*11585*/ uint16(x86_xMatch),
- /*11586*/ uint16(x86_xSetOp), uint16(x86_FLDLG2),
- /*11588*/ uint16(x86_xMatch),
- /*11589*/ uint16(x86_xSetOp), uint16(x86_F2XM1),
- /*11591*/ uint16(x86_xMatch),
- /*11592*/ uint16(x86_xSetOp), uint16(x86_FYL2X),
- /*11594*/ uint16(x86_xMatch),
- /*11595*/ uint16(x86_xSetOp), uint16(x86_FPTAN),
- /*11597*/ uint16(x86_xMatch),
- /*11598*/ uint16(x86_xSetOp), uint16(x86_FPATAN),
- /*11600*/ uint16(x86_xMatch),
- /*11601*/ uint16(x86_xSetOp), uint16(x86_FXTRACT),
- /*11603*/ uint16(x86_xMatch),
- /*11604*/ uint16(x86_xSetOp), uint16(x86_FPREM1),
- /*11606*/ uint16(x86_xMatch),
- /*11607*/ uint16(x86_xSetOp), uint16(x86_FDECSTP),
- /*11609*/ uint16(x86_xMatch),
- /*11610*/ uint16(x86_xSetOp), uint16(x86_FINCSTP),
- /*11612*/ uint16(x86_xMatch),
- /*11613*/ uint16(x86_xSetOp), uint16(x86_FPREM),
- /*11615*/ uint16(x86_xMatch),
- /*11616*/ uint16(x86_xSetOp), uint16(x86_FYL2XP1),
- /*11618*/ uint16(x86_xMatch),
- /*11619*/ uint16(x86_xSetOp), uint16(x86_FSQRT),
- /*11621*/ uint16(x86_xMatch),
- /*11622*/ uint16(x86_xSetOp), uint16(x86_FSINCOS),
- /*11624*/ uint16(x86_xMatch),
- /*11625*/ uint16(x86_xSetOp), uint16(x86_FRNDINT),
- /*11627*/ uint16(x86_xMatch),
- /*11628*/ uint16(x86_xSetOp), uint16(x86_FSCALE),
- /*11630*/ uint16(x86_xMatch),
- /*11631*/ uint16(x86_xSetOp), uint16(x86_FSIN),
- /*11633*/ uint16(x86_xMatch),
- /*11634*/ uint16(x86_xSetOp), uint16(x86_FCOS),
- /*11636*/ uint16(x86_xMatch),
- /*11637*/ uint16(x86_xCondByte), 33,
- 0xc0, 11746,
- 0xc1, 11746,
- 0xc2, 11746,
- 0xc3, 11746,
- 0xc4, 11746,
- 0xc5, 11746,
- 0xc6, 11746,
- 0xc7, 11746,
- 0xc8, 11751,
- 0xc9, 11751,
- 0xca, 11751,
- 0xcb, 11751,
- 0xcc, 11751,
- 0xcd, 11751,
- 0xce, 11751,
- 0xcf, 11751,
- 0xd0, 11756,
- 0xd1, 11756,
- 0xd2, 11756,
- 0xd3, 11756,
- 0xd4, 11756,
- 0xd5, 11756,
- 0xd6, 11756,
- 0xd7, 11756,
- 0xd8, 11761,
- 0xd9, 11761,
- 0xda, 11761,
- 0xdb, 11761,
- 0xdc, 11761,
- 0xdd, 11761,
- 0xde, 11761,
- 0xdf, 11761,
- 0xE9, 11766,
- /*11705*/ uint16(x86_xCondSlashR),
- 11714, // 0
- 11718, // 1
- 11722, // 2
- 11726, // 3
- 11730, // 4
- 11734, // 5
- 11738, // 6
- 11742, // 7
- /*11714*/ uint16(x86_xSetOp), uint16(x86_FIADD),
- /*11716*/ uint16(x86_xArgM32int),
- /*11717*/ uint16(x86_xMatch),
- /*11718*/ uint16(x86_xSetOp), uint16(x86_FIMUL),
- /*11720*/ uint16(x86_xArgM32int),
- /*11721*/ uint16(x86_xMatch),
- /*11722*/ uint16(x86_xSetOp), uint16(x86_FICOM),
- /*11724*/ uint16(x86_xArgM32int),
- /*11725*/ uint16(x86_xMatch),
- /*11726*/ uint16(x86_xSetOp), uint16(x86_FICOMP),
- /*11728*/ uint16(x86_xArgM32int),
- /*11729*/ uint16(x86_xMatch),
- /*11730*/ uint16(x86_xSetOp), uint16(x86_FISUB),
- /*11732*/ uint16(x86_xArgM32int),
- /*11733*/ uint16(x86_xMatch),
- /*11734*/ uint16(x86_xSetOp), uint16(x86_FISUBR),
- /*11736*/ uint16(x86_xArgM32int),
- /*11737*/ uint16(x86_xMatch),
- /*11738*/ uint16(x86_xSetOp), uint16(x86_FIDIV),
- /*11740*/ uint16(x86_xArgM32int),
- /*11741*/ uint16(x86_xMatch),
- /*11742*/ uint16(x86_xSetOp), uint16(x86_FIDIVR),
- /*11744*/ uint16(x86_xArgM32int),
- /*11745*/ uint16(x86_xMatch),
- /*11746*/ uint16(x86_xSetOp), uint16(x86_FCMOVB),
- /*11748*/ uint16(x86_xArgST),
- /*11749*/ uint16(x86_xArgSTi),
- /*11750*/ uint16(x86_xMatch),
- /*11751*/ uint16(x86_xSetOp), uint16(x86_FCMOVE),
- /*11753*/ uint16(x86_xArgST),
- /*11754*/ uint16(x86_xArgSTi),
- /*11755*/ uint16(x86_xMatch),
- /*11756*/ uint16(x86_xSetOp), uint16(x86_FCMOVBE),
- /*11758*/ uint16(x86_xArgST),
- /*11759*/ uint16(x86_xArgSTi),
- /*11760*/ uint16(x86_xMatch),
- /*11761*/ uint16(x86_xSetOp), uint16(x86_FCMOVU),
- /*11763*/ uint16(x86_xArgST),
- /*11764*/ uint16(x86_xArgSTi),
- /*11765*/ uint16(x86_xMatch),
- /*11766*/ uint16(x86_xSetOp), uint16(x86_FUCOMPP),
- /*11768*/ uint16(x86_xMatch),
- /*11769*/ uint16(x86_xCondByte), 50,
- 0xc0, 11904,
- 0xc1, 11904,
- 0xc2, 11904,
- 0xc3, 11904,
- 0xc4, 11904,
- 0xc5, 11904,
- 0xc6, 11904,
- 0xc7, 11904,
- 0xc8, 11909,
- 0xc9, 11909,
- 0xca, 11909,
- 0xcb, 11909,
- 0xcc, 11909,
- 0xcd, 11909,
- 0xce, 11909,
- 0xcf, 11909,
- 0xd0, 11914,
- 0xd1, 11914,
- 0xd2, 11914,
- 0xd3, 11914,
- 0xd4, 11914,
- 0xd5, 11914,
- 0xd6, 11914,
- 0xd7, 11914,
- 0xd8, 11919,
- 0xd9, 11919,
- 0xda, 11919,
- 0xdb, 11919,
- 0xdc, 11919,
- 0xdd, 11919,
- 0xde, 11919,
- 0xdf, 11919,
- 0xE2, 11924,
- 0xE3, 11927,
- 0xe8, 11930,
- 0xe9, 11930,
- 0xea, 11930,
- 0xeb, 11930,
- 0xec, 11930,
- 0xed, 11930,
- 0xee, 11930,
- 0xef, 11930,
- 0xf0, 11935,
- 0xf1, 11935,
- 0xf2, 11935,
- 0xf3, 11935,
- 0xf4, 11935,
- 0xf5, 11935,
- 0xf6, 11935,
- 0xf7, 11935,
- /*11871*/ uint16(x86_xCondSlashR),
- 11880, // 0
- 11884, // 1
- 11888, // 2
- 11892, // 3
- 0, // 4
- 11896, // 5
- 0, // 6
- 11900, // 7
- /*11880*/ uint16(x86_xSetOp), uint16(x86_FILD),
- /*11882*/ uint16(x86_xArgM32int),
- /*11883*/ uint16(x86_xMatch),
- /*11884*/ uint16(x86_xSetOp), uint16(x86_FISTTP),
- /*11886*/ uint16(x86_xArgM32int),
- /*11887*/ uint16(x86_xMatch),
- /*11888*/ uint16(x86_xSetOp), uint16(x86_FIST),
- /*11890*/ uint16(x86_xArgM32int),
- /*11891*/ uint16(x86_xMatch),
- /*11892*/ uint16(x86_xSetOp), uint16(x86_FISTP),
- /*11894*/ uint16(x86_xArgM32int),
- /*11895*/ uint16(x86_xMatch),
- /*11896*/ uint16(x86_xSetOp), uint16(x86_FLD),
- /*11898*/ uint16(x86_xArgM80fp),
- /*11899*/ uint16(x86_xMatch),
- /*11900*/ uint16(x86_xSetOp), uint16(x86_FSTP),
- /*11902*/ uint16(x86_xArgM80fp),
- /*11903*/ uint16(x86_xMatch),
- /*11904*/ uint16(x86_xSetOp), uint16(x86_FCMOVNB),
- /*11906*/ uint16(x86_xArgST),
- /*11907*/ uint16(x86_xArgSTi),
- /*11908*/ uint16(x86_xMatch),
- /*11909*/ uint16(x86_xSetOp), uint16(x86_FCMOVNE),
- /*11911*/ uint16(x86_xArgST),
- /*11912*/ uint16(x86_xArgSTi),
- /*11913*/ uint16(x86_xMatch),
- /*11914*/ uint16(x86_xSetOp), uint16(x86_FCMOVNBE),
- /*11916*/ uint16(x86_xArgST),
- /*11917*/ uint16(x86_xArgSTi),
- /*11918*/ uint16(x86_xMatch),
- /*11919*/ uint16(x86_xSetOp), uint16(x86_FCMOVNU),
- /*11921*/ uint16(x86_xArgST),
- /*11922*/ uint16(x86_xArgSTi),
- /*11923*/ uint16(x86_xMatch),
- /*11924*/ uint16(x86_xSetOp), uint16(x86_FNCLEX),
- /*11926*/ uint16(x86_xMatch),
- /*11927*/ uint16(x86_xSetOp), uint16(x86_FNINIT),
- /*11929*/ uint16(x86_xMatch),
- /*11930*/ uint16(x86_xSetOp), uint16(x86_FUCOMI),
- /*11932*/ uint16(x86_xArgST),
- /*11933*/ uint16(x86_xArgSTi),
- /*11934*/ uint16(x86_xMatch),
- /*11935*/ uint16(x86_xSetOp), uint16(x86_FCOMI),
- /*11937*/ uint16(x86_xArgST),
- /*11938*/ uint16(x86_xArgSTi),
- /*11939*/ uint16(x86_xMatch),
- /*11940*/ uint16(x86_xCondByte), 48,
- 0xc0, 12079,
- 0xc1, 12079,
- 0xc2, 12079,
- 0xc3, 12079,
- 0xc4, 12079,
- 0xc5, 12079,
- 0xc6, 12079,
- 0xc7, 12079,
- 0xc8, 12084,
- 0xc9, 12084,
- 0xca, 12084,
- 0xcb, 12084,
- 0xcc, 12084,
- 0xcd, 12084,
- 0xce, 12084,
- 0xcf, 12084,
- 0xe0, 12089,
- 0xe1, 12089,
- 0xe2, 12089,
- 0xe3, 12089,
- 0xe4, 12089,
- 0xe5, 12089,
- 0xe6, 12089,
- 0xe7, 12089,
- 0xe8, 12094,
- 0xe9, 12094,
- 0xea, 12094,
- 0xeb, 12094,
- 0xec, 12094,
- 0xed, 12094,
- 0xee, 12094,
- 0xef, 12094,
- 0xf0, 12099,
- 0xf1, 12099,
- 0xf2, 12099,
- 0xf3, 12099,
- 0xf4, 12099,
- 0xf5, 12099,
- 0xf6, 12099,
- 0xf7, 12099,
- 0xf8, 12104,
- 0xf9, 12104,
- 0xfa, 12104,
- 0xfb, 12104,
- 0xfc, 12104,
- 0xfd, 12104,
- 0xfe, 12104,
- 0xff, 12104,
- /*12038*/ uint16(x86_xCondSlashR),
- 12047, // 0
- 12051, // 1
- 12055, // 2
- 12059, // 3
- 12063, // 4
- 12067, // 5
- 12071, // 6
- 12075, // 7
- /*12047*/ uint16(x86_xSetOp), uint16(x86_FADD),
- /*12049*/ uint16(x86_xArgM64fp),
- /*12050*/ uint16(x86_xMatch),
- /*12051*/ uint16(x86_xSetOp), uint16(x86_FMUL),
- /*12053*/ uint16(x86_xArgM64fp),
- /*12054*/ uint16(x86_xMatch),
- /*12055*/ uint16(x86_xSetOp), uint16(x86_FCOM),
- /*12057*/ uint16(x86_xArgM64fp),
- /*12058*/ uint16(x86_xMatch),
- /*12059*/ uint16(x86_xSetOp), uint16(x86_FCOMP),
- /*12061*/ uint16(x86_xArgM64fp),
- /*12062*/ uint16(x86_xMatch),
- /*12063*/ uint16(x86_xSetOp), uint16(x86_FSUB),
- /*12065*/ uint16(x86_xArgM64fp),
- /*12066*/ uint16(x86_xMatch),
- /*12067*/ uint16(x86_xSetOp), uint16(x86_FSUBR),
- /*12069*/ uint16(x86_xArgM64fp),
- /*12070*/ uint16(x86_xMatch),
- /*12071*/ uint16(x86_xSetOp), uint16(x86_FDIV),
- /*12073*/ uint16(x86_xArgM64fp),
- /*12074*/ uint16(x86_xMatch),
- /*12075*/ uint16(x86_xSetOp), uint16(x86_FDIVR),
- /*12077*/ uint16(x86_xArgM64fp),
- /*12078*/ uint16(x86_xMatch),
- /*12079*/ uint16(x86_xSetOp), uint16(x86_FADD),
- /*12081*/ uint16(x86_xArgSTi),
- /*12082*/ uint16(x86_xArgST),
- /*12083*/ uint16(x86_xMatch),
- /*12084*/ uint16(x86_xSetOp), uint16(x86_FMUL),
- /*12086*/ uint16(x86_xArgSTi),
- /*12087*/ uint16(x86_xArgST),
- /*12088*/ uint16(x86_xMatch),
- /*12089*/ uint16(x86_xSetOp), uint16(x86_FSUBR),
- /*12091*/ uint16(x86_xArgSTi),
- /*12092*/ uint16(x86_xArgST),
- /*12093*/ uint16(x86_xMatch),
- /*12094*/ uint16(x86_xSetOp), uint16(x86_FSUB),
- /*12096*/ uint16(x86_xArgSTi),
- /*12097*/ uint16(x86_xArgST),
- /*12098*/ uint16(x86_xMatch),
- /*12099*/ uint16(x86_xSetOp), uint16(x86_FDIVR),
- /*12101*/ uint16(x86_xArgSTi),
- /*12102*/ uint16(x86_xArgST),
- /*12103*/ uint16(x86_xMatch),
- /*12104*/ uint16(x86_xSetOp), uint16(x86_FDIV),
- /*12106*/ uint16(x86_xArgSTi),
- /*12107*/ uint16(x86_xArgST),
- /*12108*/ uint16(x86_xMatch),
- /*12109*/ uint16(x86_xCondByte), 40,
- 0xc0, 12228,
- 0xc1, 12228,
- 0xc2, 12228,
- 0xc3, 12228,
- 0xc4, 12228,
- 0xc5, 12228,
- 0xc6, 12228,
- 0xc7, 12228,
- 0xd0, 12232,
- 0xd1, 12232,
- 0xd2, 12232,
- 0xd3, 12232,
- 0xd4, 12232,
- 0xd5, 12232,
- 0xd6, 12232,
- 0xd7, 12232,
- 0xd8, 12236,
- 0xd9, 12236,
- 0xda, 12236,
- 0xdb, 12236,
- 0xdc, 12236,
- 0xdd, 12236,
- 0xde, 12236,
- 0xdf, 12236,
- 0xe0, 12240,
- 0xe1, 12240,
- 0xe2, 12240,
- 0xe3, 12240,
- 0xe4, 12240,
- 0xe5, 12240,
- 0xe6, 12240,
- 0xe7, 12240,
- 0xe8, 12244,
- 0xe9, 12244,
- 0xea, 12244,
- 0xeb, 12244,
- 0xec, 12244,
- 0xed, 12244,
- 0xee, 12244,
- 0xef, 12244,
- /*12191*/ uint16(x86_xCondSlashR),
- 12200, // 0
- 12204, // 1
- 12208, // 2
- 12212, // 3
- 12216, // 4
- 0, // 5
- 12220, // 6
- 12224, // 7
- /*12200*/ uint16(x86_xSetOp), uint16(x86_FLD),
- /*12202*/ uint16(x86_xArgM64fp),
- /*12203*/ uint16(x86_xMatch),
- /*12204*/ uint16(x86_xSetOp), uint16(x86_FISTTP),
- /*12206*/ uint16(x86_xArgM64int),
- /*12207*/ uint16(x86_xMatch),
- /*12208*/ uint16(x86_xSetOp), uint16(x86_FST),
- /*12210*/ uint16(x86_xArgM64fp),
- /*12211*/ uint16(x86_xMatch),
- /*12212*/ uint16(x86_xSetOp), uint16(x86_FSTP),
- /*12214*/ uint16(x86_xArgM64fp),
- /*12215*/ uint16(x86_xMatch),
- /*12216*/ uint16(x86_xSetOp), uint16(x86_FRSTOR),
- /*12218*/ uint16(x86_xArgM94108byte),
- /*12219*/ uint16(x86_xMatch),
- /*12220*/ uint16(x86_xSetOp), uint16(x86_FNSAVE),
- /*12222*/ uint16(x86_xArgM94108byte),
- /*12223*/ uint16(x86_xMatch),
- /*12224*/ uint16(x86_xSetOp), uint16(x86_FNSTSW),
- /*12226*/ uint16(x86_xArgM2byte),
- /*12227*/ uint16(x86_xMatch),
- /*12228*/ uint16(x86_xSetOp), uint16(x86_FFREE),
- /*12230*/ uint16(x86_xArgSTi),
- /*12231*/ uint16(x86_xMatch),
- /*12232*/ uint16(x86_xSetOp), uint16(x86_FST),
- /*12234*/ uint16(x86_xArgSTi),
- /*12235*/ uint16(x86_xMatch),
- /*12236*/ uint16(x86_xSetOp), uint16(x86_FSTP),
- /*12238*/ uint16(x86_xArgSTi),
- /*12239*/ uint16(x86_xMatch),
- /*12240*/ uint16(x86_xSetOp), uint16(x86_FUCOM),
- /*12242*/ uint16(x86_xArgSTi),
- /*12243*/ uint16(x86_xMatch),
- /*12244*/ uint16(x86_xSetOp), uint16(x86_FUCOMP),
- /*12246*/ uint16(x86_xArgSTi),
- /*12247*/ uint16(x86_xMatch),
- /*12248*/ uint16(x86_xCondByte), 49,
- 0xc0, 12389,
- 0xc1, 12389,
- 0xc2, 12389,
- 0xc3, 12389,
- 0xc4, 12389,
- 0xc5, 12389,
- 0xc6, 12389,
- 0xc7, 12389,
- 0xc8, 12394,
- 0xc9, 12394,
- 0xca, 12394,
- 0xcb, 12394,
- 0xcc, 12394,
- 0xcd, 12394,
- 0xce, 12394,
- 0xcf, 12394,
- 0xD9, 12399,
- 0xe0, 12402,
- 0xe1, 12402,
- 0xe2, 12402,
- 0xe3, 12402,
- 0xe4, 12402,
- 0xe5, 12402,
- 0xe6, 12402,
- 0xe7, 12402,
- 0xe8, 12407,
- 0xe9, 12407,
- 0xea, 12407,
- 0xeb, 12407,
- 0xec, 12407,
- 0xed, 12407,
- 0xee, 12407,
- 0xef, 12407,
- 0xf0, 12412,
- 0xf1, 12412,
- 0xf2, 12412,
- 0xf3, 12412,
- 0xf4, 12412,
- 0xf5, 12412,
- 0xf6, 12412,
- 0xf7, 12412,
- 0xf8, 12417,
- 0xf9, 12417,
- 0xfa, 12417,
- 0xfb, 12417,
- 0xfc, 12417,
- 0xfd, 12417,
- 0xfe, 12417,
- 0xff, 12417,
- /*12348*/ uint16(x86_xCondSlashR),
- 12357, // 0
- 12361, // 1
- 12365, // 2
- 12369, // 3
- 12373, // 4
- 12377, // 5
- 12381, // 6
- 12385, // 7
- /*12357*/ uint16(x86_xSetOp), uint16(x86_FIADD),
- /*12359*/ uint16(x86_xArgM16int),
- /*12360*/ uint16(x86_xMatch),
- /*12361*/ uint16(x86_xSetOp), uint16(x86_FIMUL),
- /*12363*/ uint16(x86_xArgM16int),
- /*12364*/ uint16(x86_xMatch),
- /*12365*/ uint16(x86_xSetOp), uint16(x86_FICOM),
- /*12367*/ uint16(x86_xArgM16int),
- /*12368*/ uint16(x86_xMatch),
- /*12369*/ uint16(x86_xSetOp), uint16(x86_FICOMP),
- /*12371*/ uint16(x86_xArgM16int),
- /*12372*/ uint16(x86_xMatch),
- /*12373*/ uint16(x86_xSetOp), uint16(x86_FISUB),
- /*12375*/ uint16(x86_xArgM16int),
- /*12376*/ uint16(x86_xMatch),
- /*12377*/ uint16(x86_xSetOp), uint16(x86_FISUBR),
- /*12379*/ uint16(x86_xArgM16int),
- /*12380*/ uint16(x86_xMatch),
- /*12381*/ uint16(x86_xSetOp), uint16(x86_FIDIV),
- /*12383*/ uint16(x86_xArgM16int),
- /*12384*/ uint16(x86_xMatch),
- /*12385*/ uint16(x86_xSetOp), uint16(x86_FIDIVR),
- /*12387*/ uint16(x86_xArgM16int),
- /*12388*/ uint16(x86_xMatch),
- /*12389*/ uint16(x86_xSetOp), uint16(x86_FADDP),
- /*12391*/ uint16(x86_xArgSTi),
- /*12392*/ uint16(x86_xArgST),
- /*12393*/ uint16(x86_xMatch),
- /*12394*/ uint16(x86_xSetOp), uint16(x86_FMULP),
- /*12396*/ uint16(x86_xArgSTi),
- /*12397*/ uint16(x86_xArgST),
- /*12398*/ uint16(x86_xMatch),
- /*12399*/ uint16(x86_xSetOp), uint16(x86_FCOMPP),
- /*12401*/ uint16(x86_xMatch),
- /*12402*/ uint16(x86_xSetOp), uint16(x86_FSUBRP),
- /*12404*/ uint16(x86_xArgSTi),
- /*12405*/ uint16(x86_xArgST),
- /*12406*/ uint16(x86_xMatch),
- /*12407*/ uint16(x86_xSetOp), uint16(x86_FSUBP),
- /*12409*/ uint16(x86_xArgSTi),
- /*12410*/ uint16(x86_xArgST),
- /*12411*/ uint16(x86_xMatch),
- /*12412*/ uint16(x86_xSetOp), uint16(x86_FDIVRP),
- /*12414*/ uint16(x86_xArgSTi),
- /*12415*/ uint16(x86_xArgST),
- /*12416*/ uint16(x86_xMatch),
- /*12417*/ uint16(x86_xSetOp), uint16(x86_FDIVP),
- /*12419*/ uint16(x86_xArgSTi),
- /*12420*/ uint16(x86_xArgST),
- /*12421*/ uint16(x86_xMatch),
- /*12422*/ uint16(x86_xCondByte), 25,
- 0xc0, 12515,
- 0xc1, 12515,
- 0xc2, 12515,
- 0xc3, 12515,
- 0xc4, 12515,
- 0xc5, 12515,
- 0xc6, 12515,
- 0xc7, 12515,
- 0xE0, 12519,
- 0xe8, 12523,
- 0xe9, 12523,
- 0xea, 12523,
- 0xeb, 12523,
- 0xec, 12523,
- 0xed, 12523,
- 0xee, 12523,
- 0xef, 12523,
- 0xf0, 12528,
- 0xf1, 12528,
- 0xf2, 12528,
- 0xf3, 12528,
- 0xf4, 12528,
- 0xf5, 12528,
- 0xf6, 12528,
- 0xf7, 12528,
- /*12474*/ uint16(x86_xCondSlashR),
- 12483, // 0
- 12487, // 1
- 12491, // 2
- 12495, // 3
- 12499, // 4
- 12503, // 5
- 12507, // 6
- 12511, // 7
- /*12483*/ uint16(x86_xSetOp), uint16(x86_FILD),
- /*12485*/ uint16(x86_xArgM16int),
- /*12486*/ uint16(x86_xMatch),
- /*12487*/ uint16(x86_xSetOp), uint16(x86_FISTTP),
- /*12489*/ uint16(x86_xArgM16int),
- /*12490*/ uint16(x86_xMatch),
- /*12491*/ uint16(x86_xSetOp), uint16(x86_FIST),
- /*12493*/ uint16(x86_xArgM16int),
- /*12494*/ uint16(x86_xMatch),
- /*12495*/ uint16(x86_xSetOp), uint16(x86_FISTP),
- /*12497*/ uint16(x86_xArgM16int),
- /*12498*/ uint16(x86_xMatch),
- /*12499*/ uint16(x86_xSetOp), uint16(x86_FBLD),
- /*12501*/ uint16(x86_xArgM80dec),
- /*12502*/ uint16(x86_xMatch),
- /*12503*/ uint16(x86_xSetOp), uint16(x86_FILD),
- /*12505*/ uint16(x86_xArgM64int),
- /*12506*/ uint16(x86_xMatch),
- /*12507*/ uint16(x86_xSetOp), uint16(x86_FBSTP),
- /*12509*/ uint16(x86_xArgM80bcd),
- /*12510*/ uint16(x86_xMatch),
- /*12511*/ uint16(x86_xSetOp), uint16(x86_FISTP),
- /*12513*/ uint16(x86_xArgM64int),
- /*12514*/ uint16(x86_xMatch),
- /*12515*/ uint16(x86_xSetOp), uint16(x86_FFREEP),
- /*12517*/ uint16(x86_xArgSTi),
- /*12518*/ uint16(x86_xMatch),
- /*12519*/ uint16(x86_xSetOp), uint16(x86_FNSTSW),
- /*12521*/ uint16(x86_xArgAX),
- /*12522*/ uint16(x86_xMatch),
- /*12523*/ uint16(x86_xSetOp), uint16(x86_FUCOMIP),
- /*12525*/ uint16(x86_xArgST),
- /*12526*/ uint16(x86_xArgSTi),
- /*12527*/ uint16(x86_xMatch),
- /*12528*/ uint16(x86_xSetOp), uint16(x86_FCOMIP),
- /*12530*/ uint16(x86_xArgST),
- /*12531*/ uint16(x86_xArgSTi),
- /*12532*/ uint16(x86_xMatch),
- /*12533*/ uint16(x86_xSetOp), uint16(x86_LOOPNE),
- /*12535*/ uint16(x86_xReadCb),
- /*12536*/ uint16(x86_xArgRel8),
- /*12537*/ uint16(x86_xMatch),
- /*12538*/ uint16(x86_xSetOp), uint16(x86_LOOPE),
- /*12540*/ uint16(x86_xReadCb),
- /*12541*/ uint16(x86_xArgRel8),
- /*12542*/ uint16(x86_xMatch),
- /*12543*/ uint16(x86_xSetOp), uint16(x86_LOOP),
- /*12545*/ uint16(x86_xReadCb),
- /*12546*/ uint16(x86_xArgRel8),
- /*12547*/ uint16(x86_xMatch),
- /*12548*/ uint16(x86_xCondIs64), 12551, 12565,
- /*12551*/ uint16(x86_xCondAddrSize), 12555, 12560, 0,
- /*12555*/ uint16(x86_xSetOp), uint16(x86_JCXZ),
- /*12557*/ uint16(x86_xReadCb),
- /*12558*/ uint16(x86_xArgRel8),
- /*12559*/ uint16(x86_xMatch),
- /*12560*/ uint16(x86_xSetOp), uint16(x86_JECXZ),
- /*12562*/ uint16(x86_xReadCb),
- /*12563*/ uint16(x86_xArgRel8),
- /*12564*/ uint16(x86_xMatch),
- /*12565*/ uint16(x86_xCondAddrSize), 0, 12560, 12569,
- /*12569*/ uint16(x86_xSetOp), uint16(x86_JRCXZ),
- /*12571*/ uint16(x86_xReadCb),
- /*12572*/ uint16(x86_xArgRel8),
- /*12573*/ uint16(x86_xMatch),
- /*12574*/ uint16(x86_xSetOp), uint16(x86_IN),
- /*12576*/ uint16(x86_xReadIb),
- /*12577*/ uint16(x86_xArgAL),
- /*12578*/ uint16(x86_xArgImm8u),
- /*12579*/ uint16(x86_xMatch),
- /*12580*/ uint16(x86_xCondDataSize), 12584, 12590, 12596,
- /*12584*/ uint16(x86_xSetOp), uint16(x86_IN),
- /*12586*/ uint16(x86_xReadIb),
- /*12587*/ uint16(x86_xArgAX),
- /*12588*/ uint16(x86_xArgImm8u),
- /*12589*/ uint16(x86_xMatch),
- /*12590*/ uint16(x86_xSetOp), uint16(x86_IN),
- /*12592*/ uint16(x86_xReadIb),
- /*12593*/ uint16(x86_xArgEAX),
- /*12594*/ uint16(x86_xArgImm8u),
- /*12595*/ uint16(x86_xMatch),
- /*12596*/ uint16(x86_xSetOp), uint16(x86_IN),
- /*12598*/ uint16(x86_xReadIb),
- /*12599*/ uint16(x86_xArgEAX),
- /*12600*/ uint16(x86_xArgImm8u),
- /*12601*/ uint16(x86_xMatch),
- /*12602*/ uint16(x86_xSetOp), uint16(x86_OUT),
- /*12604*/ uint16(x86_xReadIb),
- /*12605*/ uint16(x86_xArgImm8u),
- /*12606*/ uint16(x86_xArgAL),
- /*12607*/ uint16(x86_xMatch),
- /*12608*/ uint16(x86_xCondDataSize), 12612, 12618, 12624,
- /*12612*/ uint16(x86_xSetOp), uint16(x86_OUT),
- /*12614*/ uint16(x86_xReadIb),
- /*12615*/ uint16(x86_xArgImm8u),
- /*12616*/ uint16(x86_xArgAX),
- /*12617*/ uint16(x86_xMatch),
- /*12618*/ uint16(x86_xSetOp), uint16(x86_OUT),
- /*12620*/ uint16(x86_xReadIb),
- /*12621*/ uint16(x86_xArgImm8u),
- /*12622*/ uint16(x86_xArgEAX),
- /*12623*/ uint16(x86_xMatch),
- /*12624*/ uint16(x86_xSetOp), uint16(x86_OUT),
- /*12626*/ uint16(x86_xReadIb),
- /*12627*/ uint16(x86_xArgImm8u),
- /*12628*/ uint16(x86_xArgEAX),
- /*12629*/ uint16(x86_xMatch),
- /*12630*/ uint16(x86_xCondIs64), 12633, 12647,
- /*12633*/ uint16(x86_xCondDataSize), 12637, 12642, 0,
- /*12637*/ uint16(x86_xSetOp), uint16(x86_CALL),
- /*12639*/ uint16(x86_xReadCw),
- /*12640*/ uint16(x86_xArgRel16),
- /*12641*/ uint16(x86_xMatch),
- /*12642*/ uint16(x86_xSetOp), uint16(x86_CALL),
- /*12644*/ uint16(x86_xReadCd),
- /*12645*/ uint16(x86_xArgRel32),
- /*12646*/ uint16(x86_xMatch),
- /*12647*/ uint16(x86_xCondDataSize), 12651, 12642, 12656,
- /*12651*/ uint16(x86_xSetOp), uint16(x86_CALL),
- /*12653*/ uint16(x86_xReadCd),
- /*12654*/ uint16(x86_xArgRel32),
- /*12655*/ uint16(x86_xMatch),
- /*12656*/ uint16(x86_xSetOp), uint16(x86_CALL),
- /*12658*/ uint16(x86_xReadCd),
- /*12659*/ uint16(x86_xArgRel32),
- /*12660*/ uint16(x86_xMatch),
- /*12661*/ uint16(x86_xCondIs64), 12664, 12678,
- /*12664*/ uint16(x86_xCondDataSize), 12668, 12673, 0,
- /*12668*/ uint16(x86_xSetOp), uint16(x86_JMP),
- /*12670*/ uint16(x86_xReadCw),
- /*12671*/ uint16(x86_xArgRel16),
- /*12672*/ uint16(x86_xMatch),
- /*12673*/ uint16(x86_xSetOp), uint16(x86_JMP),
- /*12675*/ uint16(x86_xReadCd),
- /*12676*/ uint16(x86_xArgRel32),
- /*12677*/ uint16(x86_xMatch),
- /*12678*/ uint16(x86_xCondDataSize), 12682, 12673, 12687,
- /*12682*/ uint16(x86_xSetOp), uint16(x86_JMP),
- /*12684*/ uint16(x86_xReadCd),
- /*12685*/ uint16(x86_xArgRel32),
- /*12686*/ uint16(x86_xMatch),
- /*12687*/ uint16(x86_xSetOp), uint16(x86_JMP),
- /*12689*/ uint16(x86_xReadCd),
- /*12690*/ uint16(x86_xArgRel32),
- /*12691*/ uint16(x86_xMatch),
- /*12692*/ uint16(x86_xCondIs64), 12695, 0,
- /*12695*/ uint16(x86_xCondDataSize), 12699, 12704, 0,
- /*12699*/ uint16(x86_xSetOp), uint16(x86_LJMP),
- /*12701*/ uint16(x86_xReadCd),
- /*12702*/ uint16(x86_xArgPtr16colon16),
- /*12703*/ uint16(x86_xMatch),
- /*12704*/ uint16(x86_xSetOp), uint16(x86_LJMP),
- /*12706*/ uint16(x86_xReadCp),
- /*12707*/ uint16(x86_xArgPtr16colon32),
- /*12708*/ uint16(x86_xMatch),
- /*12709*/ uint16(x86_xSetOp), uint16(x86_JMP),
- /*12711*/ uint16(x86_xReadCb),
- /*12712*/ uint16(x86_xArgRel8),
- /*12713*/ uint16(x86_xMatch),
- /*12714*/ uint16(x86_xSetOp), uint16(x86_IN),
- /*12716*/ uint16(x86_xArgAL),
- /*12717*/ uint16(x86_xArgDX),
- /*12718*/ uint16(x86_xMatch),
- /*12719*/ uint16(x86_xCondDataSize), 12723, 12728, 12733,
- /*12723*/ uint16(x86_xSetOp), uint16(x86_IN),
- /*12725*/ uint16(x86_xArgAX),
- /*12726*/ uint16(x86_xArgDX),
- /*12727*/ uint16(x86_xMatch),
- /*12728*/ uint16(x86_xSetOp), uint16(x86_IN),
- /*12730*/ uint16(x86_xArgEAX),
- /*12731*/ uint16(x86_xArgDX),
- /*12732*/ uint16(x86_xMatch),
- /*12733*/ uint16(x86_xSetOp), uint16(x86_IN),
- /*12735*/ uint16(x86_xArgEAX),
- /*12736*/ uint16(x86_xArgDX),
- /*12737*/ uint16(x86_xMatch),
- /*12738*/ uint16(x86_xSetOp), uint16(x86_OUT),
- /*12740*/ uint16(x86_xArgDX),
- /*12741*/ uint16(x86_xArgAL),
- /*12742*/ uint16(x86_xMatch),
- /*12743*/ uint16(x86_xCondDataSize), 12747, 12752, 12757,
- /*12747*/ uint16(x86_xSetOp), uint16(x86_OUT),
- /*12749*/ uint16(x86_xArgDX),
- /*12750*/ uint16(x86_xArgAX),
- /*12751*/ uint16(x86_xMatch),
- /*12752*/ uint16(x86_xSetOp), uint16(x86_OUT),
- /*12754*/ uint16(x86_xArgDX),
- /*12755*/ uint16(x86_xArgEAX),
- /*12756*/ uint16(x86_xMatch),
- /*12757*/ uint16(x86_xSetOp), uint16(x86_OUT),
- /*12759*/ uint16(x86_xArgDX),
- /*12760*/ uint16(x86_xArgEAX),
- /*12761*/ uint16(x86_xMatch),
- /*12762*/ uint16(x86_xSetOp), uint16(x86_ICEBP),
- /*12764*/ uint16(x86_xMatch),
- /*12765*/ uint16(x86_xSetOp), uint16(x86_HLT),
- /*12767*/ uint16(x86_xMatch),
- /*12768*/ uint16(x86_xSetOp), uint16(x86_CMC),
- /*12770*/ uint16(x86_xMatch),
- /*12771*/ uint16(x86_xCondSlashR),
- 12780, // 0
- 0, // 1
- 12786, // 2
- 12790, // 3
- 12794, // 4
- 12798, // 5
- 12802, // 6
- 12806, // 7
- /*12780*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*12782*/ uint16(x86_xReadIb),
- /*12783*/ uint16(x86_xArgRM8),
- /*12784*/ uint16(x86_xArgImm8u),
- /*12785*/ uint16(x86_xMatch),
- /*12786*/ uint16(x86_xSetOp), uint16(x86_NOT),
- /*12788*/ uint16(x86_xArgRM8),
- /*12789*/ uint16(x86_xMatch),
- /*12790*/ uint16(x86_xSetOp), uint16(x86_NEG),
- /*12792*/ uint16(x86_xArgRM8),
- /*12793*/ uint16(x86_xMatch),
- /*12794*/ uint16(x86_xSetOp), uint16(x86_MUL),
- /*12796*/ uint16(x86_xArgRM8),
- /*12797*/ uint16(x86_xMatch),
- /*12798*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*12800*/ uint16(x86_xArgRM8),
- /*12801*/ uint16(x86_xMatch),
- /*12802*/ uint16(x86_xSetOp), uint16(x86_DIV),
- /*12804*/ uint16(x86_xArgRM8),
- /*12805*/ uint16(x86_xMatch),
- /*12806*/ uint16(x86_xSetOp), uint16(x86_IDIV),
- /*12808*/ uint16(x86_xArgRM8),
- /*12809*/ uint16(x86_xMatch),
- /*12810*/ uint16(x86_xCondSlashR),
- 12819, // 0
- 0, // 1
- 12848, // 2
- 12871, // 3
- 12894, // 4
- 12917, // 5
- 12940, // 6
- 12963, // 7
- /*12819*/ uint16(x86_xCondIs64), 12822, 12838,
- /*12822*/ uint16(x86_xCondDataSize), 12826, 12832, 0,
- /*12826*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*12828*/ uint16(x86_xReadIw),
- /*12829*/ uint16(x86_xArgRM16),
- /*12830*/ uint16(x86_xArgImm16),
- /*12831*/ uint16(x86_xMatch),
- /*12832*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*12834*/ uint16(x86_xReadId),
- /*12835*/ uint16(x86_xArgRM32),
- /*12836*/ uint16(x86_xArgImm32),
- /*12837*/ uint16(x86_xMatch),
- /*12838*/ uint16(x86_xCondDataSize), 12826, 12832, 12842,
- /*12842*/ uint16(x86_xSetOp), uint16(x86_TEST),
- /*12844*/ uint16(x86_xReadId),
- /*12845*/ uint16(x86_xArgRM64),
- /*12846*/ uint16(x86_xArgImm32),
- /*12847*/ uint16(x86_xMatch),
- /*12848*/ uint16(x86_xCondIs64), 12851, 12863,
- /*12851*/ uint16(x86_xCondDataSize), 12855, 12859, 0,
- /*12855*/ uint16(x86_xSetOp), uint16(x86_NOT),
- /*12857*/ uint16(x86_xArgRM16),
- /*12858*/ uint16(x86_xMatch),
- /*12859*/ uint16(x86_xSetOp), uint16(x86_NOT),
- /*12861*/ uint16(x86_xArgRM32),
- /*12862*/ uint16(x86_xMatch),
- /*12863*/ uint16(x86_xCondDataSize), 12855, 12859, 12867,
- /*12867*/ uint16(x86_xSetOp), uint16(x86_NOT),
- /*12869*/ uint16(x86_xArgRM64),
- /*12870*/ uint16(x86_xMatch),
- /*12871*/ uint16(x86_xCondIs64), 12874, 12886,
- /*12874*/ uint16(x86_xCondDataSize), 12878, 12882, 0,
- /*12878*/ uint16(x86_xSetOp), uint16(x86_NEG),
- /*12880*/ uint16(x86_xArgRM16),
- /*12881*/ uint16(x86_xMatch),
- /*12882*/ uint16(x86_xSetOp), uint16(x86_NEG),
- /*12884*/ uint16(x86_xArgRM32),
- /*12885*/ uint16(x86_xMatch),
- /*12886*/ uint16(x86_xCondDataSize), 12878, 12882, 12890,
- /*12890*/ uint16(x86_xSetOp), uint16(x86_NEG),
- /*12892*/ uint16(x86_xArgRM64),
- /*12893*/ uint16(x86_xMatch),
- /*12894*/ uint16(x86_xCondIs64), 12897, 12909,
- /*12897*/ uint16(x86_xCondDataSize), 12901, 12905, 0,
- /*12901*/ uint16(x86_xSetOp), uint16(x86_MUL),
- /*12903*/ uint16(x86_xArgRM16),
- /*12904*/ uint16(x86_xMatch),
- /*12905*/ uint16(x86_xSetOp), uint16(x86_MUL),
- /*12907*/ uint16(x86_xArgRM32),
- /*12908*/ uint16(x86_xMatch),
- /*12909*/ uint16(x86_xCondDataSize), 12901, 12905, 12913,
- /*12913*/ uint16(x86_xSetOp), uint16(x86_MUL),
- /*12915*/ uint16(x86_xArgRM64),
- /*12916*/ uint16(x86_xMatch),
- /*12917*/ uint16(x86_xCondIs64), 12920, 12932,
- /*12920*/ uint16(x86_xCondDataSize), 12924, 12928, 0,
- /*12924*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*12926*/ uint16(x86_xArgRM16),
- /*12927*/ uint16(x86_xMatch),
- /*12928*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*12930*/ uint16(x86_xArgRM32),
- /*12931*/ uint16(x86_xMatch),
- /*12932*/ uint16(x86_xCondDataSize), 12924, 12928, 12936,
- /*12936*/ uint16(x86_xSetOp), uint16(x86_IMUL),
- /*12938*/ uint16(x86_xArgRM64),
- /*12939*/ uint16(x86_xMatch),
- /*12940*/ uint16(x86_xCondIs64), 12943, 12955,
- /*12943*/ uint16(x86_xCondDataSize), 12947, 12951, 0,
- /*12947*/ uint16(x86_xSetOp), uint16(x86_DIV),
- /*12949*/ uint16(x86_xArgRM16),
- /*12950*/ uint16(x86_xMatch),
- /*12951*/ uint16(x86_xSetOp), uint16(x86_DIV),
- /*12953*/ uint16(x86_xArgRM32),
- /*12954*/ uint16(x86_xMatch),
- /*12955*/ uint16(x86_xCondDataSize), 12947, 12951, 12959,
- /*12959*/ uint16(x86_xSetOp), uint16(x86_DIV),
- /*12961*/ uint16(x86_xArgRM64),
- /*12962*/ uint16(x86_xMatch),
- /*12963*/ uint16(x86_xCondIs64), 12966, 12978,
- /*12966*/ uint16(x86_xCondDataSize), 12970, 12974, 0,
- /*12970*/ uint16(x86_xSetOp), uint16(x86_IDIV),
- /*12972*/ uint16(x86_xArgRM16),
- /*12973*/ uint16(x86_xMatch),
- /*12974*/ uint16(x86_xSetOp), uint16(x86_IDIV),
- /*12976*/ uint16(x86_xArgRM32),
- /*12977*/ uint16(x86_xMatch),
- /*12978*/ uint16(x86_xCondDataSize), 12970, 12974, 12982,
- /*12982*/ uint16(x86_xSetOp), uint16(x86_IDIV),
- /*12984*/ uint16(x86_xArgRM64),
- /*12985*/ uint16(x86_xMatch),
- /*12986*/ uint16(x86_xSetOp), uint16(x86_CLC),
- /*12988*/ uint16(x86_xMatch),
- /*12989*/ uint16(x86_xSetOp), uint16(x86_STC),
- /*12991*/ uint16(x86_xMatch),
- /*12992*/ uint16(x86_xSetOp), uint16(x86_CLI),
- /*12994*/ uint16(x86_xMatch),
- /*12995*/ uint16(x86_xSetOp), uint16(x86_STI),
- /*12997*/ uint16(x86_xMatch),
- /*12998*/ uint16(x86_xSetOp), uint16(x86_CLD),
- /*13000*/ uint16(x86_xMatch),
- /*13001*/ uint16(x86_xSetOp), uint16(x86_STD),
- /*13003*/ uint16(x86_xMatch),
- /*13004*/ uint16(x86_xCondSlashR),
- 13013, // 0
- 13017, // 1
- 0, // 2
- 0, // 3
- 0, // 4
- 0, // 5
- 0, // 6
- 0, // 7
- /*13013*/ uint16(x86_xSetOp), uint16(x86_INC),
- /*13015*/ uint16(x86_xArgRM8),
- /*13016*/ uint16(x86_xMatch),
- /*13017*/ uint16(x86_xSetOp), uint16(x86_DEC),
- /*13019*/ uint16(x86_xArgRM8),
- /*13020*/ uint16(x86_xMatch),
- /*13021*/ uint16(x86_xCondSlashR),
- 13030, // 0
- 13053, // 1
- 13076, // 2
- 13095, // 3
- 13118, // 4
- 13137, // 5
- 13160, // 6
- 0, // 7
- /*13030*/ uint16(x86_xCondIs64), 13033, 13045,
- /*13033*/ uint16(x86_xCondDataSize), 13037, 13041, 0,
- /*13037*/ uint16(x86_xSetOp), uint16(x86_INC),
- /*13039*/ uint16(x86_xArgRM16),
- /*13040*/ uint16(x86_xMatch),
- /*13041*/ uint16(x86_xSetOp), uint16(x86_INC),
- /*13043*/ uint16(x86_xArgRM32),
- /*13044*/ uint16(x86_xMatch),
- /*13045*/ uint16(x86_xCondDataSize), 13037, 13041, 13049,
- /*13049*/ uint16(x86_xSetOp), uint16(x86_INC),
- /*13051*/ uint16(x86_xArgRM64),
- /*13052*/ uint16(x86_xMatch),
- /*13053*/ uint16(x86_xCondIs64), 13056, 13068,
- /*13056*/ uint16(x86_xCondDataSize), 13060, 13064, 0,
- /*13060*/ uint16(x86_xSetOp), uint16(x86_DEC),
- /*13062*/ uint16(x86_xArgRM16),
- /*13063*/ uint16(x86_xMatch),
- /*13064*/ uint16(x86_xSetOp), uint16(x86_DEC),
- /*13066*/ uint16(x86_xArgRM32),
- /*13067*/ uint16(x86_xMatch),
- /*13068*/ uint16(x86_xCondDataSize), 13060, 13064, 13072,
- /*13072*/ uint16(x86_xSetOp), uint16(x86_DEC),
- /*13074*/ uint16(x86_xArgRM64),
- /*13075*/ uint16(x86_xMatch),
- /*13076*/ uint16(x86_xCondIs64), 13079, 13091,
- /*13079*/ uint16(x86_xCondDataSize), 13083, 13087, 0,
- /*13083*/ uint16(x86_xSetOp), uint16(x86_CALL),
- /*13085*/ uint16(x86_xArgRM16),
- /*13086*/ uint16(x86_xMatch),
- /*13087*/ uint16(x86_xSetOp), uint16(x86_CALL),
- /*13089*/ uint16(x86_xArgRM32),
- /*13090*/ uint16(x86_xMatch),
- /*13091*/ uint16(x86_xSetOp), uint16(x86_CALL),
- /*13093*/ uint16(x86_xArgRM64),
- /*13094*/ uint16(x86_xMatch),
- /*13095*/ uint16(x86_xCondIs64), 13098, 13110,
- /*13098*/ uint16(x86_xCondDataSize), 13102, 13106, 0,
- /*13102*/ uint16(x86_xSetOp), uint16(x86_LCALL),
- /*13104*/ uint16(x86_xArgM16colon16),
- /*13105*/ uint16(x86_xMatch),
- /*13106*/ uint16(x86_xSetOp), uint16(x86_LCALL),
- /*13108*/ uint16(x86_xArgM16colon32),
- /*13109*/ uint16(x86_xMatch),
- /*13110*/ uint16(x86_xCondDataSize), 13102, 13106, 13114,
- /*13114*/ uint16(x86_xSetOp), uint16(x86_LCALL),
- /*13116*/ uint16(x86_xArgM16colon64),
- /*13117*/ uint16(x86_xMatch),
- /*13118*/ uint16(x86_xCondIs64), 13121, 13133,
- /*13121*/ uint16(x86_xCondDataSize), 13125, 13129, 0,
- /*13125*/ uint16(x86_xSetOp), uint16(x86_JMP),
- /*13127*/ uint16(x86_xArgRM16),
- /*13128*/ uint16(x86_xMatch),
- /*13129*/ uint16(x86_xSetOp), uint16(x86_JMP),
- /*13131*/ uint16(x86_xArgRM32),
- /*13132*/ uint16(x86_xMatch),
- /*13133*/ uint16(x86_xSetOp), uint16(x86_JMP),
- /*13135*/ uint16(x86_xArgRM64),
- /*13136*/ uint16(x86_xMatch),
- /*13137*/ uint16(x86_xCondIs64), 13140, 13152,
- /*13140*/ uint16(x86_xCondDataSize), 13144, 13148, 0,
- /*13144*/ uint16(x86_xSetOp), uint16(x86_LJMP),
- /*13146*/ uint16(x86_xArgM16colon16),
- /*13147*/ uint16(x86_xMatch),
- /*13148*/ uint16(x86_xSetOp), uint16(x86_LJMP),
- /*13150*/ uint16(x86_xArgM16colon32),
- /*13151*/ uint16(x86_xMatch),
- /*13152*/ uint16(x86_xCondDataSize), 13144, 13148, 13156,
- /*13156*/ uint16(x86_xSetOp), uint16(x86_LJMP),
- /*13158*/ uint16(x86_xArgM16colon64),
- /*13159*/ uint16(x86_xMatch),
- /*13160*/ uint16(x86_xCondIs64), 13163, 13175,
- /*13163*/ uint16(x86_xCondDataSize), 13167, 13171, 0,
- /*13167*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*13169*/ uint16(x86_xArgRM16),
- /*13170*/ uint16(x86_xMatch),
- /*13171*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*13173*/ uint16(x86_xArgRM32),
- /*13174*/ uint16(x86_xMatch),
- /*13175*/ uint16(x86_xCondDataSize), 13167, 13179, 13183,
- /*13179*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*13181*/ uint16(x86_xArgRM64),
- /*13182*/ uint16(x86_xMatch),
- /*13183*/ uint16(x86_xSetOp), uint16(x86_PUSH),
- /*13185*/ uint16(x86_xArgRM64),
- /*13186*/ uint16(x86_xMatch),
-}
-
-const (
- _ x86_Op = iota
-
- x86_AAA
- x86_AAD
- x86_AAM
- x86_AAS
- x86_ADC
- x86_ADD
- x86_ADDPD
- x86_ADDPS
- x86_ADDSD
- x86_ADDSS
- x86_ADDSUBPD
- x86_ADDSUBPS
- x86_AESDEC
- x86_AESDECLAST
- x86_AESENC
- x86_AESENCLAST
- x86_AESIMC
- x86_AESKEYGENASSIST
- x86_AND
- x86_ANDNPD
- x86_ANDNPS
- x86_ANDPD
- x86_ANDPS
- x86_ARPL
- x86_BLENDPD
- x86_BLENDPS
- x86_BLENDVPD
- x86_BLENDVPS
- x86_BOUND
- x86_BSF
- x86_BSR
- x86_BSWAP
- x86_BT
- x86_BTC
- x86_BTR
- x86_BTS
- x86_CALL
- x86_CBW
- x86_CDQ
- x86_CDQE
- x86_CLC
- x86_CLD
- x86_CLFLUSH
- x86_CLI
- x86_CLTS
- x86_CMC
- x86_CMOVA
- x86_CMOVAE
- x86_CMOVB
- x86_CMOVBE
- x86_CMOVE
- x86_CMOVG
- x86_CMOVGE
- x86_CMOVL
- x86_CMOVLE
- x86_CMOVNE
- x86_CMOVNO
- x86_CMOVNP
- x86_CMOVNS
- x86_CMOVO
- x86_CMOVP
- x86_CMOVS
- x86_CMP
- x86_CMPPD
- x86_CMPPS
- x86_CMPSB
- x86_CMPSD
- x86_CMPSD_XMM
- x86_CMPSQ
- x86_CMPSS
- x86_CMPSW
- x86_CMPXCHG
- x86_CMPXCHG16B
- x86_CMPXCHG8B
- x86_COMISD
- x86_COMISS
- x86_CPUID
- x86_CQO
- x86_CRC32
- x86_CVTDQ2PD
- x86_CVTDQ2PS
- x86_CVTPD2DQ
- x86_CVTPD2PI
- x86_CVTPD2PS
- x86_CVTPI2PD
- x86_CVTPI2PS
- x86_CVTPS2DQ
- x86_CVTPS2PD
- x86_CVTPS2PI
- x86_CVTSD2SI
- x86_CVTSD2SS
- x86_CVTSI2SD
- x86_CVTSI2SS
- x86_CVTSS2SD
- x86_CVTSS2SI
- x86_CVTTPD2DQ
- x86_CVTTPD2PI
- x86_CVTTPS2DQ
- x86_CVTTPS2PI
- x86_CVTTSD2SI
- x86_CVTTSS2SI
- x86_CWD
- x86_CWDE
- x86_DAA
- x86_DAS
- x86_DEC
- x86_DIV
- x86_DIVPD
- x86_DIVPS
- x86_DIVSD
- x86_DIVSS
- x86_DPPD
- x86_DPPS
- x86_EMMS
- x86_ENTER
- x86_EXTRACTPS
- x86_F2XM1
- x86_FABS
- x86_FADD
- x86_FADDP
- x86_FBLD
- x86_FBSTP
- x86_FCHS
- x86_FCMOVB
- x86_FCMOVBE
- x86_FCMOVE
- x86_FCMOVNB
- x86_FCMOVNBE
- x86_FCMOVNE
- x86_FCMOVNU
- x86_FCMOVU
- x86_FCOM
- x86_FCOMI
- x86_FCOMIP
- x86_FCOMP
- x86_FCOMPP
- x86_FCOS
- x86_FDECSTP
- x86_FDIV
- x86_FDIVP
- x86_FDIVR
- x86_FDIVRP
- x86_FFREE
- x86_FFREEP
- x86_FIADD
- x86_FICOM
- x86_FICOMP
- x86_FIDIV
- x86_FIDIVR
- x86_FILD
- x86_FIMUL
- x86_FINCSTP
- x86_FIST
- x86_FISTP
- x86_FISTTP
- x86_FISUB
- x86_FISUBR
- x86_FLD
- x86_FLD1
- x86_FLDCW
- x86_FLDENV
- x86_FLDL2E
- x86_FLDL2T
- x86_FLDLG2
- x86_FLDPI
- x86_FMUL
- x86_FMULP
- x86_FNCLEX
- x86_FNINIT
- x86_FNOP
- x86_FNSAVE
- x86_FNSTCW
- x86_FNSTENV
- x86_FNSTSW
- x86_FPATAN
- x86_FPREM
- x86_FPREM1
- x86_FPTAN
- x86_FRNDINT
- x86_FRSTOR
- x86_FSCALE
- x86_FSIN
- x86_FSINCOS
- x86_FSQRT
- x86_FST
- x86_FSTP
- x86_FSUB
- x86_FSUBP
- x86_FSUBR
- x86_FSUBRP
- x86_FTST
- x86_FUCOM
- x86_FUCOMI
- x86_FUCOMIP
- x86_FUCOMP
- x86_FUCOMPP
- x86_FWAIT
- x86_FXAM
- x86_FXCH
- x86_FXRSTOR
- x86_FXRSTOR64
- x86_FXSAVE
- x86_FXSAVE64
- x86_FXTRACT
- x86_FYL2X
- x86_FYL2XP1
- x86_HADDPD
- x86_HADDPS
- x86_HLT
- x86_HSUBPD
- x86_HSUBPS
- x86_ICEBP
- x86_IDIV
- x86_IMUL
- x86_IN
- x86_INC
- x86_INSB
- x86_INSD
- x86_INSERTPS
- x86_INSW
- x86_INT
- x86_INTO
- x86_INVD
- x86_INVLPG
- x86_INVPCID
- x86_IRET
- x86_IRETD
- x86_IRETQ
- x86_JA
- x86_JAE
- x86_JB
- x86_JBE
- x86_JCXZ
- x86_JE
- x86_JECXZ
- x86_JG
- x86_JGE
- x86_JL
- x86_JLE
- x86_JMP
- x86_JNE
- x86_JNO
- x86_JNP
- x86_JNS
- x86_JO
- x86_JP
- x86_JRCXZ
- x86_JS
- x86_LAHF
- x86_LAR
- x86_LCALL
- x86_LDDQU
- x86_LDMXCSR
- x86_LDS
- x86_LEA
- x86_LEAVE
- x86_LES
- x86_LFENCE
- x86_LFS
- x86_LGDT
- x86_LGS
- x86_LIDT
- x86_LJMP
- x86_LLDT
- x86_LMSW
- x86_LODSB
- x86_LODSD
- x86_LODSQ
- x86_LODSW
- x86_LOOP
- x86_LOOPE
- x86_LOOPNE
- x86_LRET
- x86_LSL
- x86_LSS
- x86_LTR
- x86_LZCNT
- x86_MASKMOVDQU
- x86_MASKMOVQ
- x86_MAXPD
- x86_MAXPS
- x86_MAXSD
- x86_MAXSS
- x86_MFENCE
- x86_MINPD
- x86_MINPS
- x86_MINSD
- x86_MINSS
- x86_MONITOR
- x86_MOV
- x86_MOVAPD
- x86_MOVAPS
- x86_MOVBE
- x86_MOVD
- x86_MOVDDUP
- x86_MOVDQ2Q
- x86_MOVDQA
- x86_MOVDQU
- x86_MOVHLPS
- x86_MOVHPD
- x86_MOVHPS
- x86_MOVLHPS
- x86_MOVLPD
- x86_MOVLPS
- x86_MOVMSKPD
- x86_MOVMSKPS
- x86_MOVNTDQ
- x86_MOVNTDQA
- x86_MOVNTI
- x86_MOVNTPD
- x86_MOVNTPS
- x86_MOVNTQ
- x86_MOVNTSD
- x86_MOVNTSS
- x86_MOVQ
- x86_MOVQ2DQ
- x86_MOVSB
- x86_MOVSD
- x86_MOVSD_XMM
- x86_MOVSHDUP
- x86_MOVSLDUP
- x86_MOVSQ
- x86_MOVSS
- x86_MOVSW
- x86_MOVSX
- x86_MOVSXD
- x86_MOVUPD
- x86_MOVUPS
- x86_MOVZX
- x86_MPSADBW
- x86_MUL
- x86_MULPD
- x86_MULPS
- x86_MULSD
- x86_MULSS
- x86_MWAIT
- x86_NEG
- x86_NOP
- x86_NOT
- x86_OR
- x86_ORPD
- x86_ORPS
- x86_OUT
- x86_OUTSB
- x86_OUTSD
- x86_OUTSW
- x86_PABSB
- x86_PABSD
- x86_PABSW
- x86_PACKSSDW
- x86_PACKSSWB
- x86_PACKUSDW
- x86_PACKUSWB
- x86_PADDB
- x86_PADDD
- x86_PADDQ
- x86_PADDSB
- x86_PADDSW
- x86_PADDUSB
- x86_PADDUSW
- x86_PADDW
- x86_PALIGNR
- x86_PAND
- x86_PANDN
- x86_PAUSE
- x86_PAVGB
- x86_PAVGW
- x86_PBLENDVB
- x86_PBLENDW
- x86_PCLMULQDQ
- x86_PCMPEQB
- x86_PCMPEQD
- x86_PCMPEQQ
- x86_PCMPEQW
- x86_PCMPESTRI
- x86_PCMPESTRM
- x86_PCMPGTB
- x86_PCMPGTD
- x86_PCMPGTQ
- x86_PCMPGTW
- x86_PCMPISTRI
- x86_PCMPISTRM
- x86_PEXTRB
- x86_PEXTRD
- x86_PEXTRQ
- x86_PEXTRW
- x86_PHADDD
- x86_PHADDSW
- x86_PHADDW
- x86_PHMINPOSUW
- x86_PHSUBD
- x86_PHSUBSW
- x86_PHSUBW
- x86_PINSRB
- x86_PINSRD
- x86_PINSRQ
- x86_PINSRW
- x86_PMADDUBSW
- x86_PMADDWD
- x86_PMAXSB
- x86_PMAXSD
- x86_PMAXSW
- x86_PMAXUB
- x86_PMAXUD
- x86_PMAXUW
- x86_PMINSB
- x86_PMINSD
- x86_PMINSW
- x86_PMINUB
- x86_PMINUD
- x86_PMINUW
- x86_PMOVMSKB
- x86_PMOVSXBD
- x86_PMOVSXBQ
- x86_PMOVSXBW
- x86_PMOVSXDQ
- x86_PMOVSXWD
- x86_PMOVSXWQ
- x86_PMOVZXBD
- x86_PMOVZXBQ
- x86_PMOVZXBW
- x86_PMOVZXDQ
- x86_PMOVZXWD
- x86_PMOVZXWQ
- x86_PMULDQ
- x86_PMULHRSW
- x86_PMULHUW
- x86_PMULHW
- x86_PMULLD
- x86_PMULLW
- x86_PMULUDQ
- x86_POP
- x86_POPA
- x86_POPAD
- x86_POPCNT
- x86_POPF
- x86_POPFD
- x86_POPFQ
- x86_POR
- x86_PREFETCHNTA
- x86_PREFETCHT0
- x86_PREFETCHT1
- x86_PREFETCHT2
- x86_PREFETCHW
- x86_PSADBW
- x86_PSHUFB
- x86_PSHUFD
- x86_PSHUFHW
- x86_PSHUFLW
- x86_PSHUFW
- x86_PSIGNB
- x86_PSIGND
- x86_PSIGNW
- x86_PSLLD
- x86_PSLLDQ
- x86_PSLLQ
- x86_PSLLW
- x86_PSRAD
- x86_PSRAW
- x86_PSRLD
- x86_PSRLDQ
- x86_PSRLQ
- x86_PSRLW
- x86_PSUBB
- x86_PSUBD
- x86_PSUBQ
- x86_PSUBSB
- x86_PSUBSW
- x86_PSUBUSB
- x86_PSUBUSW
- x86_PSUBW
- x86_PTEST
- x86_PUNPCKHBW
- x86_PUNPCKHDQ
- x86_PUNPCKHQDQ
- x86_PUNPCKHWD
- x86_PUNPCKLBW
- x86_PUNPCKLDQ
- x86_PUNPCKLQDQ
- x86_PUNPCKLWD
- x86_PUSH
- x86_PUSHA
- x86_PUSHAD
- x86_PUSHF
- x86_PUSHFD
- x86_PUSHFQ
- x86_PXOR
- x86_RCL
- x86_RCPPS
- x86_RCPSS
- x86_RCR
- x86_RDFSBASE
- x86_RDGSBASE
- x86_RDMSR
- x86_RDPMC
- x86_RDRAND
- x86_RDTSC
- x86_RDTSCP
- x86_RET
- x86_ROL
- x86_ROR
- x86_ROUNDPD
- x86_ROUNDPS
- x86_ROUNDSD
- x86_ROUNDSS
- x86_RSM
- x86_RSQRTPS
- x86_RSQRTSS
- x86_SAHF
- x86_SAR
- x86_SBB
- x86_SCASB
- x86_SCASD
- x86_SCASQ
- x86_SCASW
- x86_SETA
- x86_SETAE
- x86_SETB
- x86_SETBE
- x86_SETE
- x86_SETG
- x86_SETGE
- x86_SETL
- x86_SETLE
- x86_SETNE
- x86_SETNO
- x86_SETNP
- x86_SETNS
- x86_SETO
- x86_SETP
- x86_SETS
- x86_SFENCE
- x86_SGDT
- x86_SHL
- x86_SHLD
- x86_SHR
- x86_SHRD
- x86_SHUFPD
- x86_SHUFPS
- x86_SIDT
- x86_SLDT
- x86_SMSW
- x86_SQRTPD
- x86_SQRTPS
- x86_SQRTSD
- x86_SQRTSS
- x86_STC
- x86_STD
- x86_STI
- x86_STMXCSR
- x86_STOSB
- x86_STOSD
- x86_STOSQ
- x86_STOSW
- x86_STR
- x86_SUB
- x86_SUBPD
- x86_SUBPS
- x86_SUBSD
- x86_SUBSS
- x86_SWAPGS
- x86_SYSCALL
- x86_SYSENTER
- x86_SYSEXIT
- x86_SYSRET
- x86_TEST
- x86_TZCNT
- x86_UCOMISD
- x86_UCOMISS
- x86_UD1
- x86_UD2
- x86_UNPCKHPD
- x86_UNPCKHPS
- x86_UNPCKLPD
- x86_UNPCKLPS
- x86_VERR
- x86_VERW
- x86_WBINVD
- x86_WRFSBASE
- x86_WRGSBASE
- x86_WRMSR
- x86_XABORT
- x86_XADD
- x86_XBEGIN
- x86_XCHG
- x86_XEND
- x86_XGETBV
- x86_XLATB
- x86_XOR
- x86_XORPD
- x86_XORPS
- x86_XRSTOR
- x86_XRSTOR64
- x86_XRSTORS
- x86_XRSTORS64
- x86_XSAVE
- x86_XSAVE64
- x86_XSAVEC
- x86_XSAVEC64
- x86_XSAVEOPT
- x86_XSAVEOPT64
- x86_XSAVES
- x86_XSAVES64
- x86_XSETBV
- x86_XTEST
-)
-
-const x86_maxOp = x86_XTEST
-
-var x86_opNames = [...]string{
- x86_AAA: "AAA",
- x86_AAD: "AAD",
- x86_AAM: "AAM",
- x86_AAS: "AAS",
- x86_ADC: "ADC",
- x86_ADD: "ADD",
- x86_ADDPD: "ADDPD",
- x86_ADDPS: "ADDPS",
- x86_ADDSD: "ADDSD",
- x86_ADDSS: "ADDSS",
- x86_ADDSUBPD: "ADDSUBPD",
- x86_ADDSUBPS: "ADDSUBPS",
- x86_AESDEC: "AESDEC",
- x86_AESDECLAST: "AESDECLAST",
- x86_AESENC: "AESENC",
- x86_AESENCLAST: "AESENCLAST",
- x86_AESIMC: "AESIMC",
- x86_AESKEYGENASSIST: "AESKEYGENASSIST",
- x86_AND: "AND",
- x86_ANDNPD: "ANDNPD",
- x86_ANDNPS: "ANDNPS",
- x86_ANDPD: "ANDPD",
- x86_ANDPS: "ANDPS",
- x86_ARPL: "ARPL",
- x86_BLENDPD: "BLENDPD",
- x86_BLENDPS: "BLENDPS",
- x86_BLENDVPD: "BLENDVPD",
- x86_BLENDVPS: "BLENDVPS",
- x86_BOUND: "BOUND",
- x86_BSF: "BSF",
- x86_BSR: "BSR",
- x86_BSWAP: "BSWAP",
- x86_BT: "BT",
- x86_BTC: "BTC",
- x86_BTR: "BTR",
- x86_BTS: "BTS",
- x86_CALL: "CALL",
- x86_CBW: "CBW",
- x86_CDQ: "CDQ",
- x86_CDQE: "CDQE",
- x86_CLC: "CLC",
- x86_CLD: "CLD",
- x86_CLFLUSH: "CLFLUSH",
- x86_CLI: "CLI",
- x86_CLTS: "CLTS",
- x86_CMC: "CMC",
- x86_CMOVA: "CMOVA",
- x86_CMOVAE: "CMOVAE",
- x86_CMOVB: "CMOVB",
- x86_CMOVBE: "CMOVBE",
- x86_CMOVE: "CMOVE",
- x86_CMOVG: "CMOVG",
- x86_CMOVGE: "CMOVGE",
- x86_CMOVL: "CMOVL",
- x86_CMOVLE: "CMOVLE",
- x86_CMOVNE: "CMOVNE",
- x86_CMOVNO: "CMOVNO",
- x86_CMOVNP: "CMOVNP",
- x86_CMOVNS: "CMOVNS",
- x86_CMOVO: "CMOVO",
- x86_CMOVP: "CMOVP",
- x86_CMOVS: "CMOVS",
- x86_CMP: "CMP",
- x86_CMPPD: "CMPPD",
- x86_CMPPS: "CMPPS",
- x86_CMPSB: "CMPSB",
- x86_CMPSD: "CMPSD",
- x86_CMPSD_XMM: "CMPSD_XMM",
- x86_CMPSQ: "CMPSQ",
- x86_CMPSS: "CMPSS",
- x86_CMPSW: "CMPSW",
- x86_CMPXCHG: "CMPXCHG",
- x86_CMPXCHG16B: "CMPXCHG16B",
- x86_CMPXCHG8B: "CMPXCHG8B",
- x86_COMISD: "COMISD",
- x86_COMISS: "COMISS",
- x86_CPUID: "CPUID",
- x86_CQO: "CQO",
- x86_CRC32: "CRC32",
- x86_CVTDQ2PD: "CVTDQ2PD",
- x86_CVTDQ2PS: "CVTDQ2PS",
- x86_CVTPD2DQ: "CVTPD2DQ",
- x86_CVTPD2PI: "CVTPD2PI",
- x86_CVTPD2PS: "CVTPD2PS",
- x86_CVTPI2PD: "CVTPI2PD",
- x86_CVTPI2PS: "CVTPI2PS",
- x86_CVTPS2DQ: "CVTPS2DQ",
- x86_CVTPS2PD: "CVTPS2PD",
- x86_CVTPS2PI: "CVTPS2PI",
- x86_CVTSD2SI: "CVTSD2SI",
- x86_CVTSD2SS: "CVTSD2SS",
- x86_CVTSI2SD: "CVTSI2SD",
- x86_CVTSI2SS: "CVTSI2SS",
- x86_CVTSS2SD: "CVTSS2SD",
- x86_CVTSS2SI: "CVTSS2SI",
- x86_CVTTPD2DQ: "CVTTPD2DQ",
- x86_CVTTPD2PI: "CVTTPD2PI",
- x86_CVTTPS2DQ: "CVTTPS2DQ",
- x86_CVTTPS2PI: "CVTTPS2PI",
- x86_CVTTSD2SI: "CVTTSD2SI",
- x86_CVTTSS2SI: "CVTTSS2SI",
- x86_CWD: "CWD",
- x86_CWDE: "CWDE",
- x86_DAA: "DAA",
- x86_DAS: "DAS",
- x86_DEC: "DEC",
- x86_DIV: "DIV",
- x86_DIVPD: "DIVPD",
- x86_DIVPS: "DIVPS",
- x86_DIVSD: "DIVSD",
- x86_DIVSS: "DIVSS",
- x86_DPPD: "DPPD",
- x86_DPPS: "DPPS",
- x86_EMMS: "EMMS",
- x86_ENTER: "ENTER",
- x86_EXTRACTPS: "EXTRACTPS",
- x86_F2XM1: "F2XM1",
- x86_FABS: "FABS",
- x86_FADD: "FADD",
- x86_FADDP: "FADDP",
- x86_FBLD: "FBLD",
- x86_FBSTP: "FBSTP",
- x86_FCHS: "FCHS",
- x86_FCMOVB: "FCMOVB",
- x86_FCMOVBE: "FCMOVBE",
- x86_FCMOVE: "FCMOVE",
- x86_FCMOVNB: "FCMOVNB",
- x86_FCMOVNBE: "FCMOVNBE",
- x86_FCMOVNE: "FCMOVNE",
- x86_FCMOVNU: "FCMOVNU",
- x86_FCMOVU: "FCMOVU",
- x86_FCOM: "FCOM",
- x86_FCOMI: "FCOMI",
- x86_FCOMIP: "FCOMIP",
- x86_FCOMP: "FCOMP",
- x86_FCOMPP: "FCOMPP",
- x86_FCOS: "FCOS",
- x86_FDECSTP: "FDECSTP",
- x86_FDIV: "FDIV",
- x86_FDIVP: "FDIVP",
- x86_FDIVR: "FDIVR",
- x86_FDIVRP: "FDIVRP",
- x86_FFREE: "FFREE",
- x86_FFREEP: "FFREEP",
- x86_FIADD: "FIADD",
- x86_FICOM: "FICOM",
- x86_FICOMP: "FICOMP",
- x86_FIDIV: "FIDIV",
- x86_FIDIVR: "FIDIVR",
- x86_FILD: "FILD",
- x86_FIMUL: "FIMUL",
- x86_FINCSTP: "FINCSTP",
- x86_FIST: "FIST",
- x86_FISTP: "FISTP",
- x86_FISTTP: "FISTTP",
- x86_FISUB: "FISUB",
- x86_FISUBR: "FISUBR",
- x86_FLD: "FLD",
- x86_FLD1: "FLD1",
- x86_FLDCW: "FLDCW",
- x86_FLDENV: "FLDENV",
- x86_FLDL2E: "FLDL2E",
- x86_FLDL2T: "FLDL2T",
- x86_FLDLG2: "FLDLG2",
- x86_FLDPI: "FLDPI",
- x86_FMUL: "FMUL",
- x86_FMULP: "FMULP",
- x86_FNCLEX: "FNCLEX",
- x86_FNINIT: "FNINIT",
- x86_FNOP: "FNOP",
- x86_FNSAVE: "FNSAVE",
- x86_FNSTCW: "FNSTCW",
- x86_FNSTENV: "FNSTENV",
- x86_FNSTSW: "FNSTSW",
- x86_FPATAN: "FPATAN",
- x86_FPREM: "FPREM",
- x86_FPREM1: "FPREM1",
- x86_FPTAN: "FPTAN",
- x86_FRNDINT: "FRNDINT",
- x86_FRSTOR: "FRSTOR",
- x86_FSCALE: "FSCALE",
- x86_FSIN: "FSIN",
- x86_FSINCOS: "FSINCOS",
- x86_FSQRT: "FSQRT",
- x86_FST: "FST",
- x86_FSTP: "FSTP",
- x86_FSUB: "FSUB",
- x86_FSUBP: "FSUBP",
- x86_FSUBR: "FSUBR",
- x86_FSUBRP: "FSUBRP",
- x86_FTST: "FTST",
- x86_FUCOM: "FUCOM",
- x86_FUCOMI: "FUCOMI",
- x86_FUCOMIP: "FUCOMIP",
- x86_FUCOMP: "FUCOMP",
- x86_FUCOMPP: "FUCOMPP",
- x86_FWAIT: "FWAIT",
- x86_FXAM: "FXAM",
- x86_FXCH: "FXCH",
- x86_FXRSTOR: "FXRSTOR",
- x86_FXRSTOR64: "FXRSTOR64",
- x86_FXSAVE: "FXSAVE",
- x86_FXSAVE64: "FXSAVE64",
- x86_FXTRACT: "FXTRACT",
- x86_FYL2X: "FYL2X",
- x86_FYL2XP1: "FYL2XP1",
- x86_HADDPD: "HADDPD",
- x86_HADDPS: "HADDPS",
- x86_HLT: "HLT",
- x86_HSUBPD: "HSUBPD",
- x86_HSUBPS: "HSUBPS",
- x86_ICEBP: "ICEBP",
- x86_IDIV: "IDIV",
- x86_IMUL: "IMUL",
- x86_IN: "IN",
- x86_INC: "INC",
- x86_INSB: "INSB",
- x86_INSD: "INSD",
- x86_INSERTPS: "INSERTPS",
- x86_INSW: "INSW",
- x86_INT: "INT",
- x86_INTO: "INTO",
- x86_INVD: "INVD",
- x86_INVLPG: "INVLPG",
- x86_INVPCID: "INVPCID",
- x86_IRET: "IRET",
- x86_IRETD: "IRETD",
- x86_IRETQ: "IRETQ",
- x86_JA: "JA",
- x86_JAE: "JAE",
- x86_JB: "JB",
- x86_JBE: "JBE",
- x86_JCXZ: "JCXZ",
- x86_JE: "JE",
- x86_JECXZ: "JECXZ",
- x86_JG: "JG",
- x86_JGE: "JGE",
- x86_JL: "JL",
- x86_JLE: "JLE",
- x86_JMP: "JMP",
- x86_JNE: "JNE",
- x86_JNO: "JNO",
- x86_JNP: "JNP",
- x86_JNS: "JNS",
- x86_JO: "JO",
- x86_JP: "JP",
- x86_JRCXZ: "JRCXZ",
- x86_JS: "JS",
- x86_LAHF: "LAHF",
- x86_LAR: "LAR",
- x86_LCALL: "LCALL",
- x86_LDDQU: "LDDQU",
- x86_LDMXCSR: "LDMXCSR",
- x86_LDS: "LDS",
- x86_LEA: "LEA",
- x86_LEAVE: "LEAVE",
- x86_LES: "LES",
- x86_LFENCE: "LFENCE",
- x86_LFS: "LFS",
- x86_LGDT: "LGDT",
- x86_LGS: "LGS",
- x86_LIDT: "LIDT",
- x86_LJMP: "LJMP",
- x86_LLDT: "LLDT",
- x86_LMSW: "LMSW",
- x86_LODSB: "LODSB",
- x86_LODSD: "LODSD",
- x86_LODSQ: "LODSQ",
- x86_LODSW: "LODSW",
- x86_LOOP: "LOOP",
- x86_LOOPE: "LOOPE",
- x86_LOOPNE: "LOOPNE",
- x86_LRET: "LRET",
- x86_LSL: "LSL",
- x86_LSS: "LSS",
- x86_LTR: "LTR",
- x86_LZCNT: "LZCNT",
- x86_MASKMOVDQU: "MASKMOVDQU",
- x86_MASKMOVQ: "MASKMOVQ",
- x86_MAXPD: "MAXPD",
- x86_MAXPS: "MAXPS",
- x86_MAXSD: "MAXSD",
- x86_MAXSS: "MAXSS",
- x86_MFENCE: "MFENCE",
- x86_MINPD: "MINPD",
- x86_MINPS: "MINPS",
- x86_MINSD: "MINSD",
- x86_MINSS: "MINSS",
- x86_MONITOR: "MONITOR",
- x86_MOV: "MOV",
- x86_MOVAPD: "MOVAPD",
- x86_MOVAPS: "MOVAPS",
- x86_MOVBE: "MOVBE",
- x86_MOVD: "MOVD",
- x86_MOVDDUP: "MOVDDUP",
- x86_MOVDQ2Q: "MOVDQ2Q",
- x86_MOVDQA: "MOVDQA",
- x86_MOVDQU: "MOVDQU",
- x86_MOVHLPS: "MOVHLPS",
- x86_MOVHPD: "MOVHPD",
- x86_MOVHPS: "MOVHPS",
- x86_MOVLHPS: "MOVLHPS",
- x86_MOVLPD: "MOVLPD",
- x86_MOVLPS: "MOVLPS",
- x86_MOVMSKPD: "MOVMSKPD",
- x86_MOVMSKPS: "MOVMSKPS",
- x86_MOVNTDQ: "MOVNTDQ",
- x86_MOVNTDQA: "MOVNTDQA",
- x86_MOVNTI: "MOVNTI",
- x86_MOVNTPD: "MOVNTPD",
- x86_MOVNTPS: "MOVNTPS",
- x86_MOVNTQ: "MOVNTQ",
- x86_MOVNTSD: "MOVNTSD",
- x86_MOVNTSS: "MOVNTSS",
- x86_MOVQ: "MOVQ",
- x86_MOVQ2DQ: "MOVQ2DQ",
- x86_MOVSB: "MOVSB",
- x86_MOVSD: "MOVSD",
- x86_MOVSD_XMM: "MOVSD_XMM",
- x86_MOVSHDUP: "MOVSHDUP",
- x86_MOVSLDUP: "MOVSLDUP",
- x86_MOVSQ: "MOVSQ",
- x86_MOVSS: "MOVSS",
- x86_MOVSW: "MOVSW",
- x86_MOVSX: "MOVSX",
- x86_MOVSXD: "MOVSXD",
- x86_MOVUPD: "MOVUPD",
- x86_MOVUPS: "MOVUPS",
- x86_MOVZX: "MOVZX",
- x86_MPSADBW: "MPSADBW",
- x86_MUL: "MUL",
- x86_MULPD: "MULPD",
- x86_MULPS: "MULPS",
- x86_MULSD: "MULSD",
- x86_MULSS: "MULSS",
- x86_MWAIT: "MWAIT",
- x86_NEG: "NEG",
- x86_NOP: "NOP",
- x86_NOT: "NOT",
- x86_OR: "OR",
- x86_ORPD: "ORPD",
- x86_ORPS: "ORPS",
- x86_OUT: "OUT",
- x86_OUTSB: "OUTSB",
- x86_OUTSD: "OUTSD",
- x86_OUTSW: "OUTSW",
- x86_PABSB: "PABSB",
- x86_PABSD: "PABSD",
- x86_PABSW: "PABSW",
- x86_PACKSSDW: "PACKSSDW",
- x86_PACKSSWB: "PACKSSWB",
- x86_PACKUSDW: "PACKUSDW",
- x86_PACKUSWB: "PACKUSWB",
- x86_PADDB: "PADDB",
- x86_PADDD: "PADDD",
- x86_PADDQ: "PADDQ",
- x86_PADDSB: "PADDSB",
- x86_PADDSW: "PADDSW",
- x86_PADDUSB: "PADDUSB",
- x86_PADDUSW: "PADDUSW",
- x86_PADDW: "PADDW",
- x86_PALIGNR: "PALIGNR",
- x86_PAND: "PAND",
- x86_PANDN: "PANDN",
- x86_PAUSE: "PAUSE",
- x86_PAVGB: "PAVGB",
- x86_PAVGW: "PAVGW",
- x86_PBLENDVB: "PBLENDVB",
- x86_PBLENDW: "PBLENDW",
- x86_PCLMULQDQ: "PCLMULQDQ",
- x86_PCMPEQB: "PCMPEQB",
- x86_PCMPEQD: "PCMPEQD",
- x86_PCMPEQQ: "PCMPEQQ",
- x86_PCMPEQW: "PCMPEQW",
- x86_PCMPESTRI: "PCMPESTRI",
- x86_PCMPESTRM: "PCMPESTRM",
- x86_PCMPGTB: "PCMPGTB",
- x86_PCMPGTD: "PCMPGTD",
- x86_PCMPGTQ: "PCMPGTQ",
- x86_PCMPGTW: "PCMPGTW",
- x86_PCMPISTRI: "PCMPISTRI",
- x86_PCMPISTRM: "PCMPISTRM",
- x86_PEXTRB: "PEXTRB",
- x86_PEXTRD: "PEXTRD",
- x86_PEXTRQ: "PEXTRQ",
- x86_PEXTRW: "PEXTRW",
- x86_PHADDD: "PHADDD",
- x86_PHADDSW: "PHADDSW",
- x86_PHADDW: "PHADDW",
- x86_PHMINPOSUW: "PHMINPOSUW",
- x86_PHSUBD: "PHSUBD",
- x86_PHSUBSW: "PHSUBSW",
- x86_PHSUBW: "PHSUBW",
- x86_PINSRB: "PINSRB",
- x86_PINSRD: "PINSRD",
- x86_PINSRQ: "PINSRQ",
- x86_PINSRW: "PINSRW",
- x86_PMADDUBSW: "PMADDUBSW",
- x86_PMADDWD: "PMADDWD",
- x86_PMAXSB: "PMAXSB",
- x86_PMAXSD: "PMAXSD",
- x86_PMAXSW: "PMAXSW",
- x86_PMAXUB: "PMAXUB",
- x86_PMAXUD: "PMAXUD",
- x86_PMAXUW: "PMAXUW",
- x86_PMINSB: "PMINSB",
- x86_PMINSD: "PMINSD",
- x86_PMINSW: "PMINSW",
- x86_PMINUB: "PMINUB",
- x86_PMINUD: "PMINUD",
- x86_PMINUW: "PMINUW",
- x86_PMOVMSKB: "PMOVMSKB",
- x86_PMOVSXBD: "PMOVSXBD",
- x86_PMOVSXBQ: "PMOVSXBQ",
- x86_PMOVSXBW: "PMOVSXBW",
- x86_PMOVSXDQ: "PMOVSXDQ",
- x86_PMOVSXWD: "PMOVSXWD",
- x86_PMOVSXWQ: "PMOVSXWQ",
- x86_PMOVZXBD: "PMOVZXBD",
- x86_PMOVZXBQ: "PMOVZXBQ",
- x86_PMOVZXBW: "PMOVZXBW",
- x86_PMOVZXDQ: "PMOVZXDQ",
- x86_PMOVZXWD: "PMOVZXWD",
- x86_PMOVZXWQ: "PMOVZXWQ",
- x86_PMULDQ: "PMULDQ",
- x86_PMULHRSW: "PMULHRSW",
- x86_PMULHUW: "PMULHUW",
- x86_PMULHW: "PMULHW",
- x86_PMULLD: "PMULLD",
- x86_PMULLW: "PMULLW",
- x86_PMULUDQ: "PMULUDQ",
- x86_POP: "POP",
- x86_POPA: "POPA",
- x86_POPAD: "POPAD",
- x86_POPCNT: "POPCNT",
- x86_POPF: "POPF",
- x86_POPFD: "POPFD",
- x86_POPFQ: "POPFQ",
- x86_POR: "POR",
- x86_PREFETCHNTA: "PREFETCHNTA",
- x86_PREFETCHT0: "PREFETCHT0",
- x86_PREFETCHT1: "PREFETCHT1",
- x86_PREFETCHT2: "PREFETCHT2",
- x86_PREFETCHW: "PREFETCHW",
- x86_PSADBW: "PSADBW",
- x86_PSHUFB: "PSHUFB",
- x86_PSHUFD: "PSHUFD",
- x86_PSHUFHW: "PSHUFHW",
- x86_PSHUFLW: "PSHUFLW",
- x86_PSHUFW: "PSHUFW",
- x86_PSIGNB: "PSIGNB",
- x86_PSIGND: "PSIGND",
- x86_PSIGNW: "PSIGNW",
- x86_PSLLD: "PSLLD",
- x86_PSLLDQ: "PSLLDQ",
- x86_PSLLQ: "PSLLQ",
- x86_PSLLW: "PSLLW",
- x86_PSRAD: "PSRAD",
- x86_PSRAW: "PSRAW",
- x86_PSRLD: "PSRLD",
- x86_PSRLDQ: "PSRLDQ",
- x86_PSRLQ: "PSRLQ",
- x86_PSRLW: "PSRLW",
- x86_PSUBB: "PSUBB",
- x86_PSUBD: "PSUBD",
- x86_PSUBQ: "PSUBQ",
- x86_PSUBSB: "PSUBSB",
- x86_PSUBSW: "PSUBSW",
- x86_PSUBUSB: "PSUBUSB",
- x86_PSUBUSW: "PSUBUSW",
- x86_PSUBW: "PSUBW",
- x86_PTEST: "PTEST",
- x86_PUNPCKHBW: "PUNPCKHBW",
- x86_PUNPCKHDQ: "PUNPCKHDQ",
- x86_PUNPCKHQDQ: "PUNPCKHQDQ",
- x86_PUNPCKHWD: "PUNPCKHWD",
- x86_PUNPCKLBW: "PUNPCKLBW",
- x86_PUNPCKLDQ: "PUNPCKLDQ",
- x86_PUNPCKLQDQ: "PUNPCKLQDQ",
- x86_PUNPCKLWD: "PUNPCKLWD",
- x86_PUSH: "PUSH",
- x86_PUSHA: "PUSHA",
- x86_PUSHAD: "PUSHAD",
- x86_PUSHF: "PUSHF",
- x86_PUSHFD: "PUSHFD",
- x86_PUSHFQ: "PUSHFQ",
- x86_PXOR: "PXOR",
- x86_RCL: "RCL",
- x86_RCPPS: "RCPPS",
- x86_RCPSS: "RCPSS",
- x86_RCR: "RCR",
- x86_RDFSBASE: "RDFSBASE",
- x86_RDGSBASE: "RDGSBASE",
- x86_RDMSR: "RDMSR",
- x86_RDPMC: "RDPMC",
- x86_RDRAND: "RDRAND",
- x86_RDTSC: "RDTSC",
- x86_RDTSCP: "RDTSCP",
- x86_RET: "RET",
- x86_ROL: "ROL",
- x86_ROR: "ROR",
- x86_ROUNDPD: "ROUNDPD",
- x86_ROUNDPS: "ROUNDPS",
- x86_ROUNDSD: "ROUNDSD",
- x86_ROUNDSS: "ROUNDSS",
- x86_RSM: "RSM",
- x86_RSQRTPS: "RSQRTPS",
- x86_RSQRTSS: "RSQRTSS",
- x86_SAHF: "SAHF",
- x86_SAR: "SAR",
- x86_SBB: "SBB",
- x86_SCASB: "SCASB",
- x86_SCASD: "SCASD",
- x86_SCASQ: "SCASQ",
- x86_SCASW: "SCASW",
- x86_SETA: "SETA",
- x86_SETAE: "SETAE",
- x86_SETB: "SETB",
- x86_SETBE: "SETBE",
- x86_SETE: "SETE",
- x86_SETG: "SETG",
- x86_SETGE: "SETGE",
- x86_SETL: "SETL",
- x86_SETLE: "SETLE",
- x86_SETNE: "SETNE",
- x86_SETNO: "SETNO",
- x86_SETNP: "SETNP",
- x86_SETNS: "SETNS",
- x86_SETO: "SETO",
- x86_SETP: "SETP",
- x86_SETS: "SETS",
- x86_SFENCE: "SFENCE",
- x86_SGDT: "SGDT",
- x86_SHL: "SHL",
- x86_SHLD: "SHLD",
- x86_SHR: "SHR",
- x86_SHRD: "SHRD",
- x86_SHUFPD: "SHUFPD",
- x86_SHUFPS: "SHUFPS",
- x86_SIDT: "SIDT",
- x86_SLDT: "SLDT",
- x86_SMSW: "SMSW",
- x86_SQRTPD: "SQRTPD",
- x86_SQRTPS: "SQRTPS",
- x86_SQRTSD: "SQRTSD",
- x86_SQRTSS: "SQRTSS",
- x86_STC: "STC",
- x86_STD: "STD",
- x86_STI: "STI",
- x86_STMXCSR: "STMXCSR",
- x86_STOSB: "STOSB",
- x86_STOSD: "STOSD",
- x86_STOSQ: "STOSQ",
- x86_STOSW: "STOSW",
- x86_STR: "STR",
- x86_SUB: "SUB",
- x86_SUBPD: "SUBPD",
- x86_SUBPS: "SUBPS",
- x86_SUBSD: "SUBSD",
- x86_SUBSS: "SUBSS",
- x86_SWAPGS: "SWAPGS",
- x86_SYSCALL: "SYSCALL",
- x86_SYSENTER: "SYSENTER",
- x86_SYSEXIT: "SYSEXIT",
- x86_SYSRET: "SYSRET",
- x86_TEST: "TEST",
- x86_TZCNT: "TZCNT",
- x86_UCOMISD: "UCOMISD",
- x86_UCOMISS: "UCOMISS",
- x86_UD1: "UD1",
- x86_UD2: "UD2",
- x86_UNPCKHPD: "UNPCKHPD",
- x86_UNPCKHPS: "UNPCKHPS",
- x86_UNPCKLPD: "UNPCKLPD",
- x86_UNPCKLPS: "UNPCKLPS",
- x86_VERR: "VERR",
- x86_VERW: "VERW",
- x86_WBINVD: "WBINVD",
- x86_WRFSBASE: "WRFSBASE",
- x86_WRGSBASE: "WRGSBASE",
- x86_WRMSR: "WRMSR",
- x86_XABORT: "XABORT",
- x86_XADD: "XADD",
- x86_XBEGIN: "XBEGIN",
- x86_XCHG: "XCHG",
- x86_XEND: "XEND",
- x86_XGETBV: "XGETBV",
- x86_XLATB: "XLATB",
- x86_XOR: "XOR",
- x86_XORPD: "XORPD",
- x86_XORPS: "XORPS",
- x86_XRSTOR: "XRSTOR",
- x86_XRSTOR64: "XRSTOR64",
- x86_XRSTORS: "XRSTORS",
- x86_XRSTORS64: "XRSTORS64",
- x86_XSAVE: "XSAVE",
- x86_XSAVE64: "XSAVE64",
- x86_XSAVEC: "XSAVEC",
- x86_XSAVEC64: "XSAVEC64",
- x86_XSAVEOPT: "XSAVEOPT",
- x86_XSAVEOPT64: "XSAVEOPT64",
- x86_XSAVES: "XSAVES",
- x86_XSAVES64: "XSAVES64",
- x86_XSETBV: "XSETBV",
- x86_XTEST: "XTEST",
-}
diff --git a/src/cmd/pack/doc.go b/src/cmd/pack/doc.go
index 1529e07e9..a702594e2 100644
--- a/src/cmd/pack/doc.go
+++ b/src/cmd/pack/doc.go
@@ -20,6 +20,10 @@ The operation op is given by one of these letters:
t list files from the archive
x extract files from the archive
+The archive argument to the c command must be non-existent or a
+valid archive file, which will be cleared before adding new entries. It
+is an error if the file exists but is not an archive.
+
For the p, t, and x commands, listing no names on the command line
causes the operation to apply to all files in the archive.
diff --git a/src/cmd/pack/pack.go b/src/cmd/pack/pack.go
index 594433712..ffb2d617a 100644
--- a/src/cmd/pack/pack.go
+++ b/src/cmd/pack/pack.go
@@ -142,16 +142,19 @@ type Archive struct {
matchAll bool // match all files in archive
}
-// archive opens (or if necessary creates) the named archive.
+// archive opens (and if necessary creates) the named archive.
func archive(name string, mode int, files []string) *Archive {
- fd, err := os.OpenFile(name, mode, 0)
- if err != nil && mode&^os.O_TRUNC == os.O_RDWR && os.IsNotExist(err) {
- fd, err = create(name)
+ // If the file exists, it must be an archive. If it doesn't exist, or if
+ // we're doing the c command, indicated by O_TRUNC, truncate the archive.
+ if !existingArchive(name) || mode&os.O_TRUNC != 0 {
+ create(name)
+ mode &^= os.O_TRUNC
}
+ fd, err := os.OpenFile(name, mode, 0)
if err != nil {
log.Fatal(err)
}
- mustBeArchive(fd)
+ checkHeader(fd)
return &Archive{
fd: fd,
files: files,
@@ -160,23 +163,40 @@ func archive(name string, mode int, files []string) *Archive {
}
// create creates and initializes an archive that does not exist.
-func create(name string) (*os.File, error) {
- fd, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
+func create(name string) {
+ fd, err := os.Create(name)
if err != nil {
- return nil, err
+ log.Fatal(err)
+ }
+ _, err = fmt.Fprint(fd, arHeader)
+ if err != nil {
+ log.Fatal(err)
+ }
+ fd.Close()
+}
+
+// existingArchive reports whether the file exists and is a valid archive.
+// If it exists but is not an archive, existingArchive will exit.
+func existingArchive(name string) bool {
+ fd, err := os.Open(name)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return false
+ }
+ log.Fatal("cannot open file: %s", err)
}
- fmt.Fprint(fd, arHeader)
- fd.Seek(0, 0)
- return fd, nil
+ checkHeader(fd)
+ fd.Close()
+ return true
}
-// mustBeArchive verifies the header of the file. It assumes the file offset
-// is 0 coming in, and leaves it positioned immediately after the header.
-func mustBeArchive(fd *os.File) {
+// checkHeader verifies the header of the file. It assumes the file
+// is positioned at 0 and leaves it positioned at the end of the header.
+func checkHeader(fd *os.File) {
buf := make([]byte, len(arHeader))
_, err := io.ReadFull(fd, buf)
if err != nil || string(buf) != arHeader {
- log.Fatal("file is not an archive: bad header")
+ log.Fatal("%s is not an archive: bad header", fd.Name())
}
}
diff --git a/src/cmd/pack/pack_test.go b/src/cmd/pack/pack_test.go
index 486242603..cf6121fcc 100644
--- a/src/cmd/pack/pack_test.go
+++ b/src/cmd/pack/pack_test.go
@@ -56,11 +56,8 @@ func tmpDir(t *testing.T) string {
return name
}
-// Test that we can create an archive, write to it, and get the same contents back.
-// Tests the rv and then the pv command on a new archive.
-func TestCreate(t *testing.T) {
- dir := tmpDir(t)
- defer os.RemoveAll(dir)
+// testCreate creates an archive in the specified directory.
+func testCreate(t *testing.T, dir string) {
name := filepath.Join(dir, "pack.a")
ar := archive(name, os.O_RDWR, nil)
// Add an entry by hand.
@@ -85,6 +82,22 @@ func TestCreate(t *testing.T) {
}
}
+// Test that we can create an archive, write to it, and get the same contents back.
+// Tests the rv and then the pv command on a new archive.
+func TestCreate(t *testing.T) {
+ dir := tmpDir(t)
+ defer os.RemoveAll(dir)
+ testCreate(t, dir)
+}
+
+// Test that we can create an archive twice with the same name (Issue 8369).
+func TestCreateTwice(t *testing.T) {
+ dir := tmpDir(t)
+ defer os.RemoveAll(dir)
+ testCreate(t, dir)
+ testCreate(t, dir)
+}
+
// Test that we can create an archive, put some files in it, and get back a correct listing.
// Tests the tv command.
func TestTableOfContents(t *testing.T) {
@@ -186,8 +199,9 @@ func TestExtract(t *testing.T) {
// Test that pack-created archives can be understood by the tools.
func TestHello(t *testing.T) {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
+ switch runtime.GOOS {
+ case "android", "nacl":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
dir := tmpDir(t)
@@ -222,8 +236,9 @@ func TestHello(t *testing.T) {
// Test that pack works with very long lines in PKGDEF.
func TestLargeDefs(t *testing.T) {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
+ switch runtime.GOOS {
+ case "android", "nacl":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
dir := tmpDir(t)
diff --git a/src/cmd/pprof/README b/src/cmd/pprof/README
new file mode 100644
index 000000000..a728ef235
--- /dev/null
+++ b/src/cmd/pprof/README
@@ -0,0 +1,8 @@
+The pprof in this directory is adapted from the pprof used inside Google
+for C++, Java, and Go programs. Because it was developed for that broader
+context, it is overgeneralized when used here for the specific use case
+of profiling standard Go programs. However, we've left the abstractions
+intact in order to share updates between this copy and Google's internal one.
+
+Please do not take the level of abstraction in this program as an example
+to follow in your own.
diff --git a/src/cmd/pprof/doc.go b/src/cmd/pprof/doc.go
new file mode 100644
index 000000000..c6ff11d10
--- /dev/null
+++ b/src/cmd/pprof/doc.go
@@ -0,0 +1,12 @@
+// 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.
+
+// Pprof interprets and displays profiles of Go programs.
+//
+// Usage:
+//
+// go tool pprof binary profile
+//
+// For more information, see http://blog.golang.org/profiling-go-programs.
+package main
diff --git a/src/cmd/pprof/internal/commands/commands.go b/src/cmd/pprof/internal/commands/commands.go
new file mode 100644
index 000000000..51397a3c6
--- /dev/null
+++ b/src/cmd/pprof/internal/commands/commands.go
@@ -0,0 +1,215 @@
+// 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 commands defines and manages the basic pprof commands
+package commands
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "runtime"
+ "strings"
+
+ "cmd/pprof/internal/plugin"
+ "cmd/pprof/internal/report"
+ "cmd/pprof/internal/svg"
+ "cmd/pprof/internal/tempfile"
+)
+
+// Commands describes the commands accepted by pprof.
+type Commands map[string]*Command
+
+// Command describes the actions for a pprof command. Includes a
+// function for command-line completion, the report format to use
+// during report generation, any postprocessing functions, and whether
+// the command expects a regexp parameter (typically a function name).
+type Command struct {
+ Complete Completer // autocomplete for interactive mode
+ Format int // report format to generate
+ PostProcess PostProcessor // postprocessing to run on report
+ HasParam bool // Collect a parameter from the CLI
+ Usage string // Help text
+}
+
+// Completer is a function for command-line autocompletion
+type Completer func(prefix string) string
+
+// PostProcessor is a function that applies post-processing to the report output
+type PostProcessor func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error
+
+// PProf returns the basic pprof report-generation commands
+func PProf(c Completer, interactive **bool, svgpan **string) Commands {
+ return Commands{
+ // Commands that require no post-processing.
+ "tags": {nil, report.Tags, nil, false, "Outputs all tags in the profile"},
+ "raw": {c, report.Raw, nil, false, "Outputs a text representation of the raw profile"},
+ "dot": {c, report.Dot, nil, false, "Outputs a graph in DOT format"},
+ "top": {c, report.Text, nil, false, "Outputs top entries in text form"},
+ "tree": {c, report.Tree, nil, false, "Outputs a text rendering of call graph"},
+ "text": {c, report.Text, nil, false, "Outputs top entries in text form"},
+ "disasm": {c, report.Dis, nil, true, "Output annotated assembly for functions matching regexp or address"},
+ "list": {c, report.List, nil, true, "Output annotated source for functions matching regexp"},
+ "peek": {c, report.Tree, nil, true, "Output callers/callees of functions matching regexp"},
+
+ // Save binary formats to a file
+ "callgrind": {c, report.Callgrind, awayFromTTY("callgraph.out"), false, "Outputs a graph in callgrind format"},
+ "proto": {c, report.Proto, awayFromTTY("pb.gz"), false, "Outputs the profile in compressed protobuf format"},
+
+ // Generate report in DOT format and postprocess with dot
+ "gif": {c, report.Dot, invokeDot("gif"), false, "Outputs a graph image in GIF format"},
+ "pdf": {c, report.Dot, invokeDot("pdf"), false, "Outputs a graph in PDF format"},
+ "png": {c, report.Dot, invokeDot("png"), false, "Outputs a graph image in PNG format"},
+ "ps": {c, report.Dot, invokeDot("ps"), false, "Outputs a graph in PS format"},
+
+ // Save SVG output into a file after including svgpan library
+ "svg": {c, report.Dot, saveSVGToFile(svgpan), false, "Outputs a graph in SVG format"},
+
+ // Visualize postprocessed dot output
+ "eog": {c, report.Dot, invokeVisualizer(interactive, invokeDot("svg"), "svg", []string{"eog"}), false, "Visualize graph through eog"},
+ "evince": {c, report.Dot, invokeVisualizer(interactive, invokeDot("pdf"), "pdf", []string{"evince"}), false, "Visualize graph through evince"},
+ "gv": {c, report.Dot, invokeVisualizer(interactive, invokeDot("ps"), "ps", []string{"gv --noantialias"}), false, "Visualize graph through gv"},
+ "web": {c, report.Dot, invokeVisualizer(interactive, saveSVGToFile(svgpan), "svg", browsers()), false, "Visualize graph through web browser"},
+
+ // Visualize HTML directly generated by report.
+ "weblist": {c, report.WebList, invokeVisualizer(interactive, awayFromTTY("html"), "html", browsers()), true, "Output annotated source in HTML for functions matching regexp or address"},
+ }
+}
+
+// browsers returns a list of commands to attempt for web visualization
+// on the current platform
+func browsers() []string {
+ cmds := []string{"chrome", "google-chrome", "firefox"}
+ switch runtime.GOOS {
+ case "darwin":
+ cmds = append(cmds, "/usr/bin/open")
+ case "windows":
+ cmds = append(cmds, "cmd /c start")
+ default:
+ cmds = append(cmds, "xdg-open")
+ }
+ return cmds
+}
+
+// NewCompleter creates an autocompletion function for a set of commands.
+func NewCompleter(cs Commands) Completer {
+ return func(line string) string {
+ switch tokens := strings.Fields(line); len(tokens) {
+ case 0:
+ // Nothing to complete
+ case 1:
+ // Single token -- complete command name
+ found := ""
+ for c := range cs {
+ if strings.HasPrefix(c, tokens[0]) {
+ if found != "" {
+ return line
+ }
+ found = c
+ }
+ }
+ if found != "" {
+ return found
+ }
+ default:
+ // Multiple tokens -- complete using command completer
+ if c, ok := cs[tokens[0]]; ok {
+ if c.Complete != nil {
+ lastTokenIdx := len(tokens) - 1
+ lastToken := tokens[lastTokenIdx]
+ if strings.HasPrefix(lastToken, "-") {
+ lastToken = "-" + c.Complete(lastToken[1:])
+ } else {
+ lastToken = c.Complete(lastToken)
+ }
+ return strings.Join(append(tokens[:lastTokenIdx], lastToken), " ")
+ }
+ }
+ }
+ return line
+ }
+}
+
+// awayFromTTY saves the output in a file if it would otherwise go to
+// the terminal screen. This is used to avoid dumping binary data on
+// the screen.
+func awayFromTTY(format string) PostProcessor {
+ return func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error {
+ if output == os.Stdout && ui.IsTerminal() {
+ tempFile, err := tempfile.New("", "profile", "."+format)
+ if err != nil {
+ return err
+ }
+ ui.PrintErr("Generating report in ", tempFile.Name())
+ _, err = fmt.Fprint(tempFile, input)
+ return err
+ }
+ _, err := fmt.Fprint(output, input)
+ return err
+ }
+}
+
+func invokeDot(format string) PostProcessor {
+ divert := awayFromTTY(format)
+ return func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error {
+ if _, err := exec.LookPath("dot"); err != nil {
+ ui.PrintErr("Cannot find dot, have you installed Graphviz?")
+ return err
+ }
+ cmd := exec.Command("dot", "-T"+format)
+ var buf bytes.Buffer
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = input, &buf, os.Stderr
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ return divert(&buf, output, ui)
+ }
+}
+
+func saveSVGToFile(svgpan **string) PostProcessor {
+ generateSVG := invokeDot("svg")
+ divert := awayFromTTY("svg")
+ return func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error {
+ baseSVG := &bytes.Buffer{}
+ generateSVG(input, baseSVG, ui)
+ massaged := &bytes.Buffer{}
+ fmt.Fprint(massaged, svg.Massage(*baseSVG, **svgpan))
+ return divert(massaged, output, ui)
+ }
+}
+
+func invokeVisualizer(interactive **bool, format PostProcessor, suffix string, visualizers []string) PostProcessor {
+ return func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error {
+ tempFile, err := tempfile.New(os.Getenv("PPROF_TMPDIR"), "pprof", "."+suffix)
+ if err != nil {
+ return err
+ }
+ tempfile.DeferDelete(tempFile.Name())
+ if err = format(input, tempFile, ui); err != nil {
+ return err
+ }
+ tempFile.Close() // on windows, if the file is Open, start cannot access it.
+ // Try visualizers until one is successful
+ for _, v := range visualizers {
+ // Separate command and arguments for exec.Command.
+ args := strings.Split(v, " ")
+ if len(args) == 0 {
+ continue
+ }
+ viewer := exec.Command(args[0], append(args[1:], tempFile.Name())...)
+ viewer.Stderr = os.Stderr
+ if err = viewer.Start(); err == nil {
+ if !**interactive {
+ // In command-line mode, wait for the viewer to be closed
+ // before proceeding
+ return viewer.Wait()
+ }
+ return nil
+ }
+ }
+ return err
+ }
+}
diff --git a/src/cmd/pprof/internal/driver/driver.go b/src/cmd/pprof/internal/driver/driver.go
new file mode 100644
index 000000000..68b5d1b61
--- /dev/null
+++ b/src/cmd/pprof/internal/driver/driver.go
@@ -0,0 +1,1036 @@
+// 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 driver implements the core pprof functionality. It can be
+// parameterized with a flag implementation, fetch and symbolize
+// mechanisms.
+package driver
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "net/url"
+ "os"
+ "path/filepath"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "cmd/pprof/internal/commands"
+ "cmd/pprof/internal/plugin"
+ "cmd/pprof/internal/profile"
+ "cmd/pprof/internal/report"
+ "cmd/pprof/internal/tempfile"
+)
+
+// PProf acquires a profile, and symbolizes it using a profile
+// manager. Then it generates a report formatted according to the
+// options selected through the flags package.
+func PProf(flagset plugin.FlagSet, fetch plugin.Fetcher, sym plugin.Symbolizer, obj plugin.ObjTool, ui plugin.UI, overrides commands.Commands) error {
+ // Remove any temporary files created during pprof processing.
+ defer tempfile.Cleanup()
+
+ f, err := getFlags(flagset, overrides, ui)
+ if err != nil {
+ return err
+ }
+
+ obj.SetConfig(*f.flagTools)
+
+ sources := f.profileSource
+ if len(sources) > 1 {
+ source := sources[0]
+ // If the first argument is a supported object file, treat as executable.
+ if file, err := obj.Open(source, 0); err == nil {
+ file.Close()
+ f.profileExecName = source
+ sources = sources[1:]
+ } else if *f.flagBuildID == "" && isBuildID(source) {
+ f.flagBuildID = &source
+ sources = sources[1:]
+ }
+ }
+
+ // errMu protects concurrent accesses to errset and err. errset is set if an
+ // error is encountered by one of the goroutines grabbing a profile.
+ errMu, errset := sync.Mutex{}, false
+
+ // Fetch profiles.
+ wg := sync.WaitGroup{}
+ profs := make([]*profile.Profile, len(sources))
+ for i, source := range sources {
+ wg.Add(1)
+ go func(i int, src string) {
+ defer wg.Done()
+ p, grabErr := grabProfile(src, f.profileExecName, *f.flagBuildID, fetch, sym, obj, ui, f)
+ if grabErr != nil {
+ errMu.Lock()
+ defer errMu.Unlock()
+ errset, err = true, grabErr
+ return
+ }
+ profs[i] = p
+ }(i, source)
+ }
+ wg.Wait()
+ if errset {
+ return err
+ }
+
+ // Merge profiles.
+ prof := profs[0]
+ for _, p := range profs[1:] {
+ if err = prof.Merge(p, 1); err != nil {
+ return err
+ }
+ }
+
+ if *f.flagBase != "" {
+ // Fetch base profile and subtract from current profile.
+ base, err := grabProfile(*f.flagBase, f.profileExecName, *f.flagBuildID, fetch, sym, obj, ui, f)
+ if err != nil {
+ return err
+ }
+
+ if err = prof.Merge(base, -1); err != nil {
+ return err
+ }
+ }
+
+ if err := processFlags(prof, ui, f); err != nil {
+ return err
+ }
+
+ prof.RemoveUninteresting()
+
+ if *f.flagInteractive {
+ return interactive(prof, obj, ui, f)
+ }
+
+ return generate(false, prof, obj, ui, f)
+}
+
+// isBuildID determines if the profile may contain a build ID, by
+// checking that it is a string of hex digits.
+func isBuildID(id string) bool {
+ return strings.Trim(id, "0123456789abcdefABCDEF") == ""
+}
+
+// adjustURL updates the profile source URL based on heuristics. It
+// will append ?seconds=sec for CPU profiles if not already
+// specified. Returns the hostname if the profile is remote.
+func adjustURL(source string, sec int, ui plugin.UI) (adjusted, host string, duration time.Duration) {
+ // If there is a local file with this name, just use it.
+ if _, err := os.Stat(source); err == nil {
+ return source, "", 0
+ }
+
+ url, err := url.Parse(source)
+
+ // Automatically add http:// to URLs of the form hostname:port/path.
+ // url.Parse treats "hostname" as the Scheme.
+ if err != nil || (url.Host == "" && url.Scheme != "" && url.Scheme != "file") {
+ url, err = url.Parse("http://" + source)
+ if err != nil {
+ return source, url.Host, time.Duration(30) * time.Second
+ }
+ }
+ if scheme := strings.ToLower(url.Scheme); scheme == "" || scheme == "file" {
+ url.Scheme = ""
+ return url.String(), "", 0
+ }
+
+ values := url.Query()
+ if urlSeconds := values.Get("seconds"); urlSeconds != "" {
+ if us, err := strconv.ParseInt(urlSeconds, 10, 32); err == nil {
+ if sec >= 0 {
+ ui.PrintErr("Overriding -seconds for URL ", source)
+ }
+ sec = int(us)
+ }
+ }
+
+ switch strings.ToLower(url.Path) {
+ case "", "/":
+ // Apply default /profilez.
+ url.Path = "/profilez"
+ case "/protoz":
+ // Rewrite to /profilez?type=proto
+ url.Path = "/profilez"
+ values.Set("type", "proto")
+ }
+
+ if hasDuration(url.Path) {
+ if sec > 0 {
+ duration = time.Duration(sec) * time.Second
+ values.Set("seconds", fmt.Sprintf("%d", sec))
+ } else {
+ // Assume default duration: 30 seconds
+ duration = 30 * time.Second
+ }
+ }
+ url.RawQuery = values.Encode()
+ return url.String(), url.Host, duration
+}
+
+func hasDuration(path string) bool {
+ for _, trigger := range []string{"profilez", "wallz", "/profile"} {
+ if strings.Contains(path, trigger) {
+ return true
+ }
+ }
+ return false
+}
+
+// preprocess does filtering and aggregation of a profile based on the
+// requested options.
+func preprocess(prof *profile.Profile, ui plugin.UI, f *flags) error {
+ if *f.flagFocus != "" || *f.flagIgnore != "" || *f.flagHide != "" {
+ focus, ignore, hide, err := compileFocusIgnore(*f.flagFocus, *f.flagIgnore, *f.flagHide)
+ if err != nil {
+ return err
+ }
+ fm, im, hm := prof.FilterSamplesByName(focus, ignore, hide)
+
+ warnNoMatches(fm, *f.flagFocus, "Focus", ui)
+ warnNoMatches(im, *f.flagIgnore, "Ignore", ui)
+ warnNoMatches(hm, *f.flagHide, "Hide", ui)
+ }
+
+ if *f.flagTagFocus != "" || *f.flagTagIgnore != "" {
+ focus, err := compileTagFilter(*f.flagTagFocus, ui)
+ if err != nil {
+ return err
+ }
+ ignore, err := compileTagFilter(*f.flagTagIgnore, ui)
+ if err != nil {
+ return err
+ }
+ fm, im := prof.FilterSamplesByTag(focus, ignore)
+
+ warnNoMatches(fm, *f.flagTagFocus, "TagFocus", ui)
+ warnNoMatches(im, *f.flagTagIgnore, "TagIgnore", ui)
+ }
+
+ return aggregate(prof, f)
+}
+
+func compileFocusIgnore(focus, ignore, hide string) (f, i, h *regexp.Regexp, err error) {
+ if focus != "" {
+ if f, err = regexp.Compile(focus); err != nil {
+ return nil, nil, nil, fmt.Errorf("parsing focus regexp: %v", err)
+ }
+ }
+
+ if ignore != "" {
+ if i, err = regexp.Compile(ignore); err != nil {
+ return nil, nil, nil, fmt.Errorf("parsing ignore regexp: %v", err)
+ }
+ }
+
+ if hide != "" {
+ if h, err = regexp.Compile(hide); err != nil {
+ return nil, nil, nil, fmt.Errorf("parsing hide regexp: %v", err)
+ }
+ }
+ return
+}
+
+func compileTagFilter(filter string, ui plugin.UI) (f func(string, string, int64) bool, err error) {
+ if filter == "" {
+ return nil, nil
+ }
+ if numFilter := parseTagFilterRange(filter); numFilter != nil {
+ ui.PrintErr("Interpreted '", filter, "' as range, not regexp")
+ return func(key, val string, num int64) bool {
+ if val != "" {
+ return false
+ }
+ return numFilter(num, key)
+ }, nil
+ }
+ fx, err := regexp.Compile(filter)
+ if err != nil {
+ return nil, err
+ }
+
+ return func(key, val string, num int64) bool {
+ if val == "" {
+ return false
+ }
+ return fx.MatchString(key + ":" + val)
+ }, nil
+}
+
+var tagFilterRangeRx = regexp.MustCompile("([[:digit:]]+)([[:alpha:]]+)")
+
+// parseTagFilterRange returns a function to checks if a value is
+// contained on the range described by a string. It can recognize
+// strings of the form:
+// "32kb" -- matches values == 32kb
+// ":64kb" -- matches values <= 64kb
+// "4mb:" -- matches values >= 4mb
+// "12kb:64mb" -- matches values between 12kb and 64mb (both included).
+func parseTagFilterRange(filter string) func(int64, string) bool {
+ ranges := tagFilterRangeRx.FindAllStringSubmatch(filter, 2)
+ if len(ranges) == 0 {
+ return nil // No ranges were identified
+ }
+ v, err := strconv.ParseInt(ranges[0][1], 10, 64)
+ if err != nil {
+ panic(fmt.Errorf("Failed to parse int %s: %v", ranges[0][1], err))
+ }
+ value, unit := report.ScaleValue(v, ranges[0][2], ranges[0][2])
+ if len(ranges) == 1 {
+ switch match := ranges[0][0]; filter {
+ case match:
+ return func(v int64, u string) bool {
+ sv, su := report.ScaleValue(v, u, unit)
+ return su == unit && sv == value
+ }
+ case match + ":":
+ return func(v int64, u string) bool {
+ sv, su := report.ScaleValue(v, u, unit)
+ return su == unit && sv >= value
+ }
+ case ":" + match:
+ return func(v int64, u string) bool {
+ sv, su := report.ScaleValue(v, u, unit)
+ return su == unit && sv <= value
+ }
+ }
+ return nil
+ }
+ if filter != ranges[0][0]+":"+ranges[1][0] {
+ return nil
+ }
+ if v, err = strconv.ParseInt(ranges[1][1], 10, 64); err != nil {
+ panic(fmt.Errorf("Failed to parse int %s: %v", ranges[1][1], err))
+ }
+ value2, unit2 := report.ScaleValue(v, ranges[1][2], unit)
+ if unit != unit2 {
+ return nil
+ }
+ return func(v int64, u string) bool {
+ sv, su := report.ScaleValue(v, u, unit)
+ return su == unit && sv >= value && sv <= value2
+ }
+}
+
+func warnNoMatches(match bool, rx, option string, ui plugin.UI) {
+ if !match && rx != "" && rx != "." {
+ ui.PrintErr(option + " expression matched no samples: " + rx)
+ }
+}
+
+// grabProfile fetches and symbolizes a profile.
+func grabProfile(source, exec, buildid string, fetch plugin.Fetcher, sym plugin.Symbolizer, obj plugin.ObjTool, ui plugin.UI, f *flags) (*profile.Profile, error) {
+ source, host, duration := adjustURL(source, *f.flagSeconds, ui)
+ remote := host != ""
+
+ if remote {
+ ui.Print("Fetching profile from ", source)
+ if duration != 0 {
+ ui.Print("Please wait... (" + duration.String() + ")")
+ }
+ }
+
+ now := time.Now()
+ // Fetch profile from source.
+ // Give 50% slack on the timeout.
+ p, err := fetch(source, duration+duration/2, ui)
+ if err != nil {
+ return nil, err
+ }
+
+ // Update the time/duration if the profile source doesn't include it.
+ // TODO(rsilvera): Remove this when we remove support for legacy profiles.
+ if remote {
+ if p.TimeNanos == 0 {
+ p.TimeNanos = now.UnixNano()
+ }
+ if duration != 0 && p.DurationNanos == 0 {
+ p.DurationNanos = int64(duration)
+ }
+ }
+
+ // Replace executable/buildID with the options provided in the
+ // command line. Assume the executable is the first Mapping entry.
+ if exec != "" || buildid != "" {
+ if len(p.Mapping) == 0 {
+ // Create a fake mapping to hold the user option, and associate
+ // all samples to it.
+ m := &profile.Mapping{
+ ID: 1,
+ }
+ for _, l := range p.Location {
+ l.Mapping = m
+ }
+ p.Mapping = []*profile.Mapping{m}
+ }
+ if exec != "" {
+ p.Mapping[0].File = exec
+ }
+ if buildid != "" {
+ p.Mapping[0].BuildID = buildid
+ }
+ }
+
+ if err := sym(*f.flagSymbolize, source, p, obj, ui); err != nil {
+ return nil, err
+ }
+
+ // Save a copy of any remote profiles, unless the user is explicitly
+ // saving it.
+ if remote && !f.isFormat("proto") {
+ prefix := "pprof."
+ if len(p.Mapping) > 0 && p.Mapping[0].File != "" {
+ prefix = prefix + filepath.Base(p.Mapping[0].File) + "."
+ }
+ if !strings.ContainsRune(host, os.PathSeparator) {
+ prefix = prefix + host + "."
+ }
+ for _, s := range p.SampleType {
+ prefix = prefix + s.Type + "."
+ }
+
+ dir := os.Getenv("PPROF_TMPDIR")
+ tempFile, err := tempfile.New(dir, prefix, ".pb.gz")
+ if err == nil {
+ if err = p.Write(tempFile); err == nil {
+ ui.PrintErr("Saved profile in ", tempFile.Name())
+ }
+ }
+ if err != nil {
+ ui.PrintErr("Could not save profile: ", err)
+ }
+ }
+
+ if err := p.Demangle(obj.Demangle); err != nil {
+ ui.PrintErr("Failed to demangle profile: ", err)
+ }
+
+ if err := p.CheckValid(); err != nil {
+ return nil, fmt.Errorf("Grab %s: %v", source, err)
+ }
+
+ return p, nil
+}
+
+type flags struct {
+ flagInteractive *bool // Accept commands interactively
+ flagCommands map[string]*bool // pprof commands without parameters
+ flagParamCommands map[string]*string // pprof commands with parameters
+
+ flagSVGPan *string // URL to fetch the SVG Pan library
+ flagOutput *string // Output file name
+
+ flagCum *bool // Sort by cumulative data
+ flagCallTree *bool // generate a context-sensitive call tree
+
+ flagAddresses *bool // Report at address level
+ flagLines *bool // Report at source line level
+ flagFiles *bool // Report at file level
+ flagFunctions *bool // Report at function level [default]
+
+ flagSymbolize *string // Symbolization options (=none to disable)
+ flagBuildID *string // Override build if for first mapping
+
+ flagNodeCount *int // Max number of nodes to show
+ flagNodeFraction *float64 // Hide nodes below <f>*total
+ flagEdgeFraction *float64 // Hide edges below <f>*total
+ flagTrim *bool // Set to false to ignore NodeCount/*Fraction
+ flagFocus *string // Restricts to paths going through a node matching regexp
+ flagIgnore *string // Skips paths going through any nodes matching regexp
+ flagHide *string // Skips sample locations matching regexp
+ flagTagFocus *string // Restrict to samples tagged with key:value matching regexp
+ flagTagIgnore *string // Discard samples tagged with key:value matching regexp
+ flagDropNegative *bool // Skip negative values
+
+ flagBase *string // Source for base profile to user for comparison
+
+ flagSeconds *int // Length of time for dynamic profiles
+
+ flagTotalDelay *bool // Display total delay at each region
+ flagContentions *bool // Display number of delays at each region
+ flagMeanDelay *bool // Display mean delay at each region
+
+ flagInUseSpace *bool // Display in-use memory size
+ flagInUseObjects *bool // Display in-use object counts
+ flagAllocSpace *bool // Display allocated memory size
+ flagAllocObjects *bool // Display allocated object counts
+ flagDisplayUnit *string // Measurement unit to use on reports
+ flagDivideBy *float64 // Ratio to divide sample values
+
+ flagSampleIndex *int // Sample value to use in reports.
+ flagMean *bool // Use mean of sample_index over count
+
+ flagTools *string
+ profileSource []string
+ profileExecName string
+
+ extraUsage string
+ commands commands.Commands
+}
+
+func (f *flags) isFormat(format string) bool {
+ if fl := f.flagCommands[format]; fl != nil {
+ return *fl
+ }
+ if fl := f.flagParamCommands[format]; fl != nil {
+ return *fl != ""
+ }
+ return false
+}
+
+// String provides a printable representation for the current set of flags.
+func (f *flags) String(p *profile.Profile) string {
+ var ret string
+
+ if ix := *f.flagSampleIndex; ix != -1 {
+ ret += fmt.Sprintf(" %-25s : %d (%s)\n", "sample_index", ix, p.SampleType[ix].Type)
+ }
+ if ix := *f.flagMean; ix {
+ ret += boolFlagString("mean")
+ }
+ if *f.flagDisplayUnit != "minimum" {
+ ret += stringFlagString("unit", *f.flagDisplayUnit)
+ }
+
+ switch {
+ case *f.flagInteractive:
+ ret += boolFlagString("interactive")
+ }
+ for name, fl := range f.flagCommands {
+ if *fl {
+ ret += boolFlagString(name)
+ }
+ }
+
+ if *f.flagCum {
+ ret += boolFlagString("cum")
+ }
+ if *f.flagCallTree {
+ ret += boolFlagString("call_tree")
+ }
+
+ switch {
+ case *f.flagAddresses:
+ ret += boolFlagString("addresses")
+ case *f.flagLines:
+ ret += boolFlagString("lines")
+ case *f.flagFiles:
+ ret += boolFlagString("files")
+ case *f.flagFunctions:
+ ret += boolFlagString("functions")
+ }
+
+ if *f.flagNodeCount != -1 {
+ ret += intFlagString("nodecount", *f.flagNodeCount)
+ }
+
+ ret += floatFlagString("nodefraction", *f.flagNodeFraction)
+ ret += floatFlagString("edgefraction", *f.flagEdgeFraction)
+
+ if *f.flagFocus != "" {
+ ret += stringFlagString("focus", *f.flagFocus)
+ }
+ if *f.flagIgnore != "" {
+ ret += stringFlagString("ignore", *f.flagIgnore)
+ }
+ if *f.flagHide != "" {
+ ret += stringFlagString("hide", *f.flagHide)
+ }
+
+ if *f.flagTagFocus != "" {
+ ret += stringFlagString("tagfocus", *f.flagTagFocus)
+ }
+ if *f.flagTagIgnore != "" {
+ ret += stringFlagString("tagignore", *f.flagTagIgnore)
+ }
+
+ return ret
+}
+
+func boolFlagString(label string) string {
+ return fmt.Sprintf(" %-25s : true\n", label)
+}
+
+func stringFlagString(label, value string) string {
+ return fmt.Sprintf(" %-25s : %s\n", label, value)
+}
+
+func intFlagString(label string, value int) string {
+ return fmt.Sprintf(" %-25s : %d\n", label, value)
+}
+
+func floatFlagString(label string, value float64) string {
+ return fmt.Sprintf(" %-25s : %f\n", label, value)
+}
+
+// Utility routines to set flag values.
+func newBool(b bool) *bool {
+ return &b
+}
+
+func newString(s string) *string {
+ return &s
+}
+
+func newFloat64(fl float64) *float64 {
+ return &fl
+}
+
+func newInt(i int) *int {
+ return &i
+}
+
+func (f *flags) usage(ui plugin.UI) {
+ var commandMsg []string
+ for name, cmd := range f.commands {
+ if cmd.HasParam {
+ name = name + "=p"
+ }
+ commandMsg = append(commandMsg,
+ fmt.Sprintf(" -%-16s %s", name, cmd.Usage))
+ }
+
+ sort.Strings(commandMsg)
+
+ text := usageMsgHdr + strings.Join(commandMsg, "\n") + "\n" + usageMsg + "\n"
+ if f.extraUsage != "" {
+ text += f.extraUsage + "\n"
+ }
+ text += usageMsgVars
+ ui.Print(text)
+}
+
+func getFlags(flag plugin.FlagSet, overrides commands.Commands, ui plugin.UI) (*flags, error) {
+ f := &flags{
+ flagInteractive: flag.Bool("interactive", false, "Accepts commands interactively"),
+ flagCommands: make(map[string]*bool),
+ flagParamCommands: make(map[string]*string),
+
+ // Filename for file-based output formats, stdout by default.
+ flagOutput: flag.String("output", "", "Output filename for file-based outputs "),
+ // Comparisons.
+ flagBase: flag.String("base", "", "Source for base profile for comparison"),
+ flagDropNegative: flag.Bool("drop_negative", false, "Ignore negative differences"),
+
+ flagSVGPan: flag.String("svgpan", "https://www.cyberz.org/projects/SVGPan/SVGPan.js", "URL for SVGPan Library"),
+ // Data sorting criteria.
+ flagCum: flag.Bool("cum", false, "Sort by cumulative data"),
+ // Graph handling options.
+ flagCallTree: flag.Bool("call_tree", false, "Create a context-sensitive call tree"),
+ // Granularity of output resolution.
+ flagAddresses: flag.Bool("addresses", false, "Report at address level"),
+ flagLines: flag.Bool("lines", false, "Report at source line level"),
+ flagFiles: flag.Bool("files", false, "Report at source file level"),
+ flagFunctions: flag.Bool("functions", false, "Report at function level [default]"),
+ // Internal options.
+ flagSymbolize: flag.String("symbolize", "", "Options for profile symbolization"),
+ flagBuildID: flag.String("buildid", "", "Override build id for first mapping"),
+ // Filtering options
+ flagNodeCount: flag.Int("nodecount", -1, "Max number of nodes to show"),
+ flagNodeFraction: flag.Float64("nodefraction", 0.005, "Hide nodes below <f>*total"),
+ flagEdgeFraction: flag.Float64("edgefraction", 0.001, "Hide edges below <f>*total"),
+ flagTrim: flag.Bool("trim", true, "Honor nodefraction/edgefraction/nodecount defaults"),
+ flagFocus: flag.String("focus", "", "Restricts to paths going through a node matching regexp"),
+ flagIgnore: flag.String("ignore", "", "Skips paths going through any nodes matching regexp"),
+ flagHide: flag.String("hide", "", "Skips nodes matching regexp"),
+ flagTagFocus: flag.String("tagfocus", "", "Restrict to samples with tags in range or matched by regexp"),
+ flagTagIgnore: flag.String("tagignore", "", "Discard samples with tags in range or matched by regexp"),
+ // CPU profile options
+ flagSeconds: flag.Int("seconds", -1, "Length of time for dynamic profiles"),
+ // Heap profile options
+ flagInUseSpace: flag.Bool("inuse_space", false, "Display in-use memory size"),
+ flagInUseObjects: flag.Bool("inuse_objects", false, "Display in-use object counts"),
+ flagAllocSpace: flag.Bool("alloc_space", false, "Display allocated memory size"),
+ flagAllocObjects: flag.Bool("alloc_objects", false, "Display allocated object counts"),
+ flagDisplayUnit: flag.String("unit", "minimum", "Measurement units to display"),
+ flagDivideBy: flag.Float64("divide_by", 1.0, "Ratio to divide all samples before visualization"),
+ flagSampleIndex: flag.Int("sample_index", -1, "Index of sample value to report"),
+ flagMean: flag.Bool("mean", false, "Average sample value over first value (count)"),
+ // Contention profile options
+ flagTotalDelay: flag.Bool("total_delay", false, "Display total delay at each region"),
+ flagContentions: flag.Bool("contentions", false, "Display number of delays at each region"),
+ flagMeanDelay: flag.Bool("mean_delay", false, "Display mean delay at each region"),
+ flagTools: flag.String("tools", os.Getenv("PPROF_TOOLS"), "Path for object tool pathnames"),
+ extraUsage: flag.ExtraUsage(),
+ }
+
+ // Flags used during command processing
+ interactive := &f.flagInteractive
+ svgpan := &f.flagSVGPan
+ f.commands = commands.PProf(functionCompleter, interactive, svgpan)
+
+ // Override commands
+ for name, cmd := range overrides {
+ f.commands[name] = cmd
+ }
+
+ for name, cmd := range f.commands {
+ if cmd.HasParam {
+ f.flagParamCommands[name] = flag.String(name, "", "Generate a report in "+name+" format, matching regexp")
+ } else {
+ f.flagCommands[name] = flag.Bool(name, false, "Generate a report in "+name+" format")
+ }
+ }
+
+ args := flag.Parse(func() { f.usage(ui) })
+ if len(args) == 0 {
+ return nil, fmt.Errorf("no profile source specified")
+ }
+
+ f.profileSource = args
+
+ // Instruct legacy heapz parsers to grab historical allocation data,
+ // instead of the default in-use data. Not available with tcmalloc.
+ if *f.flagAllocSpace || *f.flagAllocObjects {
+ profile.LegacyHeapAllocated = true
+ }
+
+ if profileDir := os.Getenv("PPROF_TMPDIR"); profileDir == "" {
+ profileDir = os.Getenv("HOME") + "/pprof"
+ os.Setenv("PPROF_TMPDIR", profileDir)
+ if err := os.MkdirAll(profileDir, 0755); err != nil {
+ return nil, fmt.Errorf("failed to access temp dir %s: %v", profileDir, err)
+ }
+ }
+
+ return f, nil
+}
+
+func processFlags(p *profile.Profile, ui plugin.UI, f *flags) error {
+ flagDis := f.isFormat("disasm")
+ flagPeek := f.isFormat("peek")
+ flagWebList := f.isFormat("weblist")
+ flagList := f.isFormat("list")
+
+ if flagDis || flagWebList {
+ // Collect all samples at address granularity for assembly
+ // listing.
+ f.flagNodeCount = newInt(0)
+ f.flagAddresses = newBool(true)
+ f.flagLines = newBool(false)
+ f.flagFiles = newBool(false)
+ f.flagFunctions = newBool(false)
+ }
+
+ if flagPeek {
+ // Collect all samples at function granularity for peek command
+ f.flagNodeCount = newInt(0)
+ f.flagAddresses = newBool(false)
+ f.flagLines = newBool(false)
+ f.flagFiles = newBool(false)
+ f.flagFunctions = newBool(true)
+ }
+
+ if flagList {
+ // Collect all samples at fileline granularity for source
+ // listing.
+ f.flagNodeCount = newInt(0)
+ f.flagAddresses = newBool(false)
+ f.flagLines = newBool(true)
+ f.flagFiles = newBool(false)
+ f.flagFunctions = newBool(false)
+ }
+
+ if !*f.flagTrim {
+ f.flagNodeCount = newInt(0)
+ f.flagNodeFraction = newFloat64(0)
+ f.flagEdgeFraction = newFloat64(0)
+ }
+
+ if oc := countFlagMap(f.flagCommands, f.flagParamCommands); oc == 0 {
+ f.flagInteractive = newBool(true)
+ } else if oc > 1 {
+ f.usage(ui)
+ return fmt.Errorf("must set at most one output format")
+ }
+
+ // Apply nodecount defaults for non-interactive mode. The
+ // interactive shell will apply defaults for the interactive mode.
+ if *f.flagNodeCount < 0 && !*f.flagInteractive {
+ switch {
+ default:
+ f.flagNodeCount = newInt(80)
+ case f.isFormat("text"):
+ f.flagNodeCount = newInt(0)
+ }
+ }
+
+ // Apply legacy options and diagnose conflicts.
+ if rc := countFlags([]*bool{f.flagAddresses, f.flagLines, f.flagFiles, f.flagFunctions}); rc == 0 {
+ f.flagFunctions = newBool(true)
+ } else if rc > 1 {
+ f.usage(ui)
+ return fmt.Errorf("must set at most one granularity option")
+ }
+
+ var err error
+ si, sm := *f.flagSampleIndex, *f.flagMean || *f.flagMeanDelay
+ si, err = sampleIndex(p, &f.flagTotalDelay, si, 1, "delay", "-total_delay", err)
+ si, err = sampleIndex(p, &f.flagMeanDelay, si, 1, "delay", "-mean_delay", err)
+ si, err = sampleIndex(p, &f.flagContentions, si, 0, "contentions", "-contentions", err)
+
+ si, err = sampleIndex(p, &f.flagInUseSpace, si, 1, "inuse_space", "-inuse_space", err)
+ si, err = sampleIndex(p, &f.flagInUseObjects, si, 0, "inuse_objects", "-inuse_objects", err)
+ si, err = sampleIndex(p, &f.flagAllocSpace, si, 1, "alloc_space", "-alloc_space", err)
+ si, err = sampleIndex(p, &f.flagAllocObjects, si, 0, "alloc_objects", "-alloc_objects", err)
+
+ if si == -1 {
+ // Use last value if none is requested.
+ si = len(p.SampleType) - 1
+ } else if si < 0 || si >= len(p.SampleType) {
+ err = fmt.Errorf("sample_index value %d out of range [0..%d]", si, len(p.SampleType)-1)
+ }
+
+ if err != nil {
+ f.usage(ui)
+ return err
+ }
+ f.flagSampleIndex, f.flagMean = newInt(si), newBool(sm)
+ return nil
+}
+
+func sampleIndex(p *profile.Profile, flag **bool,
+ sampleIndex int,
+ newSampleIndex int,
+ sampleType, option string,
+ err error) (int, error) {
+ if err != nil || !**flag {
+ return sampleIndex, err
+ }
+ *flag = newBool(false)
+ if sampleIndex != -1 {
+ return 0, fmt.Errorf("set at most one sample value selection option")
+ }
+ if newSampleIndex >= len(p.SampleType) ||
+ p.SampleType[newSampleIndex].Type != sampleType {
+ return 0, fmt.Errorf("option %s not valid for this profile", option)
+ }
+ return newSampleIndex, nil
+}
+
+func countFlags(bs []*bool) int {
+ var c int
+ for _, b := range bs {
+ if *b {
+ c++
+ }
+ }
+ return c
+}
+
+func countFlagMap(bms map[string]*bool, bmrxs map[string]*string) int {
+ var c int
+ for _, b := range bms {
+ if *b {
+ c++
+ }
+ }
+ for _, s := range bmrxs {
+ if *s != "" {
+ c++
+ }
+ }
+ return c
+}
+
+var usageMsgHdr = "usage: pprof [options] [binary] <profile source> ...\n" +
+ "Output format (only set one):\n"
+
+var usageMsg = "Output file parameters (for file-based output formats):\n" +
+ " -output=f Generate output on file f (stdout by default)\n" +
+ "Output granularity (only set one):\n" +
+ " -functions Report at function level [default]\n" +
+ " -files Report at source file level\n" +
+ " -lines Report at source line level\n" +
+ " -addresses Report at address level\n" +
+ "Comparison options:\n" +
+ " -base <profile> Show delta from this profile\n" +
+ " -drop_negative Ignore negative differences\n" +
+ "Sorting options:\n" +
+ " -cum Sort by cumulative data\n\n" +
+ "Dynamic profile options:\n" +
+ " -seconds=N Length of time for dynamic profiles\n" +
+ "Profile trimming options:\n" +
+ " -nodecount=N Max number of nodes to show\n" +
+ " -nodefraction=f Hide nodes below <f>*total\n" +
+ " -edgefraction=f Hide edges below <f>*total\n" +
+ "Sample value selection option (by index):\n" +
+ " -sample_index Index of sample value to display\n" +
+ " -mean Average sample value over first value\n" +
+ "Sample value selection option (for heap profiles):\n" +
+ " -inuse_space Display in-use memory size\n" +
+ " -inuse_objects Display in-use object counts\n" +
+ " -alloc_space Display allocated memory size\n" +
+ " -alloc_objects Display allocated object counts\n" +
+ "Sample value selection option (for contention profiles):\n" +
+ " -total_delay Display total delay at each region\n" +
+ " -contentions Display number of delays at each region\n" +
+ " -mean_delay Display mean delay at each region\n" +
+ "Filtering options:\n" +
+ " -focus=r Restricts to paths going through a node matching regexp\n" +
+ " -ignore=r Skips paths going through any nodes matching regexp\n" +
+ " -tagfocus=r Restrict to samples tagged with key:value matching regexp\n" +
+ " Restrict to samples with numeric tags in range (eg \"32kb:1mb\")\n" +
+ " -tagignore=r Discard samples tagged with key:value matching regexp\n" +
+ " Avoid samples with numeric tags in range (eg \"1mb:\")\n" +
+ "Miscellaneous:\n" +
+ " -call_tree Generate a context-sensitive call tree\n" +
+ " -unit=u Convert all samples to unit u for display\n" +
+ " -show_bytes Display all space in bytes\n" +
+ " -divide_by=f Scale all samples by dividing them by f\n" +
+ " -buildid=id Override build id for main binary in profile\n" +
+ " -tools=path Search path for object-level tools\n" +
+ " -help This message"
+
+var usageMsgVars = "Environment Variables:\n" +
+ " PPROF_TMPDIR Location for temporary files (default $HOME/pprof)\n" +
+ " PPROF_TOOLS Search path for object-level tools\n" +
+ " PPROF_BINARY_PATH Search path for local binary files\n" +
+ " default: $HOME/pprof/binaries\n" +
+ " finds binaries by $name and $buildid/$name"
+
+func aggregate(prof *profile.Profile, f *flags) error {
+ switch {
+ case f.isFormat("proto"), f.isFormat("raw"):
+ // No aggregation for raw profiles.
+ case f.isFormat("callgrind"):
+ // Aggregate to file/line for callgrind.
+ fallthrough
+ case *f.flagLines:
+ return prof.Aggregate(true, true, true, true, false)
+ case *f.flagFiles:
+ return prof.Aggregate(true, false, true, false, false)
+ case *f.flagFunctions:
+ return prof.Aggregate(true, true, false, false, false)
+ case f.isFormat("weblist"), f.isFormat("disasm"):
+ return prof.Aggregate(false, true, true, true, true)
+ }
+ return nil
+}
+
+// parseOptions parses the options into report.Options
+// Returns a function to postprocess the report after generation.
+func parseOptions(f *flags) (o *report.Options, p commands.PostProcessor, err error) {
+
+ if *f.flagDivideBy == 0 {
+ return nil, nil, fmt.Errorf("zero divisor specified")
+ }
+
+ o = &report.Options{
+ CumSort: *f.flagCum,
+ CallTree: *f.flagCallTree,
+ PrintAddresses: *f.flagAddresses,
+ DropNegative: *f.flagDropNegative,
+ Ratio: 1 / *f.flagDivideBy,
+
+ NodeCount: *f.flagNodeCount,
+ NodeFraction: *f.flagNodeFraction,
+ EdgeFraction: *f.flagEdgeFraction,
+ OutputUnit: *f.flagDisplayUnit,
+ }
+
+ for cmd, b := range f.flagCommands {
+ if *b {
+ pcmd := f.commands[cmd]
+ o.OutputFormat = pcmd.Format
+ return o, pcmd.PostProcess, nil
+ }
+ }
+
+ for cmd, rx := range f.flagParamCommands {
+ if *rx != "" {
+ pcmd := f.commands[cmd]
+ if o.Symbol, err = regexp.Compile(*rx); err != nil {
+ return nil, nil, fmt.Errorf("parsing -%s regexp: %v", cmd, err)
+ }
+ o.OutputFormat = pcmd.Format
+ return o, pcmd.PostProcess, nil
+ }
+ }
+
+ return nil, nil, fmt.Errorf("no output format selected")
+}
+
+type sampleValueFunc func(*profile.Sample) int64
+
+// sampleFormat returns a function to extract values out of a profile.Sample,
+// and the type/units of those values.
+func sampleFormat(p *profile.Profile, f *flags) (sampleValueFunc, string, string) {
+ valueIndex := *f.flagSampleIndex
+
+ if *f.flagMean {
+ return meanExtractor(valueIndex), "mean_" + p.SampleType[valueIndex].Type, p.SampleType[valueIndex].Unit
+ }
+
+ return valueExtractor(valueIndex), p.SampleType[valueIndex].Type, p.SampleType[valueIndex].Unit
+}
+
+func valueExtractor(ix int) sampleValueFunc {
+ return func(s *profile.Sample) int64 {
+ return s.Value[ix]
+ }
+}
+
+func meanExtractor(ix int) sampleValueFunc {
+ return func(s *profile.Sample) int64 {
+ if s.Value[0] == 0 {
+ return 0
+ }
+ return s.Value[ix] / s.Value[0]
+ }
+}
+
+func generate(interactive bool, prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI, f *flags) error {
+ o, postProcess, err := parseOptions(f)
+ if err != nil {
+ return err
+ }
+
+ var w io.Writer
+ if *f.flagOutput == "" {
+ w = os.Stdout
+ } else {
+ ui.PrintErr("Generating report in ", *f.flagOutput)
+ outputFile, err := os.Create(*f.flagOutput)
+ if err != nil {
+ return err
+ }
+ defer outputFile.Close()
+ w = outputFile
+ }
+
+ value, stype, unit := sampleFormat(prof, f)
+ o.SampleType = stype
+ rpt := report.New(prof, *o, value, unit)
+
+ // Do not apply filters if we're just generating a proto, so we
+ // still have all the data.
+ if o.OutputFormat != report.Proto {
+ // Delay applying focus/ignore until after creating the report so
+ // the report reflects the total number of samples.
+ if err := preprocess(prof, ui, f); err != nil {
+ return err
+ }
+ }
+
+ if postProcess == nil {
+ return report.Generate(w, rpt, obj)
+ }
+
+ var dot bytes.Buffer
+ if err = report.Generate(&dot, rpt, obj); err != nil {
+ return err
+ }
+
+ return postProcess(&dot, w, ui)
+}
diff --git a/src/cmd/pprof/internal/driver/interactive.go b/src/cmd/pprof/internal/driver/interactive.go
new file mode 100644
index 000000000..13009bf7e
--- /dev/null
+++ b/src/cmd/pprof/internal/driver/interactive.go
@@ -0,0 +1,492 @@
+// 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 driver
+
+import (
+ "fmt"
+ "io"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+
+ "cmd/pprof/internal/commands"
+ "cmd/pprof/internal/plugin"
+ "cmd/pprof/internal/profile"
+)
+
+var profileFunctionNames = []string{}
+
+// functionCompleter replaces provided substring with a function
+// name retrieved from a profile if a single match exists. Otherwise,
+// it returns unchanged substring. It defaults to no-op if the profile
+// is not specified.
+func functionCompleter(substring string) string {
+ found := ""
+ for _, fName := range profileFunctionNames {
+ if strings.Contains(fName, substring) {
+ if found != "" {
+ return substring
+ }
+ found = fName
+ }
+ }
+ if found != "" {
+ return found
+ }
+ return substring
+}
+
+// updateAutoComplete enhances autocompletion with information that can be
+// retrieved from the profile
+func updateAutoComplete(p *profile.Profile) {
+ profileFunctionNames = nil // remove function names retrieved previously
+ for _, fn := range p.Function {
+ profileFunctionNames = append(profileFunctionNames, fn.Name)
+ }
+}
+
+// splitCommand splits the command line input into tokens separated by
+// spaces. Takes care to separate commands of the form 'top10' into
+// two tokens: 'top' and '10'
+func splitCommand(input string) []string {
+ fields := strings.Fields(input)
+ if num := strings.IndexAny(fields[0], "0123456789"); num != -1 {
+ inputNumber := fields[0][num:]
+ fields[0] = fields[0][:num]
+ fields = append([]string{fields[0], inputNumber}, fields[1:]...)
+ }
+ return fields
+}
+
+// interactive displays a prompt and reads commands for profile
+// manipulation/visualization.
+func interactive(p *profile.Profile, obj plugin.ObjTool, ui plugin.UI, f *flags) error {
+ updateAutoComplete(p)
+
+ // Enter command processing loop.
+ ui.Print("Entering interactive mode (type \"help\" for commands)")
+ ui.SetAutoComplete(commands.NewCompleter(f.commands))
+
+ for {
+ input, err := readCommand(p, ui, f)
+ if err != nil {
+ if err != io.EOF {
+ return err
+ }
+ if input == "" {
+ return nil
+ }
+ }
+ // Process simple commands.
+ switch input {
+ case "":
+ continue
+ case ":":
+ f.flagFocus = newString("")
+ f.flagIgnore = newString("")
+ f.flagTagFocus = newString("")
+ f.flagTagIgnore = newString("")
+ f.flagHide = newString("")
+ continue
+ }
+
+ fields := splitCommand(input)
+ // Process report generation commands.
+ if _, ok := f.commands[fields[0]]; ok {
+ if err := generateReport(p, fields, obj, ui, f); err != nil {
+ if err == io.EOF {
+ return nil
+ }
+ ui.PrintErr(err)
+ }
+ continue
+ }
+
+ switch cmd := fields[0]; cmd {
+ case "help":
+ commandHelp(fields, ui, f)
+ continue
+ case "exit", "quit":
+ return nil
+ }
+
+ // Process option settings.
+ if of, err := optFlags(p, input, f); err == nil {
+ f = of
+ } else {
+ ui.PrintErr("Error: ", err.Error())
+ }
+ }
+}
+
+func generateReport(p *profile.Profile, cmd []string, obj plugin.ObjTool, ui plugin.UI, f *flags) error {
+ prof := p.Copy()
+
+ cf, err := cmdFlags(prof, cmd, ui, f)
+ if err != nil {
+ return err
+ }
+
+ return generate(true, prof, obj, ui, cf)
+}
+
+// validateRegex checks if a string is a valid regular expression.
+func validateRegex(v string) error {
+ _, err := regexp.Compile(v)
+ return err
+}
+
+// readCommand prompts for and reads the next command.
+func readCommand(p *profile.Profile, ui plugin.UI, f *flags) (string, error) {
+ //ui.Print("Options:\n", f.String(p))
+ s, err := ui.ReadLine()
+ return strings.TrimSpace(s), err
+}
+
+func commandHelp(_ []string, ui plugin.UI, f *flags) error {
+ help := `
+ Commands:
+ cmd [n] [--cum] [focus_regex]* [-ignore_regex]*
+ Produce a text report with the top n entries.
+ Include samples matching focus_regex, and exclude ignore_regex.
+ Add --cum to sort using cumulative data.
+ Available commands:
+`
+ var commands []string
+ for name, cmd := range f.commands {
+ commands = append(commands, fmt.Sprintf(" %-12s %s", name, cmd.Usage))
+ }
+ sort.Strings(commands)
+
+ help = help + strings.Join(commands, "\n") + `
+ peek func_regex
+ Display callers and callees of functions matching func_regex.
+
+ dot [n] [focus_regex]* [-ignore_regex]* [>file]
+ Produce an annotated callgraph with the top n entries.
+ Include samples matching focus_regex, and exclude ignore_regex.
+ For other outputs, replace dot with:
+ - Graphic formats: dot, svg, pdf, ps, gif, png (use > to name output file)
+ - Graph viewer: gv, web, evince, eog
+
+ callgrind [n] [focus_regex]* [-ignore_regex]* [>file]
+ Produce a file in callgrind-compatible format.
+ Include samples matching focus_regex, and exclude ignore_regex.
+
+ weblist func_regex [-ignore_regex]*
+ Show annotated source with interspersed assembly in a web browser.
+
+ list func_regex [-ignore_regex]*
+ Print source for routines matching func_regex, and exclude ignore_regex.
+
+ disasm func_regex [-ignore_regex]*
+ Disassemble routines matching func_regex, and exclude ignore_regex.
+
+ tags tag_regex [-ignore_regex]*
+ List tags with key:value matching tag_regex and exclude ignore_regex.
+
+ quit/exit/^D
+ Exit pprof.
+
+ option=value
+ The following options can be set individually:
+ cum/flat: Sort entries based on cumulative or flat data
+ call_tree: Build context-sensitive call trees
+ nodecount: Max number of entries to display
+ nodefraction: Min frequency ratio of nodes to display
+ edgefraction: Min frequency ratio of edges to display
+ focus/ignore: Regexp to include/exclude samples by name/file
+ tagfocus/tagignore: Regexp or value range to filter samples by tag
+ eg "1mb", "1mb:2mb", ":64kb"
+
+ functions: Level of aggregation for sample data
+ files:
+ lines:
+ addresses:
+
+ unit: Measurement unit to use on reports
+
+ Sample value selection by index:
+ sample_index: Index of sample value to display
+ mean: Average sample value over first value
+
+ Sample value selection by name:
+ alloc_space for heap profiles
+ alloc_objects
+ inuse_space
+ inuse_objects
+
+ total_delay for contention profiles
+ mean_delay
+ contentions
+
+ : Clear focus/ignore/hide/tagfocus/tagignore`
+
+ ui.Print(help)
+ return nil
+}
+
+// cmdFlags parses the options of an interactive command and returns
+// an updated flags object.
+func cmdFlags(prof *profile.Profile, input []string, ui plugin.UI, f *flags) (*flags, error) {
+ cf := *f
+
+ var focus, ignore string
+ output := *cf.flagOutput
+ nodeCount := *cf.flagNodeCount
+ cmd := input[0]
+
+ // Update output flags based on parameters.
+ tokens := input[1:]
+ for p := 0; p < len(tokens); p++ {
+ t := tokens[p]
+ if t == "" {
+ continue
+ }
+ if c, err := strconv.ParseInt(t, 10, 32); err == nil {
+ nodeCount = int(c)
+ continue
+ }
+ switch t[0] {
+ case '>':
+ if len(t) > 1 {
+ output = t[1:]
+ continue
+ }
+ // find next token
+ for p++; p < len(tokens); p++ {
+ if tokens[p] != "" {
+ output = tokens[p]
+ break
+ }
+ }
+ case '-':
+ if t == "--cum" || t == "-cum" {
+ cf.flagCum = newBool(true)
+ continue
+ }
+ ignore = catRegex(ignore, t[1:])
+ default:
+ focus = catRegex(focus, t)
+ }
+ }
+
+ pcmd, ok := f.commands[cmd]
+ if !ok {
+ return nil, fmt.Errorf("Unexpected parse failure: %v", input)
+ }
+ // Reset flags
+ cf.flagCommands = make(map[string]*bool)
+ cf.flagParamCommands = make(map[string]*string)
+
+ if !pcmd.HasParam {
+ cf.flagCommands[cmd] = newBool(true)
+
+ switch cmd {
+ case "tags":
+ cf.flagTagFocus = newString(focus)
+ cf.flagTagIgnore = newString(ignore)
+ default:
+ cf.flagFocus = newString(catRegex(*cf.flagFocus, focus))
+ cf.flagIgnore = newString(catRegex(*cf.flagIgnore, ignore))
+ }
+ } else {
+ if focus == "" {
+ focus = "."
+ }
+ cf.flagParamCommands[cmd] = newString(focus)
+ cf.flagIgnore = newString(catRegex(*cf.flagIgnore, ignore))
+ }
+
+ if nodeCount < 0 {
+ switch cmd {
+ case "text", "top":
+ // Default text/top to 10 nodes on interactive mode
+ nodeCount = 10
+ default:
+ nodeCount = 80
+ }
+ }
+
+ cf.flagNodeCount = newInt(nodeCount)
+ cf.flagOutput = newString(output)
+
+ // Do regular flags processing
+ if err := processFlags(prof, ui, &cf); err != nil {
+ cf.usage(ui)
+ return nil, err
+ }
+
+ return &cf, nil
+}
+
+func catRegex(a, b string) string {
+ if a == "" {
+ return b
+ }
+ if b == "" {
+ return a
+ }
+ return a + "|" + b
+}
+
+// optFlags parses an interactive option setting and returns
+// an updated flags object.
+func optFlags(p *profile.Profile, input string, f *flags) (*flags, error) {
+ inputs := strings.SplitN(input, "=", 2)
+ option := strings.ToLower(strings.TrimSpace(inputs[0]))
+ var value string
+ if len(inputs) == 2 {
+ value = strings.TrimSpace(inputs[1])
+ }
+
+ of := *f
+
+ var err error
+ var bv bool
+ var uv uint64
+ var fv float64
+
+ switch option {
+ case "cum":
+ if bv, err = parseBool(value); err != nil {
+ return nil, err
+ }
+ of.flagCum = newBool(bv)
+ case "flat":
+ if bv, err = parseBool(value); err != nil {
+ return nil, err
+ }
+ of.flagCum = newBool(!bv)
+ case "call_tree":
+ if bv, err = parseBool(value); err != nil {
+ return nil, err
+ }
+ of.flagCallTree = newBool(bv)
+ case "unit":
+ of.flagDisplayUnit = newString(value)
+ case "sample_index":
+ if uv, err = strconv.ParseUint(value, 10, 32); err != nil {
+ return nil, err
+ }
+ if ix := int(uv); ix < 0 || ix >= len(p.SampleType) {
+ return nil, fmt.Errorf("sample_index out of range [0..%d]", len(p.SampleType)-1)
+ }
+ of.flagSampleIndex = newInt(int(uv))
+ case "mean":
+ if bv, err = parseBool(value); err != nil {
+ return nil, err
+ }
+ of.flagMean = newBool(bv)
+ case "nodecount":
+ if uv, err = strconv.ParseUint(value, 10, 32); err != nil {
+ return nil, err
+ }
+ of.flagNodeCount = newInt(int(uv))
+ case "nodefraction":
+ if fv, err = strconv.ParseFloat(value, 64); err != nil {
+ return nil, err
+ }
+ of.flagNodeFraction = newFloat64(fv)
+ case "edgefraction":
+ if fv, err = strconv.ParseFloat(value, 64); err != nil {
+ return nil, err
+ }
+ of.flagEdgeFraction = newFloat64(fv)
+ case "focus":
+ if err = validateRegex(value); err != nil {
+ return nil, err
+ }
+ of.flagFocus = newString(value)
+ case "ignore":
+ if err = validateRegex(value); err != nil {
+ return nil, err
+ }
+ of.flagIgnore = newString(value)
+ case "tagfocus":
+ if err = validateRegex(value); err != nil {
+ return nil, err
+ }
+ of.flagTagFocus = newString(value)
+ case "tagignore":
+ if err = validateRegex(value); err != nil {
+ return nil, err
+ }
+ of.flagTagIgnore = newString(value)
+ case "hide":
+ if err = validateRegex(value); err != nil {
+ return nil, err
+ }
+ of.flagHide = newString(value)
+ case "addresses", "files", "lines", "functions":
+ if bv, err = parseBool(value); err != nil {
+ return nil, err
+ }
+ if !bv {
+ return nil, fmt.Errorf("select one of addresses/files/lines/functions")
+ }
+ setGranularityToggle(option, &of)
+ default:
+ if ix := findSampleIndex(p, "", option); ix >= 0 {
+ of.flagSampleIndex = newInt(ix)
+ } else if ix := findSampleIndex(p, "total_", option); ix >= 0 {
+ of.flagSampleIndex = newInt(ix)
+ of.flagMean = newBool(false)
+ } else if ix := findSampleIndex(p, "mean_", option); ix >= 1 {
+ of.flagSampleIndex = newInt(ix)
+ of.flagMean = newBool(true)
+ } else {
+ return nil, fmt.Errorf("unrecognized command: %s", input)
+ }
+ }
+ return &of, nil
+}
+
+// parseBool parses a string as a boolean value.
+func parseBool(v string) (bool, error) {
+ switch strings.ToLower(v) {
+ case "true", "t", "yes", "y", "1", "":
+ return true, nil
+ case "false", "f", "no", "n", "0":
+ return false, nil
+ }
+ return false, fmt.Errorf(`illegal input "%s" for bool value`, v)
+}
+
+func findSampleIndex(p *profile.Profile, prefix, sampleType string) int {
+ if !strings.HasPrefix(sampleType, prefix) {
+ return -1
+ }
+ sampleType = strings.TrimPrefix(sampleType, prefix)
+ for i, r := range p.SampleType {
+ if r.Type == sampleType {
+ return i
+ }
+ }
+ return -1
+}
+
+// setGranularityToggle manages the set of granularity options. These
+// operate as a toggle; turning one on turns the others off.
+func setGranularityToggle(o string, fl *flags) {
+ t, f := newBool(true), newBool(false)
+ fl.flagFunctions = f
+ fl.flagFiles = f
+ fl.flagLines = f
+ fl.flagAddresses = f
+ switch o {
+ case "functions":
+ fl.flagFunctions = t
+ case "files":
+ fl.flagFiles = t
+ case "lines":
+ fl.flagLines = t
+ case "addresses":
+ fl.flagAddresses = t
+ default:
+ panic(fmt.Errorf("unexpected option %s", o))
+ }
+}
diff --git a/src/cmd/pprof/internal/fetch/fetch.go b/src/cmd/pprof/internal/fetch/fetch.go
new file mode 100644
index 000000000..ec4a6383c
--- /dev/null
+++ b/src/cmd/pprof/internal/fetch/fetch.go
@@ -0,0 +1,82 @@
+// 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 fetch provides an extensible mechanism to fetch a profile
+// from a data source.
+package fetch
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "os"
+ "strings"
+ "time"
+
+ "cmd/pprof/internal/plugin"
+ "cmd/pprof/internal/profile"
+)
+
+// FetchProfile reads from a data source (network, file) and generates a
+// profile.
+func FetchProfile(source string, timeout time.Duration) (*profile.Profile, error) {
+ return Fetcher(source, timeout, plugin.StandardUI())
+}
+
+// Fetcher is the plugin.Fetcher version of FetchProfile.
+func Fetcher(source string, timeout time.Duration, ui plugin.UI) (*profile.Profile, error) {
+ var f io.ReadCloser
+ var err error
+
+ url, err := url.Parse(source)
+ if err == nil && url.Host != "" {
+ f, err = FetchURL(source, timeout)
+ } else {
+ f, err = os.Open(source)
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ return profile.Parse(f)
+}
+
+// FetchURL fetches a profile from a URL using HTTP.
+func FetchURL(source string, timeout time.Duration) (io.ReadCloser, error) {
+ resp, err := httpGet(source, timeout)
+ if err != nil {
+ return nil, fmt.Errorf("http fetch %s: %v", source, err)
+ }
+ if resp.StatusCode != http.StatusOK {
+ return nil, fmt.Errorf("server response: %s", resp.Status)
+ }
+
+ return resp.Body, nil
+}
+
+// PostURL issues a POST to a URL over HTTP.
+func PostURL(source, post string) ([]byte, error) {
+ resp, err := http.Post(source, "application/octet-stream", strings.NewReader(post))
+ if err != nil {
+ return nil, fmt.Errorf("http post %s: %v", source, err)
+ }
+ if resp.StatusCode != http.StatusOK {
+ return nil, fmt.Errorf("server response: %s", resp.Status)
+ }
+ defer resp.Body.Close()
+ return ioutil.ReadAll(resp.Body)
+}
+
+// httpGet is a wrapper around http.Get; it is defined as a variable
+// so it can be redefined during for testing.
+var httpGet = func(url string, timeout time.Duration) (*http.Response, error) {
+ client := &http.Client{
+ Transport: &http.Transport{
+ ResponseHeaderTimeout: timeout + 5*time.Second,
+ },
+ }
+ return client.Get(url)
+}
diff --git a/src/cmd/pprof/internal/plugin/plugin.go b/src/cmd/pprof/internal/plugin/plugin.go
new file mode 100644
index 000000000..a22ec5f3c
--- /dev/null
+++ b/src/cmd/pprof/internal/plugin/plugin.go
@@ -0,0 +1,213 @@
+// 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 plugin defines the plugin implementations that the main pprof driver requires.
+package plugin
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "regexp"
+ "strings"
+ "time"
+
+ "cmd/pprof/internal/profile"
+)
+
+// A FlagSet creates and parses command-line flags.
+// It is similar to the standard flag.FlagSet.
+type FlagSet interface {
+ // Bool, Int, Float64, and String define new flags,
+ // like the functions of the same name in package flag.
+ Bool(name string, def bool, usage string) *bool
+ Int(name string, def int, usage string) *int
+ Float64(name string, def float64, usage string) *float64
+ String(name string, def string, usage string) *string
+
+ // ExtraUsage returns any additional text that should be
+ // printed after the standard usage message.
+ // The typical use of ExtraUsage is to show any custom flags
+ // defined by the specific pprof plugins being used.
+ ExtraUsage() string
+
+ // Parse initializes the flags with their values for this run
+ // and returns the non-flag command line arguments.
+ // If an unknown flag is encountered or there are no arguments,
+ // Parse should call usage and return nil.
+ Parse(usage func()) []string
+}
+
+// An ObjTool inspects shared libraries and executable files.
+type ObjTool interface {
+ // Open opens the named object file.
+ // If the object is a shared library, start is the address where
+ // it is mapped into memory in the address space being inspected.
+ Open(file string, start uint64) (ObjFile, error)
+
+ // Demangle translates a batch of symbol names from mangled
+ // form to human-readable form.
+ Demangle(names []string) (map[string]string, error)
+
+ // Disasm disassembles the named object file, starting at
+ // the start address and stopping at (before) the end address.
+ Disasm(file string, start, end uint64) ([]Inst, error)
+
+ // SetConfig configures the tool.
+ // The implementation defines the meaning of the string
+ // and can ignore it entirely.
+ SetConfig(config string)
+}
+
+// NoObjTool returns a trivial implementation of the ObjTool interface.
+// Open returns an error indicating that the requested file does not exist.
+// Demangle returns an empty map and a nil error.
+// Disasm returns an error.
+// SetConfig is a no-op.
+func NoObjTool() ObjTool {
+ return noObjTool{}
+}
+
+type noObjTool struct{}
+
+func (noObjTool) Open(file string, start uint64) (ObjFile, error) {
+ return nil, &os.PathError{Op: "open", Path: file, Err: os.ErrNotExist}
+}
+
+func (noObjTool) Demangle(name []string) (map[string]string, error) {
+ return make(map[string]string), nil
+}
+
+func (noObjTool) Disasm(file string, start, end uint64) ([]Inst, error) {
+ return nil, fmt.Errorf("disassembly not supported")
+}
+
+func (noObjTool) SetConfig(config string) {
+}
+
+// An ObjFile is a single object file: a shared library or executable.
+type ObjFile interface {
+ // Name returns the underlyinf file name, if available
+ Name() string
+
+ // Base returns the base address to use when looking up symbols in the file.
+ Base() uint64
+
+ // BuildID returns the GNU build ID of the file, or an empty string.
+ BuildID() string
+
+ // SourceLine reports the source line information for a given
+ // address in the file. Due to inlining, the source line information
+ // is in general a list of positions representing a call stack,
+ // with the leaf function first.
+ SourceLine(addr uint64) ([]Frame, error)
+
+ // Symbols returns a list of symbols in the object file.
+ // If r is not nil, Symbols restricts the list to symbols
+ // with names matching the regular expression.
+ // If addr is not zero, Symbols restricts the list to symbols
+ // containing that address.
+ Symbols(r *regexp.Regexp, addr uint64) ([]*Sym, error)
+
+ // Close closes the file, releasing associated resources.
+ Close() error
+}
+
+// A Frame describes a single line in a source file.
+type Frame struct {
+ Func string // name of function
+ File string // source file name
+ Line int // line in file
+}
+
+// A Sym describes a single symbol in an object file.
+type Sym struct {
+ Name []string // names of symbol (many if symbol was dedup'ed)
+ File string // object file containing symbol
+ Start uint64 // start virtual address
+ End uint64 // virtual address of last byte in sym (Start+size-1)
+}
+
+// An Inst is a single instruction in an assembly listing.
+type Inst struct {
+ Addr uint64 // virtual address of instruction
+ Text string // instruction text
+ File string // source file
+ Line int // source line
+}
+
+// A UI manages user interactions.
+type UI interface {
+ // Read returns a line of text (a command) read from the user.
+ ReadLine() (string, error)
+
+ // Print shows a message to the user.
+ // It formats the text as fmt.Print would and adds a final \n if not already present.
+ // For line-based UI, Print writes to standard error.
+ // (Standard output is reserved for report data.)
+ Print(...interface{})
+
+ // PrintErr shows an error message to the user.
+ // It formats the text as fmt.Print would and adds a final \n if not already present.
+ // For line-based UI, PrintErr writes to standard error.
+ PrintErr(...interface{})
+
+ // IsTerminal returns whether the UI is known to be tied to an
+ // interactive terminal (as opposed to being redirected to a file).
+ IsTerminal() bool
+
+ // SetAutoComplete instructs the UI to call complete(cmd) to obtain
+ // the auto-completion of cmd, if the UI supports auto-completion at all.
+ SetAutoComplete(complete func(string) string)
+}
+
+// StandardUI returns a UI that reads from standard input,
+// prints messages to standard output,
+// prints errors to standard error, and doesn't use auto-completion.
+func StandardUI() UI {
+ return &stdUI{r: bufio.NewReader(os.Stdin)}
+}
+
+type stdUI struct {
+ r *bufio.Reader
+}
+
+func (ui *stdUI) ReadLine() (string, error) {
+ os.Stdout.WriteString("(pprof) ")
+ return ui.r.ReadString('\n')
+}
+
+func (ui *stdUI) Print(args ...interface{}) {
+ ui.fprint(os.Stderr, args)
+}
+
+func (ui *stdUI) PrintErr(args ...interface{}) {
+ ui.fprint(os.Stderr, args)
+}
+
+func (ui *stdUI) IsTerminal() bool {
+ return false
+}
+
+func (ui *stdUI) SetAutoComplete(func(string) string) {
+}
+
+func (ui *stdUI) fprint(f *os.File, args []interface{}) {
+ text := fmt.Sprint(args...)
+ if !strings.HasSuffix(text, "\n") {
+ text += "\n"
+ }
+ f.WriteString(text)
+}
+
+// A Fetcher reads and returns the profile named by src.
+// It gives up after the given timeout, unless src contains a timeout override
+// (as defined by the implementation).
+// It can print messages to ui.
+type Fetcher func(src string, timeout time.Duration, ui UI) (*profile.Profile, error)
+
+// A Symbolizer annotates a profile with symbol information.
+// The profile was fetch from src.
+// The meaning of mode is defined by the implementation.
+type Symbolizer func(mode, src string, prof *profile.Profile, obj ObjTool, ui UI) error
diff --git a/src/cmd/pprof/internal/profile/encode.go b/src/cmd/pprof/internal/profile/encode.go
new file mode 100644
index 000000000..455aca29f
--- /dev/null
+++ b/src/cmd/pprof/internal/profile/encode.go
@@ -0,0 +1,470 @@
+// 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 profile
+
+import (
+ "errors"
+ "fmt"
+ "sort"
+)
+
+func (p *Profile) decoder() []decoder {
+ return profileDecoder
+}
+
+// preEncode populates the unexported fields to be used by encode
+// (with suffix X) from the corresponding exported fields. The
+// exported fields are cleared up to facilitate testing.
+func (p *Profile) preEncode() {
+ strings := make(map[string]int)
+ addString(strings, "")
+
+ for _, st := range p.SampleType {
+ st.typeX = addString(strings, st.Type)
+ st.unitX = addString(strings, st.Unit)
+ }
+
+ for _, s := range p.Sample {
+ s.labelX = nil
+ var keys []string
+ for k := range s.Label {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ for _, k := range keys {
+ vs := s.Label[k]
+ for _, v := range vs {
+ s.labelX = append(s.labelX,
+ Label{
+ keyX: addString(strings, k),
+ strX: addString(strings, v),
+ },
+ )
+ }
+ }
+ var numKeys []string
+ for k := range s.NumLabel {
+ numKeys = append(numKeys, k)
+ }
+ sort.Strings(numKeys)
+ for _, k := range numKeys {
+ vs := s.NumLabel[k]
+ for _, v := range vs {
+ s.labelX = append(s.labelX,
+ Label{
+ keyX: addString(strings, k),
+ numX: v,
+ },
+ )
+ }
+ }
+ s.locationIDX = nil
+ for _, l := range s.Location {
+ s.locationIDX = append(s.locationIDX, l.ID)
+ }
+ }
+
+ for _, m := range p.Mapping {
+ m.fileX = addString(strings, m.File)
+ m.buildIDX = addString(strings, m.BuildID)
+ }
+
+ for _, l := range p.Location {
+ for i, ln := range l.Line {
+ if ln.Function != nil {
+ l.Line[i].functionIDX = ln.Function.ID
+ } else {
+ l.Line[i].functionIDX = 0
+ }
+ }
+ if l.Mapping != nil {
+ l.mappingIDX = l.Mapping.ID
+ } else {
+ l.mappingIDX = 0
+ }
+ }
+ for _, f := range p.Function {
+ f.nameX = addString(strings, f.Name)
+ f.systemNameX = addString(strings, f.SystemName)
+ f.filenameX = addString(strings, f.Filename)
+ }
+
+ p.dropFramesX = addString(strings, p.DropFrames)
+ p.keepFramesX = addString(strings, p.KeepFrames)
+
+ if pt := p.PeriodType; pt != nil {
+ pt.typeX = addString(strings, pt.Type)
+ pt.unitX = addString(strings, pt.Unit)
+ }
+
+ p.stringTable = make([]string, len(strings))
+ for s, i := range strings {
+ p.stringTable[i] = s
+ }
+}
+
+func (p *Profile) encode(b *buffer) {
+ for _, x := range p.SampleType {
+ encodeMessage(b, 1, x)
+ }
+ for _, x := range p.Sample {
+ encodeMessage(b, 2, x)
+ }
+ for _, x := range p.Mapping {
+ encodeMessage(b, 3, x)
+ }
+ for _, x := range p.Location {
+ encodeMessage(b, 4, x)
+ }
+ for _, x := range p.Function {
+ encodeMessage(b, 5, x)
+ }
+ encodeStrings(b, 6, p.stringTable)
+ encodeInt64Opt(b, 7, p.dropFramesX)
+ encodeInt64Opt(b, 8, p.keepFramesX)
+ encodeInt64Opt(b, 9, p.TimeNanos)
+ encodeInt64Opt(b, 10, p.DurationNanos)
+ if pt := p.PeriodType; pt != nil && (pt.typeX != 0 || pt.unitX != 0) {
+ encodeMessage(b, 11, p.PeriodType)
+ }
+ encodeInt64Opt(b, 12, p.Period)
+}
+
+var profileDecoder = []decoder{
+ nil, // 0
+ // repeated ValueType sample_type = 1
+ func(b *buffer, m message) error {
+ x := new(ValueType)
+ pp := m.(*Profile)
+ pp.SampleType = append(pp.SampleType, x)
+ return decodeMessage(b, x)
+ },
+ // repeated Sample sample = 2
+ func(b *buffer, m message) error {
+ x := new(Sample)
+ pp := m.(*Profile)
+ pp.Sample = append(pp.Sample, x)
+ return decodeMessage(b, x)
+ },
+ // repeated Mapping mapping = 3
+ func(b *buffer, m message) error {
+ x := new(Mapping)
+ pp := m.(*Profile)
+ pp.Mapping = append(pp.Mapping, x)
+ return decodeMessage(b, x)
+ },
+ // repeated Location location = 4
+ func(b *buffer, m message) error {
+ x := new(Location)
+ pp := m.(*Profile)
+ pp.Location = append(pp.Location, x)
+ return decodeMessage(b, x)
+ },
+ // repeasted Function function = 5
+ func(b *buffer, m message) error {
+ x := new(Function)
+ pp := m.(*Profile)
+ pp.Function = append(pp.Function, x)
+ return decodeMessage(b, x)
+ },
+ // repeated string string_table = 6
+ func(b *buffer, m message) error {
+ err := decodeStrings(b, &m.(*Profile).stringTable)
+ if err != nil {
+ return err
+ }
+ if *&m.(*Profile).stringTable[0] != "" {
+ return errors.New("string_table[0] must be ''")
+ }
+ return nil
+ },
+ // repeated int64 drop_frames = 7
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).dropFramesX) },
+ // repeated int64 keep_frames = 8
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).keepFramesX) },
+ // repeated int64 time_nanos = 9
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).TimeNanos) },
+ // repeated int64 duration_nanos = 10
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).DurationNanos) },
+ // optional string period_type = 11
+ func(b *buffer, m message) error {
+ x := new(ValueType)
+ pp := m.(*Profile)
+ pp.PeriodType = x
+ return decodeMessage(b, x)
+ },
+ // repeated int64 period = 12
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).Period) },
+}
+
+// postDecode takes the unexported fields populated by decode (with
+// suffix X) and populates the corresponding exported fields.
+// The unexported fields are cleared up to facilitate testing.
+func (p *Profile) postDecode() error {
+ var err error
+
+ mappings := make(map[uint64]*Mapping)
+ for _, m := range p.Mapping {
+ m.File, err = getString(p.stringTable, &m.fileX, err)
+ m.BuildID, err = getString(p.stringTable, &m.buildIDX, err)
+ mappings[m.ID] = m
+ }
+
+ functions := make(map[uint64]*Function)
+ for _, f := range p.Function {
+ f.Name, err = getString(p.stringTable, &f.nameX, err)
+ f.SystemName, err = getString(p.stringTable, &f.systemNameX, err)
+ f.Filename, err = getString(p.stringTable, &f.filenameX, err)
+ functions[f.ID] = f
+ }
+
+ locations := make(map[uint64]*Location)
+ for _, l := range p.Location {
+ l.Mapping = mappings[l.mappingIDX]
+ l.mappingIDX = 0
+ for i, ln := range l.Line {
+ if id := ln.functionIDX; id != 0 {
+ l.Line[i].Function = functions[id]
+ if l.Line[i].Function == nil {
+ return fmt.Errorf("Function ID %d not found", id)
+ }
+ l.Line[i].functionIDX = 0
+ }
+ }
+ locations[l.ID] = l
+ }
+
+ for _, st := range p.SampleType {
+ st.Type, err = getString(p.stringTable, &st.typeX, err)
+ st.Unit, err = getString(p.stringTable, &st.unitX, err)
+ }
+
+ for _, s := range p.Sample {
+ labels := make(map[string][]string)
+ numLabels := make(map[string][]int64)
+ for _, l := range s.labelX {
+ var key, value string
+ key, err = getString(p.stringTable, &l.keyX, err)
+ if l.strX != 0 {
+ value, err = getString(p.stringTable, &l.strX, err)
+ labels[key] = append(labels[key], value)
+ } else {
+ numLabels[key] = append(numLabels[key], l.numX)
+ }
+ }
+ if len(labels) > 0 {
+ s.Label = labels
+ }
+ if len(numLabels) > 0 {
+ s.NumLabel = numLabels
+ }
+ s.Location = nil
+ for _, lid := range s.locationIDX {
+ s.Location = append(s.Location, locations[lid])
+ }
+ s.locationIDX = nil
+ }
+
+ p.DropFrames, err = getString(p.stringTable, &p.dropFramesX, err)
+ p.KeepFrames, err = getString(p.stringTable, &p.keepFramesX, err)
+
+ if pt := p.PeriodType; pt == nil {
+ p.PeriodType = &ValueType{}
+ }
+
+ if pt := p.PeriodType; pt != nil {
+ pt.Type, err = getString(p.stringTable, &pt.typeX, err)
+ pt.Unit, err = getString(p.stringTable, &pt.unitX, err)
+ }
+ p.stringTable = nil
+ return nil
+}
+
+func (p *ValueType) decoder() []decoder {
+ return valueTypeDecoder
+}
+
+func (p *ValueType) encode(b *buffer) {
+ encodeInt64Opt(b, 1, p.typeX)
+ encodeInt64Opt(b, 2, p.unitX)
+}
+
+var valueTypeDecoder = []decoder{
+ nil, // 0
+ // optional int64 type = 1
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).typeX) },
+ // optional int64 unit = 2
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).unitX) },
+}
+
+func (p *Sample) decoder() []decoder {
+ return sampleDecoder
+}
+
+func (p *Sample) encode(b *buffer) {
+ encodeUint64s(b, 1, p.locationIDX)
+ for _, x := range p.Value {
+ encodeInt64(b, 2, x)
+ }
+ for _, x := range p.labelX {
+ encodeMessage(b, 3, x)
+ }
+}
+
+var sampleDecoder = []decoder{
+ nil, // 0
+ // repeated uint64 location = 1
+ func(b *buffer, m message) error { return decodeUint64s(b, &m.(*Sample).locationIDX) },
+ // repeated int64 value = 2
+ func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Sample).Value) },
+ // repeated Label label = 3
+ func(b *buffer, m message) error {
+ s := m.(*Sample)
+ n := len(s.labelX)
+ s.labelX = append(s.labelX, Label{})
+ return decodeMessage(b, &s.labelX[n])
+ },
+}
+
+func (p Label) decoder() []decoder {
+ return labelDecoder
+}
+
+func (p Label) encode(b *buffer) {
+ encodeInt64Opt(b, 1, p.keyX)
+ encodeInt64Opt(b, 2, p.strX)
+ encodeInt64Opt(b, 3, p.numX)
+}
+
+var labelDecoder = []decoder{
+ nil, // 0
+ // optional int64 key = 1
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).keyX) },
+ // optional int64 str = 2
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).strX) },
+ // optional int64 num = 3
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).numX) },
+}
+
+func (p *Mapping) decoder() []decoder {
+ return mappingDecoder
+}
+
+func (p *Mapping) encode(b *buffer) {
+ encodeUint64Opt(b, 1, p.ID)
+ encodeUint64Opt(b, 2, p.Start)
+ encodeUint64Opt(b, 3, p.Limit)
+ encodeUint64Opt(b, 4, p.Offset)
+ encodeInt64Opt(b, 5, p.fileX)
+ encodeInt64Opt(b, 6, p.buildIDX)
+ encodeBoolOpt(b, 7, p.HasFunctions)
+ encodeBoolOpt(b, 8, p.HasFilenames)
+ encodeBoolOpt(b, 9, p.HasLineNumbers)
+ encodeBoolOpt(b, 10, p.HasInlineFrames)
+}
+
+var mappingDecoder = []decoder{
+ nil, // 0
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).ID) }, // optional uint64 id = 1
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Start) }, // optional uint64 memory_offset = 2
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Limit) }, // optional uint64 memory_limit = 3
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Offset) }, // optional uint64 file_offset = 4
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).fileX) }, // optional int64 filename = 5
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).buildIDX) }, // optional int64 build_id = 6
+ func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFunctions) }, // optional bool has_functions = 7
+ func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFilenames) }, // optional bool has_filenames = 8
+ func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasLineNumbers) }, // optional bool has_line_numbers = 9
+ func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasInlineFrames) }, // optional bool has_inline_frames = 10
+}
+
+func (p *Location) decoder() []decoder {
+ return locationDecoder
+}
+
+func (p *Location) encode(b *buffer) {
+ encodeUint64Opt(b, 1, p.ID)
+ encodeUint64Opt(b, 2, p.mappingIDX)
+ encodeUint64Opt(b, 3, p.Address)
+ for i := range p.Line {
+ encodeMessage(b, 4, &p.Line[i])
+ }
+}
+
+var locationDecoder = []decoder{
+ nil, // 0
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).ID) }, // optional uint64 id = 1;
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).mappingIDX) }, // optional uint64 mapping_id = 2;
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).Address) }, // optional uint64 address = 3;
+ func(b *buffer, m message) error { // repeated Line line = 4
+ pp := m.(*Location)
+ n := len(pp.Line)
+ pp.Line = append(pp.Line, Line{})
+ return decodeMessage(b, &pp.Line[n])
+ },
+}
+
+func (p *Line) decoder() []decoder {
+ return lineDecoder
+}
+
+func (p *Line) encode(b *buffer) {
+ encodeUint64Opt(b, 1, p.functionIDX)
+ encodeInt64Opt(b, 2, p.Line)
+}
+
+var lineDecoder = []decoder{
+ nil, // 0
+ // optional uint64 function_id = 1
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Line).functionIDX) },
+ // optional int64 line = 2
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Line) },
+}
+
+func (p *Function) decoder() []decoder {
+ return functionDecoder
+}
+
+func (p *Function) encode(b *buffer) {
+ encodeUint64Opt(b, 1, p.ID)
+ encodeInt64Opt(b, 2, p.nameX)
+ encodeInt64Opt(b, 3, p.systemNameX)
+ encodeInt64Opt(b, 4, p.filenameX)
+ encodeInt64Opt(b, 5, p.StartLine)
+}
+
+var functionDecoder = []decoder{
+ nil, // 0
+ // optional uint64 id = 1
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Function).ID) },
+ // optional int64 function_name = 2
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).nameX) },
+ // optional int64 function_system_name = 3
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).systemNameX) },
+ // repeated int64 filename = 4
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).filenameX) },
+ // optional int64 start_line = 5
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).StartLine) },
+}
+
+func addString(strings map[string]int, s string) int64 {
+ i, ok := strings[s]
+ if !ok {
+ i = len(strings)
+ strings[s] = i
+ }
+ return int64(i)
+}
+
+func getString(strings []string, strng *int64, err error) (string, error) {
+ if err != nil {
+ return "", err
+ }
+ s := int(*strng)
+ if s < 0 || s >= len(strings) {
+ return "", errMalformed
+ }
+ *strng = 0
+ return strings[s], nil
+}
diff --git a/src/cmd/pprof/internal/profile/filter.go b/src/cmd/pprof/internal/profile/filter.go
new file mode 100644
index 000000000..903616aac
--- /dev/null
+++ b/src/cmd/pprof/internal/profile/filter.go
@@ -0,0 +1,157 @@
+// 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.
+
+// Implements methods to filter samples from profiles.
+package profile
+
+import "regexp"
+
+// FilterSamplesByName filters the samples in a profile and only keeps
+// samples where at least one frame matches focus but none match ignore.
+// Returns true is the corresponding regexp matched at least one sample.
+func (p *Profile) FilterSamplesByName(focus, ignore, hide *regexp.Regexp) (fm, im, hm bool) {
+ focusOrIgnore := make(map[uint64]bool)
+ hidden := make(map[uint64]bool)
+ for _, l := range p.Location {
+ if ignore != nil && l.matchesName(ignore) {
+ im = true
+ focusOrIgnore[l.ID] = false
+ } else if focus == nil || l.matchesName(focus) {
+ fm = true
+ focusOrIgnore[l.ID] = true
+ }
+ if hide != nil && l.matchesName(hide) {
+ hm = true
+ l.Line = l.unmatchedLines(hide)
+ if len(l.Line) == 0 {
+ hidden[l.ID] = true
+ }
+ }
+ }
+
+ s := make([]*Sample, 0, len(p.Sample))
+ for _, sample := range p.Sample {
+ if focusedAndNotIgnored(sample.Location, focusOrIgnore) {
+ if len(hidden) > 0 {
+ var locs []*Location
+ for _, loc := range sample.Location {
+ if !hidden[loc.ID] {
+ locs = append(locs, loc)
+ }
+ }
+ if len(locs) == 0 {
+ // Remove sample with no locations (by not adding it to s).
+ continue
+ }
+ sample.Location = locs
+ }
+ s = append(s, sample)
+ }
+ }
+ p.Sample = s
+
+ return
+}
+
+// matchesName returns whether the function name or file in the
+// location matches the regular expression.
+func (loc *Location) matchesName(re *regexp.Regexp) bool {
+ for _, ln := range loc.Line {
+ if fn := ln.Function; fn != nil {
+ if re.MatchString(fn.Name) {
+ return true
+ }
+ if re.MatchString(fn.Filename) {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+// unmatchedLines returns the lines in the location that do not match
+// the regular expression.
+func (loc *Location) unmatchedLines(re *regexp.Regexp) []Line {
+ var lines []Line
+ for _, ln := range loc.Line {
+ if fn := ln.Function; fn != nil {
+ if re.MatchString(fn.Name) {
+ continue
+ }
+ if re.MatchString(fn.Filename) {
+ continue
+ }
+ }
+ lines = append(lines, ln)
+ }
+ return lines
+}
+
+// focusedAndNotIgnored looks up a slice of ids against a map of
+// focused/ignored locations. The map only contains locations that are
+// explicitly focused or ignored. Returns whether there is at least
+// one focused location but no ignored locations.
+func focusedAndNotIgnored(locs []*Location, m map[uint64]bool) bool {
+ var f bool
+ for _, loc := range locs {
+ if focus, focusOrIgnore := m[loc.ID]; focusOrIgnore {
+ if focus {
+ // Found focused location. Must keep searching in case there
+ // is an ignored one as well.
+ f = true
+ } else {
+ // Found ignored location. Can return false right away.
+ return false
+ }
+ }
+ }
+ return f
+}
+
+// TagMatch selects tags for filtering
+type TagMatch func(key, val string, nval int64) bool
+
+// FilterSamplesByTag removes all samples from the profile, except
+// those that match focus and do not match the ignore regular
+// expression.
+func (p *Profile) FilterSamplesByTag(focus, ignore TagMatch) (fm, im bool) {
+ samples := make([]*Sample, 0, len(p.Sample))
+ for _, s := range p.Sample {
+ focused, ignored := focusedSample(s, focus, ignore)
+ fm = fm || focused
+ im = im || ignored
+ if focused && !ignored {
+ samples = append(samples, s)
+ }
+ }
+ p.Sample = samples
+ return
+}
+
+// focusedTag checks a sample against focus and ignore regexps.
+// Returns whether the focus/ignore regexps match any tags
+func focusedSample(s *Sample, focus, ignore TagMatch) (fm, im bool) {
+ fm = focus == nil
+ for key, vals := range s.Label {
+ for _, val := range vals {
+ if ignore != nil && ignore(key, val, 0) {
+ im = true
+ }
+ if !fm && focus(key, val, 0) {
+ fm = true
+ }
+ }
+ }
+ for key, vals := range s.NumLabel {
+ for _, val := range vals {
+ if ignore != nil && ignore(key, "", val) {
+ im = true
+ }
+ if !fm && focus(key, "", val) {
+ fm = true
+ }
+ }
+ }
+ return fm, im
+}
diff --git a/src/cmd/pprof/internal/profile/legacy_profile.go b/src/cmd/pprof/internal/profile/legacy_profile.go
new file mode 100644
index 000000000..bfc8110e4
--- /dev/null
+++ b/src/cmd/pprof/internal/profile/legacy_profile.go
@@ -0,0 +1,1250 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements parsers to convert legacy profiles into the
+// profile.proto format.
+
+package profile
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "math"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var (
+ countStartRE = regexp.MustCompile(`\A(\w+) profile: total \d+\n\z`)
+ countRE = regexp.MustCompile(`\A(\d+) @(( 0x[0-9a-f]+)+)\n\z`)
+
+ heapHeaderRE = regexp.MustCompile(`heap profile: *(\d+): *(\d+) *\[ *(\d+): *(\d+) *\] *@ *(heap[_a-z0-9]*)/?(\d*)`)
+ heapSampleRE = regexp.MustCompile(`(-?\d+): *(-?\d+) *\[ *(\d+): *(\d+) *] @([ x0-9a-f]*)`)
+
+ contentionSampleRE = regexp.MustCompile(`(\d+) *(\d+) @([ x0-9a-f]*)`)
+
+ hexNumberRE = regexp.MustCompile(`0x[0-9a-f]+`)
+
+ growthHeaderRE = regexp.MustCompile(`heap profile: *(\d+): *(\d+) *\[ *(\d+): *(\d+) *\] @ growthz`)
+
+ fragmentationHeaderRE = regexp.MustCompile(`heap profile: *(\d+): *(\d+) *\[ *(\d+): *(\d+) *\] @ fragmentationz`)
+
+ threadzStartRE = regexp.MustCompile(`--- threadz \d+ ---`)
+ threadStartRE = regexp.MustCompile(`--- Thread ([[:xdigit:]]+) \(name: (.*)/(\d+)\) stack: ---`)
+
+ procMapsRE = regexp.MustCompile(`([[:xdigit:]]+)-([[:xdigit:]]+)\s+([-rwxp]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]+):([[:xdigit:]]+)\s+([[:digit:]]+)\s*(\S+)?`)
+
+ briefMapsRE = regexp.MustCompile(`\s*([[:xdigit:]]+)-([[:xdigit:]]+):\s*(\S+)(\s.*@)?([[:xdigit:]]+)?`)
+
+ // LegacyHeapAllocated instructs the heapz parsers to use the
+ // allocated memory stats instead of the default in-use memory. Note
+ // that tcmalloc doesn't provide all allocated memory, only in-use
+ // stats.
+ LegacyHeapAllocated bool
+)
+
+func isSpaceOrComment(line string) bool {
+ trimmed := strings.TrimSpace(line)
+ return len(trimmed) == 0 || trimmed[0] == '#'
+}
+
+// parseGoCount parses a Go count profile (e.g., threadcreate or
+// goroutine) and returns a new Profile.
+func parseGoCount(b []byte) (*Profile, error) {
+ r := bytes.NewBuffer(b)
+
+ var line string
+ var err error
+ for {
+ // Skip past comments and empty lines seeking a real header.
+ line, err = r.ReadString('\n')
+ if err != nil {
+ return nil, err
+ }
+ if !isSpaceOrComment(line) {
+ break
+ }
+ }
+
+ m := countStartRE.FindStringSubmatch(line)
+ if m == nil {
+ return nil, errUnrecognized
+ }
+ profileType := string(m[1])
+ p := &Profile{
+ PeriodType: &ValueType{Type: profileType, Unit: "count"},
+ Period: 1,
+ SampleType: []*ValueType{{Type: profileType, Unit: "count"}},
+ }
+ locations := make(map[uint64]*Location)
+ for {
+ line, err = r.ReadString('\n')
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return nil, err
+ }
+ if isSpaceOrComment(line) {
+ continue
+ }
+ if strings.HasPrefix(line, "---") {
+ break
+ }
+ m := countRE.FindStringSubmatch(line)
+ if m == nil {
+ return nil, errMalformed
+ }
+ n, err := strconv.ParseInt(string(m[1]), 0, 64)
+ if err != nil {
+ return nil, errMalformed
+ }
+ fields := strings.Fields(string(m[2]))
+ locs := make([]*Location, 0, len(fields))
+ for _, stk := range fields {
+ addr, err := strconv.ParseUint(stk, 0, 64)
+ if err != nil {
+ return nil, errMalformed
+ }
+ // Adjust all frames by -1 (except the leaf) to land on top of
+ // the call instruction.
+ if len(locs) > 0 {
+ addr--
+ }
+ loc := locations[addr]
+ if loc == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ locations[addr] = loc
+ p.Location = append(p.Location, loc)
+ }
+ locs = append(locs, loc)
+ }
+ p.Sample = append(p.Sample, &Sample{
+ Location: locs,
+ Value: []int64{n},
+ })
+ }
+
+ if err = parseAdditionalSections(strings.TrimSpace(line), r, p); err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+// remapLocationIDs ensures there is a location for each address
+// referenced by a sample, and remaps the samples to point to the new
+// location ids.
+func (p *Profile) remapLocationIDs() {
+ seen := make(map[*Location]bool, len(p.Location))
+ var locs []*Location
+
+ for _, s := range p.Sample {
+ for _, l := range s.Location {
+ if seen[l] {
+ continue
+ }
+ l.ID = uint64(len(locs) + 1)
+ locs = append(locs, l)
+ seen[l] = true
+ }
+ }
+ p.Location = locs
+}
+
+func (p *Profile) remapFunctionIDs() {
+ seen := make(map[*Function]bool, len(p.Function))
+ var fns []*Function
+
+ for _, l := range p.Location {
+ for _, ln := range l.Line {
+ fn := ln.Function
+ if fn == nil || seen[fn] {
+ continue
+ }
+ fn.ID = uint64(len(fns) + 1)
+ fns = append(fns, fn)
+ seen[fn] = true
+ }
+ }
+ p.Function = fns
+}
+
+// remapMappingIDs matches location addresses with existing mappings
+// and updates them appropriately. This is O(N*M), if this ever shows
+// up as a bottleneck, evaluate sorting the mappings and doing a
+// binary search, which would make it O(N*log(M)).
+func (p *Profile) remapMappingIDs() {
+ if len(p.Mapping) == 0 {
+ return
+ }
+
+ // Some profile handlers will incorrectly set regions for the main
+ // executable if its section is remapped. Fix them through heuristics.
+
+ // Remove the initial mapping if named '/anon_hugepage' and has a
+ // consecutive adjacent mapping.
+ if m := p.Mapping[0]; strings.HasPrefix(m.File, "/anon_hugepage") {
+ if len(p.Mapping) > 1 && m.Limit == p.Mapping[1].Start {
+ p.Mapping = p.Mapping[1:]
+ }
+ }
+
+ // Subtract the offset from the start of the main mapping if it
+ // ends up at a recognizable start address.
+ const expectedStart = 0x400000
+ if m := p.Mapping[0]; m.Start-m.Offset == expectedStart {
+ m.Start = expectedStart
+ m.Offset = 0
+ }
+
+ for _, l := range p.Location {
+ if a := l.Address; a != 0 {
+ for _, m := range p.Mapping {
+ if m.Start <= a && a < m.Limit {
+ l.Mapping = m
+ break
+ }
+ }
+ }
+ }
+
+ // Reset all mapping IDs.
+ for i, m := range p.Mapping {
+ m.ID = uint64(i + 1)
+ }
+}
+
+var cpuInts = []func([]byte) (uint64, []byte){
+ get32l,
+ get32b,
+ get64l,
+ get64b,
+}
+
+func get32l(b []byte) (uint64, []byte) {
+ if len(b) < 4 {
+ return 0, nil
+ }
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24, b[4:]
+}
+
+func get32b(b []byte) (uint64, []byte) {
+ if len(b) < 4 {
+ return 0, nil
+ }
+ return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24, b[4:]
+}
+
+func get64l(b []byte) (uint64, []byte) {
+ if len(b) < 8 {
+ return 0, nil
+ }
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56, b[8:]
+}
+
+func get64b(b []byte) (uint64, []byte) {
+ if len(b) < 8 {
+ return 0, nil
+ }
+ return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56, b[8:]
+}
+
+// ParseTracebacks parses a set of tracebacks and returns a newly
+// populated profile. It will accept any text file and generate a
+// Profile out of it with any hex addresses it can identify, including
+// a process map if it can recognize one. Each sample will include a
+// tag "source" with the addresses recognized in string format.
+func ParseTracebacks(b []byte) (*Profile, error) {
+ r := bytes.NewBuffer(b)
+
+ p := &Profile{
+ PeriodType: &ValueType{Type: "trace", Unit: "count"},
+ Period: 1,
+ SampleType: []*ValueType{
+ {Type: "trace", Unit: "count"},
+ },
+ }
+
+ var sources []string
+ var sloc []*Location
+
+ locs := make(map[uint64]*Location)
+ for {
+ l, err := r.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ return nil, err
+ }
+ if l == "" {
+ break
+ }
+ }
+ if sectionTrigger(l) == memoryMapSection {
+ break
+ }
+ if s, addrs := extractHexAddresses(l); len(s) > 0 {
+ for _, addr := range addrs {
+ // Addresses from stack traces point to the next instruction after
+ // each call. Adjust by -1 to land somewhere on the actual call
+ // (except for the leaf, which is not a call).
+ if len(sloc) > 0 {
+ addr--
+ }
+ loc := locs[addr]
+ if locs[addr] == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ p.Location = append(p.Location, loc)
+ locs[addr] = loc
+ }
+ sloc = append(sloc, loc)
+ }
+
+ sources = append(sources, s...)
+ } else {
+ if len(sources) > 0 || len(sloc) > 0 {
+ addTracebackSample(sloc, sources, p)
+ sloc, sources = nil, nil
+ }
+ }
+ }
+
+ // Add final sample to save any leftover data.
+ if len(sources) > 0 || len(sloc) > 0 {
+ addTracebackSample(sloc, sources, p)
+ }
+
+ if err := p.ParseMemoryMap(r); err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+func addTracebackSample(l []*Location, s []string, p *Profile) {
+ p.Sample = append(p.Sample,
+ &Sample{
+ Value: []int64{1},
+ Location: l,
+ Label: map[string][]string{"source": s},
+ })
+}
+
+// parseCPU parses a profilez legacy profile and returns a newly
+// populated Profile.
+//
+// The general format for profilez samples is a sequence of words in
+// binary format. The first words are a header with the following data:
+// 1st word -- 0
+// 2nd word -- 3
+// 3rd word -- 0 if a c++ application, 1 if a java application.
+// 4th word -- Sampling period (in microseconds).
+// 5th word -- Padding.
+func parseCPU(b []byte) (*Profile, error) {
+ var parse func([]byte) (uint64, []byte)
+ var n1, n2, n3, n4, n5 uint64
+ for _, parse = range cpuInts {
+ var tmp []byte
+ n1, tmp = parse(b)
+ n2, tmp = parse(tmp)
+ n3, tmp = parse(tmp)
+ n4, tmp = parse(tmp)
+ n5, tmp = parse(tmp)
+
+ if tmp != nil && n1 == 0 && n2 == 3 && n3 == 0 && n4 > 0 && n5 == 0 {
+ b = tmp
+ return cpuProfile(b, int64(n4), parse)
+ }
+ }
+ return nil, errUnrecognized
+}
+
+// cpuProfile returns a new Profile from C++ profilez data.
+// b is the profile bytes after the header, period is the profiling
+// period, and parse is a function to parse 8-byte chunks from the
+// profile in its native endianness.
+func cpuProfile(b []byte, period int64, parse func(b []byte) (uint64, []byte)) (*Profile, error) {
+ p := &Profile{
+ Period: period * 1000,
+ PeriodType: &ValueType{Type: "cpu", Unit: "nanoseconds"},
+ SampleType: []*ValueType{
+ {Type: "samples", Unit: "count"},
+ {Type: "cpu", Unit: "nanoseconds"},
+ },
+ }
+ var err error
+ if b, _, err = parseCPUSamples(b, parse, true, p); err != nil {
+ return nil, err
+ }
+
+ // If all samples have the same second-to-the-bottom frame, it
+ // strongly suggests that it is an uninteresting artifact of
+ // measurement -- a stack frame pushed by the signal handler. The
+ // bottom frame is always correct as it is picked up from the signal
+ // structure, not the stack. Check if this is the case and if so,
+ // remove.
+ if len(p.Sample) > 1 && len(p.Sample[0].Location) > 1 {
+ allSame := true
+ id1 := p.Sample[0].Location[1].Address
+ for _, s := range p.Sample {
+ if len(s.Location) < 2 || id1 != s.Location[1].Address {
+ allSame = false
+ break
+ }
+ }
+ if allSame {
+ for _, s := range p.Sample {
+ s.Location = append(s.Location[:1], s.Location[2:]...)
+ }
+ }
+ }
+
+ if err := p.ParseMemoryMap(bytes.NewBuffer(b)); err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+// parseCPUSamples parses a collection of profilez samples from a
+// profile.
+//
+// profilez samples are a repeated sequence of stack frames of the
+// form:
+// 1st word -- The number of times this stack was encountered.
+// 2nd word -- The size of the stack (StackSize).
+// 3rd word -- The first address on the stack.
+// ...
+// StackSize + 2 -- The last address on the stack
+// The last stack trace is of the form:
+// 1st word -- 0
+// 2nd word -- 1
+// 3rd word -- 0
+//
+// Addresses from stack traces may point to the next instruction after
+// each call. Optionally adjust by -1 to land somewhere on the actual
+// call (except for the leaf, which is not a call).
+func parseCPUSamples(b []byte, parse func(b []byte) (uint64, []byte), adjust bool, p *Profile) ([]byte, map[uint64]*Location, error) {
+ locs := make(map[uint64]*Location)
+ for len(b) > 0 {
+ var count, nstk uint64
+ count, b = parse(b)
+ nstk, b = parse(b)
+ if b == nil || nstk > uint64(len(b)/4) {
+ return nil, nil, errUnrecognized
+ }
+ var sloc []*Location
+ addrs := make([]uint64, nstk)
+ for i := 0; i < int(nstk); i++ {
+ addrs[i], b = parse(b)
+ }
+
+ if count == 0 && nstk == 1 && addrs[0] == 0 {
+ // End of data marker
+ break
+ }
+ for i, addr := range addrs {
+ if adjust && i > 0 {
+ addr--
+ }
+ loc := locs[addr]
+ if loc == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ locs[addr] = loc
+ p.Location = append(p.Location, loc)
+ }
+ sloc = append(sloc, loc)
+ }
+ p.Sample = append(p.Sample,
+ &Sample{
+ Value: []int64{int64(count), int64(count) * int64(p.Period)},
+ Location: sloc,
+ })
+ }
+ // Reached the end without finding the EOD marker.
+ return b, locs, nil
+}
+
+// parseHeap parses a heapz legacy or a growthz profile and
+// returns a newly populated Profile.
+func parseHeap(b []byte) (p *Profile, err error) {
+ r := bytes.NewBuffer(b)
+ l, err := r.ReadString('\n')
+ if err != nil {
+ return nil, errUnrecognized
+ }
+
+ sampling := ""
+
+ if header := heapHeaderRE.FindStringSubmatch(l); header != nil {
+ p = &Profile{
+ SampleType: []*ValueType{
+ {Type: "objects", Unit: "count"},
+ {Type: "space", Unit: "bytes"},
+ },
+ PeriodType: &ValueType{Type: "objects", Unit: "bytes"},
+ }
+
+ var period int64
+ if len(header[6]) > 0 {
+ if period, err = strconv.ParseInt(string(header[6]), 10, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ }
+
+ switch header[5] {
+ case "heapz_v2", "heap_v2":
+ sampling, p.Period = "v2", period
+ case "heapprofile":
+ sampling, p.Period = "", 1
+ case "heap":
+ sampling, p.Period = "v2", period/2
+ default:
+ return nil, errUnrecognized
+ }
+ } else if header = growthHeaderRE.FindStringSubmatch(l); header != nil {
+ p = &Profile{
+ SampleType: []*ValueType{
+ {Type: "objects", Unit: "count"},
+ {Type: "space", Unit: "bytes"},
+ },
+ PeriodType: &ValueType{Type: "heapgrowth", Unit: "count"},
+ Period: 1,
+ }
+ } else if header = fragmentationHeaderRE.FindStringSubmatch(l); header != nil {
+ p = &Profile{
+ SampleType: []*ValueType{
+ {Type: "objects", Unit: "count"},
+ {Type: "space", Unit: "bytes"},
+ },
+ PeriodType: &ValueType{Type: "allocations", Unit: "count"},
+ Period: 1,
+ }
+ } else {
+ return nil, errUnrecognized
+ }
+
+ if LegacyHeapAllocated {
+ for _, st := range p.SampleType {
+ st.Type = "alloc_" + st.Type
+ }
+ } else {
+ for _, st := range p.SampleType {
+ st.Type = "inuse_" + st.Type
+ }
+ }
+
+ locs := make(map[uint64]*Location)
+ for {
+ l, err = r.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ return nil, err
+ }
+
+ if l == "" {
+ break
+ }
+ }
+
+ if l = strings.TrimSpace(l); l == "" {
+ continue
+ }
+
+ if sectionTrigger(l) != unrecognizedSection {
+ break
+ }
+
+ value, blocksize, addrs, err := parseHeapSample(l, p.Period, sampling)
+ if err != nil {
+ return nil, err
+ }
+ var sloc []*Location
+ for i, addr := range addrs {
+ // Addresses from stack traces point to the next instruction after
+ // each call. Adjust by -1 to land somewhere on the actual call
+ // (except for the leaf, which is not a call).
+ if i > 0 {
+ addr--
+ }
+ loc := locs[addr]
+ if locs[addr] == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ p.Location = append(p.Location, loc)
+ locs[addr] = loc
+ }
+ sloc = append(sloc, loc)
+ }
+
+ p.Sample = append(p.Sample, &Sample{
+ Value: value,
+ Location: sloc,
+ NumLabel: map[string][]int64{"bytes": []int64{blocksize}},
+ })
+ }
+
+ if err = parseAdditionalSections(l, r, p); err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+// parseHeapSample parses a single row from a heap profile into a new Sample.
+func parseHeapSample(line string, rate int64, sampling string) (value []int64, blocksize int64, addrs []uint64, err error) {
+ sampleData := heapSampleRE.FindStringSubmatch(line)
+ if len(sampleData) != 6 {
+ return value, blocksize, addrs, fmt.Errorf("unexpected number of sample values: got %d, want 6", len(sampleData))
+ }
+
+ // Use first two values by default; tcmalloc sampling generates the
+ // same value for both, only the older heap-profile collect separate
+ // stats for in-use and allocated objects.
+ valueIndex := 1
+ if LegacyHeapAllocated {
+ valueIndex = 3
+ }
+
+ var v1, v2 int64
+ if v1, err = strconv.ParseInt(sampleData[valueIndex], 10, 64); err != nil {
+ return value, blocksize, addrs, fmt.Errorf("malformed sample: %s: %v", line, err)
+ }
+ if v2, err = strconv.ParseInt(sampleData[valueIndex+1], 10, 64); err != nil {
+ return value, blocksize, addrs, fmt.Errorf("malformed sample: %s: %v", line, err)
+ }
+
+ if v1 == 0 {
+ if v2 != 0 {
+ return value, blocksize, addrs, fmt.Errorf("allocation count was 0 but allocation bytes was %d", v2)
+ }
+ } else {
+ blocksize = v2 / v1
+ if sampling == "v2" {
+ v1, v2 = scaleHeapSample(v1, v2, rate)
+ }
+ }
+
+ value = []int64{v1, v2}
+ addrs = parseHexAddresses(sampleData[5])
+
+ return value, blocksize, addrs, nil
+}
+
+// extractHexAddresses extracts hex numbers from a string and returns
+// them, together with their numeric value, in a slice.
+func extractHexAddresses(s string) ([]string, []uint64) {
+ hexStrings := hexNumberRE.FindAllString(s, -1)
+ var ids []uint64
+ for _, s := range hexStrings {
+ if id, err := strconv.ParseUint(s, 0, 64); err == nil {
+ ids = append(ids, id)
+ } else {
+ // Do not expect any parsing failures due to the regexp matching.
+ panic("failed to parse hex value:" + s)
+ }
+ }
+ return hexStrings, ids
+}
+
+// parseHexAddresses parses hex numbers from a string and returns them
+// in a slice.
+func parseHexAddresses(s string) []uint64 {
+ _, ids := extractHexAddresses(s)
+ return ids
+}
+
+// scaleHeapSample adjusts the data from a heapz Sample to
+// account for its probability of appearing in the collected
+// data. heapz profiles are a sampling of the memory allocations
+// requests in a program. We estimate the unsampled value by dividing
+// each collected sample by its probability of appearing in the
+// profile. heapz v2 profiles rely on a poisson process to determine
+// which samples to collect, based on the desired average collection
+// rate R. The probability of a sample of size S to appear in that
+// profile is 1-exp(-S/R).
+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)
+}
+
+// parseContention parses a contentionz profile and returns a newly
+// populated Profile.
+func parseContention(b []byte) (p *Profile, err error) {
+ r := bytes.NewBuffer(b)
+ l, err := r.ReadString('\n')
+ if err != nil {
+ return nil, errUnrecognized
+ }
+
+ if !strings.HasPrefix(l, "--- contention") {
+ return nil, errUnrecognized
+ }
+
+ p = &Profile{
+ PeriodType: &ValueType{Type: "contentions", Unit: "count"},
+ Period: 1,
+ SampleType: []*ValueType{
+ {Type: "contentions", Unit: "count"},
+ {Type: "delay", Unit: "nanoseconds"},
+ },
+ }
+
+ var cpuHz int64
+ // Parse text of the form "attribute = value" before the samples.
+ const delimiter = "="
+ for {
+ l, err = r.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ return nil, err
+ }
+
+ if l == "" {
+ break
+ }
+ }
+
+ if l = strings.TrimSpace(l); l == "" {
+ continue
+ }
+
+ if strings.HasPrefix(l, "---") {
+ break
+ }
+
+ attr := strings.SplitN(l, delimiter, 2)
+ if len(attr) != 2 {
+ break
+ }
+ key, val := strings.TrimSpace(attr[0]), strings.TrimSpace(attr[1])
+ var err error
+ switch key {
+ case "cycles/second":
+ if cpuHz, err = strconv.ParseInt(val, 0, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ case "sampling period":
+ if p.Period, err = strconv.ParseInt(val, 0, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ case "ms since reset":
+ ms, err := strconv.ParseInt(val, 0, 64)
+ if err != nil {
+ return nil, errUnrecognized
+ }
+ p.DurationNanos = ms * 1000 * 1000
+ case "format":
+ // CPP contentionz profiles don't have format.
+ return nil, errUnrecognized
+ case "resolution":
+ // CPP contentionz profiles don't have resolution.
+ return nil, errUnrecognized
+ case "discarded samples":
+ default:
+ return nil, errUnrecognized
+ }
+ }
+
+ locs := make(map[uint64]*Location)
+ for {
+ if l = strings.TrimSpace(l); strings.HasPrefix(l, "---") {
+ break
+ }
+ value, addrs, err := parseContentionSample(l, p.Period, cpuHz)
+ if err != nil {
+ return nil, err
+ }
+ var sloc []*Location
+ for i, addr := range addrs {
+ // Addresses from stack traces point to the next instruction after
+ // each call. Adjust by -1 to land somewhere on the actual call
+ // (except for the leaf, which is not a call).
+ if i > 0 {
+ addr--
+ }
+ loc := locs[addr]
+ if locs[addr] == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ p.Location = append(p.Location, loc)
+ locs[addr] = loc
+ }
+ sloc = append(sloc, loc)
+ }
+ p.Sample = append(p.Sample, &Sample{
+ Value: value,
+ Location: sloc,
+ })
+
+ if l, err = r.ReadString('\n'); err != nil {
+ if err != io.EOF {
+ return nil, err
+ }
+ if l == "" {
+ break
+ }
+ }
+ }
+
+ if err = parseAdditionalSections(l, r, p); err != nil {
+ return nil, err
+ }
+
+ return p, nil
+}
+
+// parseContentionSample parses a single row from a contention profile
+// into a new Sample.
+func parseContentionSample(line string, period, cpuHz int64) (value []int64, addrs []uint64, err error) {
+ sampleData := contentionSampleRE.FindStringSubmatch(line)
+ if sampleData == nil {
+ return value, addrs, errUnrecognized
+ }
+
+ v1, err := strconv.ParseInt(sampleData[1], 10, 64)
+ if err != nil {
+ return value, addrs, fmt.Errorf("malformed sample: %s: %v", line, err)
+ }
+ v2, err := strconv.ParseInt(sampleData[2], 10, 64)
+ if err != nil {
+ return value, addrs, fmt.Errorf("malformed sample: %s: %v", line, err)
+ }
+
+ // Unsample values if period and cpuHz are available.
+ // - Delays are scaled to cycles and then to nanoseconds.
+ // - Contentions are scaled to cycles.
+ if period > 0 {
+ if cpuHz > 0 {
+ cpuGHz := float64(cpuHz) / 1e9
+ v1 = int64(float64(v1) * float64(period) / cpuGHz)
+ }
+ v2 = v2 * period
+ }
+
+ value = []int64{v2, v1}
+ addrs = parseHexAddresses(sampleData[3])
+
+ return value, addrs, nil
+}
+
+// parseThread parses a Threadz profile and returns a new Profile.
+func parseThread(b []byte) (*Profile, error) {
+ r := bytes.NewBuffer(b)
+
+ var line string
+ var err error
+ for {
+ // Skip past comments and empty lines seeking a real header.
+ line, err = r.ReadString('\n')
+ if err != nil {
+ return nil, err
+ }
+ if !isSpaceOrComment(line) {
+ break
+ }
+ }
+
+ if m := threadzStartRE.FindStringSubmatch(line); m != nil {
+ // Advance over initial comments until first stack trace.
+ for {
+ line, err = r.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ return nil, err
+ }
+
+ if line == "" {
+ break
+ }
+ }
+ if sectionTrigger(line) != unrecognizedSection || line[0] == '-' {
+ break
+ }
+ }
+ } else if t := threadStartRE.FindStringSubmatch(line); len(t) != 4 {
+ return nil, errUnrecognized
+ }
+
+ p := &Profile{
+ SampleType: []*ValueType{{Type: "thread", Unit: "count"}},
+ PeriodType: &ValueType{Type: "thread", Unit: "count"},
+ Period: 1,
+ }
+
+ locs := make(map[uint64]*Location)
+ // Recognize each thread and populate profile samples.
+ for sectionTrigger(line) == unrecognizedSection {
+ if strings.HasPrefix(line, "---- no stack trace for") {
+ line = ""
+ break
+ }
+ if t := threadStartRE.FindStringSubmatch(line); len(t) != 4 {
+ return nil, errUnrecognized
+ }
+
+ var addrs []uint64
+ line, addrs, err = parseThreadSample(r)
+ if err != nil {
+ return nil, errUnrecognized
+ }
+ if len(addrs) == 0 {
+ // We got a --same as previous threads--. Bump counters.
+ if len(p.Sample) > 0 {
+ s := p.Sample[len(p.Sample)-1]
+ s.Value[0]++
+ }
+ continue
+ }
+
+ var sloc []*Location
+ for i, addr := range addrs {
+ // Addresses from stack traces point to the next instruction after
+ // each call. Adjust by -1 to land somewhere on the actual call
+ // (except for the leaf, which is not a call).
+ if i > 0 {
+ addr--
+ }
+ loc := locs[addr]
+ if locs[addr] == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ p.Location = append(p.Location, loc)
+ locs[addr] = loc
+ }
+ sloc = append(sloc, loc)
+ }
+
+ p.Sample = append(p.Sample, &Sample{
+ Value: []int64{1},
+ Location: sloc,
+ })
+ }
+
+ if err = parseAdditionalSections(line, r, p); err != nil {
+ return nil, err
+ }
+
+ return p, nil
+}
+
+// parseThreadSample parses a symbolized or unsymbolized stack trace.
+// Returns the first line after the traceback, the sample (or nil if
+// it hits a 'same-as-previous' marker) and an error.
+func parseThreadSample(b *bytes.Buffer) (nextl string, addrs []uint64, err error) {
+ var l string
+ sameAsPrevious := false
+ for {
+ if l, err = b.ReadString('\n'); err != nil {
+ if err != io.EOF {
+ return "", nil, err
+ }
+ if l == "" {
+ break
+ }
+ }
+ if l = strings.TrimSpace(l); l == "" {
+ continue
+ }
+
+ if strings.HasPrefix(l, "---") {
+ break
+ }
+ if strings.Contains(l, "same as previous thread") {
+ sameAsPrevious = true
+ continue
+ }
+
+ addrs = append(addrs, parseHexAddresses(l)...)
+ }
+
+ if sameAsPrevious {
+ return l, nil, nil
+ }
+ return l, addrs, nil
+}
+
+// parseAdditionalSections parses any additional sections in the
+// profile, ignoring any unrecognized sections.
+func parseAdditionalSections(l string, b *bytes.Buffer, p *Profile) (err error) {
+ for {
+ if sectionTrigger(l) == memoryMapSection {
+ break
+ }
+ // Ignore any unrecognized sections.
+ if l, err := b.ReadString('\n'); err != nil {
+ if err != io.EOF {
+ return err
+ }
+ if l == "" {
+ break
+ }
+ }
+ }
+ return p.ParseMemoryMap(b)
+}
+
+// ParseMemoryMap parses a memory map in the format of
+// /proc/self/maps, and overrides the mappings in the current profile.
+// It renumbers the samples and locations in the profile correspondingly.
+func (p *Profile) ParseMemoryMap(rd io.Reader) error {
+ b := bufio.NewReader(rd)
+
+ var attrs []string
+ var r *strings.Replacer
+ const delimiter = "="
+ for {
+ l, err := b.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ return err
+ }
+ if l == "" {
+ break
+ }
+ }
+ if l = strings.TrimSpace(l); l == "" {
+ continue
+ }
+
+ if r != nil {
+ l = r.Replace(l)
+ }
+ m, err := parseMappingEntry(l)
+ if err != nil {
+ if err == errUnrecognized {
+ // Recognize assignments of the form: attr=value, and replace
+ // $attr with value on subsequent mappings.
+ if attr := strings.SplitN(l, delimiter, 2); len(attr) == 2 {
+ attrs = append(attrs, "$"+strings.TrimSpace(attr[0]), strings.TrimSpace(attr[1]))
+ r = strings.NewReplacer(attrs...)
+ }
+ // Ignore any unrecognized entries
+ continue
+ }
+ return err
+ }
+ if m == nil || (m.File == "" && len(p.Mapping) != 0) {
+ // In some cases the first entry may include the address range
+ // but not the name of the file. It should be followed by
+ // another entry with the name.
+ continue
+ }
+ if len(p.Mapping) == 1 && p.Mapping[0].File == "" {
+ // Update the name if this is the entry following that empty one.
+ p.Mapping[0].File = m.File
+ continue
+ }
+ p.Mapping = append(p.Mapping, m)
+ }
+ p.remapLocationIDs()
+ p.remapFunctionIDs()
+ p.remapMappingIDs()
+ return nil
+}
+
+func parseMappingEntry(l string) (*Mapping, error) {
+ mapping := &Mapping{}
+ var err error
+ if me := procMapsRE.FindStringSubmatch(l); len(me) == 9 {
+ if !strings.Contains(me[3], "x") {
+ // Skip non-executable entries.
+ return nil, nil
+ }
+ if mapping.Start, err = strconv.ParseUint(me[1], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ if mapping.Limit, err = strconv.ParseUint(me[2], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ if me[4] != "" {
+ if mapping.Offset, err = strconv.ParseUint(me[4], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ }
+ mapping.File = me[8]
+ return mapping, nil
+ }
+
+ if me := briefMapsRE.FindStringSubmatch(l); len(me) == 6 {
+ if mapping.Start, err = strconv.ParseUint(me[1], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ if mapping.Limit, err = strconv.ParseUint(me[2], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ mapping.File = me[3]
+ if me[5] != "" {
+ if mapping.Offset, err = strconv.ParseUint(me[5], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ }
+ return mapping, nil
+ }
+
+ return nil, errUnrecognized
+}
+
+type sectionType int
+
+const (
+ unrecognizedSection sectionType = iota
+ memoryMapSection
+)
+
+var memoryMapTriggers = []string{
+ "--- Memory map: ---",
+ "MAPPED_LIBRARIES:",
+}
+
+func sectionTrigger(line string) sectionType {
+ for _, trigger := range memoryMapTriggers {
+ if strings.Contains(line, trigger) {
+ return memoryMapSection
+ }
+ }
+ return unrecognizedSection
+}
+
+func (p *Profile) addLegacyFrameInfo() {
+ switch {
+ case isProfileType(p, heapzSampleTypes) ||
+ isProfileType(p, heapzInUseSampleTypes) ||
+ isProfileType(p, heapzAllocSampleTypes):
+ p.DropFrames, p.KeepFrames = allocRxStr, allocSkipRxStr
+ case isProfileType(p, contentionzSampleTypes):
+ p.DropFrames, p.KeepFrames = lockRxStr, ""
+ default:
+ p.DropFrames, p.KeepFrames = cpuProfilerRxStr, ""
+ }
+}
+
+var heapzSampleTypes = []string{"allocations", "size"} // early Go pprof profiles
+var heapzInUseSampleTypes = []string{"inuse_objects", "inuse_space"}
+var heapzAllocSampleTypes = []string{"alloc_objects", "alloc_space"}
+var contentionzSampleTypes = []string{"contentions", "delay"}
+
+func isProfileType(p *Profile, t []string) bool {
+ st := p.SampleType
+ if len(st) != len(t) {
+ return false
+ }
+
+ for i := range st {
+ if st[i].Type != t[i] {
+ return false
+ }
+ }
+ return true
+}
+
+var allocRxStr = strings.Join([]string{
+ // POSIX entry points.
+ `calloc`,
+ `cfree`,
+ `malloc`,
+ `free`,
+ `memalign`,
+ `do_memalign`,
+ `(__)?posix_memalign`,
+ `pvalloc`,
+ `valloc`,
+ `realloc`,
+
+ // TC malloc.
+ `tcmalloc::.*`,
+ `tc_calloc`,
+ `tc_cfree`,
+ `tc_malloc`,
+ `tc_free`,
+ `tc_memalign`,
+ `tc_posix_memalign`,
+ `tc_pvalloc`,
+ `tc_valloc`,
+ `tc_realloc`,
+ `tc_new`,
+ `tc_delete`,
+ `tc_newarray`,
+ `tc_deletearray`,
+ `tc_new_nothrow`,
+ `tc_newarray_nothrow`,
+
+ // Memory-allocation routines on OS X.
+ `malloc_zone_malloc`,
+ `malloc_zone_calloc`,
+ `malloc_zone_valloc`,
+ `malloc_zone_realloc`,
+ `malloc_zone_memalign`,
+ `malloc_zone_free`,
+
+ // Go runtime
+ `runtime\..*`,
+
+ // Other misc. memory allocation routines
+ `BaseArena::.*`,
+ `(::)?do_malloc_no_errno`,
+ `(::)?do_malloc_pages`,
+ `(::)?do_malloc`,
+ `DoSampledAllocation`,
+ `MallocedMemBlock::MallocedMemBlock`,
+ `_M_allocate`,
+ `__builtin_(vec_)?delete`,
+ `__builtin_(vec_)?new`,
+ `__gnu_cxx::new_allocator::allocate`,
+ `__libc_malloc`,
+ `__malloc_alloc_template::allocate`,
+ `allocate`,
+ `cpp_alloc`,
+ `operator new(\[\])?`,
+ `simple_alloc::allocate`,
+}, `|`)
+
+var allocSkipRxStr = strings.Join([]string{
+ // Preserve Go runtime frames that appear in the middle/bottom of
+ // the stack.
+ `runtime\.panic`,
+}, `|`)
+
+var cpuProfilerRxStr = strings.Join([]string{
+ `ProfileData::Add`,
+ `ProfileData::prof_handler`,
+ `CpuProfiler::prof_handler`,
+ `__pthread_sighandler`,
+ `__restore`,
+}, `|`)
+
+var lockRxStr = strings.Join([]string{
+ `RecordLockProfileData`,
+ `(base::)?RecordLockProfileData.*`,
+ `(base::)?SubmitMutexProfileData.*`,
+ `(base::)?SubmitSpinLockProfileData.*`,
+ `(Mutex::)?AwaitCommon.*`,
+ `(Mutex::)?Unlock.*`,
+ `(Mutex::)?UnlockSlow.*`,
+ `(Mutex::)?ReaderUnlock.*`,
+ `(MutexLock::)?~MutexLock.*`,
+ `(SpinLock::)?Unlock.*`,
+ `(SpinLock::)?SlowUnlock.*`,
+ `(SpinLockHolder::)?~SpinLockHolder.*`,
+}, `|`)
diff --git a/src/cmd/pprof/internal/profile/profile.go b/src/cmd/pprof/internal/profile/profile.go
new file mode 100644
index 000000000..7ee58eee7
--- /dev/null
+++ b/src/cmd/pprof/internal/profile/profile.go
@@ -0,0 +1,567 @@
+// 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 profile provides a representation of profile.proto and
+// methods to encode/decode profiles in this format.
+package profile
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "regexp"
+ "strings"
+ "time"
+)
+
+// Profile is an in-memory representation of profile.proto.
+type Profile struct {
+ SampleType []*ValueType
+ Sample []*Sample
+ Mapping []*Mapping
+ Location []*Location
+ Function []*Function
+
+ DropFrames string
+ KeepFrames string
+
+ TimeNanos int64
+ DurationNanos int64
+ PeriodType *ValueType
+ Period int64
+
+ dropFramesX int64
+ keepFramesX int64
+ stringTable []string
+}
+
+// ValueType corresponds to Profile.ValueType
+type ValueType struct {
+ Type string // cpu, wall, inuse_space, etc
+ Unit string // seconds, nanoseconds, bytes, etc
+
+ typeX int64
+ unitX int64
+}
+
+// Sample corresponds to Profile.Sample
+type Sample struct {
+ Location []*Location
+ Value []int64
+ Label map[string][]string
+ NumLabel map[string][]int64
+
+ locationIDX []uint64
+ labelX []Label
+}
+
+// Label corresponds to Profile.Label
+type Label struct {
+ keyX int64
+ // Exactly one of the two following values must be set
+ strX int64
+ numX int64 // Integer value for this label
+}
+
+// Mapping corresponds to Profile.Mapping
+type Mapping struct {
+ ID uint64
+ Start uint64
+ Limit uint64
+ Offset uint64
+ File string
+ BuildID string
+ HasFunctions bool
+ HasFilenames bool
+ HasLineNumbers bool
+ HasInlineFrames bool
+
+ fileX int64
+ buildIDX int64
+}
+
+// Location corresponds to Profile.Location
+type Location struct {
+ ID uint64
+ Mapping *Mapping
+ Address uint64
+ Line []Line
+
+ mappingIDX uint64
+}
+
+// Line corresponds to Profile.Line
+type Line struct {
+ Function *Function
+ Line int64
+
+ functionIDX uint64
+}
+
+// Function corresponds to Profile.Function
+type Function struct {
+ ID uint64
+ Name string
+ SystemName string
+ Filename string
+ StartLine int64
+
+ nameX int64
+ systemNameX int64
+ filenameX int64
+}
+
+// Parse parses a profile and checks for its validity. The input
+// may be a gzip-compressed encoded protobuf or one of many legacy
+// profile formats which may be unsupported in the future.
+func Parse(r io.Reader) (*Profile, error) {
+ orig, err := ioutil.ReadAll(r)
+ if err != nil {
+ return nil, err
+ }
+
+ var p *Profile
+ if len(orig) >= 2 && orig[0] == 0x1f && orig[1] == 0x8b {
+ var data []byte
+
+ if gz, err := gzip.NewReader(bytes.NewBuffer(orig)); err == nil {
+ data, err = ioutil.ReadAll(gz)
+ }
+ if err != nil {
+ return nil, fmt.Errorf("decompressing profile: %v", err)
+ }
+ orig = data
+ }
+ if p, err = parseUncompressed(orig); err != nil {
+ if p, err = parseLegacy(orig); err != nil {
+ return nil, fmt.Errorf("parsing profile: %v", err)
+ }
+ }
+
+ if err := p.CheckValid(); err != nil {
+ return nil, fmt.Errorf("malformed profile: %v", err)
+ }
+ return p, nil
+}
+
+var errUnrecognized = fmt.Errorf("unrecognized profile format")
+var errMalformed = fmt.Errorf("malformed profile format")
+
+func parseLegacy(data []byte) (*Profile, error) {
+ parsers := []func([]byte) (*Profile, error){
+ parseCPU,
+ parseHeap,
+ parseGoCount, // goroutine, threadcreate
+ parseThread,
+ parseContention,
+ }
+
+ for _, parser := range parsers {
+ p, err := parser(data)
+ if err == nil {
+ p.setMain()
+ p.addLegacyFrameInfo()
+ return p, nil
+ }
+ if err != errUnrecognized {
+ return nil, err
+ }
+ }
+ return nil, errUnrecognized
+}
+
+func parseUncompressed(data []byte) (*Profile, error) {
+ p := &Profile{}
+ if err := unmarshal(data, p); err != nil {
+ return nil, err
+ }
+
+ if err := p.postDecode(); err != nil {
+ return nil, err
+ }
+
+ return p, nil
+}
+
+var libRx = regexp.MustCompile(`([.]so$|[.]so[._][0-9]+)`)
+
+// setMain scans Mapping entries and guesses which entry is main
+// because legacy profiles don't obey the convention of putting main
+// first.
+func (p *Profile) setMain() {
+ for i := 0; i < len(p.Mapping); i++ {
+ file := strings.TrimSpace(strings.Replace(p.Mapping[i].File, "(deleted)", "", -1))
+ if len(file) == 0 {
+ continue
+ }
+ if len(libRx.FindStringSubmatch(file)) > 0 {
+ continue
+ }
+ if strings.HasPrefix(file, "[") {
+ continue
+ }
+ // Swap what we guess is main to position 0.
+ tmp := p.Mapping[i]
+ p.Mapping[i] = p.Mapping[0]
+ p.Mapping[0] = tmp
+ break
+ }
+}
+
+// Write writes the profile as a gzip-compressed marshaled protobuf.
+func (p *Profile) Write(w io.Writer) error {
+ p.preEncode()
+ b := marshal(p)
+ zw := gzip.NewWriter(w)
+ defer zw.Close()
+ _, err := zw.Write(b)
+ return err
+}
+
+// CheckValid tests whether the profile is valid. Checks include, but are
+// not limited to:
+// - len(Profile.Sample[n].value) == len(Profile.value_unit)
+// - Sample.id has a corresponding Profile.Location
+func (p *Profile) CheckValid() error {
+ // Check that sample values are consistent
+ sampleLen := len(p.SampleType)
+ if sampleLen == 0 && len(p.Sample) != 0 {
+ return fmt.Errorf("missing sample type information")
+ }
+ for _, s := range p.Sample {
+ if len(s.Value) != sampleLen {
+ return fmt.Errorf("mismatch: sample has: %d values vs. %d types", len(s.Value), len(p.SampleType))
+ }
+ }
+
+ // Check that all mappings/locations/functions are in the tables
+ // Check that there are no duplicate ids
+ mappings := make(map[uint64]*Mapping, len(p.Mapping))
+ for _, m := range p.Mapping {
+ if m.ID == 0 {
+ return fmt.Errorf("found mapping with reserved ID=0")
+ }
+ if mappings[m.ID] != nil {
+ return fmt.Errorf("multiple mappings with same id: %d", m.ID)
+ }
+ mappings[m.ID] = m
+ }
+ functions := make(map[uint64]*Function, len(p.Function))
+ for _, f := range p.Function {
+ if f.ID == 0 {
+ return fmt.Errorf("found function with reserved ID=0")
+ }
+ if functions[f.ID] != nil {
+ return fmt.Errorf("multiple functions with same id: %d", f.ID)
+ }
+ functions[f.ID] = f
+ }
+ locations := make(map[uint64]*Location, len(p.Location))
+ for _, l := range p.Location {
+ if l.ID == 0 {
+ return fmt.Errorf("found location with reserved id=0")
+ }
+ if locations[l.ID] != nil {
+ return fmt.Errorf("multiple locations with same id: %d", l.ID)
+ }
+ locations[l.ID] = l
+ if m := l.Mapping; m != nil {
+ if m.ID == 0 || mappings[m.ID] != m {
+ return fmt.Errorf("inconsistent mapping %p: %d", m, m.ID)
+ }
+ }
+ for _, ln := range l.Line {
+ if f := ln.Function; f != nil {
+ if f.ID == 0 || functions[f.ID] != f {
+ return fmt.Errorf("inconsistent function %p: %d", f, f.ID)
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// Aggregate merges the locations in the profile into equivalence
+// classes preserving the request attributes. It also updates the
+// samples to point to the merged locations.
+func (p *Profile) Aggregate(inlineFrame, function, filename, linenumber, address bool) error {
+ for _, m := range p.Mapping {
+ m.HasInlineFrames = m.HasInlineFrames && inlineFrame
+ m.HasFunctions = m.HasFunctions && function
+ m.HasFilenames = m.HasFilenames && filename
+ m.HasLineNumbers = m.HasLineNumbers && linenumber
+ }
+
+ // Aggregate functions
+ if !function || !filename {
+ for _, f := range p.Function {
+ if !function {
+ f.Name = ""
+ f.SystemName = ""
+ }
+ if !filename {
+ f.Filename = ""
+ }
+ }
+ }
+
+ // Aggregate locations
+ if !inlineFrame || !address || !linenumber {
+ for _, l := range p.Location {
+ if !inlineFrame && len(l.Line) > 1 {
+ l.Line = l.Line[len(l.Line)-1:]
+ }
+ if !linenumber {
+ for i := range l.Line {
+ l.Line[i].Line = 0
+ }
+ }
+ if !address {
+ l.Address = 0
+ }
+ }
+ }
+
+ return p.CheckValid()
+}
+
+// Print dumps a text representation of a profile. Intended mainly
+// for debugging purposes.
+func (p *Profile) String() string {
+
+ ss := make([]string, 0, len(p.Sample)+len(p.Mapping)+len(p.Location))
+ if pt := p.PeriodType; pt != nil {
+ ss = append(ss, fmt.Sprintf("PeriodType: %s %s", pt.Type, pt.Unit))
+ }
+ ss = append(ss, fmt.Sprintf("Period: %d", p.Period))
+ if p.TimeNanos != 0 {
+ ss = append(ss, fmt.Sprintf("Time: %v", time.Unix(0, p.TimeNanos)))
+ }
+ if p.DurationNanos != 0 {
+ ss = append(ss, fmt.Sprintf("Duration: %v", time.Duration(p.DurationNanos)))
+ }
+
+ ss = append(ss, "Samples:")
+ var sh1 string
+ for _, s := range p.SampleType {
+ sh1 = sh1 + fmt.Sprintf("%s/%s ", s.Type, s.Unit)
+ }
+ ss = append(ss, strings.TrimSpace(sh1))
+ for _, s := range p.Sample {
+ var sv string
+ for _, v := range s.Value {
+ sv = fmt.Sprintf("%s %10d", sv, v)
+ }
+ sv = sv + ": "
+ for _, l := range s.Location {
+ sv = sv + fmt.Sprintf("%d ", l.ID)
+ }
+ ss = append(ss, sv)
+ const labelHeader = " "
+ if len(s.Label) > 0 {
+ ls := labelHeader
+ for k, v := range s.Label {
+ ls = ls + fmt.Sprintf("%s:%v ", k, v)
+ }
+ ss = append(ss, ls)
+ }
+ if len(s.NumLabel) > 0 {
+ ls := labelHeader
+ for k, v := range s.NumLabel {
+ ls = ls + fmt.Sprintf("%s:%v ", k, v)
+ }
+ ss = append(ss, ls)
+ }
+ }
+
+ ss = append(ss, "Locations")
+ for _, l := range p.Location {
+ locStr := fmt.Sprintf("%6d: %#x ", l.ID, l.Address)
+ if m := l.Mapping; m != nil {
+ locStr = locStr + fmt.Sprintf("M=%d ", m.ID)
+ }
+ if len(l.Line) == 0 {
+ ss = append(ss, locStr)
+ }
+ for li := range l.Line {
+ lnStr := "??"
+ if fn := l.Line[li].Function; fn != nil {
+ lnStr = fmt.Sprintf("%s %s:%d s=%d",
+ fn.Name,
+ fn.Filename,
+ l.Line[li].Line,
+ fn.StartLine)
+ if fn.Name != fn.SystemName {
+ lnStr = lnStr + "(" + fn.SystemName + ")"
+ }
+ }
+ ss = append(ss, locStr+lnStr)
+ // Do not print location details past the first line
+ locStr = " "
+ }
+ }
+
+ ss = append(ss, "Mappings")
+ for _, m := range p.Mapping {
+ bits := ""
+ if m.HasFunctions {
+ bits = bits + "[FN]"
+ }
+ if m.HasFilenames {
+ bits = bits + "[FL]"
+ }
+ if m.HasLineNumbers {
+ bits = bits + "[LN]"
+ }
+ if m.HasInlineFrames {
+ bits = bits + "[IN]"
+ }
+ ss = append(ss, fmt.Sprintf("%d: %#x/%#x/%#x %s %s %s",
+ m.ID,
+ m.Start, m.Limit, m.Offset,
+ m.File,
+ m.BuildID,
+ bits))
+ }
+
+ return strings.Join(ss, "\n") + "\n"
+}
+
+// Merge adds profile p adjusted by ratio r into profile p. Profiles
+// must be compatible (same Type and SampleType).
+// TODO(rsilvera): consider normalizing the profiles based on the
+// total samples collected.
+func (p *Profile) Merge(pb *Profile, r float64) error {
+ if err := p.Compatible(pb); err != nil {
+ return err
+ }
+
+ pb = pb.Copy()
+
+ // Keep the largest of the two periods.
+ if pb.Period > p.Period {
+ p.Period = pb.Period
+ }
+
+ p.DurationNanos += pb.DurationNanos
+
+ p.Mapping = append(p.Mapping, pb.Mapping...)
+ for i, m := range p.Mapping {
+ m.ID = uint64(i + 1)
+ }
+ p.Location = append(p.Location, pb.Location...)
+ for i, l := range p.Location {
+ l.ID = uint64(i + 1)
+ }
+ p.Function = append(p.Function, pb.Function...)
+ for i, f := range p.Function {
+ f.ID = uint64(i + 1)
+ }
+
+ if r != 1.0 {
+ for _, s := range pb.Sample {
+ for i, v := range s.Value {
+ s.Value[i] = int64((float64(v) * r))
+ }
+ }
+ }
+ p.Sample = append(p.Sample, pb.Sample...)
+ return p.CheckValid()
+}
+
+// Compatible determines if two profiles can be compared/merged.
+// returns nil if the profiles are compatible; otherwise an error with
+// details on the incompatibility.
+func (p *Profile) Compatible(pb *Profile) error {
+ if !compatibleValueTypes(p.PeriodType, pb.PeriodType) {
+ return fmt.Errorf("incompatible period types %v and %v", p.PeriodType, pb.PeriodType)
+ }
+
+ if len(p.SampleType) != len(pb.SampleType) {
+ return fmt.Errorf("incompatible sample types %v and %v", p.SampleType, pb.SampleType)
+ }
+
+ for i := range p.SampleType {
+ if !compatibleValueTypes(p.SampleType[i], pb.SampleType[i]) {
+ return fmt.Errorf("incompatible sample types %v and %v", p.SampleType, pb.SampleType)
+ }
+ }
+
+ return nil
+}
+
+// HasFunctions determines if all locations in this profile have
+// symbolized function information.
+func (p *Profile) HasFunctions() bool {
+ for _, l := range p.Location {
+ if l.Mapping == nil || !l.Mapping.HasFunctions {
+ return false
+ }
+ }
+ return true
+}
+
+// HasFileLines determines if all locations in this profile have
+// symbolized file and line number information.
+func (p *Profile) HasFileLines() bool {
+ for _, l := range p.Location {
+ if l.Mapping == nil || (!l.Mapping.HasFilenames || !l.Mapping.HasLineNumbers) {
+ return false
+ }
+ }
+ return true
+}
+
+func compatibleValueTypes(v1, v2 *ValueType) bool {
+ if v1 == nil || v2 == nil {
+ return true // No grounds to disqualify.
+ }
+ return v1.Type == v2.Type && v1.Unit == v2.Unit
+}
+
+// Copy makes a fully independent copy of a profile.
+func (p *Profile) Copy() *Profile {
+ p.preEncode()
+ b := marshal(p)
+
+ pp := &Profile{}
+ if err := unmarshal(b, pp); err != nil {
+ panic(err)
+ }
+ if err := pp.postDecode(); err != nil {
+ panic(err)
+ }
+
+ return pp
+}
+
+// Demangler maps symbol names to a human-readable form. This may
+// include C++ demangling and additional simplification. Names that
+// are not demangled may be missing from the resulting map.
+type Demangler func(name []string) (map[string]string, error)
+
+// Demangle attempts to demangle and optionally simplify any function
+// names referenced in the profile. It works on a best-effort basis:
+// it will silently preserve the original names in case of any errors.
+func (p *Profile) Demangle(d Demangler) error {
+ // Collect names to demangle.
+ var names []string
+ for _, fn := range p.Function {
+ names = append(names, fn.SystemName)
+ }
+
+ // Update profile with demangled names.
+ demangled, err := d(names)
+ if err != nil {
+ return err
+ }
+ for _, fn := range p.Function {
+ if dd, ok := demangled[fn.SystemName]; ok {
+ fn.Name = dd
+ }
+ }
+ return nil
+}
diff --git a/src/cmd/pprof/internal/profile/proto.go b/src/cmd/pprof/internal/profile/proto.go
new file mode 100644
index 000000000..475cf564f
--- /dev/null
+++ b/src/cmd/pprof/internal/profile/proto.go
@@ -0,0 +1,298 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is a simple protocol buffer encoder and decoder.
+//
+// A protocol message must implement the message interface:
+// decoder() []decoder
+// encode(*buffer)
+//
+// The decode method returns a slice indexed by field number that gives the
+// function to decode that field.
+// The encode method encodes its receiver into the given buffer.
+//
+// The two methods are simple enough to be implemented by hand rather than
+// by using a protocol compiler.
+//
+// See profile.go for examples of messages implementing this interface.
+//
+// There is no support for groups, message sets, or "has" bits.
+
+package profile
+
+import "errors"
+
+type buffer struct {
+ field int
+ typ int
+ u64 uint64
+ data []byte
+ tmp [16]byte
+}
+
+type decoder func(*buffer, message) error
+
+type message interface {
+ decoder() []decoder
+ encode(*buffer)
+}
+
+func marshal(m message) []byte {
+ var b buffer
+ m.encode(&b)
+ return b.data
+}
+
+func encodeVarint(b *buffer, x uint64) {
+ for x >= 128 {
+ b.data = append(b.data, byte(x)|0x80)
+ x >>= 7
+ }
+ b.data = append(b.data, byte(x))
+}
+
+func encodeLength(b *buffer, tag int, len int) {
+ encodeVarint(b, uint64(tag)<<3|2)
+ encodeVarint(b, uint64(len))
+}
+
+func encodeUint64(b *buffer, tag int, x uint64) {
+ // append varint to b.data
+ encodeVarint(b, uint64(tag)<<3|0)
+ encodeVarint(b, x)
+}
+
+func encodeUint64s(b *buffer, tag int, x []uint64) {
+ for _, u := range x {
+ encodeUint64(b, tag, u)
+ }
+}
+
+func encodeUint64Opt(b *buffer, tag int, x uint64) {
+ if x == 0 {
+ return
+ }
+ encodeUint64(b, tag, x)
+}
+
+func encodeInt64(b *buffer, tag int, x int64) {
+ u := uint64(x)
+ encodeUint64(b, tag, u)
+}
+
+func encodeInt64Opt(b *buffer, tag int, x int64) {
+ if x == 0 {
+ return
+ }
+ encodeInt64(b, tag, x)
+}
+
+func encodeString(b *buffer, tag int, x string) {
+ encodeLength(b, tag, len(x))
+ b.data = append(b.data, x...)
+}
+
+func encodeStrings(b *buffer, tag int, x []string) {
+ for _, s := range x {
+ encodeString(b, tag, s)
+ }
+}
+
+func encodeStringOpt(b *buffer, tag int, x string) {
+ if x == "" {
+ return
+ }
+ encodeString(b, tag, x)
+}
+
+func encodeBool(b *buffer, tag int, x bool) {
+ if x {
+ encodeUint64(b, tag, 1)
+ } else {
+ encodeUint64(b, tag, 0)
+ }
+}
+
+func encodeBoolOpt(b *buffer, tag int, x bool) {
+ if x == false {
+ return
+ }
+ encodeBool(b, tag, x)
+}
+
+func encodeMessage(b *buffer, tag int, m message) {
+ n1 := len(b.data)
+ m.encode(b)
+ n2 := len(b.data)
+ encodeLength(b, tag, n2-n1)
+ n3 := len(b.data)
+ copy(b.tmp[:], b.data[n2:n3])
+ copy(b.data[n1+(n3-n2):], b.data[n1:n2])
+ copy(b.data[n1:], b.tmp[:n3-n2])
+}
+
+func unmarshal(data []byte, m message) (err error) {
+ b := buffer{data: data, typ: 2}
+ return decodeMessage(&b, m)
+}
+
+func le64(p []byte) uint64 {
+ return uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 | uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56
+}
+
+func le32(p []byte) uint32 {
+ return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
+}
+
+func decodeVarint(data []byte) (uint64, []byte, error) {
+ var i int
+ var u uint64
+ for i = 0; ; i++ {
+ if i >= 10 || i >= len(data) {
+ return 0, nil, errors.New("bad varint")
+ }
+ u |= uint64(data[i]&0x7F) << uint(7*i)
+ if data[i]&0x80 == 0 {
+ return u, data[i+1:], nil
+ }
+ }
+}
+
+func decodeField(b *buffer, data []byte) ([]byte, error) {
+ x, data, err := decodeVarint(data)
+ if err != nil {
+ return nil, err
+ }
+ b.field = int(x >> 3)
+ b.typ = int(x & 7)
+ b.data = nil
+ b.u64 = 0
+ switch b.typ {
+ case 0:
+ b.u64, data, err = decodeVarint(data)
+ if err != nil {
+ return nil, err
+ }
+ case 1:
+ if len(data) < 8 {
+ return nil, errors.New("not enough data")
+ }
+ b.u64 = le64(data[:8])
+ data = data[8:]
+ case 2:
+ var n uint64
+ n, data, err = decodeVarint(data)
+ if err != nil {
+ return nil, err
+ }
+ if n > uint64(len(data)) {
+ return nil, errors.New("too much data")
+ }
+ b.data = data[:n]
+ data = data[n:]
+ case 5:
+ if len(data) < 4 {
+ return nil, errors.New("not enough data")
+ }
+ b.u64 = uint64(le32(data[:4]))
+ data = data[4:]
+ default:
+ return nil, errors.New("unknown type: " + string(b.typ))
+ }
+
+ return data, nil
+}
+
+func checkType(b *buffer, typ int) error {
+ if b.typ != typ {
+ return errors.New("type mismatch")
+ }
+ return nil
+}
+
+func decodeMessage(b *buffer, m message) error {
+ if err := checkType(b, 2); err != nil {
+ return err
+ }
+ dec := m.decoder()
+ data := b.data
+ for len(data) > 0 {
+ // pull varint field# + type
+ var err error
+ data, err = decodeField(b, data)
+ if err != nil {
+ return err
+ }
+ if b.field >= len(dec) || dec[b.field] == nil {
+ continue
+ }
+ if err := dec[b.field](b, m); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func decodeInt64(b *buffer, x *int64) error {
+ if err := checkType(b, 0); err != nil {
+ return err
+ }
+ *x = int64(b.u64)
+ return nil
+}
+
+func decodeInt64s(b *buffer, x *[]int64) error {
+ var i int64
+ if err := decodeInt64(b, &i); err != nil {
+ return err
+ }
+ *x = append(*x, i)
+ return nil
+}
+
+func decodeUint64(b *buffer, x *uint64) error {
+ if err := checkType(b, 0); err != nil {
+ return err
+ }
+ *x = b.u64
+ return nil
+}
+
+func decodeUint64s(b *buffer, x *[]uint64) error {
+ var u uint64
+ if err := decodeUint64(b, &u); err != nil {
+ return err
+ }
+ *x = append(*x, u)
+ return nil
+}
+
+func decodeString(b *buffer, x *string) error {
+ if err := checkType(b, 2); err != nil {
+ return err
+ }
+ *x = string(b.data)
+ return nil
+}
+
+func decodeStrings(b *buffer, x *[]string) error {
+ var s string
+ if err := decodeString(b, &s); err != nil {
+ return err
+ }
+ *x = append(*x, s)
+ return nil
+}
+
+func decodeBool(b *buffer, x *bool) error {
+ if err := checkType(b, 0); err != nil {
+ return err
+ }
+ if int64(b.u64) == 0 {
+ *x = false
+ } else {
+ *x = true
+ }
+ return nil
+}
diff --git a/src/cmd/pprof/internal/profile/prune.go b/src/cmd/pprof/internal/profile/prune.go
new file mode 100644
index 000000000..abc898cb3
--- /dev/null
+++ b/src/cmd/pprof/internal/profile/prune.go
@@ -0,0 +1,97 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Implements methods to remove frames from profiles.
+
+package profile
+
+import (
+ "fmt"
+ "regexp"
+)
+
+// Prune removes all nodes beneath a node matching dropRx, and not
+// matching keepRx. If the root node of a Sample matches, the sample
+// will have an empty stack.
+func (p *Profile) Prune(dropRx, keepRx *regexp.Regexp) {
+ prune := make(map[uint64]bool)
+ pruneBeneath := make(map[uint64]bool)
+
+ for _, loc := range p.Location {
+ var i int
+ for i = len(loc.Line) - 1; i >= 0; i-- {
+ if fn := loc.Line[i].Function; fn != nil && fn.Name != "" {
+ funcName := fn.Name
+ // Account for leading '.' on the PPC ELF v1 ABI.
+ if funcName[0] == '.' {
+ funcName = funcName[1:]
+ }
+ if dropRx.MatchString(funcName) {
+ if keepRx == nil || !keepRx.MatchString(funcName) {
+ break
+ }
+ }
+ }
+ }
+
+ if i >= 0 {
+ // Found matching entry to prune.
+ pruneBeneath[loc.ID] = true
+
+ // Remove the matching location.
+ if i == len(loc.Line)-1 {
+ // Matched the top entry: prune the whole location.
+ prune[loc.ID] = true
+ } else {
+ loc.Line = loc.Line[i+1:]
+ }
+ }
+ }
+
+ // Prune locs from each Sample
+ for _, sample := range p.Sample {
+ // Scan from the root to the leaves to find the prune location.
+ // Do not prune frames before the first user frame, to avoid
+ // pruning everything.
+ foundUser := false
+ for i := len(sample.Location) - 1; i >= 0; i-- {
+ id := sample.Location[i].ID
+ if !prune[id] && !pruneBeneath[id] {
+ foundUser = true
+ continue
+ }
+ if !foundUser {
+ continue
+ }
+ if prune[id] {
+ sample.Location = sample.Location[i+1:]
+ break
+ }
+ if pruneBeneath[id] {
+ sample.Location = sample.Location[i:]
+ break
+ }
+ }
+ }
+}
+
+// RemoveUninteresting prunes and elides profiles using built-in
+// tables of uninteresting function names.
+func (p *Profile) RemoveUninteresting() error {
+ var keep, drop *regexp.Regexp
+ var err error
+
+ if p.DropFrames != "" {
+ if drop, err = regexp.Compile("^(" + p.DropFrames + ")$"); err != nil {
+ return fmt.Errorf("failed to compile regexp %s: %v", p.DropFrames, err)
+ }
+ if p.KeepFrames != "" {
+ if keep, err = regexp.Compile("^(" + p.KeepFrames + ")$"); err != nil {
+ return fmt.Errorf("failed to compile regexp %s: %v", p.KeepFrames, err)
+ }
+ }
+ p.Prune(drop, keep)
+ }
+ return nil
+}
diff --git a/src/cmd/pprof/internal/report/report.go b/src/cmd/pprof/internal/report/report.go
new file mode 100644
index 000000000..e5977fd03
--- /dev/null
+++ b/src/cmd/pprof/internal/report/report.go
@@ -0,0 +1,1718 @@
+// 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 report summarizes a performance profile into a
+// human-readable report.
+package report
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "os"
+ "path/filepath"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ "cmd/pprof/internal/plugin"
+ "cmd/pprof/internal/profile"
+)
+
+// Generate generates a report as directed by the Report.
+func Generate(w io.Writer, rpt *Report, obj plugin.ObjTool) error {
+ o := rpt.options
+
+ switch o.OutputFormat {
+ case Dot:
+ return printDOT(w, rpt)
+ case Tree:
+ return printTree(w, rpt)
+ case Text:
+ return printText(w, rpt)
+ case Raw:
+ fmt.Fprint(w, rpt.prof.String())
+ return nil
+ case Tags:
+ return printTags(w, rpt)
+ case Proto:
+ return rpt.prof.Write(w)
+ case Dis:
+ return printAssembly(w, rpt, obj)
+ case List:
+ return printSource(w, rpt)
+ case WebList:
+ return printWebSource(w, rpt, obj)
+ case Callgrind:
+ return printCallgrind(w, rpt)
+ }
+ return fmt.Errorf("unexpected output format")
+}
+
+// printAssembly prints an annotated assembly listing.
+func printAssembly(w io.Writer, rpt *Report, obj plugin.ObjTool) error {
+ g, err := newGraph(rpt)
+ if err != nil {
+ return err
+ }
+
+ o := rpt.options
+ prof := rpt.prof
+
+ // If the regexp source can be parsed as an address, also match
+ // functions that land on that address.
+ var address *uint64
+ if hex, err := strconv.ParseUint(o.Symbol.String(), 0, 64); err == nil {
+ address = &hex
+ }
+
+ fmt.Fprintln(w, "Total:", rpt.formatValue(rpt.total))
+ symbols := symbolsFromBinaries(prof, g, o.Symbol, address, obj)
+ symNodes := nodesPerSymbol(g.ns, symbols)
+ // Sort function names for printing.
+ var syms objSymbols
+ for s := range symNodes {
+ syms = append(syms, s)
+ }
+ sort.Sort(syms)
+
+ // Correlate the symbols from the binary with the profile samples.
+ for _, s := range syms {
+ sns := symNodes[s]
+
+ // Gather samples for this symbol.
+ flatSum, cumSum := sumNodes(sns)
+
+ // Get the function assembly.
+ insns, err := obj.Disasm(s.sym.File, s.sym.Start, s.sym.End)
+ if err != nil {
+ return err
+ }
+
+ ns := annotateAssembly(insns, sns, s.base)
+
+ fmt.Fprintf(w, "ROUTINE ======================== %s\n", s.sym.Name[0])
+ for _, name := range s.sym.Name[1:] {
+ fmt.Fprintf(w, " AKA ======================== %s\n", name)
+ }
+ fmt.Fprintf(w, "%10s %10s (flat, cum) %s of Total\n",
+ rpt.formatValue(flatSum), rpt.formatValue(cumSum),
+ percentage(cumSum, rpt.total))
+
+ for _, n := range ns {
+ fmt.Fprintf(w, "%10s %10s %10x: %s\n", valueOrDot(n.flat, rpt), valueOrDot(n.cum, rpt), n.info.address, n.info.name)
+ }
+ }
+ return nil
+}
+
+// symbolsFromBinaries examines the binaries listed on the profile
+// that have associated samples, and identifies symbols matching rx.
+func symbolsFromBinaries(prof *profile.Profile, g graph, rx *regexp.Regexp, address *uint64, obj plugin.ObjTool) []*objSymbol {
+ hasSamples := make(map[string]bool)
+ // Only examine mappings that have samples that match the
+ // regexp. This is an optimization to speed up pprof.
+ for _, n := range g.ns {
+ if name := n.info.prettyName(); rx.MatchString(name) && n.info.objfile != "" {
+ hasSamples[n.info.objfile] = true
+ }
+ }
+
+ // Walk all mappings looking for matching functions with samples.
+ var objSyms []*objSymbol
+ for _, m := range prof.Mapping {
+ if !hasSamples[filepath.Base(m.File)] {
+ if address == nil || !(m.Start <= *address && *address <= m.Limit) {
+ continue
+ }
+ }
+
+ f, err := obj.Open(m.File, m.Start)
+ if err != nil {
+ fmt.Printf("%v\n", err)
+ continue
+ }
+
+ // Find symbols in this binary matching the user regexp.
+ var addr uint64
+ if address != nil {
+ addr = *address
+ }
+ msyms, err := f.Symbols(rx, addr)
+ base := f.Base()
+ f.Close()
+ if err != nil {
+ continue
+ }
+ for _, ms := range msyms {
+ objSyms = append(objSyms,
+ &objSymbol{
+ sym: ms,
+ base: base,
+ },
+ )
+ }
+ }
+
+ return objSyms
+}
+
+// objSym represents a symbol identified from a binary. It includes
+// the SymbolInfo from the disasm package and the base that must be
+// added to correspond to sample addresses
+type objSymbol struct {
+ sym *plugin.Sym
+ base uint64
+}
+
+// objSymbols is a wrapper type to enable sorting of []*objSymbol.
+type objSymbols []*objSymbol
+
+func (o objSymbols) Len() int {
+ return len(o)
+}
+
+func (o objSymbols) Less(i, j int) bool {
+ if namei, namej := o[i].sym.Name[0], o[j].sym.Name[0]; namei != namej {
+ return namei < namej
+ }
+ return o[i].sym.Start < o[j].sym.Start
+}
+
+func (o objSymbols) Swap(i, j int) {
+ o[i], o[j] = o[j], o[i]
+}
+
+// nodesPerSymbol classifies nodes into a group of symbols.
+func nodesPerSymbol(ns nodes, symbols []*objSymbol) map[*objSymbol]nodes {
+ symNodes := make(map[*objSymbol]nodes)
+ for _, s := range symbols {
+ // Gather samples for this symbol.
+ for _, n := range ns {
+ address := n.info.address - s.base
+ if address >= s.sym.Start && address < s.sym.End {
+ symNodes[s] = append(symNodes[s], n)
+ }
+ }
+ }
+ return symNodes
+}
+
+// annotateAssembly annotates a set of assembly instructions with a
+// set of samples. It returns a set of nodes to display. base is an
+// offset to adjust the sample addresses.
+func annotateAssembly(insns []plugin.Inst, samples nodes, base uint64) nodes {
+ // Add end marker to simplify printing loop.
+ insns = append(insns, plugin.Inst{^uint64(0), "", "", 0})
+
+ // Ensure samples are sorted by address.
+ samples.sort(addressOrder)
+
+ var s int
+ var asm nodes
+ for ix, in := range insns[:len(insns)-1] {
+ n := node{
+ info: nodeInfo{
+ address: in.Addr,
+ name: in.Text,
+ file: trimPath(in.File),
+ lineno: in.Line,
+ },
+ }
+
+ // Sum all the samples until the next instruction (to account
+ // for samples attributed to the middle of an instruction).
+ for next := insns[ix+1].Addr; s < len(samples) && samples[s].info.address-base < next; s++ {
+ n.flat += samples[s].flat
+ n.cum += samples[s].cum
+ if samples[s].info.file != "" {
+ n.info.file = trimPath(samples[s].info.file)
+ n.info.lineno = samples[s].info.lineno
+ }
+ }
+ asm = append(asm, &n)
+ }
+
+ return asm
+}
+
+// valueOrDot formats a value according to a report, intercepting zero
+// values.
+func valueOrDot(value int64, rpt *Report) string {
+ if value == 0 {
+ return "."
+ }
+ return rpt.formatValue(value)
+}
+
+// canAccessFile determines if the filename can be opened for reading.
+func canAccessFile(path string) bool {
+ if fi, err := os.Stat(path); err == nil {
+ return fi.Mode().Perm()&0400 != 0
+ }
+ return false
+}
+
+// printTags collects all tags referenced in the profile and prints
+// them in a sorted table.
+func printTags(w io.Writer, rpt *Report) error {
+ p := rpt.prof
+
+ // Hashtable to keep accumulate tags as key,value,count.
+ tagMap := make(map[string]map[string]int64)
+ for _, s := range p.Sample {
+ for key, vals := range s.Label {
+ for _, val := range vals {
+ if valueMap, ok := tagMap[key]; ok {
+ valueMap[val] = valueMap[val] + s.Value[0]
+ continue
+ }
+ valueMap := make(map[string]int64)
+ valueMap[val] = s.Value[0]
+ tagMap[key] = valueMap
+ }
+ }
+ for key, vals := range s.NumLabel {
+ for _, nval := range vals {
+ val := scaledValueLabel(nval, key, "auto")
+ if valueMap, ok := tagMap[key]; ok {
+ valueMap[val] = valueMap[val] + s.Value[0]
+ continue
+ }
+ valueMap := make(map[string]int64)
+ valueMap[val] = s.Value[0]
+ tagMap[key] = valueMap
+ }
+ }
+ }
+
+ tagKeys := make(tags, 0, len(tagMap))
+ for key := range tagMap {
+ tagKeys = append(tagKeys, &tag{name: key})
+ }
+ sort.Sort(tagKeys)
+
+ for _, tagKey := range tagKeys {
+ var total int64
+ key := tagKey.name
+ tags := make(tags, 0, len(tagMap[key]))
+ for t, c := range tagMap[key] {
+ total += c
+ tags = append(tags, &tag{name: t, weight: c})
+ }
+
+ sort.Sort(tags)
+ fmt.Fprintf(w, "%s: Total %d\n", key, total)
+ for _, t := range tags {
+ if total > 0 {
+ fmt.Fprintf(w, " %8d (%s): %s\n", t.weight,
+ percentage(t.weight, total), t.name)
+ } else {
+ fmt.Fprintf(w, " %8d: %s\n", t.weight, t.name)
+ }
+ }
+ fmt.Fprintln(w)
+ }
+ return nil
+}
+
+// printText prints a flat text report for a profile.
+func printText(w io.Writer, rpt *Report) error {
+ g, err := newGraph(rpt)
+ if err != nil {
+ return err
+ }
+
+ origCount, droppedNodes, _ := g.preprocess(rpt)
+ fmt.Fprintln(w, strings.Join(legendDetailLabels(rpt, g, origCount, droppedNodes, 0), "\n"))
+
+ fmt.Fprintf(w, "%10s %5s%% %5s%% %10s %5s%%\n",
+ "flat", "flat", "sum", "cum", "cum")
+
+ var flatSum int64
+ for _, n := range g.ns {
+ name, flat, cum := n.info.prettyName(), n.flat, n.cum
+
+ flatSum += flat
+ fmt.Fprintf(w, "%10s %s %s %10s %s %s\n",
+ rpt.formatValue(flat),
+ percentage(flat, rpt.total),
+ percentage(flatSum, rpt.total),
+ rpt.formatValue(cum),
+ percentage(cum, rpt.total),
+ name)
+ }
+ return nil
+}
+
+// printCallgrind prints a graph for a profile on callgrind format.
+func printCallgrind(w io.Writer, rpt *Report) error {
+ g, err := newGraph(rpt)
+ if err != nil {
+ return err
+ }
+
+ o := rpt.options
+ rpt.options.NodeFraction = 0
+ rpt.options.EdgeFraction = 0
+ rpt.options.NodeCount = 0
+
+ g.preprocess(rpt)
+
+ fmt.Fprintln(w, "events:", o.SampleType+"("+o.OutputUnit+")")
+
+ files := make(map[string]int)
+ names := make(map[string]int)
+ for _, n := range g.ns {
+ fmt.Fprintln(w, "fl="+callgrindName(files, n.info.file))
+ fmt.Fprintln(w, "fn="+callgrindName(names, n.info.name))
+ sv, _ := ScaleValue(n.flat, o.SampleUnit, o.OutputUnit)
+ fmt.Fprintf(w, "%d %d\n", n.info.lineno, int(sv))
+
+ // Print outgoing edges.
+ for _, out := range sortedEdges(n.out) {
+ c, _ := ScaleValue(out.weight, o.SampleUnit, o.OutputUnit)
+ count := fmt.Sprintf("%d", int(c))
+ callee := out.dest
+ fmt.Fprintln(w, "cfl="+callgrindName(files, callee.info.file))
+ fmt.Fprintln(w, "cfn="+callgrindName(names, callee.info.name))
+ fmt.Fprintln(w, "calls="+count, callee.info.lineno)
+ fmt.Fprintln(w, n.info.lineno, count)
+ }
+ fmt.Fprintln(w)
+ }
+
+ return nil
+}
+
+// callgrindName implements the callgrind naming compression scheme.
+// For names not previously seen returns "(N) name", where N is a
+// unique index. For names previously seen returns "(N)" where N is
+// the index returned the first time.
+func callgrindName(names map[string]int, name string) string {
+ if name == "" {
+ return ""
+ }
+ if id, ok := names[name]; ok {
+ return fmt.Sprintf("(%d)", id)
+ }
+ id := len(names) + 1
+ names[name] = id
+ return fmt.Sprintf("(%d) %s", id, name)
+}
+
+// printTree prints a tree-based report in text form.
+func printTree(w io.Writer, rpt *Report) error {
+ const separator = "----------------------------------------------------------+-------------"
+ const legend = " flat flat% sum% cum cum% calls calls% + context "
+
+ g, err := newGraph(rpt)
+ if err != nil {
+ return err
+ }
+
+ origCount, droppedNodes, _ := g.preprocess(rpt)
+ fmt.Fprintln(w, strings.Join(legendDetailLabels(rpt, g, origCount, droppedNodes, 0), "\n"))
+
+ fmt.Fprintln(w, separator)
+ fmt.Fprintln(w, legend)
+ var flatSum int64
+
+ rx := rpt.options.Symbol
+ for _, n := range g.ns {
+ name, flat, cum := n.info.prettyName(), n.flat, n.cum
+
+ // Skip any entries that do not match the regexp (for the "peek" command).
+ if rx != nil && !rx.MatchString(name) {
+ continue
+ }
+
+ fmt.Fprintln(w, separator)
+ // Print incoming edges.
+ inEdges := sortedEdges(n.in)
+ inSum := inEdges.sum()
+ for _, in := range inEdges {
+ fmt.Fprintf(w, "%50s %s | %s\n", rpt.formatValue(in.weight),
+ percentage(in.weight, inSum), in.src.info.prettyName())
+ }
+
+ // Print current node.
+ flatSum += flat
+ fmt.Fprintf(w, "%10s %s %s %10s %s | %s\n",
+ rpt.formatValue(flat),
+ percentage(flat, rpt.total),
+ percentage(flatSum, rpt.total),
+ rpt.formatValue(cum),
+ percentage(cum, rpt.total),
+ name)
+
+ // Print outgoing edges.
+ outEdges := sortedEdges(n.out)
+ outSum := outEdges.sum()
+ for _, out := range outEdges {
+ fmt.Fprintf(w, "%50s %s | %s\n", rpt.formatValue(out.weight),
+ percentage(out.weight, outSum), out.dest.info.prettyName())
+ }
+ }
+ if len(g.ns) > 0 {
+ fmt.Fprintln(w, separator)
+ }
+ return nil
+}
+
+// printDOT prints an annotated callgraph in DOT format.
+func printDOT(w io.Writer, rpt *Report) error {
+ g, err := newGraph(rpt)
+ if err != nil {
+ return err
+ }
+
+ origCount, droppedNodes, droppedEdges := g.preprocess(rpt)
+
+ prof := rpt.prof
+ graphname := "unnamed"
+ if len(prof.Mapping) > 0 {
+ graphname = filepath.Base(prof.Mapping[0].File)
+ }
+ fmt.Fprintln(w, `digraph "`+graphname+`" {`)
+ fmt.Fprintln(w, `node [style=filled fillcolor="#f8f8f8"]`)
+ fmt.Fprintln(w, dotLegend(rpt, g, origCount, droppedNodes, droppedEdges))
+
+ if len(g.ns) == 0 {
+ fmt.Fprintln(w, "}")
+ return nil
+ }
+
+ // Make sure nodes have a unique consistent id.
+ nodeIndex := make(map[*node]int)
+ maxFlat := float64(g.ns[0].flat)
+ for i, n := range g.ns {
+ nodeIndex[n] = i + 1
+ if float64(n.flat) > maxFlat {
+ maxFlat = float64(n.flat)
+ }
+ }
+ var edges edgeList
+ for _, n := range g.ns {
+ node := dotNode(rpt, maxFlat, nodeIndex[n], n)
+ fmt.Fprintln(w, node)
+ if nodelets := dotNodelets(rpt, nodeIndex[n], n); nodelets != "" {
+ fmt.Fprint(w, nodelets)
+ }
+
+ // Collect outgoing edges.
+ for _, e := range n.out {
+ edges = append(edges, e)
+ }
+ }
+ // Sort edges by frequency as a hint to the graph layout engine.
+ sort.Sort(edges)
+ for _, e := range edges {
+ fmt.Fprintln(w, dotEdge(rpt, nodeIndex[e.src], nodeIndex[e.dest], e))
+ }
+ fmt.Fprintln(w, "}")
+ return nil
+}
+
+// percentage computes the percentage of total of a value, and encodes
+// it as a string. At least two digits of precision are printed.
+func percentage(value, total int64) string {
+ var ratio float64
+ if total != 0 {
+ ratio = float64(value) / float64(total) * 100
+ }
+ switch {
+ case ratio >= 99.95:
+ return " 100%"
+ case ratio >= 1.0:
+ return fmt.Sprintf("%5.2f%%", ratio)
+ default:
+ return fmt.Sprintf("%5.2g%%", ratio)
+ }
+}
+
+// dotLegend generates the overall graph label for a report in DOT format.
+func dotLegend(rpt *Report, g graph, origCount, droppedNodes, droppedEdges int) string {
+ label := legendLabels(rpt)
+ label = append(label, legendDetailLabels(rpt, g, origCount, droppedNodes, droppedEdges)...)
+ return fmt.Sprintf(`subgraph cluster_L { L [shape=box fontsize=32 label="%s\l"] }`, strings.Join(label, `\l`))
+}
+
+// legendLabels generates labels exclusive to graph visualization.
+func legendLabels(rpt *Report) []string {
+ prof := rpt.prof
+ o := rpt.options
+ var label []string
+ if len(prof.Mapping) > 0 {
+ if prof.Mapping[0].File != "" {
+ label = append(label, "File: "+filepath.Base(prof.Mapping[0].File))
+ }
+ if prof.Mapping[0].BuildID != "" {
+ label = append(label, "Build ID: "+prof.Mapping[0].BuildID)
+ }
+ }
+ if o.SampleType != "" {
+ label = append(label, "Type: "+o.SampleType)
+ }
+ if prof.TimeNanos != 0 {
+ const layout = "Jan 2, 2006 at 3:04pm (MST)"
+ label = append(label, "Time: "+time.Unix(0, prof.TimeNanos).Format(layout))
+ }
+ if prof.DurationNanos != 0 {
+ label = append(label, fmt.Sprintf("Duration: %v", time.Duration(prof.DurationNanos)))
+ }
+ return label
+}
+
+// legendDetailLabels generates labels common to graph and text visualization.
+func legendDetailLabels(rpt *Report, g graph, origCount, droppedNodes, droppedEdges int) []string {
+ nodeFraction := rpt.options.NodeFraction
+ edgeFraction := rpt.options.EdgeFraction
+ nodeCount := rpt.options.NodeCount
+
+ label := []string{}
+
+ var flatSum int64
+ for _, n := range g.ns {
+ flatSum = flatSum + n.flat
+ }
+
+ label = append(label, fmt.Sprintf("%s of %s total (%s)", rpt.formatValue(flatSum), rpt.formatValue(rpt.total), percentage(flatSum, rpt.total)))
+
+ if rpt.total > 0 {
+ if droppedNodes > 0 {
+ label = append(label, genLabel(droppedNodes, "node", "cum",
+ rpt.formatValue(int64(float64(rpt.total)*nodeFraction))))
+ }
+ if droppedEdges > 0 {
+ label = append(label, genLabel(droppedEdges, "edge", "freq",
+ rpt.formatValue(int64(float64(rpt.total)*edgeFraction))))
+ }
+ if nodeCount > 0 && nodeCount < origCount {
+ label = append(label, fmt.Sprintf("Showing top %d nodes out of %d (cum >= %s)",
+ nodeCount, origCount,
+ rpt.formatValue(g.ns[len(g.ns)-1].cum)))
+ }
+ }
+ return label
+}
+
+func genLabel(d int, n, l, f string) string {
+ if d > 1 {
+ n = n + "s"
+ }
+ return fmt.Sprintf("Dropped %d %s (%s <= %s)", d, n, l, f)
+}
+
+// dotNode generates a graph node in DOT format.
+func dotNode(rpt *Report, maxFlat float64, rIndex int, n *node) string {
+ flat, cum := n.flat, n.cum
+
+ labels := strings.Split(n.info.prettyName(), "::")
+ label := strings.Join(labels, `\n`) + `\n`
+
+ flatValue := rpt.formatValue(flat)
+ if flat > 0 {
+ label = label + fmt.Sprintf(`%s(%s)`,
+ flatValue,
+ strings.TrimSpace(percentage(flat, rpt.total)))
+ } else {
+ label = label + "0"
+ }
+ cumValue := flatValue
+ if cum != flat {
+ if flat > 0 {
+ label = label + `\n`
+ } else {
+ label = label + " "
+ }
+ cumValue = rpt.formatValue(cum)
+ label = label + fmt.Sprintf(`of %s(%s)`,
+ cumValue,
+ strings.TrimSpace(percentage(cum, rpt.total)))
+ }
+
+ // Scale font sizes from 8 to 24 based on percentage of flat frequency.
+ // Use non linear growth to emphasize the size difference.
+ baseFontSize, maxFontGrowth := 8, 16.0
+ fontSize := baseFontSize
+ if maxFlat > 0 && flat > 0 && float64(flat) <= maxFlat {
+ fontSize += int(math.Ceil(maxFontGrowth * math.Sqrt(float64(flat)/maxFlat)))
+ }
+ return fmt.Sprintf(`N%d [label="%s" fontsize=%d shape=box tooltip="%s (%s)"]`,
+ rIndex,
+ label,
+ fontSize, n.info.prettyName(), cumValue)
+}
+
+// dotEdge generates a graph edge in DOT format.
+func dotEdge(rpt *Report, from, to int, e *edgeInfo) string {
+ w := rpt.formatValue(e.weight)
+ attr := fmt.Sprintf(`label=" %s"`, w)
+ if rpt.total > 0 {
+ if weight := 1 + int(e.weight*100/rpt.total); weight > 1 {
+ attr = fmt.Sprintf(`%s weight=%d`, attr, weight)
+ }
+ if width := 1 + int(e.weight*5/rpt.total); width > 1 {
+ attr = fmt.Sprintf(`%s penwidth=%d`, attr, width)
+ }
+ }
+ arrow := "->"
+ if e.residual {
+ arrow = "..."
+ }
+ tooltip := fmt.Sprintf(`"%s %s %s (%s)"`,
+ e.src.info.prettyName(), arrow, e.dest.info.prettyName(), w)
+ attr = fmt.Sprintf(`%s tooltip=%s labeltooltip=%s`,
+ attr, tooltip, tooltip)
+
+ if e.residual {
+ attr = attr + ` style="dotted"`
+ }
+
+ if len(e.src.tags) > 0 {
+ // Separate children further if source has tags.
+ attr = attr + " minlen=2"
+ }
+ return fmt.Sprintf("N%d -> N%d [%s]", from, to, attr)
+}
+
+// dotNodelets generates the DOT boxes for the node tags.
+func dotNodelets(rpt *Report, rIndex int, n *node) (dot string) {
+ const maxNodelets = 4 // Number of nodelets for alphanumeric labels
+ const maxNumNodelets = 4 // Number of nodelets for numeric labels
+
+ var ts, nts tags
+ for _, t := range n.tags {
+ if t.unit == "" {
+ ts = append(ts, t)
+ } else {
+ nts = append(nts, t)
+ }
+ }
+
+ // Select the top maxNodelets alphanumeric labels by weight
+ sort.Sort(ts)
+ if len(ts) > maxNodelets {
+ ts = ts[:maxNodelets]
+ }
+ for i, t := range ts {
+ weight := rpt.formatValue(t.weight)
+ dot += fmt.Sprintf(`N%d_%d [label = "%s" fontsize=8 shape=box3d tooltip="%s"]`+"\n", rIndex, i, t.name, weight)
+ dot += fmt.Sprintf(`N%d -> N%d_%d [label=" %s" weight=100 tooltip="\L" labeltooltip="\L"]`+"\n", rIndex, rIndex, i, weight)
+ }
+
+ // Collapse numeric labels into maxNumNodelets buckets, of the form:
+ // 1MB..2MB, 3MB..5MB, ...
+ nts = collapseTags(nts, maxNumNodelets)
+ sort.Sort(nts)
+ for i, t := range nts {
+ weight := rpt.formatValue(t.weight)
+ dot += fmt.Sprintf(`NN%d_%d [label = "%s" fontsize=8 shape=box3d tooltip="%s"]`+"\n", rIndex, i, t.name, weight)
+ dot += fmt.Sprintf(`N%d -> NN%d_%d [label=" %s" weight=100 tooltip="\L" labeltooltip="\L"]`+"\n", rIndex, rIndex, i, weight)
+ }
+
+ return dot
+}
+
+// graph summarizes a performance profile into a format that is
+// suitable for visualization.
+type graph struct {
+ ns nodes
+}
+
+// nodes is an ordered collection of graph nodes.
+type nodes []*node
+
+// tags represent sample annotations
+type tags []*tag
+type tagMap map[string]*tag
+
+type tag struct {
+ name string
+ unit string // Describe the value, "" for non-numeric tags
+ value int64
+ weight int64
+}
+
+func (t tags) Len() int { return len(t) }
+func (t tags) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
+func (t tags) Less(i, j int) bool {
+ if t[i].weight == t[j].weight {
+ return t[i].name < t[j].name
+ }
+ return t[i].weight > t[j].weight
+}
+
+// node is an entry on a profiling report. It represents a unique
+// program location. It can include multiple names to represent
+// inlined functions.
+type node struct {
+ info nodeInfo // Information associated to this entry.
+
+ // values associated to this node.
+ // flat is exclusive to this node, cum includes all descendents.
+ flat, cum int64
+
+ // in and out contains the nodes immediately reaching or reached by this nodes.
+ in, out edgeMap
+
+ // tags provide additional information about subsets of a sample.
+ tags tagMap
+}
+
+func (ts tags) string() string {
+ var ret string
+ for _, s := range ts {
+ ret = ret + fmt.Sprintf("%s %s %d %d\n", s.name, s.unit, s.value, s.weight)
+ }
+ return ret
+}
+
+type nodeInfo struct {
+ name string
+ origName string
+ address uint64
+ file string
+ startLine, lineno int
+ inline bool
+ lowPriority bool
+ objfile string
+ parent *node // Used only if creating a calltree
+}
+
+func (n *node) addTags(s *profile.Sample, weight int64) {
+ // Add a tag with all string labels
+ var labels []string
+ for key, vals := range s.Label {
+ for _, v := range vals {
+ labels = append(labels, key+":"+v)
+ }
+ }
+ if len(labels) > 0 {
+ sort.Strings(labels)
+ l := n.tags.findOrAddTag(strings.Join(labels, `\n`), "", 0)
+ l.weight += weight
+ }
+
+ for key, nvals := range s.NumLabel {
+ for _, v := range nvals {
+ label := scaledValueLabel(v, key, "auto")
+ l := n.tags.findOrAddTag(label, key, v)
+ l.weight += weight
+ }
+ }
+}
+
+func (m tagMap) findOrAddTag(label, unit string, value int64) *tag {
+ if l := m[label]; l != nil {
+ return l
+ }
+ l := &tag{
+ name: label,
+ unit: unit,
+ value: value,
+ }
+ m[label] = l
+ return l
+}
+
+// collapseTags reduces the number of entries in a tagMap by merging
+// adjacent nodes into ranges. It uses a greedy approach to merge
+// starting with the entries with the lowest weight.
+func collapseTags(ts tags, count int) tags {
+ if len(ts) <= count {
+ return ts
+ }
+
+ sort.Sort(ts)
+ tagGroups := make([]tags, count)
+ for i, t := range ts[:count] {
+ tagGroups[i] = tags{t}
+ }
+ for _, t := range ts[count:] {
+ g, d := 0, tagDistance(t, tagGroups[0][0])
+ for i := 1; i < count; i++ {
+ if nd := tagDistance(t, tagGroups[i][0]); nd < d {
+ g, d = i, nd
+ }
+ }
+ tagGroups[g] = append(tagGroups[g], t)
+ }
+
+ var nts tags
+ for _, g := range tagGroups {
+ l, w := tagGroupLabel(g)
+ nts = append(nts, &tag{
+ name: l,
+ weight: w,
+ })
+ }
+ return nts
+}
+
+func tagDistance(t, u *tag) float64 {
+ v, _ := ScaleValue(u.value, u.unit, t.unit)
+ if v < float64(t.value) {
+ return float64(t.value) - v
+ }
+ return v - float64(t.value)
+}
+
+func tagGroupLabel(g tags) (string, int64) {
+ if len(g) == 1 {
+ t := g[0]
+ return scaledValueLabel(t.value, t.unit, "auto"), t.weight
+ }
+ min := g[0]
+ max := g[0]
+ w := min.weight
+ for _, t := range g[1:] {
+ if v, _ := ScaleValue(t.value, t.unit, min.unit); int64(v) < min.value {
+ min = t
+ }
+ if v, _ := ScaleValue(t.value, t.unit, max.unit); int64(v) > max.value {
+ max = t
+ }
+ w += t.weight
+ }
+ return scaledValueLabel(min.value, min.unit, "auto") + ".." +
+ scaledValueLabel(max.value, max.unit, "auto"), w
+}
+
+// sumNodes adds the flat and sum values on a report.
+func sumNodes(ns nodes) (flat int64, cum int64) {
+ for _, n := range ns {
+ flat += n.flat
+ cum += n.cum
+ }
+ return
+}
+
+type edgeMap map[*node]*edgeInfo
+
+// edgeInfo contains any attributes to be represented about edges in a graph/
+type edgeInfo struct {
+ src, dest *node
+ // The summary weight of the edge
+ weight int64
+ // residual edges connect nodes that were connected through a
+ // separate node, which has been removed from the report.
+ residual bool
+}
+
+// bumpWeight increases the weight of an edge. If there isn't such an
+// edge in the map one is created.
+func bumpWeight(from, to *node, w int64, residual bool) {
+ if from.out[to] != to.in[from] {
+ panic(fmt.Errorf("asymmetric edges %v %v", *from, *to))
+ }
+
+ if n := from.out[to]; n != nil {
+ n.weight += w
+ if n.residual && !residual {
+ n.residual = false
+ }
+ return
+ }
+
+ info := &edgeInfo{src: from, dest: to, weight: w, residual: residual}
+ from.out[to] = info
+ to.in[from] = info
+}
+
+// Output formats.
+const (
+ Proto = iota
+ Dot
+ Tags
+ Tree
+ Text
+ Raw
+ Dis
+ List
+ WebList
+ Callgrind
+)
+
+// Options are the formatting and filtering options used to generate a
+// profile.
+type Options struct {
+ OutputFormat int
+
+ CumSort bool
+ CallTree bool
+ PrintAddresses bool
+ DropNegative bool
+ Ratio float64
+
+ NodeCount int
+ NodeFraction float64
+ EdgeFraction float64
+
+ SampleType string
+ SampleUnit string // Unit for the sample data from the profile.
+ OutputUnit string // Units for data formatting in report.
+
+ Symbol *regexp.Regexp // Symbols to include on disassembly report.
+}
+
+// newGraph summarizes performance data from a profile into a graph.
+func newGraph(rpt *Report) (g graph, err error) {
+ prof := rpt.prof
+ o := rpt.options
+
+ // Generate a tree for graphical output if requested.
+ buildTree := o.CallTree && o.OutputFormat == Dot
+
+ locations := make(map[uint64][]nodeInfo)
+ for _, l := range prof.Location {
+ locations[l.ID] = newLocInfo(l)
+ }
+
+ nm := make(nodeMap)
+ for _, sample := range prof.Sample {
+ if sample.Location == nil {
+ continue
+ }
+
+ // Construct list of node names for sample.
+ var stack []nodeInfo
+ for _, loc := range sample.Location {
+ id := loc.ID
+ stack = append(stack, locations[id]...)
+ }
+
+ // Upfront pass to update the parent chains, to prevent the
+ // merging of nodes with different parents.
+ if buildTree {
+ var nn *node
+ for i := len(stack); i > 0; i-- {
+ n := &stack[i-1]
+ n.parent = nn
+ nn = nm.findOrInsertNode(*n)
+ }
+ }
+
+ leaf := nm.findOrInsertNode(stack[0])
+ weight := rpt.sampleValue(sample)
+ leaf.addTags(sample, weight)
+
+ // Aggregate counter data.
+ leaf.flat += weight
+ seen := make(map[*node]bool)
+ var nn *node
+ for _, s := range stack {
+ n := nm.findOrInsertNode(s)
+ if !seen[n] {
+ seen[n] = true
+ n.cum += weight
+
+ if nn != nil {
+ bumpWeight(n, nn, weight, false)
+ }
+ }
+ nn = n
+ }
+ }
+
+ // Collect new nodes into a report.
+ ns := make(nodes, 0, len(nm))
+ for _, n := range nm {
+ if rpt.options.DropNegative && n.flat < 0 {
+ continue
+ }
+ ns = append(ns, n)
+ }
+
+ return graph{ns}, nil
+}
+
+// Create a slice of formatted names for a location.
+func newLocInfo(l *profile.Location) []nodeInfo {
+ var objfile string
+
+ if m := l.Mapping; m != nil {
+ objfile = filepath.Base(m.File)
+ }
+
+ if len(l.Line) == 0 {
+ return []nodeInfo{
+ {
+ address: l.Address,
+ objfile: objfile,
+ },
+ }
+ }
+ var info []nodeInfo
+ numInlineFrames := len(l.Line) - 1
+ for li, line := range l.Line {
+ ni := nodeInfo{
+ address: l.Address,
+ lineno: int(line.Line),
+ inline: li < numInlineFrames,
+ objfile: objfile,
+ }
+
+ if line.Function != nil {
+ ni.name = line.Function.Name
+ ni.origName = line.Function.SystemName
+ ni.file = line.Function.Filename
+ ni.startLine = int(line.Function.StartLine)
+ }
+
+ info = append(info, ni)
+ }
+ return info
+}
+
+// nodeMap maps from a node info struct to a node. It is used to merge
+// report entries with the same info.
+type nodeMap map[nodeInfo]*node
+
+func (m nodeMap) findOrInsertNode(info nodeInfo) *node {
+ rr := m[info]
+ if rr == nil {
+ rr = &node{
+ info: info,
+ in: make(edgeMap),
+ out: make(edgeMap),
+ tags: make(map[string]*tag),
+ }
+ m[info] = rr
+ }
+ return rr
+}
+
+// preprocess does any required filtering/sorting according to the
+// report options. Returns the mapping from each node to any nodes
+// removed by path compression and statistics on the nodes/edges removed.
+func (g *graph) preprocess(rpt *Report) (origCount, droppedNodes, droppedEdges int) {
+ o := rpt.options
+
+ // Compute total weight of current set of nodes.
+ // This is <= rpt.total because of node filtering.
+ var totalValue int64
+ for _, n := range g.ns {
+ totalValue += n.flat
+ }
+
+ // Remove nodes with value <= total*nodeFraction
+ if nodeFraction := o.NodeFraction; nodeFraction > 0 {
+ var removed nodes
+ minValue := int64(float64(totalValue) * nodeFraction)
+ kept := make(nodes, 0, len(g.ns))
+ for _, n := range g.ns {
+ if n.cum < minValue {
+ removed = append(removed, n)
+ } else {
+ kept = append(kept, n)
+ tagsKept := make(map[string]*tag)
+ for s, t := range n.tags {
+ if t.weight >= minValue {
+ tagsKept[s] = t
+ }
+ }
+ n.tags = tagsKept
+ }
+ }
+ droppedNodes = len(removed)
+ removeNodes(removed, false, false)
+ g.ns = kept
+ }
+
+ // Remove edges below minimum frequency.
+ if edgeFraction := o.EdgeFraction; edgeFraction > 0 {
+ minEdge := int64(float64(totalValue) * edgeFraction)
+ for _, n := range g.ns {
+ for src, e := range n.in {
+ if e.weight < minEdge {
+ delete(n.in, src)
+ delete(src.out, n)
+ droppedEdges++
+ }
+ }
+ }
+ }
+
+ sortOrder := flatName
+ if o.CumSort {
+ // Force cum sorting for graph output, to preserve connectivity.
+ sortOrder = cumName
+ }
+
+ // Nodes that have flat==0 and a single in/out do not provide much
+ // information. Give them first chance to be removed. Do not consider edges
+ // from/to nodes that are expected to be removed.
+ maxNodes := o.NodeCount
+ if o.OutputFormat == Dot {
+ if maxNodes > 0 && maxNodes < len(g.ns) {
+ sortOrder = cumName
+ g.ns.sort(cumName)
+ cumCutoff := g.ns[maxNodes].cum
+ for _, n := range g.ns {
+ if n.flat == 0 {
+ if count := countEdges(n.out, cumCutoff); count > 1 {
+ continue
+ }
+ if count := countEdges(n.in, cumCutoff); count != 1 {
+ continue
+ }
+ n.info.lowPriority = true
+ }
+ }
+ }
+ }
+
+ g.ns.sort(sortOrder)
+ if maxNodes > 0 {
+ origCount = len(g.ns)
+ for index, nodes := 0, 0; index < len(g.ns); index++ {
+ nodes++
+ // For DOT output, count the tags as nodes since we will draw
+ // boxes for them.
+ if o.OutputFormat == Dot {
+ nodes += len(g.ns[index].tags)
+ }
+ if nodes > maxNodes {
+ // Trim to the top n nodes. Create dotted edges to bridge any
+ // broken connections.
+ removeNodes(g.ns[index:], true, true)
+ g.ns = g.ns[:index]
+ break
+ }
+ }
+ }
+ removeRedundantEdges(g.ns)
+
+ // Select best unit for profile output.
+ // Find the appropriate units for the smallest non-zero sample
+ if o.OutputUnit == "minimum" && len(g.ns) > 0 {
+ var maxValue, minValue int64
+
+ for _, n := range g.ns {
+ if n.flat > 0 && (minValue == 0 || n.flat < minValue) {
+ minValue = n.flat
+ }
+ if n.cum > maxValue {
+ maxValue = n.cum
+ }
+ }
+ if r := o.Ratio; r > 0 && r != 1 {
+ minValue = int64(float64(minValue) * r)
+ maxValue = int64(float64(maxValue) * r)
+ }
+
+ _, minUnit := ScaleValue(minValue, o.SampleUnit, "minimum")
+ _, maxUnit := ScaleValue(maxValue, o.SampleUnit, "minimum")
+
+ unit := minUnit
+ if minUnit != maxUnit && minValue*100 < maxValue && o.OutputFormat != Callgrind {
+ // Minimum and maximum values have different units. Scale
+ // minimum by 100 to use larger units, allowing minimum value to
+ // be scaled down to 0.01, except for callgrind reports since
+ // they can only represent integer values.
+ _, unit = ScaleValue(100*minValue, o.SampleUnit, "minimum")
+ }
+
+ if unit != "" {
+ o.OutputUnit = unit
+ } else {
+ o.OutputUnit = o.SampleUnit
+ }
+ }
+ return
+}
+
+// countEdges counts the number of edges below the specified cutoff.
+func countEdges(el edgeMap, cutoff int64) int {
+ count := 0
+ for _, e := range el {
+ if e.weight > cutoff {
+ count++
+ }
+ }
+ return count
+}
+
+// removeNodes removes nodes from a report, optionally bridging
+// connections between in/out edges and spreading out their weights
+// proportionally. residual marks new bridge edges as residual
+// (dotted).
+func removeNodes(toRemove nodes, bridge, residual bool) {
+ for _, n := range toRemove {
+ for ei := range n.in {
+ delete(ei.out, n)
+ }
+ if bridge {
+ for ei, wi := range n.in {
+ for eo, wo := range n.out {
+ var weight int64
+ if n.cum != 0 {
+ weight = int64(float64(wo.weight) * (float64(wi.weight) / float64(n.cum)))
+ }
+ bumpWeight(ei, eo, weight, residual)
+ }
+ }
+ }
+ for eo := range n.out {
+ delete(eo.in, n)
+ }
+ }
+}
+
+// removeRedundantEdges removes residual edges if the destination can
+// be reached through another path. This is done to simplify the graph
+// while preserving connectivity.
+func removeRedundantEdges(ns nodes) {
+ // Walk the nodes and outgoing edges in reverse order to prefer
+ // removing edges with the lowest weight.
+ for i := len(ns); i > 0; i-- {
+ n := ns[i-1]
+ in := sortedEdges(n.in)
+ for j := len(in); j > 0; j-- {
+ if e := in[j-1]; e.residual && isRedundant(e) {
+ delete(e.src.out, e.dest)
+ delete(e.dest.in, e.src)
+ }
+ }
+ }
+}
+
+// isRedundant determines if an edge can be removed without impacting
+// connectivity of the whole graph. This is implemented by checking if the
+// nodes have a common ancestor after removing the edge.
+func isRedundant(e *edgeInfo) bool {
+ destPred := predecessors(e, e.dest)
+ if len(destPred) == 1 {
+ return false
+ }
+ srcPred := predecessors(e, e.src)
+
+ for n := range srcPred {
+ if destPred[n] && n != e.dest {
+ return true
+ }
+ }
+ return false
+}
+
+// predecessors collects all the predecessors to node n, excluding edge e.
+func predecessors(e *edgeInfo, n *node) map[*node]bool {
+ seen := map[*node]bool{n: true}
+ queue := []*node{n}
+ for len(queue) > 0 {
+ n := queue[0]
+ queue = queue[1:]
+ for _, ie := range n.in {
+ if e == ie || seen[ie.src] {
+ continue
+ }
+ seen[ie.src] = true
+ queue = append(queue, ie.src)
+ }
+ }
+ return seen
+}
+
+// nodeSorter is a mechanism used to allow a report to be sorted
+// in different ways.
+type nodeSorter struct {
+ rs nodes
+ less func(i, j int) bool
+}
+
+func (s nodeSorter) Len() int { return len(s.rs) }
+func (s nodeSorter) Swap(i, j int) { s.rs[i], s.rs[j] = s.rs[j], s.rs[i] }
+func (s nodeSorter) Less(i, j int) bool { return s.less(i, j) }
+
+type nodeOrder int
+
+const (
+ flatName nodeOrder = iota
+ flatCumName
+ cumName
+ nameOrder
+ fileOrder
+ addressOrder
+)
+
+// sort reoders the entries in a report based on the specified
+// ordering criteria. The result is sorted in decreasing order for
+// numeric quantities, alphabetically for text, and increasing for
+// addresses.
+func (ns nodes) sort(o nodeOrder) error {
+ var s nodeSorter
+
+ switch o {
+ case flatName:
+ s = nodeSorter{ns,
+ func(i, j int) bool {
+ if iv, jv := ns[i].flat, ns[j].flat; iv != jv {
+ return iv > jv
+ }
+ if ns[i].info.prettyName() != ns[j].info.prettyName() {
+ return ns[i].info.prettyName() < ns[j].info.prettyName()
+ }
+ iv, jv := ns[i].cum, ns[j].cum
+ return iv > jv
+ },
+ }
+ case flatCumName:
+ s = nodeSorter{ns,
+ func(i, j int) bool {
+ if iv, jv := ns[i].flat, ns[j].flat; iv != jv {
+ return iv > jv
+ }
+ if iv, jv := ns[i].cum, ns[j].cum; iv != jv {
+ return iv > jv
+ }
+ return ns[i].info.prettyName() < ns[j].info.prettyName()
+ },
+ }
+ case cumName:
+ s = nodeSorter{ns,
+ func(i, j int) bool {
+ if ns[i].info.lowPriority != ns[j].info.lowPriority {
+ return ns[j].info.lowPriority
+ }
+ if iv, jv := ns[i].cum, ns[j].cum; iv != jv {
+ return iv > jv
+ }
+ if ns[i].info.prettyName() != ns[j].info.prettyName() {
+ return ns[i].info.prettyName() < ns[j].info.prettyName()
+ }
+ iv, jv := ns[i].flat, ns[j].flat
+ return iv > jv
+ },
+ }
+ case nameOrder:
+ s = nodeSorter{ns,
+ func(i, j int) bool {
+ return ns[i].info.name < ns[j].info.name
+ },
+ }
+ case fileOrder:
+ s = nodeSorter{ns,
+ func(i, j int) bool {
+ return ns[i].info.file < ns[j].info.file
+ },
+ }
+ case addressOrder:
+ s = nodeSorter{ns,
+ func(i, j int) bool {
+ return ns[i].info.address < ns[j].info.address
+ },
+ }
+ default:
+ return fmt.Errorf("report: unrecognized sort ordering: %d", o)
+ }
+ sort.Sort(s)
+ return nil
+}
+
+type edgeList []*edgeInfo
+
+// sortedEdges return a slice of the edges in the map, sorted for
+// visualization. The sort order is first based on the edge weight
+// (higher-to-lower) and then by the node names to avoid flakiness.
+func sortedEdges(edges map[*node]*edgeInfo) edgeList {
+ el := make(edgeList, 0, len(edges))
+ for _, w := range edges {
+ el = append(el, w)
+ }
+
+ sort.Sort(el)
+ return el
+}
+
+func (el edgeList) Len() int {
+ return len(el)
+}
+
+func (el edgeList) Less(i, j int) bool {
+ if el[i].weight != el[j].weight {
+ return el[i].weight > el[j].weight
+ }
+
+ from1 := el[i].src.info.prettyName()
+ from2 := el[j].src.info.prettyName()
+ if from1 != from2 {
+ return from1 < from2
+ }
+
+ to1 := el[i].dest.info.prettyName()
+ to2 := el[j].dest.info.prettyName()
+
+ return to1 < to2
+}
+
+func (el edgeList) Swap(i, j int) {
+ el[i], el[j] = el[j], el[i]
+}
+
+func (el edgeList) sum() int64 {
+ var ret int64
+ for _, e := range el {
+ ret += e.weight
+ }
+ return ret
+}
+
+// ScaleValue reformats a value from a unit to a different unit.
+func ScaleValue(value int64, fromUnit, toUnit string) (sv float64, su string) {
+ // Avoid infinite recursion on overflow.
+ if value < 0 && -value > 0 {
+ v, u := ScaleValue(-value, fromUnit, toUnit)
+ return -v, u
+ }
+ if m, u, ok := memoryLabel(value, fromUnit, toUnit); ok {
+ return m, u
+ }
+ if t, u, ok := timeLabel(value, fromUnit, toUnit); ok {
+ return t, u
+ }
+ // Skip non-interesting units.
+ switch toUnit {
+ case "count", "sample", "unit", "minimum":
+ return float64(value), ""
+ default:
+ return float64(value), toUnit
+ }
+}
+
+func scaledValueLabel(value int64, fromUnit, toUnit string) string {
+ v, u := ScaleValue(value, fromUnit, toUnit)
+
+ sv := strings.TrimSuffix(fmt.Sprintf("%.2f", v), ".00")
+ if sv == "0" || sv == "-0" {
+ return "0"
+ }
+ return sv + u
+}
+
+func memoryLabel(value int64, fromUnit, toUnit string) (v float64, u string, ok bool) {
+ fromUnit = strings.TrimSuffix(strings.ToLower(fromUnit), "s")
+ toUnit = strings.TrimSuffix(strings.ToLower(toUnit), "s")
+
+ switch fromUnit {
+ case "byte", "b":
+ case "kilobyte", "kb":
+ value *= 1024
+ case "megabyte", "mb":
+ value *= 1024 * 1024
+ case "gigabyte", "gb":
+ value *= 1024 * 1024
+ default:
+ return 0, "", false
+ }
+
+ if toUnit == "minimum" || toUnit == "auto" {
+ switch {
+ case value < 1024:
+ toUnit = "b"
+ case value < 1024*1024:
+ toUnit = "kb"
+ case value < 1024*1024*1024:
+ toUnit = "mb"
+ default:
+ toUnit = "gb"
+ }
+ }
+
+ var output float64
+ switch toUnit {
+ default:
+ output, toUnit = float64(value), "B"
+ case "kb", "kbyte", "kilobyte":
+ output, toUnit = float64(value)/1024, "kB"
+ case "mb", "mbyte", "megabyte":
+ output, toUnit = float64(value)/(1024*1024), "MB"
+ case "gb", "gbyte", "giggabyte":
+ output, toUnit = float64(value)/(1024*1024*1024), "GB"
+ }
+ return output, toUnit, true
+}
+
+func timeLabel(value int64, fromUnit, toUnit string) (v float64, u string, ok bool) {
+ fromUnit = strings.ToLower(fromUnit)
+ if len(fromUnit) > 2 {
+ fromUnit = strings.TrimSuffix(fromUnit, "s")
+ }
+
+ toUnit = strings.ToLower(toUnit)
+ if len(toUnit) > 2 {
+ toUnit = strings.TrimSuffix(toUnit, "s")
+ }
+
+ var d time.Duration
+ switch fromUnit {
+ case "nanosecond", "ns":
+ d = time.Duration(value) * time.Nanosecond
+ case "microsecond":
+ d = time.Duration(value) * time.Microsecond
+ case "millisecond", "ms":
+ d = time.Duration(value) * time.Millisecond
+ case "second", "sec":
+ d = time.Duration(value) * time.Second
+ case "cycle":
+ return float64(value), "", true
+ default:
+ return 0, "", false
+ }
+
+ if toUnit == "minimum" || toUnit == "auto" {
+ switch {
+ case d < 1*time.Microsecond:
+ toUnit = "ns"
+ case d < 1*time.Millisecond:
+ toUnit = "us"
+ case d < 1*time.Second:
+ toUnit = "ms"
+ case d < 1*time.Minute:
+ toUnit = "sec"
+ case d < 1*time.Hour:
+ toUnit = "min"
+ case d < 24*time.Hour:
+ toUnit = "hour"
+ case d < 15*24*time.Hour:
+ toUnit = "day"
+ case d < 120*24*time.Hour:
+ toUnit = "week"
+ default:
+ toUnit = "year"
+ }
+ }
+
+ var output float64
+ dd := float64(d)
+ switch toUnit {
+ case "ns", "nanosecond":
+ output, toUnit = dd/float64(time.Nanosecond), "ns"
+ case "us", "microsecond":
+ output, toUnit = dd/float64(time.Microsecond), "us"
+ case "ms", "millisecond":
+ output, toUnit = dd/float64(time.Millisecond), "ms"
+ case "min", "minute":
+ output, toUnit = dd/float64(time.Minute), "mins"
+ case "hour", "hr":
+ output, toUnit = dd/float64(time.Hour), "hrs"
+ case "day":
+ output, toUnit = dd/float64(24*time.Hour), "days"
+ case "week", "wk":
+ output, toUnit = dd/float64(7*24*time.Hour), "wks"
+ case "year", "yr":
+ output, toUnit = dd/float64(365*7*24*time.Hour), "yrs"
+ default:
+ fallthrough
+ case "sec", "second", "s":
+ output, toUnit = dd/float64(time.Second), "s"
+ }
+ return output, toUnit, true
+}
+
+// prettyName determines the printable name to be used for a node.
+func (info *nodeInfo) prettyName() string {
+ var name string
+ if info.address != 0 {
+ name = fmt.Sprintf("%016x", info.address)
+ }
+
+ if info.name != "" {
+ name = name + " " + info.name
+ }
+
+ if info.file != "" {
+ name += " " + trimPath(info.file)
+ if info.lineno != 0 {
+ name += fmt.Sprintf(":%d", info.lineno)
+ }
+ }
+
+ if info.inline {
+ name = name + " (inline)"
+ }
+
+ if name = strings.TrimSpace(name); name == "" && info.objfile != "" {
+ name = "[" + info.objfile + "]"
+ }
+ return name
+}
+
+// New builds a new report indexing the sample values interpreting the
+// samples with the provided function.
+func New(prof *profile.Profile, options Options, value func(s *profile.Sample) int64, unit string) *Report {
+ o := &options
+ if o.SampleUnit == "" {
+ o.SampleUnit = unit
+ }
+ format := func(v int64) string {
+ if r := o.Ratio; r > 0 && r != 1 {
+ fv := float64(v) * r
+ v = int64(fv)
+ }
+ return scaledValueLabel(v, o.SampleUnit, o.OutputUnit)
+ }
+ return &Report{prof, computeTotal(prof, value), o, value, format}
+}
+
+// NewDefault builds a new report indexing the sample values with the
+// last value available.
+func NewDefault(prof *profile.Profile, options Options) *Report {
+ index := len(prof.SampleType) - 1
+ o := &options
+ if o.SampleUnit == "" {
+ o.SampleUnit = strings.ToLower(prof.SampleType[index].Unit)
+ }
+ value := func(s *profile.Sample) int64 {
+ return s.Value[index]
+ }
+ format := func(v int64) string {
+ if r := o.Ratio; r > 0 && r != 1 {
+ fv := float64(v) * r
+ v = int64(fv)
+ }
+ return scaledValueLabel(v, o.SampleUnit, o.OutputUnit)
+ }
+ return &Report{prof, computeTotal(prof, value), o, value, format}
+}
+
+func computeTotal(prof *profile.Profile, value func(s *profile.Sample) int64) int64 {
+ var ret int64
+ for _, sample := range prof.Sample {
+ ret += value(sample)
+ }
+ return ret
+}
+
+// Report contains the data and associated routines to extract a
+// report from a profile.
+type Report struct {
+ prof *profile.Profile
+ total int64
+ options *Options
+ sampleValue func(*profile.Sample) int64
+ formatValue func(int64) string
+}
+
+func (rpt *Report) formatTags(s *profile.Sample) (string, bool) {
+ var labels []string
+ for key, vals := range s.Label {
+ for _, v := range vals {
+ labels = append(labels, key+":"+v)
+ }
+ }
+ for key, nvals := range s.NumLabel {
+ for _, v := range nvals {
+ labels = append(labels, scaledValueLabel(v, key, "auto"))
+ }
+ }
+ if len(labels) == 0 {
+ return "", false
+ }
+ sort.Strings(labels)
+ return strings.Join(labels, `\n`), true
+}
diff --git a/src/cmd/pprof/internal/report/source.go b/src/cmd/pprof/internal/report/source.go
new file mode 100644
index 000000000..57300dd91
--- /dev/null
+++ b/src/cmd/pprof/internal/report/source.go
@@ -0,0 +1,450 @@
+// 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 report
+
+// This file contains routines related to the generation of annotated
+// source listings.
+
+import (
+ "bufio"
+ "fmt"
+ "html/template"
+ "io"
+ "os"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+
+ "cmd/pprof/internal/plugin"
+)
+
+// printSource prints an annotated source listing, include all
+// functions with samples that match the regexp rpt.options.symbol.
+// The sources are sorted by function name and then by filename to
+// eliminate potential nondeterminism.
+func printSource(w io.Writer, rpt *Report) error {
+ o := rpt.options
+ g, err := newGraph(rpt)
+ if err != nil {
+ return err
+ }
+
+ // Identify all the functions that match the regexp provided.
+ // Group nodes for each matching function.
+ var functions nodes
+ functionNodes := make(map[string]nodes)
+ for _, n := range g.ns {
+ if !o.Symbol.MatchString(n.info.name) {
+ continue
+ }
+ if functionNodes[n.info.name] == nil {
+ functions = append(functions, n)
+ }
+ functionNodes[n.info.name] = append(functionNodes[n.info.name], n)
+ }
+ functions.sort(nameOrder)
+
+ fmt.Fprintf(w, "Total: %s\n", rpt.formatValue(rpt.total))
+ for _, fn := range functions {
+ name := fn.info.name
+
+ // Identify all the source files associated to this function.
+ // Group nodes for each source file.
+ var sourceFiles nodes
+ fileNodes := make(map[string]nodes)
+ for _, n := range functionNodes[name] {
+ if n.info.file == "" {
+ continue
+ }
+ if fileNodes[n.info.file] == nil {
+ sourceFiles = append(sourceFiles, n)
+ }
+ fileNodes[n.info.file] = append(fileNodes[n.info.file], n)
+ }
+
+ if len(sourceFiles) == 0 {
+ fmt.Printf("No source information for %s\n", name)
+ continue
+ }
+
+ sourceFiles.sort(fileOrder)
+
+ // Print each file associated with this function.
+ for _, fl := range sourceFiles {
+ filename := fl.info.file
+ fns := fileNodes[filename]
+ flatSum, cumSum := sumNodes(fns)
+
+ fnodes, path, err := getFunctionSource(name, filename, fns, 0, 0)
+ fmt.Fprintf(w, "ROUTINE ======================== %s in %s\n", name, path)
+ fmt.Fprintf(w, "%10s %10s (flat, cum) %s of Total\n",
+ rpt.formatValue(flatSum), rpt.formatValue(cumSum),
+ percentage(cumSum, rpt.total))
+
+ if err != nil {
+ fmt.Fprintf(w, " Error: %v\n", err)
+ continue
+ }
+
+ for _, fn := range fnodes {
+ fmt.Fprintf(w, "%10s %10s %6d:%s\n", valueOrDot(fn.flat, rpt), valueOrDot(fn.cum, rpt), fn.info.lineno, fn.info.name)
+ }
+ }
+ }
+ return nil
+}
+
+// printWebSource prints an annotated source listing, include all
+// functions with samples that match the regexp rpt.options.symbol.
+func printWebSource(w io.Writer, rpt *Report, obj plugin.ObjTool) error {
+ o := rpt.options
+ g, err := newGraph(rpt)
+ if err != nil {
+ return err
+ }
+
+ // If the regexp source can be parsed as an address, also match
+ // functions that land on that address.
+ var address *uint64
+ if hex, err := strconv.ParseUint(o.Symbol.String(), 0, 64); err == nil {
+ address = &hex
+ }
+
+ // Extract interesting symbols from binary files in the profile and
+ // classify samples per symbol.
+ symbols := symbolsFromBinaries(rpt.prof, g, o.Symbol, address, obj)
+ symNodes := nodesPerSymbol(g.ns, symbols)
+
+ // Sort symbols for printing.
+ var syms objSymbols
+ for s := range symNodes {
+ syms = append(syms, s)
+ }
+ sort.Sort(syms)
+
+ if len(syms) == 0 {
+ return fmt.Errorf("no samples found on routines matching: %s", o.Symbol.String())
+ }
+
+ printHeader(w, rpt)
+ for _, s := range syms {
+ name := s.sym.Name[0]
+ // Identify sources associated to a symbol by examining
+ // symbol samples. Classify samples per source file.
+ var sourceFiles nodes
+ fileNodes := make(map[string]nodes)
+ for _, n := range symNodes[s] {
+ if n.info.file == "" {
+ continue
+ }
+ if fileNodes[n.info.file] == nil {
+ sourceFiles = append(sourceFiles, n)
+ }
+ fileNodes[n.info.file] = append(fileNodes[n.info.file], n)
+ }
+
+ if len(sourceFiles) == 0 {
+ fmt.Printf("No source information for %s\n", name)
+ continue
+ }
+
+ sourceFiles.sort(fileOrder)
+
+ // Print each file associated with this function.
+ for _, fl := range sourceFiles {
+ filename := fl.info.file
+ fns := fileNodes[filename]
+
+ asm := assemblyPerSourceLine(symbols, fns, filename, obj)
+ start, end := sourceCoordinates(asm)
+
+ fnodes, path, err := getFunctionSource(name, filename, fns, start, end)
+ if err != nil {
+ fnodes, path = getMissingFunctionSource(filename, asm, start, end)
+ }
+
+ flatSum, cumSum := sumNodes(fnodes)
+ printFunctionHeader(w, name, path, flatSum, cumSum, rpt)
+ for _, fn := range fnodes {
+ printFunctionSourceLine(w, fn, asm[fn.info.lineno], rpt)
+ }
+ printFunctionClosing(w)
+ }
+ }
+ printPageClosing(w)
+ return nil
+}
+
+// sourceCoordinates returns the lowest and highest line numbers from
+// a set of assembly statements.
+func sourceCoordinates(asm map[int]nodes) (start, end int) {
+ for l := range asm {
+ if start == 0 || l < start {
+ start = l
+ }
+ if end == 0 || l > end {
+ end = l
+ }
+ }
+ return start, end
+}
+
+// assemblyPerSourceLine disassembles the binary containing a symbol
+// and classifies the assembly instructions according to its
+// corresponding source line, annotating them with a set of samples.
+func assemblyPerSourceLine(objSyms []*objSymbol, rs nodes, src string, obj plugin.ObjTool) map[int]nodes {
+ assembly := make(map[int]nodes)
+ // Identify symbol to use for this collection of samples.
+ o := findMatchingSymbol(objSyms, rs)
+ if o == nil {
+ return assembly
+ }
+
+ // Extract assembly for matched symbol
+ insns, err := obj.Disasm(o.sym.File, o.sym.Start, o.sym.End)
+ if err != nil {
+ return assembly
+ }
+
+ srcBase := filepath.Base(src)
+ anodes := annotateAssembly(insns, rs, o.base)
+ var lineno = 0
+ for _, an := range anodes {
+ if filepath.Base(an.info.file) == srcBase {
+ lineno = an.info.lineno
+ }
+ if lineno != 0 {
+ assembly[lineno] = append(assembly[lineno], an)
+ }
+ }
+
+ return assembly
+}
+
+// findMatchingSymbol looks for the symbol that corresponds to a set
+// of samples, by comparing their addresses.
+func findMatchingSymbol(objSyms []*objSymbol, ns nodes) *objSymbol {
+ for _, n := range ns {
+ for _, o := range objSyms {
+ if filepath.Base(o.sym.File) == n.info.objfile &&
+ o.sym.Start <= n.info.address-o.base &&
+ n.info.address-o.base <= o.sym.End {
+ return o
+ }
+ }
+ }
+ return nil
+}
+
+// printHeader prints the page header for a weblist report.
+func printHeader(w io.Writer, rpt *Report) {
+ fmt.Fprintln(w, weblistPageHeader)
+
+ var labels []string
+ for _, l := range legendLabels(rpt) {
+ labels = append(labels, template.HTMLEscapeString(l))
+ }
+
+ fmt.Fprintf(w, `<div class="legend">%s<br>Total: %s</div>`,
+ strings.Join(labels, "<br>\n"),
+ rpt.formatValue(rpt.total),
+ )
+}
+
+// printFunctionHeader prints a function header for a weblist report.
+func printFunctionHeader(w io.Writer, name, path string, flatSum, cumSum int64, rpt *Report) {
+ fmt.Fprintf(w, `<h1>%s</h1>%s
+<pre onClick="pprof_toggle_asm()">
+ Total: %10s %10s (flat, cum) %s
+`,
+ template.HTMLEscapeString(name), template.HTMLEscapeString(path),
+ rpt.formatValue(flatSum), rpt.formatValue(cumSum),
+ percentage(cumSum, rpt.total))
+}
+
+// printFunctionSourceLine prints a source line and the corresponding assembly.
+func printFunctionSourceLine(w io.Writer, fn *node, assembly nodes, rpt *Report) {
+ if len(assembly) == 0 {
+ fmt.Fprintf(w,
+ "<span class=line> %6d</span> <span class=nop> %10s %10s %s </span>\n",
+ fn.info.lineno,
+ valueOrDot(fn.flat, rpt), valueOrDot(fn.cum, rpt),
+ template.HTMLEscapeString(fn.info.name))
+ return
+ }
+
+ fmt.Fprintf(w,
+ "<span class=line> %6d</span> <span class=deadsrc> %10s %10s %s </span>",
+ fn.info.lineno,
+ valueOrDot(fn.flat, rpt), valueOrDot(fn.cum, rpt),
+ template.HTMLEscapeString(fn.info.name))
+ fmt.Fprint(w, "<span class=asm>")
+ for _, an := range assembly {
+ var fileline string
+ class := "disasmloc"
+ if an.info.file != "" {
+ fileline = fmt.Sprintf("%s:%d", template.HTMLEscapeString(an.info.file), an.info.lineno)
+ if an.info.lineno != fn.info.lineno {
+ class = "unimportant"
+ }
+ }
+ fmt.Fprintf(w, " %8s %10s %10s %8x: %-48s <span class=%s>%s</span>\n", "",
+ valueOrDot(an.flat, rpt), valueOrDot(an.cum, rpt),
+ an.info.address,
+ template.HTMLEscapeString(an.info.name),
+ class,
+ template.HTMLEscapeString(fileline))
+ }
+ fmt.Fprintln(w, "</span>")
+}
+
+// printFunctionClosing prints the end of a function in a weblist report.
+func printFunctionClosing(w io.Writer) {
+ fmt.Fprintln(w, "</pre>")
+}
+
+// printPageClosing prints the end of the page in a weblist report.
+func printPageClosing(w io.Writer) {
+ fmt.Fprintln(w, weblistPageClosing)
+}
+
+// getFunctionSource collects the sources of a function from a source
+// file and annotates it with the samples in fns. Returns the sources
+// as nodes, using the info.name field to hold the source code.
+func getFunctionSource(fun, file string, fns nodes, start, end int) (nodes, string, error) {
+ f, file, err := adjustSourcePath(file)
+ if err != nil {
+ return nil, file, err
+ }
+
+ lineNodes := make(map[int]nodes)
+
+ // Collect source coordinates from profile.
+ const margin = 5 // Lines before first/after last sample.
+ if start == 0 {
+ if fns[0].info.startLine != 0 {
+ start = fns[0].info.startLine
+ } else {
+ start = fns[0].info.lineno - margin
+ }
+ } else {
+ start -= margin
+ }
+ if end == 0 {
+ end = fns[0].info.lineno
+ }
+ end += margin
+ for _, n := range fns {
+ lineno := n.info.lineno
+ nodeStart := n.info.startLine
+ if nodeStart == 0 {
+ nodeStart = lineno - margin
+ }
+ nodeEnd := lineno + margin
+ if nodeStart < start {
+ start = nodeStart
+ } else if nodeEnd > end {
+ end = nodeEnd
+ }
+ lineNodes[lineno] = append(lineNodes[lineno], n)
+ }
+
+ var src nodes
+ buf := bufio.NewReader(f)
+ lineno := 1
+ for {
+ line, err := buf.ReadString('\n')
+ if err != nil {
+ if line == "" || err != io.EOF {
+ return nil, file, err
+ }
+ }
+ if lineno >= start {
+ flat, cum := sumNodes(lineNodes[lineno])
+
+ src = append(src, &node{
+ info: nodeInfo{
+ name: strings.TrimRight(line, "\n"),
+ lineno: lineno,
+ },
+ flat: flat,
+ cum: cum,
+ })
+ }
+ lineno++
+ if lineno > end {
+ break
+ }
+ }
+ return src, file, nil
+}
+
+// getMissingFunctionSource creates a dummy function body to point to
+// the source file and annotates it with the samples in asm.
+func getMissingFunctionSource(filename string, asm map[int]nodes, start, end int) (nodes, string) {
+ var fnodes nodes
+ for i := start; i <= end; i++ {
+ lrs := asm[i]
+ if len(lrs) == 0 {
+ continue
+ }
+ flat, cum := sumNodes(lrs)
+ fnodes = append(fnodes, &node{
+ info: nodeInfo{
+ name: "???",
+ lineno: i,
+ },
+ flat: flat,
+ cum: cum,
+ })
+ }
+ return fnodes, filename
+}
+
+// adjustSourcePath adjusts the pathe for a source file by trimmming
+// known prefixes and searching for the file on all parents of the
+// current working dir.
+func adjustSourcePath(path string) (*os.File, string, error) {
+ path = trimPath(path)
+ f, err := os.Open(path)
+ if err == nil {
+ return f, path, nil
+ }
+
+ if dir, wderr := os.Getwd(); wderr == nil {
+ for {
+ parent := filepath.Dir(dir)
+ if parent == dir {
+ break
+ }
+ if f, err := os.Open(filepath.Join(parent, path)); err == nil {
+ return f, filepath.Join(parent, path), nil
+ }
+
+ dir = parent
+ }
+ }
+
+ return nil, path, err
+}
+
+// trimPath cleans up a path by removing prefixes that are commonly
+// found on profiles.
+func trimPath(path string) string {
+ basePaths := []string{
+ "/proc/self/cwd/./",
+ "/proc/self/cwd/",
+ }
+
+ sPath := filepath.ToSlash(path)
+
+ for _, base := range basePaths {
+ if strings.HasPrefix(sPath, base) {
+ return filepath.FromSlash(sPath[len(base):])
+ }
+ }
+ return path
+}
diff --git a/src/cmd/pprof/internal/report/source_html.go b/src/cmd/pprof/internal/report/source_html.go
new file mode 100644
index 000000000..267fabdc4
--- /dev/null
+++ b/src/cmd/pprof/internal/report/source_html.go
@@ -0,0 +1,77 @@
+// 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 report
+
+const weblistPageHeader = `
+<!DOCTYPE html>
+<html>
+<head>
+<title>Pprof listing</title>
+<style type="text/css">
+body {
+font-family: sans-serif;
+}
+h1 {
+ font-size: 1.5em;
+ margin-bottom: 4px;
+}
+.legend {
+ font-size: 1.25em;
+}
+.line {
+color: #aaaaaa;
+}
+.nop {
+color: #aaaaaa;
+}
+.unimportant {
+color: #cccccc;
+}
+.disasmloc {
+color: #000000;
+}
+.deadsrc {
+cursor: pointer;
+}
+.deadsrc:hover {
+background-color: #eeeeee;
+}
+.livesrc {
+color: #0000ff;
+cursor: pointer;
+}
+.livesrc:hover {
+background-color: #eeeeee;
+}
+.asm {
+color: #008800;
+display: none;
+}
+</style>
+<script type="text/javascript">
+function pprof_toggle_asm(e) {
+ var target;
+ if (!e) e = window.event;
+ if (e.target) target = e.target;
+ else if (e.srcElement) target = e.srcElement;
+
+ if (target) {
+ var asm = target.nextSibling;
+ if (asm && asm.className == "asm") {
+ asm.style.display = (asm.style.display == "block" ? "" : "block");
+ e.preventDefault();
+ return false;
+ }
+ }
+}
+</script>
+</head>
+<body>
+`
+
+const weblistPageClosing = `
+</body>
+</html>
+`
diff --git a/src/cmd/pprof/internal/svg/svg.go b/src/cmd/pprof/internal/svg/svg.go
new file mode 100644
index 000000000..aa65a1a08
--- /dev/null
+++ b/src/cmd/pprof/internal/svg/svg.go
@@ -0,0 +1,75 @@
+// 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 svg provides tools related to handling of SVG files
+package svg
+
+import (
+ "bytes"
+ "regexp"
+ "strings"
+)
+
+var (
+ viewBox = regexp.MustCompile(`<svg\s*width="[^"]+"\s*height="[^"]+"\s*viewBox="[^"]+"`)
+ graphId = regexp.MustCompile(`<g id="graph\d"`)
+ svgClose = regexp.MustCompile(`</svg>`)
+)
+
+// Massage enhances the SVG output from DOT to provide bettern
+// panning inside a web browser. It uses the SVGPan library, which is
+// accessed through the svgPan URL.
+func Massage(in bytes.Buffer, svgPan string) string {
+ svg := string(in.Bytes())
+
+ // Work around for dot bug which misses quoting some ampersands,
+ // resulting on unparsable SVG.
+ svg = strings.Replace(svg, "&;", "&amp;;", -1)
+ if svgPan == "" {
+ return svg
+ }
+
+ //Dot's SVG output is
+ //
+ // <svg width="___" height="___"
+ // viewBox="___" xmlns=...>
+ // <g id="graph0" transform="...">
+ // ...
+ // </g>
+ // </svg>
+ //
+ // Change it to
+ //
+ // <svg width="100%" height="100%"
+ // xmlns=...>
+ // <script xlink:href=" ...$svgpan.. "/>
+
+ // <g id="viewport" transform="translate(0,0)">
+ // <g id="graph0" transform="...">
+ // ...
+ // </g>
+ // </g>
+ // </svg>
+
+ if loc := viewBox.FindStringIndex(svg); loc != nil {
+ svg = svg[:loc[0]] +
+ `<svg width="100%" height="100%"` +
+ svg[loc[1]:]
+ }
+
+ if loc := graphId.FindStringIndex(svg); loc != nil {
+ svg = svg[:loc[0]] +
+ `<script xlink:href="` + svgPan + `"/>` +
+ `<g id="viewport" transform="scale(0.5,0.5) translate(0,0)">` +
+ svg[loc[0]:]
+ }
+
+ if loc := svgClose.FindStringIndex(svg); loc != nil {
+ svg = svg[:loc[0]] +
+ `</g>` +
+ svg[loc[0]:]
+ }
+
+ return svg
+}
diff --git a/src/cmd/pprof/internal/symbolizer/symbolizer.go b/src/cmd/pprof/internal/symbolizer/symbolizer.go
new file mode 100644
index 000000000..86de5640d
--- /dev/null
+++ b/src/cmd/pprof/internal/symbolizer/symbolizer.go
@@ -0,0 +1,195 @@
+// 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 symbolizer provides a routine to populate a profile with
+// symbol, file and line number information. It relies on the
+// addr2liner and demangler packages to do the actual work.
+package symbolizer
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "cmd/pprof/internal/plugin"
+ "cmd/pprof/internal/profile"
+)
+
+// Symbolize adds symbol and line number information to all locations
+// in a profile. mode enables some options to control
+// symbolization. Currently only recognizes "force", which causes it
+// to overwrite any existing data.
+func Symbolize(mode string, prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI) error {
+ force := false
+ // Disable some mechanisms based on mode string.
+ for _, o := range strings.Split(strings.ToLower(mode), ":") {
+ switch o {
+ case "force":
+ force = true
+ default:
+ }
+ }
+
+ if len(prof.Mapping) == 0 {
+ return fmt.Errorf("no known mappings")
+ }
+
+ mt, err := newMapping(prof, obj, ui, force)
+ if err != nil {
+ return err
+ }
+ defer mt.close()
+
+ functions := make(map[profile.Function]*profile.Function)
+ for _, l := range mt.prof.Location {
+ m := l.Mapping
+ segment := mt.segments[m]
+ if segment == nil {
+ // Nothing to do
+ continue
+ }
+
+ stack, err := segment.SourceLine(l.Address)
+ if err != nil || len(stack) == 0 {
+ // No answers from addr2line
+ continue
+ }
+
+ l.Line = make([]profile.Line, len(stack))
+ for i, frame := range stack {
+ if frame.Func != "" {
+ m.HasFunctions = true
+ }
+ if frame.File != "" {
+ m.HasFilenames = true
+ }
+ if frame.Line != 0 {
+ m.HasLineNumbers = true
+ }
+ f := &profile.Function{
+ Name: frame.Func,
+ SystemName: frame.Func,
+ Filename: frame.File,
+ }
+ if fp := functions[*f]; fp != nil {
+ f = fp
+ } else {
+ functions[*f] = f
+ f.ID = uint64(len(mt.prof.Function)) + 1
+ mt.prof.Function = append(mt.prof.Function, f)
+ }
+ l.Line[i] = profile.Line{
+ Function: f,
+ Line: int64(frame.Line),
+ }
+ }
+
+ if len(stack) > 0 {
+ m.HasInlineFrames = true
+ }
+ }
+ return nil
+}
+
+// newMapping creates a mappingTable for a profile.
+func newMapping(prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI, force bool) (*mappingTable, error) {
+ mt := &mappingTable{
+ prof: prof,
+ segments: make(map[*profile.Mapping]plugin.ObjFile),
+ }
+
+ // Identify used mappings
+ mappings := make(map[*profile.Mapping]bool)
+ for _, l := range prof.Location {
+ mappings[l.Mapping] = true
+ }
+
+ for _, m := range prof.Mapping {
+ if !mappings[m] {
+ continue
+ }
+ // Do not attempt to re-symbolize a mapping that has already been symbolized.
+ if !force && (m.HasFunctions || m.HasFilenames || m.HasLineNumbers) {
+ continue
+ }
+
+ f, err := locateFile(obj, m.File, m.BuildID, m.Start)
+ if err != nil {
+ ui.PrintErr("Local symbolization failed for ", filepath.Base(m.File), ": ", err)
+ // Move on to other mappings
+ continue
+ }
+
+ if fid := f.BuildID(); m.BuildID != "" && fid != "" && fid != m.BuildID {
+ // Build ID mismatch - ignore.
+ f.Close()
+ continue
+ }
+
+ mt.segments[m] = f
+ }
+
+ return mt, nil
+}
+
+// locateFile opens a local file for symbolization on the search path
+// at $PPROF_BINARY_PATH. Looks inside these directories for files
+// named $BUILDID/$BASENAME and $BASENAME (if build id is available).
+func locateFile(obj plugin.ObjTool, file, buildID string, start uint64) (plugin.ObjFile, error) {
+ // Construct search path to examine
+ searchPath := os.Getenv("PPROF_BINARY_PATH")
+ if searchPath == "" {
+ // Use $HOME/pprof/binaries as default directory for local symbolization binaries
+ searchPath = filepath.Join(os.Getenv("HOME"), "pprof", "binaries")
+ }
+
+ // Collect names to search: {buildid/basename, basename}
+ var fileNames []string
+ if baseName := filepath.Base(file); buildID != "" {
+ fileNames = []string{filepath.Join(buildID, baseName), baseName}
+ } else {
+ fileNames = []string{baseName}
+ }
+ for _, path := range filepath.SplitList(searchPath) {
+ for nameIndex, name := range fileNames {
+ file := filepath.Join(path, name)
+ if f, err := obj.Open(file, start); err == nil {
+ fileBuildID := f.BuildID()
+ if buildID == "" || buildID == fileBuildID {
+ return f, nil
+ }
+ f.Close()
+ if nameIndex == 0 {
+ // If this is the first name, the path includes the build id. Report inconsistency.
+ return nil, fmt.Errorf("found file %s with inconsistent build id %s", file, fileBuildID)
+ }
+ }
+ }
+ }
+ // Try original file name
+ f, err := obj.Open(file, start)
+ if err == nil && buildID != "" {
+ if fileBuildID := f.BuildID(); fileBuildID != "" && fileBuildID != buildID {
+ // Mismatched build IDs, ignore
+ f.Close()
+ return nil, fmt.Errorf("mismatched build ids %s != %s", fileBuildID, buildID)
+ }
+ }
+ return f, err
+}
+
+// mappingTable contains the mechanisms for symbolization of a
+// profile.
+type mappingTable struct {
+ prof *profile.Profile
+ segments map[*profile.Mapping]plugin.ObjFile
+}
+
+// Close releases any external processes being used for the mapping.
+func (mt *mappingTable) close() {
+ for _, segment := range mt.segments {
+ segment.Close()
+ }
+}
diff --git a/src/cmd/pprof/internal/symbolz/symbolz.go b/src/cmd/pprof/internal/symbolz/symbolz.go
new file mode 100644
index 000000000..c81e52220
--- /dev/null
+++ b/src/cmd/pprof/internal/symbolz/symbolz.go
@@ -0,0 +1,111 @@
+// 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 symbolz symbolizes a profile using the output from the symbolz
+// service.
+package symbolz
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "net/url"
+ "regexp"
+ "strconv"
+ "strings"
+
+ "cmd/pprof/internal/profile"
+)
+
+var (
+ symbolzRE = regexp.MustCompile(`(0x[[:xdigit:]]+)\s+(.*)`)
+)
+
+// Symbolize symbolizes profile p by parsing data returned by a
+// symbolz handler. syms receives the symbolz query (hex addresses
+// separated by '+') and returns the symbolz output in a string. It
+// symbolizes all locations based on their addresses, regardless of
+// mapping.
+func Symbolize(source string, syms func(string, string) ([]byte, error), p *profile.Profile) error {
+ if source = symbolz(source, p); source == "" {
+ // If the source is not a recognizable URL, do nothing.
+ return nil
+ }
+
+ // Construct query of addresses to symbolize.
+ var a []string
+ for _, l := range p.Location {
+ if l.Address != 0 && len(l.Line) == 0 {
+ a = append(a, fmt.Sprintf("%#x", l.Address))
+ }
+ }
+
+ if len(a) == 0 {
+ // No addresses to symbolize.
+ return nil
+ }
+ lines := make(map[uint64]profile.Line)
+ functions := make(map[string]*profile.Function)
+ if b, err := syms(source, strings.Join(a, "+")); err == nil {
+ buf := bytes.NewBuffer(b)
+ for {
+ l, err := buf.ReadString('\n')
+
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return err
+ }
+
+ if symbol := symbolzRE.FindStringSubmatch(l); len(symbol) == 3 {
+ addr, err := strconv.ParseUint(symbol[1], 0, 64)
+ if err != nil {
+ return fmt.Errorf("unexpected parse failure %s: %v", symbol[1], err)
+ }
+
+ name := symbol[2]
+ fn := functions[name]
+ if fn == nil {
+ fn = &profile.Function{
+ ID: uint64(len(p.Function) + 1),
+ Name: name,
+ SystemName: name,
+ }
+ functions[name] = fn
+ p.Function = append(p.Function, fn)
+ }
+
+ lines[addr] = profile.Line{Function: fn}
+ }
+ }
+ }
+
+ for _, l := range p.Location {
+ if line, ok := lines[l.Address]; ok {
+ l.Line = []profile.Line{line}
+ if l.Mapping != nil {
+ l.Mapping.HasFunctions = true
+ }
+ }
+ }
+
+ return nil
+}
+
+// symbolz returns the corresponding symbolz source for a profile URL.
+func symbolz(source string, p *profile.Profile) string {
+ if url, err := url.Parse(source); err == nil && url.Host != "" {
+ if last := strings.LastIndex(url.Path, "/"); last != -1 {
+ if strings.HasSuffix(url.Path[:last], "pprof") {
+ url.Path = url.Path[:last] + "/symbol"
+ } else {
+ url.Path = url.Path[:last] + "/symbolz"
+ }
+ return url.String()
+ }
+ }
+
+ return ""
+}
diff --git a/src/cmd/pprof/internal/tempfile/tempfile.go b/src/cmd/pprof/internal/tempfile/tempfile.go
new file mode 100644
index 000000000..31c117690
--- /dev/null
+++ b/src/cmd/pprof/internal/tempfile/tempfile.go
@@ -0,0 +1,45 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package tempfile provides tools to create and delete temporary files
+package tempfile
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "sync"
+)
+
+// New returns an unused filename for output files.
+func New(dir, prefix, suffix string) (*os.File, error) {
+ for index := 1; index < 10000; index++ {
+ path := filepath.Join(dir, fmt.Sprintf("%s%03d%s", prefix, index, suffix))
+ if _, err := os.Stat(path); err != nil {
+ return os.Create(path)
+ }
+ }
+ // Give up
+ return nil, fmt.Errorf("could not create file of the form %s%03d%s", prefix, 1, suffix)
+}
+
+var tempFiles []string
+var tempFilesMu = sync.Mutex{}
+
+// DeferDelete marks a file to be deleted by next call to Cleanup()
+func DeferDelete(path string) {
+ tempFilesMu.Lock()
+ tempFiles = append(tempFiles, path)
+ tempFilesMu.Unlock()
+}
+
+// Cleanup removes any temporary files selected for deferred cleaning.
+func Cleanup() {
+ tempFilesMu.Lock()
+ for _, f := range tempFiles {
+ os.Remove(f)
+ }
+ tempFiles = nil
+ tempFilesMu.Unlock()
+}
diff --git a/src/cmd/pprof/pprof.go b/src/cmd/pprof/pprof.go
new file mode 100644
index 000000000..44f4f6cb7
--- /dev/null
+++ b/src/cmd/pprof/pprof.go
@@ -0,0 +1,237 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "debug/gosym"
+ "flag"
+ "fmt"
+ "os"
+ "regexp"
+ "strings"
+ "sync"
+
+ "cmd/internal/objfile"
+ "cmd/pprof/internal/commands"
+ "cmd/pprof/internal/driver"
+ "cmd/pprof/internal/fetch"
+ "cmd/pprof/internal/plugin"
+ "cmd/pprof/internal/profile"
+ "cmd/pprof/internal/symbolizer"
+ "cmd/pprof/internal/symbolz"
+)
+
+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)
+ }
+}
+
+// symbolize attempts to symbolize profile p.
+// If the source is a local binary, it tries using symbolizer and obj.
+// If the source is a URL, it fetches symbol information using symbolz.
+func symbolize(mode, source string, p *profile.Profile, obj plugin.ObjTool, ui plugin.UI) error {
+ remote, local := true, true
+ for _, o := range strings.Split(strings.ToLower(mode), ":") {
+ switch o {
+ case "none", "no":
+ return nil
+ case "local":
+ remote, local = false, true
+ case "remote":
+ remote, local = true, false
+ default:
+ ui.PrintErr("ignoring unrecognized symbolization option: " + mode)
+ ui.PrintErr("expecting -symbolize=[local|remote|none][:force]")
+ fallthrough
+ case "", "force":
+ // Ignore these options, -force is recognized by symbolizer.Symbolize
+ }
+ }
+
+ var err error
+ if local {
+ // Symbolize using binutils.
+ if err = symbolizer.Symbolize(mode, p, obj, ui); err == nil {
+ return nil
+ }
+ }
+ if remote {
+ err = symbolz.Symbolize(source, fetch.PostURL, p)
+ }
+ return err
+}
+
+// flags implements the driver.FlagPackage interface using the builtin flag package.
+type flags struct {
+}
+
+func (flags) Bool(o string, d bool, c string) *bool {
+ return flag.Bool(o, d, c)
+}
+
+func (flags) Int(o string, d int, c string) *int {
+ return flag.Int(o, d, c)
+}
+
+func (flags) Float64(o string, d float64, c string) *float64 {
+ return flag.Float64(o, d, c)
+}
+
+func (flags) String(o, d, c string) *string {
+ return flag.String(o, d, c)
+}
+
+func (flags) Parse(usage func()) []string {
+ flag.Usage = usage
+ flag.Parse()
+ args := flag.Args()
+ if len(args) == 0 {
+ usage()
+ }
+ return args
+}
+
+func (flags) ExtraUsage() string {
+ return ""
+}
+
+// objTool implements plugin.ObjTool using Go libraries
+// (instead of invoking GNU binutils).
+type objTool struct {
+ mu sync.Mutex
+ disasmCache map[string]*objfile.Disasm
+}
+
+func (*objTool) Open(name string, start uint64) (plugin.ObjFile, error) {
+ of, err := objfile.Open(name)
+ if err != nil {
+ return nil, err
+ }
+ f := &file{
+ name: name,
+ file: of,
+ }
+ return f, nil
+}
+
+func (*objTool) Demangle(names []string) (map[string]string, error) {
+ // No C++, nothing to demangle.
+ return make(map[string]string), nil
+}
+
+func (t *objTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
+ d, err := t.cachedDisasm(file)
+ if err != nil {
+ return nil, err
+ }
+ var asm []plugin.Inst
+ d.Decode(start, end, func(pc, size uint64, file string, line int, text string) {
+ asm = append(asm, plugin.Inst{Addr: pc, File: file, Line: line, Text: text})
+ })
+ return asm, nil
+}
+
+func (t *objTool) cachedDisasm(file string) (*objfile.Disasm, error) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.disasmCache == nil {
+ t.disasmCache = make(map[string]*objfile.Disasm)
+ }
+ d := t.disasmCache[file]
+ if d != nil {
+ return d, nil
+ }
+ f, err := objfile.Open(file)
+ if err != nil {
+ return nil, err
+ }
+ d, err = f.Disasm()
+ f.Close()
+ if err != nil {
+ return nil, err
+ }
+ t.disasmCache[file] = d
+ return d, nil
+}
+
+func (*objTool) SetConfig(config string) {
+ // config is usually used to say what binaries to invoke.
+ // Ignore entirely.
+}
+
+// file implements plugin.ObjFile using Go libraries
+// (instead of invoking GNU binutils).
+// A file represents a single executable being analyzed.
+type file struct {
+ name string
+ sym []objfile.Sym
+ file *objfile.File
+ pcln *gosym.Table
+}
+
+func (f *file) Name() string {
+ return f.name
+}
+
+func (f *file) Base() uint64 {
+ // No support for shared libraries.
+ return 0
+}
+
+func (f *file) BuildID() string {
+ // No support for build ID.
+ return ""
+}
+
+func (f *file) SourceLine(addr uint64) ([]plugin.Frame, error) {
+ if f.pcln == nil {
+ pcln, err := f.file.PCLineTable()
+ if err != nil {
+ return nil, err
+ }
+ f.pcln = pcln
+ }
+ file, line, fn := f.pcln.PCToLine(addr)
+ if fn == nil {
+ return nil, fmt.Errorf("no line information for PC=%#x", addr)
+ }
+ frame := []plugin.Frame{
+ {
+ Func: fn.Name,
+ File: file,
+ Line: line,
+ },
+ }
+ return frame, nil
+}
+
+func (f *file) Symbols(r *regexp.Regexp, addr uint64) ([]*plugin.Sym, error) {
+ if f.sym == nil {
+ sym, err := f.file.Symbols()
+ if err != nil {
+ return nil, err
+ }
+ f.sym = sym
+ }
+ var out []*plugin.Sym
+ for _, s := range f.sym {
+ if (r == nil || r.MatchString(s.Name)) && (addr == 0 || s.Addr <= addr && addr < s.Addr+uint64(s.Size)) {
+ out = append(out, &plugin.Sym{
+ Name: []string{s.Name},
+ File: f.name,
+ Start: s.Addr,
+ End: s.Addr + uint64(s.Size) - 1,
+ })
+ }
+ }
+ return out, nil
+}
+
+func (f *file) Close() error {
+ f.file.Close()
+ return nil
+}
diff --git a/src/cmd/yacc/Makefile b/src/cmd/yacc/Makefile
deleted file mode 100644
index f8c8169bd..000000000
--- a/src/cmd/yacc/Makefile
+++ /dev/null
@@ -1,12 +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.
-
-TARG=expr$(shell go env GOEXE)
-
-$(TARG): yacc.go expr.y
- go run yacc.go -p expr expr.y
- go build -o $(TARG) y.go
-
-clean:
- rm -f y.go y.output $(TARG)
diff --git a/src/cmd/yacc/doc.go b/src/cmd/yacc/doc.go
index ceaaf2448..702c9f0d2 100644
--- a/src/cmd/yacc/doc.go
+++ b/src/cmd/yacc/doc.go
@@ -20,8 +20,9 @@ written in C and documented at
Adepts of the original yacc will have no trouble adapting to this
form of the tool.
-The file expr.y in this directory is a yacc grammar for a very simple
-expression parser. It needs the flag "-p expr" (see below).
+The directory $GOROOT/cmd/yacc/testdata/expr is a yacc program
+for a very simple expression parser. See expr.y and main.go in that
+directory for examples of how to write and build yacc programs.
The generated parser is reentrant. Parse expects to be given an
argument that conforms to the following interface:
diff --git a/src/cmd/yacc/testdata/expr/README b/src/cmd/yacc/testdata/expr/README
new file mode 100644
index 000000000..302ef57a7
--- /dev/null
+++ b/src/cmd/yacc/testdata/expr/README
@@ -0,0 +1,20 @@
+This directory contains a simple program demonstrating how to use
+the Go version of yacc.
+
+To build it:
+
+ $ go generate
+ $ go build
+
+or
+
+ $ go generate
+ $ go run expr.go
+
+The file main.go contains the "go generate" command to run yacc to
+create expr.go from expr.y. It also has the package doc comment,
+as godoc will not scan the .y file.
+
+The actual implementation is in expr.y.
+
+The program is not installed in the binary distributions of Go.
diff --git a/src/cmd/yacc/expr.y b/src/cmd/yacc/testdata/expr/expr.y
index 77e9259da..721b1c917 100644
--- a/src/cmd/yacc/expr.y
+++ b/src/cmd/yacc/testdata/expr/expr.y
@@ -11,11 +11,6 @@
%{
-// This tag will be copied to the generated file to prevent that file
-// confusing a future build.
-
-// +build ignore
-
package main
import (
@@ -37,6 +32,8 @@ import (
%type <num> expr expr1 expr2 expr3
+%token '+' '-' '*' '/' '(' ')'
+
%token <num> NUM
%%
diff --git a/src/cmd/yacc/testdata/expr/main.go b/src/cmd/yacc/testdata/expr/main.go
new file mode 100644
index 000000000..8d5b6911f
--- /dev/null
+++ b/src/cmd/yacc/testdata/expr/main.go
@@ -0,0 +1,15 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file holds the go generate command to run yacc on the grammar in expr.y.
+// To build expr:
+// % go generate
+// % go build
+
+//go:generate -command yacc go tool yacc
+//go:generate yacc -o expr.go -p "expr" expr.y
+
+// Expr is a simple expression evaluator that serves as a working example of
+// how to use Go's yacc implemenation.
+package main
diff --git a/src/cmd/yacc/yacc.go b/src/cmd/yacc/yacc.go
index c53403266..4dba376fc 100644
--- a/src/cmd/yacc/yacc.go
+++ b/src/cmd/yacc/yacc.go
@@ -52,9 +52,9 @@ import (
"go/format"
"io/ioutil"
"os"
+ "strconv"
"strings"
"unicode"
- "unicode/utf8"
)
// the following are adjustable
@@ -195,8 +195,9 @@ type Item struct {
}
type Symb struct {
- name string
- value int
+ name string
+ noconst bool
+ value int
}
type Wset struct {
@@ -509,8 +510,7 @@ outer:
// put out non-literal terminals
for i := TOKSTART; i <= ntokens; i++ {
// non-literals
- c := tokset[i].name[0]
- if c != ' ' && c != '$' {
+ if !tokset[i].noconst {
fmt.Fprintf(ftable, "const %v = %v\n", tokset[i].name, tokset[i].value)
}
}
@@ -734,7 +734,7 @@ func defin(nt int, s string) int {
copy(anontrst, nontrst)
nontrst = anontrst
}
- nontrst[nnonter] = Symb{s, 0}
+ nontrst[nnonter] = Symb{name: s}
return NTBASE + nnonter
}
@@ -756,70 +756,26 @@ func defin(nt int, s string) int {
// establish value for token
// single character literal
- if s[0] == ' ' {
- s = s[1:]
- r, size := utf8.DecodeRuneInString(s)
- if r == utf8.RuneError && size == 1 {
- errorf("invalid UTF-8 sequence %q", s)
- }
- val = int(r)
- if val == '\\' { // escape sequence
- switch {
- case len(s) == 2:
- // single character escape sequence
- switch s[1] {
- case '\'':
- val = '\''
- case '"':
- val = '"'
- case '\\':
- val = '\\'
- case 'a':
- val = '\a'
- case 'b':
- val = '\b'
- case 'f':
- val = '\f'
- case 'n':
- val = '\n'
- case 'r':
- val = '\r'
- case 't':
- val = '\t'
- case 'v':
- val = '\v'
- default:
- errorf("invalid escape %s", s)
- }
- case s[1] == 'u' && len(s) == 2+4, // \unnnn sequence
- s[1] == 'U' && len(s) == 2+8: // \Unnnnnnnn sequence
- val = 0
- s = s[2:]
- for s != "" {
- c := int(s[0])
- switch {
- case c >= '0' && c <= '9':
- c -= '0'
- case c >= 'a' && c <= 'f':
- c -= 'a' - 10
- case c >= 'A' && c <= 'F':
- c -= 'A' - 10
- default:
- errorf(`illegal \u or \U construction`)
- }
- val = val*16 + c
- s = s[1:]
- }
- default:
- errorf("invalid escape %s", s)
- }
+ if s[0] == '\'' || s[0] == '"' {
+ q, err := strconv.Unquote(s)
+ if err != nil {
+ errorf("invalid token: %s", err)
+ }
+ rq := []rune(q)
+ if len(rq) != 1 {
+ errorf("character token too long: %s", s)
}
+ val = int(rq[0])
if val == 0 {
errorf("token value 0 is illegal")
}
+ tokset[ntokens].noconst = true
} else {
val = extval
extval++
+ if s[0] == '$' {
+ tokset[ntokens].noconst = true
+ }
}
tokset[ntokens].value = val
@@ -896,7 +852,7 @@ func gettok() int {
case '"', '\'':
match = c
- tokname = " "
+ tokname = string(c)
for {
c = getrune(finput)
if c == '\n' || c == EOF {
@@ -909,6 +865,7 @@ func gettok() int {
if tokflag {
fmt.Printf(">>> IDENTIFIER \"%v\" %v\n", tokname, lineno)
}
+ tokname += string(c)
return IDENTIFIER
}
tokname += string(c)
@@ -1029,7 +986,7 @@ func fdtype(t int) int {
}
func chfind(t int, s string) int {
- if s[0] == ' ' {
+ if s[0] == '"' || s[0] == '\'' {
t = 0
}
for i := 0; i <= ntokens; i++ {
@@ -1516,9 +1473,6 @@ func symnam(i int) string {
} else {
s = tokset[i].name
}
- if s[0] == ' ' {
- s = s[1:]
- }
return s
}
diff --git a/src/pkg/compress/bzip2/bit_reader.go b/src/compress/bzip2/bit_reader.go
index 32d1036ae..32d1036ae 100644
--- a/src/pkg/compress/bzip2/bit_reader.go
+++ b/src/compress/bzip2/bit_reader.go
diff --git a/src/pkg/compress/bzip2/bzip2.go b/src/compress/bzip2/bzip2.go
index 82e30c7c9..15575d220 100644
--- a/src/pkg/compress/bzip2/bzip2.go
+++ b/src/compress/bzip2/bzip2.go
@@ -42,6 +42,8 @@ type reader struct {
}
// NewReader returns an io.Reader which decompresses bzip2 data from r.
+// If r does not also implement io.ByteReader,
+// the decompressor may read more data than necessary from r.
func NewReader(r io.Reader) io.Reader {
bz2 := new(reader)
bz2.br = newBitReader(r)
@@ -261,6 +263,11 @@ func (bz2 *reader) readBlock() (err error) {
}
}
+ if numSymbols == 0 {
+ // There must be an EOF symbol.
+ return StructuralError("no symbols in input")
+ }
+
// A block uses between two and six different Huffman trees.
numHuffmanTrees := br.ReadBits(3)
if numHuffmanTrees < 2 || numHuffmanTrees > 6 {
@@ -307,10 +314,10 @@ func (bz2 *reader) readBlock() (err error) {
// Now we decode the arrays of code-lengths for each tree.
lengths := make([]uint8, numSymbols)
- for i := 0; i < numHuffmanTrees; i++ {
+ for i := range huffmanTrees {
// The code lengths are delta encoded from a 5-bit base value.
length := br.ReadBits(5)
- for j := 0; j < numSymbols; j++ {
+ for j := range lengths {
for {
if !br.ReadBit() {
break
@@ -333,6 +340,12 @@ func (bz2 *reader) readBlock() (err error) {
}
selectorIndex := 1 // the next tree index to use
+ if len(treeIndexes) == 0 {
+ return StructuralError("no tree selectors given")
+ }
+ if int(treeIndexes[0]) >= len(huffmanTrees) {
+ return StructuralError("tree selector out of range")
+ }
currentHuffmanTree := huffmanTrees[treeIndexes[0]]
bufIndex := 0 // indexes bz2.buf, the output buffer.
// The output of the move-to-front transform is run-length encoded and
@@ -350,6 +363,12 @@ func (bz2 *reader) readBlock() (err error) {
decoded := 0 // counts the number of symbols decoded by the current tree.
for {
if decoded == 50 {
+ if selectorIndex >= numSelectors {
+ return StructuralError("insufficient selector indices for number of symbols")
+ }
+ if int(treeIndexes[selectorIndex]) >= len(huffmanTrees) {
+ return StructuralError("tree selector out of range")
+ }
currentHuffmanTree = huffmanTrees[treeIndexes[selectorIndex]]
selectorIndex++
decoded = 0
diff --git a/src/pkg/compress/bzip2/bzip2_test.go b/src/compress/bzip2/bzip2_test.go
index 727249dc4..fb79d089e 100644
--- a/src/pkg/compress/bzip2/bzip2_test.go
+++ b/src/compress/bzip2/bzip2_test.go
@@ -208,6 +208,52 @@ func TestBufferOverrun(t *testing.T) {
ioutil.ReadAll(decompressor)
}
+func TestOutOfRangeSelector(t *testing.T) {
+ // Tests https://code.google.com/p/go/issues/detail?id=8363.
+ buffer := bytes.NewReader(outOfRangeSelector)
+ decompressor := NewReader(buffer)
+ // This shouldn't panic.
+ ioutil.ReadAll(decompressor)
+}
+
+func TestMTF(t *testing.T) {
+ mtf := newMTFDecoderWithRange(5)
+
+ // 0 1 2 3 4
+ expect := byte(1)
+ x := mtf.Decode(1)
+ if x != expect {
+ t.Errorf("expected %v, got %v", expect, x)
+ }
+
+ // 1 0 2 3 4
+ x = mtf.Decode(0)
+ if x != expect {
+ t.Errorf("expected %v, got %v", expect, x)
+ }
+
+ // 1 0 2 3 4
+ expect = byte(0)
+ x = mtf.Decode(1)
+ if x != expect {
+ t.Errorf("expected %v, got %v", expect, x)
+ }
+
+ // 0 1 2 3 4
+ expect = byte(4)
+ x = mtf.Decode(4)
+ if x != expect {
+ t.Errorf("expected %v, got %v", expect, x)
+ }
+
+ // 4 0 1 2 3
+ expect = byte(0)
+ x = mtf.Decode(1)
+ if x != expect {
+ t.Errorf("expected %v, got %v", expect, x)
+ }
+}
+
var bufferOverrunBase64 string = `
QlpoNTFBWSZTWTzyiGcACMP/////////////////////////////////3/7f3///
////4N/fCZODak2Xo44GIHZgkGzDRbFAuwAAKoFV7T6AO6qwA6APb6s2rOoAkAAD
@@ -361,3 +407,13 @@ O0A8s/iua5oFdNZTWvbVI4FUH9sKcLiB3/fIAF+sB4n8q6L+UCfmbPcAo/crQ6b3
HqhDBMY9J0q/jdz9GNYZ/1fbXdkUqAQKFePhtzJDRBZba27+LPQNMCcrHMq06F1T
4QmLmkHt7LxB2pAczUO+T2O9bHEw/HWw+dYf2MoRDUw=
`
+
+var outOfRangeSelector = []byte{
+ 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26,
+ 0x53, 0x59, 0x4e, 0xec, 0xe8, 0x36, 0x00, 0x00,
+ 0x02, 0x51, 0x80, 0x00, 0x10, 0x40, 0x00, 0x06,
+ 0x44, 0x90, 0x80, 0x20, 0x00, 0x31, 0x06, 0x4c,
+ 0x41, 0x01, 0xa7, 0xa9, 0xa5, 0x80, 0xbb, 0x94,
+ 0x31, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0x00,
+ 0x00, 0x00, 0x00,
+}
diff --git a/src/pkg/compress/bzip2/huffman.go b/src/compress/bzip2/huffman.go
index 75a6223d8..75a6223d8 100644
--- a/src/pkg/compress/bzip2/huffman.go
+++ b/src/compress/bzip2/huffman.go
diff --git a/src/compress/bzip2/move_to_front.go b/src/compress/bzip2/move_to_front.go
new file mode 100644
index 000000000..526dfb34c
--- /dev/null
+++ b/src/compress/bzip2/move_to_front.go
@@ -0,0 +1,53 @@
+// 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 bzip2
+
+// moveToFrontDecoder implements a move-to-front list. Such a list is an
+// efficient way to transform a string with repeating elements into one with
+// many small valued numbers, which is suitable for entropy encoding. It works
+// by starting with an initial list of symbols and references symbols by their
+// index into that list. When a symbol is referenced, it's moved to the front
+// of the list. Thus, a repeated symbol ends up being encoded with many zeros,
+// as the symbol will be at the front of the list after the first access.
+type moveToFrontDecoder []byte
+
+// newMTFDecoder creates a move-to-front decoder with an explicit initial list
+// of symbols.
+func newMTFDecoder(symbols []byte) moveToFrontDecoder {
+ if len(symbols) > 256 {
+ panic("too many symbols")
+ }
+ return moveToFrontDecoder(symbols)
+}
+
+// newMTFDecoderWithRange creates a move-to-front decoder with an initial
+// symbol list of 0...n-1.
+func newMTFDecoderWithRange(n int) moveToFrontDecoder {
+ if n > 256 {
+ panic("newMTFDecoderWithRange: cannot have > 256 symbols")
+ }
+
+ m := make([]byte, n)
+ for i := 0; i < n; i++ {
+ m[i] = byte(i)
+ }
+ return moveToFrontDecoder(m)
+}
+
+func (m moveToFrontDecoder) Decode(n int) (b byte) {
+ // Implement move-to-front with a simple copy. This approach
+ // beats more sophisticated approaches in benchmarking, probably
+ // because it has high locality of reference inside of a
+ // single cache line (most move-to-front operations have n < 64).
+ b = m[n]
+ copy(m[1:], m[:n])
+ m[0] = b
+ return
+}
+
+// First returns the symbol at the front of the list.
+func (m moveToFrontDecoder) First() byte {
+ return m[0]
+}
diff --git a/src/pkg/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 b/src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2
index 0bd61a6d4..0bd61a6d4 100644
--- a/src/pkg/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2
+++ b/src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2
Binary files differ
diff --git a/src/pkg/compress/bzip2/testdata/e.txt.bz2 b/src/compress/bzip2/testdata/e.txt.bz2
index 65bf3b4c3..65bf3b4c3 100644
--- a/src/pkg/compress/bzip2/testdata/e.txt.bz2
+++ b/src/compress/bzip2/testdata/e.txt.bz2
Binary files differ
diff --git a/src/pkg/compress/flate/copy.go b/src/compress/flate/copy.go
index a3200a8f4..a3200a8f4 100644
--- a/src/pkg/compress/flate/copy.go
+++ b/src/compress/flate/copy.go
diff --git a/src/pkg/compress/flate/copy_test.go b/src/compress/flate/copy_test.go
index 2011b1547..2011b1547 100644
--- a/src/pkg/compress/flate/copy_test.go
+++ b/src/compress/flate/copy_test.go
diff --git a/src/pkg/compress/flate/deflate.go b/src/compress/flate/deflate.go
index 8c79df0c6..8c79df0c6 100644
--- a/src/pkg/compress/flate/deflate.go
+++ b/src/compress/flate/deflate.go
diff --git a/src/pkg/compress/flate/deflate_test.go b/src/compress/flate/deflate_test.go
index 730234c38..730234c38 100644
--- a/src/pkg/compress/flate/deflate_test.go
+++ b/src/compress/flate/deflate_test.go
diff --git a/src/pkg/compress/flate/fixedhuff.go b/src/compress/flate/fixedhuff.go
index 9be3d5349..7df8b9a29 100644
--- a/src/pkg/compress/flate/fixedhuff.go
+++ b/src/compress/flate/fixedhuff.go
@@ -4,7 +4,7 @@
package flate
-// autogenerated by gen.go, DO NOT EDIT
+// autogenerated by go run gen.go -output fixedhuff.go, DO NOT EDIT
var fixedHuffmanDecoder = huffmanDecoder{
7,
diff --git a/src/pkg/compress/flate/flate_test.go b/src/compress/flate/flate_test.go
index 068766323..068766323 100644
--- a/src/pkg/compress/flate/flate_test.go
+++ b/src/compress/flate/flate_test.go
diff --git a/src/pkg/compress/flate/gen.go b/src/compress/flate/gen.go
index 1427557f8..6288ecddd 100644
--- a/src/pkg/compress/flate/gen.go
+++ b/src/compress/flate/gen.go
@@ -7,14 +7,21 @@
// This program generates fixedhuff.go
// Invoke as
//
-// go run gen.go |gofmt >fixedhuff.go
+// 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
@@ -113,6 +120,8 @@ func (h *huffmanDecoder) init(bits []int) bool {
}
func main() {
+ flag.Parse()
+
var h huffmanDecoder
var bits [288]int
initReverseByte()
@@ -129,27 +138,43 @@ func main() {
bits[i] = 8
}
h.init(bits[:])
- fmt.Println("package flate")
- fmt.Println()
- fmt.Println("// autogenerated by gen.go, DO NOT EDIT")
- fmt.Println()
- fmt.Println("var fixedHuffmanDecoder = huffmanDecoder{")
- fmt.Printf("\t%d,\n", h.min)
- fmt.Println("\t[huffmanNumChunks]uint32{")
+
+ 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.Printf("\t\t")
+ fmt.Fprintf(&buf, "\t\t")
} else {
- fmt.Printf(" ")
+ fmt.Fprintf(&buf, " ")
}
- fmt.Printf("0x%04x,", h.chunks[i])
+ fmt.Fprintf(&buf, "0x%04x,", h.chunks[i])
if i&7 == 7 {
- fmt.Println()
+ fmt.Fprintln(&buf)
}
}
- fmt.Println("\t},")
- fmt.Println("\tnil, 0,")
- fmt.Println("}")
+ 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
diff --git a/src/pkg/compress/flate/huffman_bit_writer.go b/src/compress/flate/huffman_bit_writer.go
index b182a710b..b182a710b 100644
--- a/src/pkg/compress/flate/huffman_bit_writer.go
+++ b/src/compress/flate/huffman_bit_writer.go
diff --git a/src/pkg/compress/flate/huffman_code.go b/src/compress/flate/huffman_code.go
index 3b9fce466..3b9fce466 100644
--- a/src/pkg/compress/flate/huffman_code.go
+++ b/src/compress/flate/huffman_code.go
diff --git a/src/pkg/compress/flate/inflate.go b/src/compress/flate/inflate.go
index ce4923eca..76519bbf4 100644
--- a/src/pkg/compress/flate/inflate.go
+++ b/src/compress/flate/inflate.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.
+//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.
@@ -54,6 +56,15 @@ func (e *WriteError) Error() string {
return "flate: write error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error()
}
+// Resetter resets a ReadCloser returned by NewReader or NewReaderDict to
+// to switch to a new underlying Reader. This permits reusing a ReadCloser
+// instead of allocating a new one.
+type Resetter interface {
+ // Reset discards any buffered data and resets the Resetter as if it was
+ // newly initialized with the given reader.
+ 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.
@@ -677,10 +688,28 @@ func makeReader(r io.Reader) Reader {
return bufio.NewReader(r)
}
+func (f *decompressor) Reset(r io.Reader, dict []byte) error {
+ *f = decompressor{
+ r: makeReader(r),
+ bits: f.bits,
+ codebits: f.codebits,
+ hist: f.hist,
+ step: (*decompressor).nextBlock,
+ }
+ if dict != nil {
+ f.setDict(dict)
+ }
+ return nil
+}
+
// NewReader returns a new ReadCloser that can be used
-// to read the uncompressed version of r. It is the caller's
-// responsibility to call Close on the ReadCloser when
-// finished reading.
+// to read the uncompressed version of r.
+// 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 ReadCloser
+// when finished reading.
+//
+// The ReadCloser returned by NewReader also implements Resetter.
func NewReader(r io.Reader) io.ReadCloser {
var f decompressor
f.bits = new([maxLit + maxDist]int)
@@ -696,6 +725,8 @@ func NewReader(r io.Reader) io.ReadCloser {
// the uncompressed data stream started with the given dictionary,
// which has already been read. NewReaderDict is typically used
// to read data compressed by NewWriterDict.
+//
+// The ReadCloser returned by NewReader also implements Resetter.
func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser {
var f decompressor
f.r = makeReader(r)
diff --git a/src/compress/flate/inflate_test.go b/src/compress/flate/inflate_test.go
new file mode 100644
index 000000000..9f25d30b3
--- /dev/null
+++ b/src/compress/flate/inflate_test.go
@@ -0,0 +1,39 @@
+// 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 flate
+
+import (
+ "bytes"
+ "io"
+ "testing"
+)
+
+func TestReset(t *testing.T) {
+ ss := []string{
+ "lorem ipsum izzle fo rizzle",
+ "the quick brown fox jumped over",
+ }
+
+ deflated := make([]bytes.Buffer, 2)
+ for i, s := range ss {
+ w, _ := NewWriter(&deflated[i], 1)
+ w.Write([]byte(s))
+ w.Close()
+ }
+
+ inflated := make([]bytes.Buffer, 2)
+
+ f := NewReader(&deflated[0])
+ io.Copy(&inflated[0], f)
+ f.(Resetter).Reset(&deflated[1], nil)
+ io.Copy(&inflated[1], f)
+ f.Close()
+
+ for i, s := range ss {
+ if s != inflated[i].String() {
+ t.Errorf("inflated[%d]:\ngot %q\nwant %q", i, inflated[i], s)
+ }
+ }
+}
diff --git a/src/pkg/compress/flate/reader_test.go b/src/compress/flate/reader_test.go
index a62ef741d..a62ef741d 100644
--- a/src/pkg/compress/flate/reader_test.go
+++ b/src/compress/flate/reader_test.go
diff --git a/src/pkg/compress/flate/reverse_bits.go b/src/compress/flate/reverse_bits.go
index c1a02720d..c1a02720d 100644
--- a/src/pkg/compress/flate/reverse_bits.go
+++ b/src/compress/flate/reverse_bits.go
diff --git a/src/pkg/compress/flate/token.go b/src/compress/flate/token.go
index 4d4917687..4d4917687 100644
--- a/src/pkg/compress/flate/token.go
+++ b/src/compress/flate/token.go
diff --git a/src/pkg/compress/flate/writer_test.go b/src/compress/flate/writer_test.go
index 58431774e..58431774e 100644
--- a/src/pkg/compress/flate/writer_test.go
+++ b/src/compress/flate/writer_test.go
diff --git a/src/pkg/compress/gzip/gunzip.go b/src/compress/gzip/gunzip.go
index 4f398b194..72ee55c4f 100644
--- a/src/pkg/compress/gzip/gunzip.go
+++ b/src/compress/gzip/gunzip.go
@@ -74,14 +74,17 @@ type Reader struct {
flg byte
buf [512]byte
err error
+ multistream bool
}
// NewReader creates a new Reader reading the given reader.
-// The implementation buffers input and may read more data than necessary from r.
+// 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.
func NewReader(r io.Reader) (*Reader, error) {
z := new(Reader)
z.r = makeReader(r)
+ z.multistream = true
z.digest = crc32.NewIEEE()
if err := z.readHeader(true); err != nil {
return nil, err
@@ -101,9 +104,30 @@ func (z *Reader) Reset(r io.Reader) error {
}
z.size = 0
z.err = nil
+ z.multistream = true
return z.readHeader(true)
}
+// Multistream controls whether the reader supports multistream files.
+//
+// If enabled (the default), the Reader expects the input to be a sequence
+// of individually gzipped data streams, each with its own header and
+// trailer, ending at EOF. The effect is that the concatenation of a sequence
+// of gzipped files is treated as equivalent to the gzip of the concatenation
+// of the sequence. This is standard behavior for gzip readers.
+//
+// Calling Multistream(false) disables this behavior; disabling the behavior
+// can be useful when reading file formats that distinguish individual gzip
+// data streams or mix gzip data streams with other data streams.
+// In this mode, when the Reader reaches the end of the data stream,
+// Read returns io.EOF. If the underlying reader implements io.ByteReader,
+// it will be left positioned just after the gzip stream.
+// To start the next stream, call z.Reset(r) followed by z.Multistream(false).
+// If there is no next stream, z.Reset(r) will return io.EOF.
+func (z *Reader) Multistream(ok bool) {
+ z.multistream = ok
+}
+
// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
func get4(p []byte) uint32 {
return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
@@ -207,7 +231,11 @@ func (z *Reader) readHeader(save bool) error {
}
z.digest.Reset()
- z.decompressor = flate.NewReader(z.r)
+ if z.decompressor == nil {
+ z.decompressor = flate.NewReader(z.r)
+ } else {
+ z.decompressor.(flate.Resetter).Reset(z.r, nil)
+ }
return nil
}
@@ -240,6 +268,10 @@ func (z *Reader) Read(p []byte) (n int, err error) {
}
// File is ok; is there another?
+ if !z.multistream {
+ return 0, io.EOF
+ }
+
if err = z.readHeader(false); err != nil {
z.err = err
return
diff --git a/src/pkg/compress/gzip/gunzip_test.go b/src/compress/gzip/gunzip_test.go
index 2471038f5..0636dec9a 100644
--- a/src/pkg/compress/gzip/gunzip_test.go
+++ b/src/compress/gzip/gunzip_test.go
@@ -9,6 +9,7 @@ import (
"io"
"io/ioutil"
"os"
+ "strings"
"testing"
"time"
)
@@ -367,3 +368,43 @@ func TestInitialReset(t *testing.T) {
t.Errorf("got %q want %q", s, gunzipTests[1].raw)
}
}
+
+func TestMultistreamFalse(t *testing.T) {
+ // Find concatenation test.
+ var tt gunzipTest
+ for _, tt = range gunzipTests {
+ if strings.HasSuffix(tt.desc, " x2") {
+ goto Found
+ }
+ }
+ t.Fatal("cannot find hello.txt x2 in gunzip tests")
+
+Found:
+ br := bytes.NewReader(tt.gzip)
+ var r Reader
+ if err := r.Reset(br); err != nil {
+ t.Fatalf("first reset: %v", err)
+ }
+
+ // Expect two streams with "hello world\n", then real EOF.
+ const hello = "hello world\n"
+
+ r.Multistream(false)
+ data, err := ioutil.ReadAll(&r)
+ if string(data) != hello || err != nil {
+ t.Fatalf("first stream = %q, %v, want %q, %v", string(data), err, hello, nil)
+ }
+
+ if err := r.Reset(br); err != nil {
+ t.Fatalf("second reset: %v", err)
+ }
+ r.Multistream(false)
+ data, err = ioutil.ReadAll(&r)
+ if string(data) != hello || err != nil {
+ t.Fatalf("second stream = %q, %v, want %q, %v", string(data), err, hello, nil)
+ }
+
+ if err := r.Reset(br); err != io.EOF {
+ t.Fatalf("third reset: err=%v, want io.EOF", err)
+ }
+}
diff --git a/src/pkg/compress/gzip/gzip.go b/src/compress/gzip/gzip.go
index 5131d128e..5131d128e 100644
--- a/src/pkg/compress/gzip/gzip.go
+++ b/src/compress/gzip/gzip.go
diff --git a/src/pkg/compress/gzip/gzip_test.go b/src/compress/gzip/gzip_test.go
index 09271b24e..09271b24e 100644
--- a/src/pkg/compress/gzip/gzip_test.go
+++ b/src/compress/gzip/gzip_test.go
diff --git a/src/pkg/compress/gzip/testdata/issue6550.gz b/src/compress/gzip/testdata/issue6550.gz
index 57972b636..57972b636 100644
--- a/src/pkg/compress/gzip/testdata/issue6550.gz
+++ b/src/compress/gzip/testdata/issue6550.gz
Binary files differ
diff --git a/src/pkg/compress/lzw/reader.go b/src/compress/lzw/reader.go
index ef5969910..526620c82 100644
--- a/src/pkg/compress/lzw/reader.go
+++ b/src/compress/lzw/reader.go
@@ -6,12 +6,16 @@
// described in T. A. Welch, ``A Technique for High-Performance Data
// Compression'', Computer, 17(6) (June 1984), pp 8-19.
//
-// In particular, it implements LZW as used by the GIF, TIFF and PDF file
+// In particular, it implements LZW as used by the GIF and PDF file
// formats, which means variable-width codes up to 12 bits and the first
// two non-literal codes are a clear code and an EOF code.
+//
+// The TIFF file format uses a similar but incompatible version of the LZW
+// algorithm. See the golang.org/x/image/tiff/lzw package for an
+// implementation.
package lzw
-// TODO(nigeltao): check that TIFF and PDF use LZW in the same way as GIF,
+// TODO(nigeltao): check that PDF uses LZW in the same way as GIF,
// modulo LSB/MSB packing order.
import (
@@ -218,6 +222,8 @@ func (d *decoder) Close() error {
// NewReader creates a new io.ReadCloser.
// Reads from the returned io.ReadCloser read and decompress data from r.
+// 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 ReadCloser when
// finished reading.
// The number of bits to use for literal codes, litWidth, must be in the
diff --git a/src/pkg/compress/lzw/reader_test.go b/src/compress/lzw/reader_test.go
index 9006c91c2..9006c91c2 100644
--- a/src/pkg/compress/lzw/reader_test.go
+++ b/src/compress/lzw/reader_test.go
diff --git a/src/pkg/compress/lzw/writer.go b/src/compress/lzw/writer.go
index 961b25f94..961b25f94 100644
--- a/src/pkg/compress/lzw/writer.go
+++ b/src/compress/lzw/writer.go
diff --git a/src/pkg/compress/lzw/writer_test.go b/src/compress/lzw/writer_test.go
index 3e4e6de21..3e4e6de21 100644
--- a/src/pkg/compress/lzw/writer_test.go
+++ b/src/compress/lzw/writer_test.go
diff --git a/src/pkg/compress/testdata/Mark.Twain-Tom.Sawyer.txt b/src/compress/testdata/Mark.Twain-Tom.Sawyer.txt
index c97da7ecc..c97da7ecc 100644
--- a/src/pkg/compress/testdata/Mark.Twain-Tom.Sawyer.txt
+++ b/src/compress/testdata/Mark.Twain-Tom.Sawyer.txt
diff --git a/src/pkg/compress/testdata/e.txt b/src/compress/testdata/e.txt
index 5ca186f14..5ca186f14 100644
--- a/src/pkg/compress/testdata/e.txt
+++ b/src/compress/testdata/e.txt
diff --git a/src/pkg/compress/testdata/pi.txt b/src/compress/testdata/pi.txt
index ca99bbc2a..ca99bbc2a 100644
--- a/src/pkg/compress/testdata/pi.txt
+++ b/src/compress/testdata/pi.txt
diff --git a/src/pkg/compress/zlib/example_test.go b/src/compress/zlib/example_test.go
index 70408895f..70408895f 100644
--- a/src/pkg/compress/zlib/example_test.go
+++ b/src/compress/zlib/example_test.go
diff --git a/src/pkg/compress/zlib/reader.go b/src/compress/zlib/reader.go
index 9e1aafda9..816f1bf6b 100644
--- a/src/pkg/compress/zlib/reader.go
+++ b/src/compress/zlib/reader.go
@@ -51,45 +51,36 @@ type reader struct {
scratch [4]byte
}
-// NewReader creates a new io.ReadCloser.
-// Reads from the returned io.ReadCloser read and decompress data from r.
+// Resetter resets a ReadCloser returned by NewReader or NewReaderDict to
+// to switch to a new underlying Reader. This permits reusing a ReadCloser
+// instead of allocating a new one.
+type Resetter interface {
+ // Reset discards any buffered data and resets the Resetter as if it was
+ // newly initialized with the given reader.
+ Reset(r io.Reader, dict []byte) error
+}
+
+// NewReader creates a new ReadCloser.
+// Reads from the returned ReadCloser read and decompress data from r.
// The implementation buffers input and may read more data than necessary from r.
// It is the caller's responsibility to call Close on the ReadCloser when done.
+//
+// The ReadCloser returned by NewReader also implements Resetter.
func NewReader(r io.Reader) (io.ReadCloser, error) {
return NewReaderDict(r, nil)
}
// NewReaderDict is like NewReader but uses a preset dictionary.
// NewReaderDict ignores the dictionary if the compressed data does not refer to it.
+// If the compressed data refers to a different dictionary, NewReaderDict returns ErrDictionary.
+//
+// The ReadCloser returned by NewReaderDict also implements Resetter.
func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
z := new(reader)
- if fr, ok := r.(flate.Reader); ok {
- z.r = fr
- } else {
- z.r = bufio.NewReader(r)
- }
- _, err := io.ReadFull(z.r, z.scratch[0:2])
+ err := z.Reset(r, dict)
if err != nil {
return nil, err
}
- h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
- if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
- return nil, ErrHeader
- }
- if z.scratch[1]&0x20 != 0 {
- _, err = io.ReadFull(z.r, z.scratch[0:4])
- if err != nil {
- return nil, err
- }
- checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
- if checksum != adler32.Checksum(dict) {
- return nil, ErrDictionary
- }
- z.decompressor = flate.NewReaderDict(z.r, dict)
- } else {
- z.decompressor = flate.NewReader(z.r)
- }
- z.digest = adler32.New()
return z, nil
}
@@ -130,3 +121,41 @@ func (z *reader) Close() error {
z.err = z.decompressor.Close()
return z.err
}
+
+func (z *reader) Reset(r io.Reader, dict []byte) error {
+ if fr, ok := r.(flate.Reader); ok {
+ z.r = fr
+ } else {
+ z.r = bufio.NewReader(r)
+ }
+ _, err := io.ReadFull(z.r, z.scratch[0:2])
+ if err != nil {
+ return err
+ }
+ h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
+ if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
+ return ErrHeader
+ }
+ haveDict := z.scratch[1]&0x20 != 0
+ if haveDict {
+ _, err = io.ReadFull(z.r, z.scratch[0:4])
+ if err != nil {
+ return err
+ }
+ checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
+ if checksum != adler32.Checksum(dict) {
+ return ErrDictionary
+ }
+ }
+ if z.decompressor == nil {
+ if haveDict {
+ z.decompressor = flate.NewReaderDict(z.r, dict)
+ } else {
+ z.decompressor = flate.NewReader(z.r)
+ }
+ } else {
+ z.decompressor.(flate.Resetter).Reset(z.r, dict)
+ }
+ z.digest = adler32.New()
+ return nil
+}
diff --git a/src/pkg/compress/zlib/reader_test.go b/src/compress/zlib/reader_test.go
index 218ccba14..218ccba14 100644
--- a/src/pkg/compress/zlib/reader_test.go
+++ b/src/compress/zlib/reader_test.go
diff --git a/src/pkg/compress/zlib/writer.go b/src/compress/zlib/writer.go
index 3b4313a8b..3b4313a8b 100644
--- a/src/pkg/compress/zlib/writer.go
+++ b/src/compress/zlib/writer.go
diff --git a/src/pkg/compress/zlib/writer_test.go b/src/compress/zlib/writer_test.go
index 71ba81aaa..71ba81aaa 100644
--- a/src/pkg/compress/zlib/writer_test.go
+++ b/src/compress/zlib/writer_test.go
diff --git a/src/pkg/container/heap/example_intheap_test.go b/src/container/heap/example_intheap_test.go
index 02d3d8668..02d3d8668 100644
--- a/src/pkg/container/heap/example_intheap_test.go
+++ b/src/container/heap/example_intheap_test.go
diff --git a/src/pkg/container/heap/example_pq_test.go b/src/container/heap/example_pq_test.go
index 7017095cb..7017095cb 100644
--- a/src/pkg/container/heap/example_pq_test.go
+++ b/src/container/heap/example_pq_test.go
diff --git a/src/pkg/container/heap/heap.go b/src/container/heap/heap.go
index c467a1191..c467a1191 100644
--- a/src/pkg/container/heap/heap.go
+++ b/src/container/heap/heap.go
diff --git a/src/pkg/container/heap/heap_test.go b/src/container/heap/heap_test.go
index b3d054c5f..b3d054c5f 100644
--- a/src/pkg/container/heap/heap_test.go
+++ b/src/container/heap/heap_test.go
diff --git a/src/pkg/container/list/example_test.go b/src/container/list/example_test.go
index 362178401..362178401 100644
--- a/src/pkg/container/list/example_test.go
+++ b/src/container/list/example_test.go
diff --git a/src/pkg/container/list/list.go b/src/container/list/list.go
index 0256768ef..0256768ef 100644
--- a/src/pkg/container/list/list.go
+++ b/src/container/list/list.go
diff --git a/src/pkg/container/list/list_test.go b/src/container/list/list_test.go
index 4d8bfc2bf..4d8bfc2bf 100644
--- a/src/pkg/container/list/list_test.go
+++ b/src/container/list/list_test.go
diff --git a/src/pkg/container/ring/ring.go b/src/container/ring/ring.go
index 6d3b3e5b3..6d3b3e5b3 100644
--- a/src/pkg/container/ring/ring.go
+++ b/src/container/ring/ring.go
diff --git a/src/pkg/container/ring/ring_test.go b/src/container/ring/ring_test.go
index 552f0e24b..552f0e24b 100644
--- a/src/pkg/container/ring/ring_test.go
+++ b/src/container/ring/ring_test.go
diff --git a/src/pkg/crypto/aes/aes_test.go b/src/crypto/aes/aes_test.go
index 363180931..363180931 100644
--- a/src/pkg/crypto/aes/aes_test.go
+++ b/src/crypto/aes/aes_test.go
diff --git a/src/pkg/crypto/aes/asm_amd64.s b/src/crypto/aes/asm_amd64.s
index 5c22881e9..6a6e6ac4b 100644
--- a/src/pkg/crypto/aes/asm_amd64.s
+++ b/src/crypto/aes/asm_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// func hasAsm() bool
// returns whether AES-NI is supported
diff --git a/src/pkg/crypto/aes/block.go b/src/crypto/aes/block.go
index 57a7e9e25..57a7e9e25 100644
--- a/src/pkg/crypto/aes/block.go
+++ b/src/crypto/aes/block.go
diff --git a/src/pkg/crypto/aes/cipher.go b/src/crypto/aes/cipher.go
index 2c6bb0a89..2c6bb0a89 100644
--- a/src/pkg/crypto/aes/cipher.go
+++ b/src/crypto/aes/cipher.go
diff --git a/src/pkg/crypto/aes/cipher_asm.go b/src/crypto/aes/cipher_asm.go
index 964eaaa6f..964eaaa6f 100644
--- a/src/pkg/crypto/aes/cipher_asm.go
+++ b/src/crypto/aes/cipher_asm.go
diff --git a/src/pkg/crypto/aes/cipher_generic.go b/src/crypto/aes/cipher_generic.go
index 1714e0f1e..1714e0f1e 100644
--- a/src/pkg/crypto/aes/cipher_generic.go
+++ b/src/crypto/aes/cipher_generic.go
diff --git a/src/pkg/crypto/aes/const.go b/src/crypto/aes/const.go
index aee73a7c5..aee73a7c5 100644
--- a/src/pkg/crypto/aes/const.go
+++ b/src/crypto/aes/const.go
diff --git a/src/pkg/crypto/cipher/benchmark_test.go b/src/crypto/cipher/benchmark_test.go
index 027b24851..027b24851 100644
--- a/src/pkg/crypto/cipher/benchmark_test.go
+++ b/src/crypto/cipher/benchmark_test.go
diff --git a/src/pkg/crypto/cipher/cbc.go b/src/crypto/cipher/cbc.go
index 241e122ee..241e122ee 100644
--- a/src/pkg/crypto/cipher/cbc.go
+++ b/src/crypto/cipher/cbc.go
diff --git a/src/pkg/crypto/cipher/cbc_aes_test.go b/src/crypto/cipher/cbc_aes_test.go
index bf9e7ad70..bf9e7ad70 100644
--- a/src/pkg/crypto/cipher/cbc_aes_test.go
+++ b/src/crypto/cipher/cbc_aes_test.go
diff --git a/src/pkg/crypto/cipher/cfb.go b/src/crypto/cipher/cfb.go
index 9b4eebf5b..9b4eebf5b 100644
--- a/src/pkg/crypto/cipher/cfb.go
+++ b/src/crypto/cipher/cfb.go
diff --git a/src/crypto/cipher/cfb_test.go b/src/crypto/cipher/cfb_test.go
new file mode 100644
index 000000000..9b544bb21
--- /dev/null
+++ b/src/crypto/cipher/cfb_test.go
@@ -0,0 +1,113 @@
+// 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.
+
+package cipher_test
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "encoding/hex"
+ "testing"
+)
+
+// cfbTests contains the test vectors from
+// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section
+// F.3.13.
+var cfbTests = []struct {
+ key, iv, plaintext, ciphertext string
+}{
+ {
+ "2b7e151628aed2a6abf7158809cf4f3c",
+ "000102030405060708090a0b0c0d0e0f",
+ "6bc1bee22e409f96e93d7e117393172a",
+ "3b3fd92eb72dad20333449f8e83cfb4a",
+ },
+ {
+ "2b7e151628aed2a6abf7158809cf4f3c",
+ "3B3FD92EB72DAD20333449F8E83CFB4A",
+ "ae2d8a571e03ac9c9eb76fac45af8e51",
+ "c8a64537a0b3a93fcde3cdad9f1ce58b",
+ },
+ {
+ "2b7e151628aed2a6abf7158809cf4f3c",
+ "C8A64537A0B3A93FCDE3CDAD9F1CE58B",
+ "30c81c46a35ce411e5fbc1191a0a52ef",
+ "26751f67a3cbb140b1808cf187a4f4df",
+ },
+ {
+ "2b7e151628aed2a6abf7158809cf4f3c",
+ "26751F67A3CBB140B1808CF187A4F4DF",
+ "f69f2445df4f9b17ad2b417be66c3710",
+ "c04b05357c5d1c0eeac4c66f9ff7f2e6",
+ },
+}
+
+func TestCFBVectors(t *testing.T) {
+ for i, test := range cfbTests {
+ key, err := hex.DecodeString(test.key)
+ if err != nil {
+ t.Fatal(err)
+ }
+ iv, err := hex.DecodeString(test.iv)
+ if err != nil {
+ t.Fatal(err)
+ }
+ plaintext, err := hex.DecodeString(test.plaintext)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expected, err := hex.DecodeString(test.ciphertext)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ciphertext := make([]byte, len(plaintext))
+ cfb := cipher.NewCFBEncrypter(block, iv)
+ cfb.XORKeyStream(ciphertext, plaintext)
+
+ if !bytes.Equal(ciphertext, expected) {
+ t.Errorf("#%d: wrong output: got %x, expected %x", i, ciphertext, expected)
+ }
+
+ cfbdec := cipher.NewCFBDecrypter(block, iv)
+ plaintextCopy := make([]byte, len(ciphertext))
+ cfbdec.XORKeyStream(plaintextCopy, ciphertext)
+
+ if !bytes.Equal(plaintextCopy, plaintextCopy) {
+ t.Errorf("#%d: wrong plaintext: got %x, expected %x", i, plaintextCopy, plaintext)
+ }
+ }
+}
+
+func TestCFBInverse(t *testing.T) {
+ block, err := aes.NewCipher(commonKey128)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ plaintext := []byte("this is the plaintext. this is the plaintext.")
+ iv := make([]byte, block.BlockSize())
+ rand.Reader.Read(iv)
+ cfb := cipher.NewCFBEncrypter(block, iv)
+ ciphertext := make([]byte, len(plaintext))
+ copy(ciphertext, plaintext)
+ cfb.XORKeyStream(ciphertext, ciphertext)
+
+ cfbdec := cipher.NewCFBDecrypter(block, iv)
+ plaintextCopy := make([]byte, len(plaintext))
+ copy(plaintextCopy, ciphertext)
+ cfbdec.XORKeyStream(plaintextCopy, plaintextCopy)
+
+ if !bytes.Equal(plaintextCopy, plaintext) {
+ t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)
+ }
+}
diff --git a/src/pkg/crypto/cipher/cipher.go b/src/crypto/cipher/cipher.go
index 67afdb1e0..67afdb1e0 100644
--- a/src/pkg/crypto/cipher/cipher.go
+++ b/src/crypto/cipher/cipher.go
diff --git a/src/pkg/crypto/cipher/cipher_test.go b/src/crypto/cipher/cipher_test.go
index 8da5bce93..8da5bce93 100644
--- a/src/pkg/crypto/cipher/cipher_test.go
+++ b/src/crypto/cipher/cipher_test.go
diff --git a/src/pkg/crypto/cipher/common_test.go b/src/crypto/cipher/common_test.go
index c75c919d1..c75c919d1 100644
--- a/src/pkg/crypto/cipher/common_test.go
+++ b/src/crypto/cipher/common_test.go
diff --git a/src/pkg/crypto/cipher/ctr.go b/src/crypto/cipher/ctr.go
index 70ac40f6a..70ac40f6a 100644
--- a/src/pkg/crypto/cipher/ctr.go
+++ b/src/crypto/cipher/ctr.go
diff --git a/src/pkg/crypto/cipher/ctr_aes_test.go b/src/crypto/cipher/ctr_aes_test.go
index d019ae0d0..d019ae0d0 100644
--- a/src/pkg/crypto/cipher/ctr_aes_test.go
+++ b/src/crypto/cipher/ctr_aes_test.go
diff --git a/src/pkg/crypto/cipher/example_test.go b/src/crypto/cipher/example_test.go
index 373f6791b..1cfa982df 100644
--- a/src/pkg/crypto/cipher/example_test.go
+++ b/src/crypto/cipher/example_test.go
@@ -240,7 +240,7 @@ func ExampleStreamReader() {
}
// Note that this example is simplistic in that it omits any
- // authentication of the encrypted data. It you were actually to use
+ // authentication of the encrypted data. If you were actually to use
// StreamReader in this manner, an attacker could flip arbitrary bits in
// the output.
}
@@ -277,7 +277,7 @@ func ExampleStreamWriter() {
}
// Note that this example is simplistic in that it omits any
- // authentication of the encrypted data. It you were actually to use
+ // authentication of the encrypted data. If you were actually to use
// StreamReader in this manner, an attacker could flip arbitrary bits in
// the decrypted result.
}
diff --git a/src/pkg/crypto/cipher/gcm.go b/src/crypto/cipher/gcm.go
index bdafd85fc..bdafd85fc 100644
--- a/src/pkg/crypto/cipher/gcm.go
+++ b/src/crypto/cipher/gcm.go
diff --git a/src/pkg/crypto/cipher/gcm_test.go b/src/crypto/cipher/gcm_test.go
index 0c502ce40..0c502ce40 100644
--- a/src/pkg/crypto/cipher/gcm_test.go
+++ b/src/crypto/cipher/gcm_test.go
diff --git a/src/pkg/crypto/cipher/io.go b/src/crypto/cipher/io.go
index 3938c0a4c..3938c0a4c 100644
--- a/src/pkg/crypto/cipher/io.go
+++ b/src/crypto/cipher/io.go
diff --git a/src/pkg/crypto/cipher/ofb.go b/src/crypto/cipher/ofb.go
index e86ebcb23..e86ebcb23 100644
--- a/src/pkg/crypto/cipher/ofb.go
+++ b/src/crypto/cipher/ofb.go
diff --git a/src/pkg/crypto/cipher/ofb_test.go b/src/crypto/cipher/ofb_test.go
index 8d3c5d3a3..8d3c5d3a3 100644
--- a/src/pkg/crypto/cipher/ofb_test.go
+++ b/src/crypto/cipher/ofb_test.go
diff --git a/src/pkg/crypto/cipher/xor.go b/src/crypto/cipher/xor.go
index f88dc8914..f88dc8914 100644
--- a/src/pkg/crypto/cipher/xor.go
+++ b/src/crypto/cipher/xor.go
diff --git a/src/pkg/crypto/cipher/xor_test.go b/src/crypto/cipher/xor_test.go
index cc1c9d72d..cc1c9d72d 100644
--- a/src/pkg/crypto/cipher/xor_test.go
+++ b/src/crypto/cipher/xor_test.go
diff --git a/src/pkg/crypto/crypto.go b/src/crypto/crypto.go
index 4b03628e6..59b23e93f 100644
--- a/src/pkg/crypto/crypto.go
+++ b/src/crypto/crypto.go
@@ -7,6 +7,7 @@ package crypto
import (
"hash"
+ "io"
"strconv"
)
@@ -14,8 +15,13 @@ import (
// package.
type Hash uint
+// HashFunc simply returns the value of h so that Hash implements SignerOpts.
+func (h Hash) HashFunc() Hash {
+ return h
+}
+
const (
- MD4 Hash = 1 + iota // import code.google.com/p/go.crypto/md4
+ MD4 Hash = 1 + iota // import golang.org/x/crypto/md4
MD5 // import crypto/md5
SHA1 // import crypto/sha1
SHA224 // import crypto/sha256
@@ -23,7 +29,11 @@ const (
SHA384 // import crypto/sha512
SHA512 // import crypto/sha512
MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA
- RIPEMD160 // import code.google.com/p/go.crypto/ripemd160
+ RIPEMD160 // import golang.org/x/crypto/ripemd160
+ SHA3_224 // import golang.org/x/crypto/sha3
+ SHA3_256 // import golang.org/x/crypto/sha3
+ SHA3_384 // import golang.org/x/crypto/sha3
+ SHA3_512 // import golang.org/x/crypto/sha3
maxHash
)
@@ -35,6 +45,10 @@ var digestSizes = []uint8{
SHA256: 32,
SHA384: 48,
SHA512: 64,
+ SHA3_224: 28,
+ SHA3_256: 32,
+ SHA3_384: 48,
+ SHA3_512: 64,
MD5SHA1: 36,
RIPEMD160: 20,
}
@@ -83,3 +97,30 @@ type PublicKey interface{}
// PrivateKey represents a private key using an unspecified algorithm.
type PrivateKey interface{}
+
+// Signer is an interface for an opaque private key that can be used for
+// signing operations. For example, an RSA key kept in a hardware module.
+type Signer interface {
+ // Public returns the public key corresponding to the opaque,
+ // private key.
+ Public() PublicKey
+
+ // Sign signs msg 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.
+ //
+ // Hash implements the SignerOpts interface and, in most cases, one can
+ // 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)
+}
+
+// SignerOpts contains options for signing with a Signer.
+type SignerOpts interface {
+ // HashFunc returns an identifier for the hash function used to produce
+ // the message passed to Signer.Sign, or else zero to indicate that no
+ // hashing was done.
+ HashFunc() Hash
+}
diff --git a/src/pkg/crypto/des/block.go b/src/crypto/des/block.go
index 26355a22e..26355a22e 100644
--- a/src/pkg/crypto/des/block.go
+++ b/src/crypto/des/block.go
diff --git a/src/pkg/crypto/des/cipher.go b/src/crypto/des/cipher.go
index 2f929ca7b..2f929ca7b 100644
--- a/src/pkg/crypto/des/cipher.go
+++ b/src/crypto/des/cipher.go
diff --git a/src/pkg/crypto/des/const.go b/src/crypto/des/const.go
index 2bd485ee8..2bd485ee8 100644
--- a/src/pkg/crypto/des/const.go
+++ b/src/crypto/des/const.go
diff --git a/src/pkg/crypto/des/des_test.go b/src/crypto/des/des_test.go
index 2bd525afe..2bd525afe 100644
--- a/src/pkg/crypto/des/des_test.go
+++ b/src/crypto/des/des_test.go
diff --git a/src/pkg/crypto/des/example_test.go b/src/crypto/des/example_test.go
index 336b59375..336b59375 100644
--- a/src/pkg/crypto/des/example_test.go
+++ b/src/crypto/des/example_test.go
diff --git a/src/pkg/crypto/dsa/dsa.go b/src/crypto/dsa/dsa.go
index b7565a61b..b7565a61b 100644
--- a/src/pkg/crypto/dsa/dsa.go
+++ b/src/crypto/dsa/dsa.go
diff --git a/src/pkg/crypto/dsa/dsa_test.go b/src/crypto/dsa/dsa_test.go
index 568416d0d..568416d0d 100644
--- a/src/pkg/crypto/dsa/dsa_test.go
+++ b/src/crypto/dsa/dsa_test.go
diff --git a/src/pkg/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go
index 1bec7437a..d6135531b 100644
--- a/src/pkg/crypto/ecdsa/ecdsa.go
+++ b/src/crypto/ecdsa/ecdsa.go
@@ -13,7 +13,9 @@ package ecdsa
// http://www.secg.org/download/aid-780/sec1-v2.pdf
import (
+ "crypto"
"crypto/elliptic"
+ "encoding/asn1"
"io"
"math/big"
)
@@ -30,6 +32,28 @@ type PrivateKey struct {
D *big.Int
}
+type ecdsaSignature struct {
+ R, S *big.Int
+}
+
+// Public returns the public key corresponding to priv.
+func (priv *PrivateKey) Public() crypto.PublicKey {
+ return &priv.PublicKey
+}
+
+// Sign signs msg with priv, reading randomness from rand. This method is
+// intended to support keys where the private part is kept in, for example, a
+// hardware module. Common uses should use the Sign function in this package
+// directly.
+func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
+ r, s, err := Sign(rand, priv, msg)
+ if err != nil {
+ return nil, err
+ }
+
+ return asn1.Marshal(ecdsaSignature{r, s})
+}
+
var one = new(big.Int).SetInt64(1)
// randFieldElement returns a random element of the field underlying the given
diff --git a/src/pkg/crypto/ecdsa/ecdsa_test.go b/src/crypto/ecdsa/ecdsa_test.go
index 0c0643193..0c0643193 100644
--- a/src/pkg/crypto/ecdsa/ecdsa_test.go
+++ b/src/crypto/ecdsa/ecdsa_test.go
diff --git a/src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2 b/src/crypto/ecdsa/testdata/SigVer.rsp.bz2
index 09fe2b427..09fe2b427 100644
--- a/src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2
+++ b/src/crypto/ecdsa/testdata/SigVer.rsp.bz2
Binary files differ
diff --git a/src/pkg/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go
index ba673f80c..ba673f80c 100644
--- a/src/pkg/crypto/elliptic/elliptic.go
+++ b/src/crypto/elliptic/elliptic.go
diff --git a/src/pkg/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go
index 4dc27c92b..4dc27c92b 100644
--- a/src/pkg/crypto/elliptic/elliptic_test.go
+++ b/src/crypto/elliptic/elliptic_test.go
diff --git a/src/pkg/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go
index 1f7ff3f9d..1f7ff3f9d 100644
--- a/src/pkg/crypto/elliptic/p224.go
+++ b/src/crypto/elliptic/p224.go
diff --git a/src/pkg/crypto/elliptic/p224_test.go b/src/crypto/elliptic/p224_test.go
index 4b26d1610..4b26d1610 100644
--- a/src/pkg/crypto/elliptic/p224_test.go
+++ b/src/crypto/elliptic/p224_test.go
diff --git a/src/pkg/crypto/elliptic/p256.go b/src/crypto/elliptic/p256.go
index 82be51e62..82be51e62 100644
--- a/src/pkg/crypto/elliptic/p256.go
+++ b/src/crypto/elliptic/p256.go
diff --git a/src/pkg/crypto/hmac/hmac.go b/src/crypto/hmac/hmac.go
index b6f4919a7..b6f4919a7 100644
--- a/src/pkg/crypto/hmac/hmac.go
+++ b/src/crypto/hmac/hmac.go
diff --git a/src/pkg/crypto/hmac/hmac_test.go b/src/crypto/hmac/hmac_test.go
index e80b7e0ba..e80b7e0ba 100644
--- a/src/pkg/crypto/hmac/hmac_test.go
+++ b/src/crypto/hmac/hmac_test.go
diff --git a/src/pkg/crypto/md5/example_test.go b/src/crypto/md5/example_test.go
index d47bb4570..d47bb4570 100644
--- a/src/pkg/crypto/md5/example_test.go
+++ b/src/crypto/md5/example_test.go
diff --git a/src/pkg/crypto/md5/gen.go b/src/crypto/md5/gen.go
index 75295e4fc..8cd0a6358 100644
--- a/src/pkg/crypto/md5/gen.go
+++ b/src/crypto/md5/gen.go
@@ -7,7 +7,7 @@
// This program generates md5block.go
// Invoke as
//
-// go run gen.go [-full] |gofmt >md5block.go
+// go run gen.go [-full] -output md5block.go
//
// The -full flag causes the generated code to do a full
// (16x) unrolling instead of a 4x unrolling.
@@ -15,18 +15,33 @@
package main
import (
+ "bytes"
"flag"
+ "go/format"
+ "io/ioutil"
"log"
- "os"
"strings"
"text/template"
)
+var filename = flag.String("output", "md5block.go", "output file name")
+
func main() {
flag.Parse()
+ var buf bytes.Buffer
+
t := template.Must(template.New("main").Funcs(funcs).Parse(program))
- if err := t.Execute(os.Stdout, data); err != nil {
+ if err := t.Execute(&buf, data); err != nil {
+ log.Fatal(err)
+ }
+
+ data, err := format.Source(buf.Bytes())
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = ioutil.WriteFile(*filename, data, 0644)
+ if err != nil {
log.Fatal(err)
}
}
@@ -165,7 +180,7 @@ var program = `// Copyright 2013 The Go Authors. All rights reserved.
// license that can be found in the LICENSE file.
// DO NOT EDIT.
-// Generate with: go run gen.go{{if .Full}} -full{{end}} | gofmt >md5block.go
+// Generate with: go run gen.go{{if .Full}} -full{{end}} -output md5block.go
package md5
diff --git a/src/pkg/crypto/md5/md5.go b/src/crypto/md5/md5.go
index 1a1f35fab..8c50c6d0b 100644
--- a/src/pkg/crypto/md5/md5.go
+++ b/src/crypto/md5/md5.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.
+//go:generate go run gen.go -full -output md5block.go
+
// Package md5 implements the MD5 hash algorithm as defined in RFC 1321.
package md5
diff --git a/src/pkg/crypto/md5/md5_test.go b/src/crypto/md5/md5_test.go
index e7faf4961..e7faf4961 100644
--- a/src/pkg/crypto/md5/md5_test.go
+++ b/src/crypto/md5/md5_test.go
diff --git a/src/pkg/crypto/md5/md5block.go b/src/crypto/md5/md5block.go
index e2a176777..64e1e7c1e 100644
--- a/src/pkg/crypto/md5/md5block.go
+++ b/src/crypto/md5/md5block.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// DO NOT EDIT.
-// Generate with: go run gen.go -full | gofmt >md5block.go
+// Generate with: go run gen.go -full -output md5block.go
package md5
diff --git a/src/pkg/crypto/md5/md5block_386.s b/src/crypto/md5/md5block_386.s
index e5c27ac9a..8e426d148 100644
--- a/src/pkg/crypto/md5/md5block_386.s
+++ b/src/crypto/md5/md5block_386.s
@@ -6,7 +6,7 @@
// #defines generating 8a assembly, and adjusted for 386,
// by the Go Authors.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// MD5 optimized for AMD64.
//
diff --git a/src/pkg/crypto/md5/md5block_amd64.s b/src/crypto/md5/md5block_amd64.s
index 178e49cd8..a3ae7d97b 100644
--- a/src/pkg/crypto/md5/md5block_amd64.s
+++ b/src/crypto/md5/md5block_amd64.s
@@ -5,7 +5,7 @@
// Translated from Perl generating GNU assembly into
// #defines generating 6a assembly by the Go Authors.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// MD5 optimized for AMD64.
//
diff --git a/src/pkg/crypto/md5/md5block_amd64p32.s b/src/crypto/md5/md5block_amd64p32.s
index a78a3f610..d918a67c5 100644
--- a/src/pkg/crypto/md5/md5block_amd64p32.s
+++ b/src/crypto/md5/md5block_amd64p32.s
@@ -9,7 +9,7 @@
// replace BP with R11, reloaded before use at return.
// replace R15 with R11.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// MD5 optimized for AMD64.
//
diff --git a/src/pkg/crypto/md5/md5block_arm.s b/src/crypto/md5/md5block_arm.s
index e644bfcd6..3b26e549b 100644
--- a/src/pkg/crypto/md5/md5block_arm.s
+++ b/src/crypto/md5/md5block_arm.s
@@ -4,7 +4,7 @@
//
// ARM version of md5block.go
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// Register definitions
table = 0 // Pointer to MD5 constants table
diff --git a/src/pkg/crypto/md5/md5block_decl.go b/src/crypto/md5/md5block_decl.go
index d7956a6d2..d7956a6d2 100644
--- a/src/pkg/crypto/md5/md5block_decl.go
+++ b/src/crypto/md5/md5block_decl.go
diff --git a/src/pkg/crypto/md5/md5block_generic.go b/src/crypto/md5/md5block_generic.go
index 263463e51..263463e51 100644
--- a/src/pkg/crypto/md5/md5block_generic.go
+++ b/src/crypto/md5/md5block_generic.go
diff --git a/src/pkg/crypto/rand/example_test.go b/src/crypto/rand/example_test.go
index 8a2717300..8a2717300 100644
--- a/src/pkg/crypto/rand/example_test.go
+++ b/src/crypto/rand/example_test.go
diff --git a/src/pkg/crypto/rand/rand.go b/src/crypto/rand/rand.go
index 4da3adb70..4da3adb70 100644
--- a/src/pkg/crypto/rand/rand.go
+++ b/src/crypto/rand/rand.go
diff --git a/src/crypto/rand/rand_linux.go b/src/crypto/rand/rand_linux.go
new file mode 100644
index 000000000..8cb59c75d
--- /dev/null
+++ b/src/crypto/rand/rand_linux.go
@@ -0,0 +1,39 @@
+// 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 rand
+
+import (
+ "internal/syscall"
+ "sync"
+)
+
+func init() {
+ altGetRandom = getRandomLinux
+}
+
+var (
+ once sync.Once
+ useSyscall bool
+)
+
+func pickStrategy() {
+ // Test whether we should use the system call or /dev/urandom.
+ // We'll fall back to urandom if:
+ // - the kernel is too old (before 3.17)
+ // - the machine has no entropy available (early boot + no hardware
+ // entropy source?) and we want to avoid blocking later.
+ var buf [1]byte
+ n, err := syscall.GetRandom(buf[:], syscall.GRND_NONBLOCK)
+ useSyscall = n == 1 && err == nil
+}
+
+func getRandomLinux(p []byte) (ok bool) {
+ once.Do(pickStrategy)
+ if !useSyscall {
+ return false
+ }
+ n, err := syscall.GetRandom(p, 0)
+ return n == len(p) && err == nil
+}
diff --git a/src/pkg/crypto/rand/rand_test.go b/src/crypto/rand/rand_test.go
index e46e61d37..e46e61d37 100644
--- a/src/pkg/crypto/rand/rand_test.go
+++ b/src/crypto/rand/rand_test.go
diff --git a/src/pkg/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go
index 1e741fda1..62d0fbdb3 100644
--- a/src/pkg/crypto/rand/rand_unix.go
+++ b/src/crypto/rand/rand_unix.go
@@ -20,6 +20,8 @@ import (
"time"
)
+const urandomDevice = "/dev/urandom"
+
// Easy implementation: read from /dev/urandom.
// This is sufficient on Linux, OS X, and FreeBSD.
@@ -27,7 +29,7 @@ func init() {
if runtime.GOOS == "plan9" {
Reader = newReader(nil)
} else {
- Reader = &devReader{name: "/dev/urandom"}
+ Reader = &devReader{name: urandomDevice}
}
}
@@ -38,7 +40,14 @@ type devReader struct {
mu sync.Mutex
}
+// altGetRandom if non-nil specifies an OS-specific function to get
+// urandom-style randomness.
+var altGetRandom func([]byte) (ok bool)
+
func (r *devReader) Read(b []byte) (n int, err error) {
+ if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) {
+ return len(b), nil
+ }
r.mu.Lock()
defer r.mu.Unlock()
if r.f == nil {
diff --git a/src/pkg/crypto/rand/rand_windows.go b/src/crypto/rand/rand_windows.go
index 82b39b64a..82b39b64a 100644
--- a/src/pkg/crypto/rand/rand_windows.go
+++ b/src/crypto/rand/rand_windows.go
diff --git a/src/pkg/crypto/rand/util.go b/src/crypto/rand/util.go
index 5f7440785..5f7440785 100644
--- a/src/pkg/crypto/rand/util.go
+++ b/src/crypto/rand/util.go
diff --git a/src/pkg/crypto/rand/util_test.go b/src/crypto/rand/util_test.go
index 1e2a4dd84..1e2a4dd84 100644
--- a/src/pkg/crypto/rand/util_test.go
+++ b/src/crypto/rand/util_test.go
diff --git a/src/pkg/crypto/rc4/rc4.go b/src/crypto/rc4/rc4.go
index 9acb681bf..9acb681bf 100644
--- a/src/pkg/crypto/rc4/rc4.go
+++ b/src/crypto/rc4/rc4.go
diff --git a/src/pkg/crypto/rc4/rc4_386.s b/src/crypto/rc4/rc4_386.s
index b04fc1fb8..54221036b 100644
--- a/src/pkg/crypto/rc4/rc4_386.s
+++ b/src/crypto/rc4/rc4_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// func xorKeyStream(dst, src *byte, n int, state *[256]byte, i, j *uint8)
TEXT ·xorKeyStream(SB),NOSPLIT,$0
diff --git a/src/pkg/crypto/rc4/rc4_amd64.s b/src/crypto/rc4/rc4_amd64.s
index e3234b6c7..57d941c8f 100644
--- a/src/pkg/crypto/rc4/rc4_amd64.s
+++ b/src/crypto/rc4/rc4_amd64.s
@@ -2,7 +2,7 @@
// http://www.zorinaq.com/papers/rc4-amd64.html
// http://www.zorinaq.com/papers/rc4-amd64.tar.bz2
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// Local modifications:
//
diff --git a/src/pkg/crypto/rc4/rc4_amd64p32.s b/src/crypto/rc4/rc4_amd64p32.s
index 27d849507..970b34e08 100644
--- a/src/pkg/crypto/rc4/rc4_amd64p32.s
+++ b/src/crypto/rc4/rc4_amd64p32.s
@@ -2,7 +2,7 @@
// http://www.zorinaq.com/papers/rc4-amd64.html
// http://www.zorinaq.com/papers/rc4-amd64.tar.bz2
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// Local modifications:
//
diff --git a/src/pkg/crypto/rc4/rc4_arm.s b/src/crypto/rc4/rc4_arm.s
index 3aad72940..51be3bf95 100644
--- a/src/pkg/crypto/rc4/rc4_arm.s
+++ b/src/crypto/rc4/rc4_arm.s
@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+// +build !nacl
+
+#include "textflag.h"
// Registers
dst = 0
diff --git a/src/pkg/crypto/rc4/rc4_asm.go b/src/crypto/rc4/rc4_asm.go
index fc71b9a6f..02e5b67d5 100644
--- a/src/pkg/crypto/rc4/rc4_asm.go
+++ b/src/crypto/rc4/rc4_asm.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 amd64 amd64p32 arm 386
+// +build amd64 amd64p32 arm,!nacl 386
package rc4
diff --git a/src/pkg/crypto/rc4/rc4_ref.go b/src/crypto/rc4/rc4_ref.go
index 1ecce1a7f..e34bd34cf 100644
--- a/src/pkg/crypto/rc4/rc4_ref.go
+++ b/src/crypto/rc4/rc4_ref.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 !amd64,!amd64p32,!arm,!386
+// +build !amd64,!amd64p32,!arm,!386 arm,nacl
package rc4
diff --git a/src/pkg/crypto/rc4/rc4_test.go b/src/crypto/rc4/rc4_test.go
index af7988246..af7988246 100644
--- a/src/pkg/crypto/rc4/rc4_test.go
+++ b/src/crypto/rc4/rc4_test.go
diff --git a/src/pkg/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go
index 59e8bb5b7..59e8bb5b7 100644
--- a/src/pkg/crypto/rsa/pkcs1v15.go
+++ b/src/crypto/rsa/pkcs1v15.go
diff --git a/src/pkg/crypto/rsa/pkcs1v15_test.go b/src/crypto/rsa/pkcs1v15_test.go
index 2dc5dbc2c..2dc5dbc2c 100644
--- a/src/pkg/crypto/rsa/pkcs1v15_test.go
+++ b/src/crypto/rsa/pkcs1v15_test.go
diff --git a/src/pkg/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
index 18eafbc05..e9f290825 100644
--- a/src/pkg/crypto/rsa/pss.go
+++ b/src/crypto/rsa/pss.go
@@ -222,6 +222,17 @@ type PSSOptions struct {
// signature. It can either be a number of bytes, or one of the special
// PSSSaltLength constants.
SaltLength int
+
+ // Hash, if not zero, overrides the hash function passed to SignPSS.
+ // This is the only way to specify the hash function when using the
+ // crypto.Signer interface.
+ Hash crypto.Hash
+}
+
+// HashFunc returns pssOpts.Hash so that PSSOptions implements
+// crypto.SignerOpts.
+func (pssOpts *PSSOptions) HashFunc() crypto.Hash {
+ return pssOpts.Hash
}
func (opts *PSSOptions) saltLength() int {
@@ -244,6 +255,10 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte,
saltLength = hash.Size()
}
+ if opts.Hash != 0 {
+ hash = opts.Hash
+ }
+
salt := make([]byte, saltLength)
if _, err = io.ReadFull(rand, salt); err != nil {
return
diff --git a/src/pkg/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go
index 32e6fc39d..32e6fc39d 100644
--- a/src/pkg/crypto/rsa/pss_test.go
+++ b/src/crypto/rsa/pss_test.go
diff --git a/src/pkg/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
index bce6ba4eb..270231128 100644
--- a/src/pkg/crypto/rsa/rsa.go
+++ b/src/crypto/rsa/rsa.go
@@ -6,6 +6,7 @@
package rsa
import (
+ "crypto"
"crypto/rand"
"crypto/subtle"
"errors"
@@ -58,6 +59,24 @@ type PrivateKey struct {
Precomputed PrecomputedValues
}
+// Public returns the public key corresponding to priv.
+func (priv *PrivateKey) Public() crypto.PublicKey {
+ return &priv.PublicKey
+}
+
+// Sign signs msg with priv, reading randomness from rand. If opts is a
+// *PSSOptions then the PSS algorithm will be used, otherwise PKCS#1 v1.5 will
+// be used. This method is intended to support keys where the private part is
+// kept in, for example, a hardware module. Common uses should use the Sign*
+// functions in this package.
+func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
+ if pssOpts, ok := opts.(*PSSOptions); ok {
+ return SignPSS(rand, priv, pssOpts.Hash, msg, pssOpts)
+ }
+
+ return SignPKCS1v15(rand, priv, opts.HashFunc(), msg)
+}
+
type PrecomputedValues struct {
Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
Qinv *big.Int // Q^-1 mod P
diff --git a/src/pkg/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go
index 4ee1c3a8b..4ee1c3a8b 100644
--- a/src/pkg/crypto/rsa/rsa_test.go
+++ b/src/crypto/rsa/rsa_test.go
diff --git a/src/pkg/crypto/rsa/testdata/pss-vect.txt.bz2 b/src/crypto/rsa/testdata/pss-vect.txt.bz2
index ad3da1ac4..ad3da1ac4 100644
--- a/src/pkg/crypto/rsa/testdata/pss-vect.txt.bz2
+++ b/src/crypto/rsa/testdata/pss-vect.txt.bz2
Binary files differ
diff --git a/src/pkg/crypto/sha1/example_test.go b/src/crypto/sha1/example_test.go
index 42aec8afa..42aec8afa 100644
--- a/src/pkg/crypto/sha1/example_test.go
+++ b/src/crypto/sha1/example_test.go
diff --git a/src/pkg/crypto/sha1/sha1.go b/src/crypto/sha1/sha1.go
index 9f1a96e36..9f1a96e36 100644
--- a/src/pkg/crypto/sha1/sha1.go
+++ b/src/crypto/sha1/sha1.go
diff --git a/src/pkg/crypto/sha1/sha1_test.go b/src/crypto/sha1/sha1_test.go
index 4a629518b..4a629518b 100644
--- a/src/pkg/crypto/sha1/sha1_test.go
+++ b/src/crypto/sha1/sha1_test.go
diff --git a/src/pkg/crypto/sha1/sha1block.go b/src/crypto/sha1/sha1block.go
index fde3c981c..fde3c981c 100644
--- a/src/pkg/crypto/sha1/sha1block.go
+++ b/src/crypto/sha1/sha1block.go
diff --git a/src/pkg/crypto/sha1/sha1block_386.s b/src/crypto/sha1/sha1block_386.s
index 688851c31..a0adabc3c 100644
--- a/src/pkg/crypto/sha1/sha1block_386.s
+++ b/src/crypto/sha1/sha1block_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// SHA1 block routine. See sha1block.go for Go equivalent.
//
diff --git a/src/pkg/crypto/sha1/sha1block_amd64.s b/src/crypto/sha1/sha1block_amd64.s
index 8ffb9d5d6..4319df63e 100644
--- a/src/pkg/crypto/sha1/sha1block_amd64.s
+++ b/src/crypto/sha1/sha1block_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// SHA1 block routine. See sha1block.go for Go equivalent.
//
diff --git a/src/pkg/crypto/sha1/sha1block_amd64p32.s b/src/crypto/sha1/sha1block_amd64p32.s
index 3c589d94f..d93fbf1ed 100644
--- a/src/pkg/crypto/sha1/sha1block_amd64p32.s
+++ b/src/crypto/sha1/sha1block_amd64p32.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// SHA1 block routine. See sha1block.go for Go equivalent.
//
diff --git a/src/pkg/crypto/sha1/sha1block_arm.s b/src/crypto/sha1/sha1block_arm.s
index 5917e8b24..f11f33dc3 100644
--- a/src/pkg/crypto/sha1/sha1block_arm.s
+++ b/src/crypto/sha1/sha1block_arm.s
@@ -4,7 +4,7 @@
//
// ARM version of md5block.go
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// SHA1 block routine. See sha1block.go for Go equivalent.
//
diff --git a/src/pkg/crypto/sha1/sha1block_decl.go b/src/crypto/sha1/sha1block_decl.go
index 24e521af1..24e521af1 100644
--- a/src/pkg/crypto/sha1/sha1block_decl.go
+++ b/src/crypto/sha1/sha1block_decl.go
diff --git a/src/pkg/crypto/sha1/sha1block_generic.go b/src/crypto/sha1/sha1block_generic.go
index 696e26b62..696e26b62 100644
--- a/src/pkg/crypto/sha1/sha1block_generic.go
+++ b/src/crypto/sha1/sha1block_generic.go
diff --git a/src/pkg/crypto/sha256/sha256.go b/src/crypto/sha256/sha256.go
index d84cebf2f..d84cebf2f 100644
--- a/src/pkg/crypto/sha256/sha256.go
+++ b/src/crypto/sha256/sha256.go
diff --git a/src/pkg/crypto/sha256/sha256_test.go b/src/crypto/sha256/sha256_test.go
index 1d883d390..1d883d390 100644
--- a/src/pkg/crypto/sha256/sha256_test.go
+++ b/src/crypto/sha256/sha256_test.go
diff --git a/src/pkg/crypto/sha256/sha256block.go b/src/crypto/sha256/sha256block.go
index ca5efd156..ca5efd156 100644
--- a/src/pkg/crypto/sha256/sha256block.go
+++ b/src/crypto/sha256/sha256block.go
diff --git a/src/pkg/crypto/sha256/sha256block_386.s b/src/crypto/sha256/sha256block_386.s
index 73ae2bf30..73ae2bf30 100644
--- a/src/pkg/crypto/sha256/sha256block_386.s
+++ b/src/crypto/sha256/sha256block_386.s
diff --git a/src/pkg/crypto/sha256/sha256block_amd64.s b/src/crypto/sha256/sha256block_amd64.s
index 95aebbe76..868eaed48 100644
--- a/src/pkg/crypto/sha256/sha256block_amd64.s
+++ b/src/crypto/sha256/sha256block_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// SHA256 block routine. See sha256block.go for Go equivalent.
//
diff --git a/src/pkg/crypto/sha256/sha256block_decl.go b/src/crypto/sha256/sha256block_decl.go
index a50c97871..a50c97871 100644
--- a/src/pkg/crypto/sha256/sha256block_decl.go
+++ b/src/crypto/sha256/sha256block_decl.go
diff --git a/src/pkg/crypto/sha512/sha512.go b/src/crypto/sha512/sha512.go
index bca7a91e2..bca7a91e2 100644
--- a/src/pkg/crypto/sha512/sha512.go
+++ b/src/crypto/sha512/sha512.go
diff --git a/src/pkg/crypto/sha512/sha512_test.go b/src/crypto/sha512/sha512_test.go
index 541860f70..541860f70 100644
--- a/src/pkg/crypto/sha512/sha512_test.go
+++ b/src/crypto/sha512/sha512_test.go
diff --git a/src/pkg/crypto/sha512/sha512block.go b/src/crypto/sha512/sha512block.go
index 648ae8f7e..648ae8f7e 100644
--- a/src/pkg/crypto/sha512/sha512block.go
+++ b/src/crypto/sha512/sha512block.go
diff --git a/src/pkg/crypto/sha512/sha512block_amd64.s b/src/crypto/sha512/sha512block_amd64.s
index 344d8d2c3..2e10233de 100644
--- a/src/pkg/crypto/sha512/sha512block_amd64.s
+++ b/src/crypto/sha512/sha512block_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// SHA512 block routine. See sha512block.go for Go equivalent.
//
diff --git a/src/pkg/crypto/sha512/sha512block_decl.go b/src/crypto/sha512/sha512block_decl.go
index bef99de2e..bef99de2e 100644
--- a/src/pkg/crypto/sha512/sha512block_decl.go
+++ b/src/crypto/sha512/sha512block_decl.go
diff --git a/src/pkg/crypto/subtle/constant_time.go b/src/crypto/subtle/constant_time.go
index 9c4b14a65..6f80e7c58 100644
--- a/src/pkg/crypto/subtle/constant_time.go
+++ b/src/crypto/subtle/constant_time.go
@@ -6,12 +6,12 @@
// code but require careful thought to use correctly.
package subtle
-// ConstantTimeCompare returns 1 iff the two equal length slices, x
+// ConstantTimeCompare returns 1 iff the two slices, x
// and y, have equal contents. The time taken is a function of the length of
// the slices and is independent of the contents.
func ConstantTimeCompare(x, y []byte) int {
if len(x) != len(y) {
- panic("subtle: slices have different lengths")
+ return 0
}
var v byte
@@ -62,7 +62,6 @@ func ConstantTimeCopy(v int, x, y []byte) {
for i := 0; i < len(x); i++ {
x[i] = x[i]&xmask | y[i]&ymask
}
- return
}
// ConstantTimeLessOrEq returns 1 if x <= y and 0 otherwise.
diff --git a/src/pkg/crypto/subtle/constant_time_test.go b/src/crypto/subtle/constant_time_test.go
index d8e321ec0..619a45444 100644
--- a/src/pkg/crypto/subtle/constant_time_test.go
+++ b/src/crypto/subtle/constant_time_test.go
@@ -18,6 +18,8 @@ var testConstantTimeCompareData = []TestConstantTimeCompareStruct{
{[]byte{}, []byte{}, 1},
{[]byte{0x11}, []byte{0x11}, 1},
{[]byte{0x12}, []byte{0x11}, 0},
+ {[]byte{0x11}, []byte{0x11, 0x12}, 0},
+ {[]byte{0x11, 0x12}, []byte{0x11}, 0},
}
func TestConstantTimeCompare(t *testing.T) {
diff --git a/src/pkg/crypto/tls/alert.go b/src/crypto/tls/alert.go
index 0856311e4..3de4834d3 100644
--- a/src/pkg/crypto/tls/alert.go
+++ b/src/crypto/tls/alert.go
@@ -35,6 +35,7 @@ const (
alertProtocolVersion alert = 70
alertInsufficientSecurity alert = 71
alertInternalError alert = 80
+ alertInappropriateFallback alert = 86
alertUserCanceled alert = 90
alertNoRenegotiation alert = 100
)
@@ -60,6 +61,7 @@ var alertText = map[alert]string{
alertProtocolVersion: "protocol version not supported",
alertInsufficientSecurity: "insufficient security level",
alertInternalError: "internal error",
+ alertInappropriateFallback: "inappropriate fallback",
alertUserCanceled: "user canceled",
alertNoRenegotiation: "no renegotiation",
}
diff --git a/src/pkg/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go
index 39a51459d..226e06d68 100644
--- a/src/pkg/crypto/tls/cipher_suites.go
+++ b/src/crypto/tls/cipher_suites.go
@@ -267,4 +267,9 @@ const (
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
+
+ // TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator
+ // that the client is doing version fallback. See
+ // https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00.
+ TLS_FALLBACK_SCSV uint16 = 0x5600
)
diff --git a/src/pkg/crypto/tls/common.go b/src/crypto/tls/common.go
index fca98bdd1..776b70c93 100644
--- a/src/pkg/crypto/tls/common.go
+++ b/src/crypto/tls/common.go
@@ -72,6 +72,7 @@ const (
extensionSupportedCurves uint16 = 10
extensionSupportedPoints uint16 = 11
extensionSignatureAlgorithms uint16 = 13
+ extensionALPN uint16 = 16
extensionSessionTicket uint16 = 35
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionRenegotiationInfo uint16 = 0xff01
@@ -164,6 +165,14 @@ type ConnectionState struct {
ServerName string // server name requested by client, if any (server side only)
PeerCertificates []*x509.Certificate // certificate chain presented by remote peer
VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
+
+ // TLSUnique contains the "tls-unique" channel binding value (see RFC
+ // 5929, section 3). For resumed sessions this value will be nil
+ // because resumption does not include enough context (see
+ // https://secure-resumption.com/#channelbindings). This will change in
+ // future versions of Go once the TLS master-secret fix has been
+ // standardized and implemented.
+ TLSUnique []byte
}
// ClientAuthType declares the policy the server will follow for
@@ -201,6 +210,32 @@ type ClientSessionCache interface {
Put(sessionKey string, cs *ClientSessionState)
}
+// ClientHelloInfo contains information from a ClientHello message in order to
+// guide certificate selection in the GetCertificate callback.
+type ClientHelloInfo struct {
+ // CipherSuites lists the CipherSuites supported by the client (e.g.
+ // TLS_RSA_WITH_RC4_128_SHA).
+ CipherSuites []uint16
+
+ // ServerName indicates the name of the server requested by the client
+ // in order to support virtual hosting. ServerName is only set if the
+ // client is using SNI (see
+ // http://tools.ietf.org/html/rfc4366#section-3.1).
+ ServerName string
+
+ // SupportedCurves lists the elliptic curves supported by the client.
+ // SupportedCurves is set only if the Supported Elliptic Curves
+ // Extension is being used (see
+ // http://tools.ietf.org/html/rfc4492#section-5.1.1).
+ SupportedCurves []CurveID
+
+ // SupportedPoints lists the point formats supported by the client.
+ // SupportedPoints is set only if the Supported Point Formats Extension
+ // is being used (see
+ // http://tools.ietf.org/html/rfc4492#section-5.1.2).
+ SupportedPoints []uint8
+}
+
// A Config structure is used to configure a TLS client or server.
// After one has been passed to a TLS function it must not be
// modified. A Config may be reused; the tls package will also not
@@ -229,6 +264,13 @@ type Config struct {
// for all connections.
NameToCertificate map[string]*Certificate
+ // GetCertificate returns a Certificate based on the given
+ // ClientHelloInfo. If GetCertificate is nil or returns nil, then the
+ // certificate is retrieved from NameToCertificate. If
+ // NameToCertificate is nil, the first element of Certificates will be
+ // used.
+ GetCertificate func(clientHello *ClientHelloInfo) (*Certificate, error)
+
// RootCAs defines the set of root certificate authorities
// that clients use when verifying server certificates.
// If RootCAs is nil, TLS uses the host's root CA set.
@@ -383,22 +425,28 @@ func (c *Config) mutualVersion(vers uint16) (uint16, bool) {
return vers, true
}
-// getCertificateForName returns the best certificate for the given name,
-// defaulting to the first element of c.Certificates if there are no good
-// options.
-func (c *Config) getCertificateForName(name string) *Certificate {
+// getCertificate returns the best certificate for the given ClientHelloInfo,
+// defaulting to the first element of c.Certificates.
+func (c *Config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, error) {
+ if c.GetCertificate != nil {
+ cert, err := c.GetCertificate(clientHello)
+ if cert != nil || err != nil {
+ return cert, err
+ }
+ }
+
if len(c.Certificates) == 1 || c.NameToCertificate == nil {
// There's only one choice, so no point doing any work.
- return &c.Certificates[0]
+ return &c.Certificates[0], nil
}
- name = strings.ToLower(name)
+ name := strings.ToLower(clientHello.ServerName)
for len(name) > 0 && name[len(name)-1] == '.' {
name = name[:len(name)-1]
}
if cert, ok := c.NameToCertificate[name]; ok {
- return cert
+ return cert, nil
}
// try replacing labels in the name with wildcards until we get a
@@ -408,12 +456,12 @@ func (c *Config) getCertificateForName(name string) *Certificate {
labels[i] = "*"
candidate := strings.Join(labels, ".")
if cert, ok := c.NameToCertificate[candidate]; ok {
- return cert
+ return cert, nil
}
}
// If nothing matches, return the first certificate.
- return &c.Certificates[0]
+ return &c.Certificates[0], nil
}
// BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate
@@ -439,7 +487,12 @@ func (c *Config) BuildNameToCertificate() {
// A Certificate is a chain of one or more certificates, leaf first.
type Certificate struct {
Certificate [][]byte
- PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey
+ // PrivateKey contains the private key corresponding to the public key
+ // in Leaf. For a server, this must be a *rsa.PrivateKey or
+ // *ecdsa.PrivateKey. For a client doing client authentication, this
+ // can be any type that implements crypto.Signer (which includes RSA
+ // and ECDSA private keys).
+ PrivateKey crypto.PrivateKey
// OCSPStaple contains an optional OCSP response which will be served
// to clients that request it.
OCSPStaple []byte
diff --git a/src/pkg/crypto/tls/conn.go b/src/crypto/tls/conn.go
index 8f7d2c144..ba8e4c22b 100644
--- a/src/pkg/crypto/tls/conn.go
+++ b/src/crypto/tls/conn.go
@@ -42,6 +42,9 @@ type Conn struct {
verifiedChains [][]*x509.Certificate
// serverName contains the server name indicated by the client, if any.
serverName string
+ // firstFinished contains the first Finished hash sent during the
+ // handshake. This is the "tls-unique" channel binding value.
+ firstFinished [12]byte
clientProtocol string
clientProtocolFallback bool
@@ -994,6 +997,9 @@ func (c *Conn) ConnectionState() ConnectionState {
state.PeerCertificates = c.peerCertificates
state.VerifiedChains = c.verifiedChains
state.ServerName = c.serverName
+ if !c.didResume {
+ state.TLSUnique = c.firstFinished[:]
+ }
}
return state
diff --git a/src/pkg/crypto/tls/conn_test.go b/src/crypto/tls/conn_test.go
index 5c555147c..ec802cad7 100644
--- a/src/pkg/crypto/tls/conn_test.go
+++ b/src/crypto/tls/conn_test.go
@@ -88,19 +88,31 @@ func TestCertificateSelection(t *testing.T) {
return -1
}
- if n := pointerToIndex(config.getCertificateForName("example.com")); n != 0 {
+ certificateForName := func(name string) *Certificate {
+ clientHello := &ClientHelloInfo{
+ ServerName: name,
+ }
+ if cert, err := config.getCertificate(clientHello); err != nil {
+ t.Errorf("unable to get certificate for name '%s': %s", name, err)
+ return nil
+ } else {
+ return cert
+ }
+ }
+
+ if n := pointerToIndex(certificateForName("example.com")); n != 0 {
t.Errorf("example.com returned certificate %d, not 0", n)
}
- if n := pointerToIndex(config.getCertificateForName("bar.example.com")); n != 1 {
+ if n := pointerToIndex(certificateForName("bar.example.com")); n != 1 {
t.Errorf("bar.example.com returned certificate %d, not 1", n)
}
- if n := pointerToIndex(config.getCertificateForName("foo.example.com")); n != 2 {
+ if n := pointerToIndex(certificateForName("foo.example.com")); n != 2 {
t.Errorf("foo.example.com returned certificate %d, not 2", n)
}
- if n := pointerToIndex(config.getCertificateForName("foo.bar.example.com")); n != 3 {
+ if n := pointerToIndex(certificateForName("foo.bar.example.com")); n != 3 {
t.Errorf("foo.bar.example.com returned certificate %d, not 3", n)
}
- if n := pointerToIndex(config.getCertificateForName("foo.bar.baz.example.com")); n != 0 {
+ if n := pointerToIndex(certificateForName("foo.bar.baz.example.com")); n != 0 {
t.Errorf("foo.bar.baz.example.com returned certificate %d, not 0", n)
}
}
diff --git a/src/pkg/crypto/tls/example_test.go b/src/crypto/tls/example_test.go
index 7628e431b..7628e431b 100644
--- a/src/pkg/crypto/tls/example_test.go
+++ b/src/crypto/tls/example_test.go
diff --git a/src/pkg/crypto/tls/generate_cert.go b/src/crypto/tls/generate_cert.go
index 5c6d8396d..83f9916ff 100644
--- a/src/pkg/crypto/tls/generate_cert.go
+++ b/src/crypto/tls/generate_cert.go
@@ -10,6 +10,8 @@
package main
import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
@@ -26,13 +28,41 @@ import (
)
var (
- host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
- validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011")
- validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
- isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
- rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate")
+ host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
+ validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011")
+ validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
+ isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
+ rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set")
+ ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521")
)
+func publicKey(priv interface{}) interface{} {
+ switch k := priv.(type) {
+ case *rsa.PrivateKey:
+ return &k.PublicKey
+ case *ecdsa.PrivateKey:
+ return &k.PublicKey
+ default:
+ return nil
+ }
+}
+
+func pemBlockForKey(priv interface{}) *pem.Block {
+ switch k := priv.(type) {
+ case *rsa.PrivateKey:
+ return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
+ case *ecdsa.PrivateKey:
+ b, err := x509.MarshalECPrivateKey(k)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
+ os.Exit(2)
+ }
+ return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
+ default:
+ return nil
+ }
+}
+
func main() {
flag.Parse()
@@ -40,7 +70,23 @@ func main() {
log.Fatalf("Missing required --host parameter")
}
- priv, err := rsa.GenerateKey(rand.Reader, *rsaBits)
+ var priv interface{}
+ var err error
+ switch *ecdsaCurve {
+ case "":
+ priv, err = rsa.GenerateKey(rand.Reader, *rsaBits)
+ case "P224":
+ priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
+ case "P256":
+ priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ case "P384":
+ priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
+ case "P521":
+ priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
+ default:
+ fmt.Fprintf(os.Stderr, "Unrecognized elliptic curve: %q", *ecdsaCurve)
+ os.Exit(1)
+ }
if err != nil {
log.Fatalf("failed to generate private key: %s", err)
}
@@ -91,7 +137,7 @@ func main() {
template.KeyUsage |= x509.KeyUsageCertSign
}
- derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
+ derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
if err != nil {
log.Fatalf("Failed to create certificate: %s", err)
}
@@ -109,7 +155,7 @@ func main() {
log.Print("failed to open key.pem for writing:", err)
return
}
- pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
+ pem.Encode(keyOut, pemBlockForKey(priv))
keyOut.Close()
log.Print("written key.pem\n")
}
diff --git a/src/pkg/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go
index a320fde1b..7f662e9c9 100644
--- a/src/pkg/crypto/tls/handshake_client.go
+++ b/src/crypto/tls/handshake_client.go
@@ -6,11 +6,11 @@ package tls
import (
"bytes"
+ "crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
- "encoding/asn1"
"errors"
"fmt"
"io"
@@ -37,6 +37,18 @@ func (c *Conn) clientHandshake() error {
return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
}
+ nextProtosLength := 0
+ for _, proto := range c.config.NextProtos {
+ if l := len(proto); l == 0 || l > 255 {
+ return errors.New("tls: invalid NextProtos value")
+ } else {
+ nextProtosLength += 1 + l
+ }
+ }
+ if nextProtosLength > 0xffff {
+ return errors.New("tls: NextProtos values too large")
+ }
+
hello := &clientHelloMsg{
vers: c.config.maxVersion(),
compressionMethods: []uint8{compressionNone},
@@ -47,6 +59,7 @@ func (c *Conn) clientHandshake() error {
supportedPoints: []uint8{pointFormatUncompressed},
nextProtoNeg: len(c.config.NextProtos) > 0,
secureRenegotiation: true,
+ alpnProtocols: c.config.NextProtos,
}
possibleCipherSuites := c.config.cipherSuites()
@@ -174,10 +187,10 @@ NextCipherSuite:
if err := hs.readSessionTicket(); err != nil {
return err
}
- if err := hs.readFinished(); err != nil {
+ if err := hs.readFinished(c.firstFinished[:]); err != nil {
return err
}
- if err := hs.sendFinished(); err != nil {
+ if err := hs.sendFinished(nil); err != nil {
return err
}
} else {
@@ -187,13 +200,13 @@ NextCipherSuite:
if err := hs.establishKeys(); err != nil {
return err
}
- if err := hs.sendFinished(); err != nil {
+ if err := hs.sendFinished(c.firstFinished[:]); err != nil {
return err
}
if err := hs.readSessionTicket(); err != nil {
return err
}
- if err := hs.readFinished(); err != nil {
+ if err := hs.readFinished(nil); err != nil {
return err
}
}
@@ -332,8 +345,8 @@ func (hs *clientHandshakeState) doFullHandshake() error {
}
// We need to search our list of client certs for one
- // where SignatureAlgorithm is RSA and the Issuer is in
- // certReq.certificateAuthorities
+ // where SignatureAlgorithm is acceptable to the server and the
+ // Issuer is in certReq.certificateAuthorities
findCert:
for i, chain := range c.config.Certificates {
if !rsaAvail && !ecdsaAvail {
@@ -360,7 +373,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
if len(certReq.certificateAuthorities) == 0 {
// they gave us an empty list, so just take the
- // first RSA cert from c.config.Certificates
+ // first cert from c.config.Certificates
chainToSend = &chain
break findCert
}
@@ -415,22 +428,24 @@ func (hs *clientHandshakeState) doFullHandshake() error {
hasSignatureAndHash: c.vers >= VersionTLS12,
}
- switch key := c.config.Certificates[0].PrivateKey.(type) {
- case *ecdsa.PrivateKey:
- digest, _, hashId := hs.finishedHash.hashForClientCertificate(signatureECDSA)
- r, s, err := ecdsa.Sign(c.config.rand(), key, digest)
- if err == nil {
- signed, err = asn1.Marshal(ecdsaSignature{r, s})
- }
+ key, ok := chainToSend.PrivateKey.(crypto.Signer)
+ if !ok {
+ c.sendAlert(alertInternalError)
+ return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey)
+ }
+ switch key.Public().(type) {
+ case *ecdsa.PublicKey:
+ digest, hashFunc, hashId := hs.finishedHash.hashForClientCertificate(signatureECDSA)
+ signed, err = key.Sign(c.config.rand(), digest, hashFunc)
certVerify.signatureAndHash.signature = signatureECDSA
certVerify.signatureAndHash.hash = hashId
- case *rsa.PrivateKey:
+ case *rsa.PublicKey:
digest, hashFunc, hashId := hs.finishedHash.hashForClientCertificate(signatureRSA)
- signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
+ signed, err = key.Sign(c.config.rand(), digest, hashFunc)
certVerify.signatureAndHash.signature = signatureRSA
certVerify.signatureAndHash.hash = hashId
default:
- err = errors.New("unknown private key type")
+ err = fmt.Errorf("tls: unknown client certificate key type: %T", key)
}
if err != nil {
c.sendAlert(alertInternalError)
@@ -483,11 +498,31 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
return false, errors.New("tls: server selected unsupported compression format")
}
- if !hs.hello.nextProtoNeg && hs.serverHello.nextProtoNeg {
+ clientDidNPN := hs.hello.nextProtoNeg
+ clientDidALPN := len(hs.hello.alpnProtocols) > 0
+ serverHasNPN := hs.serverHello.nextProtoNeg
+ serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
+
+ if !clientDidNPN && serverHasNPN {
c.sendAlert(alertHandshakeFailure)
return false, errors.New("server advertised unrequested NPN extension")
}
+ if !clientDidALPN && serverHasALPN {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("server advertised unrequested ALPN extension")
+ }
+
+ if serverHasNPN && serverHasALPN {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("server advertised both NPN and ALPN extensions")
+ }
+
+ if serverHasALPN {
+ c.clientProtocol = hs.serverHello.alpnProtocol
+ c.clientProtocolFallback = false
+ }
+
if hs.serverResumedSession() {
// Restore masterSecret and peerCerts from previous state
hs.masterSecret = hs.session.masterSecret
@@ -497,7 +532,7 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
return false, nil
}
-func (hs *clientHandshakeState) readFinished() error {
+func (hs *clientHandshakeState) readFinished(out []byte) error {
c := hs.c
c.readRecord(recordTypeChangeCipherSpec)
@@ -522,6 +557,7 @@ func (hs *clientHandshakeState) readFinished() error {
return errors.New("tls: server's Finished message was incorrect")
}
hs.finishedHash.Write(serverFinished.marshal())
+ copy(out, verify)
return nil
}
@@ -553,7 +589,7 @@ func (hs *clientHandshakeState) readSessionTicket() error {
return nil
}
-func (hs *clientHandshakeState) sendFinished() error {
+func (hs *clientHandshakeState) sendFinished(out []byte) error {
c := hs.c
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
@@ -572,6 +608,7 @@ func (hs *clientHandshakeState) sendFinished() error {
finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
hs.finishedHash.Write(finished.marshal())
c.writeRecord(recordTypeHandshake, finished.marshal())
+ copy(out, finished.verifyData)
return nil
}
@@ -584,18 +621,18 @@ func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
return serverAddr.String()
}
-// mutualProtocol finds the mutual Next Protocol Negotiation protocol given the
-// set of client and server supported protocols. The set of client supported
-// protocols must not be empty. It returns the resulting protocol and flag
+// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
+// given list of possible protocols and a list of the preference order. The
+// first list must not be empty. It returns the resulting protocol and flag
// indicating if the fallback case was reached.
-func mutualProtocol(clientProtos, serverProtos []string) (string, bool) {
- for _, s := range serverProtos {
- for _, c := range clientProtos {
+func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
+ for _, s := range preferenceProtos {
+ for _, c := range protos {
if s == c {
return s, false
}
}
}
- return clientProtos[0], true
+ return protos[0], true
}
diff --git a/src/pkg/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go
index 0d73c8e2f..e5eaa7de2 100644
--- a/src/pkg/crypto/tls/handshake_client_test.go
+++ b/src/crypto/tls/handshake_client_test.go
@@ -49,6 +49,10 @@ type clientTest struct {
// key, if not nil, contains either a *rsa.PrivateKey or
// *ecdsa.PrivateKey which is the private key for the reference server.
key interface{}
+ // validate, if not nil, is a function that will be called with the
+ // ConnectionState of the resulting connection. It returns a non-nil
+ // error if the ConnectionState is unacceptable.
+ validate func(ConnectionState) error
}
var defaultServerCommand = []string{"openssl", "s_server"}
@@ -188,6 +192,11 @@ func (test *clientTest) run(t *testing.T, write bool) {
if _, err := client.Write([]byte("hello\n")); err != nil {
t.Logf("Client.Write failed: %s", err)
}
+ if test.validate != nil {
+ if err := test.validate(client.ConnectionState()); err != nil {
+ t.Logf("validate callback returned error: %s", err)
+ }
+ }
client.Close()
clientConn.Close()
doneChan <- true
@@ -196,7 +205,7 @@ func (test *clientTest) run(t *testing.T, write bool) {
if !write {
flows, err := test.loadData()
if err != nil {
- t.Fatalf("%s: failed to load data from %s", test.name, test.dataPath())
+ t.Fatalf("%s: failed to load data from %s: %v", test.name, test.dataPath(), err)
}
for i, b := range flows {
if i%2 == 1 {
@@ -437,3 +446,45 @@ func TestLRUClientSessionCache(t *testing.T) {
t.Fatalf("failed to add nil entry to cache")
}
}
+
+func TestHandshakeClientALPNMatch(t *testing.T) {
+ config := *testConfig
+ config.NextProtos = []string{"proto2", "proto1"}
+
+ test := &clientTest{
+ name: "ALPN",
+ // Note that this needs OpenSSL 1.0.2 because that is the first
+ // version that supports the -alpn flag.
+ command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"},
+ config: &config,
+ validate: func(state ConnectionState) error {
+ // The server's preferences should override the client.
+ if state.NegotiatedProtocol != "proto1" {
+ return fmt.Errorf("Got protocol %q, wanted proto1", state.NegotiatedProtocol)
+ }
+ return nil
+ },
+ }
+ runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientALPNNoMatch(t *testing.T) {
+ config := *testConfig
+ config.NextProtos = []string{"proto3"}
+
+ test := &clientTest{
+ name: "ALPN-NoMatch",
+ // Note that this needs OpenSSL 1.0.2 because that is the first
+ // version that supports the -alpn flag.
+ command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"},
+ config: &config,
+ validate: func(state ConnectionState) error {
+ // There's no overlap so OpenSSL will not select a protocol.
+ if state.NegotiatedProtocol != "" {
+ return fmt.Errorf("Got protocol %q, wanted ''", state.NegotiatedProtocol)
+ }
+ return nil
+ },
+ }
+ runClientTestTLS12(t, test)
+}
diff --git a/src/pkg/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go
index 7bcaa5eb9..5d14871a3 100644
--- a/src/pkg/crypto/tls/handshake_messages.go
+++ b/src/crypto/tls/handshake_messages.go
@@ -22,6 +22,7 @@ type clientHelloMsg struct {
sessionTicket []uint8
signatureAndHashes []signatureAndHash
secureRenegotiation bool
+ alpnProtocols []string
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -44,7 +45,8 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
m.ticketSupported == m1.ticketSupported &&
bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) &&
- m.secureRenegotiation == m1.secureRenegotiation
+ m.secureRenegotiation == m1.secureRenegotiation &&
+ eqStrings(m.alpnProtocols, m1.alpnProtocols)
}
func (m *clientHelloMsg) marshal() []byte {
@@ -86,6 +88,17 @@ func (m *clientHelloMsg) marshal() []byte {
extensionsLength += 1
numExtensions++
}
+ if len(m.alpnProtocols) > 0 {
+ extensionsLength += 2
+ for _, s := range m.alpnProtocols {
+ if l := len(s); l == 0 || l > 255 {
+ panic("invalid ALPN protocol")
+ }
+ extensionsLength++
+ extensionsLength += len(s)
+ }
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -237,6 +250,27 @@ func (m *clientHelloMsg) marshal() []byte {
z[3] = 1
z = z[5:]
}
+ if len(m.alpnProtocols) > 0 {
+ z[0] = byte(extensionALPN >> 8)
+ z[1] = byte(extensionALPN & 0xff)
+ lengths := z[2:]
+ z = z[6:]
+
+ stringsLength := 0
+ for _, s := range m.alpnProtocols {
+ l := len(s)
+ z[0] = byte(l)
+ copy(z[1:], s)
+ z = z[1+l:]
+ stringsLength += 1 + l
+ }
+
+ lengths[2] = byte(stringsLength >> 8)
+ lengths[3] = byte(stringsLength)
+ stringsLength += 2
+ lengths[0] = byte(stringsLength >> 8)
+ lengths[1] = byte(stringsLength)
+ }
m.raw = x
@@ -291,6 +325,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.ticketSupported = false
m.sessionTicket = nil
m.signatureAndHashes = nil
+ m.alpnProtocols = nil
if len(data) == 0 {
// ClientHello is optionally followed by extension data
@@ -400,6 +435,24 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
return false
}
m.secureRenegotiation = true
+ case extensionALPN:
+ if length < 2 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l != length-2 {
+ return false
+ }
+ d := data[2:length]
+ for len(d) != 0 {
+ stringLen := int(d[0])
+ d = d[1:]
+ if stringLen == 0 || stringLen > len(d) {
+ return false
+ }
+ m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
+ d = d[stringLen:]
+ }
}
data = data[length:]
}
@@ -419,6 +472,7 @@ type serverHelloMsg struct {
ocspStapling bool
ticketSupported bool
secureRenegotiation bool
+ alpnProtocol string
}
func (m *serverHelloMsg) equal(i interface{}) bool {
@@ -437,7 +491,8 @@ func (m *serverHelloMsg) equal(i interface{}) bool {
eqStrings(m.nextProtos, m1.nextProtos) &&
m.ocspStapling == m1.ocspStapling &&
m.ticketSupported == m1.ticketSupported &&
- m.secureRenegotiation == m1.secureRenegotiation
+ m.secureRenegotiation == m1.secureRenegotiation &&
+ m.alpnProtocol == m1.alpnProtocol
}
func (m *serverHelloMsg) marshal() []byte {
@@ -468,6 +523,14 @@ func (m *serverHelloMsg) marshal() []byte {
extensionsLength += 1
numExtensions++
}
+ if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
+ if alpnLen >= 256 {
+ panic("invalid ALPN protocol")
+ }
+ extensionsLength += 2 + 1 + alpnLen
+ numExtensions++
+ }
+
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -528,6 +591,20 @@ func (m *serverHelloMsg) marshal() []byte {
z[3] = 1
z = z[5:]
}
+ if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
+ z[0] = byte(extensionALPN >> 8)
+ z[1] = byte(extensionALPN & 0xff)
+ l := 2 + 1 + alpnLen
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ l -= 2
+ z[4] = byte(l >> 8)
+ z[5] = byte(l)
+ l -= 1
+ z[6] = byte(l)
+ copy(z[7:], []byte(m.alpnProtocol))
+ z = z[7+alpnLen:]
+ }
m.raw = x
@@ -558,6 +635,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.nextProtos = nil
m.ocspStapling = false
m.ticketSupported = false
+ m.alpnProtocol = ""
if len(data) == 0 {
// ServerHello is optionally followed by extension data
@@ -612,6 +690,22 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
return false
}
m.secureRenegotiation = true
+ case extensionALPN:
+ d := data[:length]
+ if len(d) < 3 {
+ return false
+ }
+ l := int(d[0])<<8 | int(d[1])
+ if l != len(d)-2 {
+ return false
+ }
+ d = d[2:]
+ l = int(d[0])
+ if l != len(d)-1 {
+ return false
+ }
+ d = d[1:]
+ m.alpnProtocol = string(d)
}
data = data[length:]
}
diff --git a/src/pkg/crypto/tls/handshake_messages_test.go b/src/crypto/tls/handshake_messages_test.go
index f46aabdfd..a96e95c3f 100644
--- a/src/pkg/crypto/tls/handshake_messages_test.go
+++ b/src/crypto/tls/handshake_messages_test.go
@@ -138,6 +138,10 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
if rand.Intn(10) > 5 {
m.signatureAndHashes = supportedSKXSignatureAlgorithms
}
+ m.alpnProtocols = make([]string, rand.Intn(5))
+ for i := range m.alpnProtocols {
+ m.alpnProtocols[i] = randomString(rand.Intn(20)+1, rand)
+ }
return reflect.ValueOf(m)
}
@@ -166,6 +170,7 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
if rand.Intn(10) > 5 {
m.ticketSupported = true
}
+ m.alpnProtocol = randomString(rand.Intn(32)+1, rand)
return reflect.ValueOf(m)
}
diff --git a/src/pkg/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go
index dff6fd9ad..0d907656c 100644
--- a/src/pkg/crypto/tls/handshake_server.go
+++ b/src/crypto/tls/handshake_server.go
@@ -57,10 +57,10 @@ func (c *Conn) serverHandshake() error {
if err := hs.establishKeys(); err != nil {
return err
}
- if err := hs.sendFinished(); err != nil {
+ if err := hs.sendFinished(c.firstFinished[:]); err != nil {
return err
}
- if err := hs.readFinished(); err != nil {
+ if err := hs.readFinished(nil); err != nil {
return err
}
c.didResume = true
@@ -73,13 +73,13 @@ func (c *Conn) serverHandshake() error {
if err := hs.establishKeys(); err != nil {
return err
}
- if err := hs.readFinished(); err != nil {
+ if err := hs.readFinished(c.firstFinished[:]); err != nil {
return err
}
if err := hs.sendSessionTicket(); err != nil {
return err
}
- if err := hs.sendFinished(); err != nil {
+ if err := hs.sendFinished(nil); err != nil {
return err
}
}
@@ -163,13 +163,21 @@ Curves:
if len(hs.clientHello.serverName) > 0 {
c.serverName = hs.clientHello.serverName
}
- // Although sending an empty NPN extension is reasonable, Firefox has
- // had a bug around this. Best to send nothing at all if
- // config.NextProtos is empty. See
- // https://code.google.com/p/go/issues/detail?id=5445.
- if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
- hs.hello.nextProtoNeg = true
- hs.hello.nextProtos = config.NextProtos
+
+ if len(hs.clientHello.alpnProtocols) > 0 {
+ if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
+ hs.hello.alpnProtocol = selectedProto
+ c.clientProtocol = selectedProto
+ }
+ } else {
+ // Although sending an empty NPN extension is reasonable, Firefox has
+ // had a bug around this. Best to send nothing at all if
+ // config.NextProtos is empty. See
+ // https://code.google.com/p/go/issues/detail?id=5445.
+ if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
+ hs.hello.nextProtoNeg = true
+ hs.hello.nextProtos = config.NextProtos
+ }
}
if len(config.Certificates) == 0 {
@@ -178,7 +186,16 @@ Curves:
}
hs.cert = &config.Certificates[0]
if len(hs.clientHello.serverName) > 0 {
- hs.cert = config.getCertificateForName(hs.clientHello.serverName)
+ chi := &ClientHelloInfo{
+ CipherSuites: hs.clientHello.cipherSuites,
+ ServerName: hs.clientHello.serverName,
+ SupportedCurves: hs.clientHello.supportedCurves,
+ SupportedPoints: hs.clientHello.supportedPoints,
+ }
+ if hs.cert, err = config.getCertificate(chi); err != nil {
+ c.sendAlert(alertInternalError)
+ return false, err
+ }
}
_, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
@@ -207,6 +224,18 @@ Curves:
return false, errors.New("tls: no cipher suite supported by both client and server")
}
+ // See https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00.
+ for _, id := range hs.clientHello.cipherSuites {
+ if id == TLS_FALLBACK_SCSV {
+ // The client is doing a fallback connection.
+ if hs.clientHello.vers < c.config.MaxVersion {
+ c.sendAlert(alertInappropriateFallback)
+ return false, errors.New("tls: client using inppropriate protocol fallback")
+ }
+ break
+ }
+ }
+
return false, nil
}
@@ -470,7 +499,7 @@ func (hs *serverHandshakeState) establishKeys() error {
return nil
}
-func (hs *serverHandshakeState) readFinished() error {
+func (hs *serverHandshakeState) readFinished(out []byte) error {
c := hs.c
c.readRecord(recordTypeChangeCipherSpec)
@@ -510,6 +539,7 @@ func (hs *serverHandshakeState) readFinished() error {
}
hs.finishedHash.Write(clientFinished.marshal())
+ copy(out, verify)
return nil
}
@@ -539,7 +569,7 @@ func (hs *serverHandshakeState) sendSessionTicket() error {
return nil
}
-func (hs *serverHandshakeState) sendFinished() error {
+func (hs *serverHandshakeState) sendFinished(out []byte) error {
c := hs.c
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
@@ -550,6 +580,7 @@ func (hs *serverHandshakeState) sendFinished() error {
c.writeRecord(recordTypeHandshake, finished.marshal())
c.cipherSuite = hs.suite.id
+ copy(out, finished.verifyData)
return nil
}
diff --git a/src/pkg/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go
index 3444d5ca8..0338af457 100644
--- a/src/pkg/crypto/tls/handshake_server_test.go
+++ b/src/crypto/tls/handshake_server_test.go
@@ -9,7 +9,6 @@ import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rsa"
- "crypto/x509"
"encoding/hex"
"encoding/pem"
"errors"
@@ -258,6 +257,16 @@ type serverTest struct {
expectedPeerCerts []string
// config, if not nil, contains a custom Config to use for this test.
config *Config
+ // expectAlert, if true, indicates that a fatal alert should be returned
+ // when handshaking with the server.
+ expectAlert bool
+ // expectHandshakeErrorIncluding, when not empty, contains a string
+ // that must be a substring of the error resulting from the handshake.
+ expectHandshakeErrorIncluding string
+ // validate, if not nil, is a function that will be called with the
+ // ConnectionState of the resulting connection. It returns false if the
+ // ConnectionState is unacceptable.
+ validate func(ConnectionState) error
}
var defaultClientCommand = []string{"openssl", "s_client", "-no_ticket"}
@@ -354,20 +363,30 @@ func (test *serverTest) run(t *testing.T, write bool) {
config = testConfig
}
server := Server(serverConn, config)
- peerCertsChan := make(chan []*x509.Certificate, 1)
+ connStateChan := make(chan ConnectionState, 1)
go func() {
- if _, err := server.Write([]byte("hello, world\n")); err != nil {
+ var err error
+ if _, err = server.Write([]byte("hello, world\n")); err != nil {
t.Logf("Error from Server.Write: %s", err)
}
+ if len(test.expectHandshakeErrorIncluding) > 0 {
+ if err == nil {
+ t.Errorf("Error expected, but no error returned")
+ } else if s := err.Error(); !strings.Contains(s, test.expectHandshakeErrorIncluding) {
+ t.Errorf("Error expected containing '%s' but got '%s'", test.expectHandshakeErrorIncluding, s)
+ }
+ }
server.Close()
serverConn.Close()
- peerCertsChan <- server.ConnectionState().PeerCertificates
+ connStateChan <- server.ConnectionState()
}()
if !write {
flows, err := test.loadData()
if err != nil {
- t.Fatalf("%s: failed to load data from %s", test.name, test.dataPath())
+ if !test.expectAlert {
+ t.Fatalf("%s: failed to load data from %s", test.name, test.dataPath())
+ }
}
for i, b := range flows {
if i%2 == 0 {
@@ -376,17 +395,24 @@ func (test *serverTest) run(t *testing.T, write bool) {
}
bb := make([]byte, len(b))
n, err := io.ReadFull(clientConn, bb)
- if err != nil {
- t.Fatalf("%s #%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", test.name, i+1, err, n, len(bb), bb[:n], b)
- }
- if !bytes.Equal(b, bb) {
- t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", test.name, i+1, bb, b)
+ if test.expectAlert {
+ if err == nil {
+ t.Fatal("Expected read failure but read succeeded")
+ }
+ } else {
+ if err != nil {
+ t.Fatalf("%s #%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", test.name, i+1, err, n, len(bb), bb[:n], b)
+ }
+ if !bytes.Equal(b, bb) {
+ t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", test.name, i+1, bb, b)
+ }
}
}
clientConn.Close()
}
- peerCerts := <-peerCertsChan
+ connState := <-connStateChan
+ peerCerts := connState.PeerCertificates
if len(peerCerts) == len(test.expectedPeerCerts) {
for i, peerCert := range peerCerts {
block, _ := pem.Decode([]byte(test.expectedPeerCerts[i]))
@@ -398,6 +424,12 @@ func (test *serverTest) run(t *testing.T, write bool) {
t.Fatalf("%s: mismatch on peer list length: %d (wanted) != %d (got)", test.name, len(test.expectedPeerCerts), len(peerCerts))
}
+ if test.validate != nil {
+ if err := test.validate(connState); err != nil {
+ t.Fatalf("validate callback returned error: %s", err)
+ }
+ }
+
if write {
path := test.dataPath()
out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
@@ -408,7 +440,9 @@ func (test *serverTest) run(t *testing.T, write bool) {
recordingConn.Close()
if len(recordingConn.flows) < 3 {
childProcess.Stdout.(*bytes.Buffer).WriteTo(os.Stdout)
- t.Fatalf("Handshake failed")
+ if len(test.expectHandshakeErrorIncluding) == 0 {
+ t.Fatalf("Handshake failed")
+ }
}
recordingConn.WriteTo(out)
fmt.Printf("Wrote %s\n", path)
@@ -498,6 +532,49 @@ func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
runServerTestTLS12(t, test)
}
+func TestHandshakeServerALPN(t *testing.T) {
+ config := *testConfig
+ config.NextProtos = []string{"proto1", "proto2"}
+
+ test := &serverTest{
+ name: "ALPN",
+ // Note that this needs OpenSSL 1.0.2 because that is the first
+ // version that supports the -alpn flag.
+ command: []string{"openssl", "s_client", "-alpn", "proto2,proto1"},
+ config: &config,
+ validate: func(state ConnectionState) error {
+ // The server's preferences should override the client.
+ if state.NegotiatedProtocol != "proto1" {
+ return fmt.Errorf("Got protocol %q, wanted proto1", state.NegotiatedProtocol)
+ }
+ return nil
+ },
+ }
+ runServerTestTLS12(t, test)
+}
+
+func TestHandshakeServerALPNNoMatch(t *testing.T) {
+ config := *testConfig
+ config.NextProtos = []string{"proto3"}
+
+ test := &serverTest{
+ name: "ALPN-NoMatch",
+ // Note that this needs OpenSSL 1.0.2 because that is the first
+ // version that supports the -alpn flag.
+ command: []string{"openssl", "s_client", "-alpn", "proto2,proto1"},
+ config: &config,
+ validate: func(state ConnectionState) error {
+ // Rather than reject the connection, Go doesn't select
+ // a protocol when there is no overlap.
+ if state.NegotiatedProtocol != "" {
+ return fmt.Errorf("Got protocol %q, wanted ''", state.NegotiatedProtocol)
+ }
+ return nil
+ },
+ }
+ runServerTestTLS12(t, test)
+}
+
// TestHandshakeServerSNI involves a client sending an SNI extension of
// "snitest.com", which happens to match the CN of testSNICertificate. The test
// verifies that the server correctly selects that certificate.
@@ -509,6 +586,61 @@ func TestHandshakeServerSNI(t *testing.T) {
runServerTestTLS12(t, test)
}
+// TestHandshakeServerSNICertForName is similar to TestHandshakeServerSNI, but
+// tests the dynamic GetCertificate method
+func TestHandshakeServerSNIGetCertificate(t *testing.T) {
+ config := *testConfig
+
+ // Replace the NameToCertificate map with a GetCertificate function
+ nameToCert := config.NameToCertificate
+ config.NameToCertificate = nil
+ config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
+ cert, _ := nameToCert[clientHello.ServerName]
+ return cert, nil
+ }
+ test := &serverTest{
+ name: "SNI",
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"},
+ config: &config,
+ }
+ runServerTestTLS12(t, test)
+}
+
+// TestHandshakeServerSNICertForNameNotFound is similar to
+// TestHandshakeServerSNICertForName, but tests to make sure that when the
+// GetCertificate method doesn't return a cert, we fall back to what's in
+// the NameToCertificate map.
+func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) {
+ config := *testConfig
+
+ config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
+ return nil, nil
+ }
+ test := &serverTest{
+ name: "SNI",
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"},
+ config: &config,
+ }
+ runServerTestTLS12(t, test)
+}
+
+// TestHandshakeServerSNICertForNameError tests to make sure that errors in
+// GetCertificate result in a tls alert.
+func TestHandshakeServerSNIGetCertificateError(t *testing.T) {
+ config := *testConfig
+
+ config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
+ return nil, fmt.Errorf("Test error in GetCertificate")
+ }
+ test := &serverTest{
+ name: "SNI",
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"},
+ config: &config,
+ expectAlert: true,
+ }
+ runServerTestTLS12(t, test)
+}
+
// TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with
// an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate.
func TestCipherSuiteCertPreferenceECDSA(t *testing.T) {
@@ -525,7 +657,7 @@ func TestCipherSuiteCertPreferenceECDSA(t *testing.T) {
config = *testConfig
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}
config.Certificates = []Certificate{
- Certificate{
+ {
Certificate: [][]byte{testECDSACertificate},
PrivateKey: testECDSAPrivateKey,
},
@@ -583,6 +715,16 @@ func TestResumptionDisabled(t *testing.T) {
// file for ResumeDisabled does not include a resumption handshake.
}
+func TestFallbackSCSV(t *testing.T) {
+ test := &serverTest{
+ name: "FallbackSCSV",
+ // OpenSSL 1.0.1j is needed for the -fallback_scsv option.
+ command: []string{"openssl", "s_client", "-fallback_scsv"},
+ expectHandshakeErrorIncluding: "inppropriate protocol fallback",
+ }
+ runServerTestTLS11(t, test)
+}
+
// cert.pem and key.pem were generated with generate_cert.go
// Thus, they have no ExtKeyUsage fields and trigger an error
// when verification is turned on.
diff --git a/src/pkg/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go
index f95f274ab..f95f274ab 100644
--- a/src/pkg/crypto/tls/handshake_test.go
+++ b/src/crypto/tls/handshake_test.go
diff --git a/src/pkg/crypto/tls/key_agreement.go b/src/crypto/tls/key_agreement.go
index f38b701f1..0974fc6e0 100644
--- a/src/pkg/crypto/tls/key_agreement.go
+++ b/src/crypto/tls/key_agreement.go
@@ -292,6 +292,9 @@ func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Cert
if x == nil {
return nil, errClientKeyExchange
}
+ if !ka.curve.IsOnCurve(x, y) {
+ return nil, errClientKeyExchange
+ }
x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
xBytes := x.Bytes()
@@ -322,6 +325,9 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
if ka.x == nil {
return errServerKeyExchange
}
+ if !ka.curve.IsOnCurve(ka.x, ka.y) {
+ return errServerKeyExchange
+ }
serverECDHParams := skx.key[:4+publicLen]
sig := skx.key[4+publicLen:]
diff --git a/src/pkg/crypto/tls/prf.go b/src/crypto/tls/prf.go
index fb8b3ab4d..fb8b3ab4d 100644
--- a/src/pkg/crypto/tls/prf.go
+++ b/src/crypto/tls/prf.go
diff --git a/src/pkg/crypto/tls/prf_test.go b/src/crypto/tls/prf_test.go
index a9b6c9e4c..a9b6c9e4c 100644
--- a/src/pkg/crypto/tls/prf_test.go
+++ b/src/crypto/tls/prf_test.go
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
index 00722cba9..00722cba9 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
+++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
index c0be82491..c0be82491 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
+++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
index 3e6dbc271..3e6dbc271 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
+++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
index 94e686004..94e686004 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
+++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
index 30c4c6b83..30c4c6b83 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
index 868f0ceb0..868f0ceb0 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv10-RSA-RC4 b/src/crypto/tls/testdata/Client-TLSv10-RSA-RC4
index 395d53bba..395d53bba 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv10-RSA-RC4
+++ b/src/crypto/tls/testdata/Client-TLSv10-RSA-RC4
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
index 9f941f8ef..9f941f8ef 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
index fc723396a..fc723396a 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv11-RSA-RC4 b/src/crypto/tls/testdata/Client-TLSv11-RSA-RC4
index f7be3f7e9..f7be3f7e9 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv11-RSA-RC4
+++ b/src/crypto/tls/testdata/Client-TLSv11-RSA-RC4
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ALPN b/src/crypto/tls/testdata/Client-TLSv12-ALPN
new file mode 100644
index 000000000..f09a4f106
--- /dev/null
+++ b/src/crypto/tls/testdata/Client-TLSv12-ALPN
@@ -0,0 +1,97 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 8d 01 00 00 89 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 1a c0 2f |.............../|
+00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
+00000040 00 2f 00 35 c0 12 00 0a 01 00 00 46 33 74 00 00 |./.5.......F3t..|
+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 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 00 10 |................|
+00000080 00 10 00 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 |.....proto2.prot|
+00000090 6f 31 |o1|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 66 02 00 00 62 03 03 77 a9 7d 9c 4b |....f...b..w.}.K|
+00000010 69 65 aa dc 95 cb 78 08 3d d2 1a 0a 45 69 23 73 |ie....x.=...Ei#s|
+00000020 4f 41 4f 24 12 2e 57 47 b7 53 64 20 82 9a f8 e7 |OAO$..WG.Sd ....|
+00000030 79 f8 13 2c 9d cd b5 cb cb 9a 95 56 0e e9 cb a8 |y..,.......V....|
+00000040 e4 a2 8a d6 bc dc fa 25 b3 57 cc cf c0 2f 00 00 |.......%.W.../..|
+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 1b 42 c3 ae |..........A..B..|
+00000340 44 19 d3 84 7c 6c 98 cb b9 22 a2 67 63 95 aa cc |D...|l...".gc...|
+00000350 bd e4 1e f8 08 e6 60 f3 bc 83 9f 81 da 9c 1c 8c |......`.........|
+00000360 ff 6f f4 3e 1e e5 3b f6 49 61 f9 70 43 7f c1 69 |.o.>..;.Ia.pC..i|
+00000370 de 73 98 4b bd 5c c3 78 24 18 a8 ec 04 01 00 80 |.s.K.\.x$.......|
+00000380 70 d2 5b e1 39 cf 4d 54 de d2 74 4e 5e a8 b3 ca |p.[.9.MT..tN^...|
+00000390 e1 f2 4e 76 3c 77 8b ef f7 d1 df b9 ad c1 70 39 |..Nv<w........p9|
+000003a0 c7 a3 1e 0f 7b 6c 78 2e c1 86 d2 67 36 d8 25 e0 |....{lx....g6.%.|
+000003b0 e8 e5 cc 35 a2 96 a1 b4 b7 06 68 1e aa c7 06 97 |...5......h.....|
+000003c0 b7 c2 83 ce c0 17 dd 4f 9e 6f 7a bd cd c7 6e 7f |.......O.oz...n.|
+000003d0 cb 80 d1 7d 06 2d f9 f1 fb 5f cc bb d8 62 5b f0 |...}.-..._...b[.|
+000003e0 27 12 57 d5 9b 55 aa 55 4b 9a 5a f6 a5 aa c1 82 |'.W..U.UK.Z.....|
+000003f0 39 11 6b dc 83 7f a8 47 28 5a 0f 3d 3f 0f c2 22 |9.k....G(Z.=?.."|
+00000400 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 35 9d |.....(........5.|
+00000060 92 e8 bf df 7f a7 77 1b cf 03 2a bf e2 6c 62 2b |......w...*..lb+|
+00000070 26 f0 fb 93 d3 df fd 55 84 d3 ed 88 31 cb |&......U....1.|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 28 c8 c0 78 09 73 |..........(..x.s|
+00000010 58 41 73 66 88 cf db f3 fe c6 57 ab 45 be 2e d8 |XAsf......W.E...|
+00000020 4e e5 ff 42 57 13 74 d2 cc c2 62 07 39 8b 06 46 |N..BW.t...b.9..F|
+00000030 1d 8f 88 |...|
+>>> Flow 5 (client to server)
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 10 c3 5f |..............._|
+00000010 3f c8 92 6c 7a a7 23 05 f3 d8 31 20 01 52 f1 99 |?..lz.#...1 .R..|
+00000020 33 c1 2a 15 03 03 00 1a 00 00 00 00 00 00 00 02 |3.*.............|
+00000030 cc ef eb 78 e4 e1 9d 90 05 6d 95 ac f2 49 ba 8e |...x.....m...I..|
+00000040 6b 8d |k.|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch b/src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch
new file mode 100644
index 000000000..f24a70cc8
--- /dev/null
+++ b/src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch
@@ -0,0 +1,95 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 86 01 00 00 82 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 1a c0 2f |.............../|
+00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
+00000040 00 2f 00 35 c0 12 00 0a 01 00 00 3f 33 74 00 00 |./.5.......?3t..|
+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 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 00 10 |................|
+00000080 00 09 00 07 06 70 72 6f 74 6f 33 |.....proto3|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 59 02 00 00 55 03 03 69 84 d1 d3 44 |....Y...U..i...D|
+00000010 e9 66 08 48 bc 70 d8 ae 40 0b 17 69 e7 27 f6 7a |.f.H.p..@..i.'.z|
+00000020 d5 ee 86 74 54 9e a8 bb 79 76 89 20 57 53 1b 02 |...tT...yv. WS..|
+00000030 5b 70 81 a6 f1 53 bc 9d b7 42 5e ac 92 93 b5 20 |[p...S...B^.... |
+00000040 8a bb 36 cc 8f cb 7e a0 61 a2 e8 ef c0 2f 00 00 |..6...~.a..../..|
+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 04 |.............A..|
+00000330 be 27 08 6f 12 83 1b 04 76 fa 5f 16 d6 e3 64 76 |.'.o....v._...dv|
+00000340 ad 0a 77 37 71 64 44 4c 3f 1a be dc 85 ce 46 c8 |..w7qdDL?.....F.|
+00000350 29 a1 e2 24 78 66 1f 35 90 05 46 c0 91 d1 fd dd |)..$xf.5..F.....|
+00000360 b5 5b 87 d7 6d 9d 77 a7 f7 b3 df 68 27 fd 6d 04 |.[..m.w....h'.m.|
+00000370 01 00 80 7b 9b fd 0d 62 57 07 ef 97 f5 ff a9 00 |...{...bW.......|
+00000380 a0 89 35 5a 8a e6 e7 ae 7b 55 c5 dc 21 64 87 6e |..5Z....{U..!d.n|
+00000390 0f ab 85 6d 82 e8 83 fd 7d 3b 49 a7 ae 92 5f 6d |...m....};I..._m|
+000003a0 a3 42 ce ff ef a6 00 6a 33 32 1f 7b eb b7 c2 5c |.B.....j32.{...\|
+000003b0 2d 38 cf 10 4b 59 69 4d 15 e0 68 49 39 ba cb 2a |-8..KYiM..hI9..*|
+000003c0 d9 b9 f3 fe 33 01 4f 7e ac 69 02 35 a5 e0 33 8d |....3.O~.i.5..3.|
+000003d0 b3 74 34 14 45 9c 89 ad 41 2d d0 27 22 90 58 c6 |.t4.E...A-.'".X.|
+000003e0 e0 2c b4 6e 19 04 e4 46 26 ec 13 35 48 a6 3f 64 |.,.n...F&..5H.?d|
+000003f0 dc 85 2b 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 88 0d |.....(..........|
+00000060 04 8b 8e 93 55 58 d6 75 ca 16 26 42 a3 60 20 67 |....UX.u..&B.` g|
+00000070 84 cf d7 b3 10 fe 63 6c 2f 40 64 0c d6 78 |......cl/@d..x|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 28 bd 6c 2f 70 b9 |..........(.l/p.|
+00000010 2f 9c 29 70 af 34 49 4c 5b 25 c3 14 b6 6d 28 81 |/.)p.4IL[%...m(.|
+00000020 ff 54 d9 71 8d 2c c7 38 dd 44 27 6b 54 1e 53 7b |.T.q.,.8.D'kT.S{|
+00000030 22 cb 65 |".e|
+>>> Flow 5 (client to server)
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 7f 0d d7 |................|
+00000010 d9 4b 87 7b 36 fb 24 92 69 22 43 50 1e 46 fb c4 |.K.{6.$.i"CP.F..|
+00000020 86 64 6f 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.do.............|
+00000030 37 d5 2d 0a be c5 a8 ae d4 bd 2b 09 34 18 a0 87 |7.-.......+.4...|
+00000040 08 a6 |..|
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
index 207327036..207327036 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
+++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
index c3b753a7b..c3b753a7b 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
+++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
index 0037af61a..0037af61a 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
+++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
index df3eaa440..df3eaa440 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
+++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
index 76445903b..76445903b 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
index fb5af17f0..fb5af17f0 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
+++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
index 5336bbbad..5336bbbad 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
diff --git a/src/pkg/crypto/tls/testdata/Client-TLSv12-RSA-RC4 b/src/crypto/tls/testdata/Client-TLSv12-RSA-RC4
index 0377f052a..0377f052a 100644
--- a/src/pkg/crypto/tls/testdata/Client-TLSv12-RSA-RC4
+++ b/src/crypto/tls/testdata/Client-TLSv12-RSA-RC4
diff --git a/src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-3DES b/src/crypto/tls/testdata/Server-SSLv3-RSA-3DES
index a6c7a4196..a6c7a4196 100644
--- a/src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-3DES
+++ b/src/crypto/tls/testdata/Server-SSLv3-RSA-3DES
diff --git a/src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-AES b/src/crypto/tls/testdata/Server-SSLv3-RSA-AES
index 4885b267d..4885b267d 100644
--- a/src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-AES
+++ b/src/crypto/tls/testdata/Server-SSLv3-RSA-AES
diff --git a/src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-RC4 b/src/crypto/tls/testdata/Server-SSLv3-RSA-RC4
index 1314b659b..1314b659b 100644
--- a/src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-RC4
+++ b/src/crypto/tls/testdata/Server-SSLv3-RSA-RC4
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES
index 9b8cb4d9b..9b8cb4d9b 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES
+++ b/src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-3DES b/src/crypto/tls/testdata/Server-TLSv10-RSA-3DES
index c0e6241c0..c0e6241c0 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-3DES
+++ b/src/crypto/tls/testdata/Server-TLSv10-RSA-3DES
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-AES b/src/crypto/tls/testdata/Server-TLSv10-RSA-AES
index 1670997b0..1670997b0 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-AES
+++ b/src/crypto/tls/testdata/Server-TLSv10-RSA-AES
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-RC4 b/src/crypto/tls/testdata/Server-TLSv10-RSA-RC4
index d653561f9..d653561f9 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-RC4
+++ b/src/crypto/tls/testdata/Server-TLSv10-RSA-RC4
diff --git a/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV b/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV
new file mode 100644
index 000000000..2d8dfbc3b
--- /dev/null
+++ b/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV
@@ -0,0 +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 |.#.......|
+>>> Flow 2 (server to client)
+00000000 15 03 02 00 02 02 56 |......V|
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv11-RSA-RC4 b/src/crypto/tls/testdata/Server-TLSv11-RSA-RC4
index 9237db078..9237db078 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv11-RSA-RC4
+++ b/src/crypto/tls/testdata/Server-TLSv11-RSA-RC4
diff --git a/src/crypto/tls/testdata/Server-TLSv12-ALPN b/src/crypto/tls/testdata/Server-TLSv12-ALPN
new file mode 100644
index 000000000..106244d5a
--- /dev/null
+++ b/src/crypto/tls/testdata/Server-TLSv12-ALPN
@@ -0,0 +1,122 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 01 8a 01 00 01 86 03 03 34 54 69 f3 d7 |...........4Ti..|
+00000010 20 9d 1d 74 db 72 e9 2f 51 7c c2 82 0a 9b cb 6d | ..t.r./Q|.....m|
+00000020 90 b4 8e a2 1f 2f c7 66 74 8f 33 00 00 d6 c0 30 |...../.ft.3....0|
+00000030 c0 2c c0 28 c0 24 c0 14 c0 0a c0 22 c0 21 c0 20 |.,.(.$.....".!. |
+00000040 00 a5 00 a3 00 a1 00 9f 00 6b 00 6a 00 69 00 68 |.........k.j.i.h|
+00000050 00 39 00 38 00 37 00 36 00 88 00 87 00 86 00 85 |.9.8.7.6........|
+00000060 c0 32 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d |.2...*.&.......=|
+00000070 00 35 00 84 c0 2f c0 2b c0 27 c0 23 c0 13 c0 09 |.5.../.+.'.#....|
+00000080 c0 1f c0 1e c0 1d 00 a4 00 a2 00 a0 00 9e 00 67 |...............g|
+00000090 00 40 00 3f 00 3e 00 33 00 32 00 31 00 30 00 9a |.@.?.>.3.2.1.0..|
+000000a0 00 99 00 98 00 97 00 45 00 44 00 43 00 42 c0 31 |.......E.D.C.B.1|
+000000b0 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c 00 3c 00 2f |.-.).%.......<./|
+000000c0 00 96 00 41 00 07 c0 11 c0 07 c0 0c c0 02 00 05 |...A............|
+000000d0 00 04 c0 12 c0 08 c0 1c c0 1b c0 1a 00 16 00 13 |................|
+000000e0 00 10 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f |................|
+000000f0 00 0c 00 09 00 14 00 11 00 0e 00 0b 00 08 00 06 |................|
+00000100 00 03 00 ff 01 00 00 87 00 0b 00 04 03 00 01 02 |................|
+00000110 00 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b |...:.8..........|
+00000120 00 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 |................|
+00000130 00 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 |................|
+00000140 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 |...............#|
+00000150 00 00 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 |..... ..........|
+00000160 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
+00000170 02 01 02 02 02 03 00 0f 00 01 01 00 10 00 10 00 |................|
+00000180 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 |..proto2.proto1|
+>>> 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 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 14 00 00 |................|
+00000030 16 00 23 00 00 ff 01 00 01 00 00 10 00 09 00 07 |..#.............|
+00000040 06 70 72 6f 74 6f 31 16 03 03 02 be 0b 00 02 ba |.proto1.........|
+00000050 00 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 |......0...0.....|
+00000060 02 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d |..............0.|
+00000070 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 |..*.H........0E1|
+00000080 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.|
+00000090 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat|
+000000a0 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte|
+000000b0 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty|
+000000c0 20 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 | Ltd0...10042409|
+000000d0 30 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 |0938Z..110424090|
+000000e0 39 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 |938Z0E1.0...U...|
+000000f0 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f |.AU1.0...U....So|
+00000100 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 |me-State1!0...U.|
+00000110 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 |...Internet Widg|
+00000120 69 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d |its Pty Ltd0..0.|
+00000130 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d |..*.H...........|
+00000140 00 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf |.0.......y......|
+00000150 46 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a |F...i..+.CZ..-.z|
+00000160 43 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 |C...R..eL,x.#...|
+00000170 82 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c |.....;~b.,.3...\|
+00000180 7a 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 |zV.....X{&?.....|
+00000190 c9 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 |.!.J..T.Z..Bq...|
+000001a0 99 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 |...~.}}..9....Q.|
+000001b0 7c e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d ||..L;2f......q..|
+000001c0 db db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 |...k..-y........|
+000001d0 30 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad |0..0...U........|
+000001e0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..|
+000001f0 88 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 |.90u..U.#.n0l...|
+00000200 ad e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e |...Z..(.i.#i..&.|
+00000210 18 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 |..9.I.G0E1.0...U|
+00000220 04 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 |....AU1.0...U...|
+00000230 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 |.Some-State1!0..|
+00000240 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 |.U....Internet W|
+00000250 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 |idgits Pty Ltd..|
+00000260 00 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 |.........0...U..|
+00000270 04 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 |..0....0...*.H..|
+00000280 0d 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b |...........lE$.k|
+00000290 b1 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 |.Y..R.......zdu.|
+000002a0 5a 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e |Z.f..+...f..O8.n|
+000002b0 60 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 |`....A..%...z$.0|
+000002c0 1d ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 |.........1Y....x|
+000002d0 ea 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 |.PV\..Z-Z_3....u|
+000002e0 90 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c |....R...... _...|
+000002f0 a3 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b |.......W.p.&mq..|
+00000300 26 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 cd 0c |&n8P)l..........|
+00000310 00 00 c9 03 00 17 41 04 1e 18 37 ef 0d 19 51 88 |......A...7...Q.|
+00000320 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 |5uq..T[....g..$ |
+00000330 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f |>.V...(^.+-O....|
+00000340 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 |lK[.V.2B.X..I..h|
+00000350 1a 41 03 56 6b dc 5a 89 04 01 00 80 2d a0 6e 47 |.A.Vk.Z.....-.nG|
+00000360 93 a2 19 17 32 f5 42 58 93 f6 4f d4 e9 4d a4 0f |....2.BX..O..M..|
+00000370 fe 4e d7 2c 62 b6 fb 83 37 a3 09 60 4b 69 e2 4c |.N.,b...7..`Ki.L|
+00000380 fc b8 4c d1 a6 9a 89 a0 c5 76 f5 62 b7 e8 eb c2 |..L......v.b....|
+00000390 fa 0f 0e 61 86 bc 70 da 13 72 8d 87 94 16 9a 8d |...a..p..r......|
+000003a0 5f 80 82 92 77 37 4f 9e 55 5d dc 35 42 a3 75 5c |_...w7O.U].5B.u\|
+000003b0 ec a4 58 78 66 97 97 da 49 67 2e b6 7e 11 de fb |..Xxf...Ig..~...|
+000003c0 e3 8f e8 bf 1d 91 1e 91 20 1b 2a df c6 58 e4 82 |........ .*..X..|
+000003d0 ce 37 dd 6f a5 ac 51 3d 65 db 3f f5 16 03 03 00 |.7.o..Q=e.?.....|
+000003e0 04 0e 00 00 00 |.....|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 46 10 00 00 42 41 04 f3 fc ea d8 50 |....F...BA.....P|
+00000010 e6 15 b0 e7 11 c7 6d ee 09 ad 80 d5 54 eb 4f 62 |......m.....T.Ob|
+00000020 7d bb a7 2d 28 0c 66 33 42 09 cf 2b 58 f8 58 41 |}..-(.f3B..+X.XA|
+00000030 bd 46 51 0a f0 7d 8c 0c 98 9e 26 77 20 fd 5e c1 |.FQ..}....&w .^.|
+00000040 a9 b3 e5 c3 6c 05 97 e3 81 fd db 14 03 03 00 01 |....l...........|
+00000050 01 16 03 03 00 40 02 2a 28 41 e3 9c 5d 45 d4 45 |.....@.*(A..]E.E|
+00000060 51 8c 7a c0 ba b1 8e a4 84 2c f3 83 cd c4 55 5c |Q.z......,....U\|
+00000070 d6 5c 6f 72 ab 89 7a c6 d7 9c 2a 54 f0 c4 20 ee |.\or..z...*T.. .|
+00000080 37 74 9b b6 8c f7 e4 37 2c eb d4 9f 5c 5e 55 a0 |7t.....7,...\^U.|
+00000090 e2 5a fe 1e c8 67 |.Z...g|
+>>> Flow 4 (server to client)
+00000000 16 03 03 00 72 04 00 00 6e 00 00 00 00 00 68 00 |....r...n.....h.|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 |...............e|
+00000020 ea 8b c0 ef ba 59 31 75 33 96 f1 f8 c9 e1 ef 30 |.....Y1u3......0|
+00000030 00 a3 a9 1d ab c8 4b 29 94 f2 c8 c8 8d 03 57 ab |......K)......W.|
+00000040 56 df 0f 4e 0d 30 13 09 c9 e4 fa 51 4e b3 26 ad |V..N.0.....QN.&.|
+00000050 43 9f ae 62 d5 59 23 05 9b 69 8f 5b a8 ba 39 f1 |C..b.Y#..i.[..9.|
+00000060 90 84 35 bf 8f 8d d5 39 93 98 ee b9 75 03 3f 91 |..5....9....u.?.|
+00000070 e8 56 0b cb 44 a6 7a 14 03 03 00 01 01 16 03 03 |.V..D.z.........|
+00000080 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.@..............|
+00000090 00 00 f9 a0 8e 23 34 f1 61 15 a8 4e ae c4 f3 2a |.....#4.a..N...*|
+000000a0 a6 f8 ee 1b 65 c4 c0 ff 93 14 74 ed 82 ae 48 a8 |....e.....t...H.|
+000000b0 42 fb a9 24 5d dd fd 98 b8 65 73 03 88 99 e1 ed |B..$]....es.....|
+000000c0 02 95 17 03 03 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+000000d0 00 00 00 00 00 00 00 b9 b3 f5 41 84 3b 2a a9 c3 |..........A.;*..|
+000000e0 9c e3 d4 38 90 76 c1 8c f0 4f 10 1b 04 b5 07 fe |...8.v...O......|
+000000f0 79 3d 7b 77 a4 17 0f 4e df 64 70 70 9e 34 8e b6 |y={w...N.dpp.4..|
+00000100 db b2 b6 fd 41 fe b3 15 03 03 00 30 00 00 00 00 |....A......0....|
+00000110 00 00 00 00 00 00 00 00 00 00 00 00 02 73 de fe |.............s..|
+00000120 fa 4b 69 6d 30 69 79 96 7e 4f 2f 04 67 36 96 27 |.Kim0iy.~O/.g6.'|
+00000130 67 23 2b dc 7a c4 6c 34 ea fc 79 fd |g#+.z.l4..y.|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch b/src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch
new file mode 100644
index 000000000..db5881b76
--- /dev/null
+++ b/src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch
@@ -0,0 +1,121 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 01 8a 01 00 01 86 03 03 0a a8 82 53 61 |..............Sa|
+00000010 68 e0 83 91 71 36 f9 c1 19 ff e8 09 fc 21 9f 03 |h...q6.......!..|
+00000020 31 f3 87 4a 04 8c 3d c2 6e 00 32 00 00 d6 c0 30 |1..J..=.n.2....0|
+00000030 c0 2c c0 28 c0 24 c0 14 c0 0a c0 22 c0 21 c0 20 |.,.(.$.....".!. |
+00000040 00 a5 00 a3 00 a1 00 9f 00 6b 00 6a 00 69 00 68 |.........k.j.i.h|
+00000050 00 39 00 38 00 37 00 36 00 88 00 87 00 86 00 85 |.9.8.7.6........|
+00000060 c0 32 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d |.2...*.&.......=|
+00000070 00 35 00 84 c0 2f c0 2b c0 27 c0 23 c0 13 c0 09 |.5.../.+.'.#....|
+00000080 c0 1f c0 1e c0 1d 00 a4 00 a2 00 a0 00 9e 00 67 |...............g|
+00000090 00 40 00 3f 00 3e 00 33 00 32 00 31 00 30 00 9a |.@.?.>.3.2.1.0..|
+000000a0 00 99 00 98 00 97 00 45 00 44 00 43 00 42 c0 31 |.......E.D.C.B.1|
+000000b0 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c 00 3c 00 2f |.-.).%.......<./|
+000000c0 00 96 00 41 00 07 c0 11 c0 07 c0 0c c0 02 00 05 |...A............|
+000000d0 00 04 c0 12 c0 08 c0 1c c0 1b c0 1a 00 16 00 13 |................|
+000000e0 00 10 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f |................|
+000000f0 00 0c 00 09 00 14 00 11 00 0e 00 0b 00 08 00 06 |................|
+00000100 00 03 00 ff 01 00 00 87 00 0b 00 04 03 00 01 02 |................|
+00000110 00 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b |...:.8..........|
+00000120 00 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 |................|
+00000130 00 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 |................|
+00000140 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 |...............#|
+00000150 00 00 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 |..... ..........|
+00000160 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
+00000170 02 01 02 02 02 03 00 0f 00 01 01 00 10 00 10 00 |................|
+00000180 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 |..proto2.proto1|
+>>> 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 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 14 00 00 |................|
+00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 be 0b |..#.............|
+00000040 00 02 ba 00 02 b7 00 02 b4 30 82 02 b0 30 82 02 |.........0...0..|
+00000050 19 a0 03 02 01 02 02 09 00 85 b0 bb a4 8a 7f b8 |................|
+00000060 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 |.0...*.H........|
+00000070 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 |0E1.0...U....AU1|
+00000080 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 |.0...U....Some-S|
+00000090 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 |tate1!0...U....I|
+000000a0 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 |nternet Widgits |
+000000b0 50 74 79 20 4c 74 64 30 1e 17 0d 31 30 30 34 32 |Pty Ltd0...10042|
+000000c0 34 30 39 30 39 33 38 5a 17 0d 31 31 30 34 32 34 |4090938Z..110424|
+000000d0 30 39 30 39 33 38 5a 30 45 31 0b 30 09 06 03 55 |090938Z0E1.0...U|
+000000e0 04 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 |....AU1.0...U...|
+000000f0 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 |.Some-State1!0..|
+00000100 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 |.U....Internet W|
+00000110 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 30 81 |idgits Pty Ltd0.|
+00000120 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 |.0...*.H........|
+00000130 03 81 8d 00 30 81 89 02 81 81 00 bb 79 d6 f5 17 |....0.......y...|
+00000140 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 43 5a d0 03 |...F...i..+.CZ..|
+00000150 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 |-.zC...R..eL,x.#|
+00000160 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 |........;~b.,.3.|
+00000170 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b 26 3f b5 cd |..\zV.....X{&?..|
+00000180 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a bf ef 42 71 |....!.J..T.Z..Bq|
+00000190 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e |......~.}}..9...|
+000001a0 db 51 c9 7c e3 c0 4c 3b 32 66 01 cf af b1 1d b8 |.Q.|..L;2f......|
+000001b0 71 9a 1d db db 89 6b ae da 2d 79 02 03 01 00 01 |q.....k..-y.....|
+000001c0 a3 81 a7 30 81 a4 30 1d 06 03 55 1d 0e 04 16 04 |...0..0...U.....|
+000001d0 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 de d3 |.....Z..(.i.#i..|
+000001e0 26 8e 18 88 39 30 75 06 03 55 1d 23 04 6e 30 6c |&...90u..U.#.n0l|
+000001f0 80 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 de |......Z..(.i.#i.|
+00000200 d3 26 8e 18 88 39 a1 49 a4 47 30 45 31 0b 30 09 |.&...9.I.G0E1.0.|
+00000210 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 55 |..U....AU1.0...U|
+00000220 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 |....Some-State1!|
+00000230 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 |0...U....Interne|
+00000240 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 |t Widgits Pty Lt|
+00000250 64 82 09 00 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 |d...........0...|
+00000260 55 1d 13 04 05 30 03 01 01 ff 30 0d 06 09 2a 86 |U....0....0...*.|
+00000270 48 86 f7 0d 01 01 05 05 00 03 81 81 00 08 6c 45 |H.............lE|
+00000280 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a |$.k.Y..R.......z|
+00000290 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f |du.Z.f..+...f..O|
+000002a0 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 13 b1 18 7a |8.n`....A..%...z|
+000002b0 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 31 59 db 95 |$.0.........1Y..|
+000002c0 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 |..x.PV\..Z-Z_3..|
+000002d0 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f |..u....R...... _|
+000002e0 f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d |..........W.p.&m|
+000002f0 71 99 9b 26 6e 38 50 29 6c 90 a7 bd d9 16 03 03 |q..&n8P)l.......|
+00000300 00 cd 0c 00 00 c9 03 00 17 41 04 1e 18 37 ef 0d |.........A...7..|
+00000310 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
+00000320 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
+00000330 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
+00000340 a6 b5 68 1a 41 03 56 6b dc 5a 89 04 01 00 80 b9 |..h.A.Vk.Z......|
+00000350 0f 79 8a 16 f4 da 8f 27 b4 16 fc c0 51 db ae d1 |.y.....'....Q...|
+00000360 af 79 77 d5 d5 a2 13 05 45 20 cc eb ac ed cb 30 |.yw.....E .....0|
+00000370 32 2e 2c bd fa 1c 4d b5 32 a6 37 43 c8 5c 2d f8 |2.,...M.2.7C.\-.|
+00000380 6e 85 f5 cd 54 92 29 ad 13 7d d5 9e 8c 1d b7 d0 |n...T.)..}......|
+00000390 c1 c7 3d e8 ba 4a 0f 9a a6 3e 25 5f 27 62 b1 00 |..=..J...>%_'b..|
+000003a0 91 d9 23 48 3f 10 fe c5 e3 07 9a 58 57 6d cc 10 |..#H?......XWm..|
+000003b0 3b f8 1a d5 6e 8b 1f 03 6f 82 84 98 b5 f7 71 5d |;...n...o.....q]|
+000003c0 c2 ad 60 14 c1 88 07 5a 3d 99 fd a8 c9 9a 03 16 |..`....Z=.......|
+000003d0 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 76 aa 4e b9 f9 |....F...BA.v.N..|
+00000010 68 85 81 74 7c d9 f9 64 7f bd 09 83 08 5b 4f 76 |h..t|..d.....[Ov|
+00000020 6e be 79 b6 4e 97 17 63 e4 b5 1c 77 e5 85 76 8a |n.y.N..c...w..v.|
+00000030 5d 9f f1 21 88 ec f9 a7 7c 41 af f9 c5 fe 11 81 |]..!....|A......|
+00000040 11 51 8e a7 20 33 5f cf e7 90 90 14 03 03 00 01 |.Q.. 3_.........|
+00000050 01 16 03 03 00 40 44 3e 32 01 71 ac 5a b5 1f 2c |.....@D>2.q.Z..,|
+00000060 37 d9 4b 70 72 91 89 d4 d7 c2 c3 e7 ff dc 72 2a |7.Kpr.........r*|
+00000070 ba f5 30 b0 e9 dd 48 10 3d cd 98 48 a3 e3 ca de |..0...H.=..H....|
+00000080 15 0e 90 8e e5 04 14 74 42 b8 b0 12 cc 68 7b 7d |.......tB....h{}|
+00000090 6c 43 72 60 05 0d |lCr`..|
+>>> Flow 4 (server to client)
+00000000 16 03 03 00 72 04 00 00 6e 00 00 00 00 00 68 00 |....r...n.....h.|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 |...............e|
+00000020 ea 8b c0 ef ba 12 45 17 61 24 cd d2 4c 22 bb 3b |......E.a$..L".;|
+00000030 e3 0e d0 ff 83 e9 7c b7 8f 10 3c 16 1c fc c2 44 |......|...<....D|
+00000040 ef 45 f8 27 30 56 db ea eb ae f5 b6 17 b2 ef f9 |.E.'0V..........|
+00000050 96 0d 2d db e4 59 23 0a fc fa e3 13 48 57 e5 b3 |..-..Y#.....HW..|
+00000060 3a d1 f5 5e ca ef d7 3f 7b b5 f4 69 85 c3 bd da |:..^...?{..i....|
+00000070 fd 9c 50 05 2f 86 ce 14 03 03 00 01 01 16 03 03 |..P./...........|
+00000080 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.@..............|
+00000090 00 00 60 25 1c ed 6f c6 a5 bd b2 29 39 4e 09 d1 |..`%..o....)9N..|
+000000a0 64 cc 75 cd df 91 a8 90 9d 03 aa 92 07 f2 d0 8a |d.u.............|
+000000b0 60 bb 3e 85 21 22 fe f8 dc 52 3c 4e 82 77 14 14 |`.>.!"...R<N.w..|
+000000c0 0f 1f 17 03 03 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+000000d0 00 00 00 00 00 00 00 0b 87 12 62 3e e5 3e 7d 74 |..........b>.>}t|
+000000e0 0d ac c4 a9 df 67 1c 5a ad 3e 01 34 03 88 2f 39 |.....g.Z.>.4../9|
+000000f0 f7 3c 06 e4 f6 81 43 66 b1 1b ed a5 e5 b6 a8 43 |.<....Cf.......C|
+00000100 7f 36 2f b2 da 45 9a 15 03 03 00 30 00 00 00 00 |.6/..E.....0....|
+00000110 00 00 00 00 00 00 00 00 00 00 00 00 fa 63 4e c5 |.............cN.|
+00000120 77 89 71 56 e3 0a cf 98 da 2f 89 8f 74 8e 76 24 |w.qV...../..t.v$|
+00000130 e2 40 a5 9f 29 1b b2 11 ef 7a 55 7f |.@..)....zU.|
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA b/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
index 0ab8b8d74..0ab8b8d74 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
+++ b/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA b/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
index 88abb15a7..88abb15a7 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
+++ b/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven
index 547f79834..547f79834 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven
+++ b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven
index 04a5b117c..04a5b117c 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven
+++ b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven
index 562fe1aaa..562fe1aaa 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven
+++ b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES
index aacbb8670..aacbb8670 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES
+++ b/src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-IssueTicket b/src/crypto/tls/testdata/Server-TLSv12-IssueTicket
index e3e62f224..e3e62f224 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-IssueTicket
+++ b/src/crypto/tls/testdata/Server-TLSv12-IssueTicket
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable b/src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable
index 30f002681..30f002681 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable
+++ b/src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-3DES b/src/crypto/tls/testdata/Server-TLSv12-RSA-3DES
index 5995b3314..5995b3314 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-3DES
+++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-3DES
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-AES b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES
index a152a96a8..a152a96a8 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-AES
+++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM
index 0ddfe022f..0ddfe022f 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM
+++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-RC4 b/src/crypto/tls/testdata/Server-TLSv12-RSA-RC4
index b703a8f76..b703a8f76 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-RC4
+++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-RC4
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-Resume b/src/crypto/tls/testdata/Server-TLSv12-Resume
index c495d4adc..c495d4adc 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-Resume
+++ b/src/crypto/tls/testdata/Server-TLSv12-Resume
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-ResumeDisabled b/src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled
index db833f655..db833f655 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-ResumeDisabled
+++ b/src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled
diff --git a/src/pkg/crypto/tls/testdata/Server-TLSv12-SNI b/src/crypto/tls/testdata/Server-TLSv12-SNI
index 61b17a11d..61b17a11d 100644
--- a/src/pkg/crypto/tls/testdata/Server-TLSv12-SNI
+++ b/src/crypto/tls/testdata/Server-TLSv12-SNI
diff --git a/src/pkg/crypto/tls/ticket.go b/src/crypto/tls/ticket.go
index 0923027c7..0923027c7 100644
--- a/src/pkg/crypto/tls/ticket.go
+++ b/src/crypto/tls/ticket.go
diff --git a/src/pkg/crypto/tls/tls.go b/src/crypto/tls/tls.go
index d50e12029..d50e12029 100644
--- a/src/pkg/crypto/tls/tls.go
+++ b/src/crypto/tls/tls.go
diff --git a/src/pkg/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go
index f8c94ff35..e82579eee 100644
--- a/src/pkg/crypto/tls/tls_test.go
+++ b/src/crypto/tls/tls_test.go
@@ -5,6 +5,7 @@
package tls
import (
+ "bytes"
"fmt"
"io"
"net"
@@ -235,3 +236,47 @@ func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
}
return nil
}
+
+func TestTLSUniqueMatches(t *testing.T) {
+ ln := newLocalListener(t)
+ defer ln.Close()
+
+ serverTLSUniques := make(chan []byte)
+ go func() {
+ for i := 0; i < 2; i++ {
+ sconn, err := ln.Accept()
+ if err != nil {
+ t.Fatal(err)
+ }
+ serverConfig := *testConfig
+ srv := Server(sconn, &serverConfig)
+ if err := srv.Handshake(); err != nil {
+ t.Fatal(err)
+ }
+ serverTLSUniques <- srv.ConnectionState().TLSUnique
+ }
+ }()
+
+ clientConfig := *testConfig
+ clientConfig.ClientSessionCache = NewLRUClientSessionCache(1)
+ conn, err := Dial("tcp", ln.Addr().String(), &clientConfig)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(conn.ConnectionState().TLSUnique, <-serverTLSUniques) {
+ t.Error("client and server channel bindings differ")
+ }
+ conn.Close()
+
+ conn, err = Dial("tcp", ln.Addr().String(), &clientConfig)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer conn.Close()
+ if !conn.ConnectionState().DidResume {
+ t.Error("second session did not use resumption")
+ }
+ if !bytes.Equal(conn.ConnectionState().TLSUnique, <-serverTLSUniques) {
+ t.Error("client and server channel bindings differ when session resumption is used")
+ }
+}
diff --git a/src/pkg/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go
index babe94d41..babe94d41 100644
--- a/src/pkg/crypto/x509/cert_pool.go
+++ b/src/crypto/x509/cert_pool.go
diff --git a/src/pkg/crypto/x509/example_test.go b/src/crypto/x509/example_test.go
index 29e7c2139..29e7c2139 100644
--- a/src/pkg/crypto/x509/example_test.go
+++ b/src/crypto/x509/example_test.go
diff --git a/src/pkg/crypto/x509/pem_decrypt.go b/src/crypto/x509/pem_decrypt.go
index 194c81bf6..194c81bf6 100644
--- a/src/pkg/crypto/x509/pem_decrypt.go
+++ b/src/crypto/x509/pem_decrypt.go
diff --git a/src/pkg/crypto/x509/pem_decrypt_test.go b/src/crypto/x509/pem_decrypt_test.go
index 59ba6f900..13e4700bd 100644
--- a/src/pkg/crypto/x509/pem_decrypt_test.go
+++ b/src/crypto/x509/pem_decrypt_test.go
@@ -14,7 +14,7 @@ import (
func TestDecrypt(t *testing.T) {
for i, data := range testData {
- t.Logf("test %d. %s", i, data.kind)
+ t.Logf("test %v. %v", i, data.kind)
block, rest := pem.Decode(data.pemData)
if len(rest) > 0 {
t.Error("extra data")
@@ -39,7 +39,7 @@ func TestDecrypt(t *testing.T) {
func TestEncrypt(t *testing.T) {
for i, data := range testData {
- t.Logf("test %d. %s", i, data.kind)
+ t.Logf("test %v. %v", i, data.kind)
plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
if err != nil {
t.Fatal("cannot decode test DER data: ", err)
diff --git a/src/pkg/crypto/x509/pkcs1.go b/src/crypto/x509/pkcs1.go
index acebe3513..acebe3513 100644
--- a/src/pkg/crypto/x509/pkcs1.go
+++ b/src/crypto/x509/pkcs1.go
diff --git a/src/pkg/crypto/x509/pkcs8.go b/src/crypto/x509/pkcs8.go
index ba19989cb..ba19989cb 100644
--- a/src/pkg/crypto/x509/pkcs8.go
+++ b/src/crypto/x509/pkcs8.go
diff --git a/src/pkg/crypto/x509/pkcs8_test.go b/src/crypto/x509/pkcs8_test.go
index 4114efd0e..4114efd0e 100644
--- a/src/pkg/crypto/x509/pkcs8_test.go
+++ b/src/crypto/x509/pkcs8_test.go
diff --git a/src/pkg/crypto/x509/pkix/pkix.go b/src/crypto/x509/pkix/pkix.go
index 58c1e54d1..8768b7859 100644
--- a/src/pkg/crypto/x509/pkix/pkix.go
+++ b/src/crypto/x509/pkix/pkix.go
@@ -164,7 +164,7 @@ type TBSCertificateList struct {
Signature AlgorithmIdentifier
Issuer RDNSequence
ThisUpdate time.Time
- NextUpdate time.Time
+ NextUpdate time.Time `asn1:"optional"`
RevokedCertificates []RevokedCertificate `asn1:"optional"`
Extensions []Extension `asn1:"tag:0,optional,explicit"`
}
diff --git a/src/pkg/crypto/x509/root.go b/src/crypto/x509/root.go
index 8aae14e09..8aae14e09 100644
--- a/src/pkg/crypto/x509/root.go
+++ b/src/crypto/x509/root.go
diff --git a/src/pkg/crypto/x509/root_cgo_darwin.go b/src/crypto/x509/root_cgo_darwin.go
index bdcc2c170..bdcc2c170 100644
--- a/src/pkg/crypto/x509/root_cgo_darwin.go
+++ b/src/crypto/x509/root_cgo_darwin.go
diff --git a/src/pkg/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go
index 2a61d36ea..2a61d36ea 100644
--- a/src/pkg/crypto/x509/root_darwin.go
+++ b/src/crypto/x509/root_darwin.go
diff --git a/src/pkg/crypto/x509/root_darwin_test.go b/src/crypto/x509/root_darwin_test.go
index 87ea4e344..87ea4e344 100644
--- a/src/pkg/crypto/x509/root_darwin_test.go
+++ b/src/crypto/x509/root_darwin_test.go
diff --git a/src/pkg/crypto/x509/root_nocgo_darwin.go b/src/crypto/x509/root_nocgo_darwin.go
index d00e25766..d00e25766 100644
--- a/src/pkg/crypto/x509/root_nocgo_darwin.go
+++ b/src/crypto/x509/root_nocgo_darwin.go
diff --git a/src/pkg/crypto/x509/root_plan9.go b/src/crypto/x509/root_plan9.go
index 9965caade..9965caade 100644
--- a/src/pkg/crypto/x509/root_plan9.go
+++ b/src/crypto/x509/root_plan9.go
diff --git a/src/pkg/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go
index 11ad3c440..f77d6c0c5 100644
--- a/src/pkg/crypto/x509/root_unix.go
+++ b/src/crypto/x509/root_unix.go
@@ -15,6 +15,15 @@ var certFiles = []string{
"/etc/ssl/ca-bundle.pem", // OpenSUSE
"/etc/ssl/cert.pem", // OpenBSD
"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly
+ "/etc/pki/tls/cacert.pem", // OpenELEC
+ "/etc/certs/ca-certificates.crt", // Solaris 11.2+
+}
+
+// Possible directories with certificate files; stop after successfully
+// reading at least one file from a directory.
+var certDirectories = []string{
+ "/system/etc/security/cacerts", // Android
+
}
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
@@ -32,6 +41,24 @@ func initSystemRoots() {
}
}
+ for _, directory := range certDirectories {
+ fis, err := ioutil.ReadDir(directory)
+ if err != nil {
+ continue
+ }
+ rootsAdded := false
+ for _, fi := range fis {
+ data, err := ioutil.ReadFile(directory + "/" + fi.Name())
+ if err == nil && roots.AppendCertsFromPEM(data) {
+ rootsAdded = true
+ }
+ }
+ if rootsAdded {
+ systemRoots = roots
+ return
+ }
+ }
+
// All of the files failed to load. systemRoots will be nil which will
// trigger a specific error at verification time.
}
diff --git a/src/pkg/crypto/x509/root_windows.go b/src/crypto/x509/root_windows.go
index 81018b78f..81018b78f 100644
--- a/src/pkg/crypto/x509/root_windows.go
+++ b/src/crypto/x509/root_windows.go
diff --git a/src/pkg/crypto/x509/sec1.go b/src/crypto/x509/sec1.go
index 7de66754e..7de66754e 100644
--- a/src/pkg/crypto/x509/sec1.go
+++ b/src/crypto/x509/sec1.go
diff --git a/src/pkg/crypto/x509/sec1_test.go b/src/crypto/x509/sec1_test.go
index 95f18e77d..95f18e77d 100644
--- a/src/pkg/crypto/x509/sec1_test.go
+++ b/src/crypto/x509/sec1_test.go
diff --git a/src/pkg/crypto/x509/verify.go b/src/crypto/x509/verify.go
index 5fd8e3717..ec1981423 100644
--- a/src/pkg/crypto/x509/verify.go
+++ b/src/crypto/x509/verify.go
@@ -116,10 +116,9 @@ func (e UnknownAuthorityError) Error() string {
}
// SystemRootsError results when we fail to load the system root certificates.
-type SystemRootsError struct {
-}
+type SystemRootsError struct{}
-func (e SystemRootsError) Error() string {
+func (SystemRootsError) Error() string {
return "x509: failed to load system roots and no roots provided"
}
@@ -206,6 +205,9 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
// needed. If successful, it returns one or more chains where the first
// element of the chain is c and the last element is from opts.Roots.
//
+// If opts.Roots is nil and system roots are unavailable the returned error
+// will be of type SystemRootsError.
+//
// WARNING: this doesn't do any revocation checking.
func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
// Use Windows's own verification and chain building.
diff --git a/src/pkg/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
index 96b9d9b42..96b9d9b42 100644
--- a/src/pkg/crypto/x509/verify_test.go
+++ b/src/crypto/x509/verify_test.go
diff --git a/src/pkg/crypto/x509/x509.go b/src/crypto/x509/x509.go
index c347fb384..7a37b98e3 100644
--- a/src/pkg/crypto/x509/x509.go
+++ b/src/crypto/x509/x509.go
@@ -494,6 +494,11 @@ type Certificate struct {
BasicConstraintsValid bool // if true then the next two fields are valid.
IsCA bool
MaxPathLen int
+ // MaxPathLenZero indicates that BasicConstraintsValid==true and
+ // MaxPathLen==0 should be interpreted as an actual maximum path length
+ // of zero. Otherwise, that combination is interpreted as MaxPathLen
+ // not being set.
+ MaxPathLenZero bool
SubjectKeyId []byte
AuthorityKeyId []byte
@@ -913,6 +918,7 @@ func parseCertificate(in *certificate) (*Certificate, error) {
out.BasicConstraintsValid = true
out.IsCA = constraints.IsCA
out.MaxPathLen = constraints.MaxPathLen
+ out.MaxPathLenZero = out.MaxPathLen == 0
continue
}
case 17:
@@ -1227,8 +1233,15 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
}
if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) {
+ // Leaving MaxPathLen as zero indicates that no maximum path
+ // length is desired, unless MaxPathLenZero is set. A value of
+ // -1 causes encoding/asn1 to omit the value as desired.
+ maxPathLen := template.MaxPathLen
+ if maxPathLen == 0 && !template.MaxPathLenZero {
+ maxPathLen = -1
+ }
ret[n].Id = oidExtensionBasicConstraints
- ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, template.MaxPathLen})
+ ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, maxPathLen})
ret[n].Critical = true
if err != nil {
return
@@ -1328,7 +1341,7 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
dp := distributionPoint{
DistributionPoint: distributionPointName{
- FullName: asn1.RawValue{Tag: 0, Class: 2, Bytes: rawFullName},
+ FullName: asn1.RawValue{Tag: 0, Class: 2, IsCompound: true, Bytes: rawFullName},
},
}
crlDp = append(crlDp, dp)
@@ -1657,7 +1670,7 @@ var oidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14}
// CreateCertificateRequest creates a new certificate based on a template. The
// following members of template are used: Subject, Attributes,
-// SignatureAlgorithm, Extension, DNSNames, EmailAddresses, and IPAddresses.
+// SignatureAlgorithm, Extensions, DNSNames, EmailAddresses, and IPAddresses.
// The private key is the private key of the signer.
//
// The returned slice is the certificate request in DER encoding.
diff --git a/src/pkg/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go
index 2fd54c78f..4f5173fb5 100644
--- a/src/pkg/crypto/x509/x509_test.go
+++ b/src/crypto/x509/x509_test.go
@@ -707,6 +707,17 @@ func TestParseDERCRL(t *testing.T) {
// Can't check the signature here without a package cycle.
}
+func TestCRLWithoutExpiry(t *testing.T) {
+ derBytes := fromBase64("MIHYMIGZMAkGByqGSM44BAMwEjEQMA4GA1UEAxMHQ2FybERTUxcNOTkwODI3MDcwMDAwWjBpMBMCAgDIFw05OTA4MjIwNzAwMDBaMBMCAgDJFw05OTA4MjIwNzAwMDBaMBMCAgDTFw05OTA4MjIwNzAwMDBaMBMCAgDSFw05OTA4MjIwNzAwMDBaMBMCAgDUFw05OTA4MjQwNzAwMDBaMAkGByqGSM44BAMDLwAwLAIUfmVSdjP+NHMX0feW+aDU2G1cfT0CFAJ6W7fVWxjBz4fvftok8yqDnDWh")
+ certList, err := ParseDERCRL(derBytes)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !certList.TBSCertList.NextUpdate.IsZero() {
+ t.Errorf("NextUpdate is not the zero value")
+ }
+}
+
func TestParsePEMCRL(t *testing.T) {
pemBytes := fromBase64(pemCRLBase64)
certList, err := ParseCRL(pemBytes)
@@ -728,8 +739,9 @@ func TestParsePEMCRL(t *testing.T) {
}
func TestImports(t *testing.T) {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
+ switch runtime.GOOS {
+ case "android", "nacl":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
if err := exec.Command("go", "run", "x509_test_import.go").Run(); err != nil {
@@ -850,7 +862,7 @@ func TestCertificateRequestOverrides(t *testing.T) {
// An explicit extension should override the DNSNames from the
// template.
ExtraExtensions: []pkix.Extension{
- pkix.Extension{
+ {
Id: oidExtensionSubjectAltName,
Value: sanContents,
},
@@ -868,11 +880,11 @@ func TestCertificateRequestOverrides(t *testing.T) {
// with two extension attributes.
template.Attributes = []pkix.AttributeTypeAndValueSET{
- pkix.AttributeTypeAndValueSET{
+ {
Type: oidExtensionRequest,
Value: [][]pkix.AttributeTypeAndValue{
- []pkix.AttributeTypeAndValue{
- pkix.AttributeTypeAndValue{
+ {
+ {
Type: oidExtensionAuthorityInfoAccess,
Value: []byte("foo"),
},
@@ -941,6 +953,69 @@ func TestParseCertificateRequest(t *testing.T) {
}
}
+func TestMaxPathLen(t *testing.T) {
+ block, _ := pem.Decode([]byte(pemPrivateKey))
+ rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes)
+ if err != nil {
+ t.Fatalf("Failed to parse private key: %s", err)
+ }
+
+ template := &Certificate{
+ SerialNumber: big.NewInt(1),
+ Subject: pkix.Name{
+ CommonName: "Σ Acme Co",
+ },
+ NotBefore: time.Unix(1000, 0),
+ NotAfter: time.Unix(100000, 0),
+
+ BasicConstraintsValid: true,
+ IsCA: true,
+ }
+
+ serialiseAndParse := func(template *Certificate) *Certificate {
+ derBytes, err := CreateCertificate(rand.Reader, template, template, &rsaPriv.PublicKey, rsaPriv)
+ if err != nil {
+ t.Fatalf("failed to create certificate: %s", err)
+ return nil
+ }
+
+ cert, err := ParseCertificate(derBytes)
+ if err != nil {
+ t.Fatalf("failed to parse certificate: %s", err)
+ return nil
+ }
+
+ return cert
+ }
+
+ cert1 := serialiseAndParse(template)
+ if m := cert1.MaxPathLen; m != -1 {
+ t.Errorf("Omitting MaxPathLen didn't turn into -1, got %d", m)
+ }
+ if cert1.MaxPathLenZero {
+ t.Errorf("Omitting MaxPathLen resulted in MaxPathLenZero")
+ }
+
+ template.MaxPathLen = 1
+ cert2 := serialiseAndParse(template)
+ if m := cert2.MaxPathLen; m != 1 {
+ t.Errorf("Setting MaxPathLen didn't work. Got %d but set 1", m)
+ }
+ if cert2.MaxPathLenZero {
+ t.Errorf("Setting MaxPathLen resulted in MaxPathLenZero")
+ }
+
+ template.MaxPathLen = 0
+ template.MaxPathLenZero = true
+ cert3 := serialiseAndParse(template)
+ if m := cert3.MaxPathLen; m != 0 {
+ t.Errorf("Setting MaxPathLenZero didn't work, got %d", m)
+ }
+ if !cert3.MaxPathLenZero {
+ t.Errorf("Setting MaxPathLen to zero didn't result in MaxPathLenZero")
+ }
+}
+
// This CSR was generated with OpenSSL:
// openssl req -out CSR.csr -new -newkey rsa:2048 -nodes -keyout privateKey.key -config openssl.cnf
//
diff --git a/src/pkg/crypto/x509/x509_test_import.go b/src/crypto/x509/x509_test_import.go
index 3fda7da18..3fda7da18 100644
--- a/src/pkg/crypto/x509/x509_test_import.go
+++ b/src/crypto/x509/x509_test_import.go
diff --git a/src/pkg/database/sql/convert.go b/src/database/sql/convert.go
index c0b38a249..c0b38a249 100644
--- a/src/pkg/database/sql/convert.go
+++ b/src/database/sql/convert.go
diff --git a/src/pkg/database/sql/convert_test.go b/src/database/sql/convert_test.go
index 6e2483012..98af9fb64 100644
--- a/src/pkg/database/sql/convert_test.go
+++ b/src/database/sql/convert_test.go
@@ -283,6 +283,26 @@ func TestValueConverters(t *testing.T) {
// Tests that assigning to RawBytes doesn't allocate (and also works).
func TestRawBytesAllocs(t *testing.T) {
+ var tests = []struct {
+ name string
+ in interface{}
+ want string
+ }{
+ {"uint64", uint64(12345678), "12345678"},
+ {"uint32", uint32(1234), "1234"},
+ {"uint16", uint16(12), "12"},
+ {"uint8", uint8(1), "1"},
+ {"uint", uint(123), "123"},
+ {"int", int(123), "123"},
+ {"int8", int8(1), "1"},
+ {"int16", int16(12), "12"},
+ {"int32", int32(1234), "1234"},
+ {"int64", int64(12345678), "12345678"},
+ {"float32", float32(1.5), "1.5"},
+ {"float64", float64(64), "64"},
+ {"bool", false, "false"},
+ }
+
buf := make(RawBytes, 10)
test := func(name string, in interface{}, want string) {
if err := convertAssign(&buf, in); err != nil {
@@ -301,20 +321,11 @@ func TestRawBytesAllocs(t *testing.T) {
t.Fatalf("%s: got %q (len %d); want %q (len %d)", name, buf, len(buf), want, len(want))
}
}
+
n := testing.AllocsPerRun(100, func() {
- test("uint64", uint64(12345678), "12345678")
- test("uint32", uint32(1234), "1234")
- test("uint16", uint16(12), "12")
- test("uint8", uint8(1), "1")
- test("uint", uint(123), "123")
- test("int", int(123), "123")
- test("int8", int8(1), "1")
- test("int16", int16(12), "12")
- test("int32", int32(1234), "1234")
- test("int64", int64(12345678), "12345678")
- test("float32", float32(1.5), "1.5")
- test("float64", float64(64), "64")
- test("bool", false, "false")
+ for _, tt := range tests {
+ test(tt.name, tt.in, tt.want)
+ }
})
// The numbers below are only valid for 64-bit interface word sizes,
diff --git a/src/pkg/database/sql/doc.txt b/src/database/sql/doc.txt
index 405c5ed2a..405c5ed2a 100644
--- a/src/pkg/database/sql/doc.txt
+++ b/src/database/sql/doc.txt
diff --git a/src/pkg/database/sql/driver/driver.go b/src/database/sql/driver/driver.go
index eca25f29a..eca25f29a 100644
--- a/src/pkg/database/sql/driver/driver.go
+++ b/src/database/sql/driver/driver.go
diff --git a/src/pkg/database/sql/driver/types.go b/src/database/sql/driver/types.go
index 3305354df..3305354df 100644
--- a/src/pkg/database/sql/driver/types.go
+++ b/src/database/sql/driver/types.go
diff --git a/src/pkg/database/sql/driver/types_test.go b/src/database/sql/driver/types_test.go
index 1ce0ff065..1ce0ff065 100644
--- a/src/pkg/database/sql/driver/types_test.go
+++ b/src/database/sql/driver/types_test.go
diff --git a/src/pkg/database/sql/example_test.go b/src/database/sql/example_test.go
index dcb74e069..dcb74e069 100644
--- a/src/pkg/database/sql/example_test.go
+++ b/src/database/sql/example_test.go
diff --git a/src/pkg/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go
index c7db0dd77..a993fd46e 100644
--- a/src/pkg/database/sql/fakedb_test.go
+++ b/src/database/sql/fakedb_test.go
@@ -10,6 +10,7 @@ import (
"fmt"
"io"
"log"
+ "sort"
"strconv"
"strings"
"sync"
@@ -126,6 +127,29 @@ func init() {
Register("test", fdriver)
}
+func contains(list []string, y string) bool {
+ for _, x := range list {
+ if x == y {
+ return true
+ }
+ }
+ return false
+}
+
+type Dummy struct {
+ driver.Driver
+}
+
+func TestDrivers(t *testing.T) {
+ unregisterAllDrivers()
+ Register("test", fdriver)
+ Register("invalid", Dummy{})
+ all := Drivers()
+ if len(all) < 2 || !sort.StringsAreSorted(all) || !contains(all, "test") || !contains(all, "invalid") {
+ t.Fatalf("Drivers = %v, want sorted list with at least [invalid, test]", all)
+ }
+}
+
// Supports dsn forms:
// <dbname>
// <dbname>;<opts> (only currently supported option is `badConn`,
diff --git a/src/pkg/database/sql/sql.go b/src/database/sql/sql.go
index 765b80c60..6e6f246ae 100644
--- a/src/pkg/database/sql/sql.go
+++ b/src/database/sql/sql.go
@@ -13,12 +13,12 @@
package sql
import (
- "container/list"
"database/sql/driver"
"errors"
"fmt"
"io"
"runtime"
+ "sort"
"sync"
)
@@ -37,6 +37,21 @@ func Register(name string, driver driver.Driver) {
drivers[name] = driver
}
+func unregisterAllDrivers() {
+ // For tests.
+ drivers = make(map[string]driver.Driver)
+}
+
+// Drivers returns a sorted list of the names of the registered drivers.
+func Drivers() []string {
+ var list []string
+ for name := range drivers {
+ list = append(list, name)
+ }
+ sort.Strings(list)
+ return list
+}
+
// RawBytes is a byte slice that holds a reference to memory owned by
// the database itself. After a Scan into a RawBytes, the slice is only
// valid until the next call to Next, Scan, or Close.
@@ -198,8 +213,8 @@ type DB struct {
dsn string
mu sync.Mutex // protects following fields
- freeConn *list.List // of *driverConn
- connRequests *list.List // of connRequest
+ freeConn []*driverConn
+ connRequests []chan connRequest
numOpen int
pendingOpens int
// Used to signal the need for new connections
@@ -232,9 +247,6 @@ type driverConn struct {
inUse bool
onPut []func() // code (with db.mu held) run when conn is next returned
dbmuClosed bool // same as closed, but guarded by db.mu, for connIfFree
- // This is the Element returned by db.freeConn.PushFront(conn).
- // It's used by connIfFree to remove the conn from the freeConn list.
- listElem *list.Element
}
func (dc *driverConn) releaseConn(err error) {
@@ -437,8 +449,6 @@ func Open(driverName, dataSourceName string) (*DB, error) {
openerCh: make(chan struct{}, connectionRequestQueueSize),
lastPut: make(map[*driverConn]string),
}
- db.freeConn = list.New()
- db.connRequests = list.New()
go db.connectionOpener()
return db, nil
}
@@ -469,17 +479,13 @@ func (db *DB) Close() error {
}
close(db.openerCh)
var err error
- fns := make([]func() error, 0, db.freeConn.Len())
- for db.freeConn.Front() != nil {
- dc := db.freeConn.Front().Value.(*driverConn)
- dc.listElem = nil
+ fns := make([]func() error, 0, len(db.freeConn))
+ for _, dc := range db.freeConn {
fns = append(fns, dc.closeDBLocked())
- db.freeConn.Remove(db.freeConn.Front())
}
+ db.freeConn = nil
db.closed = true
- for db.connRequests.Front() != nil {
- req := db.connRequests.Front().Value.(connRequest)
- db.connRequests.Remove(db.connRequests.Front())
+ for _, req := range db.connRequests {
close(req)
}
db.mu.Unlock()
@@ -527,11 +533,11 @@ func (db *DB) SetMaxIdleConns(n int) {
db.maxIdle = db.maxOpen
}
var closing []*driverConn
- for db.freeConn.Len() > db.maxIdleConnsLocked() {
- dc := db.freeConn.Back().Value.(*driverConn)
- dc.listElem = nil
- db.freeConn.Remove(db.freeConn.Back())
- closing = append(closing, dc)
+ idleCount := len(db.freeConn)
+ maxIdle := db.maxIdleConnsLocked()
+ if idleCount > maxIdle {
+ closing = db.freeConn[maxIdle:]
+ db.freeConn = db.freeConn[:maxIdle]
}
db.mu.Unlock()
for _, c := range closing {
@@ -564,7 +570,7 @@ func (db *DB) SetMaxOpenConns(n int) {
// 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 := db.connRequests.Len() - db.pendingOpens
+ numRequests := len(db.connRequests) - db.pendingOpens
if db.maxOpen > 0 {
numCanOpen := db.maxOpen - (db.numOpen + db.pendingOpens)
if numRequests > numCanOpen {
@@ -580,7 +586,7 @@ func (db *DB) maybeOpenNewConnections() {
// Runs in a separate goroutine, opens new connections when requested.
func (db *DB) connectionOpener() {
- for _ = range db.openerCh {
+ for range db.openerCh {
db.openNewConnection()
}
}
@@ -616,7 +622,10 @@ func (db *DB) openNewConnection() {
// connRequest represents one request for a new connection
// When there are no idle connections available, DB.conn will create
// a new connRequest and put it on the db.connRequests list.
-type connRequest chan<- interface{} // takes either a *driverConn or an error
+type connRequest struct {
+ conn *driverConn
+ err error
+}
var errDBClosed = errors.New("sql: database is closed")
@@ -630,32 +639,21 @@ func (db *DB) conn() (*driverConn, error) {
// If db.maxOpen > 0 and the number of open connections is over the limit
// and there are no free connection, make a request and wait.
- if db.maxOpen > 0 && db.numOpen >= db.maxOpen && db.freeConn.Len() == 0 {
+ if db.maxOpen > 0 && db.numOpen >= db.maxOpen && len(db.freeConn) == 0 {
// Make the connRequest channel. It's buffered so that the
// connectionOpener doesn't block while waiting for the req to be read.
- ch := make(chan interface{}, 1)
- req := connRequest(ch)
- db.connRequests.PushBack(req)
+ req := make(chan connRequest, 1)
+ db.connRequests = append(db.connRequests, req)
db.maybeOpenNewConnections()
db.mu.Unlock()
- ret, ok := <-ch
- if !ok {
- return nil, errDBClosed
- }
- switch ret.(type) {
- case *driverConn:
- return ret.(*driverConn), nil
- case error:
- return nil, ret.(error)
- default:
- panic("sql: Unexpected type passed through connRequest.ch")
- }
+ ret := <-req
+ return ret.conn, ret.err
}
- if f := db.freeConn.Front(); f != nil {
- conn := f.Value.(*driverConn)
- conn.listElem = nil
- db.freeConn.Remove(f)
+ if c := len(db.freeConn); c > 0 {
+ conn := db.freeConn[0]
+ copy(db.freeConn, db.freeConn[1:])
+ db.freeConn = db.freeConn[:c-1]
conn.inUse = true
db.mu.Unlock()
return conn, nil
@@ -702,9 +700,15 @@ func (db *DB) connIfFree(wanted *driverConn) (*driverConn, error) {
if wanted.inUse {
return nil, errConnBusy
}
- if wanted.listElem != nil {
- db.freeConn.Remove(wanted.listElem)
- wanted.listElem = nil
+ idx := -1
+ for ii, v := range db.freeConn {
+ if v == wanted {
+ idx = ii
+ break
+ }
+ }
+ if idx >= 0 {
+ db.freeConn = append(db.freeConn[:idx], db.freeConn[idx+1:]...)
wanted.inUse = true
return wanted, nil
}
@@ -793,18 +797,23 @@ func (db *DB) putConn(dc *driverConn, err error) {
// If a connRequest was fulfilled or the *driverConn was placed in the
// freeConn list, then true is returned, otherwise false is returned.
func (db *DB) putConnDBLocked(dc *driverConn, err error) bool {
- if db.connRequests.Len() > 0 {
- req := db.connRequests.Front().Value.(connRequest)
- db.connRequests.Remove(db.connRequests.Front())
- if err != nil {
- req <- err
- } else {
+ if c := len(db.connRequests); c > 0 {
+ req := db.connRequests[0]
+ // This copy is O(n) but in practice faster than a linked list.
+ // TODO: consider compacting it down less often and
+ // moving the base instead?
+ copy(db.connRequests, db.connRequests[1:])
+ db.connRequests = db.connRequests[:c-1]
+ if err == nil {
dc.inUse = true
- req <- dc
+ }
+ req <- connRequest{
+ conn: dc,
+ err: err,
}
return true
- } else if err == nil && !db.closed && db.maxIdleConnsLocked() > db.freeConn.Len() {
- dc.listElem = db.freeConn.PushFront(dc)
+ } else if err == nil && !db.closed && db.maxIdleConnsLocked() > len(db.freeConn) {
+ db.freeConn = append(db.freeConn, dc)
return true
}
return false
@@ -1050,6 +1059,13 @@ type Tx struct {
// or Rollback. once done, all operations fail with
// ErrTxDone.
done bool
+
+ // All Stmts prepared for this transaction. These will be closed after the
+ // transaction has been committed or rolled back.
+ stmts struct {
+ sync.Mutex
+ v []*Stmt
+ }
}
var ErrTxDone = errors.New("sql: Transaction has already been committed or rolled back")
@@ -1071,6 +1087,15 @@ func (tx *Tx) grabConn() (*driverConn, error) {
return tx.dc, nil
}
+// Closes all Stmts prepared for this transaction.
+func (tx *Tx) closePrepared() {
+ tx.stmts.Lock()
+ for _, stmt := range tx.stmts.v {
+ stmt.Close()
+ }
+ tx.stmts.Unlock()
+}
+
// Commit commits the transaction.
func (tx *Tx) Commit() error {
if tx.done {
@@ -1078,8 +1103,12 @@ func (tx *Tx) Commit() error {
}
defer tx.close()
tx.dc.Lock()
- defer tx.dc.Unlock()
- return tx.txi.Commit()
+ err := tx.txi.Commit()
+ tx.dc.Unlock()
+ if err != driver.ErrBadConn {
+ tx.closePrepared()
+ }
+ return err
}
// Rollback aborts the transaction.
@@ -1089,8 +1118,12 @@ func (tx *Tx) Rollback() error {
}
defer tx.close()
tx.dc.Lock()
- defer tx.dc.Unlock()
- return tx.txi.Rollback()
+ err := tx.txi.Rollback()
+ tx.dc.Unlock()
+ if err != driver.ErrBadConn {
+ tx.closePrepared()
+ }
+ return err
}
// Prepare creates a prepared statement for use within a transaction.
@@ -1134,6 +1167,9 @@ func (tx *Tx) Prepare(query string) (*Stmt, error) {
},
query: query,
}
+ tx.stmts.Lock()
+ tx.stmts.v = append(tx.stmts.v, stmt)
+ tx.stmts.Unlock()
return stmt, nil
}
@@ -1162,7 +1198,7 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
dc.Lock()
si, err := dc.ci.Prepare(stmt.query)
dc.Unlock()
- return &Stmt{
+ txs := &Stmt{
db: tx.db,
tx: tx,
txsi: &driverStmt{
@@ -1172,6 +1208,10 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
query: stmt.query,
stickyErr: err,
}
+ tx.stmts.Lock()
+ tx.stmts.v = append(tx.stmts.v, txs)
+ tx.stmts.Unlock()
+ return txs
}
// Exec executes a query that doesn't return rows.
@@ -1333,15 +1373,12 @@ func (s *Stmt) connStmt() (ci *driverConn, releaseConn func(error), si driver.St
return ci, releaseConn, s.txsi.si, nil
}
- var cs connStmt
- match := false
for i := 0; i < len(s.css); i++ {
v := s.css[i]
_, err := s.db.connIfFree(v.dc)
if err == nil {
- match = true
- cs = v
- break
+ s.mu.Unlock()
+ return v.dc, v.dc.releaseConn, v.si, nil
}
if err == errConnClosed {
// Lazily remove dead conn from our freelist.
@@ -1353,28 +1390,41 @@ func (s *Stmt) connStmt() (ci *driverConn, releaseConn func(error), si driver.St
}
s.mu.Unlock()
- // Make a new conn if all are busy.
- // TODO(bradfitz): or wait for one? make configurable later?
- if !match {
- dc, err := s.db.conn()
- if err != nil {
- return nil, nil, nil, err
- }
- dc.Lock()
- si, err := dc.prepareLocked(s.query)
- dc.Unlock()
- if err != nil {
- s.db.putConn(dc, err)
- return nil, nil, nil, err
+ // If all connections are busy, either wait for one to become available (if
+ // we've already hit the maximum number of open connections) or create a
+ // new one.
+ //
+ // TODO(bradfitz): or always wait for one? make configurable later?
+ dc, err := s.db.conn()
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
+ // Do another pass over the list to see whether this statement has
+ // already been prepared on the connection assigned to us.
+ s.mu.Lock()
+ for _, v := range s.css {
+ if v.dc == dc {
+ s.mu.Unlock()
+ return dc, dc.releaseConn, v.si, nil
}
- s.mu.Lock()
- cs = connStmt{dc, si}
- s.css = append(s.css, cs)
- s.mu.Unlock()
}
+ s.mu.Unlock()
+
+ // No luck; we need to prepare the statement on this connection
+ dc.Lock()
+ si, err = dc.prepareLocked(s.query)
+ dc.Unlock()
+ if err != nil {
+ s.db.putConn(dc, err)
+ return nil, nil, nil, err
+ }
+ s.mu.Lock()
+ cs := connStmt{dc, si}
+ s.css = append(s.css, cs)
+ s.mu.Unlock()
- conn := cs.dc
- return conn, conn.releaseConn, cs.si, nil
+ return dc, dc.releaseConn, si, nil
}
// Query executes a prepared query statement with the given arguments
diff --git a/src/pkg/database/sql/sql_test.go b/src/database/sql/sql_test.go
index 7971f1491..34efdf254 100644
--- a/src/pkg/database/sql/sql_test.go
+++ b/src/database/sql/sql_test.go
@@ -24,7 +24,14 @@ func init() {
}
freedFrom := make(map[dbConn]string)
putConnHook = func(db *DB, c *driverConn) {
- if c.listElem != nil {
+ idx := -1
+ for i, v := range db.freeConn {
+ if v == c {
+ idx = i
+ break
+ }
+ }
+ if idx >= 0 {
// print before panic, as panic may get lost due to conflicting panic
// (all goroutines asleep) elsewhere, since we might not unlock
// the mutex in freeConn here.
@@ -79,15 +86,14 @@ func closeDB(t testing.TB, db *DB) {
t.Errorf("Error closing fakeConn: %v", err)
}
})
- for node, i := db.freeConn.Front(), 0; node != nil; node, i = node.Next(), i+1 {
- dc := node.Value.(*driverConn)
+ for i, dc := range db.freeConn {
if n := len(dc.openStmt); n > 0 {
// Just a sanity check. This is legal in
// general, but if we make the tests clean up
// their statements first, then we can safely
// verify this is always zero here, and any
// other value is a leak.
- t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, db.freeConn.Len(), n)
+ t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, len(db.freeConn), n)
}
}
err := db.Close()
@@ -105,10 +111,10 @@ func closeDB(t testing.TB, db *DB) {
// numPrepares assumes that db has exactly 1 idle conn and returns
// its count of calls to Prepare
func numPrepares(t *testing.T, db *DB) int {
- if n := db.freeConn.Len(); n != 1 {
+ if n := len(db.freeConn); n != 1 {
t.Fatalf("free conns = %d; want 1", n)
}
- return (db.freeConn.Front().Value.(*driverConn)).ci.(*fakeConn).numPrepare
+ return db.freeConn[0].ci.(*fakeConn).numPrepare
}
func (db *DB) numDeps() int {
@@ -133,7 +139,7 @@ func (db *DB) numDepsPollUntil(want int, d time.Duration) int {
func (db *DB) numFreeConns() int {
db.mu.Lock()
defer db.mu.Unlock()
- return db.freeConn.Len()
+ return len(db.freeConn)
}
func (db *DB) dumpDeps(t *testing.T) {
@@ -435,6 +441,33 @@ func TestExec(t *testing.T) {
}
}
+func TestTxPrepare(t *testing.T) {
+ db := newTestDB(t, "")
+ defer closeDB(t, db)
+ exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+ tx, err := db.Begin()
+ if err != nil {
+ t.Fatalf("Begin = %v", err)
+ }
+ stmt, err := tx.Prepare("INSERT|t1|name=?,age=?")
+ if err != nil {
+ t.Fatalf("Stmt, err = %v, %v", stmt, err)
+ }
+ defer stmt.Close()
+ _, err = stmt.Exec("Bobby", 7)
+ if err != nil {
+ t.Fatalf("Exec = %v", err)
+ }
+ err = tx.Commit()
+ if err != nil {
+ t.Fatalf("Commit = %v", err)
+ }
+ // Commit() should have closed the statement
+ if !stmt.closed {
+ t.Fatal("Stmt not closed after Commit")
+ }
+}
+
func TestTxStmt(t *testing.T) {
db := newTestDB(t, "")
defer closeDB(t, db)
@@ -458,6 +491,10 @@ func TestTxStmt(t *testing.T) {
if err != nil {
t.Fatalf("Commit = %v", err)
}
+ // Commit() should have closed the statement
+ if !txs.closed {
+ t.Fatal("Stmt not closed after Commit")
+ }
}
// Issue: http://golang.org/issue/2784
@@ -650,10 +687,10 @@ func TestQueryRowClosingStmt(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- if db.freeConn.Len() != 1 {
+ if len(db.freeConn) != 1 {
t.Fatalf("expected 1 free conn")
}
- fakeConn := (db.freeConn.Front().Value.(*driverConn)).ci.(*fakeConn)
+ fakeConn := db.freeConn[0].ci.(*fakeConn)
if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed {
t.Errorf("statement close mismatch: made %d, closed %d", made, closed)
}
@@ -878,13 +915,13 @@ func TestMaxIdleConns(t *testing.T) {
t.Fatal(err)
}
tx.Commit()
- if got := db.freeConn.Len(); got != 1 {
+ if got := len(db.freeConn); got != 1 {
t.Errorf("freeConns = %d; want 1", got)
}
db.SetMaxIdleConns(0)
- if got := db.freeConn.Len(); got != 0 {
+ if got := len(db.freeConn); got != 0 {
t.Errorf("freeConns after set to zero = %d; want 0", got)
}
@@ -893,7 +930,7 @@ func TestMaxIdleConns(t *testing.T) {
t.Fatal(err)
}
tx.Commit()
- if got := db.freeConn.Len(); got != 0 {
+ if got := len(db.freeConn); got != 0 {
t.Errorf("freeConns = %d; want 0", got)
}
}
@@ -1180,10 +1217,10 @@ func TestCloseConnBeforeStmts(t *testing.T) {
t.Fatal(err)
}
- if db.freeConn.Len() != 1 {
- t.Fatalf("expected 1 freeConn; got %d", db.freeConn.Len())
+ if len(db.freeConn) != 1 {
+ t.Fatalf("expected 1 freeConn; got %d", len(db.freeConn))
}
- dc := db.freeConn.Front().Value.(*driverConn)
+ dc := db.freeConn[0]
if dc.closed {
t.Errorf("conn shouldn't be closed")
}
@@ -1342,6 +1379,11 @@ func TestErrBadConnReconnect(t *testing.T) {
return nil
})
+ // Provide a way to force a re-prepare of a statement on next execution
+ forcePrepare := func(stmt *Stmt) {
+ stmt.css = nil
+ }
+
// stmt.Exec
stmt1, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?")
if err != nil {
@@ -1349,9 +1391,7 @@ func TestErrBadConnReconnect(t *testing.T) {
}
defer stmt1.Close()
// make sure we must prepare the stmt first
- for _, cs := range stmt1.css {
- cs.dc.inUse = true
- }
+ forcePrepare(stmt1)
stmtExec := func() error {
_, err := stmt1.Exec("Gopher", 3, false)
@@ -1367,9 +1407,7 @@ func TestErrBadConnReconnect(t *testing.T) {
}
defer stmt2.Close()
// make sure we must prepare the stmt first
- for _, cs := range stmt2.css {
- cs.dc.inUse = true
- }
+ forcePrepare(stmt2)
stmtQuery := func() error {
rows, err := stmt2.Query()
@@ -1708,7 +1746,7 @@ func doConcurrentTest(t testing.TB, ct concurrentTest) {
for i := 0; i < maxProcs*2; i++ {
go func() {
- for _ = range reqs {
+ for range reqs {
err := ct.test(t)
if err != nil {
wg.Done()
@@ -1750,7 +1788,7 @@ func manyConcurrentQueries(t testing.TB) {
for i := 0; i < maxProcs*2; i++ {
go func() {
- for _ = range reqs {
+ for range reqs {
rows, err := stmt.Query()
if err != nil {
t.Errorf("error on query: %v", err)
diff --git a/src/pkg/debug/dwarf/buf.go b/src/debug/dwarf/buf.go
index 53c46eb4b..53c46eb4b 100644
--- a/src/pkg/debug/dwarf/buf.go
+++ b/src/debug/dwarf/buf.go
diff --git a/src/pkg/debug/dwarf/const.go b/src/debug/dwarf/const.go
index 93c68881a..93c68881a 100644
--- a/src/pkg/debug/dwarf/const.go
+++ b/src/debug/dwarf/const.go
diff --git a/src/pkg/debug/dwarf/entry.go b/src/debug/dwarf/entry.go
index 665c6840d..665c6840d 100644
--- a/src/pkg/debug/dwarf/entry.go
+++ b/src/debug/dwarf/entry.go
diff --git a/src/pkg/debug/dwarf/open.go b/src/debug/dwarf/open.go
index c1b3f37ac..c1b3f37ac 100644
--- a/src/pkg/debug/dwarf/open.go
+++ b/src/debug/dwarf/open.go
diff --git a/src/pkg/debug/dwarf/testdata/typedef.c b/src/debug/dwarf/testdata/typedef.c
index f05f01564..f05f01564 100644
--- a/src/pkg/debug/dwarf/testdata/typedef.c
+++ b/src/debug/dwarf/testdata/typedef.c
diff --git a/src/pkg/debug/dwarf/testdata/typedef.elf b/src/debug/dwarf/testdata/typedef.elf
index b2062d2c4..b2062d2c4 100755
--- a/src/pkg/debug/dwarf/testdata/typedef.elf
+++ b/src/debug/dwarf/testdata/typedef.elf
Binary files differ
diff --git a/src/pkg/debug/dwarf/testdata/typedef.elf4 b/src/debug/dwarf/testdata/typedef.elf4
index 3d5a5a1b1..3d5a5a1b1 100644
--- a/src/pkg/debug/dwarf/testdata/typedef.elf4
+++ b/src/debug/dwarf/testdata/typedef.elf4
Binary files differ
diff --git a/src/pkg/debug/dwarf/testdata/typedef.macho b/src/debug/dwarf/testdata/typedef.macho
index f75afcccb..f75afcccb 100644
--- a/src/pkg/debug/dwarf/testdata/typedef.macho
+++ b/src/debug/dwarf/testdata/typedef.macho
Binary files differ
diff --git a/src/pkg/debug/dwarf/type.go b/src/debug/dwarf/type.go
index 68866d0b7..6986b19e7 100644
--- a/src/pkg/debug/dwarf/type.go
+++ b/src/debug/dwarf/type.go
@@ -88,6 +88,11 @@ type AddrType struct {
BasicType
}
+// An UnspecifiedType represents an implicit, unknown, ambiguous or nonexistent type.
+type UnspecifiedType struct {
+ BasicType
+}
+
// qualifiers
// A QualType represents a type that has the C/C++ "const", "restrict", or "volatile" qualifier.
@@ -113,7 +118,12 @@ func (t *ArrayType) String() string {
return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.String()
}
-func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() }
+func (t *ArrayType) Size() int64 {
+ if t.Count == -1 {
+ return 0
+ }
+ return t.Count * t.Type.Size()
+}
// A VoidType represents the C void type.
type VoidType struct {
@@ -364,32 +374,36 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
t.StrideBitSize, _ = e.Val(AttrStrideSize).(int64)
// Accumulate dimensions,
- ndim := 0
+ var dims []int64
for kid := next(); kid != nil; kid = next() {
// TODO(rsc): Can also be TagEnumerationType
// but haven't seen that in the wild yet.
switch kid.Tag {
case TagSubrangeType:
- max, ok := kid.Val(AttrUpperBound).(int64)
+ count, ok := kid.Val(AttrCount).(int64)
if !ok {
- max = -2 // Count == -1, as in x[].
- }
- if ndim == 0 {
- t.Count = max + 1
- } else {
- // Multidimensional array.
- // Create new array type underneath this one.
- t.Type = &ArrayType{Type: t.Type, Count: max + 1}
+ // Old binaries may have an upper bound instead.
+ count, ok = kid.Val(AttrUpperBound).(int64)
+ if ok {
+ count++ // Length is one more than upper bound.
+ } else if len(dims) == 0 {
+ count = -1 // As in x[].
+ }
}
- ndim++
+ dims = append(dims, count)
case TagEnumerationType:
err = DecodeError{name, kid.Offset, "cannot handle enumeration type as array bound"}
goto Error
}
}
- if ndim == 0 {
+ if len(dims) == 0 {
// LLVM generates this for x[].
- t.Count = -1
+ dims = []int64{-1}
+ }
+
+ t.Count = dims[0]
+ for i := len(dims) - 1; i >= 1; i-- {
+ t.Type = &ArrayType{Type: t.Type, Count: dims[i]}
}
case TagBaseType:
@@ -417,6 +431,17 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
typ = new(BoolType)
case encComplexFloat:
typ = new(ComplexType)
+ if name == "complex" {
+ // clang writes out 'complex' instead of 'complex float' or 'complex double'.
+ // clang also writes out a byte size that we can use to distinguish.
+ // See issue 8694.
+ switch byteSize, _ := e.Val(AttrByteSize).(int64); byteSize {
+ case 8:
+ name = "complex float"
+ case 16:
+ name = "complex double"
+ }
+ }
case encFloat:
typ = new(FloatType)
case encSigned:
@@ -465,7 +490,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
t.StructName, _ = e.Val(AttrName).(string)
t.Incomplete = e.Val(AttrDeclaration) != nil
t.Field = make([]*StructField, 0, 8)
- var lastFieldType Type
+ var lastFieldType *Type
var lastFieldBitOffset int64
for kid := next(); kid != nil; kid = next() {
if kid.Tag == TagMember {
@@ -507,7 +532,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
// (DWARF writes out 0-length arrays as if they were 1-length arrays.)
zeroArray(lastFieldType)
}
- lastFieldType = f.Type
+ lastFieldType = &f.Type
lastFieldBitOffset = bito
}
}
@@ -624,6 +649,15 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
typeCache[off] = t
t.Name, _ = e.Val(AttrName).(string)
t.Type = typeOf(e)
+
+ case TagUnspecifiedType:
+ // Unspecified type (DWARF v3 §5.2)
+ // Attributes:
+ // AttrName: name
+ t := new(UnspecifiedType)
+ typ = t
+ typeCache[off] = t
+ t.Name, _ = e.Val(AttrName).(string)
}
if err != nil {
@@ -647,13 +681,16 @@ Error:
return nil, err
}
-func zeroArray(t Type) {
- for {
- at, ok := t.(*ArrayType)
- if !ok {
- break
- }
- at.Count = 0
- t = at.Type
+func zeroArray(t *Type) {
+ if t == nil {
+ return
+ }
+ at, ok := (*t).(*ArrayType)
+ if !ok || at.Type.Size() == 0 {
+ return
}
+ // Make a copy to avoid invalidating typeCache.
+ tt := *at
+ tt.Count = 0
+ *t = &tt
}
diff --git a/src/pkg/debug/dwarf/type_test.go b/src/debug/dwarf/type_test.go
index 2cb85e74b..2cb85e74b 100644
--- a/src/pkg/debug/dwarf/type_test.go
+++ b/src/debug/dwarf/type_test.go
diff --git a/src/pkg/debug/dwarf/typeunit.go b/src/debug/dwarf/typeunit.go
index 3fd1c9973..3fd1c9973 100644
--- a/src/pkg/debug/dwarf/typeunit.go
+++ b/src/debug/dwarf/typeunit.go
diff --git a/src/pkg/debug/dwarf/unit.go b/src/debug/dwarf/unit.go
index 0fbc8e082..0fbc8e082 100644
--- a/src/pkg/debug/dwarf/unit.go
+++ b/src/debug/dwarf/unit.go
diff --git a/src/pkg/debug/elf/elf.go b/src/debug/elf/elf.go
index d622dae2a..cde296c79 100644
--- a/src/pkg/debug/elf/elf.go
+++ b/src/debug/elf/elf.go
@@ -11,6 +11,7 @@
* $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $
* $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $
* $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $
+ * "ELF for the ARM® 64-bit Architecture (AArch64)" (ARM IHI 0056B)
*
* Copyright (c) 1996-1998 John D. Polstra. All rights reserved.
* Copyright (c) 2001 David E. O'Brien
@@ -192,49 +193,50 @@ func (i Type) GoString() string { return stringName(uint32(i), typeStrings, true
type Machine uint16
const (
- EM_NONE Machine = 0 /* Unknown machine. */
- EM_M32 Machine = 1 /* AT&T WE32100. */
- EM_SPARC Machine = 2 /* Sun SPARC. */
- EM_386 Machine = 3 /* Intel i386. */
- EM_68K Machine = 4 /* Motorola 68000. */
- EM_88K Machine = 5 /* Motorola 88000. */
- EM_860 Machine = 7 /* Intel i860. */
- EM_MIPS Machine = 8 /* MIPS R3000 Big-Endian only. */
- EM_S370 Machine = 9 /* IBM System/370. */
- EM_MIPS_RS3_LE Machine = 10 /* MIPS R3000 Little-Endian. */
- EM_PARISC Machine = 15 /* HP PA-RISC. */
- EM_VPP500 Machine = 17 /* Fujitsu VPP500. */
- EM_SPARC32PLUS Machine = 18 /* SPARC v8plus. */
- EM_960 Machine = 19 /* Intel 80960. */
- EM_PPC Machine = 20 /* PowerPC 32-bit. */
- EM_PPC64 Machine = 21 /* PowerPC 64-bit. */
- EM_S390 Machine = 22 /* IBM System/390. */
- EM_V800 Machine = 36 /* NEC V800. */
- EM_FR20 Machine = 37 /* Fujitsu FR20. */
- EM_RH32 Machine = 38 /* TRW RH-32. */
- EM_RCE Machine = 39 /* Motorola RCE. */
- EM_ARM Machine = 40 /* ARM. */
- EM_SH Machine = 42 /* Hitachi SH. */
- EM_SPARCV9 Machine = 43 /* SPARC v9 64-bit. */
- EM_TRICORE Machine = 44 /* Siemens TriCore embedded processor. */
- EM_ARC Machine = 45 /* Argonaut RISC Core. */
- EM_H8_300 Machine = 46 /* Hitachi H8/300. */
- EM_H8_300H Machine = 47 /* Hitachi H8/300H. */
- EM_H8S Machine = 48 /* Hitachi H8S. */
- EM_H8_500 Machine = 49 /* Hitachi H8/500. */
- EM_IA_64 Machine = 50 /* Intel IA-64 Processor. */
- EM_MIPS_X Machine = 51 /* Stanford MIPS-X. */
- EM_COLDFIRE Machine = 52 /* Motorola ColdFire. */
- EM_68HC12 Machine = 53 /* Motorola M68HC12. */
- EM_MMA Machine = 54 /* Fujitsu MMA. */
- EM_PCP Machine = 55 /* Siemens PCP. */
- EM_NCPU Machine = 56 /* Sony nCPU. */
- EM_NDR1 Machine = 57 /* Denso NDR1 microprocessor. */
- EM_STARCORE Machine = 58 /* Motorola Star*Core processor. */
- EM_ME16 Machine = 59 /* Toyota ME16 processor. */
- EM_ST100 Machine = 60 /* STMicroelectronics ST100 processor. */
- EM_TINYJ Machine = 61 /* Advanced Logic Corp. TinyJ processor. */
- EM_X86_64 Machine = 62 /* Advanced Micro Devices x86-64 */
+ EM_NONE Machine = 0 /* Unknown machine. */
+ EM_M32 Machine = 1 /* AT&T WE32100. */
+ EM_SPARC Machine = 2 /* Sun SPARC. */
+ EM_386 Machine = 3 /* Intel i386. */
+ EM_68K Machine = 4 /* Motorola 68000. */
+ EM_88K Machine = 5 /* Motorola 88000. */
+ EM_860 Machine = 7 /* Intel i860. */
+ EM_MIPS Machine = 8 /* MIPS R3000 Big-Endian only. */
+ EM_S370 Machine = 9 /* IBM System/370. */
+ EM_MIPS_RS3_LE Machine = 10 /* MIPS R3000 Little-Endian. */
+ EM_PARISC Machine = 15 /* HP PA-RISC. */
+ EM_VPP500 Machine = 17 /* Fujitsu VPP500. */
+ EM_SPARC32PLUS Machine = 18 /* SPARC v8plus. */
+ EM_960 Machine = 19 /* Intel 80960. */
+ EM_PPC Machine = 20 /* PowerPC 32-bit. */
+ EM_PPC64 Machine = 21 /* PowerPC 64-bit. */
+ EM_S390 Machine = 22 /* IBM System/390. */
+ EM_V800 Machine = 36 /* NEC V800. */
+ EM_FR20 Machine = 37 /* Fujitsu FR20. */
+ EM_RH32 Machine = 38 /* TRW RH-32. */
+ EM_RCE Machine = 39 /* Motorola RCE. */
+ EM_ARM Machine = 40 /* ARM. */
+ EM_SH Machine = 42 /* Hitachi SH. */
+ EM_SPARCV9 Machine = 43 /* SPARC v9 64-bit. */
+ EM_TRICORE Machine = 44 /* Siemens TriCore embedded processor. */
+ EM_ARC Machine = 45 /* Argonaut RISC Core. */
+ EM_H8_300 Machine = 46 /* Hitachi H8/300. */
+ EM_H8_300H Machine = 47 /* Hitachi H8/300H. */
+ EM_H8S Machine = 48 /* Hitachi H8S. */
+ EM_H8_500 Machine = 49 /* Hitachi H8/500. */
+ EM_IA_64 Machine = 50 /* Intel IA-64 Processor. */
+ EM_MIPS_X Machine = 51 /* Stanford MIPS-X. */
+ EM_COLDFIRE Machine = 52 /* Motorola ColdFire. */
+ EM_68HC12 Machine = 53 /* Motorola M68HC12. */
+ EM_MMA Machine = 54 /* Fujitsu MMA. */
+ EM_PCP Machine = 55 /* Siemens PCP. */
+ EM_NCPU Machine = 56 /* Sony nCPU. */
+ EM_NDR1 Machine = 57 /* Denso NDR1 microprocessor. */
+ EM_STARCORE Machine = 58 /* Motorola Star*Core processor. */
+ EM_ME16 Machine = 59 /* Toyota ME16 processor. */
+ EM_ST100 Machine = 60 /* STMicroelectronics ST100 processor. */
+ EM_TINYJ Machine = 61 /* Advanced Logic Corp. TinyJ processor. */
+ EM_X86_64 Machine = 62 /* Advanced Micro Devices x86-64 */
+ EM_AARCH64 Machine = 183 /* ARM 64-bit Architecture (AArch64) */
/* Non-standard or deprecated. */
EM_486 Machine = 6 /* Intel i486. */
@@ -774,6 +776,256 @@ var rx86_64Strings = []intName{
func (i R_X86_64) String() string { return stringName(uint32(i), rx86_64Strings, false) }
func (i R_X86_64) GoString() string { return stringName(uint32(i), rx86_64Strings, true) }
+// Relocation types for AArch64 (aka arm64)
+type R_AARCH64 int
+
+const (
+ R_AARCH64_NONE R_AARCH64 = 0
+ R_AARCH64_P32_ABS32 R_AARCH64 = 1
+ R_AARCH64_P32_ABS16 R_AARCH64 = 2
+ R_AARCH64_P32_PREL32 R_AARCH64 = 3
+ R_AARCH64_P32_PREL16 R_AARCH64 = 4
+ R_AARCH64_P32_MOVW_UABS_G0 R_AARCH64 = 5
+ R_AARCH64_P32_MOVW_UABS_G0_NC R_AARCH64 = 6
+ R_AARCH64_P32_MOVW_UABS_G1 R_AARCH64 = 7
+ R_AARCH64_P32_MOVW_SABS_G0 R_AARCH64 = 8
+ R_AARCH64_P32_LD_PREL_LO19 R_AARCH64 = 9
+ R_AARCH64_P32_ADR_PREL_LO21 R_AARCH64 = 10
+ R_AARCH64_P32_ADR_PREL_PG_HI21 R_AARCH64 = 11
+ R_AARCH64_P32_ADD_ABS_LO12_NC R_AARCH64 = 12
+ R_AARCH64_P32_LDST8_ABS_LO12_NC R_AARCH64 = 13
+ R_AARCH64_P32_LDST16_ABS_LO12_NC R_AARCH64 = 14
+ R_AARCH64_P32_LDST32_ABS_LO12_NC R_AARCH64 = 15
+ R_AARCH64_P32_LDST64_ABS_LO12_NC R_AARCH64 = 16
+ R_AARCH64_P32_LDST128_ABS_LO12_NC R_AARCH64 = 17
+ R_AARCH64_P32_TSTBR14 R_AARCH64 = 18
+ R_AARCH64_P32_CONDBR19 R_AARCH64 = 19
+ R_AARCH64_P32_JUMP26 R_AARCH64 = 20
+ R_AARCH64_P32_CALL26 R_AARCH64 = 21
+ R_AARCH64_P32_GOT_LD_PREL19 R_AARCH64 = 25
+ R_AARCH64_P32_ADR_GOT_PAGE R_AARCH64 = 26
+ R_AARCH64_P32_LD32_GOT_LO12_NC R_AARCH64 = 27
+ R_AARCH64_P32_TLSGD_ADR_PAGE21 R_AARCH64 = 81
+ R_AARCH64_P32_TLSGD_ADD_LO12_NC R_AARCH64 = 82
+ R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21 R_AARCH64 = 103
+ R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC R_AARCH64 = 104
+ R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19 R_AARCH64 = 105
+ R_AARCH64_P32_TLSLE_MOVW_TPREL_G1 R_AARCH64 = 106
+ R_AARCH64_P32_TLSLE_MOVW_TPREL_G0 R_AARCH64 = 107
+ R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC R_AARCH64 = 108
+ R_AARCH64_P32_TLSLE_ADD_TPREL_HI12 R_AARCH64 = 109
+ R_AARCH64_P32_TLSLE_ADD_TPREL_LO12 R_AARCH64 = 110
+ R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC R_AARCH64 = 111
+ R_AARCH64_P32_TLSDESC_LD_PREL19 R_AARCH64 = 122
+ R_AARCH64_P32_TLSDESC_ADR_PREL21 R_AARCH64 = 123
+ R_AARCH64_P32_TLSDESC_ADR_PAGE21 R_AARCH64 = 124
+ R_AARCH64_P32_TLSDESC_LD32_LO12_NC R_AARCH64 = 125
+ R_AARCH64_P32_TLSDESC_ADD_LO12_NC R_AARCH64 = 126
+ R_AARCH64_P32_TLSDESC_CALL R_AARCH64 = 127
+ R_AARCH64_P32_COPY R_AARCH64 = 180
+ R_AARCH64_P32_GLOB_DAT R_AARCH64 = 181
+ R_AARCH64_P32_JUMP_SLOT R_AARCH64 = 182
+ R_AARCH64_P32_RELATIVE R_AARCH64 = 183
+ R_AARCH64_P32_TLS_DTPMOD R_AARCH64 = 184
+ R_AARCH64_P32_TLS_DTPREL R_AARCH64 = 185
+ R_AARCH64_P32_TLS_TPREL R_AARCH64 = 186
+ R_AARCH64_P32_TLSDESC R_AARCH64 = 187
+ R_AARCH64_P32_IRELATIVE R_AARCH64 = 188
+ R_AARCH64_NULL R_AARCH64 = 256
+ R_AARCH64_ABS64 R_AARCH64 = 257
+ R_AARCH64_ABS32 R_AARCH64 = 258
+ R_AARCH64_ABS16 R_AARCH64 = 259
+ R_AARCH64_PREL64 R_AARCH64 = 260
+ R_AARCH64_PREL32 R_AARCH64 = 261
+ R_AARCH64_PREL16 R_AARCH64 = 262
+ R_AARCH64_MOVW_UABS_G0 R_AARCH64 = 263
+ R_AARCH64_MOVW_UABS_G0_NC R_AARCH64 = 264
+ R_AARCH64_MOVW_UABS_G1 R_AARCH64 = 265
+ R_AARCH64_MOVW_UABS_G1_NC R_AARCH64 = 266
+ R_AARCH64_MOVW_UABS_G2 R_AARCH64 = 267
+ R_AARCH64_MOVW_UABS_G2_NC R_AARCH64 = 268
+ R_AARCH64_MOVW_UABS_G3 R_AARCH64 = 269
+ R_AARCH64_MOVW_SABS_G0 R_AARCH64 = 270
+ R_AARCH64_MOVW_SABS_G1 R_AARCH64 = 271
+ R_AARCH64_MOVW_SABS_G2 R_AARCH64 = 272
+ R_AARCH64_LD_PREL_LO19 R_AARCH64 = 273
+ R_AARCH64_ADR_PREL_LO21 R_AARCH64 = 274
+ R_AARCH64_ADR_PREL_PG_HI21 R_AARCH64 = 275
+ R_AARCH64_ADR_PREL_PG_HI21_NC R_AARCH64 = 276
+ R_AARCH64_ADD_ABS_LO12_NC R_AARCH64 = 277
+ R_AARCH64_LDST8_ABS_LO12_NC R_AARCH64 = 278
+ R_AARCH64_TSTBR14 R_AARCH64 = 279
+ R_AARCH64_CONDBR19 R_AARCH64 = 280
+ R_AARCH64_JUMP26 R_AARCH64 = 282
+ R_AARCH64_CALL26 R_AARCH64 = 283
+ R_AARCH64_LDST16_ABS_LO12_NC R_AARCH64 = 284
+ R_AARCH64_LDST32_ABS_LO12_NC R_AARCH64 = 285
+ R_AARCH64_LDST64_ABS_LO12_NC R_AARCH64 = 286
+ R_AARCH64_LDST128_ABS_LO12_NC R_AARCH64 = 299
+ R_AARCH64_GOT_LD_PREL19 R_AARCH64 = 309
+ R_AARCH64_ADR_GOT_PAGE R_AARCH64 = 311
+ R_AARCH64_LD64_GOT_LO12_NC R_AARCH64 = 312
+ R_AARCH64_TLSGD_ADR_PAGE21 R_AARCH64 = 513
+ R_AARCH64_TLSGD_ADD_LO12_NC R_AARCH64 = 514
+ R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 R_AARCH64 = 539
+ R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC R_AARCH64 = 540
+ R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 R_AARCH64 = 541
+ R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC R_AARCH64 = 542
+ R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 R_AARCH64 = 543
+ R_AARCH64_TLSLE_MOVW_TPREL_G2 R_AARCH64 = 544
+ R_AARCH64_TLSLE_MOVW_TPREL_G1 R_AARCH64 = 545
+ R_AARCH64_TLSLE_MOVW_TPREL_G1_NC R_AARCH64 = 546
+ R_AARCH64_TLSLE_MOVW_TPREL_G0 R_AARCH64 = 547
+ R_AARCH64_TLSLE_MOVW_TPREL_G0_NC R_AARCH64 = 548
+ R_AARCH64_TLSLE_ADD_TPREL_HI12 R_AARCH64 = 549
+ R_AARCH64_TLSLE_ADD_TPREL_LO12 R_AARCH64 = 550
+ R_AARCH64_TLSLE_ADD_TPREL_LO12_NC R_AARCH64 = 551
+ R_AARCH64_TLSDESC_LD_PREL19 R_AARCH64 = 560
+ R_AARCH64_TLSDESC_ADR_PREL21 R_AARCH64 = 561
+ R_AARCH64_TLSDESC_ADR_PAGE21 R_AARCH64 = 562
+ R_AARCH64_TLSDESC_LD64_LO12_NC R_AARCH64 = 563
+ R_AARCH64_TLSDESC_ADD_LO12_NC R_AARCH64 = 564
+ R_AARCH64_TLSDESC_OFF_G1 R_AARCH64 = 565
+ R_AARCH64_TLSDESC_OFF_G0_NC R_AARCH64 = 566
+ R_AARCH64_TLSDESC_LDR R_AARCH64 = 567
+ R_AARCH64_TLSDESC_ADD R_AARCH64 = 568
+ R_AARCH64_TLSDESC_CALL R_AARCH64 = 569
+ R_AARCH64_COPY R_AARCH64 = 1024
+ R_AARCH64_GLOB_DAT R_AARCH64 = 1025
+ R_AARCH64_JUMP_SLOT R_AARCH64 = 1026
+ R_AARCH64_RELATIVE R_AARCH64 = 1027
+ R_AARCH64_TLS_DTPMOD64 R_AARCH64 = 1028
+ R_AARCH64_TLS_DTPREL64 R_AARCH64 = 1029
+ R_AARCH64_TLS_TPREL64 R_AARCH64 = 1030
+ R_AARCH64_TLSDESC R_AARCH64 = 1031
+ R_AARCH64_IRELATIVE R_AARCH64 = 1032
+)
+
+var raarch64Strings = []intName{
+ {0, "R_AARCH64_NONE"},
+ {1, "R_AARCH64_P32_ABS32"},
+ {2, "R_AARCH64_P32_ABS16"},
+ {3, "R_AARCH64_P32_PREL32"},
+ {4, "R_AARCH64_P32_PREL16"},
+ {5, "R_AARCH64_P32_MOVW_UABS_G0"},
+ {6, "R_AARCH64_P32_MOVW_UABS_G0_NC"},
+ {7, "R_AARCH64_P32_MOVW_UABS_G1"},
+ {8, "R_AARCH64_P32_MOVW_SABS_G0"},
+ {9, "R_AARCH64_P32_LD_PREL_LO19"},
+ {10, "R_AARCH64_P32_ADR_PREL_LO21"},
+ {11, "R_AARCH64_P32_ADR_PREL_PG_HI21"},
+ {12, "R_AARCH64_P32_ADD_ABS_LO12_NC"},
+ {13, "R_AARCH64_P32_LDST8_ABS_LO12_NC"},
+ {14, "R_AARCH64_P32_LDST16_ABS_LO12_NC"},
+ {15, "R_AARCH64_P32_LDST32_ABS_LO12_NC"},
+ {16, "R_AARCH64_P32_LDST64_ABS_LO12_NC"},
+ {17, "R_AARCH64_P32_LDST128_ABS_LO12_NC"},
+ {18, "R_AARCH64_P32_TSTBR14"},
+ {19, "R_AARCH64_P32_CONDBR19"},
+ {20, "R_AARCH64_P32_JUMP26"},
+ {21, "R_AARCH64_P32_CALL26"},
+ {25, "R_AARCH64_P32_GOT_LD_PREL19"},
+ {26, "R_AARCH64_P32_ADR_GOT_PAGE"},
+ {27, "R_AARCH64_P32_LD32_GOT_LO12_NC"},
+ {81, "R_AARCH64_P32_TLSGD_ADR_PAGE21"},
+ {82, "R_AARCH64_P32_TLSGD_ADD_LO12_NC"},
+ {103, "R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21"},
+ {104, "R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC"},
+ {105, "R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19"},
+ {106, "R_AARCH64_P32_TLSLE_MOVW_TPREL_G1"},
+ {107, "R_AARCH64_P32_TLSLE_MOVW_TPREL_G0"},
+ {108, "R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC"},
+ {109, "R_AARCH64_P32_TLSLE_ADD_TPREL_HI12"},
+ {110, "R_AARCH64_P32_TLSLE_ADD_TPREL_LO12"},
+ {111, "R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC"},
+ {122, "R_AARCH64_P32_TLSDESC_LD_PREL19"},
+ {123, "R_AARCH64_P32_TLSDESC_ADR_PREL21"},
+ {124, "R_AARCH64_P32_TLSDESC_ADR_PAGE21"},
+ {125, "R_AARCH64_P32_TLSDESC_LD32_LO12_NC"},
+ {126, "R_AARCH64_P32_TLSDESC_ADD_LO12_NC"},
+ {127, "R_AARCH64_P32_TLSDESC_CALL"},
+ {180, "R_AARCH64_P32_COPY"},
+ {181, "R_AARCH64_P32_GLOB_DAT"},
+ {182, "R_AARCH64_P32_JUMP_SLOT"},
+ {183, "R_AARCH64_P32_RELATIVE"},
+ {184, "R_AARCH64_P32_TLS_DTPMOD"},
+ {185, "R_AARCH64_P32_TLS_DTPREL"},
+ {186, "R_AARCH64_P32_TLS_TPREL"},
+ {187, "R_AARCH64_P32_TLSDESC"},
+ {188, "R_AARCH64_P32_IRELATIVE"},
+ {256, "R_AARCH64_NULL"},
+ {257, "R_AARCH64_ABS64"},
+ {258, "R_AARCH64_ABS32"},
+ {259, "R_AARCH64_ABS16"},
+ {260, "R_AARCH64_PREL64"},
+ {261, "R_AARCH64_PREL32"},
+ {262, "R_AARCH64_PREL16"},
+ {263, "R_AARCH64_MOVW_UABS_G0"},
+ {264, "R_AARCH64_MOVW_UABS_G0_NC"},
+ {265, "R_AARCH64_MOVW_UABS_G1"},
+ {266, "R_AARCH64_MOVW_UABS_G1_NC"},
+ {267, "R_AARCH64_MOVW_UABS_G2"},
+ {268, "R_AARCH64_MOVW_UABS_G2_NC"},
+ {269, "R_AARCH64_MOVW_UABS_G3"},
+ {270, "R_AARCH64_MOVW_SABS_G0"},
+ {271, "R_AARCH64_MOVW_SABS_G1"},
+ {272, "R_AARCH64_MOVW_SABS_G2"},
+ {273, "R_AARCH64_LD_PREL_LO19"},
+ {274, "R_AARCH64_ADR_PREL_LO21"},
+ {275, "R_AARCH64_ADR_PREL_PG_HI21"},
+ {276, "R_AARCH64_ADR_PREL_PG_HI21_NC"},
+ {277, "R_AARCH64_ADD_ABS_LO12_NC"},
+ {278, "R_AARCH64_LDST8_ABS_LO12_NC"},
+ {279, "R_AARCH64_TSTBR14"},
+ {280, "R_AARCH64_CONDBR19"},
+ {282, "R_AARCH64_JUMP26"},
+ {283, "R_AARCH64_CALL26"},
+ {284, "R_AARCH64_LDST16_ABS_LO12_NC"},
+ {285, "R_AARCH64_LDST32_ABS_LO12_NC"},
+ {286, "R_AARCH64_LDST64_ABS_LO12_NC"},
+ {299, "R_AARCH64_LDST128_ABS_LO12_NC"},
+ {309, "R_AARCH64_GOT_LD_PREL19"},
+ {311, "R_AARCH64_ADR_GOT_PAGE"},
+ {312, "R_AARCH64_LD64_GOT_LO12_NC"},
+ {513, "R_AARCH64_TLSGD_ADR_PAGE21"},
+ {514, "R_AARCH64_TLSGD_ADD_LO12_NC"},
+ {539, "R_AARCH64_TLSIE_MOVW_GOTTPREL_G1"},
+ {540, "R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC"},
+ {541, "R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21"},
+ {542, "R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC"},
+ {543, "R_AARCH64_TLSIE_LD_GOTTPREL_PREL19"},
+ {544, "R_AARCH64_TLSLE_MOVW_TPREL_G2"},
+ {545, "R_AARCH64_TLSLE_MOVW_TPREL_G1"},
+ {546, "R_AARCH64_TLSLE_MOVW_TPREL_G1_NC"},
+ {547, "R_AARCH64_TLSLE_MOVW_TPREL_G0"},
+ {548, "R_AARCH64_TLSLE_MOVW_TPREL_G0_NC"},
+ {549, "R_AARCH64_TLSLE_ADD_TPREL_HI12"},
+ {550, "R_AARCH64_TLSLE_ADD_TPREL_LO12"},
+ {551, "R_AARCH64_TLSLE_ADD_TPREL_LO12_NC"},
+ {560, "R_AARCH64_TLSDESC_LD_PREL19"},
+ {561, "R_AARCH64_TLSDESC_ADR_PREL21"},
+ {562, "R_AARCH64_TLSDESC_ADR_PAGE21"},
+ {563, "R_AARCH64_TLSDESC_LD64_LO12_NC"},
+ {564, "R_AARCH64_TLSDESC_ADD_LO12_NC"},
+ {565, "R_AARCH64_TLSDESC_OFF_G1"},
+ {566, "R_AARCH64_TLSDESC_OFF_G0_NC"},
+ {567, "R_AARCH64_TLSDESC_LDR"},
+ {568, "R_AARCH64_TLSDESC_ADD"},
+ {569, "R_AARCH64_TLSDESC_CALL"},
+ {1024, "R_AARCH64_COPY"},
+ {1025, "R_AARCH64_GLOB_DAT"},
+ {1026, "R_AARCH64_JUMP_SLOT"},
+ {1027, "R_AARCH64_RELATIVE"},
+ {1028, "R_AARCH64_TLS_DTPMOD64"},
+ {1029, "R_AARCH64_TLS_DTPREL64"},
+ {1030, "R_AARCH64_TLS_TPREL64"},
+ {1031, "R_AARCH64_TLSDESC"},
+ {1032, "R_AARCH64_IRELATIVE"},
+}
+
+func (i R_AARCH64) String() string { return stringName(uint32(i), raarch64Strings, false) }
+func (i R_AARCH64) GoString() string { return stringName(uint32(i), raarch64Strings, true) }
+
// Relocation types for Alpha.
type R_ALPHA int
diff --git a/src/pkg/debug/elf/elf_test.go b/src/debug/elf/elf_test.go
index e3c51bb71..e3c51bb71 100644
--- a/src/pkg/debug/elf/elf_test.go
+++ b/src/debug/elf/elf_test.go
diff --git a/src/pkg/debug/elf/file.go b/src/debug/elf/file.go
index 423932fe0..de8a3a24f 100644
--- a/src/pkg/debug/elf/file.go
+++ b/src/debug/elf/file.go
@@ -405,10 +405,14 @@ func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) {
return nil, nil, errors.New("not implemented")
}
+// ErrNoSymbols is returned by File.Symbols and File.DynamicSymbols
+// if there is no such section in the File.
+var ErrNoSymbols = errors.New("no symbol section")
+
func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
symtabSection := f.SectionByType(typ)
if symtabSection == nil {
- return nil, nil, errors.New("no symbol section")
+ return nil, nil, ErrNoSymbols
}
data, err := symtabSection.Data()
@@ -451,7 +455,7 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
symtabSection := f.SectionByType(typ)
if symtabSection == nil {
- return nil, nil, errors.New("no symbol section")
+ return nil, nil, ErrNoSymbols
}
data, err := symtabSection.Data()
@@ -525,6 +529,9 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
if f.Class == ELFCLASS32 && f.Machine == EM_386 {
return f.applyRelocations386(dst, rels)
}
+ if f.Class == ELFCLASS64 && f.Machine == EM_AARCH64 {
+ return f.applyRelocationsARM64(dst, rels)
+ }
return errors.New("not implemented")
}
@@ -557,6 +564,10 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
continue
}
+ // There are relocations, so this must be a normal
+ // object file, and we only look at section symbols,
+ // so we assume that the symbol value is 0.
+
switch t {
case R_X86_64_64:
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
@@ -611,6 +622,55 @@ func (f *File) applyRelocations386(dst []byte, rels []byte) error {
return nil
}
+func (f *File) applyRelocationsARM64(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)
+ symNo := rela.Info >> 32
+ t := R_AARCH64(rela.Info & 0xffff)
+
+ 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
+ }
+
+ // There are relocations, so this must be a normal
+ // object file, and we only look at section symbols,
+ // so we assume that the symbol value is 0.
+
+ switch t {
+ case R_AARCH64_ABS64:
+ 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_AARCH64_ABS32:
+ 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) {
// There are many other DWARF sections, but these
// are the required ones, and the debug/dwarf package
@@ -633,7 +693,7 @@ func (f *File) DWARF() (*dwarf.Data, error) {
// If there's a relocation table for .debug_info, we have to process it
// now otherwise the data in .debug_info is invalid for x86-64 objects.
rela := f.Section(".rela.debug_info")
- if rela != nil && rela.Type == SHT_RELA && f.Machine == EM_X86_64 {
+ if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64) {
data, err := rela.Data()
if err != nil {
return nil, err
@@ -698,7 +758,8 @@ func (f *File) DWARF() (*dwarf.Data, error) {
return d, nil
}
-// Symbols returns the symbol table for f.
+// Symbols returns the symbol table for f. The symbols will be listed in the order
+// they appear in f.
//
// For compatibility with Go 1.0, Symbols omits the null symbol at index 0.
// After retrieving the symbols as symtab, an externally supplied index x
@@ -708,6 +769,17 @@ func (f *File) Symbols() ([]Symbol, error) {
return sym, err
}
+// DynamicSymbols returns the dynamic symbol table for f. The symbols
+// will be listed in the order they appear in f.
+//
+// For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0.
+// After retrieving the symbols as symtab, an externally supplied index x
+// corresponds to symtab[x-1], not symtab[x].
+func (f *File) DynamicSymbols() ([]Symbol, error) {
+ sym, _, err := f.getSymbols(SHT_DYNSYM)
+ return sym, err
+}
+
type ImportedSymbol struct {
Name string
Version string
diff --git a/src/pkg/debug/elf/file_test.go b/src/debug/elf/file_test.go
index 7f88a54bc..5e5ba52f3 100644
--- a/src/pkg/debug/elf/file_test.go
+++ b/src/debug/elf/file_test.go
@@ -166,11 +166,11 @@ func TestOpen(t *testing.T) {
} else {
f, err = Open(tt.file)
}
- defer f.Close()
if err != nil {
t.Errorf("cannot open file %s: %v", tt.file, err)
continue
}
+ defer f.Close()
if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
continue
@@ -261,6 +261,12 @@ var relocationTests = []relocationTest{
},
},
{
+ "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"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: int64(0x24)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
+ },
+ },
+ {
"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)"}, {Attr: dwarf.AttrLanguage, Val: int64(12)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c"}, {Attr: dwarf.AttrStmtList, Val: int64(0)}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}}}},
diff --git a/src/debug/elf/symbols_test.go b/src/debug/elf/symbols_test.go
new file mode 100644
index 000000000..1b79520e3
--- /dev/null
+++ b/src/debug/elf/symbols_test.go
@@ -0,0 +1,834 @@
+// 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 elf
+
+import (
+ "io"
+ "path"
+ "reflect"
+ "testing"
+)
+
+// TODO: remove duplicate code
+func TestSymbols(t *testing.T) {
+ do := func(file string, ts []Symbol, getfunc func(*File) ([]Symbol, error)) {
+ var f *File
+ var err error
+ if path.Ext(file) == ".gz" {
+ var r io.ReaderAt
+ if r, err = decompress(file); err == nil {
+ f, err = NewFile(r)
+ }
+ } else {
+ f, err = Open(file)
+ }
+ if err != nil {
+ t.Errorf("TestSymbols: cannot open file %s: %v", file, err)
+ return
+ }
+ defer f.Close()
+ fs, err := getfunc(f)
+ if err != nil && err != ErrNoSymbols {
+ t.Error(err)
+ return
+ } else if err == ErrNoSymbols {
+ fs = []Symbol{}
+ }
+ if !reflect.DeepEqual(ts, fs) {
+ t.Errorf("%s: Symbols = %v, want %v", file, ts, fs)
+ }
+ }
+ for file, ts := range symbolsGolden {
+ do(file, ts, (*File).Symbols)
+ }
+ for file, ts := range dynamicSymbolsGolden {
+ do(file, ts, (*File).DynamicSymbols)
+ }
+}
+
+// golden symbol table data generated by testdata/getgoldsym.c
+
+var symbolsGolden = map[string][]Symbol{
+ "testdata/gcc-amd64-linux-exec": {
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x1,
+ Value: 0x400200,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x2,
+ Value: 0x40021C,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x3,
+ Value: 0x400240,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x4,
+ Value: 0x400268,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x5,
+ Value: 0x400288,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x6,
+ Value: 0x4002E8,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x7,
+ Value: 0x400326,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x8,
+ Value: 0x400330,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x9,
+ Value: 0x400350,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0xA,
+ Value: 0x400368,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0xB,
+ Value: 0x400398,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0xC,
+ Value: 0x4003B0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0xD,
+ Value: 0x4003E0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0xE,
+ Value: 0x400594,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0xF,
+ Value: 0x4005A4,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x10,
+ Value: 0x4005B8,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x11,
+ Value: 0x4005E0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x12,
+ Value: 0x600688,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x13,
+ Value: 0x600698,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x14,
+ Value: 0x6006A8,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x15,
+ Value: 0x6006B0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x16,
+ Value: 0x600850,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x17,
+ Value: 0x600858,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x18,
+ Value: 0x600880,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x19,
+ Value: 0x600898,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x1A,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x1B,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x1C,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x1D,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x1E,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x1F,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x20,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x21,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "init.c",
+ Info: 0x4,
+ Other: 0x0,
+ Section: 0xFFF1,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "initfini.c",
+ Info: 0x4,
+ Other: 0x0,
+ Section: 0xFFF1,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "call_gmon_start",
+ Info: 0x2,
+ Other: 0x0,
+ Section: 0xD,
+ Value: 0x40040C,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "crtstuff.c",
+ Info: 0x4,
+ Other: 0x0,
+ Section: 0xFFF1,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__CTOR_LIST__",
+ Info: 0x1,
+ Other: 0x0,
+ Section: 0x12,
+ Value: 0x600688,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__DTOR_LIST__",
+ Info: 0x1,
+ Other: 0x0,
+ Section: 0x13,
+ Value: 0x600698,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__JCR_LIST__",
+ Info: 0x1,
+ Other: 0x0,
+ Section: 0x14,
+ Value: 0x6006A8,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__do_global_dtors_aux",
+ Info: 0x2,
+ Other: 0x0,
+ Section: 0xD,
+ Value: 0x400430,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "completed.6183",
+ Info: 0x1,
+ Other: 0x0,
+ Section: 0x19,
+ Value: 0x600898,
+ Size: 0x1,
+ },
+ Symbol{
+ Name: "p.6181",
+ Info: 0x1,
+ Other: 0x0,
+ Section: 0x18,
+ Value: 0x600890,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "frame_dummy",
+ Info: 0x2,
+ Other: 0x0,
+ Section: 0xD,
+ Value: 0x400470,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "crtstuff.c",
+ Info: 0x4,
+ Other: 0x0,
+ Section: 0xFFF1,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__CTOR_END__",
+ Info: 0x1,
+ Other: 0x0,
+ Section: 0x12,
+ Value: 0x600690,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__DTOR_END__",
+ Info: 0x1,
+ Other: 0x0,
+ Section: 0x13,
+ Value: 0x6006A0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__FRAME_END__",
+ Info: 0x1,
+ Other: 0x0,
+ Section: 0x11,
+ Value: 0x400680,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__JCR_END__",
+ Info: 0x1,
+ Other: 0x0,
+ Section: 0x14,
+ Value: 0x6006A8,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__do_global_ctors_aux",
+ Info: 0x2,
+ Other: 0x0,
+ Section: 0xD,
+ Value: 0x400560,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "initfini.c",
+ Info: 0x4,
+ Other: 0x0,
+ Section: 0xFFF1,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "hello.c",
+ Info: 0x4,
+ Other: 0x0,
+ Section: 0xFFF1,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "_GLOBAL_OFFSET_TABLE_",
+ Info: 0x1,
+ Other: 0x2,
+ Section: 0x17,
+ Value: 0x600858,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__init_array_end",
+ Info: 0x0,
+ Other: 0x2,
+ Section: 0x12,
+ Value: 0x600684,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__init_array_start",
+ Info: 0x0,
+ Other: 0x2,
+ Section: 0x12,
+ Value: 0x600684,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "_DYNAMIC",
+ Info: 0x1,
+ Other: 0x2,
+ Section: 0x15,
+ Value: 0x6006B0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "data_start",
+ Info: 0x20,
+ Other: 0x0,
+ Section: 0x18,
+ Value: 0x600880,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__libc_csu_fini",
+ Info: 0x12,
+ Other: 0x0,
+ Section: 0xD,
+ Value: 0x4004C0,
+ Size: 0x2,
+ },
+ Symbol{
+ Name: "_start",
+ Info: 0x12,
+ Other: 0x0,
+ Section: 0xD,
+ Value: 0x4003E0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__gmon_start__",
+ Info: 0x20,
+ Other: 0x0,
+ Section: 0x0,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "_Jv_RegisterClasses",
+ Info: 0x20,
+ Other: 0x0,
+ Section: 0x0,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "puts@@GLIBC_2.2.5",
+ Info: 0x12,
+ Other: 0x0,
+ Section: 0x0,
+ Value: 0x0,
+ Size: 0x18C,
+ },
+ Symbol{
+ Name: "_fini",
+ Info: 0x12,
+ Other: 0x0,
+ Section: 0xE,
+ Value: 0x400594,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__libc_start_main@@GLIBC_2.2.5",
+ Info: 0x12,
+ Other: 0x0,
+ Section: 0x0,
+ Value: 0x0,
+ Size: 0x1C2,
+ },
+ Symbol{
+ Name: "_IO_stdin_used",
+ Info: 0x11,
+ Other: 0x0,
+ Section: 0xF,
+ Value: 0x4005A4,
+ Size: 0x4,
+ },
+ Symbol{
+ Name: "__data_start",
+ Info: 0x10,
+ Other: 0x0,
+ Section: 0x18,
+ Value: 0x600880,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__dso_handle",
+ Info: 0x11,
+ Other: 0x2,
+ Section: 0x18,
+ Value: 0x600888,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "__libc_csu_init",
+ Info: 0x12,
+ Other: 0x0,
+ Section: 0xD,
+ Value: 0x4004D0,
+ Size: 0x89,
+ },
+ Symbol{
+ Name: "__bss_start",
+ Info: 0x10,
+ Other: 0x0,
+ Section: 0xFFF1,
+ Value: 0x600898,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "_end",
+ Info: 0x10,
+ Other: 0x0,
+ Section: 0xFFF1,
+ Value: 0x6008A0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "_edata",
+ Info: 0x10,
+ Other: 0x0,
+ Section: 0xFFF1,
+ Value: 0x600898,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "main",
+ Info: 0x12,
+ Other: 0x0,
+ Section: 0xD,
+ Value: 0x400498,
+ Size: 0x1B,
+ },
+ Symbol{
+ Name: "_init",
+ Info: 0x12,
+ Other: 0x0,
+ Section: 0xB,
+ Value: 0x400398,
+ Size: 0x0,
+ },
+ },
+ "testdata/go-relocation-test-clang-x86.obj": {
+ Symbol{
+ Name: "go-relocation-test-clang.c",
+ Info: 0x4,
+ Other: 0x0,
+ Section: 0xFFF1,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: ".Linfo_string0",
+ Info: 0x0,
+ Other: 0x0,
+ Section: 0xC,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: ".Linfo_string1",
+ Info: 0x0,
+ Other: 0x0,
+ Section: 0xC,
+ Value: 0x2C,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: ".Linfo_string2",
+ Info: 0x0,
+ Other: 0x0,
+ Section: 0xC,
+ Value: 0x47,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: ".Linfo_string3",
+ Info: 0x0,
+ Other: 0x0,
+ Section: 0xC,
+ Value: 0x4C,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: ".Linfo_string4",
+ Info: 0x0,
+ Other: 0x0,
+ Section: 0xC,
+ Value: 0x4E,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x1,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x2,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x3,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x4,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x6,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x7,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x8,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0xA,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0xC,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0xD,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0xE,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0xF,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "",
+ Info: 0x3,
+ Other: 0x0,
+ Section: 0x10,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "v",
+ Info: 0x11,
+ Other: 0x0,
+ Section: 0xFFF2,
+ Value: 0x4,
+ Size: 0x4,
+ },
+ },
+ "testdata/hello-world-core.gz": {},
+}
+
+var dynamicSymbolsGolden = map[string][]Symbol{
+ "testdata/gcc-amd64-linux-exec": {
+ Symbol{
+ Name: "__gmon_start__",
+ Info: 0x20,
+ Other: 0x0,
+ Section: 0x0,
+ Value: 0x0,
+ Size: 0x0,
+ },
+ Symbol{
+ Name: "puts",
+ Info: 0x12,
+ Other: 0x0,
+ Section: 0x0,
+ Value: 0x0,
+ Size: 0x18C,
+ },
+ Symbol{
+ Name: "__libc_start_main",
+ Info: 0x12,
+ Other: 0x0,
+ Section: 0x0,
+ Value: 0x0,
+ Size: 0x1C2,
+ },
+ },
+ "testdata/go-relocation-test-clang-x86.obj": {},
+ "testdata/hello-world-core.gz": {},
+}
diff --git a/src/pkg/debug/elf/testdata/gcc-386-freebsd-exec b/src/debug/elf/testdata/gcc-386-freebsd-exec
index 7af9c58ca..7af9c58ca 100755
--- a/src/pkg/debug/elf/testdata/gcc-386-freebsd-exec
+++ b/src/debug/elf/testdata/gcc-386-freebsd-exec
Binary files differ
diff --git a/src/pkg/debug/elf/testdata/gcc-amd64-linux-exec b/src/debug/elf/testdata/gcc-amd64-linux-exec
index c6cb1de28..c6cb1de28 100755
--- a/src/pkg/debug/elf/testdata/gcc-amd64-linux-exec
+++ b/src/debug/elf/testdata/gcc-amd64-linux-exec
Binary files differ
diff --git a/src/pkg/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj b/src/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj
index f62b1ea1c..f62b1ea1c 100644
--- a/src/pkg/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj
+++ b/src/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj
Binary files differ
diff --git a/src/pkg/debug/elf/testdata/go-relocation-test-clang-x86.obj b/src/debug/elf/testdata/go-relocation-test-clang-x86.obj
index e909cf4e6..e909cf4e6 100644
--- a/src/pkg/debug/elf/testdata/go-relocation-test-clang-x86.obj
+++ b/src/debug/elf/testdata/go-relocation-test-clang-x86.obj
Binary files differ
diff --git a/src/pkg/debug/elf/testdata/go-relocation-test-gcc424-x86-64.obj b/src/debug/elf/testdata/go-relocation-test-gcc424-x86-64.obj
index a7c6d6e56..a7c6d6e56 100644
--- a/src/pkg/debug/elf/testdata/go-relocation-test-gcc424-x86-64.obj
+++ b/src/debug/elf/testdata/go-relocation-test-gcc424-x86-64.obj
Binary files differ
diff --git a/src/pkg/debug/elf/testdata/go-relocation-test-gcc441-x86-64.obj b/src/debug/elf/testdata/go-relocation-test-gcc441-x86-64.obj
index 2d37ab6e6..2d37ab6e6 100644
--- a/src/pkg/debug/elf/testdata/go-relocation-test-gcc441-x86-64.obj
+++ b/src/debug/elf/testdata/go-relocation-test-gcc441-x86-64.obj
Binary files differ
diff --git a/src/pkg/debug/elf/testdata/go-relocation-test-gcc441-x86.obj b/src/debug/elf/testdata/go-relocation-test-gcc441-x86.obj
index 0d59fe303..0d59fe303 100644
--- a/src/pkg/debug/elf/testdata/go-relocation-test-gcc441-x86.obj
+++ b/src/debug/elf/testdata/go-relocation-test-gcc441-x86.obj
Binary files differ
diff --git a/src/debug/elf/testdata/go-relocation-test-gcc482-aarch64.obj b/src/debug/elf/testdata/go-relocation-test-gcc482-aarch64.obj
new file mode 100644
index 000000000..849e2644e
--- /dev/null
+++ b/src/debug/elf/testdata/go-relocation-test-gcc482-aarch64.obj
Binary files differ
diff --git a/src/pkg/debug/elf/testdata/hello-world-core.gz b/src/debug/elf/testdata/hello-world-core.gz
index 806af6edb..806af6edb 100644
--- a/src/pkg/debug/elf/testdata/hello-world-core.gz
+++ b/src/debug/elf/testdata/hello-world-core.gz
Binary files differ
diff --git a/src/pkg/debug/elf/testdata/hello.c b/src/debug/elf/testdata/hello.c
index 34d9ee792..34d9ee792 100644
--- a/src/pkg/debug/elf/testdata/hello.c
+++ b/src/debug/elf/testdata/hello.c
diff --git a/src/pkg/debug/gosym/pclinetest.asm b/src/debug/gosym/pclinetest.asm
index b9ee9c0a5..b9ee9c0a5 100644
--- a/src/pkg/debug/gosym/pclinetest.asm
+++ b/src/debug/gosym/pclinetest.asm
diff --git a/src/pkg/debug/gosym/pclinetest.h b/src/debug/gosym/pclinetest.h
index 156c0b87b..156c0b87b 100644
--- a/src/pkg/debug/gosym/pclinetest.h
+++ b/src/debug/gosym/pclinetest.h
diff --git a/src/pkg/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go
index 6620aefb0..6620aefb0 100644
--- a/src/pkg/debug/gosym/pclntab.go
+++ b/src/debug/gosym/pclntab.go
diff --git a/src/pkg/debug/gosym/pclntab_test.go b/src/debug/gosym/pclntab_test.go
index 35502e8c3..35502e8c3 100644
--- a/src/pkg/debug/gosym/pclntab_test.go
+++ b/src/debug/gosym/pclntab_test.go
diff --git a/src/pkg/debug/gosym/symtab.go b/src/debug/gosym/symtab.go
index 3864e3cb4..ee18499d1 100644
--- a/src/pkg/debug/gosym/symtab.go
+++ b/src/debug/gosym/symtab.go
@@ -402,7 +402,7 @@ func NewTable(symtab []byte, pcln *LineTable) (*Table, error) {
if n := len(t.Funcs); n > 0 {
t.Funcs[n-1].End = sym.Value
}
- if sym.Name == "etext" {
+ if sym.Name == "runtime.etext" || sym.Name == "etext" {
continue
}
diff --git a/src/pkg/debug/macho/fat.go b/src/debug/macho/fat.go
index 93b831526..93b831526 100644
--- a/src/pkg/debug/macho/fat.go
+++ b/src/debug/macho/fat.go
diff --git a/src/pkg/debug/macho/file.go b/src/debug/macho/file.go
index eefb74444..eefb74444 100644
--- a/src/pkg/debug/macho/file.go
+++ b/src/debug/macho/file.go
diff --git a/src/pkg/debug/macho/file_test.go b/src/debug/macho/file_test.go
index 4797780ce..4797780ce 100644
--- a/src/pkg/debug/macho/file_test.go
+++ b/src/debug/macho/file_test.go
diff --git a/src/pkg/debug/macho/macho.go b/src/debug/macho/macho.go
index d9678c8ed..d9678c8ed 100644
--- a/src/pkg/debug/macho/macho.go
+++ b/src/debug/macho/macho.go
diff --git a/src/pkg/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec b/src/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec
index 7efd19300..7efd19300 100644
--- a/src/pkg/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec
+++ b/src/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec
Binary files differ
diff --git a/src/pkg/debug/macho/testdata/gcc-386-darwin-exec b/src/debug/macho/testdata/gcc-386-darwin-exec
index 03ba1bafa..03ba1bafa 100755
--- a/src/pkg/debug/macho/testdata/gcc-386-darwin-exec
+++ b/src/debug/macho/testdata/gcc-386-darwin-exec
Binary files differ
diff --git a/src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec b/src/debug/macho/testdata/gcc-amd64-darwin-exec
index 5155a5a26..5155a5a26 100755
--- a/src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec
+++ b/src/debug/macho/testdata/gcc-amd64-darwin-exec
Binary files differ
diff --git a/src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec-debug b/src/debug/macho/testdata/gcc-amd64-darwin-exec-debug
index a47d3aef7..a47d3aef7 100644
--- a/src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec-debug
+++ b/src/debug/macho/testdata/gcc-amd64-darwin-exec-debug
Binary files differ
diff --git a/src/pkg/debug/macho/testdata/hello.c b/src/debug/macho/testdata/hello.c
index a689d3644..a689d3644 100644
--- a/src/pkg/debug/macho/testdata/hello.c
+++ b/src/debug/macho/testdata/hello.c
diff --git a/src/pkg/debug/pe/file.go b/src/debug/pe/file.go
index ce6f1408f..759e5674f 100644
--- a/src/pkg/debug/pe/file.go
+++ b/src/debug/pe/file.go
@@ -13,7 +13,6 @@ import (
"io"
"os"
"strconv"
- "unsafe"
)
// A File represents an open PE file.
@@ -125,6 +124,11 @@ func (f *File) Close() error {
return err
}
+var (
+ sizeofOptionalHeader32 = uint16(binary.Size(OptionalHeader32{}))
+ sizeofOptionalHeader64 = uint16(binary.Size(OptionalHeader64{}))
+)
+
// NewFile creates a new File for accessing a PE binary in an underlying reader.
func NewFile(r io.ReaderAt) (*File, error) {
f := new(File)
@@ -205,8 +209,8 @@ func NewFile(r io.ReaderAt) (*File, error) {
}
var oh32 OptionalHeader32
var oh64 OptionalHeader64
- switch uintptr(f.FileHeader.SizeOfOptionalHeader) {
- case unsafe.Sizeof(oh32):
+ switch f.FileHeader.SizeOfOptionalHeader {
+ case sizeofOptionalHeader32:
if err := binary.Read(sr, binary.LittleEndian, &oh32); err != nil {
return nil, err
}
@@ -214,7 +218,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
return nil, fmt.Errorf("pe32 optional header has unexpected Magic of 0x%x", oh32.Magic)
}
f.OptionalHeader = &oh32
- case unsafe.Sizeof(oh64):
+ case sizeofOptionalHeader64:
if err := binary.Read(sr, binary.LittleEndian, &oh64); err != nil {
return nil, err
}
diff --git a/src/pkg/debug/pe/file_test.go b/src/debug/pe/file_test.go
index ddbb27174..0d73969bc 100644
--- a/src/pkg/debug/pe/file_test.go
+++ b/src/debug/pe/file_test.go
@@ -125,9 +125,9 @@ var fileTests = []fileTest{
},
{
"testdata/gcc-amd64-mingw-exec",
- FileHeader{0x8664, 0x9, 0x53472993, 0x0, 0x0, 0xf0, 0x22f},
+ FileHeader{0x8664, 0x11, 0x53e4364f, 0x39600, 0x6fc, 0xf0, 0x27},
&OptionalHeader64{
- 0x20b, 0x2, 0x16, 0x6a00, 0x2400, 0x1600, 0x14e0, 0x1000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x0, 0x0, 0x5, 0x2, 0x0, 0x11000, 0x400, 0x1841e, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
+ 0x20b, 0x2, 0x16, 0x6a00, 0x2400, 0x1600, 0x14e0, 0x1000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x0, 0x0, 0x5, 0x2, 0x0, 0x45000, 0x600, 0x46f19, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
[16]DataDirectory{
{0x0, 0x0},
{0xe000, 0x990},
@@ -145,18 +145,25 @@ var fileTests = []fileTest{
{0x0, 0x0},
{0x0, 0x0},
{0x0, 0x0},
- },
- },
+ }},
[]*SectionHeader{
- {".text", 0x6860, 0x1000, 0x6a00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500020},
- {".data", 0xe0, 0x8000, 0x200, 0x6e00, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
- {".rdata", 0x6b0, 0x9000, 0x800, 0x7000, 0x0, 0x0, 0x0, 0x0, 0x40600040},
- {".pdata", 0x498, 0xa000, 0x600, 0x7800, 0x0, 0x0, 0x0, 0x0, 0x40300040},
- {".xdata", 0x488, 0xb000, 0x600, 0x7e00, 0x0, 0x0, 0x0, 0x0, 0x40300040},
+ {".text", 0x6860, 0x1000, 0x6a00, 0x600, 0x0, 0x0, 0x0, 0x0, 0x60500020},
+ {".data", 0xe0, 0x8000, 0x200, 0x7000, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
+ {".rdata", 0x6b0, 0x9000, 0x800, 0x7200, 0x0, 0x0, 0x0, 0x0, 0x40600040},
+ {".pdata", 0x498, 0xa000, 0x600, 0x7a00, 0x0, 0x0, 0x0, 0x0, 0x40300040},
+ {".xdata", 0x488, 0xb000, 0x600, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".bss", 0x1410, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0600080},
- {".idata", 0x990, 0xe000, 0xa00, 0x8400, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
- {".CRT", 0x68, 0xf000, 0x200, 0x8e00, 0x0, 0x0, 0x0, 0x0, 0xc0400040},
- {".tls", 0x48, 0x10000, 0x200, 0x9000, 0x0, 0x0, 0x0, 0x0, 0xc0600040},
+ {".idata", 0x990, 0xe000, 0xa00, 0x8600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
+ {".CRT", 0x68, 0xf000, 0x200, 0x9000, 0x0, 0x0, 0x0, 0x0, 0xc0400040},
+ {".tls", 0x48, 0x10000, 0x200, 0x9200, 0x0, 0x0, 0x0, 0x0, 0xc0600040},
+ {".debug_aranges", 0x600, 0x11000, 0x600, 0x9400, 0x0, 0x0, 0x0, 0x0, 0x42500040},
+ {".debug_info", 0x1316e, 0x12000, 0x13200, 0x9a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
+ {".debug_abbrev", 0x2ccb, 0x26000, 0x2e00, 0x1cc00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
+ {".debug_line", 0x3c4d, 0x29000, 0x3e00, 0x1fa00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
+ {".debug_frame", 0x18b8, 0x2d000, 0x1a00, 0x23800, 0x0, 0x0, 0x0, 0x0, 0x42400040},
+ {".debug_str", 0x396, 0x2f000, 0x400, 0x25200, 0x0, 0x0, 0x0, 0x0, 0x42100040},
+ {".debug_loc", 0x13240, 0x30000, 0x13400, 0x25600, 0x0, 0x0, 0x0, 0x0, 0x42100040},
+ {".debug_ranges", 0xa70, 0x44000, 0xc00, 0x38a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
},
[]*Symbol{},
},
diff --git a/src/pkg/debug/pe/pe.go b/src/debug/pe/pe.go
index 8e90b1b51..8e90b1b51 100644
--- a/src/pkg/debug/pe/pe.go
+++ b/src/debug/pe/pe.go
diff --git a/src/pkg/debug/pe/testdata/gcc-386-mingw-exec b/src/debug/pe/testdata/gcc-386-mingw-exec
index 4b808d043..4b808d043 100644
--- a/src/pkg/debug/pe/testdata/gcc-386-mingw-exec
+++ b/src/debug/pe/testdata/gcc-386-mingw-exec
Binary files differ
diff --git a/src/pkg/debug/pe/testdata/gcc-386-mingw-obj b/src/debug/pe/testdata/gcc-386-mingw-obj
index 0c84d898d..0c84d898d 100644
--- a/src/pkg/debug/pe/testdata/gcc-386-mingw-obj
+++ b/src/debug/pe/testdata/gcc-386-mingw-obj
Binary files differ
diff --git a/src/debug/pe/testdata/gcc-amd64-mingw-exec b/src/debug/pe/testdata/gcc-amd64-mingw-exec
new file mode 100644
index 000000000..ce6feb6b7
--- /dev/null
+++ b/src/debug/pe/testdata/gcc-amd64-mingw-exec
Binary files differ
diff --git a/src/pkg/debug/pe/testdata/gcc-amd64-mingw-obj b/src/debug/pe/testdata/gcc-amd64-mingw-obj
index 48ae7921f..48ae7921f 100644
--- a/src/pkg/debug/pe/testdata/gcc-amd64-mingw-obj
+++ b/src/debug/pe/testdata/gcc-amd64-mingw-obj
Binary files differ
diff --git a/src/pkg/debug/pe/testdata/hello.c b/src/debug/pe/testdata/hello.c
index a689d3644..a689d3644 100644
--- a/src/pkg/debug/pe/testdata/hello.c
+++ b/src/debug/pe/testdata/hello.c
diff --git a/src/pkg/debug/plan9obj/file.go b/src/debug/plan9obj/file.go
index 60a585719..b11ed86f1 100644
--- a/src/pkg/debug/plan9obj/file.go
+++ b/src/debug/plan9obj/file.go
@@ -15,10 +15,12 @@ import (
// A FileHeader represents a Plan 9 a.out file header.
type FileHeader struct {
- Magic uint32
- Bss uint32
- Entry uint64
- PtrSize int
+ Magic uint32
+ Bss uint32
+ Entry uint64
+ PtrSize int
+ LoadAddress uint64
+ HdrSize uint64
}
// A File represents an open Plan 9 a.out file.
@@ -148,20 +150,21 @@ func NewFile(r io.ReaderAt) (*File, error) {
}
f := &File{FileHeader: FileHeader{
- Magic: ph.Magic,
- Bss: ph.Bss,
- Entry: uint64(ph.Entry),
- PtrSize: 4,
+ Magic: ph.Magic,
+ Bss: ph.Bss,
+ Entry: uint64(ph.Entry),
+ PtrSize: 4,
+ LoadAddress: 0x1000,
+ HdrSize: 4 * 8,
}}
- hdrSize := 4 * 8
-
if ph.Magic&Magic64 != 0 {
if err := binary.Read(sr, binary.BigEndian, &f.Entry); err != nil {
return nil, err
}
f.PtrSize = 8
- hdrSize += 8
+ f.LoadAddress = 0x200000
+ f.HdrSize += 8
}
var sects = []struct {
@@ -177,7 +180,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
f.Sections = make([]*Section, 5)
- off := uint32(hdrSize)
+ off := uint32(f.HdrSize)
for i, sect := range sects {
s := new(Section)
diff --git a/src/pkg/debug/plan9obj/file_test.go b/src/debug/plan9obj/file_test.go
index 96186d815..cfd7a61d1 100644
--- a/src/pkg/debug/plan9obj/file_test.go
+++ b/src/debug/plan9obj/file_test.go
@@ -18,7 +18,7 @@ type fileTest struct {
var fileTests = []fileTest{
{
"testdata/386-plan9-exec",
- FileHeader{Magic386, 0x324, 0x14, 4},
+ FileHeader{Magic386, 0x324, 0x14, 4, 0x1000, 32},
[]*SectionHeader{
{"text", 0x4c5f, 0x20},
{"data", 0x94c, 0x4c7f},
@@ -29,7 +29,7 @@ var fileTests = []fileTest{
},
{
"testdata/amd64-plan9-exec",
- FileHeader{MagicAMD64, 0x618, 0x13, 8},
+ FileHeader{MagicAMD64, 0x618, 0x13, 8, 0x200000, 40},
[]*SectionHeader{
{"text", 0x4213, 0x28},
{"data", 0xa80, 0x423b},
diff --git a/src/pkg/debug/plan9obj/plan9obj.go b/src/debug/plan9obj/plan9obj.go
index af9858562..af9858562 100644
--- a/src/pkg/debug/plan9obj/plan9obj.go
+++ b/src/debug/plan9obj/plan9obj.go
diff --git a/src/pkg/debug/plan9obj/testdata/386-plan9-exec b/src/debug/plan9obj/testdata/386-plan9-exec
index 748e83f8e..748e83f8e 100755
--- a/src/pkg/debug/plan9obj/testdata/386-plan9-exec
+++ b/src/debug/plan9obj/testdata/386-plan9-exec
Binary files differ
diff --git a/src/pkg/debug/plan9obj/testdata/amd64-plan9-exec b/src/debug/plan9obj/testdata/amd64-plan9-exec
index 3e257dd8f..3e257dd8f 100755
--- a/src/pkg/debug/plan9obj/testdata/amd64-plan9-exec
+++ b/src/debug/plan9obj/testdata/amd64-plan9-exec
Binary files differ
diff --git a/src/pkg/debug/plan9obj/testdata/hello.c b/src/debug/plan9obj/testdata/hello.c
index c0d633e29..c0d633e29 100644
--- a/src/pkg/debug/plan9obj/testdata/hello.c
+++ b/src/debug/plan9obj/testdata/hello.c
diff --git a/src/pkg/encoding/ascii85/ascii85.go b/src/encoding/ascii85/ascii85.go
index 60da304b5..4d7193873 100644
--- a/src/pkg/encoding/ascii85/ascii85.go
+++ b/src/encoding/ascii85/ascii85.go
@@ -249,7 +249,6 @@ type decoder struct {
err error
readErr error
r io.Reader
- end bool // saw end of message
buf [1024]byte // leftover input
nbuf int
out []byte // leftover decoded output
diff --git a/src/pkg/encoding/ascii85/ascii85_test.go b/src/encoding/ascii85/ascii85_test.go
index aad199b4f..aad199b4f 100644
--- a/src/pkg/encoding/ascii85/ascii85_test.go
+++ b/src/encoding/ascii85/ascii85_test.go
diff --git a/src/pkg/encoding/asn1/asn1.go b/src/encoding/asn1/asn1.go
index ec7f91c1b..8b3d1b341 100644
--- a/src/pkg/encoding/asn1/asn1.go
+++ b/src/encoding/asn1/asn1.go
@@ -640,15 +640,19 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
// 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 {
- switch t.tag {
- case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
- universalTag = t.tag
+ if t.class == classUniversal {
+ switch t.tag {
+ case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
+ universalTag = t.tag
+ }
+ } else if params.stringType != 0 {
+ universalTag = params.stringType
}
}
// Special case for time: UTCTime and GeneralizedTime both map to the
// Go type time.Time.
- if universalTag == tagUTCTime && t.tag == tagGeneralizedTime {
+ if universalTag == tagUTCTime && t.tag == tagGeneralizedTime && t.class == classUniversal {
universalTag = tagGeneralizedTime
}
@@ -822,8 +826,19 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
return
}
+// canHaveDefaultValue reports whether k is a Kind that we will set a default
+// value for. (A signed integer, essentially.)
+func canHaveDefaultValue(k reflect.Kind) bool {
+ switch k {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return true
+ }
+
+ return false
+}
+
// setDefaultValue is used to install a default value, from a tag string, into
-// a Value. It is successful is the field was optional, even if a default value
+// a Value. It is successful if the field was optional, even if a default value
// wasn't provided or it failed to install it into the Value.
func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
if !params.optional {
@@ -833,9 +848,8 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
if params.defaultValue == nil {
return
}
- switch val := v; val.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- val.SetInt(*params.defaultValue)
+ if canHaveDefaultValue(v.Kind()) {
+ v.SetInt(*params.defaultValue)
}
return
}
diff --git a/src/pkg/encoding/asn1/asn1_test.go b/src/encoding/asn1/asn1_test.go
index b553f78e0..4e864d08a 100644
--- a/src/pkg/encoding/asn1/asn1_test.go
+++ b/src/encoding/asn1/asn1_test.go
@@ -392,6 +392,10 @@ type TestContextSpecificTags2 struct {
B int
}
+type TestContextSpecificTags3 struct {
+ S string `asn1:"tag:1,utf8"`
+}
+
type TestElementsAfterString struct {
S string
A, B int
@@ -420,6 +424,7 @@ var unmarshalTestData = []struct {
{[]byte{0x04, 0x04, 1, 2, 3, 4}, &RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}},
{[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}},
{[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}},
+ {[]byte{0x30, 0x03, 0x81, 0x01, '@'}, &TestContextSpecificTags3{"@"}},
{[]byte{0x01, 0x01, 0x00}, newBool(false)},
{[]byte{0x01, 0x01, 0xff}, newBool(true)},
{[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}},
@@ -812,3 +817,51 @@ func TestStringSlice(t *testing.T) {
}
}
}
+
+type explicitTaggedTimeTest struct {
+ Time time.Time `asn1:"explicit,tag:0"`
+}
+
+var explicitTaggedTimeTestData = []struct {
+ in []byte
+ out explicitTaggedTimeTest
+}{
+ {[]byte{0x30, 0x11, 0xa0, 0xf, 0x17, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'},
+ explicitTaggedTimeTest{time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC)}},
+ {[]byte{0x30, 0x17, 0xa0, 0xf, 0x18, 0x13, '2', '0', '1', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '+', '0', '6', '0', '7'},
+ explicitTaggedTimeTest{time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}},
+}
+
+func TestExplicitTaggedTime(t *testing.T) {
+ // Test that a time.Time will match either tagUTCTime or
+ // tagGeneralizedTime.
+ for i, test := range explicitTaggedTimeTestData {
+ var got explicitTaggedTimeTest
+ _, err := Unmarshal(test.in, &got)
+ if err != nil {
+ t.Errorf("Unmarshal failed at index %d %v", i, err)
+ }
+ if !got.Time.Equal(test.out.Time) {
+ t.Errorf("#%d: got %v, want %v", i, got.Time, test.out.Time)
+ }
+ }
+}
+
+type implicitTaggedTimeTest struct {
+ Time time.Time `asn1:"tag:24"`
+}
+
+func TestImplicitTaggedTime(t *testing.T) {
+ // An implicitly tagged time value, that happens to have an implicit
+ // tag equal to a GENERALIZEDTIME, should still be parsed as a UTCTime.
+ // (There's no "timeType" in fieldParameters to determine what type of
+ // time should be expected when implicitly tagged.)
+ der := []byte{0x30, 0x0f, 0x80 | 24, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'}
+ var result implicitTaggedTimeTest
+ if _, err := Unmarshal(der, &result); err != nil {
+ t.Fatalf("Error while parsing: %s", err)
+ }
+ if expected := time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC); !result.Time.Equal(expected) {
+ t.Errorf("Wrong result. Got %v, want %v", result.Time, expected)
+ }
+}
diff --git a/src/pkg/encoding/asn1/common.go b/src/encoding/asn1/common.go
index 33a117ece..33a117ece 100644
--- a/src/pkg/encoding/asn1/common.go
+++ b/src/encoding/asn1/common.go
diff --git a/src/pkg/encoding/asn1/marshal.go b/src/encoding/asn1/marshal.go
index e26fe59b3..b2f104b4c 100644
--- a/src/pkg/encoding/asn1/marshal.go
+++ b/src/encoding/asn1/marshal.go
@@ -513,8 +513,22 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
return
}
- if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
- return
+ if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) {
+ defaultValue := reflect.New(v.Type()).Elem()
+ defaultValue.SetInt(*params.defaultValue)
+
+ if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) {
+ return
+ }
+ }
+
+ // If no default value is given then the zero value for the type is
+ // assumed to be the default value. This isn't obviously the correct
+ // behaviour, but it's what Go has traditionally done.
+ if params.optional && params.defaultValue == nil {
+ if reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
+ return
+ }
}
if v.Type() == rawValueType {
diff --git a/src/pkg/encoding/asn1/marshal_test.go b/src/encoding/asn1/marshal_test.go
index a15acbed0..5b0115f28 100644
--- a/src/pkg/encoding/asn1/marshal_test.go
+++ b/src/encoding/asn1/marshal_test.go
@@ -58,6 +58,10 @@ type omitEmptyTest struct {
A []string `asn1:"omitempty"`
}
+type defaultTest struct {
+ A int `asn1:"optional,default:1"`
+}
+
type testSET []int
var PST = time.FixedZone("PST", -8*60*60)
@@ -133,6 +137,9 @@ var marshalTests = []marshalTest{
{omitEmptyTest{[]string{}}, "3000"},
{omitEmptyTest{[]string{"1"}}, "30053003130131"},
{"Σ", "0c02cea3"},
+ {defaultTest{0}, "3003020100"},
+ {defaultTest{1}, "3000"},
+ {defaultTest{2}, "3003020102"},
}
func TestMarshal(t *testing.T) {
diff --git a/src/pkg/encoding/base32/base32.go b/src/encoding/base32/base32.go
index d770de391..5a9e86919 100644
--- a/src/pkg/encoding/base32/base32.go
+++ b/src/encoding/base32/base32.go
@@ -73,45 +73,43 @@ func (enc *Encoding) Encode(dst, src []byte) {
}
for len(src) > 0 {
- dst[0] = 0
- dst[1] = 0
- dst[2] = 0
- dst[3] = 0
- dst[4] = 0
- dst[5] = 0
- dst[6] = 0
- dst[7] = 0
+ var b0, b1, b2, b3, b4, b5, b6, b7 byte
// Unpack 8x 5-bit source blocks into a 5 byte
// destination quantum
switch len(src) {
default:
- dst[7] |= src[4] & 0x1F
- dst[6] |= src[4] >> 5
+ b7 = src[4] & 0x1F
+ b6 = src[4] >> 5
fallthrough
case 4:
- dst[6] |= (src[3] << 3) & 0x1F
- dst[5] |= (src[3] >> 2) & 0x1F
- dst[4] |= src[3] >> 7
+ b6 |= (src[3] << 3) & 0x1F
+ b5 = (src[3] >> 2) & 0x1F
+ b4 = src[3] >> 7
fallthrough
case 3:
- dst[4] |= (src[2] << 1) & 0x1F
- dst[3] |= (src[2] >> 4) & 0x1F
+ b4 |= (src[2] << 1) & 0x1F
+ b3 = (src[2] >> 4) & 0x1F
fallthrough
case 2:
- dst[3] |= (src[1] << 4) & 0x1F
- dst[2] |= (src[1] >> 1) & 0x1F
- dst[1] |= (src[1] >> 6) & 0x1F
+ b3 |= (src[1] << 4) & 0x1F
+ b2 = (src[1] >> 1) & 0x1F
+ b1 = (src[1] >> 6) & 0x1F
fallthrough
case 1:
- dst[1] |= (src[0] << 2) & 0x1F
- dst[0] |= src[0] >> 3
+ b1 |= (src[0] << 2) & 0x1F
+ b0 = src[0] >> 3
}
// Encode 5-bit blocks using the base32 alphabet
- for j := 0; j < 8; j++ {
- dst[j] = enc.encode[dst[j]]
- }
+ dst[0] = enc.encode[b0]
+ dst[1] = enc.encode[b1]
+ dst[2] = enc.encode[b2]
+ dst[3] = enc.encode[b3]
+ dst[4] = enc.encode[b4]
+ dst[5] = enc.encode[b5]
+ dst[6] = enc.encode[b6]
+ dst[7] = enc.encode[b7]
// Pad the final quantum
if len(src) < 5 {
@@ -330,7 +328,7 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
func (enc *Encoding) DecodeString(s string) ([]byte, error) {
s = strings.Map(removeNewlinesMapper, s)
dbuf := make([]byte, enc.DecodedLen(len(s)))
- n, err := enc.Decode(dbuf, []byte(s))
+ n, _, err := enc.decode(dbuf, []byte(s))
return dbuf[:n], err
}
diff --git a/src/pkg/encoding/base32/base32_test.go b/src/encoding/base32/base32_test.go
index f56b996fa..5a68f06e1 100644
--- a/src/pkg/encoding/base32/base32_test.go
+++ b/src/encoding/base32/base32_test.go
@@ -284,3 +284,19 @@ LNEBUWIIDFON2CA3DBMJXXE5LNFY==
t.Error("Decoded results not equal")
}
}
+
+func BenchmarkEncodeToString(b *testing.B) {
+ data := make([]byte, 8192)
+ b.SetBytes(int64(len(data)))
+ for i := 0; i < b.N; i++ {
+ StdEncoding.EncodeToString(data)
+ }
+}
+
+func BenchmarkDecodeString(b *testing.B) {
+ data := StdEncoding.EncodeToString(make([]byte, 8192))
+ b.SetBytes(int64(len(data)))
+ for i := 0; i < b.N; i++ {
+ StdEncoding.DecodeString(data)
+ }
+}
diff --git a/src/pkg/encoding/base32/example_test.go b/src/encoding/base32/example_test.go
index f6128d900..f6128d900 100644
--- a/src/pkg/encoding/base32/example_test.go
+++ b/src/encoding/base32/example_test.go
diff --git a/src/pkg/encoding/base64/base64.go b/src/encoding/base64/base64.go
index e38c26d0e..ad3abe662 100644
--- a/src/pkg/encoding/base64/base64.go
+++ b/src/encoding/base64/base64.go
@@ -74,31 +74,29 @@ func (enc *Encoding) Encode(dst, src []byte) {
}
for len(src) > 0 {
- dst[0] = 0
- dst[1] = 0
- dst[2] = 0
- dst[3] = 0
+ var b0, b1, b2, b3 byte
// Unpack 4x 6-bit source blocks into a 4 byte
// destination quantum
switch len(src) {
default:
- dst[3] |= src[2] & 0x3F
- dst[2] |= src[2] >> 6
+ b3 = src[2] & 0x3F
+ b2 = src[2] >> 6
fallthrough
case 2:
- dst[2] |= (src[1] << 2) & 0x3F
- dst[1] |= src[1] >> 4
+ b2 |= (src[1] << 2) & 0x3F
+ b1 = src[1] >> 4
fallthrough
case 1:
- dst[1] |= (src[0] << 4) & 0x3F
- dst[0] |= src[0] >> 2
+ b1 |= (src[0] << 4) & 0x3F
+ b0 = src[0] >> 2
}
// Encode 6-bit blocks using the base64 alphabet
- for j := 0; j < 4; j++ {
- dst[j] = enc.encode[dst[j]]
- }
+ dst[0] = enc.encode[b0]
+ dst[1] = enc.encode[b1]
+ dst[2] = enc.encode[b2]
+ dst[3] = enc.encode[b3]
// Pad the final quantum
if len(src) < 3 {
@@ -295,7 +293,7 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
func (enc *Encoding) DecodeString(s string) ([]byte, error) {
s = strings.Map(removeNewlinesMapper, s)
dbuf := make([]byte, enc.DecodedLen(len(s)))
- n, err := enc.Decode(dbuf, []byte(s))
+ n, _, err := enc.decode(dbuf, []byte(s))
return dbuf[:n], err
}
diff --git a/src/pkg/encoding/base64/base64_test.go b/src/encoding/base64/base64_test.go
index a075194e0..7d199bfa0 100644
--- a/src/pkg/encoding/base64/base64_test.go
+++ b/src/encoding/base64/base64_test.go
@@ -342,3 +342,19 @@ func TestDecoderIssue7733(t *testing.T) {
t.Errorf("DecodeString = %q; want abcd", s)
}
}
+
+func BenchmarkEncodeToString(b *testing.B) {
+ data := make([]byte, 8192)
+ b.SetBytes(int64(len(data)))
+ for i := 0; i < b.N; i++ {
+ StdEncoding.EncodeToString(data)
+ }
+}
+
+func BenchmarkDecodeString(b *testing.B) {
+ data := StdEncoding.EncodeToString(make([]byte, 8192))
+ b.SetBytes(int64(len(data)))
+ for i := 0; i < b.N; i++ {
+ StdEncoding.DecodeString(data)
+ }
+}
diff --git a/src/pkg/encoding/base64/example_test.go b/src/encoding/base64/example_test.go
index d18b856a0..d18b856a0 100644
--- a/src/pkg/encoding/base64/example_test.go
+++ b/src/encoding/base64/example_test.go
diff --git a/src/pkg/encoding/binary/binary.go b/src/encoding/binary/binary.go
index a5694876a..466bf97c9 100644
--- a/src/pkg/encoding/binary/binary.go
+++ b/src/encoding/binary/binary.go
@@ -10,9 +10,10 @@
// type (int8, uint8, int16, float32, complex64, ...)
// or an array or struct containing only fixed-size values.
//
-// Varints are a method of encoding integers using one or more bytes;
-// numbers with smaller absolute value take a smaller number of bytes.
-// For a specification, see http://code.google.com/apis/protocolbuffers/docs/encoding.html.
+// The varint functions encode and decode single integer values using
+// a variable-length encoding; smaller values require fewer bytes.
+// For a specification, see
+// http://code.google.com/apis/protocolbuffers/docs/encoding.html.
//
// This package favors simplicity over efficiency. Clients that require
// high-performance serialization, especially for large data structures,
@@ -199,18 +200,17 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
}
// Fallback to reflect-based decoding.
- var v reflect.Value
- switch d := reflect.ValueOf(data); d.Kind() {
+ v := reflect.ValueOf(data)
+ size := -1
+ switch v.Kind() {
case reflect.Ptr:
- v = d.Elem()
+ v = v.Elem()
+ size = dataSize(v)
case reflect.Slice:
- v = d
- default:
- return errors.New("binary.Read: invalid type " + d.Type().String())
+ size = dataSize(v)
}
- size, err := dataSize(v)
- if err != nil {
- return errors.New("binary.Read: " + err.Error())
+ if size < 0 {
+ return errors.New("binary.Read: invalid type " + reflect.TypeOf(data).String())
}
d := &decoder{order: order, buf: make([]byte, size)}
if _, err := io.ReadFull(r, d.buf); err != nil {
@@ -323,68 +323,64 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error {
// Fallback to reflect-based encoding.
v := reflect.Indirect(reflect.ValueOf(data))
- size, err := dataSize(v)
- if err != nil {
- return errors.New("binary.Write: " + err.Error())
+ size := dataSize(v)
+ if size < 0 {
+ return errors.New("binary.Write: invalid type " + reflect.TypeOf(data).String())
}
buf := make([]byte, size)
e := &encoder{order: order, buf: buf}
e.value(v)
- _, err = w.Write(buf)
+ _, err := w.Write(buf)
return err
}
// Size returns how many bytes Write would generate to encode the value v, which
// must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
+// If v is neither of these, Size returns -1.
func Size(v interface{}) int {
- n, err := dataSize(reflect.Indirect(reflect.ValueOf(v)))
- if err != nil {
- return -1
- }
- return n
+ return dataSize(reflect.Indirect(reflect.ValueOf(v)))
}
// dataSize returns the number of bytes the actual data represented by v occupies in memory.
// For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice
// it returns the length of the slice times the element size and does not count the memory
-// occupied by the header.
-func dataSize(v reflect.Value) (int, error) {
+// occupied by the header. If the type of v is not acceptable, dataSize returns -1.
+func dataSize(v reflect.Value) int {
if v.Kind() == reflect.Slice {
- elem, err := sizeof(v.Type().Elem())
- if err != nil {
- return 0, err
+ if s := sizeof(v.Type().Elem()); s >= 0 {
+ return s * v.Len()
}
- return v.Len() * elem, nil
+ return -1
}
return sizeof(v.Type())
}
-func sizeof(t reflect.Type) (int, error) {
+// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable.
+func sizeof(t reflect.Type) int {
switch t.Kind() {
case reflect.Array:
- n, err := sizeof(t.Elem())
- if err != nil {
- return 0, err
+ if s := sizeof(t.Elem()); s >= 0 {
+ return s * t.Len()
}
- return t.Len() * n, nil
case reflect.Struct:
sum := 0
for i, n := 0, t.NumField(); i < n; i++ {
- s, err := sizeof(t.Field(i).Type)
- if err != nil {
- return 0, err
+ s := sizeof(t.Field(i).Type)
+ if s < 0 {
+ return -1
}
sum += s
}
- return sum, nil
+ return sum
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
- return int(t.Size()), nil
+ return int(t.Size())
}
- return 0, errors.New("invalid type " + t.String())
+
+ return -1
}
type coder struct {
@@ -594,12 +590,11 @@ func (e *encoder) value(v reflect.Value) {
}
func (d *decoder) skip(v reflect.Value) {
- n, _ := dataSize(v)
- d.buf = d.buf[n:]
+ d.buf = d.buf[dataSize(v):]
}
func (e *encoder) skip(v reflect.Value) {
- n, _ := dataSize(v)
+ n := dataSize(v)
for i := range e.buf[0:n] {
e.buf[i] = 0
}
diff --git a/src/pkg/encoding/binary/binary_test.go b/src/encoding/binary/binary_test.go
index c80c90383..8ee595fa4 100644
--- a/src/pkg/encoding/binary/binary_test.go
+++ b/src/encoding/binary/binary_test.go
@@ -289,6 +289,26 @@ func TestUnexportedRead(t *testing.T) {
Read(&buf, LittleEndian, &u2)
}
+func TestReadErrorMsg(t *testing.T) {
+ var buf bytes.Buffer
+ read := func(data interface{}) {
+ err := Read(&buf, LittleEndian, data)
+ want := "binary.Read: invalid type " + reflect.TypeOf(data).String()
+ if err == nil {
+ t.Errorf("%T: got no error; want %q", data, want)
+ return
+ }
+ if got := err.Error(); got != want {
+ t.Errorf("%T: got %q; want %q", data, got, want)
+ }
+ }
+ read(0)
+ s := new(struct{})
+ read(&s)
+ p := &s
+ read(&p)
+}
+
type byteSliceReader struct {
remain []byte
}
@@ -315,8 +335,7 @@ func BenchmarkReadStruct(b *testing.B) {
bsr := &byteSliceReader{}
var buf bytes.Buffer
Write(&buf, BigEndian, &s)
- n, _ := dataSize(reflect.ValueOf(s))
- b.SetBytes(int64(n))
+ b.SetBytes(int64(dataSize(reflect.ValueOf(s))))
t := s
b.ResetTimer()
for i := 0; i < b.N; i++ {
diff --git a/src/pkg/encoding/binary/example_test.go b/src/encoding/binary/example_test.go
index 067cf553b..067cf553b 100644
--- a/src/pkg/encoding/binary/example_test.go
+++ b/src/encoding/binary/example_test.go
diff --git a/src/pkg/encoding/binary/varint.go b/src/encoding/binary/varint.go
index 3a2dfa3c7..3a2dfa3c7 100644
--- a/src/pkg/encoding/binary/varint.go
+++ b/src/encoding/binary/varint.go
diff --git a/src/pkg/encoding/binary/varint_test.go b/src/encoding/binary/varint_test.go
index ca411ecbd..ca411ecbd 100644
--- a/src/pkg/encoding/binary/varint_test.go
+++ b/src/encoding/binary/varint_test.go
diff --git a/src/pkg/encoding/csv/reader.go b/src/encoding/csv/reader.go
index d9432954a..d9432954a 100644
--- a/src/pkg/encoding/csv/reader.go
+++ b/src/encoding/csv/reader.go
diff --git a/src/pkg/encoding/csv/reader_test.go b/src/encoding/csv/reader_test.go
index 123df06bc..123df06bc 100644
--- a/src/pkg/encoding/csv/reader_test.go
+++ b/src/encoding/csv/reader_test.go
diff --git a/src/pkg/encoding/csv/writer.go b/src/encoding/csv/writer.go
index 1faecb664..17e7bb7f5 100644
--- a/src/pkg/encoding/csv/writer.go
+++ b/src/encoding/csv/writer.go
@@ -115,10 +115,22 @@ func (w *Writer) WriteAll(records [][]string) (err error) {
}
// fieldNeedsQuotes returns true if our field must be enclosed in quotes.
-// Empty fields, files with a Comma, fields with a quote or newline, and
+// Fields with a Comma, fields with a quote or newline, and
// fields which start with a space must be enclosed in quotes.
+// We used to quote empty strings, but we do not anymore (as of Go 1.4).
+// The two representations should be equivalent, but Postgres distinguishes
+// quoted vs non-quoted empty string during database imports, and it has
+// an option to force the quoted behavior for non-quoted CSV but it has
+// no option to force the non-quoted behavior for quoted CSV, making
+// CSV with quoted empty strings strictly less useful.
+// Not quoting the empty string also makes this package match the behavior
+// of Microsoft Excel and Google Drive.
+// For Postgres, quote the data termating string `\.`.
func (w *Writer) fieldNeedsQuotes(field string) bool {
- if len(field) == 0 || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
+ if field == "" {
+ return false
+ }
+ if field == `\.` || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
return true
}
diff --git a/src/pkg/encoding/csv/writer_test.go b/src/encoding/csv/writer_test.go
index 22b740c07..8ddca0abe 100644
--- a/src/pkg/encoding/csv/writer_test.go
+++ b/src/encoding/csv/writer_test.go
@@ -28,6 +28,17 @@ var writeTests = []struct {
{Input: [][]string{{"abc\ndef"}}, Output: "\"abc\r\ndef\"\r\n", UseCRLF: true},
{Input: [][]string{{"abc\rdef"}}, Output: "\"abcdef\"\r\n", UseCRLF: true},
{Input: [][]string{{"abc\rdef"}}, Output: "\"abc\rdef\"\n", UseCRLF: false},
+ {Input: [][]string{{""}}, Output: "\n"},
+ {Input: [][]string{{"", ""}}, Output: ",\n"},
+ {Input: [][]string{{"", "", ""}}, Output: ",,\n"},
+ {Input: [][]string{{"", "", "a"}}, Output: ",,a\n"},
+ {Input: [][]string{{"", "a", ""}}, Output: ",a,\n"},
+ {Input: [][]string{{"", "a", "a"}}, Output: ",a,a\n"},
+ {Input: [][]string{{"a", "", ""}}, Output: "a,,\n"},
+ {Input: [][]string{{"a", "", "a"}}, Output: "a,,a\n"},
+ {Input: [][]string{{"a", "a", ""}}, Output: "a,a,\n"},
+ {Input: [][]string{{"a", "a", "a"}}, Output: "a,a,a\n"},
+ {Input: [][]string{{`\.`}}, Output: "\"\\.\"\n"},
}
func TestWrite(t *testing.T) {
diff --git a/src/pkg/encoding/encoding.go b/src/encoding/encoding.go
index 6d218071b..6d218071b 100644
--- a/src/pkg/encoding/encoding.go
+++ b/src/encoding/encoding.go
diff --git a/src/pkg/encoding/gob/codec_test.go b/src/encoding/gob/codec_test.go
index fa57f3761..56a7298fa 100644
--- a/src/pkg/encoding/gob/codec_test.go
+++ b/src/encoding/gob/codec_test.go
@@ -14,7 +14,6 @@ import (
"strings"
"testing"
"time"
- "unsafe"
)
var doFuzzTests = flag.Bool("gob.fuzz", false, "run the fuzz tests, which are large and very slow")
@@ -51,10 +50,16 @@ func testError(t *testing.T) {
return
}
+func newDecBuffer(data []byte) *decBuffer {
+ return &decBuffer{
+ data: data,
+ }
+}
+
// Test basic encode/decode routines for unsigned integers
func TestUintCodec(t *testing.T) {
defer testError(t)
- b := new(bytes.Buffer)
+ b := new(encBuffer)
encState := newEncoderState(b)
for _, tt := range encodeT {
b.Reset()
@@ -63,10 +68,10 @@ func TestUintCodec(t *testing.T) {
t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes())
}
}
- decState := newDecodeState(b)
for u := uint64(0); ; u = (u + 1) * 7 {
b.Reset()
encState.encodeUint(u)
+ decState := newDecodeState(newDecBuffer(b.Bytes()))
v := decState.decodeUint()
if u != v {
t.Errorf("Encode/Decode: sent %#x received %#x", u, v)
@@ -79,10 +84,10 @@ func TestUintCodec(t *testing.T) {
func verifyInt(i int64, t *testing.T) {
defer testError(t)
- var b = new(bytes.Buffer)
+ var b = new(encBuffer)
encState := newEncoderState(b)
encState.encodeInt(i)
- decState := newDecodeState(b)
+ decState := newDecodeState(newDecBuffer(b.Bytes()))
decState.buf = make([]byte, 8)
j := decState.decodeInt()
if i != j {
@@ -119,14 +124,14 @@ var complexResult = []byte{0x07, 0xFE, 0x31, 0x40, 0xFE, 0x33, 0x40}
// The result of encoding "hello" with field number 7
var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'}
-func newDecodeState(buf *bytes.Buffer) *decoderState {
+func newDecodeState(buf *decBuffer) *decoderState {
d := new(decoderState)
d.b = buf
d.buf = make([]byte, uint64Size)
return d
}
-func newEncoderState(b *bytes.Buffer) *encoderState {
+func newEncoderState(b *encBuffer) *encoderState {
b.Reset()
state := &encoderState{enc: nil, b: b}
state.fieldnum = -1
@@ -136,14 +141,14 @@ func newEncoderState(b *bytes.Buffer) *encoderState {
// Test instruction execution for encoding.
// Do not run the machine yet; instead do individual instructions crafted by hand.
func TestScalarEncInstructions(t *testing.T) {
- var b = new(bytes.Buffer)
+ var b = new(encBuffer)
// bool
{
- data := struct{ a bool }{true}
- instr := &encInstr{encBool, 6, 0, 0}
+ var data bool = true
+ instr := &encInstr{encBool, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(boolResult, b.Bytes()) {
t.Errorf("bool enc instructions: expected % x got % x", boolResult, b.Bytes())
}
@@ -152,10 +157,10 @@ func TestScalarEncInstructions(t *testing.T) {
// int
{
b.Reset()
- data := struct{ a int }{17}
- instr := &encInstr{encInt, 6, 0, 0}
+ var data int = 17
+ instr := &encInstr{encInt, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(signedResult, b.Bytes()) {
t.Errorf("int enc instructions: expected % x got % x", signedResult, b.Bytes())
}
@@ -164,10 +169,10 @@ func TestScalarEncInstructions(t *testing.T) {
// uint
{
b.Reset()
- data := struct{ a uint }{17}
- instr := &encInstr{encUint, 6, 0, 0}
+ var data uint = 17
+ instr := &encInstr{encUint, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(unsignedResult, b.Bytes()) {
t.Errorf("uint enc instructions: expected % x got % x", unsignedResult, b.Bytes())
}
@@ -176,10 +181,10 @@ func TestScalarEncInstructions(t *testing.T) {
// int8
{
b.Reset()
- data := struct{ a int8 }{17}
- instr := &encInstr{encInt8, 6, 0, 0}
+ var data int8 = 17
+ instr := &encInstr{encInt, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(signedResult, b.Bytes()) {
t.Errorf("int8 enc instructions: expected % x got % x", signedResult, b.Bytes())
}
@@ -188,10 +193,10 @@ func TestScalarEncInstructions(t *testing.T) {
// uint8
{
b.Reset()
- data := struct{ a uint8 }{17}
- instr := &encInstr{encUint8, 6, 0, 0}
+ var data uint8 = 17
+ instr := &encInstr{encUint, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(unsignedResult, b.Bytes()) {
t.Errorf("uint8 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
}
@@ -200,10 +205,10 @@ func TestScalarEncInstructions(t *testing.T) {
// int16
{
b.Reset()
- data := struct{ a int16 }{17}
- instr := &encInstr{encInt16, 6, 0, 0}
+ var data int16 = 17
+ instr := &encInstr{encInt, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(signedResult, b.Bytes()) {
t.Errorf("int16 enc instructions: expected % x got % x", signedResult, b.Bytes())
}
@@ -212,10 +217,10 @@ func TestScalarEncInstructions(t *testing.T) {
// uint16
{
b.Reset()
- data := struct{ a uint16 }{17}
- instr := &encInstr{encUint16, 6, 0, 0}
+ var data uint16 = 17
+ instr := &encInstr{encUint, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(unsignedResult, b.Bytes()) {
t.Errorf("uint16 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
}
@@ -224,10 +229,10 @@ func TestScalarEncInstructions(t *testing.T) {
// int32
{
b.Reset()
- data := struct{ a int32 }{17}
- instr := &encInstr{encInt32, 6, 0, 0}
+ var data int32 = 17
+ instr := &encInstr{encInt, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(signedResult, b.Bytes()) {
t.Errorf("int32 enc instructions: expected % x got % x", signedResult, b.Bytes())
}
@@ -236,10 +241,10 @@ func TestScalarEncInstructions(t *testing.T) {
// uint32
{
b.Reset()
- data := struct{ a uint32 }{17}
- instr := &encInstr{encUint32, 6, 0, 0}
+ var data uint32 = 17
+ instr := &encInstr{encUint, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(unsignedResult, b.Bytes()) {
t.Errorf("uint32 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
}
@@ -248,10 +253,10 @@ func TestScalarEncInstructions(t *testing.T) {
// int64
{
b.Reset()
- data := struct{ a int64 }{17}
- instr := &encInstr{encInt64, 6, 0, 0}
+ var data int64 = 17
+ instr := &encInstr{encInt, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(signedResult, b.Bytes()) {
t.Errorf("int64 enc instructions: expected % x got % x", signedResult, b.Bytes())
}
@@ -260,10 +265,10 @@ func TestScalarEncInstructions(t *testing.T) {
// uint64
{
b.Reset()
- data := struct{ a uint64 }{17}
- instr := &encInstr{encUint64, 6, 0, 0}
+ var data uint64 = 17
+ instr := &encInstr{encUint, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(unsignedResult, b.Bytes()) {
t.Errorf("uint64 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
}
@@ -272,10 +277,10 @@ func TestScalarEncInstructions(t *testing.T) {
// float32
{
b.Reset()
- data := struct{ a float32 }{17}
- instr := &encInstr{encFloat32, 6, 0, 0}
+ var data float32 = 17
+ instr := &encInstr{encFloat, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(floatResult, b.Bytes()) {
t.Errorf("float32 enc instructions: expected % x got % x", floatResult, b.Bytes())
}
@@ -284,10 +289,10 @@ func TestScalarEncInstructions(t *testing.T) {
// float64
{
b.Reset()
- data := struct{ a float64 }{17}
- instr := &encInstr{encFloat64, 6, 0, 0}
+ var data float64 = 17
+ instr := &encInstr{encFloat, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(floatResult, b.Bytes()) {
t.Errorf("float64 enc instructions: expected % x got % x", floatResult, b.Bytes())
}
@@ -296,10 +301,10 @@ func TestScalarEncInstructions(t *testing.T) {
// bytes == []uint8
{
b.Reset()
- data := struct{ a []byte }{[]byte("hello")}
- instr := &encInstr{encUint8Array, 6, 0, 0}
+ data := []byte("hello")
+ instr := &encInstr{encUint8Array, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(bytesResult, b.Bytes()) {
t.Errorf("bytes enc instructions: expected % x got % x", bytesResult, b.Bytes())
}
@@ -308,28 +313,28 @@ func TestScalarEncInstructions(t *testing.T) {
// string
{
b.Reset()
- data := struct{ a string }{"hello"}
- instr := &encInstr{encString, 6, 0, 0}
+ var data string = "hello"
+ instr := &encInstr{encString, 6, nil, 0}
state := newEncoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
+ instr.op(instr, state, reflect.ValueOf(data))
if !bytes.Equal(bytesResult, b.Bytes()) {
t.Errorf("string enc instructions: expected % x got % x", bytesResult, b.Bytes())
}
}
}
-func execDec(typ string, instr *decInstr, state *decoderState, t *testing.T, p unsafe.Pointer) {
+func execDec(typ string, instr *decInstr, state *decoderState, t *testing.T, value reflect.Value) {
defer testError(t)
v := int(state.decodeUint())
if v+state.fieldnum != 6 {
t.Fatalf("decoding field number %d, got %d", 6, v+state.fieldnum)
}
- instr.op(instr, state, decIndirect(p, instr.indir))
+ instr.op(instr, state, value.Elem())
state.fieldnum = 6
}
func newDecodeStateFromData(data []byte) *decoderState {
- b := bytes.NewBuffer(data)
+ b := newDecBuffer(data)
state := newDecodeState(b)
state.fieldnum = -1
return state
@@ -342,234 +347,198 @@ func TestScalarDecInstructions(t *testing.T) {
// bool
{
- var data struct {
- a bool
- }
- instr := &decInstr{decBool, 6, 0, 0, ovfl}
+ var data bool
+ instr := &decInstr{decBool, 6, nil, ovfl}
state := newDecodeStateFromData(boolResult)
- execDec("bool", instr, state, t, unsafe.Pointer(&data))
- if data.a != true {
- t.Errorf("bool a = %v not true", data.a)
+ execDec("bool", instr, state, t, reflect.ValueOf(&data))
+ if data != true {
+ t.Errorf("bool a = %v not true", data)
}
}
// int
{
- var data struct {
- a int
- }
- instr := &decInstr{decOpTable[reflect.Int], 6, 0, 0, ovfl}
+ var data int
+ instr := &decInstr{decOpTable[reflect.Int], 6, nil, ovfl}
state := newDecodeStateFromData(signedResult)
- execDec("int", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("int a = %v not 17", data.a)
+ execDec("int", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("int a = %v not 17", data)
}
}
// uint
{
- var data struct {
- a uint
- }
- instr := &decInstr{decOpTable[reflect.Uint], 6, 0, 0, ovfl}
+ var data uint
+ instr := &decInstr{decOpTable[reflect.Uint], 6, nil, ovfl}
state := newDecodeStateFromData(unsignedResult)
- execDec("uint", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("uint a = %v not 17", data.a)
+ execDec("uint", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("uint a = %v not 17", data)
}
}
// int8
{
- var data struct {
- a int8
- }
- instr := &decInstr{decInt8, 6, 0, 0, ovfl}
+ var data int8
+ instr := &decInstr{decInt8, 6, nil, ovfl}
state := newDecodeStateFromData(signedResult)
- execDec("int8", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("int8 a = %v not 17", data.a)
+ execDec("int8", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("int8 a = %v not 17", data)
}
}
// uint8
{
- var data struct {
- a uint8
- }
- instr := &decInstr{decUint8, 6, 0, 0, ovfl}
+ var data uint8
+ instr := &decInstr{decUint8, 6, nil, ovfl}
state := newDecodeStateFromData(unsignedResult)
- execDec("uint8", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("uint8 a = %v not 17", data.a)
+ execDec("uint8", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("uint8 a = %v not 17", data)
}
}
// int16
{
- var data struct {
- a int16
- }
- instr := &decInstr{decInt16, 6, 0, 0, ovfl}
+ var data int16
+ instr := &decInstr{decInt16, 6, nil, ovfl}
state := newDecodeStateFromData(signedResult)
- execDec("int16", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("int16 a = %v not 17", data.a)
+ execDec("int16", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("int16 a = %v not 17", data)
}
}
// uint16
{
- var data struct {
- a uint16
- }
- instr := &decInstr{decUint16, 6, 0, 0, ovfl}
+ var data uint16
+ instr := &decInstr{decUint16, 6, nil, ovfl}
state := newDecodeStateFromData(unsignedResult)
- execDec("uint16", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("uint16 a = %v not 17", data.a)
+ execDec("uint16", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("uint16 a = %v not 17", data)
}
}
// int32
{
- var data struct {
- a int32
- }
- instr := &decInstr{decInt32, 6, 0, 0, ovfl}
+ var data int32
+ instr := &decInstr{decInt32, 6, nil, ovfl}
state := newDecodeStateFromData(signedResult)
- execDec("int32", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("int32 a = %v not 17", data.a)
+ execDec("int32", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("int32 a = %v not 17", data)
}
}
// uint32
{
- var data struct {
- a uint32
- }
- instr := &decInstr{decUint32, 6, 0, 0, ovfl}
+ var data uint32
+ instr := &decInstr{decUint32, 6, nil, ovfl}
state := newDecodeStateFromData(unsignedResult)
- execDec("uint32", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("uint32 a = %v not 17", data.a)
+ execDec("uint32", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("uint32 a = %v not 17", data)
}
}
// uintptr
{
- var data struct {
- a uintptr
- }
- instr := &decInstr{decOpTable[reflect.Uintptr], 6, 0, 0, ovfl}
+ var data uintptr
+ instr := &decInstr{decOpTable[reflect.Uintptr], 6, nil, ovfl}
state := newDecodeStateFromData(unsignedResult)
- execDec("uintptr", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("uintptr a = %v not 17", data.a)
+ execDec("uintptr", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("uintptr a = %v not 17", data)
}
}
// int64
{
- var data struct {
- a int64
- }
- instr := &decInstr{decInt64, 6, 0, 0, ovfl}
+ var data int64
+ instr := &decInstr{decInt64, 6, nil, ovfl}
state := newDecodeStateFromData(signedResult)
- execDec("int64", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("int64 a = %v not 17", data.a)
+ execDec("int64", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("int64 a = %v not 17", data)
}
}
// uint64
{
- var data struct {
- a uint64
- }
- instr := &decInstr{decUint64, 6, 0, 0, ovfl}
+ var data uint64
+ instr := &decInstr{decUint64, 6, nil, ovfl}
state := newDecodeStateFromData(unsignedResult)
- execDec("uint64", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("uint64 a = %v not 17", data.a)
+ execDec("uint64", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("uint64 a = %v not 17", data)
}
}
// float32
{
- var data struct {
- a float32
- }
- instr := &decInstr{decFloat32, 6, 0, 0, ovfl}
+ var data float32
+ instr := &decInstr{decFloat32, 6, nil, ovfl}
state := newDecodeStateFromData(floatResult)
- execDec("float32", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("float32 a = %v not 17", data.a)
+ execDec("float32", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("float32 a = %v not 17", data)
}
}
// float64
{
- var data struct {
- a float64
- }
- instr := &decInstr{decFloat64, 6, 0, 0, ovfl}
+ var data float64
+ instr := &decInstr{decFloat64, 6, nil, ovfl}
state := newDecodeStateFromData(floatResult)
- execDec("float64", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("float64 a = %v not 17", data.a)
+ execDec("float64", instr, state, t, reflect.ValueOf(&data))
+ if data != 17 {
+ t.Errorf("float64 a = %v not 17", data)
}
}
// complex64
{
- var data struct {
- a complex64
- }
- instr := &decInstr{decOpTable[reflect.Complex64], 6, 0, 0, ovfl}
+ var data complex64
+ instr := &decInstr{decOpTable[reflect.Complex64], 6, nil, ovfl}
state := newDecodeStateFromData(complexResult)
- execDec("complex", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17+19i {
- t.Errorf("complex a = %v not 17+19i", data.a)
+ execDec("complex", instr, state, t, reflect.ValueOf(&data))
+ if data != 17+19i {
+ t.Errorf("complex a = %v not 17+19i", data)
}
}
// complex128
{
- var data struct {
- a complex128
- }
- instr := &decInstr{decOpTable[reflect.Complex128], 6, 0, 0, ovfl}
+ var data complex128
+ instr := &decInstr{decOpTable[reflect.Complex128], 6, nil, ovfl}
state := newDecodeStateFromData(complexResult)
- execDec("complex", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17+19i {
- t.Errorf("complex a = %v not 17+19i", data.a)
+ execDec("complex", instr, state, t, reflect.ValueOf(&data))
+ if data != 17+19i {
+ t.Errorf("complex a = %v not 17+19i", data)
}
}
// bytes == []uint8
{
- var data struct {
- a []byte
- }
- instr := &decInstr{decUint8Slice, 6, 0, 0, ovfl}
+ var data []byte
+ instr := &decInstr{decUint8Slice, 6, nil, ovfl}
state := newDecodeStateFromData(bytesResult)
- execDec("bytes", instr, state, t, unsafe.Pointer(&data))
- if string(data.a) != "hello" {
- t.Errorf(`bytes a = %q not "hello"`, string(data.a))
+ execDec("bytes", instr, state, t, reflect.ValueOf(&data))
+ if string(data) != "hello" {
+ t.Errorf(`bytes a = %q not "hello"`, string(data))
}
}
// string
{
- var data struct {
- a string
- }
- instr := &decInstr{decString, 6, 0, 0, ovfl}
+ var data string
+ instr := &decInstr{decString, 6, nil, ovfl}
state := newDecodeStateFromData(bytesResult)
- execDec("bytes", instr, state, t, unsafe.Pointer(&data))
- if data.a != "hello" {
- t.Errorf(`bytes a = %q not "hello"`, data.a)
+ execDec("bytes", instr, state, t, reflect.ValueOf(&data))
+ if data != "hello" {
+ t.Errorf(`bytes a = %q not "hello"`, data)
}
}
}
diff --git a/src/pkg/encoding/gob/debug.go b/src/encoding/gob/debug.go
index 6117eb083..536bbdb5a 100644
--- a/src/pkg/encoding/gob/debug.go
+++ b/src/encoding/gob/debug.go
@@ -306,7 +306,7 @@ func (deb *debugger) common() CommonType {
// Id typeId
id = deb.typeId()
default:
- errorf("corrupted CommonType")
+ errorf("corrupted CommonType, delta is %d fieldNum is %d", delta, fieldNum)
}
}
return CommonType{name, id}
@@ -598,11 +598,11 @@ func (deb *debugger) printBuiltin(indent tab, id typeId) {
fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
case tFloat:
x := deb.uint64()
- fmt.Fprintf(os.Stderr, "%s%g\n", indent, floatFromBits(x))
+ fmt.Fprintf(os.Stderr, "%s%g\n", indent, float64FromBits(x))
case tComplex:
r := deb.uint64()
i := deb.uint64()
- fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, floatFromBits(r), floatFromBits(i))
+ fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, float64FromBits(r), float64FromBits(i))
case tBytes:
x := int(deb.uint64())
b := make([]byte, x)
diff --git a/src/encoding/gob/dec_helpers.go b/src/encoding/gob/dec_helpers.go
new file mode 100644
index 000000000..a1b67661d
--- /dev/null
+++ b/src/encoding/gob/dec_helpers.go
@@ -0,0 +1,468 @@
+// Created by decgen --output dec_helpers.go; DO NOT EDIT
+
+// 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 gob
+
+import (
+ "math"
+ "reflect"
+)
+
+var decArrayHelper = map[reflect.Kind]decHelper{
+ reflect.Bool: decBoolArray,
+ reflect.Complex64: decComplex64Array,
+ reflect.Complex128: decComplex128Array,
+ reflect.Float32: decFloat32Array,
+ reflect.Float64: decFloat64Array,
+ reflect.Int: decIntArray,
+ reflect.Int16: decInt16Array,
+ reflect.Int32: decInt32Array,
+ reflect.Int64: decInt64Array,
+ reflect.Int8: decInt8Array,
+ reflect.String: decStringArray,
+ reflect.Uint: decUintArray,
+ reflect.Uint16: decUint16Array,
+ reflect.Uint32: decUint32Array,
+ reflect.Uint64: decUint64Array,
+ reflect.Uintptr: decUintptrArray,
+}
+
+var decSliceHelper = map[reflect.Kind]decHelper{
+ reflect.Bool: decBoolSlice,
+ reflect.Complex64: decComplex64Slice,
+ reflect.Complex128: decComplex128Slice,
+ reflect.Float32: decFloat32Slice,
+ reflect.Float64: decFloat64Slice,
+ reflect.Int: decIntSlice,
+ reflect.Int16: decInt16Slice,
+ reflect.Int32: decInt32Slice,
+ reflect.Int64: decInt64Slice,
+ reflect.Int8: decInt8Slice,
+ reflect.String: decStringSlice,
+ reflect.Uint: decUintSlice,
+ reflect.Uint16: decUint16Slice,
+ reflect.Uint32: decUint32Slice,
+ reflect.Uint64: decUint64Slice,
+ reflect.Uintptr: decUintptrSlice,
+}
+
+func decBoolArray(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decBoolSlice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decBoolSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]bool)
+ if !ok {
+ // It is kind bool but not type bool. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding bool array or slice: length exceeds input size (%d elements)", length)
+ }
+ slice[i] = state.decodeUint() != 0
+ }
+ return true
+}
+
+func decComplex64Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decComplex64Slice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decComplex64Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]complex64)
+ if !ok {
+ // It is kind complex64 but not type complex64. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding complex64 array or slice: length exceeds input size (%d elements)", length)
+ }
+ real := float32FromBits(state.decodeUint(), ovfl)
+ imag := float32FromBits(state.decodeUint(), ovfl)
+ slice[i] = complex(float32(real), float32(imag))
+ }
+ return true
+}
+
+func decComplex128Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decComplex128Slice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decComplex128Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]complex128)
+ if !ok {
+ // It is kind complex128 but not type complex128. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding complex128 array or slice: length exceeds input size (%d elements)", length)
+ }
+ real := float64FromBits(state.decodeUint())
+ imag := float64FromBits(state.decodeUint())
+ slice[i] = complex(real, imag)
+ }
+ return true
+}
+
+func decFloat32Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decFloat32Slice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decFloat32Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]float32)
+ if !ok {
+ // It is kind float32 but not type float32. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding float32 array or slice: length exceeds input size (%d elements)", length)
+ }
+ slice[i] = float32(float32FromBits(state.decodeUint(), ovfl))
+ }
+ return true
+}
+
+func decFloat64Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decFloat64Slice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decFloat64Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]float64)
+ if !ok {
+ // It is kind float64 but not type float64. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding float64 array or slice: length exceeds input size (%d elements)", length)
+ }
+ slice[i] = float64FromBits(state.decodeUint())
+ }
+ return true
+}
+
+func decIntArray(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decIntSlice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decIntSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]int)
+ if !ok {
+ // It is kind int but not type int. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding int array or slice: length exceeds input size (%d elements)", length)
+ }
+ x := state.decodeInt()
+ // MinInt and MaxInt
+ if x < ^int64(^uint(0)>>1) || int64(^uint(0)>>1) < x {
+ error_(ovfl)
+ }
+ slice[i] = int(x)
+ }
+ return true
+}
+
+func decInt16Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decInt16Slice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decInt16Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]int16)
+ if !ok {
+ // It is kind int16 but not type int16. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding int16 array or slice: length exceeds input size (%d elements)", length)
+ }
+ x := state.decodeInt()
+ if x < math.MinInt16 || math.MaxInt16 < x {
+ error_(ovfl)
+ }
+ slice[i] = int16(x)
+ }
+ return true
+}
+
+func decInt32Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decInt32Slice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decInt32Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]int32)
+ if !ok {
+ // It is kind int32 but not type int32. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding int32 array or slice: length exceeds input size (%d elements)", length)
+ }
+ x := state.decodeInt()
+ if x < math.MinInt32 || math.MaxInt32 < x {
+ error_(ovfl)
+ }
+ slice[i] = int32(x)
+ }
+ return true
+}
+
+func decInt64Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decInt64Slice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decInt64Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]int64)
+ if !ok {
+ // It is kind int64 but not type int64. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding int64 array or slice: length exceeds input size (%d elements)", length)
+ }
+ slice[i] = state.decodeInt()
+ }
+ return true
+}
+
+func decInt8Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decInt8Slice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decInt8Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]int8)
+ if !ok {
+ // It is kind int8 but not type int8. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding int8 array or slice: length exceeds input size (%d elements)", length)
+ }
+ x := state.decodeInt()
+ if x < math.MinInt8 || math.MaxInt8 < x {
+ error_(ovfl)
+ }
+ slice[i] = int8(x)
+ }
+ return true
+}
+
+func decStringArray(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decStringSlice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decStringSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]string)
+ if !ok {
+ // It is kind string but not type string. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding string array or slice: length exceeds input size (%d elements)", length)
+ }
+ u := state.decodeUint()
+ n := int(u)
+ if n < 0 || uint64(n) != u || n > state.b.Len() {
+ errorf("length of string exceeds input size (%d bytes)", u)
+ }
+ if n > state.b.Len() {
+ 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)
+ }
+ slice[i] = string(data)
+ }
+ return true
+}
+
+func decUintArray(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decUintSlice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decUintSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]uint)
+ if !ok {
+ // It is kind uint but not type uint. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding uint array or slice: length exceeds input size (%d elements)", length)
+ }
+ x := state.decodeUint()
+ /*TODO if math.MaxUint32 < x {
+ error_(ovfl)
+ }*/
+ slice[i] = uint(x)
+ }
+ return true
+}
+
+func decUint16Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decUint16Slice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decUint16Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]uint16)
+ if !ok {
+ // It is kind uint16 but not type uint16. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding uint16 array or slice: length exceeds input size (%d elements)", length)
+ }
+ x := state.decodeUint()
+ if math.MaxUint16 < x {
+ error_(ovfl)
+ }
+ slice[i] = uint16(x)
+ }
+ return true
+}
+
+func decUint32Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decUint32Slice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decUint32Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]uint32)
+ if !ok {
+ // It is kind uint32 but not type uint32. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding uint32 array or slice: length exceeds input size (%d elements)", length)
+ }
+ x := state.decodeUint()
+ if math.MaxUint32 < x {
+ error_(ovfl)
+ }
+ slice[i] = uint32(x)
+ }
+ return true
+}
+
+func decUint64Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decUint64Slice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decUint64Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]uint64)
+ if !ok {
+ // It is kind uint64 but not type uint64. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding uint64 array or slice: length exceeds input size (%d elements)", length)
+ }
+ slice[i] = state.decodeUint()
+ }
+ return true
+}
+
+func decUintptrArray(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return decUintptrSlice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+
+func decUintptrSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]uintptr)
+ if !ok {
+ // It is kind uintptr but not type uintptr. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding uintptr array or slice: length exceeds input size (%d elements)", length)
+ }
+ x := state.decodeUint()
+ if uint64(^uintptr(0)) < x {
+ error_(ovfl)
+ }
+ slice[i] = uintptr(x)
+ }
+ return true
+}
diff --git a/src/encoding/gob/decgen.go b/src/encoding/gob/decgen.go
new file mode 100644
index 000000000..da41a899e
--- /dev/null
+++ b/src/encoding/gob/decgen.go
@@ -0,0 +1,240 @@
+// 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 ignore
+
+// encgen writes the helper functions for encoding. Intended to be
+// used with go generate; see the invocation in encode.go.
+
+// TODO: We could do more by being unsafe. Add a -unsafe flag?
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/format"
+ "log"
+ "os"
+)
+
+var output = flag.String("output", "dec_helpers.go", "file name to write")
+
+type Type struct {
+ lower string
+ upper string
+ decoder string
+}
+
+var types = []Type{
+ {
+ "bool",
+ "Bool",
+ `slice[i] = state.decodeUint() != 0`,
+ },
+ {
+ "complex64",
+ "Complex64",
+ `real := float32FromBits(state.decodeUint(), ovfl)
+ imag := float32FromBits(state.decodeUint(), ovfl)
+ slice[i] = complex(float32(real), float32(imag))`,
+ },
+ {
+ "complex128",
+ "Complex128",
+ `real := float64FromBits(state.decodeUint())
+ imag := float64FromBits(state.decodeUint())
+ slice[i] = complex(real, imag)`,
+ },
+ {
+ "float32",
+ "Float32",
+ `slice[i] = float32(float32FromBits(state.decodeUint(), ovfl))`,
+ },
+ {
+ "float64",
+ "Float64",
+ `slice[i] = float64FromBits(state.decodeUint())`,
+ },
+ {
+ "int",
+ "Int",
+ `x := state.decodeInt()
+ // MinInt and MaxInt
+ if x < ^int64(^uint(0)>>1) || int64(^uint(0)>>1) < x {
+ error_(ovfl)
+ }
+ slice[i] = int(x)`,
+ },
+ {
+ "int16",
+ "Int16",
+ `x := state.decodeInt()
+ if x < math.MinInt16 || math.MaxInt16 < x {
+ error_(ovfl)
+ }
+ slice[i] = int16(x)`,
+ },
+ {
+ "int32",
+ "Int32",
+ `x := state.decodeInt()
+ if x < math.MinInt32 || math.MaxInt32 < x {
+ error_(ovfl)
+ }
+ slice[i] = int32(x)`,
+ },
+ {
+ "int64",
+ "Int64",
+ `slice[i] = state.decodeInt()`,
+ },
+ {
+ "int8",
+ "Int8",
+ `x := state.decodeInt()
+ if x < math.MinInt8 || math.MaxInt8 < x {
+ error_(ovfl)
+ }
+ slice[i] = int8(x)`,
+ },
+ {
+ "string",
+ "String",
+ `u := state.decodeUint()
+ n := int(u)
+ if n < 0 || uint64(n) != u || n > state.b.Len() {
+ errorf("length of string exceeds input size (%d bytes)", u)
+ }
+ if n > state.b.Len() {
+ 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)
+ }
+ slice[i] = string(data)`,
+ },
+ {
+ "uint",
+ "Uint",
+ `x := state.decodeUint()
+ /*TODO if math.MaxUint32 < x {
+ error_(ovfl)
+ }*/
+ slice[i] = uint(x)`,
+ },
+ {
+ "uint16",
+ "Uint16",
+ `x := state.decodeUint()
+ if math.MaxUint16 < x {
+ error_(ovfl)
+ }
+ slice[i] = uint16(x)`,
+ },
+ {
+ "uint32",
+ "Uint32",
+ `x := state.decodeUint()
+ if math.MaxUint32 < x {
+ error_(ovfl)
+ }
+ slice[i] = uint32(x)`,
+ },
+ {
+ "uint64",
+ "Uint64",
+ `slice[i] = state.decodeUint()`,
+ },
+ {
+ "uintptr",
+ "Uintptr",
+ `x := state.decodeUint()
+ if uint64(^uintptr(0)) < x {
+ error_(ovfl)
+ }
+ slice[i] = uintptr(x)`,
+ },
+ // uint8 Handled separately.
+}
+
+func main() {
+ log.SetFlags(0)
+ log.SetPrefix("decgen: ")
+ flag.Parse()
+ if flag.NArg() != 0 {
+ log.Fatal("usage: decgen [--output filename]")
+ }
+ var b bytes.Buffer
+ fmt.Fprintf(&b, "// Created by decgen --output %s; DO NOT EDIT\n", *output)
+ fmt.Fprint(&b, header)
+ printMaps(&b, "Array")
+ fmt.Fprint(&b, "\n")
+ printMaps(&b, "Slice")
+ for _, t := range types {
+ fmt.Fprintf(&b, arrayHelper, t.lower, t.upper)
+ fmt.Fprintf(&b, sliceHelper, t.lower, t.upper, t.decoder)
+ }
+ source, err := format.Source(b.Bytes())
+ if err != nil {
+ log.Fatal("source format error:", err)
+ }
+ fd, err := os.Create(*output)
+ _, err = fd.Write(source)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func printMaps(b *bytes.Buffer, upperClass string) {
+ fmt.Fprintf(b, "var dec%sHelper = map[reflect.Kind]decHelper{\n", upperClass)
+ for _, t := range types {
+ fmt.Fprintf(b, "reflect.%s: dec%s%s,\n", t.upper, t.upper, upperClass)
+ }
+ fmt.Fprintf(b, "}\n")
+}
+
+const header = `
+// 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 gob
+
+import (
+ "math"
+ "reflect"
+)
+
+`
+
+const arrayHelper = `
+func dec%[2]sArray(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return dec%[2]sSlice(state, v.Slice(0, v.Len()), length, ovfl)
+}
+`
+
+const sliceHelper = `
+func dec%[2]sSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
+ slice, ok := v.Interface().([]%[1]s)
+ if !ok {
+ // It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding %[1]s array or slice: length exceeds input size (%%d elements)", length)
+ }
+ %[3]s
+ }
+ return true
+}
+`
diff --git a/src/pkg/encoding/gob/decode.go b/src/encoding/gob/decode.go
index d8513148e..a5bef9314 100644
--- a/src/pkg/encoding/gob/decode.go
+++ b/src/encoding/gob/decode.go
@@ -2,19 +2,16 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package gob
+//go:generate go run decgen.go -output dec_helpers.go
-// TODO(rsc): When garbage collector changes, revisit
-// the allocations in this file that use unsafe.Pointer.
+package gob
import (
- "bytes"
"encoding"
"errors"
"io"
"math"
"reflect"
- "unsafe"
)
var (
@@ -23,21 +20,79 @@ var (
errRange = errors.New("gob: bad data: field numbers out of bounds")
)
+type decHelper func(state *decoderState, v reflect.Value, length int, ovfl error) bool
+
// decoderState is the execution state of an instance of the decoder. A new state
// is created for nested objects.
type decoderState struct {
dec *Decoder
// 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 *bytes.Buffer
+ b *decBuffer
fieldnum int // the last field number read.
buf []byte
next *decoderState // for free list
}
+// decBuffer is an extremely simple, fast implementation of a read-only byte buffer.
+// It is initialized by calling Size and then copying the data into the slice returned by Bytes().
+type decBuffer struct {
+ data []byte
+ offset int // Read offset.
+}
+
+func (d *decBuffer) Read(p []byte) (int, error) {
+ n := copy(p, d.data[d.offset:])
+ if n == 0 && len(p) != 0 {
+ return 0, io.EOF
+ }
+ d.offset += n
+ return n, nil
+}
+
+func (d *decBuffer) Drop(n int) {
+ if n > d.Len() {
+ panic("drop")
+ }
+ d.offset += n
+}
+
+// Size grows the buffer to exactly n bytes, so d.Bytes() will
+// return a slice of length n. Existing data is first discarded.
+func (d *decBuffer) Size(n int) {
+ d.Reset()
+ if cap(d.data) < n {
+ d.data = make([]byte, n)
+ } else {
+ d.data = d.data[0:n]
+ }
+}
+
+func (d *decBuffer) ReadByte() (byte, error) {
+ if d.offset >= len(d.data) {
+ return 0, io.EOF
+ }
+ c := d.data[d.offset]
+ d.offset++
+ return c, nil
+}
+
+func (d *decBuffer) Len() int {
+ return len(d.data) - d.offset
+}
+
+func (d *decBuffer) Bytes() []byte {
+ return d.data[d.offset:]
+}
+
+func (d *decBuffer) Reset() {
+ d.data = d.data[0:0]
+ d.offset = 0
+}
+
// We pass the bytes.Buffer separately for easier testing of the infrastructure
// without requiring a full Decoder.
-func (dec *Decoder) newDecoderState(buf *bytes.Buffer) *decoderState {
+func (dec *Decoder) newDecoderState(buf *decBuffer) *decoderState {
d := dec.freeList
if d == nil {
d = new(decoderState)
@@ -128,175 +183,118 @@ func (state *decoderState) decodeInt() int64 {
}
// decOp is the signature of a decoding operator for a given type.
-type decOp func(i *decInstr, state *decoderState, p unsafe.Pointer)
+type decOp func(i *decInstr, state *decoderState, v reflect.Value)
// The 'instructions' of the decoding machine
type decInstr struct {
- op decOp
- field int // field number of the wire type
- indir int // how many pointer indirections to reach the value in the struct
- offset uintptr // offset in the structure of the field to encode
- ovfl error // error message for overflow/underflow (for arrays, of the elements)
-}
-
-// Since the encoder writes no zeros, if we arrive at a decoder we have
-// a value to extract and store. The field number has already been read
-// (it's how we knew to call this decoder).
-// Each decoder is responsible for handling any indirections associated
-// with the data structure. If any pointer so reached is nil, allocation must
-// be done.
-
-// Walk the pointer hierarchy, allocating if we find a nil. Stop one before the end.
-func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
- for ; indir > 1; indir-- {
- if *(*unsafe.Pointer)(p) == nil {
- // Allocation required
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(unsafe.Pointer))
- }
- p = *(*unsafe.Pointer)(p)
- }
- return p
+ op decOp
+ field int // field number of the wire type
+ index []int // field access indices for destination type
+ ovfl error // error message for overflow/underflow (for arrays, of the elements)
}
// ignoreUint discards a uint value with no destination.
-func ignoreUint(i *decInstr, state *decoderState, p unsafe.Pointer) {
+func ignoreUint(i *decInstr, state *decoderState, v reflect.Value) {
state.decodeUint()
}
// ignoreTwoUints discards a uint value with no destination. It's used to skip
// complex values.
-func ignoreTwoUints(i *decInstr, state *decoderState, p unsafe.Pointer) {
+func ignoreTwoUints(i *decInstr, state *decoderState, v reflect.Value) {
state.decodeUint()
state.decodeUint()
}
-// decBool decodes a uint and stores it as a boolean through p.
-func decBool(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(bool))
+// Since the encoder writes no zeros, if we arrive at a decoder we have
+// a value to extract and store. The field number has already been read
+// (it's how we knew to call this decoder).
+// Each decoder is responsible for handling any indirections associated
+// with the data structure. If any pointer so reached is nil, allocation must
+// be done.
+
+// decAlloc takes a value and returns a settable value that can
+// be assigned to. If the value is a pointer, decAlloc guarantees it points to storage.
+// The callers to the individual decoders are expected to have used decAlloc.
+// The individual decoders don't need to it.
+func decAlloc(v reflect.Value) reflect.Value {
+ for v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
}
- p = *(*unsafe.Pointer)(p)
+ v = v.Elem()
}
- *(*bool)(p) = state.decodeUint() != 0
+ return v
}
-// decInt8 decodes an integer and stores it as an int8 through p.
-func decInt8(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int8))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decBool decodes a uint and stores it as a boolean in value.
+func decBool(i *decInstr, state *decoderState, value reflect.Value) {
+ value.SetBool(state.decodeUint() != 0)
+}
+
+// decInt8 decodes an integer and stores it as an int8 in value.
+func decInt8(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeInt()
if v < math.MinInt8 || math.MaxInt8 < v {
error_(i.ovfl)
- } else {
- *(*int8)(p) = int8(v)
}
+ value.SetInt(v)
}
-// decUint8 decodes an unsigned integer and stores it as a uint8 through p.
-func decUint8(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint8))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decUint8 decodes an unsigned integer and stores it as a uint8 in value.
+func decUint8(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeUint()
if math.MaxUint8 < v {
error_(i.ovfl)
- } else {
- *(*uint8)(p) = uint8(v)
}
+ value.SetUint(v)
}
-// decInt16 decodes an integer and stores it as an int16 through p.
-func decInt16(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int16))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decInt16 decodes an integer and stores it as an int16 in value.
+func decInt16(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeInt()
if v < math.MinInt16 || math.MaxInt16 < v {
error_(i.ovfl)
- } else {
- *(*int16)(p) = int16(v)
}
+ value.SetInt(v)
}
-// decUint16 decodes an unsigned integer and stores it as a uint16 through p.
-func decUint16(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint16))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decUint16 decodes an unsigned integer and stores it as a uint16 in value.
+func decUint16(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeUint()
if math.MaxUint16 < v {
error_(i.ovfl)
- } else {
- *(*uint16)(p) = uint16(v)
}
+ value.SetUint(v)
}
-// decInt32 decodes an integer and stores it as an int32 through p.
-func decInt32(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int32))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decInt32 decodes an integer and stores it as an int32 in value.
+func decInt32(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeInt()
if v < math.MinInt32 || math.MaxInt32 < v {
error_(i.ovfl)
- } else {
- *(*int32)(p) = int32(v)
}
+ value.SetInt(v)
}
-// decUint32 decodes an unsigned integer and stores it as a uint32 through p.
-func decUint32(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint32))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decUint32 decodes an unsigned integer and stores it as a uint32 in value.
+func decUint32(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeUint()
if math.MaxUint32 < v {
error_(i.ovfl)
- } else {
- *(*uint32)(p) = uint32(v)
}
+ value.SetUint(v)
}
-// decInt64 decodes an integer and stores it as an int64 through p.
-func decInt64(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int64))
- }
- p = *(*unsafe.Pointer)(p)
- }
- *(*int64)(p) = int64(state.decodeInt())
+// decInt64 decodes an integer and stores it as an int64 in value.
+func decInt64(i *decInstr, state *decoderState, value reflect.Value) {
+ v := state.decodeInt()
+ value.SetInt(v)
}
-// decUint64 decodes an unsigned integer and stores it as a uint64 through p.
-func decUint64(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint64))
- }
- p = *(*unsafe.Pointer)(p)
- }
- *(*uint64)(p) = uint64(state.decodeUint())
+// decUint64 decodes an unsigned integer and stores it as a uint64 in value.
+func decUint64(i *decInstr, state *decoderState, value reflect.Value) {
+ v := state.decodeUint()
+ value.SetUint(v)
}
// Floating-point numbers are transmitted as uint64s holding the bits
@@ -304,7 +302,7 @@ func decUint64(i *decInstr, state *decoderState, p unsafe.Pointer) {
// the exponent end coming out first, so integer floating point numbers
// (for example) transmit more compactly. This routine does the
// unswizzling.
-func floatFromBits(u uint64) float64 {
+func float64FromBits(u uint64) float64 {
var v uint64
for i := 0; i < 8; i++ {
v <<= 8
@@ -314,128 +312,100 @@ func floatFromBits(u uint64) float64 {
return math.Float64frombits(v)
}
-// storeFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
-// number, and stores it through p. It's a helper function for float32 and complex64.
-func storeFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
- v := floatFromBits(state.decodeUint())
+// float32FromBits decodes an unsigned integer, treats it as a 32-bit floating-point
+// number, and returns it. It's a helper function for float32 and complex64.
+// It returns a float64 because that's what reflection needs, but its return
+// value is known to be accurately representable in a float32.
+func float32FromBits(u uint64, ovfl error) float64 {
+ v := float64FromBits(u)
av := v
if av < 0 {
av = -av
}
// +Inf is OK in both 32- and 64-bit floats. Underflow is always OK.
if math.MaxFloat32 < av && av <= math.MaxFloat64 {
- error_(i.ovfl)
- } else {
- *(*float32)(p) = float32(v)
+ error_(ovfl)
}
+ return v
}
// decFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
-// number, and stores it through p.
-func decFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float32))
- }
- p = *(*unsafe.Pointer)(p)
- }
- storeFloat32(i, state, p)
+// number, and stores it in value.
+func decFloat32(i *decInstr, state *decoderState, value reflect.Value) {
+ value.SetFloat(float32FromBits(state.decodeUint(), i.ovfl))
}
// decFloat64 decodes an unsigned integer, treats it as a 64-bit floating-point
-// number, and stores it through p.
-func decFloat64(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float64))
- }
- p = *(*unsafe.Pointer)(p)
- }
- *(*float64)(p) = floatFromBits(uint64(state.decodeUint()))
+// number, and stores it in value.
+func decFloat64(i *decInstr, state *decoderState, value reflect.Value) {
+ value.SetFloat(float64FromBits(state.decodeUint()))
}
// decComplex64 decodes a pair of unsigned integers, treats them as a
-// pair of floating point numbers, and stores them as a complex64 through p.
+// pair of floating point numbers, and stores them as a complex64 in value.
// The real part comes first.
-func decComplex64(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex64))
- }
- p = *(*unsafe.Pointer)(p)
- }
- storeFloat32(i, state, p)
- storeFloat32(i, state, unsafe.Pointer(uintptr(p)+unsafe.Sizeof(float32(0))))
+func decComplex64(i *decInstr, state *decoderState, value reflect.Value) {
+ real := float32FromBits(state.decodeUint(), i.ovfl)
+ imag := float32FromBits(state.decodeUint(), i.ovfl)
+ value.SetComplex(complex(real, imag))
}
// decComplex128 decodes a pair of unsigned integers, treats them as a
-// pair of floating point numbers, and stores them as a complex128 through p.
+// pair of floating point numbers, and stores them as a complex128 in value.
// The real part comes first.
-func decComplex128(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex128))
- }
- p = *(*unsafe.Pointer)(p)
- }
- real := floatFromBits(uint64(state.decodeUint()))
- imag := floatFromBits(uint64(state.decodeUint()))
- *(*complex128)(p) = complex(real, imag)
+func decComplex128(i *decInstr, state *decoderState, value reflect.Value) {
+ real := float64FromBits(state.decodeUint())
+ imag := float64FromBits(state.decodeUint())
+ value.SetComplex(complex(real, imag))
}
-// decUint8Slice decodes a byte slice and stores through p a slice header
+// decUint8Slice decodes a byte slice and stores in value a slice header
// describing the data.
// uint8 slices are encoded as an unsigned count followed by the raw bytes.
-func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8))
- }
- p = *(*unsafe.Pointer)(p)
+func decUint8Slice(i *decInstr, state *decoderState, value reflect.Value) {
+ u := state.decodeUint()
+ n := int(u)
+ if n < 0 || uint64(n) != u {
+ errorf("length of %s exceeds input size (%d bytes)", value.Type(), u)
+ }
+ if n > state.b.Len() {
+ errorf("%s data too long for buffer: %d", value.Type(), n)
}
- n := state.decodeUint()
- if n > uint64(state.b.Len()) {
- errorf("length of []byte exceeds input size (%d bytes)", n)
+ if n > tooBig {
+ errorf("byte slice too big: %d", n)
}
- slice := (*[]uint8)(p)
- if uint64(cap(*slice)) < n {
- *slice = make([]uint8, n)
+ if value.Cap() < n {
+ value.Set(reflect.MakeSlice(value.Type(), n, n))
} else {
- *slice = (*slice)[0:n]
+ value.Set(value.Slice(0, n))
}
- if _, err := state.b.Read(*slice); err != nil {
+ if _, err := state.b.Read(value.Bytes()); err != nil {
errorf("error decoding []byte: %s", err)
}
}
-// decString decodes byte array and stores through p a string header
+// decString decodes byte array and stores in value a string header
// describing the data.
// Strings are encoded as an unsigned count followed by the raw bytes.
-func decString(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(string))
- }
- p = *(*unsafe.Pointer)(p)
+func decString(i *decInstr, state *decoderState, value reflect.Value) {
+ u := state.decodeUint()
+ n := int(u)
+ if n < 0 || uint64(n) != u || n > state.b.Len() {
+ errorf("length of %s exceeds input size (%d bytes)", value.Type(), u)
}
- n := state.decodeUint()
- if n > uint64(state.b.Len()) {
- errorf("string length exceeds input size (%d bytes)", n)
+ if n > state.b.Len() {
+ errorf("%s data too long for buffer: %d", value.Type(), n)
}
- b := make([]byte, n)
- state.b.Read(b)
- // It would be a shame to do the obvious thing here,
- // *(*string)(p) = string(b)
- // because we've already allocated the storage and this would
- // allocate again and copy. So we do this ugly hack, which is even
- // even more unsafe than it looks as it depends the memory
- // representation of a string matching the beginning of the memory
- // representation of a byte slice (a byte slice is longer).
- *(*string)(p) = *(*string)(unsafe.Pointer(&b))
+ // Read the data.
+ data := make([]byte, n)
+ if _, err := state.b.Read(data); err != nil {
+ errorf("error decoding string: %s", err)
+ }
+ value.SetString(string(data))
}
// ignoreUint8Array skips over the data for a byte slice value with no destination.
-func ignoreUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) {
+func ignoreUint8Array(i *decInstr, state *decoderState, value reflect.Value) {
b := make([]byte, state.decodeUint())
state.b.Read(b)
}
@@ -449,55 +419,29 @@ type decEngine struct {
numInstr int // the number of active instructions
}
-// allocate makes sure storage is available for an object of underlying type rtyp
-// that is indir levels of indirection through p.
-func allocate(rtyp reflect.Type, p unsafe.Pointer, indir int) unsafe.Pointer {
- if indir == 0 {
- return p
- }
- up := p
- if indir > 1 {
- up = decIndirect(up, indir)
- }
- if *(*unsafe.Pointer)(up) == nil {
- // Allocate object.
- *(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer())
- }
- return *(*unsafe.Pointer)(up)
-}
-
-// decodeSingle decodes a top-level value that is not a struct and stores it through p.
+// decodeSingle decodes a top-level value that is not a struct and stores it in value.
// Such values are preceded by a zero, making them have the memory layout of a
// struct field (although with an illegal field number).
-func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep unsafe.Pointer) {
+func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, value reflect.Value) {
state := dec.newDecoderState(&dec.buf)
+ defer dec.freeDecoderState(state)
state.fieldnum = singletonField
- delta := int(state.decodeUint())
- if delta != 0 {
+ if state.decodeUint() != 0 {
errorf("decode: corrupted data: non-zero delta for singleton")
}
instr := &engine.instr[singletonField]
- if instr.indir != ut.indir {
- errorf("internal error: inconsistent indirection instr %d ut %d", instr.indir, ut.indir)
- }
- ptr := basep // offset will be zero
- if instr.indir > 1 {
- ptr = decIndirect(ptr, instr.indir)
- }
- instr.op(instr, state, ptr)
- dec.freeDecoderState(state)
+ instr.op(instr, state, value)
}
-// decodeStruct decodes a top-level struct and stores it through p.
+// decodeStruct decodes a top-level struct and stores it in value.
// Indir is for the value, not the type. At the time of the call it may
// differ from ut.indir, which was computed when the engine was built.
// This state cannot arise for decodeSingle, which is called directly
// from the user's value, not from the innards of an engine.
-func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p unsafe.Pointer, indir int) {
- p = allocate(ut.base, p, indir)
+func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, value reflect.Value) {
state := dec.newDecoderState(&dec.buf)
+ defer dec.freeDecoderState(state)
state.fieldnum = -1
- basep := p
for state.b.Len() > 0 {
delta := int(state.decodeUint())
if delta < 0 {
@@ -512,19 +456,25 @@ func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p unsafe.P
break
}
instr := &engine.instr[fieldnum]
- p := unsafe.Pointer(uintptr(basep) + instr.offset)
- if instr.indir > 1 {
- p = decIndirect(p, instr.indir)
+ var field reflect.Value
+ if instr.index != nil {
+ // Otherwise the field is unknown to us and instr.op is an ignore op.
+ field = value.FieldByIndex(instr.index)
+ if field.Kind() == reflect.Ptr {
+ field = decAlloc(field)
+ }
}
- instr.op(instr, state, p)
+ instr.op(instr, state, field)
state.fieldnum = fieldnum
}
- dec.freeDecoderState(state)
}
+var noValue reflect.Value
+
// ignoreStruct discards the data for a struct with no destination.
func (dec *Decoder) ignoreStruct(engine *decEngine) {
state := dec.newDecoderState(&dec.buf)
+ defer dec.freeDecoderState(state)
state.fieldnum = -1
for state.b.Len() > 0 {
delta := int(state.decodeUint())
@@ -539,97 +489,89 @@ func (dec *Decoder) ignoreStruct(engine *decEngine) {
error_(errRange)
}
instr := &engine.instr[fieldnum]
- instr.op(instr, state, unsafe.Pointer(nil))
+ instr.op(instr, state, noValue)
state.fieldnum = fieldnum
}
- dec.freeDecoderState(state)
}
// ignoreSingle discards the data for a top-level non-struct value with no
// destination. It's used when calling Decode with a nil value.
func (dec *Decoder) ignoreSingle(engine *decEngine) {
state := dec.newDecoderState(&dec.buf)
+ defer dec.freeDecoderState(state)
state.fieldnum = singletonField
delta := int(state.decodeUint())
if delta != 0 {
errorf("decode: corrupted data: non-zero delta for singleton")
}
instr := &engine.instr[singletonField]
- instr.op(instr, state, unsafe.Pointer(nil))
- dec.freeDecoderState(state)
+ instr.op(instr, state, noValue)
}
// decodeArrayHelper does the work for decoding arrays and slices.
-func (dec *Decoder) decodeArrayHelper(state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) {
- instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl}
+func (dec *Decoder) decodeArrayHelper(state *decoderState, value reflect.Value, elemOp decOp, length int, ovfl error, helper decHelper) {
+ if helper != nil && helper(state, value, length, ovfl) {
+ return
+ }
+ instr := &decInstr{elemOp, 0, nil, ovfl}
+ isPtr := value.Type().Elem().Kind() == reflect.Ptr
for i := 0; i < length; i++ {
if state.b.Len() == 0 {
errorf("decoding array or slice: length exceeds input size (%d elements)", length)
}
- up := p
- if elemIndir > 1 {
- up = decIndirect(up, elemIndir)
+ v := value.Index(i)
+ if isPtr {
+ v = decAlloc(v)
}
- elemOp(instr, state, up)
- p = unsafe.Pointer(uintptr(p) + elemWid)
+ elemOp(instr, state, v)
}
}
-// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element.
+// decodeArray decodes an array and stores it in value.
// The length is an unsigned integer preceding the elements. Even though the length is redundant
// (it's part of the type), it's a useful check and is included in the encoding.
-func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) {
- if indir > 0 {
- p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
- }
+func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, value reflect.Value, elemOp decOp, length int, ovfl error, helper decHelper) {
if n := state.decodeUint(); n != uint64(length) {
errorf("length mismatch in decodeArray")
}
- dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl)
+ dec.decodeArrayHelper(state, value, elemOp, length, ovfl, helper)
}
-// decodeIntoValue is a helper for map decoding. Since maps are decoded using reflection,
-// unlike the other items we can't use a pointer directly.
-func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl error) reflect.Value {
- instr := &decInstr{op, 0, indir, 0, ovfl}
- up := unsafeAddr(v)
- if indir > 1 {
- up = decIndirect(up, indir)
+// decodeIntoValue is a helper for map decoding.
+func decodeIntoValue(state *decoderState, op decOp, isPtr bool, value reflect.Value, ovfl error) reflect.Value {
+ instr := &decInstr{op, 0, nil, ovfl}
+ v := value
+ if isPtr {
+ v = decAlloc(value)
}
- op(instr, state, up)
- return v
+ op(instr, state, v)
+ return value
}
-// decodeMap decodes a map and stores its header through p.
+// decodeMap decodes a map and stores it in value.
// Maps are encoded as a length followed by key:value pairs.
// Because the internals of maps are not visible to us, we must
// use reflection rather than pointer magic.
-func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p unsafe.Pointer, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) {
- if indir > 0 {
- p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect
- }
- up := unsafe.Pointer(p)
- if *(*unsafe.Pointer)(up) == nil { // maps are represented as a pointer in the runtime
+func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, value reflect.Value, keyOp, elemOp decOp, ovfl error) {
+ if value.IsNil() {
// Allocate map.
- *(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.MakeMap(mtyp).Pointer())
+ value.Set(reflect.MakeMap(mtyp))
}
- // Maps cannot be accessed by moving addresses around the way
- // that slices etc. can. We must recover a full reflection value for
- // the iteration.
- v := reflect.NewAt(mtyp, unsafe.Pointer(p)).Elem()
n := int(state.decodeUint())
+ keyIsPtr := mtyp.Key().Kind() == reflect.Ptr
+ elemIsPtr := mtyp.Elem().Kind() == reflect.Ptr
for i := 0; i < n; i++ {
- key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl)
- elem := decodeIntoValue(state, elemOp, elemIndir, allocValue(mtyp.Elem()), ovfl)
- v.SetMapIndex(key, elem)
+ key := decodeIntoValue(state, keyOp, keyIsPtr, allocValue(mtyp.Key()), ovfl)
+ elem := decodeIntoValue(state, elemOp, elemIsPtr, allocValue(mtyp.Elem()), ovfl)
+ value.SetMapIndex(key, elem)
}
}
// ignoreArrayHelper does the work for discarding arrays and slices.
func (dec *Decoder) ignoreArrayHelper(state *decoderState, elemOp decOp, length int) {
- instr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")}
+ instr := &decInstr{elemOp, 0, nil, errors.New("no error")}
for i := 0; i < length; i++ {
- elemOp(instr, state, nil)
+ elemOp(instr, state, noValue)
}
}
@@ -644,36 +586,34 @@ func (dec *Decoder) ignoreArray(state *decoderState, elemOp decOp, length int) {
// ignoreMap discards the data for a map value with no destination.
func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) {
n := int(state.decodeUint())
- keyInstr := &decInstr{keyOp, 0, 0, 0, errors.New("no error")}
- elemInstr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")}
+ keyInstr := &decInstr{keyOp, 0, nil, errors.New("no error")}
+ elemInstr := &decInstr{elemOp, 0, nil, errors.New("no error")}
for i := 0; i < n; i++ {
- keyOp(keyInstr, state, nil)
- elemOp(elemInstr, state, nil)
+ keyOp(keyInstr, state, noValue)
+ elemOp(elemInstr, state, noValue)
}
}
-// decodeSlice decodes a slice and stores the slice header through p.
+// decodeSlice decodes a slice and stores it in value.
// Slices are encoded as an unsigned length followed by the elements.
-func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl error) {
- nr := state.decodeUint()
- n := int(nr)
- if indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- // Allocate the slice header.
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]unsafe.Pointer))
- }
- p = *(*unsafe.Pointer)(p)
- }
- // Allocate storage for the slice elements, that is, the underlying array,
- // if the existing slice does not have the capacity.
- // Always write a header at p.
- hdrp := (*reflect.SliceHeader)(p)
- if hdrp.Cap < n {
- hdrp.Data = reflect.MakeSlice(atyp, n, n).Pointer()
- hdrp.Cap = n
+func (dec *Decoder) decodeSlice(state *decoderState, value reflect.Value, elemOp decOp, ovfl error, helper decHelper) {
+ u := state.decodeUint()
+ typ := value.Type()
+ size := uint64(typ.Elem().Size())
+ nBytes := u * size
+ n := int(u)
+ // Take care with overflow in this calculation.
+ if n < 0 || uint64(n) != u || nBytes > tooBig || (size > 0 && nBytes/size != u) {
+ // We don't check n against buffer length here because if it's a slice
+ // of interfaces, there will be buffer reloads.
+ errorf("%s slice too big: %d elements of %d bytes", typ.Elem(), u, size)
+ }
+ if value.Cap() < n {
+ value.Set(reflect.MakeSlice(typ, n, n))
+ } else {
+ value.Set(value.Slice(0, n))
}
- hdrp.Len = n
- dec.decodeArrayHelper(state, unsafe.Pointer(hdrp.Data), elemOp, elemWid, n, elemIndir, ovfl)
+ dec.decodeArrayHelper(state, value, elemOp, n, ovfl, helper)
}
// ignoreSlice skips over the data for a slice value with no destination.
@@ -681,21 +621,10 @@ func (dec *Decoder) ignoreSlice(state *decoderState, elemOp decOp) {
dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint()))
}
-// setInterfaceValue sets an interface value to a concrete value,
-// but first it checks that the assignment will succeed.
-func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
- if !value.Type().AssignableTo(ivalue.Type()) {
- errorf("%s is not assignable to type %s", value.Type(), ivalue.Type())
- }
- ivalue.Set(value)
-}
-
-// decodeInterface decodes an interface value and stores it through p.
+// decodeInterface decodes an interface value and stores it in value.
// Interfaces are encoded as the name of a concrete type followed by a value.
// If the name is empty, the value is nil and no value is sent.
-func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p unsafe.Pointer, indir int) {
- // Create a writable interface reflect.Value. We need one even for the nil case.
- ivalue := allocValue(ityp)
+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
@@ -707,13 +636,10 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p un
b := make([]byte, nr)
state.b.Read(b)
name := string(b)
+ // Allocate the destination interface value.
if name == "" {
- // Copy the representation of the nil interface value to the target.
- // This is horribly unsafe and special.
- if indir > 0 {
- p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect
- }
- *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData()
+ // Copy the nil interface value to the target.
+ value.Set(reflect.Zero(value.Type()))
return
}
if len(name) > 1024 {
@@ -735,21 +661,18 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p un
// in case we want to ignore the value by skipping it completely).
state.decodeUint()
// Read the concrete value.
- value := allocValue(typ)
- dec.decodeValue(concreteId, value)
+ v := allocValue(typ)
+ dec.decodeValue(concreteId, v)
if dec.err != nil {
error_(dec.err)
}
- // Allocate the destination interface value.
- if indir > 0 {
- p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect
- }
// Assign the concrete value to the interface.
// Tread carefully; it might not satisfy the interface.
- setInterfaceValue(ivalue, value)
- // Copy the representation of the interface value to the target.
- // This is horribly unsafe and special.
- *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData()
+ if !typ.AssignableTo(ityp) {
+ errorf("%s is not assignable to type %s", typ, ityp)
+ }
+ // Copy the interface value to the target.
+ value.Set(v)
}
// ignoreInterface discards the data for an interface value with no destination.
@@ -765,12 +688,12 @@ func (dec *Decoder) ignoreInterface(state *decoderState) {
error_(dec.err)
}
// At this point, the decoder buffer contains a delimited value. Just toss it.
- state.b.Next(int(state.decodeUint()))
+ state.b.Drop(int(state.decodeUint()))
}
// decodeGobDecoder decodes something implementing the GobDecoder interface.
// The data is encoded as a byte slice.
-func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, v reflect.Value) {
+func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, value reflect.Value) {
// Read the bytes for the value.
b := make([]byte, state.decodeUint())
_, err := state.b.Read(b)
@@ -780,11 +703,11 @@ func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, v re
// We know it's one of these.
switch ut.externalDec {
case xGob:
- err = v.Interface().(GobDecoder).GobDecode(b)
+ err = value.Interface().(GobDecoder).GobDecode(b)
case xBinary:
- err = v.Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(b)
+ err = value.Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(b)
case xText:
- err = v.Interface().(encoding.TextUnmarshaler).UnmarshalText(b)
+ err = value.Interface().(encoding.TextUnmarshaler).UnmarshalText(b)
}
if err != nil {
error_(err)
@@ -832,7 +755,7 @@ var decIgnoreOpMap = map[typeId]decOp{
// decOpFor returns the decoding op for the base type under rt and
// the indirection count to reach it.
-func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) (*decOp, int) {
+func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) *decOp {
ut := userType(rt)
// If the type implements GobEncoder, we handle it without further processing.
if ut.externalDec != 0 {
@@ -842,10 +765,9 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
// Return the pointer to the op we're already building.
if opPtr := inProgress[rt]; opPtr != nil {
- return opPtr, ut.indir
+ return opPtr
}
typ := ut.base
- indir := ut.indir
var op decOp
k := typ.Kind()
if int(k) < len(decOpTable) {
@@ -858,20 +780,21 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
case reflect.Array:
name = "element of " + name
elemId := dec.wireType[wireId].ArrayT.Elem
- elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
+ elemOp := dec.decOpFor(elemId, t.Elem(), name, inProgress)
ovfl := overflow(name)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- state.dec.decodeArray(t, state, p, *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
+ helper := decArrayHelper[t.Elem().Kind()]
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ state.dec.decodeArray(t, state, value, *elemOp, t.Len(), ovfl, helper)
}
case reflect.Map:
keyId := dec.wireType[wireId].MapT.Key
elemId := dec.wireType[wireId].MapT.Elem
- keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), "key of "+name, inProgress)
- elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress)
+ keyOp := dec.decOpFor(keyId, t.Key(), "key of "+name, inProgress)
+ elemOp := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress)
ovfl := overflow(name)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- state.dec.decodeMap(t, state, p, *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ state.dec.decodeMap(t, state, value, *keyOp, *elemOp, ovfl)
}
case reflect.Slice:
@@ -886,32 +809,34 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
} else {
elemId = dec.wireType[wireId].SliceT.Elem
}
- elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
+ elemOp := dec.decOpFor(elemId, t.Elem(), name, inProgress)
ovfl := overflow(name)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- state.dec.decodeSlice(t, state, p, *elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl)
+ helper := decSliceHelper[t.Elem().Kind()]
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ state.dec.decodeSlice(state, value, *elemOp, ovfl, helper)
}
case reflect.Struct:
// Generate a closure that calls out to the engine for the nested type.
- enginePtr, err := dec.getDecEnginePtr(wireId, userType(typ))
+ ut := userType(typ)
+ enginePtr, err := dec.getDecEnginePtr(wireId, ut)
if err != nil {
error_(err)
}
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
// indirect through enginePtr to delay evaluation for recursive structs.
- dec.decodeStruct(*enginePtr, userType(typ), p, i.indir)
+ dec.decodeStruct(*enginePtr, ut, value)
}
case reflect.Interface:
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- state.dec.decodeInterface(t, state, p, i.indir)
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ state.dec.decodeInterface(t, state, value)
}
}
}
if op == nil {
errorf("decode can't handle type %s", rt)
}
- return &op, indir
+ return &op
}
// decIgnoreOpFor returns the decoding op for a field that has no destination.
@@ -921,7 +846,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
if wireId == tInterface {
// Special case because it's a method: the ignored item might
// define types and we need to record their state in the decoder.
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreInterface(state)
}
return op
@@ -934,7 +859,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
case wire.ArrayT != nil:
elemId := wire.ArrayT.Elem
elemOp := dec.decIgnoreOpFor(elemId)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreArray(state, elemOp, wire.ArrayT.Len)
}
@@ -943,14 +868,14 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
elemId := dec.wireType[wireId].MapT.Elem
keyOp := dec.decIgnoreOpFor(keyId)
elemOp := dec.decIgnoreOpFor(elemId)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreMap(state, keyOp, elemOp)
}
case wire.SliceT != nil:
elemId := wire.SliceT.Elem
elemOp := dec.decIgnoreOpFor(elemId)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreSlice(state, elemOp)
}
@@ -960,13 +885,13 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
if err != nil {
error_(err)
}
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
// indirect through enginePtr to delay evaluation for recursive structs
state.dec.ignoreStruct(*enginePtr)
}
case wire.GobEncoderT != nil, wire.BinaryMarshalerT != nil, wire.TextMarshalerT != nil:
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreGobDecoder(state)
}
}
@@ -979,7 +904,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
// gobDecodeOpFor returns the op for a type that is known to implement
// GobDecoder.
-func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
+func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) *decOp {
rcvrType := ut.user
if ut.decIndir == -1 {
rcvrType = reflect.PtrTo(rcvrType)
@@ -989,25 +914,14 @@ func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
}
}
var op decOp
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- // Caller has gotten us to within one indirection of our value.
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(reflect.New(ut.base).Pointer())
- }
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ // We now have the base type. We need its address if the receiver is a pointer.
+ if value.Kind() != reflect.Ptr && rcvrType.Kind() == reflect.Ptr {
+ value = value.Addr()
}
- // Now p is a pointer to the base type. Do we need to climb out to
- // get to the receiver type?
- var v reflect.Value
- if ut.decIndir == -1 {
- v = reflect.NewAt(rcvrType, unsafe.Pointer(&p)).Elem()
- } else {
- v = reflect.NewAt(rcvrType, p).Elem()
- }
- state.dec.decodeGobDecoder(ut, state, v)
+ state.dec.decodeGobDecoder(ut, state, value)
}
- return &op, int(ut.indir)
-
+ return &op
}
// compatibleType asks: Are these two gob Types compatible?
@@ -1108,9 +1022,9 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de
}
return nil, errors.New("gob: decoding into local type " + name + ", received remote type " + remoteType)
}
- op, indir := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp))
+ op := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp))
ovfl := errors.New(`value for "` + name + `" out of range`)
- engine.instr[singletonField] = decInstr{*op, singletonField, indir, 0, ovfl}
+ engine.instr[singletonField] = decInstr{*op, singletonField, nil, ovfl}
engine.numInstr = 1
return
}
@@ -1121,7 +1035,7 @@ func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err
engine.instr = make([]decInstr, 1) // one item
op := dec.decIgnoreOpFor(remoteId)
ovfl := overflow(dec.typeString(remoteId))
- engine.instr[0] = decInstr{op, 0, 0, 0, ovfl}
+ engine.instr[0] = decInstr{op, 0, nil, ovfl}
engine.numInstr = 1
return
}
@@ -1164,14 +1078,14 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
// TODO(r): anonymous names
if !present || !isExported(wireField.Name) {
op := dec.decIgnoreOpFor(wireField.Id)
- engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl}
+ engine.instr[fieldnum] = decInstr{op, fieldnum, nil, ovfl}
continue
}
if !dec.compatibleType(localField.Type, wireField.Id, make(map[reflect.Type]typeId)) {
errorf("wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name)
}
- op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen)
- engine.instr[fieldnum] = decInstr{*op, fieldnum, indir, uintptr(localField.Offset), ovfl}
+ op := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen)
+ engine.instr[fieldnum] = decInstr{*op, fieldnum, localField.Index, ovfl}
engine.numInstr++
}
return
@@ -1222,22 +1136,23 @@ func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, er
return
}
-// decodeValue decodes the data stream representing a value and stores it in val.
-func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
+// decodeValue decodes the data stream representing a value and stores it in value.
+func (dec *Decoder) decodeValue(wireId typeId, value reflect.Value) {
defer catchError(&dec.err)
// If the value is nil, it means we should just ignore this item.
- if !val.IsValid() {
+ if !value.IsValid() {
dec.decodeIgnoredValue(wireId)
return
}
// Dereference down to the underlying type.
- ut := userType(val.Type())
+ ut := userType(value.Type())
base := ut.base
var enginePtr **decEngine
enginePtr, dec.err = dec.getDecEnginePtr(wireId, ut)
if dec.err != nil {
return
}
+ value = decAlloc(value)
engine := *enginePtr
if st := base; st.Kind() == reflect.Struct && ut.externalDec == 0 {
if engine.numInstr == 0 && st.NumField() > 0 &&
@@ -1245,9 +1160,9 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
name := base.Name()
errorf("type mismatch: no fields matched compiling decoder for %s", name)
}
- dec.decodeStruct(engine, ut, unsafeAddr(val), ut.indir)
+ dec.decodeStruct(engine, ut, value)
} else {
- dec.decodeSingle(engine, ut, unsafeAddr(val))
+ dec.decodeSingle(engine, ut, value)
}
}
@@ -1293,21 +1208,6 @@ func init() {
decOpTable[reflect.Uintptr] = uop
}
-// Gob assumes it can call UnsafeAddr on any Value
-// in order to get a pointer it can copy data from.
-// Values that have just been created and do not point
-// into existing structs or slices cannot be addressed,
-// so simulate it by returning a pointer to a copy.
-// Each call allocates once.
-func unsafeAddr(v reflect.Value) unsafe.Pointer {
- if v.CanAddr() {
- return unsafe.Pointer(v.UnsafeAddr())
- }
- x := reflect.New(v.Type()).Elem()
- x.Set(v)
- return unsafe.Pointer(x.UnsafeAddr())
-}
-
// Gob depends on being able to take the address
// of zeroed Values it creates, so use this wrapper instead
// of the standard reflect.Zero.
diff --git a/src/pkg/encoding/gob/decoder.go b/src/encoding/gob/decoder.go
index 3a769ec12..c453e9ba3 100644
--- a/src/pkg/encoding/gob/decoder.go
+++ b/src/encoding/gob/decoder.go
@@ -6,25 +6,28 @@ package gob
import (
"bufio"
- "bytes"
"errors"
"io"
"reflect"
"sync"
)
+// tooBig provides a sanity check for sizes; used in several places.
+// Upper limit of 1GB, allowing room to grow a little without overflow.
+// TODO: make this adjustable?
+const tooBig = 1 << 30
+
// A Decoder manages the receipt of type and data information read from the
// remote side of a connection.
type Decoder struct {
mutex sync.Mutex // each item must be received atomically
r io.Reader // source of the data
- buf bytes.Buffer // buffer for more efficient i/o from r
+ buf decBuffer // buffer for more efficient i/o from r
wireType map[typeId]*wireType // map from remote ID to local description
decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines
ignorerCache map[typeId]**decEngine // ditto for ignored objects
freeList *decoderState // list of free decoderStates; avoids reallocation
countBuf []byte // used for decoding integers while parsing messages
- tmp []byte // temporary storage for i/o; saves reallocating
err error
}
@@ -75,9 +78,7 @@ func (dec *Decoder) recvMessage() bool {
dec.err = err
return false
}
- // Upper limit of 1GB, allowing room to grow a little without overflow.
- // TODO: We might want more control over this limit.
- if nbytes >= 1<<30 {
+ if nbytes >= tooBig {
dec.err = errBadCount
return false
}
@@ -87,37 +88,17 @@ func (dec *Decoder) recvMessage() bool {
// readMessage reads the next nbytes bytes from the input.
func (dec *Decoder) readMessage(nbytes int) {
- // Allocate the dec.tmp buffer, up to 10KB.
- const maxBuf = 10 * 1024
- nTmp := nbytes
- if nTmp > maxBuf {
- nTmp = maxBuf
- }
- if cap(dec.tmp) < nTmp {
- nAlloc := nTmp + 100 // A little extra for growth.
- if nAlloc > maxBuf {
- nAlloc = maxBuf
- }
- dec.tmp = make([]byte, nAlloc)
+ if dec.buf.Len() != 0 {
+ // The buffer should always be empty now.
+ panic("non-empty decoder buffer")
}
- dec.tmp = dec.tmp[:nTmp]
-
// Read the data
- dec.buf.Grow(nbytes)
- for nbytes > 0 {
- if nbytes < nTmp {
- dec.tmp = dec.tmp[:nbytes]
- }
- var nRead int
- nRead, dec.err = io.ReadFull(dec.r, dec.tmp)
- if dec.err != nil {
- if dec.err == io.EOF {
- dec.err = io.ErrUnexpectedEOF
- }
- return
+ dec.buf.Size(nbytes)
+ _, dec.err = io.ReadFull(dec.r, dec.buf.Bytes())
+ if dec.err != nil {
+ if dec.err == io.EOF {
+ dec.err = io.ErrUnexpectedEOF
}
- dec.buf.Write(dec.tmp)
- nbytes -= nRead
}
}
@@ -209,7 +190,7 @@ func (dec *Decoder) Decode(e interface{}) error {
// Otherwise, it stores the value into v. In that case, v must represent
// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet())
// If the input is at EOF, DecodeValue returns io.EOF and
-// does not modify e.
+// does not modify v.
func (dec *Decoder) DecodeValue(v reflect.Value) error {
if v.IsValid() {
if v.Kind() == reflect.Ptr && !v.IsNil() {
diff --git a/src/pkg/encoding/gob/doc.go b/src/encoding/gob/doc.go
index d0acaba1a..d0acaba1a 100644
--- a/src/pkg/encoding/gob/doc.go
+++ b/src/encoding/gob/doc.go
diff --git a/src/pkg/encoding/gob/dump.go b/src/encoding/gob/dump.go
index 17238c98d..17238c98d 100644
--- a/src/pkg/encoding/gob/dump.go
+++ b/src/encoding/gob/dump.go
diff --git a/src/encoding/gob/enc_helpers.go b/src/encoding/gob/enc_helpers.go
new file mode 100644
index 000000000..804e539d8
--- /dev/null
+++ b/src/encoding/gob/enc_helpers.go
@@ -0,0 +1,414 @@
+// Created by encgen --output enc_helpers.go; DO NOT EDIT
+
+// 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 gob
+
+import (
+ "reflect"
+)
+
+var encArrayHelper = map[reflect.Kind]encHelper{
+ reflect.Bool: encBoolArray,
+ reflect.Complex64: encComplex64Array,
+ reflect.Complex128: encComplex128Array,
+ reflect.Float32: encFloat32Array,
+ reflect.Float64: encFloat64Array,
+ reflect.Int: encIntArray,
+ reflect.Int16: encInt16Array,
+ reflect.Int32: encInt32Array,
+ reflect.Int64: encInt64Array,
+ reflect.Int8: encInt8Array,
+ reflect.String: encStringArray,
+ reflect.Uint: encUintArray,
+ reflect.Uint16: encUint16Array,
+ reflect.Uint32: encUint32Array,
+ reflect.Uint64: encUint64Array,
+ reflect.Uintptr: encUintptrArray,
+}
+
+var encSliceHelper = map[reflect.Kind]encHelper{
+ reflect.Bool: encBoolSlice,
+ reflect.Complex64: encComplex64Slice,
+ reflect.Complex128: encComplex128Slice,
+ reflect.Float32: encFloat32Slice,
+ reflect.Float64: encFloat64Slice,
+ reflect.Int: encIntSlice,
+ reflect.Int16: encInt16Slice,
+ reflect.Int32: encInt32Slice,
+ reflect.Int64: encInt64Slice,
+ reflect.Int8: encInt8Slice,
+ reflect.String: encStringSlice,
+ reflect.Uint: encUintSlice,
+ reflect.Uint16: encUint16Slice,
+ reflect.Uint32: encUint32Slice,
+ reflect.Uint64: encUint64Slice,
+ reflect.Uintptr: encUintptrSlice,
+}
+
+func encBoolArray(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encBoolSlice(state, v.Slice(0, v.Len()))
+}
+
+func encBoolSlice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]bool)
+ if !ok {
+ // It is kind bool but not type bool. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != false || state.sendZero {
+ if x {
+ state.encodeUint(1)
+ } else {
+ state.encodeUint(0)
+ }
+ }
+ }
+ return true
+}
+
+func encComplex64Array(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encComplex64Slice(state, v.Slice(0, v.Len()))
+}
+
+func encComplex64Slice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]complex64)
+ if !ok {
+ // It is kind complex64 but not type complex64. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0+0i || state.sendZero {
+ rpart := floatBits(float64(real(x)))
+ ipart := floatBits(float64(imag(x)))
+ state.encodeUint(rpart)
+ state.encodeUint(ipart)
+ }
+ }
+ return true
+}
+
+func encComplex128Array(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encComplex128Slice(state, v.Slice(0, v.Len()))
+}
+
+func encComplex128Slice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]complex128)
+ if !ok {
+ // It is kind complex128 but not type complex128. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0+0i || state.sendZero {
+ rpart := floatBits(real(x))
+ ipart := floatBits(imag(x))
+ state.encodeUint(rpart)
+ state.encodeUint(ipart)
+ }
+ }
+ return true
+}
+
+func encFloat32Array(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encFloat32Slice(state, v.Slice(0, v.Len()))
+}
+
+func encFloat32Slice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]float32)
+ if !ok {
+ // It is kind float32 but not type float32. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ bits := floatBits(float64(x))
+ state.encodeUint(bits)
+ }
+ }
+ return true
+}
+
+func encFloat64Array(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encFloat64Slice(state, v.Slice(0, v.Len()))
+}
+
+func encFloat64Slice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]float64)
+ if !ok {
+ // It is kind float64 but not type float64. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ bits := floatBits(x)
+ state.encodeUint(bits)
+ }
+ }
+ return true
+}
+
+func encIntArray(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encIntSlice(state, v.Slice(0, v.Len()))
+}
+
+func encIntSlice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]int)
+ if !ok {
+ // It is kind int but not type int. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ state.encodeInt(int64(x))
+ }
+ }
+ return true
+}
+
+func encInt16Array(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encInt16Slice(state, v.Slice(0, v.Len()))
+}
+
+func encInt16Slice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]int16)
+ if !ok {
+ // It is kind int16 but not type int16. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ state.encodeInt(int64(x))
+ }
+ }
+ return true
+}
+
+func encInt32Array(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encInt32Slice(state, v.Slice(0, v.Len()))
+}
+
+func encInt32Slice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]int32)
+ if !ok {
+ // It is kind int32 but not type int32. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ state.encodeInt(int64(x))
+ }
+ }
+ return true
+}
+
+func encInt64Array(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encInt64Slice(state, v.Slice(0, v.Len()))
+}
+
+func encInt64Slice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]int64)
+ if !ok {
+ // It is kind int64 but not type int64. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ state.encodeInt(x)
+ }
+ }
+ return true
+}
+
+func encInt8Array(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encInt8Slice(state, v.Slice(0, v.Len()))
+}
+
+func encInt8Slice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]int8)
+ if !ok {
+ // It is kind int8 but not type int8. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ state.encodeInt(int64(x))
+ }
+ }
+ return true
+}
+
+func encStringArray(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encStringSlice(state, v.Slice(0, v.Len()))
+}
+
+func encStringSlice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]string)
+ if !ok {
+ // It is kind string but not type string. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != "" || state.sendZero {
+ state.encodeUint(uint64(len(x)))
+ state.b.WriteString(x)
+ }
+ }
+ return true
+}
+
+func encUintArray(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encUintSlice(state, v.Slice(0, v.Len()))
+}
+
+func encUintSlice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]uint)
+ if !ok {
+ // It is kind uint but not type uint. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ state.encodeUint(uint64(x))
+ }
+ }
+ return true
+}
+
+func encUint16Array(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encUint16Slice(state, v.Slice(0, v.Len()))
+}
+
+func encUint16Slice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]uint16)
+ if !ok {
+ // It is kind uint16 but not type uint16. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ state.encodeUint(uint64(x))
+ }
+ }
+ return true
+}
+
+func encUint32Array(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encUint32Slice(state, v.Slice(0, v.Len()))
+}
+
+func encUint32Slice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]uint32)
+ if !ok {
+ // It is kind uint32 but not type uint32. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ state.encodeUint(uint64(x))
+ }
+ }
+ return true
+}
+
+func encUint64Array(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encUint64Slice(state, v.Slice(0, v.Len()))
+}
+
+func encUint64Slice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]uint64)
+ if !ok {
+ // It is kind uint64 but not type uint64. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ state.encodeUint(x)
+ }
+ }
+ return true
+}
+
+func encUintptrArray(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return encUintptrSlice(state, v.Slice(0, v.Len()))
+}
+
+func encUintptrSlice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]uintptr)
+ if !ok {
+ // It is kind uintptr but not type uintptr. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != 0 || state.sendZero {
+ state.encodeUint(uint64(x))
+ }
+ }
+ return true
+}
diff --git a/src/encoding/gob/encgen.go b/src/encoding/gob/encgen.go
new file mode 100644
index 000000000..efdd92829
--- /dev/null
+++ b/src/encoding/gob/encgen.go
@@ -0,0 +1,218 @@
+// 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 ignore
+
+// encgen writes the helper functions for encoding. Intended to be
+// used with go generate; see the invocation in encode.go.
+
+// TODO: We could do more by being unsafe. Add a -unsafe flag?
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/format"
+ "log"
+ "os"
+)
+
+var output = flag.String("output", "enc_helpers.go", "file name to write")
+
+type Type struct {
+ lower string
+ upper string
+ zero string
+ encoder string
+}
+
+var types = []Type{
+ {
+ "bool",
+ "Bool",
+ "false",
+ `if x {
+ state.encodeUint(1)
+ } else {
+ state.encodeUint(0)
+ }`,
+ },
+ {
+ "complex64",
+ "Complex64",
+ "0+0i",
+ `rpart := floatBits(float64(real(x)))
+ ipart := floatBits(float64(imag(x)))
+ state.encodeUint(rpart)
+ state.encodeUint(ipart)`,
+ },
+ {
+ "complex128",
+ "Complex128",
+ "0+0i",
+ `rpart := floatBits(real(x))
+ ipart := floatBits(imag(x))
+ state.encodeUint(rpart)
+ state.encodeUint(ipart)`,
+ },
+ {
+ "float32",
+ "Float32",
+ "0",
+ `bits := floatBits(float64(x))
+ state.encodeUint(bits)`,
+ },
+ {
+ "float64",
+ "Float64",
+ "0",
+ `bits := floatBits(x)
+ state.encodeUint(bits)`,
+ },
+ {
+ "int",
+ "Int",
+ "0",
+ `state.encodeInt(int64(x))`,
+ },
+ {
+ "int16",
+ "Int16",
+ "0",
+ `state.encodeInt(int64(x))`,
+ },
+ {
+ "int32",
+ "Int32",
+ "0",
+ `state.encodeInt(int64(x))`,
+ },
+ {
+ "int64",
+ "Int64",
+ "0",
+ `state.encodeInt(x)`,
+ },
+ {
+ "int8",
+ "Int8",
+ "0",
+ `state.encodeInt(int64(x))`,
+ },
+ {
+ "string",
+ "String",
+ `""`,
+ `state.encodeUint(uint64(len(x)))
+ state.b.WriteString(x)`,
+ },
+ {
+ "uint",
+ "Uint",
+ "0",
+ `state.encodeUint(uint64(x))`,
+ },
+ {
+ "uint16",
+ "Uint16",
+ "0",
+ `state.encodeUint(uint64(x))`,
+ },
+ {
+ "uint32",
+ "Uint32",
+ "0",
+ `state.encodeUint(uint64(x))`,
+ },
+ {
+ "uint64",
+ "Uint64",
+ "0",
+ `state.encodeUint(x)`,
+ },
+ {
+ "uintptr",
+ "Uintptr",
+ "0",
+ `state.encodeUint(uint64(x))`,
+ },
+ // uint8 Handled separately.
+}
+
+func main() {
+ log.SetFlags(0)
+ log.SetPrefix("encgen: ")
+ flag.Parse()
+ if flag.NArg() != 0 {
+ log.Fatal("usage: encgen [--output filename]")
+ }
+ var b bytes.Buffer
+ fmt.Fprintf(&b, "// Created by encgen --output %s; DO NOT EDIT\n", *output)
+ fmt.Fprint(&b, header)
+ printMaps(&b, "Array")
+ fmt.Fprint(&b, "\n")
+ printMaps(&b, "Slice")
+ for _, t := range types {
+ fmt.Fprintf(&b, arrayHelper, t.lower, t.upper)
+ fmt.Fprintf(&b, sliceHelper, t.lower, t.upper, t.zero, t.encoder)
+ }
+ source, err := format.Source(b.Bytes())
+ if err != nil {
+ log.Fatal("source format error:", err)
+ }
+ fd, err := os.Create(*output)
+ _, err = fd.Write(source)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func printMaps(b *bytes.Buffer, upperClass string) {
+ fmt.Fprintf(b, "var enc%sHelper = map[reflect.Kind]encHelper{\n", upperClass)
+ for _, t := range types {
+ fmt.Fprintf(b, "reflect.%s: enc%s%s,\n", t.upper, t.upper, upperClass)
+ }
+ fmt.Fprintf(b, "}\n")
+}
+
+const header = `
+// 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 gob
+
+import (
+ "reflect"
+)
+
+`
+
+const arrayHelper = `
+func enc%[2]sArray(state *encoderState, v reflect.Value) bool {
+ // Can only slice if it is addressable.
+ if !v.CanAddr() {
+ return false
+ }
+ return enc%[2]sSlice(state, v.Slice(0, v.Len()))
+}
+`
+
+const sliceHelper = `
+func enc%[2]sSlice(state *encoderState, v reflect.Value) bool {
+ slice, ok := v.Interface().([]%[1]s)
+ if !ok {
+ // It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely.
+ return false
+ }
+ for _, x := range slice {
+ if x != %[3]s || state.sendZero {
+ %[4]s
+ }
+ }
+ return true
+}
+`
diff --git a/src/pkg/encoding/gob/encode.go b/src/encoding/gob/encode.go
index 7831c02d1..f66279f14 100644
--- a/src/pkg/encoding/gob/encode.go
+++ b/src/encoding/gob/encode.go
@@ -2,17 +2,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:generate go run encgen.go -output enc_helpers.go
+
package gob
import (
- "bytes"
"encoding"
"math"
"reflect"
- "unsafe"
)
-const uint64Size = int(unsafe.Sizeof(uint64(0)))
+const uint64Size = 8
+
+type encHelper func(state *encoderState, v reflect.Value) bool
// encoderState is the global execution state of an instance of the encoder.
// Field numbers are delta encoded and always increase. The field
@@ -20,14 +22,46 @@ const uint64Size = int(unsafe.Sizeof(uint64(0)))
// 0 terminates the structure.
type encoderState struct {
enc *Encoder
- b *bytes.Buffer
+ b *encBuffer
sendZero bool // encoding an array element or map key/value pair; send zero values
fieldnum int // the last field number written.
buf [1 + uint64Size]byte // buffer used by the encoder; here to avoid allocation.
next *encoderState // for free list
}
-func (enc *Encoder) newEncoderState(b *bytes.Buffer) *encoderState {
+// encBuffer is an extremely simple, fast implementation of a write-only byte buffer.
+// It never returns a non-nil error, but Write returns an error value so it matches io.Writer.
+type encBuffer struct {
+ data []byte
+ scratch [64]byte
+}
+
+func (e *encBuffer) WriteByte(c byte) {
+ e.data = append(e.data, c)
+}
+
+func (e *encBuffer) Write(p []byte) (int, error) {
+ e.data = append(e.data, p...)
+ return len(p), nil
+}
+
+func (e *encBuffer) WriteString(s string) {
+ e.data = append(e.data, s...)
+}
+
+func (e *encBuffer) Len() int {
+ return len(e.data)
+}
+
+func (e *encBuffer) Bytes() []byte {
+ return e.data
+}
+
+func (e *encBuffer) Reset() {
+ e.data = e.data[0:0]
+}
+
+func (enc *Encoder) newEncoderState(b *encBuffer) *encoderState {
e := enc.freeList
if e == nil {
e = new(encoderState)
@@ -38,6 +72,9 @@ func (enc *Encoder) newEncoderState(b *bytes.Buffer) *encoderState {
e.sendZero = false
e.fieldnum = 0
e.b = b
+ if len(b.data) == 0 {
+ b.data = b.scratch[0:0]
+ }
return e
}
@@ -54,10 +91,7 @@ func (enc *Encoder) freeEncoderState(e *encoderState) {
// encodeUint writes an encoded unsigned integer to state.b.
func (state *encoderState) encodeUint(x uint64) {
if x <= 0x7F {
- err := state.b.WriteByte(uint8(x))
- if err != nil {
- error_(err)
- }
+ state.b.WriteByte(uint8(x))
return
}
i := uint64Size
@@ -67,10 +101,7 @@ func (state *encoderState) encodeUint(x uint64) {
i--
}
state.buf[i] = uint8(i - uint64Size) // = loop count, negated
- _, err := state.b.Write(state.buf[i : uint64Size+1])
- if err != nil {
- error_(err)
- }
+ state.b.Write(state.buf[i : uint64Size+1])
}
// encodeInt writes an encoded signed integer to state.w.
@@ -87,14 +118,14 @@ func (state *encoderState) encodeInt(i int64) {
}
// encOp is the signature of an encoding operator for a given type.
-type encOp func(i *encInstr, state *encoderState, p unsafe.Pointer)
+type encOp func(i *encInstr, state *encoderState, v reflect.Value)
// The 'instructions' of the encoding machine
type encInstr struct {
- op encOp
- field int // field number
- indir int // how many pointer indirections to reach the value in the struct
- offset uintptr // offset in the structure of the field to encode
+ op encOp
+ field int // field number in input
+ index []int // struct index
+ indir int // how many pointer indirections to reach the value in the struct
}
// update emits a field number and updates the state to record its value for delta encoding.
@@ -115,20 +146,20 @@ func (state *encoderState) update(instr *encInstr) {
// encoded integer, followed by the field data in its appropriate
// format.
-// encIndirect dereferences p indir times and returns the result.
-func encIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
+// encIndirect dereferences pv indir times and returns the result.
+func encIndirect(pv reflect.Value, indir int) reflect.Value {
for ; indir > 0; indir-- {
- p = *(*unsafe.Pointer)(p)
- if p == nil {
- return unsafe.Pointer(nil)
+ if pv.IsNil() {
+ break
}
+ pv = pv.Elem()
}
- return p
+ return pv
}
-// encBool encodes the bool with address p as an unsigned 0 or 1.
-func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) {
- b := *(*bool)(p)
+// encBool encodes the bool referenced by v as an unsigned 0 or 1.
+func encBool(i *encInstr, state *encoderState, v reflect.Value) {
+ b := v.Bool()
if b || state.sendZero {
state.update(i)
if b {
@@ -139,102 +170,21 @@ func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) {
}
}
-// encInt encodes the int with address p.
-func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) {
- v := int64(*(*int)(p))
- if v != 0 || state.sendZero {
- state.update(i)
- state.encodeInt(v)
- }
-}
-
-// encUint encodes the uint with address p.
-func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) {
- v := uint64(*(*uint)(p))
- if v != 0 || state.sendZero {
+// encInt encodes the signed integer (int int8 int16 int32 int64) referenced by v.
+func encInt(i *encInstr, state *encoderState, v reflect.Value) {
+ value := v.Int()
+ if value != 0 || state.sendZero {
state.update(i)
- state.encodeUint(v)
+ state.encodeInt(value)
}
}
-// encInt8 encodes the int8 with address p.
-func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) {
- v := int64(*(*int8)(p))
- if v != 0 || state.sendZero {
+// encUint encodes the unsigned integer (uint uint8 uint16 uint32 uint64 uintptr) referenced by v.
+func encUint(i *encInstr, state *encoderState, v reflect.Value) {
+ value := v.Uint()
+ if value != 0 || state.sendZero {
state.update(i)
- state.encodeInt(v)
- }
-}
-
-// encUint8 encodes the uint8 with address p.
-func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) {
- v := uint64(*(*uint8)(p))
- if v != 0 || state.sendZero {
- state.update(i)
- state.encodeUint(v)
- }
-}
-
-// encInt16 encodes the int16 with address p.
-func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) {
- v := int64(*(*int16)(p))
- if v != 0 || state.sendZero {
- state.update(i)
- state.encodeInt(v)
- }
-}
-
-// encUint16 encodes the uint16 with address p.
-func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) {
- v := uint64(*(*uint16)(p))
- if v != 0 || state.sendZero {
- state.update(i)
- state.encodeUint(v)
- }
-}
-
-// encInt32 encodes the int32 with address p.
-func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) {
- v := int64(*(*int32)(p))
- if v != 0 || state.sendZero {
- state.update(i)
- state.encodeInt(v)
- }
-}
-
-// encUint encodes the uint32 with address p.
-func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) {
- v := uint64(*(*uint32)(p))
- if v != 0 || state.sendZero {
- state.update(i)
- state.encodeUint(v)
- }
-}
-
-// encInt64 encodes the int64 with address p.
-func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) {
- v := *(*int64)(p)
- if v != 0 || state.sendZero {
- state.update(i)
- state.encodeInt(v)
- }
-}
-
-// encInt64 encodes the uint64 with address p.
-func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) {
- v := *(*uint64)(p)
- if v != 0 || state.sendZero {
- state.update(i)
- state.encodeUint(v)
- }
-}
-
-// encUintptr encodes the uintptr with address p.
-func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) {
- v := uint64(*(*uintptr)(p))
- if v != 0 || state.sendZero {
- state.update(i)
- state.encodeUint(v)
+ state.encodeUint(value)
}
}
@@ -255,42 +205,20 @@ func floatBits(f float64) uint64 {
return v
}
-// encFloat32 encodes the float32 with address p.
-func encFloat32(i *encInstr, state *encoderState, p unsafe.Pointer) {
- f := *(*float32)(p)
+// encFloat encodes the floating point value (float32 float64) referenced by v.
+func encFloat(i *encInstr, state *encoderState, v reflect.Value) {
+ f := v.Float()
if f != 0 || state.sendZero {
- v := floatBits(float64(f))
+ bits := floatBits(f)
state.update(i)
- state.encodeUint(v)
+ state.encodeUint(bits)
}
}
-// encFloat64 encodes the float64 with address p.
-func encFloat64(i *encInstr, state *encoderState, p unsafe.Pointer) {
- f := *(*float64)(p)
- if f != 0 || state.sendZero {
- state.update(i)
- v := floatBits(f)
- state.encodeUint(v)
- }
-}
-
-// encComplex64 encodes the complex64 with address p.
+// encComplex encodes the complex value (complex64 complex128) referenced by v.
// Complex numbers are just a pair of floating-point numbers, real part first.
-func encComplex64(i *encInstr, state *encoderState, p unsafe.Pointer) {
- c := *(*complex64)(p)
- if c != 0+0i || state.sendZero {
- rpart := floatBits(float64(real(c)))
- ipart := floatBits(float64(imag(c)))
- state.update(i)
- state.encodeUint(rpart)
- state.encodeUint(ipart)
- }
-}
-
-// encComplex128 encodes the complex128 with address p.
-func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) {
- c := *(*complex128)(p)
+func encComplex(i *encInstr, state *encoderState, v reflect.Value) {
+ c := v.Complex()
if c != 0+0i || state.sendZero {
rpart := floatBits(real(c))
ipart := floatBits(imag(c))
@@ -300,10 +228,10 @@ func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) {
}
}
-// encUint8Array encodes the byte slice whose header has address p.
+// encUint8Array encodes the byte array referenced by v.
// Byte arrays are encoded as an unsigned count followed by the raw bytes.
-func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) {
- b := *(*[]byte)(p)
+func encUint8Array(i *encInstr, state *encoderState, v reflect.Value) {
+ b := v.Bytes()
if len(b) > 0 || state.sendZero {
state.update(i)
state.encodeUint(uint64(len(b)))
@@ -311,10 +239,10 @@ func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) {
}
}
-// encString encodes the string whose header has address p.
+// encString encodes the string referenced by v.
// Strings are encoded as an unsigned count followed by the raw bytes.
-func encString(i *encInstr, state *encoderState, p unsafe.Pointer) {
- s := *(*string)(p)
+func encString(i *encInstr, state *encoderState, v reflect.Value) {
+ s := v.String()
if len(s) > 0 || state.sendZero {
state.update(i)
state.encodeUint(uint64(len(s)))
@@ -324,7 +252,7 @@ func encString(i *encInstr, state *encoderState, p unsafe.Pointer) {
// encStructTerminator encodes the end of an encoded struct
// as delta field number of 0.
-func encStructTerminator(i *encInstr, state *encoderState, p unsafe.Pointer) {
+func encStructTerminator(i *encInstr, state *encoderState, v reflect.Value) {
state.encodeUint(0)
}
@@ -338,60 +266,83 @@ type encEngine struct {
const singletonField = 0
+// valid reports whether the value is valid and a non-nil pointer.
+// (Slices, maps, and chans take care of themselves.)
+func valid(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Invalid:
+ return false
+ case reflect.Ptr:
+ return !v.IsNil()
+ }
+ return true
+}
+
// encodeSingle encodes a single top-level non-struct value.
-func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) {
+func (enc *Encoder) encodeSingle(b *encBuffer, engine *encEngine, value reflect.Value) {
state := enc.newEncoderState(b)
+ defer enc.freeEncoderState(state)
state.fieldnum = singletonField
// There is no surrounding struct to frame the transmission, so we must
// generate data even if the item is zero. To do this, set sendZero.
state.sendZero = true
instr := &engine.instr[singletonField]
- p := basep // offset will be zero
if instr.indir > 0 {
- if p = encIndirect(p, instr.indir); p == nil {
- return
- }
+ value = encIndirect(value, instr.indir)
+ }
+ if valid(value) {
+ instr.op(instr, state, value)
}
- instr.op(instr, state, p)
- enc.freeEncoderState(state)
}
// encodeStruct encodes a single struct value.
-func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) {
+func (enc *Encoder) encodeStruct(b *encBuffer, engine *encEngine, value reflect.Value) {
+ if !valid(value) {
+ return
+ }
state := enc.newEncoderState(b)
+ defer enc.freeEncoderState(state)
state.fieldnum = -1
for i := 0; i < len(engine.instr); i++ {
instr := &engine.instr[i]
- p := unsafe.Pointer(uintptr(basep) + instr.offset)
+ if i >= value.NumField() {
+ // encStructTerminator
+ instr.op(instr, state, reflect.Value{})
+ break
+ }
+ field := value.FieldByIndex(instr.index)
if instr.indir > 0 {
- if p = encIndirect(p, instr.indir); p == nil {
+ field = encIndirect(field, instr.indir)
+ // TODO: Is field guaranteed valid? If so we could avoid this check.
+ if !valid(field) {
continue
}
}
- instr.op(instr, state, p)
+ instr.op(instr, state, field)
}
- enc.freeEncoderState(state)
}
-// encodeArray encodes the array whose 0th element is at p.
-func (enc *Encoder) encodeArray(b *bytes.Buffer, p unsafe.Pointer, op encOp, elemWid uintptr, elemIndir int, length int) {
+// encodeArray encodes an array.
+func (enc *Encoder) encodeArray(b *encBuffer, value reflect.Value, op encOp, elemIndir int, length int, helper encHelper) {
state := enc.newEncoderState(b)
+ defer enc.freeEncoderState(state)
state.fieldnum = -1
state.sendZero = true
state.encodeUint(uint64(length))
+ if helper != nil && helper(state, value) {
+ return
+ }
for i := 0; i < length; i++ {
- elemp := p
+ elem := value.Index(i)
if elemIndir > 0 {
- up := encIndirect(elemp, elemIndir)
- if up == nil {
+ elem = encIndirect(elem, elemIndir)
+ // TODO: Is elem guaranteed valid? If so we could avoid this check.
+ if !valid(elem) {
errorf("encodeArray: nil element")
}
- elemp = up
}
- op(nil, state, elemp)
- p = unsafe.Pointer(uintptr(p) + elemWid)
+ op(nil, state, elem)
}
- enc.freeEncoderState(state)
}
// encodeReflectValue is a helper for maps. It encodes the value v.
@@ -402,13 +353,11 @@ func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir in
if !v.IsValid() {
errorf("encodeReflectValue: nil element")
}
- op(nil, state, unsafeAddr(v))
+ op(nil, state, v)
}
// encodeMap encodes a map as unsigned count followed by key:value pairs.
-// Because map internals are not exposed, we must use reflection rather than
-// addresses.
-func (enc *Encoder) encodeMap(b *bytes.Buffer, mv reflect.Value, keyOp, elemOp encOp, keyIndir, elemIndir int) {
+func (enc *Encoder) encodeMap(b *encBuffer, mv reflect.Value, keyOp, elemOp encOp, keyIndir, elemIndir int) {
state := enc.newEncoderState(b)
state.fieldnum = -1
state.sendZero = true
@@ -426,7 +375,7 @@ func (enc *Encoder) encodeMap(b *bytes.Buffer, mv reflect.Value, keyOp, elemOp e
// by the type identifier (which might require defining that type right now), followed
// by the concrete value. A nil value gets sent as the empty string for the name,
// followed by no value.
-func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
+func (enc *Encoder) encodeInterface(b *encBuffer, iv reflect.Value) {
// Gobs can encode nil interface values but not typed interface
// values holding nil pointers, since nil pointers point to no value.
elem := iv.Elem()
@@ -450,10 +399,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
}
// Send the name.
state.encodeUint(uint64(len(name)))
- _, err := state.b.WriteString(name)
- if err != nil {
- error_(err)
- }
+ state.b.WriteString(name)
// Define the type id if necessary.
enc.sendTypeDescriptor(enc.writer(), state, ut)
// Send the type id.
@@ -461,7 +407,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, 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(bytes.Buffer)
+ data := new(encBuffer)
data.Write(spaceForLength)
enc.encode(data, elem, ut)
if enc.err != nil {
@@ -470,7 +416,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
enc.popWriter()
enc.writeMessage(b, data)
if enc.err != nil {
- error_(err)
+ error_(enc.err)
}
enc.freeEncoderState(state)
}
@@ -512,7 +458,7 @@ func isZero(val reflect.Value) bool {
// encGobEncoder encodes a value that implements the GobEncoder interface.
// The data is sent as a byte array.
-func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, ut *userTypeInfo, v reflect.Value) {
+func (enc *Encoder) encodeGobEncoder(b *encBuffer, ut *userTypeInfo, v reflect.Value) {
// TODO: should we catch panics from the called method?
var data []byte
@@ -539,30 +485,30 @@ func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, ut *userTypeInfo, v reflec
var encOpTable = [...]encOp{
reflect.Bool: encBool,
reflect.Int: encInt,
- reflect.Int8: encInt8,
- reflect.Int16: encInt16,
- reflect.Int32: encInt32,
- reflect.Int64: encInt64,
+ reflect.Int8: encInt,
+ reflect.Int16: encInt,
+ reflect.Int32: encInt,
+ reflect.Int64: encInt,
reflect.Uint: encUint,
- reflect.Uint8: encUint8,
- reflect.Uint16: encUint16,
- reflect.Uint32: encUint32,
- reflect.Uint64: encUint64,
- reflect.Uintptr: encUintptr,
- reflect.Float32: encFloat32,
- reflect.Float64: encFloat64,
- reflect.Complex64: encComplex64,
- reflect.Complex128: encComplex128,
+ reflect.Uint8: encUint,
+ reflect.Uint16: encUint,
+ reflect.Uint32: encUint,
+ reflect.Uint64: encUint,
+ reflect.Uintptr: encUint,
+ reflect.Float32: encFloat,
+ reflect.Float64: encFloat,
+ reflect.Complex64: encComplex,
+ reflect.Complex128: encComplex,
reflect.String: encString,
}
// encOpFor returns (a pointer to) the encoding op for the base type under rt and
// the indirection count to reach it.
-func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp) (*encOp, int) {
+func encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp, building map[*typeInfo]bool) (*encOp, int) {
ut := userType(rt)
// If the type implements GobEncoder, we handle it without further processing.
if ut.externalEnc != 0 {
- return enc.gobEncodeOpFor(ut)
+ return gobEncodeOpFor(ut)
}
// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
// Return the pointer to the op we're already building.
@@ -586,31 +532,27 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
break
}
// Slices have a header; we decode it to find the underlying array.
- elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress)
- op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
- slice := (*reflect.SliceHeader)(p)
- if !state.sendZero && slice.Len == 0 {
+ elemOp, elemIndir := encOpFor(t.Elem(), inProgress, building)
+ helper := encSliceHelper[t.Elem().Kind()]
+ op = func(i *encInstr, state *encoderState, slice reflect.Value) {
+ if !state.sendZero && slice.Len() == 0 {
return
}
state.update(i)
- state.enc.encodeArray(state.b, unsafe.Pointer(slice.Data), *elemOp, t.Elem().Size(), elemIndir, int(slice.Len))
+ state.enc.encodeArray(state.b, slice, *elemOp, elemIndir, slice.Len(), helper)
}
case reflect.Array:
// True arrays have size in the type.
- elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress)
- op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+ elemOp, elemIndir := encOpFor(t.Elem(), inProgress, building)
+ helper := encArrayHelper[t.Elem().Kind()]
+ op = func(i *encInstr, state *encoderState, array reflect.Value) {
state.update(i)
- state.enc.encodeArray(state.b, p, *elemOp, t.Elem().Size(), elemIndir, t.Len())
+ state.enc.encodeArray(state.b, array, *elemOp, elemIndir, array.Len(), helper)
}
case reflect.Map:
- keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress)
- elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress)
- op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
- // Maps cannot be accessed by moving addresses around the way
- // that slices etc. can. We must recover a full reflection value for
- // the iteration.
- v := reflect.NewAt(t, unsafe.Pointer(p)).Elem()
- mv := reflect.Indirect(v)
+ keyOp, keyIndir := encOpFor(t.Key(), inProgress, building)
+ elemOp, elemIndir := encOpFor(t.Elem(), inProgress, building)
+ op = func(i *encInstr, state *encoderState, mv reflect.Value) {
// We send zero-length (but non-nil) maps because the
// receiver might want to use the map. (Maps don't use append.)
if !state.sendZero && mv.IsNil() {
@@ -621,19 +563,16 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
}
case reflect.Struct:
// Generate a closure that calls out to the engine for the nested type.
- enc.getEncEngine(userType(typ))
+ getEncEngine(userType(typ), building)
info := mustGetTypeInfo(typ)
- op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+ op = func(i *encInstr, state *encoderState, sv reflect.Value) {
state.update(i)
// indirect through info to delay evaluation for recursive structs
- state.enc.encodeStruct(state.b, info.encoder, p)
+ enc := info.encoder.Load().(*encEngine)
+ state.enc.encodeStruct(state.b, enc, sv)
}
case reflect.Interface:
- op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
- // Interfaces transmit the name and contents of the concrete
- // value they contain.
- v := reflect.NewAt(t, unsafe.Pointer(p)).Elem()
- iv := reflect.Indirect(v)
+ op = func(i *encInstr, state *encoderState, iv reflect.Value) {
if !state.sendZero && (!iv.IsValid() || iv.IsNil()) {
return
}
@@ -648,9 +587,8 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
return &op, indir
}
-// gobEncodeOpFor returns the op for a type that is known to implement
-// GobEncoder.
-func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
+// gobEncodeOpFor returns the op for a type that is known to implement GobEncoder.
+func gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
rt := ut.user
if ut.encIndir == -1 {
rt = reflect.PtrTo(rt)
@@ -660,13 +598,13 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
}
}
var op encOp
- op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
- var v reflect.Value
+ op = func(i *encInstr, state *encoderState, v reflect.Value) {
if ut.encIndir == -1 {
// Need to climb up one level to turn value into pointer.
- v = reflect.NewAt(rt, unsafe.Pointer(&p)).Elem()
- } else {
- v = reflect.NewAt(rt, p).Elem()
+ if !v.CanAddr() {
+ errorf("unaddressable value of type %s", rt)
+ }
+ v = v.Addr()
}
if !state.sendZero && isZero(v) {
return
@@ -678,7 +616,7 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
}
// compileEnc returns the engine to compile the type.
-func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
+func compileEnc(ut *userTypeInfo, building map[*typeInfo]bool) *encEngine {
srt := ut.base
engine := new(encEngine)
seen := make(map[reflect.Type]*encOp)
@@ -692,59 +630,57 @@ func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
if !isSent(&f) {
continue
}
- op, indir := enc.encOpFor(f.Type, seen)
- engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, indir, uintptr(f.Offset)})
+ op, indir := encOpFor(f.Type, seen, building)
+ engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, f.Index, indir})
wireFieldNum++
}
if srt.NumField() > 0 && len(engine.instr) == 0 {
errorf("type %s has no exported fields", rt)
}
- engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, 0, 0})
+ engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, nil, 0})
} else {
engine.instr = make([]encInstr, 1)
- op, indir := enc.encOpFor(rt, seen)
- engine.instr[0] = encInstr{*op, singletonField, indir, 0} // offset is zero
+ op, indir := encOpFor(rt, seen, building)
+ engine.instr[0] = encInstr{*op, singletonField, nil, indir}
}
return engine
}
// getEncEngine returns the engine to compile the type.
-// typeLock must be held (or we're in initialization and guaranteed single-threaded).
-func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine {
- info, err1 := getTypeInfo(ut)
- if err1 != nil {
- error_(err1)
- }
- if info.encoder == nil {
- // Assign the encEngine now, so recursive types work correctly. But...
- info.encoder = new(encEngine)
- // ... if we fail to complete building the engine, don't cache the half-built machine.
- // Doing this here means we won't cache a type that is itself OK but
- // that contains a nested type that won't compile. The result is consistent
- // error behavior when Encode is called multiple times on the top-level type.
- ok := false
- defer func() {
- if !ok {
- info.encoder = nil
- }
- }()
- info.encoder = enc.compileEnc(ut)
- ok = true
+func getEncEngine(ut *userTypeInfo, building map[*typeInfo]bool) *encEngine {
+ info, err := getTypeInfo(ut)
+ if err != nil {
+ error_(err)
}
- return info.encoder
+ enc, ok := info.encoder.Load().(*encEngine)
+ if !ok {
+ enc = buildEncEngine(info, ut, building)
+ }
+ return enc
}
-// lockAndGetEncEngine is a function that locks and compiles.
-// This lets us hold the lock only while compiling, not when encoding.
-func (enc *Encoder) lockAndGetEncEngine(ut *userTypeInfo) *encEngine {
- typeLock.Lock()
- defer typeLock.Unlock()
- return enc.getEncEngine(ut)
+func buildEncEngine(info *typeInfo, ut *userTypeInfo, building map[*typeInfo]bool) *encEngine {
+ // Check for recursive types.
+ if building != nil && building[info] {
+ return nil
+ }
+ info.encInit.Lock()
+ defer info.encInit.Unlock()
+ enc, ok := info.encoder.Load().(*encEngine)
+ if !ok {
+ if building == nil {
+ building = make(map[*typeInfo]bool)
+ }
+ building[info] = true
+ enc = compileEnc(ut, building)
+ info.encoder.Store(enc)
+ }
+ return enc
}
-func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInfo) {
+func (enc *Encoder) encode(b *encBuffer, value reflect.Value, ut *userTypeInfo) {
defer catchError(&enc.err)
- engine := enc.lockAndGetEncEngine(ut)
+ engine := getEncEngine(ut, nil)
indir := ut.indir
if ut.externalEnc != 0 {
indir = int(ut.encIndir)
@@ -753,8 +689,8 @@ func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInf
value = reflect.Indirect(value)
}
if ut.externalEnc == 0 && value.Type().Kind() == reflect.Struct {
- enc.encodeStruct(b, engine, unsafeAddr(value))
+ enc.encodeStruct(b, engine, value)
} else {
- enc.encodeSingle(b, engine, unsafeAddr(value))
+ enc.encodeSingle(b, engine, value)
}
}
diff --git a/src/pkg/encoding/gob/encoder.go b/src/encoding/gob/encoder.go
index a3301c3bd..a340e47b5 100644
--- a/src/pkg/encoding/gob/encoder.go
+++ b/src/encoding/gob/encoder.go
@@ -5,7 +5,6 @@
package gob
import (
- "bytes"
"io"
"reflect"
"sync"
@@ -19,7 +18,7 @@ type Encoder struct {
sent map[reflect.Type]typeId // which types we've already sent
countState *encoderState // stage for writing counts
freeList *encoderState // list of free encoderStates; avoids reallocation
- byteBuf bytes.Buffer // buffer for top-level encoderState
+ byteBuf encBuffer // buffer for top-level encoderState
err error
}
@@ -34,7 +33,7 @@ func NewEncoder(w io.Writer) *Encoder {
enc := new(Encoder)
enc.w = []io.Writer{w}
enc.sent = make(map[reflect.Type]typeId)
- enc.countState = enc.newEncoderState(new(bytes.Buffer))
+ enc.countState = enc.newEncoderState(new(encBuffer))
return enc
}
@@ -60,7 +59,7 @@ func (enc *Encoder) setError(err error) {
}
// writeMessage sends the data item preceded by a unsigned count of its length.
-func (enc *Encoder) writeMessage(w io.Writer, b *bytes.Buffer) {
+func (enc *Encoder) writeMessage(w io.Writer, b *encBuffer) {
// Space has been reserved for the length at the head of the message.
// This is a little dirty: we grab the slice from the bytes.Buffer and massage
// it by hand.
@@ -88,9 +87,7 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp
if _, alreadySent := enc.sent[actual]; alreadySent {
return false
}
- typeLock.Lock()
info, err := getTypeInfo(ut)
- typeLock.Unlock()
if err != nil {
enc.setError(err)
return
@@ -191,9 +188,7 @@ func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *use
// a singleton basic type (int, []byte etc.) at top level. We don't
// need to send the type info but we do need to update enc.sent.
if !sent {
- typeLock.Lock()
info, err := getTypeInfo(ut)
- typeLock.Unlock()
if err != nil {
enc.setError(err)
return
diff --git a/src/pkg/encoding/gob/encoder_test.go b/src/encoding/gob/encoder_test.go
index 6445ce100..0ea4c0ec8 100644
--- a/src/pkg/encoding/gob/encoder_test.go
+++ b/src/encoding/gob/encoder_test.go
@@ -13,6 +13,52 @@ import (
"testing"
)
+// Test basic operations in a safe manner.
+func TestBasicEncoderDecoder(t *testing.T) {
+ var values = []interface{}{
+ true,
+ int(123),
+ int8(123),
+ int16(-12345),
+ int32(123456),
+ int64(-1234567),
+ uint(123),
+ uint8(123),
+ uint16(12345),
+ uint32(123456),
+ uint64(1234567),
+ uintptr(12345678),
+ float32(1.2345),
+ float64(1.2345678),
+ complex64(1.2345 + 2.3456i),
+ complex128(1.2345678 + 2.3456789i),
+ []byte("hello"),
+ string("hello"),
+ }
+ for _, value := range values {
+ b := new(bytes.Buffer)
+ enc := NewEncoder(b)
+ err := enc.Encode(value)
+ if err != nil {
+ t.Error("encoder fail:", err)
+ }
+ dec := NewDecoder(b)
+ result := reflect.New(reflect.TypeOf(value))
+ err = dec.Decode(result.Interface())
+ if err != nil {
+ t.Fatalf("error decoding %T: %v:", reflect.TypeOf(value), err)
+ }
+ if !reflect.DeepEqual(value, result.Elem().Interface()) {
+ t.Fatalf("%T: expected %v got %v", value, value, result.Elem().Interface())
+ }
+ }
+}
+
+type ET0 struct {
+ A int
+ B string
+}
+
type ET2 struct {
X string
}
@@ -40,14 +86,40 @@ type ET4 struct {
func TestEncoderDecoder(t *testing.T) {
b := new(bytes.Buffer)
enc := NewEncoder(b)
+ et0 := new(ET0)
+ et0.A = 7
+ et0.B = "gobs of fun"
+ err := enc.Encode(et0)
+ if err != nil {
+ t.Error("encoder fail:", err)
+ }
+ //fmt.Printf("% x %q\n", b, b)
+ //Debug(b)
+ dec := NewDecoder(b)
+ newEt0 := new(ET0)
+ err = dec.Decode(newEt0)
+ if err != nil {
+ t.Fatal("error decoding ET0:", err)
+ }
+
+ if !reflect.DeepEqual(et0, newEt0) {
+ t.Fatalf("invalid data for et0: expected %+v; got %+v", *et0, *newEt0)
+ }
+ if b.Len() != 0 {
+ t.Error("not at eof;", b.Len(), "bytes left")
+ }
+ // t.FailNow()
+
+ b = new(bytes.Buffer)
+ enc = NewEncoder(b)
et1 := new(ET1)
et1.A = 7
et1.Et2 = new(ET2)
- err := enc.Encode(et1)
+ err = enc.Encode(et1)
if err != nil {
t.Error("encoder fail:", err)
}
- dec := NewDecoder(b)
+ dec = NewDecoder(b)
newEt1 := new(ET1)
err = dec.Decode(newEt1)
if err != nil {
@@ -860,3 +932,25 @@ func Test29ElementSlice(t *testing.T) {
return
}
}
+
+// Don't crash, just give error when allocating a huge slice.
+// Issue 8084.
+func TestErrorForHugeSlice(t *testing.T) {
+ // Encode an int slice.
+ buf := new(bytes.Buffer)
+ slice := []int{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
+ err := NewEncoder(buf).Encode(slice)
+ if err != nil {
+ t.Fatal("encode:", err)
+ }
+ // Reach into the buffer and smash the count to make the encoded slice very long.
+ buf.Bytes()[buf.Len()-len(slice)-1] = 0xfa
+ // Decode and see error.
+ err = NewDecoder(buf).Decode(&slice)
+ if err == nil {
+ t.Fatal("decode: no error")
+ }
+ if !strings.Contains(err.Error(), "slice too big") {
+ t.Fatal("decode: expected slice too big error, got %s", err.Error())
+ }
+}
diff --git a/src/pkg/encoding/gob/error.go b/src/encoding/gob/error.go
index 92cc0c615..92cc0c615 100644
--- a/src/pkg/encoding/gob/error.go
+++ b/src/encoding/gob/error.go
diff --git a/src/pkg/encoding/gob/example_encdec_test.go b/src/encoding/gob/example_encdec_test.go
index e45ad4ccf..e45ad4ccf 100644
--- a/src/pkg/encoding/gob/example_encdec_test.go
+++ b/src/encoding/gob/example_encdec_test.go
diff --git a/src/pkg/encoding/gob/example_interface_test.go b/src/encoding/gob/example_interface_test.go
index 4681e6307..4681e6307 100644
--- a/src/pkg/encoding/gob/example_interface_test.go
+++ b/src/encoding/gob/example_interface_test.go
diff --git a/src/pkg/encoding/gob/example_test.go b/src/encoding/gob/example_test.go
index 020352cee..020352cee 100644
--- a/src/pkg/encoding/gob/example_test.go
+++ b/src/encoding/gob/example_test.go
diff --git a/src/pkg/encoding/gob/gobencdec_test.go b/src/encoding/gob/gobencdec_test.go
index 157b7723a..eb76b481d 100644
--- a/src/pkg/encoding/gob/gobencdec_test.go
+++ b/src/encoding/gob/gobencdec_test.go
@@ -279,7 +279,7 @@ func TestGobEncoderValueField(t *testing.T) {
b := new(bytes.Buffer)
// First a field that's a structure.
enc := NewEncoder(b)
- err := enc.Encode(GobTestValueEncDec{17, StringStruct{"HIJKL"}})
+ err := enc.Encode(&GobTestValueEncDec{17, StringStruct{"HIJKL"}})
if err != nil {
t.Fatal("encode error:", err)
}
@@ -326,7 +326,7 @@ func TestGobEncoderArrayField(t *testing.T) {
for i := range a.A.a {
a.A.a[i] = byte(i)
}
- err := enc.Encode(a)
+ err := enc.Encode(&a)
if err != nil {
t.Fatal("encode error:", err)
}
@@ -589,7 +589,8 @@ func TestGobEncoderStructSingleton(t *testing.T) {
func TestGobEncoderNonStructSingleton(t *testing.T) {
b := new(bytes.Buffer)
enc := NewEncoder(b)
- err := enc.Encode(Gobber(1234))
+ var g Gobber = 1234
+ err := enc.Encode(&g)
if err != nil {
t.Fatal("encode error:", err)
}
diff --git a/src/encoding/gob/timing_test.go b/src/encoding/gob/timing_test.go
new file mode 100644
index 000000000..940e5ad41
--- /dev/null
+++ b/src/encoding/gob/timing_test.go
@@ -0,0 +1,325 @@
+// 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 gob
+
+import (
+ "bytes"
+ "io"
+ "os"
+ "runtime"
+ "testing"
+)
+
+type Bench struct {
+ A int
+ B float64
+ C string
+ D []byte
+}
+
+func benchmarkEndToEnd(b *testing.B, ctor func() interface{}, pipe func() (r io.Reader, w io.Writer, err error)) {
+ b.RunParallel(func(pb *testing.PB) {
+ r, w, err := pipe()
+ if err != nil {
+ b.Fatal("can't get pipe:", err)
+ }
+ v := ctor()
+ enc := NewEncoder(w)
+ dec := NewDecoder(r)
+ for pb.Next() {
+ if err := enc.Encode(v); err != nil {
+ b.Fatal("encode error:", err)
+ }
+ if err := dec.Decode(v); err != nil {
+ b.Fatal("decode error:", err)
+ }
+ }
+ })
+}
+
+func BenchmarkEndToEndPipe(b *testing.B) {
+ benchmarkEndToEnd(b, func() interface{} {
+ return &Bench{7, 3.2, "now is the time", bytes.Repeat([]byte("for all good men"), 100)}
+ }, func() (r io.Reader, w io.Writer, err error) {
+ r, w, err = os.Pipe()
+ return
+ })
+}
+
+func BenchmarkEndToEndByteBuffer(b *testing.B) {
+ benchmarkEndToEnd(b, func() interface{} {
+ return &Bench{7, 3.2, "now is the time", bytes.Repeat([]byte("for all good men"), 100)}
+ }, func() (r io.Reader, w io.Writer, err error) {
+ var buf bytes.Buffer
+ return &buf, &buf, nil
+ })
+}
+
+func BenchmarkEndToEndSliceByteBuffer(b *testing.B) {
+ benchmarkEndToEnd(b, func() interface{} {
+ v := &Bench{7, 3.2, "now is the time", nil}
+ Register(v)
+ arr := make([]interface{}, 100)
+ for i := range arr {
+ arr[i] = v
+ }
+ return &arr
+ }, func() (r io.Reader, w io.Writer, err error) {
+ var buf bytes.Buffer
+ return &buf, &buf, nil
+ })
+}
+
+func TestCountEncodeMallocs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
+
+ const N = 1000
+
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
+
+ allocs := testing.AllocsPerRun(N, func() {
+ err := enc.Encode(bench)
+ if err != nil {
+ t.Fatal("encode:", err)
+ }
+ })
+ if allocs != 0 {
+ t.Fatalf("mallocs per encode of type Bench: %v; wanted 0\n", allocs)
+ }
+}
+
+func TestCountDecodeMallocs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
+
+ const N = 1000
+
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
+
+ // Fill the buffer with enough to decode
+ testing.AllocsPerRun(N, func() {
+ err := enc.Encode(bench)
+ if err != nil {
+ t.Fatal("encode:", err)
+ }
+ })
+
+ dec := NewDecoder(&buf)
+ allocs := testing.AllocsPerRun(N, func() {
+ *bench = Bench{}
+ err := dec.Decode(&bench)
+ if err != nil {
+ t.Fatal("decode:", err)
+ }
+ })
+ if allocs != 4 {
+ t.Fatalf("mallocs per decode of type Bench: %v; wanted 4\n", allocs)
+ }
+}
+
+func BenchmarkEncodeComplex128Slice(b *testing.B) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ a := make([]complex128, 1000)
+ for i := range a {
+ a[i] = 1.2 + 3.4i
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ err := enc.Encode(a)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func BenchmarkEncodeFloat64Slice(b *testing.B) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ a := make([]float64, 1000)
+ for i := range a {
+ a[i] = 1.23e4
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ err := enc.Encode(a)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func BenchmarkEncodeInt32Slice(b *testing.B) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ a := make([]int32, 1000)
+ for i := range a {
+ a[i] = 1234
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ err := enc.Encode(a)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func BenchmarkEncodeStringSlice(b *testing.B) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ a := make([]string, 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
+ data []byte
+}
+
+func (b *benchmarkBuf) Read(p []byte) (n int, err error) {
+ n = copy(p, b.data[b.offset:])
+ if n == 0 {
+ return 0, io.EOF
+ }
+ b.offset += n
+ return
+}
+
+func (b *benchmarkBuf) ReadByte() (c byte, err error) {
+ if b.offset >= len(b.data) {
+ return 0, io.EOF
+ }
+ c = b.data[b.offset]
+ b.offset++
+ return
+}
+
+func (b *benchmarkBuf) reset() {
+ b.offset = 0
+}
+
+func BenchmarkDecodeComplex128Slice(b *testing.B) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ a := make([]complex128, 1000)
+ for i := range a {
+ a[i] = 1.2 + 3.4i
+ }
+ err := enc.Encode(a)
+ if err != nil {
+ b.Fatal(err)
+ }
+ x := make([]complex128, 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)
+ }
+ }
+}
+
+func BenchmarkDecodeFloat64Slice(b *testing.B) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ a := make([]float64, 1000)
+ for i := range a {
+ a[i] = 1.23e4
+ }
+ err := enc.Encode(a)
+ if err != nil {
+ b.Fatal(err)
+ }
+ x := make([]float64, 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)
+ }
+ }
+}
+
+func BenchmarkDecodeInt32Slice(b *testing.B) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ a := make([]int32, 1000)
+ for i := range a {
+ a[i] = 1234
+ }
+ err := enc.Encode(a)
+ if err != nil {
+ b.Fatal(err)
+ }
+ x := make([]int32, 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)
+ }
+ }
+}
+
+func BenchmarkDecodeStringSlice(b *testing.B) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ a := make([]string, 1000)
+ for i := range a {
+ a[i] = "now is the time"
+ }
+ err := enc.Encode(a)
+ if err != nil {
+ b.Fatal(err)
+ }
+ x := make([]string, 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/pkg/encoding/gob/type.go b/src/encoding/gob/type.go
index cad145279..a49b71a86 100644
--- a/src/pkg/encoding/gob/type.go
+++ b/src/encoding/gob/type.go
@@ -11,6 +11,7 @@ import (
"os"
"reflect"
"sync"
+ "sync/atomic"
"unicode"
"unicode/utf8"
)
@@ -681,29 +682,51 @@ func (w *wireType) string() string {
type typeInfo struct {
id typeId
- encoder *encEngine
+ encInit sync.Mutex // protects creation of encoder
+ encoder atomic.Value // *encEngine
wire *wireType
}
-var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock
+// typeInfoMap is an atomic pointer to map[reflect.Type]*typeInfo.
+// It's updated copy-on-write. Readers just do an atomic load
+// to get the current version of the map. Writers make a full copy of
+// the map and atomically update the pointer to point to the new map.
+// Under heavy read contention, this is significantly faster than a map
+// protected by a mutex.
+var typeInfoMap atomic.Value
+
+func lookupTypeInfo(rt reflect.Type) *typeInfo {
+ m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo)
+ return m[rt]
+}
-// typeLock must be held.
func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) {
rt := ut.base
if ut.externalEnc != 0 {
// We want the user type, not the base type.
rt = ut.user
}
- info, ok := typeInfoMap[rt]
- if ok {
+ if info := lookupTypeInfo(rt); info != nil {
return info, nil
}
- info = new(typeInfo)
+ return buildTypeInfo(ut, rt)
+}
+
+// buildTypeInfo constructs the type information for the type
+// and stores it in the type info map.
+func buildTypeInfo(ut *userTypeInfo, rt reflect.Type) (*typeInfo, error) {
+ typeLock.Lock()
+ defer typeLock.Unlock()
+
+ if info := lookupTypeInfo(rt); info != nil {
+ return info, nil
+ }
+
gt, err := getBaseType(rt.Name(), rt)
if err != nil {
return nil, err
}
- info.id = gt.id()
+ info := &typeInfo{id: gt.id()}
if ut.externalEnc != 0 {
userType, err := getType(rt.Name(), ut, rt)
@@ -719,25 +742,32 @@ func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) {
case xText:
info.wire = &wireType{TextMarshalerT: gt}
}
- typeInfoMap[ut.user] = info
- return info, nil
+ rt = ut.user
+ } else {
+ t := info.id.gobType()
+ switch typ := rt; typ.Kind() {
+ case reflect.Array:
+ info.wire = &wireType{ArrayT: t.(*arrayType)}
+ case reflect.Map:
+ info.wire = &wireType{MapT: t.(*mapType)}
+ case reflect.Slice:
+ // []byte == []uint8 is a special case handled separately
+ if typ.Elem().Kind() != reflect.Uint8 {
+ info.wire = &wireType{SliceT: t.(*sliceType)}
+ }
+ case reflect.Struct:
+ info.wire = &wireType{StructT: t.(*structType)}
+ }
}
- t := info.id.gobType()
- switch typ := rt; typ.Kind() {
- case reflect.Array:
- info.wire = &wireType{ArrayT: t.(*arrayType)}
- case reflect.Map:
- info.wire = &wireType{MapT: t.(*mapType)}
- case reflect.Slice:
- // []byte == []uint8 is a special case handled separately
- if typ.Elem().Kind() != reflect.Uint8 {
- info.wire = &wireType{SliceT: t.(*sliceType)}
- }
- case reflect.Struct:
- info.wire = &wireType{StructT: t.(*structType)}
+ // Create new map with old contents plus new entry.
+ newm := make(map[reflect.Type]*typeInfo)
+ m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo)
+ for k, v := range m {
+ newm[k] = v
}
- typeInfoMap[rt] = info
+ newm[rt] = info
+ typeInfoMap.Store(newm)
return info, nil
}
diff --git a/src/pkg/encoding/gob/type_test.go b/src/encoding/gob/type_test.go
index e230d22d4..e230d22d4 100644
--- a/src/pkg/encoding/gob/type_test.go
+++ b/src/encoding/gob/type_test.go
diff --git a/src/pkg/encoding/hex/hex.go b/src/encoding/hex/hex.go
index d1fc7024a..d1fc7024a 100644
--- a/src/pkg/encoding/hex/hex.go
+++ b/src/encoding/hex/hex.go
diff --git a/src/pkg/encoding/hex/hex_test.go b/src/encoding/hex/hex_test.go
index b969636cd..b969636cd 100644
--- a/src/pkg/encoding/hex/hex_test.go
+++ b/src/encoding/hex/hex_test.go
diff --git a/src/pkg/encoding/json/bench_test.go b/src/encoding/json/bench_test.go
index 29dbc26d4..29dbc26d4 100644
--- a/src/pkg/encoding/json/bench_test.go
+++ b/src/encoding/json/bench_test.go
diff --git a/src/pkg/encoding/json/decode.go b/src/encoding/json/decode.go
index af1c908ad..705bc2e17 100644
--- a/src/pkg/encoding/json/decode.go
+++ b/src/encoding/json/decode.go
@@ -173,7 +173,6 @@ type decodeState struct {
scan scanner
nextscan scanner // for calls to nextValue
savedError error
- tempstr string // scratch space to avoid some allocations
useNumber bool
}
@@ -293,6 +292,32 @@ func (d *decodeState) value(v reflect.Value) {
}
}
+type unquotedValue struct{}
+
+// valueQuoted is like value but decodes a
+// quoted string literal or literal null into an interface value.
+// If it finds anything other than a quoted string literal or null,
+// valueQuoted returns unquotedValue{}.
+func (d *decodeState) valueQuoted() interface{} {
+ switch op := d.scanWhile(scanSkipSpace); op {
+ default:
+ d.error(errPhase)
+
+ case scanBeginArray:
+ d.array(reflect.Value{})
+
+ case scanBeginObject:
+ d.object(reflect.Value{})
+
+ case scanBeginLiteral:
+ switch v := d.literalInterface().(type) {
+ case nil, string:
+ return v
+ }
+ }
+ return unquotedValue{}
+}
+
// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
// if it encounters an Unmarshaler, indirect stops and returns that.
@@ -444,8 +469,10 @@ func (d *decodeState) array(v reflect.Value) {
}
}
+var nullLiteral = []byte("null")
+
// object consumes an object from d.data[d.off-1:], decoding into the value v.
-// the first byte of the object ('{') has been read already.
+// the first byte ('{') of the object has been read already.
func (d *decodeState) object(v reflect.Value) {
// Check for unmarshaler.
u, ut, pv := d.indirect(v, false)
@@ -478,7 +505,9 @@ func (d *decodeState) object(v reflect.Value) {
t := v.Type()
if t.Key().Kind() != reflect.String {
d.saveError(&UnmarshalTypeError{"object", v.Type()})
- break
+ d.off--
+ d.next() // skip over { } in input
+ return
}
if v.IsNil() {
v.Set(reflect.MakeMap(t))
@@ -564,9 +593,14 @@ func (d *decodeState) object(v reflect.Value) {
// Read value.
if destring {
- d.value(reflect.ValueOf(&d.tempstr))
- d.literalStore([]byte(d.tempstr), subv, true)
- d.tempstr = "" // Zero scratch space for successive values.
+ switch qv := d.valueQuoted().(type) {
+ case nil:
+ d.literalStore(nullLiteral, subv, false)
+ case string:
+ d.literalStore([]byte(qv), subv, true)
+ default:
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", item, v.Type()))
+ }
} else {
d.value(subv)
}
diff --git a/src/pkg/encoding/json/decode_test.go b/src/encoding/json/decode_test.go
index 238a87fd6..7235969b9 100644
--- a/src/pkg/encoding/json/decode_test.go
+++ b/src/encoding/json/decode_test.go
@@ -406,6 +406,13 @@ var unmarshalTests = []unmarshalTest{
ptr: new(string),
out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld",
},
+
+ // issue 8305
+ {
+ in: `{"2009-11-10T23:00:00Z": "hello world"}`,
+ ptr: &map[time.Time]string{},
+ err: &UnmarshalTypeError{"object", reflect.TypeOf(map[time.Time]string{})},
+ },
}
func TestMarshal(t *testing.T) {
@@ -514,6 +521,7 @@ func TestUnmarshal(t *testing.T) {
if tt.ptr == nil {
continue
}
+
// v = new(right-type)
v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
dec := NewDecoder(bytes.NewReader(in))
@@ -521,7 +529,9 @@ func TestUnmarshal(t *testing.T) {
dec.UseNumber()
}
if err := dec.Decode(v.Interface()); !reflect.DeepEqual(err, tt.err) {
- t.Errorf("#%d: %v want %v", i, err, tt.err)
+ t.Errorf("#%d: %v, want %v", i, err, tt.err)
+ continue
+ } else if err != nil {
continue
}
if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
@@ -1060,18 +1070,25 @@ func TestEmptyString(t *testing.T) {
}
}
-// Test that the returned error is non-nil when trying to unmarshal null string into int, for successive ,string option
-// Issue 7046
+// Test that a null for ,string is not replaced with the previous quoted string (issue 7046).
+// It should also not be an error (issue 2540, issue 8587).
func TestNullString(t *testing.T) {
type T struct {
- A int `json:",string"`
- B int `json:",string"`
+ A int `json:",string"`
+ B int `json:",string"`
+ C *int `json:",string"`
}
- data := []byte(`{"A": "1", "B": null}`)
+ data := []byte(`{"A": "1", "B": null, "C": null}`)
var s T
+ s.B = 1
+ s.C = new(int)
+ *s.C = 2
err := Unmarshal(data, &s)
- if err == nil {
- t.Fatalf("expected error; got %v", s)
+ if err != nil {
+ t.Fatalf("Unmarshal: %v")
+ }
+ if s.B != 1 || s.C != nil {
+ t.Fatalf("after Unmarshal, s.B=%d, s.C=%p, want 1, nil", s.B, s.C)
}
}
diff --git a/src/pkg/encoding/json/encode.go b/src/encoding/json/encode.go
index 741ddd89c..fca2a0980 100644
--- a/src/pkg/encoding/json/encode.go
+++ b/src/encoding/json/encode.go
@@ -40,8 +40,8 @@ import (
//
// Floating point, integer, and Number values encode as JSON numbers.
//
-// String values encode as JSON strings. InvalidUTF8Error will be returned
-// if an invalid UTF-8 sequence is encountered.
+// String values encode as JSON strings coerced to valid UTF-8,
+// replacing invalid bytes with the Unicode replacement rune.
// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
// to keep some browsers from misinterpreting JSON output as HTML.
// Ampersand "&" is also escaped to "\u0026" for the same reason.
@@ -93,6 +93,8 @@ import (
// as described in the next paragraph.
// An anonymous struct field with a name given in its JSON tag is treated as
// having that name, rather than being anonymous.
+// An anonymous struct field of interface type is treated the same as having
+// that type as its name, rather than being anonymous.
//
// The Go visibility rules for struct fields are amended for JSON when
// deciding which field to marshal or unmarshal. If there are
@@ -696,12 +698,12 @@ type ptrEncoder struct {
elemEnc encoderFunc
}
-func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
if v.IsNil() {
e.WriteString("null")
return
}
- pe.elemEnc(e, v.Elem(), false)
+ pe.elemEnc(e, v.Elem(), quoted)
}
func newPtrEncoder(t reflect.Type) encoderFunc {
@@ -803,6 +805,9 @@ func (e *encodeState) string(s string) (int, error) {
case '\r':
e.WriteByte('\\')
e.WriteByte('r')
+ case '\t':
+ e.WriteByte('\\')
+ e.WriteByte('t')
default:
// This encodes bytes < 0x20 except for \n and \r,
// as well as <, > and &. The latter are escaped because they
@@ -876,9 +881,12 @@ func (e *encodeState) stringBytes(s []byte) (int, error) {
case '\r':
e.WriteByte('\\')
e.WriteByte('r')
+ case '\t':
+ e.WriteByte('\\')
+ e.WriteByte('t')
default:
// This encodes bytes < 0x20 except for \n and \r,
- // as well as < and >. The latter are escaped because they
+ // as well as <, >, and &. The latter are escaped because they
// can lead to security holes when user-controlled strings
// are rendered into JSON and served to some browsers.
e.WriteString(`\u00`)
diff --git a/src/pkg/encoding/json/encode_test.go b/src/encoding/json/encode_test.go
index 2e89a78eb..7abfa85db 100644
--- a/src/pkg/encoding/json/encode_test.go
+++ b/src/encoding/json/encode_test.go
@@ -452,3 +452,81 @@ func TestHTMLEscape(t *testing.T) {
t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes())
}
}
+
+// golang.org/issue/8582
+func TestEncodePointerString(t *testing.T) {
+ type stringPointer struct {
+ N *int64 `json:"n,string"`
+ }
+ var n int64 = 42
+ b, err := Marshal(stringPointer{N: &n})
+ if err != nil {
+ t.Fatalf("Marshal: %v", err)
+ }
+ if got, want := string(b), `{"n":"42"}`; got != want {
+ t.Errorf("Marshal = %s, want %s", got, want)
+ }
+ var back stringPointer
+ err = Unmarshal(b, &back)
+ if err != nil {
+ t.Fatalf("Unmarshal: %v", err)
+ }
+ if back.N == nil {
+ t.Fatalf("Unmarshalled nil N field")
+ }
+ if *back.N != 42 {
+ t.Fatalf("*N = %d; want 42", *back.N)
+ }
+}
+
+var encodeStringTests = []struct {
+ in string
+ out string
+}{
+ {"\x00", `"\u0000"`},
+ {"\x01", `"\u0001"`},
+ {"\x02", `"\u0002"`},
+ {"\x03", `"\u0003"`},
+ {"\x04", `"\u0004"`},
+ {"\x05", `"\u0005"`},
+ {"\x06", `"\u0006"`},
+ {"\x07", `"\u0007"`},
+ {"\x08", `"\u0008"`},
+ {"\x09", `"\t"`},
+ {"\x0a", `"\n"`},
+ {"\x0b", `"\u000b"`},
+ {"\x0c", `"\u000c"`},
+ {"\x0d", `"\r"`},
+ {"\x0e", `"\u000e"`},
+ {"\x0f", `"\u000f"`},
+ {"\x10", `"\u0010"`},
+ {"\x11", `"\u0011"`},
+ {"\x12", `"\u0012"`},
+ {"\x13", `"\u0013"`},
+ {"\x14", `"\u0014"`},
+ {"\x15", `"\u0015"`},
+ {"\x16", `"\u0016"`},
+ {"\x17", `"\u0017"`},
+ {"\x18", `"\u0018"`},
+ {"\x19", `"\u0019"`},
+ {"\x1a", `"\u001a"`},
+ {"\x1b", `"\u001b"`},
+ {"\x1c", `"\u001c"`},
+ {"\x1d", `"\u001d"`},
+ {"\x1e", `"\u001e"`},
+ {"\x1f", `"\u001f"`},
+}
+
+func TestEncodeString(t *testing.T) {
+ for _, tt := range encodeStringTests {
+ b, err := Marshal(tt.in)
+ if err != nil {
+ t.Errorf("Marshal(%q): %v", tt.in, err)
+ continue
+ }
+ out := string(b)
+ if out != tt.out {
+ t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out)
+ }
+ }
+}
diff --git a/src/pkg/encoding/json/example_test.go b/src/encoding/json/example_test.go
index ca4e5ae68..ca4e5ae68 100644
--- a/src/pkg/encoding/json/example_test.go
+++ b/src/encoding/json/example_test.go
diff --git a/src/pkg/encoding/json/fold.go b/src/encoding/json/fold.go
index d6f77c93e..d6f77c93e 100644
--- a/src/pkg/encoding/json/fold.go
+++ b/src/encoding/json/fold.go
diff --git a/src/pkg/encoding/json/fold_test.go b/src/encoding/json/fold_test.go
index 9fb94646a..9fb94646a 100644
--- a/src/pkg/encoding/json/fold_test.go
+++ b/src/encoding/json/fold_test.go
diff --git a/src/pkg/encoding/json/indent.go b/src/encoding/json/indent.go
index e1bacafd6..e1bacafd6 100644
--- a/src/pkg/encoding/json/indent.go
+++ b/src/encoding/json/indent.go
diff --git a/src/pkg/encoding/json/scanner.go b/src/encoding/json/scanner.go
index a4609c895..a4609c895 100644
--- a/src/pkg/encoding/json/scanner.go
+++ b/src/encoding/json/scanner.go
diff --git a/src/pkg/encoding/json/scanner_test.go b/src/encoding/json/scanner_test.go
index 788034290..788034290 100644
--- a/src/pkg/encoding/json/scanner_test.go
+++ b/src/encoding/json/scanner_test.go
diff --git a/src/pkg/encoding/json/stream.go b/src/encoding/json/stream.go
index 1cb289fd8..9566ecadc 100644
--- a/src/pkg/encoding/json/stream.go
+++ b/src/encoding/json/stream.go
@@ -139,7 +139,6 @@ func nonSpace(b []byte) bool {
// An Encoder writes JSON objects to an output stream.
type Encoder struct {
w io.Writer
- e encodeState
err error
}
diff --git a/src/pkg/encoding/json/stream_test.go b/src/encoding/json/stream_test.go
index b562e8769..b562e8769 100644
--- a/src/pkg/encoding/json/stream_test.go
+++ b/src/encoding/json/stream_test.go
diff --git a/src/pkg/encoding/json/tagkey_test.go b/src/encoding/json/tagkey_test.go
index 23e71c752..23e71c752 100644
--- a/src/pkg/encoding/json/tagkey_test.go
+++ b/src/encoding/json/tagkey_test.go
diff --git a/src/pkg/encoding/json/tags.go b/src/encoding/json/tags.go
index c38fd5102..c38fd5102 100644
--- a/src/pkg/encoding/json/tags.go
+++ b/src/encoding/json/tags.go
diff --git a/src/pkg/encoding/json/tags_test.go b/src/encoding/json/tags_test.go
index 91fb18831..91fb18831 100644
--- a/src/pkg/encoding/json/tags_test.go
+++ b/src/encoding/json/tags_test.go
diff --git a/src/pkg/encoding/json/testdata/code.json.gz b/src/encoding/json/testdata/code.json.gz
index 0e2895b53..0e2895b53 100644
--- a/src/pkg/encoding/json/testdata/code.json.gz
+++ b/src/encoding/json/testdata/code.json.gz
Binary files differ
diff --git a/src/pkg/encoding/pem/pem.go b/src/encoding/pem/pem.go
index 8ff7ee8c3..8ff7ee8c3 100644
--- a/src/pkg/encoding/pem/pem.go
+++ b/src/encoding/pem/pem.go
diff --git a/src/pkg/encoding/pem/pem_test.go b/src/encoding/pem/pem_test.go
index ccce42cf1..ccce42cf1 100644
--- a/src/pkg/encoding/pem/pem_test.go
+++ b/src/encoding/pem/pem_test.go
diff --git a/src/pkg/encoding/xml/atom_test.go b/src/encoding/xml/atom_test.go
index a71284312..a71284312 100644
--- a/src/pkg/encoding/xml/atom_test.go
+++ b/src/encoding/xml/atom_test.go
diff --git a/src/pkg/encoding/xml/example_test.go b/src/encoding/xml/example_test.go
index becedd583..becedd583 100644
--- a/src/pkg/encoding/xml/example_test.go
+++ b/src/encoding/xml/example_test.go
diff --git a/src/pkg/encoding/xml/marshal.go b/src/encoding/xml/marshal.go
index 8c6342013..8c6342013 100644
--- a/src/pkg/encoding/xml/marshal.go
+++ b/src/encoding/xml/marshal.go
diff --git a/src/pkg/encoding/xml/marshal_test.go b/src/encoding/xml/marshal_test.go
index 14f73a75d..14f73a75d 100644
--- a/src/pkg/encoding/xml/marshal_test.go
+++ b/src/encoding/xml/marshal_test.go
diff --git a/src/pkg/encoding/xml/read.go b/src/encoding/xml/read.go
index 75b9f2ba1..75b9f2ba1 100644
--- a/src/pkg/encoding/xml/read.go
+++ b/src/encoding/xml/read.go
diff --git a/src/pkg/encoding/xml/read_test.go b/src/encoding/xml/read_test.go
index 01f55d0dd..01f55d0dd 100644
--- a/src/pkg/encoding/xml/read_test.go
+++ b/src/encoding/xml/read_test.go
diff --git a/src/pkg/encoding/xml/typeinfo.go b/src/encoding/xml/typeinfo.go
index 22248d20a..22248d20a 100644
--- a/src/pkg/encoding/xml/typeinfo.go
+++ b/src/encoding/xml/typeinfo.go
diff --git a/src/pkg/encoding/xml/xml.go b/src/encoding/xml/xml.go
index b473cb845..8c15b98c3 100644
--- a/src/pkg/encoding/xml/xml.go
+++ b/src/encoding/xml/xml.go
@@ -196,6 +196,7 @@ type Decoder struct {
ns map[string]string
err error
line int
+ offset int64
unmarshalDepth int
}
@@ -859,9 +860,17 @@ func (d *Decoder) getc() (b byte, ok bool) {
if b == '\n' {
d.line++
}
+ d.offset++
return b, true
}
+// InputOffset returns the input stream byte offset of the current decoder position.
+// The offset gives the location of the end of the most recently returned token
+// and the beginning of the next token.
+func (d *Decoder) InputOffset() int64 {
+ return d.offset
+}
+
// Return saved offset.
// If we did ungetc (nextByte >= 0), have to back up one.
func (d *Decoder) savedOffset() int {
@@ -891,6 +900,7 @@ func (d *Decoder) ungetc(b byte) {
d.line--
}
d.nextByte = int(b)
+ d.offset--
}
var entity = map[string]int{
diff --git a/src/pkg/encoding/xml/xml_test.go b/src/encoding/xml/xml_test.go
index 7723ab1c9..be995c0d5 100644
--- a/src/pkg/encoding/xml/xml_test.go
+++ b/src/encoding/xml/xml_test.go
@@ -170,7 +170,7 @@ var xmlInput = []string{
func TestRawToken(t *testing.T) {
d := NewDecoder(strings.NewReader(testInput))
d.Entity = testEntity
- testRawToken(t, d, rawTokens)
+ testRawToken(t, d, testInput, rawTokens)
}
const nonStrictInput = `
@@ -225,7 +225,7 @@ var nonStrictTokens = []Token{
func TestNonStrictRawToken(t *testing.T) {
d := NewDecoder(strings.NewReader(nonStrictInput))
d.Strict = false
- testRawToken(t, d, nonStrictTokens)
+ testRawToken(t, d, nonStrictInput, nonStrictTokens)
}
type downCaser struct {
@@ -254,7 +254,7 @@ func TestRawTokenAltEncoding(t *testing.T) {
}
return &downCaser{t, input.(io.ByteReader)}, nil
}
- testRawToken(t, d, rawTokensAltEncoding)
+ testRawToken(t, d, testInputAltEncoding, rawTokensAltEncoding)
}
func TestRawTokenAltEncodingNoConverter(t *testing.T) {
@@ -280,9 +280,12 @@ func TestRawTokenAltEncodingNoConverter(t *testing.T) {
}
}
-func testRawToken(t *testing.T, d *Decoder, rawTokens []Token) {
+func testRawToken(t *testing.T, d *Decoder, raw string, rawTokens []Token) {
+ lastEnd := int64(0)
for i, want := range rawTokens {
+ start := d.InputOffset()
have, err := d.RawToken()
+ end := d.InputOffset()
if err != nil {
t.Fatalf("token %d: unexpected error: %s", i, err)
}
@@ -300,6 +303,26 @@ func testRawToken(t *testing.T, d *Decoder, rawTokens []Token) {
}
t.Errorf("token %d = %s, want %s", i, shave, swant)
}
+
+ // Check that InputOffset returned actual token.
+ switch {
+ case start < lastEnd:
+ t.Errorf("token %d: position [%d,%d) for %T is before previous token", i, start, end, have)
+ case start >= end:
+ // Special case: EndElement can be synthesized.
+ if start == end && end == lastEnd {
+ break
+ }
+ t.Errorf("token %d: position [%d,%d) for %T is empty", i, start, end, have)
+ case end > int64(len(raw)):
+ t.Errorf("token %d: position [%d,%d) for %T extends beyond input", i, start, end, have)
+ default:
+ text := raw[start:end]
+ if strings.ContainsAny(text, "<>") && (!strings.HasPrefix(text, "<") || !strings.HasSuffix(text, ">")) {
+ t.Errorf("token %d: misaligned raw token %#q for %T", i, text, have)
+ }
+ }
+ lastEnd = end
}
}
diff --git a/src/pkg/errors/errors.go b/src/errors/errors.go
index 3085a7962..3085a7962 100644
--- a/src/pkg/errors/errors.go
+++ b/src/errors/errors.go
diff --git a/src/pkg/errors/errors_test.go b/src/errors/errors_test.go
index 63c05d718..63c05d718 100644
--- a/src/pkg/errors/errors_test.go
+++ b/src/errors/errors_test.go
diff --git a/src/pkg/errors/example_test.go b/src/errors/example_test.go
index 0e86828f4..0e86828f4 100644
--- a/src/pkg/errors/example_test.go
+++ b/src/errors/example_test.go
diff --git a/src/pkg/expvar/expvar.go b/src/expvar/expvar.go
index 9b6dab487..9b6dab487 100644
--- a/src/pkg/expvar/expvar.go
+++ b/src/expvar/expvar.go
diff --git a/src/pkg/expvar/expvar_test.go b/src/expvar/expvar_test.go
index 765e3b757..765e3b757 100644
--- a/src/pkg/expvar/expvar_test.go
+++ b/src/expvar/expvar_test.go
diff --git a/src/pkg/flag/example_test.go b/src/flag/example_test.go
index 04a0d20ee..04a0d20ee 100644
--- a/src/pkg/flag/example_test.go
+++ b/src/flag/example_test.go
diff --git a/src/pkg/flag/export_test.go b/src/flag/export_test.go
index 56cda58b3..56cda58b3 100644
--- a/src/pkg/flag/export_test.go
+++ b/src/flag/export_test.go
diff --git a/src/pkg/flag/flag.go b/src/flag/flag.go
index cd2a165be..60aef5d80 100644
--- a/src/pkg/flag/flag.go
+++ b/src/flag/flag.go
@@ -73,7 +73,8 @@ import (
"time"
)
-// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined.
+// ErrHelp is the error returned if the -help or -h flag is invoked
+// but no such flag is defined.
var ErrHelp = errors.New("flag: help requested")
// -- bool Value
@@ -405,6 +406,7 @@ func defaultUsage(f *FlagSet) {
// for how to write your own usage function.
// Usage prints to standard error a usage message documenting all defined command-line flags.
+// It is called when an error occurs while parsing flags.
// The function is a variable that may be changed to point to a custom function.
var Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
@@ -628,18 +630,21 @@ func Float64(name string, value float64, usage string) *float64 {
// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
// The argument p points to a time.Duration variable in which to store the value of the flag.
+// The flag accepts a value acceptable to time.ParseDuration.
func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
f.Var(newDurationValue(value, p), name, usage)
}
// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
// The argument p points to a time.Duration variable in which to store the value of the flag.
+// The flag accepts a value acceptable to time.ParseDuration.
func DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
CommandLine.Var(newDurationValue(value, p), name, usage)
}
// Duration defines a time.Duration flag with specified name, default value, and usage string.
// The return value is the address of a time.Duration variable that stores the value of the flag.
+// The flag accepts a value acceptable to time.ParseDuration.
func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration {
p := new(time.Duration)
f.DurationVar(p, name, value, usage)
@@ -648,6 +653,7 @@ func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time
// Duration defines a time.Duration flag with specified name, default value, and usage string.
// The return value is the address of a time.Duration variable that stores the value of the flag.
+// The flag accepts a value acceptable to time.ParseDuration.
func Duration(name string, value time.Duration, usage string) *time.Duration {
return CommandLine.Duration(name, value, usage)
}
@@ -697,13 +703,15 @@ func (f *FlagSet) failf(format string, a ...interface{}) error {
return err
}
-// usage calls the Usage method for the flag set, or the usage function if
-// the flag set is CommandLine.
+// usage calls the Usage method for the flag set if one is specified,
+// or the appropriate default usage function otherwise.
func (f *FlagSet) usage() {
- if f == CommandLine {
- Usage()
- } else if f.Usage == nil {
- defaultUsage(f)
+ if f.Usage == nil {
+ if f == CommandLine {
+ Usage()
+ } else {
+ defaultUsage(f)
+ }
} else {
f.Usage()
}
@@ -752,6 +760,7 @@ func (f *FlagSet) parseOne() (bool, error) {
}
return false, f.failf("flag provided but not defined: -%s", name)
}
+
if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
if has_value {
if err := fv.Set(value); err != nil {
@@ -784,7 +793,7 @@ func (f *FlagSet) parseOne() (bool, error) {
// Parse parses flag definitions from the argument list, which should not
// include the command name. Must be called after all flags in the FlagSet
// are defined and before flags are accessed by the program.
-// The return value will be ErrHelp if -help was set but not defined.
+// The return value will be ErrHelp if -help or -h were set but not defined.
func (f *FlagSet) Parse(arguments []string) error {
f.parsed = true
f.args = arguments
@@ -826,7 +835,7 @@ func Parsed() bool {
}
// CommandLine is the default set of command-line flags, parsed from os.Args.
-// The top-level functions such as BoolVar, Arg, and on are wrappers for the
+// The top-level functions such as BoolVar, Arg, and so on are wrappers for the
// methods of CommandLine.
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
diff --git a/src/pkg/flag/flag_test.go b/src/flag/flag_test.go
index 2c0387269..8c88c8c27 100644
--- a/src/pkg/flag/flag_test.go
+++ b/src/flag/flag_test.go
@@ -251,6 +251,16 @@ func TestUserDefined(t *testing.T) {
}
}
+func TestUserDefinedForCommandLine(t *testing.T) {
+ const help = "HELP"
+ var result string
+ ResetForTesting(func() { result = help })
+ Usage()
+ if result != help {
+ t.Fatalf("got %q; expected %q", result, help)
+ }
+}
+
// Declare a user-defined boolean flag type.
type boolFlagVar struct {
count int
diff --git a/src/pkg/fmt/doc.go b/src/fmt/doc.go
index 02642d6ae..ee54463e2 100644
--- a/src/pkg/fmt/doc.go
+++ b/src/fmt/doc.go
@@ -13,7 +13,7 @@
The verbs:
General:
- %v the value in a default format.
+ %v the value in a default format
when printing structs, the plus flag (%+v) adds field names
%#v a Go-syntax representation of the value
%T a Go-syntax representation of the type of the value
@@ -38,8 +38,8 @@
%E scientific notation, e.g. -1234.456E+78
%f decimal point but no exponent, e.g. 123.456
%F synonym for %f
- %g whichever of %e or %f produces more compact output
- %G whichever of %E or %f produces more compact output
+ %g %e for large exponents, %f otherwise
+ %G %E for large exponents, %F otherwise
String and slice of bytes:
%s the uninterpreted bytes of the string or slice
%q a double-quoted string safely escaped with Go syntax
@@ -51,6 +51,21 @@
There is no 'u' flag. Integers are printed unsigned if they have unsigned type.
Similarly, there is no need to specify the size of the operand (int8, int64).
+ The default format for %v is:
+ bool: %t
+ int, int8 etc.: %d
+ uint, uint8 etc.: %d, %x if printed with %#v
+ float32, complex64, etc: %g
+ string: %s
+ chan: %p
+ pointer: %p
+ For compound objects, the elements are printed using these rules, recursively,
+ laid out like this:
+ struct: {field0 field1 ...}
+ array, slice: [elem0 elem1 ...]
+ maps: map[key1:value1 key2:value2]
+ pointer to above: &{}, &[], &map[]
+
Width is specified by an optional decimal number immediately following the verb.
If absent, the width is whatever is necessary to represent the value.
Precision is specified after the (optional) width by a period followed by a
@@ -63,16 +78,20 @@
%9.2f width 9, precision 2
%9.f width 9, precision 0
- Width and precision are measured in units of Unicode code points.
- (This differs from C's printf where the units are numbers
- of bytes.) Either or both of the flags may be replaced with the
- character '*', causing their values to be obtained from the next
- operand, which must be of type int.
+ Width and precision are measured in units of Unicode code points,
+ that is, runes. (This differs from C's printf where the
+ units are always measured in bytes.) Either or both of the flags
+ may be replaced with the character '*', causing their values to be
+ obtained from the next operand, which must be of type int.
- For most values, width is the minimum number of characters to output,
+ For most values, width is the minimum number of runes to output,
padding the formatted form with spaces if necessary.
- For strings, precision is the maximum number of characters to output,
- truncating if necessary.
+
+ For strings, byte slices and byte arrays, however, precision
+ limits the length of the input to be formatted (not the size of
+ the output), truncating if necessary. Normally it is measured in
+ runes, but for these types when formatted with the %x or %X format
+ it is measured in bytes.
For floating-point values, width sets the minimum width of the field and
precision sets the number of places after the decimal, if appropriate,
@@ -147,6 +166,10 @@
func (x X) String() string { return Sprintf("<%s>", x) }
convert the value before recurring:
func (x X) String() string { return Sprintf("<%s>", string(x)) }
+ Infinite recursion can also be triggered by self-referential data
+ structures, such as a slice that contains itself as an element, if
+ that type has a String method. Such pathologies are rare, however,
+ and the package does not protect against them.
Explicit argument indexes:
@@ -160,7 +183,7 @@
For example,
fmt.Sprintf("%[2]d %[1]d\n", 11, 22)
- will yield "22, 11", while
+ will yield "22 11", while
fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6),
equivalent to
fmt.Sprintf("%6.2f", 12.0),
diff --git a/src/pkg/fmt/export_test.go b/src/fmt/export_test.go
index 89d57ee6c..89d57ee6c 100644
--- a/src/pkg/fmt/export_test.go
+++ b/src/fmt/export_test.go
diff --git a/src/pkg/fmt/fmt_test.go b/src/fmt/fmt_test.go
index 7e3d06b9f..ff5fa79a3 100644
--- a/src/pkg/fmt/fmt_test.go
+++ b/src/fmt/fmt_test.go
@@ -108,6 +108,20 @@ func (p *P) String() string {
var barray = [5]renamedUint8{1, 2, 3, 4, 5}
var bslice = barray[:]
+type byteStringer byte
+
+func (byteStringer) String() string { return "X" }
+
+var byteStringerSlice = []byteStringer{97, 98, 99, 100}
+
+type byteFormatter byte
+
+func (byteFormatter) Format(f State, _ rune) {
+ Fprint(f, "X")
+}
+
+var byteFormatterSlice = []byteFormatter{97, 98, 99, 100}
+
var b byte
var fmtTests = []struct {
@@ -125,13 +139,17 @@ var fmtTests = []struct {
{"%x", "xyz", "78797a"},
{"%X", "xyz", "78797A"},
{"%q", "abc", `"abc"`},
+ {"%#x", []byte("abc\xff"), "0x616263ff"},
+ {"%#X", []byte("abc\xff"), "0X616263FF"},
+ {"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"},
+ {"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"},
// basic bytes
{"%s", []byte("abc"), "abc"},
{"%x", []byte("abc"), "616263"},
{"% x", []byte("abc\xff"), "61 62 63 ff"},
- {"%#x", []byte("abc\xff"), "0x610x620x630xff"},
- {"%#X", []byte("abc\xff"), "0X610X620X630XFF"},
+ {"%#x", []byte("abc\xff"), "0x616263ff"},
+ {"%#X", []byte("abc\xff"), "0X616263FF"},
{"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"},
{"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"},
{"% X", []byte("abc\xff"), "61 62 63 FF"},
@@ -176,9 +194,18 @@ var fmtTests = []struct {
{"%.5s", "日本語日本語", "日本語日本"},
{"%.5s", []byte("日本語日本語"), "日本語日本"},
{"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`},
+ {"%.5x", "abcdefghijklmnopqrstuvwxyz", `6162636465`},
+ {"%.5q", []byte("abcdefghijklmnopqrstuvwxyz"), `"abcde"`},
+ {"%.5x", []byte("abcdefghijklmnopqrstuvwxyz"), `6162636465`},
{"%.3q", "日本語日本語", `"日本語"`},
{"%.3q", []byte("日本語日本語"), `"日本語"`},
+ {"%.1q", "日本語", `"日"`},
+ {"%.1q", []byte("日本語"), `"日"`},
+ {"%.1x", "日本語", `e6`},
+ {"%.1X", []byte("日本語"), `E6`},
{"%10.1q", "日本語日本語", ` "日"`},
+ {"%3c", '⌘', " ⌘"},
+ {"%5q", '\u2026', ` '…'`},
{"%10v", nil, " <nil>"},
{"%-10v", nil, "<nil> "},
@@ -379,7 +406,7 @@ var fmtTests = []struct {
{"%s", I(23), `<23>`},
{"%q", I(23), `"<23>"`},
{"%x", I(23), `3c32333e`},
- {"%#x", I(23), `0x3c0x320x330x3e`},
+ {"%#x", I(23), `0x3c32333e`},
{"%# x", I(23), `0x3c 0x32 0x33 0x3e`},
{"%d", I(23), `23`}, // Stringer applies only to string formats.
@@ -623,6 +650,21 @@ var fmtTests = []struct {
{"%+010.2f", -104.66 + 440.51i, "(-000104.66+000440.51i)"},
{"%+010.2f", +104.66 - 440.51i, "(+000104.66-000440.51i)"},
{"%+010.2f", -104.66 - 440.51i, "(-000104.66-000440.51i)"},
+
+ // []T where type T is a byte with a Stringer method.
+ {"%v", byteStringerSlice, "[X X X X]"},
+ {"%s", byteStringerSlice, "abcd"},
+ {"%q", byteStringerSlice, "\"abcd\""},
+ {"%x", byteStringerSlice, "61626364"},
+ {"%#v", byteStringerSlice, "[]fmt_test.byteStringer{0x61, 0x62, 0x63, 0x64}"},
+
+ // And the same for Formatter.
+ {"%v", byteFormatterSlice, "[X X X X]"},
+ {"%s", byteFormatterSlice, "abcd"},
+ {"%q", byteFormatterSlice, "\"abcd\""},
+ {"%x", byteFormatterSlice, "61626364"},
+ // This next case seems wrong, but the docs say the Formatter wins here.
+ {"%#v", byteFormatterSlice, "[]fmt_test.byteFormatter{X, X, X, X}"},
}
// zeroFill generates zero-filled strings of the specified width. The length
@@ -672,7 +714,7 @@ func TestSprintf(t *testing.T) {
// thing as if done by hand with two singleton prints.
func TestComplexFormatting(t *testing.T) {
var yesNo = []bool{true, false}
- var signs = []float64{1, 0, -1}
+ var values = []float64{1, 0, -1, math.Inf(1), math.Inf(-1), math.NaN()}
for _, plus := range yesNo {
for _, zero := range yesNo {
for _, space := range yesNo {
@@ -697,10 +739,10 @@ func TestComplexFormatting(t *testing.T) {
imagFmt += "+"
imagFmt += "10.2"
imagFmt += string(char)
- for _, realSign := range signs {
- for _, imagSign := range signs {
- one := Sprintf(realFmt, complex(realSign, imagSign))
- two := Sprintf("("+realFmt+imagFmt+"i)", realSign, imagSign)
+ for _, realValue := range values {
+ for _, imagValue := range values {
+ one := Sprintf(realFmt, complex(realValue, imagValue))
+ two := Sprintf("("+realFmt+imagFmt+"i)", realValue, imagValue)
if one != two {
t.Error(f, one, two)
}
@@ -819,7 +861,25 @@ func BenchmarkManyArgs(b *testing.B) {
})
}
+func BenchmarkFprintInt(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ Fprint(&buf, 123456)
+ }
+}
+
+func BenchmarkFprintIntNoAlloc(b *testing.B) {
+ var x interface{} = 123456
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ Fprint(&buf, x)
+ }
+}
+
var mallocBuf bytes.Buffer
+var mallocPointer *int // A pointer so we know the interface value won't allocate.
var mallocTest = []struct {
count int
@@ -828,14 +888,16 @@ var mallocTest = []struct {
}{
{0, `Sprintf("")`, func() { Sprintf("") }},
{1, `Sprintf("xxx")`, func() { Sprintf("xxx") }},
- {1, `Sprintf("%x")`, func() { Sprintf("%x", 7) }},
+ {2, `Sprintf("%x")`, func() { Sprintf("%x", 7) }},
{2, `Sprintf("%s")`, func() { Sprintf("%s", "hello") }},
- {1, `Sprintf("%x %x")`, func() { Sprintf("%x %x", 7, 112) }},
- // For %g we use a float32, not float64, to guarantee passing the argument
- // does not need to allocate memory to store the result in a pointer-sized word.
- {2, `Sprintf("%g")`, func() { Sprintf("%g", float32(3.14159)) }},
- {0, `Fprintf(buf, "%x %x %x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x %x %x", 7, 8, 9) }},
+ {3, `Sprintf("%x %x")`, func() { Sprintf("%x %x", 7, 112) }},
+ {2, `Sprintf("%g")`, func() { Sprintf("%g", float32(3.14159)) }}, // TODO: Can this be 1?
{1, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }},
+ // If the interface value doesn't need to allocate, amortized allocation overhead should be zero.
+ {0, `Fprintf(buf, "%x %x %x")`, func() {
+ mallocBuf.Reset()
+ Fprintf(&mallocBuf, "%x %x %x", mallocPointer, mallocPointer, mallocPointer)
+ }},
}
var _ bytes.Buffer
@@ -857,7 +919,7 @@ func TestCountMallocs(t *testing.T) {
type flagPrinter struct{}
-func (*flagPrinter) Format(f State, c rune) {
+func (flagPrinter) Format(f State, c rune) {
s := "%"
for i := 0; i < 128; i++ {
if f.Flag(i) {
@@ -903,11 +965,12 @@ func TestFlagParser(t *testing.T) {
}
func TestStructPrinter(t *testing.T) {
- var s struct {
+ type T struct {
a string
b string
c int
}
+ var s T
s.a = "abc"
s.b = "def"
s.c = 123
@@ -917,15 +980,38 @@ func TestStructPrinter(t *testing.T) {
}{
{"%v", "{abc def 123}"},
{"%+v", "{a:abc b:def c:123}"},
+ {"%#v", `fmt_test.T{a:"abc", b:"def", c:123}`},
}
for _, tt := range tests {
out := Sprintf(tt.fmt, s)
if out != tt.out {
- t.Errorf("Sprintf(%q, &s) = %q, want %q", tt.fmt, out, tt.out)
+ t.Errorf("Sprintf(%q, s) = %#q, want %#q", tt.fmt, out, tt.out)
+ }
+ // The same but with a pointer.
+ out = Sprintf(tt.fmt, &s)
+ if out != "&"+tt.out {
+ t.Errorf("Sprintf(%q, &s) = %#q, want %#q", tt.fmt, out, "&"+tt.out)
}
}
}
+func TestSlicePrinter(t *testing.T) {
+ slice := []int{}
+ s := Sprint(slice)
+ if s != "[]" {
+ t.Errorf("empty slice printed as %q not %q", s, "[]")
+ }
+ slice = []int{1, 2, 3}
+ s = Sprint(slice)
+ if s != "[1 2 3]" {
+ t.Errorf("slice: got %q expected %q", s, "[1 2 3]")
+ }
+ s = Sprint(&slice)
+ if s != "&[1 2 3]" {
+ t.Errorf("&slice: got %q expected %q", s, "&[1 2 3]")
+ }
+}
+
// presentInMap checks map printing using substrings so we don't depend on the
// print order.
func presentInMap(s string, a []string, t *testing.T) {
@@ -952,6 +1038,12 @@ func TestMapPrinter(t *testing.T) {
a := []string{"1:one", "2:two", "3:three"}
presentInMap(Sprintf("%v", m1), a, t)
presentInMap(Sprint(m1), a, t)
+ // Pointer to map prints the same but with initial &.
+ if !strings.HasPrefix(Sprint(&m1), "&") {
+ t.Errorf("no initial & for address of map")
+ }
+ presentInMap(Sprintf("%v", &m1), a, t)
+ presentInMap(Sprint(&m1), a, t)
}
func TestEmptyMap(t *testing.T) {
@@ -1082,10 +1174,10 @@ var panictests = []struct {
}
func TestPanics(t *testing.T) {
- for _, tt := range panictests {
+ for i, tt := range panictests {
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)
}
}
}
@@ -1145,3 +1237,74 @@ func TestNilDoesNotBecomeTyped(t *testing.T) {
t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got)
}
}
+
+var formatterFlagTests = []struct {
+ in string
+ val interface{}
+ out string
+}{
+ // scalar values with the (unused by fmt) 'a' verb.
+ {"%a", flagPrinter{}, "[%a]"},
+ {"%-a", flagPrinter{}, "[%-a]"},
+ {"%+a", flagPrinter{}, "[%+a]"},
+ {"%#a", flagPrinter{}, "[%#a]"},
+ {"% a", flagPrinter{}, "[% a]"},
+ {"%0a", flagPrinter{}, "[%0a]"},
+ {"%1.2a", flagPrinter{}, "[%1.2a]"},
+ {"%-1.2a", flagPrinter{}, "[%-1.2a]"},
+ {"%+1.2a", flagPrinter{}, "[%+1.2a]"},
+ {"%-+1.2a", flagPrinter{}, "[%+-1.2a]"},
+ {"%-+1.2abc", flagPrinter{}, "[%+-1.2a]bc"},
+ {"%-1.2abc", flagPrinter{}, "[%-1.2a]bc"},
+
+ // composite values with the 'a' verb
+ {"%a", [1]flagPrinter{}, "[[%a]]"},
+ {"%-a", [1]flagPrinter{}, "[[%-a]]"},
+ {"%+a", [1]flagPrinter{}, "[[%+a]]"},
+ {"%#a", [1]flagPrinter{}, "[[%#a]]"},
+ {"% a", [1]flagPrinter{}, "[[% a]]"},
+ {"%0a", [1]flagPrinter{}, "[[%0a]]"},
+ {"%1.2a", [1]flagPrinter{}, "[[%1.2a]]"},
+ {"%-1.2a", [1]flagPrinter{}, "[[%-1.2a]]"},
+ {"%+1.2a", [1]flagPrinter{}, "[[%+1.2a]]"},
+ {"%-+1.2a", [1]flagPrinter{}, "[[%+-1.2a]]"},
+ {"%-+1.2abc", [1]flagPrinter{}, "[[%+-1.2a]]bc"},
+ {"%-1.2abc", [1]flagPrinter{}, "[[%-1.2a]]bc"},
+
+ // simple values with the 'v' verb
+ {"%v", flagPrinter{}, "[%v]"},
+ {"%-v", flagPrinter{}, "[%-v]"},
+ {"%+v", flagPrinter{}, "[%+v]"},
+ {"%#v", flagPrinter{}, "[%#v]"},
+ {"% v", flagPrinter{}, "[% v]"},
+ {"%0v", flagPrinter{}, "[%0v]"},
+ {"%1.2v", flagPrinter{}, "[%1.2v]"},
+ {"%-1.2v", flagPrinter{}, "[%-1.2v]"},
+ {"%+1.2v", flagPrinter{}, "[%+1.2v]"},
+ {"%-+1.2v", flagPrinter{}, "[%+-1.2v]"},
+ {"%-+1.2vbc", flagPrinter{}, "[%+-1.2v]bc"},
+ {"%-1.2vbc", flagPrinter{}, "[%-1.2v]bc"},
+
+ // composite values with the 'v' verb.
+ {"%v", [1]flagPrinter{}, "[[%v]]"},
+ {"%-v", [1]flagPrinter{}, "[[%-v]]"},
+ {"%+v", [1]flagPrinter{}, "[[%+v]]"},
+ {"%#v", [1]flagPrinter{}, "[1]fmt_test.flagPrinter{[%#v]}"},
+ {"% v", [1]flagPrinter{}, "[[% v]]"},
+ {"%0v", [1]flagPrinter{}, "[[%0v]]"},
+ {"%1.2v", [1]flagPrinter{}, "[[%1.2v]]"},
+ {"%-1.2v", [1]flagPrinter{}, "[[%-1.2v]]"},
+ {"%+1.2v", [1]flagPrinter{}, "[[%+1.2v]]"},
+ {"%-+1.2v", [1]flagPrinter{}, "[[%+-1.2v]]"},
+ {"%-+1.2vbc", [1]flagPrinter{}, "[[%+-1.2v]]bc"},
+ {"%-1.2vbc", [1]flagPrinter{}, "[[%-1.2v]]bc"},
+}
+
+func TestFormatterFlags(t *testing.T) {
+ for _, tt := range formatterFlagTests {
+ s := Sprintf(tt.in, tt.val)
+ if s != tt.out {
+ t.Errorf("Sprintf(%q, %T) = %q, want %q", tt.in, tt.val, s, tt.out)
+ }
+ }
+}
diff --git a/src/pkg/fmt/format.go b/src/fmt/format.go
index a89c542cf..4d97d1443 100644
--- a/src/pkg/fmt/format.go
+++ b/src/fmt/format.go
@@ -34,15 +34,8 @@ func init() {
}
}
-// A fmt is the raw formatter used by Printf etc.
-// It prints into a buffer that must be set up separately.
-type fmt struct {
- intbuf [nByte]byte
- buf *buffer
- // width, precision
- wid int
- prec int
- // flags
+// flags placed in a separate struct for easy clearing.
+type fmtFlags struct {
widPresent bool
precPresent bool
minus bool
@@ -52,20 +45,27 @@ type fmt struct {
unicode bool
uniQuote bool // Use 'x'= prefix for %U if printable.
zero bool
+
+ // For the formats %+v %#v, we set the plusV/sharpV flags
+ // and clear the plus/sharp flags since %+v and %#v are in effect
+ // different, flagless formats set at the top level.
+ plusV bool
+ sharpV bool
+}
+
+// A fmt is the raw formatter used by Printf etc.
+// It prints into a buffer that must be set up separately.
+type fmt struct {
+ intbuf [nByte]byte
+ buf *buffer
+ // width, precision
+ wid int
+ prec int
+ fmtFlags
}
func (f *fmt) clearflags() {
- f.wid = 0
- f.widPresent = false
- f.prec = 0
- f.precPresent = false
- f.minus = false
- f.plus = false
- f.sharp = false
- f.space = false
- f.unicode = false
- f.uniQuote = false
- f.zero = false
+ f.fmtFlags = fmtFlags{}
}
func (f *fmt) init(buf *buffer) {
@@ -114,7 +114,7 @@ func (f *fmt) pad(b []byte) {
f.buf.Write(b)
return
}
- padding, left, right := f.computePadding(len(b))
+ padding, left, right := f.computePadding(utf8.RuneCount(b))
if left > 0 {
f.writePadding(left, padding)
}
@@ -199,10 +199,36 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
// block but it's not worth the duplication, so ua has 64 bits.
i := len(buf)
ua := uint64(a)
- for ua >= base {
- i--
- buf[i] = digits[ua%base]
- ua /= base
+ // use constants for the division and modulo for more efficient code.
+ // switch cases ordered by popularity.
+ switch base {
+ case 10:
+ for ua >= 10 {
+ i--
+ next := ua / 10
+ buf[i] = byte('0' + ua - next*10)
+ ua = next
+ }
+ case 16:
+ for ua >= 16 {
+ i--
+ buf[i] = digits[ua&0xF]
+ ua >>= 4
+ }
+ case 8:
+ for ua >= 8 {
+ i--
+ buf[i] = byte('0' + ua&7)
+ ua >>= 3
+ }
+ case 2:
+ for ua >= 2 {
+ i--
+ buf[i] = byte('0' + ua&1)
+ ua >>= 1
+ }
+ default:
+ panic("fmt: unknown base; can't happen")
}
i--
buf[i] = digits[ua]
@@ -298,7 +324,7 @@ func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
if i > 0 && f.space {
buf = append(buf, ' ')
}
- if f.sharp {
+ if f.sharp && (f.space || i == 0) {
buf = append(buf, '0', x)
}
var c byte
@@ -314,11 +340,17 @@ func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
// fmt_sx formats a string as a hexadecimal encoding of its bytes.
func (f *fmt) fmt_sx(s, digits string) {
+ if f.precPresent && f.prec < len(s) {
+ s = s[:f.prec]
+ }
f.fmt_sbx(s, nil, digits)
}
// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
func (f *fmt) fmt_bx(b []byte, digits string) {
+ if f.precPresent && f.prec < len(b) {
+ b = b[:f.prec]
+ }
f.fmt_sbx("", b, digits)
}
diff --git a/src/pkg/fmt/print.go b/src/fmt/print.go
index 302661f4c..59a30d221 100644
--- a/src/pkg/fmt/print.go
+++ b/src/fmt/print.go
@@ -128,7 +128,7 @@ var ppFree = sync.Pool{
New: func() interface{} { return new(pp) },
}
-// newPrinter allocates a new pp struct or grab a cached one.
+// newPrinter allocates a new pp struct or grabs a cached one.
func newPrinter() *pp {
p := ppFree.Get().(*pp)
p.panicking = false
@@ -297,13 +297,13 @@ func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
return
}
-func (p *pp) unknownType(v interface{}) {
- if v == nil {
+func (p *pp) unknownType(v reflect.Value) {
+ if !v.IsValid() {
p.buf.Write(nilAngleBytes)
return
}
p.buf.WriteByte('?')
- p.buf.WriteString(reflect.TypeOf(v).String())
+ p.buf.WriteString(v.Type().String())
p.buf.WriteByte('?')
}
@@ -317,11 +317,11 @@ func (p *pp) badVerb(verb rune) {
case p.arg != nil:
p.buf.WriteString(reflect.TypeOf(p.arg).String())
p.add('=')
- p.printArg(p.arg, 'v', false, false, 0)
+ p.printArg(p.arg, 'v', 0)
case p.value.IsValid():
p.buf.WriteString(p.value.Type().String())
p.add('=')
- p.printValue(p.value, 'v', false, false, 0)
+ p.printValue(p.value, 'v', 0)
default:
p.buf.Write(nilAngleBytes)
}
@@ -406,7 +406,7 @@ func (p *pp) fmtUnicode(v int64) {
p.fmt.sharp = sharp
}
-func (p *pp) fmtUint64(v uint64, verb rune, goSyntax bool) {
+func (p *pp) fmtUint64(v uint64, verb rune) {
switch verb {
case 'b':
p.fmt.integer(int64(v), 2, unsigned, ldigits)
@@ -415,7 +415,7 @@ func (p *pp) fmtUint64(v uint64, verb rune, goSyntax bool) {
case 'd':
p.fmt.integer(int64(v), 10, unsigned, ldigits)
case 'v':
- if goSyntax {
+ if p.fmt.sharpV {
p.fmt0x64(v, true)
} else {
p.fmt.integer(int64(v), 10, unsigned, ldigits)
@@ -499,10 +499,10 @@ func (p *pp) fmtComplex128(v complex128, verb rune) {
}
}
-func (p *pp) fmtString(v string, verb rune, goSyntax bool) {
+func (p *pp) fmtString(v string, verb rune) {
switch verb {
case 'v':
- if goSyntax {
+ if p.fmt.sharpV {
p.fmt.fmt_q(v)
} else {
p.fmt.fmt_s(v)
@@ -520,9 +520,9 @@ func (p *pp) fmtString(v string, verb rune, goSyntax bool) {
}
}
-func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, depth int) {
+func (p *pp) fmtBytes(v []byte, verb rune, typ reflect.Type, depth int) {
if verb == 'v' || verb == 'd' {
- if goSyntax {
+ if p.fmt.sharpV {
if v == nil {
if typ == nil {
p.buf.WriteString("[]byte(nil)")
@@ -543,15 +543,15 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, dept
}
for i, c := range v {
if i > 0 {
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.Write(commaSpaceBytes)
} else {
p.buf.WriteByte(' ')
}
}
- p.printArg(c, 'v', p.fmt.plus, goSyntax, depth+1)
+ p.printArg(c, 'v', depth+1)
}
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteByte('}')
} else {
p.buf.WriteByte(']')
@@ -572,7 +572,7 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, dept
}
}
-func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
+func (p *pp) fmtPointer(value reflect.Value, verb rune) {
use0x64 := true
switch verb {
case 'p', 'v':
@@ -594,7 +594,7 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
return
}
- if goSyntax {
+ if p.fmt.sharpV {
p.add('(')
p.buf.WriteString(value.Type().String())
p.add(')')
@@ -611,7 +611,7 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
if use0x64 {
p.fmt0x64(uint64(u), !p.fmt.sharp)
} else {
- p.fmtUint64(uint64(u), verb, false)
+ p.fmtUint64(uint64(u), verb)
}
}
}
@@ -636,42 +636,65 @@ func (p *pp) catchPanic(arg interface{}, verb rune) {
// Nested panics; the recursion in printArg cannot succeed.
panic(err)
}
+ p.fmt.clearflags() // We are done, and for this output we want default behavior.
p.buf.Write(percentBangBytes)
p.add(verb)
p.buf.Write(panicBytes)
p.panicking = true
- p.printArg(err, 'v', false, false, 0)
+ p.printArg(err, 'v', 0)
p.panicking = false
p.buf.WriteByte(')')
}
}
-func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString, handled bool) {
+// clearSpecialFlags pushes %#v back into the regular flags and returns their old state.
+func (p *pp) clearSpecialFlags() (plusV, sharpV bool) {
+ plusV = p.fmt.plusV
+ if plusV {
+ p.fmt.plus = true
+ p.fmt.plusV = false
+ }
+ sharpV = p.fmt.sharpV
+ if sharpV {
+ p.fmt.sharp = true
+ p.fmt.sharpV = false
+ }
+ return
+}
+
+// restoreSpecialFlags, whose argument should be a call to clearSpecialFlags,
+// restores the setting of the plusV and sharpV flags.
+func (p *pp) restoreSpecialFlags(plusV, sharpV bool) {
+ if plusV {
+ p.fmt.plus = false
+ p.fmt.plusV = true
+ }
+ if sharpV {
+ p.fmt.sharp = false
+ p.fmt.sharpV = true
+ }
+}
+
+func (p *pp) handleMethods(verb rune, depth int) (handled bool) {
if p.erroring {
return
}
// Is it a Formatter?
if formatter, ok := p.arg.(Formatter); ok {
handled = true
- wasString = false
+ defer p.restoreSpecialFlags(p.clearSpecialFlags())
defer p.catchPanic(p.arg, verb)
formatter.Format(p, verb)
return
}
- // Must not touch flags before Formatter looks at them.
- if plus {
- p.fmt.plus = false
- }
// If we're doing Go syntax and the argument knows how to supply it, take care of it now.
- if goSyntax {
- p.fmt.sharp = false
+ if p.fmt.sharpV {
if stringer, ok := p.arg.(GoStringer); ok {
- wasString = false
handled = true
defer p.catchPanic(p.arg, verb)
// Print the result of GoString unadorned.
- p.fmtString(stringer.GoString(), 's', false)
+ p.fmt.fmt_s(stringer.GoString())
return
}
} else {
@@ -682,30 +705,27 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString
case 'v', 's', 'x', 'X', 'q':
// Is it an error or Stringer?
// The duplication in the bodies is necessary:
- // setting wasString and handled, and deferring catchPanic,
+ // setting handled and deferring catchPanic
// must happen before calling the method.
switch v := p.arg.(type) {
case error:
- wasString = false
handled = true
defer p.catchPanic(p.arg, verb)
- p.printArg(v.Error(), verb, plus, false, depth)
+ p.printArg(v.Error(), verb, depth)
return
case Stringer:
- wasString = false
handled = true
defer p.catchPanic(p.arg, verb)
- p.printArg(v.String(), verb, plus, false, depth)
+ p.printArg(v.String(), verb, depth)
return
}
}
}
- handled = false
- return
+ return false
}
-func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+func (p *pp) printArg(arg interface{}, verb rune, depth int) (wasString bool) {
p.arg = arg
p.value = reflect.Value{}
@@ -722,26 +742,13 @@ func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int
// %T (the value's type) and %p (its address) are special; we always do them first.
switch verb {
case 'T':
- p.printArg(reflect.TypeOf(arg).String(), 's', false, false, 0)
+ p.printArg(reflect.TypeOf(arg).String(), 's', 0)
return false
case 'p':
- p.fmtPointer(reflect.ValueOf(arg), verb, goSyntax)
+ p.fmtPointer(reflect.ValueOf(arg), verb)
return false
}
- // Clear flags for base formatters.
- // handleMethods needs them, so we must restore them later.
- // We could call handleMethods here and avoid this work, but
- // handleMethods is expensive enough to be worth delaying.
- oldPlus := p.fmt.plus
- oldSharp := p.fmt.sharp
- if plus {
- p.fmt.plus = false
- }
- if goSyntax {
- p.fmt.sharp = false
- }
-
// Some types can be done without reflection.
switch f := arg.(type) {
case bool:
@@ -765,40 +772,37 @@ func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int
case int64:
p.fmtInt64(f, verb)
case uint:
- p.fmtUint64(uint64(f), verb, goSyntax)
+ p.fmtUint64(uint64(f), verb)
case uint8:
- p.fmtUint64(uint64(f), verb, goSyntax)
+ p.fmtUint64(uint64(f), verb)
case uint16:
- p.fmtUint64(uint64(f), verb, goSyntax)
+ p.fmtUint64(uint64(f), verb)
case uint32:
- p.fmtUint64(uint64(f), verb, goSyntax)
+ p.fmtUint64(uint64(f), verb)
case uint64:
- p.fmtUint64(f, verb, goSyntax)
+ p.fmtUint64(f, verb)
case uintptr:
- p.fmtUint64(uint64(f), verb, goSyntax)
+ p.fmtUint64(uint64(f), verb)
case string:
- p.fmtString(f, verb, goSyntax)
+ p.fmtString(f, verb)
wasString = verb == 's' || verb == 'v'
case []byte:
- p.fmtBytes(f, verb, goSyntax, nil, depth)
+ p.fmtBytes(f, verb, nil, depth)
wasString = verb == 's'
default:
- // Restore flags in case handleMethods finds a Formatter.
- p.fmt.plus = oldPlus
- p.fmt.sharp = oldSharp
// If the type is not simple, it might have methods.
- if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
- return isString
+ if handled := p.handleMethods(verb, depth); handled {
+ return false
}
// Need to use reflection
- return p.printReflectValue(reflect.ValueOf(arg), verb, plus, goSyntax, depth)
+ return p.printReflectValue(reflect.ValueOf(arg), verb, depth)
}
p.arg = nil
return
}
// printValue is like printArg but starts with a reflect value, not an interface{} value.
-func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+func (p *pp) printValue(value reflect.Value, verb rune, depth int) (wasString bool) {
if !value.IsValid() {
if verb == 'T' || verb == 'v' {
p.buf.Write(nilAngleBytes)
@@ -812,10 +816,10 @@ func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, dep
// %T (the value's type) and %p (its address) are special; we always do them first.
switch verb {
case 'T':
- p.printArg(value.Type().String(), 's', false, false, 0)
+ p.printArg(value.Type().String(), 's', 0)
return false
case 'p':
- p.fmtPointer(value, verb, goSyntax)
+ p.fmtPointer(value, verb)
return false
}
@@ -825,16 +829,18 @@ func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, dep
if value.CanInterface() {
p.arg = value.Interface()
}
- if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
- return isString
+ if handled := p.handleMethods(verb, depth); handled {
+ return false
}
- return p.printReflectValue(value, verb, plus, goSyntax, depth)
+ return p.printReflectValue(value, verb, depth)
}
+var byteType = reflect.TypeOf(byte(0))
+
// printReflectValue is the fallback for both printArg and printValue.
// It uses reflect to print the value.
-func (p *pp) printReflectValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+func (p *pp) printReflectValue(value reflect.Value, verb rune, depth int) (wasString bool) {
oldValue := p.value
p.value = value
BigSwitch:
@@ -844,7 +850,7 @@ BigSwitch:
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p.fmtInt64(f.Int(), verb)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- p.fmtUint64(f.Uint(), verb, goSyntax)
+ p.fmtUint64(f.Uint(), verb)
case reflect.Float32, reflect.Float64:
if f.Type().Size() == 4 {
p.fmtFloat32(float32(f.Float()), verb)
@@ -858,9 +864,9 @@ BigSwitch:
p.fmtComplex128(f.Complex(), verb)
}
case reflect.String:
- p.fmtString(f.String(), verb, goSyntax)
+ p.fmtString(f.String(), verb)
case reflect.Map:
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteString(f.Type().String())
if f.IsNil() {
p.buf.WriteString("(nil)")
@@ -873,23 +879,23 @@ BigSwitch:
keys := f.MapKeys()
for i, key := range keys {
if i > 0 {
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.Write(commaSpaceBytes)
} else {
p.buf.WriteByte(' ')
}
}
- p.printValue(key, verb, plus, goSyntax, depth+1)
+ p.printValue(key, verb, depth+1)
p.buf.WriteByte(':')
- p.printValue(f.MapIndex(key), verb, plus, goSyntax, depth+1)
+ p.printValue(f.MapIndex(key), verb, depth+1)
}
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteByte('}')
} else {
p.buf.WriteByte(']')
}
case reflect.Struct:
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteString(value.Type().String())
}
p.add('{')
@@ -897,36 +903,40 @@ BigSwitch:
t := v.Type()
for i := 0; i < v.NumField(); i++ {
if i > 0 {
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.Write(commaSpaceBytes)
} else {
p.buf.WriteByte(' ')
}
}
- if plus || goSyntax {
+ if p.fmt.plusV || p.fmt.sharpV {
if f := t.Field(i); f.Name != "" {
p.buf.WriteString(f.Name)
p.buf.WriteByte(':')
}
}
- p.printValue(getField(v, i), verb, plus, goSyntax, depth+1)
+ p.printValue(getField(v, i), verb, depth+1)
}
p.buf.WriteByte('}')
case reflect.Interface:
value := f.Elem()
if !value.IsValid() {
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteString(f.Type().String())
p.buf.Write(nilParenBytes)
} else {
p.buf.Write(nilAngleBytes)
}
} else {
- wasString = p.printValue(value, verb, plus, goSyntax, depth+1)
+ wasString = p.printValue(value, verb, depth+1)
}
case reflect.Array, reflect.Slice:
- // Byte slices are special.
- if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 {
+ // Byte slices are special:
+ // - Handle []byte (== []uint8) with fmtBytes.
+ // - Handle []T, where T is a named byte type, with fmtBytes only
+ // for the s, q, an x verbs. For other verbs, T might be a
+ // Stringer, so we use printValue to print each element.
+ if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 && (typ.Elem() == byteType || verb == 's' || verb == 'q' || verb == 'x') {
var bytes []byte
if f.Kind() == reflect.Slice {
bytes = f.Bytes()
@@ -941,11 +951,11 @@ BigSwitch:
bytes[i] = byte(f.Index(i).Uint())
}
}
- p.fmtBytes(bytes, verb, goSyntax, typ, depth)
+ p.fmtBytes(bytes, verb, typ, depth)
wasString = verb == 's'
break
}
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteString(value.Type().String())
if f.Kind() == reflect.Slice && f.IsNil() {
p.buf.WriteString("(nil)")
@@ -957,15 +967,15 @@ BigSwitch:
}
for i := 0; i < f.Len(); i++ {
if i > 0 {
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.Write(commaSpaceBytes)
} else {
p.buf.WriteByte(' ')
}
}
- p.printValue(f.Index(i), verb, plus, goSyntax, depth+1)
+ p.printValue(f.Index(i), verb, depth+1)
}
- if goSyntax {
+ if p.fmt.sharpV {
p.buf.WriteByte('}')
} else {
p.buf.WriteByte(']')
@@ -978,17 +988,21 @@ BigSwitch:
switch a := f.Elem(); a.Kind() {
case reflect.Array, reflect.Slice:
p.buf.WriteByte('&')
- p.printValue(a, verb, plus, goSyntax, depth+1)
+ p.printValue(a, verb, depth+1)
break BigSwitch
case reflect.Struct:
p.buf.WriteByte('&')
- p.printValue(a, verb, plus, goSyntax, depth+1)
+ p.printValue(a, verb, depth+1)
+ break BigSwitch
+ case reflect.Map:
+ p.buf.WriteByte('&')
+ p.printValue(a, verb, depth+1)
break BigSwitch
}
}
fallthrough
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
- p.fmtPointer(value, verb, goSyntax)
+ p.fmtPointer(value, verb)
default:
p.unknownType(f)
}
@@ -1154,9 +1168,19 @@ func (p *pp) doPrintf(format string, a []interface{}) {
arg := a[argNum]
argNum++
- goSyntax := c == 'v' && p.fmt.sharp
- plus := c == 'v' && p.fmt.plus
- p.printArg(arg, c, plus, goSyntax, 0)
+ if c == 'v' {
+ if p.fmt.sharp {
+ // Go syntax. Set the flag in the fmt and clear the sharp flag.
+ p.fmt.sharp = false
+ p.fmt.sharpV = true
+ }
+ if p.fmt.plus {
+ // Struct-field syntax. Set the flag in the fmt and clear the plus flag.
+ p.fmt.plus = false
+ p.fmt.plusV = true
+ }
+ }
+ p.printArg(arg, c, 0)
}
// Check for extra arguments unless the call accessed the arguments
@@ -1170,7 +1194,7 @@ func (p *pp) doPrintf(format string, a []interface{}) {
p.buf.WriteString(reflect.TypeOf(arg).String())
p.buf.WriteByte('=')
}
- p.printArg(arg, 'v', false, false, 0)
+ p.printArg(arg, 'v', 0)
if argNum+1 < len(a) {
p.buf.Write(commaSpaceBytes)
}
@@ -1191,7 +1215,7 @@ func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) {
p.buf.WriteByte(' ')
}
}
- prevString = p.printArg(arg, 'v', false, false, 0)
+ prevString = p.printArg(arg, 'v', 0)
}
if addnewline {
p.buf.WriteByte('\n')
diff --git a/src/pkg/fmt/scan.go b/src/fmt/scan.go
index 8a337e479..d7befeae4 100644
--- a/src/pkg/fmt/scan.go
+++ b/src/fmt/scan.go
@@ -360,6 +360,7 @@ func (r *readRune) ReadRune() (rr rune, size int, err error) {
}
if r.buf[0] < utf8.RuneSelf { // fast check for common ASCII case
rr = rune(r.buf[0])
+ size = 1 // Known to be 1.
return
}
var n int
diff --git a/src/pkg/fmt/scan_test.go b/src/fmt/scan_test.go
index d903f0c3f..541e12df2 100644
--- a/src/pkg/fmt/scan_test.go
+++ b/src/fmt/scan_test.go
@@ -842,6 +842,38 @@ func TestLineByLineFscanf(t *testing.T) {
}
}
+// TestScanStateCount verifies the correct byte count is returned. Issue 8512.
+
+// runeScanner implements the Scanner interface for TestScanStateCount.
+type runeScanner struct {
+ rune rune
+ size int
+}
+
+func (rs *runeScanner) Scan(state ScanState, verb rune) error {
+ r, size, err := state.ReadRune()
+ rs.rune = r
+ rs.size = size
+ return err
+}
+
+func TestScanStateCount(t *testing.T) {
+ var a, b, c runeScanner
+ n, err := Sscanf("12➂", "%c%c%c", &a, &b, &c)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if n != 3 {
+ t.Fatalf("expected 3 items consumed, got %d")
+ }
+ if a.rune != '1' || b.rune != '2' || c.rune != '➂' {
+ t.Errorf("bad scan rune: %q %q %q should be '1' '2' '➂'", a.rune, b.rune, c.rune)
+ }
+ if a.size != 1 || b.size != 1 || c.size != 3 {
+ t.Errorf("bad scan size: %q %q %q should be 1 1 3", a.size, b.size, c.size)
+ }
+}
+
// RecursiveInt accepts a string matching %d.%d.%d....
// and parses it into a linked list.
// It allows us to benchmark recursive descent style scanners.
diff --git a/src/pkg/fmt/stringer_test.go b/src/fmt/stringer_test.go
index 0ca3f522d..0ca3f522d 100644
--- a/src/pkg/fmt/stringer_test.go
+++ b/src/fmt/stringer_test.go
diff --git a/src/pkg/go/ast/ast.go b/src/go/ast/ast.go
index 6e635cd01..312e3d1b9 100644
--- a/src/pkg/go/ast/ast.go
+++ b/src/go/ast/ast.go
@@ -699,9 +699,9 @@ type (
// A RangeStmt represents a for statement with a range clause.
RangeStmt struct {
For token.Pos // position of "for" keyword
- Key, Value Expr // Value may be nil
- TokPos token.Pos // position of Tok
- Tok token.Token // ASSIGN, DEFINE
+ Key, Value Expr // Key, Value may be nil
+ TokPos token.Pos // position of Tok; invalid if Key == nil
+ Tok token.Token // ILLEGAL if Key == nil, ASSIGN, DEFINE
X Expr // value to range over
Body *BlockStmt
}
diff --git a/src/pkg/go/ast/ast_test.go b/src/go/ast/ast_test.go
index 1a6a283f2..1a6a283f2 100644
--- a/src/pkg/go/ast/ast_test.go
+++ b/src/go/ast/ast_test.go
diff --git a/src/pkg/go/ast/commentmap.go b/src/go/ast/commentmap.go
index ac999d627..ac999d627 100644
--- a/src/pkg/go/ast/commentmap.go
+++ b/src/go/ast/commentmap.go
diff --git a/src/pkg/go/ast/commentmap_test.go b/src/go/ast/commentmap_test.go
index e372eab74..e372eab74 100644
--- a/src/pkg/go/ast/commentmap_test.go
+++ b/src/go/ast/commentmap_test.go
diff --git a/src/pkg/go/ast/example_test.go b/src/go/ast/example_test.go
index d2e734f2c..d2e734f2c 100644
--- a/src/pkg/go/ast/example_test.go
+++ b/src/go/ast/example_test.go
diff --git a/src/pkg/go/ast/filter.go b/src/go/ast/filter.go
index fc3eeb4a1..fc3eeb4a1 100644
--- a/src/pkg/go/ast/filter.go
+++ b/src/go/ast/filter.go
diff --git a/src/pkg/go/ast/filter_test.go b/src/go/ast/filter_test.go
index 9fd86cb46..9fd86cb46 100644
--- a/src/pkg/go/ast/filter_test.go
+++ b/src/go/ast/filter_test.go
diff --git a/src/pkg/go/ast/import.go b/src/go/ast/import.go
index d2770d16c..d2770d16c 100644
--- a/src/pkg/go/ast/import.go
+++ b/src/go/ast/import.go
diff --git a/src/pkg/go/ast/print.go b/src/go/ast/print.go
index f15dc11dc..f15dc11dc 100644
--- a/src/pkg/go/ast/print.go
+++ b/src/go/ast/print.go
diff --git a/src/pkg/go/ast/print_test.go b/src/go/ast/print_test.go
index 210f16430..210f16430 100644
--- a/src/pkg/go/ast/print_test.go
+++ b/src/go/ast/print_test.go
diff --git a/src/pkg/go/ast/resolve.go b/src/go/ast/resolve.go
index 0406bfc58..0406bfc58 100644
--- a/src/pkg/go/ast/resolve.go
+++ b/src/go/ast/resolve.go
diff --git a/src/pkg/go/ast/scope.go b/src/go/ast/scope.go
index 8df5b2c65..df1529d18 100644
--- a/src/pkg/go/ast/scope.go
+++ b/src/go/ast/scope.go
@@ -80,7 +80,7 @@ type Object struct {
Name string // declared name
Decl interface{} // corresponding Field, XxxSpec, FuncDecl, LabeledStmt, AssignStmt, Scope; or nil
Data interface{} // object-specific data; or nil
- Type interface{} // place holder for type information; may be nil
+ Type interface{} // placeholder for type information; may be nil
}
// NewObj creates a new object of a given kind and name.
diff --git a/src/pkg/go/ast/walk.go b/src/go/ast/walk.go
index fedffb3f2..73ac38647 100644
--- a/src/pkg/go/ast/walk.go
+++ b/src/go/ast/walk.go
@@ -275,7 +275,9 @@ func Walk(v Visitor, node Node) {
Walk(v, n.Body)
case *RangeStmt:
- Walk(v, n.Key)
+ if n.Key != nil {
+ Walk(v, n.Key)
+ }
if n.Value != nil {
Walk(v, n.Value)
}
diff --git a/src/pkg/go/build/build.go b/src/go/build/build.go
index 412abea3a..311ecb01f 100644
--- a/src/pkg/go/build/build.go
+++ b/src/go/build/build.go
@@ -23,6 +23,7 @@ import (
"strconv"
"strings"
"unicode"
+ "unicode/utf8"
)
// A Context specifies the supporting context for a build.
@@ -206,9 +207,7 @@ func (ctxt *Context) gopath() []string {
if p == "" || p == ctxt.GOROOT {
// Empty paths are uninteresting.
// If the path is the GOROOT, ignore it.
- // People sometimes set GOPATH=$GOROOT, which is useless
- // but would cause us to find packages with import paths
- // like "pkg/math".
+ // People sometimes set GOPATH=$GOROOT.
// Do not get confused by this common mistake.
continue
}
@@ -238,7 +237,7 @@ func (ctxt *Context) gopath() []string {
func (ctxt *Context) SrcDirs() []string {
var all []string
if ctxt.GOROOT != "" {
- dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg")
+ dir := ctxt.joinPath(ctxt.GOROOT, "src")
if ctxt.isDir(dir) {
all = append(all, dir)
}
@@ -268,6 +267,9 @@ var cgoEnabled = map[string]bool{
"linux/386": true,
"linux/amd64": true,
"linux/arm": true,
+ "android/386": true,
+ "android/amd64": true,
+ "android/arm": true,
"netbsd/386": true,
"netbsd/amd64": true,
"netbsd/arm": true,
@@ -292,10 +294,10 @@ func defaultContext() Context {
// 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".
//
- // When we reach Go 1.4 the line will read
- // c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4"}
+ // When we reach Go 1.5 the line will read
+ // c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5"}
// and so on.
- c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3"}
+ c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4"}
switch os.Getenv("CGO_ENABLED") {
case "1":
@@ -334,22 +336,29 @@ const (
// If AllowBinary is set, Import can be satisfied by a compiled
// package object without corresponding sources.
AllowBinary
+
+ // If ImportComment is set, parse import comments on package statements.
+ // Import returns an error if it finds a comment it cannot understand
+ // or finds conflicting comments in multiple source files.
+ // See golang.org/s/go14customimport for more information.
+ ImportComment
)
// A Package describes the Go package found in a directory.
type Package struct {
- Dir string // directory containing package sources
- Name string // package name
- Doc string // documentation synopsis
- ImportPath string // import path of package ("" if unknown)
- Root string // root of Go tree where this package lives
- SrcRoot string // package source root directory ("" if unknown)
- PkgRoot string // package install root directory ("" if unknown)
- BinDir string // command install directory ("" if unknown)
- Goroot bool // package found in Go root
- PkgObj string // installed .a file
- AllTags []string // tags that can influence file selection in this directory
- ConflictDir string // this directory shadows Dir in $GOPATH
+ Dir string // directory containing package sources
+ Name string // package name
+ ImportComment string // path in import comment on package statement
+ Doc string // documentation synopsis
+ ImportPath string // import path of package ("" if unknown)
+ Root string // root of Go tree where this package lives
+ SrcRoot string // package source root directory ("" if unknown)
+ PkgRoot string // package install root directory ("" if unknown)
+ BinDir string // command install directory ("" if unknown)
+ Goroot bool // package found in Go root
+ PkgObj string // installed .a file
+ AllTags []string // tags that can influence file selection in this directory
+ ConflictDir string // this directory shadows Dir in $GOPATH
// Source files
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
@@ -408,6 +417,19 @@ func (e *NoGoError) Error() string {
return "no buildable Go source files in " + e.Dir
}
+// MultiplePackageError describes a directory containing
+// multiple buildable Go source files for multiple packages.
+type MultiplePackageError struct {
+ Dir string // directory containing files
+ Packages []string // package names found
+ Files []string // corresponding files: Files[i] declares package Packages[i]
+}
+
+func (e *MultiplePackageError) Error() string {
+ // Error string limited to two entries for compatibility.
+ return fmt.Sprintf("found packages %s (%s) and %s (%s) in %s", e.Packages[0], e.Files[0], e.Packages[1], e.Files[1], e.Dir)
+}
+
func nameExt(name string) string {
i := strings.LastIndex(name, ".")
if i < 0 {
@@ -468,7 +490,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
}
// Determine canonical import path, if any.
if ctxt.GOROOT != "" {
- root := ctxt.joinPath(ctxt.GOROOT, "src", "pkg")
+ root := ctxt.joinPath(ctxt.GOROOT, "src")
if sub, ok := ctxt.hasSubdir(root, p.Dir); ok {
p.Goroot = true
p.ImportPath = sub
@@ -484,7 +506,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
// but check that using it wouldn't find something
// else first.
if ctxt.GOROOT != "" {
- if dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", sub); ctxt.isDir(dir) {
+ if dir := ctxt.joinPath(ctxt.GOROOT, "src", sub); ctxt.isDir(dir) {
p.ConflictDir = dir
goto Found
}
@@ -518,7 +540,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
// Determine directory from import path.
if ctxt.GOROOT != "" {
- dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", path)
+ dir := ctxt.joinPath(ctxt.GOROOT, "src", path)
isDir := ctxt.isDir(dir)
binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga))
if isDir || binaryOnly {
@@ -564,11 +586,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
Found:
if p.Root != "" {
- if p.Goroot {
- p.SrcRoot = ctxt.joinPath(p.Root, "src", "pkg")
- } else {
- p.SrcRoot = ctxt.joinPath(p.Root, "src")
- }
+ p.SrcRoot = ctxt.joinPath(p.Root, "src")
p.PkgRoot = ctxt.joinPath(p.Root, "pkg")
p.BinDir = ctxt.joinPath(p.Root, "bin")
if pkga != "" {
@@ -589,7 +607,7 @@ Found:
}
var Sfiles []string // files with ".S" (capital S)
- var firstFile string
+ var firstFile, firstCommentFile string
imported := make(map[string][]token.Position)
testImported := make(map[string][]token.Position)
xTestImported := make(map[string][]token.Position)
@@ -670,12 +688,28 @@ Found:
p.Name = pkg
firstFile = name
} else if pkg != p.Name {
- return p, fmt.Errorf("found packages %s (%s) and %s (%s) in %s", p.Name, firstFile, pkg, name, p.Dir)
+ return p, &MultiplePackageError{p.Dir, []string{firstFile, name}, []string{p.Name, pkg}}
}
if pf.Doc != nil && p.Doc == "" {
p.Doc = doc.Synopsis(pf.Doc.Text())
}
+ if mode&ImportComment != 0 {
+ qcom, line := findImportComment(data)
+ 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 == "" {
+ 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)
+ }
+ }
+ }
+
// Record imports and information about cgo.
isCgo := false
for _, decl := range pf.Decls {
@@ -756,6 +790,117 @@ Found:
return p, pkgerr
}
+func findImportComment(data []byte) (s string, line int) {
+ // expect keyword package
+ word, data := parseWord(data)
+ if string(word) != "package" {
+ return "", 0
+ }
+
+ // expect package name
+ _, data = parseWord(data)
+
+ // now ready for import comment, a // or /* */ comment
+ // beginning and ending on the current line.
+ for len(data) > 0 && (data[0] == ' ' || data[0] == '\t' || data[0] == '\r') {
+ data = data[1:]
+ }
+
+ var comment []byte
+ switch {
+ case bytes.HasPrefix(data, slashSlash):
+ i := bytes.Index(data, newline)
+ if i < 0 {
+ i = len(data)
+ }
+ comment = data[2:i]
+ case bytes.HasPrefix(data, slashStar):
+ data = data[2:]
+ i := bytes.Index(data, starSlash)
+ if i < 0 {
+ // malformed comment
+ return "", 0
+ }
+ comment = data[:i]
+ if bytes.Contains(comment, newline) {
+ return "", 0
+ }
+ }
+ comment = bytes.TrimSpace(comment)
+
+ // split comment into `import`, `"pkg"`
+ word, arg := parseWord(comment)
+ if string(word) != "import" {
+ return "", 0
+ }
+
+ line = 1 + bytes.Count(data[:cap(data)-cap(arg)], newline)
+ return strings.TrimSpace(string(arg)), line
+}
+
+var (
+ slashSlash = []byte("//")
+ slashStar = []byte("/*")
+ starSlash = []byte("*/")
+ newline = []byte("\n")
+)
+
+// skipSpaceOrComment returns data with any leading spaces or comments removed.
+func skipSpaceOrComment(data []byte) []byte {
+ for len(data) > 0 {
+ switch data[0] {
+ case ' ', '\t', '\r', '\n':
+ data = data[1:]
+ continue
+ case '/':
+ if bytes.HasPrefix(data, slashSlash) {
+ i := bytes.Index(data, newline)
+ if i < 0 {
+ return nil
+ }
+ data = data[i+1:]
+ continue
+ }
+ if bytes.HasPrefix(data, slashStar) {
+ data = data[2:]
+ i := bytes.Index(data, starSlash)
+ if i < 0 {
+ return nil
+ }
+ data = data[i+2:]
+ continue
+ }
+ }
+ break
+ }
+ return data
+}
+
+// parseWord skips any leading spaces or comments in data
+// and then parses the beginning of data as an identifier or keyword,
+// returning that word and what remains after the word.
+func parseWord(data []byte) (word, rest []byte) {
+ data = skipSpaceOrComment(data)
+
+ // Parse past leading word characters.
+ rest = data
+ for {
+ r, size := utf8.DecodeRune(rest)
+ if unicode.IsLetter(r) || '0' <= r && r <= '9' || r == '_' {
+ rest = rest[size:]
+ continue
+ }
+ break
+ }
+
+ word = data[:len(data)-len(rest)]
+ if len(word) == 0 {
+ return nil, nil
+ }
+
+ return word, rest
+}
+
// MatchFile reports whether the file with the given name in the given directory
// matches the context and would be included in a Package created by ImportDir
// of that directory.
@@ -1124,6 +1269,9 @@ func (ctxt *Context) match(name string, allTags map[string]bool) bool {
if name == ctxt.GOOS || name == ctxt.GOARCH || name == ctxt.Compiler {
return true
}
+ if ctxt.GOOS == "android" && name == "linux" {
+ return true
+ }
// other tags
for _, tag := range ctxt.BuildTags {
@@ -1151,10 +1299,25 @@ func (ctxt *Context) match(name string, allTags map[string]bool) bool {
// name_$(GOARCH)_test.*
// name_$(GOOS)_$(GOARCH)_test.*
//
+// An exception: if GOOS=android, then files with GOOS=linux are also matched.
func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool {
if dot := strings.Index(name, "."); dot != -1 {
name = name[:dot]
}
+
+ // Before Go 1.4, a file called "linux.go" would be equivalent to having a
+ // build tag "linux" in that file. For Go 1.4 and beyond, we require this
+ // auto-tagging to apply only to files with a non-empty prefix, so
+ // "foo_linux.go" is tagged but "linux.go" is not. This allows new operating
+ // sytems, such as android, to arrive without breaking existing code with
+ // innocuous source code in "android.go". The easiest fix: cut everything
+ // in the name before the initial _.
+ i := strings.Index(name, "_")
+ if i < 0 {
+ return true
+ }
+ name = name[i:] // ignore everything before first _
+
l := strings.Split(name, "_")
if n := len(l); n > 0 && l[n-1] == "test" {
l = l[:n-1]
@@ -1165,12 +1328,21 @@ func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool {
allTags[l[n-2]] = true
allTags[l[n-1]] = true
}
- return l[n-2] == ctxt.GOOS && l[n-1] == ctxt.GOARCH
+ if l[n-1] != ctxt.GOARCH {
+ return false
+ }
+ if ctxt.GOOS == "android" && l[n-2] == "linux" {
+ return true
+ }
+ return l[n-2] == ctxt.GOOS
}
if n >= 1 && knownOS[l[n-1]] {
if allTags != nil {
allTags[l[n-1]] = true
}
+ if ctxt.GOOS == "android" && l[n-1] == "linux" {
+ return true
+ }
return l[n-1] == ctxt.GOOS
}
if n >= 1 && knownArch[l[n-1]] {
diff --git a/src/pkg/go/build/build_test.go b/src/go/build/build_test.go
index fca8d4bdb..a40def0fa 100644
--- a/src/pkg/go/build/build_test.go
+++ b/src/go/build/build_test.go
@@ -85,6 +85,20 @@ func TestEmptyImport(t *testing.T) {
}
}
+func TestEmptyFolderImport(t *testing.T) {
+ _, err := Import(".", "testdata/empty", 0)
+ if _, ok := err.(*NoGoError); !ok {
+ t.Fatal(`Import("testdata/empty") did not return NoGoError.`)
+ }
+}
+
+func TestMultiplePackageImport(t *testing.T) {
+ _, err := Import(".", "testdata/multi", 0)
+ if _, ok := err.(*MultiplePackageError); !ok {
+ t.Fatal(`Import("testdata/multi") did not return MultiplePackageError.`)
+ }
+}
+
func TestLocalDirectory(t *testing.T) {
cwd, err := os.Getwd()
if err != nil {
@@ -153,22 +167,36 @@ func (r readNopCloser) Close() error {
return nil
}
+var (
+ ctxtP9 = Context{GOARCH: "arm", GOOS: "plan9"}
+ ctxtAndroid = Context{GOARCH: "arm", GOOS: "android"}
+)
+
var matchFileTests = []struct {
+ ctxt Context
name string
data string
match bool
}{
- {"foo_arm.go", "", true},
- {"foo1_arm.go", "// +build linux\n\npackage main\n", false},
- {"foo_darwin.go", "", false},
- {"foo.go", "", true},
- {"foo1.go", "// +build linux\n\npackage main\n", false},
- {"foo.badsuffix", "", false},
+ {ctxtP9, "foo_arm.go", "", true},
+ {ctxtP9, "foo1_arm.go", "// +build linux\n\npackage main\n", false},
+ {ctxtP9, "foo_darwin.go", "", false},
+ {ctxtP9, "foo.go", "", true},
+ {ctxtP9, "foo1.go", "// +build linux\n\npackage main\n", false},
+ {ctxtP9, "foo.badsuffix", "", false},
+ {ctxtAndroid, "foo_linux.go", "", true},
+ {ctxtAndroid, "foo_android.go", "", true},
+ {ctxtAndroid, "foo_plan9.go", "", false},
+ {ctxtAndroid, "android.go", "", true},
+ {ctxtAndroid, "plan9.go", "", true},
+ {ctxtAndroid, "plan9_test.go", "", true},
+ {ctxtAndroid, "arm.s", "", true},
+ {ctxtAndroid, "amd64.s", "", true},
}
func TestMatchFile(t *testing.T) {
for _, tt := range matchFileTests {
- ctxt := Context{GOARCH: "arm", GOOS: "plan9"}
+ ctxt := tt.ctxt
ctxt.OpenFile = func(path string) (r io.ReadCloser, err error) {
if path != "x+"+tt.name {
t.Fatalf("OpenFile asked for %q, expected %q", path, "x+"+tt.name)
@@ -184,3 +212,13 @@ func TestMatchFile(t *testing.T) {
}
}
}
+
+func TestImportCmd(t *testing.T) {
+ p, err := Import("cmd/internal/objfile", "", 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !strings.HasSuffix(filepath.ToSlash(p.Dir), "src/cmd/internal/objfile") {
+ t.Fatalf("Import cmd/internal/objfile returned Dir=%q, want %q", filepath.ToSlash(p.Dir), ".../src/cmd/internal/objfile")
+ }
+}
diff --git a/src/pkg/go/build/deps_test.go b/src/go/build/deps_test.go
index 7421e144f..b74595ea8 100644
--- a/src/pkg/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -279,12 +279,12 @@ var pkgDeps = map[string][]string{
// Random byte, number generation.
// This would be part of core crypto except that it imports
// math/big, which imports fmt.
- "crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall"},
+ "crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall", "internal/syscall"},
// Mathematical crypto: dependencies on fmt (L4) and math/big.
// We could avoid some of the fmt, but math/big imports fmt anyway.
"crypto/dsa": {"L4", "CRYPTO", "math/big"},
- "crypto/ecdsa": {"L4", "CRYPTO", "crypto/elliptic", "math/big"},
+ "crypto/ecdsa": {"L4", "CRYPTO", "crypto/elliptic", "math/big", "encoding/asn1"},
"crypto/elliptic": {"L4", "CRYPTO", "math/big"},
"crypto/rsa": {"L4", "CRYPTO", "crypto/rand", "math/big"},
@@ -318,6 +318,7 @@ var pkgDeps = map[string][]string{
"net/http": {
"L4", "NET", "OS",
"compress/gzip", "crypto/tls", "mime/multipart", "runtime/debug",
+ "net/http/internal",
},
// HTTP-using packages.
@@ -325,9 +326,9 @@ var pkgDeps = map[string][]string{
"net/http/cgi": {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"},
"net/http/fcgi": {"L4", "NET", "OS", "net/http", "net/http/cgi"},
"net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http"},
- "net/http/httputil": {"L4", "NET", "OS", "net/http"},
+ "net/http/httputil": {"L4", "NET", "OS", "net/http", "net/http/internal"},
"net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof"},
- "net/rpc": {"L4", "NET", "encoding/gob", "net/http", "text/template"},
+ "net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"},
"net/rpc/jsonrpc": {"L4", "NET", "encoding/json", "net/rpc"},
}
@@ -360,7 +361,7 @@ func allowed(pkg string) map[string]bool {
}
var bools = []bool{false, true}
-var geese = []string{"darwin", "dragonfly", "freebsd", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows"}
+var geese = []string{"android", "darwin", "dragonfly", "freebsd", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows"}
var goarches = []string{"386", "amd64", "arm"}
type osPkg struct {
diff --git a/src/pkg/go/build/doc.go b/src/go/build/doc.go
index f17f76ccc..75a827bb9 100644
--- a/src/pkg/go/build/doc.go
+++ b/src/go/build/doc.go
@@ -100,6 +100,7 @@
// - "go1.1", from Go version 1.1 onward
// - "go1.2", from Go version 1.2 onward
// - "go1.3", from Go version 1.3 onward
+// - "go1.4", from Go version 1.4 onward
// - any additional words listed in ctxt.BuildTags
//
// If a file's name, after stripping the extension and a possible _test suffix,
@@ -107,12 +108,10 @@
// *_GOOS
// *_GOARCH
// *_GOOS_GOARCH
-// (example: source_windows_amd64.go) or the literals:
-// GOOS
-// GOARCH
-// (example: windows.go) where GOOS and GOARCH represent any known operating
-// system and architecture values respectively, then the file is considered to
-// have an implicit build constraint requiring those terms.
+// (example: source_windows_amd64.go) where GOOS and GOARCH represent
+// any known operating system and architecture values respectively, then
+// the file is considered to have an implicit build constraint requiring
+// those terms.
//
// To keep a file from being considered for the build:
//
@@ -134,4 +133,7 @@
// building the package for Windows; similarly, math_386.s will be included
// only when building the package for 32-bit x86.
//
+// Using GOOS=android matches build tags and files as for GOOS=linux
+// in addition to android tags and files.
+//
package build
diff --git a/src/pkg/go/build/read.go b/src/go/build/read.go
index c8079dfd1..c8079dfd1 100644
--- a/src/pkg/go/build/read.go
+++ b/src/go/build/read.go
diff --git a/src/pkg/go/build/read_test.go b/src/go/build/read_test.go
index 2dcc1208f..2dcc1208f 100644
--- a/src/pkg/go/build/read_test.go
+++ b/src/go/build/read_test.go
diff --git a/src/pkg/go/build/syslist.go b/src/go/build/syslist.go
index 5c42b946b..965f873df 100644
--- a/src/pkg/go/build/syslist.go
+++ b/src/go/build/syslist.go
@@ -4,5 +4,5 @@
package build
-const goosList = "darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows "
+const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows "
const goarchList = "386 amd64 amd64p32 arm "
diff --git a/src/pkg/go/build/syslist_test.go b/src/go/build/syslist_test.go
index 3be2928f5..3be2928f5 100644
--- a/src/pkg/go/build/syslist_test.go
+++ b/src/go/build/syslist_test.go
diff --git a/src/go/build/testdata/empty/dummy b/src/go/build/testdata/empty/dummy
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/go/build/testdata/empty/dummy
diff --git a/src/go/build/testdata/multi/file.go b/src/go/build/testdata/multi/file.go
new file mode 100644
index 000000000..ee946eb2a
--- /dev/null
+++ b/src/go/build/testdata/multi/file.go
@@ -0,0 +1,5 @@
+// Test data - not compiled.
+
+package main
+
+func main() {}
diff --git a/src/go/build/testdata/multi/file_appengine.go b/src/go/build/testdata/multi/file_appengine.go
new file mode 100644
index 000000000..4ea31e703
--- /dev/null
+++ b/src/go/build/testdata/multi/file_appengine.go
@@ -0,0 +1,5 @@
+// Test data - not compiled.
+
+package test_package
+
+func init() {}
diff --git a/src/pkg/go/build/testdata/other/file/file.go b/src/go/build/testdata/other/file/file.go
index bbfd3e9e5..bbfd3e9e5 100644
--- a/src/pkg/go/build/testdata/other/file/file.go
+++ b/src/go/build/testdata/other/file/file.go
diff --git a/src/pkg/go/build/testdata/other/main.go b/src/go/build/testdata/other/main.go
index e0904357c..e0904357c 100644
--- a/src/pkg/go/build/testdata/other/main.go
+++ b/src/go/build/testdata/other/main.go
diff --git a/src/pkg/go/doc/Makefile b/src/go/doc/Makefile
index ca4948f91..ca4948f91 100644
--- a/src/pkg/go/doc/Makefile
+++ b/src/go/doc/Makefile
diff --git a/src/pkg/go/doc/comment.go b/src/go/doc/comment.go
index f414ca409..f414ca409 100644
--- a/src/pkg/go/doc/comment.go
+++ b/src/go/doc/comment.go
diff --git a/src/pkg/go/doc/comment_test.go b/src/go/doc/comment_test.go
index ad65c2a27..ad65c2a27 100644
--- a/src/pkg/go/doc/comment_test.go
+++ b/src/go/doc/comment_test.go
diff --git a/src/pkg/go/doc/doc.go b/src/go/doc/doc.go
index 4264940a0..4264940a0 100644
--- a/src/pkg/go/doc/doc.go
+++ b/src/go/doc/doc.go
diff --git a/src/pkg/go/doc/doc_test.go b/src/go/doc/doc_test.go
index ad8ba5378..ad8ba5378 100644
--- a/src/pkg/go/doc/doc_test.go
+++ b/src/go/doc/doc_test.go
diff --git a/src/pkg/go/doc/example.go b/src/go/doc/example.go
index c414e548c..c414e548c 100644
--- a/src/pkg/go/doc/example.go
+++ b/src/go/doc/example.go
diff --git a/src/pkg/go/doc/example_test.go b/src/go/doc/example_test.go
index e154ea8bf..e154ea8bf 100644
--- a/src/pkg/go/doc/example_test.go
+++ b/src/go/doc/example_test.go
diff --git a/src/pkg/go/doc/exports.go b/src/go/doc/exports.go
index ff01285d4..1d3b466d8 100644
--- a/src/pkg/go/doc/exports.go
+++ b/src/go/doc/exports.go
@@ -6,15 +6,19 @@
package doc
-import "go/ast"
+import (
+ "go/ast"
+ "go/token"
+)
// filterIdentList removes unexported names from list in place
-// and returns the resulting list.
+// and returns the resulting list. If blankOk is set, blank
+// identifiers are considered exported names.
//
-func filterIdentList(list []*ast.Ident) []*ast.Ident {
+func filterIdentList(list []*ast.Ident, blankOk bool) []*ast.Ident {
j := 0
for _, x := range list {
- if ast.IsExported(x.Name) {
+ if ast.IsExported(x.Name) || (blankOk && x.Name == "_") {
list[j] = x
j++
}
@@ -74,7 +78,7 @@ func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList, ityp
r.remember(ityp)
}
} else {
- field.Names = filterIdentList(field.Names)
+ field.Names = filterIdentList(field.Names, false)
if len(field.Names) < n {
removedFields = true
}
@@ -136,13 +140,15 @@ func (r *reader) filterType(parent *namedType, typ ast.Expr) {
}
}
-func (r *reader) filterSpec(spec ast.Spec) bool {
+func (r *reader) filterSpec(spec ast.Spec, tok token.Token) bool {
switch s := spec.(type) {
case *ast.ImportSpec:
// always keep imports so we can collect them
return true
case *ast.ValueSpec:
- s.Names = filterIdentList(s.Names)
+ // special case: consider blank constants as exported
+ // (work-around for issue 5397)
+ s.Names = filterIdentList(s.Names, tok == token.CONST)
if len(s.Names) > 0 {
r.filterType(nil, s.Type)
return true
@@ -159,10 +165,10 @@ func (r *reader) filterSpec(spec ast.Spec) bool {
return false
}
-func (r *reader) filterSpecList(list []ast.Spec) []ast.Spec {
+func (r *reader) filterSpecList(list []ast.Spec, tok token.Token) []ast.Spec {
j := 0
for _, s := range list {
- if r.filterSpec(s) {
+ if r.filterSpec(s, tok) {
list[j] = s
j++
}
@@ -173,7 +179,7 @@ func (r *reader) filterSpecList(list []ast.Spec) []ast.Spec {
func (r *reader) filterDecl(decl ast.Decl) bool {
switch d := decl.(type) {
case *ast.GenDecl:
- d.Specs = r.filterSpecList(d.Specs)
+ d.Specs = r.filterSpecList(d.Specs, d.Tok)
return len(d.Specs) > 0
case *ast.FuncDecl:
// ok to filter these methods early because any
diff --git a/src/pkg/go/doc/filter.go b/src/go/doc/filter.go
index a6f243f33..a6f243f33 100644
--- a/src/pkg/go/doc/filter.go
+++ b/src/go/doc/filter.go
diff --git a/src/pkg/go/doc/headscan.go b/src/go/doc/headscan.go
index f55934763..1ccaa1581 100644
--- a/src/pkg/go/doc/headscan.go
+++ b/src/go/doc/headscan.go
@@ -24,6 +24,7 @@ import (
"go/token"
"os"
"path/filepath"
+ "regexp"
"runtime"
"strings"
)
@@ -33,10 +34,10 @@ var (
verbose = flag.Bool("v", false, "verbose mode")
)
-const (
- html_h = "<h3>"
- html_endh = "</h3>\n"
-)
+// ToHTML in comment.go assigns a (possibly blank) ID to each heading
+var html_h = regexp.MustCompile(`<h3 id="[^"]*">`)
+
+const html_endh = "</h3>\n"
func isGoFile(fi os.FileInfo) bool {
return strings.HasSuffix(fi.Name(), ".go") &&
@@ -47,11 +48,11 @@ func appendHeadings(list []string, comment string) []string {
var buf bytes.Buffer
doc.ToHTML(&buf, comment, nil)
for s := buf.String(); ; {
- i := strings.Index(s, html_h)
- if i < 0 {
+ loc := html_h.FindStringIndex(s)
+ if len(loc) == 0 {
break
}
- i += len(html_h)
+ i := loc[1]
j := strings.Index(s, html_endh)
if j < 0 {
list = append(list, s[i:]) // incorrect HTML
diff --git a/src/pkg/go/doc/reader.go b/src/go/doc/reader.go
index ed82c47cd..ed82c47cd 100644
--- a/src/pkg/go/doc/reader.go
+++ b/src/go/doc/reader.go
diff --git a/src/pkg/go/doc/synopsis.go b/src/go/doc/synopsis.go
index c90080b7c..c90080b7c 100644
--- a/src/pkg/go/doc/synopsis.go
+++ b/src/go/doc/synopsis.go
diff --git a/src/pkg/go/doc/synopsis_test.go b/src/go/doc/synopsis_test.go
index 59b253cb8..59b253cb8 100644
--- a/src/pkg/go/doc/synopsis_test.go
+++ b/src/go/doc/synopsis_test.go
diff --git a/src/pkg/go/doc/testdata/a.0.golden b/src/go/doc/testdata/a.0.golden
index 7e680b80b..7e680b80b 100644
--- a/src/pkg/go/doc/testdata/a.0.golden
+++ b/src/go/doc/testdata/a.0.golden
diff --git a/src/pkg/go/doc/testdata/a.1.golden b/src/go/doc/testdata/a.1.golden
index 7e680b80b..7e680b80b 100644
--- a/src/pkg/go/doc/testdata/a.1.golden
+++ b/src/go/doc/testdata/a.1.golden
diff --git a/src/pkg/go/doc/testdata/a.2.golden b/src/go/doc/testdata/a.2.golden
index 7e680b80b..7e680b80b 100644
--- a/src/pkg/go/doc/testdata/a.2.golden
+++ b/src/go/doc/testdata/a.2.golden
diff --git a/src/pkg/go/doc/testdata/a0.go b/src/go/doc/testdata/a0.go
index 2420c8a48..2420c8a48 100644
--- a/src/pkg/go/doc/testdata/a0.go
+++ b/src/go/doc/testdata/a0.go
diff --git a/src/pkg/go/doc/testdata/a1.go b/src/go/doc/testdata/a1.go
index 9fad1e09b..9fad1e09b 100644
--- a/src/pkg/go/doc/testdata/a1.go
+++ b/src/go/doc/testdata/a1.go
diff --git a/src/pkg/go/doc/testdata/b.0.golden b/src/go/doc/testdata/b.0.golden
index 9d93392ea..9d93392ea 100644
--- a/src/pkg/go/doc/testdata/b.0.golden
+++ b/src/go/doc/testdata/b.0.golden
diff --git a/src/pkg/go/doc/testdata/b.1.golden b/src/go/doc/testdata/b.1.golden
index 66c47b5c2..66c47b5c2 100644
--- a/src/pkg/go/doc/testdata/b.1.golden
+++ b/src/go/doc/testdata/b.1.golden
diff --git a/src/pkg/go/doc/testdata/b.2.golden b/src/go/doc/testdata/b.2.golden
index 9d93392ea..9d93392ea 100644
--- a/src/pkg/go/doc/testdata/b.2.golden
+++ b/src/go/doc/testdata/b.2.golden
diff --git a/src/pkg/go/doc/testdata/b.go b/src/go/doc/testdata/b.go
index e50663b3d..e50663b3d 100644
--- a/src/pkg/go/doc/testdata/b.go
+++ b/src/go/doc/testdata/b.go
diff --git a/src/pkg/go/doc/testdata/benchmark.go b/src/go/doc/testdata/benchmark.go
index 905e49644..905e49644 100644
--- a/src/pkg/go/doc/testdata/benchmark.go
+++ b/src/go/doc/testdata/benchmark.go
diff --git a/src/go/doc/testdata/blank.0.golden b/src/go/doc/testdata/blank.0.golden
new file mode 100644
index 000000000..dae3ab2af
--- /dev/null
+++ b/src/go/doc/testdata/blank.0.golden
@@ -0,0 +1,37 @@
+// Package blank is a go/doc test for the handling of _. See issue ...
+PACKAGE blank
+
+IMPORTPATH
+ testdata/blank
+
+FILENAMES
+ testdata/blank.go
+
+CONSTANTS
+ // Package constants.
+ const (
+ _ int = iota
+ I1
+ I2
+ )
+
+
+TYPES
+ // S has a padding field.
+ type S struct {
+ H uint32
+
+ A uint8
+ // contains filtered or unexported fields
+ }
+
+ //
+ type T int
+
+ // T constants.
+ const (
+ _ T = iota
+ T1
+ T2
+ )
+
diff --git a/src/go/doc/testdata/blank.1.golden b/src/go/doc/testdata/blank.1.golden
new file mode 100644
index 000000000..333d7e5b0
--- /dev/null
+++ b/src/go/doc/testdata/blank.1.golden
@@ -0,0 +1,46 @@
+// Package blank is a go/doc test for the handling of _. See issue ...
+PACKAGE blank
+
+IMPORTPATH
+ testdata/blank
+
+FILENAMES
+ testdata/blank.go
+
+CONSTANTS
+ // Package constants.
+ const (
+ _ int = iota
+ I1
+ I2
+ )
+
+
+VARIABLES
+ //
+ var _ = T(55)
+
+
+FUNCTIONS
+ //
+ func _()
+
+
+TYPES
+ // S has a padding field.
+ type S struct {
+ H uint32
+ _ uint8
+ A uint8
+ }
+
+ //
+ type T int
+
+ // T constants.
+ const (
+ _ T = iota
+ T1
+ T2
+ )
+
diff --git a/src/go/doc/testdata/blank.2.golden b/src/go/doc/testdata/blank.2.golden
new file mode 100644
index 000000000..dae3ab2af
--- /dev/null
+++ b/src/go/doc/testdata/blank.2.golden
@@ -0,0 +1,37 @@
+// Package blank is a go/doc test for the handling of _. See issue ...
+PACKAGE blank
+
+IMPORTPATH
+ testdata/blank
+
+FILENAMES
+ testdata/blank.go
+
+CONSTANTS
+ // Package constants.
+ const (
+ _ int = iota
+ I1
+ I2
+ )
+
+
+TYPES
+ // S has a padding field.
+ type S struct {
+ H uint32
+
+ A uint8
+ // contains filtered or unexported fields
+ }
+
+ //
+ type T int
+
+ // T constants.
+ const (
+ _ T = iota
+ T1
+ T2
+ )
+
diff --git a/src/go/doc/testdata/blank.go b/src/go/doc/testdata/blank.go
new file mode 100644
index 000000000..f812c77b7
--- /dev/null
+++ b/src/go/doc/testdata/blank.go
@@ -0,0 +1,38 @@
+// 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 blank is a go/doc test for the handling of _.
+// See issue 5397.
+package blank
+
+type T int
+
+// T constants.
+const (
+ _ T = iota
+ T1
+ T2
+)
+
+// Package constants.
+const (
+ _ int = iota
+ I1
+ I2
+)
+
+// Blanks not in doc output:
+
+// S has a padding field.
+type S struct {
+ H uint32
+ _ uint8
+ A uint8
+}
+
+func _() {}
+
+type _ T
+
+var _ = T(55)
diff --git a/src/pkg/go/doc/testdata/bugpara.0.golden b/src/go/doc/testdata/bugpara.0.golden
index 580485950..580485950 100644
--- a/src/pkg/go/doc/testdata/bugpara.0.golden
+++ b/src/go/doc/testdata/bugpara.0.golden
diff --git a/src/pkg/go/doc/testdata/bugpara.1.golden b/src/go/doc/testdata/bugpara.1.golden
index 580485950..580485950 100644
--- a/src/pkg/go/doc/testdata/bugpara.1.golden
+++ b/src/go/doc/testdata/bugpara.1.golden
diff --git a/src/pkg/go/doc/testdata/bugpara.2.golden b/src/go/doc/testdata/bugpara.2.golden
index 580485950..580485950 100644
--- a/src/pkg/go/doc/testdata/bugpara.2.golden
+++ b/src/go/doc/testdata/bugpara.2.golden
diff --git a/src/pkg/go/doc/testdata/bugpara.go b/src/go/doc/testdata/bugpara.go
index f5345a797..f5345a797 100644
--- a/src/pkg/go/doc/testdata/bugpara.go
+++ b/src/go/doc/testdata/bugpara.go
diff --git a/src/pkg/go/doc/testdata/c.0.golden b/src/go/doc/testdata/c.0.golden
index e21959b19..e21959b19 100644
--- a/src/pkg/go/doc/testdata/c.0.golden
+++ b/src/go/doc/testdata/c.0.golden
diff --git a/src/pkg/go/doc/testdata/c.1.golden b/src/go/doc/testdata/c.1.golden
index e21959b19..e21959b19 100644
--- a/src/pkg/go/doc/testdata/c.1.golden
+++ b/src/go/doc/testdata/c.1.golden
diff --git a/src/pkg/go/doc/testdata/c.2.golden b/src/go/doc/testdata/c.2.golden
index e21959b19..e21959b19 100644
--- a/src/pkg/go/doc/testdata/c.2.golden
+++ b/src/go/doc/testdata/c.2.golden
diff --git a/src/pkg/go/doc/testdata/c.go b/src/go/doc/testdata/c.go
index e0f39196d..e0f39196d 100644
--- a/src/pkg/go/doc/testdata/c.go
+++ b/src/go/doc/testdata/c.go
diff --git a/src/pkg/go/doc/testdata/d.0.golden b/src/go/doc/testdata/d.0.golden
index c00519953..c00519953 100644
--- a/src/pkg/go/doc/testdata/d.0.golden
+++ b/src/go/doc/testdata/d.0.golden
diff --git a/src/pkg/go/doc/testdata/d.1.golden b/src/go/doc/testdata/d.1.golden
index c00519953..c00519953 100644
--- a/src/pkg/go/doc/testdata/d.1.golden
+++ b/src/go/doc/testdata/d.1.golden
diff --git a/src/pkg/go/doc/testdata/d.2.golden b/src/go/doc/testdata/d.2.golden
index c00519953..c00519953 100644
--- a/src/pkg/go/doc/testdata/d.2.golden
+++ b/src/go/doc/testdata/d.2.golden
diff --git a/src/pkg/go/doc/testdata/d1.go b/src/go/doc/testdata/d1.go
index ebd694195..ebd694195 100644
--- a/src/pkg/go/doc/testdata/d1.go
+++ b/src/go/doc/testdata/d1.go
diff --git a/src/pkg/go/doc/testdata/d2.go b/src/go/doc/testdata/d2.go
index 2f56f4fa4..2f56f4fa4 100644
--- a/src/pkg/go/doc/testdata/d2.go
+++ b/src/go/doc/testdata/d2.go
diff --git a/src/pkg/go/doc/testdata/e.0.golden b/src/go/doc/testdata/e.0.golden
index 6987e5867..6987e5867 100644
--- a/src/pkg/go/doc/testdata/e.0.golden
+++ b/src/go/doc/testdata/e.0.golden
diff --git a/src/pkg/go/doc/testdata/e.1.golden b/src/go/doc/testdata/e.1.golden
index cbe22e0bf..cbe22e0bf 100644
--- a/src/pkg/go/doc/testdata/e.1.golden
+++ b/src/go/doc/testdata/e.1.golden
diff --git a/src/pkg/go/doc/testdata/e.2.golden b/src/go/doc/testdata/e.2.golden
index e7b05e80f..e7b05e80f 100644
--- a/src/pkg/go/doc/testdata/e.2.golden
+++ b/src/go/doc/testdata/e.2.golden
diff --git a/src/pkg/go/doc/testdata/e.go b/src/go/doc/testdata/e.go
index ec432e3e5..ec432e3e5 100644
--- a/src/pkg/go/doc/testdata/e.go
+++ b/src/go/doc/testdata/e.go
diff --git a/src/pkg/go/doc/testdata/error1.0.golden b/src/go/doc/testdata/error1.0.golden
index 6c6fe5d49..6c6fe5d49 100644
--- a/src/pkg/go/doc/testdata/error1.0.golden
+++ b/src/go/doc/testdata/error1.0.golden
diff --git a/src/pkg/go/doc/testdata/error1.1.golden b/src/go/doc/testdata/error1.1.golden
index a8dc2e71d..a8dc2e71d 100644
--- a/src/pkg/go/doc/testdata/error1.1.golden
+++ b/src/go/doc/testdata/error1.1.golden
diff --git a/src/pkg/go/doc/testdata/error1.2.golden b/src/go/doc/testdata/error1.2.golden
index 6c6fe5d49..6c6fe5d49 100644
--- a/src/pkg/go/doc/testdata/error1.2.golden
+++ b/src/go/doc/testdata/error1.2.golden
diff --git a/src/pkg/go/doc/testdata/error1.go b/src/go/doc/testdata/error1.go
index 3c777a780..3c777a780 100644
--- a/src/pkg/go/doc/testdata/error1.go
+++ b/src/go/doc/testdata/error1.go
diff --git a/src/pkg/go/doc/testdata/error2.0.golden b/src/go/doc/testdata/error2.0.golden
index dedfe412a..dedfe412a 100644
--- a/src/pkg/go/doc/testdata/error2.0.golden
+++ b/src/go/doc/testdata/error2.0.golden
diff --git a/src/pkg/go/doc/testdata/error2.1.golden b/src/go/doc/testdata/error2.1.golden
index dbcc1b03e..dbcc1b03e 100644
--- a/src/pkg/go/doc/testdata/error2.1.golden
+++ b/src/go/doc/testdata/error2.1.golden
diff --git a/src/pkg/go/doc/testdata/error2.2.golden b/src/go/doc/testdata/error2.2.golden
index dedfe412a..dedfe412a 100644
--- a/src/pkg/go/doc/testdata/error2.2.golden
+++ b/src/go/doc/testdata/error2.2.golden
diff --git a/src/pkg/go/doc/testdata/error2.go b/src/go/doc/testdata/error2.go
index 6ee96c245..6ee96c245 100644
--- a/src/pkg/go/doc/testdata/error2.go
+++ b/src/go/doc/testdata/error2.go
diff --git a/src/pkg/go/doc/testdata/example.go b/src/go/doc/testdata/example.go
index fdeda137e..fdeda137e 100644
--- a/src/pkg/go/doc/testdata/example.go
+++ b/src/go/doc/testdata/example.go
diff --git a/src/pkg/go/doc/testdata/f.0.golden b/src/go/doc/testdata/f.0.golden
index 817590186..817590186 100644
--- a/src/pkg/go/doc/testdata/f.0.golden
+++ b/src/go/doc/testdata/f.0.golden
diff --git a/src/pkg/go/doc/testdata/f.1.golden b/src/go/doc/testdata/f.1.golden
index ba68e884c..ba68e884c 100644
--- a/src/pkg/go/doc/testdata/f.1.golden
+++ b/src/go/doc/testdata/f.1.golden
diff --git a/src/pkg/go/doc/testdata/f.2.golden b/src/go/doc/testdata/f.2.golden
index 817590186..817590186 100644
--- a/src/pkg/go/doc/testdata/f.2.golden
+++ b/src/go/doc/testdata/f.2.golden
diff --git a/src/pkg/go/doc/testdata/f.go b/src/go/doc/testdata/f.go
index 7e9add907..7e9add907 100644
--- a/src/pkg/go/doc/testdata/f.go
+++ b/src/go/doc/testdata/f.go
diff --git a/src/pkg/go/doc/testdata/template.txt b/src/go/doc/testdata/template.txt
index 1b0738261..1b0738261 100644
--- a/src/pkg/go/doc/testdata/template.txt
+++ b/src/go/doc/testdata/template.txt
diff --git a/src/pkg/go/doc/testdata/testing.0.golden b/src/go/doc/testdata/testing.0.golden
index f8348f1ac..f8348f1ac 100644
--- a/src/pkg/go/doc/testdata/testing.0.golden
+++ b/src/go/doc/testdata/testing.0.golden
diff --git a/src/pkg/go/doc/testdata/testing.1.golden b/src/go/doc/testdata/testing.1.golden
index 282bb1015..282bb1015 100644
--- a/src/pkg/go/doc/testdata/testing.1.golden
+++ b/src/go/doc/testdata/testing.1.golden
diff --git a/src/pkg/go/doc/testdata/testing.2.golden b/src/go/doc/testdata/testing.2.golden
index f8348f1ac..f8348f1ac 100644
--- a/src/pkg/go/doc/testdata/testing.2.golden
+++ b/src/go/doc/testdata/testing.2.golden
diff --git a/src/pkg/go/doc/testdata/testing.go b/src/go/doc/testdata/testing.go
index 93ed494c3..93ed494c3 100644
--- a/src/pkg/go/doc/testdata/testing.go
+++ b/src/go/doc/testdata/testing.go
diff --git a/src/go/format/format.go b/src/go/format/format.go
new file mode 100644
index 000000000..668a42df2
--- /dev/null
+++ b/src/go/format/format.go
@@ -0,0 +1,266 @@
+// 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 format implements standard formatting of Go source.
+package format
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/printer"
+ "go/token"
+ "io"
+ "strings"
+)
+
+var config = printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 8}
+
+const parserMode = parser.ParseComments
+
+// Node formats node in canonical gofmt style and writes the result to dst.
+//
+// The node type must be *ast.File, *printer.CommentedNode, []ast.Decl,
+// []ast.Stmt, or assignment-compatible to ast.Expr, ast.Decl, ast.Spec,
+// or ast.Stmt. Node does not modify node. Imports are not sorted for
+// nodes representing partial source files (i.e., if the node is not an
+// *ast.File or a *printer.CommentedNode not wrapping an *ast.File).
+//
+// The function may return early (before the entire result is written)
+// and return a formatting error, for instance due to an incorrect AST.
+//
+func Node(dst io.Writer, fset *token.FileSet, node interface{}) error {
+ // Determine if we have a complete source file (file != nil).
+ var file *ast.File
+ var cnode *printer.CommentedNode
+ switch n := node.(type) {
+ case *ast.File:
+ file = n
+ case *printer.CommentedNode:
+ if f, ok := n.Node.(*ast.File); ok {
+ file = f
+ cnode = n
+ }
+ }
+
+ // Sort imports if necessary.
+ if file != nil && hasUnsortedImports(file) {
+ // Make a copy of the AST because ast.SortImports is destructive.
+ // TODO(gri) Do this more efficiently.
+ var buf bytes.Buffer
+ err := config.Fprint(&buf, fset, file)
+ if err != nil {
+ return err
+ }
+ file, err = parser.ParseFile(fset, "", buf.Bytes(), parserMode)
+ if err != nil {
+ // We should never get here. If we do, provide good diagnostic.
+ return fmt.Errorf("format.Node internal error (%s)", err)
+ }
+ ast.SortImports(fset, file)
+
+ // Use new file with sorted imports.
+ node = file
+ if cnode != nil {
+ node = &printer.CommentedNode{Node: file, Comments: cnode.Comments}
+ }
+ }
+
+ return config.Fprint(dst, fset, node)
+}
+
+// Source formats src in canonical gofmt style and returns the result
+// or an (I/O or syntax) error. src is expected to be a syntactically
+// correct Go source file, or a list of Go declarations or statements.
+//
+// If src is a partial source file, the leading and trailing space of src
+// is applied to the result (such that it has the same leading and trailing
+// space as src), and the result is indented by the same amount as the first
+// line of src containing code. Imports are not sorted for partial source files.
+//
+func Source(src []byte) ([]byte, error) {
+ fset := token.NewFileSet()
+ file, sourceAdj, indentAdj, err := parse(fset, "", src, true)
+ if err != nil {
+ return nil, err
+ }
+
+ if sourceAdj == nil {
+ // Complete source file.
+ // TODO(gri) consider doing this always.
+ ast.SortImports(fset, file)
+ }
+
+ return format(fset, file, sourceAdj, indentAdj, src, config)
+}
+
+func hasUnsortedImports(file *ast.File) bool {
+ for _, d := range file.Decls {
+ d, ok := d.(*ast.GenDecl)
+ if !ok || d.Tok != token.IMPORT {
+ // Not an import declaration, so we're done.
+ // Imports are always first.
+ return false
+ }
+ if d.Lparen.IsValid() {
+ // For now assume all grouped imports are unsorted.
+ // TODO(gri) Should check if they are sorted already.
+ return true
+ }
+ // Ungrouped imports are sorted by default.
+ }
+ return false
+}
+
+// ----------------------------------------------------------------------------
+// Support functions
+//
+// The functions parse, format, and isSpace below are identical to the
+// respective functions in cmd/gofmt/gofmt.go - keep them in sync!
+//
+// TODO(gri) Factor out this functionality, eventually.
+
+// 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.
+ fsrc := append(append([]byte("package p; func _() {"), src...), '\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 _() {"):]
+ src = src[:len(src)-(indent+len("\n}\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
+}
+
+func isSpace(b byte) bool {
+ return b == ' ' || b == '\t' || b == '\n' || b == '\r'
+}
diff --git a/src/pkg/go/format/format_test.go b/src/go/format/format_test.go
index 93f099247..d7846bec6 100644
--- a/src/pkg/go/format/format_test.go
+++ b/src/go/format/format_test.go
@@ -87,7 +87,11 @@ var tests = []string{
"\tx := 0\n\tgo f()\n\n\n",
"\n\t\t\n\n\tx := 0\n\tgo f()\n\n\n",
"\n\t\t\n\n\t\t\tx := 0\n\t\t\tgo f()\n\n\n",
- "\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\nfoo\n`\n\n\n", // no indentation inside raw strings
+ "\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\nfoo\n`\n\n\n", // no indentation added inside raw strings
+ "\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.
// erroneous programs
"ERROR1 + 2 +",
diff --git a/src/pkg/go/parser/error_test.go b/src/go/parser/error_test.go
index 8506077ce..48fb53e5b 100644
--- a/src/pkg/go/parser/error_test.go
+++ b/src/go/parser/error_test.go
@@ -34,7 +34,7 @@ import (
const testdata = "testdata"
-var fsetErrs *token.FileSet
+var fsetErrs = token.NewFileSet()
// getFile assumes that each filename occurs at most once
func getFile(filename string) (file *token.File) {
@@ -169,7 +169,6 @@ func checkErrors(t *testing.T, filename string, input interface{}) {
}
func TestErrors(t *testing.T) {
- fsetErrs = token.NewFileSet()
list, err := ioutil.ReadDir(testdata)
if err != nil {
t.Fatal(err)
diff --git a/src/pkg/go/parser/example_test.go b/src/go/parser/example_test.go
index 3c58e63a9..3c58e63a9 100644
--- a/src/pkg/go/parser/example_test.go
+++ b/src/go/parser/example_test.go
diff --git a/src/pkg/go/parser/interface.go b/src/go/parser/interface.go
index 57da4ddcd..49103058b 100644
--- a/src/pkg/go/parser/interface.go
+++ b/src/go/parser/interface.go
@@ -184,7 +184,7 @@ func ParseExpr(x string) (ast.Expr, error) {
// If a semicolon was inserted, consume it;
// report an error if there's more tokens.
- if p.tok == token.SEMICOLON {
+ if p.tok == token.SEMICOLON && p.lit == "\n" {
p.next()
}
p.expect(token.EOF)
diff --git a/src/pkg/go/parser/parser.go b/src/go/parser/parser.go
index 00dd532b2..4a005d8ff 100644
--- a/src/pkg/go/parser/parser.go
+++ b/src/go/parser/parser.go
@@ -641,6 +641,7 @@ func (p *parser) parseArrayType() ast.Expr {
}
lbrack := p.expect(token.LBRACK)
+ p.exprLev++
var len ast.Expr
// always permit ellipsis for more fault-tolerant parsing
if p.tok == token.ELLIPSIS {
@@ -649,6 +650,7 @@ func (p *parser) parseArrayType() ast.Expr {
} else if p.tok != token.RBRACK {
len = p.parseRhs()
}
+ p.exprLev--
p.expect(token.RBRACK)
elt := p.parseType()
@@ -823,9 +825,10 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [
// parameter or result variable is the function body.
p.declare(field, nil, scope, ast.Var, idents...)
p.resolve(typ)
- if p.tok == token.COMMA {
- p.next()
+ if !p.atComma("parameter list") {
+ return
}
+ p.next()
for p.tok != token.RPAREN && p.tok != token.EOF {
idents := p.parseIdentList()
typ := p.parseVarType(ellipsisOk)
@@ -840,15 +843,15 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [
}
p.next()
}
- } else {
- // Type { "," Type } (anonymous parameters)
- params = make([]*ast.Field, len(list))
- for i, typ := range list {
- p.resolve(typ)
- params[i] = &ast.Field{Type: typ}
- }
+ return
}
+ // Type { "," Type } (anonymous parameters)
+ params = make([]*ast.Field, len(list))
+ for i, typ := range list {
+ p.resolve(typ)
+ params[i] = &ast.Field{Type: typ}
+ }
return
}
@@ -2041,7 +2044,16 @@ func (p *parser) parseForStmt() ast.Stmt {
prevLev := p.exprLev
p.exprLev = -1
if p.tok != token.SEMICOLON {
- s2, isRange = p.parseSimpleStmt(rangeOk)
+ if p.tok == token.RANGE {
+ // "for range x" (nil lhs in assignment)
+ pos := p.pos
+ p.next()
+ y := []ast.Expr{&ast.UnaryExpr{OpPos: pos, Op: token.RANGE, X: p.parseRhs()}}
+ s2 = &ast.AssignStmt{Rhs: y}
+ isRange = true
+ } else {
+ s2, isRange = p.parseSimpleStmt(rangeOk)
+ }
}
if !isRange && p.tok == token.SEMICOLON {
p.next()
@@ -2066,12 +2078,14 @@ func (p *parser) parseForStmt() ast.Stmt {
// check lhs
var key, value ast.Expr
switch len(as.Lhs) {
- case 2:
- key, value = as.Lhs[0], as.Lhs[1]
+ case 0:
+ // nothing to do
case 1:
key = as.Lhs[0]
+ case 2:
+ key, value = as.Lhs[0], as.Lhs[1]
default:
- p.errorExpected(as.Lhs[0].Pos(), "1 or 2 expressions")
+ p.errorExpected(as.Lhs[len(as.Lhs)-1].Pos(), "at most 2 expressions")
return &ast.BadStmt{From: pos, To: p.safePos(body.End())}
}
// parseSimpleStmt returned a right-hand side that
@@ -2296,36 +2310,6 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen
}
}
-func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
- if p.trace {
- defer un(trace(p, "Receiver"))
- }
-
- par := p.parseParameters(scope, false)
-
- // must have exactly one receiver
- if par.NumFields() != 1 {
- p.errorExpected(par.Opening, "exactly one receiver")
- par.List = []*ast.Field{{Type: &ast.BadExpr{From: par.Opening, To: par.Closing + 1}}}
- return par
- }
-
- // recv type must be of the form ["*"] identifier
- recv := par.List[0]
- base := deref(recv.Type)
- if _, isIdent := base.(*ast.Ident); !isIdent {
- if _, isBad := base.(*ast.BadExpr); !isBad {
- // only report error if it's a new one
- p.errorExpected(base.Pos(), "(unqualified) identifier")
- }
- par.List = []*ast.Field{
- {Type: &ast.BadExpr{From: recv.Pos(), To: p.safePos(recv.End())}},
- }
- }
-
- return par
-}
-
func (p *parser) parseFuncDecl() *ast.FuncDecl {
if p.trace {
defer un(trace(p, "FunctionDecl"))
@@ -2337,7 +2321,7 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl {
var recv *ast.FieldList
if p.tok == token.LPAREN {
- recv = p.parseReceiver(scope)
+ recv = p.parseParameters(scope, false)
}
ident := p.parseIdent()
diff --git a/src/pkg/go/parser/parser_test.go b/src/go/parser/parser_test.go
index 2797ea518..85065fd18 100644
--- a/src/pkg/go/parser/parser_test.go
+++ b/src/go/parser/parser_test.go
@@ -74,36 +74,54 @@ func TestParseExpr(t *testing.T) {
src := "a + b"
x, err := ParseExpr(src)
if err != nil {
- t.Fatalf("ParseExpr(%s): %v", src, err)
+ t.Errorf("ParseExpr(%q): %v", src, err)
}
// sanity check
if _, ok := x.(*ast.BinaryExpr); !ok {
- t.Errorf("ParseExpr(%s): got %T, want *ast.BinaryExpr", src, x)
+ t.Errorf("ParseExpr(%q): got %T, want *ast.BinaryExpr", src, x)
}
// a valid type expression
src = "struct{x *int}"
x, err = ParseExpr(src)
if err != nil {
- t.Fatalf("ParseExpr(%s): %v", src, err)
+ t.Errorf("ParseExpr(%q): %v", src, err)
}
// sanity check
if _, ok := x.(*ast.StructType); !ok {
- t.Errorf("ParseExpr(%s): got %T, want *ast.StructType", src, x)
+ t.Errorf("ParseExpr(%q): got %T, want *ast.StructType", src, x)
}
// an invalid expression
src = "a + *"
- _, err = ParseExpr(src)
- if err == nil {
- t.Fatalf("ParseExpr(%s): got no error", src)
+ if _, err := ParseExpr(src); err == nil {
+ t.Errorf("ParseExpr(%q): got no error", src)
}
// a valid expression followed by extra tokens is invalid
src = "a[i] := x"
- _, err = ParseExpr(src)
- if err == nil {
- t.Fatalf("ParseExpr(%s): got no error", src)
+ if _, err := ParseExpr(src); err == nil {
+ t.Errorf("ParseExpr(%q): got no error", src)
+ }
+
+ // a semicolon is not permitted unless automatically inserted
+ src = "a + b\n"
+ if _, err := ParseExpr(src); err != nil {
+ t.Errorf("ParseExpr(%q): got error %s", src, err)
+ }
+ src = "a + b;"
+ if _, err := ParseExpr(src); err == nil {
+ t.Errorf("ParseExpr(%q): got no error", src)
+ }
+
+ // various other stuff following a valid expression
+ const validExpr = "a + b"
+ const anything = "dh3*#D)#_"
+ for _, c := range "!)]};," {
+ src := validExpr + string(c) + anything
+ if _, err := ParseExpr(src); err == nil {
+ t.Errorf("ParseExpr(%q): got no error", src)
+ }
}
// ParseExpr must not crash
diff --git a/src/pkg/go/parser/performance_test.go b/src/go/parser/performance_test.go
index f2732c0e2..f2732c0e2 100644
--- a/src/pkg/go/parser/performance_test.go
+++ b/src/go/parser/performance_test.go
diff --git a/src/pkg/go/parser/short_test.go b/src/go/parser/short_test.go
index b79406099..05e44de28 100644
--- a/src/pkg/go/parser/short_test.go
+++ b/src/go/parser/short_test.go
@@ -35,6 +35,11 @@ var valids = []string{
`package p; func f() { for _ = range "foo" + "bar" {} };`,
`package p; func f() { var s []int; g(s[:], s[i:], s[:j], s[i:j], s[i:j:k], s[:j:k]) };`,
`package p; var ( _ = (struct {*T}).m; _ = (interface {T}).m )`,
+ `package p; func ((T),) m() {}`,
+ `package p; func ((*T),) m() {}`,
+ `package p; func (*(T),) m() {}`,
+ `package p; func _(x []int) { for range x {} }`,
+ `package p; func _() { if [T{}.n]int{} {} }`,
}
func TestValid(t *testing.T) {
@@ -89,6 +94,7 @@ var invalids = []string{
`package p; func f() { go f /* ERROR HERE "function must be invoked" */ }`,
`package p; func f() { defer func() {} /* ERROR HERE "function must be invoked" */ }`,
`package p; func f() { go func() { func() { f(x func /* ERROR "expected '\)'" */ (){}) } } }`,
+ `package p; func f() (a b string /* ERROR "expected '\)'" */ , ok bool) // issue 8656`,
}
func TestInvalid(t *testing.T) {
diff --git a/src/pkg/go/parser/testdata/commas.src b/src/go/parser/testdata/commas.src
index af6e70645..af6e70645 100644
--- a/src/pkg/go/parser/testdata/commas.src
+++ b/src/go/parser/testdata/commas.src
diff --git a/src/pkg/go/parser/testdata/issue3106.src b/src/go/parser/testdata/issue3106.src
index 82796c8ce..82796c8ce 100644
--- a/src/pkg/go/parser/testdata/issue3106.src
+++ b/src/go/parser/testdata/issue3106.src
diff --git a/src/pkg/go/printer/example_test.go b/src/go/printer/example_test.go
index e570040ba..e570040ba 100644
--- a/src/pkg/go/printer/example_test.go
+++ b/src/go/printer/example_test.go
diff --git a/src/pkg/go/printer/nodes.go b/src/go/printer/nodes.go
index 04b5f1a76..d5a69349b 100644
--- a/src/pkg/go/printer/nodes.go
+++ b/src/go/printer/nodes.go
@@ -163,8 +163,8 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
size := 0
// print all list elements
+ prevLine := prev.Line
for i, x := range list {
- prevLine := line
line = p.lineFor(x.Pos())
// determine if the next linebreak, if any, needs to use formfeed:
@@ -207,8 +207,8 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
}
}
+ needsLinebreak := 0 < prevLine && prevLine < line
if i > 0 {
- needsLinebreak := prevLine < line && prevLine > 0 && line > 0
// use position of expression following the comma as
// comma position for correct comment placement, but
// only if the expression is on the same line
@@ -232,16 +232,20 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
}
}
- if isPair && size > 0 && len(list) > 1 {
- // we have a key:value expression that fits onto one line and
- // is in a list with more then one entry: use a column for the
- // key such that consecutive entries can align if possible
+ if len(list) > 1 && isPair && size > 0 && needsLinebreak {
+ // we have a key:value expression that fits onto one line
+ // and it's not on the same line as the prior expression:
+ // use a column for the key such that consecutive entries
+ // can align if possible
+ // (needsLinebreak is set if we started a new line before)
p.expr(pair.Key)
p.print(pair.Colon, token.COLON, vtab)
p.expr(pair.Value)
} else {
p.expr0(x, depth)
}
+
+ prevLine = line
}
if mode&commaTerm != 0 && next.IsValid() && p.pos.Line < next.Line {
@@ -732,7 +736,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
// don't print parentheses around an already parenthesized expression
// TODO(gri) consider making this more general and incorporate precedence levels
- p.expr0(x.X, reduceDepth(depth)) // parentheses undo one level of depth
+ p.expr0(x.X, depth)
} else {
p.print(token.LPAREN)
p.expr0(x.X, reduceDepth(depth)) // parentheses undo one level of depth
@@ -1216,14 +1220,17 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
case *ast.RangeStmt:
p.print(token.FOR, blank)
- p.expr(s.Key)
- if s.Value != nil {
- // use position of value following the comma as
- // comma position for correct comment placement
- p.print(s.Value.Pos(), token.COMMA, blank)
- p.expr(s.Value)
- }
- p.print(blank, s.TokPos, s.Tok, blank, token.RANGE, blank)
+ if s.Key != nil {
+ p.expr(s.Key)
+ if s.Value != nil {
+ // use position of value following the comma as
+ // comma position for correct comment placement
+ p.print(s.Value.Pos(), token.COMMA, blank)
+ p.expr(s.Value)
+ }
+ p.print(blank, s.TokPos, s.Tok, blank)
+ }
+ p.print(token.RANGE, blank)
p.expr(stripParens(s.X))
p.print(blank)
p.block(s.Body, 1)
diff --git a/src/pkg/go/printer/performance_test.go b/src/go/printer/performance_test.go
index 5b29affcb..5b29affcb 100644
--- a/src/pkg/go/printer/performance_test.go
+++ b/src/go/printer/performance_test.go
diff --git a/src/pkg/go/printer/printer.go b/src/go/printer/printer.go
index 280c697a0..280c697a0 100644
--- a/src/pkg/go/printer/printer.go
+++ b/src/go/printer/printer.go
diff --git a/src/pkg/go/printer/printer_test.go b/src/go/printer/printer_test.go
index 306928a69..3b0570e5b 100644
--- a/src/pkg/go/printer/printer_test.go
+++ b/src/go/printer/printer_test.go
@@ -159,13 +159,6 @@ func runcheck(t *testing.T, source, golden string, mode checkMode) {
}
func check(t *testing.T, source, golden string, mode checkMode) {
- // start a timer to produce a time-out signal
- tc := make(chan int)
- go func() {
- time.Sleep(10 * time.Second) // plenty of a safety margin, even for very slow machines
- tc <- 0
- }()
-
// run the test
cc := make(chan int)
go func() {
@@ -173,9 +166,9 @@ func check(t *testing.T, source, golden string, mode checkMode) {
cc <- 0
}()
- // wait for the first finisher
+ // wait with timeout
select {
- case <-tc:
+ case <-time.After(10 * time.Second): // plenty of a safety margin, even for very slow machines
// test running past time out
t.Errorf("%s: running too slowly", source)
case <-cc:
@@ -357,7 +350,7 @@ func idents(f *ast.File) <-chan *ast.Ident {
// identCount returns the number of identifiers found in f.
func identCount(f *ast.File) int {
n := 0
- for _ = range idents(f) {
+ for range idents(f) {
n++
}
return n
diff --git a/src/pkg/go/printer/testdata/comments.golden b/src/go/printer/testdata/comments.golden
index b1af7958a..b1af7958a 100644
--- a/src/pkg/go/printer/testdata/comments.golden
+++ b/src/go/printer/testdata/comments.golden
diff --git a/src/pkg/go/printer/testdata/comments.input b/src/go/printer/testdata/comments.input
index 983e2b2c9..983e2b2c9 100644
--- a/src/pkg/go/printer/testdata/comments.input
+++ b/src/go/printer/testdata/comments.input
diff --git a/src/pkg/go/printer/testdata/comments.x b/src/go/printer/testdata/comments.x
index ae7729286..ae7729286 100644
--- a/src/pkg/go/printer/testdata/comments.x
+++ b/src/go/printer/testdata/comments.x
diff --git a/src/pkg/go/printer/testdata/comments2.golden b/src/go/printer/testdata/comments2.golden
index 7676a26c1..7676a26c1 100644
--- a/src/pkg/go/printer/testdata/comments2.golden
+++ b/src/go/printer/testdata/comments2.golden
diff --git a/src/pkg/go/printer/testdata/comments2.input b/src/go/printer/testdata/comments2.input
index 4a055c827..4a055c827 100644
--- a/src/pkg/go/printer/testdata/comments2.input
+++ b/src/go/printer/testdata/comments2.input
diff --git a/src/pkg/go/printer/testdata/declarations.golden b/src/go/printer/testdata/declarations.golden
index a27f21fc8..9acd41b7d 100644
--- a/src/pkg/go/printer/testdata/declarations.golden
+++ b/src/go/printer/testdata/declarations.golden
@@ -593,7 +593,7 @@ var (
)
func _() {
- var privateKey2 = &Block{Type: "RSA PRIVATE KEY",
+ var privateKey2 = &Block{Type: "RSA PRIVATE KEY",
Headers: map[string]string{},
Bytes: []uint8{0x30, 0x82, 0x1, 0x3a, 0x2, 0x1, 0x0, 0x2,
0x41, 0x0, 0xb2, 0x99, 0xf, 0x49, 0xc4, 0x7d, 0xfa, 0x8c,
@@ -698,6 +698,29 @@ var _ = T4{
c: z,
}
+// no alignment of map composite entries if they are not the first entry on a line
+var _ = T{0: 0} // not aligned
+var _ = T{0: 0, // not aligned
+ 1: 1, // aligned
+ 22: 22, // aligned
+ 333: 333, 1234: 12, 12345: 0, // first on line aligned
+}
+
+// test cases form issue 8685
+// not aligned
+var _ = map[int]string{1: "spring", 2: "summer",
+ 3: "autumn", 4: "winter"}
+
+// not aligned
+var _ = map[string]string{"a": "spring", "b": "summer",
+ "c": "autumn", "d": "winter"}
+
+// aligned
+var _ = map[string]string{"a": "spring",
+ "b": "summer",
+ "c": "autumn",
+ "d": "winter"}
+
func _() {
var _ = T{
a, // must introduce trailing comma
diff --git a/src/pkg/go/printer/testdata/declarations.input b/src/go/printer/testdata/declarations.input
index d9951d386..45beec25f 100644
--- a/src/pkg/go/printer/testdata/declarations.input
+++ b/src/go/printer/testdata/declarations.input
@@ -715,6 +715,31 @@ var _ = T4{
}
+// no alignment of map composite entries if they are not the first entry on a line
+var _ = T{0: 0} // not aligned
+var _ = T{0: 0, // not aligned
+ 1: 1, // aligned
+ 22: 22, // aligned
+ 333: 333, 1234: 12, 12345: 0, // first on line aligned
+}
+
+
+// test cases form issue 8685
+// not aligned
+var _ = map[int]string{1: "spring", 2: "summer",
+ 3: "autumn", 4: "winter"}
+
+// not aligned
+var _ = map[string]string{"a": "spring", "b": "summer",
+ "c": "autumn", "d": "winter"}
+
+// aligned
+var _ = map[string]string{"a": "spring",
+"b": "summer",
+ "c": "autumn",
+"d": "winter"}
+
+
func _() {
var _ = T{
a, // must introduce trailing comma
diff --git a/src/pkg/go/printer/testdata/empty.golden b/src/go/printer/testdata/empty.golden
index a055f4758..a055f4758 100644
--- a/src/pkg/go/printer/testdata/empty.golden
+++ b/src/go/printer/testdata/empty.golden
diff --git a/src/pkg/go/printer/testdata/empty.input b/src/go/printer/testdata/empty.input
index a055f4758..a055f4758 100644
--- a/src/pkg/go/printer/testdata/empty.input
+++ b/src/go/printer/testdata/empty.input
diff --git a/src/pkg/go/printer/testdata/expressions.golden b/src/go/printer/testdata/expressions.golden
index fbe8275b3..e3d17a465 100644
--- a/src/pkg/go/printer/testdata/expressions.golden
+++ b/src/go/printer/testdata/expressions.golden
@@ -94,6 +94,11 @@ func _() {
_ = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
_ = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx)
+ // test case for issue 8021
+ // want:
+ // ([]bool{})[([]int{})[((1)+(((1)+((((1)*(((1)+(1))+(1)))+(1))*(1)))+(1)))]]
+ _ = ([]bool{})[([]int{})[((1)+(((1)+((((1)*(((1)+(1))+(1)))+(1))*(1)))+(1)))]]
+
// the parser does not restrict expressions that may appear as statements
true
42
diff --git a/src/pkg/go/printer/testdata/expressions.input b/src/go/printer/testdata/expressions.input
index f4d20fa0f..d20a59350 100644
--- a/src/pkg/go/printer/testdata/expressions.input
+++ b/src/go/printer/testdata/expressions.input
@@ -95,6 +95,11 @@ func _() {
_ = Open(dpath + "/file", O_WRONLY | O_CREAT, 0666)
_ = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx)
+ // test case for issue 8021
+ // want:
+ // ([]bool{})[([]int{})[((1)+(((1)+((((1)*(((1)+(1))+(1)))+(1))*(1)))+(1)))]]
+ _ = ([]bool{})[([]int{})[((1) + (((((1) + (((((((1) * (((((1) + (1))) + (1))))) + (1))) * (1))))) + (1))))]]
+
// the parser does not restrict expressions that may appear as statements
true
42
diff --git a/src/pkg/go/printer/testdata/expressions.raw b/src/go/printer/testdata/expressions.raw
index 97bc81dad..235733695 100644
--- a/src/pkg/go/printer/testdata/expressions.raw
+++ b/src/go/printer/testdata/expressions.raw
@@ -94,6 +94,11 @@ func _() {
_ = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
_ = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx)
+ // test case for issue 8021
+ // want:
+ // ([]bool{})[([]int{})[((1)+(((1)+((((1)*(((1)+(1))+(1)))+(1))*(1)))+(1)))]]
+ _ = ([]bool{})[([]int{})[((1)+(((1)+((((1)*(((1)+(1))+(1)))+(1))*(1)))+(1)))]]
+
// the parser does not restrict expressions that may appear as statements
true
42
diff --git a/src/pkg/go/printer/testdata/linebreaks.golden b/src/go/printer/testdata/linebreaks.golden
index 006cf1718..006cf1718 100644
--- a/src/pkg/go/printer/testdata/linebreaks.golden
+++ b/src/go/printer/testdata/linebreaks.golden
diff --git a/src/pkg/go/printer/testdata/linebreaks.input b/src/go/printer/testdata/linebreaks.input
index e782bb044..e782bb044 100644
--- a/src/pkg/go/printer/testdata/linebreaks.input
+++ b/src/go/printer/testdata/linebreaks.input
diff --git a/src/pkg/go/printer/testdata/parser.go b/src/go/printer/testdata/parser.go
index dba8bbd43..dba8bbd43 100644
--- a/src/pkg/go/printer/testdata/parser.go
+++ b/src/go/printer/testdata/parser.go
diff --git a/src/pkg/go/printer/testdata/slow.golden b/src/go/printer/testdata/slow.golden
index 43a15cb1d..43a15cb1d 100644
--- a/src/pkg/go/printer/testdata/slow.golden
+++ b/src/go/printer/testdata/slow.golden
diff --git a/src/pkg/go/printer/testdata/slow.input b/src/go/printer/testdata/slow.input
index 0e5a23d88..0e5a23d88 100644
--- a/src/pkg/go/printer/testdata/slow.input
+++ b/src/go/printer/testdata/slow.input
diff --git a/src/pkg/go/printer/testdata/statements.golden b/src/go/printer/testdata/statements.golden
index 3b298f95e..4b1346047 100644
--- a/src/pkg/go/printer/testdata/statements.golden
+++ b/src/go/printer/testdata/statements.golden
@@ -309,6 +309,9 @@ func _() {
for x := expr; expr; expr = false {
use(x)
}
+ for range []int{} {
+ println("foo")
+ }
for x := range []int{} {
use(x)
}
@@ -338,6 +341,12 @@ func _() {
a[i] = i
} // multiple lines
+ for range a {
+ }
+ for _ = range a {
+ }
+ for _, _ = range a {
+ }
for i := range a {
}
for i := range a {
@@ -435,7 +444,7 @@ func _() {
}
if x == a+b*(T{42}[0]) {
}
- if x == a+(b * (T{42}[0])) {
+ if x == a+(b*(T{42}[0])) {
}
if x == a+b*(T{42}[0]) {
}
diff --git a/src/pkg/go/printer/testdata/statements.input b/src/go/printer/testdata/statements.input
index e7fcc0e54..cade1576b 100644
--- a/src/pkg/go/printer/testdata/statements.input
+++ b/src/go/printer/testdata/statements.input
@@ -269,6 +269,8 @@ func _() {
for x := expr;expr;expr = false {
use(x)
}
+ for range []int{} {
+ println("foo")}
for x := range []int{} {
use(x) }
for x := range (([]int{})) {
@@ -289,6 +291,9 @@ func _() {
for i := 0; i < len(a); 1++ { a[i] = i
} // multiple lines
+ for range a{}
+ for _ = range a{}
+ for _, _ = range a{}
for i := range a {}
for i := range a { a[i] = i }
for i := range a { a[i] = i
diff --git a/src/pkg/go/scanner/errors.go b/src/go/scanner/errors.go
index 22de69c3c..22de69c3c 100644
--- a/src/pkg/go/scanner/errors.go
+++ b/src/go/scanner/errors.go
diff --git a/src/pkg/go/scanner/example_test.go b/src/go/scanner/example_test.go
index 9004a4ad3..9004a4ad3 100644
--- a/src/pkg/go/scanner/example_test.go
+++ b/src/go/scanner/example_test.go
diff --git a/src/pkg/go/scanner/scanner.go b/src/go/scanner/scanner.go
index cec82ea10..cec82ea10 100644
--- a/src/pkg/go/scanner/scanner.go
+++ b/src/go/scanner/scanner.go
diff --git a/src/pkg/go/scanner/scanner_test.go b/src/go/scanner/scanner_test.go
index fc450d8a6..fc450d8a6 100644
--- a/src/pkg/go/scanner/scanner_test.go
+++ b/src/go/scanner/scanner_test.go
diff --git a/src/pkg/go/token/position.go b/src/go/token/position.go
index e6f0ae6a6..82d90eeb7 100644
--- a/src/pkg/go/token/position.go
+++ b/src/go/token/position.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.
-// TODO(gri) consider making this a separate package outside the go directory.
-
package token
import (
@@ -184,6 +182,7 @@ func (f *File) SetLines(lines []int) bool {
}
// SetLinesForContent sets the line offsets for the given file content.
+// It ignores position-altering //line comments.
func (f *File) SetLinesForContent(content []byte) {
var lines []int
line := 0
@@ -255,7 +254,6 @@ func (f *File) Offset(p Pos) int {
// p must be a Pos value in that file or NoPos.
//
func (f *File) Line(p Pos) int {
- // TODO(gri) this can be implemented much more efficiently
return f.Position(p).Line
}
@@ -263,13 +261,16 @@ func searchLineInfos(a []lineInfo, x int) int {
return sort.Search(len(a), func(i int) bool { return a[i].Offset > x }) - 1
}
-// info returns the file name, line, and column number for a file offset.
-func (f *File) info(offset int) (filename string, line, column int) {
+// unpack returns the filename and line and column number for a file offset.
+// If adjusted is set, unpack will return the filename and line information
+// possibly adjusted by //line comments; otherwise those comments are ignored.
+//
+func (f *File) unpack(offset int, adjusted bool) (filename string, line, column int) {
filename = f.name
if i := searchInts(f.lines, offset); i >= 0 {
line, column = i+1, offset-f.lines[i]+1
}
- if len(f.infos) > 0 {
+ if adjusted && len(f.infos) > 0 {
// almost no files have extra line infos
if i := searchLineInfos(f.infos, offset); i >= 0 {
alt := &f.infos[i]
@@ -282,26 +283,35 @@ func (f *File) info(offset int) (filename string, line, column int) {
return
}
-func (f *File) position(p Pos) (pos Position) {
+func (f *File) position(p Pos, adjusted bool) (pos Position) {
offset := int(p) - f.base
pos.Offset = offset
- pos.Filename, pos.Line, pos.Column = f.info(offset)
+ pos.Filename, pos.Line, pos.Column = f.unpack(offset, adjusted)
return
}
-// Position returns the Position value for the given file position p;
-// p must be a Pos value in that file or NoPos.
+// PositionFor returns the Position value for the given file position p.
+// If adjusted is set, the position may be adjusted by position-altering
+// //line comments; otherwise those comments are ignored.
+// p must be a Pos value in f or NoPos.
//
-func (f *File) Position(p Pos) (pos Position) {
+func (f *File) PositionFor(p Pos, adjusted bool) (pos Position) {
if p != NoPos {
if int(p) < f.base || int(p) > f.base+f.size {
panic("illegal Pos value")
}
- pos = f.position(p)
+ pos = f.position(p, adjusted)
}
return
}
+// Position returns the Position value for the given file position p.
+// Calling f.Position(p) is equivalent to calling f.PositionFor(p, true).
+//
+func (f *File) Position(p Pos) (pos Position) {
+ return f.PositionFor(p, true)
+}
+
// -----------------------------------------------------------------------------
// FileSet
@@ -427,16 +437,27 @@ func (s *FileSet) File(p Pos) (f *File) {
return
}
-// Position converts a Pos in the fileset into a general Position.
-func (s *FileSet) Position(p Pos) (pos Position) {
+// PositionFor converts a Pos p in the fileset into a Position value.
+// If adjusted is set, the position may be adjusted by position-altering
+// //line comments; otherwise those comments are ignored.
+// p must be a Pos value in s or NoPos.
+//
+func (s *FileSet) PositionFor(p Pos, adjusted bool) (pos Position) {
if p != NoPos {
if f := s.file(p); f != nil {
- pos = f.position(p)
+ pos = f.position(p, adjusted)
}
}
return
}
+// Position converts a Pos p in the fileset into a Position value.
+// Calling s.Position(p) is equivalent to calling s.PositionFor(p, true).
+//
+func (s *FileSet) Position(p Pos) (pos Position) {
+ return s.PositionFor(p, true)
+}
+
// -----------------------------------------------------------------------------
// Helper functions
diff --git a/src/pkg/go/token/position_test.go b/src/go/token/position_test.go
index ef6cfd93c..d26939ce2 100644
--- a/src/pkg/go/token/position_test.go
+++ b/src/go/token/position_test.go
@@ -11,18 +11,18 @@ import (
"testing"
)
-func checkPos(t *testing.T, msg string, p, q Position) {
- if p.Filename != q.Filename {
- t.Errorf("%s: expected filename = %q; got %q", msg, q.Filename, p.Filename)
+func checkPos(t *testing.T, msg string, got, want Position) {
+ if got.Filename != want.Filename {
+ t.Errorf("%s: got filename = %q; want %q", msg, got.Filename, want.Filename)
}
- if p.Offset != q.Offset {
- t.Errorf("%s: expected offset = %d; got %d", msg, q.Offset, p.Offset)
+ if got.Offset != want.Offset {
+ t.Errorf("%s: got offset = %d; want %d", msg, got.Offset, want.Offset)
}
- if p.Line != q.Line {
- t.Errorf("%s: expected line = %d; got %d", msg, q.Line, p.Line)
+ if got.Line != want.Line {
+ t.Errorf("%s: got line = %d; want %d", msg, got.Line, want.Line)
}
- if p.Column != q.Column {
- t.Errorf("%s: expected column = %d; got %d", msg, q.Column, p.Column)
+ if got.Column != want.Column {
+ t.Errorf("%s: got column = %d; want %d", msg, got.Column, want.Column)
}
}
@@ -68,7 +68,7 @@ func verifyPositions(t *testing.T, fset *FileSet, f *File, lines []int) {
p := f.Pos(offs)
offs2 := f.Offset(p)
if offs2 != offs {
- t.Errorf("%s, Offset: expected offset %d; got %d", f.Name(), offs, offs2)
+ t.Errorf("%s, Offset: got offset %d; want %d", f.Name(), offs2, offs)
}
line, col := linecol(lines, offs)
msg := fmt.Sprintf("%s (offs = %d, p = %d)", f.Name(), offs, p)
@@ -93,16 +93,16 @@ func TestPositions(t *testing.T) {
for _, test := range tests {
// verify consistency of test case
if test.source != nil && len(test.source) != test.size {
- t.Errorf("%s: inconsistent test case: expected file size %d; got %d", test.filename, test.size, len(test.source))
+ t.Errorf("%s: inconsistent test case: got file size %d; want %d", test.filename, len(test.source), test.size)
}
// add file and verify name and size
f := fset.AddFile(test.filename, fset.Base()+delta, test.size)
if f.Name() != test.filename {
- t.Errorf("expected filename %q; got %q", test.filename, f.Name())
+ t.Errorf("got filename %q; want %q", f.Name(), test.filename)
}
if f.Size() != test.size {
- t.Errorf("%s: expected file size %d; got %d", f.Name(), test.size, f.Size())
+ t.Errorf("%s: got file size %d; want %d", f.Name(), f.Size(), test.size)
}
if fset.File(f.Pos(0)) != f {
t.Errorf("%s: f.Pos(0) was not found in f", f.Name())
@@ -112,12 +112,12 @@ func TestPositions(t *testing.T) {
for i, offset := range test.lines {
f.AddLine(offset)
if f.LineCount() != i+1 {
- t.Errorf("%s, AddLine: expected line count %d; got %d", f.Name(), i+1, f.LineCount())
+ t.Errorf("%s, AddLine: got line count %d; want %d", f.Name(), f.LineCount(), i+1)
}
// adding the same offset again should be ignored
f.AddLine(offset)
if f.LineCount() != i+1 {
- t.Errorf("%s, AddLine: expected unchanged line count %d; got %d", f.Name(), i+1, f.LineCount())
+ t.Errorf("%s, AddLine: got unchanged line count %d; want %d", f.Name(), f.LineCount(), i+1)
}
verifyPositions(t, fset, f, test.lines[0:i+1])
}
@@ -127,7 +127,7 @@ func TestPositions(t *testing.T) {
t.Errorf("%s: SetLines failed", f.Name())
}
if f.LineCount() != len(test.lines) {
- t.Errorf("%s, SetLines: expected line count %d; got %d", f.Name(), len(test.lines), f.LineCount())
+ t.Errorf("%s, SetLines: got line count %d; want %d", f.Name(), f.LineCount(), len(test.lines))
}
verifyPositions(t, fset, f, test.lines)
@@ -139,7 +139,7 @@ func TestPositions(t *testing.T) {
}
f.SetLinesForContent(src)
if f.LineCount() != len(test.lines) {
- t.Errorf("%s, SetLinesForContent: expected line count %d; got %d", f.Name(), len(test.lines), f.LineCount())
+ t.Errorf("%s, SetLinesForContent: got line count %d; want %d", f.Name(), f.LineCount(), len(test.lines))
}
verifyPositions(t, fset, f, test.lines)
}
@@ -177,13 +177,13 @@ func TestFiles(t *testing.T) {
j := 0
fset.Iterate(func(f *File) bool {
if f.Name() != tests[j].filename {
- t.Errorf("expected filename = %s; got %s", tests[j].filename, f.Name())
+ t.Errorf("got filename = %s; want %s", f.Name(), tests[j].filename)
}
j++
return true
})
if j != i+1 {
- t.Errorf("expected %d files; got %d", i+1, j)
+ t.Errorf("got %d files; want %d", j, i+1)
}
}
}
@@ -195,7 +195,7 @@ func TestFileSetPastEnd(t *testing.T) {
fset.AddFile(test.filename, fset.Base(), test.size)
}
if f := fset.File(Pos(fset.Base())); f != nil {
- t.Errorf("expected nil, got %v", f)
+ t.Errorf("got %v, want nil", f)
}
}
@@ -209,7 +209,7 @@ func TestFileSetCacheUnlikely(t *testing.T) {
for file, pos := range offsets {
f := fset.File(Pos(pos))
if f.Name() != file {
- t.Errorf("expecting %q at position %d, got %q", file, pos, f.Name())
+ t.Errorf("got %q at position %d, want %q", f.Name(), pos, file)
}
}
}
@@ -236,3 +236,62 @@ func TestFileSetRace(t *testing.T) {
}
stop.Wait()
}
+
+func TestPositionFor(t *testing.T) {
+ src := []byte(`
+foo
+b
+ar
+//line :100
+foobar
+//line bar:3
+done
+`)
+
+ const filename = "foo"
+ fset := NewFileSet()
+ f := fset.AddFile(filename, fset.Base(), len(src))
+ f.SetLinesForContent(src)
+
+ // verify position info
+ for i, offs := range f.lines {
+ got1 := f.PositionFor(f.Pos(offs), false)
+ got2 := f.PositionFor(f.Pos(offs), true)
+ got3 := f.Position(f.Pos(offs))
+ want := Position{filename, offs, i + 1, 1}
+ checkPos(t, "1. PositionFor unadjusted", got1, want)
+ checkPos(t, "1. PositionFor adjusted", got2, want)
+ checkPos(t, "1. Position", got3, want)
+ }
+
+ // manually add //line info on lines l1, l2
+ const l1, l2 = 5, 7
+ f.AddLineInfo(f.lines[l1-1], "", 100)
+ f.AddLineInfo(f.lines[l2-1], "bar", 3)
+
+ // unadjusted position info must remain unchanged
+ for i, offs := range f.lines {
+ got1 := f.PositionFor(f.Pos(offs), false)
+ want := Position{filename, offs, i + 1, 1}
+ checkPos(t, "2. PositionFor unadjusted", got1, want)
+ }
+
+ // adjusted position info should have changed
+ for i, offs := range f.lines {
+ got2 := f.PositionFor(f.Pos(offs), true)
+ got3 := f.Position(f.Pos(offs))
+ want := Position{filename, offs, i + 1, 1}
+ // manually compute wanted filename and line
+ line := want.Line
+ if i+1 >= l1 {
+ want.Filename = ""
+ want.Line = line - l1 + 100
+ }
+ if i+1 >= l2 {
+ want.Filename = "bar"
+ want.Line = line - l2 + 3
+ }
+ checkPos(t, "3. PositionFor adjusted", got2, want)
+ checkPos(t, "3. Position", got3, want)
+ }
+}
diff --git a/src/pkg/go/token/serialize.go b/src/go/token/serialize.go
index 4adc8f9e3..4adc8f9e3 100644
--- a/src/pkg/go/token/serialize.go
+++ b/src/go/token/serialize.go
diff --git a/src/pkg/go/token/serialize_test.go b/src/go/token/serialize_test.go
index 4e925adb6..4e925adb6 100644
--- a/src/pkg/go/token/serialize_test.go
+++ b/src/go/token/serialize_test.go
diff --git a/src/pkg/go/token/token.go b/src/go/token/token.go
index 865f63f4a..865f63f4a 100644
--- a/src/pkg/go/token/token.go
+++ b/src/go/token/token.go
diff --git a/src/pkg/hash/adler32/adler32.go b/src/hash/adler32/adler32.go
index 7c80796bf..7c80796bf 100644
--- a/src/pkg/hash/adler32/adler32.go
+++ b/src/hash/adler32/adler32.go
diff --git a/src/pkg/hash/adler32/adler32_test.go b/src/hash/adler32/adler32_test.go
index 0e9c938d8..0e9c938d8 100644
--- a/src/pkg/hash/adler32/adler32_test.go
+++ b/src/hash/adler32/adler32_test.go
diff --git a/src/pkg/hash/crc32/crc32.go b/src/hash/crc32/crc32.go
index a2a21a06f..6a6b9473b 100644
--- a/src/pkg/hash/crc32/crc32.go
+++ b/src/hash/crc32/crc32.go
@@ -17,8 +17,8 @@ const Size = 4
// Predefined polynomials.
const (
- // Far and away the most common CRC-32 polynomial.
- // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, mpeg-2, ...
+ // IEEE is by far and away the most common CRC-32 polynomial.
+ // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ...
IEEE = 0xedb88320
// Castagnoli's polynomial, used in iSCSI.
diff --git a/src/pkg/hash/crc32/crc32_amd64.s b/src/hash/crc32/crc32_amd64.s
index 95dc8bf41..30b0d0691 100644
--- a/src/pkg/hash/crc32/crc32_amd64.s
+++ b/src/hash/crc32/crc32_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// func castagnoliSSE42(crc uint32, p []byte) uint32
TEXT ·castagnoliSSE42(SB),NOSPLIT,$0
diff --git a/src/pkg/hash/crc32/crc32_amd64p32.s b/src/hash/crc32/crc32_amd64p32.s
index e34f20867..b6770eba3 100644
--- a/src/pkg/hash/crc32/crc32_amd64p32.s
+++ b/src/hash/crc32/crc32_amd64p32.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// func castagnoliSSE42(crc uint32, p []byte) uint32
TEXT ·castagnoliSSE42(SB),NOSPLIT,$0
diff --git a/src/pkg/hash/crc32/crc32_amd64x.go b/src/hash/crc32/crc32_amd64x.go
index b7e359930..b7e359930 100644
--- a/src/pkg/hash/crc32/crc32_amd64x.go
+++ b/src/hash/crc32/crc32_amd64x.go
diff --git a/src/pkg/hash/crc32/crc32_generic.go b/src/hash/crc32/crc32_generic.go
index c3fdcd685..c3fdcd685 100644
--- a/src/pkg/hash/crc32/crc32_generic.go
+++ b/src/hash/crc32/crc32_generic.go
diff --git a/src/pkg/hash/crc32/crc32_test.go b/src/hash/crc32/crc32_test.go
index 75dc26e7c..75dc26e7c 100644
--- a/src/pkg/hash/crc32/crc32_test.go
+++ b/src/hash/crc32/crc32_test.go
diff --git a/src/pkg/hash/crc64/crc64.go b/src/hash/crc64/crc64.go
index 692586798..692586798 100644
--- a/src/pkg/hash/crc64/crc64.go
+++ b/src/hash/crc64/crc64.go
diff --git a/src/pkg/hash/crc64/crc64_test.go b/src/hash/crc64/crc64_test.go
index 81a87b56e..81a87b56e 100644
--- a/src/pkg/hash/crc64/crc64_test.go
+++ b/src/hash/crc64/crc64_test.go
diff --git a/src/pkg/hash/fnv/fnv.go b/src/hash/fnv/fnv.go
index c0206613a..c0206613a 100644
--- a/src/pkg/hash/fnv/fnv.go
+++ b/src/hash/fnv/fnv.go
diff --git a/src/pkg/hash/fnv/fnv_test.go b/src/hash/fnv/fnv_test.go
index 89d39b38a..89d39b38a 100644
--- a/src/pkg/hash/fnv/fnv_test.go
+++ b/src/hash/fnv/fnv_test.go
diff --git a/src/pkg/hash/hash.go b/src/hash/hash.go
index 8d138d07f..8d138d07f 100644
--- a/src/pkg/hash/hash.go
+++ b/src/hash/hash.go
diff --git a/src/pkg/hash/test_cases.txt b/src/hash/test_cases.txt
index 26d3ccc05..26d3ccc05 100644
--- a/src/pkg/hash/test_cases.txt
+++ b/src/hash/test_cases.txt
diff --git a/src/pkg/hash/test_gen.awk b/src/hash/test_gen.awk
index 804f78679..804f78679 100644
--- a/src/pkg/hash/test_gen.awk
+++ b/src/hash/test_gen.awk
diff --git a/src/pkg/html/entity.go b/src/html/entity.go
index af8a007ed..af8a007ed 100644
--- a/src/pkg/html/entity.go
+++ b/src/html/entity.go
diff --git a/src/pkg/html/entity_test.go b/src/html/entity_test.go
index b53f866fa..b53f866fa 100644
--- a/src/pkg/html/entity_test.go
+++ b/src/html/entity_test.go
diff --git a/src/pkg/html/escape.go b/src/html/escape.go
index dd5dfa7cd..dd5dfa7cd 100644
--- a/src/pkg/html/escape.go
+++ b/src/html/escape.go
diff --git a/src/pkg/html/escape_test.go b/src/html/escape_test.go
index 2d7ad8ac2..2d7ad8ac2 100644
--- a/src/pkg/html/escape_test.go
+++ b/src/html/escape_test.go
diff --git a/src/pkg/html/template/attr.go b/src/html/template/attr.go
index d65d34007..d65d34007 100644
--- a/src/pkg/html/template/attr.go
+++ b/src/html/template/attr.go
diff --git a/src/pkg/html/template/clone_test.go b/src/html/template/clone_test.go
index e11bff2c5..e11bff2c5 100644
--- a/src/pkg/html/template/clone_test.go
+++ b/src/html/template/clone_test.go
diff --git a/src/pkg/html/template/content.go b/src/html/template/content.go
index 3715ed5c9..3715ed5c9 100644
--- a/src/pkg/html/template/content.go
+++ b/src/html/template/content.go
diff --git a/src/pkg/html/template/content_test.go b/src/html/template/content_test.go
index 5f3ffe2d3..5f3ffe2d3 100644
--- a/src/pkg/html/template/content_test.go
+++ b/src/html/template/content_test.go
diff --git a/src/pkg/html/template/context.go b/src/html/template/context.go
index 59e794d68..59e794d68 100644
--- a/src/pkg/html/template/context.go
+++ b/src/html/template/context.go
diff --git a/src/pkg/html/template/css.go b/src/html/template/css.go
index 634f183f7..634f183f7 100644
--- a/src/pkg/html/template/css.go
+++ b/src/html/template/css.go
diff --git a/src/pkg/html/template/css_test.go b/src/html/template/css_test.go
index a735638b0..a735638b0 100644
--- a/src/pkg/html/template/css_test.go
+++ b/src/html/template/css_test.go
diff --git a/src/pkg/html/template/doc.go b/src/html/template/doc.go
index d422ada37..d422ada37 100644
--- a/src/pkg/html/template/doc.go
+++ b/src/html/template/doc.go
diff --git a/src/pkg/html/template/error.go b/src/html/template/error.go
index 46e49ccf8..8f99e1b96 100644
--- a/src/pkg/html/template/error.go
+++ b/src/html/template/error.go
@@ -6,12 +6,16 @@ package template
import (
"fmt"
+ "text/template/parse"
)
// Error describes a problem encountered during template Escaping.
type Error struct {
// ErrorCode describes the kind of error.
ErrorCode ErrorCode
+ // Node is the node that caused the problem, if known.
+ // If not nil, it overrides Name and Line.
+ Node parse.Node
// Name is the name of the template in which the error was encountered.
Name string
// Line is the line number of the error in the template source or 0.
@@ -182,9 +186,13 @@ const (
)
func (e *Error) Error() string {
- if e.Line != 0 {
+ switch {
+ case e.Node != nil:
+ loc, _ := (*parse.Tree)(nil).ErrorContext(e.Node)
+ return fmt.Sprintf("html/template:%s: %s", loc, e.Description)
+ case e.Line != 0:
return fmt.Sprintf("html/template:%s:%d: %s", e.Name, e.Line, e.Description)
- } else if e.Name != "" {
+ case e.Name != "":
return fmt.Sprintf("html/template:%s: %s", e.Name, e.Description)
}
return "html/template: " + e.Description
@@ -192,6 +200,6 @@ func (e *Error) Error() string {
// errorf creates an error given a format string f and args.
// The template Name still needs to be supplied.
-func errorf(k ErrorCode, line int, f string, args ...interface{}) *Error {
- return &Error{k, "", line, fmt.Sprintf(f, args...)}
+func errorf(k ErrorCode, node parse.Node, line int, f string, args ...interface{}) *Error {
+ return &Error{k, node, "", line, fmt.Sprintf(f, args...)}
}
diff --git a/src/pkg/html/template/escape.go b/src/html/template/escape.go
index 4e379828d..ee01fb12a 100644
--- a/src/pkg/html/template/escape.go
+++ b/src/html/template/escape.go
@@ -13,40 +13,33 @@ import (
"text/template/parse"
)
-// escapeTemplates rewrites the named templates, which must be
+// escapeTemplate rewrites the named template, which must be
// associated with t, to guarantee that the output of any of the named
-// templates is properly escaped. Names should include the names of
-// all templates that might be Executed but need not include helper
-// templates. If no error is returned, then the named templates have
+// templates is properly escaped. If no error is returned, then the named templates have
// been modified. Otherwise the named templates have been rendered
// unusable.
-func escapeTemplates(tmpl *Template, names ...string) error {
+func escapeTemplate(tmpl *Template, node parse.Node, name string) error {
e := newEscaper(tmpl)
- for _, name := range names {
- c, _ := e.escapeTree(context{}, name, 0)
- var err error
- if c.err != nil {
- err, c.err.Name = c.err, name
- } else if c.state != stateText {
- err = &Error{ErrEndContext, name, 0, fmt.Sprintf("ends in a non-text context: %v", c)}
- }
- if err != nil {
- // Prevent execution of unsafe templates.
- for _, name := range names {
- if t := tmpl.set[name]; t != nil {
- t.text.Tree = nil
- t.Tree = nil
- }
- }
- return err
+ c, _ := e.escapeTree(context{}, node, name, 0)
+ var err error
+ if c.err != nil {
+ err, c.err.Name = c.err, name
+ } else if c.state != stateText {
+ err = &Error{ErrEndContext, nil, name, 0, fmt.Sprintf("ends in a non-text context: %v", c)}
+ }
+ if err != nil {
+ // Prevent execution of unsafe templates.
+ if t := tmpl.set[name]; t != nil {
+ t.escapeErr = err
+ t.text.Tree = nil
+ t.Tree = nil
}
+ return err
}
e.commit()
- for _, name := range names {
- if t := tmpl.set[name]; t != nil {
- t.escaped = true
- t.Tree = t.text.Tree
- }
+ if t := tmpl.set[name]; t != nil {
+ t.escapeErr = escapeOK
+ t.Tree = t.text.Tree
}
return nil
}
@@ -168,7 +161,7 @@ func (e *escaper) escapeAction(c context, n *parse.ActionNode) context {
case urlPartUnknown:
return context{
state: stateError,
- err: errorf(ErrAmbigContext, n.Line, "%s appears in an ambiguous URL context", n),
+ err: errorf(ErrAmbigContext, n, n.Line, "%s appears in an ambiguous URL context", n),
}
default:
panic(c.urlPart.String())
@@ -338,7 +331,7 @@ func escFnsEq(a, b string) bool {
func newIdentCmd(identifier string, pos parse.Pos) *parse.CommandNode {
return &parse.CommandNode{
NodeType: parse.NodeCommand,
- Args: []parse.Node{parse.NewIdentifier(identifier).SetPos(pos)},
+ Args: []parse.Node{parse.NewIdentifier(identifier).SetTree(nil).SetPos(pos)}, // TODO: SetTree.
}
}
@@ -372,7 +365,7 @@ func nudge(c context) context {
// join joins the two contexts of a branch template node. The result is an
// error context if either of the input contexts are error contexts, or if the
// the input contexts differ.
-func join(a, b context, line int, nodeName string) context {
+func join(a, b context, node parse.Node, nodeName string) context {
if a.state == stateError {
return a
}
@@ -405,14 +398,14 @@ func join(a, b context, line int, nodeName string) context {
// ends in an unquoted value state even though the else branch
// ends in stateBeforeValue.
if c, d := nudge(a), nudge(b); !(c.eq(a) && d.eq(b)) {
- if e := join(c, d, line, nodeName); e.state != stateError {
+ if e := join(c, d, node, nodeName); e.state != stateError {
return e
}
}
return context{
state: stateError,
- err: errorf(ErrBranchEnd, line, "{{%s}} branches end in different contexts: %v, %v", nodeName, a, b),
+ err: errorf(ErrBranchEnd, node, 0, "{{%s}} branches end in different contexts: %v, %v", nodeName, a, b),
}
}
@@ -424,7 +417,7 @@ func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string)
// We check that executing n.List once results in the same context
// as executing n.List twice.
c1, _ := e.escapeListConditionally(c0, n.List, nil)
- c0 = join(c0, c1, n.Line, nodeName)
+ c0 = join(c0, c1, n, nodeName)
if c0.state == stateError {
// Make clear that this is a problem on loop re-entry
// since developers tend to overlook that branch when
@@ -435,7 +428,7 @@ func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string)
}
}
c1 := e.escapeList(c, n.ElseList)
- return join(c0, c1, n.Line, nodeName)
+ return join(c0, c1, n, nodeName)
}
// escapeList escapes a list template node.
@@ -487,7 +480,7 @@ func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, filter f
// escapeTemplate escapes a {{template}} call node.
func (e *escaper) escapeTemplate(c context, n *parse.TemplateNode) context {
- c, name := e.escapeTree(c, n.Name, n.Line)
+ c, name := e.escapeTree(c, n, n.Name, n.Line)
if name != n.Name {
e.editTemplateNode(n, name)
}
@@ -496,7 +489,7 @@ func (e *escaper) escapeTemplate(c context, n *parse.TemplateNode) context {
// escapeTree escapes the named template starting in the given context as
// necessary and returns its output context.
-func (e *escaper) escapeTree(c context, name string, line int) (context, string) {
+func (e *escaper) escapeTree(c context, node parse.Node, name string, line int) (context, string) {
// Mangle the template name with the input context to produce a reliable
// identifier.
dname := c.mangle(name)
@@ -512,12 +505,12 @@ func (e *escaper) escapeTree(c context, name string, line int) (context, string)
if e.tmpl.set[name] != nil {
return context{
state: stateError,
- err: errorf(ErrNoSuchTemplate, line, "%q is an incomplete or empty template", name),
+ err: errorf(ErrNoSuchTemplate, node, line, "%q is an incomplete or empty template", name),
}, dname
}
return context{
state: stateError,
- err: errorf(ErrNoSuchTemplate, line, "no such template %q", name),
+ err: errorf(ErrNoSuchTemplate, node, line, "no such template %q", name),
}, dname
}
if dname != name {
@@ -549,8 +542,7 @@ func (e *escaper) computeOutCtx(c context, t *template.Template) context {
if !ok && c1.state != stateError {
return context{
state: stateError,
- // TODO: Find the first node with a line in t.text.Tree.Root
- err: errorf(ErrOutputContext, 0, "cannot compute output context for template %s", t.Name()),
+ err: errorf(ErrOutputContext, t.Tree.Root, 0, "cannot compute output context for template %s", t.Name()),
}
}
return c1
@@ -694,7 +686,7 @@ func contextAfterText(c context, s []byte) (context, int) {
if j := bytes.IndexAny(s[:i], "\"'<=`"); j >= 0 {
return context{
state: stateError,
- err: errorf(ErrBadHTML, 0, "%q in unquoted attr: %q", s[j:j+1], s[:i]),
+ err: errorf(ErrBadHTML, nil, 0, "%q in unquoted attr: %q", s[j:j+1], s[:i]),
}, len(s)
}
}
diff --git a/src/pkg/html/template/escape_test.go b/src/html/template/escape_test.go
index 3ccf93ece..ef7b87748 100644
--- a/src/pkg/html/template/escape_test.go
+++ b/src/html/template/escape_test.go
@@ -861,29 +861,29 @@ func TestErrors(t *testing.T) {
// Error cases.
{
"{{if .Cond}}<a{{end}}",
- "z:1: {{if}} branches",
+ "z:1:5: {{if}} branches",
},
{
"{{if .Cond}}\n{{else}}\n<a{{end}}",
- "z:1: {{if}} branches",
+ "z:1:5: {{if}} branches",
},
{
// Missing quote in the else branch.
`{{if .Cond}}<a href="foo">{{else}}<a href="bar>{{end}}`,
- "z:1: {{if}} branches",
+ "z:1:5: {{if}} branches",
},
{
// Different kind of attribute: href implies a URL.
"<a {{if .Cond}}href='{{else}}title='{{end}}{{.X}}'>",
- "z:1: {{if}} branches",
+ "z:1:8: {{if}} branches",
},
{
"\n{{with .X}}<a{{end}}",
- "z:2: {{with}} branches",
+ "z:2:7: {{with}} branches",
},
{
"\n{{with .X}}<a>{{else}}<a{{end}}",
- "z:2: {{with}} branches",
+ "z:2:7: {{with}} branches",
},
{
"{{range .Items}}<a{{end}}",
@@ -891,7 +891,7 @@ func TestErrors(t *testing.T) {
},
{
"\n{{range .Items}} x='<a{{end}}",
- "z:2: on range loop re-entry: {{range}} branches",
+ "z:2:8: on range loop re-entry: {{range}} branches",
},
{
"<a b=1 c={{.H}}",
@@ -903,7 +903,7 @@ func TestErrors(t *testing.T) {
},
{
`<a href="{{if .F}}/foo?a={{else}}/bar/{{end}}{{.H}}">`,
- "z:1: {{.H}} appears in an ambiguous URL context",
+ "z:1:47: {{.H}} appears in an ambiguous URL context",
},
{
`<a onclick="alert('Hello \`,
@@ -932,7 +932,7 @@ func TestErrors(t *testing.T) {
},
{
`{{template "foo"}}`,
- "z:1: no such template \"foo\"",
+ "z:1:11: no such template \"foo\"",
},
{
`<div{{template "y"}}>` +
@@ -994,6 +994,11 @@ func TestErrors(t *testing.T) {
t.Errorf("input=%q: error\n\t%q\ndoes not contain expected string\n\t%q", test.input, got, test.err)
continue
}
+ // Check that we get the same error if we call Execute again.
+ if err := tmpl.Execute(buf, nil); err == nil || err.Error() != got {
+ t.Errorf("input=%q: unexpected error on second call %q", test.input, err)
+
+ }
}
}
diff --git a/src/pkg/html/template/html.go b/src/html/template/html.go
index 9c069efd1..9c069efd1 100644
--- a/src/pkg/html/template/html.go
+++ b/src/html/template/html.go
diff --git a/src/pkg/html/template/html_test.go b/src/html/template/html_test.go
index b9b970387..b9b970387 100644
--- a/src/pkg/html/template/html_test.go
+++ b/src/html/template/html_test.go
diff --git a/src/pkg/html/template/js.go b/src/html/template/js.go
index 999a61ed0..999a61ed0 100644
--- a/src/pkg/html/template/js.go
+++ b/src/html/template/js.go
diff --git a/src/pkg/html/template/js_test.go b/src/html/template/js_test.go
index 311e1d2c4..7af7997de 100644
--- a/src/pkg/html/template/js_test.go
+++ b/src/html/template/js_test.go
@@ -138,7 +138,7 @@ func TestJSValEscaper(t *testing.T) {
// Newlines.
{"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`},
// "\v" == "v" on IE 6 so use "\x0b" instead.
- {"\t\x0b", `"\u0009\u000b"`},
+ {"\t\x0b", `"\t\u000b"`},
{struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`},
{[]interface{}{}, "[]"},
{[]interface{}{42, "foo", nil}, `[42,"foo",null]`},
diff --git a/src/pkg/html/template/template.go b/src/html/template/template.go
index d38965897..ce6170105 100644
--- a/src/pkg/html/template/template.go
+++ b/src/html/template/template.go
@@ -17,7 +17,8 @@ import (
// Template is a specialized Template from "text/template" that produces a safe
// HTML document fragment.
type Template struct {
- escaped bool
+ // Sticky error if escaping fails.
+ 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
// template's in sync.
@@ -27,6 +28,9 @@ type Template struct {
*nameSpace // common to all associated templates
}
+// escapeOK is a sentinel value used to indicate valid escaping.
+var escapeOK = fmt.Errorf("template escaped correctly")
+
// nameSpace is the data structure shared by all templates in an association.
type nameSpace struct {
mu sync.Mutex
@@ -51,11 +55,12 @@ func (t *Template) Templates() []*Template {
func (t *Template) escape() error {
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
- if !t.escaped {
- if err := escapeTemplates(t, t.Name()); err != nil {
+ if t.escapeErr == nil {
+ if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
return err
}
- t.escaped = true
+ } else if t.escapeErr != escapeOK {
+ return t.escapeErr
}
return nil
}
@@ -97,14 +102,17 @@ func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err err
if tmpl == nil {
return nil, fmt.Errorf("html/template: %q is undefined", name)
}
+ if tmpl.escapeErr != nil && tmpl.escapeErr != escapeOK {
+ return nil, tmpl.escapeErr
+ }
if tmpl.text.Tree == nil || tmpl.text.Root == nil {
return nil, fmt.Errorf("html/template: %q is an incomplete template", name)
}
if t.text.Lookup(name) == nil {
panic("html/template internal error: template escaping out of sync")
}
- if tmpl != nil && !tmpl.escaped {
- err = escapeTemplates(tmpl, name)
+ if tmpl.escapeErr == nil {
+ err = escapeTemplate(tmpl, tmpl.text.Root, name)
}
return tmpl, err
}
@@ -119,7 +127,7 @@ func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err err
// other than space, comments, and template definitions.)
func (t *Template) Parse(src string) (*Template, error) {
t.nameSpace.mu.Lock()
- t.escaped = false
+ t.escapeErr = nil
t.nameSpace.mu.Unlock()
ret, err := t.text.Parse(src)
if err != nil {
@@ -137,7 +145,7 @@ func (t *Template) Parse(src string) (*Template, error) {
tmpl = t.new(name)
}
// Restore our record of this text/template to its unescaped original state.
- tmpl.escaped = false
+ tmpl.escapeErr = nil
tmpl.text = v
tmpl.Tree = v.Tree
}
@@ -151,7 +159,7 @@ func (t *Template) Parse(src string) (*Template, error) {
func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
- if t.escaped {
+ if t.escapeErr != nil {
return nil, fmt.Errorf("html/template: cannot AddParseTree to %q after it has executed", t.Name())
}
text, err := t.text.AddParseTree(name, tree)
@@ -159,7 +167,7 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error
return nil, err
}
ret := &Template{
- false,
+ nil,
text,
text.Tree,
t.nameSpace,
@@ -179,7 +187,7 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error
func (t *Template) Clone() (*Template, error) {
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
- if t.escaped {
+ if t.escapeErr != nil {
return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
}
textClone, err := t.text.Clone()
@@ -187,7 +195,7 @@ func (t *Template) Clone() (*Template, error) {
return nil, err
}
ret := &Template{
- false,
+ nil,
textClone,
textClone.Tree,
&nameSpace{
@@ -197,12 +205,12 @@ func (t *Template) Clone() (*Template, error) {
for _, x := range textClone.Templates() {
name := x.Name()
src := t.set[name]
- if src == nil || src.escaped {
+ if src == nil || src.escapeErr != nil {
return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
}
x.Tree = x.Tree.Copy()
ret.set[name] = &Template{
- false,
+ nil,
x,
x.Tree,
ret.nameSpace,
@@ -214,7 +222,7 @@ func (t *Template) Clone() (*Template, error) {
// New allocates a new HTML template with the given name.
func New(name string) *Template {
tmpl := &Template{
- false,
+ nil,
template.New(name),
nil,
&nameSpace{
@@ -237,7 +245,7 @@ func (t *Template) New(name string) *Template {
// new is the implementation of New, without the lock.
func (t *Template) new(name string) *Template {
tmpl := &Template{
- false,
+ nil,
t.text.New(name),
nil,
t.nameSpace,
diff --git a/src/pkg/html/template/transition.go b/src/html/template/transition.go
index 7f30a7ab8..b486fcd28 100644
--- a/src/pkg/html/template/transition.go
+++ b/src/html/template/transition.go
@@ -102,7 +102,7 @@ func tTag(c context, s []byte) (context, int) {
if i == j {
return context{
state: stateError,
- err: errorf(ErrBadHTML, 0, "expected space, attr name, or end of tag, but got %q", s[i:]),
+ err: errorf(ErrBadHTML, nil, 0, "expected space, attr name, or end of tag, but got %q", s[i:]),
}, len(s)
}
switch attrType(string(s[i:j])) {
@@ -245,7 +245,7 @@ func tJS(c context, s []byte) (context, int) {
default:
return context{
state: stateError,
- err: errorf(ErrSlashAmbig, 0, "'/' could start a division or regexp: %.32q", s[i:]),
+ err: errorf(ErrSlashAmbig, nil, 0, "'/' could start a division or regexp: %.32q", s[i:]),
}, len(s)
}
default:
@@ -277,7 +277,7 @@ func tJSDelimited(c context, s []byte) (context, int) {
if i == len(s) {
return context{
state: stateError,
- err: errorf(ErrPartialEscape, 0, "unfinished escape sequence in JS string: %q", s),
+ err: errorf(ErrPartialEscape, nil, 0, "unfinished escape sequence in JS string: %q", s),
}, len(s)
}
case '[':
@@ -299,7 +299,7 @@ func tJSDelimited(c context, s []byte) (context, int) {
// into charsets is desired.
return context{
state: stateError,
- err: errorf(ErrPartialCharset, 0, "unfinished JS regexp charset: %q", s),
+ err: errorf(ErrPartialCharset, nil, 0, "unfinished JS regexp charset: %q", s),
}, len(s)
}
@@ -459,7 +459,7 @@ func tCSSStr(c context, s []byte) (context, int) {
if i == len(s) {
return context{
state: stateError,
- err: errorf(ErrPartialEscape, 0, "unfinished escape sequence in CSS string: %q", s),
+ err: errorf(ErrPartialEscape, nil, 0, "unfinished escape sequence in CSS string: %q", s),
}, len(s)
}
} else {
@@ -489,7 +489,7 @@ func eatAttrName(s []byte, i int) (int, *Error) {
// These result in a parse warning in HTML5 and are
// indicative of serious problems if seen in an attr
// name in a template.
- return -1, errorf(ErrBadHTML, 0, "%q in attribute name: %.32q", s[j:j+1], s)
+ return -1, errorf(ErrBadHTML, nil, 0, "%q in attribute name: %.32q", s[j:j+1], s)
default:
// No-op.
}
diff --git a/src/pkg/html/template/url.go b/src/html/template/url.go
index 2ca76bf38..2ca76bf38 100644
--- a/src/pkg/html/template/url.go
+++ b/src/html/template/url.go
diff --git a/src/pkg/html/template/url_test.go b/src/html/template/url_test.go
index 5182e9d79..5182e9d79 100644
--- a/src/pkg/html/template/url_test.go
+++ b/src/html/template/url_test.go
diff --git a/src/pkg/image/color/color.go b/src/image/color/color.go
index ff596a76a..ff596a76a 100644
--- a/src/pkg/image/color/color.go
+++ b/src/image/color/color.go
diff --git a/src/image/color/palette/gen.go b/src/image/color/palette/gen.go
new file mode 100644
index 000000000..2b5fdaaf2
--- /dev/null
+++ b/src/image/color/palette/gen.go
@@ -0,0 +1,121 @@
+// 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 ignore
+
+package main
+
+// This program generates palette.go. Invoke it as
+// go run gen.go -output palette.go
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/format"
+ "io"
+ "io/ioutil"
+ "log"
+)
+
+var filename = flag.String("output", "palette.go", "output file name")
+
+func main() {
+ flag.Parse()
+
+ var buf bytes.Buffer
+
+ fmt.Fprintln(&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.`)
+ fmt.Fprintln(&buf)
+ fmt.Fprintln(&buf, "// generated by go run gen.go -output palette.go; DO NOT EDIT")
+ fmt.Fprintln(&buf)
+ fmt.Fprintln(&buf, "package palette")
+ fmt.Fprintln(&buf)
+ fmt.Fprintln(&buf, `import "image/color"`)
+ fmt.Fprintln(&buf)
+ printPlan9(&buf)
+ printWebSafe(&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)
+ }
+}
+
+func printPlan9(w io.Writer) {
+ c, lines := [3]int{}, [256]string{}
+ for r, i := 0, 0; r != 4; r++ {
+ for v := 0; v != 4; v, i = v+1, i+16 {
+ for g, j := 0, v-r; g != 4; g++ {
+ for b := 0; b != 4; b, j = b+1, j+1 {
+ den := r
+ if g > den {
+ den = g
+ }
+ if b > den {
+ den = b
+ }
+ if den == 0 {
+ c[0] = 0x11 * v
+ c[1] = 0x11 * v
+ c[2] = 0x11 * v
+ } else {
+ num := 17 * (4*den + v)
+ c[0] = r * num / den
+ c[1] = g * num / den
+ c[2] = b * num / den
+ }
+ lines[i+(j&0x0f)] =
+ fmt.Sprintf("\tcolor.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", c[0], c[1], c[2])
+ }
+ }
+ }
+ }
+ fmt.Fprintln(w, "// Plan9 is a 256-color palette that partitions the 24-bit RGB space")
+ fmt.Fprintln(w, "// into 4×4×4 subdivision, with 4 shades in each subcube. Compared to the")
+ fmt.Fprintln(w, "// WebSafe, the idea is to reduce the color resolution by dicing the")
+ fmt.Fprintln(w, "// color cube into fewer cells, and to use the extra space to increase the")
+ fmt.Fprintln(w, "// intensity resolution. This results in 16 gray shades (4 gray subcubes with")
+ fmt.Fprintln(w, "// 4 samples in each), 13 shades of each primary and secondary color (3")
+ fmt.Fprintln(w, "// subcubes with 4 samples plus black) and a reasonable selection of colors")
+ fmt.Fprintln(w, "// covering the rest of the color cube. The advantage is better representation")
+ fmt.Fprintln(w, "// of continuous tones.")
+ fmt.Fprintln(w, "//")
+ fmt.Fprintln(w, "// This palette was used in the Plan 9 Operating System, described at")
+ fmt.Fprintln(w, "// http://plan9.bell-labs.com/magic/man2html/6/color")
+ fmt.Fprintln(w, "var Plan9 = []color.Color{")
+ for _, line := range lines {
+ fmt.Fprintln(w, line)
+ }
+ fmt.Fprintln(w, "}")
+ fmt.Fprintln(w)
+}
+
+func printWebSafe(w io.Writer) {
+ lines := [6 * 6 * 6]string{}
+ for r := 0; r < 6; r++ {
+ for g := 0; g < 6; g++ {
+ for b := 0; b < 6; b++ {
+ lines[36*r+6*g+b] =
+ fmt.Sprintf("\tcolor.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", 0x33*r, 0x33*g, 0x33*b)
+ }
+ }
+ }
+ fmt.Fprintln(w, "// WebSafe is a 216-color palette that was popularized by early versions")
+ fmt.Fprintln(w, "// of Netscape Navigator. It is also known as the Netscape Color Cube.")
+ fmt.Fprintln(w, "//")
+ fmt.Fprintln(w, "// See http://en.wikipedia.org/wiki/Web_colors#Web-safe_colors for details.")
+ fmt.Fprintln(w, "var WebSafe = []color.Color{")
+ for _, line := range lines {
+ fmt.Fprintln(w, line)
+ }
+ fmt.Fprintln(w, "}")
+ fmt.Fprintln(w)
+}
diff --git a/src/image/color/palette/generate.go b/src/image/color/palette/generate.go
new file mode 100644
index 000000000..64c2ec0d9
--- /dev/null
+++ b/src/image/color/palette/generate.go
@@ -0,0 +1,8 @@
+// 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.
+
+//go:generate go run gen.go -output palette.go
+
+// Package palette provides standard color palettes.
+package palette
diff --git a/src/pkg/image/color/palette/palette.go b/src/image/color/palette/palette.go
index f761e5368..0bf2c8e1a 100644
--- a/src/pkg/image/color/palette/palette.go
+++ b/src/image/color/palette/palette.go
@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// generated by go run gen.go; DO NOT EDIT
+// generated by go run gen.go -output palette.go; DO NOT EDIT
-// Package palette provides standard color palettes.
package palette
import "image/color"
diff --git a/src/pkg/image/color/ycbcr.go b/src/image/color/ycbcr.go
index 4c2f29ea0..4c2f29ea0 100644
--- a/src/pkg/image/color/ycbcr.go
+++ b/src/image/color/ycbcr.go
diff --git a/src/pkg/image/color/ycbcr_test.go b/src/image/color/ycbcr_test.go
index 92a0e6ff1..92a0e6ff1 100644
--- a/src/pkg/image/color/ycbcr_test.go
+++ b/src/image/color/ycbcr_test.go
diff --git a/src/pkg/image/decode_example_test.go b/src/image/decode_example_test.go
index 21e90fea4..21e90fea4 100644
--- a/src/pkg/image/decode_example_test.go
+++ b/src/image/decode_example_test.go
diff --git a/src/pkg/image/decode_test.go b/src/image/decode_test.go
index 8dee57ee4..8dee57ee4 100644
--- a/src/pkg/image/decode_test.go
+++ b/src/image/decode_test.go
diff --git a/src/pkg/image/draw/bench_test.go b/src/image/draw/bench_test.go
index cc62e25f1..cc62e25f1 100644
--- a/src/pkg/image/draw/bench_test.go
+++ b/src/image/draw/bench_test.go
diff --git a/src/pkg/image/draw/clip_test.go b/src/image/draw/clip_test.go
index 65381f72f..65381f72f 100644
--- a/src/pkg/image/draw/clip_test.go
+++ b/src/image/draw/clip_test.go
diff --git a/src/pkg/image/draw/draw.go b/src/image/draw/draw.go
index 661230e7c..661230e7c 100644
--- a/src/pkg/image/draw/draw.go
+++ b/src/image/draw/draw.go
diff --git a/src/pkg/image/draw/draw_test.go b/src/image/draw/draw_test.go
index 0dd7fbd47..0dd7fbd47 100644
--- a/src/pkg/image/draw/draw_test.go
+++ b/src/image/draw/draw_test.go
diff --git a/src/pkg/image/format.go b/src/image/format.go
index 3668de4e6..3668de4e6 100644
--- a/src/pkg/image/format.go
+++ b/src/image/format.go
diff --git a/src/pkg/image/geom.go b/src/image/geom.go
index 6ebaf67da..6ebaf67da 100644
--- a/src/pkg/image/geom.go
+++ b/src/image/geom.go
diff --git a/src/pkg/image/gif/reader.go b/src/image/gif/reader.go
index 926710a45..5a863e204 100644
--- a/src/pkg/image/gif/reader.go
+++ b/src/image/gif/reader.go
@@ -171,7 +171,8 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
if err != nil {
return err
}
- if d.imageFields&fColorMapFollows != 0 {
+ useLocalColorMap := d.imageFields&fColorMapFollows != 0
+ if useLocalColorMap {
m.Palette, err = d.readColorMap()
if err != nil {
return err
@@ -180,6 +181,10 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
m.Palette = d.globalColorMap
}
if d.hasTransparentIndex && int(d.transparentIndex) < len(m.Palette) {
+ if !useLocalColorMap {
+ // Clone the global color map.
+ m.Palette = append(color.Palette(nil), d.globalColorMap...)
+ }
m.Palette[d.transparentIndex] = color.RGBA{}
}
litWidth, err := d.r.ReadByte()
diff --git a/src/pkg/image/gif/reader_test.go b/src/image/gif/reader_test.go
index fc2041e99..7b6f50436 100644
--- a/src/pkg/image/gif/reader_test.go
+++ b/src/image/gif/reader_test.go
@@ -22,16 +22,16 @@ const (
trailerStr = "\x3b"
)
-func TestDecode(t *testing.T) {
- // lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes.
- lzwEncode := func(n int) []byte {
- b := &bytes.Buffer{}
- w := lzw.NewWriter(b, lzw.LSB, 2)
- w.Write(make([]byte, n))
- w.Close()
- return b.Bytes()
- }
+// lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes.
+func lzwEncode(n int) []byte {
+ b := &bytes.Buffer{}
+ w := lzw.NewWriter(b, lzw.LSB, 2)
+ w.Write(make([]byte, n))
+ w.Close()
+ return b.Bytes()
+}
+func TestDecode(t *testing.T) {
testCases := []struct {
nPix int // The number of pixels in the image data.
extra bool // Whether to write an extra block after the LZW-encoded data.
@@ -90,6 +90,52 @@ func TestDecode(t *testing.T) {
}
}
+func TestTransparentIndex(t *testing.T) {
+ b := &bytes.Buffer{}
+ b.WriteString(headerStr)
+ b.WriteString(paletteStr)
+ for transparentIndex := 0; transparentIndex < 3; transparentIndex++ {
+ if transparentIndex < 2 {
+ // Write the graphic control for the transparent index.
+ b.WriteString("\x21\xf9\x00\x01\x00\x00")
+ b.WriteByte(byte(transparentIndex))
+ b.WriteByte(0)
+ }
+ // Write an image with bounds 2x1, as per TestDecode.
+ b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
+ enc := lzwEncode(2)
+ if len(enc) > 0xff {
+ t.Fatalf("compressed length %d is too large", len(enc))
+ }
+ b.WriteByte(byte(len(enc)))
+ b.Write(enc)
+ b.WriteByte(0x00)
+ }
+ b.WriteString(trailerStr)
+
+ g, err := DecodeAll(b)
+ if err != nil {
+ t.Fatalf("DecodeAll: %v", err)
+ }
+ c0 := color.RGBA{paletteStr[0], paletteStr[1], paletteStr[2], 0xff}
+ c1 := color.RGBA{paletteStr[3], paletteStr[4], paletteStr[5], 0xff}
+ cz := color.RGBA{}
+ wants := []color.Palette{
+ {cz, c1},
+ {c0, cz},
+ {c0, c1},
+ }
+ if len(g.Image) != len(wants) {
+ t.Fatalf("got %d images, want %d", len(g.Image), len(wants))
+ }
+ for i, want := range wants {
+ got := g.Image[i].Palette
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("palette #%d:\ngot %v\nwant %v", i, got, want)
+ }
+ }
+}
+
// testGIF is a simple GIF that we can modify to test different scenarios.
var testGIF = []byte{
'G', 'I', 'F', '8', '9', 'a',
diff --git a/src/pkg/image/gif/writer.go b/src/image/gif/writer.go
index 15cd40fad..49abde704 100644
--- a/src/pkg/image/gif/writer.go
+++ b/src/image/gif/writer.go
@@ -233,10 +233,20 @@ func (e *encoder) writeImageBlock(pm *image.Paletted, delay int) {
e.writeByte(uint8(litWidth)) // LZW Minimum Code Size.
lzww := lzw.NewWriter(blockWriter{e: e}, lzw.LSB, litWidth)
- _, e.err = lzww.Write(pm.Pix)
- if e.err != nil {
- lzww.Close()
- return
+ if dx := b.Dx(); dx == pm.Stride {
+ _, e.err = lzww.Write(pm.Pix)
+ if e.err != nil {
+ lzww.Close()
+ return
+ }
+ } else {
+ for i, y := 0, b.Min.Y; y < b.Max.Y; i, y = i+pm.Stride, y+1 {
+ _, e.err = lzww.Write(pm.Pix[i : i+dx])
+ if e.err != nil {
+ lzww.Close()
+ return
+ }
+ }
}
lzww.Close()
e.writeByte(0x00) // Block Terminator.
diff --git a/src/pkg/image/gif/writer_test.go b/src/image/gif/writer_test.go
index c1ada769c..93306ffdb 100644
--- a/src/pkg/image/gif/writer_test.go
+++ b/src/image/gif/writer_test.go
@@ -102,6 +102,29 @@ func TestWriter(t *testing.T) {
}
}
+func TestSubImage(t *testing.T) {
+ m0, err := readImg("../testdata/video-001.gif")
+ if err != nil {
+ t.Fatalf("readImg: %v", err)
+ }
+ m0 = m0.(*image.Paletted).SubImage(image.Rect(0, 0, 50, 30))
+ var buf bytes.Buffer
+ err = Encode(&buf, m0, nil)
+ if err != nil {
+ t.Fatalf("Encode: %v", err)
+ }
+ m1, err := Decode(&buf)
+ if err != nil {
+ t.Fatalf("Decode: %v", err)
+ }
+ if m0.Bounds() != m1.Bounds() {
+ t.Fatalf("bounds differ: %v and %v", m0.Bounds(), m1.Bounds())
+ }
+ if averageDelta(m0, m1) != 0 {
+ t.Fatalf("images differ")
+ }
+}
+
var frames = []string{
"../testdata/video-001.gif",
"../testdata/video-005.gray.gif",
@@ -116,7 +139,7 @@ func TestEncodeAll(t *testing.T) {
for i, f := range frames {
m, err := readGIF(f)
if err != nil {
- t.Error(f, err)
+ t.Fatal(f, err)
}
g0.Image[i] = m.Image[0]
}
diff --git a/src/pkg/image/image.go b/src/image/image.go
index 32a89ef34..6b8e5c487 100644
--- a/src/pkg/image/image.go
+++ b/src/image/image.go
@@ -72,6 +72,10 @@ func (p *RGBA) ColorModel() color.Model { return color.RGBAModel }
func (p *RGBA) Bounds() Rectangle { return p.Rect }
func (p *RGBA) At(x, y int) color.Color {
+ return p.RGBAAt(x, y)
+}
+
+func (p *RGBA) RGBAAt(x, y int) color.RGBA {
if !(Point{x, y}.In(p.Rect)) {
return color.RGBA{}
}
@@ -167,6 +171,10 @@ func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
func (p *RGBA64) Bounds() Rectangle { return p.Rect }
func (p *RGBA64) At(x, y int) color.Color {
+ return p.RGBA64At(x, y)
+}
+
+func (p *RGBA64) RGBA64At(x, y int) color.RGBA64 {
if !(Point{x, y}.In(p.Rect)) {
return color.RGBA64{}
}
@@ -275,6 +283,10 @@ func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
func (p *NRGBA) Bounds() Rectangle { return p.Rect }
func (p *NRGBA) At(x, y int) color.Color {
+ return p.NRGBAAt(x, y)
+}
+
+func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA {
if !(Point{x, y}.In(p.Rect)) {
return color.NRGBA{}
}
@@ -370,6 +382,10 @@ func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
func (p *NRGBA64) At(x, y int) color.Color {
+ return p.NRGBA64At(x, y)
+}
+
+func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 {
if !(Point{x, y}.In(p.Rect)) {
return color.NRGBA64{}
}
@@ -478,6 +494,10 @@ func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
func (p *Alpha) Bounds() Rectangle { return p.Rect }
func (p *Alpha) At(x, y int) color.Color {
+ return p.AlphaAt(x, y)
+}
+
+func (p *Alpha) AlphaAt(x, y int) color.Alpha {
if !(Point{x, y}.In(p.Rect)) {
return color.Alpha{}
}
@@ -566,6 +586,10 @@ func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
func (p *Alpha16) Bounds() Rectangle { return p.Rect }
func (p *Alpha16) At(x, y int) color.Color {
+ return p.Alpha16At(x, y)
+}
+
+func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 {
if !(Point{x, y}.In(p.Rect)) {
return color.Alpha16{}
}
@@ -657,6 +681,10 @@ func (p *Gray) ColorModel() color.Model { return color.GrayModel }
func (p *Gray) Bounds() Rectangle { return p.Rect }
func (p *Gray) At(x, y int) color.Color {
+ return p.GrayAt(x, y)
+}
+
+func (p *Gray) GrayAt(x, y int) color.Gray {
if !(Point{x, y}.In(p.Rect)) {
return color.Gray{}
}
@@ -732,6 +760,10 @@ func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
func (p *Gray16) Bounds() Rectangle { return p.Rect }
func (p *Gray16) At(x, y int) color.Color {
+ return p.Gray16At(x, y)
+}
+
+func (p *Gray16) Gray16At(x, y int) color.Gray16 {
if !(Point{x, y}.In(p.Rect)) {
return color.Gray16{}
}
diff --git a/src/pkg/image/image_test.go b/src/image/image_test.go
index 799c1a7a1..799c1a7a1 100644
--- a/src/pkg/image/image_test.go
+++ b/src/image/image_test.go
diff --git a/src/pkg/image/jpeg/dct_test.go b/src/image/jpeg/dct_test.go
index 845e75887..845e75887 100644
--- a/src/pkg/image/jpeg/dct_test.go
+++ b/src/image/jpeg/dct_test.go
diff --git a/src/pkg/image/jpeg/fdct.go b/src/image/jpeg/fdct.go
index 3f8be4e32..3f8be4e32 100644
--- a/src/pkg/image/jpeg/fdct.go
+++ b/src/image/jpeg/fdct.go
diff --git a/src/image/jpeg/huffman.go b/src/image/jpeg/huffman.go
new file mode 100644
index 000000000..d4ff4cfa0
--- /dev/null
+++ b/src/image/jpeg/huffman.go
@@ -0,0 +1,244 @@
+// 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 jpeg
+
+import (
+ "io"
+)
+
+// maxCodeLength is the maximum (inclusive) number of bits in a Huffman code.
+const maxCodeLength = 16
+
+// maxNCodes is the maximum (inclusive) number of codes in a Huffman tree.
+const maxNCodes = 256
+
+// lutSize is the log-2 size of the Huffman decoder's look-up table.
+const lutSize = 8
+
+// huffman is a Huffman decoder, specified in section C.
+type huffman struct {
+ // length is the number of codes in the tree.
+ nCodes int32
+ // lut is the look-up table for the next lutSize bits in the bit-stream.
+ // The high 8 bits of the uint16 are the encoded value. The low 8 bits
+ // are 1 plus the code length, or 0 if the value is too large to fit in
+ // lutSize bits.
+ lut [1 << lutSize]uint16
+ // vals are the decoded values, sorted by their encoding.
+ vals [maxNCodes]uint8
+ // minCodes[i] is the minimum code of length i, or -1 if there are no
+ // codes of that length.
+ minCodes [maxCodeLength]int32
+ // maxCodes[i] is the maximum code of length i, or -1 if there are no
+ // codes of that length.
+ maxCodes [maxCodeLength]int32
+ // valsIndices[i] is the index into vals of minCodes[i].
+ valsIndices [maxCodeLength]int32
+}
+
+// errShortHuffmanData means that an unexpected EOF occurred while decoding
+// Huffman data.
+var errShortHuffmanData = FormatError("short Huffman data")
+
+// ensureNBits reads bytes from the byte buffer to ensure that d.bits.n is at
+// least n. For best performance (avoiding function calls inside hot loops),
+// the caller is the one responsible for first checking that d.bits.n < n.
+func (d *decoder) ensureNBits(n int32) error {
+ for {
+ c, err := d.readByteStuffedByte()
+ if err != nil {
+ if err == io.EOF {
+ return errShortHuffmanData
+ }
+ return err
+ }
+ d.bits.a = d.bits.a<<8 | uint32(c)
+ d.bits.n += 8
+ if d.bits.m == 0 {
+ d.bits.m = 1 << 7
+ } else {
+ d.bits.m <<= 8
+ }
+ if d.bits.n >= n {
+ break
+ }
+ }
+ return nil
+}
+
+// receiveExtend is the composition of RECEIVE and EXTEND, specified in section
+// F.2.2.1.
+func (d *decoder) receiveExtend(t uint8) (int32, error) {
+ if d.bits.n < int32(t) {
+ if err := d.ensureNBits(int32(t)); err != nil {
+ return 0, err
+ }
+ }
+ d.bits.n -= int32(t)
+ d.bits.m >>= t
+ s := int32(1) << t
+ x := int32(d.bits.a>>uint8(d.bits.n)) & (s - 1)
+ if x < s>>1 {
+ x += ((-1) << t) + 1
+ }
+ return x, nil
+}
+
+// processDHT processes a Define Huffman Table marker, and initializes a huffman
+// struct from its contents. Specified in section B.2.4.2.
+func (d *decoder) processDHT(n int) error {
+ for n > 0 {
+ if n < 17 {
+ return FormatError("DHT has wrong length")
+ }
+ if err := d.readFull(d.tmp[:17]); err != nil {
+ return err
+ }
+ tc := d.tmp[0] >> 4
+ if tc > maxTc {
+ return FormatError("bad Tc value")
+ }
+ th := d.tmp[0] & 0x0f
+ if th > maxTh || !d.progressive && th > 1 {
+ return FormatError("bad Th value")
+ }
+ h := &d.huff[tc][th]
+
+ // Read nCodes and h.vals (and derive h.nCodes).
+ // nCodes[i] is the number of codes with code length i.
+ // h.nCodes is the total number of codes.
+ h.nCodes = 0
+ var nCodes [maxCodeLength]int32
+ for i := range nCodes {
+ nCodes[i] = int32(d.tmp[i+1])
+ h.nCodes += nCodes[i]
+ }
+ if h.nCodes == 0 {
+ return FormatError("Huffman table has zero length")
+ }
+ if h.nCodes > maxNCodes {
+ return FormatError("Huffman table has excessive length")
+ }
+ n -= int(h.nCodes) + 17
+ if n < 0 {
+ return FormatError("DHT has wrong length")
+ }
+ if err := d.readFull(h.vals[:h.nCodes]); err != nil {
+ return err
+ }
+
+ // Derive the look-up table.
+ for i := range h.lut {
+ h.lut[i] = 0
+ }
+ var x, code uint32
+ for i := uint32(0); i < lutSize; i++ {
+ code <<= 1
+ for j := int32(0); j < nCodes[i]; j++ {
+ // The codeLength is 1+i, so shift code by 8-(1+i) to
+ // calculate the high bits for every 8-bit sequence
+ // whose codeLength's high bits matches code.
+ // The high 8 bits of lutValue are the encoded value.
+ // The low 8 bits are 1 plus the codeLength.
+ base := uint8(code << (7 - i))
+ lutValue := uint16(h.vals[x])<<8 | uint16(2+i)
+ for k := uint8(0); k < 1<<(7-i); k++ {
+ h.lut[base|k] = lutValue
+ }
+ code++
+ x++
+ }
+ }
+
+ // Derive minCodes, maxCodes, and valsIndices.
+ var c, index int32
+ for i, n := range nCodes {
+ if n == 0 {
+ h.minCodes[i] = -1
+ h.maxCodes[i] = -1
+ h.valsIndices[i] = -1
+ } else {
+ h.minCodes[i] = c
+ h.maxCodes[i] = c + n - 1
+ h.valsIndices[i] = index
+ c += n
+ index += n
+ }
+ c <<= 1
+ }
+ }
+ return nil
+}
+
+// decodeHuffman returns the next Huffman-coded value from the bit-stream,
+// decoded according to h.
+func (d *decoder) decodeHuffman(h *huffman) (uint8, error) {
+ if h.nCodes == 0 {
+ return 0, FormatError("uninitialized Huffman table")
+ }
+
+ if d.bits.n < 8 {
+ if err := d.ensureNBits(8); err != nil {
+ if err != errMissingFF00 && err != errShortHuffmanData {
+ return 0, err
+ }
+ // There are no more bytes of data in this segment, but we may still
+ // be able to read the next symbol out of the previously read bits.
+ // First, undo the readByte that the ensureNBits call made.
+ d.unreadByteStuffedByte()
+ goto slowPath
+ }
+ }
+ if v := h.lut[(d.bits.a>>uint32(d.bits.n-lutSize))&0xff]; v != 0 {
+ n := (v & 0xff) - 1
+ d.bits.n -= int32(n)
+ d.bits.m >>= n
+ return uint8(v >> 8), nil
+ }
+
+slowPath:
+ for i, code := 0, int32(0); i < maxCodeLength; i++ {
+ if d.bits.n == 0 {
+ if err := d.ensureNBits(1); err != nil {
+ return 0, err
+ }
+ }
+ if d.bits.a&d.bits.m != 0 {
+ code |= 1
+ }
+ d.bits.n--
+ d.bits.m >>= 1
+ if code <= h.maxCodes[i] {
+ return h.vals[h.valsIndices[i]+code-h.minCodes[i]], nil
+ }
+ code <<= 1
+ }
+ return 0, FormatError("bad Huffman code")
+}
+
+func (d *decoder) decodeBit() (bool, error) {
+ if d.bits.n == 0 {
+ if err := d.ensureNBits(1); err != nil {
+ return false, err
+ }
+ }
+ ret := d.bits.a&d.bits.m != 0
+ d.bits.n--
+ d.bits.m >>= 1
+ return ret, nil
+}
+
+func (d *decoder) decodeBits(n int32) (uint32, error) {
+ if d.bits.n < n {
+ if err := d.ensureNBits(n); err != nil {
+ return 0, err
+ }
+ }
+ ret := d.bits.a >> uint32(d.bits.n-n)
+ ret &= (1 << uint32(n)) - 1
+ d.bits.n -= n
+ d.bits.m >>= uint32(n)
+ return ret, nil
+}
diff --git a/src/pkg/image/jpeg/idct.go b/src/image/jpeg/idct.go
index 46fcaecb7..46fcaecb7 100644
--- a/src/pkg/image/jpeg/idct.go
+++ b/src/image/jpeg/idct.go
diff --git a/src/pkg/image/jpeg/reader.go b/src/image/jpeg/reader.go
index 356d56220..6d8b1d1d0 100644
--- a/src/pkg/image/jpeg/reader.go
+++ b/src/image/jpeg/reader.go
@@ -8,7 +8,6 @@
package jpeg
import (
- "bufio"
"image"
"image/color"
"io"
@@ -84,15 +83,36 @@ var unzig = [blockSize]int{
53, 60, 61, 54, 47, 55, 62, 63,
}
-// If the passed in io.Reader does not also have ReadByte, then Decode will introduce its own buffering.
+// Reader is deprecated.
type Reader interface {
+ io.ByteReader
io.Reader
- ReadByte() (c byte, err error)
+}
+
+// bits holds the unprocessed bits that have been taken from the byte-stream.
+// The n least significant bits of a form the unread bits, to be read in MSB to
+// LSB order.
+type bits struct {
+ a uint32 // accumulator.
+ m uint32 // mask. m==1<<(n-1) when n>0, with m==0 when n==0.
+ n int32 // the number of unread bits in a.
}
type decoder struct {
- r Reader
- b bits
+ r io.Reader
+ bits bits
+ // bytes is a byte buffer, similar to a bufio.Reader, except that it
+ // has to be able to unread more than 1 byte, due to byte stuffing.
+ // Byte stuffing is specified in section F.1.2.3.
+ bytes struct {
+ // buf[i:j] are the buffered bytes read from the underlying
+ // io.Reader that haven't yet been passed further on.
+ buf [4096]byte
+ i, j int
+ // nUnreadable is the number of bytes to back up i after
+ // overshooting. It can be 0, 1 or 2.
+ nUnreadable int
+ }
width, height int
img1 *image.Gray
img3 *image.YCbCr
@@ -104,21 +124,160 @@ type decoder struct {
progCoeffs [nColorComponent][]block // Saved state between progressive-mode scans.
huff [maxTc + 1][maxTh + 1]huffman
quant [maxTq + 1]block // Quantization tables, in zig-zag order.
- tmp [1024]byte
+ tmp [blockSize + 1]byte
+}
+
+// fill fills up the d.bytes.buf buffer from the underlying io.Reader. It
+// should only be called when there are no unread bytes in d.bytes.
+func (d *decoder) fill() error {
+ if d.bytes.i != d.bytes.j {
+ panic("jpeg: fill called when unread bytes exist")
+ }
+ // Move the last 2 bytes to the start of the buffer, in case we need
+ // to call unreadByteStuffedByte.
+ if d.bytes.j > 2 {
+ d.bytes.buf[0] = d.bytes.buf[d.bytes.j-2]
+ d.bytes.buf[1] = d.bytes.buf[d.bytes.j-1]
+ d.bytes.i, d.bytes.j = 2, 2
+ }
+ // Fill in the rest of the buffer.
+ n, err := d.r.Read(d.bytes.buf[d.bytes.j:])
+ d.bytes.j += n
+ if n > 0 {
+ err = nil
+ }
+ return err
+}
+
+// unreadByteStuffedByte undoes the most recent readByteStuffedByte call,
+// giving a byte of data back from d.bits to d.bytes. The Huffman look-up table
+// requires at least 8 bits for look-up, which means that Huffman decoding can
+// sometimes overshoot and read one or two too many bytes. Two-byte overshoot
+// can happen when expecting to read a 0xff 0x00 byte-stuffed byte.
+func (d *decoder) unreadByteStuffedByte() {
+ if d.bytes.nUnreadable == 0 {
+ panic("jpeg: unreadByteStuffedByte call cannot be fulfilled")
+ }
+ d.bytes.i -= d.bytes.nUnreadable
+ d.bytes.nUnreadable = 0
+ if d.bits.n >= 8 {
+ d.bits.a >>= 8
+ d.bits.n -= 8
+ d.bits.m >>= 8
+ }
+}
+
+// readByte returns the next byte, whether buffered or not buffered. It does
+// not care about byte stuffing.
+func (d *decoder) readByte() (x byte, err error) {
+ for d.bytes.i == d.bytes.j {
+ if err = d.fill(); err != nil {
+ return 0, err
+ }
+ }
+ x = d.bytes.buf[d.bytes.i]
+ d.bytes.i++
+ d.bytes.nUnreadable = 0
+ return x, nil
+}
+
+// errMissingFF00 means that readByteStuffedByte encountered an 0xff byte (a
+// marker byte) that wasn't the expected byte-stuffed sequence 0xff, 0x00.
+var errMissingFF00 = FormatError("missing 0xff00 sequence")
+
+// readByteStuffedByte is like readByte but is for byte-stuffed Huffman data.
+func (d *decoder) readByteStuffedByte() (x byte, err error) {
+ // Take the fast path if d.bytes.buf contains at least two bytes.
+ if d.bytes.i+2 <= d.bytes.j {
+ x = d.bytes.buf[d.bytes.i]
+ d.bytes.i++
+ d.bytes.nUnreadable = 1
+ if x != 0xff {
+ return x, err
+ }
+ if d.bytes.buf[d.bytes.i] != 0x00 {
+ return 0, errMissingFF00
+ }
+ d.bytes.i++
+ d.bytes.nUnreadable = 2
+ return 0xff, nil
+ }
+
+ x, err = d.readByte()
+ if err != nil {
+ return 0, err
+ }
+ if x != 0xff {
+ d.bytes.nUnreadable = 1
+ return x, nil
+ }
+
+ x, err = d.readByte()
+ if err != nil {
+ d.bytes.nUnreadable = 1
+ return 0, err
+ }
+ d.bytes.nUnreadable = 2
+ if x != 0x00 {
+ return 0, errMissingFF00
+ }
+ return 0xff, nil
}
-// Reads and ignores the next n bytes.
+// readFull reads exactly len(p) bytes into p. It does not care about byte
+// stuffing.
+func (d *decoder) readFull(p []byte) error {
+ // Unread the overshot bytes, if any.
+ if d.bytes.nUnreadable != 0 {
+ if d.bits.n >= 8 {
+ d.unreadByteStuffedByte()
+ }
+ d.bytes.nUnreadable = 0
+ }
+
+ for {
+ n := copy(p, d.bytes.buf[d.bytes.i:d.bytes.j])
+ p = p[n:]
+ d.bytes.i += n
+ if len(p) == 0 {
+ break
+ }
+ if err := d.fill(); err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return err
+ }
+ }
+ return nil
+}
+
+// ignore ignores the next n bytes.
func (d *decoder) ignore(n int) error {
- for n > 0 {
- m := len(d.tmp)
+ // Unread the overshot bytes, if any.
+ if d.bytes.nUnreadable != 0 {
+ if d.bits.n >= 8 {
+ d.unreadByteStuffedByte()
+ }
+ d.bytes.nUnreadable = 0
+ }
+
+ for {
+ m := d.bytes.j - d.bytes.i
if m > n {
m = n
}
- _, err := io.ReadFull(d.r, d.tmp[0:m])
- if err != nil {
+ d.bytes.i += m
+ n -= m
+ if n == 0 {
+ break
+ }
+ if err := d.fill(); err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
return err
}
- n -= m
}
return nil
}
@@ -133,8 +292,7 @@ func (d *decoder) processSOF(n int) error {
default:
return UnsupportedError("SOF has wrong length")
}
- _, err := io.ReadFull(d.r, d.tmp[:n])
- if err != nil {
+ if err := d.readFull(d.tmp[:n]); err != nil {
return err
}
// We only support 8-bit precision.
@@ -187,8 +345,7 @@ func (d *decoder) processSOF(n int) error {
func (d *decoder) processDQT(n int) error {
const qtLength = 1 + blockSize
for ; n >= qtLength; n -= qtLength {
- _, err := io.ReadFull(d.r, d.tmp[0:qtLength])
- if err != nil {
+ if err := d.readFull(d.tmp[:qtLength]); err != nil {
return err
}
pq := d.tmp[0] >> 4
@@ -214,8 +371,7 @@ func (d *decoder) processDRI(n int) error {
if n != 2 {
return FormatError("DRI has wrong length")
}
- _, err := io.ReadFull(d.r, d.tmp[0:2])
- if err != nil {
+ if err := d.readFull(d.tmp[:2]); err != nil {
return err
}
d.ri = int(d.tmp[0])<<8 + int(d.tmp[1])
@@ -224,15 +380,10 @@ func (d *decoder) processDRI(n int) error {
// decode reads a JPEG image from r and returns it as an image.Image.
func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
- if rr, ok := r.(Reader); ok {
- d.r = rr
- } else {
- d.r = bufio.NewReader(r)
- }
+ d.r = r
// Check for the Start Of Image marker.
- _, err := io.ReadFull(d.r, d.tmp[0:2])
- if err != nil {
+ if err := d.readFull(d.tmp[:2]); err != nil {
return nil, err
}
if d.tmp[0] != 0xff || d.tmp[1] != soiMarker {
@@ -241,7 +392,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
// Process the remaining segments until the End Of Image marker.
for {
- _, err := io.ReadFull(d.r, d.tmp[0:2])
+ err := d.readFull(d.tmp[:2])
if err != nil {
return nil, err
}
@@ -267,7 +418,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
// Note that extraneous 0xff bytes in e.g. SOS data are escaped as
// "\xff\x00", and so are detected a little further down below.
d.tmp[0] = d.tmp[1]
- d.tmp[1], err = d.r.ReadByte()
+ d.tmp[1], err = d.readByte()
if err != nil {
return nil, err
}
@@ -280,7 +431,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
for marker == 0xff {
// Section B.1.1.2 says, "Any marker may optionally be preceded by any
// number of fill bytes, which are bytes assigned code X'FF'".
- marker, err = d.r.ReadByte()
+ marker, err = d.readByte()
if err != nil {
return nil, err
}
@@ -300,8 +451,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
// Read the 16-bit length of the segment. The value includes the 2 bytes for the
// length itself, so we subtract 2 to get the number of remaining bytes.
- _, err = io.ReadFull(d.r, d.tmp[0:2])
- if err != nil {
+ if err = d.readFull(d.tmp[:2]); err != nil {
return nil, err
}
n := int(d.tmp[0])<<8 + int(d.tmp[1]) - 2
diff --git a/src/pkg/image/jpeg/reader_test.go b/src/image/jpeg/reader_test.go
index 926bb0434..4de2e8ee7 100644
--- a/src/pkg/image/jpeg/reader_test.go
+++ b/src/image/jpeg/reader_test.go
@@ -9,6 +9,7 @@ import (
"fmt"
"image"
"image/color"
+ "io"
"io/ioutil"
"math/rand"
"os"
@@ -86,7 +87,51 @@ func decodeFile(filename string) (image.Image, error) {
}
defer f.Close()
return Decode(f)
+}
+
+type eofReader struct {
+ data []byte // deliver from Read without EOF
+ dataEOF []byte // then deliver from Read with EOF on last chunk
+ lenAtEOF int
+}
+
+func (r *eofReader) Read(b []byte) (n int, err error) {
+ if len(r.data) > 0 {
+ n = copy(b, r.data)
+ r.data = r.data[n:]
+ } else {
+ n = copy(b, r.dataEOF)
+ r.dataEOF = r.dataEOF[n:]
+ if len(r.dataEOF) == 0 {
+ err = io.EOF
+ if r.lenAtEOF == -1 {
+ r.lenAtEOF = n
+ }
+ }
+ }
+ return
+}
+func TestDecodeEOF(t *testing.T) {
+ // Check that if reader returns final data and EOF at same time, jpeg handles it.
+ data, err := ioutil.ReadFile("../testdata/video-001.jpeg")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ n := len(data)
+ for i := 0; i < n; {
+ r := &eofReader{data[:n-i], data[n-i:], -1}
+ _, err := Decode(r)
+ if err != nil {
+ t.Errorf("Decode with Read() = %d, EOF: %v", r.lenAtEOF, err)
+ }
+ if i == 0 {
+ i = 1
+ } else {
+ i *= 2
+ }
+ }
}
// check checks that the two pix data are equal, within the given bounds.
diff --git a/src/pkg/image/jpeg/scan.go b/src/image/jpeg/scan.go
index 559235d51..2bd1d9d53 100644
--- a/src/pkg/image/jpeg/scan.go
+++ b/src/image/jpeg/scan.go
@@ -6,7 +6,6 @@ package jpeg
import (
"image"
- "io"
)
// makeImg allocates and initializes the destination image.
@@ -41,8 +40,7 @@ func (d *decoder) processSOS(n int) error {
if n < 6 || 4+2*d.nComp < n || n%2 != 0 {
return FormatError("SOS has wrong length")
}
- _, err := io.ReadFull(d.r, d.tmp[:n])
- if err != nil {
+ if err := d.readFull(d.tmp[:n]); err != nil {
return err
}
nComp := int(d.tmp[0])
@@ -67,7 +65,13 @@ func (d *decoder) processSOS(n int) error {
}
scan[i].compIndex = uint8(compIndex)
scan[i].td = d.tmp[2+2*i] >> 4
+ if scan[i].td > maxTh {
+ return FormatError("bad Td value")
+ }
scan[i].ta = d.tmp[2+2*i] & 0x0f
+ if scan[i].ta > maxTh {
+ return FormatError("bad Ta value")
+ }
}
// zigStart and zigEnd are the spectral selection bounds.
@@ -119,18 +123,17 @@ func (d *decoder) processSOS(n int) error {
}
}
- d.b = bits{}
+ d.bits = bits{}
mcu, expectedRST := 0, uint8(rst0Marker)
var (
// b is the decoded coefficients, in natural (not zig-zag) order.
b block
dc [nColorComponent]int32
- // mx0 and my0 are the location of the current (in terms of 8x8 blocks).
+ // bx and by are the location of the current (in terms of 8x8 blocks).
// For example, with 4:2:0 chroma subsampling, the block whose top left
// pixel co-ordinates are (16, 8) is the third block in the first row:
- // mx0 is 2 and my0 is 0, even though the pixel is in the second MCU.
- // TODO(nigeltao): rename mx0 and my0 to bx and by?
- mx0, my0 int
+ // bx is 2 and by is 0, even though the pixel is in the second MCU.
+ bx, by int
blockCount int
)
for my := 0; my < myy; my++ {
@@ -165,26 +168,26 @@ func (d *decoder) processSOS(n int) error {
// 0 1 2
// 3 4 5
if nComp != 1 {
- mx0, my0 = d.comp[compIndex].h*mx, d.comp[compIndex].v*my
+ bx, by = d.comp[compIndex].h*mx, d.comp[compIndex].v*my
if h0 == 1 {
- my0 += j
+ by += j
} else {
- mx0 += j % 2
- my0 += j / 2
+ bx += j % 2
+ by += j / 2
}
} else {
q := mxx * d.comp[compIndex].h
- mx0 = blockCount % q
- my0 = blockCount / q
+ bx = blockCount % q
+ by = blockCount / q
blockCount++
- if mx0*8 >= d.width || my0*8 >= d.height {
+ if bx*8 >= d.width || by*8 >= d.height {
continue
}
}
// Load the previous partially decoded coefficients, if applicable.
if d.progressive {
- b = d.progCoeffs[compIndex][my0*mxx*d.comp[compIndex].h+mx0]
+ b = d.progCoeffs[compIndex][by*mxx*d.comp[compIndex].h+bx]
} else {
b = block{}
}
@@ -217,8 +220,9 @@ func (d *decoder) processSOS(n int) error {
d.eobRun--
} else {
// Decode the AC coefficients, as specified in section F.2.2.2.
+ huff := &d.huff[acTable][scan[i].ta]
for ; zig <= zigEnd; zig++ {
- value, err := d.decodeHuffman(&d.huff[acTable][scan[i].ta])
+ value, err := d.decodeHuffman(huff)
if err != nil {
return err
}
@@ -238,7 +242,7 @@ func (d *decoder) processSOS(n int) error {
if val0 != 0x0f {
d.eobRun = uint16(1 << val0)
if val0 != 0 {
- bits, err := d.decodeBits(int(val0))
+ bits, err := d.decodeBits(int32(val0))
if err != nil {
return err
}
@@ -256,7 +260,7 @@ func (d *decoder) processSOS(n int) error {
if d.progressive {
if zigEnd != blockSize-1 || al != 0 {
// We haven't completely decoded this 8x8 block. Save the coefficients.
- d.progCoeffs[compIndex][my0*mxx*d.comp[compIndex].h+mx0] = b
+ d.progCoeffs[compIndex][by*mxx*d.comp[compIndex].h+bx] = b
// At this point, we could execute the rest of the loop body to dequantize and
// perform the inverse DCT, to save early stages of a progressive image to the
// *image.YCbCr buffers (the whole point of progressive encoding), but in Go,
@@ -273,15 +277,15 @@ func (d *decoder) processSOS(n int) error {
idct(&b)
dst, stride := []byte(nil), 0
if d.nComp == nGrayComponent {
- dst, stride = d.img1.Pix[8*(my0*d.img1.Stride+mx0):], d.img1.Stride
+ dst, stride = d.img1.Pix[8*(by*d.img1.Stride+bx):], d.img1.Stride
} else {
switch compIndex {
case 0:
- dst, stride = d.img3.Y[8*(my0*d.img3.YStride+mx0):], d.img3.YStride
+ dst, stride = d.img3.Y[8*(by*d.img3.YStride+bx):], d.img3.YStride
case 1:
- dst, stride = d.img3.Cb[8*(my0*d.img3.CStride+mx0):], d.img3.CStride
+ dst, stride = d.img3.Cb[8*(by*d.img3.CStride+bx):], d.img3.CStride
case 2:
- dst, stride = d.img3.Cr[8*(my0*d.img3.CStride+mx0):], d.img3.CStride
+ dst, stride = d.img3.Cr[8*(by*d.img3.CStride+bx):], d.img3.CStride
default:
return UnsupportedError("too many components")
}
@@ -308,8 +312,7 @@ func (d *decoder) processSOS(n int) error {
if d.ri > 0 && mcu%d.ri == 0 && mcu < mxx*myy {
// A more sophisticated decoder could use RST[0-7] markers to resynchronize from corrupt input,
// but this one assumes well-formed input, and hence the restart marker follows immediately.
- _, err := io.ReadFull(d.r, d.tmp[0:2])
- if err != nil {
+ if err := d.readFull(d.tmp[:2]); err != nil {
return err
}
if d.tmp[0] != 0xff || d.tmp[1] != expectedRST {
@@ -320,7 +323,7 @@ func (d *decoder) processSOS(n int) error {
expectedRST = rst0Marker
}
// Reset the Huffman decoder.
- d.b = bits{}
+ d.bits = bits{}
// Reset the DC components, as per section F.2.1.3.1.
dc = [nColorComponent]int32{}
// Reset the progressive decoder state, as per section G.1.2.2.
@@ -368,7 +371,7 @@ func (d *decoder) refine(b *block, h *huffman, zigStart, zigEnd, delta int32) er
if val0 != 0x0f {
d.eobRun = uint16(1 << val0)
if val0 != 0 {
- bits, err := d.decodeBits(int(val0))
+ bits, err := d.decodeBits(int32(val0))
if err != nil {
return err
}
diff --git a/src/pkg/image/jpeg/writer.go b/src/image/jpeg/writer.go
index c58fbf305..91bbde3bf 100644
--- a/src/pkg/image/jpeg/writer.go
+++ b/src/image/jpeg/writer.go
@@ -249,7 +249,7 @@ func (e *encoder) writeByte(b byte) {
e.err = e.w.WriteByte(b)
}
-// emit emits the least significant nBits bits of bits to the bitstream.
+// emit emits the least significant nBits bits of bits to the bit-stream.
// The precondition is bits < 1<<nBits && nBits <= 16.
func (e *encoder) emit(bits, nBits uint32) {
nBits += e.nBits
@@ -312,32 +312,44 @@ func (e *encoder) writeDQT() {
}
// writeSOF0 writes the Start Of Frame (Baseline) marker.
-func (e *encoder) writeSOF0(size image.Point) {
- const markerlen = 8 + 3*nColorComponent
+func (e *encoder) writeSOF0(size image.Point, nComponent int) {
+ markerlen := 8 + 3*nComponent
e.writeMarkerHeader(sof0Marker, markerlen)
e.buf[0] = 8 // 8-bit color.
e.buf[1] = uint8(size.Y >> 8)
e.buf[2] = uint8(size.Y & 0xff)
e.buf[3] = uint8(size.X >> 8)
e.buf[4] = uint8(size.X & 0xff)
- e.buf[5] = nColorComponent
- for i := 0; i < nColorComponent; i++ {
- e.buf[3*i+6] = uint8(i + 1)
- // We use 4:2:0 chroma subsampling.
- e.buf[3*i+7] = "\x22\x11\x11"[i]
- e.buf[3*i+8] = "\x00\x01\x01"[i]
+ e.buf[5] = uint8(nComponent)
+ if nComponent == 1 {
+ e.buf[6] = 1
+ // No subsampling for grayscale image.
+ e.buf[7] = 0x11
+ e.buf[8] = 0x00
+ } else {
+ for i := 0; i < nComponent; i++ {
+ e.buf[3*i+6] = uint8(i + 1)
+ // We use 4:2:0 chroma subsampling.
+ e.buf[3*i+7] = "\x22\x11\x11"[i]
+ e.buf[3*i+8] = "\x00\x01\x01"[i]
+ }
}
- e.write(e.buf[:3*(nColorComponent-1)+9])
+ e.write(e.buf[:3*(nComponent-1)+9])
}
// writeDHT writes the Define Huffman Table marker.
-func (e *encoder) writeDHT() {
+func (e *encoder) writeDHT(nComponent int) {
markerlen := 2
- for _, s := range theHuffmanSpec {
+ specs := theHuffmanSpec[:]
+ if nComponent == 1 {
+ // Drop the Chrominance tables.
+ specs = specs[:2]
+ }
+ for _, s := range specs {
markerlen += 1 + 16 + len(s.value)
}
e.writeMarkerHeader(dhtMarker, markerlen)
- for i, s := range theHuffmanSpec {
+ for i, s := range specs {
e.writeByte("\x00\x10\x01\x11"[i])
e.write(s.count[:])
e.write(s.value)
@@ -345,8 +357,8 @@ func (e *encoder) writeDHT() {
}
// writeBlock writes a block of pixel data using the given quantization table,
-// returning the post-quantized DC value of the DCT-transformed block.
-// b is in natural (not zig-zag) order.
+// returning the post-quantized DC value of the DCT-transformed block. b is in
+// natural (not zig-zag) order.
func (e *encoder) writeBlock(b *block, q quantIndex, prevDC int32) int32 {
fdct(b)
// Emit the DC delta.
@@ -390,6 +402,20 @@ func toYCbCr(m image.Image, p image.Point, yBlock, cbBlock, crBlock *block) {
}
}
+// grayToY stores the 8x8 region of m whose top-left corner is p in yBlock.
+func grayToY(m *image.Gray, p image.Point, yBlock *block) {
+ b := m.Bounds()
+ xmax := b.Max.X - 1
+ ymax := b.Max.Y - 1
+ pix := m.Pix
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ idx := m.PixOffset(min(p.X+i, xmax), min(p.Y+j, ymax))
+ yBlock[8*j+i] = int32(pix[idx])
+ }
+ }
+}
+
// rgbaToYCbCr is a specialized version of toYCbCr for image.RGBA images.
func rgbaToYCbCr(m *image.RGBA, p image.Point, yBlock, cbBlock, crBlock *block) {
b := m.Bounds()
@@ -430,7 +456,18 @@ func scale(dst *block, src *[4]block) {
}
}
-// sosHeader is the SOS marker "\xff\xda" followed by 12 bytes:
+// sosHeaderY is the SOS marker "\xff\xda" followed by 8 bytes:
+// - the marker length "\x00\x08",
+// - the number of components "\x01",
+// - component 1 uses DC table 0 and AC table 0 "\x01\x00",
+// - the bytes "\x00\x3f\x00". Section B.2.3 of the spec says that for
+// sequential DCTs, those bytes (8-bit Ss, 8-bit Se, 4-bit Ah, 4-bit Al)
+// should be 0x00, 0x3f, 0x00<<4 | 0x00.
+var sosHeaderY = []byte{
+ 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00,
+}
+
+// sosHeaderYCbCr is the SOS marker "\xff\xda" followed by 12 bytes:
// - the marker length "\x00\x0c",
// - the number of components "\x03",
// - component 1 uses DC table 0 and AC table 0 "\x01\x00",
@@ -439,14 +476,19 @@ func scale(dst *block, src *[4]block) {
// - the bytes "\x00\x3f\x00". Section B.2.3 of the spec says that for
// sequential DCTs, those bytes (8-bit Ss, 8-bit Se, 4-bit Ah, 4-bit Al)
// should be 0x00, 0x3f, 0x00<<4 | 0x00.
-var sosHeader = []byte{
+var sosHeaderYCbCr = []byte{
0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
}
// writeSOS writes the StartOfScan marker.
func (e *encoder) writeSOS(m image.Image) {
- e.write(sosHeader)
+ switch m.(type) {
+ case *image.Gray:
+ e.write(sosHeaderY)
+ default:
+ e.write(sosHeaderYCbCr)
+ }
var (
// Scratch buffers to hold the YCbCr values.
// The blocks are in natural (not zig-zag) order.
@@ -456,24 +498,36 @@ func (e *encoder) writeSOS(m image.Image) {
prevDCY, prevDCCb, prevDCCr int32
)
bounds := m.Bounds()
- rgba, _ := m.(*image.RGBA)
- for y := bounds.Min.Y; y < bounds.Max.Y; y += 16 {
- for x := bounds.Min.X; x < bounds.Max.X; x += 16 {
- for i := 0; i < 4; i++ {
- xOff := (i & 1) * 8
- yOff := (i & 2) * 4
- p := image.Pt(x+xOff, y+yOff)
- if rgba != nil {
- rgbaToYCbCr(rgba, p, &b, &cb[i], &cr[i])
- } else {
- toYCbCr(m, p, &b, &cb[i], &cr[i])
- }
+ switch m := m.(type) {
+ // TODO(wathiede): switch on m.ColorModel() instead of type.
+ case *image.Gray:
+ for y := bounds.Min.Y; y < bounds.Max.Y; y += 8 {
+ for x := bounds.Min.X; x < bounds.Max.X; x += 8 {
+ p := image.Pt(x, y)
+ grayToY(m, p, &b)
prevDCY = e.writeBlock(&b, 0, prevDCY)
}
- scale(&b, &cb)
- prevDCCb = e.writeBlock(&b, 1, prevDCCb)
- scale(&b, &cr)
- prevDCCr = e.writeBlock(&b, 1, prevDCCr)
+ }
+ default:
+ rgba, _ := m.(*image.RGBA)
+ for y := bounds.Min.Y; y < bounds.Max.Y; y += 16 {
+ for x := bounds.Min.X; x < bounds.Max.X; x += 16 {
+ for i := 0; i < 4; i++ {
+ xOff := (i & 1) * 8
+ yOff := (i & 2) * 4
+ p := image.Pt(x+xOff, y+yOff)
+ if rgba != nil {
+ rgbaToYCbCr(rgba, p, &b, &cb[i], &cr[i])
+ } else {
+ toYCbCr(m, p, &b, &cb[i], &cr[i])
+ }
+ prevDCY = e.writeBlock(&b, 0, prevDCY)
+ }
+ scale(&b, &cb)
+ prevDCCb = e.writeBlock(&b, 1, prevDCCb)
+ scale(&b, &cr)
+ prevDCCr = e.writeBlock(&b, 1, prevDCCr)
+ }
}
}
// Pad the last byte with 1's.
@@ -532,6 +586,13 @@ func Encode(w io.Writer, m image.Image, o *Options) error {
e.quant[i][j] = uint8(x)
}
}
+ // Compute number of components based on input image type.
+ nComponent := 3
+ switch m.(type) {
+ // TODO(wathiede): switch on m.ColorModel() instead of type.
+ case *image.Gray:
+ nComponent = 1
+ }
// Write the Start Of Image marker.
e.buf[0] = 0xff
e.buf[1] = 0xd8
@@ -539,9 +600,9 @@ func Encode(w io.Writer, m image.Image, o *Options) error {
// Write the quantization tables.
e.writeDQT()
// Write the image dimensions.
- e.writeSOF0(b.Size())
+ e.writeSOF0(b.Size(), nComponent)
// Write the Huffman tables.
- e.writeDHT()
+ e.writeDHT(nComponent)
// Write the image data.
e.writeSOS(m)
// Write the End Of Image marker.
diff --git a/src/pkg/image/jpeg/writer_test.go b/src/image/jpeg/writer_test.go
index 514b455dc..3df3cfcc5 100644
--- a/src/pkg/image/jpeg/writer_test.go
+++ b/src/image/jpeg/writer_test.go
@@ -160,6 +160,34 @@ func TestWriter(t *testing.T) {
}
}
+// TestWriteGrayscale tests that a grayscale images survives a round-trip
+// through encode/decode cycle.
+func TestWriteGrayscale(t *testing.T) {
+ m0 := image.NewGray(image.Rect(0, 0, 32, 32))
+ for i := range m0.Pix {
+ m0.Pix[i] = uint8(i)
+ }
+ var buf bytes.Buffer
+ if err := Encode(&buf, m0, nil); err != nil {
+ t.Fatal(err)
+ }
+ m1, err := Decode(&buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if m0.Bounds() != m1.Bounds() {
+ t.Fatalf("bounds differ: %v and %v", m0.Bounds(), m1.Bounds())
+ }
+ if _, ok := m1.(*image.Gray); !ok {
+ t.Errorf("got %T, want *image.Gray", m1)
+ }
+ // Compare the average delta to the tolerance level.
+ want := int64(2 << 8)
+ if got := averageDelta(m0, m1); got > want {
+ t.Errorf("average delta too high; got %d, want <= %d", got, want)
+ }
+}
+
// averageDelta returns the average delta in RGB space. The two images must
// have the same bounds.
func averageDelta(m0, m1 image.Image) int64 {
diff --git a/src/pkg/image/names.go b/src/image/names.go
index 8985f4921..8985f4921 100644
--- a/src/pkg/image/names.go
+++ b/src/image/names.go
diff --git a/src/pkg/image/png/paeth.go b/src/image/png/paeth.go
index 37978aa66..9ed6300c8 100644
--- a/src/pkg/image/png/paeth.go
+++ b/src/image/png/paeth.go
@@ -4,6 +4,21 @@
package png
+// intSize is either 32 or 64.
+const intSize = 32 << (^uint(0) >> 63)
+
+func abs(x int) int {
+ // m := -1 if x < 0. m := 0 otherwise.
+ m := x >> (intSize - 1)
+
+ // In two's complement representation, the negative number
+ // of any number (except the smallest one) can be computed
+ // by flipping all the bits and add 1. This is faster than
+ // code with a branch.
+ // See Hacker's Delight, section 2-4.
+ return (x ^ m) - m
+}
+
// paeth implements the Paeth filter function, as per the PNG specification.
func paeth(a, b, c uint8) uint8 {
// This is an optimized version of the sample code in the PNG spec.
@@ -16,16 +31,9 @@ func paeth(a, b, c uint8) uint8 {
pc := int(c)
pa := int(b) - pc
pb := int(a) - pc
- pc = pa + pb
- if pa < 0 {
- pa = -pa
- }
- if pb < 0 {
- pb = -pb
- }
- if pc < 0 {
- pc = -pc
- }
+ pc = abs(pa + pb)
+ pa = abs(pa)
+ pb = abs(pb)
if pa <= pb && pa <= pc {
return a
} else if pb <= pc {
@@ -44,16 +52,9 @@ func filterPaeth(cdat, pdat []byte, bytesPerPixel int) {
b = int(pdat[j])
pa = b - c
pb = a - c
- pc = pa + pb
- if pa < 0 {
- pa = -pa
- }
- if pb < 0 {
- pb = -pb
- }
- if pc < 0 {
- pc = -pc
- }
+ pc = abs(pa + pb)
+ pa = abs(pa)
+ pb = abs(pb)
if pa <= pb && pa <= pc {
// No-op.
} else if pb <= pc {
diff --git a/src/pkg/image/png/paeth_test.go b/src/image/png/paeth_test.go
index bb084861a..cfc1896cd 100644
--- a/src/pkg/image/png/paeth_test.go
+++ b/src/image/png/paeth_test.go
@@ -10,7 +10,7 @@ import (
"testing"
)
-func abs(x int) int {
+func slowAbs(x int) int {
if x < 0 {
return -x
}
@@ -21,9 +21,9 @@ func abs(x int) int {
// It is a straight port of the sample code in the PNG spec, section 9.4.
func slowPaeth(a, b, c uint8) uint8 {
p := int(a) + int(b) - int(c)
- pa := abs(p - int(a))
- pb := abs(p - int(b))
- pc := abs(p - int(c))
+ pa := slowAbs(p - int(a))
+ pb := slowAbs(p - int(b))
+ pc := slowAbs(p - int(c))
if pa <= pb && pa <= pc {
return a
} else if pb <= pc {
diff --git a/src/pkg/image/png/reader.go b/src/image/png/reader.go
index dfe299102..0a40ca161 100644
--- a/src/pkg/image/png/reader.go
+++ b/src/image/png/reader.go
@@ -57,6 +57,29 @@ const (
nFilter = 5
)
+// Interlace type.
+const (
+ itNone = 0
+ itAdam7 = 1
+)
+
+// interlaceScan defines the placement and size of a pass for Adam7 interlacing.
+type interlaceScan struct {
+ xFactor, yFactor, xOffset, yOffset int
+}
+
+// interlacing defines Adam7 interlacing, with 7 passes of reduced images.
+// See http://www.w3.org/TR/PNG/#8Interlace
+var interlacing = []interlaceScan{
+ {8, 8, 0, 0},
+ {8, 8, 4, 0},
+ {4, 8, 0, 4},
+ {4, 4, 2, 0},
+ {2, 4, 0, 2},
+ {2, 2, 1, 0},
+ {1, 2, 0, 1},
+}
+
// Decoding stage.
// The PNG specification says that the IHDR, PLTE (if present), IDAT and IEND
// chunks must appear in that order. There may be multiple IDAT chunks, and
@@ -84,6 +107,7 @@ type decoder struct {
stage int
idatLength uint32
tmp [3 * 256]byte
+ interlace int
}
// A FormatError reports that the input is not a valid PNG.
@@ -113,9 +137,16 @@ func (d *decoder) parseIHDR(length uint32) error {
return err
}
d.crc.Write(d.tmp[:13])
- if d.tmp[10] != 0 || d.tmp[11] != 0 || d.tmp[12] != 0 {
- return UnsupportedError("compression, filter or interlace method")
+ if d.tmp[10] != 0 {
+ return UnsupportedError("compression method")
}
+ if d.tmp[11] != 0 {
+ return UnsupportedError("filter method")
+ }
+ if d.tmp[12] != itNone && d.tmp[12] != itAdam7 {
+ return FormatError("invalid interlace method")
+ }
+ 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 {
@@ -287,7 +318,42 @@ func (d *decoder) decode() (image.Image, error) {
return nil, err
}
defer r.Close()
- bitsPerPixel := 0
+ var img image.Image
+ if d.interlace == itNone {
+ img, err = d.readImagePass(r, 0, false)
+ } else if d.interlace == itAdam7 {
+ // Allocate a blank image of the full size.
+ img, err = d.readImagePass(nil, 0, true)
+ for pass := 0; pass < 7; pass++ {
+ imagePass, err := d.readImagePass(r, pass, false)
+ if err != nil {
+ return nil, err
+ }
+ d.mergePassInto(img, imagePass, pass)
+ }
+ }
+
+ // Check for EOF, to verify the zlib checksum.
+ n := 0
+ for i := 0; n == 0 && err == nil; i++ {
+ if i == 100 {
+ return nil, io.ErrNoProgress
+ }
+ n, err = r.Read(d.tmp[:1])
+ }
+ if err != nil && err != io.EOF {
+ return nil, FormatError(err.Error())
+ }
+ if n != 0 || d.idatLength != 0 {
+ return nil, FormatError("too much pixel data")
+ }
+
+ return img, nil
+}
+
+// readImagePass reads a single image pass, sized according to the pass number.
+func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image.Image, error) {
+ var bitsPerPixel int = 0
pixOffset := 0
var (
gray *image.Gray
@@ -299,52 +365,63 @@ func (d *decoder) decode() (image.Image, error) {
nrgba64 *image.NRGBA64
img image.Image
)
+ width, height := d.width, d.height
+ if d.interlace == itAdam7 && !allocateOnly {
+ p := interlacing[pass]
+ // Add the multiplication factor and subtract one, effectively rounding up.
+ width = (width - p.xOffset + p.xFactor - 1) / p.xFactor
+ height = (height - p.yOffset + p.yFactor - 1) / p.yFactor
+ }
switch d.cb {
case cbG1, cbG2, cbG4, cbG8:
bitsPerPixel = d.depth
- gray = image.NewGray(image.Rect(0, 0, d.width, d.height))
+ gray = image.NewGray(image.Rect(0, 0, width, height))
img = gray
case cbGA8:
bitsPerPixel = 16
- nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height))
+ nrgba = image.NewNRGBA(image.Rect(0, 0, width, height))
img = nrgba
case cbTC8:
bitsPerPixel = 24
- rgba = image.NewRGBA(image.Rect(0, 0, d.width, d.height))
+ rgba = image.NewRGBA(image.Rect(0, 0, width, height))
img = rgba
case cbP1, cbP2, cbP4, cbP8:
bitsPerPixel = d.depth
- paletted = image.NewPaletted(image.Rect(0, 0, d.width, d.height), d.palette)
+ paletted = image.NewPaletted(image.Rect(0, 0, width, height), d.palette)
img = paletted
case cbTCA8:
bitsPerPixel = 32
- nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height))
+ nrgba = image.NewNRGBA(image.Rect(0, 0, width, height))
img = nrgba
case cbG16:
bitsPerPixel = 16
- gray16 = image.NewGray16(image.Rect(0, 0, d.width, d.height))
+ gray16 = image.NewGray16(image.Rect(0, 0, width, height))
img = gray16
case cbGA16:
bitsPerPixel = 32
- nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height))
+ nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
img = nrgba64
case cbTC16:
bitsPerPixel = 48
- rgba64 = image.NewRGBA64(image.Rect(0, 0, d.width, d.height))
+ rgba64 = image.NewRGBA64(image.Rect(0, 0, width, height))
img = rgba64
case cbTCA16:
bitsPerPixel = 64
- nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height))
+ nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
img = nrgba64
}
+ if allocateOnly {
+ return img, nil
+ }
bytesPerPixel := (bitsPerPixel + 7) / 8
- // cr and pr are the bytes for the current and previous row.
// The +1 is for the per-row filter type, which is at cr[0].
- cr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8)
- pr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8)
+ rowSize := 1 + (bitsPerPixel*width+7)/8
+ // cr and pr are the bytes for the current and previous row.
+ cr := make([]uint8, rowSize)
+ pr := make([]uint8, rowSize)
- for y := 0; y < d.height; y++ {
+ for y := 0; y < height; y++ {
// Read the decompressed bytes.
_, err := io.ReadFull(r, cr)
if err != nil {
@@ -381,25 +458,25 @@ func (d *decoder) decode() (image.Image, error) {
// Convert from bytes to colors.
switch d.cb {
case cbG1:
- for x := 0; x < d.width; x += 8 {
+ for x := 0; x < width; x += 8 {
b := cdat[x/8]
- for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
+ for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
b <<= 1
}
}
case cbG2:
- for x := 0; x < d.width; x += 4 {
+ for x := 0; x < width; x += 4 {
b := cdat[x/4]
- for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
+ for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
b <<= 2
}
}
case cbG4:
- for x := 0; x < d.width; x += 2 {
+ for x := 0; x < width; x += 2 {
b := cdat[x/2]
- for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
+ for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
b <<= 4
}
@@ -408,13 +485,13 @@ func (d *decoder) decode() (image.Image, error) {
copy(gray.Pix[pixOffset:], cdat)
pixOffset += gray.Stride
case cbGA8:
- for x := 0; x < d.width; x++ {
+ for x := 0; x < width; x++ {
ycol := cdat[2*x+0]
nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]})
}
case cbTC8:
pix, i, j := rgba.Pix, pixOffset, 0
- for x := 0; x < d.width; x++ {
+ for x := 0; x < width; x++ {
pix[i+0] = cdat[j+0]
pix[i+1] = cdat[j+1]
pix[i+2] = cdat[j+2]
@@ -424,9 +501,9 @@ func (d *decoder) decode() (image.Image, error) {
}
pixOffset += rgba.Stride
case cbP1:
- for x := 0; x < d.width; x += 8 {
+ for x := 0; x < width; x += 8 {
b := cdat[x/8]
- for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
+ for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
idx := b >> 7
if len(paletted.Palette) <= int(idx) {
paletted.Palette = paletted.Palette[:int(idx)+1]
@@ -436,9 +513,9 @@ func (d *decoder) decode() (image.Image, error) {
}
}
case cbP2:
- for x := 0; x < d.width; x += 4 {
+ for x := 0; x < width; x += 4 {
b := cdat[x/4]
- for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
+ for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
idx := b >> 6
if len(paletted.Palette) <= int(idx) {
paletted.Palette = paletted.Palette[:int(idx)+1]
@@ -448,9 +525,9 @@ func (d *decoder) decode() (image.Image, error) {
}
}
case cbP4:
- for x := 0; x < d.width; x += 2 {
+ for x := 0; x < width; x += 2 {
b := cdat[x/2]
- for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
+ for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
idx := b >> 4
if len(paletted.Palette) <= int(idx) {
paletted.Palette = paletted.Palette[:int(idx)+1]
@@ -461,7 +538,7 @@ func (d *decoder) decode() (image.Image, error) {
}
case cbP8:
if len(paletted.Palette) != 255 {
- for x := 0; x < d.width; x++ {
+ for x := 0; x < width; x++ {
if len(paletted.Palette) <= int(cdat[x]) {
paletted.Palette = paletted.Palette[:int(cdat[x])+1]
}
@@ -473,25 +550,25 @@ func (d *decoder) decode() (image.Image, error) {
copy(nrgba.Pix[pixOffset:], cdat)
pixOffset += nrgba.Stride
case cbG16:
- for x := 0; x < d.width; x++ {
+ for x := 0; x < width; x++ {
ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
gray16.SetGray16(x, y, color.Gray16{ycol})
}
case cbGA16:
- for x := 0; x < d.width; x++ {
+ for x := 0; x < width; x++ {
ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1])
acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3])
nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
}
case cbTC16:
- for x := 0; x < d.width; x++ {
+ for x := 0; x < width; x++ {
rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff})
}
case cbTCA16:
- for x := 0; x < d.width; x++ {
+ for x := 0; x < width; x++ {
rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1])
gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
@@ -504,22 +581,66 @@ func (d *decoder) decode() (image.Image, error) {
pr, cr = cr, pr
}
- // Check for EOF, to verify the zlib checksum.
- n := 0
- for i := 0; n == 0 && err == nil; i++ {
- if i == 100 {
- return nil, io.ErrNoProgress
+ return img, nil
+}
+
+// mergePassInto merges a single pass into a full sized image.
+func (d *decoder) mergePassInto(dst image.Image, src image.Image, pass int) {
+ p := interlacing[pass]
+ var (
+ srcPix []uint8
+ dstPix []uint8
+ stride int
+ rect image.Rectangle
+ bytesPerPixel int
+ )
+ switch target := dst.(type) {
+ case *image.Alpha:
+ srcPix = src.(*image.Alpha).Pix
+ dstPix, stride, rect = target.Pix, target.Stride, target.Rect
+ bytesPerPixel = 1
+ case *image.Alpha16:
+ srcPix = src.(*image.Alpha16).Pix
+ dstPix, stride, rect = target.Pix, target.Stride, target.Rect
+ bytesPerPixel = 2
+ case *image.Gray:
+ srcPix = src.(*image.Gray).Pix
+ dstPix, stride, rect = target.Pix, target.Stride, target.Rect
+ bytesPerPixel = 1
+ case *image.Gray16:
+ srcPix = src.(*image.Gray16).Pix
+ dstPix, stride, rect = target.Pix, target.Stride, target.Rect
+ bytesPerPixel = 2
+ case *image.NRGBA:
+ srcPix = src.(*image.NRGBA).Pix
+ dstPix, stride, rect = target.Pix, target.Stride, target.Rect
+ bytesPerPixel = 4
+ case *image.NRGBA64:
+ srcPix = src.(*image.NRGBA64).Pix
+ dstPix, stride, rect = target.Pix, target.Stride, target.Rect
+ bytesPerPixel = 8
+ case *image.Paletted:
+ srcPix = src.(*image.Paletted).Pix
+ dstPix, stride, rect = target.Pix, target.Stride, target.Rect
+ bytesPerPixel = 1
+ case *image.RGBA:
+ srcPix = src.(*image.RGBA).Pix
+ dstPix, stride, rect = target.Pix, target.Stride, target.Rect
+ bytesPerPixel = 4
+ case *image.RGBA64:
+ srcPix = src.(*image.RGBA64).Pix
+ dstPix, stride, rect = target.Pix, target.Stride, target.Rect
+ bytesPerPixel = 8
+ }
+ s, bounds := 0, src.Bounds()
+ for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
+ dBase := (y*p.yFactor+p.yOffset-rect.Min.Y)*stride + (p.xOffset-rect.Min.X)*bytesPerPixel
+ for x := bounds.Min.X; x < bounds.Max.X; x++ {
+ d := dBase + x*p.xFactor*bytesPerPixel
+ copy(dstPix[d:], srcPix[s:s+bytesPerPixel])
+ s += bytesPerPixel
}
- n, err = r.Read(pr[:1])
}
- if err != nil && err != io.EOF {
- return nil, FormatError(err.Error())
- }
- if n != 0 || d.idatLength != 0 {
- return nil, FormatError("too much pixel data")
- }
-
- return img, nil
}
func (d *decoder) parseIDAT(length uint32) (err error) {
diff --git a/src/pkg/image/png/reader_test.go b/src/image/png/reader_test.go
index ac0d949a9..ce772eb6f 100644
--- a/src/pkg/image/png/reader_test.go
+++ b/src/image/png/reader_test.go
@@ -30,6 +30,7 @@ var filenames = []string{
"basn3p01",
"basn3p02",
"basn3p04",
+ "basn3p04-31i",
"basn3p08",
"basn3p08-trns",
"basn4a08",
@@ -186,6 +187,13 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
c = 0
}
}
+ if c != 0 {
+ for c != 8/bitdepth {
+ b = b << uint(bitdepth)
+ c++
+ }
+ fmt.Fprintf(w, "%02x", b)
+ }
}
io.WriteString(w, "\n")
}
@@ -235,8 +243,8 @@ func TestReader(t *testing.T) {
// Compare the two, in SNG format, line by line.
for {
- pdone := pb.Scan()
- sdone := sb.Scan()
+ pdone := !pb.Scan()
+ sdone := !sb.Scan()
if pdone && sdone {
break
}
@@ -348,3 +356,7 @@ func BenchmarkDecodePaletted(b *testing.B) {
func BenchmarkDecodeRGB(b *testing.B) {
benchmarkDecode(b, "testdata/benchRGB.png", 4)
}
+
+func BenchmarkDecodeInterlacing(b *testing.B) {
+ benchmarkDecode(b, "testdata/benchRGB-interlace.png", 4)
+}
diff --git a/src/pkg/image/png/testdata/benchGray.png b/src/image/png/testdata/benchGray.png
index 42bc6c3a0..42bc6c3a0 100644
--- a/src/pkg/image/png/testdata/benchGray.png
+++ b/src/image/png/testdata/benchGray.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/benchNRGBA-gradient.png b/src/image/png/testdata/benchNRGBA-gradient.png
index 961934cca..961934cca 100644
--- a/src/pkg/image/png/testdata/benchNRGBA-gradient.png
+++ b/src/image/png/testdata/benchNRGBA-gradient.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/benchNRGBA-opaque.png b/src/image/png/testdata/benchNRGBA-opaque.png
index ca4f4a037..ca4f4a037 100644
--- a/src/pkg/image/png/testdata/benchNRGBA-opaque.png
+++ b/src/image/png/testdata/benchNRGBA-opaque.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/benchPaletted.png b/src/image/png/testdata/benchPaletted.png
index 4b4d5b992..4b4d5b992 100644
--- a/src/pkg/image/png/testdata/benchPaletted.png
+++ b/src/image/png/testdata/benchPaletted.png
Binary files differ
diff --git a/src/image/png/testdata/benchRGB-interlace.png b/src/image/png/testdata/benchRGB-interlace.png
new file mode 100644
index 000000000..b4b5daba3
--- /dev/null
+++ b/src/image/png/testdata/benchRGB-interlace.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/benchRGB.png b/src/image/png/testdata/benchRGB.png
index 31ac65a3f..31ac65a3f 100644
--- a/src/pkg/image/png/testdata/benchRGB.png
+++ b/src/image/png/testdata/benchRGB.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/invalid-crc32.png b/src/image/png/testdata/invalid-crc32.png
index e5be4086c..e5be4086c 100644
--- a/src/pkg/image/png/testdata/invalid-crc32.png
+++ b/src/image/png/testdata/invalid-crc32.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/invalid-noend.png b/src/image/png/testdata/invalid-noend.png
index 9137270d9..9137270d9 100644
--- a/src/pkg/image/png/testdata/invalid-noend.png
+++ b/src/image/png/testdata/invalid-noend.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/invalid-trunc.png b/src/image/png/testdata/invalid-trunc.png
index d0748cf65..d0748cf65 100644
--- a/src/pkg/image/png/testdata/invalid-trunc.png
+++ b/src/image/png/testdata/invalid-trunc.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/invalid-zlib.png b/src/image/png/testdata/invalid-zlib.png
index c6d051cae..c6d051cae 100644
--- a/src/pkg/image/png/testdata/invalid-zlib.png
+++ b/src/image/png/testdata/invalid-zlib.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/README b/src/image/png/testdata/pngsuite/README
index c0f78bde8..c0f78bde8 100644
--- a/src/pkg/image/png/testdata/pngsuite/README
+++ b/src/image/png/testdata/pngsuite/README
diff --git a/src/pkg/image/png/testdata/pngsuite/README.original b/src/image/png/testdata/pngsuite/README.original
index 714d12c64..714d12c64 100644
--- a/src/pkg/image/png/testdata/pngsuite/README.original
+++ b/src/image/png/testdata/pngsuite/README.original
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g01-30.png b/src/image/png/testdata/pngsuite/basn0g01-30.png
index 007750c8c..007750c8c 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g01-30.png
+++ b/src/image/png/testdata/pngsuite/basn0g01-30.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g01-30.sng b/src/image/png/testdata/pngsuite/basn0g01-30.sng
index 7fa35710c..7fa35710c 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g01-30.sng
+++ b/src/image/png/testdata/pngsuite/basn0g01-30.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g01.png b/src/image/png/testdata/pngsuite/basn0g01.png
index e31e1c7a6..e31e1c7a6 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g01.png
+++ b/src/image/png/testdata/pngsuite/basn0g01.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g01.sng b/src/image/png/testdata/pngsuite/basn0g01.sng
index 2ce069de2..2ce069de2 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g01.sng
+++ b/src/image/png/testdata/pngsuite/basn0g01.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g02-29.png b/src/image/png/testdata/pngsuite/basn0g02-29.png
index d17d8f83c..d17d8f83c 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g02-29.png
+++ b/src/image/png/testdata/pngsuite/basn0g02-29.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g02-29.sng b/src/image/png/testdata/pngsuite/basn0g02-29.sng
index afb5dba48..afb5dba48 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g02-29.sng
+++ b/src/image/png/testdata/pngsuite/basn0g02-29.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g02.png b/src/image/png/testdata/pngsuite/basn0g02.png
index 68809dd8f..68809dd8f 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g02.png
+++ b/src/image/png/testdata/pngsuite/basn0g02.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g02.sng b/src/image/png/testdata/pngsuite/basn0g02.sng
index bb53d750d..bb53d750d 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g02.sng
+++ b/src/image/png/testdata/pngsuite/basn0g02.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g04-31.png b/src/image/png/testdata/pngsuite/basn0g04-31.png
index e30644d34..e30644d34 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g04-31.png
+++ b/src/image/png/testdata/pngsuite/basn0g04-31.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g04-31.sng b/src/image/png/testdata/pngsuite/basn0g04-31.sng
index 7f7948e1f..7f7948e1f 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g04-31.sng
+++ b/src/image/png/testdata/pngsuite/basn0g04-31.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g04.png b/src/image/png/testdata/pngsuite/basn0g04.png
index 6fa089cb8..6fa089cb8 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g04.png
+++ b/src/image/png/testdata/pngsuite/basn0g04.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g04.sng b/src/image/png/testdata/pngsuite/basn0g04.sng
index a95ad01a3..a95ad01a3 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g04.sng
+++ b/src/image/png/testdata/pngsuite/basn0g04.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g08.png b/src/image/png/testdata/pngsuite/basn0g08.png
index bf522eef0..bf522eef0 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g08.png
+++ b/src/image/png/testdata/pngsuite/basn0g08.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g08.sng b/src/image/png/testdata/pngsuite/basn0g08.sng
index 7389eb774..7389eb774 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g08.sng
+++ b/src/image/png/testdata/pngsuite/basn0g08.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g16.png b/src/image/png/testdata/pngsuite/basn0g16.png
index 318ebcadf..318ebcadf 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g16.png
+++ b/src/image/png/testdata/pngsuite/basn0g16.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn0g16.sng b/src/image/png/testdata/pngsuite/basn0g16.sng
index 922391a9e..922391a9e 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn0g16.sng
+++ b/src/image/png/testdata/pngsuite/basn0g16.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn2c08.png b/src/image/png/testdata/pngsuite/basn2c08.png
index 21d2f91a8..21d2f91a8 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn2c08.png
+++ b/src/image/png/testdata/pngsuite/basn2c08.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn2c08.sng b/src/image/png/testdata/pngsuite/basn2c08.sng
index 09a61317b..09a61317b 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn2c08.sng
+++ b/src/image/png/testdata/pngsuite/basn2c08.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn2c16.png b/src/image/png/testdata/pngsuite/basn2c16.png
index 1bd4a4d0e..1bd4a4d0e 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn2c16.png
+++ b/src/image/png/testdata/pngsuite/basn2c16.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn2c16.sng b/src/image/png/testdata/pngsuite/basn2c16.sng
index bac7c9d91..bac7c9d91 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn2c16.sng
+++ b/src/image/png/testdata/pngsuite/basn2c16.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn3p01.png b/src/image/png/testdata/pngsuite/basn3p01.png
index a21db5977..a21db5977 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn3p01.png
+++ b/src/image/png/testdata/pngsuite/basn3p01.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn3p01.sng b/src/image/png/testdata/pngsuite/basn3p01.sng
index a8b3ce878..a8b3ce878 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn3p01.sng
+++ b/src/image/png/testdata/pngsuite/basn3p01.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn3p02.png b/src/image/png/testdata/pngsuite/basn3p02.png
index 1d0ab6197..1d0ab6197 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn3p02.png
+++ b/src/image/png/testdata/pngsuite/basn3p02.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn3p02.sng b/src/image/png/testdata/pngsuite/basn3p02.sng
index ab3fb375f..ab3fb375f 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn3p02.sng
+++ b/src/image/png/testdata/pngsuite/basn3p02.sng
diff --git a/src/image/png/testdata/pngsuite/basn3p04-31i.png b/src/image/png/testdata/pngsuite/basn3p04-31i.png
new file mode 100644
index 000000000..540137cb5
--- /dev/null
+++ b/src/image/png/testdata/pngsuite/basn3p04-31i.png
Binary files differ
diff --git a/src/image/png/testdata/pngsuite/basn3p04-31i.sng b/src/image/png/testdata/pngsuite/basn3p04-31i.sng
new file mode 100644
index 000000000..31b87c72d
--- /dev/null
+++ b/src/image/png/testdata/pngsuite/basn3p04-31i.sng
@@ -0,0 +1,57 @@
+#SNG: from basn3p04-31i.png
+IHDR {
+ width: 31; height: 31; bitdepth: 4;
+ using color palette;
+}
+gAMA {1.0000}
+PLTE {
+ ( 34, 0,255) # rgb = (0x22,0x00,0xff)
+ ( 0,255,255) # rgb = (0x00,0xff,0xff)
+ (136, 0,255) # rgb = (0x88,0x00,0xff)
+ ( 34,255, 0) # rgb = (0x22,0xff,0x00)
+ ( 0,153,255) # rgb = (0x00,0x99,0xff)
+ (255,102, 0) # rgb = (0xff,0x66,0x00)
+ (221, 0,255) # rgb = (0xdd,0x00,0xff)
+ (119,255, 0) # rgb = (0x77,0xff,0x00)
+ (255, 0, 0) # rgb = (0xff,0x00,0x00)
+ ( 0,255,153) # rgb = (0x00,0xff,0x99)
+ (221,255, 0) # rgb = (0xdd,0xff,0x00)
+ (255, 0,187) # rgb = (0xff,0x00,0xbb)
+ (255,187, 0) # rgb = (0xff,0xbb,0x00)
+ ( 0, 68,255) # rgb = (0x00,0x44,0xff)
+ ( 0,255, 68) # rgb = (0x00,0xff,0x44)
+}
+IMAGE {
+ pixels hex
+88885555ccccaaaa77773333eeee9990
+88885555ccccaaaa77773333eeee9990
+88885555ccccaaaa77773333eeee9990
+88885555ccccaaaa77773333eeee9990
+5555ccccaaaa77773333eeee99991110
+5555ccccaaaa77773333eeee99991110
+5555ccccaaaa77773333eeee99991110
+5555ccccaaaa77773333eeee99991110
+ccccaaaa77773333eeee999911114440
+ccccaaaa77773333eeee999911114440
+ccccaaaa77773333eeee999911114440
+ccccaaaa77773333eeee999911114440
+aaaa77773333eeee999911114444ddd0
+aaaa77773333eeee999911114444ddd0
+aaaa77773333eeee999911114444ddd0
+aaaa77773333eeee999911114444ddd0
+77773333eeee999911114444dddd0000
+77773333eeee999911114444dddd0000
+77773333eeee999911114444dddd0000
+77773333eeee999911114444dddd0000
+3333eeee999911114444dddd00002220
+3333eeee999911114444dddd00002220
+3333eeee999911114444dddd00002220
+3333eeee999911114444dddd00002220
+eeee999911114444dddd000022226660
+eeee999911114444dddd000022226660
+eeee999911114444dddd000022226660
+eeee999911114444dddd000022226660
+999911114444dddd000022226666bbb0
+999911114444dddd000022226666bbb0
+999911114444dddd000022226666bbb0
+}
diff --git a/src/pkg/image/png/testdata/pngsuite/basn3p04.png b/src/image/png/testdata/pngsuite/basn3p04.png
index 6dc6eac83..6dc6eac83 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn3p04.png
+++ b/src/image/png/testdata/pngsuite/basn3p04.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn3p04.sng b/src/image/png/testdata/pngsuite/basn3p04.sng
index a2b2fb53c..a2b2fb53c 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn3p04.sng
+++ b/src/image/png/testdata/pngsuite/basn3p04.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn3p08-trns.png b/src/image/png/testdata/pngsuite/basn3p08-trns.png
index b0fc0c1be..b0fc0c1be 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn3p08-trns.png
+++ b/src/image/png/testdata/pngsuite/basn3p08-trns.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn3p08-trns.sng b/src/image/png/testdata/pngsuite/basn3p08-trns.sng
index 78dc367bb..78dc367bb 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn3p08-trns.sng
+++ b/src/image/png/testdata/pngsuite/basn3p08-trns.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn3p08.png b/src/image/png/testdata/pngsuite/basn3p08.png
index 0e07f483c..0e07f483c 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn3p08.png
+++ b/src/image/png/testdata/pngsuite/basn3p08.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn3p08.sng b/src/image/png/testdata/pngsuite/basn3p08.sng
index 0423bb21e..0423bb21e 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn3p08.sng
+++ b/src/image/png/testdata/pngsuite/basn3p08.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn4a08.png b/src/image/png/testdata/pngsuite/basn4a08.png
index 3bb0dd06b..3bb0dd06b 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn4a08.png
+++ b/src/image/png/testdata/pngsuite/basn4a08.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn4a08.sng b/src/image/png/testdata/pngsuite/basn4a08.sng
index cc4096fac..cc4096fac 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn4a08.sng
+++ b/src/image/png/testdata/pngsuite/basn4a08.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn4a16.png b/src/image/png/testdata/pngsuite/basn4a16.png
index 6dbee9fbd..6dbee9fbd 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn4a16.png
+++ b/src/image/png/testdata/pngsuite/basn4a16.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn4a16.sng b/src/image/png/testdata/pngsuite/basn4a16.sng
index d3b9b4722..d3b9b4722 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn4a16.sng
+++ b/src/image/png/testdata/pngsuite/basn4a16.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn6a08.png b/src/image/png/testdata/pngsuite/basn6a08.png
index 610623085..610623085 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn6a08.png
+++ b/src/image/png/testdata/pngsuite/basn6a08.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn6a08.sng b/src/image/png/testdata/pngsuite/basn6a08.sng
index c1e0bf475..c1e0bf475 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn6a08.sng
+++ b/src/image/png/testdata/pngsuite/basn6a08.sng
diff --git a/src/pkg/image/png/testdata/pngsuite/basn6a16.png b/src/image/png/testdata/pngsuite/basn6a16.png
index a9bf3cb46..a9bf3cb46 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn6a16.png
+++ b/src/image/png/testdata/pngsuite/basn6a16.png
Binary files differ
diff --git a/src/pkg/image/png/testdata/pngsuite/basn6a16.sng b/src/image/png/testdata/pngsuite/basn6a16.sng
index 13c70a4d5..13c70a4d5 100644
--- a/src/pkg/image/png/testdata/pngsuite/basn6a16.sng
+++ b/src/image/png/testdata/pngsuite/basn6a16.sng
diff --git a/src/pkg/image/png/writer.go b/src/image/png/writer.go
index 629452cbf..df23270ee 100644
--- a/src/pkg/image/png/writer.go
+++ b/src/image/png/writer.go
@@ -14,7 +14,13 @@ import (
"strconv"
)
+// Encoder configures encoding PNG images.
+type Encoder struct {
+ CompressionLevel CompressionLevel
+}
+
type encoder struct {
+ enc *Encoder
w io.Writer
m image.Image
cb int
@@ -24,6 +30,18 @@ type encoder struct {
tmp [4 * 256]byte
}
+type CompressionLevel int
+
+const (
+ DefaultCompression CompressionLevel = 0
+ NoCompression CompressionLevel = -1
+ BestSpeed CompressionLevel = -2
+ BestCompression CompressionLevel = -3
+
+ // Positive CompressionLevel values are reserved to mean a numeric zlib
+ // compression level, although that is not implemented yet.
+)
+
// Big-endian.
func writeUint32(b []uint8, u uint32) {
b[0] = uint8(u >> 24)
@@ -188,7 +206,7 @@ func filter(cr *[nFilter][]byte, pr []byte, bpp int) int {
// The Paeth filter.
sum = 0
for i := 0; i < bpp; i++ {
- cdat4[i] = cdat0[i] - paeth(0, pdat[i], 0)
+ cdat4[i] = cdat0[i] - pdat[i]
sum += abs8(cdat4[i])
}
for i := bpp; i < n; i++ {
@@ -255,8 +273,11 @@ func filter(cr *[nFilter][]byte, pr []byte, bpp int) int {
return filter
}
-func writeImage(w io.Writer, m image.Image, cb int) error {
- zw := zlib.NewWriter(w)
+func writeImage(w io.Writer, m image.Image, cb int, level int) error {
+ zw, err := zlib.NewWriterLevel(w, level)
+ if err != nil {
+ return err
+ }
defer zw.Close()
bpp := 0 // Bytes per pixel.
@@ -399,7 +420,10 @@ func writeImage(w io.Writer, m image.Image, cb int) error {
}
// Apply the filter.
- f := filter(&cr, pr, bpp)
+ f := ftNone
+ if level != zlib.NoCompression {
+ f = filter(&cr, pr, bpp)
+ }
// Write the compressed bytes.
if _, err := zw.Write(cr[f]); err != nil {
@@ -419,18 +443,41 @@ func (e *encoder) writeIDATs() {
}
var bw *bufio.Writer
bw = bufio.NewWriterSize(e, 1<<15)
- e.err = writeImage(bw, e.m, e.cb)
+ e.err = writeImage(bw, e.m, e.cb, levelToZlib(e.enc.CompressionLevel))
if e.err != nil {
return
}
e.err = bw.Flush()
}
+// This function is required because we want the zero value of
+// Encoder.CompressionLevel to map to zlib.DefaultCompression.
+func levelToZlib(l CompressionLevel) int {
+ switch l {
+ case DefaultCompression:
+ return zlib.DefaultCompression
+ case NoCompression:
+ return zlib.NoCompression
+ case BestSpeed:
+ return zlib.BestSpeed
+ case BestCompression:
+ return zlib.BestCompression
+ default:
+ return zlib.DefaultCompression
+ }
+}
+
func (e *encoder) writeIEND() { e.writeChunk(nil, "IEND") }
-// Encode writes the Image m to w in PNG format. Any Image may be encoded, but
-// images that are not image.NRGBA might be encoded lossily.
+// Encode writes the Image m to w in PNG format. Any Image may be
+// encoded, but images that are not image.NRGBA might be encoded lossily.
func Encode(w io.Writer, m image.Image) error {
+ var e Encoder
+ return e.Encode(w, m)
+}
+
+// Encode writes the Image m to w in PNG format.
+func (enc *Encoder) Encode(w io.Writer, m image.Image) error {
// Obviously, negative widths and heights are invalid. Furthermore, the PNG
// spec section 11.2.2 says that zero is invalid. Excessively large images are
// also rejected.
@@ -440,6 +487,7 @@ func Encode(w io.Writer, m image.Image) error {
}
var e encoder
+ e.enc = enc
e.w = w
e.m = m
diff --git a/src/pkg/image/png/writer_test.go b/src/image/png/writer_test.go
index 3116fc9ff..d67a81569 100644
--- a/src/pkg/image/png/writer_test.go
+++ b/src/image/png/writer_test.go
@@ -40,11 +40,7 @@ func encodeDecode(m image.Image) (image.Image, error) {
if err != nil {
return nil, err
}
- m, err = Decode(&b)
- if err != nil {
- return nil, err
- }
- return m, nil
+ return Decode(&b)
}
func TestWriter(t *testing.T) {
@@ -81,6 +77,29 @@ func TestWriter(t *testing.T) {
}
}
+func TestWriterLevels(t *testing.T) {
+ m := image.NewNRGBA(image.Rect(0, 0, 100, 100))
+
+ var b1, b2 bytes.Buffer
+ if err := (&Encoder{}).Encode(&b1, m); err != nil {
+ t.Fatal(err)
+ }
+ noenc := &Encoder{CompressionLevel: NoCompression}
+ if err := noenc.Encode(&b2, m); err != nil {
+ t.Fatal(err)
+ }
+
+ if b2.Len() <= b1.Len() {
+ t.Error("DefaultCompression encoding was larger than NoCompression encoding")
+ }
+ if _, err := Decode(&b1); err != nil {
+ t.Error("cannot decode DefaultCompression")
+ }
+ if _, err := Decode(&b2); err != nil {
+ t.Error("cannot decode NoCompression")
+ }
+}
+
func TestSubImage(t *testing.T) {
m0 := image.NewRGBA(image.Rect(0, 0, 256, 256))
for y := 0; y < 256; y++ {
diff --git a/src/pkg/image/testdata/video-001.5bpp.gif b/src/image/testdata/video-001.5bpp.gif
index ce53104b2..ce53104b2 100644
--- a/src/pkg/image/testdata/video-001.5bpp.gif
+++ b/src/image/testdata/video-001.5bpp.gif
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.gif b/src/image/testdata/video-001.gif
index ca06af61b..ca06af61b 100644
--- a/src/pkg/image/testdata/video-001.gif
+++ b/src/image/testdata/video-001.gif
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.interlaced.gif b/src/image/testdata/video-001.interlaced.gif
index 590594ea9..590594ea9 100644
--- a/src/pkg/image/testdata/video-001.interlaced.gif
+++ b/src/image/testdata/video-001.interlaced.gif
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.jpeg b/src/image/testdata/video-001.jpeg
index 1b87c933b..1b87c933b 100644
--- a/src/pkg/image/testdata/video-001.jpeg
+++ b/src/image/testdata/video-001.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.png b/src/image/testdata/video-001.png
index d3468bbe8..d3468bbe8 100644
--- a/src/pkg/image/testdata/video-001.png
+++ b/src/image/testdata/video-001.png
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.progressive.jpeg b/src/image/testdata/video-001.progressive.jpeg
index b8cae2359..b8cae2359 100644
--- a/src/pkg/image/testdata/video-001.progressive.jpeg
+++ b/src/image/testdata/video-001.progressive.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.q50.420.jpeg b/src/image/testdata/video-001.q50.420.jpeg
index 83fb0f8ab..83fb0f8ab 100644
--- a/src/pkg/image/testdata/video-001.q50.420.jpeg
+++ b/src/image/testdata/video-001.q50.420.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.q50.420.progressive.jpeg b/src/image/testdata/video-001.q50.420.progressive.jpeg
index b048eb205..b048eb205 100644
--- a/src/pkg/image/testdata/video-001.q50.420.progressive.jpeg
+++ b/src/image/testdata/video-001.q50.420.progressive.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.q50.422.jpeg b/src/image/testdata/video-001.q50.422.jpeg
index 60fff4ff9..60fff4ff9 100644
--- a/src/pkg/image/testdata/video-001.q50.422.jpeg
+++ b/src/image/testdata/video-001.q50.422.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.q50.422.progressive.jpeg b/src/image/testdata/video-001.q50.422.progressive.jpeg
index 926d005de..926d005de 100644
--- a/src/pkg/image/testdata/video-001.q50.422.progressive.jpeg
+++ b/src/image/testdata/video-001.q50.422.progressive.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.q50.440.jpeg b/src/image/testdata/video-001.q50.440.jpeg
index 32eeeaef6..32eeeaef6 100644
--- a/src/pkg/image/testdata/video-001.q50.440.jpeg
+++ b/src/image/testdata/video-001.q50.440.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.q50.440.progressive.jpeg b/src/image/testdata/video-001.q50.440.progressive.jpeg
index e641a3bbb..e641a3bbb 100644
--- a/src/pkg/image/testdata/video-001.q50.440.progressive.jpeg
+++ b/src/image/testdata/video-001.q50.440.progressive.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.q50.444.jpeg b/src/image/testdata/video-001.q50.444.jpeg
index 7d5743382..7d5743382 100644
--- a/src/pkg/image/testdata/video-001.q50.444.jpeg
+++ b/src/image/testdata/video-001.q50.444.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.q50.444.progressive.jpeg b/src/image/testdata/video-001.q50.444.progressive.jpeg
index ff7d5f9ff..ff7d5f9ff 100644
--- a/src/pkg/image/testdata/video-001.q50.444.progressive.jpeg
+++ b/src/image/testdata/video-001.q50.444.progressive.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.separate.dc.progression.jpeg b/src/image/testdata/video-001.separate.dc.progression.jpeg
index 107f0fa0c..107f0fa0c 100644
--- a/src/pkg/image/testdata/video-001.separate.dc.progression.jpeg
+++ b/src/image/testdata/video-001.separate.dc.progression.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-001.separate.dc.progression.progressive.jpeg b/src/image/testdata/video-001.separate.dc.progression.progressive.jpeg
index a1d493ef8..a1d493ef8 100644
--- a/src/pkg/image/testdata/video-001.separate.dc.progression.progressive.jpeg
+++ b/src/image/testdata/video-001.separate.dc.progression.progressive.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-005.gray.gif b/src/image/testdata/video-005.gray.gif
index 23350d6dc..23350d6dc 100644
--- a/src/pkg/image/testdata/video-005.gray.gif
+++ b/src/image/testdata/video-005.gray.gif
Binary files differ
diff --git a/src/pkg/image/testdata/video-005.gray.jpeg b/src/image/testdata/video-005.gray.jpeg
index f9d6e5cdb..f9d6e5cdb 100644
--- a/src/pkg/image/testdata/video-005.gray.jpeg
+++ b/src/image/testdata/video-005.gray.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-005.gray.png b/src/image/testdata/video-005.gray.png
index 0b0ee7538..0b0ee7538 100644
--- a/src/pkg/image/testdata/video-005.gray.png
+++ b/src/image/testdata/video-005.gray.png
Binary files differ
diff --git a/src/pkg/image/testdata/video-005.gray.q50.2x2.jpeg b/src/image/testdata/video-005.gray.q50.2x2.jpeg
index 630b615f7..630b615f7 100644
--- a/src/pkg/image/testdata/video-005.gray.q50.2x2.jpeg
+++ b/src/image/testdata/video-005.gray.q50.2x2.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-005.gray.q50.2x2.progressive.jpeg b/src/image/testdata/video-005.gray.q50.2x2.progressive.jpeg
index c6b93608c..c6b93608c 100644
--- a/src/pkg/image/testdata/video-005.gray.q50.2x2.progressive.jpeg
+++ b/src/image/testdata/video-005.gray.q50.2x2.progressive.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-005.gray.q50.jpeg b/src/image/testdata/video-005.gray.q50.jpeg
index c65b5a794..c65b5a794 100644
--- a/src/pkg/image/testdata/video-005.gray.q50.jpeg
+++ b/src/image/testdata/video-005.gray.q50.jpeg
Binary files differ
diff --git a/src/pkg/image/testdata/video-005.gray.q50.progressive.jpeg b/src/image/testdata/video-005.gray.q50.progressive.jpeg
index 24b70e8bf..24b70e8bf 100644
--- a/src/pkg/image/testdata/video-005.gray.q50.progressive.jpeg
+++ b/src/image/testdata/video-005.gray.q50.progressive.jpeg
Binary files differ
diff --git a/src/pkg/image/ycbcr.go b/src/image/ycbcr.go
index 5b73bef78..7c773f2f0 100644
--- a/src/pkg/image/ycbcr.go
+++ b/src/image/ycbcr.go
@@ -60,6 +60,10 @@ func (p *YCbCr) Bounds() Rectangle {
}
func (p *YCbCr) At(x, y int) color.Color {
+ return p.YCbCrAt(x, y)
+}
+
+func (p *YCbCr) YCbCrAt(x, y int) color.YCbCr {
if !(Point{x, y}.In(p.Rect)) {
return color.YCbCr{}
}
diff --git a/src/pkg/image/ycbcr_test.go b/src/image/ycbcr_test.go
index a5f448265..a5f448265 100644
--- a/src/pkg/image/ycbcr_test.go
+++ b/src/image/ycbcr_test.go
diff --git a/src/pkg/index/suffixarray/qsufsort.go b/src/index/suffixarray/qsufsort.go
index 9c36a98f8..9c36a98f8 100644
--- a/src/pkg/index/suffixarray/qsufsort.go
+++ b/src/index/suffixarray/qsufsort.go
diff --git a/src/pkg/index/suffixarray/suffixarray.go b/src/index/suffixarray/suffixarray.go
index c59ae6eef..c59ae6eef 100644
--- a/src/pkg/index/suffixarray/suffixarray.go
+++ b/src/index/suffixarray/suffixarray.go
diff --git a/src/pkg/index/suffixarray/suffixarray_test.go b/src/index/suffixarray/suffixarray_test.go
index df3e449d3..644f00c75 100644
--- a/src/pkg/index/suffixarray/suffixarray_test.go
+++ b/src/index/suffixarray/suffixarray_test.go
@@ -287,7 +287,7 @@ func BenchmarkNewIndexRepeat(b *testing.B) {
func BenchmarkSaveRestore(b *testing.B) {
b.StopTimer()
r := rand.New(rand.NewSource(0x5a77a1)) // guarantee always same sequence
- data := make([]byte, 10<<20) // 10MB of data to index
+ data := make([]byte, 1<<20) // 1MB of data to index
for i := range data {
data[i] = byte(r.Intn(256))
}
diff --git a/src/internal/syscall/getrandom_linux.go b/src/internal/syscall/getrandom_linux.go
new file mode 100644
index 000000000..944bab3f5
--- /dev/null
+++ b/src/internal/syscall/getrandom_linux.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.
+
+package syscall
+
+import (
+ "runtime"
+ "sync/atomic"
+ stdsyscall "syscall"
+ "unsafe"
+)
+
+var randomTrap = map[string]uintptr{
+ "386": 355,
+ "amd64": 318,
+ "arm": 384,
+}[runtime.GOARCH]
+
+var randomUnsupported int32 // atomic
+
+// GetRandomFlag is a flag supported by the getrandom system call.
+type GetRandomFlag uintptr
+
+const (
+ // GRND_NONBLOCK means return EAGAIN rather than blocking.
+ GRND_NONBLOCK GetRandomFlag = 0x0001
+
+ // GRND_RANDOM means use the /dev/random pool instead of /dev/urandom.
+ GRND_RANDOM GetRandomFlag = 0x0002
+)
+
+// GetRandom calls the Linux getrandom system call.
+// See https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c6e9d6f38894798696f23c8084ca7edbf16ee895
+func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
+ if randomTrap == 0 {
+ return 0, stdsyscall.ENOSYS
+ }
+ if len(p) == 0 {
+ return 0, nil
+ }
+ if atomic.LoadInt32(&randomUnsupported) != 0 {
+ return 0, stdsyscall.ENOSYS
+ }
+ r1, _, errno := stdsyscall.Syscall(randomTrap,
+ uintptr(unsafe.Pointer(&p[0])),
+ uintptr(len(p)),
+ uintptr(flags))
+ if errno != 0 {
+ if errno == stdsyscall.ENOSYS {
+ atomic.StoreInt32(&randomUnsupported, 1)
+ }
+ return 0, errno
+ }
+ return int(r1), nil
+}
diff --git a/src/pkg/io/io.go b/src/io/io.go
index 022fdb676..7507a8492 100644
--- a/src/pkg/io/io.go
+++ b/src/io/io.go
@@ -62,8 +62,11 @@ var ErrNoProgress = errors.New("multiple Read calls return no data or error")
// allowed EOF behaviors.
//
// Implementations of Read are discouraged from returning a
-// zero byte count with a nil error, and callers should treat
-// that situation as a no-op.
+// zero byte count with a nil error, except when len(p) == 0.
+// Callers should treat a return of 0 and nil as indicating that
+// nothing happened; in particular it does not indicate EOF.
+//
+// Implementations must not retain p.
type Reader interface {
Read(p []byte) (n int, err error)
}
@@ -75,6 +78,8 @@ type Reader interface {
// and any error encountered that caused the write to stop early.
// Write must return a non-nil error if it returns n < len(p).
// Write must not modify the slice data, even temporarily.
+//
+// Implementations must not retain p.
type Writer interface {
Write(p []byte) (n int, err error)
}
@@ -192,6 +197,8 @@ type WriterTo interface {
//
// Clients of ReadAt can execute parallel ReadAt calls on the
// same input source.
+//
+// Implementations must not retain p.
type ReaderAt interface {
ReadAt(p []byte, off int64) (n int, err error)
}
@@ -209,6 +216,8 @@ type ReaderAt interface {
//
// Clients of WriteAt can execute parallel WriteAt calls on the same
// destination if the ranges do not overlap.
+//
+// Implementations must not retain p.
type WriterAt interface {
WriteAt(p []byte, off int64) (n int, err error)
}
diff --git a/src/pkg/io/io_test.go b/src/io/io_test.go
index 57db1fbf0..57db1fbf0 100644
--- a/src/pkg/io/io_test.go
+++ b/src/io/io_test.go
diff --git a/src/pkg/io/ioutil/ioutil.go b/src/io/ioutil/ioutil.go
index 909a81563..909a81563 100644
--- a/src/pkg/io/ioutil/ioutil.go
+++ b/src/io/ioutil/ioutil.go
diff --git a/src/pkg/io/ioutil/ioutil_test.go b/src/io/ioutil/ioutil_test.go
index c297847b4..c297847b4 100644
--- a/src/pkg/io/ioutil/ioutil_test.go
+++ b/src/io/ioutil/ioutil_test.go
diff --git a/src/pkg/io/ioutil/tempfile.go b/src/io/ioutil/tempfile.go
index 4a06e9756..4a06e9756 100644
--- a/src/pkg/io/ioutil/tempfile.go
+++ b/src/io/ioutil/tempfile.go
diff --git a/src/pkg/io/ioutil/tempfile_test.go b/src/io/ioutil/tempfile_test.go
index d2a132a11..d2a132a11 100644
--- a/src/pkg/io/ioutil/tempfile_test.go
+++ b/src/io/ioutil/tempfile_test.go
diff --git a/src/pkg/io/multi.go b/src/io/multi.go
index e26cc53e9..e26cc53e9 100644
--- a/src/pkg/io/multi.go
+++ b/src/io/multi.go
diff --git a/src/pkg/io/multi_test.go b/src/io/multi_test.go
index 56c6769a9..56c6769a9 100644
--- a/src/pkg/io/multi_test.go
+++ b/src/io/multi_test.go
diff --git a/src/pkg/io/pipe.go b/src/io/pipe.go
index f65354a7f..f65354a7f 100644
--- a/src/pkg/io/pipe.go
+++ b/src/io/pipe.go
diff --git a/src/pkg/io/pipe_test.go b/src/io/pipe_test.go
index b16e65306..b16e65306 100644
--- a/src/pkg/io/pipe_test.go
+++ b/src/io/pipe_test.go
diff --git a/src/lib9/fmt/dofmt.c b/src/lib9/fmt/dofmt.c
index 94a91a2aa..3b9dc3612 100644
--- a/src/lib9/fmt/dofmt.c
+++ b/src/lib9/fmt/dofmt.c
@@ -491,12 +491,6 @@ __ifmt(Fmt *f)
if(fl & FmtApost)
__needsep(&ndig, &grouping);
}
-
- /*
- * Zero values don't get 0x.
- */
- if(f->r == 'x' || f->r == 'X')
- fl &= ~(ulong)FmtSharp;
}
for(w = f->prec; n < w && p > buf+3; n++){
if((fl & FmtApost) && __needsep(&ndig, &grouping)){
diff --git a/src/lib9/tempdir_windows.c b/src/lib9/tempdir_windows.c
index 1a530059a..4c3df7cf1 100644
--- a/src/lib9/tempdir_windows.c
+++ b/src/lib9/tempdir_windows.c
@@ -70,7 +70,7 @@ removeall(char *p)
{
WinRune *r, *r1;
DWORD attr;
- char *q, *elem;
+ char *q, *qt, *elem;
HANDLE h;
WIN32_FIND_DATAW data;
@@ -91,15 +91,18 @@ removeall(char *p)
do{
q = toutf(data.cFileName);
elem = strrchr(q, '\\');
- if(elem != nil) {
+ if(elem != nil)
elem++;
- if(strcmp(elem, ".") == 0 || strcmp(elem, "..") == 0) {
- free(q);
- continue;
- }
+ else
+ elem = q;
+ if(strcmp(elem, ".") == 0 || strcmp(elem, "..") == 0) {
+ free(q);
+ continue;
}
- removeall(q);
- free(q);
+ qt = smprint("%s\\%s", p, q);
+ free(q);
+ removeall(qt);
+ free(qt);
}while(FindNextFileW(h, &data));
FindClose(h);
diff --git a/src/liblink/asm5.c b/src/liblink/asm5.c
index 465b645b2..96df9f791 100644
--- a/src/liblink/asm5.c
+++ b/src/liblink/asm5.c
@@ -35,7 +35,7 @@
#include <bio.h>
#include <link.h>
#include "../cmd/5l/5.out.h"
-#include "../pkg/runtime/stack.h"
+#include "../runtime/stack.h"
typedef struct Optab Optab;
typedef struct Oprang Oprang;
@@ -43,7 +43,7 @@ typedef uchar Opcross[32][2][32];
struct Optab
{
- char as;
+ uchar as;
uchar a1;
char a2;
uchar a3;
@@ -65,52 +65,6 @@ enum
LTO = 1<<1,
LPOOL = 1<<2,
LPCREL = 1<<3,
-
- C_NONE = 0,
- C_REG,
- C_REGREG,
- C_REGREG2,
- C_SHIFT,
- C_FREG,
- C_PSR,
- C_FCR,
-
- C_RCON, /* 0xff rotated */
- C_NCON, /* ~RCON */
- C_SCON, /* 0xffff */
- C_LCON,
- C_LCONADDR,
- C_ZFCON,
- C_SFCON,
- C_LFCON,
-
- C_RACON,
- C_LACON,
-
- C_SBRA,
- C_LBRA,
-
- C_HAUTO, /* halfword insn offset (-0xff to 0xff) */
- C_FAUTO, /* float insn offset (0 to 0x3fc, word aligned) */
- C_HFAUTO, /* both H and F */
- C_SAUTO, /* -0xfff to 0xfff */
- C_LAUTO,
-
- C_HOREG,
- C_FOREG,
- C_HFOREG,
- C_SOREG,
- C_ROREG,
- C_SROREG, /* both nil and R */
- C_LOREG,
-
- C_PC,
- C_SP,
- C_HREG,
-
- C_ADDR, /* reference to relocatable address */
-
- C_GOK,
};
static Optab optab[] =
@@ -355,10 +309,14 @@ static Optab optab[] =
{ AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0 },
{ APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0 },
{ AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0 },
+ { ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0 },
{ ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0 }, // same as ABL
{ ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0 }, // same as ABL
+ { ADATABUNDLE, C_NONE, C_NONE, C_NONE, 100, 4, 0 },
+ { ADATABUNDLEEND, C_NONE, C_NONE, C_NONE, 100, 0, 0 },
+
{ AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0 },
};
@@ -372,6 +330,7 @@ static int checkpool(Link*, Prog*, int);
static int flushpool(Link*, Prog*, int, int);
static void addpool(Link*, Prog*, Addr*);
static void asmout(Link*, Prog*, Optab*, int32*);
+static int asmoutnacl(Link*, int32, Prog*, Optab*, int32 *);
static Optab* oplook(Link*, Prog*);
static int32 oprrr(Link*, int, int);
static int32 olr(Link*, int32, int, int, int);
@@ -390,10 +349,8 @@ static int32 immrot(uint32);
static int32 immaddr(int32);
static int32 opbra(Link*, int, int);
-static Opcross opcross[8];
static Oprang oprange[ALAST];
-static char xcmp[C_GOK+1][C_GOK+1];
-static uchar repop[ALAST];
+static uchar xcmp[C_GOK+1][C_GOK+1];
static Prog zprg = {
.as = AGOK,
@@ -411,6 +368,8 @@ static Prog zprg = {
},
};
+static LSym *deferreturn;
+
static void
nocache(Prog *p)
{
@@ -419,19 +378,6 @@ nocache(Prog *p)
p->to.class = 0;
}
-static int
-scan(Link *ctxt, Prog *op, Prog *p, int c)
-{
- Prog *q;
-
- for(q = op->link; q != p && q != nil; q = q->link){
- q->pc = c;
- c += oplook(ctxt, q)->size;
- nocache(q);
- }
- return c;
-}
-
/* size of a case statement including jump table */
static int32
casesz(Link *ctxt, Prog *p)
@@ -453,13 +399,250 @@ casesz(Link *ctxt, Prog *p)
static void buildop(Link*);
+// asmoutnacl assembles the instruction p. It replaces asmout for NaCl.
+// It returns the total number of bytes put in out, and it can change
+// p->pc if extra padding is necessary.
+// In rare cases, asmoutnacl might split p into two instructions.
+// origPC is the PC for this Prog (no padding is taken into account).
+static int
+asmoutnacl(Link *ctxt, int32 origPC, Prog *p, Optab *o, int32 *out)
+{
+ int size, reg;
+ Prog *q;
+ Addr *a, *a2;
+
+ size = o->size;
+
+ // instruction specific
+ switch(p->as) {
+ default:
+ if(out != nil)
+ asmout(ctxt, p, o, out);
+ break;
+ case ADATABUNDLE: // align to 16-byte boundary
+ case ADATABUNDLEEND: // zero width instruction, just to align next instruction to 16-byte boundary
+ p->pc = (p->pc+15) & ~15;
+ if(out != nil)
+ asmout(ctxt, p, o, out);
+ break;
+ case AUNDEF:
+ case APLD:
+ size = 4;
+ if(out != nil) {
+ switch(p->as) {
+ case AUNDEF:
+ out[0] = 0xe7fedef0; // NACL_INSTR_ARM_ABORT_NOW (UDF #0xEDE0)
+ break;
+ case APLD:
+ out[0] = 0xe1a01001; // (MOVW R1, R1)
+ break;
+ }
+ }
+ break;
+ case AB:
+ case ABL:
+ if(p->to.type != D_OREG) {
+ if(out != nil)
+ asmout(ctxt, p, o, out);
+ } else {
+ if(p->to.offset != 0 || size != 4 || p->to.reg >= 16 || p->to.reg < 0)
+ ctxt->diag("unsupported instruction: %P", p);
+ if((p->pc&15) == 12)
+ p->pc += 4;
+ if(out != nil) {
+ out[0] = ((p->scond&C_SCOND)<<28) | 0x03c0013f | (p->to.reg << 12) | (p->to.reg << 16); // BIC $0xc000000f, Rx
+ if(p->as == AB)
+ out[1] = ((p->scond&C_SCOND)<<28) | 0x012fff10 | p->to.reg; // BX Rx
+ else // ABL
+ out[1] = ((p->scond&C_SCOND)<<28) | 0x012fff30 | p->to.reg; // BLX Rx
+ }
+ size = 8;
+ }
+ // align the last instruction (the actual BL) to the last instruction in a bundle
+ if(p->as == ABL) {
+ if(deferreturn == nil)
+ deferreturn = linklookup(ctxt, "runtime.deferreturn", 0);
+ if(p->to.sym == deferreturn)
+ p->pc = ((origPC+15) & ~15) + 16 - size;
+ else
+ p->pc += (16 - ((p->pc+size)&15)) & 15;
+ }
+ break;
+ case ALDREX:
+ case ALDREXD:
+ case AMOVB:
+ case AMOVBS:
+ case AMOVBU:
+ case AMOVD:
+ case AMOVF:
+ case AMOVH:
+ case AMOVHS:
+ case AMOVHU:
+ case AMOVM:
+ case AMOVW:
+ case ASTREX:
+ case ASTREXD:
+ if(p->to.type == D_REG && p->to.reg == 15 && p->from.reg == 13) { // MOVW.W x(R13), PC
+ if(out != nil)
+ asmout(ctxt, p, o, out);
+ if(size == 4) {
+ if(out != nil) {
+ // Note: 5c and 5g reg.c know that DIV/MOD smashes R12
+ // so that this return instruction expansion is valid.
+ out[0] = out[0] & ~0x3000; // change PC to R12
+ out[1] = ((p->scond&C_SCOND)<<28) | 0x03ccc13f; // BIC $0xc000000f, R12
+ out[2] = ((p->scond&C_SCOND)<<28) | 0x012fff1c; // BX R12
+ }
+ size += 8;
+ if(((p->pc+size) & 15) == 4)
+ p->pc += 4;
+ break;
+ } else {
+ // if the instruction used more than 4 bytes, then it must have used a very large
+ // offset to update R13, so we need to additionally mask R13.
+ if(out != nil) {
+ out[size/4-1] &= ~0x3000; // change PC to R12
+ out[size/4] = ((p->scond&C_SCOND)<<28) | 0x03cdd103; // BIC $0xc0000000, R13
+ out[size/4+1] = ((p->scond&C_SCOND)<<28) | 0x03ccc13f; // BIC $0xc000000f, R12
+ out[size/4+2] = ((p->scond&C_SCOND)<<28) | 0x012fff1c; // BX R12
+ }
+ // p->pc+size is only ok at 4 or 12 mod 16.
+ if((p->pc+size)%8 == 0)
+ p->pc += 4;
+ size += 12;
+ break;
+ }
+ }
+
+ if(p->to.type == D_REG && p->to.reg == 15)
+ ctxt->diag("unsupported instruction (move to another register and use indirect jump instead): %P", p);
+
+ if(p->to.type == D_OREG && p->to.reg == 13 && (p->scond & C_WBIT) && size > 4) {
+ // function prolog with very large frame size: MOVW.W R14,-100004(R13)
+ // split it into two instructions:
+ // ADD $-100004, R13
+ // MOVW R14, 0(R13)
+ q = ctxt->arch->prg();
+ p->scond &= ~C_WBIT;
+ *q = *p;
+ a = &p->to;
+ if(p->to.type == D_OREG)
+ a2 = &q->to;
+ else
+ a2 = &q->from;
+ nocache(q);
+ nocache(p);
+ // insert q after p
+ q->link = p->link;
+ p->link = q;
+ q->pcond = nil;
+ // make p into ADD $X, R13
+ p->as = AADD;
+ p->from = *a;
+ p->from.reg = NREG;
+ p->from.type = D_CONST;
+ p->to = zprg.to;
+ p->to.type = D_REG;
+ p->to.reg = 13;
+ // make q into p but load/store from 0(R13)
+ q->spadj = 0;
+ *a2 = zprg.from;
+ a2->type = D_OREG;
+ a2->reg = 13;
+ a2->sym = nil;
+ a2->offset = 0;
+ size = oplook(ctxt, p)->size;
+ break;
+ }
+
+ if((p->to.type == D_OREG && p->to.reg != 13 && p->to.reg != 9) || // MOVW Rx, X(Ry), y != 13 && y != 9
+ (p->from.type == D_OREG && p->from.reg != 13 && p->from.reg != 9)) { // MOVW X(Rx), Ry, x != 13 && x != 9
+ if(p->to.type == D_OREG)
+ a = &p->to;
+ else
+ a = &p->from;
+ reg = a->reg;
+ if(size == 4) {
+ // if addr.reg == NREG, then it is probably load from x(FP) with small x, no need to modify.
+ if(reg == NREG) {
+ if(out != nil)
+ asmout(ctxt, p, o, out);
+ } else {
+ if(out != nil)
+ out[0] = ((p->scond&C_SCOND)<<28) | 0x03c00103 | (reg << 16) | (reg << 12); // BIC $0xc0000000, Rx
+ if((p->pc&15) == 12)
+ p->pc += 4;
+ size += 4;
+ if(out != nil)
+ asmout(ctxt, p, o, &out[1]);
+ }
+ break;
+ } else {
+ // if a load/store instruction takes more than 1 word to implement, then
+ // we need to seperate the instruction into two:
+ // 1. explicitly load the address into R11.
+ // 2. load/store from R11.
+ // This won't handle .W/.P, so we should reject such code.
+ if(p->scond & (C_PBIT|C_WBIT))
+ ctxt->diag("unsupported instruction (.P/.W): %P", p);
+ q = ctxt->arch->prg();
+ *q = *p;
+ if(p->to.type == D_OREG)
+ a2 = &q->to;
+ else
+ a2 = &q->from;
+ nocache(q);
+ nocache(p);
+ // insert q after p
+ q->link = p->link;
+ p->link = q;
+ q->pcond = nil;
+ // make p into MOVW $X(R), R11
+ p->as = AMOVW;
+ p->from = *a;
+ p->from.type = D_CONST;
+ p->to = zprg.to;
+ p->to.type = D_REG;
+ p->to.reg = 11;
+ // make q into p but load/store from 0(R11)
+ *a2 = zprg.from;
+ a2->type = D_OREG;
+ a2->reg = 11;
+ a2->sym = nil;
+ a2->offset = 0;
+ size = oplook(ctxt, p)->size;
+ break;
+ }
+ } else if(out != nil)
+ asmout(ctxt, p, o, out);
+ break;
+ }
+
+ // destination register specific
+ if(p->to.type == D_REG) {
+ switch(p->to.reg) {
+ case 9:
+ ctxt->diag("invalid instruction, cannot write to R9: %P", p);
+ break;
+ case 13:
+ if(out != nil)
+ out[size/4] = 0xe3cdd103; // BIC $0xc0000000, R13
+ if(((p->pc+size) & 15) == 0)
+ p->pc += 4;
+ size += 4;
+ break;
+ }
+ }
+ return size;
+}
+
void
span5(Link *ctxt, LSym *cursym)
{
Prog *p, *op;
Optab *o;
- int m, bflag, i, v;
- int32 c, out[6];
+ int m, bflag, i, v, times;
+ int32 c, opc, out[6+3];
uchar *bp;
p = cursym->text;
@@ -472,21 +655,39 @@ span5(Link *ctxt, LSym *cursym)
ctxt->cursym = cursym;
ctxt->autosize = p->to.offset + 4;
- c = 0;
+ c = 0;
- for(op = p, p = p->link; p != nil; op = p, p = p->link) {
+ for(op = p, p = p->link; p != nil || ctxt->blitrl != nil; op = p, p = p->link) {
+ if(p == nil) {
+ if(checkpool(ctxt, op, 0)) {
+ p = op;
+ continue;
+ }
+ // can't happen: blitrl is not nil, but checkpool didn't flushpool
+ ctxt->diag("internal inconsistency");
+ break;
+ }
ctxt->curp = p;
p->pc = c;
o = oplook(ctxt, p);
- m = o->size;
+ if(ctxt->headtype != Hnacl) {
+ m = o->size;
+ } else {
+ m = asmoutnacl(ctxt, c, p, o, nil);
+ c = p->pc; // asmoutnacl might change pc for alignment
+ o = oplook(ctxt, p); // asmoutnacl might change p in rare cases
+ }
+ if(m % 4 != 0 || p->pc % 4 != 0) {
+ ctxt->diag("!pc invalid: %P size=%d", p, m);
+ }
// must check literal pool here in case p generates many instructions
if(ctxt->blitrl){
if(checkpool(ctxt, op, p->as == ACASE ? casesz(ctxt, p) : m)) {
- p->pc = scan(ctxt, op, p, c);
- c = p->pc;
+ p = op;
+ continue;
}
}
- if(m == 0 && (p->as != AFUNCDATA && p->as != APCDATA)) {
+ if(m == 0 && (p->as != AFUNCDATA && p->as != APCDATA && p->as != ADATABUNDLEEND && p->as != ANOP)) {
ctxt->diag("zero-width instruction\n%P", p);
continue;
}
@@ -506,10 +707,6 @@ span5(Link *ctxt, LSym *cursym)
flushpool(ctxt, p, 0, 0);
c += m;
}
- if(ctxt->blitrl){
- if(checkpool(ctxt, op, 0))
- c = scan(ctxt, op, nil, c);
- }
cursym->size = c;
/*
@@ -518,15 +715,19 @@ span5(Link *ctxt, LSym *cursym)
* generate extra passes putting branches
* around jmps to fix. this is rare.
*/
+ times = 0;
do {
if(ctxt->debugvlog)
Bprint(ctxt->bso, "%5.2f span1\n", cputime());
bflag = 0;
c = 0;
+ times++;
+ cursym->text->pc = 0; // force re-layout the code.
for(p = cursym->text; p != nil; p = p->link) {
ctxt->curp = p;
- p->pc = c;
o = oplook(ctxt,p);
+ if(c > p->pc)
+ p->pc = c;
/* very large branches
if(o->type == 6 && p->pcond) {
otxt = p->pcond->pc - c;
@@ -550,8 +751,22 @@ span5(Link *ctxt, LSym *cursym)
}
}
*/
- m = o->size;
- if(m == 0 && (p->as != AFUNCDATA && p->as != APCDATA)) {
+ opc = p->pc;
+ if(ctxt->headtype != Hnacl)
+ m = o->size;
+ else
+ m = asmoutnacl(ctxt, c, p, o, nil);
+ if(p->pc != opc) {
+ bflag = 1;
+ //print("%P pc changed %d to %d in iter. %d\n", p, opc, (int32)p->pc, times);
+ }
+ c = p->pc + m;
+ if(m % 4 != 0 || p->pc % 4 != 0) {
+ ctxt->diag("pc invalid: %P size=%d", p, m);
+ }
+ if(m/4 > nelem(out))
+ ctxt->diag("instruction size too large: %d > %d", m/4, nelem(out));
+ if(m == 0 && (p->as != AFUNCDATA && p->as != APCDATA && p->as != ADATABUNDLEEND && p->as != ANOP)) {
if(p->as == ATEXT) {
ctxt->autosize = p->to.offset + 4;
continue;
@@ -559,10 +774,12 @@ span5(Link *ctxt, LSym *cursym)
ctxt->diag("zero-width instruction\n%P", p);
continue;
}
- c += m;
}
cursym->size = c;
} while(bflag);
+ if(c % 4 != 0) {
+ ctxt->diag("sym->size=%d, invalid", c);
+ }
/*
* lay out the code. all the pc-relative code references,
@@ -572,26 +789,49 @@ span5(Link *ctxt, LSym *cursym)
* code references to be relocated too, and then
* perhaps we'd be able to parallelize the span loop above.
*/
- if(ctxt->gmsym == nil)
- ctxt->gmsym = linklookup(ctxt, "runtime.tlsgm", 0);
+ if(ctxt->tlsg == nil)
+ ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0);
p = cursym->text;
ctxt->autosize = p->to.offset + 4;
symgrow(ctxt, cursym, cursym->size);
bp = cursym->p;
+ c = p->pc; // even p->link might need extra padding
for(p = p->link; p != nil; p = p->link) {
ctxt->pc = p->pc;
ctxt->curp = p;
o = oplook(ctxt, p);
- asmout(ctxt, p, o, out);
- for(i=0; i<o->size/4; i++) {
+ opc = p->pc;
+ if(ctxt->headtype != Hnacl) {
+ asmout(ctxt, p, o, out);
+ m = o->size;
+ } else {
+ m = asmoutnacl(ctxt, c, p, o, out);
+ if(opc != p->pc)
+ ctxt->diag("asmoutnacl broken: pc changed (%d->%d) in last stage: %P", opc, (int32)p->pc, p);
+ }
+ if(m % 4 != 0 || p->pc % 4 != 0) {
+ ctxt->diag("final stage: pc invalid: %P size=%d", p, m);
+ }
+ if(c > p->pc)
+ ctxt->diag("PC padding invalid: want %#lld, has %#d: %P", p->pc, c, p);
+ while(c != p->pc) {
+ // emit 0xe1a00000 (MOVW R0, R0)
+ *bp++ = 0x00;
+ *bp++ = 0x00;
+ *bp++ = 0xa0;
+ *bp++ = 0xe1;
+ c += 4;
+ }
+ for(i=0; i<m/4; i++) {
v = out[i];
*bp++ = v;
*bp++ = v>>8;
*bp++ = v>>16;
*bp++ = v>>24;
}
+ c += m;
}
}
@@ -604,7 +844,7 @@ span5(Link *ctxt, LSym *cursym)
static int
checkpool(Link *ctxt, Prog *p, int sz)
{
- if(pool.size >= 0xffc || immaddr((p->pc+sz+4)+4+pool.size - pool.start+8) == 0)
+ if(pool.size >= 0xff0 || immaddr((p->pc+sz+4)+4+(12+pool.size) - (pool.start+8)) == 0)
return flushpool(ctxt, p, 1, 0);
else if(p->link == nil)
return flushpool(ctxt, p, 2, 0);
@@ -627,8 +867,15 @@ flushpool(Link *ctxt, Prog *p, int skip, int force)
q->lineno = p->lineno;
ctxt->blitrl = q;
}
- else if(!force && (p->pc+pool.size-pool.start < 2048))
+ else if(!force && (p->pc+(12+pool.size)-pool.start < 2048)) // 12 take into account the maximum nacl literal pool alignment padding size
return 0;
+ if(ctxt->headtype == Hnacl && pool.size % 16 != 0) {
+ // if pool is not multiple of 16 bytes, add an alignment marker
+ q = ctxt->arch->prg();
+ q->as = ADATABUNDLEEND;
+ ctxt->elitrl->link = q;
+ ctxt->elitrl = q;
+ }
ctxt->elitrl->link = p->link;
p->link = ctxt->blitrl;
// BUG(minux): how to correctly handle line number for constant pool entries?
@@ -661,7 +908,11 @@ addpool(Link *ctxt, Prog *p, Addr *a)
switch(c) {
default:
- t.to = *a;
+ t.to.offset = a->offset;
+ t.to.sym = a->sym;
+ t.to.type = a->type;
+ t.to.name = a->name;
+
if(ctxt->flag_shared && t.to.sym != nil)
t.pcrel = p;
break;
@@ -689,6 +940,22 @@ addpool(Link *ctxt, Prog *p, Addr *a)
}
}
+ if(ctxt->headtype == Hnacl && pool.size%16 == 0) {
+ // start a new data bundle
+ q = ctxt->arch->prg();
+ *q = zprg;
+ q->as = ADATABUNDLE;
+ q->pc = pool.size;
+ pool.size += 4;
+ if(ctxt->blitrl == nil) {
+ ctxt->blitrl = q;
+ pool.start = p->pc;
+ } else {
+ ctxt->elitrl->link = q;
+ }
+ ctxt->elitrl = q;
+ }
+
q = ctxt->arch->prg();
*q = t;
q->pc = pool.size;
@@ -758,6 +1025,8 @@ immhalf(int32 v)
return 0;
}
+static int aconsize(Link *ctxt);
+
static int
aclass(Link *ctxt, Addr *a)
{
@@ -792,7 +1061,6 @@ aclass(Link *ctxt, Addr *a)
case D_STATIC:
if(a->sym == 0 || a->sym->name == 0) {
print("null sym external\n");
- print("%D\n", a);
return C_GOK;
}
ctxt->instoffset = 0; // s.b. unused but just in case
@@ -869,7 +1137,7 @@ aclass(Link *ctxt, Addr *a)
case D_NONE:
ctxt->instoffset = a->offset;
if(a->reg != NREG)
- goto aconsize;
+ return aconsize(ctxt);
t = immrot(ctxt->instoffset);
if(t)
@@ -889,15 +1157,11 @@ aclass(Link *ctxt, Addr *a)
case D_AUTO:
ctxt->instoffset = ctxt->autosize + a->offset;
- goto aconsize;
+ return aconsize(ctxt);
case D_PARAM:
ctxt->instoffset = ctxt->autosize + a->offset + 4L;
- aconsize:
- t = immrot(ctxt->instoffset);
- if(t)
- return C_RACON;
- return C_LACON;
+ return aconsize(ctxt);
}
return C_GOK;
@@ -907,6 +1171,17 @@ aclass(Link *ctxt, Addr *a)
return C_GOK;
}
+static int
+aconsize(Link *ctxt)
+{
+ int t;
+
+ t = immrot(ctxt->instoffset);
+ if(t)
+ return C_RACON;
+ return C_LACON;
+}
+
static void
prasm(Prog *p)
{
@@ -917,7 +1192,7 @@ static Optab*
oplook(Link *ctxt, Prog *p)
{
int a1, a2, a3, r;
- char *c1, *c3;
+ uchar *c1, *c3;
Optab *o, *e;
a1 = p->optab;
@@ -941,15 +1216,10 @@ oplook(Link *ctxt, Prog *p)
r = p->as;
o = oprange[r].start;
if(o == 0) {
- a1 = opcross[repop[r]][a1][a2][a3];
- if(a1) {
- p->optab = a1+1;
- return optab+a1;
- }
o = oprange[r].stop; /* just generate an error */
}
if(0 /*debug['O']*/) {
- print("oplook %A %d %d %d\n",
+ print("oplook %A %^ %^ %^\n",
(int)p->as, a1, a2, a3);
print(" %d %d\n", p->from.type, p->to.type);
}
@@ -963,7 +1233,7 @@ oplook(Link *ctxt, Prog *p)
p->optab = (o-optab)+1;
return o;
}
- ctxt->diag("illegal combination %P; %d %d %d, %d %d",
+ ctxt->diag("illegal combination %P; %^ %^ %^, %d %d",
p, a1, a2, a3, p->from.type, p->to.type);
ctxt->diag("from %d %d to %d %d\n", p->from.type, p->from.name, p->to.type, p->to.name);
prasm(p);
@@ -1210,11 +1480,16 @@ buildop(Link *ctxt)
case ACLZ:
case AFUNCDATA:
case APCDATA:
+ case ANOP:
+ case ADATABUNDLE:
+ case ADATABUNDLEEND:
break;
}
}
}
+static int32 mov(Link*, Prog*);
+
static void
asmout(Link *ctxt, Prog *p, Optab *o, int32 *out)
{
@@ -1272,19 +1547,7 @@ if(0 /*debug['G']*/) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->na
break;
case 3: /* add R<<[IR],[R],R */
- mov:
- aclass(ctxt, &p->from);
- o1 = oprrr(ctxt, p->as, p->scond);
- o1 |= p->from.offset;
- rt = p->to.reg;
- r = p->reg;
- if(p->to.type == D_NONE)
- rt = 0;
- if(p->as == AMOVW || p->as == AMVN)
- r = 0;
- else if(r == NREG)
- r = rt;
- o1 |= (r<<16) | (rt<<12);
+ o1 = mov(ctxt, p);
break;
case 4: /* add $I,[R],R */
@@ -1377,11 +1640,11 @@ if(0 /*debug['G']*/) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->na
rel->sym = p->to.sym;
rel->add = p->to.offset;
- // runtime.tlsgm (aka gmsym) is special.
+ // 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(rel->sym == ctxt->gmsym) {
+ if(rel->sym == ctxt->tlsg) {
rel->type = R_TLS;
if(ctxt->flag_shared)
rel->add += ctxt->pc - p->pcrel->pc - 8 - rel->siz;
@@ -1557,19 +1820,23 @@ if(0 /*debug['G']*/) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->na
o1 |= p->from.reg << 0;
break;
- case 38: /* movm $con,oreg -> stm */
- o1 = (0x4 << 25);
- o1 |= p->from.offset & 0xffff;
- o1 |= p->to.reg << 16;
- aclass(ctxt, &p->to);
- goto movm;
-
- case 39: /* movm oreg,$con -> ldm */
- o1 = (0x4 << 25) | (1 << 20);
- o1 |= p->to.offset & 0xffff;
- o1 |= p->from.reg << 16;
- aclass(ctxt, &p->from);
- movm:
+ case 38:
+ case 39:
+ switch(o->type) {
+ case 38: /* movm $con,oreg -> stm */
+ o1 = (0x4 << 25);
+ o1 |= p->from.offset & 0xffff;
+ o1 |= p->to.reg << 16;
+ aclass(ctxt, &p->to);
+ break;
+
+ case 39: /* movm oreg,$con -> ldm */
+ o1 = (0x4 << 25) | (1 << 20);
+ o1 |= p->to.offset & 0xffff;
+ o1 |= p->from.reg << 16;
+ aclass(ctxt, &p->from);
+ break;
+ }
if(ctxt->instoffset != 0)
ctxt->diag("offset must be zero in MOVM; %P", p);
o1 |= (p->scond & C_SCOND) << 28;
@@ -1677,7 +1944,8 @@ if(0 /*debug['G']*/) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->na
if(p->from.reg == NREG) {
if(p->as != AMOVW)
ctxt->diag("byte MOV from shifter operand");
- goto mov;
+ o1 = mov(ctxt, p);
+ break;
}
if(p->from.offset&(1<<4))
ctxt->diag("bad shift in LDR");
@@ -1689,7 +1957,8 @@ if(0 /*debug['G']*/) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->na
case 60: /* movb R(R),R -> ldrsb indexed */
if(p->from.reg == NREG) {
ctxt->diag("byte MOV from shifter operand");
- goto mov;
+ o1 = mov(ctxt, p);
+ break;
}
if(p->from.offset&(~0xf))
ctxt->diag("bad shift in LDRSB");
@@ -2029,6 +2298,12 @@ if(0 /*debug['G']*/) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->na
o1 |= p->reg;
o1 |= p->to.offset << 16;
break;
+ case 100:
+ // DATABUNDLE: BKPT $0x5be0, signify the start of NaCl data bundle;
+ // DATABUNDLEEND: zero width alignment marker
+ if(p->as == ADATABUNDLE)
+ o1 = 0xe125be70;
+ break;
}
out[0] = o1;
@@ -2038,64 +2313,27 @@ if(0 /*debug['G']*/) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->na
out[4] = o5;
out[5] = o6;
return;
+}
-#ifdef NOTDEF
- v = p->pc;
- switch(o->size) {
- default:
- if(debug['a'])
- Bprint(&bso, " %.8ux:\t\t%P\n", v, p);
- break;
- case 4:
- if(debug['a'])
- Bprint(&bso, " %.8ux: %.8ux\t%P\n", v, o1, p);
- lputl(o1);
- break;
- case 8:
- if(debug['a'])
- Bprint(&bso, " %.8ux: %.8ux %.8ux%P\n", v, o1, o2, p);
- lputl(o1);
- lputl(o2);
- break;
- case 12:
- if(debug['a'])
- Bprint(&bso, " %.8ux: %.8ux %.8ux %.8ux%P\n", v, o1, o2, o3, p);
- lputl(o1);
- lputl(o2);
- lputl(o3);
- break;
- case 16:
- if(debug['a'])
- Bprint(&bso, " %.8ux: %.8ux %.8ux %.8ux %.8ux%P\n",
- v, o1, o2, o3, o4, p);
- lputl(o1);
- lputl(o2);
- lputl(o3);
- lputl(o4);
- break;
- case 20:
- if(debug['a'])
- Bprint(&bso, " %.8ux: %.8ux %.8ux %.8ux %.8ux %.8ux%P\n",
- v, o1, o2, o3, o4, o5, p);
- lputl(o1);
- lputl(o2);
- lputl(o3);
- lputl(o4);
- lputl(o5);
- break;
- case 24:
- if(debug['a'])
- Bprint(&bso, " %.8ux: %.8ux %.8ux %.8ux %.8ux %.8ux %.8ux%P\n",
- v, o1, o2, o3, o4, o5, o6, p);
- lputl(o1);
- lputl(o2);
- lputl(o3);
- lputl(o4);
- lputl(o5);
- lputl(o6);
- break;
- }
-#endif
+static int32
+mov(Link *ctxt, Prog *p)
+{
+ int32 o1;
+ int rt, r;
+
+ aclass(ctxt, &p->from);
+ o1 = oprrr(ctxt, p->as, p->scond);
+ o1 |= p->from.offset;
+ rt = p->to.reg;
+ r = p->reg;
+ if(p->to.type == D_NONE)
+ rt = 0;
+ if(p->as == AMOVW || p->as == AMVN)
+ r = 0;
+ else if(r == NREG)
+ r = rt;
+ o1 |= (r<<16) | (rt<<12);
+ return o1;
}
static int32
diff --git a/src/liblink/asm6.c b/src/liblink/asm6.c
index 66afc7a12..428eb9442 100644
--- a/src/liblink/asm6.c
+++ b/src/liblink/asm6.c
@@ -35,7 +35,7 @@
#include <bio.h>
#include <link.h>
#include "../cmd/6l/6.out.h"
-#include "../pkg/runtime/stack.h"
+#include "../runtime/stack.h"
enum
{
@@ -60,8 +60,6 @@ enum
FuncAlign = 16
};
-extern char *anames6[];
-
typedef struct Optab Optab;
typedef struct Movtab Movtab;
@@ -187,7 +185,7 @@ enum
Maxand = 10, /* in -a output width of the byte codes */
};
-static char ycover[Ymax*Ymax];
+static uchar ycover[Ymax*Ymax];
static int reg[D_NONE];
static int regrex[D_NONE+1];
static void asmins(Link *ctxt, Prog *p);
@@ -821,722 +819,735 @@ static uchar yaes2[] =
* encoded addressing mode for the Yml arg), and then a single immediate byte.
* Zilo_m is the same but a long (32-bit) immediate.
*/
-Optab optab[] =
+static Optab optab[] =
/* as, ytab, andproto, opcode */
{
{ AXXX },
- { AAAA, ynone, P32, 0x37 },
- { AAAD, ynone, P32, 0xd5,0x0a },
- { AAAM, ynone, P32, 0xd4,0x0a },
- { AAAS, ynone, P32, 0x3f },
- { AADCB, yxorb, Pb, 0x14,0x80,(02),0x10,0x10 },
- { AADCL, yxorl, Px, 0x83,(02),0x15,0x81,(02),0x11,0x13 },
- { AADCQ, yxorl, Pw, 0x83,(02),0x15,0x81,(02),0x11,0x13 },
- { AADCW, yxorl, Pe, 0x83,(02),0x15,0x81,(02),0x11,0x13 },
- { AADDB, yxorb, Pb, 0x04,0x80,(00),0x00,0x02 },
- { AADDL, yaddl, Px, 0x83,(00),0x05,0x81,(00),0x01,0x03 },
- { AADDPD, yxm, Pq, 0x58 },
- { AADDPS, yxm, Pm, 0x58 },
- { AADDQ, yaddl, Pw, 0x83,(00),0x05,0x81,(00),0x01,0x03 },
- { AADDSD, yxm, Pf2, 0x58 },
- { AADDSS, yxm, Pf3, 0x58 },
- { AADDW, yaddl, Pe, 0x83,(00),0x05,0x81,(00),0x01,0x03 },
+ { AAAA, ynone, P32, {0x37} },
+ { AAAD, ynone, P32, {0xd5,0x0a} },
+ { AAAM, ynone, P32, {0xd4,0x0a} },
+ { AAAS, ynone, P32, {0x3f} },
+ { AADCB, yxorb, Pb, {0x14,0x80,(02),0x10,0x10} },
+ { AADCL, yxorl, Px, {0x83,(02),0x15,0x81,(02),0x11,0x13} },
+ { AADCQ, yxorl, Pw, {0x83,(02),0x15,0x81,(02),0x11,0x13} },
+ { AADCW, yxorl, Pe, {0x83,(02),0x15,0x81,(02),0x11,0x13} },
+ { AADDB, yxorb, Pb, {0x04,0x80,(00),0x00,0x02} },
+ { AADDL, yaddl, Px, {0x83,(00),0x05,0x81,(00),0x01,0x03} },
+ { AADDPD, yxm, Pq, {0x58} },
+ { AADDPS, yxm, Pm, {0x58} },
+ { AADDQ, yaddl, Pw, {0x83,(00),0x05,0x81,(00),0x01,0x03} },
+ { AADDSD, yxm, Pf2, {0x58} },
+ { AADDSS, yxm, Pf3, {0x58} },
+ { AADDW, yaddl, Pe, {0x83,(00),0x05,0x81,(00),0x01,0x03} },
{ AADJSP },
- { AANDB, yxorb, Pb, 0x24,0x80,(04),0x20,0x22 },
- { AANDL, yxorl, Px, 0x83,(04),0x25,0x81,(04),0x21,0x23 },
- { AANDNPD, yxm, Pq, 0x55 },
- { AANDNPS, yxm, Pm, 0x55 },
- { AANDPD, yxm, Pq, 0x54 },
- { AANDPS, yxm, Pq, 0x54 },
- { AANDQ, yxorl, Pw, 0x83,(04),0x25,0x81,(04),0x21,0x23 },
- { AANDW, yxorl, Pe, 0x83,(04),0x25,0x81,(04),0x21,0x23 },
- { AARPL, yrl_ml, P32, 0x63 },
- { ABOUNDL, yrl_m, P32, 0x62 },
- { ABOUNDW, yrl_m, Pe, 0x62 },
- { ABSFL, yml_rl, Pm, 0xbc },
- { ABSFQ, yml_rl, Pw, 0x0f,0xbc },
- { ABSFW, yml_rl, Pq, 0xbc },
- { ABSRL, yml_rl, Pm, 0xbd },
- { ABSRQ, yml_rl, Pw, 0x0f,0xbd },
- { ABSRW, yml_rl, Pq, 0xbd },
- { ABSWAPL, ybswap, Px, 0x0f,0xc8 },
- { ABSWAPQ, ybswap, Pw, 0x0f,0xc8 },
- { ABTCL, ybtl, Pm, 0xba,(07),0xbb },
- { ABTCQ, ybtl, Pw, 0x0f,0xba,(07),0x0f,0xbb },
- { ABTCW, ybtl, Pq, 0xba,(07),0xbb },
- { ABTL, ybtl, Pm, 0xba,(04),0xa3 },
- { ABTQ, ybtl, Pw, 0x0f,0xba,(04),0x0f,0xa3},
- { ABTRL, ybtl, Pm, 0xba,(06),0xb3 },
- { ABTRQ, ybtl, Pw, 0x0f,0xba,(06),0x0f,0xb3 },
- { ABTRW, ybtl, Pq, 0xba,(06),0xb3 },
- { ABTSL, ybtl, Pm, 0xba,(05),0xab },
- { ABTSQ, ybtl, Pw, 0x0f,0xba,(05),0x0f,0xab },
- { ABTSW, ybtl, Pq, 0xba,(05),0xab },
- { ABTW, ybtl, Pq, 0xba,(04),0xa3 },
- { ABYTE, ybyte, Px, 1 },
- { ACALL, ycall, Px, 0xff,(02),0xe8 },
- { ACDQ, ynone, Px, 0x99 },
- { ACLC, ynone, Px, 0xf8 },
- { ACLD, ynone, Px, 0xfc },
- { ACLI, ynone, Px, 0xfa },
- { ACLTS, ynone, Pm, 0x06 },
- { ACMC, ynone, Px, 0xf5 },
- { ACMOVLCC, yml_rl, Pm, 0x43 },
- { ACMOVLCS, yml_rl, Pm, 0x42 },
- { ACMOVLEQ, yml_rl, Pm, 0x44 },
- { ACMOVLGE, yml_rl, Pm, 0x4d },
- { ACMOVLGT, yml_rl, Pm, 0x4f },
- { ACMOVLHI, yml_rl, Pm, 0x47 },
- { ACMOVLLE, yml_rl, Pm, 0x4e },
- { ACMOVLLS, yml_rl, Pm, 0x46 },
- { ACMOVLLT, yml_rl, Pm, 0x4c },
- { ACMOVLMI, yml_rl, Pm, 0x48 },
- { ACMOVLNE, yml_rl, Pm, 0x45 },
- { ACMOVLOC, yml_rl, Pm, 0x41 },
- { ACMOVLOS, yml_rl, Pm, 0x40 },
- { ACMOVLPC, yml_rl, Pm, 0x4b },
- { ACMOVLPL, yml_rl, Pm, 0x49 },
- { ACMOVLPS, yml_rl, Pm, 0x4a },
- { ACMOVQCC, yml_rl, Pw, 0x0f,0x43 },
- { ACMOVQCS, yml_rl, Pw, 0x0f,0x42 },
- { ACMOVQEQ, yml_rl, Pw, 0x0f,0x44 },
- { ACMOVQGE, yml_rl, Pw, 0x0f,0x4d },
- { ACMOVQGT, yml_rl, Pw, 0x0f,0x4f },
- { ACMOVQHI, yml_rl, Pw, 0x0f,0x47 },
- { ACMOVQLE, yml_rl, Pw, 0x0f,0x4e },
- { ACMOVQLS, yml_rl, Pw, 0x0f,0x46 },
- { ACMOVQLT, yml_rl, Pw, 0x0f,0x4c },
- { ACMOVQMI, yml_rl, Pw, 0x0f,0x48 },
- { ACMOVQNE, yml_rl, Pw, 0x0f,0x45 },
- { ACMOVQOC, yml_rl, Pw, 0x0f,0x41 },
- { ACMOVQOS, yml_rl, Pw, 0x0f,0x40 },
- { ACMOVQPC, yml_rl, Pw, 0x0f,0x4b },
- { ACMOVQPL, yml_rl, Pw, 0x0f,0x49 },
- { ACMOVQPS, yml_rl, Pw, 0x0f,0x4a },
- { ACMOVWCC, yml_rl, Pq, 0x43 },
- { ACMOVWCS, yml_rl, Pq, 0x42 },
- { ACMOVWEQ, yml_rl, Pq, 0x44 },
- { ACMOVWGE, yml_rl, Pq, 0x4d },
- { ACMOVWGT, yml_rl, Pq, 0x4f },
- { ACMOVWHI, yml_rl, Pq, 0x47 },
- { ACMOVWLE, yml_rl, Pq, 0x4e },
- { ACMOVWLS, yml_rl, Pq, 0x46 },
- { ACMOVWLT, yml_rl, Pq, 0x4c },
- { ACMOVWMI, yml_rl, Pq, 0x48 },
- { ACMOVWNE, yml_rl, Pq, 0x45 },
- { ACMOVWOC, yml_rl, Pq, 0x41 },
- { ACMOVWOS, yml_rl, Pq, 0x40 },
- { ACMOVWPC, yml_rl, Pq, 0x4b },
- { ACMOVWPL, yml_rl, Pq, 0x49 },
- { ACMOVWPS, yml_rl, Pq, 0x4a },
- { ACMPB, ycmpb, Pb, 0x3c,0x80,(07),0x38,0x3a },
- { ACMPL, ycmpl, Px, 0x83,(07),0x3d,0x81,(07),0x39,0x3b },
- { ACMPPD, yxcmpi, Px, Pe,0xc2 },
- { ACMPPS, yxcmpi, Pm, 0xc2,0 },
- { ACMPQ, ycmpl, Pw, 0x83,(07),0x3d,0x81,(07),0x39,0x3b },
- { ACMPSB, ynone, Pb, 0xa6 },
- { ACMPSD, yxcmpi, Px, Pf2,0xc2 },
- { ACMPSL, ynone, Px, 0xa7 },
- { ACMPSQ, ynone, Pw, 0xa7 },
- { ACMPSS, yxcmpi, Px, Pf3,0xc2 },
- { ACMPSW, ynone, Pe, 0xa7 },
- { ACMPW, ycmpl, Pe, 0x83,(07),0x3d,0x81,(07),0x39,0x3b },
- { ACOMISD, yxcmp, Pe, 0x2f },
- { ACOMISS, yxcmp, Pm, 0x2f },
- { ACPUID, ynone, Pm, 0xa2 },
- { ACVTPL2PD, yxcvm2, Px, Pf3,0xe6,Pe,0x2a },
- { ACVTPL2PS, yxcvm2, Pm, 0x5b,0,0x2a,0, },
- { ACVTPD2PL, yxcvm1, Px, Pf2,0xe6,Pe,0x2d },
- { ACVTPD2PS, yxm, Pe, 0x5a },
- { ACVTPS2PL, yxcvm1, Px, Pe,0x5b,Pm,0x2d },
- { ACVTPS2PD, yxm, Pm, 0x5a },
- { API2FW, ymfp, Px, 0x0c },
- { ACVTSD2SL, yxcvfl, Pf2, 0x2d },
- { ACVTSD2SQ, yxcvfq, Pw, Pf2,0x2d },
- { ACVTSD2SS, yxm, Pf2, 0x5a },
- { ACVTSL2SD, yxcvlf, Pf2, 0x2a },
- { ACVTSQ2SD, yxcvqf, Pw, Pf2,0x2a },
- { ACVTSL2SS, yxcvlf, Pf3, 0x2a },
- { ACVTSQ2SS, yxcvqf, Pw, Pf3,0x2a },
- { ACVTSS2SD, yxm, Pf3, 0x5a },
- { ACVTSS2SL, yxcvfl, Pf3, 0x2d },
- { ACVTSS2SQ, yxcvfq, Pw, Pf3,0x2d },
- { ACVTTPD2PL, yxcvm1, Px, Pe,0xe6,Pe,0x2c },
- { ACVTTPS2PL, yxcvm1, Px, Pf3,0x5b,Pm,0x2c },
- { ACVTTSD2SL, yxcvfl, Pf2, 0x2c },
- { ACVTTSD2SQ, yxcvfq, Pw, Pf2,0x2c },
- { ACVTTSS2SL, yxcvfl, Pf3, 0x2c },
- { ACVTTSS2SQ, yxcvfq, Pw, Pf3,0x2c },
- { ACWD, ynone, Pe, 0x99 },
- { ACQO, ynone, Pw, 0x99 },
- { ADAA, ynone, P32, 0x27 },
- { ADAS, ynone, P32, 0x2f },
+ { AANDB, yxorb, Pb, {0x24,0x80,(04),0x20,0x22} },
+ { AANDL, yxorl, Px, {0x83,(04),0x25,0x81,(04),0x21,0x23} },
+ { AANDNPD, yxm, Pq, {0x55} },
+ { AANDNPS, yxm, Pm, {0x55} },
+ { AANDPD, yxm, Pq, {0x54} },
+ { AANDPS, yxm, Pq, {0x54} },
+ { AANDQ, yxorl, Pw, {0x83,(04),0x25,0x81,(04),0x21,0x23} },
+ { AANDW, yxorl, Pe, {0x83,(04),0x25,0x81,(04),0x21,0x23} },
+ { AARPL, yrl_ml, P32, {0x63} },
+ { ABOUNDL, yrl_m, P32, {0x62} },
+ { ABOUNDW, yrl_m, Pe, {0x62} },
+ { ABSFL, yml_rl, Pm, {0xbc} },
+ { ABSFQ, yml_rl, Pw, {0x0f,0xbc} },
+ { ABSFW, yml_rl, Pq, {0xbc} },
+ { ABSRL, yml_rl, Pm, {0xbd} },
+ { ABSRQ, yml_rl, Pw, {0x0f,0xbd} },
+ { ABSRW, yml_rl, Pq, {0xbd} },
+ { ABSWAPL, ybswap, Px, {0x0f,0xc8} },
+ { ABSWAPQ, ybswap, Pw, {0x0f,0xc8} },
+ { ABTCL, ybtl, Pm, {0xba,(07),0xbb} },
+ { ABTCQ, ybtl, Pw, {0x0f,0xba,(07),0x0f,0xbb} },
+ { ABTCW, ybtl, Pq, {0xba,(07),0xbb} },
+ { ABTL, ybtl, Pm, {0xba,(04),0xa3} },
+ { ABTQ, ybtl, Pw, {0x0f,0xba,(04),0x0f,0xa3}},
+ { ABTRL, ybtl, Pm, {0xba,(06),0xb3} },
+ { ABTRQ, ybtl, Pw, {0x0f,0xba,(06),0x0f,0xb3} },
+ { ABTRW, ybtl, Pq, {0xba,(06),0xb3} },
+ { ABTSL, ybtl, Pm, {0xba,(05),0xab } },
+ { ABTSQ, ybtl, Pw, {0x0f,0xba,(05),0x0f,0xab} },
+ { ABTSW, ybtl, Pq, {0xba,(05),0xab } },
+ { ABTW, ybtl, Pq, {0xba,(04),0xa3} },
+ { ABYTE, ybyte, Px, {1} },
+ { ACALL, ycall, Px, {0xff,(02),0xe8} },
+ { ACDQ, ynone, Px, {0x99} },
+ { ACLC, ynone, Px, {0xf8} },
+ { ACLD, ynone, Px, {0xfc} },
+ { ACLI, ynone, Px, {0xfa} },
+ { ACLTS, ynone, Pm, {0x06} },
+ { ACMC, ynone, Px, {0xf5} },
+ { ACMOVLCC, yml_rl, Pm, {0x43} },
+ { ACMOVLCS, yml_rl, Pm, {0x42} },
+ { ACMOVLEQ, yml_rl, Pm, {0x44} },
+ { ACMOVLGE, yml_rl, Pm, {0x4d} },
+ { ACMOVLGT, yml_rl, Pm, {0x4f} },
+ { ACMOVLHI, yml_rl, Pm, {0x47} },
+ { ACMOVLLE, yml_rl, Pm, {0x4e} },
+ { ACMOVLLS, yml_rl, Pm, {0x46} },
+ { ACMOVLLT, yml_rl, Pm, {0x4c} },
+ { ACMOVLMI, yml_rl, Pm, {0x48} },
+ { ACMOVLNE, yml_rl, Pm, {0x45} },
+ { ACMOVLOC, yml_rl, Pm, {0x41} },
+ { ACMOVLOS, yml_rl, Pm, {0x40} },
+ { ACMOVLPC, yml_rl, Pm, {0x4b} },
+ { ACMOVLPL, yml_rl, Pm, {0x49} },
+ { ACMOVLPS, yml_rl, Pm, {0x4a} },
+ { ACMOVQCC, yml_rl, Pw, {0x0f,0x43} },
+ { ACMOVQCS, yml_rl, Pw, {0x0f,0x42} },
+ { ACMOVQEQ, yml_rl, Pw, {0x0f,0x44} },
+ { ACMOVQGE, yml_rl, Pw, {0x0f,0x4d} },
+ { ACMOVQGT, yml_rl, Pw, {0x0f,0x4f} },
+ { ACMOVQHI, yml_rl, Pw, {0x0f,0x47} },
+ { ACMOVQLE, yml_rl, Pw, {0x0f,0x4e} },
+ { ACMOVQLS, yml_rl, Pw, {0x0f,0x46} },
+ { ACMOVQLT, yml_rl, Pw, {0x0f,0x4c} },
+ { ACMOVQMI, yml_rl, Pw, {0x0f,0x48} },
+ { ACMOVQNE, yml_rl, Pw, {0x0f,0x45} },
+ { ACMOVQOC, yml_rl, Pw, {0x0f,0x41} },
+ { ACMOVQOS, yml_rl, Pw, {0x0f,0x40} },
+ { ACMOVQPC, yml_rl, Pw, {0x0f,0x4b} },
+ { ACMOVQPL, yml_rl, Pw, {0x0f,0x49} },
+ { ACMOVQPS, yml_rl, Pw, {0x0f,0x4a} },
+ { ACMOVWCC, yml_rl, Pq, {0x43} },
+ { ACMOVWCS, yml_rl, Pq, {0x42} },
+ { ACMOVWEQ, yml_rl, Pq, {0x44} },
+ { ACMOVWGE, yml_rl, Pq, {0x4d} },
+ { ACMOVWGT, yml_rl, Pq, {0x4f} },
+ { ACMOVWHI, yml_rl, Pq, {0x47} },
+ { ACMOVWLE, yml_rl, Pq, {0x4e} },
+ { ACMOVWLS, yml_rl, Pq, {0x46} },
+ { ACMOVWLT, yml_rl, Pq, {0x4c} },
+ { ACMOVWMI, yml_rl, Pq, {0x48} },
+ { ACMOVWNE, yml_rl, Pq, {0x45} },
+ { ACMOVWOC, yml_rl, Pq, {0x41} },
+ { ACMOVWOS, yml_rl, Pq, {0x40} },
+ { ACMOVWPC, yml_rl, Pq, {0x4b} },
+ { ACMOVWPL, yml_rl, Pq, {0x49} },
+ { ACMOVWPS, yml_rl, Pq, {0x4a} },
+ { ACMPB, ycmpb, Pb, {0x3c,0x80,(07),0x38,0x3a} },
+ { ACMPL, ycmpl, Px, {0x83,(07),0x3d,0x81,(07),0x39,0x3b} },
+ { ACMPPD, yxcmpi, Px, {Pe,0xc2} },
+ { ACMPPS, yxcmpi, Pm, {0xc2,0} },
+ { ACMPQ, ycmpl, Pw, {0x83,(07),0x3d,0x81,(07),0x39,0x3b} },
+ { ACMPSB, ynone, Pb, {0xa6} },
+ { ACMPSD, yxcmpi, Px, {Pf2,0xc2} },
+ { ACMPSL, ynone, Px, {0xa7} },
+ { ACMPSQ, ynone, Pw, {0xa7} },
+ { ACMPSS, yxcmpi, Px, {Pf3,0xc2} },
+ { ACMPSW, ynone, Pe, {0xa7} },
+ { ACMPW, ycmpl, Pe, {0x83,(07),0x3d,0x81,(07),0x39,0x3b} },
+ { ACOMISD, yxcmp, Pe, {0x2f} },
+ { ACOMISS, yxcmp, Pm, {0x2f} },
+ { ACPUID, ynone, Pm, {0xa2} },
+ { ACVTPL2PD, yxcvm2, Px, {Pf3,0xe6,Pe,0x2a} },
+ { ACVTPL2PS, yxcvm2, Pm, {0x5b,0,0x2a,0,} },
+ { ACVTPD2PL, yxcvm1, Px, {Pf2,0xe6,Pe,0x2d} },
+ { ACVTPD2PS, yxm, Pe, {0x5a} },
+ { ACVTPS2PL, yxcvm1, Px, {Pe,0x5b,Pm,0x2d} },
+ { ACVTPS2PD, yxm, Pm, {0x5a} },
+ { API2FW, ymfp, Px, {0x0c} },
+ { ACVTSD2SL, yxcvfl, Pf2, {0x2d} },
+ { ACVTSD2SQ, yxcvfq, Pw, {Pf2,0x2d} },
+ { ACVTSD2SS, yxm, Pf2, {0x5a} },
+ { ACVTSL2SD, yxcvlf, Pf2, {0x2a} },
+ { ACVTSQ2SD, yxcvqf, Pw, {Pf2,0x2a} },
+ { ACVTSL2SS, yxcvlf, Pf3, {0x2a} },
+ { ACVTSQ2SS, yxcvqf, Pw, {Pf3,0x2a} },
+ { ACVTSS2SD, yxm, Pf3, {0x5a} },
+ { ACVTSS2SL, yxcvfl, Pf3, {0x2d} },
+ { ACVTSS2SQ, yxcvfq, Pw, {Pf3,0x2d} },
+ { ACVTTPD2PL, yxcvm1, Px, {Pe,0xe6,Pe,0x2c} },
+ { ACVTTPS2PL, yxcvm1, Px, {Pf3,0x5b,Pm,0x2c} },
+ { ACVTTSD2SL, yxcvfl, Pf2, {0x2c} },
+ { ACVTTSD2SQ, yxcvfq, Pw, {Pf2,0x2c} },
+ { ACVTTSS2SL, yxcvfl, Pf3, {0x2c} },
+ { ACVTTSS2SQ, yxcvfq, Pw, {Pf3,0x2c} },
+ { ACWD, ynone, Pe, {0x99} },
+ { ACQO, ynone, Pw, {0x99} },
+ { ADAA, ynone, P32, {0x27} },
+ { ADAS, ynone, P32, {0x2f} },
{ ADATA },
- { ADECB, yincb, Pb, 0xfe,(01) },
- { ADECL, yincl, Px, 0xff,(01) },
- { ADECQ, yincl, Pw, 0xff,(01) },
- { ADECW, yincw, Pe, 0xff,(01) },
- { ADIVB, ydivb, Pb, 0xf6,(06) },
- { ADIVL, ydivl, Px, 0xf7,(06) },
- { ADIVPD, yxm, Pe, 0x5e },
- { ADIVPS, yxm, Pm, 0x5e },
- { ADIVQ, ydivl, Pw, 0xf7,(06) },
- { ADIVSD, yxm, Pf2, 0x5e },
- { ADIVSS, yxm, Pf3, 0x5e },
- { ADIVW, ydivl, Pe, 0xf7,(06) },
- { AEMMS, ynone, Pm, 0x77 },
+ { ADECB, yincb, Pb, {0xfe,(01)} },
+ { ADECL, yincl, Px, {0xff,(01)} },
+ { ADECQ, yincl, Pw, {0xff,(01)} },
+ { ADECW, yincw, Pe, {0xff,(01)} },
+ { ADIVB, ydivb, Pb, {0xf6,(06)} },
+ { ADIVL, ydivl, Px, {0xf7,(06)} },
+ { ADIVPD, yxm, Pe, {0x5e} },
+ { ADIVPS, yxm, Pm, {0x5e} },
+ { ADIVQ, ydivl, Pw, {0xf7,(06)} },
+ { ADIVSD, yxm, Pf2, {0x5e} },
+ { ADIVSS, yxm, Pf3, {0x5e} },
+ { ADIVW, ydivl, Pe, {0xf7,(06)} },
+ { AEMMS, ynone, Pm, {0x77} },
{ AENTER }, /* botch */
- { AFXRSTOR, ysvrs, Pm, 0xae,(01),0xae,(01) },
- { AFXSAVE, ysvrs, Pm, 0xae,(00),0xae,(00) },
- { AFXRSTOR64, ysvrs, Pw, 0x0f,0xae,(01),0x0f,0xae,(01) },
- { AFXSAVE64, ysvrs, Pw, 0x0f,0xae,(00),0x0f,0xae,(00) },
+ { AFXRSTOR, ysvrs, Pm, {0xae,(01),0xae,(01)} },
+ { AFXSAVE, ysvrs, Pm, {0xae,(00),0xae,(00)} },
+ { AFXRSTOR64, ysvrs, Pw, {0x0f,0xae,(01),0x0f,0xae,(01)} },
+ { AFXSAVE64, ysvrs, Pw, {0x0f,0xae,(00),0x0f,0xae,(00)} },
{ AGLOBL },
{ AGOK },
{ AHISTORY },
- { AHLT, ynone, Px, 0xf4 },
- { AIDIVB, ydivb, Pb, 0xf6,(07) },
- { AIDIVL, ydivl, Px, 0xf7,(07) },
- { AIDIVQ, ydivl, Pw, 0xf7,(07) },
- { AIDIVW, ydivl, Pe, 0xf7,(07) },
- { AIMULB, ydivb, Pb, 0xf6,(05) },
- { AIMULL, yimul, Px, 0xf7,(05),0x6b,0x69,Pm,0xaf },
- { AIMULQ, yimul, Pw, 0xf7,(05),0x6b,0x69,Pm,0xaf },
- { AIMULW, yimul, Pe, 0xf7,(05),0x6b,0x69,Pm,0xaf },
- { AIMUL3Q, yimul3, Pw, 0x6b,(00) },
- { AINB, yin, Pb, 0xe4,0xec },
- { AINCB, yincb, Pb, 0xfe,(00) },
- { AINCL, yincl, Px, 0xff,(00) },
- { AINCQ, yincl, Pw, 0xff,(00) },
- { AINCW, yincw, Pe, 0xff,(00) },
- { AINL, yin, Px, 0xe5,0xed },
- { AINSB, ynone, Pb, 0x6c },
- { AINSL, ynone, Px, 0x6d },
- { AINSW, ynone, Pe, 0x6d },
- { AINT, yint, Px, 0xcd },
- { AINTO, ynone, P32, 0xce },
- { AINW, yin, Pe, 0xe5,0xed },
- { AIRETL, ynone, Px, 0xcf },
- { AIRETQ, ynone, Pw, 0xcf },
- { AIRETW, ynone, Pe, 0xcf },
- { AJCC, yjcond, Px, 0x73,0x83,(00) },
- { AJCS, yjcond, Px, 0x72,0x82 },
- { AJCXZL, yloop, Px, 0xe3 },
- { AJCXZQ, yloop, Px, 0xe3 },
- { AJEQ, yjcond, Px, 0x74,0x84 },
- { AJGE, yjcond, Px, 0x7d,0x8d },
- { AJGT, yjcond, Px, 0x7f,0x8f },
- { AJHI, yjcond, Px, 0x77,0x87 },
- { AJLE, yjcond, Px, 0x7e,0x8e },
- { AJLS, yjcond, Px, 0x76,0x86 },
- { AJLT, yjcond, Px, 0x7c,0x8c },
- { AJMI, yjcond, Px, 0x78,0x88 },
- { AJMP, yjmp, Px, 0xff,(04),0xeb,0xe9 },
- { AJNE, yjcond, Px, 0x75,0x85 },
- { AJOC, yjcond, Px, 0x71,0x81,(00) },
- { AJOS, yjcond, Px, 0x70,0x80,(00) },
- { AJPC, yjcond, Px, 0x7b,0x8b },
- { AJPL, yjcond, Px, 0x79,0x89 },
- { AJPS, yjcond, Px, 0x7a,0x8a },
- { ALAHF, ynone, Px, 0x9f },
- { ALARL, yml_rl, Pm, 0x02 },
- { ALARW, yml_rl, Pq, 0x02 },
- { ALDMXCSR, ysvrs, Pm, 0xae,(02),0xae,(02) },
- { ALEAL, ym_rl, Px, 0x8d },
- { ALEAQ, ym_rl, Pw, 0x8d },
- { ALEAVEL, ynone, P32, 0xc9 },
- { ALEAVEQ, ynone, Py, 0xc9 },
- { ALEAVEW, ynone, Pe, 0xc9 },
- { ALEAW, ym_rl, Pe, 0x8d },
- { ALOCK, ynone, Px, 0xf0 },
- { ALODSB, ynone, Pb, 0xac },
- { ALODSL, ynone, Px, 0xad },
- { ALODSQ, ynone, Pw, 0xad },
- { ALODSW, ynone, Pe, 0xad },
- { ALONG, ybyte, Px, 4 },
- { ALOOP, yloop, Px, 0xe2 },
- { ALOOPEQ, yloop, Px, 0xe1 },
- { ALOOPNE, yloop, Px, 0xe0 },
- { ALSLL, yml_rl, Pm, 0x03 },
- { ALSLW, yml_rl, Pq, 0x03 },
- { AMASKMOVOU, yxr, Pe, 0xf7 },
- { AMASKMOVQ, ymr, Pm, 0xf7 },
- { AMAXPD, yxm, Pe, 0x5f },
- { AMAXPS, yxm, Pm, 0x5f },
- { AMAXSD, yxm, Pf2, 0x5f },
- { AMAXSS, yxm, Pf3, 0x5f },
- { AMINPD, yxm, Pe, 0x5d },
- { AMINPS, yxm, Pm, 0x5d },
- { AMINSD, yxm, Pf2, 0x5d },
- { AMINSS, yxm, Pf3, 0x5d },
- { AMOVAPD, yxmov, Pe, 0x28,0x29 },
- { AMOVAPS, yxmov, Pm, 0x28,0x29 },
- { AMOVB, ymovb, Pb, 0x88,0x8a,0xb0,0xc6,(00) },
- { AMOVBLSX, ymb_rl, Pm, 0xbe },
- { AMOVBLZX, ymb_rl, Pm, 0xb6 },
- { AMOVBQSX, ymb_rl, Pw, 0x0f,0xbe },
- { AMOVBQZX, ymb_rl, Pw, 0x0f,0xb6 },
- { AMOVBWSX, ymb_rl, Pq, 0xbe },
- { AMOVBWZX, ymb_rl, Pq, 0xb6 },
- { AMOVO, yxmov, Pe, 0x6f,0x7f },
- { AMOVOU, yxmov, Pf3, 0x6f,0x7f },
- { AMOVHLPS, yxr, Pm, 0x12 },
- { AMOVHPD, yxmov, Pe, 0x16,0x17 },
- { AMOVHPS, yxmov, Pm, 0x16,0x17 },
- { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0xb8,0xc7,(00),0x6e,0x7e,Pe,0x6e,Pe,0x7e,0 },
- { AMOVLHPS, yxr, Pm, 0x16 },
- { AMOVLPD, yxmov, Pe, 0x12,0x13 },
- { AMOVLPS, yxmov, Pm, 0x12,0x13 },
- { AMOVLQSX, yml_rl, Pw, 0x63 },
- { AMOVLQZX, yml_rl, Px, 0x8b },
- { AMOVMSKPD, yxrrl, Pq, 0x50 },
- { AMOVMSKPS, yxrrl, Pm, 0x50 },
- { AMOVNTO, yxr_ml, Pe, 0xe7 },
- { AMOVNTPD, yxr_ml, Pe, 0x2b },
- { AMOVNTPS, yxr_ml, Pm, 0x2b },
- { AMOVNTQ, ymr_ml, Pm, 0xe7 },
- { AMOVQ, ymovq, Pw, 0x89, 0x8b, 0x31, 0xc7,(00), 0xb8, 0xc7,(00), 0x6f, 0x7f, 0x6e, 0x7e, Pf2,0xd6, Pf3,0x7e, Pe,0xd6, Pe,0x6e, Pe,0x7e,0 },
- { AMOVQOZX, ymrxr, Pf3, 0xd6,0x7e },
- { AMOVSB, ynone, Pb, 0xa4 },
- { AMOVSD, yxmov, Pf2, 0x10,0x11 },
- { AMOVSL, ynone, Px, 0xa5 },
- { AMOVSQ, ynone, Pw, 0xa5 },
- { AMOVSS, yxmov, Pf3, 0x10,0x11 },
- { AMOVSW, ynone, Pe, 0xa5 },
- { AMOVUPD, yxmov, Pe, 0x10,0x11 },
- { AMOVUPS, yxmov, Pm, 0x10,0x11 },
- { AMOVW, ymovw, Pe, 0x89,0x8b,0x31,0xb8,0xc7,(00),0 },
- { AMOVWLSX, yml_rl, Pm, 0xbf },
- { AMOVWLZX, yml_rl, Pm, 0xb7 },
- { AMOVWQSX, yml_rl, Pw, 0x0f,0xbf },
- { AMOVWQZX, yml_rl, Pw, 0x0f,0xb7 },
- { AMULB, ydivb, Pb, 0xf6,(04) },
- { AMULL, ydivl, Px, 0xf7,(04) },
- { AMULPD, yxm, Pe, 0x59 },
- { AMULPS, yxm, Ym, 0x59 },
- { AMULQ, ydivl, Pw, 0xf7,(04) },
- { AMULSD, yxm, Pf2, 0x59 },
- { AMULSS, yxm, Pf3, 0x59 },
- { AMULW, ydivl, Pe, 0xf7,(04) },
+ { AHLT, ynone, Px, {0xf4} },
+ { AIDIVB, ydivb, Pb, {0xf6,(07)} },
+ { AIDIVL, ydivl, Px, {0xf7,(07)} },
+ { AIDIVQ, ydivl, Pw, {0xf7,(07)} },
+ { AIDIVW, ydivl, Pe, {0xf7,(07)} },
+ { AIMULB, ydivb, Pb, {0xf6,(05)} },
+ { AIMULL, yimul, Px, {0xf7,(05),0x6b,0x69,Pm,0xaf} },
+ { AIMULQ, yimul, Pw, {0xf7,(05),0x6b,0x69,Pm,0xaf} },
+ { AIMULW, yimul, Pe, {0xf7,(05),0x6b,0x69,Pm,0xaf} },
+ { AIMUL3Q, yimul3, Pw, {0x6b,(00)} },
+ { AINB, yin, Pb, {0xe4,0xec} },
+ { AINCB, yincb, Pb, {0xfe,(00)} },
+ { AINCL, yincl, Px, {0xff,(00)} },
+ { AINCQ, yincl, Pw, {0xff,(00)} },
+ { AINCW, yincw, Pe, {0xff,(00)} },
+ { AINL, yin, Px, {0xe5,0xed} },
+ { AINSB, ynone, Pb, {0x6c} },
+ { AINSL, ynone, Px, {0x6d} },
+ { AINSW, ynone, Pe, {0x6d} },
+ { AINT, yint, Px, {0xcd} },
+ { AINTO, ynone, P32, {0xce} },
+ { AINW, yin, Pe, {0xe5,0xed} },
+ { AIRETL, ynone, Px, {0xcf} },
+ { AIRETQ, ynone, Pw, {0xcf} },
+ { AIRETW, ynone, Pe, {0xcf} },
+ { AJCC, yjcond, Px, {0x73,0x83,(00)} },
+ { AJCS, yjcond, Px, {0x72,0x82} },
+ { AJCXZL, yloop, Px, {0xe3} },
+ { AJCXZQ, yloop, Px, {0xe3} },
+ { AJEQ, yjcond, Px, {0x74,0x84} },
+ { AJGE, yjcond, Px, {0x7d,0x8d} },
+ { AJGT, yjcond, Px, {0x7f,0x8f} },
+ { AJHI, yjcond, Px, {0x77,0x87} },
+ { AJLE, yjcond, Px, {0x7e,0x8e} },
+ { AJLS, yjcond, Px, {0x76,0x86} },
+ { AJLT, yjcond, Px, {0x7c,0x8c} },
+ { AJMI, yjcond, Px, {0x78,0x88} },
+ { AJMP, yjmp, Px, {0xff,(04),0xeb,0xe9} },
+ { AJNE, yjcond, Px, {0x75,0x85} },
+ { AJOC, yjcond, Px, {0x71,0x81,(00)} },
+ { AJOS, yjcond, Px, {0x70,0x80,(00)} },
+ { AJPC, yjcond, Px, {0x7b,0x8b} },
+ { AJPL, yjcond, Px, {0x79,0x89} },
+ { AJPS, yjcond, Px, {0x7a,0x8a} },
+ { ALAHF, ynone, Px, {0x9f} },
+ { ALARL, yml_rl, Pm, {0x02} },
+ { ALARW, yml_rl, Pq, {0x02} },
+ { ALDMXCSR, ysvrs, Pm, {0xae,(02),0xae,(02)} },
+ { ALEAL, ym_rl, Px, {0x8d} },
+ { ALEAQ, ym_rl, Pw, {0x8d} },
+ { ALEAVEL, ynone, P32, {0xc9} },
+ { ALEAVEQ, ynone, Py, {0xc9} },
+ { ALEAVEW, ynone, Pe, {0xc9} },
+ { ALEAW, ym_rl, Pe, {0x8d} },
+ { ALOCK, ynone, Px, {0xf0} },
+ { ALODSB, ynone, Pb, {0xac} },
+ { ALODSL, ynone, Px, {0xad} },
+ { ALODSQ, ynone, Pw, {0xad} },
+ { ALODSW, ynone, Pe, {0xad} },
+ { ALONG, ybyte, Px, {4} },
+ { ALOOP, yloop, Px, {0xe2} },
+ { ALOOPEQ, yloop, Px, {0xe1} },
+ { ALOOPNE, yloop, Px, {0xe0} },
+ { ALSLL, yml_rl, Pm, {0x03 } },
+ { ALSLW, yml_rl, Pq, {0x03 } },
+ { AMASKMOVOU, yxr, Pe, {0xf7} },
+ { AMASKMOVQ, ymr, Pm, {0xf7} },
+ { AMAXPD, yxm, Pe, {0x5f} },
+ { AMAXPS, yxm, Pm, {0x5f} },
+ { AMAXSD, yxm, Pf2, {0x5f} },
+ { AMAXSS, yxm, Pf3, {0x5f} },
+ { AMINPD, yxm, Pe, {0x5d} },
+ { AMINPS, yxm, Pm, {0x5d} },
+ { AMINSD, yxm, Pf2, {0x5d} },
+ { AMINSS, yxm, Pf3, {0x5d} },
+ { AMOVAPD, yxmov, Pe, {0x28,0x29} },
+ { AMOVAPS, yxmov, Pm, {0x28,0x29} },
+ { AMOVB, ymovb, Pb, {0x88,0x8a,0xb0,0xc6,(00)} },
+ { AMOVBLSX, ymb_rl, Pm, {0xbe} },
+ { AMOVBLZX, ymb_rl, Pm, {0xb6} },
+ { AMOVBQSX, ymb_rl, Pw, {0x0f,0xbe} },
+ { AMOVBQZX, ymb_rl, Pm, {0xb6} },
+ { AMOVBWSX, ymb_rl, Pq, {0xbe} },
+ { AMOVBWZX, ymb_rl, Pq, {0xb6} },
+ { AMOVO, yxmov, Pe, {0x6f,0x7f} },
+ { AMOVOU, yxmov, Pf3, {0x6f,0x7f} },
+ { AMOVHLPS, yxr, Pm, {0x12} },
+ { AMOVHPD, yxmov, Pe, {0x16,0x17} },
+ { AMOVHPS, yxmov, Pm, {0x16,0x17} },
+ { AMOVL, ymovl, Px, {0x89,0x8b,0x31,0xb8,0xc7,(00),0x6e,0x7e,Pe,0x6e,Pe,0x7e,0} },
+ { AMOVLHPS, yxr, Pm, {0x16} },
+ { AMOVLPD, yxmov, Pe, {0x12,0x13} },
+ { AMOVLPS, yxmov, Pm, {0x12,0x13} },
+ { AMOVLQSX, yml_rl, Pw, {0x63} },
+ { AMOVLQZX, yml_rl, Px, {0x8b} },
+ { AMOVMSKPD, yxrrl, Pq, {0x50} },
+ { AMOVMSKPS, yxrrl, Pm, {0x50} },
+ { AMOVNTO, yxr_ml, Pe, {0xe7} },
+ { AMOVNTPD, yxr_ml, Pe, {0x2b} },
+ { AMOVNTPS, yxr_ml, Pm, {0x2b} },
+ { AMOVNTQ, ymr_ml, Pm, {0xe7} },
+ { AMOVQ, ymovq, Pw, {0x89, 0x8b, 0x31, 0xc7,(00), 0xb8, 0xc7,(00), 0x6f, 0x7f, 0x6e, 0x7e, Pf2,0xd6, Pf3,0x7e, Pe,0xd6, Pe,0x6e, Pe,0x7e,0} },
+ { AMOVQOZX, ymrxr, Pf3, {0xd6,0x7e} },
+ { AMOVSB, ynone, Pb, {0xa4} },
+ { AMOVSD, yxmov, Pf2, {0x10,0x11} },
+ { AMOVSL, ynone, Px, {0xa5} },
+ { AMOVSQ, ynone, Pw, {0xa5} },
+ { AMOVSS, yxmov, Pf3, {0x10,0x11} },
+ { AMOVSW, ynone, Pe, {0xa5} },
+ { AMOVUPD, yxmov, Pe, {0x10,0x11} },
+ { AMOVUPS, yxmov, Pm, {0x10,0x11} },
+ { AMOVW, ymovw, Pe, {0x89,0x8b,0x31,0xb8,0xc7,(00),0} },
+ { AMOVWLSX, yml_rl, Pm, {0xbf} },
+ { AMOVWLZX, yml_rl, Pm, {0xb7} },
+ { AMOVWQSX, yml_rl, Pw, {0x0f,0xbf} },
+ { AMOVWQZX, yml_rl, Pw, {0x0f,0xb7} },
+ { AMULB, ydivb, Pb, {0xf6,(04)} },
+ { AMULL, ydivl, Px, {0xf7,(04)} },
+ { AMULPD, yxm, Pe, {0x59} },
+ { AMULPS, yxm, Ym, {0x59} },
+ { AMULQ, ydivl, Pw, {0xf7,(04)} },
+ { AMULSD, yxm, Pf2, {0x59} },
+ { AMULSS, yxm, Pf3, {0x59} },
+ { AMULW, ydivl, Pe, {0xf7,(04)} },
{ ANAME },
- { ANEGB, yscond, Pb, 0xf6,(03) },
- { ANEGL, yscond, Px, 0xf7,(03) },
- { ANEGQ, yscond, Pw, 0xf7,(03) },
- { ANEGW, yscond, Pe, 0xf7,(03) },
- { ANOP, ynop, Px, 0,0 },
- { ANOTB, yscond, Pb, 0xf6,(02) },
- { ANOTL, yscond, Px, 0xf7,(02) },
- { ANOTQ, yscond, Pw, 0xf7,(02) },
- { ANOTW, yscond, Pe, 0xf7,(02) },
- { AORB, yxorb, Pb, 0x0c,0x80,(01),0x08,0x0a },
- { AORL, yxorl, Px, 0x83,(01),0x0d,0x81,(01),0x09,0x0b },
- { AORPD, yxm, Pq, 0x56 },
- { AORPS, yxm, Pm, 0x56 },
- { AORQ, yxorl, Pw, 0x83,(01),0x0d,0x81,(01),0x09,0x0b },
- { AORW, yxorl, Pe, 0x83,(01),0x0d,0x81,(01),0x09,0x0b },
- { AOUTB, yin, Pb, 0xe6,0xee },
- { AOUTL, yin, Px, 0xe7,0xef },
- { AOUTSB, ynone, Pb, 0x6e },
- { AOUTSL, ynone, Px, 0x6f },
- { AOUTSW, ynone, Pe, 0x6f },
- { AOUTW, yin, Pe, 0xe7,0xef },
- { APACKSSLW, ymm, Py, 0x6b,Pe,0x6b },
- { APACKSSWB, ymm, Py, 0x63,Pe,0x63 },
- { APACKUSWB, ymm, Py, 0x67,Pe,0x67 },
- { APADDB, ymm, Py, 0xfc,Pe,0xfc },
- { APADDL, ymm, Py, 0xfe,Pe,0xfe },
- { APADDQ, yxm, Pe, 0xd4 },
- { APADDSB, ymm, Py, 0xec,Pe,0xec },
- { APADDSW, ymm, Py, 0xed,Pe,0xed },
- { APADDUSB, ymm, Py, 0xdc,Pe,0xdc },
- { APADDUSW, ymm, Py, 0xdd,Pe,0xdd },
- { APADDW, ymm, Py, 0xfd,Pe,0xfd },
- { APAND, ymm, Py, 0xdb,Pe,0xdb },
- { APANDN, ymm, Py, 0xdf,Pe,0xdf },
- { APAUSE, ynone, Px, 0xf3,0x90 },
- { APAVGB, ymm, Py, 0xe0,Pe,0xe0 },
- { APAVGW, ymm, Py, 0xe3,Pe,0xe3 },
- { APCMPEQB, ymm, Py, 0x74,Pe,0x74 },
- { APCMPEQL, ymm, Py, 0x76,Pe,0x76 },
- { APCMPEQW, ymm, Py, 0x75,Pe,0x75 },
- { APCMPGTB, ymm, Py, 0x64,Pe,0x64 },
- { APCMPGTL, ymm, Py, 0x66,Pe,0x66 },
- { APCMPGTW, ymm, Py, 0x65,Pe,0x65 },
- { APEXTRW, yextrw, Pq, 0xc5,(00) },
- { APF2IL, ymfp, Px, 0x1d },
- { APF2IW, ymfp, Px, 0x1c },
- { API2FL, ymfp, Px, 0x0d },
- { APFACC, ymfp, Px, 0xae },
- { APFADD, ymfp, Px, 0x9e },
- { APFCMPEQ, ymfp, Px, 0xb0 },
- { APFCMPGE, ymfp, Px, 0x90 },
- { APFCMPGT, ymfp, Px, 0xa0 },
- { APFMAX, ymfp, Px, 0xa4 },
- { APFMIN, ymfp, Px, 0x94 },
- { APFMUL, ymfp, Px, 0xb4 },
- { APFNACC, ymfp, Px, 0x8a },
- { APFPNACC, ymfp, Px, 0x8e },
- { APFRCP, ymfp, Px, 0x96 },
- { APFRCPIT1, ymfp, Px, 0xa6 },
- { APFRCPI2T, ymfp, Px, 0xb6 },
- { APFRSQIT1, ymfp, Px, 0xa7 },
- { APFRSQRT, ymfp, Px, 0x97 },
- { APFSUB, ymfp, Px, 0x9a },
- { APFSUBR, ymfp, Px, 0xaa },
- { APINSRW, yinsrw, Pq, 0xc4,(00) },
- { APINSRD, yinsr, Pq, 0x3a, 0x22, (00) },
- { APINSRQ, yinsr, Pq3, 0x3a, 0x22, (00) },
- { APMADDWL, ymm, Py, 0xf5,Pe,0xf5 },
- { APMAXSW, yxm, Pe, 0xee },
- { APMAXUB, yxm, Pe, 0xde },
- { APMINSW, yxm, Pe, 0xea },
- { APMINUB, yxm, Pe, 0xda },
- { APMOVMSKB, ymskb, Px, Pe,0xd7,0xd7 },
- { APMULHRW, ymfp, Px, 0xb7 },
- { APMULHUW, ymm, Py, 0xe4,Pe,0xe4 },
- { APMULHW, ymm, Py, 0xe5,Pe,0xe5 },
- { APMULLW, ymm, Py, 0xd5,Pe,0xd5 },
- { APMULULQ, ymm, Py, 0xf4,Pe,0xf4 },
- { APOPAL, ynone, P32, 0x61 },
- { APOPAW, ynone, Pe, 0x61 },
- { APOPFL, ynone, P32, 0x9d },
- { APOPFQ, ynone, Py, 0x9d },
- { APOPFW, ynone, Pe, 0x9d },
- { APOPL, ypopl, P32, 0x58,0x8f,(00) },
- { APOPQ, ypopl, Py, 0x58,0x8f,(00) },
- { APOPW, ypopl, Pe, 0x58,0x8f,(00) },
- { APOR, ymm, Py, 0xeb,Pe,0xeb },
- { APSADBW, yxm, Pq, 0xf6 },
- { APSHUFHW, yxshuf, Pf3, 0x70,(00) },
- { APSHUFL, yxshuf, Pq, 0x70,(00) },
- { APSHUFLW, yxshuf, Pf2, 0x70,(00) },
- { APSHUFW, ymshuf, Pm, 0x70,(00) },
- { APSHUFB, ymshufb,Pq, 0x38, 0x00 },
- { APSLLO, ypsdq, Pq, 0x73,(07) },
- { APSLLL, yps, Py, 0xf2, 0x72,(06), Pe,0xf2, Pe,0x72,(06) },
- { APSLLQ, yps, Py, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06) },
- { APSLLW, yps, Py, 0xf1, 0x71,(06), Pe,0xf1, Pe,0x71,(06) },
- { APSRAL, yps, Py, 0xe2, 0x72,(04), Pe,0xe2, Pe,0x72,(04) },
- { APSRAW, yps, Py, 0xe1, 0x71,(04), Pe,0xe1, Pe,0x71,(04) },
- { APSRLO, ypsdq, Pq, 0x73,(03) },
- { APSRLL, yps, Py, 0xd2, 0x72,(02), Pe,0xd2, Pe,0x72,(02) },
- { APSRLQ, yps, Py, 0xd3, 0x73,(02), Pe,0xd3, Pe,0x73,(02) },
- { APSRLW, yps, Py, 0xd1, 0x71,(02), Pe,0xe1, Pe,0x71,(02) },
- { APSUBB, yxm, Pe, 0xf8 },
- { APSUBL, yxm, Pe, 0xfa },
- { APSUBQ, yxm, Pe, 0xfb },
- { APSUBSB, yxm, Pe, 0xe8 },
- { APSUBSW, yxm, Pe, 0xe9 },
- { APSUBUSB, yxm, Pe, 0xd8 },
- { APSUBUSW, yxm, Pe, 0xd9 },
- { APSUBW, yxm, Pe, 0xf9 },
- { APSWAPL, ymfp, Px, 0xbb },
- { APUNPCKHBW, ymm, Py, 0x68,Pe,0x68 },
- { APUNPCKHLQ, ymm, Py, 0x6a,Pe,0x6a },
- { APUNPCKHQDQ, yxm, Pe, 0x6d },
- { APUNPCKHWL, ymm, Py, 0x69,Pe,0x69 },
- { APUNPCKLBW, ymm, Py, 0x60,Pe,0x60 },
- { APUNPCKLLQ, ymm, Py, 0x62,Pe,0x62 },
- { APUNPCKLQDQ, yxm, Pe, 0x6c },
- { APUNPCKLWL, ymm, Py, 0x61,Pe,0x61 },
- { APUSHAL, ynone, P32, 0x60 },
- { APUSHAW, ynone, Pe, 0x60 },
- { APUSHFL, ynone, P32, 0x9c },
- { APUSHFQ, ynone, Py, 0x9c },
- { APUSHFW, ynone, Pe, 0x9c },
- { APUSHL, ypushl, P32, 0x50,0xff,(06),0x6a,0x68 },
- { APUSHQ, ypushl, Py, 0x50,0xff,(06),0x6a,0x68 },
- { APUSHW, ypushl, Pe, 0x50,0xff,(06),0x6a,0x68 },
- { APXOR, ymm, Py, 0xef,Pe,0xef },
- { AQUAD, ybyte, Px, 8 },
- { ARCLB, yshb, Pb, 0xd0,(02),0xc0,(02),0xd2,(02) },
- { ARCLL, yshl, Px, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) },
- { ARCLQ, yshl, Pw, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) },
- { ARCLW, yshl, Pe, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) },
- { ARCPPS, yxm, Pm, 0x53 },
- { ARCPSS, yxm, Pf3, 0x53 },
- { ARCRB, yshb, Pb, 0xd0,(03),0xc0,(03),0xd2,(03) },
- { ARCRL, yshl, Px, 0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03) },
- { ARCRQ, yshl, Pw, 0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03) },
- { ARCRW, yshl, Pe, 0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03) },
- { AREP, ynone, Px, 0xf3 },
- { AREPN, ynone, Px, 0xf2 },
- { ARET, ynone, Px, 0xc3 },
- { ARETFW, yret, Pe, 0xcb,0xca },
- { ARETFL, yret, Px, 0xcb,0xca },
- { ARETFQ, yret, Pw, 0xcb,0xca },
- { AROLB, yshb, Pb, 0xd0,(00),0xc0,(00),0xd2,(00) },
- { AROLL, yshl, Px, 0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00) },
- { AROLQ, yshl, Pw, 0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00) },
- { AROLW, yshl, Pe, 0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00) },
- { ARORB, yshb, Pb, 0xd0,(01),0xc0,(01),0xd2,(01) },
- { ARORL, yshl, Px, 0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01) },
- { ARORQ, yshl, Pw, 0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01) },
- { ARORW, yshl, Pe, 0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01) },
- { ARSQRTPS, yxm, Pm, 0x52 },
- { ARSQRTSS, yxm, Pf3, 0x52 },
- { ASAHF, ynone, Px, 0x86,0xe0,0x50,0x9d }, /* XCHGB AH,AL; PUSH AX; POPFL */
- { ASALB, yshb, Pb, 0xd0,(04),0xc0,(04),0xd2,(04) },
- { ASALL, yshl, Px, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
- { ASALQ, yshl, Pw, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
- { ASALW, yshl, Pe, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
- { ASARB, yshb, Pb, 0xd0,(07),0xc0,(07),0xd2,(07) },
- { ASARL, yshl, Px, 0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07) },
- { ASARQ, yshl, Pw, 0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07) },
- { ASARW, yshl, Pe, 0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07) },
- { ASBBB, yxorb, Pb, 0x1c,0x80,(03),0x18,0x1a },
- { ASBBL, yxorl, Px, 0x83,(03),0x1d,0x81,(03),0x19,0x1b },
- { ASBBQ, yxorl, Pw, 0x83,(03),0x1d,0x81,(03),0x19,0x1b },
- { ASBBW, yxorl, Pe, 0x83,(03),0x1d,0x81,(03),0x19,0x1b },
- { ASCASB, ynone, Pb, 0xae },
- { ASCASL, ynone, Px, 0xaf },
- { ASCASQ, ynone, Pw, 0xaf },
- { ASCASW, ynone, Pe, 0xaf },
- { ASETCC, yscond, Pm, 0x93,(00) },
- { ASETCS, yscond, Pm, 0x92,(00) },
- { ASETEQ, yscond, Pm, 0x94,(00) },
- { ASETGE, yscond, Pm, 0x9d,(00) },
- { ASETGT, yscond, Pm, 0x9f,(00) },
- { ASETHI, yscond, Pm, 0x97,(00) },
- { ASETLE, yscond, Pm, 0x9e,(00) },
- { ASETLS, yscond, Pm, 0x96,(00) },
- { ASETLT, yscond, Pm, 0x9c,(00) },
- { ASETMI, yscond, Pm, 0x98,(00) },
- { ASETNE, yscond, Pm, 0x95,(00) },
- { ASETOC, yscond, Pm, 0x91,(00) },
- { ASETOS, yscond, Pm, 0x90,(00) },
- { ASETPC, yscond, Pm, 0x96,(00) },
- { ASETPL, yscond, Pm, 0x99,(00) },
- { ASETPS, yscond, Pm, 0x9a,(00) },
- { ASHLB, yshb, Pb, 0xd0,(04),0xc0,(04),0xd2,(04) },
- { ASHLL, yshl, Px, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
- { ASHLQ, yshl, Pw, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
- { ASHLW, yshl, Pe, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
- { ASHRB, yshb, Pb, 0xd0,(05),0xc0,(05),0xd2,(05) },
- { ASHRL, yshl, Px, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) },
- { ASHRQ, yshl, Pw, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) },
- { ASHRW, yshl, Pe, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) },
- { ASHUFPD, yxshuf, Pq, 0xc6,(00) },
- { ASHUFPS, yxshuf, Pm, 0xc6,(00) },
- { ASQRTPD, yxm, Pe, 0x51 },
- { ASQRTPS, yxm, Pm, 0x51 },
- { ASQRTSD, yxm, Pf2, 0x51 },
- { ASQRTSS, yxm, Pf3, 0x51 },
- { ASTC, ynone, Px, 0xf9 },
- { ASTD, ynone, Px, 0xfd },
- { ASTI, ynone, Px, 0xfb },
- { ASTMXCSR, ysvrs, Pm, 0xae,(03),0xae,(03) },
- { ASTOSB, ynone, Pb, 0xaa },
- { ASTOSL, ynone, Px, 0xab },
- { ASTOSQ, ynone, Pw, 0xab },
- { ASTOSW, ynone, Pe, 0xab },
- { ASUBB, yxorb, Pb, 0x2c,0x80,(05),0x28,0x2a },
- { ASUBL, yaddl, Px, 0x83,(05),0x2d,0x81,(05),0x29,0x2b },
- { ASUBPD, yxm, Pe, 0x5c },
- { ASUBPS, yxm, Pm, 0x5c },
- { ASUBQ, yaddl, Pw, 0x83,(05),0x2d,0x81,(05),0x29,0x2b },
- { ASUBSD, yxm, Pf2, 0x5c },
- { ASUBSS, yxm, Pf3, 0x5c },
- { ASUBW, yaddl, Pe, 0x83,(05),0x2d,0x81,(05),0x29,0x2b },
- { ASWAPGS, ynone, Pm, 0x01,0xf8 },
- { ASYSCALL, ynone, Px, 0x0f,0x05 }, /* fast syscall */
- { ATESTB, ytestb, Pb, 0xa8,0xf6,(00),0x84,0x84 },
- { ATESTL, ytestl, Px, 0xa9,0xf7,(00),0x85,0x85 },
- { ATESTQ, ytestl, Pw, 0xa9,0xf7,(00),0x85,0x85 },
- { ATESTW, ytestl, Pe, 0xa9,0xf7,(00),0x85,0x85 },
+ { ANEGB, yscond, Pb, {0xf6,(03)} },
+ { ANEGL, yscond, Px, {0xf7,(03)} },
+ { ANEGQ, yscond, Pw, {0xf7,(03)} },
+ { ANEGW, yscond, Pe, {0xf7,(03)} },
+ { ANOP, ynop, Px, {0,0} },
+ { ANOTB, yscond, Pb, {0xf6,(02)} },
+ { ANOTL, yscond, Px, {0xf7,(02)} },
+ { ANOTQ, yscond, Pw, {0xf7,(02)} },
+ { ANOTW, yscond, Pe, {0xf7,(02)} },
+ { AORB, yxorb, Pb, {0x0c,0x80,(01),0x08,0x0a} },
+ { AORL, yxorl, Px, {0x83,(01),0x0d,0x81,(01),0x09,0x0b} },
+ { AORPD, yxm, Pq, {0x56} },
+ { AORPS, yxm, Pm, {0x56} },
+ { AORQ, yxorl, Pw, {0x83,(01),0x0d,0x81,(01),0x09,0x0b} },
+ { AORW, yxorl, Pe, {0x83,(01),0x0d,0x81,(01),0x09,0x0b} },
+ { AOUTB, yin, Pb, {0xe6,0xee} },
+ { AOUTL, yin, Px, {0xe7,0xef} },
+ { AOUTSB, ynone, Pb, {0x6e} },
+ { AOUTSL, ynone, Px, {0x6f} },
+ { AOUTSW, ynone, Pe, {0x6f} },
+ { AOUTW, yin, Pe, {0xe7,0xef} },
+ { APACKSSLW, ymm, Py, {0x6b,Pe,0x6b} },
+ { APACKSSWB, ymm, Py, {0x63,Pe,0x63} },
+ { APACKUSWB, ymm, Py, {0x67,Pe,0x67} },
+ { APADDB, ymm, Py, {0xfc,Pe,0xfc} },
+ { APADDL, ymm, Py, {0xfe,Pe,0xfe} },
+ { APADDQ, yxm, Pe, {0xd4} },
+ { APADDSB, ymm, Py, {0xec,Pe,0xec} },
+ { APADDSW, ymm, Py, {0xed,Pe,0xed} },
+ { APADDUSB, ymm, Py, {0xdc,Pe,0xdc} },
+ { APADDUSW, ymm, Py, {0xdd,Pe,0xdd} },
+ { APADDW, ymm, Py, {0xfd,Pe,0xfd} },
+ { APAND, ymm, Py, {0xdb,Pe,0xdb} },
+ { APANDN, ymm, Py, {0xdf,Pe,0xdf} },
+ { APAUSE, ynone, Px, {0xf3,0x90} },
+ { APAVGB, ymm, Py, {0xe0,Pe,0xe0} },
+ { APAVGW, ymm, Py, {0xe3,Pe,0xe3} },
+ { APCMPEQB, ymm, Py, {0x74,Pe,0x74} },
+ { APCMPEQL, ymm, Py, {0x76,Pe,0x76} },
+ { APCMPEQW, ymm, Py, {0x75,Pe,0x75} },
+ { APCMPGTB, ymm, Py, {0x64,Pe,0x64} },
+ { APCMPGTL, ymm, Py, {0x66,Pe,0x66} },
+ { APCMPGTW, ymm, Py, {0x65,Pe,0x65} },
+ { APEXTRW, yextrw, Pq, {0xc5,(00)} },
+ { APF2IL, ymfp, Px, {0x1d} },
+ { APF2IW, ymfp, Px, {0x1c} },
+ { API2FL, ymfp, Px, {0x0d} },
+ { APFACC, ymfp, Px, {0xae} },
+ { APFADD, ymfp, Px, {0x9e} },
+ { APFCMPEQ, ymfp, Px, {0xb0} },
+ { APFCMPGE, ymfp, Px, {0x90} },
+ { APFCMPGT, ymfp, Px, {0xa0} },
+ { APFMAX, ymfp, Px, {0xa4} },
+ { APFMIN, ymfp, Px, {0x94} },
+ { APFMUL, ymfp, Px, {0xb4} },
+ { APFNACC, ymfp, Px, {0x8a} },
+ { APFPNACC, ymfp, Px, {0x8e} },
+ { APFRCP, ymfp, Px, {0x96} },
+ { APFRCPIT1, ymfp, Px, {0xa6} },
+ { APFRCPI2T, ymfp, Px, {0xb6} },
+ { APFRSQIT1, ymfp, Px, {0xa7} },
+ { APFRSQRT, ymfp, Px, {0x97} },
+ { APFSUB, ymfp, Px, {0x9a} },
+ { APFSUBR, ymfp, Px, {0xaa} },
+ { APINSRW, yinsrw, Pq, {0xc4,(00)} },
+ { APINSRD, yinsr, Pq, {0x3a, 0x22, (00)} },
+ { APINSRQ, yinsr, Pq3, {0x3a, 0x22, (00)} },
+ { APMADDWL, ymm, Py, {0xf5,Pe,0xf5} },
+ { APMAXSW, yxm, Pe, {0xee} },
+ { APMAXUB, yxm, Pe, {0xde} },
+ { APMINSW, yxm, Pe, {0xea} },
+ { APMINUB, yxm, Pe, {0xda} },
+ { APMOVMSKB, ymskb, Px, {Pe,0xd7,0xd7} },
+ { APMULHRW, ymfp, Px, {0xb7} },
+ { APMULHUW, ymm, Py, {0xe4,Pe,0xe4} },
+ { APMULHW, ymm, Py, {0xe5,Pe,0xe5} },
+ { APMULLW, ymm, Py, {0xd5,Pe,0xd5} },
+ { APMULULQ, ymm, Py, {0xf4,Pe,0xf4} },
+ { APOPAL, ynone, P32, {0x61} },
+ { APOPAW, ynone, Pe, {0x61} },
+ { APOPFL, ynone, P32, {0x9d} },
+ { APOPFQ, ynone, Py, {0x9d} },
+ { APOPFW, ynone, Pe, {0x9d} },
+ { APOPL, ypopl, P32, {0x58,0x8f,(00)} },
+ { APOPQ, ypopl, Py, {0x58,0x8f,(00)} },
+ { APOPW, ypopl, Pe, {0x58,0x8f,(00)} },
+ { APOR, ymm, Py, {0xeb,Pe,0xeb} },
+ { APSADBW, yxm, Pq, {0xf6} },
+ { APSHUFHW, yxshuf, Pf3, {0x70,(00)} },
+ { APSHUFL, yxshuf, Pq, {0x70,(00)} },
+ { APSHUFLW, yxshuf, Pf2, {0x70,(00)} },
+ { APSHUFW, ymshuf, Pm, {0x70,(00)} },
+ { APSHUFB, ymshufb,Pq, {0x38, 0x00} },
+ { APSLLO, ypsdq, Pq, {0x73,(07)} },
+ { APSLLL, yps, Py, {0xf2, 0x72,(06), Pe,0xf2, Pe,0x72,(06)} },
+ { APSLLQ, yps, Py, {0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06)} },
+ { APSLLW, yps, Py, {0xf1, 0x71,(06), Pe,0xf1, Pe,0x71,(06)} },
+ { APSRAL, yps, Py, {0xe2, 0x72,(04), Pe,0xe2, Pe,0x72,(04)} },
+ { APSRAW, yps, Py, {0xe1, 0x71,(04), Pe,0xe1, Pe,0x71,(04)} },
+ { APSRLO, ypsdq, Pq, {0x73,(03)} },
+ { APSRLL, yps, Py, {0xd2, 0x72,(02), Pe,0xd2, Pe,0x72,(02)} },
+ { APSRLQ, yps, Py, {0xd3, 0x73,(02), Pe,0xd3, Pe,0x73,(02)} },
+ { APSRLW, yps, Py, {0xd1, 0x71,(02), Pe,0xe1, Pe,0x71,(02)} },
+ { APSUBB, yxm, Pe, {0xf8} },
+ { APSUBL, yxm, Pe, {0xfa} },
+ { APSUBQ, yxm, Pe, {0xfb} },
+ { APSUBSB, yxm, Pe, {0xe8} },
+ { APSUBSW, yxm, Pe, {0xe9} },
+ { APSUBUSB, yxm, Pe, {0xd8} },
+ { APSUBUSW, yxm, Pe, {0xd9} },
+ { APSUBW, yxm, Pe, {0xf9} },
+ { APSWAPL, ymfp, Px, {0xbb} },
+ { APUNPCKHBW, ymm, Py, {0x68,Pe,0x68} },
+ { APUNPCKHLQ, ymm, Py, {0x6a,Pe,0x6a} },
+ { APUNPCKHQDQ, yxm, Pe, {0x6d} },
+ { APUNPCKHWL, ymm, Py, {0x69,Pe,0x69} },
+ { APUNPCKLBW, ymm, Py, {0x60,Pe,0x60} },
+ { APUNPCKLLQ, ymm, Py, {0x62,Pe,0x62} },
+ { APUNPCKLQDQ, yxm, Pe, {0x6c} },
+ { APUNPCKLWL, ymm, Py, {0x61,Pe,0x61} },
+ { APUSHAL, ynone, P32, {0x60} },
+ { APUSHAW, ynone, Pe, {0x60} },
+ { APUSHFL, ynone, P32, {0x9c} },
+ { APUSHFQ, ynone, Py, {0x9c} },
+ { APUSHFW, ynone, Pe, {0x9c} },
+ { APUSHL, ypushl, P32, {0x50,0xff,(06),0x6a,0x68} },
+ { APUSHQ, ypushl, Py, {0x50,0xff,(06),0x6a,0x68} },
+ { APUSHW, ypushl, Pe, {0x50,0xff,(06),0x6a,0x68} },
+ { APXOR, ymm, Py, {0xef,Pe,0xef} },
+ { AQUAD, ybyte, Px, {8} },
+ { ARCLB, yshb, Pb, {0xd0,(02),0xc0,(02),0xd2,(02)} },
+ { ARCLL, yshl, Px, {0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02)} },
+ { ARCLQ, yshl, Pw, {0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02)} },
+ { ARCLW, yshl, Pe, {0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02)} },
+ { ARCPPS, yxm, Pm, {0x53} },
+ { ARCPSS, yxm, Pf3, {0x53} },
+ { ARCRB, yshb, Pb, {0xd0,(03),0xc0,(03),0xd2,(03)} },
+ { ARCRL, yshl, Px, {0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03)} },
+ { ARCRQ, yshl, Pw, {0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03)} },
+ { ARCRW, yshl, Pe, {0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03)} },
+ { AREP, ynone, Px, {0xf3} },
+ { AREPN, ynone, Px, {0xf2} },
+ { ARET, ynone, Px, {0xc3} },
+ { ARETFW, yret, Pe, {0xcb,0xca} },
+ { ARETFL, yret, Px, {0xcb,0xca} },
+ { ARETFQ, yret, Pw, {0xcb,0xca} },
+ { AROLB, yshb, Pb, {0xd0,(00),0xc0,(00),0xd2,(00)} },
+ { AROLL, yshl, Px, {0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00)} },
+ { AROLQ, yshl, Pw, {0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00)} },
+ { AROLW, yshl, Pe, {0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00)} },
+ { ARORB, yshb, Pb, {0xd0,(01),0xc0,(01),0xd2,(01)} },
+ { ARORL, yshl, Px, {0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01)} },
+ { ARORQ, yshl, Pw, {0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01)} },
+ { ARORW, yshl, Pe, {0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01)} },
+ { ARSQRTPS, yxm, Pm, {0x52} },
+ { ARSQRTSS, yxm, Pf3, {0x52} },
+ { ASAHF, ynone, Px, {0x86,0xe0,0x50,0x9d} }, /* XCHGB AH,AL; PUSH AX; POPFL */
+ { ASALB, yshb, Pb, {0xd0,(04),0xc0,(04),0xd2,(04)} },
+ { ASALL, yshl, Px, {0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04)} },
+ { ASALQ, yshl, Pw, {0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04)} },
+ { ASALW, yshl, Pe, {0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04)} },
+ { ASARB, yshb, Pb, {0xd0,(07),0xc0,(07),0xd2,(07)} },
+ { ASARL, yshl, Px, {0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07)} },
+ { ASARQ, yshl, Pw, {0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07)} },
+ { ASARW, yshl, Pe, {0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07)} },
+ { ASBBB, yxorb, Pb, {0x1c,0x80,(03),0x18,0x1a} },
+ { ASBBL, yxorl, Px, {0x83,(03),0x1d,0x81,(03),0x19,0x1b} },
+ { ASBBQ, yxorl, Pw, {0x83,(03),0x1d,0x81,(03),0x19,0x1b} },
+ { ASBBW, yxorl, Pe, {0x83,(03),0x1d,0x81,(03),0x19,0x1b} },
+ { ASCASB, ynone, Pb, {0xae} },
+ { ASCASL, ynone, Px, {0xaf} },
+ { ASCASQ, ynone, Pw, {0xaf} },
+ { ASCASW, ynone, Pe, {0xaf} },
+ { ASETCC, yscond, Pm, {0x93,(00)} },
+ { ASETCS, yscond, Pm, {0x92,(00)} },
+ { ASETEQ, yscond, Pm, {0x94,(00)} },
+ { ASETGE, yscond, Pm, {0x9d,(00)} },
+ { ASETGT, yscond, Pm, {0x9f,(00)} },
+ { ASETHI, yscond, Pm, {0x97,(00)} },
+ { ASETLE, yscond, Pm, {0x9e,(00)} },
+ { ASETLS, yscond, Pm, {0x96,(00)} },
+ { ASETLT, yscond, Pm, {0x9c,(00)} },
+ { ASETMI, yscond, Pm, {0x98,(00)} },
+ { ASETNE, yscond, Pm, {0x95,(00)} },
+ { ASETOC, yscond, Pm, {0x91,(00)} },
+ { ASETOS, yscond, Pm, {0x90,(00)} },
+ { ASETPC, yscond, Pm, {0x9b,(00)} },
+ { ASETPL, yscond, Pm, {0x99,(00)} },
+ { ASETPS, yscond, Pm, {0x9a,(00)} },
+ { ASHLB, yshb, Pb, {0xd0,(04),0xc0,(04),0xd2,(04)} },
+ { ASHLL, yshl, Px, {0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04)} },
+ { ASHLQ, yshl, Pw, {0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04)} },
+ { ASHLW, yshl, Pe, {0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04)} },
+ { ASHRB, yshb, Pb, {0xd0,(05),0xc0,(05),0xd2,(05)} },
+ { ASHRL, yshl, Px, {0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05)} },
+ { ASHRQ, yshl, Pw, {0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05)} },
+ { ASHRW, yshl, Pe, {0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05)} },
+ { ASHUFPD, yxshuf, Pq, {0xc6,(00)} },
+ { ASHUFPS, yxshuf, Pm, {0xc6,(00)} },
+ { ASQRTPD, yxm, Pe, {0x51} },
+ { ASQRTPS, yxm, Pm, {0x51} },
+ { ASQRTSD, yxm, Pf2, {0x51} },
+ { ASQRTSS, yxm, Pf3, {0x51} },
+ { ASTC, ynone, Px, {0xf9} },
+ { ASTD, ynone, Px, {0xfd} },
+ { ASTI, ynone, Px, {0xfb} },
+ { ASTMXCSR, ysvrs, Pm, {0xae,(03),0xae,(03)} },
+ { ASTOSB, ynone, Pb, {0xaa} },
+ { ASTOSL, ynone, Px, {0xab} },
+ { ASTOSQ, ynone, Pw, {0xab} },
+ { ASTOSW, ynone, Pe, {0xab} },
+ { ASUBB, yxorb, Pb, {0x2c,0x80,(05),0x28,0x2a} },
+ { ASUBL, yaddl, Px, {0x83,(05),0x2d,0x81,(05),0x29,0x2b} },
+ { ASUBPD, yxm, Pe, {0x5c} },
+ { ASUBPS, yxm, Pm, {0x5c} },
+ { ASUBQ, yaddl, Pw, {0x83,(05),0x2d,0x81,(05),0x29,0x2b} },
+ { ASUBSD, yxm, Pf2, {0x5c} },
+ { ASUBSS, yxm, Pf3, {0x5c} },
+ { ASUBW, yaddl, Pe, {0x83,(05),0x2d,0x81,(05),0x29,0x2b} },
+ { ASWAPGS, ynone, Pm, {0x01,0xf8} },
+ { ASYSCALL, ynone, Px, {0x0f,0x05} }, /* fast syscall */
+ { ATESTB, ytestb, Pb, {0xa8,0xf6,(00),0x84,0x84} },
+ { ATESTL, ytestl, Px, {0xa9,0xf7,(00),0x85,0x85} },
+ { ATESTQ, ytestl, Pw, {0xa9,0xf7,(00),0x85,0x85} },
+ { ATESTW, ytestl, Pe, {0xa9,0xf7,(00),0x85,0x85} },
{ ATEXT, ytext, Px },
- { AUCOMISD, yxcmp, Pe, 0x2e },
- { AUCOMISS, yxcmp, Pm, 0x2e },
- { AUNPCKHPD, yxm, Pe, 0x15 },
- { AUNPCKHPS, yxm, Pm, 0x15 },
- { AUNPCKLPD, yxm, Pe, 0x14 },
- { AUNPCKLPS, yxm, Pm, 0x14 },
- { AVERR, ydivl, Pm, 0x00,(04) },
- { AVERW, ydivl, Pm, 0x00,(05) },
- { AWAIT, ynone, Px, 0x9b },
- { AWORD, ybyte, Px, 2 },
- { AXCHGB, yml_mb, Pb, 0x86,0x86 },
- { AXCHGL, yxchg, Px, 0x90,0x90,0x87,0x87 },
- { AXCHGQ, yxchg, Pw, 0x90,0x90,0x87,0x87 },
- { AXCHGW, yxchg, Pe, 0x90,0x90,0x87,0x87 },
- { AXLAT, ynone, Px, 0xd7 },
- { AXORB, yxorb, Pb, 0x34,0x80,(06),0x30,0x32 },
- { AXORL, yxorl, Px, 0x83,(06),0x35,0x81,(06),0x31,0x33 },
- { AXORPD, yxm, Pe, 0x57 },
- { AXORPS, yxm, Pm, 0x57 },
- { AXORQ, yxorl, Pw, 0x83,(06),0x35,0x81,(06),0x31,0x33 },
- { AXORW, yxorl, Pe, 0x83,(06),0x35,0x81,(06),0x31,0x33 },
-
- { AFMOVB, yfmvx, Px, 0xdf,(04) },
- { AFMOVBP, yfmvp, Px, 0xdf,(06) },
- { AFMOVD, yfmvd, Px, 0xdd,(00),0xdd,(02),0xd9,(00),0xdd,(02) },
- { AFMOVDP, yfmvdp, Px, 0xdd,(03),0xdd,(03) },
- { AFMOVF, yfmvf, Px, 0xd9,(00),0xd9,(02) },
- { AFMOVFP, yfmvp, Px, 0xd9,(03) },
- { AFMOVL, yfmvf, Px, 0xdb,(00),0xdb,(02) },
- { AFMOVLP, yfmvp, Px, 0xdb,(03) },
- { AFMOVV, yfmvx, Px, 0xdf,(05) },
- { AFMOVVP, yfmvp, Px, 0xdf,(07) },
- { AFMOVW, yfmvf, Px, 0xdf,(00),0xdf,(02) },
- { AFMOVWP, yfmvp, Px, 0xdf,(03) },
- { AFMOVX, yfmvx, Px, 0xdb,(05) },
- { AFMOVXP, yfmvp, Px, 0xdb,(07) },
+ { AUCOMISD, yxcmp, Pe, {0x2e} },
+ { AUCOMISS, yxcmp, Pm, {0x2e} },
+ { AUNPCKHPD, yxm, Pe, {0x15} },
+ { AUNPCKHPS, yxm, Pm, {0x15} },
+ { AUNPCKLPD, yxm, Pe, {0x14} },
+ { AUNPCKLPS, yxm, Pm, {0x14} },
+ { AVERR, ydivl, Pm, {0x00,(04)} },
+ { AVERW, ydivl, Pm, {0x00,(05)} },
+ { AWAIT, ynone, Px, {0x9b} },
+ { AWORD, ybyte, Px, {2} },
+ { AXCHGB, yml_mb, Pb, {0x86,0x86} },
+ { AXCHGL, yxchg, Px, {0x90,0x90,0x87,0x87} },
+ { AXCHGQ, yxchg, Pw, {0x90,0x90,0x87,0x87} },
+ { AXCHGW, yxchg, Pe, {0x90,0x90,0x87,0x87} },
+ { AXLAT, ynone, Px, {0xd7} },
+ { AXORB, yxorb, Pb, {0x34,0x80,(06),0x30,0x32} },
+ { AXORL, yxorl, Px, {0x83,(06),0x35,0x81,(06),0x31,0x33} },
+ { AXORPD, yxm, Pe, {0x57} },
+ { AXORPS, yxm, Pm, {0x57} },
+ { AXORQ, yxorl, Pw, {0x83,(06),0x35,0x81,(06),0x31,0x33} },
+ { AXORW, yxorl, Pe, {0x83,(06),0x35,0x81,(06),0x31,0x33} },
+
+ { AFMOVB, yfmvx, Px, {0xdf,(04)} },
+ { AFMOVBP, yfmvp, Px, {0xdf,(06)} },
+ { AFMOVD, yfmvd, Px, {0xdd,(00),0xdd,(02),0xd9,(00),0xdd,(02)} },
+ { AFMOVDP, yfmvdp, Px, {0xdd,(03),0xdd,(03)} },
+ { AFMOVF, yfmvf, Px, {0xd9,(00),0xd9,(02)} },
+ { AFMOVFP, yfmvp, Px, {0xd9,(03)} },
+ { AFMOVL, yfmvf, Px, {0xdb,(00),0xdb,(02)} },
+ { AFMOVLP, yfmvp, Px, {0xdb,(03)} },
+ { AFMOVV, yfmvx, Px, {0xdf,(05)} },
+ { AFMOVVP, yfmvp, Px, {0xdf,(07)} },
+ { AFMOVW, yfmvf, Px, {0xdf,(00),0xdf,(02)} },
+ { AFMOVWP, yfmvp, Px, {0xdf,(03)} },
+ { AFMOVX, yfmvx, Px, {0xdb,(05)} },
+ { AFMOVXP, yfmvp, Px, {0xdb,(07)} },
{ AFCOMB },
{ AFCOMBP },
- { AFCOMD, yfadd, Px, 0xdc,(02),0xd8,(02),0xdc,(02) }, /* botch */
- { AFCOMDP, yfadd, Px, 0xdc,(03),0xd8,(03),0xdc,(03) }, /* botch */
- { AFCOMDPP, ycompp, Px, 0xde,(03) },
- { AFCOMF, yfmvx, Px, 0xd8,(02) },
- { AFCOMFP, yfmvx, Px, 0xd8,(03) },
- { AFCOML, yfmvx, Px, 0xda,(02) },
- { AFCOMLP, yfmvx, Px, 0xda,(03) },
- { AFCOMW, yfmvx, Px, 0xde,(02) },
- { AFCOMWP, yfmvx, Px, 0xde,(03) },
-
- { AFUCOM, ycompp, Px, 0xdd,(04) },
- { AFUCOMP, ycompp, Px, 0xdd,(05) },
- { AFUCOMPP, ycompp, Px, 0xda,(13) },
-
- { AFADDDP, yfaddp, Px, 0xde,(00) },
- { AFADDW, yfmvx, Px, 0xde,(00) },
- { AFADDL, yfmvx, Px, 0xda,(00) },
- { AFADDF, yfmvx, Px, 0xd8,(00) },
- { AFADDD, yfadd, Px, 0xdc,(00),0xd8,(00),0xdc,(00) },
-
- { AFMULDP, yfaddp, Px, 0xde,(01) },
- { AFMULW, yfmvx, Px, 0xde,(01) },
- { AFMULL, yfmvx, Px, 0xda,(01) },
- { AFMULF, yfmvx, Px, 0xd8,(01) },
- { AFMULD, yfadd, Px, 0xdc,(01),0xd8,(01),0xdc,(01) },
-
- { AFSUBDP, yfaddp, Px, 0xde,(05) },
- { AFSUBW, yfmvx, Px, 0xde,(04) },
- { AFSUBL, yfmvx, Px, 0xda,(04) },
- { AFSUBF, yfmvx, Px, 0xd8,(04) },
- { AFSUBD, yfadd, Px, 0xdc,(04),0xd8,(04),0xdc,(05) },
-
- { AFSUBRDP, yfaddp, Px, 0xde,(04) },
- { AFSUBRW, yfmvx, Px, 0xde,(05) },
- { AFSUBRL, yfmvx, Px, 0xda,(05) },
- { AFSUBRF, yfmvx, Px, 0xd8,(05) },
- { AFSUBRD, yfadd, Px, 0xdc,(05),0xd8,(05),0xdc,(04) },
-
- { AFDIVDP, yfaddp, Px, 0xde,(07) },
- { AFDIVW, yfmvx, Px, 0xde,(06) },
- { AFDIVL, yfmvx, Px, 0xda,(06) },
- { AFDIVF, yfmvx, Px, 0xd8,(06) },
- { AFDIVD, yfadd, Px, 0xdc,(06),0xd8,(06),0xdc,(07) },
-
- { AFDIVRDP, yfaddp, Px, 0xde,(06) },
- { AFDIVRW, yfmvx, Px, 0xde,(07) },
- { AFDIVRL, yfmvx, Px, 0xda,(07) },
- { AFDIVRF, yfmvx, Px, 0xd8,(07) },
- { AFDIVRD, yfadd, Px, 0xdc,(07),0xd8,(07),0xdc,(06) },
-
- { AFXCHD, yfxch, Px, 0xd9,(01),0xd9,(01) },
+ { AFCOMD, yfadd, Px, {0xdc,(02),0xd8,(02),0xdc,(02)} }, /* botch */
+ { AFCOMDP, yfadd, Px, {0xdc,(03),0xd8,(03),0xdc,(03)} }, /* botch */
+ { AFCOMDPP, ycompp, Px, {0xde,(03)} },
+ { AFCOMF, yfmvx, Px, {0xd8,(02)} },
+ { AFCOMFP, yfmvx, Px, {0xd8,(03)} },
+ { AFCOML, yfmvx, Px, {0xda,(02)} },
+ { AFCOMLP, yfmvx, Px, {0xda,(03)} },
+ { AFCOMW, yfmvx, Px, {0xde,(02)} },
+ { AFCOMWP, yfmvx, Px, {0xde,(03)} },
+
+ { AFUCOM, ycompp, Px, {0xdd,(04)} },
+ { AFUCOMP, ycompp, Px, {0xdd,(05)} },
+ { AFUCOMPP, ycompp, Px, {0xda,(13)} },
+
+ { AFADDDP, yfaddp, Px, {0xde,(00)} },
+ { AFADDW, yfmvx, Px, {0xde,(00)} },
+ { AFADDL, yfmvx, Px, {0xda,(00)} },
+ { AFADDF, yfmvx, Px, {0xd8,(00)} },
+ { AFADDD, yfadd, Px, {0xdc,(00),0xd8,(00),0xdc,(00)} },
+
+ { AFMULDP, yfaddp, Px, {0xde,(01)} },
+ { AFMULW, yfmvx, Px, {0xde,(01)} },
+ { AFMULL, yfmvx, Px, {0xda,(01)} },
+ { AFMULF, yfmvx, Px, {0xd8,(01)} },
+ { AFMULD, yfadd, Px, {0xdc,(01),0xd8,(01),0xdc,(01)} },
+
+ { AFSUBDP, yfaddp, Px, {0xde,(05)} },
+ { AFSUBW, yfmvx, Px, {0xde,(04)} },
+ { AFSUBL, yfmvx, Px, {0xda,(04)} },
+ { AFSUBF, yfmvx, Px, {0xd8,(04)} },
+ { AFSUBD, yfadd, Px, {0xdc,(04),0xd8,(04),0xdc,(05)} },
+
+ { AFSUBRDP, yfaddp, Px, {0xde,(04)} },
+ { AFSUBRW, yfmvx, Px, {0xde,(05)} },
+ { AFSUBRL, yfmvx, Px, {0xda,(05)} },
+ { AFSUBRF, yfmvx, Px, {0xd8,(05)} },
+ { AFSUBRD, yfadd, Px, {0xdc,(05),0xd8,(05),0xdc,(04)} },
+
+ { AFDIVDP, yfaddp, Px, {0xde,(07)} },
+ { AFDIVW, yfmvx, Px, {0xde,(06)} },
+ { AFDIVL, yfmvx, Px, {0xda,(06)} },
+ { AFDIVF, yfmvx, Px, {0xd8,(06)} },
+ { AFDIVD, yfadd, Px, {0xdc,(06),0xd8,(06),0xdc,(07)} },
+
+ { AFDIVRDP, yfaddp, Px, {0xde,(06)} },
+ { AFDIVRW, yfmvx, Px, {0xde,(07)} },
+ { AFDIVRL, yfmvx, Px, {0xda,(07)} },
+ { AFDIVRF, yfmvx, Px, {0xd8,(07)} },
+ { AFDIVRD, yfadd, Px, {0xdc,(07),0xd8,(07),0xdc,(06)} },
+
+ { AFXCHD, yfxch, Px, {0xd9,(01),0xd9,(01)} },
{ AFFREE },
- { AFLDCW, ystcw, Px, 0xd9,(05),0xd9,(05) },
- { AFLDENV, ystcw, Px, 0xd9,(04),0xd9,(04) },
- { AFRSTOR, ysvrs, Px, 0xdd,(04),0xdd,(04) },
- { AFSAVE, ysvrs, Px, 0xdd,(06),0xdd,(06) },
- { AFSTCW, ystcw, Px, 0xd9,(07),0xd9,(07) },
- { AFSTENV, ystcw, Px, 0xd9,(06),0xd9,(06) },
- { AFSTSW, ystsw, Px, 0xdd,(07),0xdf,0xe0 },
- { AF2XM1, ynone, Px, 0xd9, 0xf0 },
- { AFABS, ynone, Px, 0xd9, 0xe1 },
- { AFCHS, ynone, Px, 0xd9, 0xe0 },
- { AFCLEX, ynone, Px, 0xdb, 0xe2 },
- { AFCOS, ynone, Px, 0xd9, 0xff },
- { AFDECSTP, ynone, Px, 0xd9, 0xf6 },
- { AFINCSTP, ynone, Px, 0xd9, 0xf7 },
- { AFINIT, ynone, Px, 0xdb, 0xe3 },
- { AFLD1, ynone, Px, 0xd9, 0xe8 },
- { AFLDL2E, ynone, Px, 0xd9, 0xea },
- { AFLDL2T, ynone, Px, 0xd9, 0xe9 },
- { AFLDLG2, ynone, Px, 0xd9, 0xec },
- { AFLDLN2, ynone, Px, 0xd9, 0xed },
- { AFLDPI, ynone, Px, 0xd9, 0xeb },
- { AFLDZ, ynone, Px, 0xd9, 0xee },
- { AFNOP, ynone, Px, 0xd9, 0xd0 },
- { AFPATAN, ynone, Px, 0xd9, 0xf3 },
- { AFPREM, ynone, Px, 0xd9, 0xf8 },
- { AFPREM1, ynone, Px, 0xd9, 0xf5 },
- { AFPTAN, ynone, Px, 0xd9, 0xf2 },
- { AFRNDINT, ynone, Px, 0xd9, 0xfc },
- { AFSCALE, ynone, Px, 0xd9, 0xfd },
- { AFSIN, ynone, Px, 0xd9, 0xfe },
- { AFSINCOS, ynone, Px, 0xd9, 0xfb },
- { AFSQRT, ynone, Px, 0xd9, 0xfa },
- { AFTST, ynone, Px, 0xd9, 0xe4 },
- { AFXAM, ynone, Px, 0xd9, 0xe5 },
- { AFXTRACT, ynone, Px, 0xd9, 0xf4 },
- { AFYL2X, ynone, Px, 0xd9, 0xf1 },
- { AFYL2XP1, ynone, Px, 0xd9, 0xf9 },
-
- { ACMPXCHGB, yrb_mb, Pb, 0x0f,0xb0 },
- { ACMPXCHGL, yrl_ml, Px, 0x0f,0xb1 },
- { ACMPXCHGW, yrl_ml, Pe, 0x0f,0xb1 },
- { ACMPXCHGQ, yrl_ml, Pw, 0x0f,0xb1 },
- { ACMPXCHG8B, yscond, Pm, 0xc7,(01) },
- { AINVD, ynone, Pm, 0x08 },
- { AINVLPG, ymbs, Pm, 0x01,(07) },
- { ALFENCE, ynone, Pm, 0xae,0xe8 },
- { AMFENCE, ynone, Pm, 0xae,0xf0 },
- { AMOVNTIL, yrl_ml, Pm, 0xc3 },
- { AMOVNTIQ, yrl_ml, Pw, 0x0f,0xc3 },
- { ARDMSR, ynone, Pm, 0x32 },
- { ARDPMC, ynone, Pm, 0x33 },
- { ARDTSC, ynone, Pm, 0x31 },
- { ARSM, ynone, Pm, 0xaa },
- { ASFENCE, ynone, Pm, 0xae,0xf8 },
- { ASYSRET, ynone, Pm, 0x07 },
- { AWBINVD, ynone, Pm, 0x09 },
- { AWRMSR, ynone, Pm, 0x30 },
-
- { AXADDB, yrb_mb, Pb, 0x0f,0xc0 },
- { AXADDL, yrl_ml, Px, 0x0f,0xc1 },
- { AXADDQ, yrl_ml, Pw, 0x0f,0xc1 },
- { AXADDW, yrl_ml, Pe, 0x0f,0xc1 },
-
- { ACRC32B, ycrc32l,Px, 0xf2,0x0f,0x38,0xf0,0 },
- { ACRC32Q, ycrc32l,Pw, 0xf2,0x0f,0x38,0xf1,0 },
+ { AFLDCW, ystcw, Px, {0xd9,(05),0xd9,(05)} },
+ { AFLDENV, ystcw, Px, {0xd9,(04),0xd9,(04)} },
+ { AFRSTOR, ysvrs, Px, {0xdd,(04),0xdd,(04)} },
+ { AFSAVE, ysvrs, Px, {0xdd,(06),0xdd,(06)} },
+ { AFSTCW, ystcw, Px, {0xd9,(07),0xd9,(07)} },
+ { AFSTENV, ystcw, Px, {0xd9,(06),0xd9,(06)} },
+ { AFSTSW, ystsw, Px, {0xdd,(07),0xdf,0xe0} },
+ { AF2XM1, ynone, Px, {0xd9, 0xf0} },
+ { AFABS, ynone, Px, {0xd9, 0xe1} },
+ { AFCHS, ynone, Px, {0xd9, 0xe0} },
+ { AFCLEX, ynone, Px, {0xdb, 0xe2} },
+ { AFCOS, ynone, Px, {0xd9, 0xff} },
+ { AFDECSTP, ynone, Px, {0xd9, 0xf6} },
+ { AFINCSTP, ynone, Px, {0xd9, 0xf7} },
+ { AFINIT, ynone, Px, {0xdb, 0xe3} },
+ { AFLD1, ynone, Px, {0xd9, 0xe8} },
+ { AFLDL2E, ynone, Px, {0xd9, 0xea} },
+ { AFLDL2T, ynone, Px, {0xd9, 0xe9} },
+ { AFLDLG2, ynone, Px, {0xd9, 0xec} },
+ { AFLDLN2, ynone, Px, {0xd9, 0xed} },
+ { AFLDPI, ynone, Px, {0xd9, 0xeb} },
+ { AFLDZ, ynone, Px, {0xd9, 0xee} },
+ { AFNOP, ynone, Px, {0xd9, 0xd0} },
+ { AFPATAN, ynone, Px, {0xd9, 0xf3} },
+ { AFPREM, ynone, Px, {0xd9, 0xf8} },
+ { AFPREM1, ynone, Px, {0xd9, 0xf5} },
+ { AFPTAN, ynone, Px, {0xd9, 0xf2} },
+ { AFRNDINT, ynone, Px, {0xd9, 0xfc} },
+ { AFSCALE, ynone, Px, {0xd9, 0xfd} },
+ { AFSIN, ynone, Px, {0xd9, 0xfe} },
+ { AFSINCOS, ynone, Px, {0xd9, 0xfb} },
+ { AFSQRT, ynone, Px, {0xd9, 0xfa} },
+ { AFTST, ynone, Px, {0xd9, 0xe4} },
+ { AFXAM, ynone, Px, {0xd9, 0xe5} },
+ { AFXTRACT, ynone, Px, {0xd9, 0xf4} },
+ { AFYL2X, ynone, Px, {0xd9, 0xf1} },
+ { AFYL2XP1, ynone, Px, {0xd9, 0xf9} },
+
+ { ACMPXCHGB, yrb_mb, Pb, {0x0f,0xb0} },
+ { ACMPXCHGL, yrl_ml, Px, {0x0f,0xb1} },
+ { ACMPXCHGW, yrl_ml, Pe, {0x0f,0xb1} },
+ { ACMPXCHGQ, yrl_ml, Pw, {0x0f,0xb1} },
+ { ACMPXCHG8B, yscond, Pm, {0xc7,(01)} },
+ { AINVD, ynone, Pm, {0x08} },
+ { AINVLPG, ymbs, Pm, {0x01,(07)} },
+ { ALFENCE, ynone, Pm, {0xae,0xe8} },
+ { AMFENCE, ynone, Pm, {0xae,0xf0} },
+ { AMOVNTIL, yrl_ml, Pm, {0xc3} },
+ { AMOVNTIQ, yrl_ml, Pw, {0x0f,0xc3} },
+ { ARDMSR, ynone, Pm, {0x32} },
+ { ARDPMC, ynone, Pm, {0x33} },
+ { ARDTSC, ynone, Pm, {0x31} },
+ { ARSM, ynone, Pm, {0xaa} },
+ { ASFENCE, ynone, Pm, {0xae,0xf8} },
+ { ASYSRET, ynone, Pm, {0x07} },
+ { AWBINVD, ynone, Pm, {0x09} },
+ { AWRMSR, ynone, Pm, {0x30} },
+
+ { AXADDB, yrb_mb, Pb, {0x0f,0xc0} },
+ { AXADDL, yrl_ml, Px, {0x0f,0xc1} },
+ { AXADDQ, yrl_ml, Pw, {0x0f,0xc1} },
+ { AXADDW, yrl_ml, Pe, {0x0f,0xc1} },
+
+ { ACRC32B, ycrc32l,Px, {0xf2,0x0f,0x38,0xf0,0} },
+ { ACRC32Q, ycrc32l,Pw, {0xf2,0x0f,0x38,0xf1,0} },
- { APREFETCHT0, yprefetch, Pm, 0x18,(01) },
- { APREFETCHT1, yprefetch, Pm, 0x18,(02) },
- { APREFETCHT2, yprefetch, Pm, 0x18,(03) },
- { APREFETCHNTA, yprefetch, Pm, 0x18,(00) },
+ { APREFETCHT0, yprefetch, Pm, {0x18,(01)} },
+ { APREFETCHT1, yprefetch, Pm, {0x18,(02)} },
+ { APREFETCHT2, yprefetch, Pm, {0x18,(03)} },
+ { APREFETCHNTA, yprefetch, Pm, {0x18,(00)} },
- { AMOVQL, yrl_ml, Px, 0x89 },
+ { AMOVQL, yrl_ml, Px, {0x89} },
- { AUNDEF, ynone, Px, 0x0f, 0x0b },
+ { AUNDEF, ynone, Px, {0x0f, 0x0b} },
- { AAESENC, yaes, Pq, 0x38,0xdc,(0) },
- { AAESENCLAST, yaes, Pq, 0x38,0xdd,(0) },
- { AAESDEC, yaes, Pq, 0x38,0xde,(0) },
- { AAESDECLAST, yaes, Pq, 0x38,0xdf,(0) },
- { AAESIMC, yaes, Pq, 0x38,0xdb,(0) },
- { AAESKEYGENASSIST, yaes2, Pq, 0x3a,0xdf,(0) },
+ { AAESENC, yaes, Pq, {0x38,0xdc,(0)} },
+ { AAESENCLAST, yaes, Pq, {0x38,0xdd,(0)} },
+ { AAESDEC, yaes, Pq, {0x38,0xde,(0)} },
+ { AAESDECLAST, yaes, Pq, {0x38,0xdf,(0)} },
+ { AAESIMC, yaes, Pq, {0x38,0xdb,(0)} },
+ { AAESKEYGENASSIST, yaes2, Pq, {0x3a,0xdf,(0)} },
- { APSHUFD, yaes2, Pq, 0x70,(0) },
- { APCLMULQDQ, yxshuf, Pq, 0x3a,0x44,0 },
+ { APSHUFD, yaes2, Pq, {0x70,(0)} },
+ { APCLMULQDQ, yxshuf, Pq, {0x3a,0x44,0} },
- { AUSEFIELD, ynop, Px, 0,0 },
+ { AUSEFIELD, ynop, Px, {0,0} },
{ ATYPE },
- { AFUNCDATA, yfuncdata, Px, 0,0 },
- { APCDATA, ypcdata, Px, 0,0 },
+ { AFUNCDATA, yfuncdata, Px, {0,0} },
+ { APCDATA, ypcdata, Px, {0,0} },
{ ACHECKNIL },
{ AVARDEF },
{ AVARKILL },
- { ADUFFCOPY, yduff, Px, 0xe8 },
- { ADUFFZERO, yduff, Px, 0xe8 },
+ { ADUFFCOPY, yduff, Px, {0xe8} },
+ { ADUFFZERO, yduff, Px, {0xe8} },
{ AEND },
- 0
+ {0}
};
static Optab* opindex[ALAST+1];
static vlong vaddr(Link*, Addr*, Reloc*);
+// isextern reports whether s describes an external symbol that must avoid pc-relative addressing.
+// This happens on systems like Solaris that call .so functions instead of system calls.
+// It does not seem to be necessary for any other systems. This is probably working
+// around a Solaris-specific bug that should be fixed differently, but we don't know
+// what that bug is. And this does fix it.
+static int
+isextern(LSym *s)
+{
+ // All the Solaris dynamic imports from libc.so begin with "libc·", which
+ // the compiler rewrites to "libc." by the time liblink gets it.
+ return strncmp(s->name, "libc.", 5) == 0;
+}
+
// single-instruction no-ops of various lengths.
// constructed by hand and disassembled with gdb to verify.
// see http://www.agner.org/optimize/optimizing_assembly.pdf for discussion.
@@ -1901,7 +1912,6 @@ prefixof(Link *ctxt, Addr *a)
case Hlinux:
case Hnetbsd:
case Hopenbsd:
- case Hplan9:
case Hsolaris:
return 0x64; // FS
case Hdarwin:
@@ -1935,10 +1945,9 @@ oclass(Link *ctxt, Addr *a)
switch(a->index) {
case D_EXTERN:
case D_STATIC:
- if(ctxt->flag_shared || ctxt->headtype == Hnacl)
- return Yiauto;
- else
- return Yi32; /* TO DO: Yi64 */
+ if(a->sym != nil && isextern(a->sym))
+ return Yi32;
+ return Yiauto; // use pc-relative addressing
case D_AUTO:
case D_PARAM:
return Yiauto;
@@ -2115,7 +2124,7 @@ oclass(Link *ctxt, Addr *a)
return Yi32; /* unsigned */
return Yi64;
}
- return Yi32; /* TO DO: D_ADDR as Yi64 */
+ return Yi32;
case D_BRANCH:
return Ybr;
@@ -2288,20 +2297,22 @@ vaddr(Link *ctxt, Addr *a, Reloc *r)
ctxt->diag("need reloc for %D", a);
sysfatal("reloc");
}
- r->siz = 4; // TODO: 8 for external symbols
+ if(isextern(s)) {
+ r->siz = 4;
+ r->type = R_ADDR;
+ } else {
+ r->siz = 4;
+ r->type = R_PCREL;
+ }
r->off = -1; // caller must fill in
r->sym = s;
r->add = v;
v = 0;
- if(ctxt->flag_shared || ctxt->headtype == Hnacl) {
- if(s->type == STLSBSS) {
- r->xadd = r->add - r->siz;
- r->type = R_TLS;
- r->xsym = s;
- } else
- r->type = R_PCREL;
- } else
- r->type = R_ADDR;
+ if(s->type == STLSBSS) {
+ r->xadd = r->add - r->siz;
+ r->type = R_TLS;
+ r->xsym = s;
+ }
break;
case D_INDIR+D_TLS:
@@ -2336,9 +2347,9 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64)
switch(t) {
default:
goto bad;
- case D_STATIC:
case D_EXTERN:
- if(ctxt->flag_shared || ctxt->headtype == Hnacl)
+ case D_STATIC:
+ if(!isextern(a->sym))
goto bad;
t = D_NONE;
v = vaddr(ctxt, a, &rel);
@@ -2402,7 +2413,7 @@ asmandsz(Link *ctxt, Addr *a, int r, int rex, int m64)
ctxt->rexflag |= (regrex[t] & Rxb) | rex;
if(t == D_NONE || (D_CS <= t && t <= D_GS) || t == D_TLS) {
- if((ctxt->flag_shared || ctxt->headtype == Hnacl) && t == D_NONE && (a->type == D_STATIC || a->type == D_EXTERN) || ctxt->asmode != 64) {
+ if((a->sym == nil || !isextern(a->sym)) && t == D_NONE && (a->type == D_STATIC || a->type == D_EXTERN) || ctxt->asmode != 64) {
*ctxt->andptr++ = (0 << 6) | (5 << 0) | (r << 3);
goto putrelv;
}
@@ -2485,7 +2496,7 @@ asmando(Link *ctxt, Addr *a, int o)
}
static void
-bytereg(Addr *a, char *t)
+bytereg(Addr *a, uint8 *t)
{
if(a->index == D_NONE && (a->type >= D_AX && a->type <= D_R15)) {
a->type = D_AL + (a->type-D_AX);
@@ -2493,139 +2504,141 @@ bytereg(Addr *a, char *t)
}
}
-#define E 0xff
+enum {
+ E = 0xff,
+};
static Movtab ymovtab[] =
{
/* push */
- {APUSHL, Ycs, Ynone, 0, 0x0e,E,0,0},
- {APUSHL, Yss, Ynone, 0, 0x16,E,0,0},
- {APUSHL, Yds, Ynone, 0, 0x1e,E,0,0},
- {APUSHL, Yes, Ynone, 0, 0x06,E,0,0},
- {APUSHL, Yfs, Ynone, 0, 0x0f,0xa0,E,0},
- {APUSHL, Ygs, Ynone, 0, 0x0f,0xa8,E,0},
- {APUSHQ, Yfs, Ynone, 0, 0x0f,0xa0,E,0},
- {APUSHQ, Ygs, Ynone, 0, 0x0f,0xa8,E,0},
-
- {APUSHW, Ycs, Ynone, 0, Pe,0x0e,E,0},
- {APUSHW, Yss, Ynone, 0, Pe,0x16,E,0},
- {APUSHW, Yds, Ynone, 0, Pe,0x1e,E,0},
- {APUSHW, Yes, Ynone, 0, Pe,0x06,E,0},
- {APUSHW, Yfs, Ynone, 0, Pe,0x0f,0xa0,E},
- {APUSHW, Ygs, Ynone, 0, Pe,0x0f,0xa8,E},
+ {APUSHL, Ycs, Ynone, 0, {0x0e,E,0,0}},
+ {APUSHL, Yss, Ynone, 0, {0x16,E,0,0}},
+ {APUSHL, Yds, Ynone, 0, {0x1e,E,0,0}},
+ {APUSHL, Yes, Ynone, 0, {0x06,E,0,0}},
+ {APUSHL, Yfs, Ynone, 0, {0x0f,0xa0,E,0}},
+ {APUSHL, Ygs, Ynone, 0, {0x0f,0xa8,E,0}},
+ {APUSHQ, Yfs, Ynone, 0, {0x0f,0xa0,E,0}},
+ {APUSHQ, Ygs, Ynone, 0, {0x0f,0xa8,E,0}},
+
+ {APUSHW, Ycs, Ynone, 0, {Pe,0x0e,E,0}},
+ {APUSHW, Yss, Ynone, 0, {Pe,0x16,E,0}},
+ {APUSHW, Yds, Ynone, 0, {Pe,0x1e,E,0}},
+ {APUSHW, Yes, Ynone, 0, {Pe,0x06,E,0}},
+ {APUSHW, Yfs, Ynone, 0, {Pe,0x0f,0xa0,E}},
+ {APUSHW, Ygs, Ynone, 0, {Pe,0x0f,0xa8,E}},
/* pop */
- {APOPL, Ynone, Yds, 0, 0x1f,E,0,0},
- {APOPL, Ynone, Yes, 0, 0x07,E,0,0},
- {APOPL, Ynone, Yss, 0, 0x17,E,0,0},
- {APOPL, Ynone, Yfs, 0, 0x0f,0xa1,E,0},
- {APOPL, Ynone, Ygs, 0, 0x0f,0xa9,E,0},
- {APOPQ, Ynone, Yfs, 0, 0x0f,0xa1,E,0},
- {APOPQ, Ynone, Ygs, 0, 0x0f,0xa9,E,0},
-
- {APOPW, Ynone, Yds, 0, Pe,0x1f,E,0},
- {APOPW, Ynone, Yes, 0, Pe,0x07,E,0},
- {APOPW, Ynone, Yss, 0, Pe,0x17,E,0},
- {APOPW, Ynone, Yfs, 0, Pe,0x0f,0xa1,E},
- {APOPW, Ynone, Ygs, 0, Pe,0x0f,0xa9,E},
+ {APOPL, Ynone, Yds, 0, {0x1f,E,0,0}},
+ {APOPL, Ynone, Yes, 0, {0x07,E,0,0}},
+ {APOPL, Ynone, Yss, 0, {0x17,E,0,0}},
+ {APOPL, Ynone, Yfs, 0, {0x0f,0xa1,E,0}},
+ {APOPL, Ynone, Ygs, 0, {0x0f,0xa9,E,0}},
+ {APOPQ, Ynone, Yfs, 0, {0x0f,0xa1,E,0}},
+ {APOPQ, Ynone, Ygs, 0, {0x0f,0xa9,E,0}},
+
+ {APOPW, Ynone, Yds, 0, {Pe,0x1f,E,0}},
+ {APOPW, Ynone, Yes, 0, {Pe,0x07,E,0}},
+ {APOPW, Ynone, Yss, 0, {Pe,0x17,E,0}},
+ {APOPW, Ynone, Yfs, 0, {Pe,0x0f,0xa1,E}},
+ {APOPW, Ynone, Ygs, 0, {Pe,0x0f,0xa9,E}},
/* mov seg */
- {AMOVW, Yes, Yml, 1, 0x8c,0,0,0},
- {AMOVW, Ycs, Yml, 1, 0x8c,1,0,0},
- {AMOVW, Yss, Yml, 1, 0x8c,2,0,0},
- {AMOVW, Yds, Yml, 1, 0x8c,3,0,0},
- {AMOVW, Yfs, Yml, 1, 0x8c,4,0,0},
- {AMOVW, Ygs, Yml, 1, 0x8c,5,0,0},
-
- {AMOVW, Yml, Yes, 2, 0x8e,0,0,0},
- {AMOVW, Yml, Ycs, 2, 0x8e,1,0,0},
- {AMOVW, Yml, Yss, 2, 0x8e,2,0,0},
- {AMOVW, Yml, Yds, 2, 0x8e,3,0,0},
- {AMOVW, Yml, Yfs, 2, 0x8e,4,0,0},
- {AMOVW, Yml, Ygs, 2, 0x8e,5,0,0},
+ {AMOVW, Yes, Yml, 1, {0x8c,0,0,0}},
+ {AMOVW, Ycs, Yml, 1, {0x8c,1,0,0}},
+ {AMOVW, Yss, Yml, 1, {0x8c,2,0,0}},
+ {AMOVW, Yds, Yml, 1, {0x8c,3,0,0}},
+ {AMOVW, Yfs, Yml, 1, {0x8c,4,0,0}},
+ {AMOVW, Ygs, Yml, 1, {0x8c,5,0,0}},
+
+ {AMOVW, Yml, Yes, 2, {0x8e,0,0,0}},
+ {AMOVW, Yml, Ycs, 2, {0x8e,1,0,0}},
+ {AMOVW, Yml, Yss, 2, {0x8e,2,0,0}},
+ {AMOVW, Yml, Yds, 2, {0x8e,3,0,0}},
+ {AMOVW, Yml, Yfs, 2, {0x8e,4,0,0}},
+ {AMOVW, Yml, Ygs, 2, {0x8e,5,0,0}},
/* mov cr */
- {AMOVL, Ycr0, Yml, 3, 0x0f,0x20,0,0},
- {AMOVL, Ycr2, Yml, 3, 0x0f,0x20,2,0},
- {AMOVL, Ycr3, Yml, 3, 0x0f,0x20,3,0},
- {AMOVL, Ycr4, Yml, 3, 0x0f,0x20,4,0},
- {AMOVL, Ycr8, Yml, 3, 0x0f,0x20,8,0},
- {AMOVQ, Ycr0, Yml, 3, 0x0f,0x20,0,0},
- {AMOVQ, Ycr2, Yml, 3, 0x0f,0x20,2,0},
- {AMOVQ, Ycr3, Yml, 3, 0x0f,0x20,3,0},
- {AMOVQ, Ycr4, Yml, 3, 0x0f,0x20,4,0},
- {AMOVQ, Ycr8, Yml, 3, 0x0f,0x20,8,0},
-
- {AMOVL, Yml, Ycr0, 4, 0x0f,0x22,0,0},
- {AMOVL, Yml, Ycr2, 4, 0x0f,0x22,2,0},
- {AMOVL, Yml, Ycr3, 4, 0x0f,0x22,3,0},
- {AMOVL, Yml, Ycr4, 4, 0x0f,0x22,4,0},
- {AMOVL, Yml, Ycr8, 4, 0x0f,0x22,8,0},
- {AMOVQ, Yml, Ycr0, 4, 0x0f,0x22,0,0},
- {AMOVQ, Yml, Ycr2, 4, 0x0f,0x22,2,0},
- {AMOVQ, Yml, Ycr3, 4, 0x0f,0x22,3,0},
- {AMOVQ, Yml, Ycr4, 4, 0x0f,0x22,4,0},
- {AMOVQ, Yml, Ycr8, 4, 0x0f,0x22,8,0},
+ {AMOVL, Ycr0, Yml, 3, {0x0f,0x20,0,0}},
+ {AMOVL, Ycr2, Yml, 3, {0x0f,0x20,2,0}},
+ {AMOVL, Ycr3, Yml, 3, {0x0f,0x20,3,0}},
+ {AMOVL, Ycr4, Yml, 3, {0x0f,0x20,4,0}},
+ {AMOVL, Ycr8, Yml, 3, {0x0f,0x20,8,0}},
+ {AMOVQ, Ycr0, Yml, 3, {0x0f,0x20,0,0}},
+ {AMOVQ, Ycr2, Yml, 3, {0x0f,0x20,2,0}},
+ {AMOVQ, Ycr3, Yml, 3, {0x0f,0x20,3,0}},
+ {AMOVQ, Ycr4, Yml, 3, {0x0f,0x20,4,0}},
+ {AMOVQ, Ycr8, Yml, 3, {0x0f,0x20,8,0}},
+
+ {AMOVL, Yml, Ycr0, 4, {0x0f,0x22,0,0}},
+ {AMOVL, Yml, Ycr2, 4, {0x0f,0x22,2,0}},
+ {AMOVL, Yml, Ycr3, 4, {0x0f,0x22,3,0}},
+ {AMOVL, Yml, Ycr4, 4, {0x0f,0x22,4,0}},
+ {AMOVL, Yml, Ycr8, 4, {0x0f,0x22,8,0}},
+ {AMOVQ, Yml, Ycr0, 4, {0x0f,0x22,0,0}},
+ {AMOVQ, Yml, Ycr2, 4, {0x0f,0x22,2,0}},
+ {AMOVQ, Yml, Ycr3, 4, {0x0f,0x22,3,0}},
+ {AMOVQ, Yml, Ycr4, 4, {0x0f,0x22,4,0}},
+ {AMOVQ, Yml, Ycr8, 4, {0x0f,0x22,8,0}},
/* mov dr */
- {AMOVL, Ydr0, Yml, 3, 0x0f,0x21,0,0},
- {AMOVL, Ydr6, Yml, 3, 0x0f,0x21,6,0},
- {AMOVL, Ydr7, Yml, 3, 0x0f,0x21,7,0},
- {AMOVQ, Ydr0, Yml, 3, 0x0f,0x21,0,0},
- {AMOVQ, Ydr6, Yml, 3, 0x0f,0x21,6,0},
- {AMOVQ, Ydr7, Yml, 3, 0x0f,0x21,7,0},
-
- {AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0},
- {AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0},
- {AMOVL, Yml, Ydr7, 4, 0x0f,0x23,7,0},
- {AMOVQ, Yml, Ydr0, 4, 0x0f,0x23,0,0},
- {AMOVQ, Yml, Ydr6, 4, 0x0f,0x23,6,0},
- {AMOVQ, Yml, Ydr7, 4, 0x0f,0x23,7,0},
+ {AMOVL, Ydr0, Yml, 3, {0x0f,0x21,0,0}},
+ {AMOVL, Ydr6, Yml, 3, {0x0f,0x21,6,0}},
+ {AMOVL, Ydr7, Yml, 3, {0x0f,0x21,7,0}},
+ {AMOVQ, Ydr0, Yml, 3, {0x0f,0x21,0,0}},
+ {AMOVQ, Ydr6, Yml, 3, {0x0f,0x21,6,0}},
+ {AMOVQ, Ydr7, Yml, 3, {0x0f,0x21,7,0}},
+
+ {AMOVL, Yml, Ydr0, 4, {0x0f,0x23,0,0}},
+ {AMOVL, Yml, Ydr6, 4, {0x0f,0x23,6,0}},
+ {AMOVL, Yml, Ydr7, 4, {0x0f,0x23,7,0}},
+ {AMOVQ, Yml, Ydr0, 4, {0x0f,0x23,0,0}},
+ {AMOVQ, Yml, Ydr6, 4, {0x0f,0x23,6,0}},
+ {AMOVQ, Yml, Ydr7, 4, {0x0f,0x23,7,0}},
/* mov tr */
- {AMOVL, Ytr6, Yml, 3, 0x0f,0x24,6,0},
- {AMOVL, Ytr7, Yml, 3, 0x0f,0x24,7,0},
+ {AMOVL, Ytr6, Yml, 3, {0x0f,0x24,6,0}},
+ {AMOVL, Ytr7, Yml, 3, {0x0f,0x24,7,0}},
- {AMOVL, Yml, Ytr6, 4, 0x0f,0x26,6,E},
- {AMOVL, Yml, Ytr7, 4, 0x0f,0x26,7,E},
+ {AMOVL, Yml, Ytr6, 4, {0x0f,0x26,6,E}},
+ {AMOVL, Yml, Ytr7, 4, {0x0f,0x26,7,E}},
/* lgdt, sgdt, lidt, sidt */
- {AMOVL, Ym, Ygdtr, 4, 0x0f,0x01,2,0},
- {AMOVL, Ygdtr, Ym, 3, 0x0f,0x01,0,0},
- {AMOVL, Ym, Yidtr, 4, 0x0f,0x01,3,0},
- {AMOVL, Yidtr, Ym, 3, 0x0f,0x01,1,0},
- {AMOVQ, Ym, Ygdtr, 4, 0x0f,0x01,2,0},
- {AMOVQ, Ygdtr, Ym, 3, 0x0f,0x01,0,0},
- {AMOVQ, Ym, Yidtr, 4, 0x0f,0x01,3,0},
- {AMOVQ, Yidtr, Ym, 3, 0x0f,0x01,1,0},
+ {AMOVL, Ym, Ygdtr, 4, {0x0f,0x01,2,0}},
+ {AMOVL, Ygdtr, Ym, 3, {0x0f,0x01,0,0}},
+ {AMOVL, Ym, Yidtr, 4, {0x0f,0x01,3,0}},
+ {AMOVL, Yidtr, Ym, 3, {0x0f,0x01,1,0}},
+ {AMOVQ, Ym, Ygdtr, 4, {0x0f,0x01,2,0}},
+ {AMOVQ, Ygdtr, Ym, 3, {0x0f,0x01,0,0}},
+ {AMOVQ, Ym, Yidtr, 4, {0x0f,0x01,3,0}},
+ {AMOVQ, Yidtr, Ym, 3, {0x0f,0x01,1,0}},
/* lldt, sldt */
- {AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0},
- {AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0},
+ {AMOVW, Yml, Yldtr, 4, {0x0f,0x00,2,0}},
+ {AMOVW, Yldtr, Yml, 3, {0x0f,0x00,0,0}},
/* lmsw, smsw */
- {AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0},
- {AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0},
+ {AMOVW, Yml, Ymsw, 4, {0x0f,0x01,6,0}},
+ {AMOVW, Ymsw, Yml, 3, {0x0f,0x01,4,0}},
/* ltr, str */
- {AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0},
- {AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0},
+ {AMOVW, Yml, Ytask, 4, {0x0f,0x00,3,0}},
+ {AMOVW, Ytask, Yml, 3, {0x0f,0x00,1,0}},
/* load full pointer */
- {AMOVL, Yml, Ycol, 5, 0,0,0,0},
- {AMOVW, Yml, Ycol, 5, Pe,0,0,0},
+ {AMOVL, Yml, Ycol, 5, {0,0,0,0}},
+ {AMOVW, Yml, Ycol, 5, {Pe,0,0,0}},
/* double shift */
- {ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0},
- {ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0},
- {ASHLQ, Ycol, Yml, 6, Pw,0xa4,0xa5,0},
- {ASHRQ, Ycol, Yml, 6, Pw,0xac,0xad,0},
- {ASHLW, Ycol, Yml, 6, Pe,0xa4,0xa5,0},
- {ASHRW, Ycol, Yml, 6, Pe,0xac,0xad,0},
+ {ASHLL, Ycol, Yml, 6, {0xa4,0xa5,0,0}},
+ {ASHRL, Ycol, Yml, 6, {0xac,0xad,0,0}},
+ {ASHLQ, Ycol, Yml, 6, {Pw,0xa4,0xa5,0}},
+ {ASHRQ, Ycol, Yml, 6, {Pw,0xac,0xad,0}},
+ {ASHLW, Ycol, Yml, 6, {Pe,0xa4,0xa5,0}},
+ {ASHRW, Ycol, Yml, 6, {Pe,0xac,0xad,0}},
/* load TLS base */
- {AMOVQ, Ytls, Yrl, 7, 0,0,0,0},
+ {AMOVQ, Ytls, Yrl, 7, {0,0,0,0}},
- 0
+ {0}
};
static int
@@ -2687,7 +2700,7 @@ mediaop(Link *ctxt, Optab *o, int op, int osize, int z)
break;
}
default:
- if(ctxt->andptr == ctxt->and || ctxt->andptr[-1] != Pm)
+ if(ctxt->andptr == ctxt->and || ctxt->and[ctxt->andptr - ctxt->and - 1] != Pm)
*ctxt->andptr++ = Pm;
break;
}
@@ -2903,8 +2916,13 @@ found:
asmando(ctxt, &p->to, o->op[z+1]);
break;
+ case Zcallindreg:
+ r = addrel(ctxt->cursym);
+ r->off = p->pc;
+ r->type = R_CALLIND;
+ r->siz = 0;
+ // fallthrough
case Zo_m64:
- case_Zo_m64:
*ctxt->andptr++ = op;
asmandsz(ctxt, &p->to, o->op[z+1], 0, 1);
break;
@@ -3062,6 +3080,7 @@ found:
break;
case Zclr:
+ ctxt->rexflag &= ~Pw;
*ctxt->andptr++ = op;
asmand(ctxt, &p->to, &p->to);
break;
@@ -3081,13 +3100,6 @@ found:
put4(ctxt, 0);
break;
- case Zcallindreg:
- r = addrel(ctxt->cursym);
- r->off = p->pc;
- r->type = R_CALLIND;
- r->siz = 0;
- goto case_Zo_m64;
-
case Zbr:
case Zjmp:
case Zloop:
@@ -3365,6 +3377,19 @@ mfound:
default:
sysfatal("unknown TLS base location for %s", headstr(ctxt->headtype));
+ case Hplan9:
+ if(ctxt->plan9privates == nil)
+ ctxt->plan9privates = linklookup(ctxt, "_privates", 0);
+ memset(&pp.from, 0, sizeof pp.from);
+ pp.from.type = D_EXTERN;
+ pp.from.sym = ctxt->plan9privates;
+ pp.from.offset = 0;
+ pp.from.index = D_NONE;
+ ctxt->rexflag |= Pw;
+ *ctxt->andptr++ = 0x8B;
+ asmand(ctxt, &pp.from, &p->to);
+ break;
+
case Hsolaris: // TODO(rsc): Delete Hsolaris from list. Should not use this code. See progedit in obj6.c.
// TLS base is 0(FS).
pp.from = p->from;
@@ -3436,7 +3461,7 @@ nacltrunc(Link *ctxt, int reg)
static void
asmins(Link *ctxt, Prog *p)
{
- int n, np, c;
+ int i, n, np, c;
uchar *and0;
Reloc *r;
@@ -3561,7 +3586,8 @@ asmins(Link *ctxt, Prog *p)
ctxt->andptr++;
}
n = ctxt->andptr - ctxt->and;
- for(r=ctxt->cursym->r+ctxt->cursym->nr; r-- > ctxt->cursym->r; ) {
+ for(i=ctxt->cursym->nr-1; i>=0; i--) {
+ r = ctxt->cursym->r+i;
if(r->off < p->pc)
break;
if(ctxt->rexflag)
diff --git a/src/liblink/asm8.c b/src/liblink/asm8.c
index 3ab527ce8..b6627d5fd 100644
--- a/src/liblink/asm8.c
+++ b/src/liblink/asm8.c
@@ -35,7 +35,7 @@
#include <bio.h>
#include <link.h>
#include "../cmd/8l/8.out.h"
-#include "../pkg/runtime/stack.h"
+#include "../runtime/stack.h"
enum
{
@@ -43,8 +43,6 @@ enum
FuncAlign = 16
};
-extern char *anames6[];
-
typedef struct Optab Optab;
struct Optab
@@ -142,7 +140,7 @@ enum
};
static uchar ycover[Ymax*Ymax];
-static char reg[D_NONE];
+static int reg[D_NONE];
static void asmins(Link *ctxt, Prog *p);
static uchar ynone[] =
@@ -617,548 +615,548 @@ static Optab optab[] =
/* as, ytab, andproto, opcode */
{
{ AXXX },
- { AAAA, ynone, Px, 0x37 },
- { AAAD, ynone, Px, 0xd5,0x0a },
- { AAAM, ynone, Px, 0xd4,0x0a },
- { AAAS, ynone, Px, 0x3f },
- { AADCB, yxorb, Pb, 0x14,0x80,(02),0x10,0x10 },
- { AADCL, yxorl, Px, 0x83,(02),0x15,0x81,(02),0x11,0x13 },
- { AADCW, yxorl, Pe, 0x83,(02),0x15,0x81,(02),0x11,0x13 },
- { AADDB, yxorb, Px, 0x04,0x80,(00),0x00,0x02 },
- { AADDL, yaddl, Px, 0x83,(00),0x05,0x81,(00),0x01,0x03 },
- { AADDW, yaddl, Pe, 0x83,(00),0x05,0x81,(00),0x01,0x03 },
+ { AAAA, ynone, Px, {0x37} },
+ { AAAD, ynone, Px, {0xd5,0x0a} },
+ { AAAM, ynone, Px, {0xd4,0x0a} },
+ { AAAS, ynone, Px, {0x3f} },
+ { AADCB, yxorb, Pb, {0x14,0x80,(02),0x10,0x10} },
+ { AADCL, yxorl, Px, {0x83,(02),0x15,0x81,(02),0x11,0x13} },
+ { AADCW, yxorl, Pe, {0x83,(02),0x15,0x81,(02),0x11,0x13} },
+ { AADDB, yxorb, Px, {0x04,0x80,(00),0x00,0x02} },
+ { AADDL, yaddl, Px, {0x83,(00),0x05,0x81,(00),0x01,0x03} },
+ { AADDW, yaddl, Pe, {0x83,(00),0x05,0x81,(00),0x01,0x03} },
{ AADJSP },
- { AANDB, yxorb, Pb, 0x24,0x80,(04),0x20,0x22 },
- { AANDL, yxorl, Px, 0x83,(04),0x25,0x81,(04),0x21,0x23 },
- { AANDW, yxorl, Pe, 0x83,(04),0x25,0x81,(04),0x21,0x23 },
- { AARPL, yrl_ml, Px, 0x63 },
- { ABOUNDL, yrl_m, Px, 0x62 },
- { ABOUNDW, yrl_m, Pe, 0x62 },
- { ABSFL, yml_rl, Pm, 0xbc },
- { ABSFW, yml_rl, Pq, 0xbc },
- { ABSRL, yml_rl, Pm, 0xbd },
- { ABSRW, yml_rl, Pq, 0xbd },
- { ABTL, yml_rl, Pm, 0xa3 },
- { ABTW, yml_rl, Pq, 0xa3 },
- { ABTCL, yml_rl, Pm, 0xbb },
- { ABTCW, yml_rl, Pq, 0xbb },
- { ABTRL, yml_rl, Pm, 0xb3 },
- { ABTRW, yml_rl, Pq, 0xb3 },
- { ABTSL, yml_rl, Pm, 0xab },
- { ABTSW, yml_rl, Pq, 0xab },
- { ABYTE, ybyte, Px, 1 },
- { ACALL, ycall, Px, 0xff,(02),0xff,(0x15),0xe8 },
- { ACLC, ynone, Px, 0xf8 },
- { ACLD, ynone, Px, 0xfc },
- { ACLI, ynone, Px, 0xfa },
- { ACLTS, ynone, Pm, 0x06 },
- { ACMC, ynone, Px, 0xf5 },
- { ACMPB, ycmpb, Pb, 0x3c,0x80,(07),0x38,0x3a },
- { ACMPL, ycmpl, Px, 0x83,(07),0x3d,0x81,(07),0x39,0x3b },
- { ACMPW, ycmpl, Pe, 0x83,(07),0x3d,0x81,(07),0x39,0x3b },
- { ACMPSB, ynone, Pb, 0xa6 },
- { ACMPSL, ynone, Px, 0xa7 },
- { ACMPSW, ynone, Pe, 0xa7 },
- { ADAA, ynone, Px, 0x27 },
- { ADAS, ynone, Px, 0x2f },
+ { AANDB, yxorb, Pb, {0x24,0x80,(04),0x20,0x22} },
+ { AANDL, yxorl, Px, {0x83,(04),0x25,0x81,(04),0x21,0x23} },
+ { AANDW, yxorl, Pe, {0x83,(04),0x25,0x81,(04),0x21,0x23} },
+ { AARPL, yrl_ml, Px, {0x63} },
+ { ABOUNDL, yrl_m, Px, {0x62} },
+ { ABOUNDW, yrl_m, Pe, {0x62} },
+ { ABSFL, yml_rl, Pm, {0xbc} },
+ { ABSFW, yml_rl, Pq, {0xbc} },
+ { ABSRL, yml_rl, Pm, {0xbd} },
+ { ABSRW, yml_rl, Pq, {0xbd} },
+ { ABTL, yml_rl, Pm, {0xa3} },
+ { ABTW, yml_rl, Pq, {0xa3} },
+ { ABTCL, yml_rl, Pm, {0xbb} },
+ { ABTCW, yml_rl, Pq, {0xbb} },
+ { ABTRL, yml_rl, Pm, {0xb3} },
+ { ABTRW, yml_rl, Pq, {0xb3} },
+ { ABTSL, yml_rl, Pm, {0xab} },
+ { ABTSW, yml_rl, Pq, {0xab} },
+ { ABYTE, ybyte, Px, {1} },
+ { ACALL, ycall, Px, {0xff,(02),0xff,(0x15),0xe8} },
+ { ACLC, ynone, Px, {0xf8} },
+ { ACLD, ynone, Px, {0xfc} },
+ { ACLI, ynone, Px, {0xfa} },
+ { ACLTS, ynone, Pm, {0x06} },
+ { ACMC, ynone, Px, {0xf5} },
+ { ACMPB, ycmpb, Pb, {0x3c,0x80,(07),0x38,0x3a} },
+ { ACMPL, ycmpl, Px, {0x83,(07),0x3d,0x81,(07),0x39,0x3b} },
+ { ACMPW, ycmpl, Pe, {0x83,(07),0x3d,0x81,(07),0x39,0x3b} },
+ { ACMPSB, ynone, Pb, {0xa6} },
+ { ACMPSL, ynone, Px, {0xa7} },
+ { ACMPSW, ynone, Pe, {0xa7} },
+ { ADAA, ynone, Px, {0x27} },
+ { ADAS, ynone, Px, {0x2f} },
{ ADATA },
- { ADECB, yincb, Pb, 0xfe,(01) },
- { ADECL, yincl, Px, 0x48,0xff,(01) },
- { ADECW, yincl, Pe, 0x48,0xff,(01) },
- { ADIVB, ydivb, Pb, 0xf6,(06) },
- { ADIVL, ydivl, Px, 0xf7,(06) },
- { ADIVW, ydivl, Pe, 0xf7,(06) },
+ { ADECB, yincb, Pb, {0xfe,(01)} },
+ { ADECL, yincl, Px, {0x48,0xff,(01)} },
+ { ADECW, yincl, Pe, {0x48,0xff,(01)} },
+ { ADIVB, ydivb, Pb, {0xf6,(06)} },
+ { ADIVL, ydivl, Px, {0xf7,(06)} },
+ { ADIVW, ydivl, Pe, {0xf7,(06)} },
{ AENTER }, /* botch */
{ AGLOBL },
{ AGOK },
{ AHISTORY },
- { AHLT, ynone, Px, 0xf4 },
- { AIDIVB, ydivb, Pb, 0xf6,(07) },
- { AIDIVL, ydivl, Px, 0xf7,(07) },
- { AIDIVW, ydivl, Pe, 0xf7,(07) },
- { AIMULB, ydivb, Pb, 0xf6,(05) },
- { AIMULL, yimul, Px, 0xf7,(05),0x6b,0x69 },
- { AIMULW, yimul, Pe, 0xf7,(05),0x6b,0x69 },
- { AINB, yin, Pb, 0xe4,0xec },
- { AINL, yin, Px, 0xe5,0xed },
- { AINW, yin, Pe, 0xe5,0xed },
- { AINCB, yincb, Pb, 0xfe,(00) },
- { AINCL, yincl, Px, 0x40,0xff,(00) },
- { AINCW, yincl, Pe, 0x40,0xff,(00) },
- { AINSB, ynone, Pb, 0x6c },
- { AINSL, ynone, Px, 0x6d },
- { AINSW, ynone, Pe, 0x6d },
- { AINT, yint, Px, 0xcd },
- { AINTO, ynone, Px, 0xce },
- { AIRETL, ynone, Px, 0xcf },
- { AIRETW, ynone, Pe, 0xcf },
- { AJCC, yjcond, Px, 0x73,0x83,(00) },
- { AJCS, yjcond, Px, 0x72,0x82 },
- { AJCXZL, yloop, Px, 0xe3 },
- { AJCXZW, yloop, Px, 0xe3 },
- { AJEQ, yjcond, Px, 0x74,0x84 },
- { AJGE, yjcond, Px, 0x7d,0x8d },
- { AJGT, yjcond, Px, 0x7f,0x8f },
- { AJHI, yjcond, Px, 0x77,0x87 },
- { AJLE, yjcond, Px, 0x7e,0x8e },
- { AJLS, yjcond, Px, 0x76,0x86 },
- { AJLT, yjcond, Px, 0x7c,0x8c },
- { AJMI, yjcond, Px, 0x78,0x88 },
- { AJMP, yjmp, Px, 0xff,(04),0xeb,0xe9 },
- { AJNE, yjcond, Px, 0x75,0x85 },
- { AJOC, yjcond, Px, 0x71,0x81,(00) },
- { AJOS, yjcond, Px, 0x70,0x80,(00) },
- { AJPC, yjcond, Px, 0x7b,0x8b },
- { AJPL, yjcond, Px, 0x79,0x89 },
- { AJPS, yjcond, Px, 0x7a,0x8a },
- { ALAHF, ynone, Px, 0x9f },
- { ALARL, yml_rl, Pm, 0x02 },
- { ALARW, yml_rl, Pq, 0x02 },
- { ALEAL, ym_rl, Px, 0x8d },
- { ALEAW, ym_rl, Pe, 0x8d },
- { ALEAVEL, ynone, Px, 0xc9 },
- { ALEAVEW, ynone, Pe, 0xc9 },
- { ALOCK, ynone, Px, 0xf0 },
- { ALODSB, ynone, Pb, 0xac },
- { ALODSL, ynone, Px, 0xad },
- { ALODSW, ynone, Pe, 0xad },
- { ALONG, ybyte, Px, 4 },
- { ALOOP, yloop, Px, 0xe2 },
- { ALOOPEQ, yloop, Px, 0xe1 },
- { ALOOPNE, yloop, Px, 0xe0 },
- { ALSLL, yml_rl, Pm, 0x03 },
- { ALSLW, yml_rl, Pq, 0x03 },
- { AMOVB, ymovb, Pb, 0x88,0x8a,0xb0,0xc6,(00) },
- { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),Pe,0x6e,Pe,0x7e,0 },
- { AMOVW, ymovw, Pe, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),0 },
- { AMOVQ, ymovq, Pf3, 0x7e },
- { AMOVBLSX, ymb_rl, Pm, 0xbe },
- { AMOVBLZX, ymb_rl, Pm, 0xb6 },
- { AMOVBWSX, ymb_rl, Pq, 0xbe },
- { AMOVBWZX, ymb_rl, Pq, 0xb6 },
- { AMOVWLSX, yml_rl, Pm, 0xbf },
- { AMOVWLZX, yml_rl, Pm, 0xb7 },
- { AMOVSB, ynone, Pb, 0xa4 },
- { AMOVSL, ynone, Px, 0xa5 },
- { AMOVSW, ynone, Pe, 0xa5 },
- { AMULB, ydivb, Pb, 0xf6,(04) },
- { AMULL, ydivl, Px, 0xf7,(04) },
- { AMULW, ydivl, Pe, 0xf7,(04) },
+ { AHLT, ynone, Px, {0xf4} },
+ { AIDIVB, ydivb, Pb, {0xf6,(07)} },
+ { AIDIVL, ydivl, Px, {0xf7,(07)} },
+ { AIDIVW, ydivl, Pe, {0xf7,(07)} },
+ { AIMULB, ydivb, Pb, {0xf6,(05)} },
+ { AIMULL, yimul, Px, {0xf7,(05),0x6b,0x69} },
+ { AIMULW, yimul, Pe, {0xf7,(05),0x6b,0x69} },
+ { AINB, yin, Pb, {0xe4,0xec} },
+ { AINL, yin, Px, {0xe5,0xed} },
+ { AINW, yin, Pe, {0xe5,0xed} },
+ { AINCB, yincb, Pb, {0xfe,(00)} },
+ { AINCL, yincl, Px, {0x40,0xff,(00)} },
+ { AINCW, yincl, Pe, {0x40,0xff,(00)} },
+ { AINSB, ynone, Pb, {0x6c} },
+ { AINSL, ynone, Px, {0x6d} },
+ { AINSW, ynone, Pe, {0x6d} },
+ { AINT, yint, Px, {0xcd} },
+ { AINTO, ynone, Px, {0xce} },
+ { AIRETL, ynone, Px, {0xcf} },
+ { AIRETW, ynone, Pe, {0xcf} },
+ { AJCC, yjcond, Px, {0x73,0x83,(00)} },
+ { AJCS, yjcond, Px, {0x72,0x82} },
+ { AJCXZL, yloop, Px, {0xe3} },
+ { AJCXZW, yloop, Px, {0xe3} },
+ { AJEQ, yjcond, Px, {0x74,0x84} },
+ { AJGE, yjcond, Px, {0x7d,0x8d} },
+ { AJGT, yjcond, Px, {0x7f,0x8f} },
+ { AJHI, yjcond, Px, {0x77,0x87} },
+ { AJLE, yjcond, Px, {0x7e,0x8e} },
+ { AJLS, yjcond, Px, {0x76,0x86} },
+ { AJLT, yjcond, Px, {0x7c,0x8c} },
+ { AJMI, yjcond, Px, {0x78,0x88} },
+ { AJMP, yjmp, Px, {0xff,(04),0xeb,0xe9} },
+ { AJNE, yjcond, Px, {0x75,0x85} },
+ { AJOC, yjcond, Px, {0x71,0x81,(00)} },
+ { AJOS, yjcond, Px, {0x70,0x80,(00)} },
+ { AJPC, yjcond, Px, {0x7b,0x8b} },
+ { AJPL, yjcond, Px, {0x79,0x89} },
+ { AJPS, yjcond, Px, {0x7a,0x8a} },
+ { ALAHF, ynone, Px, {0x9f} },
+ { ALARL, yml_rl, Pm, {0x02} },
+ { ALARW, yml_rl, Pq, {0x02} },
+ { ALEAL, ym_rl, Px, {0x8d} },
+ { ALEAW, ym_rl, Pe, {0x8d} },
+ { ALEAVEL, ynone, Px, {0xc9} },
+ { ALEAVEW, ynone, Pe, {0xc9} },
+ { ALOCK, ynone, Px, {0xf0} },
+ { ALODSB, ynone, Pb, {0xac} },
+ { ALODSL, ynone, Px, {0xad} },
+ { ALODSW, ynone, Pe, {0xad} },
+ { ALONG, ybyte, Px, {4} },
+ { ALOOP, yloop, Px, {0xe2} },
+ { ALOOPEQ, yloop, Px, {0xe1} },
+ { ALOOPNE, yloop, Px, {0xe0} },
+ { ALSLL, yml_rl, Pm, {0x03 } },
+ { ALSLW, yml_rl, Pq, {0x03 } },
+ { AMOVB, ymovb, Pb, {0x88,0x8a,0xb0,0xc6,(00)} },
+ { AMOVL, ymovl, Px, {0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),Pe,0x6e,Pe,0x7e,0} },
+ { AMOVW, ymovw, Pe, {0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),0} },
+ { AMOVQ, ymovq, Pf3, {0x7e} },
+ { AMOVBLSX, ymb_rl, Pm, {0xbe} },
+ { AMOVBLZX, ymb_rl, Pm, {0xb6} },
+ { AMOVBWSX, ymb_rl, Pq, {0xbe} },
+ { AMOVBWZX, ymb_rl, Pq, {0xb6} },
+ { AMOVWLSX, yml_rl, Pm, {0xbf} },
+ { AMOVWLZX, yml_rl, Pm, {0xb7} },
+ { AMOVSB, ynone, Pb, {0xa4} },
+ { AMOVSL, ynone, Px, {0xa5} },
+ { AMOVSW, ynone, Pe, {0xa5} },
+ { AMULB, ydivb, Pb, {0xf6,(04)} },
+ { AMULL, ydivl, Px, {0xf7,(04)} },
+ { AMULW, ydivl, Pe, {0xf7,(04)} },
{ ANAME },
- { ANEGB, yscond, Px, 0xf6,(03) },
- { ANEGL, yscond, Px, 0xf7,(03) },
- { ANEGW, yscond, Pe, 0xf7,(03) },
- { ANOP, ynop, Px,0,0 },
- { ANOTB, yscond, Px, 0xf6,(02) },
- { ANOTL, yscond, Px, 0xf7,(02) },
- { ANOTW, yscond, Pe, 0xf7,(02) },
- { AORB, yxorb, Pb, 0x0c,0x80,(01),0x08,0x0a },
- { AORL, yxorl, Px, 0x83,(01),0x0d,0x81,(01),0x09,0x0b },
- { AORW, yxorl, Pe, 0x83,(01),0x0d,0x81,(01),0x09,0x0b },
- { AOUTB, yin, Pb, 0xe6,0xee },
- { AOUTL, yin, Px, 0xe7,0xef },
- { AOUTW, yin, Pe, 0xe7,0xef },
- { AOUTSB, ynone, Pb, 0x6e },
- { AOUTSL, ynone, Px, 0x6f },
- { AOUTSW, ynone, Pe, 0x6f },
- { APAUSE, ynone, Px, 0xf3,0x90 },
- { APOPAL, ynone, Px, 0x61 },
- { APOPAW, ynone, Pe, 0x61 },
- { APOPFL, ynone, Px, 0x9d },
- { APOPFW, ynone, Pe, 0x9d },
- { APOPL, ypopl, Px, 0x58,0x8f,(00) },
- { APOPW, ypopl, Pe, 0x58,0x8f,(00) },
- { APUSHAL, ynone, Px, 0x60 },
- { APUSHAW, ynone, Pe, 0x60 },
- { APUSHFL, ynone, Px, 0x9c },
- { APUSHFW, ynone, Pe, 0x9c },
- { APUSHL, ypushl, Px, 0x50,0xff,(06),0x6a,0x68 },
- { APUSHW, ypushl, Pe, 0x50,0xff,(06),0x6a,0x68 },
- { ARCLB, yshb, Pb, 0xd0,(02),0xc0,(02),0xd2,(02) },
- { ARCLL, yshl, Px, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) },
- { ARCLW, yshl, Pe, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) },
- { ARCRB, yshb, Pb, 0xd0,(03),0xc0,(03),0xd2,(03) },
- { ARCRL, yshl, Px, 0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03) },
- { ARCRW, yshl, Pe, 0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03) },
- { AREP, ynone, Px, 0xf3 },
- { AREPN, ynone, Px, 0xf2 },
- { ARET, ynone, Px, 0xc3 },
- { AROLB, yshb, Pb, 0xd0,(00),0xc0,(00),0xd2,(00) },
- { AROLL, yshl, Px, 0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00) },
- { AROLW, yshl, Pe, 0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00) },
- { ARORB, yshb, Pb, 0xd0,(01),0xc0,(01),0xd2,(01) },
- { ARORL, yshl, Px, 0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01) },
- { ARORW, yshl, Pe, 0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01) },
- { ASAHF, ynone, Px, 0x9e },
- { ASALB, yshb, Pb, 0xd0,(04),0xc0,(04),0xd2,(04) },
- { ASALL, yshl, Px, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
- { ASALW, yshl, Pe, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
- { ASARB, yshb, Pb, 0xd0,(07),0xc0,(07),0xd2,(07) },
- { ASARL, yshl, Px, 0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07) },
- { ASARW, yshl, Pe, 0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07) },
- { ASBBB, yxorb, Pb, 0x1c,0x80,(03),0x18,0x1a },
- { ASBBL, yxorl, Px, 0x83,(03),0x1d,0x81,(03),0x19,0x1b },
- { ASBBW, yxorl, Pe, 0x83,(03),0x1d,0x81,(03),0x19,0x1b },
- { ASCASB, ynone, Pb, 0xae },
- { ASCASL, ynone, Px, 0xaf },
- { ASCASW, ynone, Pe, 0xaf },
- { ASETCC, yscond, Pm, 0x93,(00) },
- { ASETCS, yscond, Pm, 0x92,(00) },
- { ASETEQ, yscond, Pm, 0x94,(00) },
- { ASETGE, yscond, Pm, 0x9d,(00) },
- { ASETGT, yscond, Pm, 0x9f,(00) },
- { ASETHI, yscond, Pm, 0x97,(00) },
- { ASETLE, yscond, Pm, 0x9e,(00) },
- { ASETLS, yscond, Pm, 0x96,(00) },
- { ASETLT, yscond, Pm, 0x9c,(00) },
- { ASETMI, yscond, Pm, 0x98,(00) },
- { ASETNE, yscond, Pm, 0x95,(00) },
- { ASETOC, yscond, Pm, 0x91,(00) },
- { ASETOS, yscond, Pm, 0x90,(00) },
- { ASETPC, yscond, Pm, 0x96,(00) },
- { ASETPL, yscond, Pm, 0x99,(00) },
- { ASETPS, yscond, Pm, 0x9a,(00) },
- { ACDQ, ynone, Px, 0x99 },
- { ACWD, ynone, Pe, 0x99 },
- { ASHLB, yshb, Pb, 0xd0,(04),0xc0,(04),0xd2,(04) },
- { ASHLL, yshl, Px, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
- { ASHLW, yshl, Pe, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
- { ASHRB, yshb, Pb, 0xd0,(05),0xc0,(05),0xd2,(05) },
- { ASHRL, yshl, Px, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) },
- { ASHRW, yshl, Pe, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) },
- { ASTC, ynone, Px, 0xf9 },
- { ASTD, ynone, Px, 0xfd },
- { ASTI, ynone, Px, 0xfb },
- { ASTOSB, ynone, Pb, 0xaa },
- { ASTOSL, ynone, Px, 0xab },
- { ASTOSW, ynone, Pe, 0xab },
- { ASUBB, yxorb, Pb, 0x2c,0x80,(05),0x28,0x2a },
- { ASUBL, yaddl, Px, 0x83,(05),0x2d,0x81,(05),0x29,0x2b },
- { ASUBW, yaddl, Pe, 0x83,(05),0x2d,0x81,(05),0x29,0x2b },
- { ASYSCALL, ynone, Px, 0xcd,100 },
- { ATESTB, ytestb, Pb, 0xa8,0xf6,(00),0x84,0x84 },
- { ATESTL, ytestl, Px, 0xa9,0xf7,(00),0x85,0x85 },
- { ATESTW, ytestl, Pe, 0xa9,0xf7,(00),0x85,0x85 },
+ { ANEGB, yscond, Px, {0xf6,(03)} },
+ { ANEGL, yscond, Px, {0xf7,(03)} },
+ { ANEGW, yscond, Pe, {0xf7,(03)} },
+ { ANOP, ynop, Px, {0,0} },
+ { ANOTB, yscond, Px, {0xf6,(02)} },
+ { ANOTL, yscond, Px, {0xf7,(02)} },
+ { ANOTW, yscond, Pe, {0xf7,(02)} },
+ { AORB, yxorb, Pb, {0x0c,0x80,(01),0x08,0x0a} },
+ { AORL, yxorl, Px, {0x83,(01),0x0d,0x81,(01),0x09,0x0b} },
+ { AORW, yxorl, Pe, {0x83,(01),0x0d,0x81,(01),0x09,0x0b} },
+ { AOUTB, yin, Pb, {0xe6,0xee} },
+ { AOUTL, yin, Px, {0xe7,0xef} },
+ { AOUTW, yin, Pe, {0xe7,0xef} },
+ { AOUTSB, ynone, Pb, {0x6e} },
+ { AOUTSL, ynone, Px, {0x6f} },
+ { AOUTSW, ynone, Pe, {0x6f} },
+ { APAUSE, ynone, Px, {0xf3,0x90} },
+ { APOPAL, ynone, Px, {0x61} },
+ { APOPAW, ynone, Pe, {0x61} },
+ { APOPFL, ynone, Px, {0x9d} },
+ { APOPFW, ynone, Pe, {0x9d} },
+ { APOPL, ypopl, Px, {0x58,0x8f,(00)} },
+ { APOPW, ypopl, Pe, {0x58,0x8f,(00)} },
+ { APUSHAL, ynone, Px, {0x60} },
+ { APUSHAW, ynone, Pe, {0x60} },
+ { APUSHFL, ynone, Px, {0x9c} },
+ { APUSHFW, ynone, Pe, {0x9c} },
+ { APUSHL, ypushl, Px, {0x50,0xff,(06),0x6a,0x68} },
+ { APUSHW, ypushl, Pe, {0x50,0xff,(06),0x6a,0x68} },
+ { ARCLB, yshb, Pb, {0xd0,(02),0xc0,(02),0xd2,(02)} },
+ { ARCLL, yshl, Px, {0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02)} },
+ { ARCLW, yshl, Pe, {0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02)} },
+ { ARCRB, yshb, Pb, {0xd0,(03),0xc0,(03),0xd2,(03)} },
+ { ARCRL, yshl, Px, {0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03)} },
+ { ARCRW, yshl, Pe, {0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03)} },
+ { AREP, ynone, Px, {0xf3} },
+ { AREPN, ynone, Px, {0xf2} },
+ { ARET, ynone, Px, {0xc3} },
+ { AROLB, yshb, Pb, {0xd0,(00),0xc0,(00),0xd2,(00)} },
+ { AROLL, yshl, Px, {0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00)} },
+ { AROLW, yshl, Pe, {0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00)} },
+ { ARORB, yshb, Pb, {0xd0,(01),0xc0,(01),0xd2,(01)} },
+ { ARORL, yshl, Px, {0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01)} },
+ { ARORW, yshl, Pe, {0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01)} },
+ { ASAHF, ynone, Px, {0x9e} },
+ { ASALB, yshb, Pb, {0xd0,(04),0xc0,(04),0xd2,(04)} },
+ { ASALL, yshl, Px, {0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04)} },
+ { ASALW, yshl, Pe, {0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04)} },
+ { ASARB, yshb, Pb, {0xd0,(07),0xc0,(07),0xd2,(07)} },
+ { ASARL, yshl, Px, {0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07)} },
+ { ASARW, yshl, Pe, {0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07)} },
+ { ASBBB, yxorb, Pb, {0x1c,0x80,(03),0x18,0x1a} },
+ { ASBBL, yxorl, Px, {0x83,(03),0x1d,0x81,(03),0x19,0x1b} },
+ { ASBBW, yxorl, Pe, {0x83,(03),0x1d,0x81,(03),0x19,0x1b} },
+ { ASCASB, ynone, Pb, {0xae} },
+ { ASCASL, ynone, Px, {0xaf} },
+ { ASCASW, ynone, Pe, {0xaf} },
+ { ASETCC, yscond, Pm, {0x93,(00)} },
+ { ASETCS, yscond, Pm, {0x92,(00)} },
+ { ASETEQ, yscond, Pm, {0x94,(00)} },
+ { ASETGE, yscond, Pm, {0x9d,(00)} },
+ { ASETGT, yscond, Pm, {0x9f,(00)} },
+ { ASETHI, yscond, Pm, {0x97,(00)} },
+ { ASETLE, yscond, Pm, {0x9e,(00)} },
+ { ASETLS, yscond, Pm, {0x96,(00)} },
+ { ASETLT, yscond, Pm, {0x9c,(00)} },
+ { ASETMI, yscond, Pm, {0x98,(00)} },
+ { ASETNE, yscond, Pm, {0x95,(00)} },
+ { ASETOC, yscond, Pm, {0x91,(00)} },
+ { ASETOS, yscond, Pm, {0x90,(00)} },
+ { ASETPC, yscond, Pm, {0x9b,(00)} },
+ { ASETPL, yscond, Pm, {0x99,(00)} },
+ { ASETPS, yscond, Pm, {0x9a,(00)} },
+ { ACDQ, ynone, Px, {0x99} },
+ { ACWD, ynone, Pe, {0x99} },
+ { ASHLB, yshb, Pb, {0xd0,(04),0xc0,(04),0xd2,(04)} },
+ { ASHLL, yshl, Px, {0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04)} },
+ { ASHLW, yshl, Pe, {0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04)} },
+ { ASHRB, yshb, Pb, {0xd0,(05),0xc0,(05),0xd2,(05)} },
+ { ASHRL, yshl, Px, {0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05)} },
+ { ASHRW, yshl, Pe, {0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05)} },
+ { ASTC, ynone, Px, {0xf9} },
+ { ASTD, ynone, Px, {0xfd} },
+ { ASTI, ynone, Px, {0xfb} },
+ { ASTOSB, ynone, Pb, {0xaa} },
+ { ASTOSL, ynone, Px, {0xab} },
+ { ASTOSW, ynone, Pe, {0xab} },
+ { ASUBB, yxorb, Pb, {0x2c,0x80,(05),0x28,0x2a} },
+ { ASUBL, yaddl, Px, {0x83,(05),0x2d,0x81,(05),0x29,0x2b} },
+ { ASUBW, yaddl, Pe, {0x83,(05),0x2d,0x81,(05),0x29,0x2b} },
+ { ASYSCALL, ynone, Px, {0xcd,100} },
+ { ATESTB, ytestb, Pb, {0xa8,0xf6,(00),0x84,0x84} },
+ { ATESTL, ytestl, Px, {0xa9,0xf7,(00),0x85,0x85} },
+ { ATESTW, ytestl, Pe, {0xa9,0xf7,(00),0x85,0x85} },
{ ATEXT, ytext, Px },
- { AVERR, ydivl, Pm, 0x00,(04) },
- { AVERW, ydivl, Pm, 0x00,(05) },
- { AWAIT, ynone, Px, 0x9b },
- { AWORD, ybyte, Px, 2 },
- { AXCHGB, yml_mb, Pb, 0x86,0x86 },
- { AXCHGL, yxchg, Px, 0x90,0x90,0x87,0x87 },
- { AXCHGW, yxchg, Pe, 0x90,0x90,0x87,0x87 },
- { AXLAT, ynone, Px, 0xd7 },
- { AXORB, yxorb, Pb, 0x34,0x80,(06),0x30,0x32 },
- { AXORL, yxorl, Px, 0x83,(06),0x35,0x81,(06),0x31,0x33 },
- { AXORW, yxorl, Pe, 0x83,(06),0x35,0x81,(06),0x31,0x33 },
-
- { AFMOVB, yfmvx, Px, 0xdf,(04) },
- { AFMOVBP, yfmvp, Px, 0xdf,(06) },
- { AFMOVD, yfmvd, Px, 0xdd,(00),0xdd,(02),0xd9,(00),0xdd,(02) },
- { AFMOVDP, yfmvdp, Px, 0xdd,(03),0xdd,(03) },
- { AFMOVF, yfmvf, Px, 0xd9,(00),0xd9,(02) },
- { AFMOVFP, yfmvp, Px, 0xd9,(03) },
- { AFMOVL, yfmvf, Px, 0xdb,(00),0xdb,(02) },
- { AFMOVLP, yfmvp, Px, 0xdb,(03) },
- { AFMOVV, yfmvx, Px, 0xdf,(05) },
- { AFMOVVP, yfmvp, Px, 0xdf,(07) },
- { AFMOVW, yfmvf, Px, 0xdf,(00),0xdf,(02) },
- { AFMOVWP, yfmvp, Px, 0xdf,(03) },
- { AFMOVX, yfmvx, Px, 0xdb,(05) },
- { AFMOVXP, yfmvp, Px, 0xdb,(07) },
+ { AVERR, ydivl, Pm, {0x00,(04)} },
+ { AVERW, ydivl, Pm, {0x00,(05)} },
+ { AWAIT, ynone, Px, {0x9b} },
+ { AWORD, ybyte, Px, {2} },
+ { AXCHGB, yml_mb, Pb, {0x86,0x86} },
+ { AXCHGL, yxchg, Px, {0x90,0x90,0x87,0x87} },
+ { AXCHGW, yxchg, Pe, {0x90,0x90,0x87,0x87} },
+ { AXLAT, ynone, Px, {0xd7} },
+ { AXORB, yxorb, Pb, {0x34,0x80,(06),0x30,0x32} },
+ { AXORL, yxorl, Px, {0x83,(06),0x35,0x81,(06),0x31,0x33} },
+ { AXORW, yxorl, Pe, {0x83,(06),0x35,0x81,(06),0x31,0x33} },
+
+ { AFMOVB, yfmvx, Px, {0xdf,(04)} },
+ { AFMOVBP, yfmvp, Px, {0xdf,(06)} },
+ { AFMOVD, yfmvd, Px, {0xdd,(00),0xdd,(02),0xd9,(00),0xdd,(02)} },
+ { AFMOVDP, yfmvdp, Px, {0xdd,(03),0xdd,(03)} },
+ { AFMOVF, yfmvf, Px, {0xd9,(00),0xd9,(02)} },
+ { AFMOVFP, yfmvp, Px, {0xd9,(03)} },
+ { AFMOVL, yfmvf, Px, {0xdb,(00),0xdb,(02)} },
+ { AFMOVLP, yfmvp, Px, {0xdb,(03)} },
+ { AFMOVV, yfmvx, Px, {0xdf,(05)} },
+ { AFMOVVP, yfmvp, Px, {0xdf,(07)} },
+ { AFMOVW, yfmvf, Px, {0xdf,(00),0xdf,(02)} },
+ { AFMOVWP, yfmvp, Px, {0xdf,(03)} },
+ { AFMOVX, yfmvx, Px, {0xdb,(05)} },
+ { AFMOVXP, yfmvp, Px, {0xdb,(07)} },
{ AFCOMB },
{ AFCOMBP },
- { AFCOMD, yfadd, Px, 0xdc,(02),0xd8,(02),0xdc,(02) }, /* botch */
- { AFCOMDP, yfadd, Px, 0xdc,(03),0xd8,(03),0xdc,(03) }, /* botch */
- { AFCOMDPP, ycompp, Px, 0xde,(03) },
- { AFCOMF, yfmvx, Px, 0xd8,(02) },
- { AFCOMFP, yfmvx, Px, 0xd8,(03) },
- { AFCOMI, yfmvx, Px, 0xdb,(06) },
- { AFCOMIP, yfmvx, Px, 0xdf,(06) },
- { AFCOML, yfmvx, Px, 0xda,(02) },
- { AFCOMLP, yfmvx, Px, 0xda,(03) },
- { AFCOMW, yfmvx, Px, 0xde,(02) },
- { AFCOMWP, yfmvx, Px, 0xde,(03) },
-
- { AFUCOM, ycompp, Px, 0xdd,(04) },
- { AFUCOMI, ycompp, Px, 0xdb,(05) },
- { AFUCOMIP, ycompp, Px, 0xdf,(05) },
- { AFUCOMP, ycompp, Px, 0xdd,(05) },
- { AFUCOMPP, ycompp, Px, 0xda,(13) },
-
- { AFADDDP, yfaddp, Px, 0xde,(00) },
- { AFADDW, yfmvx, Px, 0xde,(00) },
- { AFADDL, yfmvx, Px, 0xda,(00) },
- { AFADDF, yfmvx, Px, 0xd8,(00) },
- { AFADDD, yfadd, Px, 0xdc,(00),0xd8,(00),0xdc,(00) },
-
- { AFMULDP, yfaddp, Px, 0xde,(01) },
- { AFMULW, yfmvx, Px, 0xde,(01) },
- { AFMULL, yfmvx, Px, 0xda,(01) },
- { AFMULF, yfmvx, Px, 0xd8,(01) },
- { AFMULD, yfadd, Px, 0xdc,(01),0xd8,(01),0xdc,(01) },
-
- { AFSUBDP, yfaddp, Px, 0xde,(05) },
- { AFSUBW, yfmvx, Px, 0xde,(04) },
- { AFSUBL, yfmvx, Px, 0xda,(04) },
- { AFSUBF, yfmvx, Px, 0xd8,(04) },
- { AFSUBD, yfadd, Px, 0xdc,(04),0xd8,(04),0xdc,(05) },
-
- { AFSUBRDP, yfaddp, Px, 0xde,(04) },
- { AFSUBRW, yfmvx, Px, 0xde,(05) },
- { AFSUBRL, yfmvx, Px, 0xda,(05) },
- { AFSUBRF, yfmvx, Px, 0xd8,(05) },
- { AFSUBRD, yfadd, Px, 0xdc,(05),0xd8,(05),0xdc,(04) },
-
- { AFDIVDP, yfaddp, Px, 0xde,(07) },
- { AFDIVW, yfmvx, Px, 0xde,(06) },
- { AFDIVL, yfmvx, Px, 0xda,(06) },
- { AFDIVF, yfmvx, Px, 0xd8,(06) },
- { AFDIVD, yfadd, Px, 0xdc,(06),0xd8,(06),0xdc,(07) },
-
- { AFDIVRDP, yfaddp, Px, 0xde,(06) },
- { AFDIVRW, yfmvx, Px, 0xde,(07) },
- { AFDIVRL, yfmvx, Px, 0xda,(07) },
- { AFDIVRF, yfmvx, Px, 0xd8,(07) },
- { AFDIVRD, yfadd, Px, 0xdc,(07),0xd8,(07),0xdc,(06) },
-
- { AFXCHD, yfxch, Px, 0xd9,(01),0xd9,(01) },
+ { AFCOMD, yfadd, Px, {0xdc,(02),0xd8,(02),0xdc,(02)} }, /* botch */
+ { AFCOMDP, yfadd, Px, {0xdc,(03),0xd8,(03),0xdc,(03)} }, /* botch */
+ { AFCOMDPP, ycompp, Px, {0xde,(03)} },
+ { AFCOMF, yfmvx, Px, {0xd8,(02)} },
+ { AFCOMFP, yfmvx, Px, {0xd8,(03)} },
+ { AFCOMI, yfmvx, Px, {0xdb,(06)} },
+ { AFCOMIP, yfmvx, Px, {0xdf,(06)} },
+ { AFCOML, yfmvx, Px, {0xda,(02)} },
+ { AFCOMLP, yfmvx, Px, {0xda,(03)} },
+ { AFCOMW, yfmvx, Px, {0xde,(02)} },
+ { AFCOMWP, yfmvx, Px, {0xde,(03)} },
+
+ { AFUCOM, ycompp, Px, {0xdd,(04)} },
+ { AFUCOMI, ycompp, Px, {0xdb,(05)} },
+ { AFUCOMIP, ycompp, Px, {0xdf,(05)} },
+ { AFUCOMP, ycompp, Px, {0xdd,(05)} },
+ { AFUCOMPP, ycompp, Px, {0xda,(13)} },
+
+ { AFADDDP, yfaddp, Px, {0xde,(00)} },
+ { AFADDW, yfmvx, Px, {0xde,(00)} },
+ { AFADDL, yfmvx, Px, {0xda,(00)} },
+ { AFADDF, yfmvx, Px, {0xd8,(00)} },
+ { AFADDD, yfadd, Px, {0xdc,(00),0xd8,(00),0xdc,(00)} },
+
+ { AFMULDP, yfaddp, Px, {0xde,(01)} },
+ { AFMULW, yfmvx, Px, {0xde,(01)} },
+ { AFMULL, yfmvx, Px, {0xda,(01)} },
+ { AFMULF, yfmvx, Px, {0xd8,(01)} },
+ { AFMULD, yfadd, Px, {0xdc,(01),0xd8,(01),0xdc,(01)} },
+
+ { AFSUBDP, yfaddp, Px, {0xde,(05)} },
+ { AFSUBW, yfmvx, Px, {0xde,(04)} },
+ { AFSUBL, yfmvx, Px, {0xda,(04)} },
+ { AFSUBF, yfmvx, Px, {0xd8,(04)} },
+ { AFSUBD, yfadd, Px, {0xdc,(04),0xd8,(04),0xdc,(05)} },
+
+ { AFSUBRDP, yfaddp, Px, {0xde,(04)} },
+ { AFSUBRW, yfmvx, Px, {0xde,(05)} },
+ { AFSUBRL, yfmvx, Px, {0xda,(05)} },
+ { AFSUBRF, yfmvx, Px, {0xd8,(05)} },
+ { AFSUBRD, yfadd, Px, {0xdc,(05),0xd8,(05),0xdc,(04)} },
+
+ { AFDIVDP, yfaddp, Px, {0xde,(07)} },
+ { AFDIVW, yfmvx, Px, {0xde,(06)} },
+ { AFDIVL, yfmvx, Px, {0xda,(06)} },
+ { AFDIVF, yfmvx, Px, {0xd8,(06)} },
+ { AFDIVD, yfadd, Px, {0xdc,(06),0xd8,(06),0xdc,(07)} },
+
+ { AFDIVRDP, yfaddp, Px, {0xde,(06)} },
+ { AFDIVRW, yfmvx, Px, {0xde,(07)} },
+ { AFDIVRL, yfmvx, Px, {0xda,(07)} },
+ { AFDIVRF, yfmvx, Px, {0xd8,(07)} },
+ { AFDIVRD, yfadd, Px, {0xdc,(07),0xd8,(07),0xdc,(06)} },
+
+ { AFXCHD, yfxch, Px, {0xd9,(01),0xd9,(01)} },
{ AFFREE },
- { AFLDCW, ystcw, Px, 0xd9,(05),0xd9,(05) },
- { AFLDENV, ystcw, Px, 0xd9,(04),0xd9,(04) },
- { AFRSTOR, ysvrs, Px, 0xdd,(04),0xdd,(04) },
- { AFSAVE, ysvrs, Px, 0xdd,(06),0xdd,(06) },
- { AFSTCW, ystcw, Px, 0xd9,(07),0xd9,(07) },
- { AFSTENV, ystcw, Px, 0xd9,(06),0xd9,(06) },
- { AFSTSW, ystsw, Px, 0xdd,(07),0xdf,0xe0 },
- { AF2XM1, ynone, Px, 0xd9, 0xf0 },
- { AFABS, ynone, Px, 0xd9, 0xe1 },
- { AFCHS, ynone, Px, 0xd9, 0xe0 },
- { AFCLEX, ynone, Px, 0xdb, 0xe2 },
- { AFCOS, ynone, Px, 0xd9, 0xff },
- { AFDECSTP, ynone, Px, 0xd9, 0xf6 },
- { AFINCSTP, ynone, Px, 0xd9, 0xf7 },
- { AFINIT, ynone, Px, 0xdb, 0xe3 },
- { AFLD1, ynone, Px, 0xd9, 0xe8 },
- { AFLDL2E, ynone, Px, 0xd9, 0xea },
- { AFLDL2T, ynone, Px, 0xd9, 0xe9 },
- { AFLDLG2, ynone, Px, 0xd9, 0xec },
- { AFLDLN2, ynone, Px, 0xd9, 0xed },
- { AFLDPI, ynone, Px, 0xd9, 0xeb },
- { AFLDZ, ynone, Px, 0xd9, 0xee },
- { AFNOP, ynone, Px, 0xd9, 0xd0 },
- { AFPATAN, ynone, Px, 0xd9, 0xf3 },
- { AFPREM, ynone, Px, 0xd9, 0xf8 },
- { AFPREM1, ynone, Px, 0xd9, 0xf5 },
- { AFPTAN, ynone, Px, 0xd9, 0xf2 },
- { AFRNDINT, ynone, Px, 0xd9, 0xfc },
- { AFSCALE, ynone, Px, 0xd9, 0xfd },
- { AFSIN, ynone, Px, 0xd9, 0xfe },
- { AFSINCOS, ynone, Px, 0xd9, 0xfb },
- { AFSQRT, ynone, Px, 0xd9, 0xfa },
- { AFTST, ynone, Px, 0xd9, 0xe4 },
- { AFXAM, ynone, Px, 0xd9, 0xe5 },
- { AFXTRACT, ynone, Px, 0xd9, 0xf4 },
- { AFYL2X, ynone, Px, 0xd9, 0xf1 },
- { AFYL2XP1, ynone, Px, 0xd9, 0xf9 },
+ { AFLDCW, ystcw, Px, {0xd9,(05),0xd9,(05)} },
+ { AFLDENV, ystcw, Px, {0xd9,(04),0xd9,(04)} },
+ { AFRSTOR, ysvrs, Px, {0xdd,(04),0xdd,(04)} },
+ { AFSAVE, ysvrs, Px, {0xdd,(06),0xdd,(06)} },
+ { AFSTCW, ystcw, Px, {0xd9,(07),0xd9,(07)} },
+ { AFSTENV, ystcw, Px, {0xd9,(06),0xd9,(06)} },
+ { AFSTSW, ystsw, Px, {0xdd,(07),0xdf,0xe0} },
+ { AF2XM1, ynone, Px, {0xd9, 0xf0} },
+ { AFABS, ynone, Px, {0xd9, 0xe1} },
+ { AFCHS, ynone, Px, {0xd9, 0xe0} },
+ { AFCLEX, ynone, Px, {0xdb, 0xe2} },
+ { AFCOS, ynone, Px, {0xd9, 0xff} },
+ { AFDECSTP, ynone, Px, {0xd9, 0xf6} },
+ { AFINCSTP, ynone, Px, {0xd9, 0xf7} },
+ { AFINIT, ynone, Px, {0xdb, 0xe3} },
+ { AFLD1, ynone, Px, {0xd9, 0xe8} },
+ { AFLDL2E, ynone, Px, {0xd9, 0xea} },
+ { AFLDL2T, ynone, Px, {0xd9, 0xe9} },
+ { AFLDLG2, ynone, Px, {0xd9, 0xec} },
+ { AFLDLN2, ynone, Px, {0xd9, 0xed} },
+ { AFLDPI, ynone, Px, {0xd9, 0xeb} },
+ { AFLDZ, ynone, Px, {0xd9, 0xee} },
+ { AFNOP, ynone, Px, {0xd9, 0xd0} },
+ { AFPATAN, ynone, Px, {0xd9, 0xf3} },
+ { AFPREM, ynone, Px, {0xd9, 0xf8} },
+ { AFPREM1, ynone, Px, {0xd9, 0xf5} },
+ { AFPTAN, ynone, Px, {0xd9, 0xf2} },
+ { AFRNDINT, ynone, Px, {0xd9, 0xfc} },
+ { AFSCALE, ynone, Px, {0xd9, 0xfd} },
+ { AFSIN, ynone, Px, {0xd9, 0xfe} },
+ { AFSINCOS, ynone, Px, {0xd9, 0xfb} },
+ { AFSQRT, ynone, Px, {0xd9, 0xfa} },
+ { AFTST, ynone, Px, {0xd9, 0xe4} },
+ { AFXAM, ynone, Px, {0xd9, 0xe5} },
+ { AFXTRACT, ynone, Px, {0xd9, 0xf4} },
+ { AFYL2X, ynone, Px, {0xd9, 0xf1} },
+ { AFYL2XP1, ynone, Px, {0xd9, 0xf9} },
{ AEND },
{ ADYNT_ },
{ AINIT_ },
{ ASIGNAME },
- { ACMPXCHGB, yrb_mb, Pm, 0xb0 },
- { ACMPXCHGL, yrl_ml, Pm, 0xb1 },
- { ACMPXCHGW, yrl_ml, Pm, 0xb1 },
- { ACMPXCHG8B, yscond, Pm, 0xc7,(01) },
-
- { ACPUID, ynone, Pm, 0xa2 },
- { ARDTSC, ynone, Pm, 0x31 },
-
- { AXADDB, yrb_mb, Pb, 0x0f,0xc0 },
- { AXADDL, yrl_ml, Pm, 0xc1 },
- { AXADDW, yrl_ml, Pe, 0x0f,0xc1 },
-
- { ACMOVLCC, yml_rl, Pm, 0x43 },
- { ACMOVLCS, yml_rl, Pm, 0x42 },
- { ACMOVLEQ, yml_rl, Pm, 0x44 },
- { ACMOVLGE, yml_rl, Pm, 0x4d },
- { ACMOVLGT, yml_rl, Pm, 0x4f },
- { ACMOVLHI, yml_rl, Pm, 0x47 },
- { ACMOVLLE, yml_rl, Pm, 0x4e },
- { ACMOVLLS, yml_rl, Pm, 0x46 },
- { ACMOVLLT, yml_rl, Pm, 0x4c },
- { ACMOVLMI, yml_rl, Pm, 0x48 },
- { ACMOVLNE, yml_rl, Pm, 0x45 },
- { ACMOVLOC, yml_rl, Pm, 0x41 },
- { ACMOVLOS, yml_rl, Pm, 0x40 },
- { ACMOVLPC, yml_rl, Pm, 0x4b },
- { ACMOVLPL, yml_rl, Pm, 0x49 },
- { ACMOVLPS, yml_rl, Pm, 0x4a },
- { ACMOVWCC, yml_rl, Pq, 0x43 },
- { ACMOVWCS, yml_rl, Pq, 0x42 },
- { ACMOVWEQ, yml_rl, Pq, 0x44 },
- { ACMOVWGE, yml_rl, Pq, 0x4d },
- { ACMOVWGT, yml_rl, Pq, 0x4f },
- { ACMOVWHI, yml_rl, Pq, 0x47 },
- { ACMOVWLE, yml_rl, Pq, 0x4e },
- { ACMOVWLS, yml_rl, Pq, 0x46 },
- { ACMOVWLT, yml_rl, Pq, 0x4c },
- { ACMOVWMI, yml_rl, Pq, 0x48 },
- { ACMOVWNE, yml_rl, Pq, 0x45 },
- { ACMOVWOC, yml_rl, Pq, 0x41 },
- { ACMOVWOS, yml_rl, Pq, 0x40 },
- { ACMOVWPC, yml_rl, Pq, 0x4b },
- { ACMOVWPL, yml_rl, Pq, 0x49 },
- { ACMOVWPS, yml_rl, Pq, 0x4a },
-
- { AFCMOVCC, yfcmv, Px, 0xdb,(00) },
- { AFCMOVCS, yfcmv, Px, 0xda,(00) },
- { AFCMOVEQ, yfcmv, Px, 0xda,(01) },
- { AFCMOVHI, yfcmv, Px, 0xdb,(02) },
- { AFCMOVLS, yfcmv, Px, 0xda,(02) },
- { AFCMOVNE, yfcmv, Px, 0xdb,(01) },
- { AFCMOVNU, yfcmv, Px, 0xdb,(03) },
- { AFCMOVUN, yfcmv, Px, 0xda,(03) },
-
- { ALFENCE, ynone, Pm, 0xae,0xe8 },
- { AMFENCE, ynone, Pm, 0xae,0xf0 },
- { ASFENCE, ynone, Pm, 0xae,0xf8 },
-
- { AEMMS, ynone, Pm, 0x77 },
-
- { APREFETCHT0, yprefetch, Pm, 0x18,(01) },
- { APREFETCHT1, yprefetch, Pm, 0x18,(02) },
- { APREFETCHT2, yprefetch, Pm, 0x18,(03) },
- { APREFETCHNTA, yprefetch, Pm, 0x18,(00) },
-
- { ABSWAPL, ybswap, Pm, 0xc8 },
+ { ACMPXCHGB, yrb_mb, Pm, {0xb0} },
+ { ACMPXCHGL, yrl_ml, Pm, {0xb1} },
+ { ACMPXCHGW, yrl_ml, Pm, {0xb1} },
+ { ACMPXCHG8B, yscond, Pm, {0xc7,(01)} },
+
+ { ACPUID, ynone, Pm, {0xa2} },
+ { ARDTSC, ynone, Pm, {0x31} },
+
+ { AXADDB, yrb_mb, Pb, {0x0f,0xc0} },
+ { AXADDL, yrl_ml, Pm, {0xc1} },
+ { AXADDW, yrl_ml, Pe, {0x0f,0xc1} },
+
+ { ACMOVLCC, yml_rl, Pm, {0x43} },
+ { ACMOVLCS, yml_rl, Pm, {0x42} },
+ { ACMOVLEQ, yml_rl, Pm, {0x44} },
+ { ACMOVLGE, yml_rl, Pm, {0x4d} },
+ { ACMOVLGT, yml_rl, Pm, {0x4f} },
+ { ACMOVLHI, yml_rl, Pm, {0x47} },
+ { ACMOVLLE, yml_rl, Pm, {0x4e} },
+ { ACMOVLLS, yml_rl, Pm, {0x46} },
+ { ACMOVLLT, yml_rl, Pm, {0x4c} },
+ { ACMOVLMI, yml_rl, Pm, {0x48} },
+ { ACMOVLNE, yml_rl, Pm, {0x45} },
+ { ACMOVLOC, yml_rl, Pm, {0x41} },
+ { ACMOVLOS, yml_rl, Pm, {0x40} },
+ { ACMOVLPC, yml_rl, Pm, {0x4b} },
+ { ACMOVLPL, yml_rl, Pm, {0x49} },
+ { ACMOVLPS, yml_rl, Pm, {0x4a} },
+ { ACMOVWCC, yml_rl, Pq, {0x43} },
+ { ACMOVWCS, yml_rl, Pq, {0x42} },
+ { ACMOVWEQ, yml_rl, Pq, {0x44} },
+ { ACMOVWGE, yml_rl, Pq, {0x4d} },
+ { ACMOVWGT, yml_rl, Pq, {0x4f} },
+ { ACMOVWHI, yml_rl, Pq, {0x47} },
+ { ACMOVWLE, yml_rl, Pq, {0x4e} },
+ { ACMOVWLS, yml_rl, Pq, {0x46} },
+ { ACMOVWLT, yml_rl, Pq, {0x4c} },
+ { ACMOVWMI, yml_rl, Pq, {0x48} },
+ { ACMOVWNE, yml_rl, Pq, {0x45} },
+ { ACMOVWOC, yml_rl, Pq, {0x41} },
+ { ACMOVWOS, yml_rl, Pq, {0x40} },
+ { ACMOVWPC, yml_rl, Pq, {0x4b} },
+ { ACMOVWPL, yml_rl, Pq, {0x49} },
+ { ACMOVWPS, yml_rl, Pq, {0x4a} },
+
+ { AFCMOVCC, yfcmv, Px, {0xdb,(00)} },
+ { AFCMOVCS, yfcmv, Px, {0xda,(00)} },
+ { AFCMOVEQ, yfcmv, Px, {0xda,(01)} },
+ { AFCMOVHI, yfcmv, Px, {0xdb,(02)} },
+ { AFCMOVLS, yfcmv, Px, {0xda,(02)} },
+ { AFCMOVNE, yfcmv, Px, {0xdb,(01)} },
+ { AFCMOVNU, yfcmv, Px, {0xdb,(03)} },
+ { AFCMOVUN, yfcmv, Px, {0xda,(03)} },
+
+ { ALFENCE, ynone, Pm, {0xae,0xe8} },
+ { AMFENCE, ynone, Pm, {0xae,0xf0} },
+ { ASFENCE, ynone, Pm, {0xae,0xf8} },
+
+ { AEMMS, ynone, Pm, {0x77} },
+
+ { APREFETCHT0, yprefetch, Pm, {0x18,(01)} },
+ { APREFETCHT1, yprefetch, Pm, {0x18,(02)} },
+ { APREFETCHT2, yprefetch, Pm, {0x18,(03)} },
+ { APREFETCHNTA, yprefetch, Pm, {0x18,(00)} },
+
+ { ABSWAPL, ybswap, Pm, {0xc8} },
- { AUNDEF, ynone, Px, 0x0f, 0x0b },
-
- { AADDPD, yxm, Pq, 0x58 },
- { AADDPS, yxm, Pm, 0x58 },
- { AADDSD, yxm, Pf2, 0x58 },
- { AADDSS, yxm, Pf3, 0x58 },
- { AANDNPD, yxm, Pq, 0x55 },
- { AANDNPS, yxm, Pm, 0x55 },
- { AANDPD, yxm, Pq, 0x54 },
- { AANDPS, yxm, Pq, 0x54 },
- { ACMPPD, yxcmpi, Px, Pe,0xc2 },
- { ACMPPS, yxcmpi, Pm, 0xc2,0 },
- { ACMPSD, yxcmpi, Px, Pf2,0xc2 },
- { ACMPSS, yxcmpi, Px, Pf3,0xc2 },
- { ACOMISD, yxcmp, Pe, 0x2f },
- { ACOMISS, yxcmp, Pm, 0x2f },
- { ACVTPL2PD, yxcvm2, Px, Pf3,0xe6,Pe,0x2a },
- { ACVTPL2PS, yxcvm2, Pm, 0x5b,0,0x2a,0, },
- { ACVTPD2PL, yxcvm1, Px, Pf2,0xe6,Pe,0x2d },
- { ACVTPD2PS, yxm, Pe, 0x5a },
- { ACVTPS2PL, yxcvm1, Px, Pe,0x5b,Pm,0x2d },
- { ACVTPS2PD, yxm, Pm, 0x5a },
- { ACVTSD2SL, yxcvfl, Pf2, 0x2d },
- { ACVTSD2SS, yxm, Pf2, 0x5a },
- { ACVTSL2SD, yxcvlf, Pf2, 0x2a },
- { ACVTSL2SS, yxcvlf, Pf3, 0x2a },
- { ACVTSS2SD, yxm, Pf3, 0x5a },
- { ACVTSS2SL, yxcvfl, Pf3, 0x2d },
- { ACVTTPD2PL, yxcvm1, Px, Pe,0xe6,Pe,0x2c },
- { ACVTTPS2PL, yxcvm1, Px, Pf3,0x5b,Pm,0x2c },
- { ACVTTSD2SL, yxcvfl, Pf2, 0x2c },
- { ACVTTSS2SL, yxcvfl, Pf3, 0x2c },
- { ADIVPD, yxm, Pe, 0x5e },
- { ADIVPS, yxm, Pm, 0x5e },
- { ADIVSD, yxm, Pf2, 0x5e },
- { ADIVSS, yxm, Pf3, 0x5e },
- { AMASKMOVOU, yxr, Pe, 0xf7 },
- { AMAXPD, yxm, Pe, 0x5f },
- { AMAXPS, yxm, Pm, 0x5f },
- { AMAXSD, yxm, Pf2, 0x5f },
- { AMAXSS, yxm, Pf3, 0x5f },
- { AMINPD, yxm, Pe, 0x5d },
- { AMINPS, yxm, Pm, 0x5d },
- { AMINSD, yxm, Pf2, 0x5d },
- { AMINSS, yxm, Pf3, 0x5d },
- { AMOVAPD, yxmov, Pe, 0x28,0x29 },
- { AMOVAPS, yxmov, Pm, 0x28,0x29 },
- { AMOVO, yxmov, Pe, 0x6f,0x7f },
- { AMOVOU, yxmov, Pf3, 0x6f,0x7f },
- { AMOVHLPS, yxr, Pm, 0x12 },
- { AMOVHPD, yxmov, Pe, 0x16,0x17 },
- { AMOVHPS, yxmov, Pm, 0x16,0x17 },
- { AMOVLHPS, yxr, Pm, 0x16 },
- { AMOVLPD, yxmov, Pe, 0x12,0x13 },
- { AMOVLPS, yxmov, Pm, 0x12,0x13 },
- { AMOVMSKPD, yxrrl, Pq, 0x50 },
- { AMOVMSKPS, yxrrl, Pm, 0x50 },
- { AMOVNTO, yxr_ml, Pe, 0xe7 },
- { AMOVNTPD, yxr_ml, Pe, 0x2b },
- { AMOVNTPS, yxr_ml, Pm, 0x2b },
- { AMOVSD, yxmov, Pf2, 0x10,0x11 },
- { AMOVSS, yxmov, Pf3, 0x10,0x11 },
- { AMOVUPD, yxmov, Pe, 0x10,0x11 },
- { AMOVUPS, yxmov, Pm, 0x10,0x11 },
- { AMULPD, yxm, Pe, 0x59 },
- { AMULPS, yxm, Ym, 0x59 },
- { AMULSD, yxm, Pf2, 0x59 },
- { AMULSS, yxm, Pf3, 0x59 },
- { AORPD, yxm, Pq, 0x56 },
- { AORPS, yxm, Pm, 0x56 },
- { APADDQ, yxm, Pe, 0xd4 },
- { APAND, yxm, Pe, 0xdb },
- { APCMPEQB, yxmq, Pe ,0x74 },
- { APMAXSW, yxm, Pe, 0xee },
- { APMAXUB, yxm, Pe, 0xde },
- { APMINSW, yxm, Pe, 0xea },
- { APMINUB, yxm, Pe, 0xda },
- { APMOVMSKB, ymskb, Px, Pe,0xd7,0xd7 },
- { APSADBW, yxm, Pq, 0xf6 },
- { APSUBB, yxm, Pe, 0xf8 },
- { APSUBL, yxm, Pe, 0xfa },
- { APSUBQ, yxm, Pe, 0xfb },
- { APSUBSB, yxm, Pe, 0xe8 },
- { APSUBSW, yxm, Pe, 0xe9 },
- { APSUBUSB, yxm, Pe, 0xd8 },
- { APSUBUSW, yxm, Pe, 0xd9 },
- { APSUBW, yxm, Pe, 0xf9 },
- { APUNPCKHQDQ, yxm, Pe, 0x6d },
- { APUNPCKLQDQ, yxm, Pe, 0x6c },
- { APXOR, yxm, Pe, 0xef },
- { ARCPPS, yxm, Pm, 0x53 },
- { ARCPSS, yxm, Pf3, 0x53 },
- { ARSQRTPS, yxm, Pm, 0x52 },
- { ARSQRTSS, yxm, Pf3, 0x52 },
- { ASQRTPD, yxm, Pe, 0x51 },
- { ASQRTPS, yxm, Pm, 0x51 },
- { ASQRTSD, yxm, Pf2, 0x51 },
- { ASQRTSS, yxm, Pf3, 0x51 },
- { ASUBPD, yxm, Pe, 0x5c },
- { ASUBPS, yxm, Pm, 0x5c },
- { ASUBSD, yxm, Pf2, 0x5c },
- { ASUBSS, yxm, Pf3, 0x5c },
- { AUCOMISD, yxcmp, Pe, 0x2e },
- { AUCOMISS, yxcmp, Pm, 0x2e },
- { AUNPCKHPD, yxm, Pe, 0x15 },
- { AUNPCKHPS, yxm, Pm, 0x15 },
- { AUNPCKLPD, yxm, Pe, 0x14 },
- { AUNPCKLPS, yxm, Pm, 0x14 },
- { AXORPD, yxm, Pe, 0x57 },
- { AXORPS, yxm, Pm, 0x57 },
-
- { AAESENC, yaes, Pq, 0x38,0xdc,(0) },
- { APINSRD, yinsrd, Pq, 0x3a, 0x22, (00) },
- { APSHUFB, ymshufb,Pq, 0x38, 0x00 },
-
- { AUSEFIELD, ynop, Px, 0,0 },
+ { AUNDEF, ynone, Px, {0x0f, 0x0b} },
+
+ { AADDPD, yxm, Pq, {0x58} },
+ { AADDPS, yxm, Pm, {0x58} },
+ { AADDSD, yxm, Pf2, {0x58} },
+ { AADDSS, yxm, Pf3, {0x58} },
+ { AANDNPD, yxm, Pq, {0x55} },
+ { AANDNPS, yxm, Pm, {0x55} },
+ { AANDPD, yxm, Pq, {0x54} },
+ { AANDPS, yxm, Pq, {0x54} },
+ { ACMPPD, yxcmpi, Px, {Pe,0xc2} },
+ { ACMPPS, yxcmpi, Pm, {0xc2,0} },
+ { ACMPSD, yxcmpi, Px, {Pf2,0xc2} },
+ { ACMPSS, yxcmpi, Px, {Pf3,0xc2} },
+ { ACOMISD, yxcmp, Pe, {0x2f} },
+ { ACOMISS, yxcmp, Pm, {0x2f} },
+ { ACVTPL2PD, yxcvm2, Px, {Pf3,0xe6,Pe,0x2a} },
+ { ACVTPL2PS, yxcvm2, Pm, {0x5b,0,0x2a,0,} },
+ { ACVTPD2PL, yxcvm1, Px, {Pf2,0xe6,Pe,0x2d} },
+ { ACVTPD2PS, yxm, Pe, {0x5a} },
+ { ACVTPS2PL, yxcvm1, Px, {Pe,0x5b,Pm,0x2d} },
+ { ACVTPS2PD, yxm, Pm, {0x5a} },
+ { ACVTSD2SL, yxcvfl, Pf2, {0x2d} },
+ { ACVTSD2SS, yxm, Pf2, {0x5a} },
+ { ACVTSL2SD, yxcvlf, Pf2, {0x2a} },
+ { ACVTSL2SS, yxcvlf, Pf3, {0x2a} },
+ { ACVTSS2SD, yxm, Pf3, {0x5a} },
+ { ACVTSS2SL, yxcvfl, Pf3, {0x2d} },
+ { ACVTTPD2PL, yxcvm1, Px, {Pe,0xe6,Pe,0x2c} },
+ { ACVTTPS2PL, yxcvm1, Px, {Pf3,0x5b,Pm,0x2c} },
+ { ACVTTSD2SL, yxcvfl, Pf2, {0x2c} },
+ { ACVTTSS2SL, yxcvfl, Pf3, {0x2c} },
+ { ADIVPD, yxm, Pe, {0x5e} },
+ { ADIVPS, yxm, Pm, {0x5e} },
+ { ADIVSD, yxm, Pf2, {0x5e} },
+ { ADIVSS, yxm, Pf3, {0x5e} },
+ { AMASKMOVOU, yxr, Pe, {0xf7} },
+ { AMAXPD, yxm, Pe, {0x5f} },
+ { AMAXPS, yxm, Pm, {0x5f} },
+ { AMAXSD, yxm, Pf2, {0x5f} },
+ { AMAXSS, yxm, Pf3, {0x5f} },
+ { AMINPD, yxm, Pe, {0x5d} },
+ { AMINPS, yxm, Pm, {0x5d} },
+ { AMINSD, yxm, Pf2, {0x5d} },
+ { AMINSS, yxm, Pf3, {0x5d} },
+ { AMOVAPD, yxmov, Pe, {0x28,0x29} },
+ { AMOVAPS, yxmov, Pm, {0x28,0x29} },
+ { AMOVO, yxmov, Pe, {0x6f,0x7f} },
+ { AMOVOU, yxmov, Pf3, {0x6f,0x7f} },
+ { AMOVHLPS, yxr, Pm, {0x12} },
+ { AMOVHPD, yxmov, Pe, {0x16,0x17} },
+ { AMOVHPS, yxmov, Pm, {0x16,0x17} },
+ { AMOVLHPS, yxr, Pm, {0x16} },
+ { AMOVLPD, yxmov, Pe, {0x12,0x13} },
+ { AMOVLPS, yxmov, Pm, {0x12,0x13} },
+ { AMOVMSKPD, yxrrl, Pq, {0x50} },
+ { AMOVMSKPS, yxrrl, Pm, {0x50} },
+ { AMOVNTO, yxr_ml, Pe, {0xe7} },
+ { AMOVNTPD, yxr_ml, Pe, {0x2b} },
+ { AMOVNTPS, yxr_ml, Pm, {0x2b} },
+ { AMOVSD, yxmov, Pf2, {0x10,0x11} },
+ { AMOVSS, yxmov, Pf3, {0x10,0x11} },
+ { AMOVUPD, yxmov, Pe, {0x10,0x11} },
+ { AMOVUPS, yxmov, Pm, {0x10,0x11} },
+ { AMULPD, yxm, Pe, {0x59} },
+ { AMULPS, yxm, Ym, {0x59} },
+ { AMULSD, yxm, Pf2, {0x59} },
+ { AMULSS, yxm, Pf3, {0x59} },
+ { AORPD, yxm, Pq, {0x56} },
+ { AORPS, yxm, Pm, {0x56} },
+ { APADDQ, yxm, Pe, {0xd4} },
+ { APAND, yxm, Pe, {0xdb} },
+ { APCMPEQB, yxmq, Pe, {0x74} },
+ { APMAXSW, yxm, Pe, {0xee} },
+ { APMAXUB, yxm, Pe, {0xde} },
+ { APMINSW, yxm, Pe, {0xea} },
+ { APMINUB, yxm, Pe, {0xda} },
+ { APMOVMSKB, ymskb, Px, {Pe,0xd7,0xd7} },
+ { APSADBW, yxm, Pq, {0xf6} },
+ { APSUBB, yxm, Pe, {0xf8} },
+ { APSUBL, yxm, Pe, {0xfa} },
+ { APSUBQ, yxm, Pe, {0xfb} },
+ { APSUBSB, yxm, Pe, {0xe8} },
+ { APSUBSW, yxm, Pe, {0xe9} },
+ { APSUBUSB, yxm, Pe, {0xd8} },
+ { APSUBUSW, yxm, Pe, {0xd9} },
+ { APSUBW, yxm, Pe, {0xf9} },
+ { APUNPCKHQDQ, yxm, Pe, {0x6d} },
+ { APUNPCKLQDQ, yxm, Pe, {0x6c} },
+ { APXOR, yxm, Pe, {0xef} },
+ { ARCPPS, yxm, Pm, {0x53} },
+ { ARCPSS, yxm, Pf3, {0x53} },
+ { ARSQRTPS, yxm, Pm, {0x52} },
+ { ARSQRTSS, yxm, Pf3, {0x52} },
+ { ASQRTPD, yxm, Pe, {0x51} },
+ { ASQRTPS, yxm, Pm, {0x51} },
+ { ASQRTSD, yxm, Pf2, {0x51} },
+ { ASQRTSS, yxm, Pf3, {0x51} },
+ { ASUBPD, yxm, Pe, {0x5c} },
+ { ASUBPS, yxm, Pm, {0x5c} },
+ { ASUBSD, yxm, Pf2, {0x5c} },
+ { ASUBSS, yxm, Pf3, {0x5c} },
+ { AUCOMISD, yxcmp, Pe, {0x2e} },
+ { AUCOMISS, yxcmp, Pm, {0x2e} },
+ { AUNPCKHPD, yxm, Pe, {0x15} },
+ { AUNPCKHPS, yxm, Pm, {0x15} },
+ { AUNPCKLPD, yxm, Pe, {0x14} },
+ { AUNPCKLPS, yxm, Pm, {0x14} },
+ { AXORPD, yxm, Pe, {0x57} },
+ { AXORPS, yxm, Pm, {0x57} },
+
+ { AAESENC, yaes, Pq, {0x38,0xdc,(0)} },
+ { APINSRD, yinsrd, Pq, {0x3a, 0x22, (00)} },
+ { APSHUFB, ymshufb,Pq, {0x38, 0x00} },
+
+ { AUSEFIELD, ynop, Px, {0,0} },
{ ATYPE },
- { AFUNCDATA, yfuncdata, Px, 0,0 },
- { APCDATA, ypcdata, Px, 0,0 },
+ { AFUNCDATA, yfuncdata, Px, {0,0} },
+ { APCDATA, ypcdata, Px, {0,0} },
{ ACHECKNIL },
{ AVARDEF },
{ AVARKILL },
- { ADUFFCOPY, yduff, Px, 0xe8 },
- { ADUFFZERO, yduff, Px, 0xe8 },
+ { ADUFFCOPY, yduff, Px, {0xe8} },
+ { ADUFFZERO, yduff, Px, {0xe8} },
- 0
+ {0}
};
static int32 vaddr(Link*, Addr*, Reloc*);
@@ -1902,7 +1900,11 @@ bad:
return;
}
-#define E 0xff
+enum
+{
+ E = 0xff,
+};
+
static uchar ymovtab[] =
{
/* push */
@@ -2134,7 +2136,7 @@ mediaop(Link *ctxt, Optab *o, int op, int osize, int z)
break;
}
default:
- if(ctxt->andptr == ctxt->and || ctxt->andptr[-1] != Pm)
+ if(ctxt->andptr == ctxt->and || ctxt->and[ctxt->andptr - ctxt->and - 1] != Pm)
*ctxt->andptr++ = Pm;
break;
}
@@ -2289,8 +2291,13 @@ found:
*ctxt->andptr++ = p->from.offset;
break;
+ case Zcallindreg:
+ r = addrel(ctxt->cursym);
+ r->off = p->pc;
+ r->type = R_CALLIND;
+ r->siz = 0;
+ // fallthrough
case Zo_m:
- case_Zo_m:
*ctxt->andptr++ = op;
asmand(ctxt, &p->to, o->op[z+1]);
break;
@@ -2511,13 +2518,6 @@ found:
put4(ctxt, 0);
break;
- case Zcallindreg:
- r = addrel(ctxt->cursym);
- r->off = p->pc;
- r->type = R_CALLIND;
- r->siz = 0;
- goto case_Zo_m;
-
case Zbyte:
v = vaddr(ctxt, &p->from, &rel);
if(rel.siz != 0) {
@@ -2707,11 +2707,11 @@ mfound:
break;
case Hplan9:
- if(ctxt->plan9tos == nil)
- ctxt->plan9tos = linklookup(ctxt, "_tos", 0);
+ if(ctxt->plan9privates == nil)
+ ctxt->plan9privates = linklookup(ctxt, "_privates", 0);
memset(&pp.from, 0, sizeof pp.from);
pp.from.type = D_EXTERN;
- pp.from.sym = ctxt->plan9tos;
+ pp.from.sym = ctxt->plan9privates;
pp.from.offset = 0;
pp.from.index = D_NONE;
*ctxt->andptr++ = 0x8B;
diff --git a/src/liblink/data.c b/src/liblink/data.c
index 4504f4171..e5efa2eb2 100644
--- a/src/liblink/data.c
+++ b/src/liblink/data.c
@@ -83,6 +83,8 @@ savedata(Link *ctxt, LSym *s, Prog *p, char *pn)
siz = ctxt->arch->datasize(p);
if(off < 0 || siz < 0 || off >= 1<<30 || siz >= 100)
mangle(pn);
+ if(ctxt->enforce_data_order && off < s->np)
+ ctxt->diag("data out of order (already have %d)\n%P", p);
symgrow(ctxt, s, off+siz);
if(p->to.type == ctxt->arch->D_FCONST) {
diff --git a/src/liblink/ld.c b/src/liblink/ld.c
index 9ea0e9a73..6d0fe4a2a 100644
--- a/src/liblink/ld.c
+++ b/src/liblink/ld.c
@@ -130,16 +130,26 @@ find1(int32 l, int c)
}
void
-nuxiinit(void)
+nuxiinit(LinkArch *arch)
{
int i, c;
+ if(arch->endian != BigEndian && arch->endian != LittleEndian)
+ sysfatal("unknown endian (%#x) for arch %s", arch->endian, arch->name);
+
for(i=0; i<4; i++) {
- c = find1(0x04030201L, i+1);
- if(i < 2)
- inuxi2[i] = c;
- if(i < 1)
- inuxi1[i] = c;
+ c = find1(arch->endian, i+1);
+ if(arch->endian == LittleEndian) {
+ if(i < 2)
+ inuxi2[i] = c;
+ if(i < 1)
+ inuxi1[i] = c;
+ } else {
+ if(i >= 2)
+ inuxi2[i-2] = c;
+ if(i >= 3)
+ inuxi1[i-3] = c;
+ }
inuxi4[i] = c;
if(c == i) {
inuxi8[i] = c;
@@ -149,8 +159,13 @@ nuxiinit(void)
inuxi8[i+4] = c;
}
fnuxi4[i] = c;
- fnuxi8[i] = c;
- fnuxi8[i+4] = c+4;
+ if(c == i) {
+ fnuxi8[i] = c;
+ fnuxi8[i+4] = c+4;
+ } else {
+ fnuxi8[i] = c+4;
+ fnuxi8[i+4] = c;
+ }
}
}
@@ -161,7 +176,10 @@ uchar inuxi2[2];
uchar inuxi4[4];
uchar inuxi8[8];
-#define LOG 5
+enum
+{
+ LOG = 5,
+};
void
mkfwd(LSym *sym)
{
diff --git a/src/liblink/list5.c b/src/liblink/list5.c
index 4a4e8c71f..a91df55e6 100644
--- a/src/liblink/list5.c
+++ b/src/liblink/list5.c
@@ -46,6 +46,7 @@ static int Pconv(Fmt *fp);
static int Rconv(Fmt *fp);
static int RAconv(Fmt *fp);
static int DSconv(Fmt *fp);
+static int DRconv(Fmt*);
#pragma varargck type "$" char*
#pragma varargck type "M" Addr*
@@ -59,6 +60,9 @@ listinit5(void)
fmtinstall('P', Pconv);
fmtinstall('R', Rconv);
+ // for liblink internal use
+ fmtinstall('^', DRconv);
+
// for internal use
fmtinstall('$', DSconv);
fmtinstall('M', Mconv);
@@ -314,6 +318,19 @@ Rconv(Fmt *fp)
}
static int
+DRconv(Fmt *fp)
+{
+ char *s;
+ int a;
+
+ a = va_arg(fp->args, int);
+ s = "C_??";
+ if(a >= C_NONE && a <= C_NCLASS)
+ s = cnames5[a];
+ return fmtstrcpy(fp, s);
+}
+
+static int
Mconv(Fmt *fp)
{
char str[STRINGSZ];
diff --git a/src/liblink/list6.c b/src/liblink/list6.c
index fe708d877..0635fdf1f 100644
--- a/src/liblink/list6.c
+++ b/src/liblink/list6.c
@@ -217,7 +217,7 @@ conv:
return fmtstrcpy(fp, str);
}
-char* regstr[] =
+static char* regstr[] =
{
"AL", /* [D_AL] */
"CL",
diff --git a/src/liblink/list8.c b/src/liblink/list8.c
index 786692416..63d96b9f9 100644
--- a/src/liblink/list8.c
+++ b/src/liblink/list8.c
@@ -211,7 +211,7 @@ conv:
return fmtstrcpy(fp, str);
}
-char* regstr[] =
+static char* regstr[] =
{
"AL", /* [D_AL] */
"CL",
diff --git a/src/liblink/obj5.c b/src/liblink/obj5.c
index ccd4c81c7..d7f2714ed 100644
--- a/src/liblink/obj5.c
+++ b/src/liblink/obj5.c
@@ -33,7 +33,7 @@
#include <bio.h>
#include <link.h>
#include "../cmd/5l/5.out.h"
-#include "../pkg/runtime/stack.h"
+#include "../runtime/stack.h"
static Prog zprg = {
.as = AGOK,
@@ -92,7 +92,7 @@ progedit(Link *ctxt, Prog *p)
{
char literal[64];
LSym *s;
- LSym *tlsfallback;
+ static LSym *tlsfallback;
p->from.class = 0;
p->to.class = 0;
@@ -111,19 +111,43 @@ progedit(Link *ctxt, Prog *p)
// Replace TLS register fetches on older ARM procesors.
switch(p->as) {
case AMRC:
- // If the instruction matches MRC 15, 0, <reg>, C13, C0, 3, replace it.
- if(ctxt->goarm < 7 && (p->to.offset & 0xffff0fff) == 0xee1d0f70) {
- tlsfallback = linklookup(ctxt, "runtime.read_tls_fallback", 0);
+ // Treat MRC 15, 0, <reg>, C13, C0, 3 specially.
+ if((p->to.offset & 0xffff0fff) == 0xee1d0f70) {
+ // Because the instruction might be rewriten to a BL which returns in R0
+ // the register must be zero.
+ if ((p->to.offset & 0xf000) != 0)
+ ctxt->diag("%L: TLS MRC instruction must write to R0 as it might get translated into a BL instruction", p->lineno);
+
+ if(ctxt->goarm < 7) {
+ // Replace it with BL runtime.read_tls_fallback(SB) for ARM CPUs that lack the tls extension.
+ if(tlsfallback == nil)
+ tlsfallback = linklookup(ctxt, "runtime.read_tls_fallback", 0);
+ // MOVW LR, R11
+ p->as = AMOVW;
+ p->from.type = D_REG;
+ p->from.reg = REGLINK;
+ p->to.type = D_REG;
+ p->to.reg = REGTMP;
- // BL runtime.read_tls_fallback(SB)
- p->as = ABL;
- p->to.type = D_BRANCH;
- p->to.sym = tlsfallback;
- p->to.offset = 0;
- } else {
- // Otherwise, MRC/MCR instructions need no further treatment.
- p->as = AWORD;
+ // BL runtime.read_tls_fallback(SB)
+ p = appendp(ctxt, p);
+ p->as = ABL;
+ p->to.type = D_BRANCH;
+ p->to.sym = tlsfallback;
+ p->to.offset = 0;
+
+ // MOVW R11, LR
+ p = appendp(ctxt, p);
+ p->as = AMOVW;
+ p->from.type = D_REG;
+ p->from.reg = REGTMP;
+ p->to.type = D_REG;
+ p->to.reg = REGLINK;
+ break;
+ }
}
+ // Otherwise, MRC/MCR instructions need no further treatment.
+ p->as = AWORD;
break;
}
@@ -173,15 +197,15 @@ progedit(Link *ctxt, Prog *p)
if(ctxt->flag_shared) {
// Shared libraries use R_ARM_TLS_IE32 instead of
// R_ARM_TLS_LE32, replacing the link time constant TLS offset in
- // runtime.tlsgm with an address to a GOT entry containing the
- // offset. Rewrite $runtime.tlsgm(SB) to runtime.tlsgm(SB) to
+ // runtime.tlsg with an address to a GOT entry containing the
+ // offset. Rewrite $runtime.tlsg(SB) to runtime.tlsg(SB) to
// compensate.
- if(ctxt->gmsym == nil)
- ctxt->gmsym = linklookup(ctxt, "runtime.tlsgm", 0);
+ if(ctxt->tlsg == nil)
+ ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0);
- if(p->from.type == D_CONST && p->from.name == D_EXTERN && p->from.sym == ctxt->gmsym)
+ if(p->from.type == D_CONST && p->from.name == D_EXTERN && p->from.sym == ctxt->tlsg)
p->from.type = D_OREG;
- if(p->to.type == D_CONST && p->to.name == D_EXTERN && p->to.sym == ctxt->gmsym)
+ if(p->to.type == D_CONST && p->to.name == D_EXTERN && p->to.sym == ctxt->tlsg)
p->to.type = D_OREG;
}
}
@@ -233,7 +257,7 @@ nocache(Prog *p)
static void
addstacksplit(Link *ctxt, LSym *cursym)
{
- Prog *p, *pl, *q, *q1, *q2;
+ Prog *p, *pl, *p1, *p2, *q, *q1, *q2;
int o;
int32 autosize, autoffset;
@@ -429,32 +453,89 @@ addstacksplit(Link *ctxt, LSym *cursym)
p->spadj = autosize;
if(cursym->text->reg & WRAPPER) {
- // g->panicwrap += autosize;
- // MOVW panicwrap_offset(g), R3
- // ADD $autosize, R3
- // MOVW R3 panicwrap_offset(g)
+ // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+ //
+ // MOVW g_panic(g), R1
+ // CMP $0, R1
+ // B.EQ end
+ // MOVW panic_argp(R1), R2
+ // ADD $(autosize+4), R13, R3
+ // CMP R2, R3
+ // B.NE end
+ // ADD $4, R13, R4
+ // MOVW R4, panic_argp(R1)
+ // end:
+ // NOP
+ //
+ // The NOP is needed to give the jumps somewhere to land.
+ // It is a liblink NOP, not an ARM NOP: it encodes to 0 instruction bytes.
+
p = appendp(ctxt, p);
p->as = AMOVW;
p->from.type = D_OREG;
p->from.reg = REGG;
- p->from.offset = 2*ctxt->arch->ptrsize;
+ p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
p->to.type = D_REG;
- p->to.reg = 3;
+ p->to.reg = 1;
+
+ p = appendp(ctxt, p);
+ p->as = ACMP;
+ p->from.type = D_CONST;
+ p->from.offset = 0;
+ p->reg = 1;
+
+ p = appendp(ctxt, p);
+ p->as = ABEQ;
+ p->to.type = D_BRANCH;
+ p1 = p;
+
+ p = appendp(ctxt, p);
+ p->as = AMOVW;
+ p->from.type = D_OREG;
+ p->from.reg = 1;
+ p->from.offset = 0; // Panic.argp
+ p->to.type = D_REG;
+ p->to.reg = 2;
p = appendp(ctxt, p);
p->as = AADD;
p->from.type = D_CONST;
- p->from.offset = autosize;
+ p->from.offset = autosize+4;
+ p->reg = 13;
p->to.type = D_REG;
p->to.reg = 3;
-
+
+ p = appendp(ctxt, p);
+ p->as = ACMP;
+ p->from.type = D_REG;
+ p->from.reg = 2;
+ p->reg = 3;
+
+ p = appendp(ctxt, p);
+ p->as = ABNE;
+ p->to.type = D_BRANCH;
+ p2 = p;
+
+ p = appendp(ctxt, p);
+ p->as = AADD;
+ p->from.type = D_CONST;
+ p->from.offset = 4;
+ p->reg = 13;
+ p->to.type = D_REG;
+ p->to.reg = 4;
+
p = appendp(ctxt, p);
p->as = AMOVW;
p->from.type = D_REG;
- p->from.reg = 3;
+ p->from.reg = 4;
p->to.type = D_OREG;
- p->to.reg = REGG;
- p->to.offset = 2*ctxt->arch->ptrsize;
+ p->to.reg = 1;
+ p->to.offset = 0; // Panic.argp
+
+ p = appendp(ctxt, p);
+ p->as = ANOP;
+ p1->pcond = p;
+ p2->pcond = p;
}
break;
@@ -475,44 +556,6 @@ addstacksplit(Link *ctxt, LSym *cursym)
}
}
- if(cursym->text->reg & WRAPPER) {
- int scond;
-
- // Preserve original RET's cond, to allow RET.EQ
- // in the implementation of reflect.call.
- scond = p->scond;
- p->scond = C_SCOND_NONE;
-
- // g->panicwrap -= autosize;
- // MOVW panicwrap_offset(g), R3
- // SUB $autosize, R3
- // MOVW R3 panicwrap_offset(g)
- p->as = AMOVW;
- p->from.type = D_OREG;
- p->from.reg = REGG;
- p->from.offset = 2*ctxt->arch->ptrsize;
- p->to.type = D_REG;
- p->to.reg = 3;
- p = appendp(ctxt, p);
-
- p->as = ASUB;
- p->from.type = D_CONST;
- p->from.offset = autosize;
- p->to.type = D_REG;
- p->to.reg = 3;
- p = appendp(ctxt, p);
-
- p->as = AMOVW;
- p->from.type = D_REG;
- p->from.reg = 3;
- p->to.type = D_OREG;
- p->to.reg = REGG;
- p->to.offset = 2*ctxt->arch->ptrsize;
- p = appendp(ctxt, p);
-
- p->scond = scond;
- }
-
p->as = AMOVW;
p->scond |= C_PBIT;
p->from.type = D_OREG;
@@ -707,41 +750,42 @@ softfloat(Link *ctxt, LSym *cursym)
default:
goto notsoft;
+ }
- soft:
- if (!wasfloat || (p->mark&LABEL)) {
- next = ctxt->arch->prg();
- *next = *p;
+ soft:
+ if (!wasfloat || (p->mark&LABEL)) {
+ next = ctxt->arch->prg();
+ *next = *p;
- // BL _sfloat(SB)
- *p = zprg;
- p->link = next;
- p->as = ABL;
+ // BL _sfloat(SB)
+ *p = zprg;
+ p->link = next;
+ p->as = ABL;
p->to.type = D_BRANCH;
- p->to.sym = symsfloat;
- p->lineno = next->lineno;
-
- p = next;
- wasfloat = 1;
- }
- break;
+ p->to.sym = symsfloat;
+ p->lineno = next->lineno;
- notsoft:
- wasfloat = 0;
+ p = next;
+ wasfloat = 1;
}
+ continue;
+
+ notsoft:
+ wasfloat = 0;
}
}
static Prog*
stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
{
- int32 arg;
-
// MOVW g_stackguard(g), R1
p = appendp(ctxt, p);
p->as = AMOVW;
p->from.type = D_OREG;
p->from.reg = REGG;
+ p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
p->to.type = D_REG;
p->to.reg = 1;
@@ -820,29 +864,6 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
p->scond = C_SCOND_NE;
}
- // MOVW.LS $framesize, R1
- p = appendp(ctxt, p);
- p->as = AMOVW;
- p->scond = C_SCOND_LS;
- p->from.type = D_CONST;
- p->from.offset = framesize;
- p->to.type = D_REG;
- p->to.reg = 1;
-
- // MOVW.LS $args, R2
- p = appendp(ctxt, p);
- p->as = AMOVW;
- p->scond = C_SCOND_LS;
- p->from.type = D_CONST;
- arg = ctxt->cursym->text->to.offset2;
- if(arg == 1) // special marker for known 0
- arg = 0;
- if(arg&3)
- ctxt->diag("misaligned argument size in stack split");
- p->from.offset = arg;
- p->to.type = D_REG;
- p->to.reg = 2;
-
// MOVW.LS R14, R3
p = appendp(ctxt, p);
p->as = AMOVW;
@@ -857,7 +878,10 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
p->as = ABL;
p->scond = C_SCOND_LS;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[noctxt];
+ if(ctxt->cursym->cfunc)
+ p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
+ else
+ p->to.sym = ctxt->symmorestack[noctxt];
// BLS start
p = appendp(ctxt, p);
@@ -1025,6 +1049,7 @@ loop:
LinkArch linkarm = {
.name = "arm",
.thechar = '5',
+ .endian = LittleEndian,
.addstacksplit = addstacksplit,
.assemble = span5,
@@ -1052,6 +1077,7 @@ LinkArch linkarm = {
.D_PARAM = D_PARAM,
.D_SCONST = D_SCONST,
.D_STATIC = D_STATIC,
+ .D_OREG = D_OREG,
.ACALL = ABL,
.ADATA = ADATA,
diff --git a/src/liblink/obj6.c b/src/liblink/obj6.c
index b1bcd0dc0..2acfd2f70 100644
--- a/src/liblink/obj6.c
+++ b/src/liblink/obj6.c
@@ -33,7 +33,7 @@
#include <bio.h>
#include <link.h>
#include "../cmd/6l/6.out.h"
-#include "../pkg/runtime/stack.h"
+#include "../runtime/stack.h"
static Prog zprg = {
.back = 2,
@@ -103,7 +103,7 @@ static int
canuselocaltls(Link *ctxt)
{
switch(ctxt->headtype) {
-// case Hlinux:
+ case Hplan9:
case Hwindows:
return 0;
}
@@ -342,32 +342,6 @@ nacladdr(Link *ctxt, Prog *p, Addr *a)
}
}
-static char*
-morename[] =
-{
- "runtime.morestack00",
- "runtime.morestack00_noctxt",
- "runtime.morestack10",
- "runtime.morestack10_noctxt",
- "runtime.morestack01",
- "runtime.morestack01_noctxt",
- "runtime.morestack11",
- "runtime.morestack11_noctxt",
-
- "runtime.morestack8",
- "runtime.morestack8_noctxt",
- "runtime.morestack16",
- "runtime.morestack16_noctxt",
- "runtime.morestack24",
- "runtime.morestack24_noctxt",
- "runtime.morestack32",
- "runtime.morestack32_noctxt",
- "runtime.morestack40",
- "runtime.morestack40_noctxt",
- "runtime.morestack48",
- "runtime.morestack48_noctxt",
-};
-
static Prog* load_g_cx(Link*, Prog*);
static Prog* stacksplit(Link*, Prog*, int32, int32, int, Prog**);
static void indir_cx(Link*, Addr*);
@@ -388,20 +362,21 @@ parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
static void
addstacksplit(Link *ctxt, LSym *cursym)
{
- Prog *p, *q, *q1;
+ Prog *p, *q, *p1, *p2;
int32 autoffset, deltasp;
int a, pcsize;
- uint32 i;
vlong textstksiz, textarg;
- if(ctxt->gmsym == nil)
- ctxt->gmsym = linklookup(ctxt, "runtime.tlsgm", 0);
+ if(ctxt->tlsg == nil)
+ ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0);
if(ctxt->symmorestack[0] == nil) {
- if(nelem(morename) > nelem(ctxt->symmorestack))
- sysfatal("Link.symmorestack needs at least %d elements", nelem(morename));
- for(i=0; i<nelem(morename); i++)
- ctxt->symmorestack[i] = linklookup(ctxt, morename[i], 0);
+ ctxt->symmorestack[0] = linklookup(ctxt, "runtime.morestack", 0);
+ ctxt->symmorestack[1] = linklookup(ctxt, "runtime.morestack_noctxt", 0);
}
+
+ if(ctxt->headtype == Hplan9 && ctxt->plan9privates == nil)
+ ctxt->plan9privates = linklookup(ctxt, "_privates", 0);
+
ctxt->cursym = cursym;
if(cursym->text == nil || cursym->text->link == nil)
@@ -459,51 +434,88 @@ addstacksplit(Link *ctxt, LSym *cursym)
deltasp = autoffset;
if(cursym->text->from.scale & WRAPPER) {
- // g->panicwrap += autoffset + ctxt->arch->regsize;
- p = appendp(ctxt, p);
- p->as = AADDL;
- p->from.type = D_CONST;
- p->from.offset = autoffset + ctxt->arch->regsize;
- indir_cx(ctxt, &p->to);
- p->to.offset = 2*ctxt->arch->ptrsize;
- }
+ // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+ //
+ // MOVQ g_panic(CX), BX
+ // TESTQ BX, BX
+ // JEQ end
+ // LEAQ (autoffset+8)(SP), DI
+ // CMPQ panic_argp(BX), DI
+ // JNE end
+ // MOVQ SP, panic_argp(BX)
+ // end:
+ // NOP
+ //
+ // The NOP is needed to give the jumps somewhere to land.
+ // It is a liblink NOP, not an x86 NOP: it encodes to 0 instruction bytes.
- if(ctxt->debugstack > 1 && autoffset) {
- // 6l -K -K means double-check for stack overflow
- // even after calling morestack and even if the
- // function is marked as nosplit.
p = appendp(ctxt, p);
p->as = AMOVQ;
- indir_cx(ctxt, &p->from);
- p->from.offset = 0;
+ p->from.type = D_INDIR+D_CX;
+ p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
p->to.type = D_BX;
+ if(ctxt->headtype == Hnacl) {
+ p->as = AMOVL;
+ p->from.type = D_INDIR+D_R15;
+ p->from.scale = 1;
+ p->from.index = D_CX;
+ }
p = appendp(ctxt, p);
- p->as = ASUBQ;
- p->from.type = D_CONST;
- p->from.offset = StackSmall+32;
+ p->as = ATESTQ;
+ p->from.type = D_BX;
p->to.type = D_BX;
+ if(ctxt->headtype == Hnacl)
+ p->as = ATESTL;
+
+ p = appendp(ctxt, p);
+ p->as = AJEQ;
+ p->to.type = D_BRANCH;
+ p1 = p;
+
+ p = appendp(ctxt, p);
+ p->as = ALEAQ;
+ p->from.type = D_INDIR+D_SP;
+ p->from.offset = autoffset+8;
+ p->to.type = D_DI;
+ if(ctxt->headtype == Hnacl)
+ p->as = ALEAL;
p = appendp(ctxt, p);
p->as = ACMPQ;
- p->from.type = D_SP;
- p->to.type = D_BX;
+ p->from.type = D_INDIR+D_BX;
+ p->from.offset = 0; // Panic.argp
+ p->to.type = D_DI;
+ if(ctxt->headtype == Hnacl) {
+ p->as = ACMPL;
+ p->from.type = D_INDIR+D_R15;
+ p->from.scale = 1;
+ p->from.index = D_BX;
+ }
p = appendp(ctxt, p);
- p->as = AJHI;
+ p->as = AJNE;
p->to.type = D_BRANCH;
- q1 = p;
+ p2 = p;
p = appendp(ctxt, p);
- p->as = AINT;
- p->from.type = D_CONST;
- p->from.offset = 3;
+ p->as = AMOVQ;
+ p->from.type = D_SP;
+ p->to.type = D_INDIR+D_BX;
+ p->to.offset = 0; // Panic.argp
+ if(ctxt->headtype == Hnacl) {
+ p->as = AMOVL;
+ p->to.type = D_INDIR+D_R15;
+ p->to.scale = 1;
+ p->to.index = D_BX;
+ }
p = appendp(ctxt, p);
p->as = ANOP;
- q1->pcond = p;
+ p1->pcond = p;
+ p2->pcond = p;
}
-
+
if(ctxt->debugzerostack && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
// 6l -Z means zero the stack frame on entry.
// This slows down function calls but can help avoid
@@ -585,19 +597,6 @@ addstacksplit(Link *ctxt, LSym *cursym)
if(autoffset != deltasp)
ctxt->diag("unbalanced PUSH/POP");
- if(cursym->text->from.scale & WRAPPER) {
- p = load_g_cx(ctxt, p);
- p = appendp(ctxt, p);
- // g->panicwrap -= autoffset + ctxt->arch->regsize;
- p->as = ASUBL;
- p->from.type = D_CONST;
- p->from.offset = autoffset + ctxt->arch->regsize;
- indir_cx(ctxt, &p->to);
- p->to.offset = 2*ctxt->arch->ptrsize;
- p = appendp(ctxt, p);
- p->as = ARET;
- }
-
if(autoffset) {
p->as = AADJSP;
p->from.type = D_CONST;
@@ -667,9 +666,9 @@ static Prog*
stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog **jmpok)
{
Prog *q, *q1;
- uint32 moreconst1, moreconst2, i;
int cmp, lea, mov, sub;
+ USED(textarg);
cmp = ACMPQ;
lea = ALEAQ;
mov = AMOVQ;
@@ -682,35 +681,6 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog
sub = ASUBL;
}
- if(ctxt->debugstack) {
- // 6l -K means check not only for stack
- // overflow but stack underflow.
- // On underflow, INT 3 (breakpoint).
- // Underflow itself is rare but this also
- // catches out-of-sync stack guard info
-
- p = appendp(ctxt, p);
- p->as = cmp;
- indir_cx(ctxt, &p->from);
- p->from.offset = 8;
- p->to.type = D_SP;
-
- p = appendp(ctxt, p);
- p->as = AJHI;
- p->to.type = D_BRANCH;
- p->to.offset = 4;
- q1 = p;
-
- p = appendp(ctxt, p);
- p->as = AINT;
- p->from.type = D_CONST;
- p->from.offset = 3;
-
- p = appendp(ctxt, p);
- p->as = ANOP;
- q1->pcond = p;
- }
-
q1 = nil;
if(framesize <= StackSmall) {
// small stack: SP <= stackguard
@@ -719,6 +689,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog
p->as = cmp;
p->from.type = D_SP;
indir_cx(ctxt, &p->to);
+ p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
} else if(framesize <= StackBig) {
// large stack: SP-framesize <= stackguard-StackSmall
// LEAQ -xxx(SP), AX
@@ -733,6 +706,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog
p->as = cmp;
p->from.type = D_AX;
indir_cx(ctxt, &p->to);
+ p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
} else {
// Such a large stack we need to protect against wraparound.
// If SP is close to zero:
@@ -752,7 +728,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog
p = appendp(ctxt, p);
p->as = mov;
indir_cx(ctxt, &p->from);
- p->from.offset = 0;
+ p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
p->to.type = D_SI;
p = appendp(ctxt, p);
@@ -790,70 +768,13 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog
p->to.type = D_BRANCH;
q = p;
- // If we ask for more stack, we'll get a minimum of StackMin bytes.
- // We need a stack frame large enough to hold the top-of-stack data,
- // the function arguments+results, our caller's PC, our frame,
- // a word for the return PC of the next call, and then the StackLimit bytes
- // that must be available on entry to any function called from a function
- // that did a stack check. If StackMin is enough, don't ask for a specific
- // amount: then we can use the custom functions and save a few
- // instructions.
- moreconst1 = 0;
- if(StackTop + textarg + ctxt->arch->ptrsize + framesize + ctxt->arch->ptrsize + StackLimit >= StackMin)
- moreconst1 = framesize;
- moreconst2 = textarg;
- if(moreconst2 == 1) // special marker
- moreconst2 = 0;
- if((moreconst2&7) != 0)
- ctxt->diag("misaligned argument size in stack split");
- // 4 varieties varieties (const1==0 cross const2==0)
- // and 6 subvarieties of (const1==0 and const2!=0)
p = appendp(ctxt, p);
- if(moreconst1 == 0 && moreconst2 == 0) {
- p->as = ACALL;
- p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[0*2+noctxt];
- } else
- if(moreconst1 != 0 && moreconst2 == 0) {
- p->as = AMOVL;
- p->from.type = D_CONST;
- p->from.offset = moreconst1;
- p->to.type = D_AX;
-
- p = appendp(ctxt, p);
- p->as = ACALL;
- p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[1*2+noctxt];
- } else
- if(moreconst1 == 0 && moreconst2 <= 48 && moreconst2%8 == 0) {
- i = moreconst2/8 + 3;
- p->as = ACALL;
- p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[i*2+noctxt];
- } else
- if(moreconst1 == 0 && moreconst2 != 0) {
- p->as = AMOVL;
- p->from.type = D_CONST;
- p->from.offset = moreconst2;
- p->to.type = D_AX;
-
- p = appendp(ctxt, p);
- p->as = ACALL;
- p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[2*2+noctxt];
- } else {
- // Pass framesize and argsize.
- p->as = AMOVQ;
- p->from.type = D_CONST;
- p->from.offset = (uint64)moreconst2 << 32;
- p->from.offset |= moreconst1;
- p->to.type = D_AX;
-
- p = appendp(ctxt, p);
- p->as = ACALL;
- p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[3*2+noctxt];
- }
+ p->as = ACALL;
+ p->to.type = D_BRANCH;
+ if(ctxt->cursym->cfunc)
+ p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
+ else
+ p->to.sym = ctxt->symmorestack[noctxt];
p = appendp(ctxt, p);
p->as = AJMP;
@@ -954,7 +875,7 @@ xfol(Link *ctxt, Prog *p, Prog **last)
{
Prog *q;
int i;
- enum as a;
+ int a;
loop:
if(p == nil)
@@ -1083,6 +1004,7 @@ prg(void)
LinkArch linkamd64 = {
.name = "amd64",
.thechar = '6',
+ .endian = LittleEndian,
.addstacksplit = addstacksplit,
.assemble = span6,
@@ -1128,6 +1050,7 @@ LinkArch linkamd64 = {
LinkArch linkamd64p32 = {
.name = "amd64p32",
.thechar = '6',
+ .endian = LittleEndian,
.addstacksplit = addstacksplit,
.assemble = span6,
diff --git a/src/liblink/obj8.c b/src/liblink/obj8.c
index 72934c149..f54153ae9 100644
--- a/src/liblink/obj8.c
+++ b/src/liblink/obj8.c
@@ -33,7 +33,7 @@
#include <bio.h>
#include <link.h>
#include "../cmd/8l/8.out.h"
-#include "../pkg/runtime/stack.h"
+#include "../runtime/stack.h"
static Prog zprg = {
.back = 2,
@@ -261,7 +261,7 @@ static Prog* stacksplit(Link*, Prog*, int32, int, Prog**);
static void
addstacksplit(Link *ctxt, LSym *cursym)
{
- Prog *p, *q;
+ Prog *p, *q, *p1, *p2;
int32 autoffset, deltasp;
int a;
@@ -270,8 +270,8 @@ addstacksplit(Link *ctxt, LSym *cursym)
ctxt->symmorestack[1] = linklookup(ctxt, "runtime.morestack_noctxt", 0);
}
- if(ctxt->headtype == Hplan9 && ctxt->plan9tos == nil)
- ctxt->plan9tos = linklookup(ctxt, "_tos", 0);
+ if(ctxt->headtype == Hplan9 && ctxt->plan9privates == nil)
+ ctxt->plan9privates = linklookup(ctxt, "_privates", 0);
ctxt->cursym = cursym;
@@ -317,13 +317,64 @@ addstacksplit(Link *ctxt, LSym *cursym)
deltasp = autoffset;
if(cursym->text->from.scale & WRAPPER) {
- // g->panicwrap += autoffset + ctxt->arch->ptrsize;
+ // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+ //
+ // MOVL g_panic(CX), BX
+ // TESTL BX, BX
+ // JEQ end
+ // LEAL (autoffset+4)(SP), DI
+ // CMPL panic_argp(BX), DI
+ // JNE end
+ // MOVL SP, panic_argp(BX)
+ // end:
+ // NOP
+ //
+ // The NOP is needed to give the jumps somewhere to land.
+ // It is a liblink NOP, not an x86 NOP: it encodes to 0 instruction bytes.
+
p = appendp(ctxt, p);
- p->as = AADDL;
- p->from.type = D_CONST;
- p->from.offset = autoffset + ctxt->arch->ptrsize;
- p->to.type = D_INDIR+D_CX;
- p->to.offset = 2*ctxt->arch->ptrsize;
+ p->as = AMOVL;
+ p->from.type = D_INDIR+D_CX;
+ p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
+ p->to.type = D_BX;
+
+ p = appendp(ctxt, p);
+ p->as = ATESTL;
+ p->from.type = D_BX;
+ p->to.type = D_BX;
+
+ p = appendp(ctxt, p);
+ p->as = AJEQ;
+ p->to.type = D_BRANCH;
+ p1 = p;
+
+ p = appendp(ctxt, p);
+ p->as = ALEAL;
+ p->from.type = D_INDIR+D_SP;
+ p->from.offset = autoffset+4;
+ p->to.type = D_DI;
+
+ p = appendp(ctxt, p);
+ p->as = ACMPL;
+ p->from.type = D_INDIR+D_BX;
+ p->from.offset = 0; // Panic.argp
+ p->to.type = D_DI;
+
+ p = appendp(ctxt, p);
+ p->as = AJNE;
+ p->to.type = D_BRANCH;
+ p2 = p;
+
+ p = appendp(ctxt, p);
+ p->as = AMOVL;
+ p->from.type = D_SP;
+ p->to.type = D_INDIR+D_BX;
+ p->to.offset = 0; // Panic.argp
+
+ p = appendp(ctxt, p);
+ p->as = ANOP;
+ p1->pcond = p;
+ p2->pcond = p;
}
if(ctxt->debugzerostack && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
@@ -396,19 +447,6 @@ addstacksplit(Link *ctxt, LSym *cursym)
if(autoffset != deltasp)
ctxt->diag("unbalanced PUSH/POP");
- if(cursym->text->from.scale & WRAPPER) {
- p = load_g_cx(ctxt, p);
- p = appendp(ctxt, p);
- // g->panicwrap -= autoffset + ctxt->arch->ptrsize;
- p->as = ASUBL;
- p->from.type = D_CONST;
- p->from.offset = autoffset + ctxt->arch->ptrsize;
- p->to.type = D_INDIR+D_CX;
- p->to.offset = 2*ctxt->arch->ptrsize;
- p = appendp(ctxt, p);
- p->as = ARET;
- }
-
if(autoffset) {
p->as = AADJSP;
p->from.type = D_CONST;
@@ -463,7 +501,6 @@ static Prog*
stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
{
Prog *q, *q1;
- int arg;
if(ctxt->debugstack) {
// 8l -K means check not only for stack
@@ -501,6 +538,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
p->as = ACMPL;
p->from.type = D_SP;
p->to.type = D_INDIR+D_CX;
+ p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
} else if(framesize <= StackBig) {
// large stack: SP-framesize <= stackguard-StackSmall
// LEAL -(framesize-StackSmall)(SP), AX
@@ -515,6 +555,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
p->as = ACMPL;
p->from.type = D_AX;
p->to.type = D_INDIR+D_CX;
+ p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
} else {
// Such a large stack we need to protect against wraparound
// if SP is close to zero.
@@ -534,6 +577,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
p->as = AMOVL;
p->from.type = D_INDIR+D_CX;
p->from.offset = 0;
+ p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+ if(ctxt->cursym->cfunc)
+ p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
p->to.type = D_SI;
p = appendp(ctxt, p);
@@ -573,37 +619,13 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
p->to.offset = 4;
q = p;
- p = appendp(ctxt, p); // save frame size in DI
- p->as = AMOVL;
- p->to.type = D_DI;
- p->from.type = D_CONST;
-
- // If we ask for more stack, we'll get a minimum of StackMin bytes.
- // We need a stack frame large enough to hold the top-of-stack data,
- // the function arguments+results, our caller's PC, our frame,
- // a word for the return PC of the next call, and then the StackLimit bytes
- // that must be available on entry to any function called from a function
- // that did a stack check. If StackMin is enough, don't ask for a specific
- // amount: then we can use the custom functions and save a few
- // instructions.
- if(StackTop + ctxt->cursym->text->to.offset2 + ctxt->arch->ptrsize + framesize + ctxt->arch->ptrsize + StackLimit >= StackMin)
- p->from.offset = (framesize+7) & ~7LL;
-
- arg = ctxt->cursym->text->to.offset2;
- if(arg == 1) // special marker for known 0
- arg = 0;
- if(arg&3)
- ctxt->diag("misaligned argument size in stack split");
- p = appendp(ctxt, p); // save arg size in AX
- p->as = AMOVL;
- p->to.type = D_AX;
- p->from.type = D_CONST;
- p->from.offset = arg;
-
p = appendp(ctxt, p);
p->as = ACALL;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[noctxt];
+ if(ctxt->cursym->cfunc)
+ p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
+ else
+ p->to.sym = ctxt->symmorestack[noctxt];
p = appendp(ctxt, p);
p->as = AJMP;
@@ -697,7 +719,7 @@ xfol(Link *ctxt, Prog *p, Prog **last)
{
Prog *q;
int i;
- enum as a;
+ int a;
loop:
if(p == nil)
@@ -816,6 +838,7 @@ loop:
LinkArch link386 = {
.name = "386",
.thechar = '8',
+ .endian = LittleEndian,
.addstacksplit = addstacksplit,
.assemble = span8,
diff --git a/src/liblink/objfile.c b/src/liblink/objfile.c
index 610f87954..b2478ec17 100644
--- a/src/liblink/objfile.c
+++ b/src/liblink/objfile.c
@@ -38,7 +38,8 @@
// - type [int]
// - name [string]
// - version [int]
-// - dupok [int]
+// - flags [int]
+// 1 dupok
// - size [int]
// - gotype [symbol reference]
// - p [data block]
@@ -50,7 +51,9 @@
// - args [int]
// - locals [int]
// - nosplit [int]
-// - leaf [int]
+// - flags [int]
+// 1 leaf
+// 2 C function
// - nlocal [int]
// - local [nlocal automatics]
// - pcln [pcln table]
@@ -100,6 +103,7 @@
#include <bio.h>
#include <link.h>
#include "../cmd/ld/textflag.h"
+#include "../runtime/funcdata.h"
static void writesym(Link*, Biobuf*, LSym*);
static void wrint(Biobuf*, int64);
@@ -121,7 +125,7 @@ static LSym *rdsym(Link*, Biobuf*, char*);
void
writeobj(Link *ctxt, Biobuf *b)
{
- int flag;
+ int flag, found;
Hist *h;
LSym *s, *text, *etext, *curtext, *data, *edata;
Plist *pl;
@@ -183,12 +187,7 @@ writeobj(Link *ctxt, Biobuf *b)
s->size = p->to.offset;
if(s->type == 0 || s->type == SXREF)
s->type = SBSS;
-
- if(ctxt->arch->thechar == '5')
- flag = p->reg;
- else
- flag = p->from.scale;
-
+ flag = ctxt->arch->textflag(p);
if(flag & DUPOK)
s->dupok = 1;
if(flag & RODATA)
@@ -221,10 +220,7 @@ writeobj(Link *ctxt, Biobuf *b)
else
etext->next = s;
etext = s;
- if(ctxt->arch->thechar == '5')
- flag = p->reg;
- else
- flag = p->from.scale;
+ flag = ctxt->arch->textflag(p);
if(flag & DUPOK)
s->dupok = 1;
if(flag & NOSPLIT)
@@ -237,6 +233,17 @@ writeobj(Link *ctxt, Biobuf *b)
continue;
}
+ if(p->as == ctxt->arch->AFUNCDATA) {
+ // Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information.
+ if(curtext == nil) // func _() {}
+ continue;
+ if(strcmp(p->to.sym->name, "go_args_stackmap") == 0) {
+ if(p->from.type != ctxt->arch->D_CONST || p->from.offset != FUNCDATA_ArgsPointerMaps)
+ ctxt->diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps");
+ p->to.sym = linklookup(ctxt, smprint("%s.args_stackmap", curtext->name), curtext->version);
+ }
+ }
+
if(curtext == nil)
continue;
s = curtext;
@@ -244,6 +251,32 @@ writeobj(Link *ctxt, Biobuf *b)
s->etext = p;
}
}
+
+ // Add reference to Go arguments for C or assembly functions without them.
+ for(s = text; s != nil; s = s->next) {
+ if(strncmp(s->name, "\"\".", 3) != 0)
+ continue;
+ found = 0;
+ for(p = s->text; p != nil; p = p->link) {
+ if(p->as == ctxt->arch->AFUNCDATA && p->from.type == ctxt->arch->D_CONST && p->from.offset == FUNCDATA_ArgsPointerMaps) {
+ found = 1;
+ break;
+ }
+ }
+ if(!found) {
+ p = appendp(ctxt, s->text);
+ p->as = ctxt->arch->AFUNCDATA;
+ p->from.type = ctxt->arch->D_CONST;
+ p->from.offset = FUNCDATA_ArgsPointerMaps;
+ if(ctxt->arch->thechar == '6' || ctxt->arch->thechar == '8')
+ p->to.type = ctxt->arch->D_EXTERN;
+ else {
+ p->to.type = ctxt->arch->D_OREG;
+ p->to.name = ctxt->arch->D_EXTERN;
+ }
+ p->to.sym = linklookup(ctxt, smprint("%s.args_stackmap", s->name), s->version);
+ }
+ }
// Turn functions into machine code images.
for(s = text; s != nil; s = s->next) {
@@ -297,6 +330,8 @@ writesym(Link *ctxt, Biobuf *b, LSym *s)
Bprint(ctxt->bso, "t=%d ", s->type);
if(s->dupok)
Bprint(ctxt->bso, "dupok ");
+ if(s->cfunc)
+ Bprint(ctxt->bso, "cfunc ");
if(s->nosplit)
Bprint(ctxt->bso, "nosplit ");
Bprint(ctxt->bso, "size=%lld value=%lld", (vlong)s->size, (vlong)s->value);
@@ -359,7 +394,7 @@ writesym(Link *ctxt, Biobuf *b, LSym *s)
wrint(b, s->args);
wrint(b, s->locals);
wrint(b, s->nosplit);
- wrint(b, s->leaf);
+ wrint(b, s->leaf | s->cfunc<<1);
n = 0;
for(a = s->autom; a != nil; a = a->link)
n++;
@@ -515,7 +550,7 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
static int ndup;
char *name;
Reloc *r;
- LSym *s, *dup;
+ LSym *s, *dup, *typ;
Pcln *pc;
Auto *a;
@@ -527,6 +562,7 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
if(v != 0 && v != 1)
sysfatal("invalid symbol version %d", v);
dupok = rdint(f);
+ dupok &= 1;
size = rdint(f);
if(v != 0)
@@ -550,7 +586,11 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
s->type = t;
if(s->size < size)
s->size = size;
- s->gotype = rdsym(ctxt, f, pkg);
+ typ = rdsym(ctxt, f, pkg);
+ if(typ != nil) // if bss sym defined multiple times, take type from any one def
+ s->gotype = typ;
+ if(dup != nil && typ != nil)
+ dup->gotype = typ;
rddata(f, &s->p, &s->np);
s->maxp = s->np;
n = rdint(f);
@@ -581,7 +621,9 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
s->args = rdint(f);
s->locals = rdint(f);
s->nosplit = rdint(f);
- s->leaf = rdint(f);
+ v = rdint(f);
+ s->leaf = v&1;
+ s->cfunc = v&2;
n = rdint(f);
for(i=0; i<n; i++) {
a = emallocz(sizeof *a);
@@ -637,6 +679,8 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
Bprint(ctxt->bso, "t=%d ", s->type);
if(s->dupok)
Bprint(ctxt->bso, "dupok ");
+ if(s->cfunc)
+ Bprint(ctxt->bso, "cfunc ");
if(s->nosplit)
Bprint(ctxt->bso, "nosplit ");
Bprint(ctxt->bso, "size=%lld value=%lld", (vlong)s->size, (vlong)s->value);
diff --git a/src/liblink/pcln.c b/src/liblink/pcln.c
index 4b2b85543..f0ee1dc67 100644
--- a/src/liblink/pcln.c
+++ b/src/liblink/pcln.c
@@ -279,7 +279,7 @@ linkpcln(Link *ctxt, LSym *cursym)
}
// pcdata.
for(i=0; i<npcdata; i++) {
- if(!(havepc[i/32]>>(i%32))&1)
+ if(((havepc[i/32]>>(i%32))&1) == 0)
continue;
funcpctab(ctxt, &pcln->pcdata[i], cursym, "pctopcdata", pctopcdata, (void*)(uintptr)i);
}
diff --git a/src/liblink/sym.c b/src/liblink/sym.c
index cba50e9c7..bd8551846 100644
--- a/src/liblink/sym.c
+++ b/src/liblink/sym.c
@@ -44,19 +44,20 @@ static struct {
char *name;
int val;
} headers[] = {
- "darwin", Hdarwin,
- "dragonfly", Hdragonfly,
- "elf", Helf,
- "freebsd", Hfreebsd,
- "linux", Hlinux,
- "nacl", Hnacl,
- "netbsd", Hnetbsd,
- "openbsd", Hopenbsd,
- "plan9", Hplan9,
- "solaris", Hsolaris,
- "windows", Hwindows,
- "windowsgui", Hwindows,
- 0, 0
+ {"android", Hlinux},
+ {"darwin", Hdarwin},
+ {"dragonfly", Hdragonfly},
+ {"elf", Helf},
+ {"freebsd", Hfreebsd},
+ {"linux", Hlinux},
+ {"nacl", Hnacl},
+ {"netbsd", Hnetbsd},
+ {"openbsd", Hopenbsd},
+ {"plan9", Hplan9},
+ {"solaris", Hsolaris},
+ {"windows", Hwindows},
+ {"windowsgui", Hwindows},
+ {0, 0},
};
int
@@ -90,7 +91,7 @@ linknew(LinkArch *arch)
char *p;
char buf[1024];
- nuxiinit();
+ nuxiinit(arch);
ctxt = emallocz(sizeof *ctxt);
ctxt->arch = arch;
@@ -127,8 +128,6 @@ linknew(LinkArch *arch)
default:
sysfatal("unknown thread-local storage offset for %s", headstr(ctxt->headtype));
case Hplan9:
- ctxt->tlsoffset = -2*ctxt->arch->ptrsize;
- break;
case Hwindows:
break;
case Hlinux:
@@ -155,13 +154,16 @@ linknew(LinkArch *arch)
case '8':
ctxt->tlsoffset = -8;
break;
+ case '5':
+ ctxt->tlsoffset = 0;
+ break;
}
break;
case Hdarwin:
/*
* OS X system constants - offset from 0(GS) to our TLS.
- * Explained in ../../pkg/runtime/cgo/gcc_darwin_*.c.
+ * Explained in ../../runtime/cgo/gcc_darwin_*.c.
*/
switch(ctxt->arch->thechar) {
default:
@@ -192,19 +194,14 @@ LSym*
linknewsym(Link *ctxt, char *symb, int v)
{
LSym *s;
- int l;
- l = strlen(symb) + 1;
s = malloc(sizeof(*s));
memset(s, 0, sizeof(*s));
s->dynid = -1;
s->plt = -1;
s->got = -1;
- s->name = malloc(l + 1);
- memmove(s->name, symb, l);
- s->name[l] = '\0';
-
+ s->name = estrdup(symb);
s->type = 0;
s->version = v;
s->value = 0;
diff --git a/src/pkg/log/example_test.go b/src/log/example_test.go
index 74385a3a0..74385a3a0 100644
--- a/src/pkg/log/example_test.go
+++ b/src/log/example_test.go
diff --git a/src/pkg/log/log.go b/src/log/log.go
index d37e4375e..d37e4375e 100644
--- a/src/pkg/log/log.go
+++ b/src/log/log.go
diff --git a/src/pkg/log/log_test.go b/src/log/log_test.go
index 158c3d93c..158c3d93c 100644
--- a/src/pkg/log/log_test.go
+++ b/src/log/log_test.go
diff --git a/src/pkg/log/syslog/syslog.go b/src/log/syslog/syslog.go
index 5e0959916..5e0959916 100644
--- a/src/pkg/log/syslog/syslog.go
+++ b/src/log/syslog/syslog.go
diff --git a/src/pkg/log/syslog/syslog_plan9.go b/src/log/syslog/syslog_plan9.go
index 0c05f6f83..0c05f6f83 100644
--- a/src/pkg/log/syslog/syslog_plan9.go
+++ b/src/log/syslog/syslog_plan9.go
diff --git a/src/pkg/log/syslog/syslog_test.go b/src/log/syslog/syslog_test.go
index 24a460f6d..6a863fed3 100644
--- a/src/pkg/log/syslog/syslog_test.go
+++ b/src/log/syslog/syslog_test.go
@@ -314,7 +314,7 @@ func TestConcurrentReconnect(t *testing.T) {
count := make(chan int)
go func() {
ct := 0
- for _ = range done {
+ for range done {
ct++
// we are looking for 500 out of 1000 events
// here because lots of log messages are lost
diff --git a/src/pkg/log/syslog/syslog_unix.go b/src/log/syslog/syslog_unix.go
index f6d2f1b7a..1cdabec69 100644
--- a/src/pkg/log/syslog/syslog_unix.go
+++ b/src/log/syslog/syslog_unix.go
@@ -16,7 +16,7 @@ import (
func unixSyslog() (conn serverConn, err error) {
logTypes := []string{"unixgram", "unix"}
- logPaths := []string{"/dev/log", "/var/run/syslog"}
+ logPaths := []string{"/dev/log", "/var/run/syslog", "/var/run/log"}
for _, network := range logTypes {
for _, path := range logPaths {
conn, err := net.Dial(network, path)
diff --git a/src/pkg/log/syslog/syslog_windows.go b/src/log/syslog/syslog_windows.go
index 8d99e2e59..8d99e2e59 100644
--- a/src/pkg/log/syslog/syslog_windows.go
+++ b/src/log/syslog/syslog_windows.go
diff --git a/src/make.bash b/src/make.bash
index d7b63ff09..fbc6f5d89 100755
--- a/src/make.bash
+++ b/src/make.bash
@@ -106,7 +106,7 @@ if [ "$(uname -s)" == "GNU/kFreeBSD" ]; then
fi
# Clean old generated file that will cause problems in the build.
-rm -f ./pkg/runtime/runtime_defs.go
+rm -f ./runtime/runtime_defs.go
# Finally! Run the build.
diff --git a/src/make.bat b/src/make.bat
index 23b799e36..fff1eb601 100644
--- a/src/make.bat
+++ b/src/make.bat
@@ -60,7 +60,7 @@ echo # Building C bootstrap tool.
echo cmd/dist
if not exist ..\bin\tool mkdir ..\bin\tool
:: Windows has no glob expansion, so spell out cmd/dist/*.c.
-gcc -O2 -Wall -Werror -o cmd/dist/dist.exe -Icmd/dist %DEFGOROOT% cmd/dist/buf.c cmd/dist/build.c cmd/dist/buildgc.c cmd/dist/buildgo.c cmd/dist/buildruntime.c cmd/dist/goc2c.c cmd/dist/main.c cmd/dist/windows.c cmd/dist/arm.c
+gcc -O2 -Wall -Werror -o cmd/dist/dist.exe -Icmd/dist %DEFGOROOT% cmd/dist/buf.c cmd/dist/build.c cmd/dist/buildgc.c cmd/dist/buildgo.c cmd/dist/buildruntime.c cmd/dist/main.c cmd/dist/windows.c cmd/dist/arm.c
if errorlevel 1 goto fail
.\cmd\dist\dist env -wp >env.bat
if errorlevel 1 goto fail
@@ -115,5 +115,6 @@ goto end
:fail
set GOBUILDFAIL=1
+if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%
:end
diff --git a/src/make.rc b/src/make.rc
index ab152c0db..7a62d6af0 100755
--- a/src/make.rc
+++ b/src/make.rc
@@ -40,7 +40,7 @@ if(! test -f run.rc){
../include/plan9/mklibc.rc > ../include/plan9/libc_plan9.h
# Clean old generated file that will cause problems in the build.
-rm -f ./pkg/runtime/runtime_defs.go
+rm -f ./runtime/runtime_defs.go
# Determine the host compiler toolchain.
eval `{grep '^(CC|LD|O)=' /$objtype/mkfile}
diff --git a/src/pkg/math/abs.go b/src/math/abs.go
index bc41a6d6b..bc41a6d6b 100644
--- a/src/pkg/math/abs.go
+++ b/src/math/abs.go
diff --git a/src/pkg/math/abs_386.s b/src/math/abs_386.s
index 3490cf66c..f30a439c2 100644
--- a/src/pkg/math/abs_386.s
+++ b/src/math/abs_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Abs(x float64) float64
TEXT ·Abs(SB),NOSPLIT,$0
diff --git a/src/pkg/math/abs_amd64.s b/src/math/abs_amd64.s
index 779c8f548..0424eb5fa 100644
--- a/src/pkg/math/abs_amd64.s
+++ b/src/math/abs_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Abs(x float64) float64
TEXT ·Abs(SB),NOSPLIT,$0
diff --git a/src/pkg/math/abs_amd64p32.s b/src/math/abs_amd64p32.s
index 08c8c6b33..08c8c6b33 100644
--- a/src/pkg/math/abs_amd64p32.s
+++ b/src/math/abs_amd64p32.s
diff --git a/src/pkg/math/abs_arm.s b/src/math/abs_arm.s
index b5117ab39..bfa77eb49 100644
--- a/src/pkg/math/abs_arm.s
+++ b/src/math/abs_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Abs(SB),NOSPLIT,$0
MOVW x_lo+0(FP), R0
diff --git a/src/pkg/math/acosh.go b/src/math/acosh.go
index e394008b0..e394008b0 100644
--- a/src/pkg/math/acosh.go
+++ b/src/math/acosh.go
diff --git a/src/pkg/math/all_test.go b/src/math/all_test.go
index 0d8b10f67..763efb2e6 100644
--- a/src/pkg/math/all_test.go
+++ b/src/math/all_test.go
@@ -456,7 +456,19 @@ var modf = [][2]float64{
{1.0000000000000000e+00, 8.2530809168085506044576505e-01},
{-8.0000000000000000e+00, -6.8592476857560136238589621e-01},
}
-var nextafter = []float64{
+var nextafter32 = []float32{
+ 4.979012489318848e+00,
+ 7.738873004913330e+00,
+ -2.768800258636475e-01,
+ -5.010602951049805e+00,
+ 9.636294364929199e+00,
+ 2.926377534866333e+00,
+ 5.229084014892578e+00,
+ 2.727940082550049e+00,
+ 1.825308203697205e+00,
+ -8.685923576354980e+00,
+}
+var nextafter64 = []float64{
4.97901192488367438926388786e+00,
7.73887247457810545370193722e+00,
-2.7688005719200153853520874e-01,
@@ -1331,7 +1343,32 @@ var modfSC = [][2]float64{
{NaN(), NaN()},
}
-var vfnextafterSC = [][2]float64{
+var vfnextafter32SC = [][2]float32{
+ {0, 0},
+ {0, float32(Copysign(0, -1))},
+ {0, -1},
+ {0, float32(NaN())},
+ {float32(Copysign(0, -1)), 1},
+ {float32(Copysign(0, -1)), 0},
+ {float32(Copysign(0, -1)), float32(Copysign(0, -1))},
+ {float32(Copysign(0, -1)), -1},
+ {float32(NaN()), 0},
+ {float32(NaN()), float32(NaN())},
+}
+var nextafter32SC = []float32{
+ 0,
+ 0,
+ -1.401298464e-45, // Float32frombits(0x80000001)
+ float32(NaN()),
+ 1.401298464e-45, // Float32frombits(0x00000001)
+ float32(Copysign(0, -1)),
+ float32(Copysign(0, -1)),
+ -1.401298464e-45, // Float32frombits(0x80000001)
+ float32(NaN()),
+ float32(NaN()),
+}
+
+var vfnextafter64SC = [][2]float64{
{0, 0},
{0, Copysign(0, -1)},
{0, -1},
@@ -1343,7 +1380,7 @@ var vfnextafterSC = [][2]float64{
{NaN(), 0},
{NaN(), NaN()},
}
-var nextafterSC = []float64{
+var nextafter64SC = []float64{
0,
0,
-4.9406564584124654418e-324, // Float64frombits(0x8000000000000001)
@@ -2303,15 +2340,29 @@ func TestModf(t *testing.T) {
}
}
-func TestNextafter(t *testing.T) {
+func TestNextafter32(t *testing.T) {
+ for i := 0; i < len(vf); i++ {
+ vfi := float32(vf[i])
+ if f := Nextafter32(vfi, 10); nextafter32[i] != f {
+ t.Errorf("Nextafter32(%g, %g) = %g want %g", vfi, 10.0, f, nextafter32[i])
+ }
+ }
+ for i := 0; i < len(vfnextafter32SC); i++ {
+ if f := Nextafter32(vfnextafter32SC[i][0], vfnextafter32SC[i][1]); !alike(float64(nextafter32SC[i]), float64(f)) {
+ t.Errorf("Nextafter32(%g, %g) = %g want %g", vfnextafter32SC[i][0], vfnextafter32SC[i][1], f, nextafter32SC[i])
+ }
+ }
+}
+
+func TestNextafter64(t *testing.T) {
for i := 0; i < len(vf); i++ {
- if f := Nextafter(vf[i], 10); nextafter[i] != f {
- t.Errorf("Nextafter(%g, %g) = %g want %g", vf[i], 10.0, f, nextafter[i])
+ if f := Nextafter(vf[i], 10); nextafter64[i] != f {
+ t.Errorf("Nextafter64(%g, %g) = %g want %g", vf[i], 10.0, f, nextafter64[i])
}
}
- for i := 0; i < len(vfnextafterSC); i++ {
- if f := Nextafter(vfnextafterSC[i][0], vfnextafterSC[i][1]); !alike(nextafterSC[i], f) {
- t.Errorf("Nextafter(%g, %g) = %g want %g", vfnextafterSC[i][0], vfnextafterSC[i][1], f, nextafterSC[i])
+ for i := 0; i < len(vfnextafter64SC); i++ {
+ if f := Nextafter(vfnextafter64SC[i][0], vfnextafter64SC[i][1]); !alike(nextafter64SC[i], f) {
+ t.Errorf("Nextafter64(%g, %g) = %g want %g", vfnextafter64SC[i][0], vfnextafter64SC[i][1], f, nextafter64SC[i])
}
}
}
@@ -2827,7 +2878,13 @@ func BenchmarkModf(b *testing.B) {
}
}
-func BenchmarkNextafter(b *testing.B) {
+func BenchmarkNextafter32(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Nextafter32(.5, 1)
+ }
+}
+
+func BenchmarkNextafter64(b *testing.B) {
for i := 0; i < b.N; i++ {
Nextafter(.5, 1)
}
diff --git a/src/pkg/math/asin.go b/src/math/asin.go
index 88b851e55..88b851e55 100644
--- a/src/pkg/math/asin.go
+++ b/src/math/asin.go
diff --git a/src/pkg/math/asin_386.s b/src/math/asin_386.s
index 2c1d27094..4f34e123e 100644
--- a/src/pkg/math/asin_386.s
+++ b/src/math/asin_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Asin(x float64) float64
TEXT ·Asin(SB),NOSPLIT,$0
diff --git a/src/pkg/math/asin_amd64.s b/src/math/asin_amd64.s
index ea48104ac..1a43d489b 100644
--- a/src/pkg/math/asin_amd64.s
+++ b/src/math/asin_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Asin(SB),NOSPLIT,$0
JMP ·asin(SB)
diff --git a/src/pkg/math/asin_amd64p32.s b/src/math/asin_amd64p32.s
index 2751c475f..2751c475f 100644
--- a/src/pkg/math/asin_amd64p32.s
+++ b/src/math/asin_amd64p32.s
diff --git a/src/pkg/math/asin_arm.s b/src/math/asin_arm.s
index b90526003..8fe03b61d 100644
--- a/src/pkg/math/asin_arm.s
+++ b/src/math/asin_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Asin(SB),NOSPLIT,$0
B ·asin(SB)
diff --git a/src/pkg/math/asinh.go b/src/math/asinh.go
index ff2de0215..ff2de0215 100644
--- a/src/pkg/math/asinh.go
+++ b/src/math/asinh.go
diff --git a/src/pkg/math/atan.go b/src/math/atan.go
index 7fcc90b8b..7fcc90b8b 100644
--- a/src/pkg/math/atan.go
+++ b/src/math/atan.go
diff --git a/src/pkg/math/atan2.go b/src/math/atan2.go
index d84b332c9..d84b332c9 100644
--- a/src/pkg/math/atan2.go
+++ b/src/math/atan2.go
diff --git a/src/pkg/math/atan2_386.s b/src/math/atan2_386.s
index fb649316a..31a74e726 100644
--- a/src/pkg/math/atan2_386.s
+++ b/src/math/atan2_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Atan2(y, x float64) float64 // =atan(y/x)
TEXT ·Atan2(SB),NOSPLIT,$0
diff --git a/src/pkg/math/atan2_amd64.s b/src/math/atan2_amd64.s
index f7a5a11d4..fc471f76c 100644
--- a/src/pkg/math/atan2_amd64.s
+++ b/src/math/atan2_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Atan2(SB),NOSPLIT,$0
JMP ·atan2(SB)
diff --git a/src/pkg/math/atan2_amd64p32.s b/src/math/atan2_amd64p32.s
index 3fdc03ca8..3fdc03ca8 100644
--- a/src/pkg/math/atan2_amd64p32.s
+++ b/src/math/atan2_amd64p32.s
diff --git a/src/pkg/math/atan2_arm.s b/src/math/atan2_arm.s
index 24bff2c03..06c12ecbc 100644
--- a/src/pkg/math/atan2_arm.s
+++ b/src/math/atan2_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Atan2(SB),NOSPLIT,$0
B ·atan2(SB)
diff --git a/src/pkg/math/atan_386.s b/src/math/atan_386.s
index aad8ffcec..f3976b1d3 100644
--- a/src/pkg/math/atan_386.s
+++ b/src/math/atan_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Atan(x float64) float64
TEXT ·Atan(SB),NOSPLIT,$0
diff --git a/src/pkg/math/atan_amd64.s b/src/math/atan_amd64.s
index fc4a91b0d..b801ae99d 100644
--- a/src/pkg/math/atan_amd64.s
+++ b/src/math/atan_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Atan(SB),NOSPLIT,$0
JMP ·atan(SB)
diff --git a/src/pkg/math/atan_amd64p32.s b/src/math/atan_amd64p32.s
index 1c1f6ceda..1c1f6ceda 100644
--- a/src/pkg/math/atan_amd64p32.s
+++ b/src/math/atan_amd64p32.s
diff --git a/src/pkg/math/atan_arm.s b/src/math/atan_arm.s
index defa93a1e..d190a8bb0 100644
--- a/src/pkg/math/atan_arm.s
+++ b/src/math/atan_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Atan(SB),NOSPLIT,$0
B ·atan(SB)
diff --git a/src/pkg/math/atanh.go b/src/math/atanh.go
index 113d5c103..113d5c103 100644
--- a/src/pkg/math/atanh.go
+++ b/src/math/atanh.go
diff --git a/src/pkg/math/big/arith.go b/src/math/big/arith.go
index 3d5a8682d..3d5a8682d 100644
--- a/src/pkg/math/big/arith.go
+++ b/src/math/big/arith.go
diff --git a/src/pkg/math/big/arith_386.s b/src/math/big/arith_386.s
index 15b036c65..1b47c898f 100644
--- a/src/pkg/math/big/arith_386.s
+++ b/src/math/big/arith_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// This file provides fast assembly versions for the elementary
// arithmetic operations on vectors implemented in arith.go.
diff --git a/src/pkg/math/big/arith_amd64.s b/src/math/big/arith_amd64.s
index e2113a7e3..56c4cb050 100644
--- a/src/pkg/math/big/arith_amd64.s
+++ b/src/math/big/arith_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// This file provides fast assembly versions for the elementary
// arithmetic operations on vectors implemented in arith.go.
diff --git a/src/pkg/math/big/arith_amd64p32.s b/src/math/big/arith_amd64p32.s
index 227870a00..908dbbdc5 100644
--- a/src/pkg/math/big/arith_amd64p32.s
+++ b/src/math/big/arith_amd64p32.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·mulWW(SB),NOSPLIT,$0
JMP ·mulWW_g(SB)
diff --git a/src/pkg/math/big/arith_arm.s b/src/math/big/arith_arm.s
index 8d36761c4..a4c51c212 100644
--- a/src/pkg/math/big/arith_arm.s
+++ b/src/math/big/arith_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// This file provides fast assembly versions for the elementary
// arithmetic operations on vectors implemented in arith.go.
diff --git a/src/pkg/math/big/arith_decl.go b/src/math/big/arith_decl.go
index 068cc8d93..068cc8d93 100644
--- a/src/pkg/math/big/arith_decl.go
+++ b/src/math/big/arith_decl.go
diff --git a/src/pkg/math/big/arith_test.go b/src/math/big/arith_test.go
index 3615a659c..3615a659c 100644
--- a/src/pkg/math/big/arith_test.go
+++ b/src/math/big/arith_test.go
diff --git a/src/pkg/math/big/calibrate_test.go b/src/math/big/calibrate_test.go
index f69ffbf5c..f69ffbf5c 100644
--- a/src/pkg/math/big/calibrate_test.go
+++ b/src/math/big/calibrate_test.go
diff --git a/src/pkg/math/big/example_test.go b/src/math/big/example_test.go
index 078be47f9..078be47f9 100644
--- a/src/pkg/math/big/example_test.go
+++ b/src/math/big/example_test.go
diff --git a/src/pkg/math/big/gcd_test.go b/src/math/big/gcd_test.go
index c0b9f5830..c0b9f5830 100644
--- a/src/pkg/math/big/gcd_test.go
+++ b/src/math/big/gcd_test.go
diff --git a/src/pkg/math/big/hilbert_test.go b/src/math/big/hilbert_test.go
index 1a84341b3..1a84341b3 100644
--- a/src/pkg/math/big/hilbert_test.go
+++ b/src/math/big/hilbert_test.go
diff --git a/src/pkg/math/big/int.go b/src/math/big/int.go
index 269949d61..d22e39e7c 100644
--- a/src/pkg/math/big/int.go
+++ b/src/math/big/int.go
@@ -510,10 +510,30 @@ func (z *Int) Scan(s fmt.ScanState, ch rune) error {
return err
}
+// low32 returns the least significant 32 bits of z.
+func low32(z nat) uint32 {
+ if len(z) == 0 {
+ return 0
+ }
+ return uint32(z[0])
+}
+
+// low64 returns the least significant 64 bits of z.
+func low64(z nat) uint64 {
+ if len(z) == 0 {
+ return 0
+ }
+ v := uint64(z[0])
+ if _W == 32 && len(z) > 1 {
+ v |= uint64(z[1]) << 32
+ }
+ return v
+}
+
// Int64 returns the int64 representation of x.
// If x cannot be represented in an int64, the result is undefined.
func (x *Int) Int64() int64 {
- v := int64(x.Uint64())
+ v := int64(low64(x.abs))
if x.neg {
v = -v
}
@@ -523,14 +543,7 @@ func (x *Int) Int64() int64 {
// Uint64 returns the uint64 representation of x.
// If x cannot be represented in a uint64, the result is undefined.
func (x *Int) Uint64() uint64 {
- if len(x.abs) == 0 {
- return 0
- }
- v := uint64(x.abs[0])
- if _W == 32 && len(x.abs) > 1 {
- v |= uint64(x.abs[1]) << 32
- }
- return v
+ return low64(x.abs)
}
// SetString sets z to the value of s, interpreted in the given base,
@@ -592,6 +605,12 @@ func (z *Int) Exp(x, y, m *Int) *Int {
z.abs = z.abs.expNN(x.abs, yWords, mWords)
z.neg = len(z.abs) > 0 && x.neg && len(yWords) > 0 && yWords[0]&1 == 1 // 0 has no sign
+ if z.neg && len(mWords) > 0 {
+ // make modulus result positive
+ z.abs = z.abs.sub(mWords, z.abs) // z == x**y mod |m| && 0 <= z < |m|
+ z.neg = false
+ }
+
return z
}
@@ -733,15 +752,16 @@ func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int {
return z
}
-// ModInverse sets z to the multiplicative inverse of g in the group ℤ/pℤ (where
-// p is a prime) and returns z.
-func (z *Int) ModInverse(g, p *Int) *Int {
+// ModInverse sets z to the multiplicative inverse of g in the ring ℤ/nℤ
+// and returns z. If g and n are not relatively prime, the result is undefined.
+func (z *Int) ModInverse(g, n *Int) *Int {
var d Int
- d.GCD(z, nil, g, p)
- // x and y are such that g*x + p*y = d. Since p is prime, d = 1. Taking
- // that modulo p results in g*x = 1, therefore x is the inverse element.
+ d.GCD(z, nil, g, n)
+ // x and y are such that g*x + n*y = d. Since g and n are
+ // relatively prime, d = 1. Taking that modulo n results in
+ // g*x = 1, therefore x is the inverse element.
if z.neg {
- z.Add(z, p)
+ z.Add(z, n)
}
return z
}
@@ -997,12 +1017,12 @@ func (z *Int) UnmarshalJSON(text []byte) error {
return nil
}
-// MarshalText implements the encoding.TextMarshaler interface
+// 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
+// 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)
diff --git a/src/pkg/math/big/int_test.go b/src/math/big/int_test.go
index 299dc72fb..6070cf325 100644
--- a/src/pkg/math/big/int_test.go
+++ b/src/math/big/int_test.go
@@ -787,6 +787,7 @@ var expTests = []struct {
{"-5", "0", "", "1"},
{"5", "1", "", "5"},
{"-5", "1", "", "-5"},
+ {"-5", "1", "7", "2"},
{"-2", "3", "2", "0"},
{"5", "2", "", "25"},
{"1", "65537", "2", "1"},
@@ -802,6 +803,13 @@ var expTests = []struct {
"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
},
+ // test case for issue 8822
+ {
+ "-0x1BCE04427D8032319A89E5C4136456671AC620883F2C4139E57F91307C485AD2D6204F4F87A58262652DB5DBBAC72B0613E51B835E7153BEC6068F5C8D696B74DBD18FEC316AEF73985CF0475663208EB46B4F17DD9DA55367B03323E5491A70997B90C059FB34809E6EE55BCFBD5F2F52233BFE62E6AA9E4E26A1D4C2439883D14F2633D55D8AA66A1ACD5595E778AC3A280517F1157989E70C1A437B849F1877B779CC3CDDEDE2DAA6594A6C66D181A00A5F777EE60596D8773998F6E988DEAE4CCA60E4DDCF9590543C89F74F603259FCAD71660D30294FBBE6490300F78A9D63FA660DC9417B8B9DDA28BEB3977B621B988E23D4D954F322C3540541BC649ABD504C50FADFD9F0987D58A2BF689313A285E773FF02899A6EF887D1D4A0D2",
+ "0xB08FFB20760FFED58FADA86DFEF71AD72AA0FA763219618FE022C197E54708BB1191C66470250FCE8879487507CEE41381CA4D932F81C2B3F1AB20B539D50DCD",
+ "0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73",
+ "21484252197776302499639938883777710321993113097987201050501182909581359357618579566746556372589385361683610524730509041328855066514963385522570894839035884713051640171474186548713546686476761306436434146475140156284389181808675016576845833340494848283681088886584219750554408060556769486628029028720727393293111678826356480455433909233520504112074401376133077150471237549474149190242010469539006449596611576612573955754349042329130631128234637924786466585703488460540228477440853493392086251021228087076124706778899179648655221663765993962724699135217212118535057766739392069738618682722216712319320435674779146070442",
+ },
}
func TestExp(t *testing.T) {
@@ -833,12 +841,12 @@ func TestExp(t *testing.T) {
}
if m == nil {
- // the result should be the same as for m == 0;
- // specifically, there should be no div-zero panic
+ // The result should be the same as for m == 0;
+ // specifically, there should be no div-zero panic.
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, z1, z2)
+ t.Errorf("#%d: got %s want %s", i, z2, z1)
}
}
}
@@ -1440,24 +1448,40 @@ func TestNot(t *testing.T) {
var modInverseTests = []struct {
element string
- prime string
+ modulus string
}{
- {"1", "7"},
- {"1", "13"},
+ {"1234567", "458948883992"},
{"239487239847", "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919"},
}
func TestModInverse(t *testing.T) {
- var element, prime Int
+ var element, modulus, gcd, inverse Int
one := NewInt(1)
for i, test := range modInverseTests {
(&element).SetString(test.element, 10)
- (&prime).SetString(test.prime, 10)
- inverse := new(Int).ModInverse(&element, &prime)
- inverse.Mul(inverse, &element)
- inverse.Mod(inverse, &prime)
- if inverse.Cmp(one) != 0 {
- t.Errorf("#%d: failed (e·e^(-1)=%s)", i, inverse)
+ (&modulus).SetString(test.modulus, 10)
+ (&inverse).ModInverse(&element, &modulus)
+ (&inverse).Mul(&inverse, &element)
+ (&inverse).Mod(&inverse, &modulus)
+ if (&inverse).Cmp(one) != 0 {
+ t.Errorf("#%d: failed (e·e^(-1)=%s)", i, &inverse)
+ }
+ }
+ // exhaustive test for small values
+ for n := 2; n < 100; n++ {
+ (&modulus).SetInt64(int64(n))
+ for x := 1; x < n; x++ {
+ (&element).SetInt64(int64(x))
+ (&gcd).GCD(nil, nil, &element, &modulus)
+ if (&gcd).Cmp(one) != 0 {
+ continue
+ }
+ (&inverse).ModInverse(&element, &modulus)
+ (&inverse).Mul(&inverse, &element)
+ (&inverse).Mod(&inverse, &modulus)
+ if (&inverse).Cmp(one) != 0 {
+ t.Errorf("ModInverse(%d,%d)*%d%%%d=%d, not 1", &element, &modulus, &element, &modulus, &inverse)
+ }
}
}
}
diff --git a/src/pkg/math/big/nat.go b/src/math/big/nat.go
index 16a87f5c5..16a87f5c5 100644
--- a/src/pkg/math/big/nat.go
+++ b/src/math/big/nat.go
diff --git a/src/pkg/math/big/nat_test.go b/src/math/big/nat_test.go
index a2ae53385..a2ae53385 100644
--- a/src/pkg/math/big/nat_test.go
+++ b/src/math/big/nat_test.go
diff --git a/src/pkg/math/big/rat.go b/src/math/big/rat.go
index f0973b390..c5339fe44 100644
--- a/src/pkg/math/big/rat.go
+++ b/src/math/big/rat.go
@@ -64,28 +64,125 @@ func (z *Rat) SetFloat64(f float64) *Rat {
return z.norm()
}
-// isFinite reports whether f represents a finite rational value.
-// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
-func isFinite(f float64) bool {
- return math.Abs(f) <= math.MaxFloat64
-}
+// quotToFloat32 returns the non-negative float32 value
+// nearest to the quotient a/b, using round-to-even in
+// halfway cases. It does not mutate its arguments.
+// Preconditions: b is non-zero; a and b have no common factors.
+func quotToFloat32(a, b nat) (f float32, exact bool) {
+ const (
+ // float size in bits
+ Fsize = 32
+
+ // mantissa
+ Msize = 23
+ Msize1 = Msize + 1 // incl. implicit 1
+ Msize2 = Msize1 + 1
+
+ // exponent
+ Esize = Fsize - Msize1
+ Ebias = 1<<(Esize-1) - 1
+ Emin = 1 - Ebias
+ Emax = Ebias
+ )
-// low64 returns the least significant 64 bits of natural number z.
-func low64(z nat) uint64 {
- if len(z) == 0 {
- return 0
+ // TODO(adonovan): specialize common degenerate cases: 1.0, integers.
+ alen := a.bitLen()
+ if alen == 0 {
+ return 0, true
}
- if _W == 32 && len(z) > 1 {
- return uint64(z[1])<<32 | uint64(z[0])
+ blen := b.bitLen()
+ if blen == 0 {
+ panic("division by zero")
}
- return uint64(z[0])
+
+ // 1. Left-shift A or B such that quotient A/B is in [1<<Msize1, 1<<(Msize2+1)
+ // (Msize2 bits if A < B when they are left-aligned, Msize2+1 bits if A >= B).
+ // This is 2 or 3 more than the float32 mantissa field width of Msize:
+ // - the optional extra bit is shifted away in step 3 below.
+ // - the high-order 1 is omitted in "normal" representation;
+ // - the low-order 1 will be used during rounding then discarded.
+ exp := alen - blen
+ var a2, b2 nat
+ a2 = a2.set(a)
+ b2 = b2.set(b)
+ if shift := Msize2 - exp; shift > 0 {
+ a2 = a2.shl(a2, uint(shift))
+ } else if shift < 0 {
+ b2 = b2.shl(b2, uint(-shift))
+ }
+
+ // 2. Compute quotient and remainder (q, r). NB: due to the
+ // extra shift, the low-order bit of q is logically the
+ // high-order bit of r.
+ var q nat
+ q, r := q.div(a2, a2, b2) // (recycle a2)
+ mantissa := low32(q)
+ haveRem := len(r) > 0 // mantissa&1 && !haveRem => remainder is exactly half
+
+ // 3. If quotient didn't fit in Msize2 bits, redo division by b2<<1
+ // (in effect---we accomplish this incrementally).
+ if mantissa>>Msize2 == 1 {
+ if mantissa&1 == 1 {
+ haveRem = true
+ }
+ mantissa >>= 1
+ exp++
+ }
+ if mantissa>>Msize1 != 1 {
+ panic(fmt.Sprintf("expected exactly %d bits of result", Msize2))
+ }
+
+ // 4. Rounding.
+ if Emin-Msize <= exp && exp <= Emin {
+ // Denormal case; lose 'shift' bits of precision.
+ shift := uint(Emin - (exp - 1)) // [1..Esize1)
+ lostbits := mantissa & (1<<shift - 1)
+ haveRem = haveRem || lostbits != 0
+ mantissa >>= shift
+ exp = 2 - Ebias // == exp + shift
+ }
+ // Round q using round-half-to-even.
+ exact = !haveRem
+ if mantissa&1 != 0 {
+ exact = false
+ if haveRem || mantissa&2 != 0 {
+ if mantissa++; mantissa >= 1<<Msize2 {
+ // Complete rollover 11...1 => 100...0, so shift is safe
+ mantissa >>= 1
+ exp++
+ }
+ }
+ }
+ mantissa >>= 1 // discard rounding bit. Mantissa now scaled by 1<<Msize1.
+
+ f = float32(math.Ldexp(float64(mantissa), exp-Msize1))
+ if math.IsInf(float64(f), 0) {
+ exact = false
+ }
+ return
}
-// quotToFloat returns the non-negative IEEE 754 double-precision
-// value nearest to the quotient a/b, using round-to-even in halfway
-// cases. It does not mutate its arguments.
+// quotToFloat64 returns the non-negative float64 value
+// nearest to the quotient a/b, using round-to-even in
+// halfway cases. It does not mutate its arguments.
// Preconditions: b is non-zero; a and b have no common factors.
-func quotToFloat(a, b nat) (f float64, exact bool) {
+func quotToFloat64(a, b nat) (f float64, exact bool) {
+ const (
+ // float size in bits
+ Fsize = 64
+
+ // mantissa
+ Msize = 52
+ Msize1 = Msize + 1 // incl. implicit 1
+ Msize2 = Msize1 + 1
+
+ // exponent
+ Esize = Fsize - Msize1
+ Ebias = 1<<(Esize-1) - 1
+ Emin = 1 - Ebias
+ Emax = Ebias
+ )
+
// TODO(adonovan): specialize common degenerate cases: 1.0, integers.
alen := a.bitLen()
if alen == 0 {
@@ -96,17 +193,17 @@ func quotToFloat(a, b nat) (f float64, exact bool) {
panic("division by zero")
}
- // 1. Left-shift A or B such that quotient A/B is in [1<<53, 1<<55).
- // (54 bits if A<B when they are left-aligned, 55 bits if A>=B.)
- // This is 2 or 3 more than the float64 mantissa field width of 52:
+ // 1. Left-shift A or B such that quotient A/B is in [1<<Msize1, 1<<(Msize2+1)
+ // (Msize2 bits if A < B when they are left-aligned, Msize2+1 bits if A >= B).
+ // This is 2 or 3 more than the float64 mantissa field width of Msize:
// - the optional extra bit is shifted away in step 3 below.
- // - the high-order 1 is omitted in float64 "normal" representation;
+ // - the high-order 1 is omitted in "normal" representation;
// - the low-order 1 will be used during rounding then discarded.
exp := alen - blen
var a2, b2 nat
a2 = a2.set(a)
b2 = b2.set(b)
- if shift := 54 - exp; shift > 0 {
+ if shift := Msize2 - exp; shift > 0 {
a2 = a2.shl(a2, uint(shift))
} else if shift < 0 {
b2 = b2.shl(b2, uint(-shift))
@@ -120,49 +217,65 @@ func quotToFloat(a, b nat) (f float64, exact bool) {
mantissa := low64(q)
haveRem := len(r) > 0 // mantissa&1 && !haveRem => remainder is exactly half
- // 3. If quotient didn't fit in 54 bits, re-do division by b2<<1
+ // 3. If quotient didn't fit in Msize2 bits, redo division by b2<<1
// (in effect---we accomplish this incrementally).
- if mantissa>>54 == 1 {
+ if mantissa>>Msize2 == 1 {
if mantissa&1 == 1 {
haveRem = true
}
mantissa >>= 1
exp++
}
- if mantissa>>53 != 1 {
- panic("expected exactly 54 bits of result")
+ if mantissa>>Msize1 != 1 {
+ panic(fmt.Sprintf("expected exactly %d bits of result", Msize2))
}
// 4. Rounding.
- if -1022-52 <= exp && exp <= -1022 {
+ if Emin-Msize <= exp && exp <= Emin {
// Denormal case; lose 'shift' bits of precision.
- shift := uint64(-1022 - (exp - 1)) // [1..53)
+ shift := uint(Emin - (exp - 1)) // [1..Esize1)
lostbits := mantissa & (1<<shift - 1)
haveRem = haveRem || lostbits != 0
mantissa >>= shift
- exp = -1023 + 2
+ exp = 2 - Ebias // == exp + shift
}
// Round q using round-half-to-even.
exact = !haveRem
if mantissa&1 != 0 {
exact = false
if haveRem || mantissa&2 != 0 {
- if mantissa++; mantissa >= 1<<54 {
+ if mantissa++; mantissa >= 1<<Msize2 {
// Complete rollover 11...1 => 100...0, so shift is safe
mantissa >>= 1
exp++
}
}
}
- mantissa >>= 1 // discard rounding bit. Mantissa now scaled by 2^53.
+ mantissa >>= 1 // discard rounding bit. Mantissa now scaled by 1<<Msize1.
- f = math.Ldexp(float64(mantissa), exp-53)
+ f = math.Ldexp(float64(mantissa), exp-Msize1)
if math.IsInf(f, 0) {
exact = false
}
return
}
+// Float32 returns the nearest float32 value for x and a bool indicating
+// whether f represents x exactly. If the magnitude of x is too large to
+// be represented by a float32, f is an infinity and exact is false.
+// The sign of f always matches the sign of x, even if f == 0.
+func (x *Rat) Float32() (f float32, exact bool) {
+ b := x.b.abs
+ if len(b) == 0 {
+ b = b.set(natOne) // materialize denominator
+ }
+ f, exact = quotToFloat32(x.a.abs, b)
+ if x.a.neg {
+ f = -f
+ }
+ return
+}
+
// Float64 returns the nearest float64 value for x and a bool indicating
// whether f represents x exactly. If the magnitude of x is too large to
// be represented by a float64, f is an infinity and exact is false.
@@ -172,7 +285,7 @@ func (x *Rat) Float64() (f float64, exact bool) {
if len(b) == 0 {
b = b.set(natOne) // materialize denominator
}
- f, exact = quotToFloat(x.a.abs, b)
+ f, exact = quotToFloat64(x.a.abs, b)
if x.a.neg {
f = -f
}
@@ -439,6 +552,9 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
if z.b.abs, _, err = z.b.abs.scan(strings.NewReader(s), 10); err != nil {
return nil, false
}
+ if len(z.b.abs) == 0 {
+ return nil, false
+ }
return z.norm(), true
}
@@ -586,12 +702,12 @@ func (z *Rat) GobDecode(buf []byte) error {
return nil
}
-// MarshalText implements the encoding.TextMarshaler interface
+// 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
+// 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)
diff --git a/src/pkg/math/big/rat_test.go b/src/math/big/rat_test.go
index 414a67d41..5dbbb3510 100644
--- a/src/pkg/math/big/rat_test.go
+++ b/src/math/big/rat_test.go
@@ -89,6 +89,7 @@ var setStringTests = []struct {
{"53/70893980658822810696", "53/70893980658822810696", true},
{"106/141787961317645621392", "53/70893980658822810696", true},
{"204211327800791583.81095", "4084226556015831676219/20000", true},
+ {in: "1/0", ok: false},
}
func TestRatSetString(t *testing.T) {
@@ -751,7 +752,6 @@ var float64inputs = []string{
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
"2.2250738585072012e-308",
// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
-
"2.2250738585072011e-308",
// A very large number (initially wrongly parsed by the fast algorithm).
@@ -790,6 +790,68 @@ var float64inputs = []string{
"1/3",
}
+// isFinite reports whether f represents a finite rational value.
+// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
+func isFinite(f float64) bool {
+ return math.Abs(f) <= math.MaxFloat64
+}
+
+func TestFloat32SpecialCases(t *testing.T) {
+ for _, input := range float64inputs {
+ if strings.HasPrefix(input, "long:") {
+ if testing.Short() {
+ continue
+ }
+ input = input[len("long:"):]
+ }
+
+ r, ok := new(Rat).SetString(input)
+ if !ok {
+ t.Errorf("Rat.SetString(%q) failed", input)
+ continue
+ }
+ f, exact := r.Float32()
+
+ // 1. Check string -> Rat -> float32 conversions are
+ // consistent with strconv.ParseFloat.
+ // Skip this check if the input uses "a/b" rational syntax.
+ if !strings.Contains(input, "/") {
+ e64, _ := strconv.ParseFloat(input, 32)
+ e := float32(e64)
+
+ // Careful: negative Rats too small for
+ // float64 become -0, but Rat obviously cannot
+ // preserve the sign from SetString("-0").
+ switch {
+ case math.Float32bits(e) == math.Float32bits(f):
+ // Ok: bitwise equal.
+ case f == 0 && r.Num().BitLen() == 0:
+ // Ok: Rat(0) is equivalent to both +/- float64(0).
+ default:
+ t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
+ }
+ }
+
+ if !isFinite(float64(f)) {
+ continue
+ }
+
+ // 2. Check f is best approximation to r.
+ if !checkIsBestApprox32(t, f, r) {
+ // Append context information.
+ t.Errorf("(input was %q)", input)
+ }
+
+ // 3. Check f->R->f roundtrip is non-lossy.
+ checkNonLossyRoundtrip32(t, f)
+
+ // 4. Check exactness using slow algorithm.
+ if wasExact := new(Rat).SetFloat64(float64(f)).Cmp(r) == 0; wasExact != exact {
+ t.Errorf("Rat.SetString(%q).Float32().exact = %t, want %t", input, exact, wasExact)
+ }
+ }
+}
+
func TestFloat64SpecialCases(t *testing.T) {
for _, input := range float64inputs {
if strings.HasPrefix(input, "long:") {
@@ -830,13 +892,13 @@ func TestFloat64SpecialCases(t *testing.T) {
}
// 2. Check f is best approximation to r.
- if !checkIsBestApprox(t, f, r) {
+ if !checkIsBestApprox64(t, f, r) {
// Append context information.
t.Errorf("(input was %q)", input)
}
// 3. Check f->R->f roundtrip is non-lossy.
- checkNonLossyRoundtrip(t, f)
+ checkNonLossyRoundtrip64(t, f)
// 4. Check exactness using slow algorithm.
if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
@@ -845,6 +907,54 @@ func TestFloat64SpecialCases(t *testing.T) {
}
}
+func TestFloat32Distribution(t *testing.T) {
+ // Generate a distribution of (sign, mantissa, exp) values
+ // broader than the float32 range, and check Rat.Float32()
+ // always picks the closest float32 approximation.
+ var add = []int64{
+ 0,
+ 1,
+ 3,
+ 5,
+ 7,
+ 9,
+ 11,
+ }
+ var winc, einc = uint64(1), 1 // soak test (~1.5s on x86-64)
+ if testing.Short() {
+ winc, einc = 5, 15 // quick test (~60ms on x86-64)
+ }
+
+ for _, sign := range "+-" {
+ for _, a := range add {
+ for wid := uint64(0); wid < 30; wid += winc {
+ b := 1<<wid + a
+ if sign == '-' {
+ b = -b
+ }
+ for exp := -150; exp < 150; exp += einc {
+ num, den := NewInt(b), NewInt(1)
+ if exp > 0 {
+ num.Lsh(num, uint(exp))
+ } else {
+ den.Lsh(den, uint(-exp))
+ }
+ r := new(Rat).SetFrac(num, den)
+ f, _ := r.Float32()
+
+ if !checkIsBestApprox32(t, f, r) {
+ // Append context information.
+ t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)",
+ b, exp, f, f, math.Ldexp(float64(b), exp), r)
+ }
+
+ checkNonLossyRoundtrip32(t, f)
+ }
+ }
+ }
+ }
+}
+
func TestFloat64Distribution(t *testing.T) {
// Generate a distribution of (sign, mantissa, exp) values
// broader than the float64 range, and check Rat.Float64()
@@ -858,7 +968,7 @@ func TestFloat64Distribution(t *testing.T) {
9,
11,
}
- var winc, einc = uint64(1), int(1) // soak test (~75s on x86-64)
+ var winc, einc = uint64(1), 1 // soak test (~75s on x86-64)
if testing.Short() {
winc, einc = 10, 500 // quick test (~12ms on x86-64)
}
@@ -866,7 +976,7 @@ func TestFloat64Distribution(t *testing.T) {
for _, sign := range "+-" {
for _, a := range add {
for wid := uint64(0); wid < 60; wid += winc {
- b := int64(1<<wid + a)
+ b := 1<<wid + a
if sign == '-' {
b = -b
}
@@ -880,20 +990,20 @@ func TestFloat64Distribution(t *testing.T) {
r := new(Rat).SetFrac(num, den)
f, _ := r.Float64()
- if !checkIsBestApprox(t, f, r) {
+ if !checkIsBestApprox64(t, f, r) {
// Append context information.
t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)",
b, exp, f, f, math.Ldexp(float64(b), exp), r)
}
- checkNonLossyRoundtrip(t, f)
+ checkNonLossyRoundtrip64(t, f)
}
}
}
}
}
-// TestFloat64NonFinite checks that SetFloat64 of a non-finite value
+// TestSetFloat64NonFinite checks that SetFloat64 of a non-finite value
// returns nil.
func TestSetFloat64NonFinite(t *testing.T) {
for _, f := range []float64{math.NaN(), math.Inf(+1), math.Inf(-1)} {
@@ -904,9 +1014,27 @@ func TestSetFloat64NonFinite(t *testing.T) {
}
}
-// checkNonLossyRoundtrip checks that a float->Rat->float roundtrip is
+// checkNonLossyRoundtrip32 checks that a float->Rat->float roundtrip is
// non-lossy for finite f.
-func checkNonLossyRoundtrip(t *testing.T, f float64) {
+func checkNonLossyRoundtrip32(t *testing.T, f float32) {
+ if !isFinite(float64(f)) {
+ return
+ }
+ r := new(Rat).SetFloat64(float64(f))
+ if r == nil {
+ t.Errorf("Rat.SetFloat64(float64(%g) (%b)) == nil", f, f)
+ return
+ }
+ f2, exact := r.Float32()
+ if f != f2 || !exact {
+ t.Errorf("Rat.SetFloat64(float64(%g)).Float32() = %g (%b), %v, want %g (%b), %v; delta = %b",
+ f, f2, f2, exact, f, f, true, f2-f)
+ }
+}
+
+// checkNonLossyRoundtrip64 checks that a float->Rat->float roundtrip is
+// non-lossy for finite f.
+func checkNonLossyRoundtrip64(t *testing.T, f float64) {
if !isFinite(f) {
return
}
@@ -928,10 +1056,47 @@ func delta(r *Rat, f float64) *Rat {
return d.Abs(d)
}
-// checkIsBestApprox checks that f is the best possible float64
+// checkIsBestApprox32 checks that f is the best possible float32
+// approximation of r.
+// Returns true on success.
+func checkIsBestApprox32(t *testing.T, f float32, r *Rat) bool {
+ if math.Abs(float64(f)) >= math.MaxFloat32 {
+ // Cannot check +Inf, -Inf, nor the float next to them (MaxFloat32).
+ // But we have tests for these special cases.
+ return true
+ }
+
+ // r must be strictly between f0 and f1, the floats bracketing f.
+ f0 := math.Nextafter32(f, float32(math.Inf(-1)))
+ f1 := math.Nextafter32(f, float32(math.Inf(+1)))
+
+ // For f to be correct, r must be closer to f than to f0 or f1.
+ df := delta(r, float64(f))
+ df0 := delta(r, float64(f0))
+ df1 := delta(r, float64(f1))
+ if df.Cmp(df0) > 0 {
+ t.Errorf("Rat(%v).Float32() = %g (%b), but previous float32 %g (%b) is closer", r, f, f, f0, f0)
+ return false
+ }
+ if df.Cmp(df1) > 0 {
+ t.Errorf("Rat(%v).Float32() = %g (%b), but next float32 %g (%b) is closer", r, f, f, f1, f1)
+ return false
+ }
+ if df.Cmp(df0) == 0 && !isEven32(f) {
+ t.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0)
+ return false
+ }
+ if df.Cmp(df1) == 0 && !isEven32(f) {
+ t.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1)
+ return false
+ }
+ return true
+}
+
+// checkIsBestApprox64 checks that f is the best possible float64
// approximation of r.
// Returns true on success.
-func checkIsBestApprox(t *testing.T, f float64, r *Rat) bool {
+func checkIsBestApprox64(t *testing.T, f float64, r *Rat) bool {
if math.Abs(f) >= math.MaxFloat64 {
// Cannot check +Inf, -Inf, nor the float next to them (MaxFloat64).
// But we have tests for these special cases.
@@ -954,18 +1119,19 @@ func checkIsBestApprox(t *testing.T, f float64, r *Rat) bool {
t.Errorf("Rat(%v).Float64() = %g (%b), but next float64 %g (%b) is closer", r, f, f, f1, f1)
return false
}
- if df.Cmp(df0) == 0 && !isEven(f) {
+ if df.Cmp(df0) == 0 && !isEven64(f) {
t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0)
return false
}
- if df.Cmp(df1) == 0 && !isEven(f) {
+ if df.Cmp(df1) == 0 && !isEven64(f) {
t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1)
return false
}
return true
}
-func isEven(f float64) bool { return math.Float64bits(f)&1 == 0 }
+func isEven32(f float32) bool { return math.Float32bits(f)&1 == 0 }
+func isEven64(f float64) bool { return math.Float64bits(f)&1 == 0 }
func TestIsFinite(t *testing.T) {
finites := []float64{
diff --git a/src/pkg/math/bits.go b/src/math/bits.go
index d85ee9cb1..d85ee9cb1 100644
--- a/src/pkg/math/bits.go
+++ b/src/math/bits.go
diff --git a/src/pkg/math/cbrt.go b/src/math/cbrt.go
index 272e30923..272e30923 100644
--- a/src/pkg/math/cbrt.go
+++ b/src/math/cbrt.go
diff --git a/src/pkg/math/cmplx/abs.go b/src/math/cmplx/abs.go
index f3cd1073e..f3cd1073e 100644
--- a/src/pkg/math/cmplx/abs.go
+++ b/src/math/cmplx/abs.go
diff --git a/src/pkg/math/cmplx/asin.go b/src/math/cmplx/asin.go
index 61880a257..61880a257 100644
--- a/src/pkg/math/cmplx/asin.go
+++ b/src/math/cmplx/asin.go
diff --git a/src/pkg/math/cmplx/cmath_test.go b/src/math/cmplx/cmath_test.go
index f285646af..f285646af 100644
--- a/src/pkg/math/cmplx/cmath_test.go
+++ b/src/math/cmplx/cmath_test.go
diff --git a/src/pkg/math/cmplx/conj.go b/src/math/cmplx/conj.go
index 34a4277c1..34a4277c1 100644
--- a/src/pkg/math/cmplx/conj.go
+++ b/src/math/cmplx/conj.go
diff --git a/src/pkg/math/cmplx/exp.go b/src/math/cmplx/exp.go
index 485ed2c78..485ed2c78 100644
--- a/src/pkg/math/cmplx/exp.go
+++ b/src/math/cmplx/exp.go
diff --git a/src/pkg/math/cmplx/isinf.go b/src/math/cmplx/isinf.go
index d5a65b44b..d5a65b44b 100644
--- a/src/pkg/math/cmplx/isinf.go
+++ b/src/math/cmplx/isinf.go
diff --git a/src/pkg/math/cmplx/isnan.go b/src/math/cmplx/isnan.go
index 05d0cce63..05d0cce63 100644
--- a/src/pkg/math/cmplx/isnan.go
+++ b/src/math/cmplx/isnan.go
diff --git a/src/pkg/math/cmplx/log.go b/src/math/cmplx/log.go
index 881a064d8..881a064d8 100644
--- a/src/pkg/math/cmplx/log.go
+++ b/src/math/cmplx/log.go
diff --git a/src/pkg/math/cmplx/phase.go b/src/math/cmplx/phase.go
index 03cece8a5..03cece8a5 100644
--- a/src/pkg/math/cmplx/phase.go
+++ b/src/math/cmplx/phase.go
diff --git a/src/pkg/math/cmplx/polar.go b/src/math/cmplx/polar.go
index 9b192bc62..9b192bc62 100644
--- a/src/pkg/math/cmplx/polar.go
+++ b/src/math/cmplx/polar.go
diff --git a/src/pkg/math/cmplx/pow.go b/src/math/cmplx/pow.go
index 1630b879b..1630b879b 100644
--- a/src/pkg/math/cmplx/pow.go
+++ b/src/math/cmplx/pow.go
diff --git a/src/pkg/math/cmplx/rect.go b/src/math/cmplx/rect.go
index bf94d787e..bf94d787e 100644
--- a/src/pkg/math/cmplx/rect.go
+++ b/src/math/cmplx/rect.go
diff --git a/src/pkg/math/cmplx/sin.go b/src/math/cmplx/sin.go
index 2c57536ed..2c57536ed 100644
--- a/src/pkg/math/cmplx/sin.go
+++ b/src/math/cmplx/sin.go
diff --git a/src/pkg/math/cmplx/sqrt.go b/src/math/cmplx/sqrt.go
index 4ef6807ad..4ef6807ad 100644
--- a/src/pkg/math/cmplx/sqrt.go
+++ b/src/math/cmplx/sqrt.go
diff --git a/src/pkg/math/cmplx/tan.go b/src/math/cmplx/tan.go
index 9485315d8..9485315d8 100644
--- a/src/pkg/math/cmplx/tan.go
+++ b/src/math/cmplx/tan.go
diff --git a/src/pkg/math/const.go b/src/math/const.go
index f1247c383..f1247c383 100644
--- a/src/pkg/math/const.go
+++ b/src/math/const.go
diff --git a/src/pkg/math/copysign.go b/src/math/copysign.go
index 719c64b9e..719c64b9e 100644
--- a/src/pkg/math/copysign.go
+++ b/src/math/copysign.go
diff --git a/src/pkg/math/dim.go b/src/math/dim.go
index 1c634d415..1c634d415 100644
--- a/src/pkg/math/dim.go
+++ b/src/math/dim.go
diff --git a/src/pkg/math/dim_386.s b/src/math/dim_386.s
index f715114c4..c8194fed8 100644
--- a/src/pkg/math/dim_386.s
+++ b/src/math/dim_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Dim(SB),NOSPLIT,$0
JMP ·dim(SB)
diff --git a/src/pkg/math/dim_amd64.s b/src/math/dim_amd64.s
index 38423ef02..622cc3fba 100644
--- a/src/pkg/math/dim_amd64.s
+++ b/src/math/dim_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#define PosInf 0x7FF0000000000000
#define NaN 0x7FF8000000000001
diff --git a/src/pkg/math/dim_amd64p32.s b/src/math/dim_amd64p32.s
index e5e34479d..e5e34479d 100644
--- a/src/pkg/math/dim_amd64p32.s
+++ b/src/math/dim_amd64p32.s
diff --git a/src/pkg/math/dim_arm.s b/src/math/dim_arm.s
index 162f08cda..be6695068 100644
--- a/src/pkg/math/dim_arm.s
+++ b/src/math/dim_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Dim(SB),NOSPLIT,$0
B ·dim(SB)
diff --git a/src/pkg/math/erf.go b/src/math/erf.go
index 4cd80f80c..4cd80f80c 100644
--- a/src/pkg/math/erf.go
+++ b/src/math/erf.go
diff --git a/src/pkg/math/exp.go b/src/math/exp.go
index f31585fa7..f31585fa7 100644
--- a/src/pkg/math/exp.go
+++ b/src/math/exp.go
diff --git a/src/pkg/math/exp2_386.s b/src/math/exp2_386.s
index 71959d94d..7d11920c2 100644
--- a/src/pkg/math/exp2_386.s
+++ b/src/math/exp2_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Exp2(x float64) float64
TEXT ·Exp2(SB),NOSPLIT,$0
diff --git a/src/pkg/math/exp2_amd64.s b/src/math/exp2_amd64.s
index 77a53dad4..903c83589 100644
--- a/src/pkg/math/exp2_amd64.s
+++ b/src/math/exp2_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Exp2(SB),NOSPLIT,$0
JMP ·exp2(SB)
diff --git a/src/pkg/math/exp2_amd64p32.s b/src/math/exp2_amd64p32.s
index 4d3830914..4d3830914 100644
--- a/src/pkg/math/exp2_amd64p32.s
+++ b/src/math/exp2_amd64p32.s
diff --git a/src/pkg/math/exp2_arm.s b/src/math/exp2_arm.s
index fe51f2522..58283cd08 100644
--- a/src/pkg/math/exp2_arm.s
+++ b/src/math/exp2_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Exp2(SB),NOSPLIT,$0
B ·exp2(SB)
diff --git a/src/pkg/math/exp_386.s b/src/math/exp_386.s
index af2d680d5..6a478a5e6 100644
--- a/src/pkg/math/exp_386.s
+++ b/src/math/exp_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Exp(x float64) float64
TEXT ·Exp(SB),NOSPLIT,$0
diff --git a/src/pkg/math/exp_amd64.s b/src/math/exp_amd64.s
index 070b45264..d9cf8fd86 100644
--- a/src/pkg/math/exp_amd64.s
+++ b/src/math/exp_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// The method is based on a paper by Naoki Shibata: "Efficient evaluation
// methods of elementary functions suitable for SIMD computation", Proc.
diff --git a/src/pkg/math/exp_amd64p32.s b/src/math/exp_amd64p32.s
index 98ac2e91e..98ac2e91e 100644
--- a/src/pkg/math/exp_amd64p32.s
+++ b/src/math/exp_amd64p32.s
diff --git a/src/pkg/math/exp_arm.s b/src/math/exp_arm.s
index 130b502ac..ce36d03ca 100644
--- a/src/pkg/math/exp_arm.s
+++ b/src/math/exp_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Exp(SB),NOSPLIT,$0
B ·exp(SB)
diff --git a/src/pkg/math/expm1.go b/src/math/expm1.go
index 8f56e15cc..8f56e15cc 100644
--- a/src/pkg/math/expm1.go
+++ b/src/math/expm1.go
diff --git a/src/pkg/math/expm1_386.s b/src/math/expm1_386.s
index b268c58c6..a48ca8a58 100644
--- a/src/pkg/math/expm1_386.s
+++ b/src/math/expm1_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Expm1(x float64) float64
TEXT ·Expm1(SB),NOSPLIT,$0
diff --git a/src/pkg/math/expm1_amd64.s b/src/math/expm1_amd64.s
index 66a75b3d5..b7d5a3be0 100644
--- a/src/pkg/math/expm1_amd64.s
+++ b/src/math/expm1_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Expm1(SB),NOSPLIT,$0
JMP ·expm1(SB)
diff --git a/src/pkg/math/expm1_amd64p32.s b/src/math/expm1_amd64p32.s
index 709ebefcb..709ebefcb 100644
--- a/src/pkg/math/expm1_amd64p32.s
+++ b/src/math/expm1_amd64p32.s
diff --git a/src/pkg/math/expm1_arm.s b/src/math/expm1_arm.s
index 838744447..5f80d872f 100644
--- a/src/pkg/math/expm1_arm.s
+++ b/src/math/expm1_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Expm1(SB),NOSPLIT,$0
B ·expm1(SB)
diff --git a/src/pkg/math/export_test.go b/src/math/export_test.go
index 02992d70e..02992d70e 100644
--- a/src/pkg/math/export_test.go
+++ b/src/math/export_test.go
diff --git a/src/pkg/math/floor.go b/src/math/floor.go
index 9d30629c5..9d30629c5 100644
--- a/src/pkg/math/floor.go
+++ b/src/math/floor.go
diff --git a/src/pkg/math/floor_386.s b/src/math/floor_386.s
index 37d5a4559..31c9b174d 100644
--- a/src/pkg/math/floor_386.s
+++ b/src/math/floor_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Ceil(x float64) float64
TEXT ·Ceil(SB),NOSPLIT,$0
diff --git a/src/pkg/math/floor_amd64.s b/src/math/floor_amd64.s
index 2fd31c4fa..67b7cdec0 100644
--- a/src/pkg/math/floor_amd64.s
+++ b/src/math/floor_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#define Big 0x4330000000000000 // 2**52
diff --git a/src/pkg/math/floor_amd64p32.s b/src/math/floor_amd64p32.s
index 5b87d7a40..5b87d7a40 100644
--- a/src/pkg/math/floor_amd64p32.s
+++ b/src/math/floor_amd64p32.s
diff --git a/src/pkg/math/floor_arm.s b/src/math/floor_arm.s
index cb3b98e95..59091765b 100644
--- a/src/pkg/math/floor_arm.s
+++ b/src/math/floor_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Floor(SB),NOSPLIT,$0
B ·floor(SB)
diff --git a/src/pkg/math/frexp.go b/src/math/frexp.go
index 0e26feb66..0e26feb66 100644
--- a/src/pkg/math/frexp.go
+++ b/src/math/frexp.go
diff --git a/src/pkg/math/frexp_386.s b/src/math/frexp_386.s
index c6d0a80ed..5bff7e215 100644
--- a/src/pkg/math/frexp_386.s
+++ b/src/math/frexp_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Frexp(f float64) (frac float64, exp int)
TEXT ·Frexp(SB),NOSPLIT,$0
diff --git a/src/pkg/math/frexp_amd64.s b/src/math/frexp_amd64.s
index 03d101243..93a321039 100644
--- a/src/pkg/math/frexp_amd64.s
+++ b/src/math/frexp_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Frexp(SB),NOSPLIT,$0
JMP ·frexp(SB)
diff --git a/src/pkg/math/frexp_amd64p32.s b/src/math/frexp_amd64p32.s
index fbb564539..fbb564539 100644
--- a/src/pkg/math/frexp_amd64p32.s
+++ b/src/math/frexp_amd64p32.s
diff --git a/src/pkg/math/frexp_arm.s b/src/math/frexp_arm.s
index 9d40ae46a..7842eca59 100644
--- a/src/pkg/math/frexp_arm.s
+++ b/src/math/frexp_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Frexp(SB),NOSPLIT,$0
B ·frexp(SB)
diff --git a/src/pkg/math/gamma.go b/src/math/gamma.go
index 164f54f33..164f54f33 100644
--- a/src/pkg/math/gamma.go
+++ b/src/math/gamma.go
diff --git a/src/pkg/math/hypot.go b/src/math/hypot.go
index 2087cb05b..2087cb05b 100644
--- a/src/pkg/math/hypot.go
+++ b/src/math/hypot.go
diff --git a/src/pkg/math/hypot_386.s b/src/math/hypot_386.s
index eec1bf554..d321f465b 100644
--- a/src/pkg/math/hypot_386.s
+++ b/src/math/hypot_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Hypot(p, q float64) float64
TEXT ·Hypot(SB),NOSPLIT,$0
diff --git a/src/pkg/math/hypot_amd64.s b/src/math/hypot_amd64.s
index 5c0ff4dd8..a68eebc8c 100644
--- a/src/pkg/math/hypot_amd64.s
+++ b/src/math/hypot_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#define PosInf 0x7FF0000000000000
#define NaN 0x7FF8000000000001
diff --git a/src/pkg/math/hypot_amd64p32.s b/src/math/hypot_amd64p32.s
index b84542ae3..b84542ae3 100644
--- a/src/pkg/math/hypot_amd64p32.s
+++ b/src/math/hypot_amd64p32.s
diff --git a/src/pkg/math/hypot_arm.s b/src/math/hypot_arm.s
index 2562aa830..9c8abca13 100644
--- a/src/pkg/math/hypot_arm.s
+++ b/src/math/hypot_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Hypot(SB),NOSPLIT,$0
B ·hypot(SB)
diff --git a/src/pkg/math/j0.go b/src/math/j0.go
index c20a9b22a..c20a9b22a 100644
--- a/src/pkg/math/j0.go
+++ b/src/math/j0.go
diff --git a/src/pkg/math/j1.go b/src/math/j1.go
index 7ac186b72..7ac186b72 100644
--- a/src/pkg/math/j1.go
+++ b/src/math/j1.go
diff --git a/src/pkg/math/jn.go b/src/math/jn.go
index a7909eb24..a7909eb24 100644
--- a/src/pkg/math/jn.go
+++ b/src/math/jn.go
diff --git a/src/pkg/math/ldexp.go b/src/math/ldexp.go
index b5d2a5e7e..b5d2a5e7e 100644
--- a/src/pkg/math/ldexp.go
+++ b/src/math/ldexp.go
diff --git a/src/pkg/math/ldexp_386.s b/src/math/ldexp_386.s
index baf377ead..ac8e8ba54 100644
--- a/src/pkg/math/ldexp_386.s
+++ b/src/math/ldexp_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Ldexp(frac float64, exp int) float64
TEXT ·Ldexp(SB),NOSPLIT,$0
diff --git a/src/pkg/math/ldexp_amd64.s b/src/math/ldexp_amd64.s
index c7fc226ef..6063a6480 100644
--- a/src/pkg/math/ldexp_amd64.s
+++ b/src/math/ldexp_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Ldexp(SB),NOSPLIT,$0
JMP ·ldexp(SB)
diff --git a/src/pkg/math/ldexp_amd64p32.s b/src/math/ldexp_amd64p32.s
index 9aa9d9da3..9aa9d9da3 100644
--- a/src/pkg/math/ldexp_amd64p32.s
+++ b/src/math/ldexp_amd64p32.s
diff --git a/src/pkg/math/ldexp_arm.s b/src/math/ldexp_arm.s
index 16744ea57..fcffa2e0f 100644
--- a/src/pkg/math/ldexp_arm.s
+++ b/src/math/ldexp_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Ldexp(SB),NOSPLIT,$0
B ·ldexp(SB)
diff --git a/src/pkg/math/lgamma.go b/src/math/lgamma.go
index 6a02c412d..6a02c412d 100644
--- a/src/pkg/math/lgamma.go
+++ b/src/math/lgamma.go
diff --git a/src/pkg/math/log.go b/src/math/log.go
index 818f00a73..818f00a73 100644
--- a/src/pkg/math/log.go
+++ b/src/math/log.go
diff --git a/src/pkg/math/log10.go b/src/math/log10.go
index 95cfbf47c..95cfbf47c 100644
--- a/src/pkg/math/log10.go
+++ b/src/math/log10.go
diff --git a/src/pkg/math/log10_386.s b/src/math/log10_386.s
index 4ae069da6..2897f3c15 100644
--- a/src/pkg/math/log10_386.s
+++ b/src/math/log10_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Log10(x float64) float64
TEXT ·Log10(SB),NOSPLIT,$0
diff --git a/src/pkg/math/log10_amd64.s b/src/math/log10_amd64.s
index b9ae83268..8382ba7ae 100644
--- a/src/pkg/math/log10_amd64.s
+++ b/src/math/log10_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Log10(SB),NOSPLIT,$0
JMP ·log10(SB)
diff --git a/src/pkg/math/log10_amd64p32.s b/src/math/log10_amd64p32.s
index bf43841e2..bf43841e2 100644
--- a/src/pkg/math/log10_amd64p32.s
+++ b/src/math/log10_amd64p32.s
diff --git a/src/pkg/math/log10_arm.s b/src/math/log10_arm.s
index fa7580f6f..dbcb8351c 100644
--- a/src/pkg/math/log10_arm.s
+++ b/src/math/log10_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Log10(SB),NOSPLIT,$0
B ·log10(SB)
diff --git a/src/pkg/math/log1p.go b/src/math/log1p.go
index 12b98684c..12b98684c 100644
--- a/src/pkg/math/log1p.go
+++ b/src/math/log1p.go
diff --git a/src/pkg/math/log1p_386.s b/src/math/log1p_386.s
index 3b30fd5b7..1c2d683a8 100644
--- a/src/pkg/math/log1p_386.s
+++ b/src/math/log1p_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Log1p(x float64) float64
TEXT ·Log1p(SB),NOSPLIT,$0
diff --git a/src/pkg/math/log1p_amd64.s b/src/math/log1p_amd64.s
index 48c24f41f..1e58fb110 100644
--- a/src/pkg/math/log1p_amd64.s
+++ b/src/math/log1p_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Log1p(SB),NOSPLIT,$0
JMP ·log1p(SB)
diff --git a/src/pkg/math/log1p_amd64p32.s b/src/math/log1p_amd64p32.s
index a14b5e38a..a14b5e38a 100644
--- a/src/pkg/math/log1p_amd64p32.s
+++ b/src/math/log1p_amd64p32.s
diff --git a/src/pkg/math/log1p_arm.s b/src/math/log1p_arm.s
index fd2740d0d..95d549678 100644
--- a/src/pkg/math/log1p_arm.s
+++ b/src/math/log1p_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Log1p(SB),NOSPLIT,$0
B ·log1p(SB)
diff --git a/src/pkg/math/log_386.s b/src/math/log_386.s
index 21a0633b1..ff998afb4 100644
--- a/src/pkg/math/log_386.s
+++ b/src/math/log_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Log(x float64) float64
TEXT ·Log(SB),NOSPLIT,$0
diff --git a/src/pkg/math/log_amd64.s b/src/math/log_amd64.s
index dffc5aec8..84c60ab4d 100644
--- a/src/pkg/math/log_amd64.s
+++ b/src/math/log_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#define HSqrt2 7.07106781186547524401e-01 // sqrt(2)/2
#define Ln2Hi 6.93147180369123816490e-01 // 0x3fe62e42fee00000
diff --git a/src/pkg/math/log_amd64p32.s b/src/math/log_amd64p32.s
index 5058d607e..5058d607e 100644
--- a/src/pkg/math/log_amd64p32.s
+++ b/src/math/log_amd64p32.s
diff --git a/src/pkg/math/log_arm.s b/src/math/log_arm.s
index 28448aeef..e21d0366e 100644
--- a/src/pkg/math/log_arm.s
+++ b/src/math/log_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Log(SB),NOSPLIT,$0
B ·log(SB)
diff --git a/src/pkg/math/logb.go b/src/math/logb.go
index f2769d4fd..f2769d4fd 100644
--- a/src/pkg/math/logb.go
+++ b/src/math/logb.go
diff --git a/src/pkg/math/mod.go b/src/math/mod.go
index e1a414e5f..e1a414e5f 100644
--- a/src/pkg/math/mod.go
+++ b/src/math/mod.go
diff --git a/src/pkg/math/mod_386.s b/src/math/mod_386.s
index 9b3b6bd06..10ad98be3 100644
--- a/src/pkg/math/mod_386.s
+++ b/src/math/mod_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Mod(x, y float64) float64
TEXT ·Mod(SB),NOSPLIT,$0
diff --git a/src/pkg/math/mod_amd64.s b/src/math/mod_amd64.s
index bef83fcf7..f99dbe293 100644
--- a/src/pkg/math/mod_amd64.s
+++ b/src/math/mod_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Mod(SB),NOSPLIT,$0
JMP ·mod(SB)
diff --git a/src/pkg/math/mod_amd64p32.s b/src/math/mod_amd64p32.s
index c1b231124..c1b231124 100644
--- a/src/pkg/math/mod_amd64p32.s
+++ b/src/math/mod_amd64p32.s
diff --git a/src/pkg/math/mod_arm.s b/src/math/mod_arm.s
index 1f51588f8..5afb3594d 100644
--- a/src/pkg/math/mod_arm.s
+++ b/src/math/mod_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Mod(SB),NOSPLIT,$0
B ·mod(SB)
diff --git a/src/pkg/math/modf.go b/src/math/modf.go
index 1e8376a93..1e8376a93 100644
--- a/src/pkg/math/modf.go
+++ b/src/math/modf.go
diff --git a/src/pkg/math/modf_386.s b/src/math/modf_386.s
index 07a0dc5cf..3debd3b95 100644
--- a/src/pkg/math/modf_386.s
+++ b/src/math/modf_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Modf(f float64) (int float64, frac float64)
TEXT ·Modf(SB),NOSPLIT,$0
diff --git a/src/pkg/math/modf_amd64.s b/src/math/modf_amd64.s
index 05feb4bf9..701cf72a3 100644
--- a/src/pkg/math/modf_amd64.s
+++ b/src/math/modf_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Modf(SB),NOSPLIT,$0
JMP ·modf(SB)
diff --git a/src/pkg/math/modf_amd64p32.s b/src/math/modf_amd64p32.s
index 5508c2547..5508c2547 100644
--- a/src/pkg/math/modf_amd64p32.s
+++ b/src/math/modf_amd64p32.s
diff --git a/src/pkg/math/modf_arm.s b/src/math/modf_arm.s
index e6bd26d53..ea3c8dc74 100644
--- a/src/pkg/math/modf_arm.s
+++ b/src/math/modf_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Modf(SB),NOSPLIT,$0
B ·modf(SB)
diff --git a/src/math/nextafter.go b/src/math/nextafter.go
new file mode 100644
index 000000000..bbb139986
--- /dev/null
+++ b/src/math/nextafter.go
@@ -0,0 +1,47 @@
+// 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.
+
+package math
+
+// Nextafter32 returns the next representable float32 value after x towards y.
+// Special cases:
+// Nextafter32(x, x) = x
+// Nextafter32(NaN, y) = NaN
+// Nextafter32(x, NaN) = NaN
+func Nextafter32(x, y float32) (r float32) {
+ switch {
+ case IsNaN(float64(x)) || IsNaN(float64(y)): // special case
+ r = float32(NaN())
+ case x == y:
+ r = x
+ case x == 0:
+ r = float32(Copysign(float64(Float32frombits(1)), float64(y)))
+ case (y > x) == (x > 0):
+ r = Float32frombits(Float32bits(x) + 1)
+ default:
+ r = Float32frombits(Float32bits(x) - 1)
+ }
+ return
+}
+
+// Nextafter returns the next representable float64 value after x towards y.
+// Special cases:
+// Nextafter64(x, x) = x
+// Nextafter64(NaN, y) = NaN
+// Nextafter64(x, NaN) = NaN
+func Nextafter(x, y float64) (r float64) {
+ switch {
+ case IsNaN(x) || IsNaN(y): // special case
+ r = NaN()
+ case x == y:
+ r = x
+ case x == 0:
+ r = Copysign(Float64frombits(1), y)
+ case (y > x) == (x > 0):
+ r = Float64frombits(Float64bits(x) + 1)
+ default:
+ r = Float64frombits(Float64bits(x) - 1)
+ }
+ return
+}
diff --git a/src/pkg/math/pow.go b/src/math/pow.go
index 77af25648..77af25648 100644
--- a/src/pkg/math/pow.go
+++ b/src/math/pow.go
diff --git a/src/pkg/math/pow10.go b/src/math/pow10.go
index f5ad28bb4..f5ad28bb4 100644
--- a/src/pkg/math/pow10.go
+++ b/src/math/pow10.go
diff --git a/src/pkg/math/rand/example_test.go b/src/math/rand/example_test.go
index f42991453..f42991453 100644
--- a/src/pkg/math/rand/example_test.go
+++ b/src/math/rand/example_test.go
diff --git a/src/pkg/math/rand/exp.go b/src/math/rand/exp.go
index 4bc110f91..4bc110f91 100644
--- a/src/pkg/math/rand/exp.go
+++ b/src/math/rand/exp.go
diff --git a/src/pkg/math/rand/normal.go b/src/math/rand/normal.go
index ba4ea54ca..ba4ea54ca 100644
--- a/src/pkg/math/rand/normal.go
+++ b/src/math/rand/normal.go
diff --git a/src/pkg/math/rand/rand.go b/src/math/rand/rand.go
index 3ffb5c4e5..3ffb5c4e5 100644
--- a/src/pkg/math/rand/rand.go
+++ b/src/math/rand/rand.go
diff --git a/src/pkg/math/rand/rand_test.go b/src/math/rand/rand_test.go
index ab0dc49b4..ab0dc49b4 100644
--- a/src/pkg/math/rand/rand_test.go
+++ b/src/math/rand/rand_test.go
diff --git a/src/pkg/math/rand/regress_test.go b/src/math/rand/regress_test.go
index 2b012af89..2b012af89 100644
--- a/src/pkg/math/rand/regress_test.go
+++ b/src/math/rand/regress_test.go
diff --git a/src/pkg/math/rand/rng.go b/src/math/rand/rng.go
index 947c49f0f..947c49f0f 100644
--- a/src/pkg/math/rand/rng.go
+++ b/src/math/rand/rng.go
diff --git a/src/pkg/math/rand/zipf.go b/src/math/rand/zipf.go
index 8db2c6f5b..8db2c6f5b 100644
--- a/src/pkg/math/rand/zipf.go
+++ b/src/math/rand/zipf.go
diff --git a/src/pkg/math/remainder.go b/src/math/remainder.go
index 9a4e4154c..9a4e4154c 100644
--- a/src/pkg/math/remainder.go
+++ b/src/math/remainder.go
diff --git a/src/pkg/math/remainder_386.s b/src/math/remainder_386.s
index bbe13a0d9..318fa2c46 100644
--- a/src/pkg/math/remainder_386.s
+++ b/src/math/remainder_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Remainder(x, y float64) float64
TEXT ·Remainder(SB),NOSPLIT,$0
diff --git a/src/pkg/math/remainder_amd64.s b/src/math/remainder_amd64.s
index e5e23c7ce..f7fda99d8 100644
--- a/src/pkg/math/remainder_amd64.s
+++ b/src/math/remainder_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Remainder(SB),NOSPLIT,$0
JMP ·remainder(SB)
diff --git a/src/pkg/math/remainder_amd64p32.s b/src/math/remainder_amd64p32.s
index cd5cf55ff..cd5cf55ff 100644
--- a/src/pkg/math/remainder_amd64p32.s
+++ b/src/math/remainder_amd64p32.s
diff --git a/src/pkg/math/remainder_arm.s b/src/math/remainder_arm.s
index 8728afe93..1ae597a60 100644
--- a/src/pkg/math/remainder_arm.s
+++ b/src/math/remainder_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Remainder(SB),NOSPLIT,$0
B ·remainder(SB)
diff --git a/src/pkg/math/signbit.go b/src/math/signbit.go
index 670cc1a66..670cc1a66 100644
--- a/src/pkg/math/signbit.go
+++ b/src/math/signbit.go
diff --git a/src/pkg/math/sin.go b/src/math/sin.go
index ed85f21be..ed85f21be 100644
--- a/src/pkg/math/sin.go
+++ b/src/math/sin.go
diff --git a/src/pkg/math/sin_386.s b/src/math/sin_386.s
index 09271c035..ccc8e64be 100644
--- a/src/pkg/math/sin_386.s
+++ b/src/math/sin_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Cos(x float64) float64
TEXT ·Cos(SB),NOSPLIT,$0
diff --git a/src/pkg/math/sin_amd64.s b/src/math/sin_amd64.s
index 008bf4be5..0c33cecef 100644
--- a/src/pkg/math/sin_amd64.s
+++ b/src/math/sin_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Sin(SB),NOSPLIT,$0
JMP ·sin(SB)
diff --git a/src/pkg/math/sin_amd64p32.s b/src/math/sin_amd64p32.s
index 9f93eba20..9f93eba20 100644
--- a/src/pkg/math/sin_amd64p32.s
+++ b/src/math/sin_amd64p32.s
diff --git a/src/pkg/math/sin_arm.s b/src/math/sin_arm.s
index a057b4fc9..467af3dea 100644
--- a/src/pkg/math/sin_arm.s
+++ b/src/math/sin_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Sin(SB),NOSPLIT,$0
B ·sin(SB)
diff --git a/src/pkg/math/sincos.go b/src/math/sincos.go
index 718030319..718030319 100644
--- a/src/pkg/math/sincos.go
+++ b/src/math/sincos.go
diff --git a/src/pkg/math/sincos_386.s b/src/math/sincos_386.s
index bf964b168..83af5016e 100644
--- a/src/pkg/math/sincos_386.s
+++ b/src/math/sincos_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Sincos(x float64) (sin, cos float64)
TEXT ·Sincos(SB),NOSPLIT,$0
diff --git a/src/pkg/math/sincos_amd64.s b/src/math/sincos_amd64.s
index bccc1ade1..59bf55f58 100644
--- a/src/pkg/math/sincos_amd64.s
+++ b/src/math/sincos_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// The method is based on a paper by Naoki Shibata: "Efficient evaluation
// methods of elementary functions suitable for SIMD computation", Proc.
@@ -15,9 +15,7 @@
// The README file says, "The software is in public domain.
// You can use the software without any obligation."
//
-// This code is a simplified version of the original. The CMPSD
-// instruction, not generated by the compiler, eliminates jumps in the
-// body of the calculation.
+// This code is a simplified version of the original.
#define PosOne 0x3FF0000000000000
#define PosInf 0x7FF0000000000000
@@ -96,11 +94,10 @@ TEXT ·Sincos(SB),NOSPLIT,$0
// if ((q + 1) & 2) != 0 { sin, cos = cos, sin }
MOVQ $1, DX
ADDQ BX, DX
- MOVQ $2, AX
- ANDQ AX, DX
- MOVQ DX, X0
- MOVSD $0.0, X3
- CMPSD X0, X3, 0 // cmpeq; x1= x, x2= z, x3 = y, x7= d, bx= q
+ ANDQ $2, DX
+ SHRQ $1, DX
+ SUBQ $1, DX
+ MOVQ DX, X3
// sin = (y & z) | (^y & x)
MOVAPD X2, X0
ANDPD X3, X0 // x0= sin
diff --git a/src/pkg/math/sincos_amd64p32.s b/src/math/sincos_amd64p32.s
index 360e94d09..360e94d09 100644
--- a/src/pkg/math/sincos_amd64p32.s
+++ b/src/math/sincos_amd64p32.s
diff --git a/src/pkg/math/sincos_arm.s b/src/math/sincos_arm.s
index b6866af54..9fe048248 100644
--- a/src/pkg/math/sincos_arm.s
+++ b/src/math/sincos_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Sincos(SB),NOSPLIT,$0
B ·sincos(SB)
diff --git a/src/pkg/math/sinh.go b/src/math/sinh.go
index 139b911fe..139b911fe 100644
--- a/src/pkg/math/sinh.go
+++ b/src/math/sinh.go
diff --git a/src/pkg/math/sqrt.go b/src/math/sqrt.go
index 1bd4437f1..fdc869992 100644
--- a/src/pkg/math/sqrt.go
+++ b/src/math/sqrt.go
@@ -80,7 +80,7 @@ package math
//
//
// Notes: Rounding mode detection omitted. The constants "mask", "shift",
-// and "bias" are found in src/pkg/math/bits.go
+// and "bias" are found in src/math/bits.go
// Sqrt returns the square root of x.
//
diff --git a/src/pkg/math/sqrt_386.s b/src/math/sqrt_386.s
index 2d0c786d0..5234a1e88 100644
--- a/src/pkg/math/sqrt_386.s
+++ b/src/math/sqrt_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Sqrt(x float64) float64
TEXT ·Sqrt(SB),NOSPLIT,$0
diff --git a/src/pkg/math/sqrt_amd64.s b/src/math/sqrt_amd64.s
index 1508944c9..443d83fe3 100644
--- a/src/pkg/math/sqrt_amd64.s
+++ b/src/math/sqrt_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Sqrt(x float64) float64
TEXT ·Sqrt(SB),NOSPLIT,$0
diff --git a/src/pkg/math/sqrt_amd64p32.s b/src/math/sqrt_amd64p32.s
index d83a286c2..d83a286c2 100644
--- a/src/pkg/math/sqrt_amd64p32.s
+++ b/src/math/sqrt_amd64p32.s
diff --git a/src/pkg/math/sqrt_arm.s b/src/math/sqrt_arm.s
index f731ee976..4f9dc2e03 100644
--- a/src/pkg/math/sqrt_arm.s
+++ b/src/math/sqrt_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Sqrt(x float64) float64
TEXT ·Sqrt(SB),NOSPLIT,$0
diff --git a/src/pkg/math/tan.go b/src/math/tan.go
index 285eff1ab..285eff1ab 100644
--- a/src/pkg/math/tan.go
+++ b/src/math/tan.go
diff --git a/src/pkg/math/tan_386.s b/src/math/tan_386.s
index 2320326e3..f1bdae153 100644
--- a/src/pkg/math/tan_386.s
+++ b/src/math/tan_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// func Tan(x float64) float64
TEXT ·Tan(SB),NOSPLIT,$0
diff --git a/src/pkg/math/tan_amd64.s b/src/math/tan_amd64.s
index 9fa5f148e..39aa08061 100644
--- a/src/pkg/math/tan_amd64.s
+++ b/src/math/tan_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Tan(SB),NOSPLIT,$0
JMP ·tan(SB)
diff --git a/src/pkg/math/tan_amd64p32.s b/src/math/tan_amd64p32.s
index 9b3f70de7..9b3f70de7 100644
--- a/src/pkg/math/tan_amd64p32.s
+++ b/src/math/tan_amd64p32.s
diff --git a/src/pkg/math/tan_arm.s b/src/math/tan_arm.s
index 68fea318d..36c7c128f 100644
--- a/src/pkg/math/tan_arm.s
+++ b/src/math/tan_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·Tan(SB),NOSPLIT,$0
B ·tan(SB)
diff --git a/src/pkg/math/tanh.go b/src/math/tanh.go
index cf0ffa192..cf0ffa192 100644
--- a/src/pkg/math/tanh.go
+++ b/src/math/tanh.go
diff --git a/src/pkg/math/unsafe.go b/src/math/unsafe.go
index 5ae67420f..5ae67420f 100644
--- a/src/pkg/math/unsafe.go
+++ b/src/math/unsafe.go
diff --git a/src/pkg/mime/grammar.go b/src/mime/grammar.go
index 2347324aa..2347324aa 100644
--- a/src/pkg/mime/grammar.go
+++ b/src/mime/grammar.go
diff --git a/src/pkg/mime/mediatype.go b/src/mime/mediatype.go
index ad63f9bb9..ad63f9bb9 100644
--- a/src/pkg/mime/mediatype.go
+++ b/src/mime/mediatype.go
diff --git a/src/pkg/mime/mediatype_test.go b/src/mime/mediatype_test.go
index 026bfa4d7..026bfa4d7 100644
--- a/src/pkg/mime/mediatype_test.go
+++ b/src/mime/mediatype_test.go
diff --git a/src/pkg/mime/multipart/example_test.go b/src/mime/multipart/example_test.go
index 26135b785..6d6ba81d5 100644
--- a/src/pkg/mime/multipart/example_test.go
+++ b/src/mime/multipart/example_test.go
@@ -18,7 +18,7 @@ import (
func ExampleNewReader() {
msg := &mail.Message{
Header: map[string][]string{
- "Content-Type": []string{"multipart/mixed; boundary=foo"},
+ "Content-Type": {"multipart/mixed; boundary=foo"},
},
Body: strings.NewReader(
"--foo\r\nFoo: one\r\n\r\nA section\r\n" +
diff --git a/src/pkg/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
index eee53fc8d..eee53fc8d 100644
--- a/src/pkg/mime/multipart/formdata.go
+++ b/src/mime/multipart/formdata.go
diff --git a/src/pkg/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
index 6e2388baf..6e2388baf 100644
--- a/src/pkg/mime/multipart/formdata_test.go
+++ b/src/mime/multipart/formdata_test.go
diff --git a/src/pkg/mime/multipart/multipart.go b/src/mime/multipart/multipart.go
index 7382efab9..01a667d93 100644
--- a/src/pkg/mime/multipart/multipart.go
+++ b/src/mime/multipart/multipart.go
@@ -90,8 +90,7 @@ func (p *Part) parseContentDisposition() {
func NewReader(r io.Reader, boundary string) *Reader {
b := []byte("\r\n--" + boundary + "--")
return &Reader{
- bufReader: bufio.NewReader(r),
-
+ bufReader: bufio.NewReader(r),
nl: b[:2],
nlDashBoundary: b[:len(b)-2],
dashBoundaryDash: b[2:],
diff --git a/src/pkg/mime/multipart/multipart_test.go b/src/mime/multipart/multipart_test.go
index d662e8340..d662e8340 100644
--- a/src/pkg/mime/multipart/multipart_test.go
+++ b/src/mime/multipart/multipart_test.go
diff --git a/src/pkg/mime/multipart/quotedprintable.go b/src/mime/multipart/quotedprintable.go
index 9ff4ee703..9ff4ee703 100644
--- a/src/pkg/mime/multipart/quotedprintable.go
+++ b/src/mime/multipart/quotedprintable.go
diff --git a/src/pkg/mime/multipart/quotedprintable_test.go b/src/mime/multipart/quotedprintable_test.go
index c4de3eb75..c4de3eb75 100644
--- a/src/pkg/mime/multipart/quotedprintable_test.go
+++ b/src/mime/multipart/quotedprintable_test.go
diff --git a/src/pkg/mime/multipart/testdata/nested-mime b/src/mime/multipart/testdata/nested-mime
index 71c238e38..71c238e38 100644
--- a/src/pkg/mime/multipart/testdata/nested-mime
+++ b/src/mime/multipart/testdata/nested-mime
diff --git a/src/pkg/mime/multipart/writer.go b/src/mime/multipart/writer.go
index e13a956af..e13a956af 100644
--- a/src/pkg/mime/multipart/writer.go
+++ b/src/mime/multipart/writer.go
diff --git a/src/pkg/mime/multipart/writer_test.go b/src/mime/multipart/writer_test.go
index 52d68bcb6..ba00c97ec 100644
--- a/src/pkg/mime/multipart/writer_test.go
+++ b/src/mime/multipart/writer_test.go
@@ -111,3 +111,18 @@ func TestWriterSetBoundary(t *testing.T) {
t.Errorf("expected my-separator in output. got: %q", got)
}
}
+
+func TestWriterBoundaryGoroutines(t *testing.T) {
+ // Verify there's no data race accessing any lazy boundary if it's used by
+ // different goroutines. This was previously broken by
+ // https://codereview.appspot.com/95760043/ and reverted in
+ // https://codereview.appspot.com/117600043/
+ w := NewWriter(ioutil.Discard)
+ done := make(chan int)
+ go func() {
+ w.CreateFormField("foo")
+ done <- 1
+ }()
+ w.Boundary()
+ <-done
+}
diff --git a/src/pkg/mime/testdata/test.types b/src/mime/testdata/test.types
index 9b040edd7..9b040edd7 100644
--- a/src/pkg/mime/testdata/test.types
+++ b/src/mime/testdata/test.types
diff --git a/src/pkg/mime/testdata/test.types.plan9 b/src/mime/testdata/test.types.plan9
index 19dbf41cc..19dbf41cc 100644
--- a/src/pkg/mime/testdata/test.types.plan9
+++ b/src/mime/testdata/test.types.plan9
diff --git a/src/mime/type.go b/src/mime/type.go
new file mode 100644
index 000000000..ffda1f0ce
--- /dev/null
+++ b/src/mime/type.go
@@ -0,0 +1,121 @@
+// 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.
+
+// Package mime implements parts of the MIME spec.
+package mime
+
+import (
+ "fmt"
+ "strings"
+ "sync"
+)
+
+var (
+ mimeLock sync.RWMutex
+ mimeTypesLower = map[string]string{
+ ".css": "text/css; charset=utf-8",
+ ".gif": "image/gif",
+ ".htm": "text/html; charset=utf-8",
+ ".html": "text/html; charset=utf-8",
+ ".jpg": "image/jpeg",
+ ".js": "application/x-javascript",
+ ".pdf": "application/pdf",
+ ".png": "image/png",
+ ".xml": "text/xml; charset=utf-8",
+ }
+ mimeTypes = clone(mimeTypesLower)
+)
+
+func clone(m map[string]string) map[string]string {
+ m2 := make(map[string]string, len(m))
+ for k, v := range m {
+ m2[k] = v
+ if strings.ToLower(k) != k {
+ panic("keys in mimeTypesLower must be lowercase")
+ }
+ }
+ return m2
+}
+
+var once sync.Once // guards initMime
+
+// TypeByExtension returns the MIME type associated with the file extension ext.
+// The extension ext should begin with a leading dot, as in ".html".
+// When ext has no associated type, TypeByExtension returns "".
+//
+// Extensions are looked up first case-sensitively, then case-insensitively.
+//
+// The built-in table is small but on unix it is augmented by the local
+// system's mime.types file(s) if available under one or more of these
+// names:
+//
+// /etc/mime.types
+// /etc/apache2/mime.types
+// /etc/apache/mime.types
+//
+// On Windows, MIME types are extracted from the registry.
+//
+// Text types have the charset parameter set to "utf-8" by default.
+func TypeByExtension(ext string) string {
+ once.Do(initMime)
+ mimeLock.RLock()
+ defer mimeLock.RUnlock()
+
+ // Case-sensitive lookup.
+ v := mimeTypes[ext]
+ if v != "" {
+ return v
+ }
+
+ // Case-insensitive lookup.
+ // Optimistically assume a short ASCII extension and be
+ // allocation-free in that case.
+ var buf [10]byte
+ lower := buf[:0]
+ const utf8RuneSelf = 0x80 // from utf8 package, but not importing it.
+ for i := 0; i < len(ext); i++ {
+ c := ext[i]
+ if c >= utf8RuneSelf {
+ // Slow path.
+ return mimeTypesLower[strings.ToLower(ext)]
+ }
+ if 'A' <= c && c <= 'Z' {
+ lower = append(lower, c+('a'-'A'))
+ } else {
+ lower = append(lower, c)
+ }
+ }
+ // The conversion from []byte to string doesn't allocate in
+ // a map lookup.
+ return mimeTypesLower[string(lower)]
+}
+
+// AddExtensionType sets the MIME type associated with
+// the extension ext to typ. The extension should begin with
+// a leading dot, as in ".html".
+func AddExtensionType(ext, typ string) error {
+ if !strings.HasPrefix(ext, ".") {
+ return fmt.Errorf(`mime: extension %q misses dot`, ext)
+ }
+ once.Do(initMime)
+ return setExtensionType(ext, typ)
+}
+
+func setExtensionType(extension, mimeType string) error {
+ _, param, err := ParseMediaType(mimeType)
+ if err != nil {
+ return err
+ }
+ if strings.HasPrefix(mimeType, "text/") && param["charset"] == "" {
+ param["charset"] = "utf-8"
+ mimeType = FormatMediaType(mimeType, param)
+ }
+ extLower := strings.ToLower(extension)
+
+ mimeLock.Lock()
+ mimeTypes[extension] = mimeType
+ mimeTypesLower[extLower] = mimeType
+ mimeLock.Unlock()
+ return nil
+}
diff --git a/src/pkg/mime/type_plan9.go b/src/mime/type_plan9.go
index b8f0511ee..8cbf6777f 100644
--- a/src/pkg/mime/type_plan9.go
+++ b/src/mime/type_plan9.go
@@ -48,6 +48,6 @@ func initMimeForTests() map[string]string {
return map[string]string{
".t1": "application/test",
".t2": "text/test; charset=utf-8",
- ".png": "image/png",
+ ".pNg": "image/png",
}
}
diff --git a/src/mime/type_test.go b/src/mime/type_test.go
new file mode 100644
index 000000000..d2d254ae9
--- /dev/null
+++ b/src/mime/type_test.go
@@ -0,0 +1,54 @@
+// 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.
+
+package mime
+
+import (
+ "testing"
+)
+
+var typeTests = initMimeForTests()
+
+func TestTypeByExtension(t *testing.T) {
+ for ext, want := range typeTests {
+ val := TypeByExtension(ext)
+ if val != want {
+ t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want)
+ }
+ }
+}
+
+func TestTypeByExtensionCase(t *testing.T) {
+ const custom = "test/test; charset=iso-8859-1"
+ const caps = "test/test; WAS=ALLCAPS"
+ if err := AddExtensionType(".TEST", caps); err != nil {
+ t.Fatalf("error %s for AddExtension(%s)", err, custom)
+ }
+ if err := AddExtensionType(".tesT", custom); err != nil {
+ t.Fatalf("error %s for AddExtension(%s)", err, custom)
+ }
+
+ // case-sensitive lookup
+ if got := TypeByExtension(".tesT"); got != custom {
+ t.Fatalf("for .tesT, got %q; want %q", got, custom)
+ }
+ if got := TypeByExtension(".TEST"); got != caps {
+ t.Fatalf("for .TEST, got %q; want %s", got, caps)
+ }
+
+ // case-insensitive
+ if got := TypeByExtension(".TesT"); got != custom {
+ t.Fatalf("for .TesT, got %q; want %q", got, custom)
+ }
+}
+
+func TestLookupMallocs(t *testing.T) {
+ n := testing.AllocsPerRun(10000, func() {
+ TypeByExtension(".html")
+ TypeByExtension(".HtML")
+ })
+ if n > 0 {
+ t.Errorf("allocs = %v; want 0", n)
+ }
+}
diff --git a/src/pkg/mime/type_unix.go b/src/mime/type_unix.go
index 1d394315a..3e404cf74 100644
--- a/src/pkg/mime/type_unix.go
+++ b/src/mime/type_unix.go
@@ -53,7 +53,7 @@ func initMime() {
func initMimeForTests() map[string]string {
typeFiles = []string{"testdata/test.types"}
return map[string]string{
- ".t1": "application/test",
+ ".T1": "application/test",
".t2": "text/test; charset=utf-8",
".png": "image/png",
}
diff --git a/src/pkg/mime/type_windows.go b/src/mime/type_windows.go
index 180f948d1..ae758d78b 100644
--- a/src/pkg/mime/type_windows.go
+++ b/src/mime/type_windows.go
@@ -58,6 +58,6 @@ func initMime() {
func initMimeForTests() map[string]string {
return map[string]string{
- ".png": "image/png",
+ ".PnG": "image/png",
}
}
diff --git a/src/nacltest.bash b/src/nacltest.bash
index e5bbb4b68..6220d39f1 100755
--- a/src/nacltest.bash
+++ b/src/nacltest.bash
@@ -13,8 +13,23 @@
set -e
ulimit -c 0
+# guess GOARCH if not set
+naclGOARCH=$GOARCH
+if [ -z "$naclGOARCH" ]; then
+ case "$(uname -m)" in
+ x86_64)
+ naclGOARCH=amd64p32
+ ;;
+ armv7l) # NativeClient on ARM only supports ARMv7A.
+ naclGOARCH=arm
+ ;;
+ i?86)
+ naclGOARCH=386
+ ;;
+ esac
+fi
+
# Check GOARCH.
-naclGOARCH=${GOARCH:-386}
case "$naclGOARCH" in
amd64p32)
if ! which sel_ldr_x86_64 >/dev/null; then
@@ -28,6 +43,12 @@ amd64p32)
exit 1
fi
;;
+arm)
+ if ! which sel_ldr_arm >/dev/null; then
+ echo 'cannot find sel_ldr_arm' 1>&2
+ exit 1
+ fi
+ ;;
*)
echo 'unsupported $GOARCH for nacl: '"$naclGOARCH" 1>&2
exit 1
@@ -45,12 +66,14 @@ if [ ! -f make.bash ]; then
exit 1
fi
GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH ./make.bash
-unset GOROOT
+
+# the builder might have set GOROOT_FINAL.
+export GOROOT=$(pwd)/..
# Build zip file embedded in package syscall.
gobin=${GOBIN:-$(pwd)/../bin}
-rm -f pkg/syscall/fstest_nacl.go
-GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH $gobin/go run ../misc/nacl/mkzip.go -p syscall -r .. ../misc/nacl/testzip.proto pkg/syscall/fstest_nacl.go
+rm -f syscall/fstest_nacl.go
+GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH $gobin/go run ../misc/nacl/mkzip.go -p syscall -r .. ../misc/nacl/testzip.proto syscall/fstest_nacl.go
# Run standard build and tests.
export PATH=$(pwd)/../misc/nacl:$PATH
diff --git a/src/net/cgo_android.go b/src/net/cgo_android.go
new file mode 100644
index 000000000..3819ce56a
--- /dev/null
+++ b/src/net/cgo_android.go
@@ -0,0 +1,14 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build cgo,!netgo
+
+package net
+
+//#include <netdb.h>
+import "C"
+
+func cgoAddrInfoFlags() C.int {
+ return C.AI_CANONNAME
+}
diff --git a/src/pkg/net/cgo_bsd.go b/src/net/cgo_bsd.go
index 3090d3019..3090d3019 100644
--- a/src/pkg/net/cgo_bsd.go
+++ b/src/net/cgo_bsd.go
diff --git a/src/pkg/net/cgo_linux.go b/src/net/cgo_linux.go
index 693aef03d..4ef2d0cd1 100644
--- a/src/pkg/net/cgo_linux.go
+++ b/src/net/cgo_linux.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 cgo,!netgo
+// +build !android,cgo,!netgo
package net
diff --git a/src/pkg/net/cgo_netbsd.go b/src/net/cgo_netbsd.go
index 09c5ad2d9..09c5ad2d9 100644
--- a/src/pkg/net/cgo_netbsd.go
+++ b/src/net/cgo_netbsd.go
diff --git a/src/pkg/net/cgo_openbsd.go b/src/net/cgo_openbsd.go
index 09c5ad2d9..09c5ad2d9 100644
--- a/src/pkg/net/cgo_openbsd.go
+++ b/src/net/cgo_openbsd.go
diff --git a/src/pkg/net/cgo_stub.go b/src/net/cgo_stub.go
index f533c1421..f533c1421 100644
--- a/src/pkg/net/cgo_stub.go
+++ b/src/net/cgo_stub.go
diff --git a/src/pkg/net/cgo_unix.go b/src/net/cgo_unix.go
index 1f366ee5c..1f366ee5c 100644
--- a/src/pkg/net/cgo_unix.go
+++ b/src/net/cgo_unix.go
diff --git a/src/pkg/net/cgo_unix_test.go b/src/net/cgo_unix_test.go
index 33566ce9c..33566ce9c 100644
--- a/src/pkg/net/cgo_unix_test.go
+++ b/src/net/cgo_unix_test.go
diff --git a/src/pkg/net/conn_test.go b/src/net/conn_test.go
index 37bb4e2c0..9c9d1a805 100644
--- a/src/pkg/net/conn_test.go
+++ b/src/net/conn_test.go
@@ -38,7 +38,7 @@ func TestConnAndListener(t *testing.T) {
}
case "unixpacket":
switch runtime.GOOS {
- case "darwin", "nacl", "openbsd", "plan9", "windows":
+ case "android", "darwin", "nacl", "openbsd", "plan9", "windows":
continue
case "freebsd": // FreeBSD 8 doesn't support unixpacket
continue
diff --git a/src/pkg/net/dial.go b/src/net/dial.go
index 93569c253..e6f0436cd 100644
--- a/src/pkg/net/dial.go
+++ b/src/net/dial.go
@@ -118,9 +118,8 @@ func resolveAddr(op, net, addr string, deadline time.Time) (netaddr, error) {
// "unixpacket".
//
// For TCP and UDP networks, addresses have the form host:port.
-// If host is a literal IPv6 address or host name, it must be enclosed
-// in square brackets as in "[::1]:80", "[ipv6-host]:http" or
-// "[ipv6-host%zone]:80".
+// If host is a literal IPv6 address it must be enclosed
+// in square brackets as in "[::1]:80" or "[ipv6-host%zone]:80".
// The functions JoinHostPort and SplitHostPort manipulate addresses
// in this form.
//
@@ -214,14 +213,12 @@ func dialMulti(net, addr string, la Addr, ras addrList, deadline time.Time) (Con
nracers := len(ras)
for nracers > 0 {
sig <- true
- select {
- case racer := <-lane:
- if racer.error == nil {
- return racer.Conn, nil
- }
- lastErr = racer.error
- nracers--
+ racer := <-lane
+ if racer.error == nil {
+ return racer.Conn, nil
}
+ lastErr = racer.error
+ nracers--
}
return nil, lastErr
}
diff --git a/src/pkg/net/dial_gen.go b/src/net/dial_gen.go
index ada623300..ada623300 100644
--- a/src/pkg/net/dial_gen.go
+++ b/src/net/dial_gen.go
diff --git a/src/pkg/net/dial_gen_test.go b/src/net/dial_gen_test.go
index c857acd06..c857acd06 100644
--- a/src/pkg/net/dial_gen_test.go
+++ b/src/net/dial_gen_test.go
diff --git a/src/pkg/net/dial_test.go b/src/net/dial_test.go
index f9260fd28..42898d669 100644
--- a/src/pkg/net/dial_test.go
+++ b/src/net/dial_test.go
@@ -119,6 +119,7 @@ func TestSelfConnect(t *testing.T) {
// TODO(brainman): do not know why it hangs.
t.Skip("skipping known-broken test on windows")
}
+
// Test that Dial does not honor self-connects.
// See the comment in DialTCP.
@@ -149,8 +150,12 @@ func TestSelfConnect(t *testing.T) {
for i := 0; i < n; i++ {
c, err := DialTimeout("tcp", addr, time.Millisecond)
if err == nil {
+ if c.LocalAddr().String() == addr {
+ t.Errorf("#%d: Dial %q self-connect", i, addr)
+ } else {
+ t.Logf("#%d: Dial %q succeeded - possibly racing with other listener", i, addr)
+ }
c.Close()
- t.Errorf("#%d: Dial %q succeeded", i, addr)
}
}
}
@@ -334,6 +339,8 @@ func numTCP() (ntcp, nopen, nclose int, err error) {
}
func TestDialMultiFDLeak(t *testing.T) {
+ t.Skip("flaky test - golang.org/issue/8764")
+
if !supportsIPv4 || !supportsIPv6 {
t.Skip("neither ipv4 nor ipv6 is supported")
}
@@ -460,6 +467,11 @@ func TestDialer(t *testing.T) {
}
func TestDialDualStackLocalhost(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl":
+ t.Skipf("skipping test on %q", runtime.GOOS)
+ }
+
if ips, err := LookupIP("localhost"); err != nil {
t.Fatalf("LookupIP failed: %v", err)
} else if len(ips) < 2 || !supportsIPv4 || !supportsIPv6 {
@@ -488,7 +500,7 @@ func TestDialDualStackLocalhost(t *testing.T) {
}
d := &Dialer{DualStack: true}
- for _ = range dss.lns {
+ for range dss.lns {
if c, err := d.Dial("tcp", "localhost:"+dss.port); err != nil {
t.Errorf("Dial failed: %v", err)
} else {
diff --git a/src/pkg/net/dialgoogle_test.go b/src/net/dialgoogle_test.go
index df5895afa..df5895afa 100644
--- a/src/pkg/net/dialgoogle_test.go
+++ b/src/net/dialgoogle_test.go
diff --git a/src/pkg/net/dnsclient.go b/src/net/dnsclient.go
index 9bffa11f9..e8014e4ff 100644
--- a/src/pkg/net/dnsclient.go
+++ b/src/net/dnsclient.go
@@ -196,9 +196,7 @@ func (addrs byPriorityWeight) shuffleByWeight() {
s += int(addrs[i].Weight)
if s > n {
if i > 0 {
- t := addrs[i]
- copy(addrs[1:i+1], addrs[0:i])
- addrs[0] = t
+ addrs[0], addrs[i] = addrs[i], addrs[0]
}
break
}
diff --git a/src/pkg/net/dnsclient_test.go b/src/net/dnsclient_test.go
index 435eb3550..435eb3550 100644
--- a/src/pkg/net/dnsclient_test.go
+++ b/src/net/dnsclient_test.go
diff --git a/src/pkg/net/dnsclient_unix.go b/src/net/dnsclient_unix.go
index 3713efd0e..7511083f7 100644
--- a/src/pkg/net/dnsclient_unix.go
+++ b/src/net/dnsclient_unix.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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// DNS client: see RFC 1035.
// Has to be linked into package net for Dial.
@@ -16,6 +16,7 @@
package net
import (
+ "errors"
"io"
"math/rand"
"os"
@@ -23,118 +24,174 @@ import (
"time"
)
-// Send a request on the connection and hope for a reply.
-// Up to cfg.attempts attempts.
-func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, error) {
- _, useTCP := c.(*TCPConn)
- if len(name) >= 256 {
- return nil, &DNSError{Err: "name too long", Name: name}
+// A dnsConn represents a DNS transport endpoint.
+type dnsConn interface {
+ Conn
+
+ // readDNSResponse reads a DNS response message from the DNS
+ // transport endpoint and returns the received DNS response
+ // message.
+ readDNSResponse() (*dnsMsg, error)
+
+ // writeDNSQuery writes a DNS query message to the DNS
+ // connection endpoint.
+ writeDNSQuery(*dnsMsg) error
+}
+
+func (c *UDPConn) readDNSResponse() (*dnsMsg, error) {
+ b := make([]byte, 512) // see RFC 1035
+ n, err := c.Read(b)
+ if err != nil {
+ return nil, err
}
- out := new(dnsMsg)
- out.id = uint16(rand.Int()) ^ uint16(time.Now().UnixNano())
- out.question = []dnsQuestion{
- {name, qtype, dnsClassINET},
+ msg := &dnsMsg{}
+ if !msg.Unpack(b[:n]) {
+ return nil, errors.New("cannot unmarshal DNS message")
}
- out.recursion_desired = true
- msg, ok := out.Pack()
+ return msg, nil
+}
+
+func (c *UDPConn) writeDNSQuery(msg *dnsMsg) error {
+ b, ok := msg.Pack()
if !ok {
- return nil, &DNSError{Err: "internal error - cannot pack message", Name: name}
+ return errors.New("cannot marshal DNS message")
}
- if useTCP {
- mlen := uint16(len(msg))
- msg = append([]byte{byte(mlen >> 8), byte(mlen)}, msg...)
+ if _, err := c.Write(b); err != nil {
+ return err
}
- for attempt := 0; attempt < cfg.attempts; attempt++ {
- n, err := c.Write(msg)
+ return nil
+}
+
+func (c *TCPConn) readDNSResponse() (*dnsMsg, error) {
+ b := make([]byte, 1280) // 1280 is a reasonable initial size for IP over Ethernet, see RFC 4035
+ if _, err := io.ReadFull(c, b[:2]); err != nil {
+ return nil, err
+ }
+ l := int(b[0])<<8 | int(b[1])
+ if l > len(b) {
+ b = make([]byte, l)
+ }
+ n, err := io.ReadFull(c, b[:l])
+ if err != nil {
+ return nil, err
+ }
+ msg := &dnsMsg{}
+ if !msg.Unpack(b[:n]) {
+ return nil, errors.New("cannot unmarshal DNS message")
+ }
+ return msg, nil
+}
+
+func (c *TCPConn) writeDNSQuery(msg *dnsMsg) error {
+ b, ok := msg.Pack()
+ if !ok {
+ return errors.New("cannot marshal DNS message")
+ }
+ l := uint16(len(b))
+ b = append([]byte{byte(l >> 8), byte(l)}, b...)
+ if _, err := c.Write(b); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (d *Dialer) dialDNS(network, server string) (dnsConn, error) {
+ switch network {
+ case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
+ default:
+ return nil, UnknownNetworkError(network)
+ }
+ // Calling Dial here is scary -- we have to be sure not to
+ // dial a name that will require a DNS lookup, or Dial will
+ // call back here to translate it. The DNS config parser has
+ // already checked that all the cfg.servers[i] are IP
+ // addresses, which Dial will use without a DNS lookup.
+ c, err := d.Dial(network, server)
+ if err != nil {
+ return nil, err
+ }
+ switch network {
+ case "tcp", "tcp4", "tcp6":
+ return c.(*TCPConn), nil
+ case "udp", "udp4", "udp6":
+ return c.(*UDPConn), nil
+ }
+ panic("unreachable")
+}
+
+// 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}
+ out := dnsMsg{
+ dnsMsgHdr: dnsMsgHdr{
+ recursion_desired: true,
+ },
+ question: []dnsQuestion{
+ {name, qtype, dnsClassINET},
+ },
+ }
+ for _, network := range []string{"udp", "tcp"} {
+ c, err := d.dialDNS(network, server)
if err != nil {
return nil, err
}
-
- if cfg.timeout == 0 {
- c.SetReadDeadline(noDeadline)
- } else {
- c.SetReadDeadline(time.Now().Add(time.Duration(cfg.timeout) * time.Second))
+ defer c.Close()
+ if timeout > 0 {
+ c.SetDeadline(time.Now().Add(timeout))
}
- buf := make([]byte, 2000)
- if useTCP {
- n, err = io.ReadFull(c, buf[:2])
- if err != nil {
- if e, ok := err.(Error); ok && e.Timeout() {
- continue
- }
- }
- mlen := int(buf[0])<<8 | int(buf[1])
- if mlen > len(buf) {
- buf = make([]byte, mlen)
- }
- n, err = io.ReadFull(c, buf[:mlen])
- } else {
- n, err = c.Read(buf)
+ out.id = uint16(rand.Int()) ^ uint16(time.Now().UnixNano())
+ if err := c.writeDNSQuery(&out); err != nil {
+ return nil, err
}
+ in, err := c.readDNSResponse()
if err != nil {
- if e, ok := err.(Error); ok && e.Timeout() {
- continue
- }
return nil, err
}
- buf = buf[:n]
- in := new(dnsMsg)
- if !in.Unpack(buf) || in.id != out.id {
+ if in.id != out.id {
+ return nil, errors.New("DNS message ID mismatch")
+ }
+ if in.truncated { // see RFC 5966
continue
}
return in, nil
}
- var server string
- if a := c.RemoteAddr(); a != nil {
- server = a.String()
- }
- return nil, &DNSError{Err: "no answer from server", Name: name, Server: server, IsTimeout: true}
+ return nil, errors.New("no answer from DNS server")
}
// Do a lookup for a single name, which must be rooted
// (otherwise answer will not find the answers).
-func tryOneName(cfg *dnsConfig, name string, qtype uint16) (cname string, addrs []dnsRR, err error) {
+func tryOneName(cfg *dnsConfig, name string, qtype uint16) (string, []dnsRR, error) {
if len(cfg.servers) == 0 {
return "", nil, &DNSError{Err: "no DNS servers", Name: name}
}
- for i := 0; i < len(cfg.servers); i++ {
- // Calling Dial here is scary -- we have to be sure
- // not to dial a name that will require a DNS lookup,
- // or Dial will call back here to translate it.
- // The DNS config parser has already checked that
- // all the cfg.servers[i] are IP addresses, which
- // Dial will use without a DNS lookup.
- server := cfg.servers[i] + ":53"
- c, cerr := Dial("udp", server)
- if cerr != nil {
- err = cerr
- continue
- }
- msg, merr := exchange(cfg, c, name, qtype)
- c.Close()
- if merr != nil {
- err = merr
- continue
- }
- if msg.truncated { // see RFC 5966
- c, cerr = Dial("tcp", server)
- if cerr != nil {
- err = cerr
+ 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++ {
+ for _, server := range cfg.servers {
+ server = JoinHostPort(server, "53")
+ msg, err := exchange(server, name, qtype, timeout)
+ if err != nil {
+ lastErr = &DNSError{
+ Err: err.Error(),
+ Name: name,
+ Server: server,
+ }
+ if nerr, ok := err.(Error); ok && nerr.Timeout() {
+ lastErr.(*DNSError).IsTimeout = true
+ }
continue
}
- msg, merr = exchange(cfg, c, name, qtype)
- c.Close()
- if merr != nil {
- err = merr
- continue
+ cname, addrs, err := answer(name, server, msg, qtype)
+ if err == nil || err.(*DNSError).Err == noSuchHost {
+ return cname, addrs, err
}
- }
- cname, addrs, err = answer(name, server, msg, qtype)
- if err == nil || err.(*DNSError).Err == noSuchHost {
- break
+ lastErr = err
}
}
- return
+ return "", nil, lastErr
}
func convertRR_A(records []dnsRR) []IP {
@@ -240,13 +297,10 @@ func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err error)
}
// Can try as ordinary name.
cname, addrs, err = tryOneName(cfg.dnsConfig, rname, qtype)
- if err == nil {
+ if rooted || err == nil {
return
}
}
- if rooted {
- return
- }
// Otherwise, try suffixes.
for i := 0; i < len(cfg.dnsConfig.search); i++ {
@@ -260,15 +314,15 @@ func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err error)
}
}
- // Last ditch effort: try unsuffixed.
- rname := name
- if !rooted {
- rname += "."
- }
- cname, addrs, err = tryOneName(cfg.dnsConfig, rname, qtype)
- if err == nil {
- return
+ // Last ditch effort: try unsuffixed only if we haven't already,
+ // that is, name is not rooted and has less than ndots dots.
+ if count(name, '.') < cfg.dnsConfig.ndots {
+ cname, addrs, err = tryOneName(cfg.dnsConfig, name+".", qtype)
+ if err == nil {
+ return
+ }
}
+
if e, ok := err.(*DNSError); ok {
// Show original name passed to lookup, not suffixed one.
// In general we might have tried many suffixes; showing
@@ -320,31 +374,36 @@ func goLookupIP(name string) (addrs []IP, err error) {
return
}
}
- var records []dnsRR
- var cname string
- var err4, err6 error
- cname, records, err4 = lookup(name, dnsTypeA)
- addrs = convertRR_A(records)
- if cname != "" {
- name = cname
- }
- _, records, err6 = lookup(name, dnsTypeAAAA)
- if err4 != nil && err6 == nil {
- // Ignore A error because AAAA lookup succeeded.
- err4 = nil
+ type racer struct {
+ qtype uint16
+ rrs []dnsRR
+ error
}
- if err6 != nil && len(addrs) > 0 {
- // Ignore AAAA error because A lookup succeeded.
- err6 = nil
+ lane := make(chan racer, 1)
+ qtypes := [...]uint16{dnsTypeA, dnsTypeAAAA}
+ for _, qtype := range qtypes {
+ go func(qtype uint16) {
+ _, rrs, err := lookup(name, qtype)
+ lane <- racer{qtype, rrs, err}
+ }(qtype)
}
- if err4 != nil {
- return nil, err4
+ var lastErr error
+ for range qtypes {
+ racer := <-lane
+ if racer.error != nil {
+ lastErr = racer.error
+ continue
+ }
+ switch racer.qtype {
+ case dnsTypeA:
+ addrs = append(addrs, convertRR_A(racer.rrs)...)
+ case dnsTypeAAAA:
+ addrs = append(addrs, convertRR_AAAA(racer.rrs)...)
+ }
}
- if err6 != nil {
- return nil, err6
+ if len(addrs) == 0 && lastErr != nil {
+ return nil, lastErr
}
-
- addrs = append(addrs, convertRR_AAAA(records)...)
return addrs, nil
}
diff --git a/src/pkg/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index 2350142d6..1167c26b3 100644
--- a/src/pkg/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -16,19 +16,79 @@ import (
"time"
)
-func TestTCPLookup(t *testing.T) {
+var dnsTransportFallbackTests = []struct {
+ server string
+ name string
+ qtype uint16
+ timeout int
+ rcode int
+}{
+ // Querying "com." with qtype=255 usually makes an answer
+ // which requires more than 512 bytes.
+ {"8.8.8.8:53", "com.", dnsTypeALL, 2, dnsRcodeSuccess},
+ {"8.8.4.4:53", "com.", dnsTypeALL, 4, dnsRcodeSuccess},
+}
+
+func TestDNSTransportFallback(t *testing.T) {
if testing.Short() || !*testExternal {
t.Skip("skipping test to avoid external network")
}
- c, err := Dial("tcp", "8.8.8.8:53")
- if err != nil {
- t.Fatalf("Dial failed: %v", err)
+
+ for _, tt := range dnsTransportFallbackTests {
+ timeout := time.Duration(tt.timeout) * time.Second
+ msg, err := exchange(tt.server, tt.name, tt.qtype, timeout)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ switch msg.rcode {
+ case tt.rcode, dnsRcodeServerFailure:
+ default:
+ t.Errorf("got %v from %v; want %v", msg.rcode, tt.server, tt.rcode)
+ continue
+ }
}
- defer c.Close()
- cfg := &dnsConfig{timeout: 10, attempts: 3}
- _, err = exchange(cfg, c, "com.", dnsTypeALL)
- if err != nil {
- t.Fatalf("exchange failed: %v", err)
+}
+
+// See RFC 6761 for further information about the reserved, pseudo
+// domain names.
+var specialDomainNameTests = []struct {
+ name string
+ qtype uint16
+ rcode int
+}{
+ // Name resoltion APIs and libraries should not recongnize the
+ // followings as special.
+ {"1.0.168.192.in-addr.arpa.", dnsTypePTR, dnsRcodeNameError},
+ {"test.", dnsTypeALL, dnsRcodeNameError},
+ {"example.com.", dnsTypeALL, dnsRcodeSuccess},
+
+ // Name resoltion APIs and libraries should recongnize the
+ // followings as special and should not send any queries.
+ // Though, we test those names here for verifying nagative
+ // answers at DNS query-response interaction level.
+ {"localhost.", dnsTypeALL, dnsRcodeNameError},
+ {"invalid.", dnsTypeALL, dnsRcodeNameError},
+}
+
+func TestSpecialDomainName(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ server := "8.8.8.8:53"
+ for _, tt := range specialDomainNameTests {
+ msg, err := exchange(server, tt.name, tt.qtype, 0)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ switch msg.rcode {
+ case tt.rcode, dnsRcodeServerFailure:
+ default:
+ t.Errorf("got %v from %v; want %v", msg.rcode, server, tt.rcode)
+ continue
+ }
}
}
@@ -144,7 +204,7 @@ func TestReloadResolvConfChange(t *testing.T) {
if _, err := goLookupIP("golang.org"); err != nil {
t.Fatalf("goLookupIP(good) failed: %v", err)
}
- r.WantServers([]string{"[8.8.8.8]"})
+ r.WantServers([]string{"8.8.8.8"})
// Using a bad resolv.conf when we had a good one
// before should not update the config
@@ -155,5 +215,32 @@ func TestReloadResolvConfChange(t *testing.T) {
// A new good config should get picked up
r.SetConf("nameserver 8.8.4.4")
- r.WantServers([]string{"[8.8.4.4]"})
+ r.WantServers([]string{"8.8.4.4"})
+}
+
+func BenchmarkGoLookupIP(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ goLookupIP("www.example.com")
+ }
+}
+
+func BenchmarkGoLookupIPNoSuchHost(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ goLookupIP("some.nonexistent")
+ }
+}
+
+func BenchmarkGoLookupIPWithBrokenNameServer(b *testing.B) {
+ onceLoadConfig.Do(loadDefaultConfig)
+ if cfg.dnserr != nil || cfg.dnsConfig == nil {
+ b.Fatalf("loadConfig failed: %v", cfg.dnserr)
+ }
+ // This looks ugly but it's safe as long as benchmarks are run
+ // sequentially in package testing.
+ orig := cfg.dnsConfig
+ cfg.dnsConfig.servers = append([]string{"203.0.113.254"}, cfg.dnsConfig.servers...) // use TEST-NET-3 block, see RFC 5737
+ for i := 0; i < b.N; i++ {
+ goLookupIP("www.example.com")
+ }
+ cfg.dnsConfig = orig
}
diff --git a/src/pkg/net/dnsconfig_unix.go b/src/net/dnsconfig_unix.go
index db45716f1..66ab7c4dd 100644
--- a/src/pkg/net/dnsconfig_unix.go
+++ b/src/net/dnsconfig_unix.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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// Read system DNS config from /etc/resolv.conf
@@ -25,13 +25,12 @@ func dnsReadConfig(filename string) (*dnsConfig, error) {
if err != nil {
return nil, &DNSConfigError{err}
}
- conf := new(dnsConfig)
- conf.servers = make([]string, 0, 3) // small, but the standard limit
- conf.search = make([]string, 0)
- conf.ndots = 1
- conf.timeout = 5
- conf.attempts = 2
- conf.rotate = false
+ defer file.close()
+ conf := &dnsConfig{
+ ndots: 1,
+ timeout: 5,
+ attempts: 2,
+ }
for line, ok := file.readLine(); ok; line, ok = file.readLine() {
f := getFields(line)
if len(f) < 1 {
@@ -39,30 +38,20 @@ func dnsReadConfig(filename string) (*dnsConfig, error) {
}
switch f[0] {
case "nameserver": // add one name server
- a := conf.servers
- n := len(a)
- if len(f) > 1 && n < cap(a) {
+ if len(f) > 1 && len(conf.servers) < 3 { // small, but the standard limit
// One more check: make sure server name is
// just an IP address. Otherwise we need DNS
// to look it up.
- name := f[1]
- switch len(ParseIP(name)) {
- case 16:
- name = "[" + name + "]"
- fallthrough
- case 4:
- a = a[0 : n+1]
- a[n] = name
- conf.servers = a
+ if parseIPv4(f[1]) != nil {
+ conf.servers = append(conf.servers, f[1])
+ } else if ip, _ := parseIPv6(f[1], true); ip != nil {
+ conf.servers = append(conf.servers, f[1])
}
}
case "domain": // set search path to just this domain
if len(f) > 1 {
- conf.search = make([]string, 1)
- conf.search[0] = f[1]
- } else {
- conf.search = make([]string, 0)
+ conf.search = []string{f[1]}
}
case "search": // set search path to given servers
@@ -99,8 +88,6 @@ func dnsReadConfig(filename string) (*dnsConfig, error) {
}
}
}
- file.close()
-
return conf, nil
}
diff --git a/src/net/dnsconfig_unix_test.go b/src/net/dnsconfig_unix_test.go
new file mode 100644
index 000000000..94fb0c32e
--- /dev/null
+++ b/src/net/dnsconfig_unix_test.go
@@ -0,0 +1,69 @@
+// 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 darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package net
+
+import (
+ "reflect"
+ "testing"
+)
+
+var dnsReadConfigTests = []struct {
+ name string
+ conf dnsConfig
+}{
+ {
+ name: "testdata/resolv.conf",
+ conf: dnsConfig{
+ servers: []string{"8.8.8.8", "2001:4860:4860::8888", "fe80::1%lo0"},
+ search: []string{"localdomain"},
+ ndots: 5,
+ timeout: 10,
+ attempts: 3,
+ rotate: true,
+ },
+ },
+ {
+ name: "testdata/domain-resolv.conf",
+ conf: dnsConfig{
+ servers: []string{"8.8.8.8"},
+ search: []string{"localdomain"},
+ ndots: 1,
+ timeout: 5,
+ attempts: 2,
+ },
+ },
+ {
+ name: "testdata/search-resolv.conf",
+ conf: dnsConfig{
+ servers: []string{"8.8.8.8"},
+ search: []string{"test", "invalid"},
+ ndots: 1,
+ timeout: 5,
+ attempts: 2,
+ },
+ },
+ {
+ name: "testdata/empty-resolv.conf",
+ conf: dnsConfig{
+ ndots: 1,
+ timeout: 5,
+ attempts: 2,
+ },
+ },
+}
+
+func TestDNSReadConfig(t *testing.T) {
+ for _, tt := range dnsReadConfigTests {
+ conf, err := dnsReadConfig(tt.name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(conf, &tt.conf) {
+ t.Errorf("got %v; want %v", conf, &tt.conf)
+ }
+ }
+}
diff --git a/src/pkg/net/dnsmsg.go b/src/net/dnsmsg.go
index 161afb2a5..161afb2a5 100644
--- a/src/pkg/net/dnsmsg.go
+++ b/src/net/dnsmsg.go
diff --git a/src/pkg/net/dnsmsg_test.go b/src/net/dnsmsg_test.go
index c39dbdb04..c39dbdb04 100644
--- a/src/pkg/net/dnsmsg_test.go
+++ b/src/net/dnsmsg_test.go
diff --git a/src/pkg/net/dnsname_test.go b/src/net/dnsname_test.go
index 57dd25fe4..57dd25fe4 100644
--- a/src/pkg/net/dnsname_test.go
+++ b/src/net/dnsname_test.go
diff --git a/src/pkg/net/example_test.go b/src/net/example_test.go
index 6f2f9074c..6f2f9074c 100644
--- a/src/pkg/net/example_test.go
+++ b/src/net/example_test.go
diff --git a/src/pkg/net/fd_mutex.go b/src/net/fd_mutex.go
index 6d5509d7f..6d5509d7f 100644
--- a/src/pkg/net/fd_mutex.go
+++ b/src/net/fd_mutex.go
diff --git a/src/pkg/net/fd_mutex_test.go b/src/net/fd_mutex_test.go
index c34ec59b9..c34ec59b9 100644
--- a/src/pkg/net/fd_mutex_test.go
+++ b/src/net/fd_mutex_test.go
diff --git a/src/pkg/net/fd_plan9.go b/src/net/fd_plan9.go
index 5fe8effc2..5fe8effc2 100644
--- a/src/pkg/net/fd_plan9.go
+++ b/src/net/fd_plan9.go
diff --git a/src/pkg/net/fd_poll_nacl.go b/src/net/fd_poll_nacl.go
index a3701f876..a3701f876 100644
--- a/src/pkg/net/fd_poll_nacl.go
+++ b/src/net/fd_poll_nacl.go
diff --git a/src/pkg/net/fd_poll_runtime.go b/src/net/fd_poll_runtime.go
index 2bddc836c..2bddc836c 100644
--- a/src/pkg/net/fd_poll_runtime.go
+++ b/src/net/fd_poll_runtime.go
diff --git a/src/pkg/net/fd_unix.go b/src/net/fd_unix.go
index e22861abb..7fa43f6ab 100644
--- a/src/pkg/net/fd_unix.go
+++ b/src/net/fd_unix.go
@@ -401,7 +401,7 @@ func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
return
}
-func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
+func (fd *netFD) accept() (netfd *netFD, err error) {
if err := fd.readLock(); err != nil {
return nil, err
}
@@ -438,7 +438,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err e
return nil, err
}
lsa, _ := syscall.Getsockname(netfd.sysfd)
- netfd.setAddr(toAddr(lsa), toAddr(rsa))
+ netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
return netfd, nil
}
diff --git a/src/pkg/net/fd_unix_test.go b/src/net/fd_unix_test.go
index fe8e8ff6a..fe8e8ff6a 100644
--- a/src/pkg/net/fd_unix_test.go
+++ b/src/net/fd_unix_test.go
diff --git a/src/pkg/net/fd_windows.go b/src/net/fd_windows.go
index d1129dccc..f3a534a1d 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/net/fd_windows.go
@@ -294,6 +294,18 @@ func (fd *netFD) init() error {
fd.skipSyncNotif = true
}
}
+ // Disable SIO_UDP_CONNRESET behavior.
+ // http://support.microsoft.com/kb/263823
+ switch fd.net {
+ case "udp", "udp4", "udp6":
+ ret := uint32(0)
+ flag := uint32(0)
+ size := uint32(unsafe.Sizeof(flag))
+ err := syscall.WSAIoctl(fd.sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
+ if err != nil {
+ return os.NewSyscallError("WSAIoctl", err)
+ }
+ }
fd.rop.mode = 'r'
fd.wop.mode = 'w'
fd.rop.fd = fd
@@ -520,7 +532,7 @@ func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
})
}
-func (fd *netFD) acceptOne(toAddr func(syscall.Sockaddr) Addr, rawsa []syscall.RawSockaddrAny, o *operation) (*netFD, error) {
+func (fd *netFD) acceptOne(rawsa []syscall.RawSockaddrAny, o *operation) (*netFD, error) {
// Get new socket.
s, err := sysSocket(fd.family, fd.sotype, 0)
if err != nil {
@@ -559,7 +571,7 @@ func (fd *netFD) acceptOne(toAddr func(syscall.Sockaddr) Addr, rawsa []syscall.R
return netfd, nil
}
-func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
+func (fd *netFD) accept() (*netFD, error) {
if err := fd.readLock(); err != nil {
return nil, err
}
@@ -570,7 +582,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
var err error
var rawsa [2]syscall.RawSockaddrAny
for {
- netfd, err = fd.acceptOne(toAddr, rawsa[:], o)
+ netfd, err = fd.acceptOne(rawsa[:], o)
if err == nil {
break
}
@@ -603,7 +615,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
lsa, _ := lrsa.Sockaddr()
rsa, _ := rrsa.Sockaddr()
- netfd.setAddr(toAddr(lsa), toAddr(rsa))
+ netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
return netfd, nil
}
diff --git a/src/pkg/net/file_plan9.go b/src/net/file_plan9.go
index 068f0881d..068f0881d 100644
--- a/src/pkg/net/file_plan9.go
+++ b/src/net/file_plan9.go
diff --git a/src/net/file_stub.go b/src/net/file_stub.go
new file mode 100644
index 000000000..4281072ef
--- /dev/null
+++ b/src/net/file_stub.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.
+
+// +build nacl
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+// FileConn returns a copy of the network connection corresponding to
+// the open file f. It is the caller's responsibility to close f when
+// finished. Closing c does not affect f, and closing f does not
+// affect c.
+func FileConn(f *os.File) (c Conn, err error) {
+ return nil, syscall.ENOPROTOOPT
+
+}
+
+// FileListener returns a copy of the network listener corresponding
+// to the open file f. It is the caller's responsibility to close l
+// when finished. Closing l does not affect f, and closing f does not
+// affect l.
+func FileListener(f *os.File) (l Listener, err error) {
+ return nil, syscall.ENOPROTOOPT
+
+}
+
+// FilePacketConn returns a copy of the packet network connection
+// corresponding to the open file f. It is the caller's
+// responsibility to close f when finished. Closing c does not affect
+// f, and closing f does not affect c.
+func FilePacketConn(f *os.File) (c PacketConn, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
diff --git a/src/pkg/net/file_test.go b/src/net/file_test.go
index d81bca782..6fab06a9c 100644
--- a/src/pkg/net/file_test.go
+++ b/src/net/file_test.go
@@ -89,7 +89,7 @@ var fileListenerTests = []struct {
func TestFileListener(t *testing.T) {
switch runtime.GOOS {
- case "windows":
+ case "nacl", "windows":
t.Skipf("skipping test on %q", runtime.GOOS)
}
diff --git a/src/pkg/net/file_unix.go b/src/net/file_unix.go
index 07b3ecf62..214a4196c 100644
--- a/src/pkg/net/file_unix.go
+++ b/src/net/file_unix.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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
package net
diff --git a/src/pkg/net/file_windows.go b/src/net/file_windows.go
index ca2b9b226..ca2b9b226 100644
--- a/src/pkg/net/file_windows.go
+++ b/src/net/file_windows.go
diff --git a/src/pkg/net/hosts.go b/src/net/hosts.go
index e6674ba34..9400503e4 100644
--- a/src/pkg/net/hosts.go
+++ b/src/net/hosts.go
@@ -51,7 +51,7 @@ func readHosts() {
}
}
// Update the data cache.
- hosts.expire = time.Now().Add(cacheMaxAge)
+ hosts.expire = now.Add(cacheMaxAge)
hosts.path = hp
hosts.byName = hs
hosts.byAddr = is
diff --git a/src/pkg/net/hosts_test.go b/src/net/hosts_test.go
index 2fe358e07..2fe358e07 100644
--- a/src/pkg/net/hosts_test.go
+++ b/src/net/hosts_test.go
diff --git a/src/pkg/net/http/cgi/child.go b/src/net/http/cgi/child.go
index 45fc2e57c..45fc2e57c 100644
--- a/src/pkg/net/http/cgi/child.go
+++ b/src/net/http/cgi/child.go
diff --git a/src/pkg/net/http/cgi/child_test.go b/src/net/http/cgi/child_test.go
index 075d8411b..075d8411b 100644
--- a/src/pkg/net/http/cgi/child_test.go
+++ b/src/net/http/cgi/child_test.go
diff --git a/src/pkg/net/http/cgi/host.go b/src/net/http/cgi/host.go
index ec95a972c..ec95a972c 100644
--- a/src/pkg/net/http/cgi/host.go
+++ b/src/net/http/cgi/host.go
diff --git a/src/pkg/net/http/cgi/host_test.go b/src/net/http/cgi/host_test.go
index 8c16e6897..8c16e6897 100644
--- a/src/pkg/net/http/cgi/host_test.go
+++ b/src/net/http/cgi/host_test.go
diff --git a/src/pkg/net/http/cgi/matryoshka_test.go b/src/net/http/cgi/matryoshka_test.go
index 18c4803e7..18c4803e7 100644
--- a/src/pkg/net/http/cgi/matryoshka_test.go
+++ b/src/net/http/cgi/matryoshka_test.go
diff --git a/src/pkg/net/http/cgi/plan9_test.go b/src/net/http/cgi/plan9_test.go
index c8235831b..c8235831b 100644
--- a/src/pkg/net/http/cgi/plan9_test.go
+++ b/src/net/http/cgi/plan9_test.go
diff --git a/src/pkg/net/http/cgi/posix_test.go b/src/net/http/cgi/posix_test.go
index 5ff9e7d5e..5ff9e7d5e 100644
--- a/src/pkg/net/http/cgi/posix_test.go
+++ b/src/net/http/cgi/posix_test.go
diff --git a/src/pkg/net/http/cgi/testdata/test.cgi b/src/net/http/cgi/testdata/test.cgi
index 3214df6f0..3214df6f0 100755
--- a/src/pkg/net/http/cgi/testdata/test.cgi
+++ b/src/net/http/cgi/testdata/test.cgi
diff --git a/src/pkg/net/http/client.go b/src/net/http/client.go
index a5a3abe61..ce884d1f0 100644
--- a/src/pkg/net/http/client.go
+++ b/src/net/http/client.go
@@ -101,6 +101,30 @@ type RoundTripper interface {
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
+// refererForURL returns a referer without any authentication info or
+// an empty string if lastReq scheme is https and newReq scheme is http.
+func refererForURL(lastReq, newReq *url.URL) string {
+ // https://tools.ietf.org/html/rfc7231#section-5.5.2
+ // "Clients SHOULD NOT include a Referer header field in a
+ // (non-secure) HTTP request if the referring page was
+ // transferred with a secure protocol."
+ if lastReq.Scheme == "https" && newReq.Scheme == "http" {
+ return ""
+ }
+ referer := lastReq.String()
+ if lastReq.User != nil {
+ // This is not very efficient, but is the best we can
+ // do without:
+ // - introducing a new method on URL
+ // - creating a race condition
+ // - copying the URL struct manually, which would cause
+ // maintenance problems down the line
+ auth := lastReq.User.String() + "@"
+ referer = strings.Replace(referer, auth, "", 1)
+ }
+ return referer
+}
+
// Used in Send to implement io.ReadCloser by bundling together the
// bufio.Reader through which we read the response, and the underlying
// network connection.
@@ -324,8 +348,8 @@ func (c *Client) doFollowingRedirects(ireq *Request, shouldRedirect func(int) bo
if len(via) > 0 {
// Add the Referer header.
lastReq := via[len(via)-1]
- if lastReq.URL.Scheme != "https" {
- nreq.Header.Set("Referer", lastReq.URL.String())
+ if ref := refererForURL(lastReq.URL, nreq.URL); ref != "" {
+ nreq.Header.Set("Referer", ref)
}
err = redirectChecker(nreq, via)
diff --git a/src/pkg/net/http/client_test.go b/src/net/http/client_test.go
index 6392c1baf..56b6563c4 100644
--- a/src/pkg/net/http/client_test.go
+++ b/src/net/http/client_test.go
@@ -1036,3 +1036,40 @@ func TestClientTrailers(t *testing.T) {
t.Errorf("Response trailers = %#v; want %#v", res.Trailer, want)
}
}
+
+func TestReferer(t *testing.T) {
+ tests := []struct {
+ lastReq, newReq string // from -> to URLs
+ want string
+ }{
+ // don't send user:
+ {"http://gopher@test.com", "http://link.com", "http://test.com"},
+ {"https://gopher@test.com", "https://link.com", "https://test.com"},
+
+ // don't send a user and password:
+ {"http://gopher:go@test.com", "http://link.com", "http://test.com"},
+ {"https://gopher:go@test.com", "https://link.com", "https://test.com"},
+
+ // nothing to do:
+ {"http://test.com", "http://link.com", "http://test.com"},
+ {"https://test.com", "https://link.com", "https://test.com"},
+
+ // https to http doesn't send a referer:
+ {"https://test.com", "http://link.com", ""},
+ {"https://gopher:go@test.com", "http://link.com", ""},
+ }
+ for _, tt := range tests {
+ l, err := url.Parse(tt.lastReq)
+ if err != nil {
+ t.Fatal(err)
+ }
+ n, err := url.Parse(tt.newReq)
+ if err != nil {
+ t.Fatal(err)
+ }
+ r := ExportRefererForURL(l, n)
+ if r != tt.want {
+ t.Errorf("refererForURL(%q, %q) = %q; want %q", tt.lastReq, tt.newReq, r, tt.want)
+ }
+ }
+}
diff --git a/src/pkg/net/http/cookie.go b/src/net/http/cookie.go
index dc60ba87f..a0d0fdbbd 100644
--- a/src/pkg/net/http/cookie.go
+++ b/src/net/http/cookie.go
@@ -56,7 +56,7 @@ func readSetCookies(h Header) []*Cookie {
if !isCookieNameValid(name) {
continue
}
- value, success := parseCookieValue(value)
+ value, success := parseCookieValue(value, true)
if !success {
continue
}
@@ -76,7 +76,7 @@ func readSetCookies(h Header) []*Cookie {
attr, val = attr[:j], attr[j+1:]
}
lowerAttr := strings.ToLower(attr)
- val, success = parseCookieValue(val)
+ val, success = parseCookieValue(val, false)
if !success {
c.Unparsed = append(c.Unparsed, parts[i])
continue
@@ -205,7 +205,7 @@ func readCookies(h Header, filter string) []*Cookie {
if filter != "" && filter != name {
continue
}
- val, success := parseCookieValue(val)
+ val, success := parseCookieValue(val, true)
if !success {
continue
}
@@ -345,9 +345,9 @@ func sanitizeOrWarn(fieldName string, valid func(byte) bool, v string) string {
return string(buf)
}
-func parseCookieValue(raw string) (string, bool) {
+func parseCookieValue(raw string, allowDoubleQuote bool) (string, bool) {
// Strip the quotes, if present.
- if len(raw) > 1 && raw[0] == '"' && raw[len(raw)-1] == '"' {
+ if allowDoubleQuote && len(raw) > 1 && raw[0] == '"' && raw[len(raw)-1] == '"' {
raw = raw[1 : len(raw)-1]
}
for i := 0; i < len(raw); i++ {
diff --git a/src/pkg/net/http/cookie_test.go b/src/net/http/cookie_test.go
index f78f37299..98dc2fade 100644
--- a/src/pkg/net/http/cookie_test.go
+++ b/src/net/http/cookie_test.go
@@ -313,6 +313,14 @@ var readCookiesTests = []struct {
{Name: "c2", Value: "v2"},
},
},
+ {
+ Header{"Cookie": {`Cookie-1="v$1"; c2="v2"`}},
+ "",
+ []*Cookie{
+ {Name: "Cookie-1", Value: "v$1"},
+ {Name: "c2", Value: "v2"},
+ },
+ },
}
func TestReadCookies(t *testing.T) {
@@ -327,6 +335,30 @@ func TestReadCookies(t *testing.T) {
}
}
+func TestSetCookieDoubleQuotes(t *testing.T) {
+ res := &Response{Header: Header{}}
+ res.Header.Add("Set-Cookie", `quoted0=none; max-age=30`)
+ res.Header.Add("Set-Cookie", `quoted1="cookieValue"; max-age=31`)
+ res.Header.Add("Set-Cookie", `quoted2=cookieAV; max-age="32"`)
+ res.Header.Add("Set-Cookie", `quoted3="both"; max-age="33"`)
+ got := res.Cookies()
+ want := []*Cookie{
+ {Name: "quoted0", Value: "none", MaxAge: 30},
+ {Name: "quoted1", Value: "cookieValue", MaxAge: 31},
+ {Name: "quoted2", Value: "cookieAV"},
+ {Name: "quoted3", Value: "both"},
+ }
+ if len(got) != len(want) {
+ t.Fatal("got %d cookies, want %d", len(got), len(want))
+ }
+ for i, w := range want {
+ g := got[i]
+ if g.Name != w.Name || g.Value != w.Value || g.MaxAge != w.MaxAge {
+ t.Errorf("cookie #%d:\ngot %v\nwant %v", i, g, w)
+ }
+ }
+}
+
func TestCookieSanitizeValue(t *testing.T) {
defer log.SetOutput(os.Stderr)
var logbuf bytes.Buffer
diff --git a/src/pkg/net/http/cookiejar/jar.go b/src/net/http/cookiejar/jar.go
index 389ab58e4..0e0fac928 100644
--- a/src/pkg/net/http/cookiejar/jar.go
+++ b/src/net/http/cookiejar/jar.go
@@ -30,7 +30,7 @@ import (
// set a cookie for bar.com.
//
// A public suffix list implementation is in the package
-// code.google.com/p/go.net/publicsuffix.
+// golang.org/x/net/publicsuffix.
type PublicSuffixList interface {
// PublicSuffix returns the public suffix of domain.
//
diff --git a/src/pkg/net/http/cookiejar/jar_test.go b/src/net/http/cookiejar/jar_test.go
index 3aa601586..3aa601586 100644
--- a/src/pkg/net/http/cookiejar/jar_test.go
+++ b/src/net/http/cookiejar/jar_test.go
diff --git a/src/pkg/net/http/cookiejar/punycode.go b/src/net/http/cookiejar/punycode.go
index ea7ceb5ef..ea7ceb5ef 100644
--- a/src/pkg/net/http/cookiejar/punycode.go
+++ b/src/net/http/cookiejar/punycode.go
diff --git a/src/pkg/net/http/cookiejar/punycode_test.go b/src/net/http/cookiejar/punycode_test.go
index 0301de14e..0301de14e 100644
--- a/src/pkg/net/http/cookiejar/punycode_test.go
+++ b/src/net/http/cookiejar/punycode_test.go
diff --git a/src/pkg/net/http/doc.go b/src/net/http/doc.go
index b1216e8da..b1216e8da 100644
--- a/src/pkg/net/http/doc.go
+++ b/src/net/http/doc.go
diff --git a/src/pkg/net/http/example_test.go b/src/net/http/example_test.go
index 88b97d9e3..88b97d9e3 100644
--- a/src/pkg/net/http/example_test.go
+++ b/src/net/http/example_test.go
diff --git a/src/pkg/net/http/export_test.go b/src/net/http/export_test.go
index 960563b24..87b6c0773 100644
--- a/src/pkg/net/http/export_test.go
+++ b/src/net/http/export_test.go
@@ -9,6 +9,7 @@ package http
import (
"net"
+ "net/url"
"time"
)
@@ -57,6 +58,26 @@ func (t *Transport) IdleConnChMapSizeForTesting() int {
return len(t.idleConnCh)
}
+func (t *Transport) IsIdleForTesting() bool {
+ t.idleMu.Lock()
+ defer t.idleMu.Unlock()
+ return t.wantIdle
+}
+
+func (t *Transport) RequestIdleConnChForTesting() {
+ t.getIdleConnCh(connectMethod{nil, "http", "example.com"})
+}
+
+func (t *Transport) PutIdleTestConn() bool {
+ c, _ := net.Pipe()
+ return t.putIdleConn(&persistConn{
+ t: t,
+ conn: c, // dummy
+ closech: make(chan struct{}), // so it can be closed
+ cacheKey: connectMethodKey{"", "http", "example.com"},
+ })
+}
+
func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler {
f := func() <-chan time.Time {
return ch
@@ -66,7 +87,22 @@ func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler {
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
+}
+
+var ExportServerNewConn = (*Server).newConn
+
+var ExportCloseWriteAndWait = (*conn).closeWriteAndWait
diff --git a/src/pkg/net/http/fcgi/child.go b/src/net/http/fcgi/child.go
index a3beaa33a..a3beaa33a 100644
--- a/src/pkg/net/http/fcgi/child.go
+++ b/src/net/http/fcgi/child.go
diff --git a/src/pkg/net/http/fcgi/fcgi.go b/src/net/http/fcgi/fcgi.go
index 06bba0488..06bba0488 100644
--- a/src/pkg/net/http/fcgi/fcgi.go
+++ b/src/net/http/fcgi/fcgi.go
diff --git a/src/pkg/net/http/fcgi/fcgi_test.go b/src/net/http/fcgi/fcgi_test.go
index 6c7e1a9ce..6c7e1a9ce 100644
--- a/src/pkg/net/http/fcgi/fcgi_test.go
+++ b/src/net/http/fcgi/fcgi_test.go
diff --git a/src/pkg/net/http/filetransport.go b/src/net/http/filetransport.go
index 821787e0c..821787e0c 100644
--- a/src/pkg/net/http/filetransport.go
+++ b/src/net/http/filetransport.go
diff --git a/src/pkg/net/http/filetransport_test.go b/src/net/http/filetransport_test.go
index 6f1a537e2..6f1a537e2 100644
--- a/src/pkg/net/http/filetransport_test.go
+++ b/src/net/http/filetransport_test.go
diff --git a/src/pkg/net/http/fs.go b/src/net/http/fs.go
index 8576cf844..e322f710a 100644
--- a/src/pkg/net/http/fs.go
+++ b/src/net/http/fs.go
@@ -22,8 +22,12 @@ import (
"time"
)
-// A Dir implements http.FileSystem using the native file
-// system restricted to a specific directory tree.
+// A Dir implements FileSystem using the native file system restricted to a
+// specific directory tree.
+//
+// While the FileSystem.Open method takes '/'-separated paths, a Dir's string
+// value is a filename on the native file system, not a URL, so it is separated
+// by filepath.Separator, which isn't necessarily '/'.
//
// An empty Dir is treated as ".".
type Dir string
@@ -139,7 +143,7 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
if checkLastModified(w, r, modtime) {
return
}
- rangeReq, done := checkETag(w, r)
+ rangeReq, done := checkETag(w, r, modtime)
if done {
return
}
@@ -212,12 +216,6 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
code = StatusPartialContent
w.Header().Set("Content-Range", ra.contentRange(size))
case len(ranges) > 1:
- for _, ra := range ranges {
- if ra.start > size {
- Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
- return
- }
- }
sendSize = rangesMIMESize(ranges, ctype, size)
code = StatusPartialContent
@@ -281,11 +279,14 @@ func checkLastModified(w ResponseWriter, r *Request, modtime time.Time) bool {
}
// checkETag implements If-None-Match and If-Range checks.
-// The ETag must have been previously set in the ResponseWriter's headers.
+//
+// The ETag or modtime must have been previously set in the
+// ResponseWriter's headers. The modtime is only compared at second
+// granularity and may be the zero value to mean unknown.
//
// The return value is the effective request "Range" header to use and
// whether this request is now considered done.
-func checkETag(w ResponseWriter, r *Request) (rangeReq string, done bool) {
+func checkETag(w ResponseWriter, r *Request, modtime time.Time) (rangeReq string, done bool) {
etag := w.Header().get("Etag")
rangeReq = r.Header.get("Range")
@@ -296,11 +297,17 @@ func checkETag(w ResponseWriter, r *Request) (rangeReq string, done bool) {
// We only support ETag versions.
// The caller must have set the ETag on the response already.
if ir := r.Header.get("If-Range"); ir != "" && ir != etag {
- // TODO(bradfitz): handle If-Range requests with Last-Modified
- // times instead of ETags? I'd rather not, at least for
- // now. That seems like a bug/compromise in the RFC 2616, and
- // I've never heard of anybody caring about that (yet).
- rangeReq = ""
+ // The If-Range value is typically the ETag value, but it may also be
+ // the modtime date. See golang.org/issue/8367.
+ timeMatches := false
+ if !modtime.IsZero() {
+ if t, err := ParseTime(ir); err == nil && t.Unix() == modtime.Unix() {
+ timeMatches = true
+ }
+ }
+ if !timeMatches {
+ rangeReq = ""
+ }
}
if inm := r.Header.get("If-None-Match"); inm != "" {
@@ -378,7 +385,7 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
// use contents of index.html for directory, if present
if d.IsDir() {
- index := name + indexPage
+ index := strings.TrimSuffix(name, "/") + indexPage
ff, err := fs.Open(index)
if err == nil {
defer ff.Close()
@@ -400,7 +407,7 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
return
}
- // serverContent will check modification time
+ // serveContent will check modification time
sizeFunc := func() (int64, error) { return d.Size(), nil }
serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, f)
}
diff --git a/src/pkg/net/http/fs_test.go b/src/net/http/fs_test.go
index f968565f9..8770d9b41 100644
--- a/src/pkg/net/http/fs_test.go
+++ b/src/net/http/fs_test.go
@@ -721,6 +721,28 @@ func TestServeContent(t *testing.T) {
wantStatus: 200,
wantContentType: "text/css; charset=utf-8",
},
+ "range_with_modtime": {
+ file: "testdata/style.css",
+ modtime: time.Date(2014, 6, 25, 17, 12, 18, 0 /* nanos */, time.UTC),
+ reqHeader: map[string]string{
+ "Range": "bytes=0-4",
+ "If-Range": "Wed, 25 Jun 2014 17:12:18 GMT",
+ },
+ wantStatus: StatusPartialContent,
+ wantContentType: "text/css; charset=utf-8",
+ wantLastMod: "Wed, 25 Jun 2014 17:12:18 GMT",
+ },
+ "range_with_modtime_nanos": {
+ file: "testdata/style.css",
+ modtime: time.Date(2014, 6, 25, 17, 12, 18, 123 /* nanos */, time.UTC),
+ reqHeader: map[string]string{
+ "Range": "bytes=0-4",
+ "If-Range": "Wed, 25 Jun 2014 17:12:18 GMT",
+ },
+ wantStatus: StatusPartialContent,
+ wantContentType: "text/css; charset=utf-8",
+ wantLastMod: "Wed, 25 Jun 2014 17:12:18 GMT",
+ },
}
for testName, tt := range tests {
var content io.ReadSeeker
@@ -855,4 +877,41 @@ func TestLinuxSendfileChild(*testing.T) {
}
}
+func TestFileServerCleanPath(t *testing.T) {
+ tests := []struct {
+ path string
+ wantCode int
+ wantOpen []string
+ }{
+ {"/", 200, []string{"/", "/index.html"}},
+ {"/dir", 301, []string{"/dir"}},
+ {"/dir/", 200, []string{"/dir", "/dir/index.html"}},
+ }
+ for _, tt := range tests {
+ var log []string
+ rr := httptest.NewRecorder()
+ req, _ := NewRequest("GET", "http://foo.localhost"+tt.path, nil)
+ FileServer(fileServerCleanPathDir{&log}).ServeHTTP(rr, req)
+ if !reflect.DeepEqual(log, tt.wantOpen) {
+ t.Logf("For %s: Opens = %q; want %q", tt.path, log, tt.wantOpen)
+ }
+ if rr.Code != tt.wantCode {
+ t.Logf("For %s: Response code = %d; want %d", tt.path, rr.Code, tt.wantCode)
+ }
+ }
+}
+
+type fileServerCleanPathDir struct {
+ log *[]string
+}
+
+func (d fileServerCleanPathDir) Open(path string) (File, error) {
+ *(d.log) = append(*(d.log), path)
+ if path == "/" || path == "/dir" || path == "/dir/" {
+ // Just return back something that's a directory.
+ return Dir(".").Open(".")
+ }
+ return nil, os.ErrNotExist
+}
+
type panicOnSeek struct{ io.ReadSeeker }
diff --git a/src/pkg/net/http/header.go b/src/net/http/header.go
index 153b94370..153b94370 100644
--- a/src/pkg/net/http/header.go
+++ b/src/net/http/header.go
diff --git a/src/pkg/net/http/header_test.go b/src/net/http/header_test.go
index 9dcd591fa..9dcd591fa 100644
--- a/src/pkg/net/http/header_test.go
+++ b/src/net/http/header_test.go
diff --git a/src/pkg/net/http/httptest/example_test.go b/src/net/http/httptest/example_test.go
index 42a0ec953..42a0ec953 100644
--- a/src/pkg/net/http/httptest/example_test.go
+++ b/src/net/http/httptest/example_test.go
diff --git a/src/pkg/net/http/httptest/recorder.go b/src/net/http/httptest/recorder.go
index 5451f5423..5451f5423 100644
--- a/src/pkg/net/http/httptest/recorder.go
+++ b/src/net/http/httptest/recorder.go
diff --git a/src/pkg/net/http/httptest/recorder_test.go b/src/net/http/httptest/recorder_test.go
index 2b563260c..2b563260c 100644
--- a/src/pkg/net/http/httptest/recorder_test.go
+++ b/src/net/http/httptest/recorder_test.go
diff --git a/src/pkg/net/http/httptest/server.go b/src/net/http/httptest/server.go
index 7f265552f..789e7bf41 100644
--- a/src/pkg/net/http/httptest/server.go
+++ b/src/net/http/httptest/server.go
@@ -203,7 +203,7 @@ func (h *waitGroupHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// 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/pkg/crypto/tls:
+// generated from src/crypto/tls:
// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
diff --git a/src/pkg/net/http/httptest/server_test.go b/src/net/http/httptest/server_test.go
index 4fc4c7020..500a9f0b8 100644
--- a/src/pkg/net/http/httptest/server_test.go
+++ b/src/net/http/httptest/server_test.go
@@ -8,7 +8,6 @@ import (
"io/ioutil"
"net/http"
"testing"
- "time"
)
func TestServer(t *testing.T) {
@@ -28,26 +27,3 @@ func TestServer(t *testing.T) {
t.Errorf("got %q, want hello", string(got))
}
}
-
-func TestIssue7264(t *testing.T) {
- t.Skip("broken test - removed at tip")
- for i := 0; i < 1000; i++ {
- func() {
- inHandler := make(chan bool, 1)
- ts := NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- inHandler <- true
- }))
- defer ts.Close()
- tr := &http.Transport{
- ResponseHeaderTimeout: time.Nanosecond,
- }
- defer tr.CloseIdleConnections()
- c := &http.Client{Transport: tr}
- res, err := c.Get(ts.URL)
- <-inHandler
- if err == nil {
- res.Body.Close()
- }
- }()
- }
-}
diff --git a/src/pkg/net/http/httputil/dump.go b/src/net/http/httputil/dump.go
index 2a7a413d0..ac8f103f9 100644
--- a/src/pkg/net/http/httputil/dump.go
+++ b/src/net/http/httputil/dump.go
@@ -95,19 +95,27 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
// with a dummy response.
var buf bytes.Buffer // records the output
pr, pw := io.Pipe()
+ defer pr.Close()
+ defer pw.Close()
dr := &delegateReader{c: make(chan io.Reader)}
// Wait for the request before replying with a dummy response:
go func() {
- http.ReadRequest(bufio.NewReader(pr))
+ req, err := http.ReadRequest(bufio.NewReader(pr))
+ if err == nil {
+ // Ensure all the body is read; otherwise
+ // we'll get a partial dump.
+ io.Copy(ioutil.Discard, req.Body)
+ req.Body.Close()
+ }
dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\n\r\n")
}()
t := &http.Transport{
+ DisableKeepAlives: true,
Dial: func(net, addr string) (net.Conn, error) {
return &dumpConn{io.MultiWriter(&buf, pw), dr}, nil
},
}
- defer t.CloseIdleConnections()
_, err := t.RoundTrip(reqSend)
diff --git a/src/pkg/net/http/httputil/dump_test.go b/src/net/http/httputil/dump_test.go
index e1ffb3935..024ee5a86 100644
--- a/src/pkg/net/http/httputil/dump_test.go
+++ b/src/net/http/httputil/dump_test.go
@@ -111,6 +111,30 @@ var dumpTests = []dumpTest{
NoBody: true,
},
+
+ // Request with Body > 8196 (default buffer size)
+ {
+ Req: http.Request{
+ Method: "POST",
+ URL: &url.URL{
+ Scheme: "http",
+ Host: "post.tld",
+ Path: "/",
+ },
+ ContentLength: 8193,
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ },
+
+ Body: bytes.Repeat([]byte("a"), 8193),
+
+ WantDumpOut: "POST / HTTP/1.1\r\n" +
+ "Host: post.tld\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
+ "Content-Length: 8193\r\n" +
+ "Accept-Encoding: gzip\r\n\r\n" +
+ strings.Repeat("a", 8193),
+ },
}
func TestDumpRequest(t *testing.T) {
@@ -125,6 +149,8 @@ func TestDumpRequest(t *testing.T) {
tt.Req.Body = ioutil.NopCloser(bytes.NewReader(b))
case func() io.ReadCloser:
tt.Req.Body = b()
+ default:
+ t.Fatalf("Test %d: unsupported Body of %T", i, tt.Body)
}
}
setBody()
@@ -159,7 +185,9 @@ func TestDumpRequest(t *testing.T) {
}
}
if dg := runtime.NumGoroutine() - numg0; dg > 4 {
- t.Errorf("Unexpectedly large number of new goroutines: %d new", dg)
+ buf := make([]byte, 4096)
+ buf = buf[:runtime.Stack(buf, true)]
+ t.Errorf("Unexpectedly large number of new goroutines: %d new: %s", dg, buf)
}
}
diff --git a/src/pkg/net/http/httputil/httputil.go b/src/net/http/httputil/httputil.go
index 74fb6c655..2e523e9e2 100644
--- a/src/pkg/net/http/httputil/httputil.go
+++ b/src/net/http/httputil/httputil.go
@@ -6,7 +6,10 @@
// more common ones in the net/http package.
package httputil
-import "io"
+import (
+ "io"
+ "net/http/internal"
+)
// NewChunkedReader returns a new chunkedReader that translates the data read from r
// out of HTTP "chunked" format before returning it.
@@ -15,7 +18,7 @@ import "io"
// NewChunkedReader is not needed by normal applications. The http package
// automatically decodes chunking when reading response bodies.
func NewChunkedReader(r io.Reader) io.Reader {
- return newChunkedReader(r)
+ return internal.NewChunkedReader(r)
}
// NewChunkedWriter returns a new chunkedWriter that translates writes into HTTP
@@ -28,5 +31,9 @@ func NewChunkedReader(r io.Reader) io.Reader {
// would result in double chunking or chunking with a Content-Length
// length, both of which are wrong.
func NewChunkedWriter(w io.Writer) io.WriteCloser {
- return newChunkedWriter(w)
+ return internal.NewChunkedWriter(w)
}
+
+// ErrLineTooLong is returned when reading malformed chunked data
+// with lines that are too long.
+var ErrLineTooLong = internal.ErrLineTooLong
diff --git a/src/pkg/net/http/httputil/persist.go b/src/net/http/httputil/persist.go
index 987bcc96b..987bcc96b 100644
--- a/src/pkg/net/http/httputil/persist.go
+++ b/src/net/http/httputil/persist.go
diff --git a/src/pkg/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
index 48ada5f5f..ab4637018 100644
--- a/src/pkg/net/http/httputil/reverseproxy.go
+++ b/src/net/http/httputil/reverseproxy.go
@@ -40,6 +40,12 @@ type ReverseProxy struct {
// response body.
// If zero, no periodic flushing is done.
FlushInterval time.Duration
+
+ // ErrorLog specifies an optional logger for errors
+ // that occur when attempting to proxy the request.
+ // If nil, logging goes to os.Stderr via the log package's
+ // standard logger.
+ ErrorLog *log.Logger
}
func singleJoiningSlash(a, b string) string {
@@ -138,7 +144,7 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
res, err := transport.RoundTrip(outreq)
if err != nil {
- log.Printf("http: proxy error: %v", err)
+ p.logf("http: proxy error: %v", err)
rw.WriteHeader(http.StatusInternalServerError)
return
}
@@ -171,6 +177,14 @@ func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader) {
io.Copy(dst, src)
}
+func (p *ReverseProxy) logf(format string, args ...interface{}) {
+ if p.ErrorLog != nil {
+ p.ErrorLog.Printf(format, args...)
+ } else {
+ log.Printf(format, args...)
+ }
+}
+
type writeFlusher interface {
io.Writer
http.Flusher
diff --git a/src/pkg/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
index e9539b44b..e9539b44b 100644
--- a/src/pkg/net/http/httputil/reverseproxy_test.go
+++ b/src/net/http/httputil/reverseproxy_test.go
diff --git a/src/pkg/net/http/chunked.go b/src/net/http/internal/chunked.go
index 749f29d32..9294deb3e 100644
--- a/src/pkg/net/http/chunked.go
+++ b/src/net/http/internal/chunked.go
@@ -4,10 +4,9 @@
// The wire protocol for HTTP's "chunked" Transfer-Encoding.
-// This code is duplicated in net/http and net/http/httputil.
-// Please make any changes in both files.
-
-package http
+// Package internal contains HTTP internals shared by net/http and
+// net/http/httputil.
+package internal
import (
"bufio"
@@ -21,13 +20,13 @@ const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
var ErrLineTooLong = errors.New("header line too long")
-// newChunkedReader returns a new chunkedReader that translates the data read from r
+// NewChunkedReader returns a new chunkedReader that translates the data read from r
// out of HTTP "chunked" format before returning it.
// The chunkedReader returns io.EOF when the final 0-length chunk is read.
//
-// newChunkedReader is not needed by normal applications. The http package
+// NewChunkedReader is not needed by normal applications. The http package
// automatically decodes chunking when reading response bodies.
-func newChunkedReader(r io.Reader) io.Reader {
+func NewChunkedReader(r io.Reader) io.Reader {
br, ok := r.(*bufio.Reader)
if !ok {
br = bufio.NewReader(r)
@@ -135,16 +134,16 @@ func isASCIISpace(b byte) bool {
return b == ' ' || b == '\t' || b == '\n' || b == '\r'
}
-// newChunkedWriter returns a new chunkedWriter that translates writes into HTTP
+// 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.
//
-// newChunkedWriter is not needed by normal applications. The http
+// NewChunkedWriter is not needed by normal applications. The http
// package adds chunking automatically if handlers don't set a
// Content-Length header. Using newChunkedWriter inside a handler
// would result in double chunking or chunking with a Content-Length
// length, both of which are wrong.
-func newChunkedWriter(w io.Writer) io.WriteCloser {
+func NewChunkedWriter(w io.Writer) io.WriteCloser {
return &chunkedWriter{w}
}
diff --git a/src/pkg/net/http/chunked_test.go b/src/net/http/internal/chunked_test.go
index 34544790a..ebc626ea9 100644
--- a/src/pkg/net/http/chunked_test.go
+++ b/src/net/http/internal/chunked_test.go
@@ -2,10 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This code is duplicated in net/http and net/http/httputil.
-// Please make any changes in both files.
-
-package http
+package internal
import (
"bufio"
@@ -20,7 +17,7 @@ import (
func TestChunk(t *testing.T) {
var b bytes.Buffer
- w := newChunkedWriter(&b)
+ w := NewChunkedWriter(&b)
const chunk1 = "hello, "
const chunk2 = "world! 0123456789abcdef"
w.Write([]byte(chunk1))
@@ -31,7 +28,7 @@ func TestChunk(t *testing.T) {
t.Fatalf("chunk writer wrote %q; want %q", g, e)
}
- r := newChunkedReader(&b)
+ r := NewChunkedReader(&b)
data, err := ioutil.ReadAll(r)
if err != nil {
t.Logf(`data: "%s"`, data)
@@ -46,12 +43,12 @@ func TestChunkReadMultiple(t *testing.T) {
// Bunch of small chunks, all read together.
{
var b bytes.Buffer
- w := newChunkedWriter(&b)
+ w := NewChunkedWriter(&b)
w.Write([]byte("foo"))
w.Write([]byte("bar"))
w.Close()
- r := newChunkedReader(&b)
+ r := NewChunkedReader(&b)
buf := make([]byte, 10)
n, err := r.Read(buf)
if n != 6 || err != io.EOF {
@@ -67,7 +64,7 @@ func TestChunkReadMultiple(t *testing.T) {
// should prevent the second chunk header from being read.
{
var b bytes.Buffer
- w := newChunkedWriter(&b)
+ w := NewChunkedWriter(&b)
// fillBufChunk is 11 bytes + 3 bytes header + 2 bytes footer = 16 bytes,
// the same as the bufio ReaderSize below (the minimum), so even
// though we're going to try to Read with a buffer larger enough to also
@@ -78,7 +75,7 @@ func TestChunkReadMultiple(t *testing.T) {
w.Write([]byte(shortChunk))
w.Close()
- r := newChunkedReader(bufio.NewReaderSize(&b, 16))
+ r := NewChunkedReader(bufio.NewReaderSize(&b, 16))
buf := make([]byte, len(fillBufChunk)+len(shortChunk))
n, err := r.Read(buf)
if n != len(fillBufChunk) || err != nil {
@@ -97,7 +94,7 @@ func TestChunkReadMultiple(t *testing.T) {
// And test that we see an EOF chunk, even though our buffer is already full:
{
- r := newChunkedReader(bufio.NewReader(strings.NewReader("3\r\nfoo\r\n0\r\n")))
+ r := NewChunkedReader(bufio.NewReader(strings.NewReader("3\r\nfoo\r\n0\r\n")))
buf := make([]byte, 3)
n, err := r.Read(buf)
if n != 3 || err != io.EOF {
@@ -114,7 +111,7 @@ func TestChunkReaderAllocs(t *testing.T) {
t.Skip("skipping in short mode")
}
var buf bytes.Buffer
- w := newChunkedWriter(&buf)
+ w := NewChunkedWriter(&buf)
a, b, c := []byte("aaaaaa"), []byte("bbbbbbbbbbbb"), []byte("cccccccccccccccccccccccc")
w.Write(a)
w.Write(b)
@@ -127,7 +124,7 @@ func TestChunkReaderAllocs(t *testing.T) {
mallocs := testing.AllocsPerRun(100, func() {
byter.Seek(0, 0)
bufr.Reset(byter)
- r := newChunkedReader(bufr)
+ r := NewChunkedReader(bufr)
n, err := io.ReadFull(r, readBuf)
if n != len(readBuf)-1 {
t.Fatalf("read %d bytes; want %d", n, len(readBuf)-1)
diff --git a/src/pkg/net/http/jar.go b/src/net/http/jar.go
index 5c3de0dad..5c3de0dad 100644
--- a/src/pkg/net/http/jar.go
+++ b/src/net/http/jar.go
diff --git a/src/pkg/net/http/lex.go b/src/net/http/lex.go
index cb33318f4..cb33318f4 100644
--- a/src/pkg/net/http/lex.go
+++ b/src/net/http/lex.go
diff --git a/src/pkg/net/http/lex_test.go b/src/net/http/lex_test.go
index 6d9d294f7..6d9d294f7 100644
--- a/src/pkg/net/http/lex_test.go
+++ b/src/net/http/lex_test.go
diff --git a/src/pkg/net/http/z_last_test.go b/src/net/http/main_test.go
index 5a0cc1198..b8c71fd19 100644
--- a/src/pkg/net/http/z_last_test.go
+++ b/src/net/http/main_test.go
@@ -5,7 +5,9 @@
package http_test
import (
+ "fmt"
"net/http"
+ "os"
"runtime"
"sort"
"strings"
@@ -13,6 +15,14 @@ import (
"time"
)
+func TestMain(m *testing.M) {
+ v := m.Run()
+ if v == 0 && goroutineLeaked() {
+ os.Exit(1)
+ }
+ os.Exit(v)
+}
+
func interestingGoroutines() (gs []string) {
buf := make([]byte, 2<<20)
buf = buf[:runtime.Stack(buf, true)]
@@ -30,6 +40,7 @@ func interestingGoroutines() (gs []string) {
// These only show up with GOTRACEBACK=2; Issue 5005 (comment 28)
strings.Contains(stack, "runtime.goexit") ||
strings.Contains(stack, "created by runtime.gc") ||
+ strings.Contains(stack, "net/http_test.interestingGoroutines") ||
strings.Contains(stack, "runtime.MHeap_Scavenger") {
continue
}
@@ -40,10 +51,10 @@ func interestingGoroutines() (gs []string) {
}
// Verify the other tests didn't leave any goroutines running.
-// This is in a file named z_last_test.go so it sorts at the end.
-func TestGoroutinesRunning(t *testing.T) {
+func goroutineLeaked() bool {
if testing.Short() {
- t.Skip("not counting goroutines for leakage in -short mode")
+ // not counting goroutines for leakage in -short mode
+ return false
}
gs := interestingGoroutines()
@@ -54,13 +65,14 @@ func TestGoroutinesRunning(t *testing.T) {
n++
}
- t.Logf("num goroutines = %d", n)
- if n > 0 {
- t.Error("Too many goroutines.")
- for stack, count := range stackCount {
- t.Logf("%d instances of:\n%s", count, stack)
- }
+ if n == 0 {
+ return false
+ }
+ fmt.Fprintf(os.Stderr, "Too many goroutines running after net/http test(s).\n")
+ for stack, count := range stackCount {
+ fmt.Fprintf(os.Stderr, "%d instances of:\n%s\n", count, stack)
}
+ return true
}
func afterTest(t *testing.T) {
diff --git a/src/pkg/net/http/npn_test.go b/src/net/http/npn_test.go
index 98b8930d0..98b8930d0 100644
--- a/src/pkg/net/http/npn_test.go
+++ b/src/net/http/npn_test.go
diff --git a/src/pkg/net/http/pprof/pprof.go b/src/net/http/pprof/pprof.go
index 0c7548e3e..a23f1bc4b 100644
--- a/src/pkg/net/http/pprof/pprof.go
+++ b/src/net/http/pprof/pprof.go
@@ -162,6 +162,10 @@ func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Unknown profile: %s\n", name)
return
}
+ gc, _ := strconv.Atoi(r.FormValue("gc"))
+ if name == "heap" && gc > 0 {
+ runtime.GC()
+ }
p.WriteTo(w, debug)
return
}
diff --git a/src/pkg/net/http/proxy_test.go b/src/net/http/proxy_test.go
index b6aed3792..b6aed3792 100644
--- a/src/pkg/net/http/proxy_test.go
+++ b/src/net/http/proxy_test.go
diff --git a/src/pkg/net/http/race.go b/src/net/http/race.go
index 766503967..766503967 100644
--- a/src/pkg/net/http/race.go
+++ b/src/net/http/race.go
diff --git a/src/pkg/net/http/range_test.go b/src/net/http/range_test.go
index ef911af7b..ef911af7b 100644
--- a/src/pkg/net/http/range_test.go
+++ b/src/net/http/range_test.go
diff --git a/src/pkg/net/http/readrequest_test.go b/src/net/http/readrequest_test.go
index ffdd6a892..e930d99af 100644
--- a/src/pkg/net/http/readrequest_test.go
+++ b/src/net/http/readrequest_test.go
@@ -11,6 +11,7 @@ import (
"io"
"net/url"
"reflect"
+ "strings"
"testing"
)
@@ -295,14 +296,39 @@ var reqTests = []reqTest{
noTrailer,
noError,
},
+
+ // Connection: close. golang.org/issue/8261
+ {
+ "GET / HTTP/1.1\r\nHost: issue8261.com\r\nConnection: close\r\n\r\n",
+ &Request{
+ Method: "GET",
+ URL: &url.URL{
+ Path: "/",
+ },
+ Header: Header{
+ // This wasn't removed from Go 1.0 to
+ // Go 1.3, so locking it in that we
+ // keep this:
+ "Connection": []string{"close"},
+ },
+ Host: "issue8261.com",
+ Proto: "HTTP/1.1",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Close: true,
+ RequestURI: "/",
+ },
+
+ noBody,
+ noTrailer,
+ noError,
+ },
}
func TestReadRequest(t *testing.T) {
for i := range reqTests {
tt := &reqTests[i]
- var braw bytes.Buffer
- braw.WriteString(tt.Raw)
- req, err := ReadRequest(bufio.NewReader(&braw))
+ req, err := ReadRequest(bufio.NewReader(strings.NewReader(tt.Raw)))
if err != nil {
if err.Error() != tt.Error {
t.Errorf("#%d: error %q, want error %q", i, err.Error(), tt.Error)
@@ -311,21 +337,22 @@ func TestReadRequest(t *testing.T) {
}
rbody := req.Body
req.Body = nil
- diff(t, fmt.Sprintf("#%d Request", i), req, tt.Req)
+ testName := fmt.Sprintf("Test %d (%q)", i, tt.Raw)
+ diff(t, testName, req, tt.Req)
var bout bytes.Buffer
if rbody != nil {
_, err := io.Copy(&bout, rbody)
if err != nil {
- t.Fatalf("#%d. copying body: %v", i, err)
+ t.Fatalf("%s: copying body: %v", testName, err)
}
rbody.Close()
}
body := bout.String()
if body != tt.Body {
- t.Errorf("#%d: Body = %q want %q", i, body, tt.Body)
+ t.Errorf("%s: Body = %q want %q", testName, body, tt.Body)
}
if !reflect.DeepEqual(tt.Trailer, req.Trailer) {
- t.Errorf("#%d. Trailers differ.\n got: %v\nwant: %v", i, req.Trailer, tt.Trailer)
+ t.Errorf("%s: Trailers differ.\n got: %v\nwant: %v", testName, req.Trailer, tt.Trailer)
}
}
}
diff --git a/src/pkg/net/http/request.go b/src/net/http/request.go
index a67092066..487eebcb8 100644
--- a/src/pkg/net/http/request.go
+++ b/src/net/http/request.go
@@ -10,6 +10,7 @@ import (
"bufio"
"bytes"
"crypto/tls"
+ "encoding/base64"
"errors"
"fmt"
"io"
@@ -390,10 +391,16 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
w = bw
}
- fmt.Fprintf(w, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), ruri)
+ _, err := fmt.Fprintf(w, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), ruri)
+ if err != nil {
+ return err
+ }
// Header lines
- fmt.Fprintf(w, "Host: %s\r\n", host)
+ _, err = fmt.Fprintf(w, "Host: %s\r\n", host)
+ if err != nil {
+ return err
+ }
// Use the defaultUserAgent unless the Header contains one, which
// may be blank to not send the header.
@@ -404,7 +411,10 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
}
}
if userAgent != "" {
- fmt.Fprintf(w, "User-Agent: %s\r\n", userAgent)
+ _, err = fmt.Fprintf(w, "User-Agent: %s\r\n", userAgent)
+ if err != nil {
+ return err
+ }
}
// Process Body,ContentLength,Close,Trailer
@@ -429,7 +439,10 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
}
}
- io.WriteString(w, "\r\n")
+ _, err = io.WriteString(w, "\r\n")
+ if err != nil {
+ return err
+ }
// Write body and trailer
err = tw.WriteBody(w)
@@ -509,6 +522,35 @@ func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
return req, nil
}
+// BasicAuth returns the username and password provided in the request's
+// Authorization header, if the request uses HTTP Basic Authentication.
+// See RFC 2617, Section 2.
+func (r *Request) BasicAuth() (username, password string, ok bool) {
+ auth := r.Header.Get("Authorization")
+ if auth == "" {
+ return
+ }
+ return parseBasicAuth(auth)
+}
+
+// parseBasicAuth parses an HTTP Basic Authentication string.
+// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ("Aladdin", "open sesame", true).
+func parseBasicAuth(auth string) (username, password string, ok bool) {
+ if !strings.HasPrefix(auth, "Basic ") {
+ return
+ }
+ c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(auth, "Basic "))
+ if err != nil {
+ return
+ }
+ cs := string(c)
+ s := strings.IndexByte(cs, ':')
+ if s < 0 {
+ return
+ }
+ return cs[:s], cs[s+1:], true
+}
+
// SetBasicAuth sets the request's Authorization header to use HTTP
// Basic Authentication with the provided username and password.
//
@@ -623,6 +665,7 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) {
return nil, err
}
+ req.Close = shouldClose(req.ProtoMajor, req.ProtoMinor, req.Header, false)
return req, nil
}
@@ -807,8 +850,10 @@ func (r *Request) ParseMultipartForm(maxMemory int64) error {
// FormValue returns the first value for the named component of the query.
// POST and PUT body parameters take precedence over URL query string values.
-// FormValue calls ParseMultipartForm and ParseForm if necessary.
-// To access multiple values of the same key use ParseForm.
+// FormValue calls ParseMultipartForm and ParseForm if necessary and ignores
+// any errors returned by these functions.
+// To access multiple values of the same key, call ParseForm and
+// then inspect Request.Form directly.
func (r *Request) FormValue(key string) string {
if r.Form == nil {
r.ParseMultipartForm(defaultMaxMemory)
@@ -821,7 +866,8 @@ func (r *Request) FormValue(key string) string {
// PostFormValue returns the first value for the named component of the POST
// or PUT request body. URL query parameters are ignored.
-// PostFormValue calls ParseMultipartForm and ParseForm if necessary.
+// PostFormValue calls ParseMultipartForm and ParseForm if necessary and ignores
+// any errors returned by these functions.
func (r *Request) PostFormValue(key string) string {
if r.PostForm == nil {
r.ParseMultipartForm(defaultMaxMemory)
diff --git a/src/pkg/net/http/request_test.go b/src/net/http/request_test.go
index b9fa3c2bf..759ea4e8b 100644
--- a/src/pkg/net/http/request_test.go
+++ b/src/net/http/request_test.go
@@ -7,6 +7,7 @@ package http_test
import (
"bufio"
"bytes"
+ "encoding/base64"
"fmt"
"io"
"io/ioutil"
@@ -396,6 +397,75 @@ func TestParseHTTPVersion(t *testing.T) {
}
}
+type getBasicAuthTest struct {
+ username, password string
+ ok bool
+}
+
+type parseBasicAuthTest getBasicAuthTest
+
+type basicAuthCredentialsTest struct {
+ username, password string
+}
+
+var getBasicAuthTests = []struct {
+ username, password string
+ ok bool
+}{
+ {"Aladdin", "open sesame", true},
+ {"Aladdin", "open:sesame", true},
+ {"", "", true},
+}
+
+func TestGetBasicAuth(t *testing.T) {
+ for _, tt := range getBasicAuthTests {
+ r, _ := NewRequest("GET", "http://example.com/", nil)
+ r.SetBasicAuth(tt.username, tt.password)
+ username, password, ok := r.BasicAuth()
+ if ok != tt.ok || username != tt.username || password != tt.password {
+ t.Errorf("BasicAuth() = %#v, want %#v", getBasicAuthTest{username, password, ok},
+ getBasicAuthTest{tt.username, tt.password, tt.ok})
+ }
+ }
+ // Unauthenticated request.
+ r, _ := NewRequest("GET", "http://example.com/", nil)
+ username, password, ok := r.BasicAuth()
+ if ok {
+ t.Errorf("expected false from BasicAuth when the request is unauthenticated")
+ }
+ want := basicAuthCredentialsTest{"", ""}
+ if username != want.username || password != want.password {
+ t.Errorf("expected credentials: %#v when the request is unauthenticated, got %#v",
+ want, basicAuthCredentialsTest{username, password})
+ }
+}
+
+var parseBasicAuthTests = []struct {
+ header, username, password string
+ ok bool
+}{
+ {"Basic " + base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "Aladdin", "open sesame", true},
+ {"Basic " + base64.StdEncoding.EncodeToString([]byte("Aladdin:open:sesame")), "Aladdin", "open:sesame", true},
+ {"Basic " + base64.StdEncoding.EncodeToString([]byte(":")), "", "", true},
+ {"Basic" + base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "", "", false},
+ {base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "", "", false},
+ {"Basic ", "", "", false},
+ {"Basic Aladdin:open sesame", "", "", false},
+ {`Digest username="Aladdin"`, "", "", false},
+}
+
+func TestParseBasicAuth(t *testing.T) {
+ for _, tt := range parseBasicAuthTests {
+ r, _ := NewRequest("GET", "http://example.com/", nil)
+ r.Header.Set("Authorization", tt.header)
+ username, password, ok := r.BasicAuth()
+ if ok != tt.ok || username != tt.username || password != tt.password {
+ t.Errorf("BasicAuth() = %#v, want %#v", getBasicAuthTest{username, password, ok},
+ getBasicAuthTest{tt.username, tt.password, tt.ok})
+ }
+ }
+}
+
type logWrites struct {
t *testing.T
dst *[]string
diff --git a/src/pkg/net/http/requestwrite_test.go b/src/net/http/requestwrite_test.go
index dc0e204ca..7a6bd5878 100644
--- a/src/pkg/net/http/requestwrite_test.go
+++ b/src/net/http/requestwrite_test.go
@@ -280,7 +280,7 @@ var reqWriteTests = []reqWriteTest{
ContentLength: 10, // but we're going to send only 5 bytes
},
Body: []byte("12345"),
- WantError: errors.New("http: Request.ContentLength=10 with Body length 5"),
+ WantError: errors.New("http: ContentLength=10 with Body length 5"),
},
// Request with a ContentLength of 4 but an 8 byte body.
@@ -294,7 +294,7 @@ var reqWriteTests = []reqWriteTest{
ContentLength: 4, // but we're going to try to send 8 bytes
},
Body: []byte("12345678"),
- WantError: errors.New("http: Request.ContentLength=4 with Body length 8"),
+ WantError: errors.New("http: ContentLength=4 with Body length 8"),
},
// Request with a 5 ContentLength and nil body.
@@ -563,3 +563,61 @@ func mustParseURL(s string) *url.URL {
}
return u
}
+
+type writerFunc func([]byte) (int, error)
+
+func (f writerFunc) Write(p []byte) (int, error) { return f(p) }
+
+// TestRequestWriteError tests the Write err != nil checks in (*Request).write.
+func TestRequestWriteError(t *testing.T) {
+ failAfter, writeCount := 0, 0
+ errFail := errors.New("fake write failure")
+
+ // w is the buffered io.Writer to write the request to. It
+ // fails exactly once on its Nth Write call, as controlled by
+ // failAfter. It also tracks the number of calls in
+ // writeCount.
+ w := struct {
+ io.ByteWriter // to avoid being wrapped by a bufio.Writer
+ io.Writer
+ }{
+ nil,
+ writerFunc(func(p []byte) (n int, err error) {
+ writeCount++
+ if failAfter == 0 {
+ err = errFail
+ }
+ failAfter--
+ return len(p), err
+ }),
+ }
+
+ req, _ := NewRequest("GET", "http://example.com/", nil)
+ const writeCalls = 4 // number of Write calls in current implementation
+ sawGood := false
+ for n := 0; n <= writeCalls+2; n++ {
+ failAfter = n
+ writeCount = 0
+ err := req.Write(w)
+ var wantErr error
+ if n < writeCalls {
+ wantErr = errFail
+ }
+ if err != wantErr {
+ t.Errorf("for fail-after %d Writes, err = %v; want %v", n, err, wantErr)
+ continue
+ }
+ if err == nil {
+ sawGood = true
+ if writeCount != writeCalls {
+ t.Fatalf("writeCalls constant is outdated in test")
+ }
+ }
+ if writeCount > writeCalls || writeCount > n+1 {
+ t.Errorf("for fail-after %d, saw unexpectedly high (%d) write calls", n, writeCount)
+ }
+ }
+ if !sawGood {
+ t.Fatalf("writeCalls constant is outdated in test")
+ }
+}
diff --git a/src/pkg/net/http/response.go b/src/net/http/response.go
index 5d2c39080..5d2c39080 100644
--- a/src/pkg/net/http/response.go
+++ b/src/net/http/response.go
diff --git a/src/pkg/net/http/response_test.go b/src/net/http/response_test.go
index 4b8946f7a..06e940d9a 100644
--- a/src/pkg/net/http/response_test.go
+++ b/src/net/http/response_test.go
@@ -12,6 +12,7 @@ import (
"fmt"
"io"
"io/ioutil"
+ "net/http/internal"
"net/url"
"reflect"
"regexp"
@@ -376,6 +377,34 @@ some body`,
"Body here\n",
},
+
+ // 206 Partial Content. golang.org/issue/8923
+ {
+ "HTTP/1.1 206 Partial Content\r\n" +
+ "Content-Type: text/plain; charset=utf-8\r\n" +
+ "Accept-Ranges: bytes\r\n" +
+ "Content-Range: bytes 0-5/1862\r\n" +
+ "Content-Length: 6\r\n\r\n" +
+ "foobar",
+
+ Response{
+ Status: "206 Partial Content",
+ StatusCode: 206,
+ Proto: "HTTP/1.1",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Request: dummyReq("GET"),
+ Header: Header{
+ "Accept-Ranges": []string{"bytes"},
+ "Content-Length": []string{"6"},
+ "Content-Type": []string{"text/plain; charset=utf-8"},
+ "Content-Range": []string{"bytes 0-5/1862"},
+ },
+ ContentLength: 6,
+ },
+
+ "foobar",
+ },
}
func TestReadResponse(t *testing.T) {
@@ -451,7 +480,7 @@ func TestReadResponseCloseInMiddle(t *testing.T) {
}
var wr io.Writer = &buf
if test.chunked {
- wr = newChunkedWriter(wr)
+ wr = internal.NewChunkedWriter(wr)
}
if test.compressed {
buf.WriteString("Content-Encoding: gzip\r\n")
diff --git a/src/pkg/net/http/responsewrite_test.go b/src/net/http/responsewrite_test.go
index 585b13b85..585b13b85 100644
--- a/src/pkg/net/http/responsewrite_test.go
+++ b/src/net/http/responsewrite_test.go
diff --git a/src/pkg/net/http/serve_test.go b/src/net/http/serve_test.go
index 9e4d226bf..5e0a0053c 100644
--- a/src/pkg/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -15,6 +15,7 @@ import (
"io"
"io/ioutil"
"log"
+ "math/rand"
"net"
. "net/http"
"net/http/httptest"
@@ -777,6 +778,35 @@ func TestChunkedResponseHeaders(t *testing.T) {
}
}
+func TestIdentityResponseHeaders(t *testing.T) {
+ defer afterTest(t)
+ log.SetOutput(ioutil.Discard) // is noisy otherwise
+ defer log.SetOutput(os.Stderr)
+
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.Header().Set("Transfer-Encoding", "identity")
+ w.(Flusher).Flush()
+ fmt.Fprintf(w, "I am an identity response.")
+ }))
+ defer ts.Close()
+
+ res, err := Get(ts.URL)
+ if err != nil {
+ t.Fatalf("Get error: %v", err)
+ }
+ defer res.Body.Close()
+
+ if g, e := res.TransferEncoding, []string(nil); !reflect.DeepEqual(g, e) {
+ t.Errorf("expected TransferEncoding of %v; got %v", e, g)
+ }
+ if _, haveCL := res.Header["Content-Length"]; haveCL {
+ t.Errorf("Unexpected Content-Length")
+ }
+ if !res.Close {
+ t.Errorf("expected Connection: close; got %v", res.Close)
+ }
+}
+
// Test304Responses verifies that 304s don't declare that they're
// chunking in their response headers and aren't allowed to produce
// output.
@@ -1188,6 +1218,82 @@ func TestTimeoutHandler(t *testing.T) {
}
}
+// See issues 8209 and 8414.
+func TestTimeoutHandlerRace(t *testing.T) {
+ defer afterTest(t)
+
+ delayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
+ ms, _ := strconv.Atoi(r.URL.Path[1:])
+ if ms == 0 {
+ ms = 1
+ }
+ for i := 0; i < ms; i++ {
+ w.Write([]byte("hi"))
+ time.Sleep(time.Millisecond)
+ }
+ })
+
+ ts := httptest.NewServer(TimeoutHandler(delayHi, 20*time.Millisecond, ""))
+ defer ts.Close()
+
+ var wg sync.WaitGroup
+ gate := make(chan bool, 10)
+ n := 50
+ if testing.Short() {
+ n = 10
+ gate = make(chan bool, 3)
+ }
+ for i := 0; i < n; i++ {
+ gate <- true
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ defer func() { <-gate }()
+ res, err := Get(fmt.Sprintf("%s/%d", ts.URL, rand.Intn(50)))
+ if err == nil {
+ io.Copy(ioutil.Discard, res.Body)
+ res.Body.Close()
+ }
+ }()
+ }
+ wg.Wait()
+}
+
+// See issues 8209 and 8414.
+func TestTimeoutHandlerRaceHeader(t *testing.T) {
+ defer afterTest(t)
+
+ delay204 := HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.WriteHeader(204)
+ })
+
+ ts := httptest.NewServer(TimeoutHandler(delay204, time.Nanosecond, ""))
+ defer ts.Close()
+
+ var wg sync.WaitGroup
+ gate := make(chan bool, 50)
+ n := 500
+ if testing.Short() {
+ n = 10
+ }
+ for i := 0; i < n; i++ {
+ gate <- true
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ defer func() { <-gate }()
+ res, err := Get(ts.URL)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer res.Body.Close()
+ io.Copy(ioutil.Discard, res.Body)
+ }()
+ }
+ wg.Wait()
+}
+
// Verifies we don't path.Clean() on the wrong parts in redirects.
func TestRedirectMunging(t *testing.T) {
req, _ := NewRequest("GET", "http://example.com/", nil)
@@ -2404,13 +2510,13 @@ func TestServerConnState(t *testing.T) {
}
want := map[int][]ConnState{
- 1: []ConnState{StateNew, StateActive, StateIdle, StateActive, StateClosed},
- 2: []ConnState{StateNew, StateActive, StateIdle, StateActive, StateClosed},
- 3: []ConnState{StateNew, StateActive, StateHijacked},
- 4: []ConnState{StateNew, StateActive, StateHijacked},
- 5: []ConnState{StateNew, StateClosed},
- 6: []ConnState{StateNew, StateActive, StateClosed},
- 7: []ConnState{StateNew, StateActive, StateIdle, StateClosed},
+ 1: {StateNew, StateActive, StateIdle, StateActive, StateClosed},
+ 2: {StateNew, StateActive, StateIdle, StateActive, StateClosed},
+ 3: {StateNew, StateActive, StateHijacked},
+ 4: {StateNew, StateActive, StateHijacked},
+ 5: {StateNew, StateClosed},
+ 6: {StateNew, StateActive, StateClosed},
+ 7: {StateNew, StateActive, StateIdle, StateClosed},
}
logString := func(m map[int][]ConnState) string {
var b bytes.Buffer
@@ -2530,6 +2636,126 @@ func TestServerConnStateNew(t *testing.T) {
}
}
+type closeWriteTestConn struct {
+ rwTestConn
+ didCloseWrite bool
+}
+
+func (c *closeWriteTestConn) CloseWrite() error {
+ c.didCloseWrite = true
+ return nil
+}
+
+func TestCloseWrite(t *testing.T) {
+ var srv Server
+ var testConn closeWriteTestConn
+ c, err := ExportServerNewConn(&srv, &testConn)
+ if err != nil {
+ t.Fatal(err)
+ }
+ ExportCloseWriteAndWait(c)
+ if !testConn.didCloseWrite {
+ t.Error("didn't see CloseWrite call")
+ }
+}
+
+// This verifies that a handler can Flush and then Hijack.
+//
+// An similar test crashed once during development, but it was only
+// testing this tangentially and temporarily until another TODO was
+// fixed.
+//
+// So add an explicit test for this.
+func TestServerFlushAndHijack(t *testing.T) {
+ defer afterTest(t)
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ io.WriteString(w, "Hello, ")
+ w.(Flusher).Flush()
+ conn, buf, _ := w.(Hijacker).Hijack()
+ buf.WriteString("6\r\nworld!\r\n0\r\n\r\n")
+ if err := buf.Flush(); err != nil {
+ t.Error(err)
+ }
+ if err := conn.Close(); err != nil {
+ t.Error(err)
+ }
+ }))
+ defer ts.Close()
+ res, err := Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ all, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if want := "Hello, world!"; string(all) != want {
+ t.Errorf("Got %q; want %q", all, want)
+ }
+}
+
+// golang.org/issue/8534 -- the Server shouldn't reuse a connection
+// for keep-alive after it's seen any Write error (e.g. a timeout) on
+// that net.Conn.
+//
+// To test, verify we don't timeout or see fewer unique client
+// addresses (== unique connections) than requests.
+func TestServerKeepAliveAfterWriteError(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in -short mode")
+ }
+ defer afterTest(t)
+ const numReq = 3
+ addrc := make(chan string, numReq)
+ ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ addrc <- r.RemoteAddr
+ time.Sleep(500 * time.Millisecond)
+ w.(Flusher).Flush()
+ }))
+ ts.Config.WriteTimeout = 250 * time.Millisecond
+ ts.Start()
+ defer ts.Close()
+
+ errc := make(chan error, numReq)
+ go func() {
+ defer close(errc)
+ for i := 0; i < numReq; i++ {
+ res, err := Get(ts.URL)
+ if res != nil {
+ res.Body.Close()
+ }
+ errc <- err
+ }
+ }()
+
+ timeout := time.NewTimer(numReq * 2 * time.Second) // 4x overkill
+ defer timeout.Stop()
+ addrSeen := map[string]bool{}
+ numOkay := 0
+ for {
+ select {
+ case v := <-addrc:
+ addrSeen[v] = true
+ case err, ok := <-errc:
+ if !ok {
+ if len(addrSeen) != numReq {
+ t.Errorf("saw %d unique client addresses; want %d", len(addrSeen), numReq)
+ }
+ if numOkay != 0 {
+ t.Errorf("got %d successful client requests; want 0", numOkay)
+ }
+ return
+ }
+ if err == nil {
+ numOkay++
+ }
+ case <-timeout.C:
+ t.Fatal("timeout waiting for requests to complete")
+ }
+ }
+}
+
func BenchmarkClientServer(b *testing.B) {
b.ReportAllocs()
b.StopTimer()
@@ -2559,24 +2785,44 @@ func BenchmarkClientServer(b *testing.B) {
}
func BenchmarkClientServerParallel4(b *testing.B) {
- benchmarkClientServerParallel(b, 4)
+ benchmarkClientServerParallel(b, 4, false)
}
func BenchmarkClientServerParallel64(b *testing.B) {
- benchmarkClientServerParallel(b, 64)
+ benchmarkClientServerParallel(b, 64, false)
}
-func benchmarkClientServerParallel(b *testing.B, parallelism int) {
+func BenchmarkClientServerParallelTLS4(b *testing.B) {
+ benchmarkClientServerParallel(b, 4, true)
+}
+
+func BenchmarkClientServerParallelTLS64(b *testing.B) {
+ benchmarkClientServerParallel(b, 64, true)
+}
+
+func benchmarkClientServerParallel(b *testing.B, parallelism int, useTLS bool) {
b.ReportAllocs()
- ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+ ts := httptest.NewUnstartedServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
fmt.Fprintf(rw, "Hello world.\n")
}))
+ if useTLS {
+ ts.StartTLS()
+ } else {
+ ts.Start()
+ }
defer ts.Close()
b.ResetTimer()
b.SetParallelism(parallelism)
b.RunParallel(func(pb *testing.PB) {
+ noVerifyTransport := &Transport{
+ TLSClientConfig: &tls.Config{
+ InsecureSkipVerify: true,
+ },
+ }
+ defer noVerifyTransport.CloseIdleConnections()
+ client := &Client{Transport: noVerifyTransport}
for pb.Next() {
- res, err := Get(ts.URL)
+ res, err := client.Get(ts.URL)
if err != nil {
b.Logf("Get: %v", err)
continue
diff --git a/src/pkg/net/http/server.go b/src/net/http/server.go
index eae097eb8..008d5aa7a 100644
--- a/src/pkg/net/http/server.go
+++ b/src/net/http/server.go
@@ -42,6 +42,12 @@ var (
// 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.
+//
+// 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)
}
@@ -108,6 +114,8 @@ 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
@@ -426,13 +434,14 @@ func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
c.remoteAddr = rwc.RemoteAddr().String()
c.server = srv
c.rwc = rwc
+ c.w = rwc
if debugServerConnections {
c.rwc = newLoggingConn("server", c.rwc)
}
c.sr = liveSwitchReader{r: c.rwc}
c.lr = io.LimitReader(&c.sr, noLimit).(*io.LimitedReader)
br := newBufioReader(c.lr)
- bw := newBufioWriterSize(c.rwc, 4<<10)
+ bw := newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)
c.buf = bufio.NewReadWriter(br, bw)
return c, nil
}
@@ -833,13 +842,20 @@ func (cw *chunkWriter) writeHeader(p []byte) {
} else if hasCL {
delHeader("Transfer-Encoding")
} else if w.req.ProtoAtLeast(1, 1) {
- // HTTP/1.1 or greater: use chunked transfer encoding
- // to avoid closing the connection at EOF.
- // TODO: this blows away any custom or stacked Transfer-Encoding they
- // might have set. Deal with that as need arises once we have a valid
- // use case.
- cw.chunking = true
- setHeader.transferEncoding = "chunked"
+ // HTTP/1.1 or greater: Transfer-Encoding has been set to identity, and no
+ // content-length has been provided. The connection must be closed after the
+ // reply is written, and no chunking is to be done. This is the setup
+ // recommended in the Server-Sent Events candidate recommendation 11,
+ // section 8.
+ if hasTE && te == "identity" {
+ cw.chunking = false
+ w.closeAfterReply = true
+ } else {
+ // HTTP/1.1 or greater: use chunked transfer encoding
+ // to avoid closing the connection at EOF.
+ cw.chunking = true
+ setHeader.transferEncoding = "chunked"
+ }
} else {
// HTTP version < 1.1: cannot do chunked transfer
// encoding and we don't know the Content-Length so
@@ -943,8 +959,10 @@ func (w *response) bodyAllowed() bool {
// 2. (*response).w, a *bufio.Writer of bufferBeforeChunkingSize bytes
// 3. chunkWriter.Writer (whose writeHeader finalizes Content-Length/Type)
// and which writes the chunk headers, if needed.
-// 4. conn.buf, a bufio.Writer of default (4kB) bytes
-// 5. the rwc, the net.Conn.
+// 4. conn.buf, a bufio.Writer of default (4kB) bytes, writing to ->
+// 5. checkConnErrorWriter{c}, which notes any non-nil error on Write
+// and populates c.werr with it if so. but otherwise writes to:
+// 6. the rwc, the net.Conn.
//
// TODO(bradfitz): short-circuit some of the buffering when the
// initial header contains both a Content-Type and Content-Length.
@@ -1014,6 +1032,12 @@ func (w *response) finishRequest() {
// Did not write enough. Avoid getting out of sync.
w.closeAfterReply = true
}
+
+ // There was some error writing to the underlying connection
+ // during the request, so don't re-use this conn.
+ if w.conn.werr != nil {
+ w.closeAfterReply = true
+ }
}
func (w *response) Flush() {
@@ -1058,15 +1082,21 @@ func (c *conn) close() {
// This timeout is somewhat arbitrary (~latency around the planet).
const rstAvoidanceDelay = 500 * time.Millisecond
+type closeWriter interface {
+ CloseWrite() error
+}
+
+var _ closeWriter = (*net.TCPConn)(nil)
+
// closeWrite flushes any outstanding data and sends a FIN packet (if
// client is connected via TCP), signalling that we're done. We then
-// pause for a bit, hoping the client processes it before `any
+// pause for a bit, hoping the client processes it before any
// subsequent RST.
//
// See http://golang.org/issue/3595
func (c *conn) closeWriteAndWait() {
c.finalFlush()
- if tcp, ok := c.rwc.(*net.TCPConn); ok {
+ if tcp, ok := c.rwc.(closeWriter); ok {
tcp.CloseWrite()
}
time.Sleep(rstAvoidanceDelay)
@@ -1916,9 +1946,9 @@ func (tw *timeoutWriter) Header() Header {
func (tw *timeoutWriter) Write(p []byte) (int, error) {
tw.mu.Lock()
- timedOut := tw.timedOut
- tw.mu.Unlock()
- if timedOut {
+ defer tw.mu.Unlock()
+ tw.wroteHeader = true // implicitly at least
+ if tw.timedOut {
return 0, ErrHandlerTimeout
}
return tw.w.Write(p)
@@ -1926,12 +1956,11 @@ func (tw *timeoutWriter) Write(p []byte) (int, error) {
func (tw *timeoutWriter) WriteHeader(code int) {
tw.mu.Lock()
+ defer tw.mu.Unlock()
if tw.timedOut || tw.wroteHeader {
- tw.mu.Unlock()
return
}
tw.wroteHeader = true
- tw.mu.Unlock()
tw.w.WriteHeader(code)
}
@@ -2050,3 +2079,18 @@ func (c *loggingConn) Close() (err error) {
log.Printf("%s.Close() = %v", c.name, err)
return
}
+
+// checkConnErrorWriter writes to c.rwc and records any write errors to c.werr.
+// It only contains one field (and a pointer field at that), so it
+// fits in an interface value without an extra allocation.
+type checkConnErrorWriter struct {
+ c *conn
+}
+
+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.
+ if err != nil && w.c.werr == nil {
+ w.c.werr = err
+ }
+ return
+}
diff --git a/src/pkg/net/http/sniff.go b/src/net/http/sniff.go
index 68f519b05..68f519b05 100644
--- a/src/pkg/net/http/sniff.go
+++ b/src/net/http/sniff.go
diff --git a/src/pkg/net/http/sniff_test.go b/src/net/http/sniff_test.go
index 24ca27afc..24ca27afc 100644
--- a/src/pkg/net/http/sniff_test.go
+++ b/src/net/http/sniff_test.go
diff --git a/src/pkg/net/http/status.go b/src/net/http/status.go
index d253bd5cb..d253bd5cb 100644
--- a/src/pkg/net/http/status.go
+++ b/src/net/http/status.go
diff --git a/src/pkg/net/http/testdata/file b/src/net/http/testdata/file
index 11f11f9be..11f11f9be 100644
--- a/src/pkg/net/http/testdata/file
+++ b/src/net/http/testdata/file
diff --git a/src/pkg/net/http/testdata/index.html b/src/net/http/testdata/index.html
index da8e1e93d..da8e1e93d 100644
--- a/src/pkg/net/http/testdata/index.html
+++ b/src/net/http/testdata/index.html
diff --git a/src/pkg/net/http/testdata/style.css b/src/net/http/testdata/style.css
index 208d16d42..208d16d42 100644
--- a/src/pkg/net/http/testdata/style.css
+++ b/src/net/http/testdata/style.css
diff --git a/src/pkg/net/http/transfer.go b/src/net/http/transfer.go
index 7f6368652..520500330 100644
--- a/src/pkg/net/http/transfer.go
+++ b/src/net/http/transfer.go
@@ -11,6 +11,7 @@ import (
"fmt"
"io"
"io/ioutil"
+ "net/http/internal"
"net/textproto"
"sort"
"strconv"
@@ -18,6 +19,10 @@ import (
"sync"
)
+// ErrLineTooLong is returned when reading request or response bodies
+// with malformed chunked encoding.
+var ErrLineTooLong = internal.ErrLineTooLong
+
type errorReader struct {
err error
}
@@ -198,7 +203,7 @@ func (t *transferWriter) WriteBody(w io.Writer) error {
// Write body
if t.Body != nil {
if chunked(t.TransferEncoding) {
- cw := newChunkedWriter(w)
+ cw := internal.NewChunkedWriter(w)
_, err = io.Copy(cw, t.Body)
if err == nil {
err = cw.Close()
@@ -223,7 +228,7 @@ func (t *transferWriter) WriteBody(w io.Writer) error {
}
if !t.ResponseToHEAD && t.ContentLength != -1 && t.ContentLength != ncopy {
- return fmt.Errorf("http: Request.ContentLength=%d with Body length %d",
+ return fmt.Errorf("http: ContentLength=%d with Body length %d",
t.ContentLength, ncopy)
}
@@ -298,7 +303,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
t.StatusCode = rr.StatusCode
t.ProtoMajor = rr.ProtoMajor
t.ProtoMinor = rr.ProtoMinor
- t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header)
+ t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header, true)
isResponse = true
if rr.Request != nil {
t.RequestMethod = rr.Request.Method
@@ -365,7 +370,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
if noBodyExpected(t.RequestMethod) {
t.Body = eofReader
} else {
- t.Body = &body{src: newChunkedReader(r), hdr: msg, r: r, closing: t.Close}
+ t.Body = &body{src: internal.NewChunkedReader(r), hdr: msg, r: r, closing: t.Close}
}
case realLength == 0:
t.Body = eofReader
@@ -497,7 +502,7 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
// Determine whether to hang up after sending a request and body, or
// receiving a response and body
// 'header' is the request headers
-func shouldClose(major, minor int, header Header) bool {
+func shouldClose(major, minor int, header Header, removeCloseHeader bool) bool {
if major < 1 {
return true
} else if major == 1 && minor == 0 {
@@ -509,7 +514,9 @@ func shouldClose(major, minor int, header Header) bool {
// TODO: Should split on commas, toss surrounding white space,
// and check each field.
if strings.ToLower(header.get("Connection")) == "close" {
- header.Del("Connection")
+ if removeCloseHeader {
+ header.Del("Connection")
+ }
return true
}
}
diff --git a/src/pkg/net/http/transfer_test.go b/src/net/http/transfer_test.go
index 48cd540b9..48cd540b9 100644
--- a/src/pkg/net/http/transfer_test.go
+++ b/src/net/http/transfer_test.go
diff --git a/src/pkg/net/http/transport.go b/src/net/http/transport.go
index b1cc632a7..782f7cd39 100644
--- a/src/pkg/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -43,17 +43,20 @@ var DefaultTransport RoundTripper = &Transport{
// MaxIdleConnsPerHost.
const DefaultMaxIdleConnsPerHost = 2
-// Transport is an implementation of RoundTripper that supports http,
-// https, and http proxies (for either http or https with CONNECT).
+// 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.
type Transport struct {
- idleMu sync.Mutex
- idleConn map[connectMethodKey][]*persistConn
- idleConnCh map[connectMethodKey]chan *persistConn
+ idleMu sync.Mutex
+ wantIdle bool // user has requested to close all idle conns
+ idleConn map[connectMethodKey][]*persistConn
+ idleConnCh map[connectMethodKey]chan *persistConn
+
reqMu sync.Mutex
reqCanceler map[*Request]func()
- altMu sync.RWMutex
- altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper
+
+ altMu sync.RWMutex
+ altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper
// Proxy specifies a function to return a proxy for a given
// Request. If the function returns a non-nil error, the
@@ -61,11 +64,22 @@ type Transport struct {
// If Proxy is nil or returns a nil *URL, no proxy is used.
Proxy func(*Request) (*url.URL, error)
- // Dial specifies the dial function for creating TCP
- // connections.
+ // Dial specifies the dial function for creating unencrypted
+ // TCP connections.
// If Dial is nil, net.Dial is used.
Dial func(network, addr string) (net.Conn, error)
+ // DialTLS specifies an optional dial function for creating
+ // TLS connections for non-proxied HTTPS requests.
+ //
+ // If DialTLS is nil, Dial and TLSClientConfig are used.
+ //
+ // If DialTLS is set, the Dial hook is not used for HTTPS
+ // requests and the TLSClientConfig and TLSHandshakeTimeout
+ // are ignored. The returned net.Conn is assumed to already be
+ // past the TLS handshake.
+ DialTLS func(network, addr string) (net.Conn, error)
+
// TLSClientConfig specifies the TLS configuration to use with
// tls.Client. If nil, the default configuration is used.
TLSClientConfig *tls.Config
@@ -105,15 +119,28 @@ type Transport struct {
// ProxyFromEnvironment returns the URL of the proxy to use for a
// given request, as indicated by the environment variables
-// $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy).
-// An error is returned if the proxy environment is invalid.
+// HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the lowercase versions
+// thereof). HTTPS_PROXY takes precedence over HTTP_PROXY for https
+// requests.
+//
+// The environment values may be either a complete URL or a
+// "host[:port]", in which case the "http" scheme is assumed.
+// An error is returned if the value is a different form.
+//
// A nil URL and nil error are returned if no proxy is defined in the
-// environment, or a proxy should not be used for the given request.
+// environment, or a proxy should not be used for the given request,
+// as defined by NO_PROXY.
//
// As a special case, if req.URL.Host is "localhost" (with or without
// a port number), then a nil URL and nil error will be returned.
func ProxyFromEnvironment(req *Request) (*url.URL, error) {
- proxy := httpProxyEnv.Get()
+ var proxy string
+ if req.URL.Scheme == "https" {
+ proxy = httpsProxyEnv.Get()
+ }
+ if proxy == "" {
+ proxy = httpProxyEnv.Get()
+ }
if proxy == "" {
return nil, nil
}
@@ -238,6 +265,7 @@ func (t *Transport) CloseIdleConnections() {
m := t.idleConn
t.idleConn = nil
t.idleConnCh = nil
+ t.wantIdle = true
t.idleMu.Unlock()
for _, conns := range m {
for _, pconn := range conns {
@@ -265,6 +293,9 @@ var (
httpProxyEnv = &envOnce{
names: []string{"HTTP_PROXY", "http_proxy"},
}
+ httpsProxyEnv = &envOnce{
+ names: []string{"HTTPS_PROXY", "https_proxy"},
+ }
noProxyEnv = &envOnce{
names: []string{"NO_PROXY", "no_proxy"},
}
@@ -305,7 +336,7 @@ func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectM
if t.Proxy != nil {
cm.proxyURL, err = t.Proxy(treq.Request)
}
- return cm, nil
+ return cm, err
}
// proxyAuth returns the Proxy-Authorization header to set
@@ -358,6 +389,11 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
delete(t.idleConnCh, key)
}
}
+ if t.wantIdle {
+ t.idleMu.Unlock()
+ pconn.close()
+ return false
+ }
if t.idleConn == nil {
t.idleConn = make(map[connectMethodKey][]*persistConn)
}
@@ -386,6 +422,7 @@ func (t *Transport) getIdleConnCh(cm connectMethod) chan *persistConn {
key := cm.key()
t.idleMu.Lock()
defer t.idleMu.Unlock()
+ t.wantIdle = false
if t.idleConnCh == nil {
t.idleConnCh = make(map[connectMethodKey]chan *persistConn)
}
@@ -444,6 +481,9 @@ func (t *Transport) dial(network, addr string) (c net.Conn, err error) {
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
@@ -460,9 +500,17 @@ func (t *Transport) getConn(req *Request, cm connectMethod) (*persistConn, error
dialc := make(chan dialRes)
handlePendingDial := func() {
- if v := <-dialc; v.err == nil {
- t.putIdleConn(v.pc)
+ if prePendingDial != nil {
+ prePendingDial()
}
+ go func() {
+ if v := <-dialc; v.err == nil {
+ t.putIdleConn(v.pc)
+ }
+ if postPendingDial != nil {
+ postPendingDial()
+ }
+ }()
}
cancelc := make(chan struct{})
@@ -484,53 +532,65 @@ func (t *Transport) getConn(req *Request, cm connectMethod) (*persistConn, error
// else's dial that they didn't use.
// But our dial is still going, so give it away
// when it finishes:
- go handlePendingDial()
+ handlePendingDial()
return pc, nil
case <-cancelc:
- go handlePendingDial()
+ handlePendingDial()
return nil, errors.New("net/http: request canceled while waiting for connection")
}
}
func (t *Transport) dialConn(cm connectMethod) (*persistConn, error) {
- conn, err := t.dial("tcp", cm.addr())
- if err != nil {
- if cm.proxyURL != nil {
- err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err)
- }
- return nil, err
- }
-
- pa := cm.proxyAuth()
-
pconn := &persistConn{
t: t,
cacheKey: cm.key(),
- conn: conn,
reqch: make(chan requestAndChan, 1),
writech: make(chan writeRequest, 1),
closech: make(chan struct{}),
writeErrCh: make(chan error, 1),
}
+ tlsDial := t.DialTLS != nil && cm.targetScheme == "https" && cm.proxyURL == nil
+ if tlsDial {
+ var err error
+ pconn.conn, err = t.DialTLS("tcp", cm.addr())
+ if err != nil {
+ return nil, err
+ }
+ if tc, ok := pconn.conn.(*tls.Conn); ok {
+ cs := tc.ConnectionState()
+ pconn.tlsState = &cs
+ }
+ } else {
+ conn, err := t.dial("tcp", cm.addr())
+ if err != nil {
+ if cm.proxyURL != nil {
+ err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err)
+ }
+ return nil, err
+ }
+ pconn.conn = conn
+ }
+ // Proxy setup.
switch {
case cm.proxyURL == nil:
- // Do nothing.
+ // Do nothing. Not using a proxy.
case cm.targetScheme == "http":
pconn.isProxy = true
- if pa != "" {
+ if pa := cm.proxyAuth(); pa != "" {
pconn.mutateHeaderFunc = func(h Header) {
h.Set("Proxy-Authorization", pa)
}
}
case cm.targetScheme == "https":
+ conn := pconn.conn
connectReq := &Request{
Method: "CONNECT",
URL: &url.URL{Opaque: cm.targetAddr},
Host: cm.targetAddr,
Header: make(Header),
}
- if pa != "" {
+ if pa := cm.proxyAuth(); pa != "" {
connectReq.Header.Set("Proxy-Authorization", pa)
}
connectReq.Write(conn)
@@ -551,7 +611,7 @@ func (t *Transport) dialConn(cm connectMethod) (*persistConn, error) {
}
}
- if cm.targetScheme == "https" {
+ if cm.targetScheme == "https" && !tlsDial {
// Initiate TLS and check remote host name against certificate.
cfg := t.TLSClientConfig
if cfg == nil || cfg.ServerName == "" {
@@ -564,7 +624,7 @@ func (t *Transport) dialConn(cm connectMethod) (*persistConn, error) {
cfg = &clone
}
}
- plainConn := conn
+ plainConn := pconn.conn
tlsConn := tls.Client(plainConn, cfg)
errc := make(chan error, 2)
var timer *time.Timer // for canceling TLS handshake
@@ -980,11 +1040,14 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
}
// Ask for a compressed version if the caller didn't set their
- // own value for Accept-Encoding. We only attempted to
+ // own value for Accept-Encoding. We only attempt to
// uncompress the gzip stream if we were the layer that
// requested it.
requestedGzip := false
- if !pc.t.DisableCompression && req.Header.Get("Accept-Encoding") == "" && req.Method != "HEAD" {
+ if !pc.t.DisableCompression &&
+ req.Header.Get("Accept-Encoding") == "" &&
+ req.Header.Get("Range") == "" &&
+ req.Method != "HEAD" {
// Request gzip only, not deflate. Deflate is ambiguous and
// not as universally supported anyway.
// See: http://www.gzip.org/zlib/zlib_faq.html#faq38
@@ -993,6 +1056,10 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
// due to a bug in nginx:
// http://trac.nginx.org/nginx/ticket/358
// http://golang.org/issue/5522
+ //
+ // We don't request gzip if the request is for a range, since
+ // auto-decoding a portion of a gzipped document will just fail
+ // anyway. See http://golang.org/issue/8923
requestedGzip = true
req.extraHeaders().Set("Accept-Encoding", "gzip")
}
diff --git a/src/pkg/net/http/transport_test.go b/src/net/http/transport_test.go
index 964ca0fca..defa63370 100644
--- a/src/pkg/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -1063,20 +1063,18 @@ func TestTransportConcurrency(t *testing.T) {
var wg sync.WaitGroup
wg.Add(numReqs)
- tr := &Transport{
- Dial: func(netw, addr string) (c net.Conn, err error) {
- // Due to the Transport's "socket late
- // binding" (see idleConnCh in transport.go),
- // the numReqs HTTP requests below can finish
- // with a dial still outstanding. So count
- // our dials as work too so the leak checker
- // doesn't complain at us.
- wg.Add(1)
- defer wg.Done()
- return net.Dial(netw, addr)
- },
- }
+ // Due to the Transport's "socket late binding" (see
+ // idleConnCh in transport.go), the numReqs HTTP requests
+ // below can finish with a dial still outstanding. To keep
+ // the leak checker happy, keep track of pending dials and
+ // wait for them to finish (and be closed or returned to the
+ // idle pool) before we close idle connections.
+ SetPendingDialHooks(func() { wg.Add(1) }, wg.Done)
+ defer SetPendingDialHooks(nil, nil)
+
+ tr := &Transport{}
defer tr.CloseIdleConnections()
+
c := &Client{Transport: tr}
reqs := make(chan string)
defer close(reqs)
@@ -1703,26 +1701,40 @@ Content-Length: %d
}
type proxyFromEnvTest struct {
- req string // URL to fetch; blank means "http://example.com"
- env string
- noenv string
+ req string // URL to fetch; blank means "http://example.com"
+
+ env string // HTTP_PROXY
+ httpsenv string // HTTPS_PROXY
+ noenv string // NO_RPXY
+
want string
wanterr error
}
func (t proxyFromEnvTest) String() string {
var buf bytes.Buffer
+ space := func() {
+ if buf.Len() > 0 {
+ buf.WriteByte(' ')
+ }
+ }
if t.env != "" {
fmt.Fprintf(&buf, "http_proxy=%q", t.env)
}
+ if t.httpsenv != "" {
+ space()
+ fmt.Fprintf(&buf, "https_proxy=%q", t.httpsenv)
+ }
if t.noenv != "" {
- fmt.Fprintf(&buf, " no_proxy=%q", t.noenv)
+ space()
+ fmt.Fprintf(&buf, "no_proxy=%q", t.noenv)
}
req := "http://example.com"
if t.req != "" {
req = t.req
}
- fmt.Fprintf(&buf, " req=%q", req)
+ space()
+ fmt.Fprintf(&buf, "req=%q", req)
return strings.TrimSpace(buf.String())
}
@@ -1733,7 +1745,15 @@ var proxyFromEnvTests = []proxyFromEnvTest{
{env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"},
{env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"},
{env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"},
+
+ // Don't use secure for http
+ {req: "http://insecure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://http.proxy.tld"},
+ // Use secure for https.
+ {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://secure.proxy.tld"},
+ {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "https://secure.proxy.tld", want: "https://secure.proxy.tld"},
+
{want: "<nil>"},
+
{noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
{noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
{noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
@@ -1745,6 +1765,7 @@ func TestProxyFromEnvironment(t *testing.T) {
ResetProxyEnv()
for _, tt := range proxyFromEnvTests {
os.Setenv("HTTP_PROXY", tt.env)
+ os.Setenv("HTTPS_PROXY", tt.httpsenv)
os.Setenv("NO_PROXY", tt.noenv)
ResetCachedEnvironment()
reqURL := tt.req
@@ -2098,6 +2119,136 @@ func TestTransportClosesBodyOnError(t *testing.T) {
}
}
+func TestTransportDialTLS(t *testing.T) {
+ var mu sync.Mutex // guards following
+ var gotReq, didDial bool
+
+ ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ mu.Lock()
+ gotReq = true
+ mu.Unlock()
+ }))
+ defer ts.Close()
+ tr := &Transport{
+ DialTLS: func(netw, addr string) (net.Conn, error) {
+ mu.Lock()
+ didDial = true
+ mu.Unlock()
+ c, err := tls.Dial(netw, addr, &tls.Config{
+ InsecureSkipVerify: true,
+ })
+ if err != nil {
+ return nil, err
+ }
+ return c, c.Handshake()
+ },
+ }
+ defer tr.CloseIdleConnections()
+ client := &Client{Transport: tr}
+ res, err := client.Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+ mu.Lock()
+ if !gotReq {
+ t.Error("didn't get request")
+ }
+ if !didDial {
+ t.Error("didn't use dial hook")
+ }
+}
+
+// Test for issue 8755
+// Ensure that if a proxy returns an error, it is exposed by RoundTrip
+func TestRoundTripReturnsProxyError(t *testing.T) {
+ badProxy := func(*http.Request) (*url.URL, error) {
+ return nil, errors.New("errorMessage")
+ }
+
+ tr := &Transport{Proxy: badProxy}
+
+ req, _ := http.NewRequest("GET", "http://example.com", nil)
+
+ _, err := tr.RoundTrip(req)
+
+ if err == nil {
+ t.Error("Expected proxy error to be returned by RoundTrip")
+ }
+}
+
+// tests that putting an idle conn after a call to CloseIdleConns does return it
+func TestTransportCloseIdleConnsThenReturn(t *testing.T) {
+ tr := &Transport{}
+ wantIdle := func(when string, n int) bool {
+ got := tr.IdleConnCountForTesting("|http|example.com") // key used by PutIdleTestConn
+ if got == n {
+ return true
+ }
+ t.Errorf("%s: idle conns = %d; want %d", when, got, n)
+ return false
+ }
+ wantIdle("start", 0)
+ if !tr.PutIdleTestConn() {
+ t.Fatal("put failed")
+ }
+ if !tr.PutIdleTestConn() {
+ t.Fatal("second put failed")
+ }
+ wantIdle("after put", 2)
+ tr.CloseIdleConnections()
+ if !tr.IsIdleForTesting() {
+ t.Error("should be idle after CloseIdleConnections")
+ }
+ wantIdle("after close idle", 0)
+ if tr.PutIdleTestConn() {
+ t.Fatal("put didn't fail")
+ }
+ wantIdle("after second put", 0)
+
+ tr.RequestIdleConnChForTesting() // should toggle the transport out of idle mode
+ if tr.IsIdleForTesting() {
+ t.Error("shouldn't be idle after RequestIdleConnChForTesting")
+ }
+ if !tr.PutIdleTestConn() {
+ t.Fatal("after re-activation")
+ }
+ wantIdle("after final put", 1)
+}
+
+// This tests that an client requesting a content range won't also
+// implicitly ask for gzip support. If they want that, they need to do it
+// on their own.
+// golang.org/issue/8923
+func TestTransportRangeAndGzip(t *testing.T) {
+ defer afterTest(t)
+ reqc := make(chan *Request, 1)
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ reqc <- r
+ }))
+ defer ts.Close()
+
+ req, _ := NewRequest("GET", ts.URL, nil)
+ req.Header.Set("Range", "bytes=7-11")
+ res, err := DefaultClient.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ select {
+ case r := <-reqc:
+ if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
+ t.Error("Transport advertised gzip support in the Accept header")
+ }
+ if r.Header.Get("Range") == "" {
+ t.Error("no Range in request")
+ }
+ case <-time.After(10 * time.Second):
+ t.Fatal("timeout")
+ }
+ res.Body.Close()
+}
+
func wantBody(res *http.Response, err error, want string) error {
if err != nil {
return err
diff --git a/src/pkg/net/http/triv.go b/src/net/http/triv.go
index 232d65089..232d65089 100644
--- a/src/pkg/net/http/triv.go
+++ b/src/net/http/triv.go
diff --git a/src/pkg/net/interface.go b/src/net/interface.go
index 2e9f1ebc6..2e9f1ebc6 100644
--- a/src/pkg/net/interface.go
+++ b/src/net/interface.go
diff --git a/src/pkg/net/interface_bsd.go b/src/net/interface_bsd.go
index 16775579d..16775579d 100644
--- a/src/pkg/net/interface_bsd.go
+++ b/src/net/interface_bsd.go
diff --git a/src/pkg/net/interface_bsd_test.go b/src/net/interface_bsd_test.go
index 88daf7393..88daf7393 100644
--- a/src/pkg/net/interface_bsd_test.go
+++ b/src/net/interface_bsd_test.go
diff --git a/src/pkg/net/interface_darwin.go b/src/net/interface_darwin.go
index ad0937db0..ad0937db0 100644
--- a/src/pkg/net/interface_darwin.go
+++ b/src/net/interface_darwin.go
diff --git a/src/pkg/net/interface_dragonfly.go b/src/net/interface_dragonfly.go
index c9ce5a7ac..c9ce5a7ac 100644
--- a/src/pkg/net/interface_dragonfly.go
+++ b/src/net/interface_dragonfly.go
diff --git a/src/pkg/net/interface_freebsd.go b/src/net/interface_freebsd.go
index 5df767910..5df767910 100644
--- a/src/pkg/net/interface_freebsd.go
+++ b/src/net/interface_freebsd.go
diff --git a/src/pkg/net/interface_linux.go b/src/net/interface_linux.go
index 1115d0fc4..1115d0fc4 100644
--- a/src/pkg/net/interface_linux.go
+++ b/src/net/interface_linux.go
diff --git a/src/pkg/net/interface_linux_test.go b/src/net/interface_linux_test.go
index d8800bd0c..d8800bd0c 100644
--- a/src/pkg/net/interface_linux_test.go
+++ b/src/net/interface_linux_test.go
diff --git a/src/pkg/net/interface_netbsd.go b/src/net/interface_netbsd.go
index c9ce5a7ac..c9ce5a7ac 100644
--- a/src/pkg/net/interface_netbsd.go
+++ b/src/net/interface_netbsd.go
diff --git a/src/pkg/net/interface_openbsd.go b/src/net/interface_openbsd.go
index c9ce5a7ac..c9ce5a7ac 100644
--- a/src/pkg/net/interface_openbsd.go
+++ b/src/net/interface_openbsd.go
diff --git a/src/pkg/net/interface_stub.go b/src/net/interface_stub.go
index c38fb7f76..c38fb7f76 100644
--- a/src/pkg/net/interface_stub.go
+++ b/src/net/interface_stub.go
diff --git a/src/pkg/net/interface_test.go b/src/net/interface_test.go
index efabb5f3c..efabb5f3c 100644
--- a/src/pkg/net/interface_test.go
+++ b/src/net/interface_test.go
diff --git a/src/pkg/net/interface_unix_test.go b/src/net/interface_unix_test.go
index 01f609f15..01f609f15 100644
--- a/src/pkg/net/interface_unix_test.go
+++ b/src/net/interface_unix_test.go
diff --git a/src/pkg/net/interface_windows.go b/src/net/interface_windows.go
index 0759dc255..0759dc255 100644
--- a/src/pkg/net/interface_windows.go
+++ b/src/net/interface_windows.go
diff --git a/src/pkg/net/ip.go b/src/net/ip.go
index 0582009b8..4a93e97b3 100644
--- a/src/pkg/net/ip.go
+++ b/src/net/ip.go
@@ -287,6 +287,7 @@ func (ip IP) String() string {
if j > i && j-i > e1-e0 {
e0 = i
e1 = j
+ i = j
}
}
// The symbol "::" MUST NOT be used to shorten just one 16 bit 0 field.
@@ -295,21 +296,23 @@ func (ip IP) String() string {
e1 = -1
}
+ const maxLen = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
+ b := make([]byte, 0, maxLen)
+
// Print with possible :: in place of run of zeros
- var s string
for i := 0; i < IPv6len; i += 2 {
if i == e0 {
- s += "::"
+ b = append(b, ':', ':')
i = e1
if i >= IPv6len {
break
}
} else if i > 0 {
- s += ":"
+ b = append(b, ':')
}
- s += itox((uint(p[i])<<8)|uint(p[i+1]), 1)
+ b = appendHex(b, (uint32(p[i])<<8)|uint32(p[i+1]))
}
- return s
+ return string(b)
}
// ipEmptyString is like ip.String except that it returns
@@ -419,14 +422,14 @@ func (m IPMask) Size() (ones, bits int) {
// String returns the hexadecimal form of m, with no punctuation.
func (m IPMask) String() string {
- s := ""
- for _, b := range m {
- s += itox(uint(b), 2)
- }
- if len(s) == 0 {
+ if len(m) == 0 {
return "<nil>"
}
- return s
+ buf := make([]byte, len(m)*2)
+ for i, b := range m {
+ buf[i*2], buf[i*2+1] = hexDigit[b>>4], hexDigit[b&0xf]
+ }
+ return string(buf)
}
func networkNumberAndMask(n *IPNet) (ip IP, m IPMask) {
@@ -646,11 +649,16 @@ func (e *ParseError) Error() string {
// If s is not a valid textual representation of an IP address,
// ParseIP returns nil.
func ParseIP(s string) IP {
- if ip := parseIPv4(s); ip != nil {
- return ip
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ case '.':
+ return parseIPv4(s)
+ case ':':
+ ip, _ := parseIPv6(s, false)
+ return ip
+ }
}
- ip, _ := parseIPv6(s, false)
- return ip
+ return nil
}
// ParseCIDR parses s as a CIDR notation IP address and mask,
diff --git a/src/pkg/net/ip_test.go b/src/net/ip_test.go
index ffeb9d315..485ff5115 100644
--- a/src/pkg/net/ip_test.go
+++ b/src/net/ip_test.go
@@ -44,6 +44,14 @@ func TestParseIP(t *testing.T) {
}
}
+func BenchmarkParseIP(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _, tt := range parseIPTests {
+ ParseIP(tt.in)
+ }
+ }
+}
+
// Issue 6339
func TestMarshalEmptyIP(t *testing.T) {
for _, in := range [][]byte{nil, []byte("")} {
@@ -91,6 +99,16 @@ func TestIPString(t *testing.T) {
}
}
+func BenchmarkIPString(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _, tt := range ipStringTests {
+ if tt.in != nil {
+ tt.in.String()
+ }
+ }
+ }
+}
+
var ipMaskTests = []struct {
in IP
mask IPMask
@@ -131,6 +149,14 @@ func TestIPMaskString(t *testing.T) {
}
}
+func BenchmarkIPMaskString(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _, tt := range ipMaskStringTests {
+ tt.in.String()
+ }
+ }
+}
+
var parseCIDRTests = []struct {
in string
ip IP
diff --git a/src/pkg/net/ipraw_test.go b/src/net/ipraw_test.go
index 0632dafc6..92dc8dc56 100644
--- a/src/pkg/net/ipraw_test.go
+++ b/src/net/ipraw_test.go
@@ -68,6 +68,11 @@ func skipRawSocketTest(t *testing.T) (skip bool, skipmsg string) {
}
func TestResolveIPAddr(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl":
+ t.Skipf("skipping test on %q", runtime.GOOS)
+ }
+
for _, tt := range resolveIPAddrTests {
addr, err := ResolveIPAddr(tt.net, tt.litAddrOrName)
if err != tt.err {
diff --git a/src/pkg/net/iprawsock.go b/src/net/iprawsock.go
index 5cc361390..5cc361390 100644
--- a/src/pkg/net/iprawsock.go
+++ b/src/net/iprawsock.go
diff --git a/src/pkg/net/iprawsock_plan9.go b/src/net/iprawsock_plan9.go
index e62d116b8..e62d116b8 100644
--- a/src/pkg/net/iprawsock_plan9.go
+++ b/src/net/iprawsock_plan9.go
diff --git a/src/pkg/net/iprawsock_posix.go b/src/net/iprawsock_posix.go
index bbb3f3ed6..99b081ba8 100644
--- a/src/pkg/net/iprawsock_posix.go
+++ b/src/net/iprawsock_posix.go
@@ -198,7 +198,7 @@ func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn,
if raddr == nil {
return nil, &OpError{Op: "dial", Net: netProto, Addr: nil, Err: errMissingAddress}
}
- fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
+ fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial")
if err != nil {
return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: err}
}
@@ -219,7 +219,7 @@ func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
default:
return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: UnknownNetworkError(netProto)}
}
- fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
+ fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen")
if err != nil {
return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: err}
}
diff --git a/src/pkg/net/ipsock.go b/src/net/ipsock.go
index dda857803..dda857803 100644
--- a/src/pkg/net/ipsock.go
+++ b/src/net/ipsock.go
diff --git a/src/pkg/net/ipsock_plan9.go b/src/net/ipsock_plan9.go
index 94ceea31b..94ceea31b 100644
--- a/src/pkg/net/ipsock_plan9.go
+++ b/src/net/ipsock_plan9.go
diff --git a/src/pkg/net/ipsock_posix.go b/src/net/ipsock_posix.go
index 2ba4c8efd..f9ebe40a2 100644
--- a/src/pkg/net/ipsock_posix.go
+++ b/src/net/ipsock_posix.go
@@ -132,9 +132,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, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
+func internetSocket(net string, laddr, raddr sockaddr, deadline time.Time, sotype, proto int, mode string) (fd *netFD, err error) {
family, ipv6only := favoriteAddrFamily(net, laddr, raddr, mode)
- return socket(net, family, sotype, proto, ipv6only, laddr, raddr, deadline, toAddr)
+ return socket(net, family, sotype, proto, ipv6only, laddr, raddr, deadline)
}
func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
diff --git a/src/pkg/net/ipsock_test.go b/src/net/ipsock_test.go
index 9ecaaec69..9ecaaec69 100644
--- a/src/pkg/net/ipsock_test.go
+++ b/src/net/ipsock_test.go
diff --git a/src/pkg/net/lookup.go b/src/net/lookup.go
index 20f20578c..aeffe6c9b 100644
--- a/src/pkg/net/lookup.go
+++ b/src/net/lookup.go
@@ -40,10 +40,16 @@ func lookupIPMerge(host string) (addrs []IP, err error) {
addrsi, err, shared := lookupGroup.Do(host, func() (interface{}, error) {
return lookupIP(host)
})
+ return lookupIPReturn(addrsi, err, shared)
+}
+
+// lookupIPReturn turns the return values from singleflight.Do into
+// the return values from LookupIP.
+func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IP, error) {
if err != nil {
return nil, err
}
- addrs = addrsi.([]IP)
+ addrs := addrsi.([]IP)
if shared {
clone := make([]IP, len(addrs))
copy(clone, addrs)
@@ -52,41 +58,40 @@ func lookupIPMerge(host string) (addrs []IP, err error) {
return addrs, nil
}
+// lookupIPDeadline looks up a hostname with a deadline.
func lookupIPDeadline(host string, deadline time.Time) (addrs []IP, err error) {
if deadline.IsZero() {
return lookupIPMerge(host)
}
- // TODO(bradfitz): consider pushing the deadline down into the
- // name resolution functions. But that involves fixing it for
- // the native Go resolver, cgo, Windows, etc.
- //
- // In the meantime, just use a goroutine. Most users affected
- // by http://golang.org/issue/2631 are due to TCP connections
- // to unresponsive hosts, not DNS.
+ // We could push the deadline down into the name resolution
+ // functions. However, the most commonly used implementation
+ // calls getaddrinfo, which has no timeout.
+
timeout := deadline.Sub(time.Now())
if timeout <= 0 {
- err = errTimeout
- return
+ return nil, errTimeout
}
t := time.NewTimer(timeout)
defer t.Stop()
- type res struct {
- addrs []IP
- err error
- }
- resc := make(chan res, 1)
- go func() {
- a, err := lookupIPMerge(host)
- resc <- res{a, err}
- }()
+
+ ch := lookupGroup.DoChan(host, func() (interface{}, error) {
+ return lookupIP(host)
+ })
+
select {
case <-t.C:
- err = errTimeout
- case r := <-resc:
- addrs, err = r.addrs, r.err
+ // The DNS lookup timed out for some reason. Force
+ // future requests to start the DNS lookup again
+ // rather than waiting for the current lookup to
+ // complete. See issue 8602.
+ lookupGroup.Forget(host)
+
+ return nil, errTimeout
+
+ case r := <-ch:
+ return lookupIPReturn(r.v, r.err, r.shared)
}
- return
}
// LookupPort looks up the port for the given network and service.
diff --git a/src/pkg/net/lookup_plan9.go b/src/net/lookup_plan9.go
index b80ac10e0..b80ac10e0 100644
--- a/src/pkg/net/lookup_plan9.go
+++ b/src/net/lookup_plan9.go
diff --git a/src/net/lookup_stub.go b/src/net/lookup_stub.go
new file mode 100644
index 000000000..502aafb27
--- /dev/null
+++ b/src/net/lookup_stub.go
@@ -0,0 +1,49 @@
+// 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 nacl
+
+package net
+
+import "syscall"
+
+func lookupProtocol(name string) (proto int, err error) {
+ return 0, syscall.ENOPROTOOPT
+}
+
+func lookupHost(host string) (addrs []string, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
+
+func lookupIP(host string) (ips []IP, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
+
+func lookupPort(network, service string) (port int, err error) {
+ return 0, syscall.ENOPROTOOPT
+}
+
+func lookupCNAME(name string) (cname string, err error) {
+ return "", syscall.ENOPROTOOPT
+}
+
+func lookupSRV(service, proto, name string) (cname string, srvs []*SRV, err error) {
+ return "", nil, syscall.ENOPROTOOPT
+}
+
+func lookupMX(name string) (mxs []*MX, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
+
+func lookupNS(name string) (nss []*NS, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
+
+func lookupTXT(name string) (txts []string, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
+
+func lookupAddr(addr string) (ptrs []string, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go
new file mode 100644
index 000000000..057e1322b
--- /dev/null
+++ b/src/net/lookup_test.go
@@ -0,0 +1,231 @@
+// 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.
+
+// TODO It would be nice to use a mock DNS server, to eliminate
+// external dependencies.
+
+package net
+
+import (
+ "flag"
+ "strings"
+ "testing"
+)
+
+var testExternal = flag.Bool("external", true, "allow use of external networks during long test")
+
+var lookupGoogleSRVTests = []struct {
+ service, proto, name string
+ cname, target string
+}{
+ {
+ "xmpp-server", "tcp", "google.com",
+ ".google.com", ".google.com",
+ },
+ {
+ "", "", "_xmpp-server._tcp.google.com", // non-standard back door
+ ".google.com", ".google.com",
+ },
+}
+
+func TestLookupGoogleSRV(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ for _, tt := range lookupGoogleSRVTests {
+ cname, srvs, err := LookupSRV(tt.service, tt.proto, tt.name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(srvs) == 0 {
+ t.Error("got no record")
+ }
+ if !strings.Contains(cname, tt.cname) {
+ t.Errorf("got %q; want %q", cname, tt.cname)
+ }
+ for _, srv := range srvs {
+ if !strings.Contains(srv.Target, tt.target) {
+ t.Errorf("got %v; want a record containing %q", srv, tt.target)
+ }
+ }
+ }
+}
+
+func TestLookupGmailMX(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ mxs, err := LookupMX("gmail.com")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(mxs) == 0 {
+ t.Error("got no record")
+ }
+ for _, mx := range mxs {
+ if !strings.Contains(mx.Host, ".google.com") {
+ t.Errorf("got %v; want a record containing .google.com.", mx)
+ }
+ }
+}
+
+func TestLookupGmailNS(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ nss, err := LookupNS("gmail.com")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(nss) == 0 {
+ t.Error("got no record")
+ }
+ for _, ns := range nss {
+ if !strings.Contains(ns.Host, ".google.com") {
+ t.Errorf("got %v; want a record containing .google.com.", ns)
+ }
+ }
+}
+
+func TestLookupGmailTXT(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ txts, err := LookupTXT("gmail.com")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(txts) == 0 {
+ t.Error("got no record")
+ }
+ for _, txt := range txts {
+ if !strings.Contains(txt, "spf") {
+ t.Errorf("got %q; want a spf record", txt)
+ }
+ }
+}
+
+var lookupGooglePublicDNSAddrs = []struct {
+ addr string
+ 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."},
+}
+
+func TestLookupGooglePublicDNSAddr(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ for _, tt := range lookupGooglePublicDNSAddrs {
+ names, err := LookupAddr(tt.addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(names) == 0 {
+ t.Error("got no record")
+ }
+ for _, name := range names {
+ if !strings.HasSuffix(name, tt.name) {
+ t.Errorf("got %q; want a record containing %q", name, tt.name)
+ }
+ }
+ }
+}
+
+func TestLookupIANACNAME(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ cname, err := LookupCNAME("www.iana.org")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !strings.HasSuffix(cname, ".icann.org.") {
+ t.Errorf("got %q; want a record containing .icann.org.", cname)
+ }
+}
+
+func TestLookupGoogleHost(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ addrs, err := LookupHost("google.com")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(addrs) == 0 {
+ t.Error("got no record")
+ }
+ for _, addr := range addrs {
+ if ParseIP(addr) == nil {
+ t.Errorf("got %q; want a literal ip address", addr)
+ }
+ }
+}
+
+func TestLookupGoogleIP(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ ips, err := LookupIP("google.com")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(ips) == 0 {
+ t.Error("got no record")
+ }
+ for _, ip := range ips {
+ if ip.To4() == nil && ip.To16() == nil {
+ t.Errorf("got %v; want an ip address", ip)
+ }
+ }
+}
+
+var revAddrTests = []struct {
+ Addr string
+ Reverse string
+ ErrPrefix string
+}{
+ {"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""},
+ {"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""},
+ {"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""},
+ {"::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", ""},
+ {"1::", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.ip6.arpa.", ""},
+ {"1234:567::89a:bcde", "e.d.c.b.a.9.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.7.6.5.0.4.3.2.1.ip6.arpa.", ""},
+ {"1234:567:fefe:bcbc:adad:9e4a:89a:bcde", "e.d.c.b.a.9.8.0.a.4.e.9.d.a.d.a.c.b.c.b.e.f.e.f.7.6.5.0.4.3.2.1.ip6.arpa.", ""},
+ {"1.2.3", "", "unrecognized address"},
+ {"1.2.3.4.5", "", "unrecognized address"},
+ {"1234:567:bcbca::89a:bcde", "", "unrecognized address"},
+ {"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"},
+}
+
+func TestReverseAddress(t *testing.T) {
+ for i, tt := range revAddrTests {
+ a, err := reverseaddr(tt.Addr)
+ if len(tt.ErrPrefix) > 0 && err == nil {
+ t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix)
+ continue
+ }
+ if len(tt.ErrPrefix) == 0 && err != nil {
+ t.Errorf("#%d: expected <nil>, got %q (error)", i, err)
+ }
+ if err != nil && err.(*DNSError).Err != tt.ErrPrefix {
+ t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err)
+ }
+ if a != tt.Reverse {
+ t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
+ }
+ }
+}
diff --git a/src/pkg/net/lookup_unix.go b/src/net/lookup_unix.go
index b1d2f8f31..a54578456 100644
--- a/src/pkg/net/lookup_unix.go
+++ b/src/net/lookup_unix.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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
package net
diff --git a/src/pkg/net/lookup_windows.go b/src/net/lookup_windows.go
index 130364231..6a925b0a7 100644
--- a/src/pkg/net/lookup_windows.go
+++ b/src/net/lookup_windows.go
@@ -210,14 +210,21 @@ func lookupCNAME(name string) (cname string, err error) {
defer releaseThread()
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
+ // 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
+ }
if e != nil {
return "", os.NewSyscallError("LookupCNAME", e)
}
defer syscall.DnsRecordListFree(r, 1)
- if r != nil && r.Type == syscall.DNS_TYPE_CNAME {
- v := (*syscall.DNSPTRData)(unsafe.Pointer(&r.Data[0]))
- cname = syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]) + "."
- }
+
+ resolved := resolveCNAME(syscall.StringToUTF16Ptr(name), r)
+ cname = syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(resolved))[:]) + "."
return
}
@@ -236,8 +243,9 @@ func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
return "", nil, os.NewSyscallError("LookupSRV", e)
}
defer syscall.DnsRecordListFree(r, 1)
+
addrs = make([]*SRV, 0, 10)
- for p := r; p != nil && p.Type == syscall.DNS_TYPE_SRV; p = p.Next {
+ for _, p := range validRecs(r, syscall.DNS_TYPE_SRV, target) {
v := (*syscall.DNSSRVData)(unsafe.Pointer(&p.Data[0]))
addrs = append(addrs, &SRV{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Target))[:]), v.Port, v.Priority, v.Weight})
}
@@ -254,8 +262,9 @@ func lookupMX(name string) (mx []*MX, err error) {
return nil, os.NewSyscallError("LookupMX", e)
}
defer syscall.DnsRecordListFree(r, 1)
+
mx = make([]*MX, 0, 10)
- for p := r; p != nil && p.Type == syscall.DNS_TYPE_MX; p = p.Next {
+ for _, p := range validRecs(r, syscall.DNS_TYPE_MX, name) {
v := (*syscall.DNSMXData)(unsafe.Pointer(&p.Data[0]))
mx = append(mx, &MX{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.NameExchange))[:]) + ".", v.Preference})
}
@@ -272,8 +281,9 @@ func lookupNS(name string) (ns []*NS, err error) {
return nil, os.NewSyscallError("LookupNS", e)
}
defer syscall.DnsRecordListFree(r, 1)
+
ns = make([]*NS, 0, 10)
- for p := r; p != nil && p.Type == syscall.DNS_TYPE_NS; p = p.Next {
+ for _, p := range validRecs(r, syscall.DNS_TYPE_NS, name) {
v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
ns = append(ns, &NS{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]) + "."})
}
@@ -289,9 +299,10 @@ func lookupTXT(name string) (txt []string, err error) {
return nil, os.NewSyscallError("LookupTXT", e)
}
defer syscall.DnsRecordListFree(r, 1)
+
txt = make([]string, 0, 10)
- if r != nil && r.Type == syscall.DNS_TYPE_TEXT {
- d := (*syscall.DNSTXTData)(unsafe.Pointer(&r.Data[0]))
+ for _, p := range validRecs(r, syscall.DNS_TYPE_TEXT, name) {
+ d := (*syscall.DNSTXTData)(unsafe.Pointer(&p.Data[0]))
for _, v := range (*[1 << 10]*uint16)(unsafe.Pointer(&(d.StringArray[0])))[:d.StringCount] {
s := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(v))[:])
txt = append(txt, s)
@@ -313,10 +324,58 @@ func lookupAddr(addr string) (name []string, err error) {
return nil, os.NewSyscallError("LookupAddr", e)
}
defer syscall.DnsRecordListFree(r, 1)
+
name = make([]string, 0, 10)
- for p := r; p != nil && p.Type == syscall.DNS_TYPE_PTR; p = p.Next {
+ for _, p := range validRecs(r, syscall.DNS_TYPE_PTR, arpa) {
v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
name = append(name, syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]))
}
return name, nil
}
+
+const dnsSectionMask = 0x0003
+
+// returns only results applicable to name and resolves CNAME entries
+func validRecs(r *syscall.DNSRecord, dnstype uint16, name string) []*syscall.DNSRecord {
+ cname := syscall.StringToUTF16Ptr(name)
+ if dnstype != syscall.DNS_TYPE_CNAME {
+ cname = resolveCNAME(cname, r)
+ }
+ rec := make([]*syscall.DNSRecord, 0, 10)
+ for p := r; p != nil; p = p.Next {
+ if p.Dw&dnsSectionMask != syscall.DnsSectionAnswer {
+ continue
+ }
+ if p.Type != dnstype {
+ continue
+ }
+ if !syscall.DnsNameCompare(cname, p.Name) {
+ continue
+ }
+ rec = append(rec, p)
+ }
+ return rec
+}
+
+// returns the last CNAME in chain
+func resolveCNAME(name *uint16, r *syscall.DNSRecord) *uint16 {
+ // limit cname resolving to 10 in case of a infinite CNAME loop
+Cname:
+ for cnameloop := 0; cnameloop < 10; cnameloop++ {
+ for p := r; p != nil; p = p.Next {
+ if p.Dw&dnsSectionMask != syscall.DnsSectionAnswer {
+ continue
+ }
+ if p.Type != syscall.DNS_TYPE_CNAME {
+ continue
+ }
+ if !syscall.DnsNameCompare(name, p.Name) {
+ continue
+ }
+ name = (*syscall.DNSPTRData)(unsafe.Pointer(&r.Data[0])).Host
+ continue Cname
+ }
+ break
+ }
+ return name
+}
diff --git a/src/net/lookup_windows_test.go b/src/net/lookup_windows_test.go
new file mode 100644
index 000000000..7495b5b57
--- /dev/null
+++ b/src/net/lookup_windows_test.go
@@ -0,0 +1,243 @@
+// 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 (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "os/exec"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+var nslookupTestServers = []string{"mail.golang.com", "gmail.com"}
+
+func toJson(v interface{}) string {
+ data, _ := json.Marshal(v)
+ return string(data)
+}
+
+func TestLookupMX(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+ for _, server := range nslookupTestServers {
+ mx, err := LookupMX(server)
+ if err != nil {
+ t.Errorf("failed %s: %s", server, err)
+ continue
+ }
+ if len(mx) == 0 {
+ t.Errorf("no results")
+ continue
+ }
+ expected, err := nslookupMX(server)
+ if err != nil {
+ t.Logf("skipping failed nslookup %s test: %s", server, err)
+ }
+ sort.Sort(byPrefAndHost(expected))
+ sort.Sort(byPrefAndHost(mx))
+ if !reflect.DeepEqual(expected, mx) {
+ t.Errorf("different results %s:\texp:%v\tgot:%v", server, toJson(expected), toJson(mx))
+ }
+ }
+}
+
+func TestLookupCNAME(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+ for _, server := range nslookupTestServers {
+ cname, err := LookupCNAME(server)
+ if err != nil {
+ t.Errorf("failed %s: %s", server, err)
+ continue
+ }
+ if cname == "" {
+ t.Errorf("no result %s", server)
+ }
+ expected, err := nslookupCNAME(server)
+ if err != nil {
+ t.Logf("skipping failed nslookup %s test: %s", server, err)
+ continue
+ }
+ if expected != cname {
+ t.Errorf("different results %s:\texp:%v\tgot:%v", server, expected, cname)
+ }
+ }
+}
+
+func TestLookupNS(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+ for _, server := range nslookupTestServers {
+ ns, err := LookupNS(server)
+ if err != nil {
+ t.Errorf("failed %s: %s", server, err)
+ continue
+ }
+ if len(ns) == 0 {
+ t.Errorf("no results")
+ continue
+ }
+ expected, err := nslookupNS(server)
+ if err != nil {
+ t.Logf("skipping failed nslookup %s test: %s", server, err)
+ continue
+ }
+ sort.Sort(byHost(expected))
+ sort.Sort(byHost(ns))
+ if !reflect.DeepEqual(expected, ns) {
+ t.Errorf("different results %s:\texp:%v\tgot:%v", toJson(server), toJson(expected), ns)
+ }
+ }
+}
+
+func TestLookupTXT(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+ for _, server := range nslookupTestServers {
+ txt, err := LookupTXT(server)
+ if err != nil {
+ t.Errorf("failed %s: %s", server, err)
+ continue
+ }
+ if len(txt) == 0 {
+ t.Errorf("no results")
+ continue
+ }
+ expected, err := nslookupTXT(server)
+ if err != nil {
+ t.Logf("skipping failed nslookup %s test: %s", server, err)
+ continue
+ }
+ sort.Strings(expected)
+ sort.Strings(txt)
+ if !reflect.DeepEqual(expected, txt) {
+ t.Errorf("different results %s:\texp:%v\tgot:%v", server, toJson(expected), toJson(txt))
+ }
+ }
+}
+
+type byPrefAndHost []*MX
+
+func (s byPrefAndHost) Len() int { return len(s) }
+func (s byPrefAndHost) Less(i, j int) bool {
+ if s[i].Pref != s[j].Pref {
+ return s[i].Pref < s[j].Pref
+ }
+ return s[i].Host < s[j].Host
+}
+func (s byPrefAndHost) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+type byHost []*NS
+
+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
+ cmd := exec.Command("nslookup", "-querytype="+qtype, name)
+ cmd.Stdout = &out
+ cmd.Stderr = &err
+ if err := cmd.Run(); err != nil {
+ return "", err
+ }
+ r := strings.Replace(out.String(), "\r\n", "\n", -1)
+ // nslookup stderr output contains also debug information such as
+ // "Non-authoritative answer" and it doesn't return the correct errcode
+ if strings.Contains(err.String(), "can't find") {
+ return r, errors.New(err.String())
+ }
+ return r, nil
+}
+
+func nslookupMX(name string) (mx []*MX, err error) {
+ var r string
+ if r, err = nslookup("mx", name); err != nil {
+ return
+ }
+ mx = make([]*MX, 0, 10)
+ // linux nslookup syntax
+ // 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)})
+ }
+ // 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)})
+ }
+ return
+}
+
+func nslookupNS(name string) (ns []*NS, err error) {
+ var r string
+ if r, err = nslookup("ns", name); err != nil {
+ return
+ }
+ ns = make([]*NS, 0, 10)
+ // 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])})
+ }
+ return
+}
+
+func nslookupCNAME(name string) (cname string, err error) {
+ var r string
+ if r, err = nslookup("cname", name); err != nil {
+ return
+ }
+ // mail.golang.com canonical name = golang.org.
+ rx := regexp.MustCompile(`(?m)^([a-z0-9.\-]+)\s+canonical name\s*=\s*([a-z0-9.\-]+)$`)
+ // assumes the last CNAME is the correct one
+ last := name
+ for _, ans := range rx.FindAllStringSubmatch(r, -1) {
+ last = ans[2]
+ }
+ return fqdn(last), nil
+}
+
+func nslookupTXT(name string) (txt []string, err error) {
+ var r string
+ if r, err = nslookup("txt", name); err != nil {
+ return
+ }
+ txt = make([]string, 0, 10)
+ // linux
+ // golang.org text = "v=spf1 redirect=_spf.google.com"
+
+ // windows
+ // golang.org text =
+ //
+ // "v=spf1 redirect=_spf.google.com"
+ rx := regexp.MustCompile(`(?m)^([a-z0-9.\-]+)\s+text\s*=\s*"(.*)"$`)
+ for _, ans := range rx.FindAllStringSubmatch(r, -1) {
+ txt = append(txt, ans[2])
+ }
+ return
+}
diff --git a/src/pkg/net/mac.go b/src/net/mac.go
index d616b1f68..d616b1f68 100644
--- a/src/pkg/net/mac.go
+++ b/src/net/mac.go
diff --git a/src/pkg/net/mac_test.go b/src/net/mac_test.go
index 8f9dc6685..8f9dc6685 100644
--- a/src/pkg/net/mac_test.go
+++ b/src/net/mac_test.go
diff --git a/src/pkg/net/mail/message.go b/src/net/mail/message.go
index ba0778caa..19aa888d8 100644
--- a/src/pkg/net/mail/message.go
+++ b/src/net/mail/message.go
@@ -28,6 +28,7 @@ import (
"strconv"
"strings"
"time"
+ "unicode"
)
var debug = debugT(false)
@@ -445,7 +446,7 @@ func decodeRFC2047Word(s string) (string, error) {
return "", errors.New("address not RFC 2047 encoded")
}
charset, enc := strings.ToLower(fields[1]), strings.ToLower(fields[2])
- if charset != "iso-8859-1" && charset != "utf-8" {
+ if charset != "us-ascii" && charset != "iso-8859-1" && charset != "utf-8" {
return "", fmt.Errorf("charset not supported: %q", charset)
}
@@ -466,6 +467,16 @@ func decodeRFC2047Word(s string) (string, error) {
}
switch charset {
+ case "us-ascii":
+ b := new(bytes.Buffer)
+ for _, c := range dec {
+ if c >= 0x80 {
+ b.WriteRune(unicode.ReplacementChar)
+ } else {
+ b.WriteRune(rune(c))
+ }
+ }
+ return b.String(), nil
case "iso-8859-1":
b := new(bytes.Buffer)
for _, c := range dec {
diff --git a/src/pkg/net/mail/message_test.go b/src/net/mail/message_test.go
index eb9c8cbdc..6ba48be04 100644
--- a/src/pkg/net/mail/message_test.go
+++ b/src/net/mail/message_test.go
@@ -194,6 +194,16 @@ func TestAddressParsing(t *testing.T) {
},
},
},
+ // RFC 2047 "Q"-encoded US-ASCII address. Dumb but legal.
+ {
+ `=?us-ascii?q?J=6Frg_Doe?= <joerg@example.com>`,
+ []*Address{
+ {
+ Name: `Jorg Doe`,
+ Address: "joerg@example.com",
+ },
+ },
+ },
// RFC 2047 "Q"-encoded UTF-8 address.
{
`=?utf-8?q?J=C3=B6rg_Doe?= <joerg@example.com>`,
diff --git a/src/pkg/net/mockicmp_test.go b/src/net/mockicmp_test.go
index e742365ea..e742365ea 100644
--- a/src/pkg/net/mockicmp_test.go
+++ b/src/net/mockicmp_test.go
diff --git a/src/pkg/net/mockserver_test.go b/src/net/mockserver_test.go
index 68ded5d75..68ded5d75 100644
--- a/src/pkg/net/mockserver_test.go
+++ b/src/net/mockserver_test.go
diff --git a/src/pkg/net/multicast_test.go b/src/net/multicast_test.go
index 63dbce88e..5f253f44a 100644
--- a/src/pkg/net/multicast_test.go
+++ b/src/net/multicast_test.go
@@ -25,7 +25,7 @@ var ipv4MulticastListenerTests = []struct {
// port.
func TestIPv4MulticastListener(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "android", "nacl", "plan9":
t.Skipf("skipping test on %q", runtime.GOOS)
case "solaris":
t.Skipf("skipping test on solaris, see issue 7399")
diff --git a/src/pkg/net/net.go b/src/net/net.go
index ca56af54f..cb31af5e3 100644
--- a/src/pkg/net/net.go
+++ b/src/net/net.go
@@ -32,7 +32,6 @@ The Listen function creates servers:
conn, err := ln.Accept()
if err != nil {
// handle error
- continue
}
go handleConnection(conn)
}
diff --git a/src/pkg/net/net_test.go b/src/net/net_test.go
index bfed4d657..bfed4d657 100644
--- a/src/pkg/net/net_test.go
+++ b/src/net/net_test.go
diff --git a/src/pkg/net/net_windows_test.go b/src/net/net_windows_test.go
index 750a4304b..750a4304b 100644
--- a/src/pkg/net/net_windows_test.go
+++ b/src/net/net_windows_test.go
diff --git a/src/pkg/net/netgo_unix_test.go b/src/net/netgo_unix_test.go
index 9fb2a567d..9fb2a567d 100644
--- a/src/pkg/net/netgo_unix_test.go
+++ b/src/net/netgo_unix_test.go
diff --git a/src/pkg/net/packetconn_test.go b/src/net/packetconn_test.go
index b6e4e76f9..b6e4e76f9 100644
--- a/src/pkg/net/packetconn_test.go
+++ b/src/net/packetconn_test.go
diff --git a/src/pkg/net/parse.go b/src/net/parse.go
index ee6e7e995..e1d0130c9 100644
--- a/src/pkg/net/parse.go
+++ b/src/net/parse.go
@@ -210,18 +210,18 @@ func itod(i uint) string {
return string(b[bp:])
}
-// Convert i to hexadecimal string.
-func itox(i uint, min int) string {
- // Assemble hexadecimal in reverse order.
- var b [32]byte
- bp := len(b)
- for ; i > 0 || min > 0; i /= 16 {
- bp--
- b[bp] = "0123456789abcdef"[byte(i%16)]
- min--
+// Convert i to a hexadecimal string. Leading zeros are not printed.
+func appendHex(dst []byte, i uint32) []byte {
+ if i == 0 {
+ return append(dst, '0')
}
-
- return string(b[bp:])
+ for j := 7; j >= 0; j-- {
+ v := i >> uint(j*4)
+ if v > 0 {
+ dst = append(dst, hexDigit[v&0xf])
+ }
+ }
+ return dst
}
// Number of occurrences of b in s.
diff --git a/src/pkg/net/parse_test.go b/src/net/parse_test.go
index b86bc3288..7b213b75b 100644
--- a/src/pkg/net/parse_test.go
+++ b/src/net/parse_test.go
@@ -12,9 +12,9 @@ import (
)
func TestReadLine(t *testing.T) {
- // /etc/services file does not exist on windows and Plan 9.
+ // /etc/services file does not exist on android, plan9, windows.
switch runtime.GOOS {
- case "plan9", "windows":
+ case "android", "plan9", "windows":
t.Skipf("skipping test on %q", runtime.GOOS)
}
filename := "/etc/services" // a nice big file
diff --git a/src/pkg/net/pipe.go b/src/net/pipe.go
index f1a2eca4e..f1a2eca4e 100644
--- a/src/pkg/net/pipe.go
+++ b/src/net/pipe.go
diff --git a/src/pkg/net/pipe_test.go b/src/net/pipe_test.go
index afe4f2408..afe4f2408 100644
--- a/src/pkg/net/pipe_test.go
+++ b/src/net/pipe_test.go
diff --git a/src/pkg/net/port.go b/src/net/port.go
index c24f4ed5b..c24f4ed5b 100644
--- a/src/pkg/net/port.go
+++ b/src/net/port.go
diff --git a/src/pkg/net/port_test.go b/src/net/port_test.go
index 9e8968f35..4811ade69 100644
--- a/src/pkg/net/port_test.go
+++ b/src/net/port_test.go
@@ -5,6 +5,7 @@
package net
import (
+ "runtime"
"testing"
)
@@ -43,6 +44,11 @@ var porttests = []portTest{
}
func TestLookupPort(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl":
+ t.Skipf("skipping test on %q", runtime.GOOS)
+ }
+
for i := 0; i < len(porttests); i++ {
tt := porttests[i]
if port, err := LookupPort(tt.netw, tt.name); port != tt.port || (err == nil) != tt.ok {
diff --git a/src/pkg/net/port_unix.go b/src/net/port_unix.go
index 89558c1f0..348c771c3 100644
--- a/src/pkg/net/port_unix.go
+++ b/src/net/port_unix.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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// Read system port mappings from /etc/services
diff --git a/src/pkg/net/protoconn_test.go b/src/net/protoconn_test.go
index 12856b6c3..12856b6c3 100644
--- a/src/pkg/net/protoconn_test.go
+++ b/src/net/protoconn_test.go
diff --git a/src/pkg/net/race.go b/src/net/race.go
index 2f02a6c22..2f02a6c22 100644
--- a/src/pkg/net/race.go
+++ b/src/net/race.go
diff --git a/src/pkg/net/race0.go b/src/net/race0.go
index f50429779..f50429779 100644
--- a/src/pkg/net/race0.go
+++ b/src/net/race0.go
diff --git a/src/pkg/net/rpc/client.go b/src/net/rpc/client.go
index 21f79b068..d0c4a6921 100644
--- a/src/pkg/net/rpc/client.go
+++ b/src/net/rpc/client.go
@@ -41,10 +41,10 @@ type Call struct {
type Client struct {
codec ClientCodec
- sending sync.Mutex
+ reqMutex sync.Mutex // protects following
+ request Request
mutex sync.Mutex // protects following
- request Request
seq uint64
pending map[uint64]*Call
closing bool // user has called Close
@@ -69,8 +69,8 @@ type ClientCodec interface {
}
func (client *Client) send(call *Call) {
- client.sending.Lock()
- defer client.sending.Unlock()
+ client.reqMutex.Lock()
+ defer client.reqMutex.Unlock()
// Register this call.
client.mutex.Lock()
@@ -146,7 +146,7 @@ func (client *Client) input() {
}
}
// Terminate pending calls.
- client.sending.Lock()
+ client.reqMutex.Lock()
client.mutex.Lock()
client.shutdown = true
closing := client.closing
@@ -162,7 +162,7 @@ func (client *Client) input() {
call.done()
}
client.mutex.Unlock()
- client.sending.Unlock()
+ client.reqMutex.Unlock()
if debugLog && err != io.EOF && !closing {
log.Println("rpc: client protocol error:", err)
}
diff --git a/src/net/rpc/client_test.go b/src/net/rpc/client_test.go
new file mode 100644
index 000000000..5dd111b29
--- /dev/null
+++ b/src/net/rpc/client_test.go
@@ -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.
+
+package rpc
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "runtime"
+ "strings"
+ "testing"
+)
+
+type shutdownCodec struct {
+ responded chan int
+ closed bool
+}
+
+func (c *shutdownCodec) WriteRequest(*Request, interface{}) error { return nil }
+func (c *shutdownCodec) ReadResponseBody(interface{}) error { return nil }
+func (c *shutdownCodec) ReadResponseHeader(*Response) error {
+ c.responded <- 1
+ return errors.New("shutdownCodec ReadResponseHeader")
+}
+func (c *shutdownCodec) Close() error {
+ c.closed = true
+ return nil
+}
+
+func TestCloseCodec(t *testing.T) {
+ codec := &shutdownCodec{responded: make(chan int)}
+ client := NewClientWithCodec(codec)
+ <-codec.responded
+ client.Close()
+ if !codec.closed {
+ t.Error("client.Close did not close codec")
+ }
+}
+
+// Test that errors in gob shut down the connection. Issue 7689.
+
+type R struct {
+ msg []byte // Not exported, so R does not work with gob.
+}
+
+type S struct{}
+
+func (s *S) Recv(nul *struct{}, reply *R) error {
+ *reply = R{[]byte("foo")}
+ return nil
+}
+
+func TestGobError(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ t.Skip("skipping test; see http://golang.org/issue/8908")
+ }
+ defer func() {
+ err := recover()
+ if err == nil {
+ t.Fatal("no error")
+ }
+ if !strings.Contains("reading body EOF", err.(error).Error()) {
+ t.Fatal("expected `reading body EOF', got", err)
+ }
+ }()
+ Register(new(S))
+
+ listen, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ panic(err)
+ }
+ go Accept(listen)
+
+ client, err := Dial("tcp", listen.Addr().String())
+ if err != nil {
+ panic(err)
+ }
+
+ var reply Reply
+ err = client.Call("S.Recv", &struct{}{}, &reply)
+ if err != nil {
+ panic(err)
+ }
+
+ fmt.Printf("%#v\n", reply)
+ client.Close()
+
+ listen.Close()
+}
diff --git a/src/pkg/net/rpc/debug.go b/src/net/rpc/debug.go
index 926466d62..98b2c1c6c 100644
--- a/src/pkg/net/rpc/debug.go
+++ b/src/net/rpc/debug.go
@@ -11,9 +11,9 @@ package rpc
import (
"fmt"
+ "html/template"
"net/http"
"sort"
- "text/template"
)
const debugText = `<html>
diff --git a/src/pkg/net/rpc/jsonrpc/all_test.go b/src/net/rpc/jsonrpc/all_test.go
index a433a365e..a433a365e 100644
--- a/src/pkg/net/rpc/jsonrpc/all_test.go
+++ b/src/net/rpc/jsonrpc/all_test.go
diff --git a/src/pkg/net/rpc/jsonrpc/client.go b/src/net/rpc/jsonrpc/client.go
index 2194f2125..2194f2125 100644
--- a/src/pkg/net/rpc/jsonrpc/client.go
+++ b/src/net/rpc/jsonrpc/client.go
diff --git a/src/pkg/net/rpc/jsonrpc/server.go b/src/net/rpc/jsonrpc/server.go
index e6d37cfa6..e6d37cfa6 100644
--- a/src/pkg/net/rpc/jsonrpc/server.go
+++ b/src/net/rpc/jsonrpc/server.go
diff --git a/src/pkg/net/rpc/server.go b/src/net/rpc/server.go
index 6b264b46b..83728d55a 100644
--- a/src/pkg/net/rpc/server.go
+++ b/src/net/rpc/server.go
@@ -395,6 +395,7 @@ type gobServerCodec struct {
dec *gob.Decoder
enc *gob.Encoder
encBuf *bufio.Writer
+ closed bool
}
func (c *gobServerCodec) ReadRequestHeader(r *Request) error {
@@ -407,15 +408,32 @@ func (c *gobServerCodec) ReadRequestBody(body interface{}) error {
func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) (err error) {
if err = c.enc.Encode(r); err != nil {
+ if c.encBuf.Flush() == nil {
+ // Gob couldn't encode the header. Should not happen, so if it does,
+ // shut down the connection to signal that the connection is broken.
+ log.Println("rpc: gob error encoding response:", err)
+ c.Close()
+ }
return
}
if err = c.enc.Encode(body); err != nil {
+ if c.encBuf.Flush() == nil {
+ // Was a gob problem encoding the body but the header has been written.
+ // Shut down the connection to signal that the connection is broken.
+ log.Println("rpc: gob error encoding body:", err)
+ c.Close()
+ }
return
}
return c.encBuf.Flush()
}
func (c *gobServerCodec) Close() error {
+ if c.closed {
+ // Only call c.rwc.Close once; otherwise the semantics are undefined.
+ return nil
+ }
+ c.closed = true
return c.rwc.Close()
}
@@ -426,7 +444,12 @@ func (c *gobServerCodec) Close() error {
// connection. To use an alternate codec, use ServeCodec.
func (server *Server) ServeConn(conn io.ReadWriteCloser) {
buf := bufio.NewWriter(conn)
- srv := &gobServerCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(buf), buf}
+ srv := &gobServerCodec{
+ rwc: conn,
+ dec: gob.NewDecoder(conn),
+ enc: gob.NewEncoder(buf),
+ encBuf: buf,
+ }
server.ServeCodec(srv)
}
diff --git a/src/pkg/net/rpc/server_test.go b/src/net/rpc/server_test.go
index 0dc4ddc2d..0dc4ddc2d 100644
--- a/src/pkg/net/rpc/server_test.go
+++ b/src/net/rpc/server_test.go
diff --git a/src/pkg/net/sendfile_dragonfly.go b/src/net/sendfile_dragonfly.go
index bc88fd3b9..bc88fd3b9 100644
--- a/src/pkg/net/sendfile_dragonfly.go
+++ b/src/net/sendfile_dragonfly.go
diff --git a/src/pkg/net/sendfile_freebsd.go b/src/net/sendfile_freebsd.go
index ffc147262..ffc147262 100644
--- a/src/pkg/net/sendfile_freebsd.go
+++ b/src/net/sendfile_freebsd.go
diff --git a/src/pkg/net/sendfile_linux.go b/src/net/sendfile_linux.go
index 5e117636a..5e117636a 100644
--- a/src/pkg/net/sendfile_linux.go
+++ b/src/net/sendfile_linux.go
diff --git a/src/pkg/net/sendfile_stub.go b/src/net/sendfile_stub.go
index 03426ef0d..03426ef0d 100644
--- a/src/pkg/net/sendfile_stub.go
+++ b/src/net/sendfile_stub.go
diff --git a/src/pkg/net/sendfile_windows.go b/src/net/sendfile_windows.go
index b128ba27b..b128ba27b 100644
--- a/src/pkg/net/sendfile_windows.go
+++ b/src/net/sendfile_windows.go
diff --git a/src/pkg/net/server_test.go b/src/net/server_test.go
index 6a2bb9243..6a2bb9243 100644
--- a/src/pkg/net/server_test.go
+++ b/src/net/server_test.go
diff --git a/src/net/singleflight.go b/src/net/singleflight.go
new file mode 100644
index 000000000..bf599f0cc
--- /dev/null
+++ b/src/net/singleflight.go
@@ -0,0 +1,109 @@
+// 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 net
+
+import "sync"
+
+// call is an in-flight or completed singleflight.Do call
+type call struct {
+ wg sync.WaitGroup
+
+ // These fields are written once before the WaitGroup is done
+ // and are only read after the WaitGroup is done.
+ val interface{}
+ err error
+
+ // These fields are read and written with the singleflight
+ // mutex held before the WaitGroup is done, and are read but
+ // not written after the WaitGroup is done.
+ dups int
+ chans []chan<- singleflightResult
+}
+
+// singleflight represents a class of work and forms a namespace in
+// which units of work can be executed with duplicate suppression.
+type singleflight struct {
+ mu sync.Mutex // protects m
+ m map[string]*call // lazily initialized
+}
+
+// singleflightResult holds the results of Do, so they can be passed
+// on a channel.
+type singleflightResult struct {
+ v interface{}
+ err error
+ shared bool
+}
+
+// Do executes and returns the results of the given function, making
+// sure that only one execution is in-flight for a given key at a
+// time. If a duplicate comes in, the duplicate caller waits for the
+// original to complete and receives the same results.
+// The return value shared indicates whether v was given to multiple callers.
+func (g *singleflight) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) {
+ g.mu.Lock()
+ if g.m == nil {
+ g.m = make(map[string]*call)
+ }
+ if c, ok := g.m[key]; ok {
+ c.dups++
+ g.mu.Unlock()
+ c.wg.Wait()
+ return c.val, c.err, true
+ }
+ c := new(call)
+ c.wg.Add(1)
+ g.m[key] = c
+ g.mu.Unlock()
+
+ g.doCall(c, key, fn)
+ return c.val, c.err, c.dups > 0
+}
+
+// DoChan is like Do but returns a channel that will receive the
+// results when they are ready.
+func (g *singleflight) DoChan(key string, fn func() (interface{}, error)) <-chan singleflightResult {
+ ch := make(chan singleflightResult, 1)
+ g.mu.Lock()
+ if g.m == nil {
+ g.m = make(map[string]*call)
+ }
+ if c, ok := g.m[key]; ok {
+ c.dups++
+ c.chans = append(c.chans, ch)
+ g.mu.Unlock()
+ return ch
+ }
+ c := &call{chans: []chan<- singleflightResult{ch}}
+ c.wg.Add(1)
+ g.m[key] = c
+ g.mu.Unlock()
+
+ go g.doCall(c, key, fn)
+
+ return ch
+}
+
+// doCall handles the single call for a key.
+func (g *singleflight) doCall(c *call, key string, fn func() (interface{}, error)) {
+ c.val, c.err = fn()
+ c.wg.Done()
+
+ g.mu.Lock()
+ delete(g.m, key)
+ for _, ch := range c.chans {
+ ch <- singleflightResult{c.val, c.err, c.dups > 0}
+ }
+ g.mu.Unlock()
+}
+
+// Forget tells the singleflight to forget about a key. Future calls
+// to Do for this key will call the function rather than waiting for
+// an earlier call to complete.
+func (g *singleflight) Forget(key string) {
+ g.mu.Lock()
+ delete(g.m, key)
+ g.mu.Unlock()
+}
diff --git a/src/pkg/net/smtp/auth.go b/src/net/smtp/auth.go
index 3f1339ebc..3f1339ebc 100644
--- a/src/pkg/net/smtp/auth.go
+++ b/src/net/smtp/auth.go
diff --git a/src/pkg/net/smtp/example_test.go b/src/net/smtp/example_test.go
index d551e365a..d551e365a 100644
--- a/src/pkg/net/smtp/example_test.go
+++ b/src/net/smtp/example_test.go
diff --git a/src/pkg/net/smtp/smtp.go b/src/net/smtp/smtp.go
index 87dea442c..87dea442c 100644
--- a/src/pkg/net/smtp/smtp.go
+++ b/src/net/smtp/smtp.go
diff --git a/src/pkg/net/smtp/smtp_test.go b/src/net/smtp/smtp_test.go
index 3fba1ea5a..5c659e8a0 100644
--- a/src/pkg/net/smtp/smtp_test.go
+++ b/src/net/smtp/smtp_test.go
@@ -669,7 +669,7 @@ func sendMail(hostPort string) error {
// 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/pkg/crypto/tls:
+// generated from src/crypto/tls:
// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
diff --git a/src/pkg/net/sock_bsd.go b/src/net/sock_bsd.go
index 48fb78527..6c37109f5 100644
--- a/src/pkg/net/sock_bsd.go
+++ b/src/net/sock_bsd.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 darwin dragonfly freebsd nacl netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
package net
diff --git a/src/pkg/net/sock_cloexec.go b/src/net/sock_cloexec.go
index dec81855b..dec81855b 100644
--- a/src/pkg/net/sock_cloexec.go
+++ b/src/net/sock_cloexec.go
diff --git a/src/pkg/net/sock_linux.go b/src/net/sock_linux.go
index cc5ce153b..cc5ce153b 100644
--- a/src/pkg/net/sock_linux.go
+++ b/src/net/sock_linux.go
diff --git a/src/pkg/net/sock_plan9.go b/src/net/sock_plan9.go
index 88d9ed15c..88d9ed15c 100644
--- a/src/pkg/net/sock_plan9.go
+++ b/src/net/sock_plan9.go
diff --git a/src/pkg/net/sock_posix.go b/src/net/sock_posix.go
index c80c7d6a2..3f956df65 100644
--- a/src/pkg/net/sock_posix.go
+++ b/src/net/sock_posix.go
@@ -36,7 +36,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, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
+func socket(net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, deadline time.Time) (fd *netFD, err error) {
s, err := sysSocket(family, sotype, proto)
if err != nil {
return nil, err
@@ -75,27 +75,51 @@ func socket(net string, family, sotype, proto int, ipv6only bool, laddr, raddr s
if laddr != nil && raddr == nil {
switch sotype {
case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET:
- if err := fd.listenStream(laddr, listenerBacklog, toAddr); err != nil {
+ if err := fd.listenStream(laddr, listenerBacklog); err != nil {
fd.Close()
return nil, err
}
return fd, nil
case syscall.SOCK_DGRAM:
- if err := fd.listenDatagram(laddr, toAddr); err != nil {
+ if err := fd.listenDatagram(laddr); err != nil {
fd.Close()
return nil, err
}
return fd, nil
}
}
- if err := fd.dial(laddr, raddr, deadline, toAddr); err != nil {
+ if err := fd.dial(laddr, raddr, deadline); err != nil {
fd.Close()
return nil, err
}
return fd, nil
}
-func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) error {
+func (fd *netFD) addrFunc() func(syscall.Sockaddr) Addr {
+ switch fd.family {
+ case syscall.AF_INET, syscall.AF_INET6:
+ switch fd.sotype {
+ case syscall.SOCK_STREAM:
+ return sockaddrToTCP
+ case syscall.SOCK_DGRAM:
+ return sockaddrToUDP
+ case syscall.SOCK_RAW:
+ return sockaddrToIP
+ }
+ case syscall.AF_UNIX:
+ switch fd.sotype {
+ case syscall.SOCK_STREAM:
+ return sockaddrToUnix
+ case syscall.SOCK_DGRAM:
+ return sockaddrToUnixgram
+ case syscall.SOCK_SEQPACKET:
+ return sockaddrToUnixpacket
+ }
+ }
+ return func(syscall.Sockaddr) Addr { return nil }
+}
+
+func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time) error {
var err error
var lsa syscall.Sockaddr
if laddr != nil {
@@ -123,14 +147,14 @@ func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time, toAddr func(sys
}
lsa, _ = syscall.Getsockname(fd.sysfd)
if rsa, _ = syscall.Getpeername(fd.sysfd); rsa != nil {
- fd.setAddr(toAddr(lsa), toAddr(rsa))
+ fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa))
} else {
- fd.setAddr(toAddr(lsa), raddr)
+ fd.setAddr(fd.addrFunc()(lsa), raddr)
}
return nil
}
-func (fd *netFD) listenStream(laddr sockaddr, backlog int, toAddr func(syscall.Sockaddr) Addr) error {
+func (fd *netFD) listenStream(laddr sockaddr, backlog int) error {
if err := setDefaultListenerSockopts(fd.sysfd); err != nil {
return err
}
@@ -148,11 +172,11 @@ func (fd *netFD) listenStream(laddr sockaddr, backlog int, toAddr func(syscall.S
return err
}
lsa, _ := syscall.Getsockname(fd.sysfd)
- fd.setAddr(toAddr(lsa), nil)
+ fd.setAddr(fd.addrFunc()(lsa), nil)
return nil
}
-func (fd *netFD) listenDatagram(laddr sockaddr, toAddr func(syscall.Sockaddr) Addr) error {
+func (fd *netFD) listenDatagram(laddr sockaddr) error {
switch addr := laddr.(type) {
case *UDPAddr:
// We provide a socket that listens to a wildcard
@@ -187,6 +211,6 @@ func (fd *netFD) listenDatagram(laddr sockaddr, toAddr func(syscall.Sockaddr) Ad
return err
}
lsa, _ := syscall.Getsockname(fd.sysfd)
- fd.setAddr(toAddr(lsa), nil)
+ fd.setAddr(fd.addrFunc()(lsa), nil)
return nil
}
diff --git a/src/pkg/net/sock_solaris.go b/src/net/sock_stub.go
index 90fe9de89..ed6b08948 100644
--- a/src/pkg/net/sock_solaris.go
+++ b/src/net/sock_stub.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 nacl solaris
+
package net
import "syscall"
diff --git a/src/pkg/net/sock_windows.go b/src/net/sock_windows.go
index 6ccde3a24..6ccde3a24 100644
--- a/src/pkg/net/sock_windows.go
+++ b/src/net/sock_windows.go
diff --git a/src/pkg/net/sockopt_bsd.go b/src/net/sockopt_bsd.go
index 77d51d737..00e4dbf37 100644
--- a/src/pkg/net/sockopt_bsd.go
+++ b/src/net/sockopt_bsd.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 darwin dragonfly freebsd nacl netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
package net
@@ -17,7 +17,7 @@ func setDefaultSockopts(s, family, sotype int, ipv6only bool) error {
// On DragonFly BSD, we adjust the ephemeral port
// range because unlike other BSD systems its default
// port range doesn't conform to IANA recommendation
- // as described in RFC 6355 and is pretty narrow.
+ // as described in RFC 6056 and is pretty narrow.
switch family {
case syscall.AF_INET:
syscall.SetsockoptInt(s, syscall.IPPROTO_IP, syscall.IP_PORTRANGE, syscall.IP_PORTRANGE_HIGH)
diff --git a/src/pkg/net/sockopt_linux.go b/src/net/sockopt_linux.go
index 54c20b140..54c20b140 100644
--- a/src/pkg/net/sockopt_linux.go
+++ b/src/net/sockopt_linux.go
diff --git a/src/pkg/net/sockopt_plan9.go b/src/net/sockopt_plan9.go
index 8bc689b6c..8bc689b6c 100644
--- a/src/pkg/net/sockopt_plan9.go
+++ b/src/net/sockopt_plan9.go
diff --git a/src/pkg/net/sockopt_posix.go b/src/net/sockopt_posix.go
index 921918c37..1654d1b85 100644
--- a/src/pkg/net/sockopt_posix.go
+++ b/src/net/sockopt_posix.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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package net
diff --git a/src/pkg/net/sockopt_solaris.go b/src/net/sockopt_solaris.go
index 54c20b140..54c20b140 100644
--- a/src/pkg/net/sockopt_solaris.go
+++ b/src/net/sockopt_solaris.go
diff --git a/src/net/sockopt_stub.go b/src/net/sockopt_stub.go
new file mode 100644
index 000000000..de5ee0bb6
--- /dev/null
+++ b/src/net/sockopt_stub.go
@@ -0,0 +1,37 @@
+// 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 nacl
+
+package net
+
+import "syscall"
+
+func setDefaultSockopts(s, family, sotype int, ipv6only bool) error {
+ return nil
+}
+
+func setDefaultListenerSockopts(s int) error {
+ return nil
+}
+
+func setDefaultMulticastSockopts(s int) error {
+ return nil
+}
+
+func setReadBuffer(fd *netFD, bytes int) error {
+ return syscall.ENOPROTOOPT
+}
+
+func setWriteBuffer(fd *netFD, bytes int) error {
+ return syscall.ENOPROTOOPT
+}
+
+func setKeepAlive(fd *netFD, keepalive bool) error {
+ return syscall.ENOPROTOOPT
+}
+
+func setLinger(fd *netFD, sec int) error {
+ return syscall.ENOPROTOOPT
+}
diff --git a/src/pkg/net/sockopt_windows.go b/src/net/sockopt_windows.go
index cb64a40c6..cb64a40c6 100644
--- a/src/pkg/net/sockopt_windows.go
+++ b/src/net/sockopt_windows.go
diff --git a/src/pkg/net/sockoptip_bsd.go b/src/net/sockoptip_bsd.go
index 87132f0f4..2199e480d 100644
--- a/src/pkg/net/sockoptip_bsd.go
+++ b/src/net/sockoptip_bsd.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 darwin dragonfly freebsd nacl netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
package net
diff --git a/src/pkg/net/sockoptip_linux.go b/src/net/sockoptip_linux.go
index a69b778e4..a69b778e4 100644
--- a/src/pkg/net/sockoptip_linux.go
+++ b/src/net/sockoptip_linux.go
diff --git a/src/pkg/net/sockoptip_posix.go b/src/net/sockoptip_posix.go
index b5c80e449..c2579be91 100644
--- a/src/pkg/net/sockoptip_posix.go
+++ b/src/net/sockoptip_posix.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 darwin dragonfly freebsd linux nacl netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package net
diff --git a/src/pkg/net/sockoptip_stub.go b/src/net/sockoptip_stub.go
index dcd3a22b5..32ec5ddb8 100644
--- a/src/pkg/net/sockoptip_stub.go
+++ b/src/net/sockoptip_stub.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 solaris
+// +build nacl solaris
package net
@@ -10,30 +10,30 @@ import "syscall"
func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
// See golang.org/issue/7399.
- return syscall.EINVAL
+ return syscall.ENOPROTOOPT
}
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
// See golang.org/issue/7399.
- return syscall.EINVAL
+ return syscall.ENOPROTOOPT
}
func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
// See golang.org/issue/7399.
- return syscall.EINVAL
+ return syscall.ENOPROTOOPT
}
func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
// See golang.org/issue/7399.
- return syscall.EINVAL
+ return syscall.ENOPROTOOPT
}
func setIPv6MulticastLoopback(fd *netFD, v bool) error {
// See golang.org/issue/7399.
- return syscall.EINVAL
+ return syscall.ENOPROTOOPT
}
func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
// See golang.org/issue/7399.
- return syscall.EINVAL
+ return syscall.ENOPROTOOPT
}
diff --git a/src/pkg/net/sockoptip_windows.go b/src/net/sockoptip_windows.go
index 7b11f207a..7b11f207a 100644
--- a/src/pkg/net/sockoptip_windows.go
+++ b/src/net/sockoptip_windows.go
diff --git a/src/pkg/net/sys_cloexec.go b/src/net/sys_cloexec.go
index 898fb7c0c..898fb7c0c 100644
--- a/src/pkg/net/sys_cloexec.go
+++ b/src/net/sys_cloexec.go
diff --git a/src/pkg/net/tcp_test.go b/src/net/tcp_test.go
index c04198ea0..c04198ea0 100644
--- a/src/pkg/net/tcp_test.go
+++ b/src/net/tcp_test.go
diff --git a/src/pkg/net/tcpsock.go b/src/net/tcpsock.go
index f3dfbd23d..f3dfbd23d 100644
--- a/src/pkg/net/tcpsock.go
+++ b/src/net/tcpsock.go
diff --git a/src/pkg/net/tcpsock_plan9.go b/src/net/tcpsock_plan9.go
index 52019d7b4..52019d7b4 100644
--- a/src/pkg/net/tcpsock_plan9.go
+++ b/src/net/tcpsock_plan9.go
diff --git a/src/pkg/net/tcpsock_posix.go b/src/net/tcpsock_posix.go
index b79b115ca..dd78aefa7 100644
--- a/src/pkg/net/tcpsock_posix.go
+++ b/src/net/tcpsock_posix.go
@@ -153,7 +153,7 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
}
func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
- fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
+ fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial")
// TCP has a rarely used mechanism called a 'simultaneous connection' in
// which Dial("tcp", addr1, addr2) run on the machine at addr1 can
@@ -183,7 +183,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", sockaddrToTCP)
+ fd, err = internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial")
}
if err != nil {
@@ -231,7 +231,7 @@ func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
if l == nil || l.fd == nil {
return nil, syscall.EINVAL
}
- fd, err := l.fd.accept(sockaddrToTCP)
+ fd, err := l.fd.accept()
if err != nil {
return nil, err
}
@@ -291,7 +291,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", sockaddrToTCP)
+ fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_STREAM, 0, "listen")
if err != nil {
return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
}
diff --git a/src/pkg/net/tcpsockopt_darwin.go b/src/net/tcpsockopt_darwin.go
index 33140849c..1f1609088 100644
--- a/src/pkg/net/tcpsockopt_darwin.go
+++ b/src/net/tcpsockopt_darwin.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.
-// TCP socket options for darwin
-
package net
import (
@@ -12,16 +10,20 @@ import (
"time"
)
-// Set keep alive period.
+const sysTCP_KEEPINTVL = 0x101
+
func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
-
// The kernel expects seconds so round to next highest second.
d += (time.Second - time.Nanosecond)
secs := int(d.Seconds())
-
+ switch err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, sysTCP_KEEPINTVL, secs); err {
+ case nil, syscall.ENOPROTOOPT: // OS X 10.7 and earlier don't support this option
+ default:
+ return os.NewSyscallError("setsockopt", err)
+ }
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs))
}
diff --git a/src/pkg/net/tcpsockopt_dragonfly.go b/src/net/tcpsockopt_dragonfly.go
index d10a77773..0aa213239 100644
--- a/src/pkg/net/tcpsockopt_dragonfly.go
+++ b/src/net/tcpsockopt_dragonfly.go
@@ -10,20 +10,17 @@ import (
"time"
)
-// Set keep alive period.
func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
-
- // The kernel expects milliseconds so round to next highest millisecond.
+ // The kernel expects milliseconds so round to next highest
+ // millisecond.
d += (time.Millisecond - time.Nanosecond)
- msecs := int(time.Duration(d.Nanoseconds()) / time.Millisecond)
-
- err := os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, msecs))
- if err != nil {
- return err
+ msecs := int(d / time.Millisecond)
+ if err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, msecs); err != nil {
+ return os.NewSyscallError("setsockopt", err)
}
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, msecs))
}
diff --git a/src/net/tcpsockopt_openbsd.go b/src/net/tcpsockopt_openbsd.go
new file mode 100644
index 000000000..041e1786a
--- /dev/null
+++ b/src/net/tcpsockopt_openbsd.go
@@ -0,0 +1,16 @@
+// 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 (
+ "syscall"
+ "time"
+)
+
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+ // OpenBSD has no user-settable per-socket TCP keepalive
+ // options.
+ return syscall.ENOPROTOOPT
+}
diff --git a/src/pkg/net/tcpsockopt_plan9.go b/src/net/tcpsockopt_plan9.go
index 0e7a6647c..0e7a6647c 100644
--- a/src/pkg/net/tcpsockopt_plan9.go
+++ b/src/net/tcpsockopt_plan9.go
diff --git a/src/pkg/net/tcpsockopt_posix.go b/src/net/tcpsockopt_posix.go
index 6484bad4b..0abf3f97f 100644
--- a/src/pkg/net/tcpsockopt_posix.go
+++ b/src/net/tcpsockopt_posix.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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package net
diff --git a/src/net/tcpsockopt_stub.go b/src/net/tcpsockopt_stub.go
new file mode 100644
index 000000000..b413a764d
--- /dev/null
+++ b/src/net/tcpsockopt_stub.go
@@ -0,0 +1,20 @@
+// 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 nacl
+
+package net
+
+import (
+ "syscall"
+ "time"
+)
+
+func setNoDelay(fd *netFD, noDelay bool) error {
+ return syscall.ENOPROTOOPT
+}
+
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+ return syscall.ENOPROTOOPT
+}
diff --git a/src/pkg/net/tcpsockopt_unix.go b/src/net/tcpsockopt_unix.go
index 2693a541d..c9f604cad 100644
--- a/src/pkg/net/tcpsockopt_unix.go
+++ b/src/net/tcpsockopt_unix.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 freebsd linux nacl netbsd
+// +build freebsd linux netbsd solaris
package net
@@ -12,20 +12,16 @@ import (
"time"
)
-// Set keep alive period.
func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
-
// The kernel expects seconds so round to next highest second.
d += (time.Second - time.Nanosecond)
secs := int(d.Seconds())
-
- err := os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs))
- if err != nil {
- return err
+ if err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs); err != nil {
+ return os.NewSyscallError("setsockopt", err)
}
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs))
}
diff --git a/src/pkg/net/tcpsockopt_windows.go b/src/net/tcpsockopt_windows.go
index 8ef140797..091f5233f 100644
--- a/src/pkg/net/tcpsockopt_windows.go
+++ b/src/net/tcpsockopt_windows.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.
-// TCP socket options for windows
-
package net
import (
@@ -18,14 +16,14 @@ func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
return err
}
defer fd.decref()
-
- // Windows expects milliseconds so round to next highest millisecond.
+ // The kernel expects milliseconds so round to next highest
+ // millisecond.
d += (time.Millisecond - time.Nanosecond)
- millis := uint32(d / time.Millisecond)
+ msecs := uint32(d / time.Millisecond)
ka := syscall.TCPKeepalive{
OnOff: 1,
- Time: millis,
- Interval: millis,
+ Time: msecs,
+ Interval: msecs,
}
ret := uint32(0)
size := uint32(unsafe.Sizeof(ka))
diff --git a/src/net/testdata/domain-resolv.conf b/src/net/testdata/domain-resolv.conf
new file mode 100644
index 000000000..ff269180f
--- /dev/null
+++ b/src/net/testdata/domain-resolv.conf
@@ -0,0 +1,5 @@
+# /etc/resolv.conf
+
+search test invalid
+domain localdomain
+nameserver 8.8.8.8
diff --git a/src/net/testdata/empty-resolv.conf b/src/net/testdata/empty-resolv.conf
new file mode 100644
index 000000000..c4b2b5765
--- /dev/null
+++ b/src/net/testdata/empty-resolv.conf
@@ -0,0 +1 @@
+# /etc/resolv.conf
diff --git a/src/pkg/net/testdata/hosts b/src/net/testdata/hosts
index b60176389..b60176389 100644
--- a/src/pkg/net/testdata/hosts
+++ b/src/net/testdata/hosts
diff --git a/src/pkg/net/testdata/hosts_singleline b/src/net/testdata/hosts_singleline
index 5f5f74a3f..5f5f74a3f 100644
--- a/src/pkg/net/testdata/hosts_singleline
+++ b/src/net/testdata/hosts_singleline
diff --git a/src/pkg/net/testdata/igmp b/src/net/testdata/igmp
index 5f380a2c7..5f380a2c7 100644
--- a/src/pkg/net/testdata/igmp
+++ b/src/net/testdata/igmp
diff --git a/src/pkg/net/testdata/igmp6 b/src/net/testdata/igmp6
index 6cd5a2d4d..6cd5a2d4d 100644
--- a/src/pkg/net/testdata/igmp6
+++ b/src/net/testdata/igmp6
diff --git a/src/net/testdata/resolv.conf b/src/net/testdata/resolv.conf
new file mode 100644
index 000000000..04e87eed0
--- /dev/null
+++ b/src/net/testdata/resolv.conf
@@ -0,0 +1,8 @@
+# /etc/resolv.conf
+
+domain localdomain
+nameserver 8.8.8.8
+nameserver 2001:4860:4860::8888
+nameserver fe80::1%lo0
+options ndots:5 timeout:10 attempts:3 rotate
+options attempts 3
diff --git a/src/net/testdata/search-resolv.conf b/src/net/testdata/search-resolv.conf
new file mode 100644
index 000000000..1c846bfaf
--- /dev/null
+++ b/src/net/testdata/search-resolv.conf
@@ -0,0 +1,5 @@
+# /etc/resolv.conf
+
+domain localdomain
+search test invalid
+nameserver 8.8.8.8
diff --git a/src/pkg/net/textproto/header.go b/src/net/textproto/header.go
index 7fb32f804..7fb32f804 100644
--- a/src/pkg/net/textproto/header.go
+++ b/src/net/textproto/header.go
diff --git a/src/pkg/net/textproto/pipeline.go b/src/net/textproto/pipeline.go
index ca50eddac..ca50eddac 100644
--- a/src/pkg/net/textproto/pipeline.go
+++ b/src/net/textproto/pipeline.go
diff --git a/src/pkg/net/textproto/reader.go b/src/net/textproto/reader.go
index eea9207f2..eea9207f2 100644
--- a/src/pkg/net/textproto/reader.go
+++ b/src/net/textproto/reader.go
diff --git a/src/pkg/net/textproto/reader_test.go b/src/net/textproto/reader_test.go
index cbc0ed183..cbc0ed183 100644
--- a/src/pkg/net/textproto/reader_test.go
+++ b/src/net/textproto/reader_test.go
diff --git a/src/pkg/net/textproto/textproto.go b/src/net/textproto/textproto.go
index 026eb026b..026eb026b 100644
--- a/src/pkg/net/textproto/textproto.go
+++ b/src/net/textproto/textproto.go
diff --git a/src/pkg/net/textproto/writer.go b/src/net/textproto/writer.go
index 03e2fd658..03e2fd658 100644
--- a/src/pkg/net/textproto/writer.go
+++ b/src/net/textproto/writer.go
diff --git a/src/pkg/net/textproto/writer_test.go b/src/net/textproto/writer_test.go
index e03ab5e15..e03ab5e15 100644
--- a/src/pkg/net/textproto/writer_test.go
+++ b/src/net/textproto/writer_test.go
diff --git a/src/pkg/net/timeout_test.go b/src/net/timeout_test.go
index 9ef0c4d15..9ef0c4d15 100644
--- a/src/pkg/net/timeout_test.go
+++ b/src/net/timeout_test.go
diff --git a/src/pkg/net/udp_test.go b/src/net/udp_test.go
index e1778779c..125bbca6c 100644
--- a/src/pkg/net/udp_test.go
+++ b/src/net/udp_test.go
@@ -9,6 +9,7 @@ import (
"runtime"
"strings"
"testing"
+ "time"
)
func TestResolveUDPAddr(t *testing.T) {
@@ -34,6 +35,46 @@ func TestResolveUDPAddr(t *testing.T) {
}
}
+func TestReadFromUDP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9":
+ t.Skipf("skipping test on %q, see issue 8916", runtime.GOOS)
+ }
+
+ ra, err := ResolveUDPAddr("udp", "127.0.0.1:7")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ la, err := ResolveUDPAddr("udp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ c, err := ListenUDP("udp", la)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ _, err = c.WriteToUDP([]byte("a"), ra)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+ if err != nil {
+ t.Fatal(err)
+ }
+ b := make([]byte, 1)
+ _, _, err = c.ReadFromUDP(b)
+ if err == nil {
+ t.Fatal("ReadFromUDP should fail")
+ } else if !isTimeout(err) {
+ t.Fatal(err)
+ }
+}
+
func TestWriteToUDP(t *testing.T) {
switch runtime.GOOS {
case "plan9":
diff --git a/src/pkg/net/udpsock.go b/src/net/udpsock.go
index 4c99ae4af..4c99ae4af 100644
--- a/src/pkg/net/udpsock.go
+++ b/src/net/udpsock.go
diff --git a/src/pkg/net/udpsock_plan9.go b/src/net/udpsock_plan9.go
index 510ac5e4a..510ac5e4a 100644
--- a/src/pkg/net/udpsock_plan9.go
+++ b/src/net/udpsock_plan9.go
diff --git a/src/pkg/net/udpsock_posix.go b/src/net/udpsock_posix.go
index 5dfba94e9..a0533366a 100644
--- a/src/pkg/net/udpsock_posix.go
+++ b/src/net/udpsock_posix.go
@@ -175,7 +175,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", sockaddrToUDP)
+ fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_DGRAM, 0, "dial")
if err != nil {
return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
}
@@ -198,7 +198,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", sockaddrToUDP)
+ fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen")
if err != nil {
return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
}
@@ -218,7 +218,7 @@ func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, e
if gaddr == nil || gaddr.IP == nil {
return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
}
- fd, err := internetSocket(net, gaddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
+ fd, err := internetSocket(net, gaddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen")
if err != nil {
return nil, &OpError{Op: "listen", Net: net, Addr: gaddr, Err: err}
}
diff --git a/src/pkg/net/unicast_posix_test.go b/src/net/unicast_posix_test.go
index 452ac9254..ab7ef40a7 100644
--- a/src/pkg/net/unicast_posix_test.go
+++ b/src/net/unicast_posix_test.go
@@ -204,6 +204,9 @@ func TestDualStackTCPListener(t *testing.T) {
// to a test listener with various address families, differnet
// listening address and same port.
func TestDualStackUDPListener(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in -short mode, see issue 5001")
+ }
switch runtime.GOOS {
case "plan9":
t.Skipf("skipping test on %q", runtime.GOOS)
diff --git a/src/pkg/net/unix_test.go b/src/net/unix_test.go
index 05643ddf9..1cdff3908 100644
--- a/src/pkg/net/unix_test.go
+++ b/src/net/unix_test.go
@@ -256,8 +256,11 @@ func TestUnixConnLocalAndRemoteNames(t *testing.T) {
t.Fatalf("UnixConn.Write failed: %v", err)
}
- if runtime.GOOS == "linux" && laddr == "" {
- laddr = "@" // autobind feature
+ switch runtime.GOOS {
+ case "android", "linux":
+ if laddr == "" {
+ laddr = "@" // autobind feature
+ }
}
var connAddrs = [3]struct{ got, want Addr }{
{ln.Addr(), ta},
@@ -308,9 +311,13 @@ func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
}
}()
- if runtime.GOOS == "linux" && laddr == "" {
- laddr = "@" // autobind feature
+ switch runtime.GOOS {
+ case "android", "linux":
+ if laddr == "" {
+ laddr = "@" // autobind feature
+ }
}
+
var connAddrs = [4]struct{ got, want Addr }{
{c1.LocalAddr(), ta},
{c1.RemoteAddr(), nil},
diff --git a/src/pkg/net/unixsock.go b/src/net/unixsock.go
index 85955845b..85955845b 100644
--- a/src/pkg/net/unixsock.go
+++ b/src/net/unixsock.go
diff --git a/src/pkg/net/unixsock_plan9.go b/src/net/unixsock_plan9.go
index c60c1d83b..c60c1d83b 100644
--- a/src/pkg/net/unixsock_plan9.go
+++ b/src/net/unixsock_plan9.go
diff --git a/src/pkg/net/unixsock_posix.go b/src/net/unixsock_posix.go
index 2610779bf..3c2e78bdc 100644
--- a/src/pkg/net/unixsock_posix.go
+++ b/src/net/unixsock_posix.go
@@ -42,14 +42,7 @@ func unixSocket(net string, laddr, raddr sockaddr, mode string, deadline time.Ti
return nil, errors.New("unknown mode: " + mode)
}
- f := sockaddrToUnix
- if sotype == syscall.SOCK_DGRAM {
- f = sockaddrToUnixgram
- } else if sotype == syscall.SOCK_SEQPACKET {
- f = sockaddrToUnixpacket
- }
-
- fd, err := socket(net, syscall.AF_UNIX, sotype, 0, false, laddr, raddr, deadline, f)
+ fd, err := socket(net, syscall.AF_UNIX, sotype, 0, false, laddr, raddr, deadline)
if err != nil {
return nil, err
}
@@ -286,11 +279,7 @@ func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
if l == nil || l.fd == nil {
return nil, syscall.EINVAL
}
- toAddr := sockaddrToUnix
- if l.fd.sotype == syscall.SOCK_SEQPACKET {
- toAddr = sockaddrToUnixpacket
- }
- fd, err := l.fd.accept(toAddr)
+ fd, err := l.fd.accept()
if err != nil {
return nil, err
}
diff --git a/src/pkg/net/url/example_test.go b/src/net/url/example_test.go
index 56c5dc696..e55c1aa16 100644
--- a/src/pkg/net/url/example_test.go
+++ b/src/net/url/example_test.go
@@ -7,7 +7,10 @@ package url_test
import (
"fmt"
"log"
+ "net/http"
+ "net/http/httputil"
"net/url"
+ "strings"
)
func ExampleValues() {
@@ -39,3 +42,30 @@ func ExampleURL() {
fmt.Println(u)
// Output: https://google.com/search?q=golang
}
+
+func ExampleURL_opaque() {
+ // Sending a literal '%' in an HTTP request's Path
+ req := &http.Request{
+ Method: "GET",
+ Host: "example.com", // takes precendence over URL.Host
+ URL: &url.URL{
+ Host: "ignored",
+ Scheme: "https",
+ Opaque: "/%2f/",
+ },
+ Header: http.Header{
+ "User-Agent": {"godoc-example/0.1"},
+ },
+ }
+ out, err := httputil.DumpRequestOut(req, true)
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Println(strings.Replace(string(out), "\r", "", -1))
+ // Output:
+ // GET /%2f/ HTTP/1.1
+ // Host: example.com
+ // User-Agent: godoc-example/0.1
+ // Accept-Encoding: gzip
+ //
+}
diff --git a/src/pkg/net/url/url.go b/src/net/url/url.go
index 75f650a27..f167408fa 100644
--- a/src/pkg/net/url/url.go
+++ b/src/net/url/url.go
@@ -64,7 +64,6 @@ func (e EscapeError) Error() string {
// Return true if the specified character should be escaped when
// appearing in a URL string, according to RFC 3986.
-// When 'all' is true the full range of reserved characters are matched.
func shouldEscape(c byte, mode encoding) bool {
// §2.3 Unreserved characters (alphanum)
if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' {
@@ -86,10 +85,12 @@ func shouldEscape(c byte, mode encoding) bool {
// last two as well. That leaves only ? to escape.
return c == '?'
- case encodeUserPassword: // §3.2.2
- // The RFC allows ; : & = + $ , in userinfo, so we must escape only @ and /.
- // The parsing of userinfo treats : as special so we must escape that too.
- return c == '@' || c == '/' || c == ':'
+ case encodeUserPassword: // §3.2.1
+ // The RFC allows ';', ':', '&', '=', '+', '$', and ',' in
+ // userinfo, so we must escape only '@', '/', and '?'.
+ // The parsing of userinfo treats ':' as special so we must escape
+ // that too.
+ return c == '@' || c == '/' || c == '?' || c == ':'
case encodeQueryComponent: // §3.4
// The RFC reserves (so we must escape) everything.
@@ -440,6 +441,24 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
}
// String reassembles the URL into a valid URL string.
+// The general form of the result is one of:
+//
+// scheme:opaque
+// scheme://userinfo@host/path?query#fragment
+//
+// If u.Opaque is non-empty, String uses the first form;
+// otherwise it uses the second form.
+//
+// In the second form, the following rules apply:
+// - if u.Scheme is empty, scheme: is omitted.
+// - if u.User is nil, userinfo@ is omitted.
+// - if u.Host is empty, host/ is omitted.
+// - if u.Scheme and u.Host are empty and u.User is nil,
+// the entire scheme://userinfo@host/ is omitted.
+// - if u.Host is non-empty and u.Path begins with a /,
+// the form host/path does not add its own /.
+// - if u.RawQuery is empty, ?query is omitted.
+// - if u.Fragment is empty, #fragment is omitted.
func (u *URL) String() string {
var buf bytes.Buffer
if u.Scheme != "" {
diff --git a/src/pkg/net/url/url_test.go b/src/net/url/url_test.go
index cad758f23..d8b19d805 100644
--- a/src/pkg/net/url/url_test.go
+++ b/src/net/url/url_test.go
@@ -279,6 +279,16 @@ var urltests = []URLTest{
},
"a/b/c",
},
+ // escaped '?' in username and password
+ {
+ "http://%3Fam:pa%3Fsword@google.com",
+ &URL{
+ Scheme: "http",
+ User: UserPassword("?am", "pa?sword"),
+ Host: "google.com",
+ },
+ "",
+ },
}
// more useful string for debugging than fmt's struct printer
@@ -903,3 +913,49 @@ func TestParseFailure(t *testing.T) {
t.Errorf(`ParseQuery(%q) returned error %q, want something containing %q"`, url, errStr, "%gh")
}
}
+
+type shouldEscapeTest struct {
+ in byte
+ mode encoding
+ escape bool
+}
+
+var shouldEscapeTests = []shouldEscapeTest{
+ // Unreserved characters (§2.3)
+ {'a', encodePath, false},
+ {'a', encodeUserPassword, false},
+ {'a', encodeQueryComponent, false},
+ {'a', encodeFragment, false},
+ {'z', encodePath, false},
+ {'A', encodePath, false},
+ {'Z', encodePath, false},
+ {'0', encodePath, false},
+ {'9', encodePath, false},
+ {'-', encodePath, false},
+ {'-', encodeUserPassword, false},
+ {'-', encodeQueryComponent, false},
+ {'-', encodeFragment, false},
+ {'.', encodePath, false},
+ {'_', encodePath, false},
+ {'~', encodePath, false},
+
+ // User information (§3.2.1)
+ {':', encodeUserPassword, true},
+ {'/', encodeUserPassword, true},
+ {'?', encodeUserPassword, true},
+ {'@', encodeUserPassword, true},
+ {'$', encodeUserPassword, false},
+ {'&', encodeUserPassword, false},
+ {'+', encodeUserPassword, false},
+ {',', encodeUserPassword, false},
+ {';', encodeUserPassword, false},
+ {'=', encodeUserPassword, false},
+}
+
+func TestShouldEscape(t *testing.T) {
+ for _, tt := range shouldEscapeTests {
+ if shouldEscape(tt.in, tt.mode) != tt.escape {
+ t.Errorf("shouldEscape(%q, %v) returned %v; expected %v", tt.in, tt.mode, !tt.escape, tt.escape)
+ }
+ }
+}
diff --git a/src/net/z_last_test.go b/src/net/z_last_test.go
new file mode 100644
index 000000000..716c103db
--- /dev/null
+++ b/src/net/z_last_test.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 net
+
+import (
+ "flag"
+ "fmt"
+ "testing"
+ "time"
+)
+
+var testDNSFlood = flag.Bool("dnsflood", false, "whether to test dns query flooding")
+
+func TestDNSThreadLimit(t *testing.T) {
+ if !*testDNSFlood {
+ t.Skip("test disabled; use -dnsflood to enable")
+ }
+
+ const N = 10000
+ c := make(chan int, N)
+ for i := 0; i < N; i++ {
+ go func(i int) {
+ LookupIP(fmt.Sprintf("%d.net-test.golang.org", i))
+ c <- 1
+ }(i)
+ }
+ // Don't bother waiting for the stragglers; stop at 0.9 N.
+ for i := 0; i < N*9/10; i++ {
+ if i%100 == 0 {
+ //println("TestDNSThreadLimit:", i)
+ }
+ <-c
+ }
+
+ // If we're still here, it worked.
+}
+
+func TestLookupIPDeadline(t *testing.T) {
+ if !*testDNSFlood {
+ t.Skip("test disabled; use -dnsflood to enable")
+ }
+
+ const N = 5000
+ const timeout = 3 * time.Second
+ c := make(chan error, 2*N)
+ for i := 0; i < N; i++ {
+ name := fmt.Sprintf("%d.net-test.golang.org", i)
+ go func() {
+ _, err := lookupIPDeadline(name, time.Now().Add(timeout/2))
+ c <- err
+ }()
+ go func() {
+ _, err := lookupIPDeadline(name, time.Now().Add(timeout))
+ c <- err
+ }()
+ }
+ qstats := struct {
+ succeeded, failed int
+ timeout, temporary, other int
+ unknown int
+ }{}
+ deadline := time.After(timeout + time.Second)
+ for i := 0; i < 2*N; i++ {
+ select {
+ case <-deadline:
+ t.Fatal("deadline exceeded")
+ case err := <-c:
+ switch err := err.(type) {
+ case nil:
+ qstats.succeeded++
+ case Error:
+ qstats.failed++
+ if err.Timeout() {
+ qstats.timeout++
+ }
+ if err.Temporary() {
+ qstats.temporary++
+ }
+ if !err.Timeout() && !err.Temporary() {
+ qstats.other++
+ }
+ default:
+ qstats.failed++
+ qstats.unknown++
+ }
+ }
+ }
+
+ // A high volume of DNS queries for sub-domain of golang.org
+ // would be coordinated by authoritative or recursive server,
+ // or stub resolver which implements query-response rate
+ // limitation, so we can expect some query successes and more
+ // failures including timeout, temporary and other here.
+ // As a rule, unknown must not be shown but it might possibly
+ // happen due to issue 4856 for now.
+ 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)
+}
diff --git a/src/pkg/os/dir_plan9.go b/src/os/dir_plan9.go
index 8195c02a4..8195c02a4 100644
--- a/src/pkg/os/dir_plan9.go
+++ b/src/os/dir_plan9.go
diff --git a/src/pkg/os/dir_unix.go b/src/os/dir_unix.go
index d353e405e..589db8527 100644
--- a/src/pkg/os/dir_unix.go
+++ b/src/os/dir_unix.go
@@ -36,7 +36,7 @@ func (f *File) readdirnames(n int) (names []string, err error) {
if d.bufp >= d.nbuf {
d.bufp = 0
var errno error
- d.nbuf, errno = syscall.ReadDirent(f.fd, d.buf)
+ d.nbuf, errno = fixCount(syscall.ReadDirent(f.fd, d.buf))
if errno != nil {
return names, NewSyscallError("readdirent", errno)
}
diff --git a/src/pkg/os/dir_windows.go b/src/os/dir_windows.go
index 931316048..931316048 100644
--- a/src/pkg/os/dir_windows.go
+++ b/src/os/dir_windows.go
diff --git a/src/pkg/os/doc.go b/src/os/doc.go
index 389a8eb14..389a8eb14 100644
--- a/src/pkg/os/doc.go
+++ b/src/os/doc.go
diff --git a/src/pkg/os/env.go b/src/os/env.go
index db7fc72b8..d0494a476 100644
--- a/src/pkg/os/env.go
+++ b/src/os/env.go
@@ -91,6 +91,11 @@ func Setenv(key, value string) error {
return nil
}
+// Unsetenv unsets a single environment variable.
+func Unsetenv(key string) error {
+ return syscall.Unsetenv(key)
+}
+
// Clearenv deletes all environment variables.
func Clearenv() {
syscall.Clearenv()
diff --git a/src/pkg/os/env_test.go b/src/os/env_test.go
index 991fa4d05..e61806751 100644
--- a/src/pkg/os/env_test.go
+++ b/src/os/env_test.go
@@ -7,6 +7,7 @@ package os_test
import (
. "os"
"reflect"
+ "strings"
"testing"
)
@@ -68,3 +69,28 @@ func TestConsistentEnviron(t *testing.T) {
}
}
}
+
+func TestUnsetenv(t *testing.T) {
+ const testKey = "GO_TEST_UNSETENV"
+ set := func() bool {
+ prefix := testKey + "="
+ for _, key := range Environ() {
+ if strings.HasPrefix(key, prefix) {
+ return true
+ }
+ }
+ return false
+ }
+ if err := Setenv(testKey, "1"); err != nil {
+ t.Fatalf("Setenv: %v", err)
+ }
+ if !set() {
+ t.Error("Setenv didn't set TestUnsetenv")
+ }
+ if err := Unsetenv(testKey); err != nil {
+ t.Fatalf("Unsetenv: %v", err)
+ }
+ if set() {
+ t.Fatal("Unsetenv didn't clear TestUnsetenv")
+ }
+}
diff --git a/src/pkg/os/env_unix_test.go b/src/os/env_unix_test.go
index 5ec07ee1b..5ec07ee1b 100644
--- a/src/pkg/os/env_unix_test.go
+++ b/src/os/env_unix_test.go
diff --git a/src/pkg/os/error.go b/src/os/error.go
index 8810e6930..8810e6930 100644
--- a/src/pkg/os/error.go
+++ b/src/os/error.go
diff --git a/src/pkg/os/error_plan9.go b/src/os/error_plan9.go
index 85260c82a..001cdfcf2 100644
--- a/src/pkg/os/error_plan9.go
+++ b/src/os/error_plan9.go
@@ -25,7 +25,8 @@ func isNotExist(err error) bool {
case *LinkError:
err = pe.Err
}
- return contains(err.Error(), "does not exist")
+ return contains(err.Error(), "does not exist") || contains(err.Error(), "not found") ||
+ contains(err.Error(), "has been removed") || contains(err.Error(), "no parent")
}
func isPermission(err error) bool {
diff --git a/src/pkg/os/error_test.go b/src/os/error_test.go
index 02ed2351c..02ed2351c 100644
--- a/src/pkg/os/error_test.go
+++ b/src/os/error_test.go
diff --git a/src/pkg/os/error_unix.go b/src/os/error_unix.go
index f2aabbb45..f2aabbb45 100644
--- a/src/pkg/os/error_unix.go
+++ b/src/os/error_unix.go
diff --git a/src/pkg/os/error_windows.go b/src/os/error_windows.go
index 83db6c078..83db6c078 100644
--- a/src/pkg/os/error_windows.go
+++ b/src/os/error_windows.go
diff --git a/src/pkg/os/error_windows_test.go b/src/os/error_windows_test.go
index 3e6504f8d..3e6504f8d 100644
--- a/src/pkg/os/error_windows_test.go
+++ b/src/os/error_windows_test.go
diff --git a/src/pkg/os/exec.go b/src/os/exec.go
index 5aea3098b..5aea3098b 100644
--- a/src/pkg/os/exec.go
+++ b/src/os/exec.go
diff --git a/src/pkg/os/exec/example_test.go b/src/os/exec/example_test.go
index 55eaac8ab..55eaac8ab 100644
--- a/src/pkg/os/exec/example_test.go
+++ b/src/os/exec/example_test.go
diff --git a/src/pkg/os/exec/exec.go b/src/os/exec/exec.go
index a70ed0d20..72b4905d5 100644
--- a/src/pkg/os/exec/exec.go
+++ b/src/os/exec/exec.go
@@ -55,8 +55,15 @@ type Cmd struct {
// calling process's current directory.
Dir string
- // Stdin specifies the process's standard input. If Stdin is
- // nil, the process reads from the null device (os.DevNull).
+ // Stdin specifies the process's standard input.
+ // If Stdin is nil, the process reads from the null device (os.DevNull).
+ // If Stdin is an *os.File, the process's standard input is connected
+ // directly to that file.
+ // Otherwise, during the execution of the command a separate
+ // goroutine reads from Stdin and delivers that data to the command
+ // over a pipe. In this case, Wait does not complete until the goroutine
+ // stops copying, either because it has reached the end of Stdin
+ // (EOF or a read error) or because writing to the pipe returned an error.
Stdin io.Reader
// Stdout and Stderr specify the process's standard output and error.
@@ -358,7 +365,7 @@ func (c *Cmd) Wait() error {
c.ProcessState = state
var copyError error
- for _ = range c.goroutine {
+ for range c.goroutine {
if err := <-c.errch; err != nil && copyError == nil {
copyError = err
}
diff --git a/src/pkg/os/exec/exec_test.go b/src/os/exec/exec_test.go
index 6f77ac38a..197d3e8b4 100644
--- a/src/pkg/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -246,7 +246,7 @@ func TestPipeLookPathLeak(t *testing.T) {
}
func numOpenFDS(t *testing.T) (n int, lsof []byte) {
- lsof, err := exec.Command("lsof", "-n", "-p", strconv.Itoa(os.Getpid())).Output()
+ lsof, err := exec.Command("lsof", "-b", "-n", "-p", strconv.Itoa(os.Getpid())).Output()
if err != nil {
t.Skip("skipping test; error finding or running lsof")
}
@@ -258,15 +258,7 @@ var testedAlreadyLeaked = false
// basefds returns the number of expected file descriptors
// to be present in a process at start.
func basefds() uintptr {
- n := os.Stderr.Fd() + 1
-
- // Go runtime for 32-bit Plan 9 requires that /dev/bintime
- // be kept open.
- // See ../../runtime/time_plan9_386.c:/^runtime·nanotime
- if runtime.GOOS == "plan9" && runtime.GOARCH == "386" {
- n++
- }
- return n
+ return os.Stderr.Fd() + 1
}
func closeUnexpectedFds(t *testing.T, m string) {
@@ -383,8 +375,9 @@ func TestExtraFilesFDShuffle(t *testing.T) {
}
func TestExtraFiles(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("no operating system support; skipping")
+ switch runtime.GOOS {
+ case "nacl", "windows":
+ t.Skipf("skipping test on %q", runtime.GOOS)
}
// Ensure that file descriptors have not already been leaked into
diff --git a/src/pkg/os/exec/lp_plan9.go b/src/os/exec/lp_plan9.go
index 5aa8a54ed..5aa8a54ed 100644
--- a/src/pkg/os/exec/lp_plan9.go
+++ b/src/os/exec/lp_plan9.go
diff --git a/src/pkg/os/exec/lp_test.go b/src/os/exec/lp_test.go
index 77d8e848c..77d8e848c 100644
--- a/src/pkg/os/exec/lp_test.go
+++ b/src/os/exec/lp_test.go
diff --git a/src/pkg/os/exec/lp_unix.go b/src/os/exec/lp_unix.go
index 3f895d5b3..3f895d5b3 100644
--- a/src/pkg/os/exec/lp_unix.go
+++ b/src/os/exec/lp_unix.go
diff --git a/src/pkg/os/exec/lp_unix_test.go b/src/os/exec/lp_unix_test.go
index 051db664a..051db664a 100644
--- a/src/pkg/os/exec/lp_unix_test.go
+++ b/src/os/exec/lp_unix_test.go
diff --git a/src/pkg/os/exec/lp_windows.go b/src/os/exec/lp_windows.go
index c3efd67e9..c3efd67e9 100644
--- a/src/pkg/os/exec/lp_windows.go
+++ b/src/os/exec/lp_windows.go
diff --git a/src/pkg/os/exec/lp_windows_test.go b/src/os/exec/lp_windows_test.go
index 72df03ed2..72df03ed2 100644
--- a/src/pkg/os/exec/lp_windows_test.go
+++ b/src/os/exec/lp_windows_test.go
diff --git a/src/pkg/os/exec_plan9.go b/src/os/exec_plan9.go
index 676be36ac..676be36ac 100644
--- a/src/pkg/os/exec_plan9.go
+++ b/src/os/exec_plan9.go
diff --git a/src/pkg/os/exec_posix.go b/src/os/exec_posix.go
index fb9d291e6..fb9d291e6 100644
--- a/src/pkg/os/exec_posix.go
+++ b/src/os/exec_posix.go
diff --git a/src/pkg/os/exec_unix.go b/src/os/exec_unix.go
index 1b1e3350b..ed97f85e2 100644
--- a/src/pkg/os/exec_unix.go
+++ b/src/os/exec_unix.go
@@ -34,18 +34,26 @@ func (p *Process) wait() (ps *ProcessState, err error) {
return ps, nil
}
+var errFinished = errors.New("os: process already finished")
+
func (p *Process) signal(sig Signal) error {
- if p.done() {
- return errors.New("os: process already finished")
- }
if p.Pid == -1 {
return errors.New("os: process already released")
}
+ if p.Pid == 0 {
+ return errors.New("os: process not initialized")
+ }
+ if p.done() {
+ return errFinished
+ }
s, ok := sig.(syscall.Signal)
if !ok {
return errors.New("os: unsupported signal type")
}
if e := syscall.Kill(p.Pid, s); e != nil {
+ if e == syscall.ESRCH {
+ return errFinished
+ }
return e
}
return nil
diff --git a/src/pkg/os/exec_windows.go b/src/os/exec_windows.go
index c4f3d4f85..393393b23 100644
--- a/src/pkg/os/exec_windows.go
+++ b/src/os/exec_windows.go
@@ -53,6 +53,9 @@ func terminateProcess(pid, exitcode int) error {
}
func (p *Process) signal(sig Signal) error {
+ if p.handle == uintptr(syscall.InvalidHandle) {
+ return syscall.EINVAL
+ }
if p.done() {
return errors.New("os: process already finished")
}
diff --git a/src/pkg/os/export_test.go b/src/os/export_test.go
index 9fa7936ae..9fa7936ae 100644
--- a/src/pkg/os/export_test.go
+++ b/src/os/export_test.go
diff --git a/src/pkg/os/file.go b/src/os/file.go
index b4a745801..e12428cbe 100644
--- a/src/pkg/os/file.go
+++ b/src/os/file.go
@@ -255,3 +255,12 @@ var lstat = Lstat
func Rename(oldpath, newpath string) error {
return rename(oldpath, newpath)
}
+
+// Many functions in package syscall return a count of -1 instead of 0.
+// Using fixCount(call()) instead of call() corrects the count.
+func fixCount(n int, err error) (int, error) {
+ if n < 0 {
+ n = 0
+ }
+ return n, err
+}
diff --git a/src/pkg/os/file_plan9.go b/src/os/file_plan9.go
index a804b8197..132594eed 100644
--- a/src/pkg/os/file_plan9.go
+++ b/src/os/file_plan9.go
@@ -25,7 +25,8 @@ type file struct {
dirinfo *dirInfo // nil unless directory being read
}
-// Fd returns the integer Unix file descriptor referencing the open file.
+// Fd returns the integer Plan 9 file descriptor referencing the open file.
+// The file descriptor is valid only until f.Close is called or f is garbage collected.
func (f *File) Fd() uintptr {
if f == nil {
return ^(uintptr(0))
@@ -244,14 +245,14 @@ func (f *File) Sync() (err error) {
// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func (f *File) read(b []byte) (n int, err error) {
- return syscall.Read(f.fd, b)
+ return fixCount(syscall.Read(f.fd, b))
}
// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to nil.
func (f *File) pread(b []byte, off int64) (n int, err error) {
- return syscall.Pread(f.fd, b, off)
+ return fixCount(syscall.Pread(f.fd, b, off))
}
// write writes len(b) bytes to the File.
@@ -262,7 +263,7 @@ func (f *File) write(b []byte) (n int, err error) {
if len(b) == 0 {
return 0, nil
}
- return syscall.Write(f.fd, b)
+ return fixCount(syscall.Write(f.fd, b))
}
// pwrite writes len(b) bytes to the File starting at byte offset off.
@@ -273,7 +274,7 @@ func (f *File) pwrite(b []byte, off int64) (n int, err error) {
if len(b) == 0 {
return 0, nil
}
- return syscall.Pwrite(f.fd, b, off)
+ return fixCount(syscall.Pwrite(f.fd, b, off))
}
// seek sets the offset for the next Read or Write on file to offset, interpreted
diff --git a/src/pkg/os/file_posix.go b/src/os/file_posix.go
index b3466b15c..fbb3b5e4d 100644
--- a/src/pkg/os/file_posix.go
+++ b/src/os/file_posix.go
@@ -13,32 +13,12 @@ import (
func sigpipe() // implemented in package runtime
-// Link creates newname as a hard link to the oldname file.
-// If there is an error, it will be of type *LinkError.
-func Link(oldname, newname string) error {
- e := syscall.Link(oldname, newname)
- if e != nil {
- return &LinkError{"link", oldname, newname, e}
- }
- return nil
-}
-
-// Symlink creates newname as a symbolic link to oldname.
-// If there is an error, it will be of type *LinkError.
-func Symlink(oldname, newname string) error {
- e := syscall.Symlink(oldname, newname)
- if e != nil {
- return &LinkError{"symlink", oldname, newname, e}
- }
- return nil
-}
-
// Readlink returns the destination of the named symbolic link.
// If there is an error, it will be of type *PathError.
func Readlink(name string) (string, error) {
for len := 128; ; len *= 2 {
b := make([]byte, len)
- n, e := syscall.Readlink(name, b)
+ n, e := fixCount(syscall.Readlink(name, b))
if e != nil {
return "", &PathError{"readlink", name, e}
}
diff --git a/src/pkg/os/file_unix.go b/src/os/file_unix.go
index 76168339d..ff4fc7d12 100644
--- a/src/pkg/os/file_unix.go
+++ b/src/os/file_unix.go
@@ -29,6 +29,7 @@ type file struct {
}
// Fd returns the integer Unix file descriptor referencing the open file.
+// The file descriptor is valid only until f.Close is called or f is garbage collected.
func (f *File) Fd() uintptr {
if f == nil {
return ^(uintptr(0))
@@ -187,7 +188,7 @@ func (f *File) read(b []byte) (n int, err error) {
if needsMaxRW && len(b) > maxRW {
b = b[:maxRW]
}
- return syscall.Read(f.fd, b)
+ return fixCount(syscall.Read(f.fd, b))
}
// pread reads len(b) bytes from the File starting at byte offset off.
@@ -197,7 +198,7 @@ func (f *File) pread(b []byte, off int64) (n int, err error) {
if needsMaxRW && len(b) > maxRW {
b = b[:maxRW]
}
- return syscall.Pread(f.fd, b, off)
+ return fixCount(syscall.Pread(f.fd, b, off))
}
// write writes len(b) bytes to the File.
@@ -208,7 +209,7 @@ func (f *File) write(b []byte) (n int, err error) {
if needsMaxRW && len(bcap) > maxRW {
bcap = bcap[:maxRW]
}
- m, err := syscall.Write(f.fd, bcap)
+ m, err := fixCount(syscall.Write(f.fd, bcap))
n += m
// If the syscall wrote some data but not all (short write)
@@ -234,7 +235,7 @@ func (f *File) pwrite(b []byte, off int64) (n int, err error) {
if needsMaxRW && len(b) > maxRW {
b = b[:maxRW]
}
- return syscall.Pwrite(f.fd, b, off)
+ return fixCount(syscall.Pwrite(f.fd, b, off))
}
// seek sets the offset for the next Read or Write on file to offset, interpreted
@@ -308,7 +309,31 @@ func basename(name string) string {
func TempDir() string {
dir := Getenv("TMPDIR")
if dir == "" {
- dir = "/tmp"
+ if runtime.GOOS == "android" {
+ dir = "/data/local/tmp"
+ } else {
+ dir = "/tmp"
+ }
}
return dir
}
+
+// Link creates newname as a hard link to the oldname file.
+// If there is an error, it will be of type *LinkError.
+func Link(oldname, newname string) error {
+ e := syscall.Link(oldname, newname)
+ if e != nil {
+ return &LinkError{"link", oldname, newname, e}
+ }
+ return nil
+}
+
+// Symlink creates newname as a symbolic link to oldname.
+// If there is an error, it will be of type *LinkError.
+func Symlink(oldname, newname string) error {
+ e := syscall.Symlink(oldname, newname)
+ if e != nil {
+ return &LinkError{"symlink", oldname, newname, e}
+ }
+ return nil
+}
diff --git a/src/pkg/os/file_windows.go b/src/os/file_windows.go
index efe8bc03f..2a90a5055 100644
--- a/src/pkg/os/file_windows.go
+++ b/src/os/file_windows.go
@@ -36,6 +36,7 @@ type file struct {
}
// Fd returns the Windows handle referencing the open file.
+// The handle is valid only until f.Close is called or f is garbage collected.
func (file *File) Fd() uintptr {
if file == nil {
return uintptr(syscall.InvalidHandle)
@@ -117,8 +118,10 @@ func openDir(name string) (file *File, err error) {
}
d.path = name
if !isAbs(d.path) {
- cwd, _ := Getwd()
- d.path = cwd + `\` + d.path
+ d.path, e = syscall.FullPath(d.path)
+ if e != nil {
+ return nil, e
+ }
}
f := newFile(r, name)
f.dirinfo = d
@@ -293,7 +296,7 @@ func (f *File) read(b []byte) (n int, err error) {
if f.isConsole {
return f.readConsole(b)
}
- return syscall.Read(f.fd, b)
+ return fixCount(syscall.Read(f.fd, b))
}
// pread reads len(b) bytes from the File starting at byte offset off.
@@ -374,7 +377,7 @@ func (f *File) write(b []byte) (n int, err error) {
if f.isConsole {
return f.writeConsole(b)
}
- return syscall.Write(f.fd, b)
+ return fixCount(syscall.Write(f.fd, b))
}
// pwrite writes len(b) bytes to the File starting at byte offset off.
@@ -493,3 +496,101 @@ func TempDir() string {
}
return string(utf16.Decode(dirw[0:n]))
}
+
+// Link creates newname as a hard link to the oldname file.
+// If there is an error, it will be of type *LinkError.
+func Link(oldname, newname string) error {
+ n, err := syscall.UTF16PtrFromString(newname)
+ if err != nil {
+ return &LinkError{"link", oldname, newname, err}
+ }
+ o, err := syscall.UTF16PtrFromString(oldname)
+ if err != nil {
+ return &LinkError{"link", oldname, newname, err}
+ }
+
+ e := syscall.CreateHardLink(n, o, 0)
+ if e != nil {
+ return &LinkError{"link", oldname, newname, err}
+ }
+ return nil
+}
+
+// Symlink creates newname as a symbolic link to oldname.
+// If there is an error, it will be of type *LinkError.
+func Symlink(oldname, newname string) error {
+ // CreateSymbolicLink is not supported before Windows Vista
+ if syscall.LoadCreateSymbolicLink() != nil {
+ return &LinkError{"symlink", oldname, newname, syscall.EWINDOWS}
+ }
+
+ // '/' does not work in link's content
+ oldname = fromSlash(oldname)
+
+ // need the exact location of the oldname when its relative to determine if its a directory
+ destpath := oldname
+ if !isAbs(oldname) {
+ destpath = dirname(newname) + `\` + oldname
+ }
+
+ fi, err := Lstat(destpath)
+ isdir := err == nil && fi.IsDir()
+
+ n, err := syscall.UTF16PtrFromString(newname)
+ if err != nil {
+ return &LinkError{"symlink", oldname, newname, err}
+ }
+ o, err := syscall.UTF16PtrFromString(oldname)
+ if err != nil {
+ return &LinkError{"symlink", oldname, newname, err}
+ }
+
+ var flags uint32
+ if isdir {
+ flags |= syscall.SYMBOLIC_LINK_FLAG_DIRECTORY
+ }
+ err = syscall.CreateSymbolicLink(n, o, flags)
+ if err != nil {
+ return &LinkError{"symlink", oldname, newname, err}
+ }
+ return nil
+}
+
+func fromSlash(path string) string {
+ // Replace each '/' with '\\' if present
+ var pathbuf []byte
+ var lastSlash int
+ for i, b := range path {
+ if b == '/' {
+ if pathbuf == nil {
+ pathbuf = make([]byte, len(path))
+ }
+ copy(pathbuf[lastSlash:], path[lastSlash:i])
+ pathbuf[i] = '\\'
+ lastSlash = i + 1
+ }
+ }
+ if pathbuf == nil {
+ return path
+ }
+
+ copy(pathbuf[lastSlash:], path[lastSlash:])
+ return string(pathbuf)
+}
+
+func dirname(path string) string {
+ vol := volumeName(path)
+ i := len(path) - 1
+ for i >= len(vol) && !IsPathSeparator(path[i]) {
+ i--
+ }
+ dir := path[len(vol) : i+1]
+ last := len(dir) - 1
+ if last > 0 && IsPathSeparator(dir[last]) {
+ dir = dir[:last]
+ }
+ if dir == "" {
+ dir = "."
+ }
+ return vol + dir
+}
diff --git a/src/pkg/os/getwd.go b/src/os/getwd.go
index a72edeaee..d5da53b34 100644
--- a/src/pkg/os/getwd.go
+++ b/src/os/getwd.go
@@ -5,6 +5,7 @@
package os
import (
+ "runtime"
"sync"
"syscall"
)
@@ -23,22 +24,16 @@ var useSyscallwd = func(error) bool { return true }
// reached via multiple paths (due to symbolic links),
// Getwd may return any one of them.
func Getwd() (dir string, err error) {
- // If the operating system provides a Getwd call, use it.
- if syscall.ImplementsGetwd {
- s, e := syscall.Getwd()
- if useSyscallwd(e) {
- return s, NewSyscallError("getwd", e)
- }
+ if runtime.GOOS == "windows" {
+ return syscall.Getwd()
}
- // Otherwise, we're trying to find our way back to ".".
+ // Clumsy but widespread kludge:
+ // if $PWD is set and matches ".", use it.
dot, err := Stat(".")
if err != nil {
return "", err
}
-
- // Clumsy but widespread kludge:
- // if $PWD is set and matches ".", use it.
dir = Getenv("PWD")
if len(dir) > 0 && dir[0] == '/' {
d, err := Stat(dir)
@@ -47,6 +42,15 @@ func Getwd() (dir string, err error) {
}
}
+ // If the operating system provides a Getwd call, use it.
+ // Otherwise, we're trying to find our way back to ".".
+ if syscall.ImplementsGetwd {
+ s, e := syscall.Getwd()
+ if useSyscallwd(e) {
+ return s, NewSyscallError("getwd", e)
+ }
+ }
+
// Apply same kludge but to cached dir instead of $PWD.
getwdCache.Lock()
dir = getwdCache.dir
diff --git a/src/pkg/os/getwd_darwin.go b/src/os/getwd_darwin.go
index e51ffcd5e..e51ffcd5e 100644
--- a/src/pkg/os/getwd_darwin.go
+++ b/src/os/getwd_darwin.go
diff --git a/src/pkg/os/os_test.go b/src/os/os_test.go
index 16d5984e9..a30a2b031 100644
--- a/src/pkg/os/os_test.go
+++ b/src/os/os_test.go
@@ -18,12 +18,15 @@ import (
"runtime"
"sort"
"strings"
+ "sync"
"syscall"
"testing"
"text/template"
"time"
)
+var supportsSymlinks = true
+
var dot = []string{
"dir_unix.go",
"env.go",
@@ -42,6 +45,14 @@ type sysDir struct {
var sysdir = func() (sd *sysDir) {
switch runtime.GOOS {
+ case "android":
+ sd = &sysDir{
+ "/system/etc",
+ []string{
+ "audio_policy.conf",
+ "system_fonts.xml",
+ },
+ }
case "windows":
sd = &sysDir{
Getenv("SystemRoot") + "\\system32\\drivers\\etc",
@@ -108,12 +119,27 @@ func newFile(testName string, t *testing.T) (f *File) {
// On Unix, override $TMPDIR in case the user
// has it set to an NFS-mounted directory.
dir := ""
- if runtime.GOOS != "windows" {
+ if runtime.GOOS != "android" && runtime.GOOS != "windows" {
dir = "/tmp"
}
f, err := ioutil.TempFile(dir, "_Go_"+testName)
if err != nil {
- t.Fatalf("open %s: %s", testName, err)
+ t.Fatalf("TempFile %s: %s", testName, err)
+ }
+ return
+}
+
+func newDir(testName string, t *testing.T) (name string) {
+ // Use a local file system, not NFS.
+ // On Unix, override $TMPDIR in case the user
+ // has it set to an NFS-mounted directory.
+ dir := ""
+ if runtime.GOOS != "android" && runtime.GOOS != "windows" {
+ dir = "/tmp"
+ }
+ name, err := ioutil.TempDir(dir, "_Go_"+testName)
+ if err != nil {
+ t.Fatalf("TempDir %s: %s", testName, err)
}
return
}
@@ -284,10 +310,12 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
// big directory that doesn't change often.
dir := "/usr/bin"
switch runtime.GOOS {
- case "windows":
- dir = Getenv("SystemRoot") + "\\system32"
+ case "android":
+ dir = "/system/bin"
case "plan9":
dir = "/bin"
+ case "windows":
+ dir = Getenv("SystemRoot") + "\\system32"
}
file, err := Open(dir)
if err != nil {
@@ -465,7 +493,7 @@ func TestReaddirStatFailures(t *testing.T) {
func TestHardLink(t *testing.T) {
// Hardlinks are not supported under windows or Plan 9.
- if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+ if runtime.GOOS == "plan9" {
return
}
from, to := "hardlinktestfrom", "hardlinktestto"
@@ -498,8 +526,12 @@ func TestHardLink(t *testing.T) {
func TestSymlink(t *testing.T) {
switch runtime.GOOS {
- case "windows", "plan9", "nacl":
+ case "android", "nacl", "plan9":
t.Skipf("skipping on %s", runtime.GOOS)
+ case "windows":
+ if !supportsSymlinks {
+ t.Skipf("skipping on %s", runtime.GOOS)
+ }
}
from, to := "symlinktestfrom", "symlinktestto"
Remove(from) // Just in case.
@@ -560,8 +592,12 @@ func TestSymlink(t *testing.T) {
func TestLongSymlink(t *testing.T) {
switch runtime.GOOS {
- case "windows", "plan9", "nacl":
+ case "plan9", "nacl":
t.Skipf("skipping on %s", runtime.GOOS)
+ case "windows":
+ if !supportsSymlinks {
+ t.Skipf("skipping on %s", runtime.GOOS)
+ }
}
s := "0123456789abcdef"
// Long, but not too long: a common limit is 255.
@@ -630,8 +666,9 @@ func exec(t *testing.T, dir, cmd string, args []string, expect string) {
}
func TestStartProcess(t *testing.T) {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
+ switch runtime.GOOS {
+ case "android", "nacl":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
var dir, cmd string
@@ -733,35 +770,49 @@ func TestTruncate(t *testing.T) {
}
}
-// Use TempDir() to make sure we're on a local file system,
+// Use TempDir (via newFile) to make sure we're on a local file system,
// so that timings are not distorted by latency and caching.
// On NFS, timings can be off due to caching of meta-data on
// NFS servers (Issue 848).
func TestChtimes(t *testing.T) {
f := newFile("TestChtimes", t)
defer Remove(f.Name())
- defer f.Close()
f.Write([]byte("hello, world\n"))
f.Close()
- st, err := Stat(f.Name())
+ testChtimes(t, f.Name())
+}
+
+// Use TempDir (via newDir) to make sure we're on a local file system,
+// so that timings are not distorted by latency and caching.
+// On NFS, timings can be off due to caching of meta-data on
+// NFS servers (Issue 848).
+func TestChtimesDir(t *testing.T) {
+ name := newDir("TestChtimes", t)
+ defer RemoveAll(name)
+
+ testChtimes(t, name)
+}
+
+func testChtimes(t *testing.T, name string) {
+ st, err := Stat(name)
if err != nil {
- t.Fatalf("Stat %s: %s", f.Name(), err)
+ t.Fatalf("Stat %s: %s", name, err)
}
preStat := st
// Move access and modification time back a second
at := Atime(preStat)
mt := preStat.ModTime()
- err = Chtimes(f.Name(), at.Add(-time.Second), mt.Add(-time.Second))
+ err = Chtimes(name, at.Add(-time.Second), mt.Add(-time.Second))
if err != nil {
- t.Fatalf("Chtimes %s: %s", f.Name(), err)
+ t.Fatalf("Chtimes %s: %s", name, err)
}
- st, err = Stat(f.Name())
+ st, err = Stat(name)
if err != nil {
- t.Fatalf("second Stat %s: %s", f.Name(), err)
+ t.Fatalf("second Stat %s: %s", name, err)
}
postStat := st
@@ -790,12 +841,16 @@ func TestChdirAndGetwd(t *testing.T) {
t.Fatalf("Open .: %s", err)
}
// These are chosen carefully not to be symlinks on a Mac
- // (unlike, say, /var, /etc, and /tmp).
- dirs := []string{"/", "/usr/bin"}
- // /usr/bin does not usually exist on Plan 9.
- if runtime.GOOS == "plan9" {
+ // (unlike, say, /var, /etc), except /tmp, which we handle below.
+ dirs := []string{"/", "/usr/bin", "/tmp"}
+ // /usr/bin does not usually exist on Plan 9 or Android.
+ switch runtime.GOOS {
+ case "android":
+ dirs = []string{"/", "/system/bin"}
+ case "plan9":
dirs = []string{"/", "/usr"}
}
+ oldwd := Getenv("PWD")
for mode := 0; mode < 2; mode++ {
for _, d := range dirs {
if mode == 0 {
@@ -809,7 +864,11 @@ func TestChdirAndGetwd(t *testing.T) {
err = fd1.Chdir()
fd1.Close()
}
+ if d == "/tmp" {
+ Setenv("PWD", "/tmp")
+ }
pwd, err1 := Getwd()
+ Setenv("PWD", oldwd)
err2 := fd.Chdir()
if err2 != nil {
// We changed the current directory and cannot go back.
@@ -912,6 +971,12 @@ func TestOpenError(t *testing.T) {
syscallErrStr := perr.Err.Error()
expectedErrStr := strings.Replace(tt.error.Error(), "file ", "", 1)
if !strings.HasSuffix(syscallErrStr, expectedErrStr) {
+ // Some Plan 9 file servers incorrectly return
+ // EACCES rather than EISDIR when a directory is
+ // opened for write.
+ if tt.error == syscall.EISDIR && strings.HasSuffix(syscallErrStr, syscall.EACCES.Error()) {
+ continue
+ }
t.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt.path, tt.mode, syscallErrStr, expectedErrStr)
}
continue
@@ -972,9 +1037,9 @@ func run(t *testing.T, cmd []string) string {
func TestHostname(t *testing.T) {
// There is no other way to fetch hostname on windows, but via winapi.
- // On Plan 9 it is can be taken from #c/sysname as Hostname() does.
+ // On Plan 9 it can be taken from #c/sysname as Hostname() does.
switch runtime.GOOS {
- case "windows", "plan9", "nacl":
+ case "android", "nacl", "plan9", "windows":
t.Skipf("skipping on %s", runtime.GOOS)
}
@@ -1234,8 +1299,9 @@ func TestReadAtEOF(t *testing.T) {
}
func testKillProcess(t *testing.T, processKiller func(p *Process)) {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
+ switch runtime.GOOS {
+ case "android", "nacl":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
dir, err := ioutil.TempDir("", "go-build")
@@ -1293,6 +1359,36 @@ func TestKillStartProcess(t *testing.T) {
})
}
+func TestGetppid(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl":
+ t.Skip("skipping on nacl")
+ case "plan9":
+ // TODO: golang.org/issue/8206
+ t.Skipf("skipping test on plan9; see issue 8206")
+ }
+
+ if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
+ fmt.Print(Getppid())
+ Exit(0)
+ }
+
+ cmd := osexec.Command(Args[0], "-test.run=TestGetppid")
+ cmd.Env = append(Environ(), "GO_WANT_HELPER_PROCESS=1")
+
+ // verify that Getppid() from the forked process reports our process id
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("Failed to spawn child process: %v %q", err, string(output))
+ }
+
+ childPpid := string(output)
+ ourPid := fmt.Sprintf("%d", Getpid())
+ if childPpid != ourPid {
+ t.Fatalf("Child process reports parent process id '%v', expected '%v'", childPpid, ourPid)
+ }
+}
+
func TestKillFindProcess(t *testing.T) {
testKillProcess(t, func(p *Process) {
p2, err := FindProcess(p.Pid)
@@ -1337,3 +1433,52 @@ func TestNilFileMethods(t *testing.T) {
}
}
}
+
+func mkdirTree(t *testing.T, root string, level, max int) {
+ if level >= max {
+ return
+ }
+ level++
+ for i := 'a'; i < 'c'; i++ {
+ dir := filepath.Join(root, string(i))
+ if err := Mkdir(dir, 0700); err != nil {
+ t.Fatal(err)
+ }
+ mkdirTree(t, dir, level, max)
+ }
+}
+
+// Test that simultaneous RemoveAll do not report an error.
+// As long as it gets removed, we should be happy.
+func TestRemoveAllRace(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ // Windows has very strict rules about things like
+ // removing directories while someone else has
+ // them open. The racing doesn't work out nicely
+ // like it does on Unix.
+ t.Skip("skipping on windows")
+ }
+
+ n := runtime.GOMAXPROCS(16)
+ defer runtime.GOMAXPROCS(n)
+ root, err := ioutil.TempDir("", "issue")
+ if err != nil {
+ t.Fatal(err)
+ }
+ mkdirTree(t, root, 1, 6)
+ hold := make(chan struct{})
+ var wg sync.WaitGroup
+ for i := 0; i < 4; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ <-hold
+ err := RemoveAll(root)
+ if err != nil {
+ t.Errorf("unexpected error: %T, %q", err, err)
+ }
+ }()
+ }
+ close(hold) // let workers race to remove root
+ wg.Wait()
+}
diff --git a/src/pkg/os/os_unix_test.go b/src/os/os_unix_test.go
index 21d40ccaf..21d40ccaf 100644
--- a/src/pkg/os/os_unix_test.go
+++ b/src/os/os_unix_test.go
diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go
new file mode 100644
index 000000000..fd96713ea
--- /dev/null
+++ b/src/os/os_windows_test.go
@@ -0,0 +1,81 @@
+package os_test
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "syscall"
+ "testing"
+)
+
+func init() {
+ tmpdir, err := ioutil.TempDir("", "symtest")
+ if err != nil {
+ panic("failed to create temp directory: " + err.Error())
+ }
+ defer os.RemoveAll(tmpdir)
+
+ err = os.Symlink("target", filepath.Join(tmpdir, "symlink"))
+ if err == nil {
+ return
+ }
+
+ err = err.(*os.LinkError).Err
+ switch err {
+ case syscall.EWINDOWS, syscall.ERROR_PRIVILEGE_NOT_HELD:
+ supportsSymlinks = false
+ }
+}
+
+func TestSameWindowsFile(t *testing.T) {
+ temp, err := ioutil.TempDir("", "TestSameWindowsFile")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(temp)
+
+ wd, err := os.Getwd()
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = os.Chdir(temp)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Chdir(wd)
+
+ f, err := os.Create("a")
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.Close()
+
+ ia1, err := os.Stat("a")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ path, err := filepath.Abs("a")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ia2, err := os.Stat(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !os.SameFile(ia1, ia2) {
+ t.Errorf("files should be same")
+ }
+
+ p := filepath.VolumeName(path) + filepath.Base(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ ia3, err := os.Stat(p)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !os.SameFile(ia1, ia3) {
+ t.Errorf("files should be same")
+ }
+}
diff --git a/src/pkg/os/path.go b/src/os/path.go
index 02a77ec80..84a3be334 100644
--- a/src/pkg/os/path.go
+++ b/src/os/path.go
@@ -17,7 +17,7 @@ import (
// If path is already a directory, MkdirAll does nothing
// and returns nil.
func MkdirAll(path string, perm FileMode) error {
- // If path exists, stop with success or error.
+ // Fast path: if we can tell whether path is a directory or file, stop with success or error.
dir, err := Stat(path)
if err == nil {
if dir.IsDir() {
@@ -26,7 +26,7 @@ func MkdirAll(path string, perm FileMode) error {
return &PathError{"mkdir", path, syscall.ENOTDIR}
}
- // Doesn't already exist; make sure parent does.
+ // Slow path: make sure parent exists and then call Mkdir for path.
i := len(path)
for i > 0 && IsPathSeparator(path[i-1]) { // Skip trailing path separator.
i--
@@ -45,7 +45,7 @@ func MkdirAll(path string, perm FileMode) error {
}
}
- // Now parent exists, try to create.
+ // Parent now exists; invoke Mkdir and use its result.
err = Mkdir(path, perm)
if err != nil {
// Handle arguments like "foo/." by
@@ -66,7 +66,7 @@ func MkdirAll(path string, perm FileMode) error {
func RemoveAll(path string) error {
// Simple case: if Remove works, we're done.
err := Remove(path)
- if err == nil {
+ if err == nil || IsNotExist(err) {
return nil
}
@@ -86,6 +86,11 @@ func RemoveAll(path string) error {
// Directory.
fd, err := Open(path)
if err != nil {
+ if IsNotExist(err) {
+ // Race. It was deleted between the Lstat and Open.
+ // Return nil per RemoveAll's docs.
+ return nil
+ }
return err
}
@@ -116,6 +121,9 @@ func RemoveAll(path string) error {
// Remove directory.
err1 := Remove(path)
+ if err1 == nil || IsNotExist(err1) {
+ return nil
+ }
if err == nil {
err = err1
}
diff --git a/src/pkg/os/path_plan9.go b/src/os/path_plan9.go
index 64bad500a..64bad500a 100644
--- a/src/pkg/os/path_plan9.go
+++ b/src/os/path_plan9.go
diff --git a/src/pkg/os/path_test.go b/src/os/path_test.go
index 3af21cde9..6f24a4313 100644
--- a/src/pkg/os/path_test.go
+++ b/src/os/path_test.go
@@ -168,8 +168,12 @@ func TestRemoveAll(t *testing.T) {
func TestMkdirAllWithSymlink(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9", "windows":
+ case "nacl", "plan9":
t.Skipf("skipping on %s", runtime.GOOS)
+ case "windows":
+ if !supportsSymlinks {
+ t.Skipf("skipping on %s", runtime.GOOS)
+ }
}
tmpDir, err := ioutil.TempDir("", "TestMkdirAllWithSymlink-")
@@ -198,8 +202,9 @@ func TestMkdirAllWithSymlink(t *testing.T) {
}
func TestMkdirAllAtSlash(t *testing.T) {
- if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
- return
+ switch runtime.GOOS {
+ case "android", "plan9", "windows":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
RemoveAll("/_go_os_test")
err := MkdirAll("/_go_os_test/dir", 0777)
diff --git a/src/pkg/os/path_unix.go b/src/os/path_unix.go
index 0211107dd..0211107dd 100644
--- a/src/pkg/os/path_unix.go
+++ b/src/os/path_unix.go
diff --git a/src/pkg/os/path_windows.go b/src/os/path_windows.go
index 61f2ca59f..61f2ca59f 100644
--- a/src/pkg/os/path_windows.go
+++ b/src/os/path_windows.go
diff --git a/src/pkg/os/pipe_bsd.go b/src/os/pipe_bsd.go
index 3b81ed20f..3b81ed20f 100644
--- a/src/pkg/os/pipe_bsd.go
+++ b/src/os/pipe_bsd.go
diff --git a/src/pkg/os/pipe_linux.go b/src/os/pipe_linux.go
index 9bafad84f..9bafad84f 100644
--- a/src/pkg/os/pipe_linux.go
+++ b/src/os/pipe_linux.go
diff --git a/src/pkg/os/proc.go b/src/os/proc.go
index 38c436ec5..774f09900 100644
--- a/src/pkg/os/proc.go
+++ b/src/os/proc.go
@@ -6,11 +6,24 @@
package os
-import "syscall"
+import (
+ "runtime"
+ "syscall"
+)
// Args hold the command-line arguments, starting with the program name.
var Args []string
+func init() {
+ if runtime.GOOS == "windows" {
+ // Initialized in exec_windows.go.
+ return
+ }
+ Args = runtime_args()
+}
+
+func runtime_args() []string // in package runtime
+
// Getuid returns the numeric user id of the caller.
func Getuid() int { return syscall.Getuid() }
diff --git a/src/pkg/os/signal/example_test.go b/src/os/signal/example_test.go
index 079ee5070..079ee5070 100644
--- a/src/pkg/os/signal/example_test.go
+++ b/src/os/signal/example_test.go
diff --git a/src/pkg/os/signal/sig.s b/src/os/signal/sig.s
index f860924aa..d54c284b5 100644
--- a/src/pkg/os/signal/sig.s
+++ b/src/os/signal/sig.s
@@ -6,7 +6,7 @@
// +build amd64 amd64p32 arm 386
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
#ifdef GOARCH_arm
#define JMP B
diff --git a/src/pkg/os/signal/signal.go b/src/os/signal/signal.go
index 300427549..300427549 100644
--- a/src/pkg/os/signal/signal.go
+++ b/src/os/signal/signal.go
diff --git a/src/pkg/os/signal/signal_stub.go b/src/os/signal/signal_stub.go
index d0a6935ff..d0a6935ff 100644
--- a/src/pkg/os/signal/signal_stub.go
+++ b/src/os/signal/signal_stub.go
diff --git a/src/pkg/os/signal/signal_test.go b/src/os/signal/signal_test.go
index 076fe3f93..22337a72d 100644
--- a/src/pkg/os/signal/signal_test.go
+++ b/src/os/signal/signal_test.go
@@ -125,7 +125,7 @@ func TestStop(t *testing.T) {
if sig != syscall.SIGHUP || *sendUncaughtSighup == 1 {
syscall.Kill(syscall.Getpid(), sig)
}
- time.Sleep(10 * time.Millisecond)
+ time.Sleep(100 * time.Millisecond)
// Ask for signal
c := make(chan os.Signal, 1)
@@ -140,7 +140,7 @@ func TestStop(t *testing.T) {
select {
case s := <-c:
t.Fatalf("unexpected signal %v", s)
- case <-time.After(10 * time.Millisecond):
+ case <-time.After(100 * time.Millisecond):
// nothing to read - good
}
@@ -154,7 +154,7 @@ func TestStop(t *testing.T) {
select {
case s := <-c:
t.Fatalf("unexpected signal %v", s)
- case <-time.After(10 * time.Millisecond):
+ case <-time.After(100 * time.Millisecond):
// nothing to read - good
}
}
diff --git a/src/pkg/os/signal/signal_unix.go b/src/os/signal/signal_unix.go
index 94b8ab3dd..94b8ab3dd 100644
--- a/src/pkg/os/signal/signal_unix.go
+++ b/src/os/signal/signal_unix.go
diff --git a/src/pkg/os/signal/signal_windows_test.go b/src/os/signal/signal_windows_test.go
index f3e6706b7..f3e6706b7 100644
--- a/src/pkg/os/signal/signal_windows_test.go
+++ b/src/os/signal/signal_windows_test.go
diff --git a/src/pkg/os/stat_darwin.go b/src/os/stat_darwin.go
index 0eea52201..0eea52201 100644
--- a/src/pkg/os/stat_darwin.go
+++ b/src/os/stat_darwin.go
diff --git a/src/pkg/os/stat_dragonfly.go b/src/os/stat_dragonfly.go
index 605c1d9b6..605c1d9b6 100644
--- a/src/pkg/os/stat_dragonfly.go
+++ b/src/os/stat_dragonfly.go
diff --git a/src/pkg/os/stat_freebsd.go b/src/os/stat_freebsd.go
index 2ffb60fe2..2ffb60fe2 100644
--- a/src/pkg/os/stat_freebsd.go
+++ b/src/os/stat_freebsd.go
diff --git a/src/pkg/os/stat_linux.go b/src/os/stat_linux.go
index 605c1d9b6..605c1d9b6 100644
--- a/src/pkg/os/stat_linux.go
+++ b/src/os/stat_linux.go
diff --git a/src/pkg/os/stat_nacl.go b/src/os/stat_nacl.go
index a503b59fa..a503b59fa 100644
--- a/src/pkg/os/stat_nacl.go
+++ b/src/os/stat_nacl.go
diff --git a/src/pkg/os/stat_netbsd.go b/src/os/stat_netbsd.go
index 2ffb60fe2..2ffb60fe2 100644
--- a/src/pkg/os/stat_netbsd.go
+++ b/src/os/stat_netbsd.go
diff --git a/src/pkg/os/stat_openbsd.go b/src/os/stat_openbsd.go
index 605c1d9b6..605c1d9b6 100644
--- a/src/pkg/os/stat_openbsd.go
+++ b/src/os/stat_openbsd.go
diff --git a/src/pkg/os/stat_plan9.go b/src/os/stat_plan9.go
index 25c9a8c14..25c9a8c14 100644
--- a/src/pkg/os/stat_plan9.go
+++ b/src/os/stat_plan9.go
diff --git a/src/pkg/os/stat_solaris.go b/src/os/stat_solaris.go
index 605c1d9b6..605c1d9b6 100644
--- a/src/pkg/os/stat_solaris.go
+++ b/src/os/stat_solaris.go
diff --git a/src/pkg/os/stat_windows.go b/src/os/stat_windows.go
index 6dc386685..f396c1db3 100644
--- a/src/pkg/os/stat_windows.go
+++ b/src/os/stat_windows.go
@@ -49,8 +49,29 @@ func (file *File) Stat() (fi FileInfo, err error) {
// Stat returns a FileInfo structure describing the named file.
// If there is an error, it will be of type *PathError.
func Stat(name string) (fi FileInfo, err error) {
+ for {
+ fi, err = Lstat(name)
+ if err != nil {
+ return
+ }
+ if fi.Mode()&ModeSymlink == 0 {
+ return
+ }
+ name, err = Readlink(name)
+ if err != nil {
+ return
+ }
+ }
+ return fi, err
+}
+
+// Lstat returns the FileInfo structure describing the named file.
+// If the file is a symbolic link, the returned FileInfo
+// 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) (fi FileInfo, err error) {
if len(name) == 0 {
- return nil, &PathError{"Stat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
+ return nil, &PathError{"Lstat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
}
if name == DevNull {
return &devNullStat, nil
@@ -58,7 +79,7 @@ func Stat(name string) (fi FileInfo, err error) {
fs := &fileStat{name: basename(name)}
namep, e := syscall.UTF16PtrFromString(name)
if e != nil {
- return nil, &PathError{"Stat", name, e}
+ return nil, &PathError{"Lstat", name, e}
}
e = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fs.sys)))
if e != nil {
@@ -66,21 +87,14 @@ func Stat(name string) (fi FileInfo, err error) {
}
fs.path = name
if !isAbs(fs.path) {
- cwd, _ := Getwd()
- fs.path = cwd + `\` + fs.path
+ fs.path, e = syscall.FullPath(fs.path)
+ if e != nil {
+ return nil, e
+ }
}
return fs, nil
}
-// Lstat returns the FileInfo structure describing the named file.
-// If the file is a symbolic link, the returned FileInfo
-// 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) (fi FileInfo, err error) {
- // No links on Windows
- return Stat(name)
-}
-
// basename removes trailing slashes and the leading
// directory name and drive letter from path name.
func basename(name string) string {
@@ -105,10 +119,6 @@ func basename(name string) string {
return name
}
-func isSlash(c uint8) bool {
- return c == '\\' || c == '/'
-}
-
func isAbs(path string) (b bool) {
v := volumeName(path)
if v == "" {
@@ -118,7 +128,7 @@ func isAbs(path string) (b bool) {
if path == "" {
return false
}
- return isSlash(path[0])
+ return IsPathSeparator(path[0])
}
func volumeName(path string) (v string) {
@@ -133,20 +143,20 @@ func volumeName(path string) (v string) {
return path[:2]
}
// is it UNC
- if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) &&
- !isSlash(path[2]) && path[2] != '.' {
+ if l := len(path); l >= 5 && IsPathSeparator(path[0]) && IsPathSeparator(path[1]) &&
+ !IsPathSeparator(path[2]) && path[2] != '.' {
// first, leading `\\` and next shouldn't be `\`. its server name.
for n := 3; n < l-1; n++ {
// second, next '\' shouldn't be repeated.
- if isSlash(path[n]) {
+ if IsPathSeparator(path[n]) {
n++
// third, following something characters. its share name.
- if !isSlash(path[n]) {
+ if !IsPathSeparator(path[n]) {
if path[n] == '.' {
break
}
for ; n < l; n++ {
- if isSlash(path[n]) {
+ if IsPathSeparator(path[n]) {
break
}
}
diff --git a/src/pkg/os/str.go b/src/os/str.go
index e3606b61e..e3606b61e 100644
--- a/src/pkg/os/str.go
+++ b/src/os/str.go
diff --git a/src/pkg/os/sys_bsd.go b/src/os/sys_bsd.go
index 8ad5e2183..8ad5e2183 100644
--- a/src/pkg/os/sys_bsd.go
+++ b/src/os/sys_bsd.go
diff --git a/src/pkg/os/sys_darwin.go b/src/os/sys_darwin.go
index 7a8330abb..7a8330abb 100644
--- a/src/pkg/os/sys_darwin.go
+++ b/src/os/sys_darwin.go
diff --git a/src/pkg/os/sys_freebsd.go b/src/os/sys_freebsd.go
index 273c2df1c..273c2df1c 100644
--- a/src/pkg/os/sys_freebsd.go
+++ b/src/os/sys_freebsd.go
diff --git a/src/pkg/os/sys_linux.go b/src/os/sys_linux.go
index 76cdf5043..76cdf5043 100644
--- a/src/pkg/os/sys_linux.go
+++ b/src/os/sys_linux.go
diff --git a/src/pkg/os/sys_nacl.go b/src/os/sys_nacl.go
index 07907c847..07907c847 100644
--- a/src/pkg/os/sys_nacl.go
+++ b/src/os/sys_nacl.go
diff --git a/src/pkg/os/sys_plan9.go b/src/os/sys_plan9.go
index 07a7905f4..07a7905f4 100644
--- a/src/pkg/os/sys_plan9.go
+++ b/src/os/sys_plan9.go
diff --git a/src/pkg/os/sys_solaris.go b/src/os/sys_solaris.go
index 917e8f2b0..917e8f2b0 100644
--- a/src/pkg/os/sys_solaris.go
+++ b/src/os/sys_solaris.go
diff --git a/src/pkg/os/sys_unix.go b/src/os/sys_unix.go
index 39c20dc73..39c20dc73 100644
--- a/src/pkg/os/sys_unix.go
+++ b/src/os/sys_unix.go
diff --git a/src/pkg/os/sys_windows.go b/src/os/sys_windows.go
index 92617de5e..92617de5e 100644
--- a/src/pkg/os/sys_windows.go
+++ b/src/os/sys_windows.go
diff --git a/src/pkg/os/types.go b/src/os/types.go
index 473d431d4..473d431d4 100644
--- a/src/pkg/os/types.go
+++ b/src/os/types.go
diff --git a/src/pkg/os/types_notwin.go b/src/os/types_notwin.go
index ea1a07393..ea1a07393 100644
--- a/src/pkg/os/types_notwin.go
+++ b/src/os/types_notwin.go
diff --git a/src/pkg/os/types_windows.go b/src/os/types_windows.go
index 38901681e..7b2e54698 100644
--- a/src/pkg/os/types_windows.go
+++ b/src/os/types_windows.go
@@ -39,6 +39,9 @@ func (fs *fileStat) Mode() (m FileMode) {
} else {
m |= 0666
}
+ if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 {
+ m |= ModeSymlink
+ }
return m
}
diff --git a/src/pkg/os/user/lookup.go b/src/os/user/lookup.go
index 09f00c7bd..09f00c7bd 100644
--- a/src/pkg/os/user/lookup.go
+++ b/src/os/user/lookup.go
diff --git a/src/pkg/os/user/lookup_plan9.go b/src/os/user/lookup_plan9.go
index f7ef3482b..f7ef3482b 100644
--- a/src/pkg/os/user/lookup_plan9.go
+++ b/src/os/user/lookup_plan9.go
diff --git a/src/pkg/os/user/lookup_stubs.go b/src/os/user/lookup_stubs.go
index 86f0e6e64..4fb0e3c6e 100644
--- a/src/pkg/os/user/lookup_stubs.go
+++ b/src/os/user/lookup_stubs.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 !cgo,!windows,!plan9
+// +build !cgo,!windows,!plan9 android
package user
diff --git a/src/pkg/os/user/lookup_unix.go b/src/os/user/lookup_unix.go
index f2baf05bb..0871473df 100644
--- a/src/pkg/os/user/lookup_unix.go
+++ b/src/os/user/lookup_unix.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 darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris
// +build cgo
package user
diff --git a/src/pkg/os/user/lookup_windows.go b/src/os/user/lookup_windows.go
index 99c325ff0..99c325ff0 100644
--- a/src/pkg/os/user/lookup_windows.go
+++ b/src/os/user/lookup_windows.go
diff --git a/src/pkg/os/user/user.go b/src/os/user/user.go
index e8680fe54..e8680fe54 100644
--- a/src/pkg/os/user/user.go
+++ b/src/os/user/user.go
diff --git a/src/pkg/os/user/user_test.go b/src/os/user/user_test.go
index 9d9420e80..9d9420e80 100644
--- a/src/pkg/os/user/user_test.go
+++ b/src/os/user/user_test.go
diff --git a/src/pkg/path/example_test.go b/src/path/example_test.go
index fa8c28d2e..fa8c28d2e 100644
--- a/src/pkg/path/example_test.go
+++ b/src/path/example_test.go
diff --git a/src/pkg/path/filepath/example_unix_test.go b/src/path/filepath/example_unix_test.go
index f3fe076c3..f3fe076c3 100644
--- a/src/pkg/path/filepath/example_unix_test.go
+++ b/src/path/filepath/example_unix_test.go
diff --git a/src/pkg/path/filepath/export_test.go b/src/path/filepath/export_test.go
index 0cf9e3bca..0cf9e3bca 100644
--- a/src/pkg/path/filepath/export_test.go
+++ b/src/path/filepath/export_test.go
diff --git a/src/pkg/path/filepath/match.go b/src/path/filepath/match.go
index a9bcc103c..ecc07aa5d 100644
--- a/src/pkg/path/filepath/match.go
+++ b/src/path/filepath/match.go
@@ -228,6 +228,9 @@ func getEsc(chunk string) (r rune, nchunk string, err error) {
// as in Match. The pattern may describe hierarchical names such as
// /usr/*/bin/ed (assuming the Separator is '/').
//
+// Glob ignores file system errors such as I/O errors reading directories.
+// The only possible returned error is ErrBadPattern, when pattern
+// is malformed.
func Glob(pattern string) (matches []string, err error) {
if !hasMeta(pattern) {
if _, err = os.Lstat(pattern); err != nil {
@@ -283,10 +286,7 @@ func glob(dir, pattern string, matches []string) (m []string, e error) {
}
defer d.Close()
- names, err := d.Readdirnames(-1)
- if err != nil {
- return
- }
+ names, _ := d.Readdirnames(-1)
sort.Strings(names)
for _, n := range names {
diff --git a/src/pkg/path/filepath/match_test.go b/src/path/filepath/match_test.go
index 382692eaa..20ec5aa2a 100644
--- a/src/pkg/path/filepath/match_test.go
+++ b/src/path/filepath/match_test.go
@@ -167,8 +167,13 @@ var globSymlinkTests = []struct {
func TestGlobSymlink(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9", "windows":
+ case "nacl", "plan9":
t.Skipf("skipping on %s", runtime.GOOS)
+ case "windows":
+ if !supportsSymlinks {
+ t.Skipf("skipping on %s", runtime.GOOS)
+ }
+
}
tmpDir, err := ioutil.TempDir("", "globsymlink")
diff --git a/src/pkg/path/filepath/path.go b/src/path/filepath/path.go
index 71603cc59..d37fc9dfc 100644
--- a/src/pkg/path/filepath/path.go
+++ b/src/path/filepath/path.go
@@ -231,6 +231,10 @@ func EvalSymlinks(path string) (string, error) {
// working directory to turn it into an absolute path. The absolute
// path name for a given file is not guaranteed to be unique.
func Abs(path string) (string, error) {
+ return abs(path)
+}
+
+func unixAbs(path string) (string, error) {
if IsAbs(path) {
return Clean(path), nil
}
@@ -448,13 +452,6 @@ func Dir(path string) string {
i--
}
dir := Clean(path[len(vol) : i+1])
- last := len(dir) - 1
- if last > 0 && os.IsPathSeparator(dir[last]) {
- dir = dir[:last]
- }
- if dir == "" {
- dir = "."
- }
return vol + dir
}
diff --git a/src/pkg/path/filepath/path_plan9.go b/src/path/filepath/path_plan9.go
index 12e85aae0..ee8912d58 100644
--- a/src/pkg/path/filepath/path_plan9.go
+++ b/src/path/filepath/path_plan9.go
@@ -28,3 +28,7 @@ func splitList(path string) []string {
}
return strings.Split(path, string(ListSeparator))
}
+
+func abs(path string) (string, error) {
+ return unixAbs(path)
+}
diff --git a/src/pkg/path/filepath/path_test.go b/src/path/filepath/path_test.go
index 819bd217c..399284b97 100644
--- a/src/pkg/path/filepath/path_test.go
+++ b/src/path/filepath/path_test.go
@@ -15,6 +15,8 @@ import (
"testing"
)
+var supportsSymlinks = true
+
type PathTest struct {
path, result string
}
@@ -626,6 +628,8 @@ var winisabstests = []IsAbsTest{
{`\`, false},
{`\Windows`, false},
{`c:a\b`, false},
+ {`c:\a\b`, true},
+ {`c:/a/b`, true},
{`\\host\share\foo`, true},
{`//host/share/foo/bar`, true},
}
@@ -716,7 +720,7 @@ func TestEvalSymlinks(t *testing.T) {
if d.dest == "" {
err = os.Mkdir(path, 0755)
} else {
- if runtime.GOOS != "windows" {
+ if supportsSymlinks {
err = os.Symlink(d.dest, path)
}
}
@@ -726,7 +730,9 @@ func TestEvalSymlinks(t *testing.T) {
}
var tests []EvalSymlinksTest
- if runtime.GOOS == "windows" {
+ if supportsSymlinks {
+ tests = EvalSymlinksTests
+ } else {
for _, d := range EvalSymlinksTests {
if d.path == d.dest {
// will test only real files and directories
@@ -739,15 +745,13 @@ func TestEvalSymlinks(t *testing.T) {
tests = append(tests, d2)
}
}
- } else {
- tests = EvalSymlinksTests
}
// Evaluate the symlink farm.
for _, d := range tests {
path := simpleJoin(tmpDir, d.path)
dest := simpleJoin(tmpDir, d.dest)
- if filepath.IsAbs(d.dest) {
+ if filepath.IsAbs(d.dest) || os.IsPathSeparator(d.dest[0]) {
dest = d.dest
}
if p, err := filepath.EvalSymlinks(path); err != nil {
@@ -782,12 +786,6 @@ var absTests = []string{
}
func TestAbs(t *testing.T) {
- oldwd, err := os.Getwd()
- if err != nil {
- t.Fatal("Getwd failed: ", err)
- }
- defer os.Chdir(oldwd)
-
root, err := ioutil.TempDir("", "TestAbs")
if err != nil {
t.Fatal("TempDir failed: ", err)
@@ -811,6 +809,19 @@ func TestAbs(t *testing.T) {
}
}
+ if runtime.GOOS == "windows" {
+ vol := filepath.VolumeName(root)
+ var extra []string
+ for _, path := range absTests {
+ if strings.Index(path, "$") != -1 {
+ continue
+ }
+ path = vol + path
+ extra = append(extra, path)
+ }
+ absTests = append(absTests, extra...)
+ }
+
err = os.Chdir(absTestDirs[0])
if err != nil {
t.Fatal("chdir failed: ", err)
diff --git a/src/pkg/path/filepath/path_unix.go b/src/path/filepath/path_unix.go
index 7aba0ab5b..4e7d0d1b4 100644
--- a/src/pkg/path/filepath/path_unix.go
+++ b/src/path/filepath/path_unix.go
@@ -30,3 +30,7 @@ func splitList(path string) []string {
}
return strings.Split(path, string(ListSeparator))
}
+
+func abs(path string) (string, error) {
+ return unixAbs(path)
+}
diff --git a/src/pkg/path/filepath/path_windows.go b/src/path/filepath/path_windows.go
index e99997257..ec50f6b26 100644
--- a/src/pkg/path/filepath/path_windows.go
+++ b/src/path/filepath/path_windows.go
@@ -6,6 +6,7 @@ package filepath
import (
"strings"
+ "syscall"
)
func isSlash(c uint8) bool {
@@ -103,3 +104,7 @@ func splitList(path string) []string {
return list
}
+
+func abs(path string) (string, error) {
+ return syscall.FullPath(path)
+}
diff --git a/src/pkg/path/filepath/path_windows_test.go b/src/path/filepath/path_windows_test.go
index 8a9be8e89..100cf30a4 100644
--- a/src/pkg/path/filepath/path_windows_test.go
+++ b/src/path/filepath/path_windows_test.go
@@ -10,9 +10,29 @@ import (
"os/exec"
"path/filepath"
"reflect"
+ "syscall"
"testing"
)
+func init() {
+ tmpdir, err := ioutil.TempDir("", "symtest")
+ if err != nil {
+ panic("failed to create temp directory: " + err.Error())
+ }
+ defer os.RemoveAll(tmpdir)
+
+ err = os.Symlink("target", filepath.Join(tmpdir, "symlink"))
+ if err == nil {
+ return
+ }
+
+ err = err.(*os.LinkError).Err
+ switch err {
+ case syscall.EWINDOWS, syscall.ERROR_PRIVILEGE_NOT_HELD:
+ supportsSymlinks = false
+ }
+}
+
func TestWinSplitListTestsAreValid(t *testing.T) {
comspec := os.Getenv("ComSpec")
if comspec == "" {
diff --git a/src/pkg/path/filepath/symlink.go b/src/path/filepath/symlink.go
index 307dd0f8f..df0a9e0c2 100644
--- a/src/pkg/path/filepath/symlink.go
+++ b/src/path/filepath/symlink.go
@@ -2,18 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !windows
-
package filepath
import (
"bytes"
"errors"
"os"
- "strings"
)
-func evalSymlinks(path string) (string, error) {
+const utf8RuneSelf = 0x80
+
+func walkSymlinks(path string) (string, error) {
const maxIter = 255
originalPath := path
// consume path by taking each frontmost path element,
@@ -25,7 +24,13 @@ func evalSymlinks(path string) (string, error) {
}
// find next path component, p
- i := strings.IndexRune(path, Separator)
+ 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, ""
@@ -47,7 +52,7 @@ func evalSymlinks(path string) (string, error) {
}
if fi.Mode()&os.ModeSymlink == 0 {
b.WriteString(p)
- if path != "" {
+ if path != "" || (b.Len() == 2 && len(p) == 2 && p[1] == ':') {
b.WriteRune(Separator)
}
continue
@@ -58,7 +63,7 @@ func evalSymlinks(path string) (string, error) {
if err != nil {
return "", err
}
- if IsAbs(dest) {
+ if IsAbs(dest) || os.IsPathSeparator(dest[0]) {
b.Reset()
}
path = dest + string(Separator) + path
diff --git a/src/path/filepath/symlink_unix.go b/src/path/filepath/symlink_unix.go
new file mode 100644
index 000000000..d20e63a98
--- /dev/null
+++ b/src/path/filepath/symlink_unix.go
@@ -0,0 +1,7 @@
+// +build !windows
+
+package filepath
+
+func evalSymlinks(path string) (string, error) {
+ return walkSymlinks(path)
+}
diff --git a/src/pkg/path/filepath/symlink_windows.go b/src/path/filepath/symlink_windows.go
index 9adc8a48a..327c2c89a 100644
--- a/src/pkg/path/filepath/symlink_windows.go
+++ b/src/path/filepath/symlink_windows.go
@@ -50,6 +50,11 @@ func toLong(path string) (string, error) {
}
func evalSymlinks(path string) (string, error) {
+ path, err := walkSymlinks(path)
+ if err != nil {
+ return "", err
+ }
+
p, err := toShort(path)
if err != nil {
return "", err
diff --git a/src/pkg/path/match.go b/src/path/match.go
index 8154bf602..8154bf602 100644
--- a/src/pkg/path/match.go
+++ b/src/path/match.go
diff --git a/src/pkg/path/match_test.go b/src/path/match_test.go
index 6b0676f81..6b0676f81 100644
--- a/src/pkg/path/match_test.go
+++ b/src/path/match_test.go
diff --git a/src/pkg/path/path.go b/src/path/path.go
index bdb85c6b9..98a6d5292 100644
--- a/src/pkg/path/path.go
+++ b/src/path/path.go
@@ -206,13 +206,5 @@ func IsAbs(path string) bool {
// slash.
func Dir(path string) string {
dir, _ := Split(path)
- dir = Clean(dir)
- last := len(dir) - 1
- if last > 0 && dir[last] == '/' {
- dir = dir[:last]
- }
- if dir == "" {
- dir = "."
- }
- return dir
+ return Clean(dir)
}
diff --git a/src/pkg/path/path_test.go b/src/path/path_test.go
index 13b585223..13b585223 100644
--- a/src/pkg/path/path_test.go
+++ b/src/path/path_test.go
diff --git a/src/pkg/bytes/bytes.s b/src/pkg/bytes/bytes.s
deleted file mode 100644
index 55103bae0..000000000
--- a/src/pkg/bytes/bytes.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.
-
-// This file is here just to make the go tool happy.
diff --git a/src/pkg/compress/bzip2/move_to_front.go b/src/pkg/compress/bzip2/move_to_front.go
deleted file mode 100644
index b7e75a700..000000000
--- a/src/pkg/compress/bzip2/move_to_front.go
+++ /dev/null
@@ -1,98 +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 bzip2
-
-// moveToFrontDecoder implements a move-to-front list. Such a list is an
-// efficient way to transform a string with repeating elements into one with
-// many small valued numbers, which is suitable for entropy encoding. It works
-// by starting with an initial list of symbols and references symbols by their
-// index into that list. When a symbol is referenced, it's moved to the front
-// of the list. Thus, a repeated symbol ends up being encoded with many zeros,
-// as the symbol will be at the front of the list after the first access.
-type moveToFrontDecoder struct {
- // Rather than actually keep the list in memory, the symbols are stored
- // as a circular, double linked list with the symbol indexed by head
- // at the front of the list.
- symbols [256]byte
- next [256]uint8
- prev [256]uint8
- head uint8
- len int
-}
-
-// newMTFDecoder creates a move-to-front decoder with an explicit initial list
-// of symbols.
-func newMTFDecoder(symbols []byte) *moveToFrontDecoder {
- if len(symbols) > 256 {
- panic("too many symbols")
- }
-
- m := new(moveToFrontDecoder)
- copy(m.symbols[:], symbols)
- m.len = len(symbols)
- m.threadLinkedList()
- return m
-}
-
-// newMTFDecoderWithRange creates a move-to-front decoder with an initial
-// symbol list of 0...n-1.
-func newMTFDecoderWithRange(n int) *moveToFrontDecoder {
- if n > 256 {
- panic("newMTFDecoderWithRange: cannot have > 256 symbols")
- }
-
- m := new(moveToFrontDecoder)
- for i := 0; i < n; i++ {
- m.symbols[byte(i)] = byte(i)
- }
- m.len = n
- m.threadLinkedList()
- return m
-}
-
-// threadLinkedList creates the initial linked-list pointers.
-func (m *moveToFrontDecoder) threadLinkedList() {
- if m.len == 0 {
- return
- }
-
- m.prev[0] = uint8(m.len - 1)
-
- for i := byte(0); int(i) < m.len-1; i++ {
- m.next[i] = uint8(i + 1)
- m.prev[i+1] = uint8(i)
- }
-
- m.next[m.len-1] = 0
-}
-
-func (m *moveToFrontDecoder) Decode(n int) (b byte) {
- // Most of the time, n will be zero so it's worth dealing with this
- // simple case.
- if n == 0 {
- return m.symbols[m.head]
- }
-
- i := m.head
- for j := 0; j < n; j++ {
- i = m.next[i]
- }
- b = m.symbols[i]
-
- m.next[m.prev[i]] = m.next[i]
- m.prev[m.next[i]] = m.prev[i]
- m.next[i] = m.head
- m.prev[i] = m.prev[m.head]
- m.next[m.prev[m.head]] = i
- m.prev[m.head] = i
- m.head = i
-
- return
-}
-
-// First returns the symbol at the front of the list.
-func (m *moveToFrontDecoder) First() byte {
- return m.symbols[m.head]
-}
diff --git a/src/pkg/crypto/cipher/cfb_test.go b/src/pkg/crypto/cipher/cfb_test.go
deleted file mode 100644
index ec708ab2b..000000000
--- a/src/pkg/crypto/cipher/cfb_test.go
+++ /dev/null
@@ -1,38 +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.
-
-package cipher_test
-
-import (
- "bytes"
- "crypto/aes"
- "crypto/cipher"
- "crypto/rand"
- "testing"
-)
-
-func TestCFB(t *testing.T) {
- block, err := aes.NewCipher(commonKey128)
- if err != nil {
- t.Error(err)
- return
- }
-
- plaintext := []byte("this is the plaintext. this is the plaintext.")
- iv := make([]byte, block.BlockSize())
- rand.Reader.Read(iv)
- cfb := cipher.NewCFBEncrypter(block, iv)
- ciphertext := make([]byte, len(plaintext))
- copy(ciphertext, plaintext)
- cfb.XORKeyStream(ciphertext, ciphertext)
-
- cfbdec := cipher.NewCFBDecrypter(block, iv)
- plaintextCopy := make([]byte, len(plaintext))
- copy(plaintextCopy, ciphertext)
- cfbdec.XORKeyStream(plaintextCopy, plaintextCopy)
-
- if !bytes.Equal(plaintextCopy, plaintext) {
- t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)
- }
-}
diff --git a/src/pkg/debug/pe/testdata/gcc-amd64-mingw-exec b/src/pkg/debug/pe/testdata/gcc-amd64-mingw-exec
deleted file mode 100644
index 78d4e5fed..000000000
--- a/src/pkg/debug/pe/testdata/gcc-amd64-mingw-exec
+++ /dev/null
Binary files differ
diff --git a/src/pkg/encoding/gob/timing_test.go b/src/pkg/encoding/gob/timing_test.go
deleted file mode 100644
index 9fbb0ac6d..000000000
--- a/src/pkg/encoding/gob/timing_test.go
+++ /dev/null
@@ -1,109 +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 gob
-
-import (
- "bytes"
- "io"
- "os"
- "runtime"
- "testing"
-)
-
-type Bench struct {
- A int
- B float64
- C string
- D []byte
-}
-
-func benchmarkEndToEnd(r io.Reader, w io.Writer, b *testing.B) {
- b.StopTimer()
- enc := NewEncoder(w)
- dec := NewDecoder(r)
- bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- if enc.Encode(bench) != nil {
- panic("encode error")
- }
- if dec.Decode(bench) != nil {
- panic("decode error")
- }
- }
-}
-
-func BenchmarkEndToEndPipe(b *testing.B) {
- r, w, err := os.Pipe()
- if err != nil {
- b.Fatal("can't get pipe:", err)
- }
- benchmarkEndToEnd(r, w, b)
-}
-
-func BenchmarkEndToEndByteBuffer(b *testing.B) {
- var buf bytes.Buffer
- benchmarkEndToEnd(&buf, &buf, b)
-}
-
-func TestCountEncodeMallocs(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping malloc count in short mode")
- }
- if runtime.GOMAXPROCS(0) > 1 {
- t.Skip("skipping; GOMAXPROCS>1")
- }
-
- const N = 1000
-
- var buf bytes.Buffer
- enc := NewEncoder(&buf)
- bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
-
- allocs := testing.AllocsPerRun(N, func() {
- err := enc.Encode(bench)
- if err != nil {
- t.Fatal("encode:", err)
- }
- })
- if allocs != 0 {
- t.Fatalf("mallocs per encode of type Bench: %v; wanted 0\n", allocs)
- }
-}
-
-func TestCountDecodeMallocs(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping malloc count in short mode")
- }
- if runtime.GOMAXPROCS(0) > 1 {
- t.Skip("skipping; GOMAXPROCS>1")
- }
-
- const N = 1000
-
- var buf bytes.Buffer
- enc := NewEncoder(&buf)
- bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
-
- // Fill the buffer with enough to decode
- testing.AllocsPerRun(N, func() {
- err := enc.Encode(bench)
- if err != nil {
- t.Fatal("encode:", err)
- }
- })
-
- dec := NewDecoder(&buf)
- allocs := testing.AllocsPerRun(N, func() {
- *bench = Bench{}
- err := dec.Decode(&bench)
- if err != nil {
- t.Fatal("decode:", err)
- }
- })
- if allocs != 3 {
- t.Fatalf("mallocs per decode of type Bench: %v; wanted 3\n", allocs)
- }
-}
diff --git a/src/pkg/go/format/format.go b/src/pkg/go/format/format.go
deleted file mode 100644
index 3d00a645d..000000000
--- a/src/pkg/go/format/format.go
+++ /dev/null
@@ -1,199 +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 format implements standard formatting of Go source.
-package format
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/parser"
- "go/printer"
- "go/token"
- "io"
- "strings"
-)
-
-var config = printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 8}
-
-// Node formats node in canonical gofmt style and writes the result to dst.
-//
-// The node type must be *ast.File, *printer.CommentedNode, []ast.Decl,
-// []ast.Stmt, or assignment-compatible to ast.Expr, ast.Decl, ast.Spec,
-// or ast.Stmt. Node does not modify node. Imports are not sorted for
-// nodes representing partial source files (i.e., if the node is not an
-// *ast.File or a *printer.CommentedNode not wrapping an *ast.File).
-//
-// The function may return early (before the entire result is written)
-// and return a formatting error, for instance due to an incorrect AST.
-//
-func Node(dst io.Writer, fset *token.FileSet, node interface{}) error {
- // Determine if we have a complete source file (file != nil).
- var file *ast.File
- var cnode *printer.CommentedNode
- switch n := node.(type) {
- case *ast.File:
- file = n
- case *printer.CommentedNode:
- if f, ok := n.Node.(*ast.File); ok {
- file = f
- cnode = n
- }
- }
-
- // Sort imports if necessary.
- if file != nil && hasUnsortedImports(file) {
- // Make a copy of the AST because ast.SortImports is destructive.
- // TODO(gri) Do this more efficiently.
- var buf bytes.Buffer
- err := config.Fprint(&buf, fset, file)
- if err != nil {
- return err
- }
- file, err = parser.ParseFile(fset, "", buf.Bytes(), parser.ParseComments)
- if err != nil {
- // We should never get here. If we do, provide good diagnostic.
- return fmt.Errorf("format.Node internal error (%s)", err)
- }
- ast.SortImports(fset, file)
-
- // Use new file with sorted imports.
- node = file
- if cnode != nil {
- node = &printer.CommentedNode{Node: file, Comments: cnode.Comments}
- }
- }
-
- return config.Fprint(dst, fset, node)
-}
-
-// Source formats src in canonical gofmt style and returns the result
-// or an (I/O or syntax) error. src is expected to be a syntactically
-// correct Go source file, or a list of Go declarations or statements.
-//
-// If src is a partial source file, the leading and trailing space of src
-// is applied to the result (such that it has the same leading and trailing
-// space as src), and the result is indented by the same amount as the first
-// line of src containing code. Imports are not sorted for partial source files.
-//
-func Source(src []byte) ([]byte, error) {
- fset := token.NewFileSet()
- node, err := parse(fset, src)
- if err != nil {
- return nil, err
- }
-
- var buf bytes.Buffer
- if file, ok := node.(*ast.File); ok {
- // Complete source file.
- ast.SortImports(fset, file)
- err := config.Fprint(&buf, fset, file)
- if err != nil {
- return nil, err
- }
-
- } else {
- // 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 // index of last line in leading space
- }
- j++
- }
- buf.Write(src[:i])
-
- // Determine 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
- }
-
- // Format the source.
- cfg := config
- cfg.Indent = indent
- err := cfg.Fprint(&buf, fset, node)
- if err != nil {
- return nil, err
- }
-
- // Determine and append trailing space.
- i = len(src)
- for i > 0 && isSpace(src[i-1]) {
- i--
- }
- buf.Write(src[i:])
- }
-
- return buf.Bytes(), nil
-}
-
-func hasUnsortedImports(file *ast.File) bool {
- for _, d := range file.Decls {
- d, ok := d.(*ast.GenDecl)
- if !ok || d.Tok != token.IMPORT {
- // Not an import declaration, so we're done.
- // Imports are always first.
- return false
- }
- if d.Lparen.IsValid() {
- // For now assume all grouped imports are unsorted.
- // TODO(gri) Should check if they are sorted already.
- return true
- }
- // Ungrouped imports are sorted by default.
- }
- return false
-}
-
-func isSpace(b byte) bool {
- return b == ' ' || b == '\t' || b == '\n' || b == '\r'
-}
-
-func parse(fset *token.FileSet, src []byte) (interface{}, error) {
- // Try as a complete source file.
- file, err := parser.ParseFile(fset, "", src, parser.ParseComments)
- if err == nil {
- return file, nil
- }
- // If the source is missing a package clause, try as a source fragment; otherwise fail.
- if !strings.Contains(err.Error(), "expected 'package'") {
- return nil, err
- }
-
- // Try as a declaration list by prepending a package clause in front of src.
- // Use ';' not '\n' to keep line numbers intact.
- psrc := append([]byte("package p;"), src...)
- file, err = parser.ParseFile(fset, "", psrc, parser.ParseComments)
- if err == nil {
- return file.Decls, nil
- }
- // If the source is missing a declaration, try as a statement list; otherwise fail.
- if !strings.Contains(err.Error(), "expected declaration") {
- return nil, err
- }
-
- // Try as statement list by wrapping a function around src.
- fsrc := append(append([]byte("package p; func _() {"), src...), '}')
- file, err = parser.ParseFile(fset, "", fsrc, parser.ParseComments)
- if err == nil {
- return file.Decls[0].(*ast.FuncDecl).Body.List, nil
- }
-
- // Failed, and out of options.
- return nil, err
-}
diff --git a/src/pkg/image/color/palette/gen.go b/src/pkg/image/color/palette/gen.go
deleted file mode 100644
index 4f4d88345..000000000
--- a/src/pkg/image/color/palette/gen.go
+++ /dev/null
@@ -1,101 +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 ignore
-
-package main
-
-// This program generates palette.go. Invoke it as
-// go run gen.go | gofmt > palette.go
-
-import (
- "fmt"
-)
-
-func main() {
- fmt.Println(`// 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.`)
- fmt.Println()
- fmt.Println("// generated by go run gen.go; DO NOT EDIT")
- fmt.Println()
- fmt.Println("// Package palette provides standard color palettes.")
- fmt.Println("package palette")
- fmt.Println()
- fmt.Println(`import "image/color"`)
- fmt.Println()
- printPlan9()
- printWebSafe()
-}
-
-func printPlan9() {
- c, lines := [3]int{}, [256]string{}
- for r, i := 0, 0; r != 4; r++ {
- for v := 0; v != 4; v, i = v+1, i+16 {
- for g, j := 0, v-r; g != 4; g++ {
- for b := 0; b != 4; b, j = b+1, j+1 {
- den := r
- if g > den {
- den = g
- }
- if b > den {
- den = b
- }
- if den == 0 {
- c[0] = 0x11 * v
- c[1] = 0x11 * v
- c[2] = 0x11 * v
- } else {
- num := 17 * (4*den + v)
- c[0] = r * num / den
- c[1] = g * num / den
- c[2] = b * num / den
- }
- lines[i+(j&0x0f)] =
- fmt.Sprintf("\tcolor.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", c[0], c[1], c[2])
- }
- }
- }
- }
- fmt.Println("// Plan9 is a 256-color palette that partitions the 24-bit RGB space")
- fmt.Println("// into 4×4×4 subdivision, with 4 shades in each subcube. Compared to the")
- fmt.Println("// WebSafe, the idea is to reduce the color resolution by dicing the")
- fmt.Println("// color cube into fewer cells, and to use the extra space to increase the")
- fmt.Println("// intensity resolution. This results in 16 gray shades (4 gray subcubes with")
- fmt.Println("// 4 samples in each), 13 shades of each primary and secondary color (3")
- fmt.Println("// subcubes with 4 samples plus black) and a reasonable selection of colors")
- fmt.Println("// covering the rest of the color cube. The advantage is better representation")
- fmt.Println("// of continuous tones.")
- fmt.Println("//")
- fmt.Println("// This palette was used in the Plan 9 Operating System, described at")
- fmt.Println("// http://plan9.bell-labs.com/magic/man2html/6/color")
- fmt.Println("var Plan9 = []color.Color{")
- for _, line := range lines {
- fmt.Println(line)
- }
- fmt.Println("}")
- fmt.Println()
-}
-
-func printWebSafe() {
- lines := [6 * 6 * 6]string{}
- for r := 0; r < 6; r++ {
- for g := 0; g < 6; g++ {
- for b := 0; b < 6; b++ {
- lines[36*r+6*g+b] =
- fmt.Sprintf("\tcolor.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", 0x33*r, 0x33*g, 0x33*b)
- }
- }
- }
- fmt.Println("// WebSafe is a 216-color palette that was popularized by early versions")
- fmt.Println("// of Netscape Navigator. It is also known as the Netscape Color Cube.")
- fmt.Println("//")
- fmt.Println("// See http://en.wikipedia.org/wiki/Web_colors#Web-safe_colors for details.")
- fmt.Println("var WebSafe = []color.Color{")
- for _, line := range lines {
- fmt.Println(line)
- }
- fmt.Println("}")
- fmt.Println()
-}
diff --git a/src/pkg/image/jpeg/huffman.go b/src/pkg/image/jpeg/huffman.go
deleted file mode 100644
index f53d873a5..000000000
--- a/src/pkg/image/jpeg/huffman.go
+++ /dev/null
@@ -1,219 +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 jpeg
-
-import "io"
-
-// Each code is at most 16 bits long.
-const maxCodeLength = 16
-
-// Each decoded value is a uint8, so there are at most 256 such values.
-const maxNumValues = 256
-
-// Bit stream for the Huffman decoder.
-// The n least significant bits of a form the unread bits, to be read in MSB to LSB order.
-type bits struct {
- a uint32 // accumulator.
- m uint32 // mask. m==1<<(n-1) when n>0, with m==0 when n==0.
- n int // the number of unread bits in a.
-}
-
-// Huffman table decoder, specified in section C.
-type huffman struct {
- l [maxCodeLength]int
- length int // sum of l[i].
- val [maxNumValues]uint8 // the decoded values, as sorted by their encoding.
- size [maxNumValues]int // size[i] is the number of bits to encode val[i].
- code [maxNumValues]int // code[i] is the encoding of val[i].
- minCode [maxCodeLength]int // min codes of length i, or -1 if no codes of that length.
- maxCode [maxCodeLength]int // max codes of length i, or -1 if no codes of that length.
- valIndex [maxCodeLength]int // index into val of minCode[i].
-}
-
-// Reads bytes from the io.Reader to ensure that bits.n is at least n.
-func (d *decoder) ensureNBits(n int) error {
- for d.b.n < n {
- c, err := d.r.ReadByte()
- if err != nil {
- if err == io.EOF {
- return FormatError("short Huffman data")
- }
- return err
- }
- d.b.a = d.b.a<<8 | uint32(c)
- d.b.n += 8
- if d.b.m == 0 {
- d.b.m = 1 << 7
- } else {
- d.b.m <<= 8
- }
- // Byte stuffing, specified in section F.1.2.3.
- if c == 0xff {
- c, err = d.r.ReadByte()
- if err != nil {
- if err == io.EOF {
- return FormatError("short Huffman data")
- }
- return err
- }
- if c != 0x00 {
- return FormatError("missing 0xff00 sequence")
- }
- }
- }
- return nil
-}
-
-// The composition of RECEIVE and EXTEND, specified in section F.2.2.1.
-func (d *decoder) receiveExtend(t uint8) (int32, error) {
- if d.b.n < int(t) {
- if err := d.ensureNBits(int(t)); err != nil {
- return 0, err
- }
- }
- d.b.n -= int(t)
- d.b.m >>= t
- s := int32(1) << t
- x := int32(d.b.a>>uint8(d.b.n)) & (s - 1)
- if x < s>>1 {
- x += ((-1) << t) + 1
- }
- return x, nil
-}
-
-// Processes a Define Huffman Table marker, and initializes a huffman struct from its contents.
-// Specified in section B.2.4.2.
-func (d *decoder) processDHT(n int) error {
- for n > 0 {
- if n < 17 {
- return FormatError("DHT has wrong length")
- }
- _, err := io.ReadFull(d.r, d.tmp[0:17])
- if err != nil {
- return err
- }
- tc := d.tmp[0] >> 4
- if tc > maxTc {
- return FormatError("bad Tc value")
- }
- th := d.tmp[0] & 0x0f
- if th > maxTh || !d.progressive && th > 1 {
- return FormatError("bad Th value")
- }
- h := &d.huff[tc][th]
-
- // Read l and val (and derive length).
- h.length = 0
- for i := 0; i < maxCodeLength; i++ {
- h.l[i] = int(d.tmp[i+1])
- h.length += h.l[i]
- }
- if h.length == 0 {
- return FormatError("Huffman table has zero length")
- }
- if h.length > maxNumValues {
- return FormatError("Huffman table has excessive length")
- }
- n -= h.length + 17
- if n < 0 {
- return FormatError("DHT has wrong length")
- }
- _, err = io.ReadFull(d.r, h.val[0:h.length])
- if err != nil {
- return err
- }
-
- // Derive size.
- k := 0
- for i := 0; i < maxCodeLength; i++ {
- for j := 0; j < h.l[i]; j++ {
- h.size[k] = i + 1
- k++
- }
- }
-
- // Derive code.
- code := 0
- size := h.size[0]
- for i := 0; i < h.length; i++ {
- if size != h.size[i] {
- code <<= uint8(h.size[i] - size)
- size = h.size[i]
- }
- h.code[i] = code
- code++
- }
-
- // Derive minCode, maxCode, and valIndex.
- k = 0
- index := 0
- for i := 0; i < maxCodeLength; i++ {
- if h.l[i] == 0 {
- h.minCode[i] = -1
- h.maxCode[i] = -1
- h.valIndex[i] = -1
- } else {
- h.minCode[i] = k
- h.maxCode[i] = k + h.l[i] - 1
- h.valIndex[i] = index
- k += h.l[i]
- index += h.l[i]
- }
- k <<= 1
- }
- }
- return nil
-}
-
-// Returns the next Huffman-coded value from the bit stream, decoded according to h.
-// TODO(nigeltao): This decoding algorithm is simple, but slow. A lookahead table, instead of always
-// peeling off only 1 bit at time, ought to be faster.
-func (d *decoder) decodeHuffman(h *huffman) (uint8, error) {
- if h.length == 0 {
- return 0, FormatError("uninitialized Huffman table")
- }
- for i, code := 0, 0; i < maxCodeLength; i++ {
- if d.b.n == 0 {
- if err := d.ensureNBits(1); err != nil {
- return 0, err
- }
- }
- if d.b.a&d.b.m != 0 {
- code |= 1
- }
- d.b.n--
- d.b.m >>= 1
- if code <= h.maxCode[i] {
- return h.val[h.valIndex[i]+code-h.minCode[i]], nil
- }
- code <<= 1
- }
- return 0, FormatError("bad Huffman code")
-}
-
-func (d *decoder) decodeBit() (bool, error) {
- if d.b.n == 0 {
- if err := d.ensureNBits(1); err != nil {
- return false, err
- }
- }
- ret := d.b.a&d.b.m != 0
- d.b.n--
- d.b.m >>= 1
- return ret, nil
-}
-
-func (d *decoder) decodeBits(n int) (uint32, error) {
- if d.b.n < n {
- if err := d.ensureNBits(n); err != nil {
- return 0, err
- }
- }
- ret := d.b.a >> uint(d.b.n-n)
- ret &= (1 << uint(n)) - 1
- d.b.n -= n
- d.b.m >>= uint(n)
- return ret, nil
-}
diff --git a/src/pkg/math/nextafter.go b/src/pkg/math/nextafter.go
deleted file mode 100644
index 7c4b5bcdf..000000000
--- a/src/pkg/math/nextafter.go
+++ /dev/null
@@ -1,27 +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.
-
-package math
-
-// Nextafter returns the next representable value after x towards y.
-// If x == y, then x is returned.
-//
-// Special cases are:
-// Nextafter(NaN, y) = NaN
-// Nextafter(x, NaN) = NaN
-func Nextafter(x, y float64) (r float64) {
- switch {
- case IsNaN(x) || IsNaN(y): // special case
- r = NaN()
- case x == y:
- r = x
- case x == 0:
- r = Copysign(Float64frombits(1), y)
- case (y > x) == (x > 0):
- r = Float64frombits(Float64bits(x) + 1)
- default:
- r = Float64frombits(Float64bits(x) - 1)
- }
- return
-}
diff --git a/src/pkg/mime/type.go b/src/pkg/mime/type.go
deleted file mode 100644
index 00cff263b..000000000
--- a/src/pkg/mime/type.go
+++ /dev/null
@@ -1,77 +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.
-
-// Package mime implements parts of the MIME spec.
-package mime
-
-import (
- "fmt"
- "strings"
- "sync"
-)
-
-var mimeTypes = map[string]string{
- ".css": "text/css; charset=utf-8",
- ".gif": "image/gif",
- ".htm": "text/html; charset=utf-8",
- ".html": "text/html; charset=utf-8",
- ".jpg": "image/jpeg",
- ".js": "application/x-javascript",
- ".pdf": "application/pdf",
- ".png": "image/png",
- ".xml": "text/xml; charset=utf-8",
-}
-
-var mimeLock sync.RWMutex
-
-var once sync.Once
-
-// TypeByExtension returns the MIME type associated with the file extension ext.
-// The extension ext should begin with a leading dot, as in ".html".
-// When ext has no associated type, TypeByExtension returns "".
-//
-// The built-in table is small but on unix it is augmented by the local
-// system's mime.types file(s) if available under one or more of these
-// names:
-//
-// /etc/mime.types
-// /etc/apache2/mime.types
-// /etc/apache/mime.types
-//
-// Windows system mime types are extracted from registry.
-//
-// Text types have the charset parameter set to "utf-8" by default.
-func TypeByExtension(ext string) string {
- once.Do(initMime)
- mimeLock.RLock()
- typename := mimeTypes[ext]
- mimeLock.RUnlock()
- return typename
-}
-
-// AddExtensionType sets the MIME type associated with
-// the extension ext to typ. The extension should begin with
-// a leading dot, as in ".html".
-func AddExtensionType(ext, typ string) error {
- if ext == "" || ext[0] != '.' {
- return fmt.Errorf(`mime: extension "%s" misses dot`, ext)
- }
- once.Do(initMime)
- return setExtensionType(ext, typ)
-}
-
-func setExtensionType(extension, mimeType string) error {
- _, param, err := ParseMediaType(mimeType)
- if err != nil {
- return err
- }
- if strings.HasPrefix(mimeType, "text/") && param["charset"] == "" {
- param["charset"] = "utf-8"
- mimeType = FormatMediaType(mimeType, param)
- }
- mimeLock.Lock()
- mimeTypes[extension] = mimeType
- mimeLock.Unlock()
- return nil
-}
diff --git a/src/pkg/mime/type_test.go b/src/pkg/mime/type_test.go
deleted file mode 100644
index 07e1cd5da..000000000
--- a/src/pkg/mime/type_test.go
+++ /dev/null
@@ -1,29 +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.
-
-package mime
-
-import "testing"
-
-var typeTests = initMimeForTests()
-
-func TestTypeByExtension(t *testing.T) {
- for ext, want := range typeTests {
- val := TypeByExtension(ext)
- if val != want {
- t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want)
- }
-
- }
-}
-
-func TestCustomExtension(t *testing.T) {
- custom := "text/xml; charset=iso-8859-1"
- if error := AddExtensionType(".xml", custom); error != nil {
- t.Fatalf("error %s for AddExtension(%s)", error, custom)
- }
- if registered := TypeByExtension(".xml"); registered != custom {
- t.Fatalf("registered %s instead of %s", registered, custom)
- }
-}
diff --git a/src/pkg/net/dnsconfig_unix_test.go b/src/pkg/net/dnsconfig_unix_test.go
deleted file mode 100644
index 37ed4931d..000000000
--- a/src/pkg/net/dnsconfig_unix_test.go
+++ /dev/null
@@ -1,46 +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 darwin dragonfly freebsd linux netbsd openbsd solaris
-
-package net
-
-import "testing"
-
-func TestDNSReadConfig(t *testing.T) {
- dnsConfig, err := dnsReadConfig("testdata/resolv.conf")
- if err != nil {
- t.Fatal(err)
- }
-
- if len(dnsConfig.servers) != 1 {
- t.Errorf("len(dnsConfig.servers) = %d; want %d", len(dnsConfig.servers), 1)
- }
- if dnsConfig.servers[0] != "[192.168.1.1]" {
- t.Errorf("dnsConfig.servers[0] = %s; want %s", dnsConfig.servers[0], "[192.168.1.1]")
- }
-
- if len(dnsConfig.search) != 1 {
- t.Errorf("len(dnsConfig.search) = %d; want %d", len(dnsConfig.search), 1)
- }
- if dnsConfig.search[0] != "Home" {
- t.Errorf("dnsConfig.search[0] = %s; want %s", dnsConfig.search[0], "Home")
- }
-
- if dnsConfig.ndots != 5 {
- t.Errorf("dnsConfig.ndots = %d; want %d", dnsConfig.ndots, 5)
- }
-
- if dnsConfig.timeout != 10 {
- t.Errorf("dnsConfig.timeout = %d; want %d", dnsConfig.timeout, 10)
- }
-
- if dnsConfig.attempts != 3 {
- t.Errorf("dnsConfig.attempts = %d; want %d", dnsConfig.attempts, 3)
- }
-
- if dnsConfig.rotate != true {
- t.Errorf("dnsConfig.rotate = %t; want %t", dnsConfig.rotate, true)
- }
-}
diff --git a/src/pkg/net/empty.c b/src/pkg/net/empty.c
deleted file mode 100644
index a515c2fe2..000000000
--- a/src/pkg/net/empty.c
+++ /dev/null
@@ -1,8 +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.
-
-// This file is required to prevent compiler errors
-// when the package built with CGO_ENABLED=0.
-// Otherwise the compiler says:
-// pkg/net/fd_poll_runtime.go:15: missing function body
diff --git a/src/pkg/net/http/httputil/chunked.go b/src/pkg/net/http/httputil/chunked.go
deleted file mode 100644
index 9632bfd19..000000000
--- a/src/pkg/net/http/httputil/chunked.go
+++ /dev/null
@@ -1,203 +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.
-
-// The wire protocol for HTTP's "chunked" Transfer-Encoding.
-
-// This code is duplicated in net/http and net/http/httputil.
-// Please make any changes in both files.
-
-package httputil
-
-import (
- "bufio"
- "bytes"
- "errors"
- "fmt"
- "io"
-)
-
-const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
-
-var ErrLineTooLong = errors.New("header line too long")
-
-// newChunkedReader returns a new chunkedReader that translates the data read from r
-// out of HTTP "chunked" format before returning it.
-// The chunkedReader returns io.EOF when the final 0-length chunk is read.
-//
-// newChunkedReader is not needed by normal applications. The http package
-// automatically decodes chunking when reading response bodies.
-func newChunkedReader(r io.Reader) io.Reader {
- br, ok := r.(*bufio.Reader)
- if !ok {
- br = bufio.NewReader(r)
- }
- return &chunkedReader{r: br}
-}
-
-type chunkedReader struct {
- r *bufio.Reader
- n uint64 // unread bytes in chunk
- err error
- buf [2]byte
-}
-
-func (cr *chunkedReader) beginChunk() {
- // chunk-size CRLF
- var line []byte
- line, cr.err = readLine(cr.r)
- if cr.err != nil {
- return
- }
- cr.n, cr.err = parseHexUint(line)
- if cr.err != nil {
- return
- }
- if cr.n == 0 {
- cr.err = io.EOF
- }
-}
-
-func (cr *chunkedReader) chunkHeaderAvailable() bool {
- n := cr.r.Buffered()
- if n > 0 {
- peek, _ := cr.r.Peek(n)
- return bytes.IndexByte(peek, '\n') >= 0
- }
- return false
-}
-
-func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
- for cr.err == nil {
- if cr.n == 0 {
- if n > 0 && !cr.chunkHeaderAvailable() {
- // We've read enough. Don't potentially block
- // reading a new chunk header.
- break
- }
- cr.beginChunk()
- continue
- }
- if len(b) == 0 {
- break
- }
- rbuf := b
- if uint64(len(rbuf)) > cr.n {
- rbuf = rbuf[:cr.n]
- }
- var n0 int
- n0, cr.err = cr.r.Read(rbuf)
- n += n0
- b = b[n0:]
- cr.n -= uint64(n0)
- // If we're at the end of a chunk, read the next two
- // bytes to verify they are "\r\n".
- if cr.n == 0 && cr.err == nil {
- if _, cr.err = io.ReadFull(cr.r, cr.buf[:2]); cr.err == nil {
- if cr.buf[0] != '\r' || cr.buf[1] != '\n' {
- cr.err = errors.New("malformed chunked encoding")
- }
- }
- }
- }
- return n, cr.err
-}
-
-// 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 {
- // We always know when EOF is coming.
- // If the caller asked for a line, there should be a line.
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- } else if err == bufio.ErrBufferFull {
- err = ErrLineTooLong
- }
- return nil, err
- }
- if len(p) >= maxLineLength {
- return nil, ErrLineTooLong
- }
- return trimTrailingWhitespace(p), nil
-}
-
-func trimTrailingWhitespace(b []byte) []byte {
- for len(b) > 0 && isASCIISpace(b[len(b)-1]) {
- b = b[:len(b)-1]
- }
- return b
-}
-
-func isASCIISpace(b byte) bool {
- return b == ' ' || b == '\t' || b == '\n' || b == '\r'
-}
-
-// 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.
-//
-// newChunkedWriter is not needed by normal applications. The http
-// package adds chunking automatically if handlers don't set a
-// Content-Length header. Using newChunkedWriter inside a handler
-// would result in double chunking or chunking with a Content-Length
-// length, both of which are wrong.
-func newChunkedWriter(w io.Writer) io.WriteCloser {
- return &chunkedWriter{w}
-}
-
-// Writing to chunkedWriter translates to writing in HTTP chunked Transfer
-// Encoding wire format to the underlying Wire chunkedWriter.
-type chunkedWriter struct {
- Wire io.Writer
-}
-
-// Write the contents of data as one chunk to Wire.
-// NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has
-// a bug since it does not check for success of io.WriteString
-func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
-
- // Don't send 0-length data. It looks like EOF for chunked encoding.
- if len(data) == 0 {
- return 0, nil
- }
-
- if _, err = fmt.Fprintf(cw.Wire, "%x\r\n", len(data)); err != nil {
- return 0, err
- }
- if n, err = cw.Wire.Write(data); err != nil {
- return
- }
- if n != len(data) {
- err = io.ErrShortWrite
- return
- }
- _, err = io.WriteString(cw.Wire, "\r\n")
-
- return
-}
-
-func (cw *chunkedWriter) Close() error {
- _, err := io.WriteString(cw.Wire, "0\r\n")
- return err
-}
-
-func parseHexUint(v []byte) (n uint64, err error) {
- for _, b := range v {
- n <<= 4
- switch {
- case '0' <= b && b <= '9':
- b = b - '0'
- case 'a' <= b && b <= 'f':
- b = b - 'a' + 10
- case 'A' <= b && b <= 'F':
- b = b - 'A' + 10
- default:
- return 0, errors.New("invalid byte in chunk length")
- }
- n |= uint64(b)
- }
- return
-}
diff --git a/src/pkg/net/http/httputil/chunked_test.go b/src/pkg/net/http/httputil/chunked_test.go
deleted file mode 100644
index a7a577468..000000000
--- a/src/pkg/net/http/httputil/chunked_test.go
+++ /dev/null
@@ -1,159 +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.
-
-// This code is duplicated in net/http and net/http/httputil.
-// Please make any changes in both files.
-
-package httputil
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "strings"
- "testing"
-)
-
-func TestChunk(t *testing.T) {
- var b bytes.Buffer
-
- w := newChunkedWriter(&b)
- const chunk1 = "hello, "
- const chunk2 = "world! 0123456789abcdef"
- w.Write([]byte(chunk1))
- w.Write([]byte(chunk2))
- w.Close()
-
- if g, e := b.String(), "7\r\nhello, \r\n17\r\nworld! 0123456789abcdef\r\n0\r\n"; g != e {
- t.Fatalf("chunk writer wrote %q; want %q", g, e)
- }
-
- r := newChunkedReader(&b)
- data, err := ioutil.ReadAll(r)
- if err != nil {
- t.Logf(`data: "%s"`, data)
- t.Fatalf("ReadAll from reader: %v", err)
- }
- if g, e := string(data), chunk1+chunk2; g != e {
- t.Errorf("chunk reader read %q; want %q", g, e)
- }
-}
-
-func TestChunkReadMultiple(t *testing.T) {
- // Bunch of small chunks, all read together.
- {
- var b bytes.Buffer
- w := newChunkedWriter(&b)
- w.Write([]byte("foo"))
- w.Write([]byte("bar"))
- w.Close()
-
- r := newChunkedReader(&b)
- buf := make([]byte, 10)
- n, err := r.Read(buf)
- if n != 6 || err != io.EOF {
- t.Errorf("Read = %d, %v; want 6, EOF", n, err)
- }
- buf = buf[:n]
- if string(buf) != "foobar" {
- t.Errorf("Read = %q; want %q", buf, "foobar")
- }
- }
-
- // One big chunk followed by a little chunk, but the small bufio.Reader size
- // should prevent the second chunk header from being read.
- {
- var b bytes.Buffer
- w := newChunkedWriter(&b)
- // fillBufChunk is 11 bytes + 3 bytes header + 2 bytes footer = 16 bytes,
- // the same as the bufio ReaderSize below (the minimum), so even
- // though we're going to try to Read with a buffer larger enough to also
- // receive "foo", the second chunk header won't be read yet.
- const fillBufChunk = "0123456789a"
- const shortChunk = "foo"
- w.Write([]byte(fillBufChunk))
- w.Write([]byte(shortChunk))
- w.Close()
-
- r := newChunkedReader(bufio.NewReaderSize(&b, 16))
- buf := make([]byte, len(fillBufChunk)+len(shortChunk))
- n, err := r.Read(buf)
- if n != len(fillBufChunk) || err != nil {
- t.Errorf("Read = %d, %v; want %d, nil", n, err, len(fillBufChunk))
- }
- buf = buf[:n]
- if string(buf) != fillBufChunk {
- t.Errorf("Read = %q; want %q", buf, fillBufChunk)
- }
-
- n, err = r.Read(buf)
- if n != len(shortChunk) || err != io.EOF {
- t.Errorf("Read = %d, %v; want %d, EOF", n, err, len(shortChunk))
- }
- }
-
- // And test that we see an EOF chunk, even though our buffer is already full:
- {
- r := newChunkedReader(bufio.NewReader(strings.NewReader("3\r\nfoo\r\n0\r\n")))
- buf := make([]byte, 3)
- n, err := r.Read(buf)
- if n != 3 || err != io.EOF {
- t.Errorf("Read = %d, %v; want 3, EOF", n, err)
- }
- if string(buf) != "foo" {
- t.Errorf("buf = %q; want foo", buf)
- }
- }
-}
-
-func TestChunkReaderAllocs(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping in short mode")
- }
- var buf bytes.Buffer
- w := newChunkedWriter(&buf)
- a, b, c := []byte("aaaaaa"), []byte("bbbbbbbbbbbb"), []byte("cccccccccccccccccccccccc")
- w.Write(a)
- w.Write(b)
- w.Write(c)
- w.Close()
-
- readBuf := make([]byte, len(a)+len(b)+len(c)+1)
- byter := bytes.NewReader(buf.Bytes())
- bufr := bufio.NewReader(byter)
- mallocs := testing.AllocsPerRun(100, func() {
- byter.Seek(0, 0)
- bufr.Reset(byter)
- r := newChunkedReader(bufr)
- n, err := io.ReadFull(r, readBuf)
- if n != len(readBuf)-1 {
- t.Fatalf("read %d bytes; want %d", n, len(readBuf)-1)
- }
- if err != io.ErrUnexpectedEOF {
- t.Fatalf("read error = %v; want ErrUnexpectedEOF", err)
- }
- })
- if mallocs > 1.5 {
- t.Errorf("mallocs = %v; want 1", mallocs)
- }
-}
-
-func TestParseHexUint(t *testing.T) {
- 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)
- }
- }
- _, err := parseHexUint([]byte("bogus"))
- if err == nil {
- t.Error("expected error on bogus input")
- }
-}
diff --git a/src/pkg/net/lookup_test.go b/src/pkg/net/lookup_test.go
deleted file mode 100644
index 3355e4694..000000000
--- a/src/pkg/net/lookup_test.go
+++ /dev/null
@@ -1,137 +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.
-
-// TODO It would be nice to use a mock DNS server, to eliminate
-// external dependencies.
-
-package net
-
-import (
- "flag"
- "strings"
- "testing"
-)
-
-var testExternal = flag.Bool("external", true, "allow use of external networks during long test")
-
-func TestGoogleSRV(t *testing.T) {
- if testing.Short() || !*testExternal {
- t.Skip("skipping test to avoid external network")
- }
- _, addrs, err := LookupSRV("xmpp-server", "tcp", "google.com")
- if err != nil {
- t.Errorf("failed: %s", err)
- }
- if len(addrs) == 0 {
- t.Errorf("no results")
- }
-
- // Non-standard back door.
- _, addrs, err = LookupSRV("", "", "_xmpp-server._tcp.google.com")
- if err != nil {
- t.Errorf("back door failed: %s", err)
- }
- if len(addrs) == 0 {
- t.Errorf("back door no results")
- }
-}
-
-func TestGmailMX(t *testing.T) {
- if testing.Short() || !*testExternal {
- t.Skip("skipping test to avoid external network")
- }
- mx, err := LookupMX("gmail.com")
- if err != nil {
- t.Errorf("failed: %s", err)
- }
- if len(mx) == 0 {
- t.Errorf("no results")
- }
-}
-
-func TestGmailNS(t *testing.T) {
- if testing.Short() || !*testExternal {
- t.Skip("skipping test to avoid external network")
- }
- ns, err := LookupNS("gmail.com")
- if err != nil {
- t.Errorf("failed: %s", err)
- }
- if len(ns) == 0 {
- t.Errorf("no results")
- }
-}
-
-func TestGmailTXT(t *testing.T) {
- if testing.Short() || !*testExternal {
- t.Skip("skipping test to avoid external network")
- }
- txt, err := LookupTXT("gmail.com")
- if err != nil {
- t.Errorf("failed: %s", err)
- }
- if len(txt) == 0 || len(txt[0]) == 0 {
- t.Errorf("no results")
- }
-}
-
-func TestGoogleDNSAddr(t *testing.T) {
- if testing.Short() || !*testExternal {
- t.Skip("skipping test to avoid external network")
- }
- names, err := LookupAddr("8.8.8.8")
- if err != nil {
- t.Errorf("failed: %s", err)
- }
- if len(names) == 0 {
- t.Errorf("no results")
- }
-}
-
-func TestLookupIANACNAME(t *testing.T) {
- if testing.Short() || !*testExternal {
- t.Skip("skipping test to avoid external network")
- }
- cname, err := LookupCNAME("www.iana.org")
- if !strings.HasSuffix(cname, ".icann.org.") || err != nil {
- t.Errorf(`LookupCNAME("www.iana.org.") = %q, %v, want "*.icann.org.", nil`, cname, err)
- }
-}
-
-var revAddrTests = []struct {
- Addr string
- Reverse string
- ErrPrefix string
-}{
- {"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""},
- {"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""},
- {"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""},
- {"::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", ""},
- {"1::", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.ip6.arpa.", ""},
- {"1234:567::89a:bcde", "e.d.c.b.a.9.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.7.6.5.0.4.3.2.1.ip6.arpa.", ""},
- {"1234:567:fefe:bcbc:adad:9e4a:89a:bcde", "e.d.c.b.a.9.8.0.a.4.e.9.d.a.d.a.c.b.c.b.e.f.e.f.7.6.5.0.4.3.2.1.ip6.arpa.", ""},
- {"1.2.3", "", "unrecognized address"},
- {"1.2.3.4.5", "", "unrecognized address"},
- {"1234:567:bcbca::89a:bcde", "", "unrecognized address"},
- {"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"},
-}
-
-func TestReverseAddress(t *testing.T) {
- for i, tt := range revAddrTests {
- a, err := reverseaddr(tt.Addr)
- if len(tt.ErrPrefix) > 0 && err == nil {
- t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix)
- continue
- }
- if len(tt.ErrPrefix) == 0 && err != nil {
- t.Errorf("#%d: expected <nil>, got %q (error)", i, err)
- }
- if err != nil && err.(*DNSError).Err != tt.ErrPrefix {
- t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err)
- }
- if a != tt.Reverse {
- t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
- }
- }
-}
diff --git a/src/pkg/net/rpc/client_test.go b/src/pkg/net/rpc/client_test.go
deleted file mode 100644
index bbfc1ec3a..000000000
--- a/src/pkg/net/rpc/client_test.go
+++ /dev/null
@@ -1,36 +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 rpc
-
-import (
- "errors"
- "testing"
-)
-
-type shutdownCodec struct {
- responded chan int
- closed bool
-}
-
-func (c *shutdownCodec) WriteRequest(*Request, interface{}) error { return nil }
-func (c *shutdownCodec) ReadResponseBody(interface{}) error { return nil }
-func (c *shutdownCodec) ReadResponseHeader(*Response) error {
- c.responded <- 1
- return errors.New("shutdownCodec ReadResponseHeader")
-}
-func (c *shutdownCodec) Close() error {
- c.closed = true
- return nil
-}
-
-func TestCloseCodec(t *testing.T) {
- codec := &shutdownCodec{responded: make(chan int)}
- client := NewClientWithCodec(codec)
- <-codec.responded
- client.Close()
- if !codec.closed {
- t.Error("client.Close did not close codec")
- }
-}
diff --git a/src/pkg/net/singleflight.go b/src/pkg/net/singleflight.go
deleted file mode 100644
index dc58affda..000000000
--- a/src/pkg/net/singleflight.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 net
-
-import "sync"
-
-// call is an in-flight or completed singleflight.Do call
-type call struct {
- wg sync.WaitGroup
- val interface{}
- err error
- dups int
-}
-
-// singleflight represents a class of work and forms a namespace in
-// which units of work can be executed with duplicate suppression.
-type singleflight struct {
- mu sync.Mutex // protects m
- m map[string]*call // lazily initialized
-}
-
-// Do executes and returns the results of the given function, making
-// sure that only one execution is in-flight for a given key at a
-// time. If a duplicate comes in, the duplicate caller waits for the
-// original to complete and receives the same results.
-// The return value shared indicates whether v was given to multiple callers.
-func (g *singleflight) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) {
- g.mu.Lock()
- if g.m == nil {
- g.m = make(map[string]*call)
- }
- if c, ok := g.m[key]; ok {
- c.dups++
- g.mu.Unlock()
- c.wg.Wait()
- return c.val, c.err, true
- }
- c := new(call)
- c.wg.Add(1)
- g.m[key] = c
- g.mu.Unlock()
-
- c.val, c.err = fn()
- c.wg.Done()
-
- g.mu.Lock()
- delete(g.m, key)
- g.mu.Unlock()
-
- return c.val, c.err, c.dups > 0
-}
diff --git a/src/pkg/net/tcpsockopt_openbsd.go b/src/pkg/net/tcpsockopt_openbsd.go
deleted file mode 100644
index 3480f932c..000000000
--- a/src/pkg/net/tcpsockopt_openbsd.go
+++ /dev/null
@@ -1,27 +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.
-
-// TCP socket options for openbsd
-
-package net
-
-import (
- "os"
- "syscall"
- "time"
-)
-
-// Set keep alive period.
-func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
- if err := fd.incref(); err != nil {
- return err
- }
- defer fd.decref()
-
- // The kernel expects seconds so round to next highest second.
- d += (time.Second - time.Nanosecond)
- secs := int(d.Seconds())
-
- return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.SO_KEEPALIVE, secs))
-}
diff --git a/src/pkg/net/tcpsockopt_solaris.go b/src/pkg/net/tcpsockopt_solaris.go
deleted file mode 100644
index eaab6b678..000000000
--- a/src/pkg/net/tcpsockopt_solaris.go
+++ /dev/null
@@ -1,27 +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.
-
-// TCP socket options for solaris
-
-package net
-
-import (
- "os"
- "syscall"
- "time"
-)
-
-// Set keep alive period.
-func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
- if err := fd.incref(); err != nil {
- return err
- }
- defer fd.decref()
-
- // The kernel expects seconds so round to next highest second.
- d += (time.Second - time.Nanosecond)
- secs := int(d.Seconds())
-
- return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.SO_KEEPALIVE, secs))
-}
diff --git a/src/pkg/net/testdata/resolv.conf b/src/pkg/net/testdata/resolv.conf
deleted file mode 100644
index 3841bbf90..000000000
--- a/src/pkg/net/testdata/resolv.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/resolv.conf
-
-domain Home
-nameserver 192.168.1.1
-options ndots:5 timeout:10 attempts:3 rotate
-options attempts 3
diff --git a/src/pkg/net/z_last_test.go b/src/pkg/net/z_last_test.go
deleted file mode 100644
index 4f6a54a56..000000000
--- a/src/pkg/net/z_last_test.go
+++ /dev/null
@@ -1,37 +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 (
- "flag"
- "fmt"
- "testing"
-)
-
-var testDNSFlood = flag.Bool("dnsflood", false, "whether to test dns query flooding")
-
-func TestDNSThreadLimit(t *testing.T) {
- if !*testDNSFlood {
- t.Skip("test disabled; use -dnsflood to enable")
- }
-
- const N = 10000
- c := make(chan int, N)
- for i := 0; i < N; i++ {
- go func(i int) {
- LookupIP(fmt.Sprintf("%d.net-test.golang.org", i))
- c <- 1
- }(i)
- }
- // Don't bother waiting for the stragglers; stop at 0.9 N.
- for i := 0; i < N*9/10; i++ {
- if i%100 == 0 {
- //println("TestDNSThreadLimit:", i)
- }
- <-c
- }
-
- // If we're still here, it worked.
-}
diff --git a/src/pkg/reflect/export_test.go b/src/pkg/reflect/export_test.go
deleted file mode 100644
index 0778ad37f..000000000
--- a/src/pkg/reflect/export_test.go
+++ /dev/null
@@ -1,19 +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 reflect
-
-// MakeRO returns a copy of v with the read-only flag set.
-func MakeRO(v Value) Value {
- v.flag |= flagRO
- return v
-}
-
-// IsRO reports whether v's read-only flag is set.
-func IsRO(v Value) bool {
- return v.flag&flagRO != 0
-}
-
-var ArrayOf = arrayOf
-var CallGC = &callGC
diff --git a/src/pkg/runtime/alg.goc b/src/pkg/runtime/alg.goc
deleted file mode 100644
index f1b8d5982..000000000
--- a/src/pkg/runtime/alg.goc
+++ /dev/null
@@ -1,549 +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
-#include "runtime.h"
-#include "type.h"
-#include "../../cmd/ld/textflag.h"
-
-#define M0 (sizeof(uintptr)==4 ? 2860486313UL : 33054211828000289ULL)
-#define M1 (sizeof(uintptr)==4 ? 3267000013UL : 23344194077549503ULL)
-
-static bool use_aeshash;
-
-/*
- * map and chan helpers for
- * dealing with unknown types
- */
-void
-runtime·memhash(uintptr *h, uintptr s, void *a)
-{
- byte *b;
- uintptr hash;
- if(!NaCl && use_aeshash) {
- runtime·aeshash(h, s, a);
- return;
- }
-
- b = a;
- hash = M0 ^ *h;
- while(s > 0) {
- hash = (hash ^ *b) * M1;
- b++;
- s--;
- }
- *h = hash;
-}
-
-void
-runtime·memequal(bool *eq, uintptr s, void *a, void *b)
-{
- if(a == b) {
- *eq = 1;
- return;
- }
- *eq = runtime·memeq(a, b, s);
-}
-
-void
-runtime·memprint(uintptr s, void *a)
-{
- uint64 v;
-
- v = 0xbadb00b;
- switch(s) {
- case 1:
- v = *(uint8*)a;
- break;
- case 2:
- v = *(uint16*)a;
- break;
- case 4:
- v = *(uint32*)a;
- break;
- case 8:
- v = *(uint64*)a;
- break;
- }
- runtime·printint(v);
-}
-
-void
-runtime·memcopy(uintptr s, void *a, void *b)
-{
- if(b == nil) {
- runtime·memclr(a, s);
- return;
- }
- runtime·memmove(a, b, s);
-}
-
-void
-runtime·memequal0(bool *eq, uintptr s, void *a, void *b)
-{
- USED(s);
- USED(a);
- USED(b);
- *eq = true;
-}
-
-void
-runtime·memcopy0(uintptr s, void *a, void *b)
-{
- USED(s);
- USED(a);
- USED(b);
-}
-
-void
-runtime·memequal8(bool *eq, uintptr s, void *a, void *b)
-{
- USED(s);
- *eq = *(uint8*)a == *(uint8*)b;
-}
-
-void
-runtime·memcopy8(uintptr s, void *a, void *b)
-{
- USED(s);
- if(b == nil) {
- *(uint8*)a = 0;
- return;
- }
- *(uint8*)a = *(uint8*)b;
-}
-
-void
-runtime·memequal16(bool *eq, uintptr s, void *a, void *b)
-{
- USED(s);
- *eq = *(uint16*)a == *(uint16*)b;
-}
-
-void
-runtime·memcopy16(uintptr s, void *a, void *b)
-{
- USED(s);
- if(b == nil) {
- *(uint16*)a = 0;
- return;
- }
- *(uint16*)a = *(uint16*)b;
-}
-
-void
-runtime·memequal32(bool *eq, uintptr s, void *a, void *b)
-{
- USED(s);
- *eq = *(uint32*)a == *(uint32*)b;
-}
-
-void
-runtime·memcopy32(uintptr s, void *a, void *b)
-{
- USED(s);
- if(b == nil) {
- *(uint32*)a = 0;
- return;
- }
- *(uint32*)a = *(uint32*)b;
-}
-
-void
-runtime·memequal64(bool *eq, uintptr s, void *a, void *b)
-{
- USED(s);
- *eq = *(uint64*)a == *(uint64*)b;
-}
-
-void
-runtime·memcopy64(uintptr s, void *a, void *b)
-{
- USED(s);
- if(b == nil) {
- *(uint64*)a = 0;
- return;
- }
- *(uint64*)a = *(uint64*)b;
-}
-
-void
-runtime·memequal128(bool *eq, uintptr s, void *a, void *b)
-{
- USED(s);
- *eq = ((uint64*)a)[0] == ((uint64*)b)[0] && ((uint64*)a)[1] == ((uint64*)b)[1];
-}
-
-void
-runtime·memcopy128(uintptr s, void *a, void *b)
-{
- USED(s);
- if(b == nil) {
- ((uint64*)a)[0] = 0;
- ((uint64*)a)[1] = 0;
- return;
- }
- ((uint64*)a)[0] = ((uint64*)b)[0];
- ((uint64*)a)[1] = ((uint64*)b)[1];
-}
-
-void
-runtime·f32equal(bool *eq, uintptr s, void *a, void *b)
-{
- USED(s);
- *eq = *(float32*)a == *(float32*)b;
-}
-
-void
-runtime·f64equal(bool *eq, uintptr s, void *a, void *b)
-{
- USED(s);
- *eq = *(float64*)a == *(float64*)b;
-}
-
-void
-runtime·c64equal(bool *eq, uintptr s, void *a, void *b)
-{
- Complex64 *ca, *cb;
-
- USED(s);
- ca = a;
- cb = b;
- *eq = ca->real == cb->real && ca->imag == cb->imag;
-}
-
-void
-runtime·c128equal(bool *eq, uintptr s, void *a, void *b)
-{
- Complex128 *ca, *cb;
-
- USED(s);
- ca = a;
- cb = b;
- *eq = ca->real == cb->real && ca->imag == cb->imag;
-}
-
-// NOTE: Because NaN != NaN, a map can contain any
-// number of (mostly useless) entries keyed with NaNs.
-// To avoid long hash chains, we assign a random number
-// as the hash value for a NaN.
-
-void
-runtime·f32hash(uintptr *h, uintptr s, void *a)
-{
- uintptr hash;
- float32 f;
-
- USED(s);
- f = *(float32*)a;
- if(f == 0)
- hash = 0; // +0, -0
- else if(f != f)
- hash = runtime·fastrand1(); // any kind of NaN
- else
- hash = *(uint32*)a;
- *h = (*h ^ hash ^ M0) * M1;
-}
-
-void
-runtime·f64hash(uintptr *h, uintptr s, void *a)
-{
- uintptr hash;
- float64 f;
- uint64 u;
-
- USED(s);
- f = *(float64*)a;
- if(f == 0)
- hash = 0; // +0, -0
- else if(f != f)
- hash = runtime·fastrand1(); // any kind of NaN
- else {
- u = *(uint64*)a;
- if(sizeof(uintptr) == 4)
- hash = ((uint32)(u>>32) * M1) ^ (uint32)u;
- else
- hash = u;
- }
- *h = (*h ^ hash ^ M0) * M1;
-}
-
-void
-runtime·c64hash(uintptr *h, uintptr s, void *a)
-{
- USED(s);
- runtime·f32hash(h, 0, a);
- runtime·f32hash(h, 0, (float32*)a+1);
-}
-
-void
-runtime·c128hash(uintptr *h, uintptr s, void *a)
-{
- USED(s);
- runtime·f64hash(h, 0, a);
- runtime·f64hash(h, 0, (float64*)a+1);
-}
-
-void
-runtime·slicecopy(uintptr s, void *a, void *b)
-{
- USED(s);
- if(b == nil) {
- ((Slice*)a)->array = 0;
- ((Slice*)a)->len = 0;
- ((Slice*)a)->cap = 0;
- return;
- }
- ((Slice*)a)->array = ((Slice*)b)->array;
- ((Slice*)a)->len = ((Slice*)b)->len;
- ((Slice*)a)->cap = ((Slice*)b)->cap;
-}
-
-void
-runtime·strhash(uintptr *h, uintptr s, void *a)
-{
- USED(s);
- runtime·memhash(h, ((String*)a)->len, ((String*)a)->str);
-}
-
-void
-runtime·strequal(bool *eq, uintptr s, void *a, void *b)
-{
- intgo alen;
- byte *s1, *s2;
-
- USED(s);
- alen = ((String*)a)->len;
- if(alen != ((String*)b)->len) {
- *eq = false;
- return;
- }
- s1 = ((String*)a)->str;
- s2 = ((String*)b)->str;
- if(s1 == s2) {
- *eq = true;
- return;
- }
- *eq = runtime·memeq(s1, s2, alen);
-}
-
-void
-runtime·strprint(uintptr s, void *a)
-{
- USED(s);
- runtime·printstring(*(String*)a);
-}
-
-void
-runtime·strcopy(uintptr s, void *a, void *b)
-{
- USED(s);
- if(b == nil) {
- ((String*)a)->str = 0;
- ((String*)a)->len = 0;
- return;
- }
- ((String*)a)->str = ((String*)b)->str;
- ((String*)a)->len = ((String*)b)->len;
-}
-
-void
-runtime·interhash(uintptr *h, uintptr s, void *a)
-{
- USED(s);
- *h = runtime·ifacehash(*(Iface*)a, *h ^ M0) * M1;
-}
-
-void
-runtime·interprint(uintptr s, void *a)
-{
- USED(s);
- runtime·printiface(*(Iface*)a);
-}
-
-void
-runtime·interequal(bool *eq, uintptr s, void *a, void *b)
-{
- USED(s);
- *eq = runtime·ifaceeq_c(*(Iface*)a, *(Iface*)b);
-}
-
-void
-runtime·intercopy(uintptr s, void *a, void *b)
-{
- USED(s);
- if(b == nil) {
- ((Iface*)a)->tab = 0;
- ((Iface*)a)->data = 0;
- return;
- }
- ((Iface*)a)->tab = ((Iface*)b)->tab;
- ((Iface*)a)->data = ((Iface*)b)->data;
-}
-
-void
-runtime·nilinterhash(uintptr *h, uintptr s, void *a)
-{
- USED(s);
- *h = runtime·efacehash(*(Eface*)a, *h ^ M0) * M1;
-}
-
-void
-runtime·nilinterprint(uintptr s, void *a)
-{
- USED(s);
- runtime·printeface(*(Eface*)a);
-}
-
-void
-runtime·nilinterequal(bool *eq, uintptr s, void *a, void *b)
-{
- USED(s);
- *eq = runtime·efaceeq_c(*(Eface*)a, *(Eface*)b);
-}
-
-void
-runtime·nilintercopy(uintptr s, void *a, void *b)
-{
- USED(s);
- if(b == nil) {
- ((Eface*)a)->type = 0;
- ((Eface*)a)->data = 0;
- return;
- }
- ((Eface*)a)->type = ((Eface*)b)->type;
- ((Eface*)a)->data = ((Eface*)b)->data;
-}
-
-void
-runtime·nohash(uintptr *h, uintptr s, void *a)
-{
- USED(s);
- USED(a);
- USED(h);
- runtime·panicstring("hash of unhashable type");
-}
-
-void
-runtime·noequal(bool *eq, uintptr s, void *a, void *b)
-{
- USED(s);
- USED(a);
- USED(b);
- USED(eq);
- runtime·panicstring("comparing uncomparable types");
-}
-
-Alg
-runtime·algarray[] =
-{
-[AMEM] { runtime·memhash, runtime·memequal, runtime·memprint, runtime·memcopy },
-[ANOEQ] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy },
-[ASTRING] { runtime·strhash, runtime·strequal, runtime·strprint, runtime·strcopy },
-[AINTER] { runtime·interhash, runtime·interequal, runtime·interprint, runtime·intercopy },
-[ANILINTER] { runtime·nilinterhash, runtime·nilinterequal, runtime·nilinterprint, runtime·nilintercopy },
-[ASLICE] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·slicecopy },
-[AFLOAT32] { runtime·f32hash, runtime·f32equal, runtime·memprint, runtime·memcopy },
-[AFLOAT64] { runtime·f64hash, runtime·f64equal, runtime·memprint, runtime·memcopy },
-[ACPLX64] { runtime·c64hash, runtime·c64equal, runtime·memprint, runtime·memcopy },
-[ACPLX128] { runtime·c128hash, runtime·c128equal, runtime·memprint, runtime·memcopy },
-[AMEM0] { runtime·memhash, runtime·memequal0, runtime·memprint, runtime·memcopy0 },
-[AMEM8] { runtime·memhash, runtime·memequal8, runtime·memprint, runtime·memcopy8 },
-[AMEM16] { runtime·memhash, runtime·memequal16, runtime·memprint, runtime·memcopy16 },
-[AMEM32] { runtime·memhash, runtime·memequal32, runtime·memprint, runtime·memcopy32 },
-[AMEM64] { runtime·memhash, runtime·memequal64, runtime·memprint, runtime·memcopy64 },
-[AMEM128] { runtime·memhash, runtime·memequal128, runtime·memprint, runtime·memcopy128 },
-[ANOEQ0] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy0 },
-[ANOEQ8] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy8 },
-[ANOEQ16] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy16 },
-[ANOEQ32] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy32 },
-[ANOEQ64] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy64 },
-[ANOEQ128] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy128 },
-};
-
-// Runtime helpers.
-
-// used in asm_{386,amd64}.s
-#pragma dataflag NOPTR
-byte runtime·aeskeysched[HashRandomBytes];
-
-void
-runtime·hashinit(void)
-{
- if(NaCl)
- return;
-
- // Install aes hash algorithm if we have the instructions we need
- if((runtime·cpuid_ecx & (1 << 25)) != 0 && // aes (aesenc)
- (runtime·cpuid_ecx & (1 << 9)) != 0 && // sse3 (pshufb)
- (runtime·cpuid_ecx & (1 << 19)) != 0) { // sse4.1 (pinsr{d,q})
- byte *rnd;
- int32 n;
- use_aeshash = true;
- runtime·algarray[AMEM].hash = runtime·aeshash;
- runtime·algarray[AMEM8].hash = runtime·aeshash;
- runtime·algarray[AMEM16].hash = runtime·aeshash;
- runtime·algarray[AMEM32].hash = runtime·aeshash32;
- runtime·algarray[AMEM64].hash = runtime·aeshash64;
- runtime·algarray[AMEM128].hash = runtime·aeshash;
- runtime·algarray[ASTRING].hash = runtime·aeshashstr;
-
- // Initialize with random data so hash collisions will be hard to engineer.
- runtime·get_random_data(&rnd, &n);
- if(n > HashRandomBytes)
- n = HashRandomBytes;
- runtime·memmove(runtime·aeskeysched, rnd, n);
- if(n < HashRandomBytes) {
- // Not very random, but better than nothing.
- int64 t = runtime·nanotime();
- while (n < HashRandomBytes) {
- runtime·aeskeysched[n++] = (int8)(t >> (8 * (n % 8)));
- }
- }
- }
-}
-
-// func equal(t *Type, x T, y T) (ret bool)
-#pragma textflag NOSPLIT
-void
-runtime·equal(Type *t, ...)
-{
- byte *x, *y;
- bool *ret;
-
- x = (byte*)ROUND((uintptr)(&t+1), t->align);
- y = x + t->size;
- ret = (bool*)ROUND((uintptr)(y+t->size), Structrnd);
- t->alg->equal(ret, t->size, x, y);
-}
-
-// Testing adapter for memclr
-func memclrBytes(s Slice) {
- runtime·memclr(s.array, s.len);
-}
-
-// Testing adapters for hash quality tests (see hash_test.go)
-func haveGoodHash() (res bool) {
- res = use_aeshash;
-}
-
-func stringHash(s String, seed uintptr) (res uintptr) {
- runtime·algarray[ASTRING].hash(&seed, sizeof(String), &s);
- res = seed;
-}
-
-func bytesHash(s Slice, seed uintptr) (res uintptr) {
- runtime·algarray[AMEM].hash(&seed, s.len, s.array);
- res = seed;
-}
-
-func int32Hash(i uint32, seed uintptr) (res uintptr) {
- runtime·algarray[AMEM32].hash(&seed, sizeof(uint32), &i);
- res = seed;
-}
-
-func int64Hash(i uint64, seed uintptr) (res uintptr) {
- runtime·algarray[AMEM64].hash(&seed, sizeof(uint64), &i);
- res = seed;
-}
diff --git a/src/pkg/runtime/atomic_arm.c b/src/pkg/runtime/atomic_arm.c
deleted file mode 100644
index d914475c7..000000000
--- a/src/pkg/runtime/atomic_arm.c
+++ /dev/null
@@ -1,169 +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.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
-
-static struct {
- Lock l;
- byte pad[CacheLineSize-sizeof(Lock)];
-} locktab[57];
-
-#define LOCK(addr) (&locktab[((uintptr)(addr)>>3)%nelem(locktab)].l)
-
-// Atomic add and return new value.
-#pragma textflag NOSPLIT
-uint32
-runtime·xadd(uint32 volatile *val, int32 delta)
-{
- uint32 oval, nval;
-
- for(;;){
- oval = *val;
- nval = oval + delta;
- if(runtime·cas(val, oval, nval))
- return nval;
- }
-}
-
-#pragma textflag NOSPLIT
-uint32
-runtime·xchg(uint32 volatile* addr, uint32 v)
-{
- uint32 old;
-
- for(;;) {
- old = *addr;
- if(runtime·cas(addr, old, v))
- return old;
- }
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·xchgp(void* volatile* addr, void* v)
-{
- void *old;
-
- for(;;) {
- old = *addr;
- if(runtime·casp(addr, old, v))
- return old;
- }
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·procyield(uint32 cnt)
-{
- uint32 volatile i;
-
- for(i = 0; i < cnt; i++) {
- }
-}
-
-#pragma textflag NOSPLIT
-uint32
-runtime·atomicload(uint32 volatile* addr)
-{
- return runtime·xadd(addr, 0);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·atomicloadp(void* volatile* addr)
-{
- return (void*)runtime·xadd((uint32 volatile*)addr, 0);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·atomicstorep(void* volatile* addr, void* v)
-{
- void *old;
-
- for(;;) {
- old = *addr;
- if(runtime·casp(addr, old, v))
- return;
- }
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·atomicstore(uint32 volatile* addr, uint32 v)
-{
- uint32 old;
-
- for(;;) {
- old = *addr;
- if(runtime·cas(addr, old, v))
- return;
- }
-}
-
-#pragma textflag NOSPLIT
-bool
-runtime·cas64(uint64 volatile *addr, uint64 old, uint64 new)
-{
- bool res;
-
- runtime·lock(LOCK(addr));
- if(*addr == old) {
- *addr = new;
- res = true;
- } else {
- res = false;
- }
- runtime·unlock(LOCK(addr));
- return res;
-}
-
-#pragma textflag NOSPLIT
-uint64
-runtime·xadd64(uint64 volatile *addr, int64 delta)
-{
- uint64 res;
-
- runtime·lock(LOCK(addr));
- res = *addr + delta;
- *addr = res;
- runtime·unlock(LOCK(addr));
- return res;
-}
-
-#pragma textflag NOSPLIT
-uint64
-runtime·xchg64(uint64 volatile *addr, uint64 v)
-{
- uint64 res;
-
- runtime·lock(LOCK(addr));
- res = *addr;
- *addr = v;
- runtime·unlock(LOCK(addr));
- return res;
-}
-
-#pragma textflag NOSPLIT
-uint64
-runtime·atomicload64(uint64 volatile *addr)
-{
- uint64 res;
-
- runtime·lock(LOCK(addr));
- res = *addr;
- runtime·unlock(LOCK(addr));
- return res;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·atomicstore64(uint64 volatile *addr, uint64 v)
-{
- runtime·lock(LOCK(addr));
- *addr = v;
- runtime·unlock(LOCK(addr));
-}
diff --git a/src/pkg/runtime/callback_windows.c b/src/pkg/runtime/callback_windows.c
deleted file mode 100644
index 285678fba..000000000
--- a/src/pkg/runtime/callback_windows.c
+++ /dev/null
@@ -1,77 +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.
-
-#include "runtime.h"
-#include "type.h"
-#include "typekind.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "zasm_GOOS_GOARCH.h"
-
-typedef struct Callbacks Callbacks;
-struct Callbacks {
- Lock;
- WinCallbackContext* ctxt[cb_max];
- int32 n;
-};
-
-static Callbacks cbs;
-
-WinCallbackContext** runtime·cbctxts; // to simplify access to cbs.ctxt in sys_windows_*.s
-
-// Call back from windows dll into go.
-byte *
-runtime·compilecallback(Eface fn, bool cleanstack)
-{
- FuncType *ft;
- Type *t;
- int32 argsize, i, n;
- WinCallbackContext *c;
-
- if(fn.type == nil || fn.type->kind != KindFunc)
- runtime·panicstring("compilecallback: not a function");
- ft = (FuncType*)fn.type;
- if(ft->out.len != 1)
- runtime·panicstring("compilecallback: function must have one output parameter");
- if(((Type**)ft->out.array)[0]->size != sizeof(uintptr))
- runtime·panicstring("compilecallback: output parameter size is wrong");
- argsize = 0;
- for(i=0; i<ft->in.len; i++) {
- t = ((Type**)ft->in.array)[i];
- if(t->size > sizeof(uintptr))
- runtime·panicstring("compilecallback: input parameter size is wrong");
- argsize += sizeof(uintptr);
- }
-
- runtime·lock(&cbs);
- if(runtime·cbctxts == nil)
- runtime·cbctxts = &(cbs.ctxt[0]);
- n = cbs.n;
- for(i=0; i<n; i++) {
- if(cbs.ctxt[i]->gobody == fn.data && cbs.ctxt[i]->cleanstack == cleanstack) {
- runtime·unlock(&cbs);
- // runtime·callbackasm is just a series of CALL instructions
- // (each is 5 bytes long), and we want callback to arrive at
- // correspondent call instruction instead of start of
- // runtime·callbackasm.
- return (byte*)runtime·callbackasm + i * 5;
- }
- }
- if(n >= cb_max)
- runtime·throw("too many callback functions");
- c = runtime·mal(sizeof *c);
- c->gobody = fn.data;
- c->argsize = argsize;
- c->cleanstack = cleanstack;
- if(cleanstack && argsize!=0)
- c->restorestack = argsize;
- else
- c->restorestack = 0;
- cbs.ctxt[n] = c;
- cbs.n++;
- runtime·unlock(&cbs);
-
- // as before
- return (byte*)runtime·callbackasm + n * 5;
-}
diff --git a/src/pkg/runtime/chan.goc b/src/pkg/runtime/chan.goc
deleted file mode 100644
index 7a584717b..000000000
--- a/src/pkg/runtime/chan.goc
+++ /dev/null
@@ -1,1155 +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
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "type.h"
-#include "race.h"
-#include "malloc.h"
-#include "chan.h"
-#include "../../cmd/ld/textflag.h"
-
-uint32 runtime·Hchansize = sizeof(Hchan);
-
-static void dequeueg(WaitQ*);
-static SudoG* dequeue(WaitQ*);
-static void enqueue(WaitQ*, SudoG*);
-static void destroychan(Hchan*);
-static void racesync(Hchan*, SudoG*);
-
-static Hchan*
-makechan(ChanType *t, int64 hint)
-{
- Hchan *c;
- Type *elem;
-
- elem = t->elem;
-
- // compiler checks this but be safe.
- if(elem->size >= (1<<16))
- runtime·throw("makechan: invalid channel element type");
- if((sizeof(*c)%MAXALIGN) != 0 || elem->align > MAXALIGN)
- runtime·throw("makechan: bad alignment");
-
- if(hint < 0 || (intgo)hint != hint || (elem->size > 0 && hint > (MaxMem - sizeof(*c)) / elem->size))
- runtime·panicstring("makechan: size out of range");
-
- // allocate memory in one call
- c = (Hchan*)runtime·mallocgc(sizeof(*c) + hint*elem->size, (uintptr)t | TypeInfo_Chan, 0);
- c->elemsize = elem->size;
- c->elemtype = elem;
- c->dataqsiz = hint;
-
- if(debug)
- runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; dataqsiz=%D\n",
- c, (int64)elem->size, elem->alg, (int64)c->dataqsiz);
-
- return c;
-}
-
-func reflect·makechan(t *ChanType, size uint64) (c *Hchan) {
- c = makechan(t, size);
-}
-
-func makechan(t *ChanType, size int64) (c *Hchan) {
- c = makechan(t, size);
-}
-
-/*
- * generic single channel send/recv
- * if the bool pointer is nil,
- * then the full exchange will
- * occur. if pres is not nil,
- * then the protocol will not
- * sleep but return if it could
- * not complete.
- *
- * sleep can wake up with g->param == nil
- * when a channel involved in the sleep has
- * been closed. it is easiest to loop and re-run
- * the operation; we'll see that it's now closed.
- */
-static bool
-chansend(ChanType *t, Hchan *c, byte *ep, bool block, void *pc)
-{
- SudoG *sg;
- SudoG mysg;
- G* gp;
- int64 t0;
-
- if(raceenabled)
- runtime·racereadobjectpc(ep, t->elem, runtime·getcallerpc(&t), chansend);
-
- if(c == nil) {
- USED(t);
- if(!block)
- return false;
- runtime·park(nil, nil, "chan send (nil chan)");
- return false; // not reached
- }
-
- if(debug) {
- runtime·printf("chansend: chan=%p; elem=", c);
- c->elemtype->alg->print(c->elemsize, ep);
- runtime·prints("\n");
- }
-
- t0 = 0;
- mysg.releasetime = 0;
- if(runtime·blockprofilerate > 0) {
- t0 = runtime·cputicks();
- mysg.releasetime = -1;
- }
-
- runtime·lock(c);
- if(raceenabled)
- runtime·racereadpc(c, pc, chansend);
- if(c->closed)
- goto closed;
-
- if(c->dataqsiz > 0)
- goto asynch;
-
- sg = dequeue(&c->recvq);
- if(sg != nil) {
- if(raceenabled)
- racesync(c, sg);
- runtime·unlock(c);
-
- gp = sg->g;
- gp->param = sg;
- if(sg->elem != nil)
- c->elemtype->alg->copy(c->elemsize, sg->elem, ep);
- if(sg->releasetime)
- sg->releasetime = runtime·cputicks();
- runtime·ready(gp);
- return true;
- }
-
- if(!block) {
- runtime·unlock(c);
- return false;
- }
-
- mysg.elem = ep;
- mysg.g = g;
- mysg.selectdone = nil;
- g->param = nil;
- enqueue(&c->sendq, &mysg);
- runtime·parkunlock(c, "chan send");
-
- if(g->param == nil) {
- runtime·lock(c);
- if(!c->closed)
- runtime·throw("chansend: spurious wakeup");
- goto closed;
- }
-
- if(mysg.releasetime > 0)
- runtime·blockevent(mysg.releasetime - t0, 2);
-
- return true;
-
-asynch:
- if(c->closed)
- goto closed;
-
- if(c->qcount >= c->dataqsiz) {
- if(!block) {
- runtime·unlock(c);
- return false;
- }
- mysg.g = g;
- mysg.elem = nil;
- mysg.selectdone = nil;
- enqueue(&c->sendq, &mysg);
- runtime·parkunlock(c, "chan send");
-
- runtime·lock(c);
- goto asynch;
- }
-
- if(raceenabled) {
- runtime·raceacquire(chanbuf(c, c->sendx));
- runtime·racerelease(chanbuf(c, c->sendx));
- }
-
- c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->sendx), ep);
- if(++c->sendx == c->dataqsiz)
- c->sendx = 0;
- c->qcount++;
-
- sg = dequeue(&c->recvq);
- if(sg != nil) {
- gp = sg->g;
- runtime·unlock(c);
- if(sg->releasetime)
- sg->releasetime = runtime·cputicks();
- runtime·ready(gp);
- } else
- runtime·unlock(c);
- if(mysg.releasetime > 0)
- runtime·blockevent(mysg.releasetime - t0, 2);
- return true;
-
-closed:
- runtime·unlock(c);
- runtime·panicstring("send on closed channel");
- return false; // not reached
-}
-
-
-static bool
-chanrecv(ChanType *t, Hchan* c, byte *ep, bool block, bool *received)
-{
- SudoG *sg;
- SudoG mysg;
- G *gp;
- int64 t0;
-
- // raceenabled: don't need to check ep, as it is always on the stack.
-
- if(debug)
- runtime·printf("chanrecv: chan=%p\n", c);
-
- if(c == nil) {
- USED(t);
- if(!block)
- return false;
- runtime·park(nil, nil, "chan receive (nil chan)");
- return false; // not reached
- }
-
- t0 = 0;
- mysg.releasetime = 0;
- if(runtime·blockprofilerate > 0) {
- t0 = runtime·cputicks();
- mysg.releasetime = -1;
- }
-
- runtime·lock(c);
- if(c->dataqsiz > 0)
- goto asynch;
-
- if(c->closed)
- goto closed;
-
- sg = dequeue(&c->sendq);
- if(sg != nil) {
- if(raceenabled)
- racesync(c, sg);
- runtime·unlock(c);
-
- if(ep != nil)
- c->elemtype->alg->copy(c->elemsize, ep, sg->elem);
- gp = sg->g;
- gp->param = sg;
- if(sg->releasetime)
- sg->releasetime = runtime·cputicks();
- runtime·ready(gp);
-
- if(received != nil)
- *received = true;
- return true;
- }
-
- if(!block) {
- runtime·unlock(c);
- return false;
- }
-
- mysg.elem = ep;
- mysg.g = g;
- mysg.selectdone = nil;
- g->param = nil;
- enqueue(&c->recvq, &mysg);
- runtime·parkunlock(c, "chan receive");
-
- if(g->param == nil) {
- runtime·lock(c);
- if(!c->closed)
- runtime·throw("chanrecv: spurious wakeup");
- goto closed;
- }
-
- if(received != nil)
- *received = true;
- if(mysg.releasetime > 0)
- runtime·blockevent(mysg.releasetime - t0, 2);
- return true;
-
-asynch:
- if(c->qcount <= 0) {
- if(c->closed)
- goto closed;
-
- if(!block) {
- runtime·unlock(c);
- if(received != nil)
- *received = false;
- return false;
- }
- mysg.g = g;
- mysg.elem = nil;
- mysg.selectdone = nil;
- enqueue(&c->recvq, &mysg);
- runtime·parkunlock(c, "chan receive");
-
- runtime·lock(c);
- goto asynch;
- }
-
- if(raceenabled) {
- runtime·raceacquire(chanbuf(c, c->recvx));
- runtime·racerelease(chanbuf(c, c->recvx));
- }
-
- if(ep != nil)
- c->elemtype->alg->copy(c->elemsize, ep, chanbuf(c, c->recvx));
- c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->recvx), nil);
- if(++c->recvx == c->dataqsiz)
- c->recvx = 0;
- c->qcount--;
-
- sg = dequeue(&c->sendq);
- if(sg != nil) {
- gp = sg->g;
- runtime·unlock(c);
- if(sg->releasetime)
- sg->releasetime = runtime·cputicks();
- runtime·ready(gp);
- } else
- runtime·unlock(c);
-
- if(received != nil)
- *received = true;
- if(mysg.releasetime > 0)
- runtime·blockevent(mysg.releasetime - t0, 2);
- return true;
-
-closed:
- if(ep != nil)
- c->elemtype->alg->copy(c->elemsize, ep, nil);
- if(received != nil)
- *received = false;
- if(raceenabled)
- runtime·raceacquire(c);
- runtime·unlock(c);
- if(mysg.releasetime > 0)
- runtime·blockevent(mysg.releasetime - t0, 2);
- return true;
-}
-
-#pragma textflag NOSPLIT
-func chansend1(t *ChanType, c *Hchan, elem *byte) {
- chansend(t, c, elem, true, runtime·getcallerpc(&t));
-}
-
-#pragma textflag NOSPLIT
-func chanrecv1(t *ChanType, c *Hchan, elem *byte) {
- chanrecv(t, c, elem, true, nil);
-}
-
-// chanrecv2(hchan *chan any, elem *any) (received bool);
-#pragma textflag NOSPLIT
-func chanrecv2(t *ChanType, c *Hchan, elem *byte) (received bool) {
- chanrecv(t, c, elem, true, &received);
-}
-
-// compiler implements
-//
-// select {
-// case c <- v:
-// ... foo
-// default:
-// ... bar
-// }
-//
-// as
-//
-// if selectnbsend(c, v) {
-// ... foo
-// } else {
-// ... bar
-// }
-//
-#pragma textflag NOSPLIT
-func selectnbsend(t *ChanType, c *Hchan, elem *byte) (selected bool) {
- selected = chansend(t, c, elem, false, runtime·getcallerpc(&t));
-}
-
-// compiler implements
-//
-// select {
-// case v = <-c:
-// ... foo
-// default:
-// ... bar
-// }
-//
-// as
-//
-// if selectnbrecv(&v, c) {
-// ... foo
-// } else {
-// ... bar
-// }
-//
-#pragma textflag NOSPLIT
-func selectnbrecv(t *ChanType, elem *byte, c *Hchan) (selected bool) {
- selected = chanrecv(t, c, elem, false, nil);
-}
-
-// compiler implements
-//
-// select {
-// case v, ok = <-c:
-// ... foo
-// default:
-// ... bar
-// }
-//
-// as
-//
-// if c != nil && selectnbrecv2(&v, &ok, c) {
-// ... foo
-// } else {
-// ... bar
-// }
-//
-#pragma textflag NOSPLIT
-func selectnbrecv2(t *ChanType, elem *byte, received *bool, c *Hchan) (selected bool) {
- selected = chanrecv(t, c, elem, false, received);
-}
-
-#pragma textflag NOSPLIT
-func reflect·chansend(t *ChanType, c *Hchan, elem *byte, nb bool) (selected bool) {
- selected = chansend(t, c, elem, !nb, runtime·getcallerpc(&t));
-}
-
-func reflect·chanrecv(t *ChanType, c *Hchan, nb bool, elem *byte) (selected bool, received bool) {
- received = false;
- selected = chanrecv(t, c, elem, !nb, &received);
-}
-
-static Select* newselect(int32);
-
-#pragma textflag NOSPLIT
-func newselect(size int32) (sel *byte) {
- sel = (byte*)newselect(size);
-}
-
-static Select*
-newselect(int32 size)
-{
- int32 n;
- Select *sel;
-
- n = 0;
- if(size > 1)
- n = size-1;
-
- // allocate all the memory we need in a single allocation
- // start with Select with size cases
- // then lockorder with size entries
- // then pollorder with size entries
- sel = runtime·mal(sizeof(*sel) +
- n*sizeof(sel->scase[0]) +
- size*sizeof(sel->lockorder[0]) +
- size*sizeof(sel->pollorder[0]));
-
- sel->tcase = size;
- sel->ncase = 0;
- sel->lockorder = (void*)(sel->scase + size);
- sel->pollorder = (void*)(sel->lockorder + size);
-
- if(debug)
- runtime·printf("newselect s=%p size=%d\n", sel, size);
- return sel;
-}
-
-// cut in half to give stack a chance to split
-static void selectsend(Select *sel, Hchan *c, void *pc, void *elem, int32 so);
-
-#pragma textflag NOSPLIT
-func selectsend(sel *Select, c *Hchan, elem *byte) (selected bool) {
- selected = false;
-
- // nil cases do not compete
- if(c != nil)
- selectsend(sel, c, runtime·getcallerpc(&sel), elem, (byte*)&selected - (byte*)&sel);
-}
-
-static void
-selectsend(Select *sel, Hchan *c, void *pc, void *elem, int32 so)
-{
- int32 i;
- Scase *cas;
-
- i = sel->ncase;
- if(i >= sel->tcase)
- runtime·throw("selectsend: too many cases");
- sel->ncase = i+1;
- cas = &sel->scase[i];
-
- cas->pc = pc;
- cas->chan = c;
- cas->so = so;
- cas->kind = CaseSend;
- cas->sg.elem = elem;
-
- if(debug)
- runtime·printf("selectsend s=%p pc=%p chan=%p so=%d\n",
- sel, cas->pc, cas->chan, cas->so);
-}
-
-// cut in half to give stack a chance to split
-static void selectrecv(Select *sel, Hchan *c, void *pc, void *elem, bool*, int32 so);
-
-#pragma textflag NOSPLIT
-func selectrecv(sel *Select, c *Hchan, elem *byte) (selected bool) {
- selected = false;
-
- // nil cases do not compete
- if(c != nil)
- selectrecv(sel, c, runtime·getcallerpc(&sel), elem, nil, (byte*)&selected - (byte*)&sel);
-}
-
-#pragma textflag NOSPLIT
-func selectrecv2(sel *Select, c *Hchan, elem *byte, received *bool) (selected bool) {
- selected = false;
-
- // nil cases do not compete
- if(c != nil)
- selectrecv(sel, c, runtime·getcallerpc(&sel), elem, received, (byte*)&selected - (byte*)&sel);
-}
-
-static void
-selectrecv(Select *sel, Hchan *c, void *pc, void *elem, bool *received, int32 so)
-{
- int32 i;
- Scase *cas;
-
- i = sel->ncase;
- if(i >= sel->tcase)
- runtime·throw("selectrecv: too many cases");
- sel->ncase = i+1;
- cas = &sel->scase[i];
- cas->pc = pc;
- cas->chan = c;
-
- cas->so = so;
- cas->kind = CaseRecv;
- cas->sg.elem = elem;
- cas->receivedp = received;
-
- if(debug)
- runtime·printf("selectrecv s=%p pc=%p chan=%p so=%d\n",
- sel, cas->pc, cas->chan, cas->so);
-}
-
-// cut in half to give stack a chance to split
-static void selectdefault(Select*, void*, int32);
-
-#pragma textflag NOSPLIT
-func selectdefault(sel *Select) (selected bool) {
- selected = false;
- selectdefault(sel, runtime·getcallerpc(&sel), (byte*)&selected - (byte*)&sel);
-}
-
-static void
-selectdefault(Select *sel, void *callerpc, int32 so)
-{
- int32 i;
- Scase *cas;
-
- i = sel->ncase;
- if(i >= sel->tcase)
- runtime·throw("selectdefault: too many cases");
- sel->ncase = i+1;
- cas = &sel->scase[i];
- cas->pc = callerpc;
- cas->chan = nil;
-
- cas->so = so;
- cas->kind = CaseDefault;
-
- if(debug)
- runtime·printf("selectdefault s=%p pc=%p so=%d\n",
- sel, cas->pc, cas->so);
-}
-
-static void
-sellock(Select *sel)
-{
- uint32 i;
- Hchan *c, *c0;
-
- c = nil;
- for(i=0; i<sel->ncase; i++) {
- c0 = sel->lockorder[i];
- if(c0 && c0 != c) {
- c = sel->lockorder[i];
- runtime·lock(c);
- }
- }
-}
-
-static void
-selunlock(Select *sel)
-{
- int32 i, n, r;
- Hchan *c;
-
- // We must be very careful here to not touch sel after we have unlocked
- // the last lock, because sel can be freed right after the last unlock.
- // Consider the following situation.
- // First M calls runtime·park() in runtime·selectgo() passing the sel.
- // Once runtime·park() has unlocked the last lock, another M makes
- // the G that calls select runnable again and schedules it for execution.
- // When the G runs on another M, it locks all the locks and frees sel.
- // Now if the first M touches sel, it will access freed memory.
- n = (int32)sel->ncase;
- r = 0;
- // skip the default case
- if(n>0 && sel->lockorder[0] == nil)
- r = 1;
- for(i = n-1; i >= r; i--) {
- c = sel->lockorder[i];
- if(i>0 && sel->lockorder[i-1] == c)
- continue; // will unlock it on the next iteration
- runtime·unlock(c);
- }
-}
-
-static bool
-selparkcommit(G *gp, void *sel)
-{
- USED(gp);
- selunlock(sel);
- return true;
-}
-
-func block() {
- runtime·park(nil, nil, "select (no cases)"); // forever
-}
-
-static void* selectgo(Select**);
-
-// selectgo(sel *byte);
-//
-// overwrites return pc on stack to signal which case of the select
-// to run, so cannot appear at the top of a split stack.
-#pragma textflag NOSPLIT
-func selectgo(sel *Select) {
- runtime·setcallerpc(&sel, selectgo(&sel));
-}
-
-static void*
-selectgo(Select **selp)
-{
- Select *sel;
- uint32 o, i, j, k, done;
- int64 t0;
- Scase *cas, *dfl;
- Hchan *c;
- SudoG *sg;
- G *gp;
- byte *as;
- void *pc;
-
- sel = *selp;
-
- if(debug)
- runtime·printf("select: sel=%p\n", sel);
-
- t0 = 0;
- if(runtime·blockprofilerate > 0) {
- t0 = runtime·cputicks();
- for(i=0; i<sel->ncase; i++)
- sel->scase[i].sg.releasetime = -1;
- }
-
- // The compiler rewrites selects that statically have
- // only 0 or 1 cases plus default into simpler constructs.
- // The only way we can end up with such small sel->ncase
- // values here is for a larger select in which most channels
- // have been nilled out. The general code handles those
- // cases correctly, and they are rare enough not to bother
- // optimizing (and needing to test).
-
- // generate permuted order
- for(i=0; i<sel->ncase; i++)
- sel->pollorder[i] = i;
- for(i=1; i<sel->ncase; i++) {
- o = sel->pollorder[i];
- j = runtime·fastrand1()%(i+1);
- sel->pollorder[i] = sel->pollorder[j];
- sel->pollorder[j] = o;
- }
-
- // sort the cases by Hchan address to get the locking order.
- // simple heap sort, to guarantee n log n time and constant stack footprint.
- for(i=0; i<sel->ncase; i++) {
- j = i;
- c = sel->scase[j].chan;
- while(j > 0 && sel->lockorder[k=(j-1)/2] < c) {
- sel->lockorder[j] = sel->lockorder[k];
- j = k;
- }
- sel->lockorder[j] = c;
- }
- for(i=sel->ncase; i-->0; ) {
- c = sel->lockorder[i];
- sel->lockorder[i] = sel->lockorder[0];
- j = 0;
- for(;;) {
- k = j*2+1;
- if(k >= i)
- break;
- if(k+1 < i && sel->lockorder[k] < sel->lockorder[k+1])
- k++;
- if(c < sel->lockorder[k]) {
- sel->lockorder[j] = sel->lockorder[k];
- j = k;
- continue;
- }
- break;
- }
- sel->lockorder[j] = c;
- }
- /*
- for(i=0; i+1<sel->ncase; i++)
- if(sel->lockorder[i] > sel->lockorder[i+1]) {
- runtime·printf("i=%d %p %p\n", i, sel->lockorder[i], sel->lockorder[i+1]);
- runtime·throw("select: broken sort");
- }
- */
- sellock(sel);
-
-loop:
- // pass 1 - look for something already waiting
- dfl = nil;
- for(i=0; i<sel->ncase; i++) {
- o = sel->pollorder[i];
- cas = &sel->scase[o];
- c = cas->chan;
-
- switch(cas->kind) {
- case CaseRecv:
- if(c->dataqsiz > 0) {
- if(c->qcount > 0)
- goto asyncrecv;
- } else {
- sg = dequeue(&c->sendq);
- if(sg != nil)
- goto syncrecv;
- }
- if(c->closed)
- goto rclose;
- break;
-
- case CaseSend:
- if(raceenabled)
- runtime·racereadpc(c, cas->pc, chansend);
- if(c->closed)
- goto sclose;
- if(c->dataqsiz > 0) {
- if(c->qcount < c->dataqsiz)
- goto asyncsend;
- } else {
- sg = dequeue(&c->recvq);
- if(sg != nil)
- goto syncsend;
- }
- break;
-
- case CaseDefault:
- dfl = cas;
- break;
- }
- }
-
- if(dfl != nil) {
- selunlock(sel);
- cas = dfl;
- goto retc;
- }
-
-
- // pass 2 - enqueue on all chans
- done = 0;
- for(i=0; i<sel->ncase; i++) {
- o = sel->pollorder[i];
- cas = &sel->scase[o];
- c = cas->chan;
- sg = &cas->sg;
- sg->g = g;
- sg->selectdone = &done;
-
- switch(cas->kind) {
- case CaseRecv:
- enqueue(&c->recvq, sg);
- break;
-
- case CaseSend:
- enqueue(&c->sendq, sg);
- break;
- }
- }
-
- g->param = nil;
- runtime·park(selparkcommit, sel, "select");
-
- sellock(sel);
- sg = g->param;
-
- // pass 3 - dequeue from unsuccessful chans
- // otherwise they stack up on quiet channels
- for(i=0; i<sel->ncase; i++) {
- cas = &sel->scase[i];
- if(cas != (Scase*)sg) {
- c = cas->chan;
- if(cas->kind == CaseSend)
- dequeueg(&c->sendq);
- else
- dequeueg(&c->recvq);
- }
- }
-
- if(sg == nil)
- goto loop;
-
- cas = (Scase*)sg;
- c = cas->chan;
-
- if(c->dataqsiz > 0)
- runtime·throw("selectgo: shouldn't happen");
-
- if(debug)
- runtime·printf("wait-return: sel=%p c=%p cas=%p kind=%d\n",
- sel, c, cas, cas->kind);
-
- if(cas->kind == CaseRecv) {
- if(cas->receivedp != nil)
- *cas->receivedp = true;
- }
-
- if(raceenabled) {
- if(cas->kind == CaseRecv && cas->sg.elem != nil)
- runtime·racewriteobjectpc(cas->sg.elem, c->elemtype, cas->pc, chanrecv);
- else if(cas->kind == CaseSend)
- runtime·racereadobjectpc(cas->sg.elem, c->elemtype, cas->pc, chansend);
- }
-
- selunlock(sel);
- goto retc;
-
-asyncrecv:
- // can receive from buffer
- if(raceenabled) {
- if(cas->sg.elem != nil)
- runtime·racewriteobjectpc(cas->sg.elem, c->elemtype, cas->pc, chanrecv);
- runtime·raceacquire(chanbuf(c, c->recvx));
- runtime·racerelease(chanbuf(c, c->recvx));
- }
- if(cas->receivedp != nil)
- *cas->receivedp = true;
- if(cas->sg.elem != nil)
- c->elemtype->alg->copy(c->elemsize, cas->sg.elem, chanbuf(c, c->recvx));
- c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->recvx), nil);
- if(++c->recvx == c->dataqsiz)
- c->recvx = 0;
- c->qcount--;
- sg = dequeue(&c->sendq);
- if(sg != nil) {
- gp = sg->g;
- selunlock(sel);
- if(sg->releasetime)
- sg->releasetime = runtime·cputicks();
- runtime·ready(gp);
- } else {
- selunlock(sel);
- }
- goto retc;
-
-asyncsend:
- // can send to buffer
- if(raceenabled) {
- runtime·raceacquire(chanbuf(c, c->sendx));
- runtime·racerelease(chanbuf(c, c->sendx));
- runtime·racereadobjectpc(cas->sg.elem, c->elemtype, cas->pc, chansend);
- }
- c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->sendx), cas->sg.elem);
- if(++c->sendx == c->dataqsiz)
- c->sendx = 0;
- c->qcount++;
- sg = dequeue(&c->recvq);
- if(sg != nil) {
- gp = sg->g;
- selunlock(sel);
- if(sg->releasetime)
- sg->releasetime = runtime·cputicks();
- runtime·ready(gp);
- } else {
- selunlock(sel);
- }
- goto retc;
-
-syncrecv:
- // can receive from sleeping sender (sg)
- if(raceenabled) {
- if(cas->sg.elem != nil)
- runtime·racewriteobjectpc(cas->sg.elem, c->elemtype, cas->pc, chanrecv);
- racesync(c, sg);
- }
- selunlock(sel);
- if(debug)
- runtime·printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
- if(cas->receivedp != nil)
- *cas->receivedp = true;
- if(cas->sg.elem != nil)
- c->elemtype->alg->copy(c->elemsize, cas->sg.elem, sg->elem);
- gp = sg->g;
- gp->param = sg;
- if(sg->releasetime)
- sg->releasetime = runtime·cputicks();
- runtime·ready(gp);
- goto retc;
-
-rclose:
- // read at end of closed channel
- selunlock(sel);
- if(cas->receivedp != nil)
- *cas->receivedp = false;
- if(cas->sg.elem != nil)
- c->elemtype->alg->copy(c->elemsize, cas->sg.elem, nil);
- if(raceenabled)
- runtime·raceacquire(c);
- goto retc;
-
-syncsend:
- // can send to sleeping receiver (sg)
- if(raceenabled) {
- runtime·racereadobjectpc(cas->sg.elem, c->elemtype, cas->pc, chansend);
- racesync(c, sg);
- }
- selunlock(sel);
- if(debug)
- runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
- if(sg->elem != nil)
- c->elemtype->alg->copy(c->elemsize, sg->elem, cas->sg.elem);
- gp = sg->g;
- gp->param = sg;
- if(sg->releasetime)
- sg->releasetime = runtime·cputicks();
- runtime·ready(gp);
-
-retc:
- // return pc corresponding to chosen case.
- // Set boolean passed during select creation
- // (at offset selp + cas->so) to true.
- // If cas->so == 0, this is a reflect-driven select and we
- // don't need to update the boolean.
- pc = cas->pc;
- if(cas->so > 0) {
- as = (byte*)selp + cas->so;
- *as = true;
- }
- if(cas->sg.releasetime > 0)
- runtime·blockevent(cas->sg.releasetime - t0, 2);
- runtime·free(sel);
- return pc;
-
-sclose:
- // send on closed channel
- selunlock(sel);
- runtime·panicstring("send on closed channel");
- return nil; // not reached
-}
-
-// This struct must match ../reflect/value.go:/runtimeSelect.
-typedef struct runtimeSelect runtimeSelect;
-struct runtimeSelect
-{
- uintptr dir;
- ChanType *typ;
- Hchan *ch;
- byte *val;
-};
-
-// This enum must match ../reflect/value.go:/SelectDir.
-enum SelectDir {
- SelectSend = 1,
- SelectRecv,
- SelectDefault,
-};
-
-func reflect·rselect(cases Slice) (chosen int, recvOK bool) {
- int32 i;
- Select *sel;
- runtimeSelect* rcase, *rc;
-
- chosen = -1;
- recvOK = false;
-
- rcase = (runtimeSelect*)cases.array;
-
- sel = newselect(cases.len);
- for(i=0; i<cases.len; i++) {
- rc = &rcase[i];
- switch(rc->dir) {
- case SelectDefault:
- selectdefault(sel, (void*)i, 0);
- break;
- case SelectSend:
- if(rc->ch == nil)
- break;
- selectsend(sel, rc->ch, (void*)i, rc->val, 0);
- break;
- case SelectRecv:
- if(rc->ch == nil)
- break;
- selectrecv(sel, rc->ch, (void*)i, rc->val, &recvOK, 0);
- break;
- }
- }
-
- chosen = (intgo)(uintptr)selectgo(&sel);
-}
-
-static void closechan(Hchan *c, void *pc);
-
-#pragma textflag NOSPLIT
-func closechan(c *Hchan) {
- closechan(c, runtime·getcallerpc(&c));
-}
-
-#pragma textflag NOSPLIT
-func reflect·chanclose(c *Hchan) {
- closechan(c, runtime·getcallerpc(&c));
-}
-
-static void
-closechan(Hchan *c, void *pc)
-{
- SudoG *sg;
- G* gp;
-
- if(c == nil)
- runtime·panicstring("close of nil channel");
-
- runtime·lock(c);
- if(c->closed) {
- runtime·unlock(c);
- runtime·panicstring("close of closed channel");
- }
-
- if(raceenabled) {
- runtime·racewritepc(c, pc, runtime·closechan);
- runtime·racerelease(c);
- }
-
- c->closed = true;
-
- // release all readers
- for(;;) {
- sg = dequeue(&c->recvq);
- if(sg == nil)
- break;
- gp = sg->g;
- gp->param = nil;
- if(sg->releasetime)
- sg->releasetime = runtime·cputicks();
- runtime·ready(gp);
- }
-
- // release all writers
- for(;;) {
- sg = dequeue(&c->sendq);
- if(sg == nil)
- break;
- gp = sg->g;
- gp->param = nil;
- if(sg->releasetime)
- sg->releasetime = runtime·cputicks();
- runtime·ready(gp);
- }
-
- runtime·unlock(c);
-}
-
-func reflect·chanlen(c *Hchan) (len int) {
- if(c == nil)
- len = 0;
- else
- len = c->qcount;
-}
-
-func reflect·chancap(c *Hchan) (cap int) {
- if(c == nil)
- cap = 0;
- else
- cap = c->dataqsiz;
-}
-
-static SudoG*
-dequeue(WaitQ *q)
-{
- SudoG *sgp;
-
-loop:
- sgp = q->first;
- if(sgp == nil)
- return nil;
- q->first = sgp->link;
-
- // 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 || !runtime·cas(sgp->selectdone, 0, 1))
- goto loop;
- }
-
- return sgp;
-}
-
-static void
-dequeueg(WaitQ *q)
-{
- SudoG **l, *sgp, *prevsgp;
-
- prevsgp = nil;
- for(l=&q->first; (sgp=*l) != nil; l=&sgp->link, prevsgp=sgp) {
- if(sgp->g == g) {
- *l = sgp->link;
- if(q->last == sgp)
- q->last = prevsgp;
- break;
- }
- }
-}
-
-static void
-enqueue(WaitQ *q, SudoG *sgp)
-{
- sgp->link = nil;
- if(q->first == nil) {
- q->first = sgp;
- q->last = sgp;
- return;
- }
- q->last->link = sgp;
- q->last = sgp;
-}
-
-static void
-racesync(Hchan *c, SudoG *sg)
-{
- runtime·racerelease(chanbuf(c, 0));
- runtime·raceacquireg(sg->g, chanbuf(c, 0));
- runtime·racereleaseg(sg->g, chanbuf(c, 0));
- runtime·raceacquire(chanbuf(c, 0));
-}
diff --git a/src/pkg/runtime/complex.goc b/src/pkg/runtime/complex.goc
deleted file mode 100644
index 40935cf1c..000000000
--- a/src/pkg/runtime/complex.goc
+++ /dev/null
@@ -1,58 +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.
-
-package runtime
-#include "runtime.h"
-
-func complex128div(n Complex128, d Complex128) (q Complex128) {
- int32 ninf, dinf, nnan, dnan;
- float64 a, b, ratio, denom;
-
- // Special cases as in C99.
- ninf = n.real == runtime·posinf || n.real == runtime·neginf ||
- n.imag == runtime·posinf || n.imag == runtime·neginf;
- dinf = d.real == runtime·posinf || d.real == runtime·neginf ||
- d.imag == runtime·posinf || d.imag == runtime·neginf;
-
- nnan = !ninf && (ISNAN(n.real) || ISNAN(n.imag));
- dnan = !dinf && (ISNAN(d.real) || ISNAN(d.imag));
-
- if(nnan || dnan) {
- q.real = runtime·nan;
- q.imag = runtime·nan;
- } else if(ninf && !dinf) {
- q.real = runtime·posinf;
- q.imag = runtime·posinf;
- } else if(!ninf && dinf) {
- q.real = 0;
- q.imag = 0;
- } else if(d.real == 0 && d.imag == 0) {
- if(n.real == 0 && n.imag == 0) {
- q.real = runtime·nan;
- q.imag = runtime·nan;
- } else {
- q.real = runtime·posinf;
- q.imag = runtime·posinf;
- }
- } else {
- // Standard complex arithmetic, factored to avoid unnecessary overflow.
- a = d.real;
- if(a < 0)
- a = -a;
- b = d.imag;
- if(b < 0)
- b = -b;
- if(a <= b) {
- ratio = d.real/d.imag;
- denom = d.real*ratio + d.imag;
- q.real = (n.real*ratio + n.imag) / denom;
- q.imag = (n.imag*ratio - n.real) / denom;
- } else {
- ratio = d.imag/d.real;
- denom = d.imag*ratio + d.real;
- q.real = (n.imag*ratio + n.real) / denom;
- q.imag = (n.imag - n.real*ratio) / denom;
- }
- }
-}
diff --git a/src/pkg/runtime/cpuprof.goc b/src/pkg/runtime/cpuprof.goc
deleted file mode 100644
index faaea2943..000000000
--- a/src/pkg/runtime/cpuprof.goc
+++ /dev/null
@@ -1,433 +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.
-
-// CPU profiling.
-// Based on algorithms and data structures used in
-// http://code.google.com/p/google-perftools/.
-//
-// The main difference between this code and the google-perftools
-// code is that this code is written to allow copying the profile data
-// to an arbitrary io.Writer, while the google-perftools code always
-// writes to an operating system file.
-//
-// The signal handler for the profiling clock tick adds a new stack trace
-// to a hash table tracking counts for recent traces. Most clock ticks
-// hit in the cache. In the event of a cache miss, an entry must be
-// evicted from the hash table, copied to a log that will eventually be
-// written as profile data. The google-perftools code flushed the
-// log itself during the signal handler. This code cannot do that, because
-// the io.Writer might block or need system calls or locks that are not
-// safe to use from within the signal handler. Instead, we split the log
-// into two halves and let the signal handler fill one half while a goroutine
-// is writing out the other half. When the signal handler fills its half, it
-// offers to swap with the goroutine. If the writer is not done with its half,
-// we lose the stack trace for this clock tick (and record that loss).
-// The goroutine interacts with the signal handler by calling getprofile() to
-// get the next log piece to write, implicitly handing back the last log
-// piece it obtained.
-//
-// The state of this dance between the signal handler and the goroutine
-// is encoded in the Profile.handoff field. If handoff == 0, then the goroutine
-// is not using either log half and is waiting (or will soon be waiting) for
-// a new piece by calling notesleep(&p->wait). If the signal handler
-// changes handoff from 0 to non-zero, it must call notewakeup(&p->wait)
-// to wake the goroutine. The value indicates the number of entries in the
-// log half being handed off. The goroutine leaves the non-zero value in
-// place until it has finished processing the log half and then flips the number
-// back to zero. Setting the high bit in handoff means that the profiling is over,
-// and the goroutine is now in charge of flushing the data left in the hash table
-// to the log and returning that data.
-//
-// The handoff field is manipulated using atomic operations.
-// For the most part, the manipulation of handoff is orderly: if handoff == 0
-// then the signal handler owns it and can change it to non-zero.
-// If handoff != 0 then the goroutine owns it and can change it to zero.
-// If that were the end of the story then we would not need to manipulate
-// handoff using atomic operations. The operations are needed, however,
-// in order to let the log closer set the high bit to indicate "EOF" safely
-// in the situation when normally the goroutine "owns" handoff.
-
-package runtime
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-
-enum
-{
- HashSize = 1<<10,
- LogSize = 1<<17,
- Assoc = 4,
- MaxStack = 64,
-};
-
-typedef struct Profile Profile;
-typedef struct Bucket Bucket;
-typedef struct Entry Entry;
-
-struct Entry {
- uintptr count;
- uintptr depth;
- uintptr stack[MaxStack];
-};
-
-struct Bucket {
- Entry entry[Assoc];
-};
-
-struct Profile {
- bool on; // profiling is on
- Note wait; // goroutine waits here
- uintptr count; // tick count
- uintptr evicts; // eviction count
- uintptr lost; // lost ticks that need to be logged
-
- // Active recent stack traces.
- Bucket hash[HashSize];
-
- // Log of traces evicted from hash.
- // Signal handler has filled log[toggle][:nlog].
- // Goroutine is writing log[1-toggle][:handoff].
- uintptr log[2][LogSize/2];
- uintptr nlog;
- int32 toggle;
- uint32 handoff;
-
- // Writer state.
- // Writer maintains its own toggle to avoid races
- // looking at signal handler's toggle.
- uint32 wtoggle;
- bool wholding; // holding & need to release a log half
- bool flushing; // flushing hash table - profile is over
- bool eod_sent; // special end-of-data record sent; => flushing
-};
-
-static Lock lk;
-static Profile *prof;
-
-static void tick(uintptr*, int32);
-static void add(Profile*, uintptr*, int32);
-static bool evict(Profile*, Entry*);
-static bool flushlog(Profile*);
-
-static uintptr eod[3] = {0, 1, 0};
-
-// LostProfileData is a no-op function used in profiles
-// to mark the number of profiling stack traces that were
-// discarded due to slow data writers.
-static void
-LostProfileData(void)
-{
-}
-
-// SetCPUProfileRate sets the CPU profiling rate.
-// The user documentation is in debug.go.
-void
-runtime·SetCPUProfileRate(intgo hz)
-{
- uintptr *p;
- uintptr n;
-
- // Clamp hz to something reasonable.
- if(hz < 0)
- hz = 0;
- if(hz > 1000000)
- hz = 1000000;
-
- runtime·lock(&lk);
- if(hz > 0) {
- if(prof == nil) {
- prof = runtime·SysAlloc(sizeof *prof, &mstats.other_sys);
- if(prof == nil) {
- runtime·printf("runtime: cpu profiling cannot allocate memory\n");
- runtime·unlock(&lk);
- return;
- }
- }
- if(prof->on || prof->handoff != 0) {
- runtime·printf("runtime: cannot set cpu profile rate until previous profile has finished.\n");
- runtime·unlock(&lk);
- return;
- }
-
- prof->on = true;
- p = prof->log[0];
- // pprof binary header format.
- // http://code.google.com/p/google-perftools/source/browse/trunk/src/profiledata.cc#117
- *p++ = 0; // count for header
- *p++ = 3; // depth for header
- *p++ = 0; // version number
- *p++ = 1000000 / hz; // period (microseconds)
- *p++ = 0;
- prof->nlog = p - prof->log[0];
- prof->toggle = 0;
- prof->wholding = false;
- prof->wtoggle = 0;
- prof->flushing = false;
- prof->eod_sent = false;
- runtime·noteclear(&prof->wait);
-
- runtime·setcpuprofilerate(tick, hz);
- } else if(prof != nil && prof->on) {
- runtime·setcpuprofilerate(nil, 0);
- prof->on = false;
-
- // Now add is not running anymore, and getprofile owns the entire log.
- // Set the high bit in prof->handoff to tell getprofile.
- for(;;) {
- n = prof->handoff;
- if(n&0x80000000)
- runtime·printf("runtime: setcpuprofile(off) twice");
- if(runtime·cas(&prof->handoff, n, n|0x80000000))
- break;
- }
- if(n == 0) {
- // we did the transition from 0 -> nonzero so we wake getprofile
- runtime·notewakeup(&prof->wait);
- }
- }
- runtime·unlock(&lk);
-}
-
-static void
-tick(uintptr *pc, int32 n)
-{
- add(prof, pc, n);
-}
-
-// add adds the stack trace to the profile.
-// It is called from signal handlers and other limited environments
-// and cannot allocate memory or acquire locks that might be
-// held at the time of the signal, nor can it use substantial amounts
-// of stack. It is allowed to call evict.
-static void
-add(Profile *p, uintptr *pc, int32 n)
-{
- int32 i, j;
- uintptr h, x;
- Bucket *b;
- Entry *e;
-
- if(n > MaxStack)
- n = MaxStack;
-
- // Compute hash.
- h = 0;
- for(i=0; i<n; i++) {
- h = h<<8 | (h>>(8*(sizeof(h)-1)));
- x = pc[i];
- h += x*31 + x*7 + x*3;
- }
- p->count++;
-
- // Add to entry count if already present in table.
- b = &p->hash[h%HashSize];
- for(i=0; i<Assoc; i++) {
- e = &b->entry[i];
- if(e->depth != n)
- continue;
- for(j=0; j<n; j++)
- if(e->stack[j] != pc[j])
- goto ContinueAssoc;
- e->count++;
- return;
- ContinueAssoc:;
- }
-
- // Evict entry with smallest count.
- e = &b->entry[0];
- for(i=1; i<Assoc; i++)
- if(b->entry[i].count < e->count)
- e = &b->entry[i];
- if(e->count > 0) {
- if(!evict(p, e)) {
- // Could not evict entry. Record lost stack.
- p->lost++;
- return;
- }
- p->evicts++;
- }
-
- // Reuse the newly evicted entry.
- e->depth = n;
- e->count = 1;
- for(i=0; i<n; i++)
- e->stack[i] = pc[i];
-}
-
-// evict copies the given entry's data into the log, so that
-// the entry can be reused. evict is called from add, which
-// is called from the profiling signal handler, so it must not
-// allocate memory or block. It is safe to call flushLog.
-// evict returns true if the entry was copied to the log,
-// false if there was no room available.
-static bool
-evict(Profile *p, Entry *e)
-{
- int32 i, d, nslot;
- uintptr *log, *q;
-
- d = e->depth;
- nslot = d+2;
- log = p->log[p->toggle];
- if(p->nlog+nslot > nelem(p->log[0])) {
- if(!flushlog(p))
- return false;
- log = p->log[p->toggle];
- }
-
- q = log+p->nlog;
- *q++ = e->count;
- *q++ = d;
- for(i=0; i<d; i++)
- *q++ = e->stack[i];
- p->nlog = q - log;
- e->count = 0;
- return true;
-}
-
-// flushlog tries to flush the current log and switch to the other one.
-// flushlog is called from evict, called from add, called from the signal handler,
-// 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.
-static bool
-flushlog(Profile *p)
-{
- uintptr *log, *q;
-
- if(!runtime·cas(&p->handoff, 0, p->nlog))
- return false;
- runtime·notewakeup(&p->wait);
-
- p->toggle = 1 - p->toggle;
- log = p->log[p->toggle];
- q = log;
- if(p->lost > 0) {
- *q++ = p->lost;
- *q++ = 1;
- *q++ = (uintptr)LostProfileData;
- p->lost = 0;
- }
- p->nlog = q - log;
- return true;
-}
-
-// getprofile blocks until the next block of profiling data is available
-// and returns it as a []byte. It is called from the writing goroutine.
-Slice
-getprofile(Profile *p)
-{
- uint32 i, j, n;
- Slice ret;
- Bucket *b;
- Entry *e;
-
- ret.array = nil;
- ret.len = 0;
- ret.cap = 0;
-
- if(p == nil)
- return ret;
-
- if(p->wholding) {
- // Release previous log to signal handling side.
- // Loop because we are racing against SetCPUProfileRate(0).
- for(;;) {
- n = p->handoff;
- if(n == 0) {
- runtime·printf("runtime: phase error during cpu profile handoff\n");
- return ret;
- }
- if(n & 0x80000000) {
- p->wtoggle = 1 - p->wtoggle;
- p->wholding = false;
- p->flushing = true;
- goto flush;
- }
- if(runtime·cas(&p->handoff, n, 0))
- break;
- }
- p->wtoggle = 1 - p->wtoggle;
- p->wholding = false;
- }
-
- if(p->flushing)
- goto flush;
-
- if(!p->on && p->handoff == 0)
- return ret;
-
- // Wait for new log.
- runtime·notetsleepg(&p->wait, -1);
- runtime·noteclear(&p->wait);
-
- n = p->handoff;
- if(n == 0) {
- runtime·printf("runtime: phase error during cpu profile wait\n");
- return ret;
- }
- if(n == 0x80000000) {
- p->flushing = true;
- goto flush;
- }
- n &= ~0x80000000;
-
- // Return new log to caller.
- p->wholding = true;
-
- ret.array = (byte*)p->log[p->wtoggle];
- ret.len = n*sizeof(uintptr);
- ret.cap = ret.len;
- return ret;
-
-flush:
- // In flush mode.
- // Add is no longer being called. We own the log.
- // Also, p->handoff is non-zero, so flushlog will return false.
- // Evict the hash table into the log and return it.
- for(i=0; i<HashSize; i++) {
- b = &p->hash[i];
- for(j=0; j<Assoc; j++) {
- e = &b->entry[j];
- if(e->count > 0 && !evict(p, e)) {
- // Filled the log. Stop the loop and return what we've got.
- goto breakflush;
- }
- }
- }
-breakflush:
-
- // Return pending log data.
- if(p->nlog > 0) {
- // Note that we're using toggle now, not wtoggle,
- // because we're working on the log directly.
- ret.array = (byte*)p->log[p->toggle];
- ret.len = p->nlog*sizeof(uintptr);
- ret.cap = ret.len;
- p->nlog = 0;
- return ret;
- }
-
- // Made it through the table without finding anything to log.
- if(!p->eod_sent) {
- // We may not have space to append this to the partial log buf,
- // so we always return a new slice for the end-of-data marker.
- p->eod_sent = true;
- ret.array = (byte*)eod;
- ret.len = sizeof eod;
- ret.cap = ret.len;
- return ret;
- }
-
- // Finally done. Clean up and return nil.
- p->flushing = false;
- if(!runtime·cas(&p->handoff, p->handoff, 0))
- runtime·printf("runtime: profile flush racing with something\n");
- return ret; // set to nil at top of function
-}
-
-// CPUProfile returns the next cpu profile block as a []byte.
-// The user documentation is in debug.go.
-func CPUProfile() (ret Slice) {
- ret = getprofile(prof);
-}
diff --git a/src/pkg/runtime/debug.go b/src/pkg/runtime/debug.go
deleted file mode 100644
index d82afb08e..000000000
--- a/src/pkg/runtime/debug.go
+++ /dev/null
@@ -1,172 +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
-
-// Breakpoint executes a breakpoint trap.
-func Breakpoint()
-
-// 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()
-
-// 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()
-
-// GOMAXPROCS sets the maximum number of CPUs that can be executing
-// simultaneously and returns the previous setting. If n < 1, it does not
-// change the current setting.
-// The number of logical CPUs on the local machine can be queried with NumCPU.
-// This call will go away when the scheduler improves.
-func GOMAXPROCS(n int) int
-
-// NumCPU returns the number of logical CPUs on the local machine.
-func NumCPU() int
-
-// NumCgoCall returns the number of cgo calls made by the current process.
-func NumCgoCall() int64
-
-// NumGoroutine returns the number of goroutines that currently exist.
-func NumGoroutine() int
-
-// MemProfileRate controls the fraction of memory allocations
-// that are recorded and reported in the memory profile.
-// The profiler aims to sample an average of
-// one allocation per MemProfileRate bytes allocated.
-//
-// To include every allocated block in the profile, set MemProfileRate to 1.
-// To turn off profiling entirely, set MemProfileRate to 0.
-//
-// The tools that process the memory profiles assume that the
-// profile rate is constant across the lifetime of the program
-// and equal to the current value. Programs that change the
-// memory profiling rate should do so just once, as early as
-// possible in the execution of the program (for example,
-// at the beginning of main).
-var MemProfileRate int = 512 * 1024
-
-// A MemProfileRecord describes the live objects allocated
-// by a particular call sequence (stack trace).
-type MemProfileRecord struct {
- AllocBytes, FreeBytes int64 // number of bytes allocated, freed
- AllocObjects, FreeObjects int64 // number of objects allocated, freed
- Stack0 [32]uintptr // stack trace for this record; ends at first 0 entry
-}
-
-// InUseBytes returns the number of bytes in use (AllocBytes - FreeBytes).
-func (r *MemProfileRecord) InUseBytes() int64 { return r.AllocBytes - r.FreeBytes }
-
-// InUseObjects returns the number of objects in use (AllocObjects - FreeObjects).
-func (r *MemProfileRecord) InUseObjects() int64 {
- return r.AllocObjects - r.FreeObjects
-}
-
-// Stack returns the stack trace associated with the record,
-// a prefix of r.Stack0.
-func (r *MemProfileRecord) Stack() []uintptr {
- for i, v := range r.Stack0 {
- if v == 0 {
- return r.Stack0[0:i]
- }
- }
- return r.Stack0[0:]
-}
-
-// 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.
-//
-// If inuseZero is true, the profile includes allocation records
-// where r.AllocBytes > 0 but r.AllocBytes == r.FreeBytes.
-// These are sites where memory was allocated, but it has all
-// been released back to the runtime.
-//
-// Most clients should use the runtime/pprof package or
-// the testing package's -test.memprofile flag instead
-// of calling MemProfile directly.
-func MemProfile(p []MemProfileRecord, inuseZero bool) (n int, ok bool)
-
-// A StackRecord describes a single execution stack.
-type StackRecord struct {
- Stack0 [32]uintptr // stack trace for this record; ends at first 0 entry
-}
-
-// Stack returns the stack trace associated with the record,
-// a prefix of r.Stack0.
-func (r *StackRecord) Stack() []uintptr {
- for i, v := range r.Stack0 {
- if v == 0 {
- return r.Stack0[0:i]
- }
- }
- return r.Stack0[0:]
-}
-
-// ThreadCreateProfile returns n, the number of records in the thread creation profile.
-// If len(p) >= n, ThreadCreateProfile copies the profile into p and returns n, true.
-// If len(p) < n, ThreadCreateProfile does not change p and returns n, false.
-//
-// Most clients should use the runtime/pprof package instead
-// of calling ThreadCreateProfile directly.
-func ThreadCreateProfile(p []StackRecord) (n int, ok bool)
-
-// GoroutineProfile returns n, the number of records in the active goroutine stack profile.
-// If len(p) >= n, GoroutineProfile copies the profile into p and returns n, true.
-// If len(p) < n, GoroutineProfile does not change p and returns n, false.
-//
-// Most clients should use the runtime/pprof package instead
-// of calling GoroutineProfile directly.
-func GoroutineProfile(p []StackRecord) (n int, ok bool)
-
-// CPUProfile returns the next chunk of binary CPU profiling stack trace data,
-// blocking until data is available. If profiling is turned off and all the profile
-// data accumulated while it was on has been returned, CPUProfile returns nil.
-// The caller must save the returned data before calling CPUProfile again.
-//
-// Most clients should use the runtime/pprof package or
-// the testing package's -test.cpuprofile flag instead of calling
-// CPUProfile directly.
-func CPUProfile() []byte
-
-// SetCPUProfileRate sets the CPU profiling rate to hz samples per second.
-// If hz <= 0, SetCPUProfileRate turns off profiling.
-// If the profiler is on, the rate cannot be changed without first turning it off.
-//
-// Most clients should use the runtime/pprof package or
-// the testing package's -test.cpuprofile flag instead of calling
-// SetCPUProfileRate directly.
-func SetCPUProfileRate(hz int)
-
-// SetBlockProfileRate controls the fraction of goroutine blocking events
-// that are reported in the blocking profile. The profiler aims to sample
-// an average of one blocking event per rate nanoseconds spent blocked.
-//
-// To include every blocking event in the profile, pass rate = 1.
-// To turn off profiling entirely, pass rate <= 0.
-func SetBlockProfileRate(rate int)
-
-// BlockProfileRecord describes blocking events originated
-// at a particular call sequence (stack trace).
-type BlockProfileRecord struct {
- Count int64
- Cycles int64
- StackRecord
-}
-
-// BlockProfile returns n, the number of records in the current blocking profile.
-// If len(p) >= n, BlockProfile copies the profile into p and returns n, true.
-// If len(p) < n, BlockProfile does not change p and returns n, false.
-//
-// Most clients should use the runtime/pprof package or
-// the testing package's -test.blockprofile flag instead
-// of calling BlockProfile directly.
-func BlockProfile(p []BlockProfileRecord) (n int, ok bool)
-
-// Stack formats a stack trace of the calling goroutine into buf
-// and returns the number of bytes written to buf.
-// If all is true, Stack formats stack traces of all other goroutines
-// into buf after the trace for the current goroutine.
-func Stack(buf []byte, all bool) int
diff --git a/src/pkg/runtime/env_plan9.c b/src/pkg/runtime/env_plan9.c
deleted file mode 100644
index f732c9f29..000000000
--- a/src/pkg/runtime/env_plan9.c
+++ /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.
-
-#include "runtime.h"
-#include "os_GOOS.h"
-
-byte*
-runtime·getenv(int8 *s)
-{
- int32 fd, n, r;
- intgo len;
- byte file[128];
- byte *p;
- static byte b[128];
-
- len = runtime·findnull((byte*)s);
- if(len > sizeof file-6)
- return nil;
-
- runtime·memclr(file, sizeof file);
- runtime·memmove((void*)file, (void*)"/env/", 5);
- runtime·memmove((void*)(file+5), (void*)s, len);
-
- fd = runtime·open((int8*)file, OREAD, 0);
- if(fd < 0)
- return nil;
- n = runtime·seek(fd, 0, 2);
- if(runtime·strcmp((byte*)s, (byte*)"GOTRACEBACK") == 0){
- // should not call malloc
- if(n >= sizeof b)
- return nil;
- runtime·memclr(b, sizeof b);
- p = b;
- }else
- p = runtime·malloc(n+1);
- r = runtime·pread(fd, p, n, 0);
- runtime·close(fd);
- if(r < 0)
- return nil;
- return p;
-}
diff --git a/src/pkg/runtime/env_posix.c b/src/pkg/runtime/env_posix.c
deleted file mode 100644
index 4c8288f6b..000000000
--- a/src/pkg/runtime/env_posix.c
+++ /dev/null
@@ -1,73 +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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-
-Slice syscall·envs;
-
-byte*
-runtime·getenv(int8 *s)
-{
- int32 i, j;
- intgo len;
- byte *v, *bs;
- String* envv;
- int32 envc;
-
- bs = (byte*)s;
- len = runtime·findnull(bs);
- envv = (String*)syscall·envs.array;
- envc = syscall·envs.len;
- for(i=0; i<envc; i++){
- if(envv[i].len <= len)
- continue;
- v = envv[i].str;
- for(j=0; j<len; j++)
- if(bs[j] != v[j])
- goto nomatch;
- if(v[len] != '=')
- goto nomatch;
- return v+len+1;
- nomatch:;
- }
- return nil;
-}
-
-void (*_cgo_setenv)(byte**);
-
-// Update the C environment if cgo is loaded.
-// Called from syscall.Setenv.
-void
-syscall·setenv_c(String k, String v)
-{
- byte *arg[2];
- uintptr len;
-
- if(_cgo_setenv == nil)
- return;
-
- // Objects that are explicitly freed must be at least 16 bytes in size,
- // so that they are not allocated using tiny alloc.
- len = k.len + 1;
- if(len < TinySize)
- len = TinySize;
- arg[0] = runtime·malloc(len);
- runtime·memmove(arg[0], k.str, k.len);
- arg[0][k.len] = 0;
-
- len = v.len + 1;
- if(len < TinySize)
- len = TinySize;
- arg[1] = runtime·malloc(len);
- runtime·memmove(arg[1], v.str, v.len);
- arg[1][v.len] = 0;
-
- runtime·asmcgocall((void*)_cgo_setenv, arg);
- runtime·free(arg[0]);
- runtime·free(arg[1]);
-}
diff --git a/src/pkg/runtime/export_test.go b/src/pkg/runtime/export_test.go
deleted file mode 100644
index 7a31b63b3..000000000
--- a/src/pkg/runtime/export_test.go
+++ /dev/null
@@ -1,92 +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.
-
-// Export guts for testing.
-
-package runtime
-
-var Fadd64 = fadd64
-var Fsub64 = fsub64
-var Fmul64 = fmul64
-var Fdiv64 = fdiv64
-var F64to32 = f64to32
-var F32to64 = f32to64
-var Fcmp64 = fcmp64
-var Fintto64 = fintto64
-var F64toint = f64toint
-
-func entersyscall()
-func exitsyscall()
-func golockedOSThread() bool
-func stackguard() (sp, limit uintptr)
-
-var Entersyscall = entersyscall
-var Exitsyscall = exitsyscall
-var LockedOSThread = golockedOSThread
-var Stackguard = stackguard
-
-type LFNode struct {
- Next *LFNode
- Pushcnt uintptr
-}
-
-func lfstackpush_go(head *uint64, node *LFNode)
-func lfstackpop_go(head *uint64) *LFNode
-
-var LFStackPush = lfstackpush_go
-var LFStackPop = lfstackpop_go
-
-type ParFor struct {
- body *byte
- done uint32
- Nthr uint32
- nthrmax uint32
- thrseq uint32
- Cnt uint32
- Ctx *byte
- wait bool
-}
-
-func newParFor(nthrmax uint32) *ParFor
-func parForSetup(desc *ParFor, nthr, n uint32, ctx *byte, wait bool, body func(*ParFor, uint32))
-func parForDo(desc *ParFor)
-func parForIters(desc *ParFor, tid uintptr) (uintptr, uintptr)
-
-var NewParFor = newParFor
-var ParForSetup = parForSetup
-var ParForDo = parForDo
-
-func ParForIters(desc *ParFor, tid uint32) (uint32, uint32) {
- begin, end := parForIters(desc, uintptr(tid))
- return uint32(begin), uint32(end)
-}
-
-func testSchedLocalQueue()
-func testSchedLocalQueueSteal()
-
-var TestSchedLocalQueue1 = testSchedLocalQueue
-var TestSchedLocalQueueSteal1 = testSchedLocalQueueSteal
-
-func haveGoodHash() bool
-func stringHash(s string, seed uintptr) uintptr
-func bytesHash(b []byte, seed uintptr) uintptr
-func int32Hash(i uint32, seed uintptr) uintptr
-func int64Hash(i uint64, seed uintptr) uintptr
-
-var HaveGoodHash = haveGoodHash
-var StringHash = stringHash
-var BytesHash = bytesHash
-var Int32Hash = int32Hash
-var Int64Hash = int64Hash
-
-var hashLoad float64 // declared in hashmap.c
-var HashLoad = &hashLoad
-
-func memclrBytes(b []byte)
-
-var MemclrBytes = memclrBytes
-
-func gogoBytes() int32
-
-var GogoBytes = gogoBytes
diff --git a/src/pkg/runtime/funcdata.h b/src/pkg/runtime/funcdata.h
deleted file mode 100644
index e20b6ae25..000000000
--- a/src/pkg/runtime/funcdata.h
+++ /dev/null
@@ -1,24 +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.
-
-// This file defines the IDs for PCDATA and FUNCDATA instructions
-// in Go binaries. It is included by both C and assembly, so it must
-// be written using #defines. It is included by the runtime package
-// as well as the compilers.
-
-#define PCDATA_ArgSize 0 /* argument size at CALL instruction */
-#define PCDATA_StackMapIndex 1
-
-#define FUNCDATA_ArgsPointerMaps 2 /* garbage collector blocks */
-#define FUNCDATA_LocalsPointerMaps 3
-#define FUNCDATA_DeadValueMaps 4
-
-// To be used in assembly.
-#define ARGSIZE(n) PCDATA $PCDATA_ArgSize, $n
-
-// ArgsSizeUnknown is set in Func.argsize to mark all functions
-// whose argument size is unknown (C vararg functions, and
-// assembly code without an explicit specification).
-// This value is generated by the compiler, assembler, or linker.
-#define ArgsSizeUnknown 0x80000000
diff --git a/src/pkg/runtime/hashmap.goc b/src/pkg/runtime/hashmap.goc
deleted file mode 100644
index 3327bed65..000000000
--- a/src/pkg/runtime/hashmap.goc
+++ /dev/null
@@ -1,1078 +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
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "type.h"
-#include "race.h"
-#include "hashmap.h"
-#include "typekind.h"
-#include "../../cmd/ld/textflag.h"
-
-enum
-{
- docheck = 0, // check invariants before and after every op. Slow!!!
- debug = 0, // print every operation
- checkgc = 0 || docheck, // check interaction of mallocgc() with the garbage collector
-};
-static void
-check(MapType *t, Hmap *h)
-{
- uintptr bucket, oldbucket;
- Bucket *b;
- uintptr i;
- uintptr hash;
- uintgo cnt;
- uint8 top;
- bool eq;
- byte *k, *v;
-
- cnt = 0;
-
- // check buckets
- for(bucket = 0; bucket < (uintptr)1 << h->B; bucket++) {
- for(b = (Bucket*)(h->buckets + bucket * h->bucketsize); b != nil; b = b->overflow) {
- for(i = 0, k = (byte*)b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
- if(b->tophash[i] == Empty)
- continue;
- if(b->tophash[i] > Empty && b->tophash[i] < MinTopHash)
- runtime·throw("evacuated cell in buckets");
- cnt++;
- t->key->alg->equal(&eq, t->key->size, IK(h, k), IK(h, k));
- if(!eq)
- continue; // NaN!
- hash = h->hash0;
- t->key->alg->hash(&hash, t->key->size, IK(h, k));
- top = hash >> (8*sizeof(uintptr) - 8);
- if(top < MinTopHash)
- top += MinTopHash;
- if(top != b->tophash[i])
- runtime·throw("bad hash");
- }
- }
- }
-
- // check oldbuckets
- if(h->oldbuckets != nil) {
- for(oldbucket = 0; oldbucket < (uintptr)1 << (h->B - 1); oldbucket++) {
- b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
- for(; b != nil; b = b->overflow) {
- for(i = 0, k = (byte*)b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
- if(b->tophash[i] < MinTopHash)
- continue;
- if(oldbucket < h->nevacuate)
- runtime·throw("unevacuated entry in an evacuated bucket");
- cnt++;
- t->key->alg->equal(&eq, t->key->size, IK(h, k), IK(h, k));
- if(!eq)
- continue; // NaN!
- hash = h->hash0;
- t->key->alg->hash(&hash, t->key->size, IK(h, k));
- top = hash >> (8*sizeof(uintptr) - 8);
- if(top < MinTopHash)
- top += MinTopHash;
- if(top != b->tophash[i])
- runtime·throw("bad hash (old)");
- }
- }
- }
- }
-
- if(cnt != h->count) {
- runtime·printf("%D %D\n", (uint64)cnt, (uint64)h->count);
- runtime·throw("entries missing");
- }
-}
-
-static void
-hash_init(MapType *t, Hmap *h, uint32 hint)
-{
- uint8 B;
- byte *buckets;
- uintptr keysize, valuesize, bucketsize;
- uint8 flags;
-
- flags = 0;
-
- // figure out how big we have to make everything
- keysize = t->key->size;
- if(keysize > MAXKEYSIZE) {
- flags |= IndirectKey;
- keysize = sizeof(byte*);
- }
- valuesize = t->elem->size;
- if(valuesize > MAXVALUESIZE) {
- flags |= IndirectValue;
- valuesize = sizeof(byte*);
- }
- bucketsize = offsetof(Bucket, data[0]) + (keysize + valuesize) * BUCKETSIZE;
- if(bucketsize != t->bucket->size) {
- runtime·printf("runtime: bucketsize=%p but t->bucket->size=%p; t=%S\n", bucketsize, t->bucket->size, *t->string);
- runtime·throw("bucketsize wrong");
- }
-
- // invariants we depend on. We should probably check these at compile time
- // somewhere, but for now we'll do it here.
- if(t->key->align > BUCKETSIZE)
- runtime·throw("key align too big");
- if(t->elem->align > BUCKETSIZE)
- runtime·throw("value align too big");
- if(t->key->size % t->key->align != 0)
- runtime·throw("key size not a multiple of key align");
- if(t->elem->size % t->elem->align != 0)
- runtime·throw("value size not a multiple of value align");
- if(BUCKETSIZE < 8)
- runtime·throw("bucketsize too small for proper alignment");
- if((offsetof(Bucket, data[0]) & (t->key->align-1)) != 0)
- runtime·throw("need padding in bucket (key)");
- if((offsetof(Bucket, data[0]) & (t->elem->align-1)) != 0)
- runtime·throw("need padding in bucket (value)");
-
- // find size parameter which will hold the requested # of elements
- B = 0;
- while(hint > BUCKETSIZE && hint > LOAD * ((uintptr)1 << B))
- B++;
-
- // allocate initial hash table
- // If hint is large zeroing this memory could take a while.
- if(checkgc) mstats.next_gc = mstats.heap_alloc;
- if(B == 0) {
- // done lazily later.
- buckets = nil;
- } else {
- buckets = runtime·cnewarray(t->bucket, (uintptr)1 << B);
- }
-
- // initialize Hmap
- h->count = 0;
- h->B = B;
- h->flags = flags;
- h->keysize = keysize;
- h->valuesize = valuesize;
- h->bucketsize = bucketsize;
- h->hash0 = runtime·fastrand1();
- h->buckets = buckets;
- h->oldbuckets = nil;
- h->nevacuate = 0;
- if(docheck)
- check(t, h);
-}
-
-// Moves entries in oldbuckets[i] to buckets[i] and buckets[i+2^k].
-// We leave the original bucket intact, except for marking the topbits
-// entries as evacuated, so that iterators can still iterate through the old buckets.
-static void
-evacuate(MapType *t, Hmap *h, uintptr oldbucket)
-{
- Bucket *b;
- Bucket *x, *y;
- Bucket *newx, *newy;
- uintptr xi, yi;
- uintptr newbit;
- uintptr hash;
- uintptr i;
- byte *k, *v;
- byte *xk, *yk, *xv, *yv;
- uint8 top;
- bool eq;
-
- b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
- newbit = (uintptr)1 << (h->B - 1);
-
- if(!evacuated(b)) {
- // TODO: reuse overflow buckets instead of using new ones, if there
- // is no iterator using the old buckets. (If !OldIterator.)
-
- x = (Bucket*)(h->buckets + oldbucket * h->bucketsize);
- y = (Bucket*)(h->buckets + (oldbucket + newbit) * h->bucketsize);
- xi = 0;
- yi = 0;
- xk = (byte*)x->data;
- yk = (byte*)y->data;
- xv = xk + h->keysize * BUCKETSIZE;
- yv = yk + h->keysize * BUCKETSIZE;
- for(; b != nil; b = b->overflow) {
- for(i = 0, k = (byte*)b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
- top = b->tophash[i];
- if(top == Empty) {
- b->tophash[i] = EvacuatedEmpty;
- continue;
- }
- if(top < MinTopHash)
- runtime·throw("bad state");
-
- // Compute hash to make our evacuation decision (whether we need
- // to send this key/value to bucket x or bucket y).
- hash = h->hash0;
- t->key->alg->hash(&hash, t->key->size, IK(h, k));
- if((h->flags & Iterator) != 0) {
- t->key->alg->equal(&eq, t->key->size, IK(h, k), IK(h, k));
- if(!eq) {
- // If key != key (NaNs), then the hash could be (and probably
- // will be) entirely different from the old hash. Moreover,
- // it isn't reproducible. Reproducibility is required in the
- // presence of iterators, as our evacuation decision must
- // match whatever decision the iterator made.
- // Fortunately, we have the freedom to send these keys either
- // way. Also, tophash is meaningless for these kinds of keys.
- // We let the low bit of tophash drive the evacuation decision.
- // We recompute a new random tophash for the next level so
- // these keys will get evenly distributed across all buckets
- // after multiple grows.
- if((top & 1) != 0)
- hash |= newbit;
- else
- hash &= ~newbit;
- top = hash >> (8*sizeof(uintptr)-8);
- if(top < MinTopHash)
- top += MinTopHash;
- }
- }
-
- if((hash & newbit) == 0) {
- b->tophash[i] = EvacuatedX;
- if(xi == BUCKETSIZE) {
- if(checkgc) mstats.next_gc = mstats.heap_alloc;
- newx = runtime·cnew(t->bucket);
- x->overflow = newx;
- x = newx;
- xi = 0;
- xk = (byte*)x->data;
- xv = xk + h->keysize * BUCKETSIZE;
- }
- x->tophash[xi] = top;
- if((h->flags & IndirectKey) != 0) {
- *(byte**)xk = *(byte**)k; // copy pointer
- } else {
- t->key->alg->copy(t->key->size, xk, k); // copy value
- }
- if((h->flags & IndirectValue) != 0) {
- *(byte**)xv = *(byte**)v;
- } else {
- t->elem->alg->copy(t->elem->size, xv, v);
- }
- xi++;
- xk += h->keysize;
- xv += h->valuesize;
- } else {
- b->tophash[i] = EvacuatedY;
- if(yi == BUCKETSIZE) {
- if(checkgc) mstats.next_gc = mstats.heap_alloc;
- newy = runtime·cnew(t->bucket);
- y->overflow = newy;
- y = newy;
- yi = 0;
- yk = (byte*)y->data;
- yv = yk + h->keysize * BUCKETSIZE;
- }
- y->tophash[yi] = top;
- if((h->flags & IndirectKey) != 0) {
- *(byte**)yk = *(byte**)k;
- } else {
- t->key->alg->copy(t->key->size, yk, k);
- }
- if((h->flags & IndirectValue) != 0) {
- *(byte**)yv = *(byte**)v;
- } else {
- t->elem->alg->copy(t->elem->size, yv, v);
- }
- yi++;
- yk += h->keysize;
- yv += h->valuesize;
- }
- }
- }
-
- // Unlink the overflow buckets & clear key/value to help GC.
- if((h->flags & OldIterator) == 0) {
- b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
- b->overflow = nil;
- runtime·memclr((byte*)b->data, h->bucketsize - offsetof(Bucket, data[0]));
- }
- }
-
- // Advance evacuation mark
- if(oldbucket == h->nevacuate) {
- h->nevacuate = oldbucket + 1;
- if(oldbucket + 1 == newbit) // newbit == # of oldbuckets
- // Growing is all done. Free old main bucket array.
- h->oldbuckets = nil;
- }
- if(docheck)
- check(t, h);
-}
-
-static void
-grow_work(MapType *t, Hmap *h, uintptr bucket)
-{
- uintptr noldbuckets;
-
- noldbuckets = (uintptr)1 << (h->B - 1);
-
- // make sure we evacuate the oldbucket corresponding
- // to the bucket we're about to use
- evacuate(t, h, bucket & (noldbuckets - 1));
-
- // evacuate one more oldbucket to make progress on growing
- if(h->oldbuckets != nil)
- evacuate(t, h, h->nevacuate);
-}
-
-static void
-hash_grow(MapType *t, Hmap *h)
-{
- byte *old_buckets;
- byte *new_buckets;
- uint8 flags;
-
- // allocate a bigger hash table
- if(h->oldbuckets != nil)
- runtime·throw("evacuation not done in time");
- old_buckets = h->buckets;
- if(checkgc) mstats.next_gc = mstats.heap_alloc;
- new_buckets = runtime·cnewarray(t->bucket, (uintptr)1 << (h->B + 1));
- flags = (h->flags & ~(Iterator | OldIterator));
- if((h->flags & Iterator) != 0)
- flags |= OldIterator;
-
- // commit the grow (atomic wrt gc)
- h->B++;
- h->flags = flags;
- h->oldbuckets = old_buckets;
- h->buckets = new_buckets;
- h->nevacuate = 0;
-
- // the actual copying of the hash table data is done incrementally
- // by grow_work() and evacuate().
- if(docheck)
- check(t, h);
-}
-
-// returns ptr to value associated with key *keyp, or nil if none.
-// if it returns non-nil, updates *keyp to point to the currently stored key.
-static byte*
-hash_lookup(MapType *t, Hmap *h, byte **keyp)
-{
- void *key;
- uintptr hash;
- uintptr bucket, oldbucket;
- Bucket *b;
- uint8 top;
- uintptr i;
- bool eq;
- byte *k, *k2, *v;
-
- key = *keyp;
- if(docheck)
- check(t, h);
- if(h->count == 0)
- return nil;
- hash = h->hash0;
- t->key->alg->hash(&hash, t->key->size, key);
- bucket = hash & (((uintptr)1 << h->B) - 1);
- if(h->oldbuckets != nil) {
- oldbucket = bucket & (((uintptr)1 << (h->B - 1)) - 1);
- b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
- if(evacuated(b)) {
- b = (Bucket*)(h->buckets + bucket * h->bucketsize);
- }
- } else {
- b = (Bucket*)(h->buckets + bucket * h->bucketsize);
- }
- top = hash >> (sizeof(uintptr)*8 - 8);
- if(top < MinTopHash)
- top += MinTopHash;
- do {
- for(i = 0, k = (byte*)b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
- if(b->tophash[i] == top) {
- k2 = IK(h, k);
- t->key->alg->equal(&eq, t->key->size, key, k2);
- if(eq) {
- *keyp = k2;
- return IV(h, v);
- }
- }
- }
- b = b->overflow;
- } while(b != nil);
- return nil;
-}
-
-// Specialized versions of mapaccess1 for specific types.
-// See ./hashmap_fast.c and ../../cmd/gc/walk.c.
-#define HASH_LOOKUP1 runtime·mapaccess1_fast32
-#define HASH_LOOKUP2 runtime·mapaccess2_fast32
-#define KEYTYPE uint32
-#define HASHFUNC runtime·algarray[AMEM32].hash
-#define FASTKEY(x) true
-#define QUICK_NE(x,y) ((x) != (y))
-#define QUICK_EQ(x,y) true
-#define SLOW_EQ(x,y) true
-#define MAYBE_EQ(x,y) true
-#include "hashmap_fast.c"
-
-#undef HASH_LOOKUP1
-#undef HASH_LOOKUP2
-#undef KEYTYPE
-#undef HASHFUNC
-#undef FASTKEY
-#undef QUICK_NE
-#undef QUICK_EQ
-#undef SLOW_EQ
-#undef MAYBE_EQ
-
-#define HASH_LOOKUP1 runtime·mapaccess1_fast64
-#define HASH_LOOKUP2 runtime·mapaccess2_fast64
-#define KEYTYPE uint64
-#define HASHFUNC runtime·algarray[AMEM64].hash
-#define FASTKEY(x) true
-#define QUICK_NE(x,y) ((x) != (y))
-#define QUICK_EQ(x,y) true
-#define SLOW_EQ(x,y) true
-#define MAYBE_EQ(x,y) true
-#include "hashmap_fast.c"
-
-#undef HASH_LOOKUP1
-#undef HASH_LOOKUP2
-#undef KEYTYPE
-#undef HASHFUNC
-#undef FASTKEY
-#undef QUICK_NE
-#undef QUICK_EQ
-#undef SLOW_EQ
-#undef MAYBE_EQ
-
-#ifdef GOARCH_amd64
-#define CHECKTYPE uint64
-#endif
-#ifdef GOARCH_amd64p32
-#define CHECKTYPE uint32
-#endif
-#ifdef GOARCH_386
-#define CHECKTYPE uint32
-#endif
-#ifdef GOARCH_arm
-// can't use uint32 on arm because our loads aren't aligned.
-// TODO: use uint32 for arm v6+?
-#define CHECKTYPE uint8
-#endif
-
-#define HASH_LOOKUP1 runtime·mapaccess1_faststr
-#define HASH_LOOKUP2 runtime·mapaccess2_faststr
-#define KEYTYPE String
-#define HASHFUNC runtime·algarray[ASTRING].hash
-#define FASTKEY(x) ((x).len < 32)
-#define QUICK_NE(x,y) ((x).len != (y).len)
-#define QUICK_EQ(x,y) ((x).str == (y).str)
-#define SLOW_EQ(x,y) runtime·memeq((x).str, (y).str, (x).len)
-#define MAYBE_EQ(x,y) (*(CHECKTYPE*)(x).str == *(CHECKTYPE*)(y).str && *(CHECKTYPE*)((x).str + (x).len - sizeof(CHECKTYPE)) == *(CHECKTYPE*)((y).str + (x).len - sizeof(CHECKTYPE)))
-#include "hashmap_fast.c"
-
-static void
-hash_insert(MapType *t, Hmap *h, void *key, void *value)
-{
- uintptr hash;
- uintptr bucket;
- uintptr i;
- bool eq;
- Bucket *b;
- Bucket *newb;
- uint8 *inserti;
- byte *insertk, *insertv;
- uint8 top;
- byte *k, *v;
- byte *kmem, *vmem;
-
- if(docheck)
- check(t, h);
- hash = h->hash0;
- t->key->alg->hash(&hash, t->key->size, key);
- if(h->buckets == nil)
- h->buckets = runtime·cnewarray(t->bucket, 1);
-
- again:
- bucket = hash & (((uintptr)1 << h->B) - 1);
- if(h->oldbuckets != nil)
- grow_work(t, h, bucket);
- b = (Bucket*)(h->buckets + bucket * h->bucketsize);
- top = hash >> (sizeof(uintptr)*8 - 8);
- if(top < MinTopHash)
- top += MinTopHash;
- inserti = nil;
- insertk = nil;
- insertv = nil;
- while(true) {
- for(i = 0, k = (byte*)b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
- if(b->tophash[i] != top) {
- if(b->tophash[i] == Empty && inserti == nil) {
- inserti = &b->tophash[i];
- insertk = k;
- insertv = v;
- }
- continue;
- }
- t->key->alg->equal(&eq, t->key->size, key, IK(h, k));
- if(!eq)
- continue;
- // already have a mapping for key. Update it.
- t->key->alg->copy(t->key->size, IK(h, k), key); // Need to update key for keys which are distinct but equal (e.g. +0.0 and -0.0)
- t->elem->alg->copy(t->elem->size, IV(h, v), value);
- if(docheck)
- check(t, h);
- return;
- }
- if(b->overflow == nil)
- break;
- b = b->overflow;
- }
-
- // did not find mapping for key. Allocate new cell & add entry.
- if(h->count >= LOAD * ((uintptr)1 << h->B) && h->count >= BUCKETSIZE) {
- hash_grow(t, h);
- goto again; // Growing the table invalidates everything, so try again
- }
-
- if(inserti == nil) {
- // all current buckets are full, allocate a new one.
- if(checkgc) mstats.next_gc = mstats.heap_alloc;
- newb = runtime·cnew(t->bucket);
- b->overflow = newb;
- inserti = newb->tophash;
- insertk = (byte*)newb->data;
- insertv = insertk + h->keysize * BUCKETSIZE;
- }
-
- // store new key/value at insert position
- if((h->flags & IndirectKey) != 0) {
- if(checkgc) mstats.next_gc = mstats.heap_alloc;
- kmem = runtime·cnew(t->key);
- *(byte**)insertk = kmem;
- insertk = kmem;
- }
- if((h->flags & IndirectValue) != 0) {
- if(checkgc) mstats.next_gc = mstats.heap_alloc;
- vmem = runtime·cnew(t->elem);
- *(byte**)insertv = vmem;
- insertv = vmem;
- }
- t->key->alg->copy(t->key->size, insertk, key);
- t->elem->alg->copy(t->elem->size, insertv, value);
- *inserti = top;
- h->count++;
- if(docheck)
- check(t, h);
-}
-
-static void
-hash_remove(MapType *t, Hmap *h, void *key)
-{
- uintptr hash;
- uintptr bucket;
- Bucket *b;
- uint8 top;
- uintptr i;
- byte *k, *v;
- bool eq;
-
- if(docheck)
- check(t, h);
- if(h->count == 0)
- return;
- hash = h->hash0;
- t->key->alg->hash(&hash, t->key->size, key);
- bucket = hash & (((uintptr)1 << h->B) - 1);
- if(h->oldbuckets != nil)
- grow_work(t, h, bucket);
- b = (Bucket*)(h->buckets + bucket * h->bucketsize);
- top = hash >> (sizeof(uintptr)*8 - 8);
- if(top < MinTopHash)
- top += MinTopHash;
- do {
- for(i = 0, k = (byte*)b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
- if(b->tophash[i] != top)
- continue;
- t->key->alg->equal(&eq, t->key->size, key, IK(h, k));
- if(!eq)
- continue;
-
- if((h->flags & IndirectKey) != 0) {
- *(byte**)k = nil;
- } else {
- t->key->alg->copy(t->key->size, k, nil);
- }
- if((h->flags & IndirectValue) != 0) {
- *(byte**)v = nil;
- } else {
- t->elem->alg->copy(t->elem->size, v, nil);
- }
-
- b->tophash[i] = Empty;
- h->count--;
-
- // TODO: consolidate buckets if they are mostly empty
- // can only consolidate if there are no live iterators at this size.
- if(docheck)
- check(t, h);
- return;
- }
- b = b->overflow;
- } while(b != nil);
-}
-
-// TODO: shrink the map, the same way we grow it.
-
-// iterator state:
-// bucket: the current bucket ID
-// b: the current Bucket in the chain
-// i: the next offset to check in the current bucket
-static void
-hash_iter_init(MapType *t, Hmap *h, Hiter *it)
-{
- uint32 old;
-
- if(sizeof(Hiter) / sizeof(uintptr) != 10) {
- runtime·throw("hash_iter size incorrect"); // see ../../cmd/gc/reflect.c
- }
- it->t = t;
- it->h = h;
-
- // grab snapshot of bucket state
- it->B = h->B;
- it->buckets = h->buckets;
-
- // iterator state
- it->bucket = 0;
- it->offset = runtime·fastrand1() & (BUCKETSIZE - 1);
- it->done = false;
- it->bptr = nil;
-
- // Remember we have an iterator.
- // Can run concurrently with another hash_iter_init().
- for(;;) {
- old = h->flags;
- if((old&(Iterator|OldIterator)) == (Iterator|OldIterator))
- break;
- if(runtime·cas(&h->flags, old, old|Iterator|OldIterator))
- break;
- }
-
- if(h->buckets == nil) {
- // Empty map. Force next hash_next to exit without
- // evaluating h->bucket.
- it->done = true;
- }
-}
-
-// initializes it->key and it->value to the next key/value pair
-// in the iteration, or nil if we've reached the end.
-static void
-hash_next(Hiter *it)
-{
- Hmap *h;
- MapType *t;
- uintptr bucket, oldbucket;
- uintptr hash;
- Bucket *b;
- uintptr i, offi;
- intptr check_bucket;
- bool eq;
- byte *k, *v;
- byte *rk, *rv;
-
- h = it->h;
- t = it->t;
- bucket = it->bucket;
- b = it->bptr;
- i = it->i;
- check_bucket = it->check_bucket;
-
-next:
- if(b == nil) {
- if(it->done) {
- // end of iteration
- it->key = nil;
- it->value = nil;
- return;
- }
- if(h->oldbuckets != nil && it->B == h->B) {
- // Iterator was started in the middle of a grow, and the grow isn't done yet.
- // If the bucket we're looking at hasn't been filled in yet (i.e. the old
- // bucket hasn't been evacuated) then we need to iterate through the old
- // bucket and only return the ones that will be migrated to this bucket.
- oldbucket = bucket & (((uintptr)1 << (it->B - 1)) - 1);
- b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
- if(!evacuated(b)) {
- check_bucket = bucket;
- } else {
- b = (Bucket*)(it->buckets + bucket * h->bucketsize);
- check_bucket = -1;
- }
- } else {
- b = (Bucket*)(it->buckets + bucket * h->bucketsize);
- check_bucket = -1;
- }
- bucket++;
- if(bucket == ((uintptr)1 << it->B)) {
- bucket = 0;
- it->done = true;
- }
- i = 0;
- }
- for(; i < BUCKETSIZE; i++) {
- offi = (i + it->offset) & (BUCKETSIZE - 1);
- k = (byte*)b->data + h->keysize * offi;
- v = (byte*)b->data + h->keysize * BUCKETSIZE + h->valuesize * offi;
- if(b->tophash[offi] != Empty && b->tophash[offi] != EvacuatedEmpty) {
- if(check_bucket >= 0) {
- // Special case: iterator was started during a grow and the
- // grow is not done yet. We're working on a bucket whose
- // oldbucket has not been evacuated yet. Or at least, it wasn't
- // evacuated when we started the bucket. So we're iterating
- // through the oldbucket, skipping any keys that will go
- // to the other new bucket (each oldbucket expands to two
- // buckets during a grow).
- t->key->alg->equal(&eq, t->key->size, IK(h, k), IK(h, k));
- if(eq) {
- // If the item in the oldbucket is not destined for
- // the current new bucket in the iteration, skip it.
- hash = h->hash0;
- t->key->alg->hash(&hash, t->key->size, IK(h, k));
- if((hash & (((uintptr)1 << it->B) - 1)) != check_bucket) {
- continue;
- }
- } else {
- // Hash isn't repeatable if k != k (NaNs). We need a
- // repeatable and randomish choice of which direction
- // to send NaNs during evacuation. We'll use the low
- // bit of tophash to decide which way NaNs go.
- // NOTE: this case is why we need two evacuate tophash
- // values, evacuatedX and evacuatedY, that differ in
- // their low bit.
- if(check_bucket >> (it->B - 1) != (b->tophash[offi] & 1)) {
- continue;
- }
- }
- }
- if(b->tophash[offi] != EvacuatedX && b->tophash[offi] != EvacuatedY) {
- // this is the golden data, we can return it.
- it->key = IK(h, k);
- it->value = IV(h, v);
- } else {
- // The hash table has grown since the iterator was started.
- // The golden data for this key is now somewhere else.
- t->key->alg->equal(&eq, t->key->size, IK(h, k), IK(h, k));
- if(eq) {
- // Check the current hash table for the data.
- // This code handles the case where the key
- // has been deleted, updated, or deleted and reinserted.
- // NOTE: we need to regrab the key as it has potentially been
- // updated to an equal() but not identical key (e.g. +0.0 vs -0.0).
- rk = IK(h, k);
- rv = hash_lookup(t, it->h, &rk);
- if(rv == nil)
- continue; // key has been deleted
- it->key = rk;
- it->value = rv;
- } else {
- // if key!=key then the entry can't be deleted or
- // updated, so we can just return it. That's lucky for
- // us because when key!=key we can't look it up
- // successfully in the current table.
- it->key = IK(h, k);
- it->value = IV(h, v);
- }
- }
- it->bucket = bucket;
- it->bptr = b;
- it->i = i + 1;
- it->check_bucket = check_bucket;
- return;
- }
- }
- b = b->overflow;
- i = 0;
- goto next;
-}
-
-//
-/// interfaces to go runtime
-//
-
-func reflect·ismapkey(typ *Type) (ret bool) {
- ret = typ != nil && typ->alg->hash != runtime·nohash;
-}
-
-static Hmap*
-makemap_c(MapType *typ, int64 hint)
-{
- Hmap *h;
- Type *key;
-
- key = typ->key;
-
- if(sizeof(Hmap) > 48)
- runtime·panicstring("hmap too large");
-
- if(hint < 0 || (int32)hint != hint)
- runtime·panicstring("makemap: size out of range");
-
- if(key->alg->hash == runtime·nohash)
- runtime·throw("runtime.makemap: unsupported map key type");
-
- h = runtime·cnew(typ->hmap);
- hash_init(typ, h, hint);
-
- // these calculations are compiler dependent.
- // figure out offsets of map call arguments.
-
- if(debug) {
- runtime·printf("makemap: map=%p; keysize=%p; valsize=%p; keyalg=%p; valalg=%p\n",
- h, key->size, typ->elem->size, key->alg, typ->elem->alg);
- }
-
- return h;
-}
-
-func makemap(typ *MapType, hint int64) (ret *Hmap) {
- ret = makemap_c(typ, hint);
-}
-
-func reflect·makemap(t *MapType) (ret *Hmap) {
- ret = makemap_c(t, 0);
-}
-
-// NOTE: The returned pointer may keep the whole map live, so don't
-// hold onto it for very long.
-#pragma textflag NOSPLIT
-func mapaccess1(t *MapType, h *Hmap, key *byte) (val *byte) {
- if(raceenabled && h != nil) {
- runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapaccess1);
- runtime·racereadobjectpc(key, t->key, runtime·getcallerpc(&t), runtime·mapaccess1);
- }
- if(h == nil || h->count == 0) {
- val = t->elem->zero;
- } else {
- val = hash_lookup(t, h, &key);
- if(val == nil)
- val = t->elem->zero;
- }
-
- if(debug) {
- runtime·prints("runtime.mapaccess1: map=");
- runtime·printpointer(h);
- runtime·prints("; key=");
- t->key->alg->print(t->key->size, key);
- runtime·prints("; val=");
- t->elem->alg->print(t->elem->size, val);
- runtime·prints("\n");
- }
-}
-
-// NOTE: The returned pointer keeps the whole map live, so don't
-// hold onto it for very long.
-#pragma textflag NOSPLIT
-func mapaccess2(t *MapType, h *Hmap, key *byte) (val *byte, pres bool) {
- if(raceenabled && h != nil) {
- runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapaccess2);
- runtime·racereadobjectpc(key, t->key, runtime·getcallerpc(&t), runtime·mapaccess2);
- }
-
- if(h == nil || h->count == 0) {
- val = t->elem->zero;
- pres = false;
- } else {
- val = hash_lookup(t, h, &key);
- if(val == nil) {
- val = t->elem->zero;
- pres = false;
- } else {
- pres = true;
- }
- }
-
- if(debug) {
- runtime·prints("runtime.mapaccess2: map=");
- runtime·printpointer(h);
- runtime·prints("; key=");
- t->key->alg->print(t->key->size, key);
- runtime·prints("; val=");
- t->elem->alg->print(t->elem->size, val);
- runtime·prints("; pres=");
- runtime·printbool(pres);
- runtime·prints("\n");
- }
-}
-
-#pragma textflag NOSPLIT
-func reflect·mapaccess(t *MapType, h *Hmap, key *byte) (val *byte) {
- if(h == nil)
- val = nil;
- else {
- if(raceenabled) {
- runtime·racereadpc(h, runtime·getcallerpc(&t), reflect·mapaccess);
- runtime·racereadobjectpc(key, t->key, runtime·getcallerpc(&t), reflect·mapaccess);
- }
- val = hash_lookup(t, h, &key);
- }
-}
-
-#pragma textflag NOSPLIT
-func mapassign1(t *MapType, h *Hmap, key *byte, val *byte) {
- if(h == nil)
- runtime·panicstring("assignment to entry in nil map");
-
- if(raceenabled) {
- runtime·racewritepc(h, runtime·getcallerpc(&t), runtime·mapassign1);
- runtime·racereadobjectpc(key, t->key, runtime·getcallerpc(&t), runtime·mapassign1);
- runtime·racereadobjectpc(val, t->elem, runtime·getcallerpc(&t), runtime·mapassign1);
- }
-
- hash_insert(t, h, key, val);
-
- if(debug) {
- runtime·prints("mapassign1: map=");
- runtime·printpointer(h);
- runtime·prints("; key=");
- t->key->alg->print(t->key->size, key);
- runtime·prints("; val=");
- t->elem->alg->print(t->elem->size, val);
- runtime·prints("\n");
- }
-}
-
-#pragma textflag NOSPLIT
-func mapdelete(t *MapType, h *Hmap, key *byte) {
- if(h == nil)
- return;
-
- if(raceenabled) {
- runtime·racewritepc(h, runtime·getcallerpc(&t), runtime·mapdelete);
- runtime·racereadobjectpc(key, t->key, runtime·getcallerpc(&t), runtime·mapdelete);
- }
-
- hash_remove(t, h, key);
-
- if(debug) {
- runtime·prints("mapdelete: map=");
- runtime·printpointer(h);
- runtime·prints("; key=");
- t->key->alg->print(t->key->size, key);
- runtime·prints("\n");
- }
-}
-
-#pragma textflag NOSPLIT
-func reflect·mapassign(t *MapType, h *Hmap, key *byte, val *byte) {
- if(h == nil)
- runtime·panicstring("assignment to entry in nil map");
- if(raceenabled) {
- runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign);
- runtime·racereadobjectpc(key, t->key, runtime·getcallerpc(&t), reflect·mapassign);
- runtime·racereadobjectpc(val, t->elem, runtime·getcallerpc(&t), reflect·mapassign);
- }
-
- hash_insert(t, h, key, val);
-
- if(debug) {
- runtime·prints("mapassign: map=");
- runtime·printpointer(h);
- runtime·prints("; key=");
- t->key->alg->print(t->key->size, key);
- runtime·prints("; val=");
- t->elem->alg->print(t->elem->size, val);
- runtime·prints("\n");
- }
-}
-
-#pragma textflag NOSPLIT
-func reflect·mapdelete(t *MapType, h *Hmap, key *byte) {
- if(h == nil)
- return; // see bug 8051
- if(raceenabled) {
- runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapdelete);
- runtime·racereadobjectpc(key, t->key, runtime·getcallerpc(&t), reflect·mapdelete);
- }
- hash_remove(t, h, key);
-
- if(debug) {
- runtime·prints("mapdelete: map=");
- runtime·printpointer(h);
- runtime·prints("; key=");
- t->key->alg->print(t->key->size, key);
- runtime·prints("\n");
- }
-}
-
-#pragma textflag NOSPLIT
-func mapiterinit(t *MapType, h *Hmap, it *Hiter) {
- // Clear pointer fields so garbage collector does not complain.
- it->key = nil;
- it->value = nil;
- it->t = nil;
- it->h = nil;
- it->buckets = nil;
- it->bptr = nil;
-
- if(h == nil || h->count == 0) {
- it->key = nil;
- return;
- }
- if(raceenabled)
- runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapiterinit);
- hash_iter_init(t, h, it);
- hash_next(it);
- if(debug) {
- runtime·prints("runtime.mapiterinit: map=");
- runtime·printpointer(h);
- runtime·prints("; iter=");
- runtime·printpointer(it);
- runtime·prints("; key=");
- runtime·printpointer(it->key);
- runtime·prints("\n");
- }
-}
-
-func reflect·mapiterinit(t *MapType, h *Hmap) (it *Hiter) {
- it = runtime·mal(sizeof *it);
- runtime·mapiterinit(t, h, it);
-}
-
-#pragma textflag NOSPLIT
-func mapiternext(it *Hiter) {
- if(raceenabled)
- runtime·racereadpc(it->h, runtime·getcallerpc(&it), runtime·mapiternext);
-
- hash_next(it);
- if(debug) {
- runtime·prints("runtime.mapiternext: iter=");
- runtime·printpointer(it);
- runtime·prints("; key=");
- runtime·printpointer(it->key);
- runtime·prints("\n");
- }
-}
-
-func reflect·mapiternext(it *Hiter) {
- runtime·mapiternext(it);
-}
-
-func reflect·mapiterkey(it *Hiter) (key *byte) {
- key = it->key;
-}
-
-#pragma textflag NOSPLIT
-func reflect·maplen(h *Hmap) (len int) {
- if(h == nil)
- len = 0;
- else {
- len = h->count;
- if(raceenabled)
- runtime·racereadpc(h, runtime·getcallerpc(&h), reflect·maplen);
- }
-}
-
-// exported value for testing
-float64 runtime·hashLoad = LOAD;
diff --git a/src/pkg/runtime/hashmap.h b/src/pkg/runtime/hashmap.h
deleted file mode 100644
index 522d1ad01..000000000
--- a/src/pkg/runtime/hashmap.h
+++ /dev/null
@@ -1,147 +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.
-
-// This file contains the implementation of Go's map type.
-//
-// The map is just a hash table. The data is arranged
-// into an array of buckets. Each bucket contains up to
-// 8 key/value pairs. The low-order bits of the hash are
-// used to select a bucket. Each bucket contains a few
-// high-order bits of each hash to distinguish the entries
-// within a single bucket.
-//
-// If more than 8 keys hash to a bucket, we chain on
-// extra buckets.
-//
-// When the hashtable grows, we allocate a new array
-// of buckets twice as big. Buckets are incrementally
-// copied from the old bucket array to the new bucket array.
-//
-// Map iterators walk through the array of buckets and
-// return the keys in walk order (bucket #, then overflow
-// chain order, then bucket index). To maintain iteration
-// semantics, we never move keys within their bucket (if
-// we did, keys might be returned 0 or 2 times). When
-// growing the table, iterators remain iterating through the
-// old table and must check the new table if the bucket
-// they are iterating through has been moved ("evacuated")
-// to the new table.
-
-// Maximum number of key/value pairs a bucket can hold.
-#define BUCKETSIZE 8
-
-// Maximum average load of a bucket that triggers growth.
-#define LOAD 6.5
-
-// Picking LOAD: too large and we have lots of overflow
-// buckets, too small and we waste a lot of space. I wrote
-// a simple program to check some stats for different loads:
-// (64-bit, 8 byte keys and values)
-// LOAD %overflow bytes/entry hitprobe missprobe
-// 4.00 2.13 20.77 3.00 4.00
-// 4.50 4.05 17.30 3.25 4.50
-// 5.00 6.85 14.77 3.50 5.00
-// 5.50 10.55 12.94 3.75 5.50
-// 6.00 15.27 11.67 4.00 6.00
-// 6.50 20.90 10.79 4.25 6.50
-// 7.00 27.14 10.15 4.50 7.00
-// 7.50 34.03 9.73 4.75 7.50
-// 8.00 41.10 9.40 5.00 8.00
-//
-// %overflow = percentage of buckets which have an overflow bucket
-// bytes/entry = overhead bytes used per key/value pair
-// hitprobe = # of entries to check when looking up a present key
-// missprobe = # of entries to check when looking up an absent key
-//
-// Keep in mind this data is for maximally loaded tables, i.e. just
-// before the table grows. Typical tables will be somewhat less loaded.
-
-// Maximum key or value size to keep inline (instead of mallocing per element).
-// Must fit in a uint8.
-// Fast versions cannot handle big values - the cutoff size for
-// fast versions in ../../cmd/gc/walk.c must be at most this value.
-#define MAXKEYSIZE 128
-#define MAXVALUESIZE 128
-
-typedef struct Bucket Bucket;
-struct Bucket
-{
- // Note: the format of the Bucket is encoded in ../../cmd/gc/reflect.c and
- // ../reflect/type.go. Don't change this structure without also changing that code!
- uint8 tophash[BUCKETSIZE]; // top 8 bits of hash of each entry (or special mark below)
- Bucket *overflow; // overflow bucket, if any
- uint64 data[1]; // BUCKETSIZE keys followed by BUCKETSIZE values
-};
-// NOTE: packing all the keys together and then all the values together makes the
-// code a bit more complicated than alternating key/value/key/value/... but it allows
-// us to eliminate padding which would be needed for, e.g., map[int64]int8.
-
-// tophash values. We reserve a few possibilities for special marks.
-// Each bucket (including its overflow buckets, if any) will have either all or none of its
-// entries in the Evacuated* states (except during the evacuate() method, which only happens
-// during map writes and thus no one else can observe the map during that time).
-enum
-{
- Empty = 0, // cell is empty
- EvacuatedEmpty = 1, // cell is empty, bucket is evacuated.
- EvacuatedX = 2, // key/value is valid. Entry has been evacuated to first half of larger table.
- EvacuatedY = 3, // same as above, but evacuated to second half of larger table.
- MinTopHash = 4, // minimum tophash for a normal filled cell.
-};
-#define evacuated(b) ((b)->tophash[0] > Empty && (b)->tophash[0] < MinTopHash)
-
-struct Hmap
-{
- // Note: the format of the Hmap is encoded in ../../cmd/gc/reflect.c and
- // ../reflect/type.go. Don't change this structure without also changing that code!
- uintgo count; // # live cells == size of map. Must be first (used by len() builtin)
- uint32 flags;
- uint32 hash0; // hash seed
- uint8 B; // log_2 of # of buckets (can hold up to LOAD * 2^B items)
- uint8 keysize; // key size in bytes
- uint8 valuesize; // value size in bytes
- uint16 bucketsize; // bucket size in bytes
-
- byte *buckets; // array of 2^B Buckets. may be nil if count==0.
- byte *oldbuckets; // previous bucket array of half the size, non-nil only when growing
- uintptr nevacuate; // progress counter for evacuation (buckets less than this have been evacuated)
-};
-
-// possible flags
-enum
-{
- IndirectKey = 1, // storing pointers to keys
- IndirectValue = 2, // storing pointers to values
- Iterator = 4, // there may be an iterator using buckets
- OldIterator = 8, // there may be an iterator using oldbuckets
-};
-
-// Macros for dereferencing indirect keys
-#define IK(h, p) (((h)->flags & IndirectKey) != 0 ? *(byte**)(p) : (p))
-#define IV(h, p) (((h)->flags & IndirectValue) != 0 ? *(byte**)(p) : (p))
-
-// If you modify Hiter, also change cmd/gc/reflect.c to indicate
-// the layout of this structure.
-struct Hiter
-{
- uint8* key; // Must be in first position. Write nil to indicate iteration end (see cmd/gc/range.c).
- uint8* value; // Must be in second position (see cmd/gc/range.c).
-
- MapType *t;
- Hmap *h;
- byte *buckets; // bucket ptr at hash_iter initialization time
- struct Bucket *bptr; // current bucket
-
- uint8 offset; // intra-bucket offset to start from during iteration (should be big enough to hold BUCKETSIZE-1)
- bool done;
-
- // state of table at time iterator is initialized
- uint8 B;
-
- // iter state
- uintptr bucket;
- uintptr i;
- intptr check_bucket;
-};
-
diff --git a/src/pkg/runtime/hashmap_fast.c b/src/pkg/runtime/hashmap_fast.c
deleted file mode 100644
index 83bf6feb5..000000000
--- a/src/pkg/runtime/hashmap_fast.c
+++ /dev/null
@@ -1,233 +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.
-
-// Fast hashmap lookup specialized to a specific key type.
-// Included by hashmap.c once for each specialized type.
-
-// +build ignore
-
-// Because this file is #included, it cannot be processed by goc2c,
-// so we have to handle the Go resuts ourselves.
-
-#pragma textflag NOSPLIT
-void
-HASH_LOOKUP1(MapType *t, Hmap *h, KEYTYPE key, GoOutput base, ...)
-{
- uintptr bucket, i;
- Bucket *b;
- KEYTYPE *k;
- byte *v, **valueptr;
- uint8 top;
- int8 keymaybe;
-
- valueptr = (byte**)&base;
- if(debug) {
- runtime·prints("runtime.mapaccess1_fastXXX: map=");
- runtime·printpointer(h);
- runtime·prints("; key=");
- t->key->alg->print(t->key->size, &key);
- runtime·prints("\n");
- }
- if(h == nil || h->count == 0) {
- *valueptr = t->elem->zero;
- return;
- }
- if(raceenabled)
- runtime·racereadpc(h, runtime·getcallerpc(&t), HASH_LOOKUP1);
- if(docheck)
- check(t, h);
-
- if(h->B == 0) {
- // One-bucket table. Don't hash, just check each bucket entry.
- b = (Bucket*)h->buckets;
- if(FASTKEY(key)) {
- for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
- if(b->tophash[i] == Empty)
- continue;
- if(QUICK_NE(key, *k))
- continue;
- if(QUICK_EQ(key, *k) || SLOW_EQ(key, *k)) {
- *valueptr = v;
- return;
- }
- }
- } else {
- keymaybe = -1;
- for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
- if(b->tophash[i] == Empty)
- continue;
- if(QUICK_NE(key, *k))
- continue;
- if(QUICK_EQ(key, *k)) {
- *valueptr = v;
- return;
- }
- if(MAYBE_EQ(key, *k)) {
- if(keymaybe >= 0) {
- // Two same-length strings in this bucket.
- // use slow path.
- // TODO: keep track of more than just 1. We could
- // afford about 3 equals calls before it would be more
- // expensive than 1 hash + 1 equals.
- goto dohash;
- }
- keymaybe = i;
- }
- }
- if(keymaybe >= 0) {
- k = (KEYTYPE*)b->data + keymaybe;
- if(SLOW_EQ(key, *k)) {
- *valueptr = (byte*)((KEYTYPE*)b->data + BUCKETSIZE) + keymaybe * h->valuesize;
- return;
- }
- }
- }
- } else {
-dohash:
- bucket = h->hash0;
- HASHFUNC(&bucket, sizeof(KEYTYPE), &key);
- top = bucket >> (sizeof(uintptr)*8 - 8);
- if(top < MinTopHash)
- top += MinTopHash;
- bucket &= (((uintptr)1 << h->B) - 1);
- if(h->oldbuckets != nil) {
- i = bucket & (((uintptr)1 << (h->B - 1)) - 1);
- b = (Bucket*)(h->oldbuckets + i * h->bucketsize);
- if(evacuated(b)) {
- b = (Bucket*)(h->buckets + bucket * h->bucketsize);
- }
- } else {
- b = (Bucket*)(h->buckets + bucket * h->bucketsize);
- }
- do {
- for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
- if(b->tophash[i] != top)
- continue;
- if(QUICK_NE(key, *k))
- continue;
- if(QUICK_EQ(key, *k) || SLOW_EQ(key, *k)) {
- *valueptr = v;
- return;
- }
- }
- b = b->overflow;
- } while(b != nil);
- }
- *valueptr = t->elem->zero;
-}
-
-#pragma textflag NOSPLIT
-void
-HASH_LOOKUP2(MapType *t, Hmap *h, KEYTYPE key, GoOutput base, ...)
-{
- uintptr bucket, i;
- Bucket *b;
- KEYTYPE *k;
- byte *v, **valueptr;
- uint8 top;
- int8 keymaybe;
- bool *okptr;
-
- valueptr = (byte**)&base;
- okptr = (bool*)(valueptr+1);
- if(debug) {
- runtime·prints("runtime.mapaccess2_fastXXX: map=");
- runtime·printpointer(h);
- runtime·prints("; key=");
- t->key->alg->print(t->key->size, &key);
- runtime·prints("\n");
- }
- if(h == nil || h->count == 0) {
- *valueptr = t->elem->zero;
- *okptr = false;
- return;
- }
- if(raceenabled)
- runtime·racereadpc(h, runtime·getcallerpc(&t), HASH_LOOKUP2);
- if(docheck)
- check(t, h);
-
- if(h->B == 0) {
- // One-bucket table. Don't hash, just check each bucket entry.
- b = (Bucket*)h->buckets;
- if(FASTKEY(key)) {
- for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
- if(b->tophash[i] == Empty)
- continue;
- if(QUICK_NE(key, *k))
- continue;
- if(QUICK_EQ(key, *k) || SLOW_EQ(key, *k)) {
- *valueptr = v;
- *okptr = true;
- return;
- }
- }
- } else {
- keymaybe = -1;
- for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
- if(b->tophash[i] == Empty)
- continue;
- if(QUICK_NE(key, *k))
- continue;
- if(QUICK_EQ(key, *k)) {
- *valueptr = v;
- *okptr = true;
- return;
- }
- if(MAYBE_EQ(key, *k)) {
- if(keymaybe >= 0) {
- // Two same-length strings in this bucket.
- // use slow path.
- // TODO: keep track of more than just 1. We could
- // afford about 3 equals calls before it would be more
- // expensive than 1 hash + 1 equals.
- goto dohash;
- }
- keymaybe = i;
- }
- }
- if(keymaybe >= 0) {
- k = (KEYTYPE*)b->data + keymaybe;
- if(SLOW_EQ(key, *k)) {
- *valueptr = (byte*)((KEYTYPE*)b->data + BUCKETSIZE) + keymaybe * h->valuesize;
- *okptr = true;
- return;
- }
- }
- }
- } else {
-dohash:
- bucket = h->hash0;
- HASHFUNC(&bucket, sizeof(KEYTYPE), &key);
- top = bucket >> (sizeof(uintptr)*8 - 8);
- if(top < MinTopHash)
- top += MinTopHash;
- bucket &= (((uintptr)1 << h->B) - 1);
- if(h->oldbuckets != nil) {
- i = bucket & (((uintptr)1 << (h->B - 1)) - 1);
- b = (Bucket*)(h->oldbuckets + i * h->bucketsize);
- if(evacuated(b)) {
- b = (Bucket*)(h->buckets + bucket * h->bucketsize);
- }
- } else {
- b = (Bucket*)(h->buckets + bucket * h->bucketsize);
- }
- do {
- for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
- if(b->tophash[i] != top)
- continue;
- if(QUICK_NE(key, *k))
- continue;
- if(QUICK_EQ(key, *k) || SLOW_EQ(key, *k)) {
- *valueptr = v;
- *okptr = true;
- return;
- }
- }
- b = b->overflow;
- } while(b != nil);
- }
- *valueptr = t->elem->zero;
- *okptr = false;
-}
diff --git a/src/pkg/runtime/iface.goc b/src/pkg/runtime/iface.goc
deleted file mode 100644
index c0a17e303..000000000
--- a/src/pkg/runtime/iface.goc
+++ /dev/null
@@ -1,620 +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
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "type.h"
-#include "typekind.h"
-#include "malloc.h"
-#include "../../cmd/ld/textflag.h"
-
-func printiface(i Iface) {
- runtime·printf("(%p,%p)", i.tab, i.data);
-}
-
-func printeface(e Eface) {
- runtime·printf("(%p,%p)", e.type, e.data);
-}
-
-static Itab* hash[1009];
-static Lock ifacelock;
-
-static Itab*
-itab(InterfaceType *inter, Type *type, int32 canfail)
-{
- int32 locked;
- int32 ni;
- Method *t, *et;
- IMethod *i, *ei;
- uint32 h;
- String *iname, *ipkgPath;
- Itab *m;
- UncommonType *x;
- Type *itype;
- Eface err;
-
- if(inter->mhdr.len == 0)
- runtime·throw("internal error - misuse of itab");
-
- locked = 0;
-
- // easy case
- x = type->x;
- if(x == nil) {
- if(canfail)
- return nil;
- iname = inter->m[0].name;
- goto throw;
- }
-
- // compiler has provided some good hash codes for us.
- h = inter->hash;
- h += 17 * type->hash;
- // TODO(rsc): h += 23 * x->mhash ?
- h %= nelem(hash);
-
- // look twice - once without lock, once with.
- // common case will be no lock contention.
- for(locked=0; locked<2; locked++) {
- if(locked)
- runtime·lock(&ifacelock);
- for(m=runtime·atomicloadp(&hash[h]); m!=nil; m=m->link) {
- if(m->inter == inter && m->type == type) {
- if(m->bad) {
- m = nil;
- if(!canfail) {
- // this can only happen if the conversion
- // was already done once using the , ok form
- // and we have a cached negative result.
- // the cached result doesn't record which
- // interface function was missing, so jump
- // down to the interface check, which will
- // do more work but give a better error.
- goto search;
- }
- }
- if(locked)
- runtime·unlock(&ifacelock);
- return m;
- }
- }
- }
-
- ni = inter->mhdr.len;
- m = runtime·persistentalloc(sizeof(*m) + ni*sizeof m->fun[0], 0, &mstats.other_sys);
- m->inter = inter;
- m->type = type;
-
-search:
- // both inter and type have method sorted by name,
- // and interface names are unique,
- // so can iterate over both in lock step;
- // the loop is O(ni+nt) not O(ni*nt).
- i = inter->m;
- ei = i + inter->mhdr.len;
- t = x->m;
- et = t + x->mhdr.len;
- for(; i < ei; i++) {
- itype = i->type;
- iname = i->name;
- ipkgPath = i->pkgPath;
- for(;; t++) {
- if(t >= et) {
- if(!canfail) {
- throw:
- // didn't find method
- runtime·newTypeAssertionError(
- nil, type->string, inter->string,
- iname, &err);
- if(locked)
- runtime·unlock(&ifacelock);
- runtime·panic(err);
- return nil; // not reached
- }
- m->bad = 1;
- goto out;
- }
- if(t->mtyp == itype && t->name == iname && t->pkgPath == ipkgPath)
- break;
- }
- if(m)
- m->fun[i - inter->m] = t->ifn;
- }
-
-out:
- if(!locked)
- runtime·panicstring("invalid itab locking");
- m->link = hash[h];
- runtime·atomicstorep(&hash[h], m);
- runtime·unlock(&ifacelock);
- if(m->bad)
- return nil;
- return m;
-}
-
-// call the callback for every itab that is currently allocated.
-void
-runtime·iterate_itabs(void (*callback)(Itab*))
-{
- int32 i;
- Itab *tab;
-
- for(i = 0; i < nelem(hash); i++) {
- for(tab = hash[i]; tab != nil; tab = tab->link) {
- callback(tab);
- }
- }
-}
-
-static void
-copyin(Type *t, void *src, void **dst)
-{
- uintptr size;
- void *p;
- Alg *alg;
-
- size = t->size;
- alg = t->alg;
-
- if(size <= sizeof(*dst))
- alg->copy(size, dst, src);
- else {
- p = runtime·cnew(t);
- alg->copy(size, p, src);
- *dst = p;
- }
-}
-
-static void
-copyout(Type *t, void **src, void *dst)
-{
- uintptr size;
- Alg *alg;
-
- size = t->size;
- alg = t->alg;
-
- if(size <= sizeof(*src))
- alg->copy(size, dst, src);
- else
- alg->copy(size, dst, *src);
-}
-
-#pragma textflag NOSPLIT
-func typ2Itab(t *Type, inter *InterfaceType, cache **Itab) (tab *Itab) {
- tab = itab(inter, t, 0);
- runtime·atomicstorep(cache, tab);
-}
-
-#pragma textflag NOSPLIT
-func convT2I(t *Type, inter *InterfaceType, cache **Itab, elem *byte) (ret Iface) {
- Itab *tab;
-
- tab = runtime·atomicloadp(cache);
- if(!tab) {
- tab = itab(inter, t, 0);
- runtime·atomicstorep(cache, tab);
- }
- ret.tab = tab;
- copyin(t, elem, &ret.data);
-}
-
-#pragma textflag NOSPLIT
-func convT2E(t *Type, elem *byte) (ret Eface) {
- ret.type = t;
- copyin(t, elem, &ret.data);
-}
-
-static void assertI2Tret(Type *t, Iface i, byte *ret);
-
-/*
- * NOTE: Cannot use 'func' here, because we have to declare
- * a return value, the only types we have are at least 1 byte large,
- * goc2c will zero the return value, and the actual return value
- * might have size 0 bytes, in which case the zeroing of the
- * 1 or more bytes would be wrong.
- * Using C lets us control (avoid) the initial zeroing.
- */
-#pragma textflag NOSPLIT
-void
-runtime·assertI2T(Type *t, Iface i, GoOutput retbase)
-{
- assertI2Tret(t, i, (byte*)&retbase);
-}
-
-static void
-assertI2Tret(Type *t, Iface i, byte *ret)
-{
- Itab *tab;
- Eface err;
-
- tab = i.tab;
- if(tab == nil) {
- runtime·newTypeAssertionError(
- nil, nil, t->string,
- nil, &err);
- runtime·panic(err);
- }
- if(tab->type != t) {
- runtime·newTypeAssertionError(
- tab->inter->string, tab->type->string, t->string,
- nil, &err);
- runtime·panic(err);
- }
- copyout(t, &i.data, ret);
-}
-
-#pragma textflag NOSPLIT
-func assertI2T2(t *Type, i Iface) (ret byte, ...) {
- bool *ok;
- int32 wid;
-
- wid = t->size;
- ok = (bool*)(&ret + wid);
-
- if(i.tab == nil || i.tab->type != t) {
- *ok = false;
- runtime·memclr(&ret, wid);
- return;
- }
-
- *ok = true;
- copyout(t, &i.data, &ret);
-}
-
-func assertI2TOK(t *Type, i Iface) (ok bool) {
- ok = i.tab!=nil && i.tab->type==t;
-}
-
-static void assertE2Tret(Type *t, Eface e, byte *ret);
-
-/*
- * NOTE: Cannot use 'func' here. See assertI2T above.
- */
-#pragma textflag NOSPLIT
-void
-runtime·assertE2T(Type *t, Eface e, GoOutput retbase)
-{
- assertE2Tret(t, e, (byte*)&retbase);
-}
-
-static void
-assertE2Tret(Type *t, Eface e, byte *ret)
-{
- Eface err;
-
- if(e.type == nil) {
- runtime·newTypeAssertionError(
- nil, nil, t->string,
- nil, &err);
- runtime·panic(err);
- }
- if(e.type != t) {
- runtime·newTypeAssertionError(
- nil, e.type->string, t->string,
- nil, &err);
- runtime·panic(err);
- }
- copyout(t, &e.data, ret);
-}
-
-#pragma textflag NOSPLIT
-func assertE2T2(t *Type, e Eface) (ret byte, ...) {
- bool *ok;
- int32 wid;
-
- wid = t->size;
- ok = (bool*)(&ret + wid);
-
- if(t != e.type) {
- *ok = false;
- runtime·memclr(&ret, wid);
- return;
- }
-
- *ok = true;
- copyout(t, &e.data, &ret);
-}
-
-func assertE2TOK(t *Type, e Eface) (ok bool) {
- ok = t==e.type;
-}
-
-func convI2E(i Iface) (ret Eface) {
- Itab *tab;
-
- ret.data = i.data;
- if((tab = i.tab) == nil)
- ret.type = nil;
- else
- ret.type = tab->type;
-}
-
-func assertI2E(inter *InterfaceType, i Iface) (ret Eface) {
- Itab *tab;
- Eface err;
-
- tab = i.tab;
- if(tab == nil) {
- // explicit conversions require non-nil interface value.
- runtime·newTypeAssertionError(
- nil, nil, inter->string,
- nil, &err);
- runtime·panic(err);
- }
- ret.data = i.data;
- ret.type = tab->type;
-}
-
-func assertI2E2(inter *InterfaceType, i Iface) (ret Eface, ok bool) {
- Itab *tab;
-
- USED(inter);
- tab = i.tab;
- if(tab == nil) {
- ret.type = nil;
- ok = 0;
- } else {
- ret.type = tab->type;
- ok = 1;
- }
- ret.data = i.data;
-}
-
-func convI2I(inter *InterfaceType, i Iface) (ret Iface) {
- Itab *tab;
-
- ret.data = i.data;
- if((tab = i.tab) == nil)
- ret.tab = nil;
- else if(tab->inter == inter)
- ret.tab = tab;
- else
- ret.tab = itab(inter, tab->type, 0);
-}
-
-void
-runtime·ifaceI2I(InterfaceType *inter, Iface i, Iface *ret)
-{
- Itab *tab;
- Eface err;
-
- tab = i.tab;
- if(tab == nil) {
- // explicit conversions require non-nil interface value.
- runtime·newTypeAssertionError(
- nil, nil, inter->string,
- nil, &err);
- runtime·panic(err);
- }
- ret->data = i.data;
- ret->tab = itab(inter, tab->type, 0);
-}
-
-func assertI2I(inter *InterfaceType, i Iface) (ret Iface) {
- runtime·ifaceI2I(inter, i, &ret);
-}
-
-func assertI2I2(inter *InterfaceType, i Iface) (ret Iface, ok bool) {
- Itab *tab;
-
- tab = i.tab;
- if(tab != nil && (tab->inter == inter || (tab = itab(inter, tab->type, 1)) != nil)) {
- ret.data = i.data;
- ret.tab = tab;
- ok = 1;
- } else {
- ret.data = 0;
- ret.tab = 0;
- ok = 0;
- }
-}
-
-void
-runtime·ifaceE2I(InterfaceType *inter, Eface e, Iface *ret)
-{
- Type *t;
- Eface err;
-
- t = e.type;
- if(t == nil) {
- // explicit conversions require non-nil interface value.
- runtime·newTypeAssertionError(
- nil, nil, inter->string,
- nil, &err);
- runtime·panic(err);
- }
- ret->data = e.data;
- ret->tab = itab(inter, t, 0);
-}
-
-bool
-runtime·ifaceE2I2(InterfaceType *inter, Eface e, Iface *ret)
-{
- ret->tab = itab(inter, e.type, 1);
- if(ret->tab == nil)
- return false;
- ret->data = e.data;
- return true;
-}
-
-func reflect·ifaceE2I(inter *InterfaceType, e Eface, dst *Iface) {
- runtime·ifaceE2I(inter, e, dst);
-}
-
-func assertE2I(inter *InterfaceType, e Eface) (ret Iface) {
- runtime·ifaceE2I(inter, e, &ret);
-}
-
-func assertE2I2(inter *InterfaceType, e Eface) (ret Iface, ok bool) {
- if(e.type == nil) {
- ok = 0;
- ret.data = nil;
- ret.tab = nil;
- } else if((ret.tab = itab(inter, e.type, 1)) == nil) {
- ok = 0;
- ret.data = nil;
- } else {
- ok = 1;
- ret.data = e.data;
- }
-}
-
-func assertE2E(inter *InterfaceType, e Eface) (ret Eface) {
- Type *t;
- Eface err;
-
- t = e.type;
- if(t == nil) {
- // explicit conversions require non-nil interface value.
- runtime·newTypeAssertionError(
- nil, nil, inter->string,
- nil, &err);
- runtime·panic(err);
- }
- ret = e;
-}
-
-func assertE2E2(inter *InterfaceType, e Eface) (ret Eface, ok bool) {
- USED(inter);
- ret = e;
- ok = e.type != nil;
-}
-
-static uintptr
-ifacehash1(void *data, Type *t, uintptr h)
-{
- Alg *alg;
- uintptr size;
- Eface err;
-
- if(t == nil)
- return 0;
-
- alg = t->alg;
- size = t->size;
- if(alg->hash == runtime·nohash) {
- // calling nohash will panic too,
- // but we can print a better error.
- runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"hash of unhashable type "), *t->string), &err);
- runtime·panic(err);
- }
- if(size <= sizeof(data))
- alg->hash(&h, size, &data);
- else
- alg->hash(&h, size, data);
- return h;
-}
-
-uintptr
-runtime·ifacehash(Iface a, uintptr h)
-{
- if(a.tab == nil)
- return h;
- return ifacehash1(a.data, a.tab->type, h);
-}
-
-uintptr
-runtime·efacehash(Eface a, uintptr h)
-{
- return ifacehash1(a.data, a.type, h);
-}
-
-static bool
-ifaceeq1(void *data1, void *data2, Type *t)
-{
- uintptr size;
- Alg *alg;
- Eface err;
- bool eq;
-
- alg = t->alg;
- size = t->size;
-
- if(alg->equal == runtime·noequal) {
- // calling noequal will panic too,
- // but we can print a better error.
- runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"comparing uncomparable type "), *t->string), &err);
- runtime·panic(err);
- }
-
- eq = 0;
- if(size <= sizeof(data1))
- alg->equal(&eq, size, &data1, &data2);
- else
- alg->equal(&eq, size, data1, data2);
- return eq;
-}
-
-bool
-runtime·ifaceeq_c(Iface i1, Iface i2)
-{
- if(i1.tab != i2.tab)
- return false;
- if(i1.tab == nil)
- return true;
- return ifaceeq1(i1.data, i2.data, i1.tab->type);
-}
-
-bool
-runtime·efaceeq_c(Eface e1, Eface e2)
-{
- if(e1.type != e2.type)
- return false;
- if(e1.type == nil)
- return true;
- return ifaceeq1(e1.data, e2.data, e1.type);
-}
-
-func ifaceeq(i1 Iface, i2 Iface) (ret bool) {
- ret = runtime·ifaceeq_c(i1, i2);
-}
-
-func efaceeq(e1 Eface, e2 Eface) (ret bool) {
- ret = runtime·efaceeq_c(e1, e2);
-}
-
-func ifacethash(i1 Iface) (ret uint32) {
- Itab *tab;
-
- ret = 0;
- tab = i1.tab;
- if(tab != nil)
- ret = tab->type->hash;
-}
-
-func efacethash(e1 Eface) (ret uint32) {
- Type *t;
-
- ret = 0;
- t = e1.type;
- if(t != nil)
- ret = t->hash;
-}
-
-func reflect·unsafe_Typeof(e Eface) (ret Eface) {
- if(e.type == nil) {
- ret.type = nil;
- ret.data = nil;
- } else {
- ret = *(Eface*)(e.type);
- }
-}
-
-func reflect·unsafe_New(t *Type) (ret *byte) {
- ret = runtime·cnew(t);
-}
-
-func reflect·unsafe_NewArray(t *Type, n int) (ret *byte) {
- ret = runtime·cnewarray(t, n);
-}
-
-func reflect·typelinks() (ret Slice) {
- extern Type *typelink[], *etypelink[];
- static int32 first = 1;
- ret.array = (byte*)typelink;
- ret.len = etypelink - typelink;
- ret.cap = ret.len;
-}
diff --git a/src/pkg/runtime/lock_futex.c b/src/pkg/runtime/lock_futex.c
deleted file mode 100644
index c16ac905d..000000000
--- a/src/pkg/runtime/lock_futex.c
+++ /dev/null
@@ -1,201 +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 dragonfly freebsd linux
-
-#include "runtime.h"
-#include "stack.h"
-#include "../../cmd/ld/textflag.h"
-
-// This implementation depends on OS-specific implementations of
-//
-// runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
-// Atomically,
-// if(*addr == val) sleep
-// Might be woken up spuriously; that's allowed.
-// Don't sleep longer than ns; ns < 0 means forever.
-//
-// runtime·futexwakeup(uint32 *addr, uint32 cnt)
-// If any procs are sleeping on addr, wake up at most cnt.
-
-enum
-{
- MUTEX_UNLOCKED = 0,
- MUTEX_LOCKED = 1,
- MUTEX_SLEEPING = 2,
-
- ACTIVE_SPIN = 4,
- ACTIVE_SPIN_CNT = 30,
- PASSIVE_SPIN = 1,
-};
-
-// Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING.
-// MUTEX_SLEEPING means that there is presumably at least one sleeping thread.
-// Note that there can be spinning threads during all states - they do not
-// affect mutex's state.
-void
-runtime·lock(Lock *l)
-{
- uint32 i, v, wait, spin;
-
- if(m->locks++ < 0)
- runtime·throw("runtime·lock: lock count");
-
- // Speculative grab for lock.
- v = runtime·xchg((uint32*)&l->key, MUTEX_LOCKED);
- if(v == MUTEX_UNLOCKED)
- return;
-
- // wait is either MUTEX_LOCKED or MUTEX_SLEEPING
- // depending on whether there is a thread sleeping
- // on this mutex. If we ever change l->key from
- // MUTEX_SLEEPING to some other value, we must be
- // careful to change it back to MUTEX_SLEEPING before
- // returning, to ensure that the sleeping thread gets
- // its wakeup call.
- wait = v;
-
- // On uniprocessor's, no point spinning.
- // On multiprocessors, spin for ACTIVE_SPIN attempts.
- spin = 0;
- if(runtime·ncpu > 1)
- spin = ACTIVE_SPIN;
-
- for(;;) {
- // Try for lock, spinning.
- for(i = 0; i < spin; i++) {
- while(l->key == MUTEX_UNLOCKED)
- if(runtime·cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
- return;
- runtime·procyield(ACTIVE_SPIN_CNT);
- }
-
- // Try for lock, rescheduling.
- for(i=0; i < PASSIVE_SPIN; i++) {
- while(l->key == MUTEX_UNLOCKED)
- if(runtime·cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
- return;
- runtime·osyield();
- }
-
- // Sleep.
- v = runtime·xchg((uint32*)&l->key, MUTEX_SLEEPING);
- if(v == MUTEX_UNLOCKED)
- return;
- wait = MUTEX_SLEEPING;
- runtime·futexsleep((uint32*)&l->key, MUTEX_SLEEPING, -1);
- }
-}
-
-void
-runtime·unlock(Lock *l)
-{
- uint32 v;
-
- v = runtime·xchg((uint32*)&l->key, MUTEX_UNLOCKED);
- if(v == MUTEX_UNLOCKED)
- runtime·throw("unlock of unlocked lock");
- if(v == MUTEX_SLEEPING)
- runtime·futexwakeup((uint32*)&l->key, 1);
-
- if(--m->locks < 0)
- runtime·throw("runtime·unlock: lock count");
- if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
- g->stackguard0 = StackPreempt;
-}
-
-// One-time notifications.
-void
-runtime·noteclear(Note *n)
-{
- n->key = 0;
-}
-
-void
-runtime·notewakeup(Note *n)
-{
- uint32 old;
-
- old = runtime·xchg((uint32*)&n->key, 1);
- if(old != 0) {
- runtime·printf("notewakeup - double wakeup (%d)\n", old);
- runtime·throw("notewakeup - double wakeup");
- }
- runtime·futexwakeup((uint32*)&n->key, 1);
-}
-
-void
-runtime·notesleep(Note *n)
-{
- if(g != m->g0)
- runtime·throw("notesleep not on g0");
- while(runtime·atomicload((uint32*)&n->key) == 0) {
- m->blocked = true;
- runtime·futexsleep((uint32*)&n->key, 0, -1);
- m->blocked = false;
- }
-}
-
-#pragma textflag NOSPLIT
-static bool
-notetsleep(Note *n, int64 ns, int64 deadline, int64 now)
-{
- // Conceptually, deadline and now are local variables.
- // They are passed as arguments so that the space for them
- // does not count against our nosplit stack sequence.
-
- if(ns < 0) {
- while(runtime·atomicload((uint32*)&n->key) == 0) {
- m->blocked = true;
- runtime·futexsleep((uint32*)&n->key, 0, -1);
- m->blocked = false;
- }
- return true;
- }
-
- if(runtime·atomicload((uint32*)&n->key) != 0)
- return true;
-
- deadline = runtime·nanotime() + ns;
- for(;;) {
- m->blocked = true;
- runtime·futexsleep((uint32*)&n->key, 0, ns);
- m->blocked = false;
- if(runtime·atomicload((uint32*)&n->key) != 0)
- break;
- now = runtime·nanotime();
- if(now >= deadline)
- break;
- ns = deadline - now;
- }
- return runtime·atomicload((uint32*)&n->key) != 0;
-}
-
-bool
-runtime·notetsleep(Note *n, int64 ns)
-{
- bool res;
-
- if(g != m->g0 && !m->gcing)
- runtime·throw("notetsleep not on g0");
-
- res = notetsleep(n, ns, 0, 0);
- return res;
-}
-
-// same as runtime·notetsleep, but called on user g (not g0)
-// calls only nosplit functions between entersyscallblock/exitsyscall
-bool
-runtime·notetsleepg(Note *n, int64 ns)
-{
- bool res;
-
- if(g == m->g0)
- runtime·throw("notetsleepg on g0");
-
- runtime·entersyscallblock();
- res = notetsleep(n, ns, 0, 0);
- runtime·exitsyscall();
- return res;
-}
diff --git a/src/pkg/runtime/lock_sema.c b/src/pkg/runtime/lock_sema.c
deleted file mode 100644
index ff8fdfd42..000000000
--- a/src/pkg/runtime/lock_sema.c
+++ /dev/null
@@ -1,266 +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 darwin nacl netbsd openbsd plan9 solaris windows
-
-#include "runtime.h"
-#include "stack.h"
-#include "../../cmd/ld/textflag.h"
-
-// 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.
-//
-// 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.
-// 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.
-//
-
-enum
-{
- LOCKED = 1,
-
- ACTIVE_SPIN = 4,
- ACTIVE_SPIN_CNT = 30,
- PASSIVE_SPIN = 1,
-};
-
-void
-runtime·lock(Lock *l)
-{
- uintptr v;
- uint32 i, spin;
-
- if(m->locks++ < 0)
- runtime·throw("runtime·lock: lock count");
-
- // Speculative grab for lock.
- if(runtime·casp((void**)&l->key, nil, (void*)LOCKED))
- return;
-
- if(m->waitsema == 0)
- m->waitsema = runtime·semacreate();
-
- // On uniprocessor's, no point spinning.
- // On multiprocessors, spin for ACTIVE_SPIN attempts.
- spin = 0;
- if(runtime·ncpu > 1)
- spin = ACTIVE_SPIN;
-
- for(i=0;; i++) {
- v = (uintptr)runtime·atomicloadp((void**)&l->key);
- if((v&LOCKED) == 0) {
-unlocked:
- if(runtime·casp((void**)&l->key, (void*)v, (void*)(v|LOCKED)))
- return;
- i = 0;
- }
- if(i<spin)
- runtime·procyield(ACTIVE_SPIN_CNT);
- else if(i<spin+PASSIVE_SPIN)
- runtime·osyield();
- else {
- // Someone else has it.
- // l->waitm points to a linked list of M's waiting
- // for this lock, chained through m->nextwaitm.
- // Queue this M.
- for(;;) {
- m->nextwaitm = (void*)(v&~LOCKED);
- if(runtime·casp((void**)&l->key, (void*)v, (void*)((uintptr)m|LOCKED)))
- break;
- v = (uintptr)runtime·atomicloadp((void**)&l->key);
- if((v&LOCKED) == 0)
- goto unlocked;
- }
- if(v&LOCKED) {
- // Queued. Wait.
- runtime·semasleep(-1);
- i = 0;
- }
- }
- }
-}
-
-void
-runtime·unlock(Lock *l)
-{
- uintptr v;
- M *mp;
-
- for(;;) {
- v = (uintptr)runtime·atomicloadp((void**)&l->key);
- if(v == LOCKED) {
- if(runtime·casp((void**)&l->key, (void*)LOCKED, nil))
- break;
- } else {
- // Other M's are waiting for the lock.
- // Dequeue an M.
- mp = (void*)(v&~LOCKED);
- if(runtime·casp((void**)&l->key, (void*)v, mp->nextwaitm)) {
- // Dequeued an M. Wake it.
- runtime·semawakeup(mp);
- break;
- }
- }
- }
-
- if(--m->locks < 0)
- runtime·throw("runtime·unlock: lock count");
- if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
- g->stackguard0 = StackPreempt;
-}
-
-// One-time notifications.
-void
-runtime·noteclear(Note *n)
-{
- n->key = 0;
-}
-
-void
-runtime·notewakeup(Note *n)
-{
- M *mp;
-
- do
- mp = runtime·atomicloadp((void**)&n->key);
- while(!runtime·casp((void**)&n->key, mp, (void*)LOCKED));
-
- // Successfully set waitm to LOCKED.
- // What was it before?
- if(mp == nil) {
- // Nothing was waiting. Done.
- } else if(mp == (M*)LOCKED) {
- // Two notewakeups! Not allowed.
- runtime·throw("notewakeup - double wakeup");
- } else {
- // Must be the waiting m. Wake it up.
- runtime·semawakeup(mp);
- }
-}
-
-void
-runtime·notesleep(Note *n)
-{
- if(g != m->g0)
- runtime·throw("notesleep not on g0");
-
- if(m->waitsema == 0)
- m->waitsema = runtime·semacreate();
- if(!runtime·casp((void**)&n->key, nil, m)) { // must be LOCKED (got wakeup)
- if(n->key != LOCKED)
- runtime·throw("notesleep - waitm out of sync");
- return;
- }
- // Queued. Sleep.
- m->blocked = true;
- runtime·semasleep(-1);
- m->blocked = false;
-}
-
-#pragma textflag NOSPLIT
-static bool
-notetsleep(Note *n, int64 ns, int64 deadline, M *mp)
-{
- // Conceptually, deadline and mp are local variables.
- // They are passed as arguments so that the space for them
- // does not count against our nosplit stack sequence.
-
- // Register for wakeup on n->waitm.
- if(!runtime·casp((void**)&n->key, nil, m)) { // must be LOCKED (got wakeup already)
- if(n->key != LOCKED)
- runtime·throw("notetsleep - waitm out of sync");
- return true;
- }
-
- if(ns < 0) {
- // Queued. Sleep.
- m->blocked = true;
- runtime·semasleep(-1);
- m->blocked = false;
- return true;
- }
-
- deadline = runtime·nanotime() + ns;
- for(;;) {
- // Registered. Sleep.
- m->blocked = true;
- if(runtime·semasleep(ns) >= 0) {
- m->blocked = false;
- // Acquired semaphore, semawakeup unregistered us.
- // Done.
- return true;
- }
- m->blocked = false;
-
- // Interrupted or timed out. Still registered. Semaphore not acquired.
- ns = deadline - runtime·nanotime();
- if(ns <= 0)
- break;
- // Deadline hasn't arrived. Keep sleeping.
- }
-
- // Deadline arrived. Still registered. Semaphore not acquired.
- // Want to give up and return, but have to unregister first,
- // so that any notewakeup racing with the return does not
- // try to grant us the semaphore when we don't expect it.
- for(;;) {
- mp = runtime·atomicloadp((void**)&n->key);
- if(mp == m) {
- // No wakeup yet; unregister if possible.
- if(runtime·casp((void**)&n->key, mp, nil))
- return false;
- } else if(mp == (M*)LOCKED) {
- // Wakeup happened so semaphore is available.
- // Grab it to avoid getting out of sync.
- m->blocked = true;
- if(runtime·semasleep(-1) < 0)
- runtime·throw("runtime: unable to acquire - semaphore out of sync");
- m->blocked = false;
- return true;
- } else
- runtime·throw("runtime: unexpected waitm - semaphore out of sync");
- }
-}
-
-bool
-runtime·notetsleep(Note *n, int64 ns)
-{
- bool res;
-
- if(g != m->g0 && !m->gcing)
- runtime·throw("notetsleep not on g0");
-
- if(m->waitsema == 0)
- m->waitsema = runtime·semacreate();
-
- res = notetsleep(n, ns, 0, nil);
- return res;
-}
-
-// same as runtime·notetsleep, but called on user g (not g0)
-// calls only nosplit functions between entersyscallblock/exitsyscall
-bool
-runtime·notetsleepg(Note *n, int64 ns)
-{
- bool res;
-
- if(g == m->g0)
- runtime·throw("notetsleepg on g0");
-
- if(m->waitsema == 0)
- m->waitsema = runtime·semacreate();
-
- runtime·entersyscallblock();
- res = notetsleep(n, ns, 0, nil);
- runtime·exitsyscall();
- return res;
-}
diff --git a/src/pkg/runtime/malloc.goc b/src/pkg/runtime/malloc.goc
deleted file mode 100644
index 7b7e350d8..000000000
--- a/src/pkg/runtime/malloc.goc
+++ /dev/null
@@ -1,939 +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.
-
-// See malloc.h for overview.
-//
-// TODO(rsc): double-check stats.
-
-package runtime
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "type.h"
-#include "typekind.h"
-#include "race.h"
-#include "stack.h"
-#include "../../cmd/ld/textflag.h"
-
-// Mark mheap as 'no pointers', it does not contain interesting pointers but occupies ~45K.
-#pragma dataflag NOPTR
-MHeap runtime·mheap;
-#pragma dataflag NOPTR
-MStats mstats;
-
-int32 runtime·checking;
-
-extern MStats mstats; // defined in zruntime_def_$GOOS_$GOARCH.go
-
-extern volatile intgo runtime·MemProfileRate;
-
-static MSpan* largealloc(uint32, uintptr*);
-static void profilealloc(void *v, uintptr size);
-static void settype(MSpan *s, void *v, uintptr typ);
-
-// Allocate an object of at least size bytes.
-// Small objects are allocated from the per-thread cache's free lists.
-// Large objects (> 32 kB) are allocated straight from the heap.
-// If the block will be freed with runtime·free(), typ must be 0.
-void*
-runtime·mallocgc(uintptr size, uintptr typ, uint32 flag)
-{
- int32 sizeclass;
- uintptr tinysize, size1;
- intgo rate;
- MCache *c;
- MSpan *s;
- MLink *v, *next;
- byte *tiny;
-
- if(size == 0) {
- // All 0-length allocations use this pointer.
- // The language does not require the allocations to
- // have distinct values.
- return &runtime·zerobase;
- }
- if(m->mallocing)
- runtime·throw("malloc/free - deadlock");
- // Disable preemption during settype.
- // We can not use m->mallocing for this, because settype calls mallocgc.
- m->locks++;
- m->mallocing = 1;
-
- if(DebugTypeAtBlockEnd)
- size += sizeof(uintptr);
-
- c = m->mcache;
- if(!runtime·debug.efence && size <= MaxSmallSize) {
- if((flag&(FlagNoScan|FlagNoGC)) == FlagNoScan && size < TinySize) {
- // Tiny allocator.
- //
- // Tiny allocator combines several tiny allocation requests
- // into a single memory block. The resulting memory block
- // is freed when all subobjects are unreachable. The subobjects
- // must be FlagNoScan (don't have pointers), this ensures that
- // the amount of potentially wasted memory is bounded.
- //
- // Size of the memory block used for combining (TinySize) is tunable.
- // Current setting is 16 bytes, which relates to 2x worst case memory
- // wastage (when all but one subobjects are unreachable).
- // 8 bytes would result in no wastage at all, but provides less
- // opportunities for combining.
- // 32 bytes provides more opportunities for combining,
- // but can lead to 4x worst case wastage.
- // The best case winning is 8x regardless of block size.
- //
- // Objects obtained from tiny allocator must not be freed explicitly.
- // So when an object will be freed explicitly, we ensure that
- // its size >= TinySize.
- //
- // SetFinalizer has a special case for objects potentially coming
- // from tiny allocator, it such case it allows to set finalizers
- // for an inner byte of a memory block.
- //
- // The main targets of tiny allocator are small strings and
- // standalone escaping variables. On a json benchmark
- // the allocator reduces number of allocations by ~12% and
- // reduces heap size by ~20%.
-
- tinysize = c->tinysize;
- if(size <= tinysize) {
- tiny = c->tiny;
- // Align tiny pointer for required (conservative) alignment.
- if((size&7) == 0)
- tiny = (byte*)ROUND((uintptr)tiny, 8);
- else if((size&3) == 0)
- tiny = (byte*)ROUND((uintptr)tiny, 4);
- else if((size&1) == 0)
- tiny = (byte*)ROUND((uintptr)tiny, 2);
- size1 = size + (tiny - c->tiny);
- if(size1 <= tinysize) {
- // The object fits into existing tiny block.
- v = (MLink*)tiny;
- c->tiny += size1;
- c->tinysize -= size1;
- m->mallocing = 0;
- m->locks--;
- if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
- g->stackguard0 = StackPreempt;
- return v;
- }
- }
- // Allocate a new TinySize block.
- s = c->alloc[TinySizeClass];
- if(s->freelist == nil)
- s = runtime·MCache_Refill(c, TinySizeClass);
- v = s->freelist;
- next = v->next;
- s->freelist = next;
- s->ref++;
- if(next != nil) // prefetching nil leads to a DTLB miss
- PREFETCH(next);
- ((uint64*)v)[0] = 0;
- ((uint64*)v)[1] = 0;
- // See if we need to replace the existing tiny block with the new one
- // based on amount of remaining free space.
- if(TinySize-size > tinysize) {
- c->tiny = (byte*)v + size;
- c->tinysize = TinySize - size;
- }
- size = TinySize;
- goto done;
- }
- // Allocate from mcache free lists.
- // Inlined version of SizeToClass().
- if(size <= 1024-8)
- sizeclass = runtime·size_to_class8[(size+7)>>3];
- else
- sizeclass = runtime·size_to_class128[(size-1024+127) >> 7];
- size = runtime·class_to_size[sizeclass];
- s = c->alloc[sizeclass];
- if(s->freelist == nil)
- s = runtime·MCache_Refill(c, sizeclass);
- v = s->freelist;
- next = v->next;
- s->freelist = next;
- s->ref++;
- if(next != nil) // prefetching nil leads to a DTLB miss
- PREFETCH(next);
- if(!(flag & FlagNoZero)) {
- v->next = nil;
- // block is zeroed iff second word is zero ...
- if(size > 2*sizeof(uintptr) && ((uintptr*)v)[1] != 0)
- runtime·memclr((byte*)v, size);
- }
- done:
- c->local_cachealloc += size;
- } else {
- // Allocate directly from heap.
- s = largealloc(flag, &size);
- v = (void*)(s->start << PageShift);
- }
-
- if(flag & FlagNoGC)
- runtime·marknogc(v);
- else if(!(flag & FlagNoScan))
- runtime·markscan(v);
-
- if(DebugTypeAtBlockEnd)
- *(uintptr*)((uintptr)v+size-sizeof(uintptr)) = typ;
-
- m->mallocing = 0;
- // TODO: save type even if FlagNoScan? Potentially expensive but might help
- // heap profiling/tracing.
- if(UseSpanType && !(flag & FlagNoScan) && typ != 0)
- settype(s, v, typ);
-
- if(raceenabled)
- runtime·racemalloc(v, size);
-
- if(runtime·debug.allocfreetrace)
- runtime·tracealloc(v, size, typ);
-
- if(!(flag & FlagNoProfiling) && (rate = runtime·MemProfileRate) > 0) {
- if(size < rate && size < c->next_sample)
- c->next_sample -= size;
- else
- profilealloc(v, size);
- }
-
- m->locks--;
- if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
- g->stackguard0 = StackPreempt;
-
- if(!(flag & FlagNoInvokeGC) && mstats.heap_alloc >= mstats.next_gc)
- runtime·gc(0);
-
- return v;
-}
-
-static MSpan*
-largealloc(uint32 flag, uintptr *sizep)
-{
- uintptr npages, size;
- MSpan *s;
- void *v;
-
- // Allocate directly from heap.
- size = *sizep;
- if(size + PageSize < size)
- runtime·throw("out of memory");
- npages = size >> PageShift;
- if((size & PageMask) != 0)
- npages++;
- s = runtime·MHeap_Alloc(&runtime·mheap, npages, 0, 1, !(flag & FlagNoZero));
- if(s == nil)
- runtime·throw("out of memory");
- s->limit = (byte*)(s->start<<PageShift) + size;
- *sizep = npages<<PageShift;
- v = (void*)(s->start << PageShift);
- // setup for mark sweep
- runtime·markspan(v, 0, 0, true);
- return s;
-}
-
-static void
-profilealloc(void *v, uintptr size)
-{
- uintptr rate;
- int32 next;
- MCache *c;
-
- c = m->mcache;
- rate = runtime·MemProfileRate;
- if(size < rate) {
- // pick next profile time
- // If you change this, also change allocmcache.
- if(rate > 0x3fffffff) // make 2*rate not overflow
- rate = 0x3fffffff;
- next = runtime·fastrand1() % (2*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 -= (size - c->next_sample);
- if(next < 0)
- next = 0;
- c->next_sample = next;
- }
- runtime·MProf_Malloc(v, size);
-}
-
-void*
-runtime·malloc(uintptr size)
-{
- return runtime·mallocgc(size, 0, FlagNoInvokeGC);
-}
-
-// Free the object whose base pointer is v.
-void
-runtime·free(void *v)
-{
- int32 sizeclass;
- MSpan *s;
- MCache *c;
- uintptr size;
-
- if(v == nil)
- return;
-
- // If you change this also change mgc0.c:/^sweep,
- // which has a copy of the guts of free.
-
- if(m->mallocing)
- runtime·throw("malloc/free - deadlock");
- m->mallocing = 1;
-
- if(!runtime·mlookup(v, nil, nil, &s)) {
- runtime·printf("free %p: not an allocated block\n", v);
- runtime·throw("free runtime·mlookup");
- }
- size = s->elemsize;
- sizeclass = s->sizeclass;
- // Objects that are smaller than TinySize can be allocated using tiny alloc,
- // if then such object is combined with an object with finalizer, we will crash.
- if(size < TinySize)
- runtime·throw("freeing too small block");
-
- if(runtime·debug.allocfreetrace)
- runtime·tracefree(v, size);
-
- // Ensure that the span is swept.
- // If we free into an unswept span, we will corrupt GC bitmaps.
- runtime·MSpan_EnsureSwept(s);
-
- if(s->specials != nil)
- runtime·freeallspecials(s, v, size);
-
- c = m->mcache;
- if(sizeclass == 0) {
- // Large object.
- s->needzero = 1;
- // Must mark v freed before calling unmarkspan and MHeap_Free:
- // they might coalesce v into other spans and change the bitmap further.
- runtime·markfreed(v);
- runtime·unmarkspan(v, 1<<PageShift);
- // NOTE(rsc,dvyukov): The original implementation of efence
- // in CL 22060046 used SysFree instead of SysFault, so that
- // the operating system would eventually give the memory
- // back to us again, so that an efence program could run
- // longer without running out of memory. Unfortunately,
- // calling SysFree here without any kind of adjustment of the
- // heap data structures means that when the memory does
- // come back to us, we have the wrong metadata for it, either in
- // the MSpan structures or in the garbage collection bitmap.
- // Using SysFault here means that the program will run out of
- // memory fairly quickly in efence mode, but at least it won't
- // have mysterious crashes due to confused memory reuse.
- // It should be possible to switch back to SysFree if we also
- // implement and then call some kind of MHeap_DeleteSpan.
- if(runtime·debug.efence)
- runtime·SysFault((void*)(s->start<<PageShift), size);
- else
- runtime·MHeap_Free(&runtime·mheap, s, 1);
- c->local_nlargefree++;
- c->local_largefree += size;
- } else {
- // Small object.
- if(size > 2*sizeof(uintptr))
- ((uintptr*)v)[1] = (uintptr)0xfeedfeedfeedfeedll; // mark as "needs to be zeroed"
- else if(size > sizeof(uintptr))
- ((uintptr*)v)[1] = 0;
- // Must mark v freed before calling MCache_Free:
- // it might coalesce v and other blocks into a bigger span
- // and change the bitmap further.
- c->local_nsmallfree[sizeclass]++;
- c->local_cachealloc -= size;
- if(c->alloc[sizeclass] == s) {
- // We own the span, so we can just add v to the freelist
- runtime·markfreed(v);
- ((MLink*)v)->next = s->freelist;
- s->freelist = v;
- s->ref--;
- } else {
- // Someone else owns this span. Add to free queue.
- runtime·MCache_Free(c, v, sizeclass, size);
- }
- }
- m->mallocing = 0;
-}
-
-int32
-runtime·mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
-{
- uintptr n, i;
- byte *p;
- MSpan *s;
-
- m->mcache->local_nlookup++;
- if (sizeof(void*) == 4 && m->mcache->local_nlookup >= (1<<30)) {
- // purge cache stats to prevent overflow
- runtime·lock(&runtime·mheap);
- runtime·purgecachedstats(m->mcache);
- runtime·unlock(&runtime·mheap);
- }
-
- s = runtime·MHeap_LookupMaybe(&runtime·mheap, v);
- if(sp)
- *sp = s;
- if(s == nil) {
- runtime·checkfreed(v, 1);
- if(base)
- *base = nil;
- if(size)
- *size = 0;
- return 0;
- }
-
- p = (byte*)((uintptr)s->start<<PageShift);
- if(s->sizeclass == 0) {
- // Large object.
- if(base)
- *base = p;
- if(size)
- *size = s->npages<<PageShift;
- return 1;
- }
-
- n = s->elemsize;
- if(base) {
- i = ((byte*)v - p)/n;
- *base = p + i*n;
- }
- if(size)
- *size = n;
-
- return 1;
-}
-
-void
-runtime·purgecachedstats(MCache *c)
-{
- MHeap *h;
- int32 i;
-
- // Protected by either heap or GC lock.
- h = &runtime·mheap;
- mstats.heap_alloc += c->local_cachealloc;
- c->local_cachealloc = 0;
- mstats.nlookup += c->local_nlookup;
- c->local_nlookup = 0;
- h->largefree += c->local_largefree;
- c->local_largefree = 0;
- h->nlargefree += c->local_nlargefree;
- c->local_nlargefree = 0;
- for(i=0; i<nelem(c->local_nsmallfree); i++) {
- h->nsmallfree[i] += c->local_nsmallfree[i];
- c->local_nsmallfree[i] = 0;
- }
-}
-
-// Size of the trailing by_size array differs between Go and C,
-// NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
-// sizeof_C_MStats is what C thinks about size of Go struct.
-uintptr runtime·sizeof_C_MStats = sizeof(MStats) - (NumSizeClasses - 61) * sizeof(mstats.by_size[0]);
-
-#define MaxArena32 (2U<<30)
-
-void
-runtime·mallocinit(void)
-{
- byte *p, *p1;
- uintptr arena_size, bitmap_size, spans_size, p_size;
- extern byte end[];
- uintptr limit;
- uint64 i;
- bool reserved;
-
- p = nil;
- p_size = 0;
- arena_size = 0;
- bitmap_size = 0;
- spans_size = 0;
- reserved = false;
-
- // for 64-bit build
- USED(p);
- USED(p_size);
- USED(arena_size);
- USED(bitmap_size);
- USED(spans_size);
-
- runtime·InitSizes();
-
- if(runtime·class_to_size[TinySizeClass] != TinySize)
- runtime·throw("bad TinySizeClass");
-
- // limit = runtime·memlimit();
- // See https://code.google.com/p/go/issues/detail?id=5049
- // TODO(rsc): Fix after 1.1.
- limit = 0;
-
- // 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(sizeof(void*) == 8 && (limit == 0 || limit > (1<<30))) {
- // On a 64-bit machine, allocate from a single contiguous reservation.
- // 128 GB (MaxMem) should be big enough for now.
- //
- // The code will work with the reservation at any address, but ask
- // SysReserve to use 0x0000XXc000000000 if possible (XX=00...7f).
- // Allocating a 128 GB region takes away 37 bits, and the amd64
- // doesn't let us choose the top 17 bits, so that leaves the 11 bits
- // in the middle of 0x00c0 for us to choose. Choosing 0x00c0 means
- // that the valid memory addresses will begin 0x00c0, 0x00c1, ..., 0x00df.
- // In little-endian, that's c0 00, c1 00, ..., df 00. None of those are valid
- // UTF-8 sequences, and they are otherwise as far away from
- // ff (likely a common byte) as possible. If that fails, we try other 0xXXc0
- // addresses. An earlier attempt to use 0x11f8 caused out of memory errors
- // on OS X during thread allocations. 0x00c0 causes conflicts with
- // AddressSanitizer which reserves all memory up to 0x0100.
- // These choices are both for debuggability and to reduce the
- // odds of the conservative garbage collector not collecting memory
- // because some non-pointer block of memory had a bit pattern
- // that matched a memory address.
- //
- // Actually we reserve 136 GB (because the bitmap ends up being 8 GB)
- // but it hardly matters: e0 00 is not valid UTF-8 either.
- //
- // If this fails we fall back to the 32 bit memory mechanism
- arena_size = MaxMem;
- bitmap_size = arena_size / (sizeof(void*)*8/4);
- spans_size = arena_size / PageSize * sizeof(runtime·mheap.spans[0]);
- spans_size = ROUND(spans_size, PageSize);
- for(i = 0; i <= 0x7f; i++) {
- p = (void*)(i<<40 | 0x00c0ULL<<32);
- p_size = bitmap_size + spans_size + arena_size + PageSize;
- p = runtime·SysReserve(p, p_size, &reserved);
- if(p != nil)
- break;
- }
- }
- if (p == nil) {
- // On a 32-bit machine, we can't typically get away
- // with a giant virtual address space reservation.
- // Instead we map the memory information bitmap
- // immediately after the data segment, large enough
- // to handle another 2GB of mappings (256 MB),
- // along with a reservation for another 512 MB of memory.
- // When that gets used up, we'll start asking the kernel
- // for any memory anywhere and hope it's in the 2GB
- // following the bitmap (presumably the executable begins
- // near the bottom of memory, so we'll have to use up
- // most of memory before the kernel resorts to giving out
- // memory before the beginning of the text segment).
- //
- // Alternatively we could reserve 512 MB bitmap, enough
- // for 4GB of mappings, and then accept any memory the
- // kernel threw at us, but normally that's a waste of 512 MB
- // of address space, which is probably too much in a 32-bit world.
- bitmap_size = MaxArena32 / (sizeof(void*)*8/4);
- arena_size = 512<<20;
- spans_size = MaxArena32 / PageSize * sizeof(runtime·mheap.spans[0]);
- if(limit > 0 && arena_size+bitmap_size+spans_size > limit) {
- bitmap_size = (limit / 9) & ~((1<<PageShift) - 1);
- arena_size = bitmap_size * 8;
- spans_size = arena_size / PageSize * sizeof(runtime·mheap.spans[0]);
- }
- spans_size = ROUND(spans_size, PageSize);
-
- // SysReserve treats the address we ask for, end, as a hint,
- // not as an absolute requirement. If we ask for the end
- // of the data segment but the operating system requires
- // a little more space before we can start allocating, it will
- // give out a slightly higher pointer. Except QEMU, which
- // is buggy, as usual: it won't adjust the pointer upward.
- // So adjust it upward a little bit ourselves: 1/4 MB to get
- // away from the running binary image and then round up
- // to a MB boundary.
- p = (byte*)ROUND((uintptr)end + (1<<18), 1<<20);
- p_size = bitmap_size + spans_size + arena_size + PageSize;
- p = runtime·SysReserve(p, p_size, &reserved);
- if(p == nil)
- runtime·throw("runtime: cannot reserve arena virtual address space");
- }
-
- // PageSize can be larger than OS definition of page size,
- // so SysReserve can give us a PageSize-unaligned pointer.
- // To overcome this we ask for PageSize more and round up the pointer.
- p1 = (byte*)ROUND((uintptr)p, PageSize);
-
- runtime·mheap.spans = (MSpan**)p1;
- runtime·mheap.bitmap = p1 + spans_size;
- runtime·mheap.arena_start = p1 + spans_size + bitmap_size;
- runtime·mheap.arena_used = runtime·mheap.arena_start;
- runtime·mheap.arena_end = p + p_size;
- runtime·mheap.arena_reserved = reserved;
-
- if(((uintptr)runtime·mheap.arena_start & (PageSize-1)) != 0)
- runtime·throw("misrounded allocation in mallocinit");
-
- // Initialize the rest of the allocator.
- runtime·MHeap_Init(&runtime·mheap);
- m->mcache = runtime·allocmcache();
-
- // See if it works.
- runtime·free(runtime·malloc(TinySize));
-}
-
-void*
-runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
-{
- byte *p, *p_end;
- uintptr p_size;
- bool reserved;
-
- 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.
- byte *new_end;
-
- p_size = ROUND(n + PageSize, 256<<20);
- new_end = h->arena_end + p_size;
- if(new_end <= h->arena_start + MaxArena32) {
- // TODO: It would be bad if part of the arena
- // is reserved and part is not.
- p = runtime·SysReserve(h->arena_end, p_size, &reserved);
- if(p == h->arena_end) {
- h->arena_end = new_end;
- h->arena_reserved = reserved;
- }
- else if(p+p_size <= h->arena_start + MaxArena32) {
- // Keep everything page-aligned.
- // Our pages are bigger than hardware pages.
- h->arena_end = p+p_size;
- h->arena_used = p + (-(uintptr)p&(PageSize-1));
- h->arena_reserved = reserved;
- } else {
- uint64 stat;
- stat = 0;
- runtime·SysFree(p, p_size, &stat);
- }
- }
- }
- if(n <= h->arena_end - h->arena_used) {
- // Keep taking from our reservation.
- p = h->arena_used;
- runtime·SysMap(p, n, h->arena_reserved, &mstats.heap_sys);
- h->arena_used += n;
- runtime·MHeap_MapBits(h);
- runtime·MHeap_MapSpans(h);
- if(raceenabled)
- runtime·racemapshadow(p, n);
-
- if(((uintptr)p & (PageSize-1)) != 0)
- runtime·throw("misrounded allocation in MHeap_SysAlloc");
- return p;
- }
-
- // If using 64-bit, our reservation is all we have.
- if(h->arena_end - h->arena_start >= MaxArena32)
- return nil;
-
- // On 32-bit, once the reservation is gone we can
- // try to get memory at a location chosen by the OS
- // and hope that it is in the range we allocated bitmap for.
- p_size = ROUND(n, PageSize) + PageSize;
- p = runtime·SysAlloc(p_size, &mstats.heap_sys);
- if(p == nil)
- return nil;
-
- if(p < h->arena_start || p+p_size - h->arena_start >= MaxArena32) {
- runtime·printf("runtime: memory allocated by OS (%p) not in usable range [%p,%p)\n",
- p, h->arena_start, h->arena_start+MaxArena32);
- runtime·SysFree(p, p_size, &mstats.heap_sys);
- return nil;
- }
-
- p_end = p + p_size;
- p += -(uintptr)p & (PageSize-1);
- if(p+n > h->arena_used) {
- h->arena_used = p+n;
- if(p_end > h->arena_end)
- h->arena_end = p_end;
- runtime·MHeap_MapBits(h);
- runtime·MHeap_MapSpans(h);
- if(raceenabled)
- runtime·racemapshadow(p, n);
- }
-
- if(((uintptr)p & (PageSize-1)) != 0)
- runtime·throw("misrounded allocation in MHeap_SysAlloc");
- return p;
-}
-
-static struct
-{
- Lock;
- byte* pos;
- byte* end;
-} persistent;
-
-enum
-{
- PersistentAllocChunk = 256<<10,
- PersistentAllocMaxBlock = 64<<10, // VM reservation granularity is 64K on windows
-};
-
-// Wrapper around SysAlloc that can allocate small chunks.
-// There is no associated free operation.
-// Intended for things like function/type/debug-related persistent data.
-// If align is 0, uses default align (currently 8).
-void*
-runtime·persistentalloc(uintptr size, uintptr align, uint64 *stat)
-{
- byte *p;
-
- if(align != 0) {
- if(align&(align-1))
- runtime·throw("persistentalloc: align is not a power of 2");
- if(align > PageSize)
- runtime·throw("persistentalloc: align is too large");
- } else
- align = 8;
- if(size >= PersistentAllocMaxBlock)
- return runtime·SysAlloc(size, stat);
- runtime·lock(&persistent);
- persistent.pos = (byte*)ROUND((uintptr)persistent.pos, align);
- if(persistent.pos + size > persistent.end) {
- persistent.pos = runtime·SysAlloc(PersistentAllocChunk, &mstats.other_sys);
- if(persistent.pos == nil) {
- runtime·unlock(&persistent);
- runtime·throw("runtime: cannot allocate memory");
- }
- persistent.end = persistent.pos + PersistentAllocChunk;
- }
- p = persistent.pos;
- persistent.pos += size;
- runtime·unlock(&persistent);
- if(stat != &mstats.other_sys) {
- // reaccount the allocation against provided stat
- runtime·xadd64(stat, size);
- runtime·xadd64(&mstats.other_sys, -(uint64)size);
- }
- return p;
-}
-
-static void
-settype(MSpan *s, void *v, uintptr typ)
-{
- uintptr size, ofs, j, t;
- uintptr ntypes, nbytes2, nbytes3;
- uintptr *data2;
- byte *data3;
-
- if(s->sizeclass == 0) {
- s->types.compression = MTypes_Single;
- s->types.data = typ;
- return;
- }
- size = s->elemsize;
- ofs = ((uintptr)v - (s->start<<PageShift)) / size;
-
- switch(s->types.compression) {
- case MTypes_Empty:
- ntypes = (s->npages << PageShift) / size;
- nbytes3 = 8*sizeof(uintptr) + 1*ntypes;
- data3 = runtime·mallocgc(nbytes3, 0, FlagNoProfiling|FlagNoScan|FlagNoInvokeGC);
- s->types.compression = MTypes_Bytes;
- s->types.data = (uintptr)data3;
- ((uintptr*)data3)[1] = typ;
- data3[8*sizeof(uintptr) + ofs] = 1;
- break;
-
- case MTypes_Words:
- ((uintptr*)s->types.data)[ofs] = typ;
- break;
-
- case MTypes_Bytes:
- data3 = (byte*)s->types.data;
- for(j=1; j<8; j++) {
- if(((uintptr*)data3)[j] == typ) {
- break;
- }
- if(((uintptr*)data3)[j] == 0) {
- ((uintptr*)data3)[j] = typ;
- break;
- }
- }
- if(j < 8) {
- data3[8*sizeof(uintptr) + ofs] = j;
- } else {
- ntypes = (s->npages << PageShift) / size;
- nbytes2 = ntypes * sizeof(uintptr);
- data2 = runtime·mallocgc(nbytes2, 0, FlagNoProfiling|FlagNoScan|FlagNoInvokeGC);
- s->types.compression = MTypes_Words;
- s->types.data = (uintptr)data2;
-
- // Move the contents of data3 to data2. Then deallocate data3.
- for(j=0; j<ntypes; j++) {
- t = data3[8*sizeof(uintptr) + j];
- t = ((uintptr*)data3)[t];
- data2[j] = t;
- }
- data2[ofs] = typ;
- }
- break;
- }
-}
-
-uintptr
-runtime·gettype(void *v)
-{
- MSpan *s;
- uintptr t, ofs;
- byte *data;
-
- s = runtime·MHeap_LookupMaybe(&runtime·mheap, v);
- if(s != nil) {
- t = 0;
- switch(s->types.compression) {
- case MTypes_Empty:
- break;
- case MTypes_Single:
- t = s->types.data;
- break;
- case MTypes_Words:
- ofs = (uintptr)v - (s->start<<PageShift);
- t = ((uintptr*)s->types.data)[ofs/s->elemsize];
- break;
- case MTypes_Bytes:
- ofs = (uintptr)v - (s->start<<PageShift);
- data = (byte*)s->types.data;
- t = data[8*sizeof(uintptr) + ofs/s->elemsize];
- t = ((uintptr*)data)[t];
- break;
- default:
- runtime·throw("runtime·gettype: invalid compression kind");
- }
- if(0) {
- runtime·printf("%p -> %d,%X\n", v, (int32)s->types.compression, (int64)t);
- }
- return t;
- }
- return 0;
-}
-
-// Runtime stubs.
-
-void*
-runtime·mal(uintptr n)
-{
- return runtime·mallocgc(n, 0, 0);
-}
-
-#pragma textflag NOSPLIT
-func new(typ *Type) (ret *uint8) {
- ret = runtime·mallocgc(typ->size, (uintptr)typ | TypeInfo_SingleObject, typ->kind&KindNoPointers ? FlagNoScan : 0);
-}
-
-static void*
-cnew(Type *typ, intgo n, int32 objtyp)
-{
- if((objtyp&(PtrSize-1)) != objtyp)
- runtime·throw("runtime: invalid objtyp");
- if(n < 0 || (typ->size > 0 && n > MaxMem/typ->size))
- runtime·panicstring("runtime: allocation size out of range");
- return runtime·mallocgc(typ->size*n, (uintptr)typ | objtyp, typ->kind&KindNoPointers ? FlagNoScan : 0);
-}
-
-// same as runtime·new, but callable from C
-void*
-runtime·cnew(Type *typ)
-{
- return cnew(typ, 1, TypeInfo_SingleObject);
-}
-
-void*
-runtime·cnewarray(Type *typ, intgo n)
-{
- return cnew(typ, n, TypeInfo_Array);
-}
-
-func GC() {
- runtime·gc(2); // force GC and do eager sweep
-}
-
-func SetFinalizer(obj Eface, finalizer Eface) {
- byte *base;
- uintptr size;
- FuncType *ft;
- int32 i;
- uintptr nret;
- Type *t;
- Type *fint;
- PtrType *ot;
- Iface iface;
-
- if(obj.type == nil) {
- runtime·printf("runtime.SetFinalizer: first argument is nil interface\n");
- goto throw;
- }
- if(obj.type->kind != KindPtr) {
- runtime·printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *obj.type->string);
- goto throw;
- }
- ot = (PtrType*)obj.type;
- // As an implementation detail we do not run finalizers for zero-sized objects,
- // because we use &runtime·zerobase for all such allocations.
- if(ot->elem != nil && ot->elem->size == 0)
- return;
- // The following check is required for cases when a user passes a pointer to composite literal,
- // but compiler makes it a pointer to global. For example:
- // var Foo = &Object{}
- // func main() {
- // runtime.SetFinalizer(Foo, nil)
- // }
- // See issue 7656.
- if((byte*)obj.data < runtime·mheap.arena_start || runtime·mheap.arena_used <= (byte*)obj.data)
- return;
- if(!runtime·mlookup(obj.data, &base, &size, nil) || obj.data != base) {
- // As an implementation detail we allow to set finalizers for an inner byte
- // of an object if it could come from tiny alloc (see mallocgc for details).
- if(ot->elem == nil || (ot->elem->kind&KindNoPointers) == 0 || ot->elem->size >= TinySize) {
- runtime·printf("runtime.SetFinalizer: pointer not at beginning of allocated block (%p)\n", obj.data);
- goto throw;
- }
- }
- if(finalizer.type != nil) {
- runtime·createfing();
- if(finalizer.type->kind != KindFunc)
- goto badfunc;
- ft = (FuncType*)finalizer.type;
- if(ft->dotdotdot || ft->in.len != 1)
- goto badfunc;
- fint = *(Type**)ft->in.array;
- if(fint == obj.type) {
- // ok - same type
- } else if(fint->kind == KindPtr && (fint->x == nil || fint->x->name == nil || obj.type->x == nil || obj.type->x->name == nil) && ((PtrType*)fint)->elem == ((PtrType*)obj.type)->elem) {
- // ok - not same type, but both pointers,
- // one or the other is unnamed, and same element type, so assignable.
- } else if(fint->kind == KindInterface && ((InterfaceType*)fint)->mhdr.len == 0) {
- // ok - satisfies empty interface
- } else if(fint->kind == KindInterface && runtime·ifaceE2I2((InterfaceType*)fint, obj, &iface)) {
- // ok - satisfies non-empty interface
- } else
- goto badfunc;
-
- // compute size needed for return parameters
- nret = 0;
- for(i=0; i<ft->out.len; i++) {
- t = ((Type**)ft->out.array)[i];
- nret = ROUND(nret, t->align) + t->size;
- }
- nret = ROUND(nret, sizeof(void*));
- ot = (PtrType*)obj.type;
- if(!runtime·addfinalizer(obj.data, finalizer.data, nret, fint, ot)) {
- runtime·printf("runtime.SetFinalizer: finalizer already set\n");
- goto throw;
- }
- } else {
- // NOTE: asking to remove a finalizer when there currently isn't one set is OK.
- runtime·removefinalizer(obj.data);
- }
- return;
-
-badfunc:
- runtime·printf("runtime.SetFinalizer: cannot pass %S to finalizer %S\n", *obj.type->string, *finalizer.type->string);
-throw:
- runtime·throw("runtime.SetFinalizer");
-}
diff --git a/src/pkg/runtime/malloc1.go b/src/pkg/runtime/malloc1.go
deleted file mode 100644
index da92f4c2f..000000000
--- a/src/pkg/runtime/malloc1.go
+++ /dev/null
@@ -1,26 +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 ignore
-
-// trivial malloc test
-
-package main
-
-import (
- "flag"
- "fmt"
- "runtime"
-)
-
-var chatty = flag.Bool("v", false, "chatty")
-
-func main() {
- memstats := new(runtime.MemStats)
- runtime.Free(runtime.Alloc(1))
- runtime.ReadMemStats(memstats)
- if *chatty {
- fmt.Printf("%+v %v\n", memstats, uint64(0))
- }
-}
diff --git a/src/pkg/runtime/mallocrand.go b/src/pkg/runtime/mallocrand.go
deleted file mode 100644
index f1bcb89cf..000000000
--- a/src/pkg/runtime/mallocrand.go
+++ /dev/null
@@ -1,93 +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 ignore
-
-// Random malloc test.
-
-package main
-
-import (
- "flag"
- "math/rand"
- "runtime"
- "unsafe"
-)
-
-var chatty = flag.Bool("v", false, "chatty")
-
-var footprint uint64
-var allocated uint64
-
-func bigger() {
- memstats := new(runtime.MemStats)
- runtime.ReadMemStats(memstats)
- if f := memstats.Sys; footprint < f {
- footprint = f
- if *chatty {
- println("Footprint", footprint, " for ", allocated)
- }
- if footprint > 1e9 {
- println("too big")
- panic("fail")
- }
- }
-}
-
-// Prime the data structures by allocating one of
-// each block in order. After this, there should be
-// little reason to ask for more memory from the OS.
-func prime() {
- for i := 0; i < 16; i++ {
- b := runtime.Alloc(1 << uint(i))
- runtime.Free(b)
- }
- for i := uintptr(0); i < 256; i++ {
- b := runtime.Alloc(i << 12)
- runtime.Free(b)
- }
-}
-
-func memset(b *byte, c byte, n uintptr) {
- np := uintptr(n)
- for i := uintptr(0); i < np; i++ {
- *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(b)) + i)) = c
- }
-}
-
-func main() {
- flag.Parse()
- // prime()
- var blocks [1]struct {
- base *byte
- siz uintptr
- }
- for i := 0; i < 1<<10; i++ {
- if i%(1<<10) == 0 && *chatty {
- println(i)
- }
- b := rand.Int() % len(blocks)
- if blocks[b].base != nil {
- // println("Free", blocks[b].siz, blocks[b].base)
- runtime.Free(blocks[b].base)
- blocks[b].base = nil
- allocated -= uint64(blocks[b].siz)
- continue
- }
- siz := uintptr(rand.Int() >> (11 + rand.Uint32()%20))
- base := runtime.Alloc(siz)
- // ptr := uintptr(syscall.BytePtr(base))+uintptr(siz/2)
- // obj, size, ref, ok := allocator.find(ptr)
- // if obj != base || *ref != 0 || !ok {
- // println("find", siz, obj, ref, ok)
- // panic("fail")
- // }
- blocks[b].base = base
- blocks[b].siz = siz
- allocated += uint64(siz)
- // println("Alloc", siz, base)
- memset(base, 0xbb, siz)
- bigger()
- }
-}
diff --git a/src/pkg/runtime/mallocrep.go b/src/pkg/runtime/mallocrep.go
deleted file mode 100644
index 03ee71edb..000000000
--- a/src/pkg/runtime/mallocrep.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.
-
-// Repeated malloc test.
-
-// +build ignore
-
-package main
-
-import (
- "flag"
- "runtime"
-)
-
-var chatty = flag.Bool("v", false, "chatty")
-
-var oldsys uint64
-var memstats runtime.MemStats
-
-func bigger() {
- st := &memstats
- runtime.ReadMemStats(st)
- if oldsys < st.Sys {
- oldsys = st.Sys
- if *chatty {
- println(st.Sys, " system bytes for ", st.Alloc, " Go bytes")
- }
- if st.Sys > 1e9 {
- println("too big")
- panic("fail")
- }
- }
-}
-
-func main() {
- runtime.GC() // clean up garbage from init
- runtime.ReadMemStats(&memstats) // first call can do some allocations
- runtime.MemProfileRate = 0 // disable profiler
- stacks := memstats.Alloc // ignore stacks
- flag.Parse()
- for i := 0; i < 1<<7; i++ {
- for j := 1; j <= 1<<22; j <<= 1 {
- if i == 0 && *chatty {
- println("First alloc:", j)
- }
- if a := memstats.Alloc - stacks; a != 0 {
- println("no allocations but stats report", a, "bytes allocated")
- panic("fail")
- }
- b := runtime.Alloc(uintptr(j))
- runtime.ReadMemStats(&memstats)
- during := memstats.Alloc - stacks
- runtime.Free(b)
- runtime.ReadMemStats(&memstats)
- if a := memstats.Alloc - stacks; a != 0 {
- println("allocated ", j, ": wrong stats: during=", during, " after=", a, " (want 0)")
- panic("fail")
- }
- bigger()
- }
- if i%(1<<10) == 0 && *chatty {
- println(i)
- }
- if i == 0 {
- if *chatty {
- println("Primed", i)
- }
- // runtime.frozen = true
- }
- }
-}
diff --git a/src/pkg/runtime/mallocrep1.go b/src/pkg/runtime/mallocrep1.go
deleted file mode 100644
index bc33e3a6b..000000000
--- a/src/pkg/runtime/mallocrep1.go
+++ /dev/null
@@ -1,144 +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 ignore
-
-// Repeated malloc test.
-
-package main
-
-import (
- "flag"
- "fmt"
- "runtime"
- "strconv"
-)
-
-var chatty = flag.Bool("v", false, "chatty")
-var reverse = flag.Bool("r", false, "reverse")
-var longtest = flag.Bool("l", false, "long test")
-
-var b []*byte
-var stats = new(runtime.MemStats)
-
-func OkAmount(size, n uintptr) bool {
- if n < size {
- return false
- }
- if size < 16*8 {
- if n > size+16 {
- return false
- }
- } else {
- if n > size*9/8 {
- return false
- }
- }
- return true
-}
-
-func AllocAndFree(size, count int) {
- defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
- if *chatty {
- fmt.Printf("size=%d count=%d ...\n", size, count)
- }
- runtime.ReadMemStats(stats)
- n1 := stats.Alloc
- for i := 0; i < count; i++ {
- b[i] = runtime.Alloc(uintptr(size))
- base, n := runtime.Lookup(b[i])
- if base != b[i] || !OkAmount(uintptr(size), n) {
- println("lookup failed: got", base, n, "for", b[i])
- panic("fail")
- }
- runtime.ReadMemStats(stats)
- if stats.Sys > 1e9 {
- println("too much memory allocated")
- panic("fail")
- }
- }
- runtime.ReadMemStats(stats)
- n2 := stats.Alloc
- if *chatty {
- fmt.Printf("size=%d count=%d stats=%+v\n", size, count, *stats)
- }
- n3 := stats.Alloc
- for j := 0; j < count; j++ {
- i := j
- if *reverse {
- i = count - 1 - j
- }
- alloc := uintptr(stats.Alloc)
- base, n := runtime.Lookup(b[i])
- if base != b[i] || !OkAmount(uintptr(size), n) {
- println("lookup failed: got", base, n, "for", b[i])
- panic("fail")
- }
- runtime.Free(b[i])
- runtime.ReadMemStats(stats)
- if stats.Alloc != uint64(alloc-n) {
- println("free alloc got", stats.Alloc, "expected", alloc-n, "after free of", n)
- panic("fail")
- }
- if stats.Sys > 1e9 {
- println("too much memory allocated")
- panic("fail")
- }
- }
- runtime.ReadMemStats(stats)
- n4 := stats.Alloc
-
- if *chatty {
- fmt.Printf("size=%d count=%d stats=%+v\n", size, count, *stats)
- }
- if n2-n1 != n3-n4 {
- println("wrong alloc count: ", n2-n1, n3-n4)
- panic("fail")
- }
-}
-
-func atoi(s string) int {
- i, _ := strconv.Atoi(s)
- return i
-}
-
-func main() {
- runtime.MemProfileRate = 0 // disable profiler
- flag.Parse()
- b = make([]*byte, 10000)
- if flag.NArg() > 0 {
- AllocAndFree(atoi(flag.Arg(0)), atoi(flag.Arg(1)))
- return
- }
- maxb := 1 << 22
- if !*longtest {
- maxb = 1 << 19
- }
- for j := 1; j <= maxb; j <<= 1 {
- n := len(b)
- max := uintptr(1 << 28)
- if !*longtest {
- max = uintptr(maxb)
- }
- if uintptr(j)*uintptr(n) > max {
- n = int(max / uintptr(j))
- }
- if n < 10 {
- n = 10
- }
- for m := 1; m <= n; {
- AllocAndFree(j, m)
- if m == n {
- break
- }
- m = 5 * m / 4
- if m < 4 {
- m++
- }
- if m > n {
- m = n
- }
- }
- }
-}
diff --git a/src/pkg/runtime/memclr_plan9_amd64.s b/src/pkg/runtime/memclr_plan9_amd64.s
deleted file mode 100644
index 6b33054f5..000000000
--- a/src/pkg/runtime/memclr_plan9_amd64.s
+++ /dev/null
@@ -1,48 +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 "../../cmd/ld/textflag.h"
-
-// void runtime·memclr(void*, uintptr)
-TEXT runtime·memclr(SB), NOSPLIT, $0-16
- MOVQ ptr+0(FP), DI
- MOVQ n+8(FP), BX
- XORQ AX, AX
-
-clr_tail:
- TESTQ BX, BX
- JEQ clr_0
- CMPQ BX, $2
- JBE clr_1or2
- CMPQ BX, $4
- JBE clr_3or4
- CMPQ BX, $8
- JBE clr_5through8
- CMPQ BX, $16
- JBE clr_9through16
- MOVQ BX, CX
- SHRQ $2, CX
- REP
- STOSQ
- ANDQ $3, BX
- JNE clr_tail
- RET
-
-clr_1or2:
- MOVB AX, (DI)
- MOVB AX, -1(DI)(BX*1)
-clr_0:
- RET
-clr_3or4:
- MOVW AX, (DI)
- MOVW AX, -2(DI)(BX*1)
- RET
-clr_5through8:
- MOVL AX, (DI)
- MOVL AX, -4(DI)(BX*1)
- RET
-clr_9through16:
- MOVQ AX, (DI)
- MOVQ AX, -8(DI)(BX*1)
- RET
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
deleted file mode 100644
index 392da535b..000000000
--- a/src/pkg/runtime/mgc0.c
+++ /dev/null
@@ -1,2892 +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.
-
-// Garbage collector (GC).
-//
-// GC is:
-// - mark&sweep
-// - mostly precise (with the exception of some C-allocated objects, assembly frames/arguments, etc)
-// - parallel (up to MaxGcproc threads)
-// - partially concurrent (mark is stop-the-world, while sweep is concurrent)
-// - non-moving/non-compacting
-// - full (non-partial)
-//
-// GC rate.
-// Next GC is after we've allocated an extra amount of memory proportional to
-// the amount already in use. The proportion is controlled by GOGC environment variable
-// (100 by default). If GOGC=100 and we're using 4M, we'll GC again when we get to 8M
-// (this mark is tracked in next_gc variable). This keeps the GC cost in linear
-// proportion to the allocation cost. Adjusting GOGC just changes the linear constant
-// (and also the amount of extra memory used).
-//
-// Concurrent sweep.
-// The sweep phase proceeds concurrently with normal program execution.
-// The heap is swept span-by-span both lazily (when a goroutine needs another span)
-// and concurrently in a background goroutine (this helps programs that are not CPU bound).
-// However, at the end of the stop-the-world GC phase we don't know the size of the live heap,
-// and so next_gc calculation is tricky and happens as follows.
-// At the end of the stop-the-world phase next_gc is conservatively set based on total
-// heap size; all spans are marked as "needs sweeping".
-// Whenever a span is swept, next_gc is decremented by GOGC*newly_freed_memory.
-// The background sweeper goroutine simply sweeps spans one-by-one bringing next_gc
-// closer to the target value. However, this is not enough to avoid over-allocating memory.
-// Consider that a goroutine wants to allocate a new span for a large object and
-// there are no free swept spans, but there are small-object unswept spans.
-// If the goroutine naively allocates a new span, it can surpass the yet-unknown
-// target next_gc value. In order to prevent such cases (1) when a goroutine needs
-// to allocate a new small-object span, it sweeps small-object spans for the same
-// object size until it frees at least one object; (2) when a goroutine needs to
-// allocate large-object span from heap, it sweeps spans until it frees at least
-// that many pages into heap. Together these two measures ensure that we don't surpass
-// target next_gc value by a large margin. There is an exception: if a goroutine sweeps
-// and frees two nonadjacent one-page spans to the heap, it will allocate a new two-page span,
-// but there can still be other one-page unswept spans which could be combined into a two-page span.
-// It's critical to ensure that no operations proceed on unswept spans (that would corrupt
-// mark bits in GC bitmap). During GC all mcaches are flushed into the central cache,
-// so they are empty. When a goroutine grabs a new span into mcache, it sweeps it.
-// When a goroutine explicitly frees an object or sets a finalizer, it ensures that
-// the span is swept (either by sweeping it, or by waiting for the concurrent sweep to finish).
-// The finalizer goroutine is kicked off only when all spans are swept.
-// When the next GC starts, it sweeps all not-yet-swept spans (if any).
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "stack.h"
-#include "mgc0.h"
-#include "chan.h"
-#include "race.h"
-#include "type.h"
-#include "typekind.h"
-#include "funcdata.h"
-#include "../../cmd/ld/textflag.h"
-
-enum {
- Debug = 0,
- CollectStats = 0,
- ConcurrentSweep = 1,
-
- WorkbufSize = 16*1024,
- FinBlockSize = 4*1024,
-
- handoffThreshold = 4,
- IntermediateBufferCapacity = 64,
-
- // Bits in type information
- PRECISE = 1,
- LOOP = 2,
- PC_BITS = PRECISE | LOOP,
-
- RootData = 0,
- RootBss = 1,
- RootFinalizers = 2,
- RootSpanTypes = 3,
- RootFlushCaches = 4,
- RootCount = 5,
-};
-
-#define GcpercentUnknown (-2)
-
-// Initialized from $GOGC. GOGC=off means no gc.
-static int32 gcpercent = GcpercentUnknown;
-
-static FuncVal* poolcleanup;
-
-void
-sync·runtime_registerPoolCleanup(FuncVal *f)
-{
- poolcleanup = f;
-}
-
-static void
-clearpools(void)
-{
- P *p, **pp;
- MCache *c;
- int32 i;
-
- // clear sync.Pool's
- if(poolcleanup != nil)
- reflect·call(poolcleanup, nil, 0, 0);
-
- for(pp=runtime·allp; p=*pp; pp++) {
- // clear tinyalloc pool
- c = p->mcache;
- if(c != nil) {
- c->tiny = nil;
- c->tinysize = 0;
- }
- // clear defer pools
- for(i=0; i<nelem(p->deferpool); i++)
- p->deferpool[i] = nil;
- }
-}
-
-// Holding worldsema grants an M the right to try to stop the world.
-// The procedure is:
-//
-// runtime·semacquire(&runtime·worldsema);
-// m->gcing = 1;
-// runtime·stoptheworld();
-//
-// ... do stuff ...
-//
-// m->gcing = 0;
-// runtime·semrelease(&runtime·worldsema);
-// runtime·starttheworld();
-//
-uint32 runtime·worldsema = 1;
-
-typedef struct Obj Obj;
-struct Obj
-{
- byte *p; // data pointer
- uintptr n; // size of data in bytes
- uintptr ti; // type info
-};
-
-typedef struct Workbuf Workbuf;
-struct Workbuf
-{
-#define SIZE (WorkbufSize-sizeof(LFNode)-sizeof(uintptr))
- LFNode node; // must be first
- uintptr nobj;
- Obj obj[SIZE/sizeof(Obj) - 1];
- uint8 _padding[SIZE%sizeof(Obj) + sizeof(Obj)];
-#undef SIZE
-};
-
-typedef struct Finalizer Finalizer;
-struct Finalizer
-{
- FuncVal *fn;
- void *arg;
- uintptr nret;
- Type *fint;
- PtrType *ot;
-};
-
-typedef struct FinBlock FinBlock;
-struct FinBlock
-{
- FinBlock *alllink;
- FinBlock *next;
- int32 cnt;
- int32 cap;
- Finalizer fin[1];
-};
-
-extern byte data[];
-extern byte edata[];
-extern byte bss[];
-extern byte ebss[];
-
-extern byte gcdata[];
-extern byte gcbss[];
-
-static Lock finlock; // protects the following variables
-static FinBlock *finq; // list of finalizers that are to be executed
-static FinBlock *finc; // cache of free blocks
-static FinBlock *allfin; // list of all blocks
-bool runtime·fingwait;
-bool runtime·fingwake;
-
-static Lock gclock;
-static G* fing;
-
-static void runfinq(void);
-static void bgsweep(void);
-static Workbuf* getempty(Workbuf*);
-static Workbuf* getfull(Workbuf*);
-static void putempty(Workbuf*);
-static Workbuf* handoff(Workbuf*);
-static void gchelperstart(void);
-static void flushallmcaches(void);
-static bool scanframe(Stkframe *frame, void *wbufp);
-static void addstackroots(G *gp, Workbuf **wbufp);
-
-static FuncVal runfinqv = {runfinq};
-static FuncVal bgsweepv = {bgsweep};
-
-static struct {
- uint64 full; // lock-free list of full blocks
- uint64 empty; // lock-free list of empty blocks
- byte pad0[CacheLineSize]; // prevents false-sharing between full/empty and nproc/nwait
- uint32 nproc;
- int64 tstart;
- volatile uint32 nwait;
- volatile uint32 ndone;
- Note alldone;
- ParFor *markfor;
-
- Lock;
- byte *chunk;
- uintptr nchunk;
-} work;
-
-enum {
- GC_DEFAULT_PTR = GC_NUM_INSTR,
- GC_CHAN,
-
- GC_NUM_INSTR2
-};
-
-static struct {
- struct {
- uint64 sum;
- uint64 cnt;
- } ptr;
- uint64 nbytes;
- struct {
- uint64 sum;
- uint64 cnt;
- uint64 notype;
- uint64 typelookup;
- } obj;
- uint64 rescan;
- uint64 rescanbytes;
- uint64 instr[GC_NUM_INSTR2];
- uint64 putempty;
- uint64 getfull;
- struct {
- uint64 foundbit;
- uint64 foundword;
- uint64 foundspan;
- } flushptrbuf;
- struct {
- uint64 foundbit;
- uint64 foundword;
- uint64 foundspan;
- } markonly;
- uint32 nbgsweep;
- uint32 npausesweep;
-} gcstats;
-
-// markonly marks an object. It returns true if the object
-// has been marked by this function, false otherwise.
-// This function doesn't append the object to any buffer.
-static bool
-markonly(void *obj)
-{
- byte *p;
- uintptr *bitp, bits, shift, x, xbits, off, j;
- MSpan *s;
- PageID k;
-
- // Words outside the arena cannot be pointers.
- if(obj < runtime·mheap.arena_start || obj >= runtime·mheap.arena_used)
- return false;
-
- // obj may be a pointer to a live object.
- // Try to find the beginning of the object.
-
- // Round down to word boundary.
- obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
-
- // Find bits for this word.
- off = (uintptr*)obj - (uintptr*)runtime·mheap.arena_start;
- bitp = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- xbits = *bitp;
- bits = xbits >> shift;
-
- // Pointing at the beginning of a block?
- if((bits & (bitAllocated|bitBlockBoundary)) != 0) {
- if(CollectStats)
- runtime·xadd64(&gcstats.markonly.foundbit, 1);
- goto found;
- }
-
- // Pointing just past the beginning?
- // Scan backward a little to find a block boundary.
- for(j=shift; j-->0; ) {
- if(((xbits>>j) & (bitAllocated|bitBlockBoundary)) != 0) {
- shift = j;
- bits = xbits>>shift;
- if(CollectStats)
- runtime·xadd64(&gcstats.markonly.foundword, 1);
- goto found;
- }
- }
-
- // Otherwise consult span table to find beginning.
- // (Manually inlined copy of MHeap_LookupMaybe.)
- k = (uintptr)obj>>PageShift;
- x = k;
- x -= (uintptr)runtime·mheap.arena_start>>PageShift;
- s = runtime·mheap.spans[x];
- if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse)
- return false;
- p = (byte*)((uintptr)s->start<<PageShift);
- if(s->sizeclass == 0) {
- obj = p;
- } else {
- uintptr size = s->elemsize;
- int32 i = ((byte*)obj - p)/size;
- obj = p+i*size;
- }
-
- // Now that we know the object header, reload bits.
- off = (uintptr*)obj - (uintptr*)runtime·mheap.arena_start;
- bitp = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- xbits = *bitp;
- bits = xbits >> shift;
- if(CollectStats)
- runtime·xadd64(&gcstats.markonly.foundspan, 1);
-
-found:
- // Now we have bits, bitp, and shift correct for
- // obj pointing at the base of the object.
- // Only care about allocated and not marked.
- if((bits & (bitAllocated|bitMarked)) != bitAllocated)
- return false;
- if(work.nproc == 1)
- *bitp |= bitMarked<<shift;
- else {
- for(;;) {
- x = *bitp;
- if(x & (bitMarked<<shift))
- return false;
- if(runtime·casp((void**)bitp, (void*)x, (void*)(x|(bitMarked<<shift))))
- break;
- }
- }
-
- // The object is now marked
- return true;
-}
-
-// PtrTarget is a structure used by intermediate buffers.
-// The intermediate buffers hold GC data before it
-// is moved/flushed to the work buffer (Workbuf).
-// The size of an intermediate buffer is very small,
-// such as 32 or 64 elements.
-typedef struct PtrTarget PtrTarget;
-struct PtrTarget
-{
- void *p;
- uintptr ti;
-};
-
-typedef struct Scanbuf Scanbuf;
-struct Scanbuf
-{
- struct {
- PtrTarget *begin;
- PtrTarget *end;
- PtrTarget *pos;
- } ptr;
- struct {
- Obj *begin;
- Obj *end;
- Obj *pos;
- } obj;
- Workbuf *wbuf;
- Obj *wp;
- uintptr nobj;
-};
-
-typedef struct BufferList BufferList;
-struct BufferList
-{
- PtrTarget ptrtarget[IntermediateBufferCapacity];
- Obj obj[IntermediateBufferCapacity];
- uint32 busy;
- byte pad[CacheLineSize];
-};
-#pragma dataflag NOPTR
-static BufferList bufferList[MaxGcproc];
-
-static Type *itabtype;
-
-static void enqueue(Obj obj, Workbuf **_wbuf, Obj **_wp, uintptr *_nobj);
-
-// flushptrbuf moves data from the PtrTarget buffer to the work buffer.
-// The PtrTarget buffer contains blocks irrespective of whether the blocks have been marked or scanned,
-// while the work buffer contains blocks which have been marked
-// and are prepared to be scanned by the garbage collector.
-//
-// _wp, _wbuf, _nobj are input/output parameters and are specifying the work buffer.
-//
-// A simplified drawing explaining how the todo-list moves from a structure to another:
-//
-// scanblock
-// (find pointers)
-// Obj ------> PtrTarget (pointer targets)
-// ↑ |
-// | |
-// `----------'
-// flushptrbuf
-// (find block start, mark and enqueue)
-static void
-flushptrbuf(Scanbuf *sbuf)
-{
- byte *p, *arena_start, *obj;
- uintptr size, *bitp, bits, shift, j, x, xbits, off, nobj, ti, n;
- MSpan *s;
- PageID k;
- Obj *wp;
- Workbuf *wbuf;
- PtrTarget *ptrbuf;
- PtrTarget *ptrbuf_end;
-
- arena_start = runtime·mheap.arena_start;
-
- wp = sbuf->wp;
- wbuf = sbuf->wbuf;
- nobj = sbuf->nobj;
-
- ptrbuf = sbuf->ptr.begin;
- ptrbuf_end = sbuf->ptr.pos;
- n = ptrbuf_end - sbuf->ptr.begin;
- sbuf->ptr.pos = sbuf->ptr.begin;
-
- if(CollectStats) {
- runtime·xadd64(&gcstats.ptr.sum, n);
- runtime·xadd64(&gcstats.ptr.cnt, 1);
- }
-
- // If buffer is nearly full, get a new one.
- if(wbuf == nil || nobj+n >= nelem(wbuf->obj)) {
- if(wbuf != nil)
- wbuf->nobj = nobj;
- wbuf = getempty(wbuf);
- wp = wbuf->obj;
- nobj = 0;
-
- if(n >= nelem(wbuf->obj))
- runtime·throw("ptrbuf has to be smaller than WorkBuf");
- }
-
- while(ptrbuf < ptrbuf_end) {
- obj = ptrbuf->p;
- ti = ptrbuf->ti;
- ptrbuf++;
-
- // obj belongs to interval [mheap.arena_start, mheap.arena_used).
- if(Debug > 1) {
- if(obj < runtime·mheap.arena_start || obj >= runtime·mheap.arena_used)
- runtime·throw("object is outside of mheap");
- }
-
- // obj may be a pointer to a live object.
- // Try to find the beginning of the object.
-
- // Round down to word boundary.
- if(((uintptr)obj & ((uintptr)PtrSize-1)) != 0) {
- obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
- ti = 0;
- }
-
- // Find bits for this word.
- off = (uintptr*)obj - (uintptr*)arena_start;
- bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- xbits = *bitp;
- bits = xbits >> shift;
-
- // Pointing at the beginning of a block?
- if((bits & (bitAllocated|bitBlockBoundary)) != 0) {
- if(CollectStats)
- runtime·xadd64(&gcstats.flushptrbuf.foundbit, 1);
- goto found;
- }
-
- ti = 0;
-
- // Pointing just past the beginning?
- // Scan backward a little to find a block boundary.
- for(j=shift; j-->0; ) {
- if(((xbits>>j) & (bitAllocated|bitBlockBoundary)) != 0) {
- obj = (byte*)obj - (shift-j)*PtrSize;
- shift = j;
- bits = xbits>>shift;
- if(CollectStats)
- runtime·xadd64(&gcstats.flushptrbuf.foundword, 1);
- goto found;
- }
- }
-
- // Otherwise consult span table to find beginning.
- // (Manually inlined copy of MHeap_LookupMaybe.)
- k = (uintptr)obj>>PageShift;
- x = k;
- x -= (uintptr)arena_start>>PageShift;
- s = runtime·mheap.spans[x];
- if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse)
- continue;
- p = (byte*)((uintptr)s->start<<PageShift);
- if(s->sizeclass == 0) {
- obj = p;
- } else {
- size = s->elemsize;
- int32 i = ((byte*)obj - p)/size;
- obj = p+i*size;
- }
-
- // Now that we know the object header, reload bits.
- off = (uintptr*)obj - (uintptr*)arena_start;
- bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- xbits = *bitp;
- bits = xbits >> shift;
- if(CollectStats)
- runtime·xadd64(&gcstats.flushptrbuf.foundspan, 1);
-
- found:
- // Now we have bits, bitp, and shift correct for
- // obj pointing at the base of the object.
- // Only care about allocated and not marked.
- if((bits & (bitAllocated|bitMarked)) != bitAllocated)
- continue;
- if(work.nproc == 1)
- *bitp |= bitMarked<<shift;
- else {
- for(;;) {
- x = *bitp;
- if(x & (bitMarked<<shift))
- goto continue_obj;
- if(runtime·casp((void**)bitp, (void*)x, (void*)(x|(bitMarked<<shift))))
- break;
- }
- }
-
- // If object has no pointers, don't need to scan further.
- if((bits & bitScan) == 0)
- continue;
-
- // Ask span about size class.
- // (Manually inlined copy of MHeap_Lookup.)
- x = (uintptr)obj >> PageShift;
- x -= (uintptr)arena_start>>PageShift;
- s = runtime·mheap.spans[x];
-
- PREFETCH(obj);
-
- *wp = (Obj){obj, s->elemsize, ti};
- wp++;
- nobj++;
- continue_obj:;
- }
-
- // If another proc wants a pointer, give it some.
- if(work.nwait > 0 && nobj > handoffThreshold && work.full == 0) {
- wbuf->nobj = nobj;
- wbuf = handoff(wbuf);
- nobj = wbuf->nobj;
- wp = wbuf->obj + nobj;
- }
-
- sbuf->wp = wp;
- sbuf->wbuf = wbuf;
- sbuf->nobj = nobj;
-}
-
-static void
-flushobjbuf(Scanbuf *sbuf)
-{
- uintptr nobj, off;
- Obj *wp, obj;
- Workbuf *wbuf;
- Obj *objbuf;
- Obj *objbuf_end;
-
- wp = sbuf->wp;
- wbuf = sbuf->wbuf;
- nobj = sbuf->nobj;
-
- objbuf = sbuf->obj.begin;
- objbuf_end = sbuf->obj.pos;
- sbuf->obj.pos = sbuf->obj.begin;
-
- while(objbuf < objbuf_end) {
- obj = *objbuf++;
-
- // Align obj.b to a word boundary.
- off = (uintptr)obj.p & (PtrSize-1);
- if(off != 0) {
- obj.p += PtrSize - off;
- obj.n -= PtrSize - off;
- obj.ti = 0;
- }
-
- if(obj.p == nil || obj.n == 0)
- continue;
-
- // If buffer is full, get a new one.
- if(wbuf == nil || nobj >= nelem(wbuf->obj)) {
- if(wbuf != nil)
- wbuf->nobj = nobj;
- wbuf = getempty(wbuf);
- wp = wbuf->obj;
- nobj = 0;
- }
-
- *wp = obj;
- wp++;
- nobj++;
- }
-
- // If another proc wants a pointer, give it some.
- if(work.nwait > 0 && nobj > handoffThreshold && work.full == 0) {
- wbuf->nobj = nobj;
- wbuf = handoff(wbuf);
- nobj = wbuf->nobj;
- wp = wbuf->obj + nobj;
- }
-
- sbuf->wp = wp;
- sbuf->wbuf = wbuf;
- sbuf->nobj = nobj;
-}
-
-// Program that scans the whole block and treats every block element as a potential pointer
-static uintptr defaultProg[2] = {PtrSize, GC_DEFAULT_PTR};
-
-// Hchan program
-static uintptr chanProg[2] = {0, GC_CHAN};
-
-// Local variables of a program fragment or loop
-typedef struct Frame Frame;
-struct Frame {
- uintptr count, elemsize, b;
- uintptr *loop_or_ret;
-};
-
-// Sanity check for the derived type info objti.
-static void
-checkptr(void *obj, uintptr objti)
-{
- uintptr *pc1, *pc2, type, tisize, i, j, x;
- byte *objstart;
- Type *t;
- MSpan *s;
-
- if(!Debug)
- runtime·throw("checkptr is debug only");
-
- if(obj < runtime·mheap.arena_start || obj >= runtime·mheap.arena_used)
- return;
- type = runtime·gettype(obj);
- t = (Type*)(type & ~(uintptr)(PtrSize-1));
- if(t == nil)
- return;
- x = (uintptr)obj >> PageShift;
- x -= (uintptr)(runtime·mheap.arena_start)>>PageShift;
- s = runtime·mheap.spans[x];
- objstart = (byte*)((uintptr)s->start<<PageShift);
- if(s->sizeclass != 0) {
- i = ((byte*)obj - objstart)/s->elemsize;
- objstart += i*s->elemsize;
- }
- tisize = *(uintptr*)objti;
- // Sanity check for object size: it should fit into the memory block.
- if((byte*)obj + tisize > objstart + s->elemsize) {
- runtime·printf("object of type '%S' at %p/%p does not fit in block %p/%p\n",
- *t->string, obj, tisize, objstart, s->elemsize);
- runtime·throw("invalid gc type info");
- }
- if(obj != objstart)
- return;
- // If obj points to the beginning of the memory block,
- // check type info as well.
- if(t->string == nil ||
- // Gob allocates unsafe pointers for indirection.
- (runtime·strcmp(t->string->str, (byte*)"unsafe.Pointer") &&
- // Runtime and gc think differently about closures.
- runtime·strstr(t->string->str, (byte*)"struct { F uintptr") != t->string->str)) {
- pc1 = (uintptr*)objti;
- pc2 = (uintptr*)t->gc;
- // A simple best-effort check until first GC_END.
- for(j = 1; pc1[j] != GC_END && pc2[j] != GC_END; j++) {
- if(pc1[j] != pc2[j]) {
- runtime·printf("invalid gc type info for '%s', type info %p [%d]=%p, block info %p [%d]=%p\n",
- t->string ? (int8*)t->string->str : (int8*)"?", pc1, (int32)j, pc1[j], pc2, (int32)j, pc2[j]);
- runtime·throw("invalid gc type info");
- }
- }
- }
-}
-
-// scanblock scans a block of n bytes starting at pointer b for references
-// to other objects, scanning any it finds recursively until there are no
-// unscanned objects left. Instead of using an explicit recursion, it keeps
-// a work list in the Workbuf* structures and loops in the main function
-// body. Keeping an explicit work list is easier on the stack allocator and
-// more efficient.
-static void
-scanblock(Workbuf *wbuf, bool keepworking)
-{
- byte *b, *arena_start, *arena_used;
- uintptr n, i, end_b, elemsize, size, ti, objti, count, type, nobj;
- uintptr *pc, precise_type, nominal_size;
- uintptr *chan_ret, chancap;
- void *obj;
- Type *t, *et;
- Slice *sliceptr;
- String *stringptr;
- Frame *stack_ptr, stack_top, stack[GC_STACK_CAPACITY+4];
- BufferList *scanbuffers;
- Scanbuf sbuf;
- Eface *eface;
- Iface *iface;
- Hchan *chan;
- ChanType *chantype;
- Obj *wp;
-
- if(sizeof(Workbuf) % WorkbufSize != 0)
- runtime·throw("scanblock: size of Workbuf is suboptimal");
-
- // Memory arena parameters.
- arena_start = runtime·mheap.arena_start;
- arena_used = runtime·mheap.arena_used;
-
- stack_ptr = stack+nelem(stack)-1;
-
- precise_type = false;
- nominal_size = 0;
-
- if(wbuf) {
- nobj = wbuf->nobj;
- wp = &wbuf->obj[nobj];
- } else {
- nobj = 0;
- wp = nil;
- }
-
- // Initialize sbuf
- scanbuffers = &bufferList[m->helpgc];
-
- sbuf.ptr.begin = sbuf.ptr.pos = &scanbuffers->ptrtarget[0];
- sbuf.ptr.end = sbuf.ptr.begin + nelem(scanbuffers->ptrtarget);
-
- sbuf.obj.begin = sbuf.obj.pos = &scanbuffers->obj[0];
- sbuf.obj.end = sbuf.obj.begin + nelem(scanbuffers->obj);
-
- sbuf.wbuf = wbuf;
- sbuf.wp = wp;
- sbuf.nobj = nobj;
-
- // (Silence the compiler)
- chan = nil;
- chantype = nil;
- chan_ret = nil;
-
- goto next_block;
-
- for(;;) {
- // Each iteration scans the block b of length n, queueing pointers in
- // the work buffer.
-
- if(CollectStats) {
- runtime·xadd64(&gcstats.nbytes, n);
- runtime·xadd64(&gcstats.obj.sum, sbuf.nobj);
- runtime·xadd64(&gcstats.obj.cnt, 1);
- }
-
- if(ti != 0) {
- if(Debug > 1) {
- runtime·printf("scanblock %p %D ti %p\n", b, (int64)n, ti);
- }
- pc = (uintptr*)(ti & ~(uintptr)PC_BITS);
- precise_type = (ti & PRECISE);
- stack_top.elemsize = pc[0];
- if(!precise_type)
- nominal_size = pc[0];
- if(ti & LOOP) {
- stack_top.count = 0; // 0 means an infinite number of iterations
- stack_top.loop_or_ret = pc+1;
- } else {
- stack_top.count = 1;
- }
- if(Debug) {
- // Simple sanity check for provided type info ti:
- // The declared size of the object must be not larger than the actual size
- // (it can be smaller due to inferior pointers).
- // It's difficult to make a comprehensive check due to inferior pointers,
- // reflection, gob, etc.
- if(pc[0] > n) {
- runtime·printf("invalid gc type info: type info size %p, block size %p\n", pc[0], n);
- runtime·throw("invalid gc type info");
- }
- }
- } else if(UseSpanType) {
- if(CollectStats)
- runtime·xadd64(&gcstats.obj.notype, 1);
-
- type = runtime·gettype(b);
- if(type != 0) {
- if(CollectStats)
- runtime·xadd64(&gcstats.obj.typelookup, 1);
-
- t = (Type*)(type & ~(uintptr)(PtrSize-1));
- switch(type & (PtrSize-1)) {
- case TypeInfo_SingleObject:
- pc = (uintptr*)t->gc;
- precise_type = true; // type information about 'b' is precise
- stack_top.count = 1;
- stack_top.elemsize = pc[0];
- break;
- case TypeInfo_Array:
- pc = (uintptr*)t->gc;
- if(pc[0] == 0)
- goto next_block;
- precise_type = true; // type information about 'b' is precise
- stack_top.count = 0; // 0 means an infinite number of iterations
- stack_top.elemsize = pc[0];
- stack_top.loop_or_ret = pc+1;
- break;
- case TypeInfo_Chan:
- chan = (Hchan*)b;
- chantype = (ChanType*)t;
- chan_ret = nil;
- pc = chanProg;
- break;
- default:
- if(Debug > 1)
- runtime·printf("scanblock %p %D type %p %S\n", b, (int64)n, type, *t->string);
- runtime·throw("scanblock: invalid type");
- return;
- }
- if(Debug > 1)
- runtime·printf("scanblock %p %D type %p %S pc=%p\n", b, (int64)n, type, *t->string, pc);
- } else {
- pc = defaultProg;
- if(Debug > 1)
- runtime·printf("scanblock %p %D unknown type\n", b, (int64)n);
- }
- } else {
- pc = defaultProg;
- if(Debug > 1)
- runtime·printf("scanblock %p %D no span types\n", b, (int64)n);
- }
-
- if(IgnorePreciseGC)
- pc = defaultProg;
-
- pc++;
- stack_top.b = (uintptr)b;
- end_b = (uintptr)b + n - PtrSize;
-
- for(;;) {
- if(CollectStats)
- runtime·xadd64(&gcstats.instr[pc[0]], 1);
-
- obj = nil;
- objti = 0;
- switch(pc[0]) {
- case GC_PTR:
- obj = *(void**)(stack_top.b + pc[1]);
- objti = pc[2];
- if(Debug > 2)
- runtime·printf("gc_ptr @%p: %p ti=%p\n", stack_top.b+pc[1], obj, objti);
- pc += 3;
- if(Debug)
- checkptr(obj, objti);
- break;
-
- case GC_SLICE:
- sliceptr = (Slice*)(stack_top.b + pc[1]);
- if(Debug > 2)
- runtime·printf("gc_slice @%p: %p/%D/%D\n", sliceptr, sliceptr->array, (int64)sliceptr->len, (int64)sliceptr->cap);
- if(sliceptr->cap != 0) {
- obj = sliceptr->array;
- // Can't use slice element type for scanning,
- // because if it points to an array embedded
- // in the beginning of a struct,
- // we will scan the whole struct as the slice.
- // So just obtain type info from heap.
- }
- pc += 3;
- break;
-
- case GC_APTR:
- obj = *(void**)(stack_top.b + pc[1]);
- if(Debug > 2)
- runtime·printf("gc_aptr @%p: %p\n", stack_top.b+pc[1], obj);
- pc += 2;
- break;
-
- case GC_STRING:
- stringptr = (String*)(stack_top.b + pc[1]);
- if(Debug > 2)
- runtime·printf("gc_string @%p: %p/%D\n", stack_top.b+pc[1], stringptr->str, (int64)stringptr->len);
- if(stringptr->len != 0)
- markonly(stringptr->str);
- pc += 2;
- continue;
-
- case GC_EFACE:
- eface = (Eface*)(stack_top.b + pc[1]);
- pc += 2;
- if(Debug > 2)
- runtime·printf("gc_eface @%p: %p %p\n", stack_top.b+pc[1], eface->type, eface->data);
- if(eface->type == nil)
- continue;
-
- // eface->type
- t = eface->type;
- if((void*)t >= arena_start && (void*)t < arena_used) {
- *sbuf.ptr.pos++ = (PtrTarget){t, 0};
- if(sbuf.ptr.pos == sbuf.ptr.end)
- flushptrbuf(&sbuf);
- }
-
- // eface->data
- if(eface->data >= arena_start && eface->data < arena_used) {
- if(t->size <= sizeof(void*)) {
- if((t->kind & KindNoPointers))
- continue;
-
- obj = eface->data;
- if((t->kind & ~KindNoPointers) == KindPtr) {
- // Only use type information if it is a pointer-containing type.
- // This matches the GC programs written by cmd/gc/reflect.c's
- // dgcsym1 in case TPTR32/case TPTR64. See rationale there.
- et = ((PtrType*)t)->elem;
- if(!(et->kind & KindNoPointers))
- objti = (uintptr)((PtrType*)t)->elem->gc;
- }
- } else {
- obj = eface->data;
- objti = (uintptr)t->gc;
- }
- }
- break;
-
- case GC_IFACE:
- iface = (Iface*)(stack_top.b + pc[1]);
- pc += 2;
- if(Debug > 2)
- runtime·printf("gc_iface @%p: %p/%p %p\n", stack_top.b+pc[1], iface->tab, nil, iface->data);
- if(iface->tab == nil)
- continue;
-
- // iface->tab
- if((void*)iface->tab >= arena_start && (void*)iface->tab < arena_used) {
- *sbuf.ptr.pos++ = (PtrTarget){iface->tab, (uintptr)itabtype->gc};
- if(sbuf.ptr.pos == sbuf.ptr.end)
- flushptrbuf(&sbuf);
- }
-
- // iface->data
- if(iface->data >= arena_start && iface->data < arena_used) {
- t = iface->tab->type;
- if(t->size <= sizeof(void*)) {
- if((t->kind & KindNoPointers))
- continue;
-
- obj = iface->data;
- if((t->kind & ~KindNoPointers) == KindPtr) {
- // Only use type information if it is a pointer-containing type.
- // This matches the GC programs written by cmd/gc/reflect.c's
- // dgcsym1 in case TPTR32/case TPTR64. See rationale there.
- et = ((PtrType*)t)->elem;
- if(!(et->kind & KindNoPointers))
- objti = (uintptr)((PtrType*)t)->elem->gc;
- }
- } else {
- obj = iface->data;
- objti = (uintptr)t->gc;
- }
- }
- break;
-
- case GC_DEFAULT_PTR:
- while(stack_top.b <= end_b) {
- obj = *(byte**)stack_top.b;
- if(Debug > 2)
- runtime·printf("gc_default_ptr @%p: %p\n", stack_top.b, obj);
- stack_top.b += PtrSize;
- if(obj >= arena_start && obj < arena_used) {
- *sbuf.ptr.pos++ = (PtrTarget){obj, 0};
- if(sbuf.ptr.pos == sbuf.ptr.end)
- flushptrbuf(&sbuf);
- }
- }
- goto next_block;
-
- case GC_END:
- if(--stack_top.count != 0) {
- // Next iteration of a loop if possible.
- stack_top.b += stack_top.elemsize;
- if(stack_top.b + stack_top.elemsize <= end_b+PtrSize) {
- pc = stack_top.loop_or_ret;
- continue;
- }
- i = stack_top.b;
- } else {
- // Stack pop if possible.
- if(stack_ptr+1 < stack+nelem(stack)) {
- pc = stack_top.loop_or_ret;
- stack_top = *(++stack_ptr);
- continue;
- }
- i = (uintptr)b + nominal_size;
- }
- if(!precise_type) {
- // Quickly scan [b+i,b+n) for possible pointers.
- for(; i<=end_b; i+=PtrSize) {
- if(*(byte**)i != nil) {
- // Found a value that may be a pointer.
- // Do a rescan of the entire block.
- enqueue((Obj){b, n, 0}, &sbuf.wbuf, &sbuf.wp, &sbuf.nobj);
- if(CollectStats) {
- runtime·xadd64(&gcstats.rescan, 1);
- runtime·xadd64(&gcstats.rescanbytes, n);
- }
- break;
- }
- }
- }
- goto next_block;
-
- case GC_ARRAY_START:
- i = stack_top.b + pc[1];
- count = pc[2];
- elemsize = pc[3];
- pc += 4;
-
- // Stack push.
- *stack_ptr-- = stack_top;
- stack_top = (Frame){count, elemsize, i, pc};
- continue;
-
- case GC_ARRAY_NEXT:
- if(--stack_top.count != 0) {
- stack_top.b += stack_top.elemsize;
- pc = stack_top.loop_or_ret;
- } else {
- // Stack pop.
- stack_top = *(++stack_ptr);
- pc += 1;
- }
- continue;
-
- case GC_CALL:
- // Stack push.
- *stack_ptr-- = stack_top;
- stack_top = (Frame){1, 0, stack_top.b + pc[1], pc+3 /*return address*/};
- pc = (uintptr*)((byte*)pc + *(int32*)(pc+2)); // target of the CALL instruction
- continue;
-
- case GC_REGION:
- obj = (void*)(stack_top.b + pc[1]);
- size = pc[2];
- objti = pc[3];
- pc += 4;
-
- if(Debug > 2)
- runtime·printf("gc_region @%p: %D %p\n", stack_top.b+pc[1], (int64)size, objti);
- *sbuf.obj.pos++ = (Obj){obj, size, objti};
- if(sbuf.obj.pos == sbuf.obj.end)
- flushobjbuf(&sbuf);
- continue;
-
- case GC_CHAN_PTR:
- chan = *(Hchan**)(stack_top.b + pc[1]);
- if(Debug > 2 && chan != nil)
- runtime·printf("gc_chan_ptr @%p: %p/%D/%D %p\n", stack_top.b+pc[1], chan, (int64)chan->qcount, (int64)chan->dataqsiz, pc[2]);
- if(chan == nil) {
- pc += 3;
- continue;
- }
- if(markonly(chan)) {
- chantype = (ChanType*)pc[2];
- if(!(chantype->elem->kind & KindNoPointers)) {
- // Start chanProg.
- chan_ret = pc+3;
- pc = chanProg+1;
- continue;
- }
- }
- pc += 3;
- continue;
-
- case GC_CHAN:
- // There are no heap pointers in struct Hchan,
- // so we can ignore the leading sizeof(Hchan) bytes.
- if(!(chantype->elem->kind & KindNoPointers)) {
- // Channel's buffer follows Hchan immediately in memory.
- // Size of buffer (cap(c)) is second int in the chan struct.
- chancap = ((uintgo*)chan)[1];
- if(chancap > 0) {
- // TODO(atom): split into two chunks so that only the
- // in-use part of the circular buffer is scanned.
- // (Channel routines zero the unused part, so the current
- // code does not lead to leaks, it's just a little inefficient.)
- *sbuf.obj.pos++ = (Obj){(byte*)chan+runtime·Hchansize, chancap*chantype->elem->size,
- (uintptr)chantype->elem->gc | PRECISE | LOOP};
- if(sbuf.obj.pos == sbuf.obj.end)
- flushobjbuf(&sbuf);
- }
- }
- if(chan_ret == nil)
- goto next_block;
- pc = chan_ret;
- continue;
-
- default:
- runtime·printf("runtime: invalid GC instruction %p at %p\n", pc[0], pc);
- runtime·throw("scanblock: invalid GC instruction");
- return;
- }
-
- if(obj >= arena_start && obj < arena_used) {
- *sbuf.ptr.pos++ = (PtrTarget){obj, objti};
- if(sbuf.ptr.pos == sbuf.ptr.end)
- flushptrbuf(&sbuf);
- }
- }
-
- next_block:
- // Done scanning [b, b+n). Prepare for the next iteration of
- // the loop by setting b, n, ti to the parameters for the next block.
-
- if(sbuf.nobj == 0) {
- flushptrbuf(&sbuf);
- flushobjbuf(&sbuf);
-
- if(sbuf.nobj == 0) {
- if(!keepworking) {
- if(sbuf.wbuf)
- putempty(sbuf.wbuf);
- return;
- }
- // Emptied our buffer: refill.
- sbuf.wbuf = getfull(sbuf.wbuf);
- if(sbuf.wbuf == nil)
- return;
- sbuf.nobj = sbuf.wbuf->nobj;
- sbuf.wp = sbuf.wbuf->obj + sbuf.wbuf->nobj;
- }
- }
-
- // Fetch b from the work buffer.
- --sbuf.wp;
- b = sbuf.wp->p;
- n = sbuf.wp->n;
- ti = sbuf.wp->ti;
- sbuf.nobj--;
- }
-}
-
-// Append obj to the work buffer.
-// _wbuf, _wp, _nobj are input/output parameters and are specifying the work buffer.
-static void
-enqueue(Obj obj, Workbuf **_wbuf, Obj **_wp, uintptr *_nobj)
-{
- uintptr nobj, off;
- Obj *wp;
- Workbuf *wbuf;
-
- if(Debug > 1)
- runtime·printf("append obj(%p %D %p)\n", obj.p, (int64)obj.n, obj.ti);
-
- // Align obj.b to a word boundary.
- off = (uintptr)obj.p & (PtrSize-1);
- if(off != 0) {
- obj.p += PtrSize - off;
- obj.n -= PtrSize - off;
- obj.ti = 0;
- }
-
- if(obj.p == nil || obj.n == 0)
- return;
-
- // Load work buffer state
- wp = *_wp;
- wbuf = *_wbuf;
- nobj = *_nobj;
-
- // If another proc wants a pointer, give it some.
- if(work.nwait > 0 && nobj > handoffThreshold && work.full == 0) {
- wbuf->nobj = nobj;
- wbuf = handoff(wbuf);
- nobj = wbuf->nobj;
- wp = wbuf->obj + nobj;
- }
-
- // If buffer is full, get a new one.
- if(wbuf == nil || nobj >= nelem(wbuf->obj)) {
- if(wbuf != nil)
- wbuf->nobj = nobj;
- wbuf = getempty(wbuf);
- wp = wbuf->obj;
- nobj = 0;
- }
-
- *wp = obj;
- wp++;
- nobj++;
-
- // Save work buffer state
- *_wp = wp;
- *_wbuf = wbuf;
- *_nobj = nobj;
-}
-
-static void
-enqueue1(Workbuf **wbufp, Obj obj)
-{
- Workbuf *wbuf;
-
- wbuf = *wbufp;
- if(wbuf->nobj >= nelem(wbuf->obj))
- *wbufp = wbuf = getempty(wbuf);
- wbuf->obj[wbuf->nobj++] = obj;
-}
-
-static void
-markroot(ParFor *desc, uint32 i)
-{
- Workbuf *wbuf;
- FinBlock *fb;
- MHeap *h;
- MSpan **allspans, *s;
- uint32 spanidx, sg;
- G *gp;
- void *p;
-
- USED(&desc);
- wbuf = getempty(nil);
- // Note: if you add a case here, please also update heapdump.c:dumproots.
- switch(i) {
- case RootData:
- enqueue1(&wbuf, (Obj){data, edata - data, (uintptr)gcdata});
- break;
-
- case RootBss:
- enqueue1(&wbuf, (Obj){bss, ebss - bss, (uintptr)gcbss});
- break;
-
- case RootFinalizers:
- for(fb=allfin; fb; fb=fb->alllink)
- enqueue1(&wbuf, (Obj){(byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]), 0});
- break;
-
- case RootSpanTypes:
- // mark span types and MSpan.specials (to walk spans only once)
- h = &runtime·mheap;
- sg = h->sweepgen;
- allspans = h->allspans;
- for(spanidx=0; spanidx<runtime·mheap.nspan; spanidx++) {
- Special *sp;
- SpecialFinalizer *spf;
-
- s = allspans[spanidx];
- if(s->sweepgen != sg) {
- runtime·printf("sweep %d %d\n", s->sweepgen, sg);
- runtime·throw("gc: unswept span");
- }
- if(s->state != MSpanInUse)
- continue;
- // The garbage collector ignores type pointers stored in MSpan.types:
- // - Compiler-generated types are stored outside of heap.
- // - The reflect package has runtime-generated types cached in its data structures.
- // The garbage collector relies on finding the references via that cache.
- if(s->types.compression == MTypes_Words || s->types.compression == MTypes_Bytes)
- markonly((byte*)s->types.data);
- 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*)sp;
- // A finalizer can be set for an inner byte of an object, find object beginning.
- p = (void*)((s->start << PageShift) + spf->offset/s->elemsize*s->elemsize);
- enqueue1(&wbuf, (Obj){p, s->elemsize, 0});
- enqueue1(&wbuf, (Obj){(void*)&spf->fn, PtrSize, 0});
- enqueue1(&wbuf, (Obj){(void*)&spf->fint, PtrSize, 0});
- enqueue1(&wbuf, (Obj){(void*)&spf->ot, PtrSize, 0});
- }
- }
- break;
-
- case RootFlushCaches:
- flushallmcaches();
- break;
-
- default:
- // the rest is scanning goroutine stacks
- if(i - RootCount >= runtime·allglen)
- runtime·throw("markroot: bad index");
- gp = runtime·allg[i - RootCount];
- // remember when we've first observed the G blocked
- // needed only to output in traceback
- if((gp->status == Gwaiting || gp->status == Gsyscall) && gp->waitsince == 0)
- gp->waitsince = work.tstart;
- addstackroots(gp, &wbuf);
- break;
-
- }
-
- if(wbuf)
- scanblock(wbuf, false);
-}
-
-// Get an empty work buffer off the work.empty list,
-// allocating new buffers as needed.
-static Workbuf*
-getempty(Workbuf *b)
-{
- if(b != nil)
- runtime·lfstackpush(&work.full, &b->node);
- b = (Workbuf*)runtime·lfstackpop(&work.empty);
- if(b == nil) {
- // Need to allocate.
- runtime·lock(&work);
- if(work.nchunk < sizeof *b) {
- work.nchunk = 1<<20;
- work.chunk = runtime·SysAlloc(work.nchunk, &mstats.gc_sys);
- if(work.chunk == nil)
- runtime·throw("runtime: cannot allocate memory");
- }
- b = (Workbuf*)work.chunk;
- work.chunk += sizeof *b;
- work.nchunk -= sizeof *b;
- runtime·unlock(&work);
- }
- b->nobj = 0;
- return b;
-}
-
-static void
-putempty(Workbuf *b)
-{
- if(CollectStats)
- runtime·xadd64(&gcstats.putempty, 1);
-
- runtime·lfstackpush(&work.empty, &b->node);
-}
-
-// Get a full work buffer off the work.full list, or return nil.
-static Workbuf*
-getfull(Workbuf *b)
-{
- int32 i;
-
- if(CollectStats)
- runtime·xadd64(&gcstats.getfull, 1);
-
- if(b != nil)
- runtime·lfstackpush(&work.empty, &b->node);
- b = (Workbuf*)runtime·lfstackpop(&work.full);
- if(b != nil || work.nproc == 1)
- return b;
-
- runtime·xadd(&work.nwait, +1);
- for(i=0;; i++) {
- if(work.full != 0) {
- runtime·xadd(&work.nwait, -1);
- b = (Workbuf*)runtime·lfstackpop(&work.full);
- if(b != nil)
- return b;
- runtime·xadd(&work.nwait, +1);
- }
- if(work.nwait == work.nproc)
- return nil;
- if(i < 10) {
- m->gcstats.nprocyield++;
- runtime·procyield(20);
- } else if(i < 20) {
- m->gcstats.nosyield++;
- runtime·osyield();
- } else {
- m->gcstats.nsleep++;
- runtime·usleep(100);
- }
- }
-}
-
-static Workbuf*
-handoff(Workbuf *b)
-{
- int32 n;
- Workbuf *b1;
-
- // Make new buffer with half of b's pointers.
- b1 = getempty(nil);
- n = b->nobj/2;
- b->nobj -= n;
- b1->nobj = n;
- runtime·memmove(b1->obj, b->obj+b->nobj, n*sizeof b1->obj[0]);
- m->gcstats.nhandoff++;
- m->gcstats.nhandoffcnt += n;
-
- // Put b on full list - let first half of b get stolen.
- runtime·lfstackpush(&work.full, &b->node);
- return b1;
-}
-
-extern byte pclntab[]; // base for f->ptrsoff
-
-BitVector
-runtime·stackmapdata(StackMap *stackmap, int32 n)
-{
- if(n < 0 || n >= stackmap->n)
- runtime·throw("stackmapdata: index out of range");
- return (BitVector){stackmap->nbit, stackmap->data + n*((stackmap->nbit+31)/32)};
-}
-
-// Scans an interface data value when the interface type indicates
-// that it is a pointer.
-static void
-scaninterfacedata(uintptr bits, byte *scanp, bool afterprologue, void *wbufp)
-{
- Itab *tab;
- Type *type;
-
- if(runtime·precisestack && afterprologue) {
- if(bits == BitsIface) {
- tab = *(Itab**)scanp;
- if(tab->type->size <= sizeof(void*) && (tab->type->kind & KindNoPointers))
- return;
- } else { // bits == BitsEface
- type = *(Type**)scanp;
- if(type->size <= sizeof(void*) && (type->kind & KindNoPointers))
- return;
- }
- }
- enqueue1(wbufp, (Obj){scanp+PtrSize, PtrSize, 0});
-}
-
-// Starting from scanp, scans words corresponding to set bits.
-static void
-scanbitvector(Func *f, bool precise, byte *scanp, BitVector *bv, bool afterprologue, void *wbufp)
-{
- uintptr word, bits;
- uint32 *wordp;
- int32 i, remptrs;
- byte *p;
-
- wordp = bv->data;
- for(remptrs = bv->n; remptrs > 0; remptrs -= 32) {
- word = *wordp++;
- if(remptrs < 32)
- i = remptrs;
- else
- i = 32;
- i /= BitsPerPointer;
- for(; i > 0; i--) {
- bits = word & 3;
- switch(bits) {
- case BitsDead:
- if(runtime·debug.gcdead)
- *(uintptr*)scanp = PoisonGC;
- break;
- case BitsScalar:
- break;
- case BitsPointer:
- p = *(byte**)scanp;
- if(p != nil) {
- if(Debug > 2)
- runtime·printf("frame %s @%p: ptr %p\n", runtime·funcname(f), scanp, p);
- if(precise && (p < (byte*)PageSize || (uintptr)p == PoisonGC || (uintptr)p == PoisonStack)) {
- // Looks like a junk value in a pointer slot.
- // Liveness analysis wrong?
- m->traceback = 2;
- runtime·printf("bad pointer in frame %s at %p: %p\n", runtime·funcname(f), scanp, p);
- runtime·throw("bad pointer in scanbitvector");
- }
- enqueue1(wbufp, (Obj){scanp, PtrSize, 0});
- }
- break;
- case BitsMultiWord:
- p = scanp;
- word >>= BitsPerPointer;
- scanp += PtrSize;
- i--;
- if(i == 0) {
- // Get next chunk of bits
- remptrs -= 32;
- word = *wordp++;
- if(remptrs < 32)
- i = remptrs;
- else
- i = 32;
- i /= BitsPerPointer;
- }
- switch(word & 3) {
- case BitsString:
- if(Debug > 2)
- runtime·printf("frame %s @%p: string %p/%D\n", runtime·funcname(f), p, ((String*)p)->str, (int64)((String*)p)->len);
- if(((String*)p)->len != 0)
- markonly(((String*)p)->str);
- break;
- case BitsSlice:
- word >>= BitsPerPointer;
- scanp += PtrSize;
- i--;
- if(i == 0) {
- // Get next chunk of bits
- remptrs -= 32;
- word = *wordp++;
- if(remptrs < 32)
- i = remptrs;
- else
- i = 32;
- i /= BitsPerPointer;
- }
- if(Debug > 2)
- runtime·printf("frame %s @%p: slice %p/%D/%D\n", runtime·funcname(f), p, ((Slice*)p)->array, (int64)((Slice*)p)->len, (int64)((Slice*)p)->cap);
- if(((Slice*)p)->cap < ((Slice*)p)->len) {
- m->traceback = 2;
- runtime·printf("bad slice in frame %s at %p: %p/%p/%p\n", runtime·funcname(f), p, ((byte**)p)[0], ((byte**)p)[1], ((byte**)p)[2]);
- runtime·throw("slice capacity smaller than length");
- }
- if(((Slice*)p)->cap != 0)
- enqueue1(wbufp, (Obj){p, PtrSize, 0});
- break;
- case BitsIface:
- case BitsEface:
- if(*(byte**)p != nil) {
- if(Debug > 2) {
- if((word&3) == BitsEface)
- runtime·printf("frame %s @%p: eface %p %p\n", runtime·funcname(f), p, ((uintptr*)p)[0], ((uintptr*)p)[1]);
- else
- runtime·printf("frame %s @%p: iface %p %p\n", runtime·funcname(f), p, ((uintptr*)p)[0], ((uintptr*)p)[1]);
- }
- scaninterfacedata(word & 3, p, afterprologue, wbufp);
- }
- break;
- }
- }
- word >>= BitsPerPointer;
- scanp += PtrSize;
- }
- }
-}
-
-// Scan a stack frame: local variables and function arguments/results.
-static bool
-scanframe(Stkframe *frame, void *wbufp)
-{
- Func *f;
- StackMap *stackmap;
- BitVector bv;
- uintptr size;
- uintptr targetpc;
- int32 pcdata;
- bool afterprologue;
- bool precise;
-
- f = frame->fn;
- targetpc = frame->continpc;
- if(targetpc == 0) {
- // Frame is dead.
- return true;
- }
- if(targetpc != f->entry)
- targetpc--;
- pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, targetpc);
- 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
- // at the function prologue, assume so and hope for the best.
- pcdata = 0;
- }
-
- // Scan local variables if stack frame has been allocated.
- // Use pointer information if known.
- afterprologue = (frame->varp > (byte*)frame->sp);
- precise = false;
- if(afterprologue) {
- stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
- if(stackmap == nil) {
- // No locals information, scan everything.
- size = frame->varp - (byte*)frame->sp;
- if(Debug > 2)
- runtime·printf("frame %s unsized locals %p+%p\n", runtime·funcname(f), frame->varp-size, size);
- enqueue1(wbufp, (Obj){frame->varp - size, size, 0});
- } else if(stackmap->n < 0) {
- // Locals size information, scan just the locals.
- size = -stackmap->n;
- if(Debug > 2)
- runtime·printf("frame %s conservative locals %p+%p\n", runtime·funcname(f), frame->varp-size, size);
- enqueue1(wbufp, (Obj){frame->varp - size, size, 0});
- } else if(stackmap->n > 0) {
- // Locals bitmap information, scan just the pointers in
- // locals.
- if(pcdata < 0 || pcdata >= stackmap->n) {
- // don't know where we are
- runtime·printf("pcdata is %d and %d stack map entries for %s (targetpc=%p)\n",
- pcdata, stackmap->n, runtime·funcname(f), targetpc);
- runtime·throw("scanframe: bad symbol table");
- }
- bv = runtime·stackmapdata(stackmap, pcdata);
- size = (bv.n * PtrSize) / BitsPerPointer;
- precise = true;
- scanbitvector(f, true, frame->varp - size, &bv, afterprologue, wbufp);
- }
- }
-
- // Scan arguments.
- // Use pointer information if known.
- stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
- if(stackmap != nil) {
- bv = runtime·stackmapdata(stackmap, pcdata);
- scanbitvector(f, precise, frame->argp, &bv, true, wbufp);
- } else {
- if(Debug > 2)
- runtime·printf("frame %s conservative args %p+%p\n", runtime·funcname(f), frame->argp, (uintptr)frame->arglen);
- enqueue1(wbufp, (Obj){frame->argp, frame->arglen, 0});
- }
- return true;
-}
-
-static void
-addstackroots(G *gp, Workbuf **wbufp)
-{
- M *mp;
- int32 n;
- Stktop *stk;
- uintptr sp, guard;
- void *base;
- uintptr size;
-
- switch(gp->status){
- default:
- runtime·printf("unexpected G.status %d (goroutine %p %D)\n", gp->status, gp, gp->goid);
- runtime·throw("mark - bad status");
- case Gdead:
- return;
- case Grunning:
- runtime·throw("mark - world not stopped");
- case Grunnable:
- case Gsyscall:
- case Gwaiting:
- break;
- }
-
- if(gp == g)
- runtime·throw("can't scan our own stack");
- if((mp = gp->m) != nil && mp->helpgc)
- runtime·throw("can't scan gchelper stack");
-
- if(gp->syscallstack != (uintptr)nil) {
- // Scanning another goroutine that is about to enter or might
- // have just exited a system call. It may be executing code such
- // as schedlock and may have needed to start a new stack segment.
- // Use the stack segment and stack pointer at the time of
- // the system call instead, since that won't change underfoot.
- sp = gp->syscallsp;
- stk = (Stktop*)gp->syscallstack;
- guard = gp->syscallguard;
- } else {
- // Scanning another goroutine's stack.
- // The goroutine is usually asleep (the world is stopped).
- sp = gp->sched.sp;
- stk = (Stktop*)gp->stackbase;
- guard = gp->stackguard;
- // For function about to start, context argument is a root too.
- if(gp->sched.ctxt != 0 && runtime·mlookup(gp->sched.ctxt, &base, &size, nil))
- enqueue1(wbufp, (Obj){base, size, 0});
- }
- if(ScanStackByFrames) {
- USED(sp);
- USED(stk);
- USED(guard);
- runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff, scanframe, wbufp, false);
- } else {
- n = 0;
- while(stk) {
- if(sp < guard-StackGuard || (uintptr)stk < sp) {
- runtime·printf("scanstack inconsistent: g%D#%d sp=%p not in [%p,%p]\n", gp->goid, n, sp, guard-StackGuard, stk);
- runtime·throw("scanstack");
- }
- if(Debug > 2)
- runtime·printf("conservative stack %p+%p\n", (byte*)sp, (uintptr)stk-sp);
- enqueue1(wbufp, (Obj){(byte*)sp, (uintptr)stk - sp, (uintptr)defaultProg | PRECISE | LOOP});
- sp = stk->gobuf.sp;
- guard = stk->stackguard;
- stk = (Stktop*)stk->stackbase;
- n++;
- }
- }
-}
-
-void
-runtime·queuefinalizer(byte *p, FuncVal *fn, uintptr nret, Type *fint, PtrType *ot)
-{
- FinBlock *block;
- Finalizer *f;
-
- runtime·lock(&finlock);
- if(finq == nil || finq->cnt == finq->cap) {
- if(finc == nil) {
- finc = runtime·persistentalloc(FinBlockSize, 0, &mstats.gc_sys);
- finc->cap = (FinBlockSize - sizeof(FinBlock)) / sizeof(Finalizer) + 1;
- finc->alllink = allfin;
- allfin = finc;
- }
- block = finc;
- finc = block->next;
- block->next = finq;
- finq = block;
- }
- f = &finq->fin[finq->cnt];
- finq->cnt++;
- f->fn = fn;
- f->nret = nret;
- f->fint = fint;
- f->ot = ot;
- f->arg = p;
- runtime·fingwake = true;
- runtime·unlock(&finlock);
-}
-
-void
-runtime·iterate_finq(void (*callback)(FuncVal*, byte*, uintptr, Type*, PtrType*))
-{
- FinBlock *fb;
- Finalizer *f;
- uintptr i;
-
- for(fb = allfin; fb; fb = fb->alllink) {
- for(i = 0; i < fb->cnt; i++) {
- f = &fb->fin[i];
- callback(f->fn, f->arg, f->nret, f->fint, f->ot);
- }
- }
-}
-
-void
-runtime·MSpan_EnsureSwept(MSpan *s)
-{
- uint32 sg;
-
- // Caller must disable preemption.
- // Otherwise when this function returns the span can become unswept again
- // (if GC is triggered on another goroutine).
- if(m->locks == 0 && m->mallocing == 0 && g != m->g0)
- runtime·throw("MSpan_EnsureSwept: m is not locked");
-
- sg = runtime·mheap.sweepgen;
- if(runtime·atomicload(&s->sweepgen) == sg)
- return;
- if(runtime·cas(&s->sweepgen, sg-2, sg-1)) {
- runtime·MSpan_Sweep(s);
- return;
- }
- // unfortunate condition, and we don't have efficient means to wait
- while(runtime·atomicload(&s->sweepgen) != sg)
- runtime·osyield();
-}
-
-// Sweep frees or collects finalizers for blocks not marked in the mark phase.
-// It clears the mark bits in preparation for the next GC round.
-// Returns true if the span was returned to heap.
-bool
-runtime·MSpan_Sweep(MSpan *s)
-{
- int32 cl, n, npages, nfree;
- uintptr size, off, *bitp, shift, bits;
- uint32 sweepgen;
- byte *p;
- MCache *c;
- byte *arena_start;
- MLink head, *end;
- byte *type_data;
- byte compression;
- uintptr type_data_inc;
- MLink *x;
- Special *special, **specialp, *y;
- bool res, sweepgenset;
-
- // It's critical that we enter this function with preemption disabled,
- // GC must not start while we are in the middle of this function.
- if(m->locks == 0 && m->mallocing == 0 && g != m->g0)
- runtime·throw("MSpan_Sweep: m is not locked");
- sweepgen = runtime·mheap.sweepgen;
- if(s->state != MSpanInUse || s->sweepgen != sweepgen-1) {
- runtime·printf("MSpan_Sweep: state=%d sweepgen=%d mheap.sweepgen=%d\n",
- s->state, s->sweepgen, sweepgen);
- runtime·throw("MSpan_Sweep: bad span state");
- }
- arena_start = runtime·mheap.arena_start;
- cl = s->sizeclass;
- size = s->elemsize;
- if(cl == 0) {
- n = 1;
- } else {
- // Chunk full of small blocks.
- npages = runtime·class_to_allocnpages[cl];
- n = (npages << PageShift) / size;
- }
- res = false;
- nfree = 0;
- end = &head;
- c = m->mcache;
- sweepgenset = false;
-
- // mark any free objects in this span so we don't collect them
- for(x = s->freelist; x != nil; x = x->next) {
- // This is markonly(x) but faster because we don't need
- // atomic access and we're guaranteed to be pointing at
- // the head of a valid object.
- off = (uintptr*)x - (uintptr*)runtime·mheap.arena_start;
- bitp = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- *bitp |= bitMarked<<shift;
- }
-
- // Unlink & free special records for any objects we're about to free.
- specialp = &s->specials;
- special = *specialp;
- while(special != nil) {
- // A finalizer can be set for an inner byte of an object, find object beginning.
- p = (byte*)(s->start << PageShift) + special->offset/size*size;
- off = (uintptr*)p - (uintptr*)arena_start;
- bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- bits = *bitp>>shift;
- if((bits & (bitAllocated|bitMarked)) == bitAllocated) {
- // Find the exact byte for which the special was setup
- // (as opposed to object beginning).
- p = (byte*)(s->start << PageShift) + special->offset;
- // about to free object: splice out special record
- y = special;
- special = special->next;
- *specialp = special;
- if(!runtime·freespecial(y, p, size, false)) {
- // stop freeing of object if it has a finalizer
- *bitp |= bitMarked << shift;
- }
- } else {
- // object is still live: keep special record
- specialp = &special->next;
- special = *specialp;
- }
- }
-
- type_data = (byte*)s->types.data;
- type_data_inc = sizeof(uintptr);
- compression = s->types.compression;
- switch(compression) {
- case MTypes_Bytes:
- type_data += 8*sizeof(uintptr);
- type_data_inc = 1;
- break;
- }
-
- // Sweep through n objects of given size starting at p.
- // This thread owns the span now, so it can manipulate
- // the block bitmap without atomic operations.
- p = (byte*)(s->start << PageShift);
- for(; n > 0; n--, p += size, type_data+=type_data_inc) {
- off = (uintptr*)p - (uintptr*)arena_start;
- bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- bits = *bitp>>shift;
-
- if((bits & bitAllocated) == 0)
- continue;
-
- if((bits & bitMarked) != 0) {
- *bitp &= ~(bitMarked<<shift);
- continue;
- }
-
- if(runtime·debug.allocfreetrace)
- runtime·tracefree(p, size);
-
- // Clear mark and scan bits.
- *bitp &= ~((bitScan|bitMarked)<<shift);
-
- if(cl == 0) {
- // Free large span.
- runtime·unmarkspan(p, 1<<PageShift);
- s->needzero = 1;
- // important to set sweepgen before returning it to heap
- runtime·atomicstore(&s->sweepgen, sweepgen);
- sweepgenset = true;
- // See note about SysFault vs SysFree in malloc.goc.
- if(runtime·debug.efence)
- runtime·SysFault(p, size);
- else
- runtime·MHeap_Free(&runtime·mheap, s, 1);
- c->local_nlargefree++;
- c->local_largefree += size;
- runtime·xadd64(&mstats.next_gc, -(uint64)(size * (gcpercent + 100)/100));
- res = true;
- } else {
- // Free small object.
- switch(compression) {
- case MTypes_Words:
- *(uintptr*)type_data = 0;
- break;
- case MTypes_Bytes:
- *(byte*)type_data = 0;
- break;
- }
- if(size > 2*sizeof(uintptr))
- ((uintptr*)p)[1] = (uintptr)0xdeaddeaddeaddeadll; // mark as "needs to be zeroed"
- else if(size > sizeof(uintptr))
- ((uintptr*)p)[1] = 0;
-
- end->next = (MLink*)p;
- end = (MLink*)p;
- nfree++;
- }
- }
-
- // We need to set s->sweepgen = h->sweepgen only when all blocks are swept,
- // because of the potential for a concurrent free/SetFinalizer.
- // 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.
-
- if(!sweepgenset && 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) {
- runtime·printf("MSpan_Sweep: state=%d sweepgen=%d mheap.sweepgen=%d\n",
- s->state, s->sweepgen, sweepgen);
- runtime·throw("MSpan_Sweep: bad span state after sweep");
- }
- runtime·atomicstore(&s->sweepgen, sweepgen);
- }
- if(nfree > 0) {
- c->local_nsmallfree[cl] += nfree;
- c->local_cachealloc -= nfree * size;
- runtime·xadd64(&mstats.next_gc, -(uint64)(nfree * size * (gcpercent + 100)/100));
- res = runtime·MCentral_FreeSpan(&runtime·mheap.central[cl], s, nfree, head.next, end);
- //MCentral_FreeSpan updates sweepgen
- }
- return res;
-}
-
-// State of background sweep.
-// Pretected by gclock.
-static struct
-{
- G* g;
- bool parked;
-
- MSpan** spans;
- uint32 nspan;
- uint32 spanidx;
-} sweep;
-
-// background sweeping goroutine
-static void
-bgsweep(void)
-{
- g->issystem = 1;
- for(;;) {
- while(runtime·sweepone() != -1) {
- gcstats.nbgsweep++;
- runtime·gosched();
- }
- runtime·lock(&gclock);
- if(!runtime·mheap.sweepdone) {
- // It's possible if GC has happened between sweepone has
- // returned -1 and gclock lock.
- runtime·unlock(&gclock);
- continue;
- }
- sweep.parked = true;
- g->isbackground = true;
- runtime·parkunlock(&gclock, "GC sweep wait");
- g->isbackground = false;
- }
-}
-
-// sweeps one span
-// returns number of pages returned to heap, or -1 if there is nothing to sweep
-uintptr
-runtime·sweepone(void)
-{
- MSpan *s;
- uint32 idx, sg;
- uintptr npages;
-
- // increment locks to ensure that the goroutine is not preempted
- // in the middle of sweep thus leaving the span in an inconsistent state for next GC
- m->locks++;
- sg = runtime·mheap.sweepgen;
- for(;;) {
- idx = runtime·xadd(&sweep.spanidx, 1) - 1;
- if(idx >= sweep.nspan) {
- runtime·mheap.sweepdone = true;
- m->locks--;
- return -1;
- }
- s = sweep.spans[idx];
- if(s->state != MSpanInUse) {
- s->sweepgen = sg;
- continue;
- }
- if(s->sweepgen != sg-2 || !runtime·cas(&s->sweepgen, sg-2, sg-1))
- continue;
- if(s->incache)
- runtime·throw("sweep of incache span");
- npages = s->npages;
- if(!runtime·MSpan_Sweep(s))
- npages = 0;
- m->locks--;
- return npages;
- }
-}
-
-static void
-dumpspan(uint32 idx)
-{
- int32 sizeclass, n, npages, i, column;
- uintptr size;
- byte *p;
- byte *arena_start;
- MSpan *s;
- bool allocated;
-
- s = runtime·mheap.allspans[idx];
- if(s->state != MSpanInUse)
- return;
- arena_start = runtime·mheap.arena_start;
- p = (byte*)(s->start << PageShift);
- sizeclass = s->sizeclass;
- size = s->elemsize;
- if(sizeclass == 0) {
- n = 1;
- } else {
- npages = runtime·class_to_allocnpages[sizeclass];
- n = (npages << PageShift) / size;
- }
-
- runtime·printf("%p .. %p:\n", p, p+n*size);
- column = 0;
- for(; n>0; n--, p+=size) {
- uintptr off, *bitp, shift, bits;
-
- off = (uintptr*)p - (uintptr*)arena_start;
- bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- bits = *bitp>>shift;
-
- allocated = ((bits & bitAllocated) != 0);
-
- for(i=0; i<size; i+=sizeof(void*)) {
- if(column == 0) {
- runtime·printf("\t");
- }
- if(i == 0) {
- runtime·printf(allocated ? "(" : "[");
- runtime·printf("%p: ", p+i);
- } else {
- runtime·printf(" ");
- }
-
- runtime·printf("%p", *(void**)(p+i));
-
- if(i+sizeof(void*) >= size) {
- runtime·printf(allocated ? ") " : "] ");
- }
-
- column++;
- if(column == 8) {
- runtime·printf("\n");
- column = 0;
- }
- }
- }
- runtime·printf("\n");
-}
-
-// A debugging function to dump the contents of memory
-void
-runtime·memorydump(void)
-{
- uint32 spanidx;
-
- for(spanidx=0; spanidx<runtime·mheap.nspan; spanidx++) {
- dumpspan(spanidx);
- }
-}
-
-void
-runtime·gchelper(void)
-{
- uint32 nproc;
-
- m->traceback = 2;
- gchelperstart();
-
- // parallel mark for over gc roots
- runtime·parfordo(work.markfor);
-
- // help other threads scan secondary blocks
- scanblock(nil, true);
-
- bufferList[m->helpgc].busy = 0;
- nproc = work.nproc; // work.nproc can change right after we increment work.ndone
- if(runtime·xadd(&work.ndone, +1) == nproc-1)
- runtime·notewakeup(&work.alldone);
- m->traceback = 0;
-}
-
-static void
-cachestats(void)
-{
- MCache *c;
- P *p, **pp;
-
- for(pp=runtime·allp; p=*pp; pp++) {
- c = p->mcache;
- if(c==nil)
- continue;
- runtime·purgecachedstats(c);
- }
-}
-
-static void
-flushallmcaches(void)
-{
- P *p, **pp;
- MCache *c;
-
- // Flush MCache's to MCentral.
- for(pp=runtime·allp; p=*pp; pp++) {
- c = p->mcache;
- if(c==nil)
- continue;
- runtime·MCache_ReleaseAll(c);
- }
-}
-
-void
-runtime·updatememstats(GCStats *stats)
-{
- M *mp;
- MSpan *s;
- int32 i;
- uint64 stacks_inuse, smallfree;
- uint64 *src, *dst;
-
- if(stats)
- runtime·memclr((byte*)stats, sizeof(*stats));
- stacks_inuse = 0;
- for(mp=runtime·allm; mp; mp=mp->alllink) {
- stacks_inuse += mp->stackinuse*FixedStack;
- if(stats) {
- src = (uint64*)&mp->gcstats;
- dst = (uint64*)stats;
- for(i=0; i<sizeof(*stats)/sizeof(uint64); i++)
- dst[i] += src[i];
- runtime·memclr((byte*)&mp->gcstats, sizeof(mp->gcstats));
- }
- }
- mstats.stacks_inuse = stacks_inuse;
- mstats.mcache_inuse = runtime·mheap.cachealloc.inuse;
- mstats.mspan_inuse = runtime·mheap.spanalloc.inuse;
- mstats.sys = mstats.heap_sys + mstats.stacks_sys + mstats.mspan_sys +
- mstats.mcache_sys + mstats.buckhash_sys + mstats.gc_sys + mstats.other_sys;
-
- // Calculate memory allocator stats.
- // During program execution we only count number of frees and amount of freed memory.
- // Current number of alive object in the heap and amount of alive heap memory
- // are calculated by scanning all spans.
- // Total number of mallocs is calculated as number of frees plus number of alive objects.
- // Similarly, total amount of allocated memory is calculated as amount of freed memory
- // plus amount of alive heap memory.
- mstats.alloc = 0;
- mstats.total_alloc = 0;
- mstats.nmalloc = 0;
- mstats.nfree = 0;
- for(i = 0; i < nelem(mstats.by_size); i++) {
- mstats.by_size[i].nmalloc = 0;
- mstats.by_size[i].nfree = 0;
- }
-
- // Flush MCache's to MCentral.
- flushallmcaches();
-
- // Aggregate local stats.
- cachestats();
-
- // Scan all spans and count number of alive objects.
- for(i = 0; i < runtime·mheap.nspan; i++) {
- s = runtime·mheap.allspans[i];
- if(s->state != MSpanInUse)
- continue;
- if(s->sizeclass == 0) {
- mstats.nmalloc++;
- mstats.alloc += s->elemsize;
- } else {
- mstats.nmalloc += s->ref;
- mstats.by_size[s->sizeclass].nmalloc += s->ref;
- mstats.alloc += s->ref*s->elemsize;
- }
- }
-
- // Aggregate by size class.
- smallfree = 0;
- mstats.nfree = runtime·mheap.nlargefree;
- for(i = 0; i < nelem(mstats.by_size); i++) {
- mstats.nfree += runtime·mheap.nsmallfree[i];
- mstats.by_size[i].nfree = runtime·mheap.nsmallfree[i];
- mstats.by_size[i].nmalloc += runtime·mheap.nsmallfree[i];
- smallfree += runtime·mheap.nsmallfree[i] * runtime·class_to_size[i];
- }
- mstats.nmalloc += mstats.nfree;
-
- // Calculate derived stats.
- mstats.total_alloc = mstats.alloc + runtime·mheap.largefree + smallfree;
- mstats.heap_alloc = mstats.alloc;
- mstats.heap_objects = mstats.nmalloc - mstats.nfree;
-}
-
-// Structure of arguments passed to function gc().
-// This allows the arguments to be passed via runtime·mcall.
-struct gc_args
-{
- int64 start_time; // start time of GC in ns (just before stoptheworld)
- bool eagersweep;
-};
-
-static void gc(struct gc_args *args);
-static void mgc(G *gp);
-
-static int32
-readgogc(void)
-{
- byte *p;
-
- p = runtime·getenv("GOGC");
- if(p == nil || p[0] == '\0')
- return 100;
- if(runtime·strcmp(p, (byte*)"off") == 0)
- return -1;
- return runtime·atoi(p);
-}
-
-// force = 1 - do GC regardless of current heap usage
-// force = 2 - go GC and eager sweep
-void
-runtime·gc(int32 force)
-{
- struct gc_args a;
- int32 i;
-
- // The atomic operations are not atomic if the uint64s
- // are not aligned on uint64 boundaries. This has been
- // a problem in the past.
- if((((uintptr)&work.empty) & 7) != 0)
- runtime·throw("runtime: gc work buffer is misaligned");
- if((((uintptr)&work.full) & 7) != 0)
- runtime·throw("runtime: gc work buffer is misaligned");
-
- // 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 priority inversion
- // problems, don't bother trying to run gc
- // while holding a lock. The next mallocgc
- // without a lock will do the gc instead.
- if(!mstats.enablegc || g == m->g0 || m->locks > 0 || runtime·panicking)
- return;
-
- if(gcpercent == GcpercentUnknown) { // first time through
- runtime·lock(&runtime·mheap);
- if(gcpercent == GcpercentUnknown)
- gcpercent = readgogc();
- runtime·unlock(&runtime·mheap);
- }
- if(gcpercent < 0)
- return;
-
- runtime·semacquire(&runtime·worldsema, false);
- if(force==0 && mstats.heap_alloc < mstats.next_gc) {
- // typically threads which lost the race to grab
- // worldsema exit here when gc is done.
- runtime·semrelease(&runtime·worldsema);
- return;
- }
-
- // Ok, we're doing it! Stop everybody else
- a.start_time = runtime·nanotime();
- a.eagersweep = force >= 2;
- m->gcing = 1;
- runtime·stoptheworld();
-
- clearpools();
-
- // Run gc on the g0 stack. We do this so that the g stack
- // we're currently running on will no longer change. Cuts
- // the root set down a bit (g0 stacks are not scanned, and
- // we don't need to scan gc's internal state). Also an
- // enabler for copyable stacks.
- for(i = 0; i < (runtime·debug.gctrace > 1 ? 2 : 1); i++) {
- if(i > 0)
- a.start_time = runtime·nanotime();
- // switch to g0, call gc(&a), then switch back
- g->param = &a;
- g->status = Gwaiting;
- g->waitreason = "garbage collection";
- runtime·mcall(mgc);
- }
-
- // all done
- m->gcing = 0;
- m->locks++;
- runtime·semrelease(&runtime·worldsema);
- runtime·starttheworld();
- m->locks--;
-
- // now that gc is done, kick off finalizer thread if needed
- if(!ConcurrentSweep) {
- // give the queued finalizers, if any, a chance to run
- runtime·gosched();
- }
-}
-
-static void
-mgc(G *gp)
-{
- gc(gp->param);
- gp->param = nil;
- gp->status = Grunning;
- runtime·gogo(&gp->sched);
-}
-
-static void
-gc(struct gc_args *args)
-{
- int64 t0, t1, t2, t3, t4;
- uint64 heap0, heap1, obj, ninstr;
- GCStats stats;
- uint32 i;
- Eface eface;
-
- if(runtime·debug.allocfreetrace)
- runtime·tracegc();
-
- m->traceback = 2;
- t0 = args->start_time;
- work.tstart = args->start_time;
-
- if(CollectStats)
- runtime·memclr((byte*)&gcstats, sizeof(gcstats));
-
- m->locks++; // disable gc during mallocs in parforalloc
- if(work.markfor == nil)
- work.markfor = runtime·parforalloc(MaxGcproc);
- m->locks--;
-
- if(itabtype == nil) {
- // get C pointer to the Go type "itab"
- runtime·gc_itab_ptr(&eface);
- itabtype = ((PtrType*)eface.type)->elem;
- }
-
- t1 = 0;
- if(runtime·debug.gctrace)
- t1 = runtime·nanotime();
-
- // Sweep what is not sweeped by bgsweep.
- while(runtime·sweepone() != -1)
- gcstats.npausesweep++;
-
- work.nwait = 0;
- work.ndone = 0;
- work.nproc = runtime·gcprocs();
- runtime·parforsetup(work.markfor, work.nproc, RootCount + runtime·allglen, nil, false, markroot);
- if(work.nproc > 1) {
- runtime·noteclear(&work.alldone);
- runtime·helpgc(work.nproc);
- }
-
- t2 = 0;
- if(runtime·debug.gctrace)
- t2 = runtime·nanotime();
-
- gchelperstart();
- runtime·parfordo(work.markfor);
- scanblock(nil, true);
-
- t3 = 0;
- if(runtime·debug.gctrace)
- t3 = runtime·nanotime();
-
- bufferList[m->helpgc].busy = 0;
- if(work.nproc > 1)
- runtime·notesleep(&work.alldone);
-
- cachestats();
- // next_gc calculation is tricky with concurrent sweep since we don't know size of live heap
- // estimate what was live heap size after previous GC (for tracing only)
- heap0 = mstats.next_gc*100/(gcpercent+100);
- // conservatively set next_gc to high value assuming that everything is live
- // concurrent/lazy sweep will reduce this number while discovering new garbage
- mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/100;
-
- t4 = runtime·nanotime();
- mstats.last_gc = runtime·unixnanotime(); // must be Unix time to make sense to user
- mstats.pause_ns[mstats.numgc%nelem(mstats.pause_ns)] = t4 - t0;
- mstats.pause_total_ns += t4 - t0;
- mstats.numgc++;
- if(mstats.debuggc)
- runtime·printf("pause %D\n", t4-t0);
-
- if(runtime·debug.gctrace) {
- heap1 = mstats.heap_alloc;
- runtime·updatememstats(&stats);
- if(heap1 != mstats.heap_alloc) {
- runtime·printf("runtime: mstats skew: heap=%D/%D\n", heap1, mstats.heap_alloc);
- runtime·throw("mstats skew");
- }
- obj = mstats.nmalloc - mstats.nfree;
-
- stats.nprocyield += work.markfor->nprocyield;
- stats.nosyield += work.markfor->nosyield;
- stats.nsleep += work.markfor->nsleep;
-
- runtime·printf("gc%d(%d): %D+%D+%D+%D us, %D -> %D MB, %D (%D-%D) objects,"
- " %d/%d/%d sweeps,"
- " %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\n",
- mstats.numgc, work.nproc, (t1-t0)/1000, (t2-t1)/1000, (t3-t2)/1000, (t4-t3)/1000,
- heap0>>20, heap1>>20, obj,
- mstats.nmalloc, mstats.nfree,
- sweep.nspan, gcstats.nbgsweep, gcstats.npausesweep,
- stats.nhandoff, stats.nhandoffcnt,
- work.markfor->nsteal, work.markfor->nstealcnt,
- stats.nprocyield, stats.nosyield, stats.nsleep);
- gcstats.nbgsweep = gcstats.npausesweep = 0;
- if(CollectStats) {
- runtime·printf("scan: %D bytes, %D objects, %D untyped, %D types from MSpan\n",
- gcstats.nbytes, gcstats.obj.cnt, gcstats.obj.notype, gcstats.obj.typelookup);
- if(gcstats.ptr.cnt != 0)
- runtime·printf("avg ptrbufsize: %D (%D/%D)\n",
- gcstats.ptr.sum/gcstats.ptr.cnt, gcstats.ptr.sum, gcstats.ptr.cnt);
- if(gcstats.obj.cnt != 0)
- runtime·printf("avg nobj: %D (%D/%D)\n",
- gcstats.obj.sum/gcstats.obj.cnt, gcstats.obj.sum, gcstats.obj.cnt);
- runtime·printf("rescans: %D, %D bytes\n", gcstats.rescan, gcstats.rescanbytes);
-
- runtime·printf("instruction counts:\n");
- ninstr = 0;
- for(i=0; i<nelem(gcstats.instr); i++) {
- runtime·printf("\t%d:\t%D\n", i, gcstats.instr[i]);
- ninstr += gcstats.instr[i];
- }
- runtime·printf("\ttotal:\t%D\n", ninstr);
-
- runtime·printf("putempty: %D, getfull: %D\n", gcstats.putempty, gcstats.getfull);
-
- runtime·printf("markonly base lookup: bit %D word %D span %D\n", gcstats.markonly.foundbit, gcstats.markonly.foundword, gcstats.markonly.foundspan);
- runtime·printf("flushptrbuf base lookup: bit %D word %D span %D\n", gcstats.flushptrbuf.foundbit, gcstats.flushptrbuf.foundword, gcstats.flushptrbuf.foundspan);
- }
- }
-
- // We cache current runtime·mheap.allspans array in sweep.spans,
- // because the former can be resized and freed.
- // Otherwise we would need to take heap lock every time
- // we want to convert span index to span pointer.
-
- // Free the old cached array if necessary.
- if(sweep.spans && sweep.spans != runtime·mheap.allspans)
- runtime·SysFree(sweep.spans, sweep.nspan*sizeof(sweep.spans[0]), &mstats.other_sys);
- // Cache the current array.
- runtime·mheap.sweepspans = runtime·mheap.allspans;
- runtime·mheap.sweepgen += 2;
- runtime·mheap.sweepdone = false;
- sweep.spans = runtime·mheap.allspans;
- sweep.nspan = runtime·mheap.nspan;
- sweep.spanidx = 0;
-
- // Temporary disable concurrent sweep, because we see failures on builders.
- if(ConcurrentSweep && !args->eagersweep) {
- runtime·lock(&gclock);
- if(sweep.g == nil)
- sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, runtime·gc);
- else if(sweep.parked) {
- sweep.parked = false;
- runtime·ready(sweep.g);
- }
- runtime·unlock(&gclock);
- } else {
- // Sweep all spans eagerly.
- while(runtime·sweepone() != -1)
- gcstats.npausesweep++;
- }
-
- // Shrink a stack if not much of it is being used.
- // TODO: do in a parfor
- for(i = 0; i < runtime·allglen; i++)
- runtime·shrinkstack(runtime·allg[i]);
-
- runtime·MProf_GC();
- m->traceback = 0;
-}
-
-extern uintptr runtime·sizeof_C_MStats;
-
-void
-runtime·ReadMemStats(MStats *stats)
-{
- // Have to acquire worldsema to stop the world,
- // because stoptheworld can only be used by
- // one goroutine at a time, and there might be
- // a pending garbage collection already calling it.
- runtime·semacquire(&runtime·worldsema, false);
- m->gcing = 1;
- runtime·stoptheworld();
- runtime·updatememstats(nil);
- // Size of the trailing by_size array differs between Go and C,
- // NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
- runtime·memcopy(runtime·sizeof_C_MStats, stats, &mstats);
- m->gcing = 0;
- m->locks++;
- runtime·semrelease(&runtime·worldsema);
- runtime·starttheworld();
- m->locks--;
-}
-
-void
-runtime∕debug·readGCStats(Slice *pauses)
-{
- uint64 *p;
- uint32 i, n;
-
- // Calling code in runtime/debug should make the slice large enough.
- if(pauses->cap < nelem(mstats.pause_ns)+3)
- runtime·throw("runtime: short slice passed to readGCStats");
-
- // Pass back: pauses, last gc (absolute time), number of gc, total pause ns.
- p = (uint64*)pauses->array;
- runtime·lock(&runtime·mheap);
- n = mstats.numgc;
- if(n > nelem(mstats.pause_ns))
- n = nelem(mstats.pause_ns);
-
- // The pause buffer is circular. The most recent pause is at
- // pause_ns[(numgc-1)%nelem(pause_ns)], and then backward
- // from there to go back farther in time. We deliver the times
- // most recent first (in p[0]).
- for(i=0; i<n; i++)
- p[i] = mstats.pause_ns[(mstats.numgc-1-i)%nelem(mstats.pause_ns)];
-
- p[n] = mstats.last_gc;
- p[n+1] = mstats.numgc;
- p[n+2] = mstats.pause_total_ns;
- runtime·unlock(&runtime·mheap);
- pauses->len = n+3;
-}
-
-int32
-runtime·setgcpercent(int32 in) {
- int32 out;
-
- runtime·lock(&runtime·mheap);
- if(gcpercent == GcpercentUnknown)
- gcpercent = readgogc();
- out = gcpercent;
- if(in < 0)
- in = -1;
- gcpercent = in;
- runtime·unlock(&runtime·mheap);
- return out;
-}
-
-static void
-gchelperstart(void)
-{
- if(m->helpgc < 0 || m->helpgc >= MaxGcproc)
- runtime·throw("gchelperstart: bad m->helpgc");
- if(runtime·xchg(&bufferList[m->helpgc].busy, 1))
- runtime·throw("gchelperstart: already busy");
- if(g != m->g0)
- runtime·throw("gchelper not running on g0 stack");
-}
-
-static void
-runfinq(void)
-{
- Finalizer *f;
- FinBlock *fb, *next;
- byte *frame;
- uint32 framesz, framecap, i;
- Eface *ef, ef1;
-
- // This function blocks for long periods of time, and because it is written in C
- // we have no liveness information. Zero everything so that uninitialized pointers
- // do not cause memory leaks.
- f = nil;
- fb = nil;
- next = nil;
- frame = nil;
- framecap = 0;
- framesz = 0;
- i = 0;
- ef = nil;
- ef1.type = nil;
- ef1.data = nil;
-
- // force flush to memory
- USED(&f);
- USED(&fb);
- USED(&next);
- USED(&framesz);
- USED(&i);
- USED(&ef);
- USED(&ef1);
-
- for(;;) {
- runtime·lock(&finlock);
- fb = finq;
- finq = nil;
- if(fb == nil) {
- runtime·fingwait = true;
- g->isbackground = true;
- runtime·parkunlock(&finlock, "finalizer wait");
- g->isbackground = false;
- continue;
- }
- runtime·unlock(&finlock);
- if(raceenabled)
- runtime·racefingo();
- for(; fb; fb=next) {
- next = fb->next;
- for(i=0; i<fb->cnt; i++) {
- f = &fb->fin[i];
- framesz = sizeof(Eface) + f->nret;
- if(framecap < framesz) {
- runtime·free(frame);
- // The frame does not contain pointers interesting for GC,
- // all not yet finalized objects are stored in finq.
- // If we do not mark it as FlagNoScan,
- // the last finalized object is not collected.
- frame = runtime·mallocgc(framesz, 0, FlagNoScan|FlagNoInvokeGC);
- framecap = framesz;
- }
- if(f->fint == nil)
- runtime·throw("missing type in runfinq");
- if(f->fint->kind == KindPtr) {
- // direct use of pointer
- *(void**)frame = f->arg;
- } else if(((InterfaceType*)f->fint)->mhdr.len == 0) {
- // convert to empty interface
- ef = (Eface*)frame;
- ef->type = f->ot;
- ef->data = f->arg;
- } else {
- // convert to interface with methods, via empty interface.
- ef1.type = f->ot;
- ef1.data = f->arg;
- if(!runtime·ifaceE2I2((InterfaceType*)f->fint, ef1, (Iface*)frame))
- runtime·throw("invalid type conversion in runfinq");
- }
- reflect·call(f->fn, frame, framesz, framesz);
- f->fn = nil;
- f->arg = nil;
- f->ot = nil;
- }
- fb->cnt = 0;
- runtime·lock(&finlock);
- fb->next = finc;
- finc = fb;
- runtime·unlock(&finlock);
- }
-
- // Zero everything that's dead, to avoid memory leaks.
- // See comment at top of function.
- f = nil;
- fb = nil;
- next = nil;
- i = 0;
- ef = nil;
- ef1.type = nil;
- ef1.data = nil;
- runtime·gc(1); // trigger another gc to clean up the finalized objects, if possible
- }
-}
-
-void
-runtime·createfing(void)
-{
- if(fing != nil)
- return;
- // Here we use gclock instead of finlock,
- // because newproc1 can allocate, which can cause on-demand span sweep,
- // which can queue finalizers, which would deadlock.
- runtime·lock(&gclock);
- if(fing == nil)
- fing = runtime·newproc1(&runfinqv, nil, 0, 0, runtime·gc);
- runtime·unlock(&gclock);
-}
-
-G*
-runtime·wakefing(void)
-{
- G *res;
-
- res = nil;
- runtime·lock(&finlock);
- if(runtime·fingwait && runtime·fingwake) {
- runtime·fingwait = false;
- runtime·fingwake = false;
- res = fing;
- }
- runtime·unlock(&finlock);
- return res;
-}
-
-void
-runtime·marknogc(void *v)
-{
- uintptr *b, off, shift;
-
- off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start; // word offset
- b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- *b = (*b & ~(bitAllocated<<shift)) | bitBlockBoundary<<shift;
-}
-
-void
-runtime·markscan(void *v)
-{
- uintptr *b, off, shift;
-
- off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start; // word offset
- b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- *b |= bitScan<<shift;
-}
-
-// mark the block at v as freed.
-void
-runtime·markfreed(void *v)
-{
- uintptr *b, off, shift;
-
- if(0)
- runtime·printf("markfreed %p\n", v);
-
- if((byte*)v > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
- runtime·throw("markfreed: bad pointer");
-
- off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start; // word offset
- b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- *b = (*b & ~(bitMask<<shift)) | (bitAllocated<<shift);
-}
-
-// check that the block at v of size n is marked freed.
-void
-runtime·checkfreed(void *v, uintptr n)
-{
- uintptr *b, bits, off, shift;
-
- if(!runtime·checking)
- return;
-
- if((byte*)v+n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
- return; // not allocated, so okay
-
- off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start; // word offset
- b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
-
- bits = *b>>shift;
- if((bits & bitAllocated) != 0) {
- runtime·printf("checkfreed %p+%p: off=%p have=%p\n",
- v, n, off, bits & bitMask);
- runtime·throw("checkfreed: not freed");
- }
-}
-
-// mark the span of memory at v as having n blocks of the given size.
-// if leftover is true, there is left over space at the end of the span.
-void
-runtime·markspan(void *v, uintptr size, uintptr n, bool leftover)
-{
- uintptr *b, *b0, off, shift, i, x;
- byte *p;
-
- if((byte*)v+size*n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
- runtime·throw("markspan: bad pointer");
-
- if(runtime·checking) {
- // bits should be all zero at the start
- off = (byte*)v + size - runtime·mheap.arena_start;
- b = (uintptr*)(runtime·mheap.arena_start - off/wordsPerBitmapWord);
- for(i = 0; i < size/PtrSize/wordsPerBitmapWord; i++) {
- if(b[i] != 0)
- runtime·throw("markspan: span bits not zero");
- }
- }
-
- p = v;
- if(leftover) // mark a boundary just past end of last block too
- n++;
-
- b0 = nil;
- x = 0;
- for(; n-- > 0; p += size) {
- // Okay to use non-atomic ops here, because we control
- // the entire span, and each bitmap word has bits for only
- // one span, so no other goroutines are changing these
- // bitmap words.
- off = (uintptr*)p - (uintptr*)runtime·mheap.arena_start; // word offset
- b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- if(b0 != b) {
- if(b0 != nil)
- *b0 = x;
- b0 = b;
- x = 0;
- }
- x |= bitAllocated<<shift;
- }
- *b0 = x;
-}
-
-// unmark the span of memory at v of length n bytes.
-void
-runtime·unmarkspan(void *v, uintptr n)
-{
- uintptr *p, *b, off;
-
- if((byte*)v+n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
- runtime·throw("markspan: bad pointer");
-
- p = v;
- off = p - (uintptr*)runtime·mheap.arena_start; // word offset
- if(off % wordsPerBitmapWord != 0)
- runtime·throw("markspan: unaligned pointer");
- b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
- n /= PtrSize;
- if(n%wordsPerBitmapWord != 0)
- runtime·throw("unmarkspan: unaligned length");
- // Okay to use non-atomic ops here, because we control
- // the entire span, and each bitmap word has bits for only
- // one span, so no other goroutines are changing these
- // bitmap words.
- n /= wordsPerBitmapWord;
- while(n-- > 0)
- *b-- = 0;
-}
-
-void
-runtime·MHeap_MapBits(MHeap *h)
-{
- // 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.
- enum {
- bitmapChunk = 8192
- };
- uintptr n;
-
- n = (h->arena_used - h->arena_start) / wordsPerBitmapWord;
- n = ROUND(n, bitmapChunk);
- n = ROUND(n, PhysPageSize);
- if(h->bitmap_mapped >= n)
- return;
-
- runtime·SysMap(h->arena_start - n, n - h->bitmap_mapped, h->arena_reserved, &mstats.gc_sys);
- h->bitmap_mapped = n;
-}
diff --git a/src/pkg/runtime/mgc0.go b/src/pkg/runtime/mgc0.go
deleted file mode 100644
index 624485d18..000000000
--- a/src/pkg/runtime/mgc0.go
+++ /dev/null
@@ -1,27 +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
-
-// Called from C. Returns the Go type *m.
-func gc_m_ptr(ret *interface{}) {
- *ret = (*m)(nil)
-}
-
-// Called from C. Returns the Go type *g.
-func gc_g_ptr(ret *interface{}) {
- *ret = (*g)(nil)
-}
-
-// Called from C. Returns the Go type *itab.
-func gc_itab_ptr(ret *interface{}) {
- *ret = (*itab)(nil)
-}
-
-func timenow() (sec int64, nsec int32)
-
-func gc_unixnanotime(now *int64) {
- sec, nsec := timenow()
- *now = sec*1e9 + int64(nsec)
-}
diff --git a/src/pkg/runtime/mgc0.h b/src/pkg/runtime/mgc0.h
deleted file mode 100644
index 16000d1ae..000000000
--- a/src/pkg/runtime/mgc0.h
+++ /dev/null
@@ -1,87 +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.
-
-// Garbage collector (GC)
-
-// GC instruction opcodes.
-//
-// The opcode of an instruction is followed by zero or more
-// arguments to the instruction.
-//
-// Meaning of arguments:
-// off Offset (in bytes) from the start of the current object
-// objgc Pointer to GC info of an object
-// objgcrel Offset to GC info of an object
-// len Length of an array
-// elemsize Size (in bytes) of an element
-// size Size (in bytes)
-//
-// NOTE: There is a copy of these in ../reflect/type.go.
-// They must be kept in sync.
-enum {
- GC_END, // End of object, loop or subroutine. Args: none
- GC_PTR, // A typed pointer. Args: (off, objgc)
- GC_APTR, // Pointer to an arbitrary object. Args: (off)
- GC_ARRAY_START, // Start an array with a fixed length. Args: (off, len, elemsize)
- GC_ARRAY_NEXT, // The next element of an array. Args: none
- GC_CALL, // Call a subroutine. Args: (off, objgcrel)
- GC_CHAN_PTR, // Go channel. Args: (off, ChanType*)
- GC_STRING, // Go string. Args: (off)
- GC_EFACE, // interface{}. Args: (off)
- GC_IFACE, // interface{...}. Args: (off)
- GC_SLICE, // Go slice. Args: (off, objgc)
- GC_REGION, // A region/part of the current object. Args: (off, size, objgc)
-
- GC_NUM_INSTR, // Number of instruction opcodes
-};
-
-enum {
- // Size of GC's fixed stack.
- //
- // The current GC implementation permits:
- // - at most 1 stack allocation because of GC_CALL
- // - at most GC_STACK_CAPACITY allocations because of GC_ARRAY_START
- GC_STACK_CAPACITY = 8,
-};
-
-enum {
- ScanStackByFrames = 1,
- IgnorePreciseGC = 0,
-
- // Four bits per word (see #defines below).
- wordsPerBitmapWord = sizeof(void*)*8/4,
- bitShift = sizeof(void*)*8/4,
-};
-
-// Bits in per-word bitmap.
-// #defines because enum might not be able to hold the values.
-//
-// Each word in the bitmap describes wordsPerBitmapWord words
-// of heap memory. There are 4 bitmap bits dedicated to each heap word,
-// so on a 64-bit system there is one bitmap word per 16 heap words.
-// The bits in the word are packed together by type first, then by
-// heap location, so each 64-bit bitmap word consists of, from top to bottom,
-// the 16 bitMarked bits for the corresponding heap words,
-// then the 16 bitScan/bitBlockBoundary bits, then the 16 bitAllocated bits.
-// This layout makes it easier to iterate over the bits of a given type.
-//
-// The bitmap starts at mheap.arena_start and extends *backward* from
-// there. On a 64-bit system the off'th word in the arena is tracked by
-// the off/16+1'th word before mheap.arena_start. (On a 32-bit system,
-// the only difference is that the divisor is 8.)
-//
-// To pull out the bits corresponding to a given pointer p, we use:
-//
-// off = p - (uintptr*)mheap.arena_start; // word offset
-// b = (uintptr*)mheap.arena_start - off/wordsPerBitmapWord - 1;
-// shift = off % wordsPerBitmapWord
-// bits = *b >> shift;
-// /* then test bits & bitAllocated, bits & bitMarked, etc. */
-//
-#define bitAllocated ((uintptr)1<<(bitShift*0)) /* block start; eligible for garbage collection */
-#define bitScan ((uintptr)1<<(bitShift*1)) /* when bitAllocated is set */
-#define bitMarked ((uintptr)1<<(bitShift*2)) /* when bitAllocated is set */
-#define bitBlockBoundary ((uintptr)1<<(bitShift*1)) /* when bitAllocated is NOT set - mark for FlagNoGC objects */
-
-#define bitMask (bitAllocated | bitScan | bitMarked)
diff --git a/src/pkg/runtime/mprof.goc b/src/pkg/runtime/mprof.goc
deleted file mode 100644
index 9c23a16f8..000000000
--- a/src/pkg/runtime/mprof.goc
+++ /dev/null
@@ -1,527 +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.
-
-// Malloc profiling.
-// Patterned after tcmalloc's algorithms; shorter code.
-
-package runtime
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "defs_GOOS_GOARCH.h"
-#include "type.h"
-
-// NOTE(rsc): Everything here could use cas if contention became an issue.
-static Lock proflock;
-
-// All memory allocations are local and do not escape outside of the profiler.
-// The profiler is forbidden from referring to garbage-collected memory.
-
-enum { MProf, BProf }; // profile types
-
-// Per-call-stack profiling information.
-// Lookup by hashing call stack into a linked-list hash table.
-struct Bucket
-{
- Bucket *next; // next in hash list
- Bucket *allnext; // next in list of all mbuckets/bbuckets
- int32 typ;
- // Generally unions can break precise GC,
- // this one is fine because it does not contain pointers.
- union
- {
- struct // typ == MProf
- {
- // The following complex 3-stage scheme of stats accumulation
- // is required to obtain a consistent picture of mallocs and frees
- // for some point in time.
- // The problem is that mallocs come in real time, while frees
- // come only after a GC during concurrent sweeping. So if we would
- // naively count them, we would get a skew toward mallocs.
- //
- // Mallocs are accounted in recent stats.
- // Explicit frees are accounted in recent stats.
- // GC frees are accounted in prev stats.
- // After GC prev stats are added to final stats and
- // recent stats are moved into prev stats.
- uintptr allocs;
- uintptr frees;
- uintptr alloc_bytes;
- uintptr free_bytes;
-
- uintptr prev_allocs; // since last but one till last gc
- uintptr prev_frees;
- uintptr prev_alloc_bytes;
- uintptr prev_free_bytes;
-
- uintptr recent_allocs; // since last gc till now
- uintptr recent_frees;
- uintptr recent_alloc_bytes;
- uintptr recent_free_bytes;
-
- };
- struct // typ == BProf
- {
- int64 count;
- int64 cycles;
- };
- };
- uintptr hash; // hash of size + stk
- uintptr size;
- uintptr nstk;
- uintptr stk[1];
-};
-enum {
- BuckHashSize = 179999,
-};
-static Bucket **buckhash;
-static Bucket *mbuckets; // memory profile buckets
-static Bucket *bbuckets; // blocking profile buckets
-static uintptr bucketmem;
-
-// Return the bucket for stk[0:nstk], allocating new bucket if needed.
-static Bucket*
-stkbucket(int32 typ, uintptr size, uintptr *stk, int32 nstk, bool alloc)
-{
- int32 i;
- uintptr h;
- Bucket *b;
-
- if(buckhash == nil) {
- buckhash = runtime·SysAlloc(BuckHashSize*sizeof buckhash[0], &mstats.buckhash_sys);
- if(buckhash == nil)
- runtime·throw("runtime: cannot allocate memory");
- }
-
- // Hash stack.
- h = 0;
- for(i=0; i<nstk; i++) {
- h += stk[i];
- h += h<<10;
- h ^= h>>6;
- }
- // hash in size
- h += size;
- h += h<<10;
- h ^= h>>6;
- // finalize
- h += h<<3;
- h ^= h>>11;
-
- i = h%BuckHashSize;
- for(b = buckhash[i]; b; b=b->next)
- if(b->typ == typ && b->hash == h && b->size == size && b->nstk == nstk &&
- runtime·mcmp((byte*)b->stk, (byte*)stk, nstk*sizeof stk[0]) == 0)
- return b;
-
- if(!alloc)
- return nil;
-
- b = runtime·persistentalloc(sizeof *b + nstk*sizeof stk[0], 0, &mstats.buckhash_sys);
- bucketmem += sizeof *b + nstk*sizeof stk[0];
- runtime·memmove(b->stk, stk, nstk*sizeof stk[0]);
- b->typ = typ;
- b->hash = h;
- b->size = size;
- b->nstk = nstk;
- b->next = buckhash[i];
- buckhash[i] = b;
- if(typ == MProf) {
- b->allnext = mbuckets;
- mbuckets = b;
- } else {
- b->allnext = bbuckets;
- bbuckets = b;
- }
- return b;
-}
-
-static void
-MProf_GC(void)
-{
- Bucket *b;
-
- for(b=mbuckets; b; b=b->allnext) {
- b->allocs += b->prev_allocs;
- b->frees += b->prev_frees;
- b->alloc_bytes += b->prev_alloc_bytes;
- b->free_bytes += b->prev_free_bytes;
-
- b->prev_allocs = b->recent_allocs;
- b->prev_frees = b->recent_frees;
- b->prev_alloc_bytes = b->recent_alloc_bytes;
- b->prev_free_bytes = b->recent_free_bytes;
-
- b->recent_allocs = 0;
- b->recent_frees = 0;
- b->recent_alloc_bytes = 0;
- b->recent_free_bytes = 0;
- }
-}
-
-// Record that a gc just happened: all the 'recent' statistics are now real.
-void
-runtime·MProf_GC(void)
-{
- runtime·lock(&proflock);
- MProf_GC();
- runtime·unlock(&proflock);
-}
-
-// Called by malloc to record a profiled block.
-void
-runtime·MProf_Malloc(void *p, uintptr size)
-{
- uintptr stk[32];
- Bucket *b;
- int32 nstk;
-
- nstk = runtime·callers(1, stk, nelem(stk));
- runtime·lock(&proflock);
- b = stkbucket(MProf, size, stk, nstk, true);
- b->recent_allocs++;
- b->recent_alloc_bytes += size;
- runtime·unlock(&proflock);
-
- // Setprofilebucket locks a bunch of other mutexes, so we call it outside of proflock.
- // This reduces potential contention and chances of deadlocks.
- // Since the object must be alive during call to MProf_Malloc,
- // it's fine to do this non-atomically.
- runtime·setprofilebucket(p, b);
-}
-
-// Called when freeing a profiled block.
-void
-runtime·MProf_Free(Bucket *b, uintptr size, bool freed)
-{
- runtime·lock(&proflock);
- if(freed) {
- b->recent_frees++;
- b->recent_free_bytes += size;
- } else {
- b->prev_frees++;
- b->prev_free_bytes += size;
- }
- runtime·unlock(&proflock);
-}
-
-int64 runtime·blockprofilerate; // in CPU ticks
-
-void
-runtime·SetBlockProfileRate(intgo rate)
-{
- int64 r;
-
- if(rate <= 0)
- r = 0; // disable profiling
- else {
- // convert ns to cycles, use float64 to prevent overflow during multiplication
- r = (float64)rate*runtime·tickspersecond()/(1000*1000*1000);
- if(r == 0)
- r = 1;
- }
- runtime·atomicstore64((uint64*)&runtime·blockprofilerate, r);
-}
-
-void
-runtime·blockevent(int64 cycles, int32 skip)
-{
- int32 nstk;
- int64 rate;
- uintptr stk[32];
- Bucket *b;
-
- if(cycles <= 0)
- return;
- rate = runtime·atomicload64((uint64*)&runtime·blockprofilerate);
- if(rate <= 0 || (rate > cycles && runtime·fastrand1()%rate > cycles))
- return;
-
- nstk = runtime·callers(skip, stk, nelem(stk));
- runtime·lock(&proflock);
- b = stkbucket(BProf, 0, stk, nstk, true);
- b->count++;
- b->cycles += cycles;
- runtime·unlock(&proflock);
-}
-
-// Go interface to profile data. (Declared in debug.go)
-
-// Must match MemProfileRecord in debug.go.
-typedef struct Record Record;
-struct Record {
- int64 alloc_bytes, free_bytes;
- int64 alloc_objects, free_objects;
- uintptr stk[32];
-};
-
-// Write b's data to r.
-static void
-record(Record *r, Bucket *b)
-{
- int32 i;
-
- r->alloc_bytes = b->alloc_bytes;
- r->free_bytes = b->free_bytes;
- r->alloc_objects = b->allocs;
- r->free_objects = b->frees;
- for(i=0; i<b->nstk && i<nelem(r->stk); i++)
- r->stk[i] = b->stk[i];
- for(; i<nelem(r->stk); i++)
- r->stk[i] = 0;
-}
-
-func MemProfile(p Slice, include_inuse_zero bool) (n int, ok bool) {
- Bucket *b;
- Record *r;
- bool clear;
-
- runtime·lock(&proflock);
- n = 0;
- clear = true;
- for(b=mbuckets; b; b=b->allnext) {
- if(include_inuse_zero || b->alloc_bytes != b->free_bytes)
- n++;
- if(b->allocs != 0 || b->frees != 0)
- clear = false;
- }
- if(clear) {
- // Absolutely no data, suggesting that a garbage collection
- // has not yet happened. In order to allow profiling when
- // garbage collection is disabled from the beginning of execution,
- // accumulate stats as if a GC just happened, and recount buckets.
- MProf_GC();
- MProf_GC();
- n = 0;
- for(b=mbuckets; b; b=b->allnext)
- if(include_inuse_zero || b->alloc_bytes != b->free_bytes)
- n++;
- }
- ok = false;
- if(n <= p.len) {
- ok = true;
- r = (Record*)p.array;
- for(b=mbuckets; b; b=b->allnext)
- if(include_inuse_zero || b->alloc_bytes != b->free_bytes)
- record(r++, b);
- }
- runtime·unlock(&proflock);
-}
-
-void
-runtime·iterate_memprof(void (*callback)(Bucket*, uintptr, uintptr*, uintptr, uintptr, uintptr))
-{
- Bucket *b;
-
- runtime·lock(&proflock);
- for(b=mbuckets; b; b=b->allnext) {
- callback(b, b->nstk, b->stk, b->size, b->allocs, b->frees);
- }
- runtime·unlock(&proflock);
-}
-
-// Must match BlockProfileRecord in debug.go.
-typedef struct BRecord BRecord;
-struct BRecord {
- int64 count;
- int64 cycles;
- uintptr stk[32];
-};
-
-func BlockProfile(p Slice) (n int, ok bool) {
- Bucket *b;
- BRecord *r;
- int32 i;
-
- runtime·lock(&proflock);
- n = 0;
- for(b=bbuckets; b; b=b->allnext)
- n++;
- ok = false;
- if(n <= p.len) {
- ok = true;
- r = (BRecord*)p.array;
- for(b=bbuckets; b; b=b->allnext, r++) {
- r->count = b->count;
- r->cycles = b->cycles;
- for(i=0; i<b->nstk && i<nelem(r->stk); i++)
- r->stk[i] = b->stk[i];
- for(; i<nelem(r->stk); i++)
- r->stk[i] = 0;
- }
- }
- runtime·unlock(&proflock);
-}
-
-// Must match StackRecord in debug.go.
-typedef struct TRecord TRecord;
-struct TRecord {
- uintptr stk[32];
-};
-
-func ThreadCreateProfile(p Slice) (n int, ok bool) {
- TRecord *r;
- M *first, *mp;
-
- first = runtime·atomicloadp(&runtime·allm);
- n = 0;
- for(mp=first; mp; mp=mp->alllink)
- n++;
- ok = false;
- if(n <= p.len) {
- ok = true;
- r = (TRecord*)p.array;
- for(mp=first; mp; mp=mp->alllink) {
- runtime·memmove(r->stk, mp->createstack, sizeof r->stk);
- r++;
- }
- }
-}
-
-func Stack(b Slice, all bool) (n int) {
- uintptr pc, sp;
-
- sp = runtime·getcallersp(&b);
- pc = (uintptr)runtime·getcallerpc(&b);
-
- if(all) {
- runtime·semacquire(&runtime·worldsema, false);
- m->gcing = 1;
- runtime·stoptheworld();
- }
-
- if(b.len == 0)
- n = 0;
- else{
- g->writebuf = (byte*)b.array;
- g->writenbuf = b.len;
- runtime·goroutineheader(g);
- runtime·traceback(pc, sp, 0, g);
- if(all)
- runtime·tracebackothers(g);
- n = b.len - g->writenbuf;
- g->writebuf = nil;
- g->writenbuf = 0;
- }
-
- if(all) {
- m->gcing = 0;
- runtime·semrelease(&runtime·worldsema);
- runtime·starttheworld();
- }
-}
-
-static void
-saveg(uintptr pc, uintptr sp, G *gp, TRecord *r)
-{
- int32 n;
-
- n = runtime·gentraceback(pc, sp, 0, gp, 0, r->stk, nelem(r->stk), nil, nil, false);
- if(n < nelem(r->stk))
- r->stk[n] = 0;
-}
-
-func GoroutineProfile(b Slice) (n int, ok bool) {
- uintptr pc, sp, i;
- TRecord *r;
- G *gp;
-
- sp = runtime·getcallersp(&b);
- pc = (uintptr)runtime·getcallerpc(&b);
-
- ok = false;
- n = runtime·gcount();
- if(n <= b.len) {
- runtime·semacquire(&runtime·worldsema, false);
- m->gcing = 1;
- runtime·stoptheworld();
-
- n = runtime·gcount();
- if(n <= b.len) {
- ok = true;
- r = (TRecord*)b.array;
- saveg(pc, sp, g, r++);
- for(i = 0; i < runtime·allglen; i++) {
- gp = runtime·allg[i];
- if(gp == g || gp->status == Gdead)
- continue;
- saveg(~(uintptr)0, ~(uintptr)0, gp, r++);
- }
- }
-
- m->gcing = 0;
- runtime·semrelease(&runtime·worldsema);
- runtime·starttheworld();
- }
-}
-
-// Tracing of alloc/free/gc.
-
-static Lock tracelock;
-
-static int8*
-typeinfoname(int32 typeinfo)
-{
- if(typeinfo == TypeInfo_SingleObject)
- return "single object";
- else if(typeinfo == TypeInfo_Array)
- return "array";
- else if(typeinfo == TypeInfo_Chan)
- return "channel";
- runtime·throw("typinfoname: unknown type info");
- return nil;
-}
-
-void
-runtime·tracealloc(void *p, uintptr size, uintptr typ)
-{
- int8 *name;
- Type *type;
-
- runtime·lock(&tracelock);
- m->traceback = 2;
- type = (Type*)(typ & ~3);
- name = typeinfoname(typ & 3);
- if(type == nil)
- runtime·printf("tracealloc(%p, %p, %s)\n", p, size, name);
- else
- runtime·printf("tracealloc(%p, %p, %s of %S)\n", p, size, name, *type->string);
- if(m->curg == nil || g == m->curg) {
- runtime·goroutineheader(g);
- runtime·traceback((uintptr)runtime·getcallerpc(&p), (uintptr)runtime·getcallersp(&p), 0, g);
- } else {
- runtime·goroutineheader(m->curg);
- runtime·traceback(~(uintptr)0, ~(uintptr)0, 0, m->curg);
- }
- runtime·printf("\n");
- m->traceback = 0;
- runtime·unlock(&tracelock);
-}
-
-void
-runtime·tracefree(void *p, uintptr size)
-{
- runtime·lock(&tracelock);
- m->traceback = 2;
- runtime·printf("tracefree(%p, %p)\n", p, size);
- runtime·goroutineheader(g);
- runtime·traceback((uintptr)runtime·getcallerpc(&p), (uintptr)runtime·getcallersp(&p), 0, g);
- runtime·printf("\n");
- m->traceback = 0;
- runtime·unlock(&tracelock);
-}
-
-void
-runtime·tracegc(void)
-{
- runtime·lock(&tracelock);
- m->traceback = 2;
- runtime·printf("tracegc()\n");
- // running on m->g0 stack; show all non-g0 goroutines
- runtime·tracebackothers(g);
- runtime·printf("end tracegc\n");
- runtime·printf("\n");
- m->traceback = 0;
- runtime·unlock(&tracelock);
-}
diff --git a/src/pkg/runtime/netpoll.goc b/src/pkg/runtime/netpoll.goc
deleted file mode 100644
index 7b3d16d02..000000000
--- a/src/pkg/runtime/netpoll.goc
+++ /dev/null
@@ -1,467 +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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
-
-package net
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-
-// Integrated network poller (platform-independent part).
-// A particular implementation (epoll/kqueue) must define the following functions:
-// void runtime·netpollinit(void); // to initialize the poller
-// int32 runtime·netpollopen(uintptr fd, PollDesc *pd); // to arm edge-triggered notifications
- // and associate fd with pd.
-// An implementation must call the following function to denote that the pd is ready.
-// void runtime·netpollready(G **gpp, PollDesc *pd, int32 mode);
-
-// PollDesc contains 2 binary semaphores, rg and wg, to park reader and writer
-// goroutines respectively. The semaphore can be in the following states:
-// READY - io readiness notification is pending;
-// a goroutine consumes the notification by changing the state to nil.
-// WAIT - a goroutine prepares to park on the semaphore, but not yet parked;
-// the goroutine commits to park by changing the state to G pointer,
-// or, alternatively, concurrent io notification changes the state to READY,
-// or, alternatively, concurrent timeout/close changes the state to nil.
-// G pointer - the goroutine is blocked on the semaphore;
-// io notification or timeout/close changes the state to READY or nil respectively
-// and unparks the goroutine.
-// nil - nothing of the above.
-#define READY ((G*)1)
-#define WAIT ((G*)2)
-
-enum
-{
- PollBlockSize = 4*1024,
-};
-
-struct PollDesc
-{
- PollDesc* link; // in pollcache, protected by pollcache.Lock
-
- // The lock protects pollOpen, pollSetDeadline, pollUnblock and deadlineimpl operations.
- // This fully covers seq, rt and wt variables. fd is constant throughout the PollDesc lifetime.
- // pollReset, pollWait, pollWaitCanceled and runtime·netpollready (IO rediness notification)
- // proceed w/o taking the lock. So closing, rg, rd, wg and wd are manipulated
- // in a lock-free way by all operations.
- Lock; // protectes the following fields
- uintptr fd;
- bool closing;
- uintptr seq; // protects from stale timers and ready notifications
- G* rg; // READY, WAIT, G waiting for read or nil
- Timer rt; // read deadline timer (set if rt.fv != nil)
- int64 rd; // read deadline
- G* wg; // READY, WAIT, G waiting for write or nil
- Timer wt; // write deadline timer
- int64 wd; // write deadline
- void* user; // user settable cookie
-};
-
-static struct
-{
- Lock;
- PollDesc* first;
- // PollDesc objects must be type-stable,
- // because we can get ready notification from epoll/kqueue
- // after the descriptor is closed/reused.
- // Stale notifications are detected using seq variable,
- // seq is incremented when deadlines are changed or descriptor is reused.
-} pollcache;
-
-static bool netpollblock(PollDesc*, int32, bool);
-static G* netpollunblock(PollDesc*, int32, bool);
-static void deadline(int64, Eface);
-static void readDeadline(int64, Eface);
-static void writeDeadline(int64, Eface);
-static PollDesc* allocPollDesc(void);
-static intgo checkerr(PollDesc *pd, int32 mode);
-
-static FuncVal deadlineFn = {(void(*)(void))deadline};
-static FuncVal readDeadlineFn = {(void(*)(void))readDeadline};
-static FuncVal writeDeadlineFn = {(void(*)(void))writeDeadline};
-
-// runtimeNano returns the current value of the runtime clock in nanoseconds.
-func runtimeNano() (ns int64) {
- ns = runtime·nanotime();
-}
-
-func runtime_pollServerInit() {
- runtime·netpollinit();
-}
-
-func runtime_pollOpen(fd uintptr) (pd *PollDesc, errno int) {
- pd = allocPollDesc();
- runtime·lock(pd);
- if(pd->wg != nil && pd->wg != READY)
- runtime·throw("runtime_pollOpen: blocked write on free descriptor");
- if(pd->rg != nil && pd->rg != READY)
- runtime·throw("runtime_pollOpen: blocked read on free descriptor");
- pd->fd = fd;
- pd->closing = false;
- pd->seq++;
- pd->rg = nil;
- pd->rd = 0;
- pd->wg = nil;
- pd->wd = 0;
- runtime·unlock(pd);
-
- errno = runtime·netpollopen(fd, pd);
-}
-
-func runtime_pollClose(pd *PollDesc) {
- if(!pd->closing)
- runtime·throw("runtime_pollClose: close w/o unblock");
- if(pd->wg != nil && pd->wg != READY)
- runtime·throw("runtime_pollClose: blocked write on closing descriptor");
- if(pd->rg != nil && pd->rg != READY)
- runtime·throw("runtime_pollClose: blocked read on closing descriptor");
- runtime·netpollclose(pd->fd);
- runtime·lock(&pollcache);
- pd->link = pollcache.first;
- pollcache.first = pd;
- runtime·unlock(&pollcache);
-}
-
-func runtime_pollReset(pd *PollDesc, mode int) (err int) {
- err = checkerr(pd, mode);
- if(err)
- goto ret;
- if(mode == 'r')
- pd->rg = nil;
- else if(mode == 'w')
- pd->wg = nil;
-ret:
-}
-
-func runtime_pollWait(pd *PollDesc, mode int) (err int) {
- err = checkerr(pd, mode);
- if(err == 0) {
- // As for now only Solaris uses level-triggered IO.
- if(Solaris)
- runtime·netpollarm(pd, mode);
- while(!netpollblock(pd, mode, false)) {
- err = checkerr(pd, mode);
- if(err != 0)
- break;
- // Can happen if timeout has fired and unblocked us,
- // but before we had a chance to run, timeout has been reset.
- // Pretend it has not happened and retry.
- }
- }
-}
-
-func runtime_pollWaitCanceled(pd *PollDesc, mode int) {
- // This function is used only on windows after a failed attempt to cancel
- // a pending async IO operation. Wait for ioready, ignore closing or timeouts.
- while(!netpollblock(pd, mode, true))
- ;
-}
-
-func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
- G *rg, *wg;
-
- runtime·lock(pd);
- if(pd->closing) {
- runtime·unlock(pd);
- return;
- }
- pd->seq++; // invalidate current timers
- // Reset current timers.
- if(pd->rt.fv) {
- runtime·deltimer(&pd->rt);
- pd->rt.fv = nil;
- }
- if(pd->wt.fv) {
- runtime·deltimer(&pd->wt);
- pd->wt.fv = nil;
- }
- // Setup new timers.
- if(d != 0 && d <= runtime·nanotime())
- d = -1;
- if(mode == 'r' || mode == 'r'+'w')
- pd->rd = d;
- if(mode == 'w' || mode == 'r'+'w')
- pd->wd = d;
- if(pd->rd > 0 && pd->rd == pd->wd) {
- pd->rt.fv = &deadlineFn;
- pd->rt.when = pd->rd;
- // Copy current seq into the timer arg.
- // Timer func will check the seq against current descriptor seq,
- // if they differ the descriptor was reused or timers were reset.
- pd->rt.arg.type = (Type*)pd->seq;
- pd->rt.arg.data = pd;
- runtime·addtimer(&pd->rt);
- } else {
- if(pd->rd > 0) {
- pd->rt.fv = &readDeadlineFn;
- pd->rt.when = pd->rd;
- pd->rt.arg.type = (Type*)pd->seq;
- pd->rt.arg.data = pd;
- runtime·addtimer(&pd->rt);
- }
- if(pd->wd > 0) {
- pd->wt.fv = &writeDeadlineFn;
- pd->wt.when = pd->wd;
- pd->wt.arg.type = (Type*)pd->seq;
- pd->wt.arg.data = pd;
- runtime·addtimer(&pd->wt);
- }
- }
- // If we set the new deadline in the past, unblock currently pending IO if any.
- rg = nil;
- runtime·atomicstorep(&wg, nil); // full memory barrier between stores to rd/wd and load of rg/wg in netpollunblock
- if(pd->rd < 0)
- rg = netpollunblock(pd, 'r', false);
- if(pd->wd < 0)
- wg = netpollunblock(pd, 'w', false);
- runtime·unlock(pd);
- if(rg)
- runtime·ready(rg);
- if(wg)
- runtime·ready(wg);
-}
-
-func runtime_pollUnblock(pd *PollDesc) {
- G *rg, *wg;
-
- runtime·lock(pd);
- if(pd->closing)
- runtime·throw("runtime_pollUnblock: already closing");
- pd->closing = true;
- pd->seq++;
- runtime·atomicstorep(&rg, nil); // full memory barrier between store to closing and read of rg/wg in netpollunblock
- rg = netpollunblock(pd, 'r', false);
- wg = netpollunblock(pd, 'w', false);
- if(pd->rt.fv) {
- runtime·deltimer(&pd->rt);
- pd->rt.fv = nil;
- }
- if(pd->wt.fv) {
- runtime·deltimer(&pd->wt);
- pd->wt.fv = nil;
- }
- runtime·unlock(pd);
- if(rg)
- runtime·ready(rg);
- if(wg)
- runtime·ready(wg);
-}
-
-uintptr
-runtime·netpollfd(PollDesc *pd)
-{
- return pd->fd;
-}
-
-void**
-runtime·netpolluser(PollDesc *pd)
-{
- return &pd->user;
-}
-
-bool
-runtime·netpollclosing(PollDesc *pd)
-{
- return pd->closing;
-}
-
-void
-runtime·netpolllock(PollDesc *pd)
-{
- runtime·lock(pd);
-}
-
-void
-runtime·netpollunlock(PollDesc *pd)
-{
- runtime·unlock(pd);
-}
-
-// make pd ready, newly runnable goroutines (if any) are enqueued info gpp list
-void
-runtime·netpollready(G **gpp, PollDesc *pd, int32 mode)
-{
- G *rg, *wg;
-
- rg = wg = nil;
- if(mode == 'r' || mode == 'r'+'w')
- rg = netpollunblock(pd, 'r', true);
- if(mode == 'w' || mode == 'r'+'w')
- wg = netpollunblock(pd, 'w', true);
- if(rg) {
- rg->schedlink = *gpp;
- *gpp = rg;
- }
- if(wg) {
- wg->schedlink = *gpp;
- *gpp = wg;
- }
-}
-
-static intgo
-checkerr(PollDesc *pd, int32 mode)
-{
- if(pd->closing)
- return 1; // errClosing
- if((mode == 'r' && pd->rd < 0) || (mode == 'w' && pd->wd < 0))
- return 2; // errTimeout
- return 0;
-}
-
-static bool
-blockcommit(G *gp, G **gpp)
-{
- return runtime·casp(gpp, WAIT, gp);
-}
-
-// returns true if IO is ready, or false if timedout or closed
-// waitio - wait only for completed IO, ignore errors
-static bool
-netpollblock(PollDesc *pd, int32 mode, bool waitio)
-{
- G **gpp, *old;
-
- gpp = &pd->rg;
- if(mode == 'w')
- gpp = &pd->wg;
-
- // set the gpp semaphore to WAIT
- for(;;) {
- old = *gpp;
- if(old == READY) {
- *gpp = nil;
- return true;
- }
- if(old != nil)
- runtime·throw("netpollblock: double wait");
- if(runtime·casp(gpp, nil, WAIT))
- break;
- }
-
- // need to recheck error states after setting gpp to WAIT
- // this is necessary because runtime_pollUnblock/runtime_pollSetDeadline/deadlineimpl
- // do the opposite: store to closing/rd/wd, membarrier, load of rg/wg
- if(waitio || checkerr(pd, mode) == 0)
- runtime·park((bool(*)(G*, void*))blockcommit, gpp, "IO wait");
- // be careful to not lose concurrent READY notification
- old = runtime·xchgp(gpp, nil);
- if(old > WAIT)
- runtime·throw("netpollblock: corrupted state");
- return old == READY;
-}
-
-static G*
-netpollunblock(PollDesc *pd, int32 mode, bool ioready)
-{
- G **gpp, *old, *new;
-
- gpp = &pd->rg;
- if(mode == 'w')
- gpp = &pd->wg;
-
- for(;;) {
- old = *gpp;
- if(old == READY)
- return nil;
- if(old == nil && !ioready) {
- // Only set READY for ioready. runtime_pollWait
- // will check for timeout/cancel before waiting.
- return nil;
- }
- new = nil;
- if(ioready)
- new = READY;
- if(runtime·casp(gpp, old, new))
- break;
- }
- if(old > WAIT)
- return old; // must be G*
- return nil;
-}
-
-static void
-deadlineimpl(int64 now, Eface arg, bool read, bool write)
-{
- PollDesc *pd;
- uint32 seq;
- G *rg, *wg;
-
- USED(now);
- pd = (PollDesc*)arg.data;
- // This is the seq when the timer was set.
- // If it's stale, ignore the timer event.
- seq = (uintptr)arg.type;
- rg = wg = nil;
- runtime·lock(pd);
- if(seq != pd->seq) {
- // The descriptor was reused or timers were reset.
- runtime·unlock(pd);
- return;
- }
- if(read) {
- if(pd->rd <= 0 || pd->rt.fv == nil)
- runtime·throw("deadlineimpl: inconsistent read deadline");
- pd->rd = -1;
- runtime·atomicstorep(&pd->rt.fv, nil); // full memory barrier between store to rd and load of rg in netpollunblock
- rg = netpollunblock(pd, 'r', false);
- }
- if(write) {
- if(pd->wd <= 0 || (pd->wt.fv == nil && !read))
- runtime·throw("deadlineimpl: inconsistent write deadline");
- pd->wd = -1;
- runtime·atomicstorep(&pd->wt.fv, nil); // full memory barrier between store to wd and load of wg in netpollunblock
- wg = netpollunblock(pd, 'w', false);
- }
- runtime·unlock(pd);
- if(rg)
- runtime·ready(rg);
- if(wg)
- runtime·ready(wg);
-}
-
-static void
-deadline(int64 now, Eface arg)
-{
- deadlineimpl(now, arg, true, true);
-}
-
-static void
-readDeadline(int64 now, Eface arg)
-{
- deadlineimpl(now, arg, true, false);
-}
-
-static void
-writeDeadline(int64 now, Eface arg)
-{
- deadlineimpl(now, arg, false, true);
-}
-
-static PollDesc*
-allocPollDesc(void)
-{
- PollDesc *pd;
- uint32 i, n;
-
- runtime·lock(&pollcache);
- if(pollcache.first == nil) {
- n = PollBlockSize/sizeof(*pd);
- if(n == 0)
- n = 1;
- // Must be in non-GC memory because can be referenced
- // only from epoll/kqueue internals.
- pd = runtime·persistentalloc(n*sizeof(*pd), 0, &mstats.other_sys);
- for(i = 0; i < n; i++) {
- pd[i].link = pollcache.first;
- pollcache.first = &pd[i];
- }
- }
- pd = pollcache.first;
- pollcache.first = pd->link;
- runtime·unlock(&pollcache);
- return pd;
-}
diff --git a/src/pkg/runtime/netpoll_epoll.c b/src/pkg/runtime/netpoll_epoll.c
deleted file mode 100644
index 9ea5e1a59..000000000
--- a/src/pkg/runtime/netpoll_epoll.c
+++ /dev/null
@@ -1,102 +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 linux
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-
-int32 runtime·epollcreate(int32 size);
-int32 runtime·epollcreate1(int32 flags);
-int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev);
-int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
-void runtime·closeonexec(int32 fd);
-
-static int32 epfd = -1; // epoll descriptor
-
-void
-runtime·netpollinit(void)
-{
- epfd = runtime·epollcreate1(EPOLL_CLOEXEC);
- if(epfd >= 0)
- return;
- epfd = runtime·epollcreate(1024);
- if(epfd >= 0) {
- runtime·closeonexec(epfd);
- return;
- }
- runtime·printf("netpollinit: failed to create descriptor (%d)\n", -epfd);
- runtime·throw("netpollinit: failed to create descriptor");
-}
-
-int32
-runtime·netpollopen(uintptr fd, PollDesc *pd)
-{
- EpollEvent ev;
- int32 res;
-
- ev.events = EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET;
- ev.data = (uint64)pd;
- res = runtime·epollctl(epfd, EPOLL_CTL_ADD, (int32)fd, &ev);
- return -res;
-}
-
-int32
-runtime·netpollclose(uintptr fd)
-{
- EpollEvent ev;
- int32 res;
-
- res = runtime·epollctl(epfd, EPOLL_CTL_DEL, (int32)fd, &ev);
- return -res;
-}
-
-void
-runtime·netpollarm(PollDesc* pd, int32 mode)
-{
- USED(pd, mode);
- runtime·throw("unused");
-}
-
-// polls for ready network connections
-// returns list of goroutines that become runnable
-G*
-runtime·netpoll(bool block)
-{
- static int32 lasterr;
- EpollEvent events[128], *ev;
- int32 n, i, waitms, mode;
- G *gp;
-
- if(epfd == -1)
- return nil;
- waitms = -1;
- if(!block)
- waitms = 0;
-retry:
- n = runtime·epollwait(epfd, events, nelem(events), waitms);
- if(n < 0) {
- if(n != -EINTR && n != lasterr) {
- lasterr = n;
- runtime·printf("runtime: epollwait on fd %d failed with %d\n", epfd, -n);
- }
- goto retry;
- }
- gp = nil;
- for(i = 0; i < n; i++) {
- ev = &events[i];
- if(ev->events == 0)
- continue;
- mode = 0;
- if(ev->events & (EPOLLIN|EPOLLRDHUP|EPOLLHUP|EPOLLERR))
- mode += 'r';
- if(ev->events & (EPOLLOUT|EPOLLHUP|EPOLLERR))
- mode += 'w';
- if(mode)
- runtime·netpollready(&gp, (void*)ev->data, mode);
- }
- if(block && gp == nil)
- goto retry;
- return gp;
-}
diff --git a/src/pkg/runtime/netpoll_kqueue.c b/src/pkg/runtime/netpoll_kqueue.c
deleted file mode 100644
index 171346cce..000000000
--- a/src/pkg/runtime/netpoll_kqueue.c
+++ /dev/null
@@ -1,111 +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 darwin dragonfly freebsd netbsd openbsd
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-
-// Integrated network poller (kqueue-based implementation).
-
-int32 runtime·kqueue(void);
-int32 runtime·kevent(int32, Kevent*, int32, Kevent*, int32, Timespec*);
-void runtime·closeonexec(int32);
-
-static int32 kq = -1;
-
-void
-runtime·netpollinit(void)
-{
- kq = runtime·kqueue();
- if(kq < 0) {
- runtime·printf("netpollinit: kqueue failed with %d\n", -kq);
- runtime·throw("netpollinit: kqueue failed");
- }
- runtime·closeonexec(kq);
-}
-
-int32
-runtime·netpollopen(uintptr fd, PollDesc *pd)
-{
- Kevent ev[2];
- int32 n;
-
- // Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
- // for the whole fd lifetime. The notifications are automatically unregistered
- // when fd is closed.
- ev[0].ident = (uint32)fd;
- ev[0].filter = EVFILT_READ;
- ev[0].flags = EV_ADD|EV_CLEAR;
- ev[0].fflags = 0;
- ev[0].data = 0;
- ev[0].udata = (kevent_udata)pd;
- ev[1] = ev[0];
- ev[1].filter = EVFILT_WRITE;
- n = runtime·kevent(kq, ev, 2, nil, 0, nil);
- if(n < 0)
- return -n;
- return 0;
-}
-
-int32
-runtime·netpollclose(uintptr fd)
-{
- // Don't need to unregister because calling close()
- // on fd will remove any kevents that reference the descriptor.
- USED(fd);
- return 0;
-}
-
-void
-runtime·netpollarm(PollDesc* pd, int32 mode)
-{
- USED(pd, mode);
- runtime·throw("unused");
-}
-
-// Polls for ready network connections.
-// Returns list of goroutines that become runnable.
-G*
-runtime·netpoll(bool block)
-{
- static int32 lasterr;
- Kevent events[64], *ev;
- Timespec ts, *tp;
- int32 n, i, mode;
- G *gp;
-
- if(kq == -1)
- return nil;
- tp = nil;
- if(!block) {
- ts.tv_sec = 0;
- ts.tv_nsec = 0;
- tp = &ts;
- }
- gp = nil;
-retry:
- n = runtime·kevent(kq, nil, 0, events, nelem(events), tp);
- if(n < 0) {
- if(n != -EINTR && n != lasterr) {
- lasterr = n;
- runtime·printf("runtime: kevent on fd %d failed with %d\n", kq, -n);
- }
- goto retry;
- }
- for(i = 0; i < n; i++) {
- ev = &events[i];
- mode = 0;
- if(ev->filter == EVFILT_READ)
- mode += 'r';
- if(ev->filter == EVFILT_WRITE)
- mode += 'w';
- if(mode)
- runtime·netpollready(&gp, (PollDesc*)ev->udata, mode);
- }
- if(block && gp == nil)
- goto retry;
- return gp;
-}
diff --git a/src/pkg/runtime/netpoll_nacl.c b/src/pkg/runtime/netpoll_nacl.c
deleted file mode 100644
index b75753a23..000000000
--- a/src/pkg/runtime/netpoll_nacl.c
+++ /dev/null
@@ -1,37 +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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-
-// Fake network poller for NaCl.
-// Should never be used, because NaCl network connections do not honor "SetNonblock".
-
-void
-runtime·netpollinit(void)
-{
-}
-
-int32
-runtime·netpollopen(uintptr fd, PollDesc *pd)
-{
- USED(fd);
- USED(pd);
- return 0;
-}
-
-int32
-runtime·netpollclose(uintptr fd)
-{
- USED(fd);
- return 0;
-}
-
-G*
-runtime·netpoll(bool block)
-{
- USED(block);
- return nil;
-}
diff --git a/src/pkg/runtime/noasm_arm.goc b/src/pkg/runtime/noasm_arm.goc
deleted file mode 100644
index fe3591e8a..000000000
--- a/src/pkg/runtime/noasm_arm.goc
+++ /dev/null
@@ -1,74 +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.
-
-// Routines that are implemented in assembly in asm_{amd64,386}.s
-// but are implemented in C for arm.
-
-package runtime
-#include "runtime.h"
-#include "../../cmd/ld/textflag.h"
-
-#pragma textflag NOSPLIT
-func cmpstring(s1 String, s2 String) (v int) {
- uintgo i, l;
- byte c1, c2;
-
- l = s1.len;
- if(s2.len < l)
- l = s2.len;
- for(i=0; i<l; i++) {
- c1 = s1.str[i];
- c2 = s2.str[i];
- if(c1 < c2) {
- v = -1;
- goto done;
- }
- if(c1 > c2) {
- v = +1;
- goto done;
- }
- }
- if(s1.len < s2.len) {
- v = -1;
- goto done;
- }
- if(s1.len > s2.len) {
- v = +1;
- goto done;
- }
- v = 0;
- done:;
-}
-
-#pragma textflag NOSPLIT
-func bytes·Compare(s1 Slice, s2 Slice) (v int) {
- uintgo i, l;
- byte c1, c2;
-
- l = s1.len;
- if(s2.len < l)
- l = s2.len;
- for(i=0; i<l; i++) {
- c1 = s1.array[i];
- c2 = s2.array[i];
- if(c1 < c2) {
- v = -1;
- goto done;
- }
- if(c1 > c2) {
- v = +1;
- goto done;
- }
- }
- if(s1.len < s2.len) {
- v = -1;
- goto done;
- }
- if(s1.len > s2.len) {
- v = +1;
- goto done;
- }
- v = 0;
- done:;
-}
diff --git a/src/pkg/runtime/os_solaris.h b/src/pkg/runtime/os_solaris.h
deleted file mode 100644
index f3fae5da2..000000000
--- a/src/pkg/runtime/os_solaris.h
+++ /dev/null
@@ -1,51 +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.
-
-#define SS_DISABLE 2
-
-#define SIG_BLOCK 1
-#define SIG_UNBLOCK 2
-#define SIG_SETMASK 3
-
-typedef uintptr kevent_udata;
-
-struct sigaction;
-
-void runtime·sigpanic(void);
-
-void runtime·setitimer(int32, Itimerval*, Itimerval*);
-void runtime·sigaction(int32, struct Sigaction*, struct Sigaction*);
-void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
-void runtime·sigprocmask(int32, Sigset*, Sigset*);
-void runtime·unblocksignals(void);
-int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
-
-#define NSIG 73 /* number of signals in runtime·SigTab array */
-#define SI_USER 0
-
-void runtime·raisesigpipe(void);
-void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
-void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
-void runtime·sigpanic(void);
-
-#define _UC_SIGMASK 0x01
-#define _UC_CPU 0x04
-
-#define RLIMIT_AS 10
-typedef struct Rlimit Rlimit;
-struct Rlimit {
- int64 rlim_cur;
- int64 rlim_max;
-};
-int32 runtime·getrlimit(int32, Rlimit*);
-
-// Call a library function with SysV conventions,
-// and switch to os stack during the call.
-#pragma varargck countpos runtime·sysvicall6 2
-#pragma varargck type runtime·sysvicall6 uintptr
-#pragma varargck type runtime·sysvicall6 int32
-void runtime·asmsysvicall6(void *c);
-uintptr runtime·sysvicall6(uintptr fn, int32 count, ...);
-
-void runtime·miniterrno(void *fn);
diff --git a/src/pkg/runtime/os_windows_386.c b/src/pkg/runtime/os_windows_386.c
deleted file mode 100644
index c36a00114..000000000
--- a/src/pkg/runtime/os_windows_386.c
+++ /dev/null
@@ -1,138 +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.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-
-void
-runtime·dumpregs(Context *r)
-{
- runtime·printf("eax %x\n", r->Eax);
- runtime·printf("ebx %x\n", r->Ebx);
- runtime·printf("ecx %x\n", r->Ecx);
- runtime·printf("edx %x\n", r->Edx);
- runtime·printf("edi %x\n", r->Edi);
- runtime·printf("esi %x\n", r->Esi);
- runtime·printf("ebp %x\n", r->Ebp);
- runtime·printf("esp %x\n", r->Esp);
- runtime·printf("eip %x\n", r->Eip);
- runtime·printf("eflags %x\n", r->EFlags);
- runtime·printf("cs %x\n", r->SegCs);
- runtime·printf("fs %x\n", r->SegFs);
- runtime·printf("gs %x\n", r->SegGs);
-}
-
-#define DBG_PRINTEXCEPTION_C 0x40010006
-
-// Called by sigtramp from Windows VEH handler.
-// Return value signals whether the exception has been handled (-1)
-// or should be made available to other handlers in the chain (0).
-uint32
-runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
-{
- bool crash;
- uintptr *sp;
- extern byte text[], etext[];
-
- if(info->ExceptionCode == DBG_PRINTEXCEPTION_C) {
- // This exception is intended to be caught by debuggers.
- // There is a not-very-informational message like
- // "Invalid parameter passed to C runtime function"
- // sitting at info->ExceptionInformation[0] (a wchar_t*),
- // with length info->ExceptionInformation[1].
- // The default behavior is to ignore this exception,
- // but somehow returning 0 here (meaning keep going)
- // makes the program crash instead. Maybe Windows has no
- // other handler registered? In any event, ignore it.
- return -1;
- }
-
- // Only handle exception if executing instructions in Go binary
- // (not Windows library code).
- if(r->Eip < (uint32)text || (uint32)etext < r->Eip)
- return 0;
-
- switch(info->ExceptionCode) {
- case EXCEPTION_BREAKPOINT:
- // It is unclear whether this is needed, unclear whether it
- // would work, and unclear how to test it. Leave out for now.
- // This only handles breakpoint instructions written in the
- // assembly sources, not breakpoints set by a debugger, and
- // there are very few of the former.
- //
- // r->Eip--; // because 8l generates 2 bytes for INT3
- // return 0;
- break;
- }
-
- if(gp != nil && runtime·issigpanic(info->ExceptionCode)) {
- // 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 = info->ExceptionCode;
- gp->sigcode0 = info->ExceptionInformation[0];
- gp->sigcode1 = info->ExceptionInformation[1];
- gp->sigpc = r->Eip;
-
- // Only push runtime·sigpanic if r->eip != 0.
- // If r->eip == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic and we
- // won't get to see who faulted.)
- if(r->Eip != 0) {
- sp = (uintptr*)r->Esp;
- *--sp = r->Eip;
- r->Esp = (uintptr)sp;
- }
- r->Eip = (uintptr)runtime·sigpanic;
- return -1;
- }
-
- if(runtime·panicking) // traceback already printed
- runtime·exit(2);
- runtime·panicking = 1;
-
- runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode,
- info->ExceptionInformation[0], info->ExceptionInformation[1], r->Eip);
-
- runtime·printf("PC=%x\n", r->Eip);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback(&crash)){
- runtime·traceback(r->Eip, r->Esp, 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(r);
- }
-
- if(crash)
- runtime·crash();
-
- runtime·exit(2);
- return -1; // not reached
-}
-
-void
-runtime·sigenable(uint32 sig)
-{
- USED(sig);
-}
-
-void
-runtime·sigdisable(uint32 sig)
-{
- USED(sig);
-}
-
-void
-runtime·dosigprof(Context *r, G *gp, M *mp)
-{
- runtime·sigprof((uint8*)r->Eip, (uint8*)r->Esp, nil, gp, mp);
-}
diff --git a/src/pkg/runtime/os_windows_amd64.c b/src/pkg/runtime/os_windows_amd64.c
deleted file mode 100644
index 7fb973cde..000000000
--- a/src/pkg/runtime/os_windows_amd64.c
+++ /dev/null
@@ -1,144 +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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-
-void
-runtime·dumpregs(Context *r)
-{
- runtime·printf("rax %X\n", r->Rax);
- runtime·printf("rbx %X\n", r->Rbx);
- runtime·printf("rcx %X\n", r->Rcx);
- runtime·printf("rdx %X\n", r->Rdx);
- runtime·printf("rdi %X\n", r->Rdi);
- runtime·printf("rsi %X\n", r->Rsi);
- runtime·printf("rbp %X\n", r->Rbp);
- runtime·printf("rsp %X\n", r->Rsp);
- runtime·printf("r8 %X\n", r->R8 );
- runtime·printf("r9 %X\n", r->R9 );
- runtime·printf("r10 %X\n", r->R10);
- runtime·printf("r11 %X\n", r->R11);
- runtime·printf("r12 %X\n", r->R12);
- runtime·printf("r13 %X\n", r->R13);
- runtime·printf("r14 %X\n", r->R14);
- runtime·printf("r15 %X\n", r->R15);
- runtime·printf("rip %X\n", r->Rip);
- runtime·printf("rflags %X\n", r->EFlags);
- runtime·printf("cs %X\n", (uint64)r->SegCs);
- runtime·printf("fs %X\n", (uint64)r->SegFs);
- runtime·printf("gs %X\n", (uint64)r->SegGs);
-}
-
-#define DBG_PRINTEXCEPTION_C 0x40010006
-
-// Called by sigtramp from Windows VEH handler.
-// Return value signals whether the exception has been handled (-1)
-// or should be made available to other handlers in the chain (0).
-uint32
-runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
-{
- bool crash;
- uintptr *sp;
- extern byte text[], etext[];
-
- if(info->ExceptionCode == DBG_PRINTEXCEPTION_C) {
- // This exception is intended to be caught by debuggers.
- // There is a not-very-informational message like
- // "Invalid parameter passed to C runtime function"
- // sitting at info->ExceptionInformation[0] (a wchar_t*),
- // with length info->ExceptionInformation[1].
- // The default behavior is to ignore this exception,
- // but somehow returning 0 here (meaning keep going)
- // makes the program crash instead. Maybe Windows has no
- // other handler registered? In any event, ignore it.
- return -1;
- }
-
- // Only handle exception if executing instructions in Go binary
- // (not Windows library code).
- if(r->Rip < (uint64)text || (uint64)etext < r->Rip)
- return 0;
-
- switch(info->ExceptionCode) {
- case EXCEPTION_BREAKPOINT:
- // It is unclear whether this is needed, unclear whether it
- // would work, and unclear how to test it. Leave out for now.
- // This only handles breakpoint instructions written in the
- // assembly sources, not breakpoints set by a debugger, and
- // there are very few of the former.
- break;
- }
-
- if(gp != nil && runtime·issigpanic(info->ExceptionCode)) {
- // 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 = info->ExceptionCode;
- gp->sigcode0 = info->ExceptionInformation[0];
- gp->sigcode1 = info->ExceptionInformation[1];
- gp->sigpc = r->Rip;
-
- // Only push runtime·sigpanic if r->rip != 0.
- // If r->rip == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic and we
- // won't get to see who faulted.)
- if(r->Rip != 0) {
- sp = (uintptr*)r->Rsp;
- *--sp = r->Rip;
- r->Rsp = (uintptr)sp;
- }
- r->Rip = (uintptr)runtime·sigpanic;
- return -1;
- }
-
- if(runtime·panicking) // traceback already printed
- runtime·exit(2);
- runtime·panicking = 1;
-
- runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode,
- info->ExceptionInformation[0], info->ExceptionInformation[1], r->Rip);
-
-
- runtime·printf("PC=%X\n", r->Rip);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback(&crash)){
- runtime·traceback(r->Rip, r->Rsp, 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(r);
- }
-
- if(crash)
- runtime·crash();
-
- runtime·exit(2);
- return -1; // not reached
-}
-
-void
-runtime·sigenable(uint32 sig)
-{
- USED(sig);
-}
-
-void
-runtime·sigdisable(uint32 sig)
-{
- USED(sig);
-}
-
-void
-runtime·dosigprof(Context *r, G *gp, M *mp)
-{
- runtime·sigprof((uint8*)r->Rip, (uint8*)r->Rsp, nil, gp, mp);
-}
diff --git a/src/pkg/runtime/panic.c b/src/pkg/runtime/panic.c
deleted file mode 100644
index f577b37b5..000000000
--- a/src/pkg/runtime/panic.c
+++ /dev/null
@@ -1,566 +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.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "stack.h"
-#include "malloc.h"
-#include "../../cmd/ld/textflag.h"
-
-// Code related to defer, panic and recover.
-
-uint32 runtime·panicking;
-static Lock paniclk;
-
-// Each P holds pool for defers with arg sizes 8, 24, 40, 56 and 72 bytes.
-// Memory block is 40 (24 for 32 bits) bytes larger due to Defer header.
-// This maps exactly to malloc size classes.
-
-// defer size class for arg size sz
-#define DEFERCLASS(sz) (((sz)+7)>>4)
-// total size of memory block for defer with arg size sz
-#define TOTALSIZE(sz) (sizeof(Defer) - sizeof(((Defer*)nil)->args) + ROUND(sz, sizeof(uintptr)))
-
-// Allocate a Defer, usually using per-P pool.
-// Each defer must be released with freedefer.
-static Defer*
-newdefer(int32 siz)
-{
- int32 total, sc;
- Defer *d;
- P *p;
-
- d = nil;
- sc = DEFERCLASS(siz);
- if(sc < nelem(p->deferpool)) {
- p = m->p;
- d = p->deferpool[sc];
- if(d)
- p->deferpool[sc] = d->link;
- }
- if(d == nil) {
- // deferpool is empty or just a big defer
- total = TOTALSIZE(siz);
- d = runtime·malloc(total);
- }
- d->siz = siz;
- d->special = 0;
- d->link = g->defer;
- g->defer = d;
- return d;
-}
-
-// Free the given defer.
-// The defer cannot be used after this call.
-static void
-freedefer(Defer *d)
-{
- int32 sc;
- P *p;
-
- if(d->special)
- return;
- sc = DEFERCLASS(d->siz);
- if(sc < nelem(p->deferpool)) {
- p = m->p;
- d->link = p->deferpool[sc];
- p->deferpool[sc] = d;
- // No need to wipe out pointers in argp/pc/fn/args,
- // because we empty the pool before GC.
- } else
- runtime·free(d);
-}
-
-// Create a new deferred function fn with siz bytes of arguments.
-// The compiler turns a defer 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. It's OK for this to call
-// functions that split the stack.
-#pragma textflag NOSPLIT
-uintptr
-runtime·deferproc(int32 siz, FuncVal *fn, ...)
-{
- Defer *d;
-
- d = newdefer(siz);
- d->fn = fn;
- d->pc = runtime·getcallerpc(&siz);
- if(thechar == '5')
- d->argp = (byte*)(&fn+2); // skip caller's saved link register
- else
- d->argp = (byte*)(&fn+1);
- runtime·memmove(d->args, d->argp, d->siz);
-
- // deferproc returns 0 normally.
- // a deferred func that stops a panic
- // makes the deferproc return 1.
- // the code the compiler generates always
- // checks the return value and jumps to the
- // end of the function if deferproc returns != 0.
- return 0;
-}
-
-// Run a deferred function if there is one.
-// The compiler inserts a call to this at the end of any
-// function which calls defer.
-// If there is a deferred function, this will call runtime·jmpdefer,
-// which will jump to the deferred function such that it appears
-// to have been called by the caller of deferreturn at the point
-// just before deferreturn was called. The effect is that deferreturn
-// is called again and again until there are no more deferred functions.
-// Cannot split the stack because we reuse the caller's frame to
-// call the deferred function.
-
-// The single argument isn't actually used - it just has its address
-// taken so it can be matched against pending defers.
-#pragma textflag NOSPLIT
-void
-runtime·deferreturn(uintptr arg0)
-{
- Defer *d;
- byte *argp;
- FuncVal *fn;
-
- d = g->defer;
- if(d == nil)
- return;
- argp = (byte*)&arg0;
- if(d->argp != argp)
- return;
-
- // Moving arguments around.
- // Do not allow preemption here, because the garbage collector
- // won't know the form of the arguments until the jmpdefer can
- // flip the PC over to fn.
- m->locks++;
- runtime·memmove(argp, d->args, d->siz);
- fn = d->fn;
- g->defer = d->link;
- freedefer(d);
- m->locks--;
- if(m->locks == 0 && g->preempt)
- g->stackguard0 = StackPreempt;
- runtime·jmpdefer(fn, argp);
-}
-
-// Ensure that defer arg sizes that map to the same defer size class
-// also map to the same malloc size class.
-void
-runtime·testdefersizes(void)
-{
- P *p;
- int32 i, siz, defersc, mallocsc;
- int32 map[nelem(p->deferpool)];
-
- for(i=0; i<nelem(p->deferpool); i++)
- map[i] = -1;
- for(i=0;; i++) {
- defersc = DEFERCLASS(i);
- if(defersc >= nelem(p->deferpool))
- break;
- siz = TOTALSIZE(i);
- mallocsc = runtime·SizeToClass(siz);
- siz = runtime·class_to_size[mallocsc];
- // runtime·printf("defer class %d: arg size %d, block size %d(%d)\n", defersc, i, siz, mallocsc);
- if(map[defersc] < 0) {
- map[defersc] = mallocsc;
- continue;
- }
- if(map[defersc] != mallocsc) {
- runtime·printf("bad defer size class: i=%d siz=%d mallocsc=%d/%d\n",
- i, siz, map[defersc], mallocsc);
- runtime·throw("bad defer size class");
- }
- }
-}
-
-// Run all deferred functions for the current goroutine.
-static void
-rundefer(void)
-{
- Defer *d;
-
- while((d = g->defer) != nil) {
- g->defer = d->link;
- reflect·call(d->fn, (byte*)d->args, d->siz, d->siz);
- freedefer(d);
- }
-}
-
-// Print all currently active panics. Used when crashing.
-static void
-printpanics(Panic *p)
-{
- if(p->link) {
- printpanics(p->link);
- runtime·printf("\t");
- }
- runtime·printf("panic: ");
- runtime·printany(p->arg);
- if(p->recovered)
- runtime·printf(" [recovered]");
- runtime·printf("\n");
-}
-
-static void recovery(G*);
-static void abortpanic(Panic*);
-static FuncVal abortpanicV = { (void(*)(void))abortpanic };
-
-// The implementation of the predeclared function panic.
-void
-runtime·panic(Eface e)
-{
- Defer *d, dabort;
- Panic p;
- void *pc, *argp;
-
- runtime·memclr((byte*)&p, sizeof p);
- p.arg = e;
- p.link = g->panic;
- p.stackbase = g->stackbase;
- g->panic = &p;
-
- dabort.fn = &abortpanicV;
- dabort.siz = sizeof(&p);
- dabort.args[0] = &p;
- dabort.argp = NoArgs;
- dabort.special = true;
-
- for(;;) {
- d = g->defer;
- if(d == nil)
- break;
- // take defer off list in case of recursive panic
- g->defer = d->link;
- g->ispanic = true; // rock for runtime·newstack, where runtime·newstackcall ends up
- argp = d->argp;
- pc = d->pc;
-
- // The deferred function may cause another panic,
- // so newstackcall may not return. Set up a defer
- // to mark this panic aborted if that happens.
- dabort.link = g->defer;
- g->defer = &dabort;
- p.defer = d;
-
- runtime·newstackcall(d->fn, (byte*)d->args, d->siz);
-
- // Newstackcall did not panic. Remove dabort.
- if(g->defer != &dabort)
- runtime·throw("bad defer entry in panic");
- g->defer = dabort.link;
-
- freedefer(d);
- if(p.recovered) {
- g->panic = p.link;
- // Aborted panics are marked but remain on the g->panic list.
- // Recovery will unwind the stack frames containing their Panic structs.
- // Remove them from the list and free the associated defers.
- while(g->panic && g->panic->aborted) {
- freedefer(g->panic->defer);
- g->panic = g->panic->link;
- }
- if(g->panic == nil) // must be done with signal
- g->sig = 0;
- // Pass information about recovering frame to recovery.
- g->sigcode0 = (uintptr)argp;
- g->sigcode1 = (uintptr)pc;
- runtime·mcall(recovery);
- runtime·throw("recovery failed"); // mcall should not return
- }
- }
-
- // ran out of deferred calls - old-school panic now
- runtime·startpanic();
- printpanics(g->panic);
- runtime·dopanic(0); // should not return
- runtime·exit(1); // not reached
-}
-
-static void
-abortpanic(Panic *p)
-{
- p->aborted = true;
-}
-
-// 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.
-static void
-recovery(G *gp)
-{
- void *argp;
- uintptr pc;
-
- // Info about defer passed in G struct.
- argp = (void*)gp->sigcode0;
- pc = (uintptr)gp->sigcode1;
-
- // Unwind to the stack frame with d's arguments in it.
- runtime·unwindstack(gp, argp);
-
- // Make the deferproc for this d return again,
- // this time returning 1. The calling function will
- // jump to the standard return epilogue.
- // The -2*sizeof(uintptr) makes up for the
- // two extra words that are on the stack at
- // each call to deferproc.
- // (The pc we're returning to does pop pop
- // before it tests the return value.)
- // On the arm there are 2 saved LRs mixed in too.
- if(thechar == '5')
- gp->sched.sp = (uintptr)argp - 4*sizeof(uintptr);
- else
- gp->sched.sp = (uintptr)argp - 2*sizeof(uintptr);
- gp->sched.pc = pc;
- gp->sched.lr = 0;
- gp->sched.ret = 1;
- runtime·gogo(&gp->sched);
-}
-
-// Free stack frames until we hit the last one
-// or until we find the one that contains the sp.
-void
-runtime·unwindstack(G *gp, byte *sp)
-{
- Stktop *top;
- byte *stk;
-
- // Must be called from a different goroutine, usually m->g0.
- if(g == gp)
- runtime·throw("unwindstack on self");
-
- while((top = (Stktop*)gp->stackbase) != 0 && top->stackbase != 0) {
- stk = (byte*)gp->stackguard - StackGuard;
- if(stk <= sp && sp < (byte*)gp->stackbase)
- break;
- gp->stackbase = top->stackbase;
- gp->stackguard = top->stackguard;
- gp->stackguard0 = gp->stackguard;
- runtime·stackfree(gp, stk, top);
- }
-
- if(sp != nil && (sp < (byte*)gp->stackguard - StackGuard || (byte*)gp->stackbase < sp)) {
- runtime·printf("recover: %p not in [%p, %p]\n", sp, gp->stackguard - StackGuard, gp->stackbase);
- runtime·throw("bad unwindstack");
- }
-}
-
-// The implementation of the predeclared function recover.
-// Cannot split the stack because it needs to reliably
-// find the stack segment of its caller.
-#pragma textflag NOSPLIT
-void
-runtime·recover(byte *argp, GoOutput retbase, ...)
-{
- Panic *p;
- Stktop *top;
- Eface *ret;
-
- // Must be an unrecovered panic in progress.
- // Must be on a stack segment created for a deferred call during a panic.
- // Must be at the top of that segment, meaning the deferred call itself
- // and not something it called. The top frame in the segment will have
- // argument pointer argp == top - top->argsize.
- // The subtraction of g->panicwrap allows wrapper functions that
- // do not count as official calls to adjust what we consider the top frame
- // while they are active on the stack. The linker emits adjustments of
- // g->panicwrap in the prologue and epilogue of functions marked as wrappers.
- ret = (Eface*)&retbase;
- top = (Stktop*)g->stackbase;
- p = g->panic;
- if(p != nil && !p->recovered && top->panic && argp == (byte*)top - top->argsize - g->panicwrap) {
- p->recovered = 1;
- *ret = p->arg;
- } else {
- ret->type = nil;
- ret->data = nil;
- }
-}
-
-void
-runtime·startpanic(void)
-{
- if(runtime·mheap.cachealloc.size == 0) { // very early
- runtime·printf("runtime: panic before malloc heap initialized\n");
- m->mallocing = 1; // tell rest of panic not to try to malloc
- } else if(m->mcache == nil) // can happen if called from signal handler or throw
- m->mcache = runtime·allocmcache();
- switch(m->dying) {
- case 0:
- m->dying = 1;
- if(g != nil)
- g->writebuf = nil;
- runtime·xadd(&runtime·panicking, 1);
- runtime·lock(&paniclk);
- if(runtime·debug.schedtrace > 0 || runtime·debug.scheddetail > 0)
- runtime·schedtrace(true);
- runtime·freezetheworld();
- return;
- case 1:
- // Something failed while panicing, probably the print of the
- // argument to panic(). Just print a stack trace and exit.
- m->dying = 2;
- runtime·printf("panic during panic\n");
- runtime·dopanic(0);
- runtime·exit(3);
- case 2:
- // This is a genuine bug in the runtime, we couldn't even
- // print the stack trace successfully.
- m->dying = 3;
- runtime·printf("stack trace unavailable\n");
- runtime·exit(4);
- default:
- // Can't even print! Just exit.
- runtime·exit(5);
- }
-}
-
-void
-runtime·dopanic(int32 unused)
-{
- static bool didothers;
- bool crash;
- int32 t;
-
- if(g->sig != 0)
- runtime·printf("[signal %x code=%p addr=%p pc=%p]\n",
- g->sig, g->sigcode0, g->sigcode1, g->sigpc);
-
- if((t = runtime·gotraceback(&crash)) > 0){
- if(g != m->g0) {
- runtime·printf("\n");
- runtime·goroutineheader(g);
- runtime·traceback((uintptr)runtime·getcallerpc(&unused), (uintptr)runtime·getcallersp(&unused), 0, g);
- } else if(t >= 2 || m->throwing > 0) {
- runtime·printf("\nruntime stack:\n");
- runtime·traceback((uintptr)runtime·getcallerpc(&unused), (uintptr)runtime·getcallersp(&unused), 0, g);
- }
- if(!didothers) {
- didothers = true;
- runtime·tracebackothers(g);
- }
- }
- runtime·unlock(&paniclk);
- if(runtime·xadd(&runtime·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.
- static Lock deadlock;
- runtime·lock(&deadlock);
- runtime·lock(&deadlock);
- }
-
- if(crash)
- runtime·crash();
-
- runtime·exit(2);
-}
-
-void
-runtime·panicindex(void)
-{
- runtime·panicstring("index out of range");
-}
-
-void
-runtime·panicslice(void)
-{
- runtime·panicstring("slice bounds out of range");
-}
-
-void
-runtime·throwreturn(void)
-{
- // can only happen if compiler is broken
- runtime·throw("no return at end of a typed function - compiler is broken");
-}
-
-void
-runtime·throwinit(void)
-{
- // can only happen with linker skew
- runtime·throw("recursive call during initialization - linker skew");
-}
-
-bool
-runtime·canpanic(G *gp)
-{
- byte g;
-
- USED(&g); // don't use global g, it points to gsignal
-
- // 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->gcing != 0 || m->dying != 0)
- return false;
- if(gp->status != Grunning || gp->syscallsp != 0)
- return false;
-#ifdef GOOS_windows
- if(m->libcallsp != 0)
- return false;
-#endif
- return true;
-}
-
-void
-runtime·throw(int8 *s)
-{
- if(m->throwing == 0)
- m->throwing = 1;
- runtime·startpanic();
- runtime·printf("fatal error: %s\n", s);
- runtime·dopanic(0);
- *(int32*)0 = 0; // not reached
- runtime·exit(1); // even more not reached
-}
-
-void
-runtime·panicstring(int8 *s)
-{
- Eface err;
-
- // m->softfloat is set during software floating point,
- // which might cause a fault during a memory load.
- // It increments m->locks to avoid preemption.
- // If we're panicking, the software floating point frames
- // will be unwound, so decrement m->locks as they would.
- if(m->softfloat) {
- m->locks--;
- m->softfloat = 0;
- }
-
- if(m->mallocing) {
- runtime·printf("panic: %s\n", s);
- runtime·throw("panic during malloc");
- }
- if(m->gcing) {
- runtime·printf("panic: %s\n", s);
- runtime·throw("panic during gc");
- }
- if(m->locks) {
- runtime·printf("panic: %s\n", s);
- runtime·throw("panic holding locks");
- }
- runtime·newErrorCString(s, &err);
- runtime·panic(err);
-}
-
-void
-runtime·Goexit(void)
-{
- rundefer();
- runtime·goexit();
-}
-
-void
-runtime·panicdivide(void)
-{
- runtime·panicstring("integer divide by zero");
-}
diff --git a/src/pkg/runtime/print.c b/src/pkg/runtime/print.c
deleted file mode 100644
index a04708fae..000000000
--- a/src/pkg/runtime/print.c
+++ /dev/null
@@ -1,393 +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.
-
-#include "runtime.h"
-#include "type.h"
-#include "../../cmd/ld/textflag.h"
-
-//static Lock debuglock;
-
-static void vprintf(int8*, byte*);
-
-// write to goroutine-local buffer if diverting output,
-// or else standard error.
-static void
-gwrite(void *v, intgo n)
-{
- if(g == nil || g->writebuf == nil) {
- runtime·write(2, v, n);
- return;
- }
-
- if(g->writenbuf == 0)
- return;
-
- if(n > g->writenbuf)
- n = g->writenbuf;
- runtime·memmove(g->writebuf, v, n);
- g->writebuf += n;
- g->writenbuf -= n;
-}
-
-void
-runtime·dump(byte *p, int32 n)
-{
- int32 i;
-
- for(i=0; i<n; i++) {
- runtime·printpointer((byte*)(p[i]>>4));
- runtime·printpointer((byte*)(p[i]&0xf));
- if((i&15) == 15)
- runtime·prints("\n");
- else
- runtime·prints(" ");
- }
- if(n & 15)
- runtime·prints("\n");
-}
-
-void
-runtime·prints(int8 *s)
-{
- gwrite(s, runtime·findnull((byte*)s));
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·printf(int8 *s, ...)
-{
- byte *arg;
-
- arg = (byte*)(&s+1);
- vprintf(s, arg);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·snprintf(byte *buf, int32 n, int8 *s, ...)
-{
- byte *arg;
- int32 m;
-
- arg = (byte*)(&s+1);
- g->writebuf = buf;
- g->writenbuf = n-1;
- vprintf(s, arg);
- *g->writebuf = '\0';
- m = g->writebuf - buf;
- g->writenbuf = 0;
- g->writebuf = nil;
- return m;
-}
-
-// Very simple printf. Only for debugging prints.
-// Do not add to this without checking with Rob.
-static void
-vprintf(int8 *s, byte *base)
-{
- int8 *p, *lp;
- uintptr arg, siz;
- byte *v;
-
- //runtime·lock(&debuglock);
-
- lp = p = s;
- arg = (uintptr)base;
- for(; *p; p++) {
- if(*p != '%')
- continue;
- if(p > lp)
- gwrite(lp, p-lp);
- p++;
- siz = 0;
- switch(*p) {
- case 't':
- case 'c':
- siz = 1;
- break;
- case 'd': // 32-bit
- case 'x':
- arg = ROUND(arg, 4);
- siz = 4;
- break;
- case 'D': // 64-bit
- case 'U':
- case 'X':
- case 'f':
- arg = ROUND(arg, sizeof(uintreg));
- siz = 8;
- break;
- case 'C':
- arg = ROUND(arg, sizeof(uintreg));
- siz = 16;
- break;
- case 'p': // pointer-sized
- case 's':
- arg = ROUND(arg, sizeof(uintptr));
- siz = sizeof(uintptr);
- break;
- case 'S': // pointer-aligned but bigger
- arg = ROUND(arg, sizeof(uintptr));
- siz = sizeof(String);
- break;
- case 'a': // pointer-aligned but bigger
- arg = ROUND(arg, sizeof(uintptr));
- siz = sizeof(Slice);
- break;
- case 'i': // pointer-aligned but bigger
- case 'e':
- arg = ROUND(arg, sizeof(uintptr));
- siz = sizeof(Eface);
- break;
- }
- v = (byte*)arg;
- switch(*p) {
- case 'a':
- runtime·printslice(*(Slice*)v);
- break;
- case 'c':
- runtime·printbyte(*(int8*)v);
- break;
- case 'd':
- runtime·printint(*(int32*)v);
- break;
- case 'D':
- runtime·printint(*(int64*)v);
- break;
- case 'e':
- runtime·printeface(*(Eface*)v);
- break;
- case 'f':
- runtime·printfloat(*(float64*)v);
- break;
- case 'C':
- runtime·printcomplex(*(Complex128*)v);
- break;
- case 'i':
- runtime·printiface(*(Iface*)v);
- break;
- case 'p':
- runtime·printpointer(*(void**)v);
- break;
- case 's':
- runtime·prints(*(int8**)v);
- break;
- case 'S':
- runtime·printstring(*(String*)v);
- break;
- case 't':
- runtime·printbool(*(bool*)v);
- break;
- case 'U':
- runtime·printuint(*(uint64*)v);
- break;
- case 'x':
- runtime·printhex(*(uint32*)v);
- break;
- case 'X':
- runtime·printhex(*(uint64*)v);
- break;
- }
- arg += siz;
- lp = p+1;
- }
- if(p > lp)
- gwrite(lp, p-lp);
-
- //runtime·unlock(&debuglock);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·goprintf(String s, ...)
-{
- // Can assume s has terminating NUL because only
- // the Go compiler generates calls to runtime·goprintf, using
- // string constants, and all the string constants have NULs.
- vprintf((int8*)s.str, (byte*)(&s+1));
-}
-
-void
-runtime·printpc(void *p)
-{
- runtime·prints("PC=");
- runtime·printhex((uint64)runtime·getcallerpc(p));
-}
-
-void
-runtime·printbool(bool v)
-{
- if(v) {
- gwrite((byte*)"true", 4);
- return;
- }
- gwrite((byte*)"false", 5);
-}
-
-void
-runtime·printbyte(int8 c)
-{
- gwrite(&c, 1);
-}
-
-void
-runtime·printfloat(float64 v)
-{
- byte buf[20];
- int32 e, s, i, n;
- float64 h;
-
- if(ISNAN(v)) {
- gwrite("NaN", 3);
- return;
- }
- if(v == runtime·posinf) {
- gwrite("+Inf", 4);
- return;
- }
- if(v == runtime·neginf) {
- gwrite("-Inf", 4);
- return;
- }
-
- n = 7; // digits printed
- e = 0; // exp
- s = 0; // sign
- if(v == 0) {
- if(1/v == runtime·neginf)
- s = 1;
- } else {
- // sign
- if(v < 0) {
- v = -v;
- s = 1;
- }
-
- // normalize
- while(v >= 10) {
- e++;
- v /= 10;
- }
- while(v < 1) {
- e--;
- v *= 10;
- }
-
- // round
- h = 5;
- for(i=0; i<n; i++)
- h /= 10;
-
- v += h;
- if(v >= 10) {
- e++;
- v /= 10;
- }
- }
-
- // format +d.dddd+edd
- buf[0] = '+';
- if(s)
- buf[0] = '-';
- for(i=0; i<n; i++) {
- s = v;
- buf[i+2] = s+'0';
- v -= 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] = (e/100) + '0';
- buf[n+5] = (e/10)%10 + '0';
- buf[n+6] = (e%10) + '0';
- gwrite(buf, n+7);
-}
-
-void
-runtime·printcomplex(Complex128 v)
-{
- gwrite("(", 1);
- runtime·printfloat(v.real);
- runtime·printfloat(v.imag);
- gwrite("i)", 2);
-}
-
-void
-runtime·printuint(uint64 v)
-{
- byte buf[100];
- int32 i;
-
- for(i=nelem(buf)-1; i>0; i--) {
- buf[i] = v%10 + '0';
- if(v < 10)
- break;
- v = v/10;
- }
- gwrite(buf+i, nelem(buf)-i);
-}
-
-void
-runtime·printint(int64 v)
-{
- if(v < 0) {
- gwrite("-", 1);
- v = -v;
- }
- runtime·printuint(v);
-}
-
-void
-runtime·printhex(uint64 v)
-{
- static int8 *dig = "0123456789abcdef";
- byte buf[100];
- int32 i;
-
- i=nelem(buf);
- for(; v>0; v/=16)
- buf[--i] = dig[v%16];
- if(i == nelem(buf))
- buf[--i] = '0';
- buf[--i] = 'x';
- buf[--i] = '0';
- gwrite(buf+i, nelem(buf)-i);
-}
-
-void
-runtime·printpointer(void *p)
-{
- runtime·printhex((uintptr)p);
-}
-
-void
-runtime·printstring(String v)
-{
- if(v.len > runtime·maxstring) {
- gwrite("[string too long]", 17);
- return;
- }
- if(v.len > 0)
- gwrite(v.str, v.len);
-}
-
-void
-runtime·printsp(void)
-{
- gwrite(" ", 1);
-}
-
-void
-runtime·printnl(void)
-{
- gwrite("\n", 1);
-}
diff --git a/src/pkg/runtime/race.go b/src/pkg/runtime/race.go
deleted file mode 100644
index 2a9124d64..000000000
--- a/src/pkg/runtime/race.go
+++ /dev/null
@@ -1,31 +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
-
-// Public race detection API, present iff build with -race.
-
-package runtime
-
-import (
- "unsafe"
-)
-
-// RaceDisable disables handling of race events in the current goroutine.
-func RaceDisable()
-
-// RaceEnable re-enables handling of race events in the current goroutine.
-func RaceEnable()
-
-func RaceAcquire(addr unsafe.Pointer)
-func RaceRelease(addr unsafe.Pointer)
-func RaceReleaseMerge(addr unsafe.Pointer)
-
-func RaceRead(addr unsafe.Pointer)
-func RaceWrite(addr unsafe.Pointer)
-func RaceReadRange(addr unsafe.Pointer, len int)
-func RaceWriteRange(addr unsafe.Pointer, len int)
-
-func RaceSemacquire(s *uint32)
-func RaceSemrelease(s *uint32)
diff --git a/src/pkg/runtime/race/race_darwin_amd64.syso b/src/pkg/runtime/race/race_darwin_amd64.syso
deleted file mode 100644
index 249a878ef..000000000
--- a/src/pkg/runtime/race/race_darwin_amd64.syso
+++ /dev/null
Binary files differ
diff --git a/src/pkg/runtime/race/race_linux_amd64.syso b/src/pkg/runtime/race/race_linux_amd64.syso
deleted file mode 100644
index 8120484d4..000000000
--- a/src/pkg/runtime/race/race_linux_amd64.syso
+++ /dev/null
Binary files differ
diff --git a/src/pkg/runtime/race/race_windows_amd64.syso b/src/pkg/runtime/race/race_windows_amd64.syso
deleted file mode 100644
index 67db40f21..000000000
--- a/src/pkg/runtime/race/race_windows_amd64.syso
+++ /dev/null
Binary files differ
diff --git a/src/pkg/runtime/race0.c b/src/pkg/runtime/race0.c
deleted file mode 100644
index eddb0be79..000000000
--- a/src/pkg/runtime/race0.c
+++ /dev/null
@@ -1,124 +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.
-
-// Stub implementation of the race detector API.
-// +build !race
-
-#include "runtime.h"
-
-uintptr
-runtime·raceinit(void)
-{
- return 0;
-}
-
-void
-runtime·racefini(void)
-{
-}
-
-
-void
-runtime·racemapshadow(void *addr, uintptr size)
-{
- USED(addr);
- USED(size);
-}
-
-void
-runtime·racewritepc(void *addr, void *callpc, void *pc)
-{
- USED(addr);
- USED(callpc);
- USED(pc);
-}
-
-void
-runtime·racereadpc(void *addr, void *callpc, void *pc)
-{
- USED(addr);
- USED(callpc);
- USED(pc);
-}
-
-void
-runtime·racewriterangepc(void *addr, uintptr sz, void *callpc, void *pc)
-{
- USED(addr);
- USED(sz);
- USED(callpc);
- USED(pc);
-}
-
-void
-runtime·racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc)
-{
- USED(addr);
- USED(sz);
- USED(callpc);
- USED(pc);
-}
-
-void
-runtime·raceacquire(void *addr)
-{
- USED(addr);
-}
-
-void
-runtime·raceacquireg(G *gp, void *addr)
-{
- USED(gp);
- USED(addr);
-}
-
-void
-runtime·racerelease(void *addr)
-{
- USED(addr);
-}
-
-void
-runtime·racereleaseg(G *gp, void *addr)
-{
- USED(gp);
- USED(addr);
-}
-
-void
-runtime·racereleasemerge(void *addr)
-{
- USED(addr);
-}
-
-void
-runtime·racereleasemergeg(G *gp, void *addr)
-{
- USED(gp);
- USED(addr);
-}
-
-void
-runtime·racefingo(void)
-{
-}
-
-void
-runtime·racemalloc(void *p, uintptr sz)
-{
- USED(p);
- USED(sz);
-}
-
-uintptr
-runtime·racegostart(void *pc)
-{
- USED(pc);
- return 0;
-}
-
-void
-runtime·racegoend(void)
-{
-}
diff --git a/src/pkg/runtime/rdebug.goc b/src/pkg/runtime/rdebug.goc
deleted file mode 100644
index 042b30ace..000000000
--- a/src/pkg/runtime/rdebug.goc
+++ /dev/null
@@ -1,27 +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∕debug
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "stack.h"
-
-func setMaxStack(in int) (out int) {
- out = runtime·maxstacksize;
- runtime·maxstacksize = in;
-}
-
-func setGCPercent(in int) (out int) {
- out = runtime·setgcpercent(in);
-}
-
-func setMaxThreads(in int) (out int) {
- out = runtime·setmaxthreads(in);
-}
-
-func SetPanicOnFault(enabled bool) (old bool) {
- old = g->paniconfault;
- g->paniconfault = enabled;
-}
diff --git a/src/pkg/runtime/rt0_plan9_386.s b/src/pkg/runtime/rt0_plan9_386.s
deleted file mode 100644
index dad75c84d..000000000
--- a/src/pkg/runtime/rt0_plan9_386.s
+++ /dev/null
@@ -1,42 +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 "../../cmd/ld/textflag.h"
-
-TEXT _rt0_386_plan9(SB),NOSPLIT, $0
- MOVL AX, _tos(SB)
-
- // move arguments down to make room for
- // m and g at top of stack, right before Tos.
- MOVL SP, SI
- SUBL $8, SP
- MOVL SP, DI
-
- MOVL AX, CX
- SUBL SI, CX
- CLD
- REP; MOVSB
-
- // adjust argv
- SUBL SI, DI
- MOVL newargc+0(SP), CX
- LEAL newargv+4(SP), BP
-argv_fix:
- ADDL DI, 0(BP)
- ADDL $4, BP
- LOOP argv_fix
-
- CALL runtime·asminit(SB)
-
- MOVL 0(SP), AX
- LEAL 4(SP), BX
- PUSHL BX
- PUSHL AX
- PUSHL $-1
-
- JMP _rt0_go(SB)
-
-DATA runtime·isplan9(SB)/4, $1
-GLOBL runtime·isplan9(SB), $4
-GLOBL _tos(SB), $4
diff --git a/src/pkg/runtime/rt0_plan9_amd64.s b/src/pkg/runtime/rt0_plan9_amd64.s
deleted file mode 100644
index 79a7c92fc..000000000
--- a/src/pkg/runtime/rt0_plan9_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 "../../cmd/ld/textflag.h"
-
-TEXT _rt0_amd64_plan9(SB),NOSPLIT,$-8
- LEAQ 8(SP), SI // argv
- MOVQ 0(SP), DI // argc
- MOVQ $_rt0_go(SB), AX
- JMP AX
-
-DATA runtime·isplan9(SB)/4, $1
-GLOBL runtime·isplan9(SB), $4
diff --git a/src/pkg/runtime/rune.c b/src/pkg/runtime/rune.c
deleted file mode 100644
index ed867269d..000000000
--- a/src/pkg/runtime/rune.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * The authors of this software are Rob Pike and Ken Thompson.
- * Copyright (c) 2002 by Lucent Technologies.
- * Portions Copyright 2009 The Go Authors. All rights reserved.
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- */
-
-/*
- * This code is copied, with slight editing due to type differences,
- * from a subset of ../lib9/utf/rune.c
- */
-
-#include "runtime.h"
-
-enum
-{
- Bit1 = 7,
- Bitx = 6,
- Bit2 = 5,
- Bit3 = 4,
- Bit4 = 3,
- Bit5 = 2,
-
- T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */
- Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */
- T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */
- T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */
- T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */
- T5 = ((1<<(Bit5+1))-1) ^ 0xFF, /* 1111 1000 */
-
- Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */
- Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */
- Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */
- Rune4 = (1<<(Bit4+3*Bitx))-1, /* 0001 1111 1111 1111 1111 1111 */
-
- Maskx = (1<<Bitx)-1, /* 0011 1111 */
- Testx = Maskx ^ 0xFF, /* 1100 0000 */
-
- Runeerror = 0xFFFD,
- Runeself = 0x80,
-
- SurrogateMin = 0xD800,
- SurrogateMax = 0xDFFF,
-
- Bad = Runeerror,
-
- Runemax = 0x10FFFF, /* maximum rune value */
-};
-
-/*
- * Modified by Wei-Hwa Huang, Google Inc., on 2004-09-24
- * This is a slower but "safe" version of the old chartorune
- * that works on strings that are not necessarily null-terminated.
- *
- * If you know for sure that your string is null-terminated,
- * chartorune will be a bit faster.
- *
- * It is guaranteed not to attempt to access "length"
- * past the incoming pointer. This is to avoid
- * possible access violations. If the string appears to be
- * well-formed but incomplete (i.e., to get the whole Rune
- * we'd need to read past str+length) then we'll set the Rune
- * to Bad and return 0.
- *
- * Note that if we have decoding problems for other
- * reasons, we return 1 instead of 0.
- */
-int32
-runtime·charntorune(int32 *rune, uint8 *str, int32 length)
-{
- int32 c, c1, c2, c3, l;
-
- /* When we're not allowed to read anything */
- if(length <= 0) {
- goto badlen;
- }
-
- /*
- * one character sequence (7-bit value)
- * 00000-0007F => T1
- */
- c = *(uint8*)str;
- if(c < Tx) {
- *rune = c;
- return 1;
- }
-
- // If we can't read more than one character we must stop
- if(length <= 1) {
- goto badlen;
- }
-
- /*
- * two character sequence (11-bit value)
- * 0080-07FF => T2 Tx
- */
- c1 = *(uint8*)(str+1) ^ Tx;
- if(c1 & Testx)
- goto bad;
- if(c < T3) {
- if(c < T2)
- goto bad;
- l = ((c << Bitx) | c1) & Rune2;
- if(l <= Rune1)
- goto bad;
- *rune = l;
- return 2;
- }
-
- // If we can't read more than two characters we must stop
- if(length <= 2) {
- goto badlen;
- }
-
- /*
- * three character sequence (16-bit value)
- * 0800-FFFF => T3 Tx Tx
- */
- c2 = *(uint8*)(str+2) ^ Tx;
- if(c2 & Testx)
- goto bad;
- if(c < T4) {
- l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
- if(l <= Rune2)
- goto bad;
- if (SurrogateMin <= l && l <= SurrogateMax)
- goto bad;
- *rune = l;
- return 3;
- }
-
- if (length <= 3)
- goto badlen;
-
- /*
- * four character sequence (21-bit value)
- * 10000-1FFFFF => T4 Tx Tx Tx
- */
- c3 = *(uint8*)(str+3) ^ Tx;
- if (c3 & Testx)
- goto bad;
- if (c < T5) {
- l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4;
- if (l <= Rune3 || l > Runemax)
- goto bad;
- *rune = l;
- return 4;
- }
-
- // Support for 5-byte or longer UTF-8 would go here, but
- // since we don't have that, we'll just fall through to bad.
-
- /*
- * bad decoding
- */
-bad:
- *rune = Bad;
- return 1;
-badlen:
- // was return 0, but return 1 is more convenient for the runtime.
- *rune = Bad;
- return 1;
-
-}
-
-int32
-runtime·runetochar(byte *str, int32 rune) /* note: in original, arg2 was pointer */
-{
- /* Runes are signed, so convert to unsigned for range check. */
- uint32 c;
-
- /*
- * one character sequence
- * 00000-0007F => 00-7F
- */
- c = rune;
- if(c <= Rune1) {
- str[0] = c;
- return 1;
- }
-
- /*
- * two character sequence
- * 0080-07FF => T2 Tx
- */
- if(c <= Rune2) {
- str[0] = T2 | (c >> 1*Bitx);
- str[1] = Tx | (c & Maskx);
- return 2;
- }
-
- /*
- * If the Rune is out of range or a surrogate half, convert it to the error rune.
- * Do this test here because the error rune encodes to three bytes.
- * Doing it earlier would duplicate work, since an out of range
- * Rune wouldn't have fit in one or two bytes.
- */
- if (c > Runemax)
- c = Runeerror;
- if (SurrogateMin <= c && c <= SurrogateMax)
- c = Runeerror;
-
- /*
- * three character sequence
- * 0800-FFFF => T3 Tx Tx
- */
- if (c <= Rune3) {
- str[0] = T3 | (c >> 2*Bitx);
- str[1] = Tx | ((c >> 1*Bitx) & Maskx);
- str[2] = Tx | (c & Maskx);
- return 3;
- }
-
- /*
- * four character sequence (21-bit value)
- * 10000-1FFFFF => T4 Tx Tx Tx
- */
- str[0] = T4 | (c >> 3*Bitx);
- str[1] = Tx | ((c >> 2*Bitx) & Maskx);
- str[2] = Tx | ((c >> 1*Bitx) & Maskx);
- str[3] = Tx | (c & Maskx);
- return 4;
-}
diff --git a/src/pkg/runtime/runtime1.goc b/src/pkg/runtime/runtime1.goc
deleted file mode 100644
index c6f6b626a..000000000
--- a/src/pkg/runtime/runtime1.goc
+++ /dev/null
@@ -1,128 +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.
-
-package runtime
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "type.h"
-
-func GOMAXPROCS(n int) (ret int) {
- ret = runtime·gomaxprocsfunc(n);
-}
-
-func NumCPU() (ret int) {
- ret = runtime·ncpu;
-}
-
-func NumCgoCall() (ret int64) {
- M *mp;
-
- ret = 0;
- for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink)
- ret += mp->ncgocall;
-}
-
-func newParFor(nthrmax uint32) (desc *ParFor) {
- desc = runtime·parforalloc(nthrmax);
-}
-
-func parForSetup(desc *ParFor, nthr uint32, n uint32, ctx *byte, wait bool, body *byte) {
- runtime·parforsetup(desc, nthr, n, ctx, wait, *(void(**)(ParFor*, uint32))body);
-}
-
-func parForDo(desc *ParFor) {
- runtime·parfordo(desc);
-}
-
-func parForIters(desc *ParFor, tid uintptr) (start uintptr, end uintptr) {
- runtime·parforiters(desc, tid, &start, &end);
-}
-
-func gogoBytes() (x int32) {
- x = RuntimeGogoBytes;
-}
-
-func typestring(e Eface) (s String) {
- s = *e.type->string;
-}
-
-func golockedOSThread() (ret bool) {
- ret = runtime·lockedOSThread();
-}
-
-func NumGoroutine() (ret int) {
- ret = runtime·gcount();
-}
-
-func getgoroot() (out String) {
- byte *p;
-
- p = runtime·getenv("GOROOT");
- out = runtime·gostringnocopy(p);
-}
-
-/*
- * We assume that all architectures turn faults and the like
- * into apparent calls to runtime.sigpanic. If we see a "call"
- * to runtime.sigpanic, we do not back up the PC to find the
- * line number of the CALL instruction, because there is no CALL.
- */
-void runtime·sigpanic(void);
-
-func Caller(skip int) (retpc uintptr, retfile String, retline int, retbool bool) {
- Func *f, *g;
- uintptr pc;
- uintptr rpc[2];
-
- /*
- * Ask for two PCs: the one we were asked for
- * and what it called, so that we can see if it
- * "called" sigpanic.
- */
- retpc = 0;
- if(runtime·callers(1+skip-1, rpc, 2) < 2) {
- retfile = runtime·emptystring;
- retline = 0;
- retbool = false;
- } else if((f = runtime·findfunc(rpc[1])) == nil) {
- retfile = runtime·emptystring;
- retline = 0;
- retbool = true; // have retpc at least
- } else {
- retpc = rpc[1];
- pc = retpc;
- g = runtime·findfunc(rpc[0]);
- if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic))
- pc--;
- retline = runtime·funcline(f, pc, &retfile);
- retbool = true;
- }
-}
-
-func Callers(skip int, pc Slice) (retn int) {
- // runtime.callers uses pc.array==nil as a signal
- // to print a stack trace. Pick off 0-length pc here
- // so that we don't let a nil pc slice get to it.
- if(pc.len == 0)
- retn = 0;
- else
- retn = runtime·callers(skip, (uintptr*)pc.array, pc.len);
-}
-
-func runtime∕pprof·runtime_cyclesPerSecond() (res int64) {
- res = runtime·tickspersecond();
-}
-
-func sync·runtime_procPin() (p int) {
- M *mp;
-
- mp = m;
- // Disable preemption.
- mp->locks++;
- p = mp->p->id;
-}
-
-func sync·runtime_procUnpin() {
- m->locks--;
-}
diff --git a/src/pkg/runtime/sema.goc b/src/pkg/runtime/sema.goc
deleted file mode 100644
index c1e8e4e18..000000000
--- a/src/pkg/runtime/sema.goc
+++ /dev/null
@@ -1,294 +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.
-
-// Semaphore implementation exposed to Go.
-// Intended use is provide a sleep and wakeup
-// primitive that can be used in the contended case
-// of other synchronization primitives.
-// Thus it targets the same goal as Linux's futex,
-// but it has much simpler semantics.
-//
-// That is, don't think of these as semaphores.
-// Think of them as a way to implement sleep and wakeup
-// such that every sleep is paired with a single wakeup,
-// even if, due to races, the wakeup happens before the sleep.
-//
-// See Mullender and Cox, ``Semaphores in Plan 9,''
-// http://swtch.com/semaphore.pdf
-
-package sync
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
-
-typedef struct SemaWaiter SemaWaiter;
-struct SemaWaiter
-{
- uint32 volatile* addr;
- G* g;
- int64 releasetime;
- int32 nrelease; // -1 for acquire
- SemaWaiter* prev;
- SemaWaiter* next;
-};
-
-typedef struct SemaRoot SemaRoot;
-struct SemaRoot
-{
- Lock;
- SemaWaiter* head;
- SemaWaiter* tail;
- // Number of waiters. Read w/o the lock.
- uint32 volatile nwait;
-};
-
-// Prime to not correlate with any user patterns.
-#define SEMTABLESZ 251
-
-struct semtable
-{
- SemaRoot;
- uint8 pad[CacheLineSize-sizeof(SemaRoot)];
-};
-#pragma dataflag NOPTR /* mark semtable as 'no pointers', hiding from garbage collector */
-static struct semtable semtable[SEMTABLESZ];
-
-static SemaRoot*
-semroot(uint32 *addr)
-{
- return &semtable[((uintptr)addr >> 3) % SEMTABLESZ];
-}
-
-static void
-semqueue(SemaRoot *root, uint32 volatile *addr, SemaWaiter *s)
-{
- s->g = g;
- s->addr = addr;
- s->next = nil;
- s->prev = root->tail;
- if(root->tail)
- root->tail->next = s;
- else
- root->head = s;
- root->tail = s;
-}
-
-static void
-semdequeue(SemaRoot *root, SemaWaiter *s)
-{
- if(s->next)
- s->next->prev = s->prev;
- else
- root->tail = s->prev;
- if(s->prev)
- s->prev->next = s->next;
- else
- root->head = s->next;
- s->prev = nil;
- s->next = nil;
-}
-
-static int32
-cansemacquire(uint32 *addr)
-{
- uint32 v;
-
- while((v = runtime·atomicload(addr)) > 0)
- if(runtime·cas(addr, v, v-1))
- return 1;
- return 0;
-}
-
-void
-runtime·semacquire(uint32 volatile *addr, bool profile)
-{
- SemaWaiter s; // Needs to be allocated on stack, otherwise garbage collector could deallocate it
- SemaRoot *root;
- int64 t0;
-
- // Easy case.
- if(cansemacquire(addr))
- return;
-
- // Harder case:
- // increment waiter count
- // try cansemacquire one more time, return if succeeded
- // enqueue itself as a waiter
- // sleep
- // (waiter descriptor is dequeued by signaler)
- root = semroot(addr);
- t0 = 0;
- s.releasetime = 0;
- if(profile && runtime·blockprofilerate > 0) {
- t0 = runtime·cputicks();
- s.releasetime = -1;
- }
- for(;;) {
- runtime·lock(root);
- // Add ourselves to nwait to disable "easy case" in semrelease.
- runtime·xadd(&root->nwait, 1);
- // Check cansemacquire to avoid missed wakeup.
- if(cansemacquire(addr)) {
- runtime·xadd(&root->nwait, -1);
- runtime·unlock(root);
- return;
- }
- // Any semrelease after the cansemacquire knows we're waiting
- // (we set nwait above), so go to sleep.
- semqueue(root, addr, &s);
- runtime·parkunlock(root, "semacquire");
- if(cansemacquire(addr)) {
- if(t0)
- runtime·blockevent(s.releasetime - t0, 3);
- return;
- }
- }
-}
-
-void
-runtime·semrelease(uint32 volatile *addr)
-{
- SemaWaiter *s;
- SemaRoot *root;
-
- root = semroot(addr);
- runtime·xadd(addr, 1);
-
- // Easy case: no waiters?
- // This check must happen after the xadd, to avoid a missed wakeup
- // (see loop in semacquire).
- if(runtime·atomicload(&root->nwait) == 0)
- return;
-
- // Harder case: search for a waiter and wake it.
- runtime·lock(root);
- if(runtime·atomicload(&root->nwait) == 0) {
- // The count is already consumed by another goroutine,
- // so no need to wake up another goroutine.
- runtime·unlock(root);
- return;
- }
- for(s = root->head; s; s = s->next) {
- if(s->addr == addr) {
- runtime·xadd(&root->nwait, -1);
- semdequeue(root, s);
- break;
- }
- }
- runtime·unlock(root);
- if(s) {
- if(s->releasetime)
- s->releasetime = runtime·cputicks();
- runtime·ready(s->g);
- }
-}
-
-// TODO(dvyukov): move to netpoll.goc once it's used by all OSes.
-void net·runtime_Semacquire(uint32 *addr)
-{
- runtime·semacquire(addr, true);
-}
-
-void net·runtime_Semrelease(uint32 *addr)
-{
- runtime·semrelease(addr);
-}
-
-func runtime_Semacquire(addr *uint32) {
- runtime·semacquire(addr, true);
-}
-
-func runtime_Semrelease(addr *uint32) {
- runtime·semrelease(addr);
-}
-
-typedef struct SyncSema SyncSema;
-struct SyncSema
-{
- Lock;
- SemaWaiter* head;
- SemaWaiter* tail;
-};
-
-func runtime_Syncsemcheck(size uintptr) {
- if(size != sizeof(SyncSema)) {
- runtime·printf("bad SyncSema size: sync:%D runtime:%D\n", (int64)size, (int64)sizeof(SyncSema));
- runtime·throw("bad SyncSema size");
- }
-}
-
-// Syncsemacquire waits for a pairing Syncsemrelease on the same semaphore s.
-func runtime_Syncsemacquire(s *SyncSema) {
- SemaWaiter w, *wake;
- int64 t0;
-
- w.g = g;
- w.nrelease = -1;
- w.next = nil;
- w.releasetime = 0;
- t0 = 0;
- if(runtime·blockprofilerate > 0) {
- t0 = runtime·cputicks();
- w.releasetime = -1;
- }
-
- runtime·lock(s);
- if(s->head && s->head->nrelease > 0) {
- // have pending release, consume it
- wake = nil;
- s->head->nrelease--;
- if(s->head->nrelease == 0) {
- wake = s->head;
- s->head = wake->next;
- if(s->head == nil)
- s->tail = nil;
- }
- runtime·unlock(s);
- if(wake)
- runtime·ready(wake->g);
- } else {
- // enqueue itself
- if(s->tail == nil)
- s->head = &w;
- else
- s->tail->next = &w;
- s->tail = &w;
- runtime·parkunlock(s, "semacquire");
- if(t0)
- runtime·blockevent(w.releasetime - t0, 2);
- }
-}
-
-// Syncsemrelease waits for n pairing Syncsemacquire on the same semaphore s.
-func runtime_Syncsemrelease(s *SyncSema, n uint32) {
- SemaWaiter w, *wake;
-
- w.g = g;
- w.nrelease = (int32)n;
- w.next = nil;
- w.releasetime = 0;
-
- runtime·lock(s);
- while(w.nrelease > 0 && s->head && s->head->nrelease < 0) {
- // have pending acquire, satisfy it
- wake = s->head;
- s->head = wake->next;
- if(s->head == nil)
- s->tail = nil;
- if(wake->releasetime)
- wake->releasetime = runtime·cputicks();
- runtime·ready(wake->g);
- w.nrelease--;
- }
- if(w.nrelease > 0) {
- // enqueue itself
- if(s->tail == nil)
- s->head = &w;
- else
- s->tail->next = &w;
- s->tail = &w;
- runtime·parkunlock(s, "semarelease");
- } else
- runtime·unlock(s);
-}
diff --git a/src/pkg/runtime/sigqueue.goc b/src/pkg/runtime/sigqueue.goc
deleted file mode 100644
index e08bf98aa..000000000
--- a/src/pkg/runtime/sigqueue.goc
+++ /dev/null
@@ -1,165 +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.
-
-// This file implements runtime support for signal handling.
-//
-// Most synchronization primitives are not available from
-// the signal handler (it cannot block, allocate memory, or use locks)
-// so the handler communicates with a processing goroutine
-// via struct sig, below.
-//
-// sigsend() is called by the signal handler to queue a new signal.
-// signal_recv() is called by the Go program to receive a newly queued signal.
-// Synchronization between sigsend() and signal_recv() is based on the sig.state
-// variable. It can be in 3 states: 0, HASWAITER and HASSIGNAL.
-// HASWAITER means that signal_recv() is blocked on sig.Note and there are no
-// new pending signals.
-// HASSIGNAL means that sig.mask *may* contain new pending signals,
-// signal_recv() can't be blocked in this state.
-// 0 means that there are no new pending signals and signal_recv() is not blocked.
-// Transitions between states are done atomically with CAS.
-// When signal_recv() is unblocked, it resets sig.Note and rechecks sig.mask.
-// If several sigsend()'s and signal_recv() execute concurrently, it can lead to
-// unnecessary rechecks of sig.mask, but must not lead to missed signals
-// nor deadlocks.
-
-package runtime
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "cgocall.h"
-#include "../../cmd/ld/textflag.h"
-
-static struct {
- Note;
- uint32 mask[(NSIG+31)/32];
- uint32 wanted[(NSIG+31)/32];
- uint32 state;
- bool inuse;
-} sig;
-
-enum {
- HASWAITER = 1,
- HASSIGNAL = 2,
-};
-
-// Called from sighandler to send a signal back out of the signal handling thread.
-bool
-runtime·sigsend(int32 s)
-{
- uint32 bit, mask, old, new;
-
- if(!sig.inuse || s < 0 || s >= 32*nelem(sig.wanted) || !(sig.wanted[s/32]&(1U<<(s&31))))
- return false;
- bit = 1 << (s&31);
- for(;;) {
- mask = sig.mask[s/32];
- if(mask & bit)
- break; // signal already in queue
- if(runtime·cas(&sig.mask[s/32], mask, mask|bit)) {
- // Added to queue.
- // Only send a wakeup if the receiver needs a kick.
- for(;;) {
- old = runtime·atomicload(&sig.state);
- if(old == HASSIGNAL)
- break;
- if(old == HASWAITER)
- new = 0;
- else // if(old == 0)
- new = HASSIGNAL;
- if(runtime·cas(&sig.state, old, new)) {
- if (old == HASWAITER)
- runtime·notewakeup(&sig);
- break;
- }
- }
- break;
- }
- }
- return true;
-}
-
-// Called to receive the next queued signal.
-// Must only be called from a single goroutine at a time.
-func signal_recv() (m uint32) {
- static uint32 recv[nelem(sig.mask)];
- uint32 i, old, new;
-
- for(;;) {
- // Serve from local copy if there are bits left.
- for(i=0; i<NSIG; i++) {
- if(recv[i/32]&(1U<<(i&31))) {
- recv[i/32] ^= 1U<<(i&31);
- m = i;
- goto done;
- }
- }
-
- // Check and update sig.state.
- for(;;) {
- old = runtime·atomicload(&sig.state);
- if(old == HASWAITER)
- runtime·throw("inconsistent state in signal_recv");
- if(old == HASSIGNAL)
- new = 0;
- else // if(old == 0)
- new = HASWAITER;
- if(runtime·cas(&sig.state, old, new)) {
- if (new == HASWAITER) {
- runtime·notetsleepg(&sig, -1);
- runtime·noteclear(&sig);
- }
- break;
- }
- }
-
- // Get a new local copy.
- for(i=0; i<nelem(sig.mask); i++) {
- for(;;) {
- m = sig.mask[i];
- if(runtime·cas(&sig.mask[i], m, 0))
- break;
- }
- recv[i] = m;
- }
- }
-
-done:;
- // goc requires that we fall off the end of functions
- // that return values instead of using our own return
- // statements.
-}
-
-// Must only be called from a single goroutine at a time.
-func signal_enable(s uint32) {
- if(!sig.inuse) {
- // The first call to signal_enable is for us
- // to use for initialization. It does not pass
- // signal information in m.
- sig.inuse = true; // enable reception of signals; cannot disable
- runtime·noteclear(&sig);
- return;
- }
-
- if(s >= nelem(sig.wanted)*32)
- return;
- sig.wanted[s/32] |= 1U<<(s&31);
- runtime·sigenable(s);
-}
-
-// Must only be called from a single goroutine at a time.
-func signal_disable(s uint32) {
- if(s >= nelem(sig.wanted)*32)
- return;
- sig.wanted[s/32] &= ~(1U<<(s&31));
- runtime·sigdisable(s);
-}
-
-// This runs on a foreign stack, without an m or a g. No stack split.
-#pragma textflag NOSPLIT
-void
-runtime·badsignal(uintptr sig)
-{
- runtime·cgocallback((void (*)(void))runtime·sigsend, &sig, sizeof(sig));
-}
diff --git a/src/pkg/runtime/slice.goc b/src/pkg/runtime/slice.goc
deleted file mode 100644
index 2a14dafab..000000000
--- a/src/pkg/runtime/slice.goc
+++ /dev/null
@@ -1,204 +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
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "type.h"
-#include "typekind.h"
-#include "malloc.h"
-#include "race.h"
-#include "stack.h"
-#include "../../cmd/ld/textflag.h"
-
-enum
-{
- debug = 0
-};
-
-static void makeslice1(SliceType*, intgo, intgo, Slice*);
-static void growslice1(SliceType*, Slice, intgo, Slice *);
-
-// see also unsafe·NewArray
-func makeslice(t *SliceType, len int64, cap int64) (ret Slice) {
- // NOTE: The len > MaxMem/elemsize check here is not strictly necessary,
- // but it produces a 'len out of range' error instead of a 'cap out of range' error
- // when someone does make([]T, bignumber). 'cap out of range' is true too,
- // but since the cap is only being supplied implicitly, saying len is clearer.
- // See issue 4085.
- if(len < 0 || (intgo)len != len || t->elem->size > 0 && len > MaxMem / t->elem->size)
- runtime·panicstring("makeslice: len out of range");
-
- if(cap < len || (intgo)cap != cap || t->elem->size > 0 && cap > MaxMem / t->elem->size)
- runtime·panicstring("makeslice: cap out of range");
-
- makeslice1(t, len, cap, &ret);
-
- if(debug) {
- runtime·printf("makeslice(%S, %D, %D); ret=",
- *t->string, len, cap);
- runtime·printslice(ret);
- }
-}
-
-// Dummy word to use as base pointer for make([]T, 0).
-// Since you cannot take the address of such a slice,
-// you can't tell that they all have the same base pointer.
-uintptr runtime·zerobase;
-
-static void
-makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret)
-{
- ret->len = len;
- ret->cap = cap;
- ret->array = runtime·cnewarray(t->elem, cap);
-}
-
-// growslice(type *Type, x, []T, n int64) []T
-func growslice(t *SliceType, old Slice, n int64) (ret Slice) {
- int64 cap;
- void *pc;
-
- if(n < 1)
- runtime·panicstring("growslice: invalid n");
-
- cap = old.cap + n;
-
- if((intgo)cap != cap || cap < (int64)old.cap || (t->elem->size > 0 && cap > MaxMem/t->elem->size))
- runtime·panicstring("growslice: cap out of range");
-
- if(raceenabled) {
- pc = runtime·getcallerpc(&t);
- runtime·racereadrangepc(old.array, old.len*t->elem->size, pc, runtime·growslice);
- }
-
- growslice1(t, old, cap, &ret);
-
- if(debug) {
- runtime·printf("growslice(%S,", *t->string);
- runtime·printslice(old);
- runtime·printf(", new cap=%D) =", cap);
- runtime·printslice(ret);
- }
-}
-
-static void
-growslice1(SliceType *t, Slice x, intgo newcap, Slice *ret)
-{
- intgo newcap1;
- uintptr capmem, lenmem;
- int32 flag;
- Type *typ;
-
- typ = t->elem;
- if(typ->size == 0) {
- *ret = x;
- ret->cap = newcap;
- return;
- }
-
- newcap1 = x.cap;
-
- // Using newcap directly for m+m < newcap handles
- // both the case where m == 0 and also the case where
- // m+m/4 wraps around, in which case the loop
- // below might never terminate.
- if(newcap1+newcap1 < newcap)
- newcap1 = newcap;
- else {
- do {
- if(x.len < 1024)
- newcap1 += newcap1;
- else
- newcap1 += newcap1/4;
- } while(newcap1 < newcap);
- }
-
- if(newcap1 > MaxMem/typ->size)
- runtime·panicstring("growslice: cap out of range");
- capmem = runtime·roundupsize(newcap1*typ->size);
- flag = 0;
- // Can't use FlagNoZero w/o FlagNoScan, because otherwise GC can scan unitialized memory.
- if(typ->kind&KindNoPointers)
- flag = FlagNoScan|FlagNoZero;
- ret->array = runtime·mallocgc(capmem, (uintptr)typ|TypeInfo_Array, flag);
- ret->len = x.len;
- ret->cap = capmem/typ->size;
- lenmem = x.len*typ->size;
- runtime·memmove(ret->array, x.array, lenmem);
- if(typ->kind&KindNoPointers)
- runtime·memclr(ret->array+lenmem, capmem-lenmem);
-}
-
-#pragma textflag NOSPLIT
-func copy(to Slice, fm Slice, width uintptr) (ret int) {
- void *pc;
-
- if(fm.len == 0 || to.len == 0 || width == 0) {
- ret = 0;
- goto out;
- }
-
- ret = fm.len;
- if(to.len < ret)
- ret = to.len;
-
- if(raceenabled) {
- pc = runtime·getcallerpc(&to);
- runtime·racewriterangepc(to.array, ret*width, pc, runtime·copy);
- runtime·racereadrangepc(fm.array, ret*width, pc, runtime·copy);
- }
-
- if(ret == 1 && width == 1) { // common case worth about 2x to do here
- *to.array = *fm.array; // known to be a byte pointer
- } else {
- runtime·memmove(to.array, fm.array, ret*width);
- }
-
-out:
-
- if(debug) {
- runtime·prints("main·copy: to=");
- runtime·printslice(to);
- runtime·prints("; fm=");
- runtime·printslice(fm);
- runtime·prints("; width=");
- runtime·printint(width);
- runtime·prints("; ret=");
- runtime·printint(ret);
- runtime·prints("\n");
- }
-}
-
-#pragma textflag NOSPLIT
-func slicestringcopy(to Slice, fm String) (ret int) {
- void *pc;
-
- if(fm.len == 0 || to.len == 0) {
- ret = 0;
- goto out;
- }
-
- ret = fm.len;
- if(to.len < ret)
- ret = to.len;
-
- if(raceenabled) {
- pc = runtime·getcallerpc(&to);
- runtime·racewriterangepc(to.array, ret, pc, runtime·slicestringcopy);
- }
-
- runtime·memmove(to.array, fm.str, ret);
-
-out:;
-}
-
-func printslice(a Slice) {
- runtime·prints("[");
- runtime·printint(a.len);
- runtime·prints("/");
- runtime·printint(a.cap);
- runtime·prints("]");
- runtime·printpointer(a.array);
-}
diff --git a/src/pkg/runtime/stack.c b/src/pkg/runtime/stack.c
deleted file mode 100644
index 1680f004e..000000000
--- a/src/pkg/runtime/stack.c
+++ /dev/null
@@ -1,947 +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 "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "stack.h"
-#include "funcdata.h"
-#include "typekind.h"
-#include "type.h"
-#include "../../cmd/ld/textflag.h"
-
-enum
-{
- // 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
-};
-
-typedef struct StackCacheNode StackCacheNode;
-struct StackCacheNode
-{
- StackCacheNode *next;
- void* batch[StackCacheBatch-1];
-};
-
-static StackCacheNode *stackcache;
-static Lock stackcachemu;
-
-// stackcacherefill/stackcacherelease implement a global cache of stack segments.
-// The cache is required to prevent unlimited growth of per-thread caches.
-static void
-stackcacherefill(void)
-{
- StackCacheNode *n;
- int32 i, pos;
-
- runtime·lock(&stackcachemu);
- n = stackcache;
- if(n)
- stackcache = n->next;
- runtime·unlock(&stackcachemu);
- if(n == nil) {
- n = (StackCacheNode*)runtime·SysAlloc(FixedStack*StackCacheBatch, &mstats.stacks_sys);
- if(n == nil)
- runtime·throw("out of memory (stackcacherefill)");
- for(i = 0; i < StackCacheBatch-1; i++)
- n->batch[i] = (byte*)n + (i+1)*FixedStack;
- }
- pos = m->stackcachepos;
- for(i = 0; i < StackCacheBatch-1; i++) {
- m->stackcache[pos] = n->batch[i];
- pos = (pos + 1) % StackCacheSize;
- }
- m->stackcache[pos] = n;
- pos = (pos + 1) % StackCacheSize;
- m->stackcachepos = pos;
- m->stackcachecnt += StackCacheBatch;
-}
-
-static void
-stackcacherelease(void)
-{
- StackCacheNode *n;
- uint32 i, pos;
-
- pos = (m->stackcachepos - m->stackcachecnt) % StackCacheSize;
- n = (StackCacheNode*)m->stackcache[pos];
- pos = (pos + 1) % StackCacheSize;
- for(i = 0; i < StackCacheBatch-1; i++) {
- n->batch[i] = m->stackcache[pos];
- pos = (pos + 1) % StackCacheSize;
- }
- m->stackcachecnt -= StackCacheBatch;
- runtime·lock(&stackcachemu);
- n->next = stackcache;
- stackcache = n;
- runtime·unlock(&stackcachemu);
-}
-
-void*
-runtime·stackalloc(G *gp, uint32 n)
-{
- uint32 pos;
- void *v;
- bool malloced;
- Stktop *top;
-
- // 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).
- if(g != m->g0)
- runtime·throw("stackalloc not on scheduler stack");
- if((n & (n-1)) != 0)
- runtime·throw("stack size not a power of 2");
- if(StackDebug >= 1)
- runtime·printf("stackalloc %d\n", n);
-
- gp->stacksize += n;
- if(runtime·debug.efence || StackFromSystem) {
- v = runtime·SysAlloc(ROUND(n, PageSize), &mstats.stacks_sys);
- if(v == nil)
- runtime·throw("out of memory (stackalloc)");
- return v;
- }
-
- // Minimum-sized stacks are allocated with a fixed-size free-list allocator,
- // but if we need a stack of a bigger size, we fall back on malloc
- // (assuming that inside malloc all the stack frames are small,
- // so that we do not deadlock).
- malloced = true;
- if(n == FixedStack || m->mallocing) {
- if(n != FixedStack) {
- runtime·printf("stackalloc: in malloc, size=%d want %d\n", FixedStack, n);
- runtime·throw("stackalloc");
- }
- if(m->stackcachecnt == 0)
- stackcacherefill();
- pos = m->stackcachepos;
- pos = (pos - 1) % StackCacheSize;
- v = m->stackcache[pos];
- m->stackcachepos = pos;
- m->stackcachecnt--;
- m->stackinuse++;
- malloced = false;
- } else
- v = runtime·mallocgc(n, 0, FlagNoProfiling|FlagNoGC|FlagNoZero|FlagNoInvokeGC);
-
- top = (Stktop*)((byte*)v+n-sizeof(Stktop));
- runtime·memclr((byte*)top, sizeof(*top));
- top->malloced = malloced;
- return v;
-}
-
-void
-runtime·stackfree(G *gp, void *v, Stktop *top)
-{
- uint32 pos;
- uintptr n;
-
- n = (uintptr)(top+1) - (uintptr)v;
- if(StackDebug >= 1)
- runtime·printf("stackfree %p %d\n", v, (int32)n);
- gp->stacksize -= n;
- if(runtime·debug.efence || StackFromSystem) {
- if(runtime·debug.efence || StackFaultOnFree)
- runtime·SysFault(v, n);
- else
- runtime·SysFree(v, n, &mstats.stacks_sys);
- return;
- }
- if(top->malloced) {
- runtime·free(v);
- return;
- }
- if(n != FixedStack)
- runtime·throw("stackfree: bad fixed size");
- if(m->stackcachecnt == StackCacheSize)
- stackcacherelease();
- pos = m->stackcachepos;
- m->stackcache[pos] = v;
- m->stackcachepos = (pos + 1) % StackCacheSize;
- m->stackcachecnt++;
- m->stackinuse--;
-}
-
-// Called from runtime·lessstack when returning from a function which
-// allocated a new stack segment. The function's return value is in
-// m->cret.
-void
-runtime·oldstack(void)
-{
- Stktop *top;
- uint32 argsize;
- byte *sp, *old;
- uintptr *src, *dst, *dstend;
- G *gp;
- int64 goid;
- int32 oldstatus;
-
- gp = m->curg;
- top = (Stktop*)gp->stackbase;
- old = (byte*)gp->stackguard - StackGuard;
- sp = (byte*)top;
- argsize = top->argsize;
-
- if(StackDebug >= 1) {
- runtime·printf("runtime: oldstack gobuf={pc:%p sp:%p lr:%p} cret=%p argsize=%p\n",
- top->gobuf.pc, top->gobuf.sp, top->gobuf.lr, (uintptr)m->cret, (uintptr)argsize);
- }
-
- // gp->status is usually Grunning, but it could be Gsyscall if a stack overflow
- // happens during a function call inside entersyscall.
- oldstatus = gp->status;
-
- gp->sched = top->gobuf;
- gp->sched.ret = m->cret;
- m->cret = 0; // drop reference
- gp->status = Gwaiting;
- gp->waitreason = "stack unsplit";
-
- if(argsize > 0) {
- sp -= argsize;
- dst = (uintptr*)top->argp;
- dstend = dst + argsize/sizeof(*dst);
- src = (uintptr*)sp;
- while(dst < dstend)
- *dst++ = *src++;
- }
- goid = top->gobuf.g->goid; // fault if g is bad, before gogo
- USED(goid);
-
- gp->stackbase = top->stackbase;
- gp->stackguard = top->stackguard;
- gp->stackguard0 = gp->stackguard;
- gp->panicwrap = top->panicwrap;
- runtime·stackfree(gp, old, top);
-
- gp->status = oldstatus;
- runtime·gogo(&gp->sched);
-}
-
-uintptr runtime·maxstacksize = 1<<20; // enough until runtime.main sets it for real
-
-static uint8*
-mapnames[] = {
- (uint8*)"---",
- (uint8*)"scalar",
- (uint8*)"ptr",
- (uint8*)"multi",
-};
-
-// Stack frame layout
-//
-// (x86)
-// +------------------+
-// | args from caller |
-// +------------------+ <- frame->argp
-// | return address |
-// +------------------+ <- frame->varp
-// | locals |
-// +------------------+
-// | args to callee |
-// +------------------+ <- frame->sp
-//
-// (arm: TODO)
-
-typedef struct CopyableInfo CopyableInfo;
-struct CopyableInfo {
- byte *stk; // bottom address of segment
- byte *base; // top address of segment (including Stktop)
- int32 frames; // count of copyable frames (-1 = not copyable)
-};
-
-void runtime·main(void);
-
-static bool
-checkframecopy(Stkframe *frame, void *arg)
-{
- CopyableInfo *cinfo;
- Func *f;
- StackMap *stackmap;
-
- cinfo = arg;
- f = frame->fn;
- if(StackDebug >= 2)
- runtime·printf(" checking %s frame=[%p,%p] stk=[%p,%p]\n", runtime·funcname(f), frame->sp, frame->fp, cinfo->stk, cinfo->base);
- // if we're not in the segment any more, return immediately.
- if(frame->varp < cinfo->stk || frame->varp >= cinfo->base) {
- if(StackDebug >= 2)
- runtime·printf(" <next segment>\n");
- return false; // stop traceback
- }
- if(f->entry == (uintptr)runtime·main) {
- // A special routine at the TOS of the main routine.
- // We will allow it to be copied even though we don't
- // have full GC info for it (because it is written in C).
- cinfo->frames++;
- return false; // stop traceback
- }
- if(frame->varp != (byte*)frame->sp) { // not in prologue (and has at least one local or outarg)
- stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
- if(stackmap == nil) {
- cinfo->frames = -1;
- if(StackDebug >= 1)
- runtime·printf("copystack: no locals info for %s\n", runtime·funcname(f));
- return false;
- }
- if(stackmap->n <= 0) {
- cinfo->frames = -1;
- if(StackDebug >= 1)
- runtime·printf("copystack: locals size info only for %s\n", runtime·funcname(f));
- return false;
- }
- }
- if(frame->arglen != 0) {
- stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
- if(stackmap == nil) {
- cinfo->frames = -1;
- if(StackDebug >= 1)
- runtime·printf("copystack: no arg info for %s\n", runtime·funcname(f));
- return false;
- }
- }
- cinfo->frames++;
- return true; // this frame is ok; keep going
-}
-
-// If the top segment of the stack contains an uncopyable
-// frame, return -1. Otherwise return the number of frames
-// in the top segment, all of which are copyable.
-static int32
-copyabletopsegment(G *gp)
-{
- CopyableInfo cinfo;
- Defer *d;
- Func *f;
- FuncVal *fn;
- StackMap *stackmap;
-
- cinfo.stk = (byte*)gp->stackguard - StackGuard;
- cinfo.base = (byte*)gp->stackbase + sizeof(Stktop);
- cinfo.frames = 0;
-
- // Check that each frame is copyable. As a side effect,
- // count the frames.
- runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff, checkframecopy, &cinfo, false);
- if(StackDebug >= 1 && cinfo.frames != -1)
- runtime·printf("copystack: %d copyable frames\n", cinfo.frames);
-
- // Check to make sure all Defers are copyable
- for(d = gp->defer; d != nil; d = d->link) {
- if(cinfo.stk <= (byte*)d && (byte*)d < cinfo.base) {
- // Defer is on the stack. Its copyableness has
- // been established during stack walking.
- // For now, this only happens with the Defer in runtime.main.
- continue;
- }
- if(d->argp < cinfo.stk || cinfo.base <= d->argp)
- break; // a defer for the next segment
- fn = d->fn;
- if(fn == nil) // See issue 8047
- continue;
- f = runtime·findfunc((uintptr)fn->fn);
- if(f == nil)
- return -1;
-
- // Check to make sure we have an args pointer map for the defer's args.
- // We only need the args map, but we check
- // for the locals map also, because when the locals map
- // isn't provided it means the ptr map came from C and
- // C (particularly, cgo) lies to us. See issue 7695.
- stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
- if(stackmap == nil || stackmap->n <= 0)
- return -1;
- stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
- if(stackmap == nil || stackmap->n <= 0)
- return -1;
-
- if(cinfo.stk <= (byte*)fn && (byte*)fn < cinfo.base) {
- // FuncVal is on the stack. Again, its copyableness
- // was established during stack walking.
- continue;
- }
- // The FuncVal may have pointers in it, but fortunately for us
- // the compiler won't put pointers into the stack in a
- // heap-allocated FuncVal.
- // One day if we do need to check this, we'll need maps of the
- // pointerness of the closure args. The only place we have that map
- // right now is in the gc program for the FuncVal. Ugh.
- }
-
- return cinfo.frames;
-}
-
-typedef struct AdjustInfo AdjustInfo;
-struct AdjustInfo {
- byte *oldstk; // bottom address of segment
- byte *oldbase; // top address of segment (after Stktop)
- uintptr delta; // ptr distance from old to new stack (newbase - oldbase)
-};
-
-// bv describes the memory starting at address scanp.
-// Adjust any pointers contained therein.
-static void
-adjustpointers(byte **scanp, BitVector *bv, AdjustInfo *adjinfo, Func *f)
-{
- uintptr delta;
- int32 num, i;
- byte *p, *minp, *maxp;
- Type *t;
- Itab *tab;
-
- minp = adjinfo->oldstk;
- maxp = adjinfo->oldbase;
- delta = adjinfo->delta;
- num = bv->n / BitsPerPointer;
- for(i = 0; i < num; i++) {
- if(StackDebug >= 4)
- runtime·printf(" %p:%s:%p\n", &scanp[i], mapnames[bv->data[i / (32 / BitsPerPointer)] >> (i * BitsPerPointer & 31) & 3], scanp[i]);
- switch(bv->data[i / (32 / BitsPerPointer)] >> (i * BitsPerPointer & 31) & 3) {
- case BitsDead:
- if(runtime·debug.gcdead)
- scanp[i] = (byte*)PoisonStack;
- break;
- case BitsScalar:
- break;
- case BitsPointer:
- p = scanp[i];
- if(f != nil && (byte*)0 < p && (p < (byte*)PageSize || (uintptr)p == PoisonGC || (uintptr)p == PoisonStack)) {
- // Looks like a junk value in a pointer slot.
- // Live analysis wrong?
- m->traceback = 2;
- runtime·printf("runtime: bad pointer in frame %s at %p: %p\n", runtime·funcname(f), &scanp[i], p);
- runtime·throw("bad pointer!");
- }
- if(minp <= p && p < maxp) {
- if(StackDebug >= 3)
- runtime·printf("adjust ptr %p %s\n", p, runtime·funcname(f));
- scanp[i] = p + delta;
- }
- break;
- case BitsMultiWord:
- switch(bv->data[(i+1) / (32 / BitsPerPointer)] >> ((i+1) * BitsPerPointer & 31) & 3) {
- case BitsString:
- // string referents are never on the stack, never need to be adjusted
- i++; // skip len
- break;
- case BitsSlice:
- p = scanp[i];
- if(minp <= p && p < maxp) {
- if(StackDebug >= 3)
- runtime·printf("adjust slice %p\n", p);
- scanp[i] = p + delta;
- }
- i += 2; // skip len, cap
- break;
- case BitsEface:
- t = (Type*)scanp[i];
- if(t != nil && (t->size > PtrSize || (t->kind & KindNoPointers) == 0)) {
- p = scanp[i+1];
- if(minp <= p && p < maxp) {
- if(StackDebug >= 3)
- runtime·printf("adjust eface %p\n", p);
- if(t->size > PtrSize) // currently we always allocate such objects on the heap
- runtime·throw("large interface value found on stack");
- scanp[i+1] = p + delta;
- }
- }
- i++;
- break;
- case BitsIface:
- tab = (Itab*)scanp[i];
- if(tab != nil) {
- t = tab->type;
- //runtime·printf(" type=%p\n", t);
- if(t->size > PtrSize || (t->kind & KindNoPointers) == 0) {
- p = scanp[i+1];
- if(minp <= p && p < maxp) {
- if(StackDebug >= 3)
- runtime·printf("adjust iface %p\n", p);
- if(t->size > PtrSize) // currently we always allocate such objects on the heap
- runtime·throw("large interface value found on stack");
- scanp[i+1] = p + delta;
- }
- }
- }
- i++;
- break;
- }
- break;
- }
- }
-}
-
-// Note: the argument/return area is adjusted by the callee.
-static bool
-adjustframe(Stkframe *frame, void *arg)
-{
- AdjustInfo *adjinfo;
- Func *f;
- StackMap *stackmap;
- int32 pcdata;
- BitVector bv;
- uintptr targetpc;
-
- adjinfo = arg;
- f = frame->fn;
- if(StackDebug >= 2)
- runtime·printf(" adjusting %s frame=[%p,%p] pc=%p continpc=%p\n", runtime·funcname(f), frame->sp, frame->fp, frame->pc, frame->continpc);
- if(f->entry == (uintptr)runtime·main)
- return true;
- targetpc = frame->continpc;
- if(targetpc == 0) {
- // Frame is dead.
- return true;
- }
- if(targetpc != f->entry)
- targetpc--;
- pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, targetpc);
- if(pcdata == -1)
- pcdata = 0; // in prologue
-
- // adjust local pointers
- if(frame->varp != (byte*)frame->sp) {
- stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
- if(stackmap == nil)
- runtime·throw("no locals info");
- if(stackmap->n <= 0)
- runtime·throw("locals size info only");
- bv = runtime·stackmapdata(stackmap, pcdata);
- if(StackDebug >= 3)
- runtime·printf(" locals\n");
- adjustpointers((byte**)frame->varp - bv.n / BitsPerPointer, &bv, adjinfo, f);
- }
- // adjust inargs and outargs
- if(frame->arglen != 0) {
- stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
- if(stackmap == nil)
- runtime·throw("no arg info");
- bv = runtime·stackmapdata(stackmap, pcdata);
- if(StackDebug >= 3)
- runtime·printf(" args\n");
- adjustpointers((byte**)frame->argp, &bv, adjinfo, nil);
- }
- return true;
-}
-
-static void
-adjustctxt(G *gp, AdjustInfo *adjinfo)
-{
- if(adjinfo->oldstk <= (byte*)gp->sched.ctxt && (byte*)gp->sched.ctxt < adjinfo->oldbase)
- gp->sched.ctxt = (byte*)gp->sched.ctxt + adjinfo->delta;
-}
-
-static void
-adjustdefers(G *gp, AdjustInfo *adjinfo)
-{
- Defer *d, **dp;
- Func *f;
- FuncVal *fn;
- StackMap *stackmap;
- BitVector bv;
-
- for(dp = &gp->defer, d = *dp; d != nil; dp = &d->link, d = *dp) {
- if(adjinfo->oldstk <= (byte*)d && (byte*)d < adjinfo->oldbase) {
- // The Defer record is on the stack. Its fields will
- // get adjusted appropriately.
- // This only happens for runtime.main now, but a compiler
- // optimization could do more of this.
- *dp = (Defer*)((byte*)d + adjinfo->delta);
- continue;
- }
- if(d->argp < adjinfo->oldstk || adjinfo->oldbase <= d->argp)
- break; // a defer for the next segment
- fn = d->fn;
- if(fn == nil) {
- // Defer of nil function. It will panic when run, and there
- // aren't any args to adjust. See issue 8047.
- d->argp += adjinfo->delta;
- continue;
- }
- f = runtime·findfunc((uintptr)fn->fn);
- if(f == nil)
- runtime·throw("can't adjust unknown defer");
- if(StackDebug >= 4)
- runtime·printf(" checking defer %s\n", runtime·funcname(f));
- // Defer's FuncVal might be on the stack
- if(adjinfo->oldstk <= (byte*)fn && (byte*)fn < adjinfo->oldbase) {
- if(StackDebug >= 3)
- runtime·printf(" adjust defer fn %s\n", runtime·funcname(f));
- d->fn = (FuncVal*)((byte*)fn + adjinfo->delta);
- } else {
- // deferred function's args might point into the stack.
- if(StackDebug >= 3)
- runtime·printf(" adjust deferred args for %s\n", runtime·funcname(f));
- stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
- if(stackmap == nil)
- runtime·throw("runtime: deferred function has no arg ptr map");
- bv = runtime·stackmapdata(stackmap, 0);
- adjustpointers(d->args, &bv, adjinfo, f);
- }
- d->argp += adjinfo->delta;
- }
-}
-
-// Copies the top stack segment of gp to a new stack segment of a
-// different size. The top segment must contain nframes frames.
-static void
-copystack(G *gp, uintptr nframes, uintptr newsize)
-{
- byte *oldstk, *oldbase, *newstk, *newbase;
- uintptr oldsize, used;
- AdjustInfo adjinfo;
- Stktop *oldtop, *newtop;
- bool malloced;
-
- if(gp->syscallstack != 0)
- runtime·throw("can't handle stack copy in syscall yet");
- oldstk = (byte*)gp->stackguard - StackGuard;
- oldbase = (byte*)gp->stackbase + sizeof(Stktop);
- oldsize = oldbase - oldstk;
- used = oldbase - (byte*)gp->sched.sp;
- oldtop = (Stktop*)gp->stackbase;
-
- // allocate new stack
- newstk = runtime·stackalloc(gp, newsize);
- newbase = newstk + newsize;
- newtop = (Stktop*)(newbase - sizeof(Stktop));
- malloced = newtop->malloced;
-
- if(StackDebug >= 1)
- runtime·printf("copystack [%p %p]/%d -> [%p %p]/%d\n", oldstk, oldbase, (int32)oldsize, newstk, newbase, (int32)newsize);
- USED(oldsize);
-
- // adjust pointers in the to-be-copied frames
- adjinfo.oldstk = oldstk;
- adjinfo.oldbase = oldbase;
- adjinfo.delta = newbase - oldbase;
- runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, nframes, adjustframe, &adjinfo, false);
-
- // adjust other miscellaneous things that have pointers into stacks.
- adjustctxt(gp, &adjinfo);
- adjustdefers(gp, &adjinfo);
-
- // copy the stack (including Stktop) to the new location
- runtime·memmove(newbase - used, oldbase - used, used);
- newtop->malloced = malloced;
-
- // Swap out old stack for new one
- gp->stackbase = (uintptr)newtop;
- gp->stackguard = (uintptr)newstk + StackGuard;
- gp->stackguard0 = (uintptr)newstk + StackGuard; // NOTE: might clobber a preempt request
- if(gp->stack0 == (uintptr)oldstk)
- gp->stack0 = (uintptr)newstk;
- gp->sched.sp = (uintptr)(newbase - used);
-
- // free old stack
- runtime·stackfree(gp, oldstk, oldtop);
-}
-
-// round x up to a power of 2.
-int32
-runtime·round2(int32 x)
-{
- int32 s;
-
- s = 0;
- while((1 << s) < x)
- s++;
- return 1 << s;
-}
-
-// Called from runtime·newstackcall or from runtime·morestack when a new
-// stack segment is needed. Allocate a new stack big enough for
-// m->moreframesize bytes, copy m->moreargsize bytes to the new frame,
-// and then act as though runtime·lessstack called the function at
-// m->morepc.
-void
-runtime·newstack(void)
-{
- int32 framesize, argsize, oldstatus, oldsize, newsize, nframes;
- Stktop *top, *oldtop;
- byte *stk, *oldstk, *oldbase;
- uintptr sp;
- uintptr *src, *dst, *dstend;
- G *gp;
- Gobuf label, morebuf;
- void *moreargp;
- bool newstackcall;
-
- if(m->forkstackguard)
- runtime·throw("split stack after fork");
- if(m->morebuf.g != m->curg) {
- runtime·printf("runtime: newstack called from g=%p\n"
- "\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n",
- m->morebuf.g, m, m->curg, m->g0, m->gsignal);
- runtime·throw("runtime: wrong goroutine in newstack");
- }
-
- // gp->status is usually Grunning, but it could be Gsyscall if a stack overflow
- // happens during a function call inside entersyscall.
- gp = m->curg;
- oldstatus = gp->status;
-
- framesize = m->moreframesize;
- argsize = m->moreargsize;
- moreargp = m->moreargp;
- m->moreargp = nil;
- morebuf = m->morebuf;
- m->morebuf.pc = (uintptr)nil;
- m->morebuf.lr = (uintptr)nil;
- m->morebuf.sp = (uintptr)nil;
- gp->status = Gwaiting;
- gp->waitreason = "stack growth";
- newstackcall = framesize==1;
- if(newstackcall)
- framesize = 0;
-
- // For newstackcall the context already points to beginning of runtime·newstackcall.
- if(!newstackcall)
- runtime·rewindmorestack(&gp->sched);
-
- sp = gp->sched.sp;
- if(thechar == '6' || thechar == '8') {
- // The call to morestack cost a word.
- sp -= sizeof(uintptr);
- }
- if(StackDebug >= 1 || sp < gp->stackguard - StackGuard) {
- runtime·printf("runtime: newstack framesize=%p argsize=%p sp=%p stack=[%p, %p]\n"
- "\tmorebuf={pc:%p sp:%p lr:%p}\n"
- "\tsched={pc:%p sp:%p lr:%p ctxt:%p}\n",
- (uintptr)framesize, (uintptr)argsize, sp, gp->stackguard - StackGuard, gp->stackbase,
- m->morebuf.pc, m->morebuf.sp, m->morebuf.lr,
- gp->sched.pc, gp->sched.sp, gp->sched.lr, gp->sched.ctxt);
- }
- if(sp < gp->stackguard - StackGuard) {
- runtime·printf("runtime: split stack overflow: %p < %p\n", sp, gp->stackguard - StackGuard);
- runtime·throw("runtime: split stack overflow");
- }
-
- if(argsize % sizeof(uintptr) != 0) {
- runtime·printf("runtime: stack growth with misaligned argsize %d\n", argsize);
- runtime·throw("runtime: stack growth argsize");
- }
-
- if(gp->stackguard0 == (uintptr)StackPreempt) {
- if(gp == m->g0)
- runtime·throw("runtime: preempt g0");
- if(oldstatus == Grunning && m->p == nil && m->locks == 0)
- runtime·throw("runtime: g is running but p is not");
- if(oldstatus == Gsyscall && m->locks == 0)
- runtime·throw("runtime: stack growth during syscall");
- // Be conservative about where we preempt.
- // We are interested in preempting user Go code, not runtime code.
- if(oldstatus != Grunning || m->locks || m->mallocing || m->gcing || m->p->status != Prunning) {
- // Let the goroutine keep running for now.
- // gp->preempt is set, so it will be preempted next time.
- gp->stackguard0 = gp->stackguard;
- gp->status = oldstatus;
- runtime·gogo(&gp->sched); // never return
- }
- // Act like goroutine called runtime.Gosched.
- gp->status = oldstatus;
- runtime·gosched0(gp); // never return
- }
-
- // If every frame on the top segment is copyable, allocate a bigger segment
- // and move the segment instead of allocating a new segment.
- if(runtime·copystack) {
- if(!runtime·precisestack)
- runtime·throw("can't copy stacks without precise stacks");
- nframes = copyabletopsegment(gp);
- if(nframes != -1) {
- oldstk = (byte*)gp->stackguard - StackGuard;
- oldbase = (byte*)gp->stackbase + sizeof(Stktop);
- oldsize = oldbase - oldstk;
- newsize = oldsize * 2;
- copystack(gp, nframes, newsize);
- if(StackDebug >= 1)
- runtime·printf("stack grow done\n");
- if(gp->stacksize > runtime·maxstacksize) {
- runtime·printf("runtime: goroutine stack exceeds %D-byte limit\n", (uint64)runtime·maxstacksize);
- runtime·throw("stack overflow");
- }
- gp->status = oldstatus;
- runtime·gogo(&gp->sched);
- }
- // TODO: if stack is uncopyable because we're in C code, patch return value at
- // end of C code to trigger a copy as soon as C code exits. That way, we'll
- // have stack available if we get this deep again.
- }
-
- // allocate new segment.
- framesize += argsize;
- framesize += StackExtra; // room for more functions, Stktop.
- if(framesize < StackMin)
- framesize = StackMin;
- framesize += StackSystem;
- framesize = runtime·round2(framesize);
- stk = runtime·stackalloc(gp, framesize);
- if(gp->stacksize > runtime·maxstacksize) {
- runtime·printf("runtime: goroutine stack exceeds %D-byte limit\n", (uint64)runtime·maxstacksize);
- runtime·throw("stack overflow");
- }
- top = (Stktop*)(stk+framesize-sizeof(*top));
-
- if(StackDebug >= 1) {
- runtime·printf("\t-> new stack [%p, %p]\n", stk, top);
- }
-
- top->stackbase = gp->stackbase;
- top->stackguard = gp->stackguard;
- top->gobuf = morebuf;
- top->argp = moreargp;
- top->argsize = argsize;
-
- // copy flag from panic
- top->panic = gp->ispanic;
- gp->ispanic = false;
-
- // if this isn't a panic, maybe we're splitting the stack for a panic.
- // if we're splitting in the top frame, propagate the panic flag
- // forward so that recover will know we're in a panic.
- oldtop = (Stktop*)top->stackbase;
- if(oldtop != nil && oldtop->panic && top->argp == (byte*)oldtop - oldtop->argsize - gp->panicwrap)
- top->panic = true;
-
- top->panicwrap = gp->panicwrap;
- gp->panicwrap = 0;
-
- gp->stackbase = (uintptr)top;
- gp->stackguard = (uintptr)stk + StackGuard;
- gp->stackguard0 = gp->stackguard;
-
- sp = (uintptr)top;
- if(argsize > 0) {
- sp -= argsize;
- dst = (uintptr*)sp;
- dstend = dst + argsize/sizeof(*dst);
- src = (uintptr*)top->argp;
- while(dst < dstend)
- *dst++ = *src++;
- }
- if(thechar == '5') {
- // caller would have saved its LR below args.
- sp -= sizeof(void*);
- *(void**)sp = nil;
- }
-
- // Continue as if lessstack had just called m->morepc
- // (the PC that decided to grow the stack).
- runtime·memclr((byte*)&label, sizeof label);
- label.sp = sp;
- label.pc = (uintptr)runtime·lessstack;
- label.g = m->curg;
- if(newstackcall)
- runtime·gostartcallfn(&label, (FuncVal*)m->cret);
- else {
- runtime·gostartcall(&label, (void(*)(void))gp->sched.pc, gp->sched.ctxt);
- gp->sched.ctxt = nil;
- }
- gp->status = oldstatus;
- runtime·gogo(&label);
-
- *(int32*)345 = 123; // never return
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·nilfunc(void)
-{
- *(byte*)0 = 0;
-}
-
-// adjust Gobuf as if it executed a call to fn
-// and then did an immediate gosave.
-void
-runtime·gostartcallfn(Gobuf *gobuf, FuncVal *fv)
-{
- void *fn;
-
- if(fv != nil)
- fn = fv->fn;
- else
- fn = runtime·nilfunc;
- runtime·gostartcall(gobuf, fn, fv);
-}
-
-// Maybe shrink the stack being used by gp.
-// Called at garbage collection time.
-void
-runtime·shrinkstack(G *gp)
-{
- int32 nframes;
- byte *oldstk, *oldbase;
- uintptr used, oldsize, newsize;
- MSpan *span;
-
- if(!runtime·copystack)
- return;
- oldstk = (byte*)gp->stackguard - StackGuard;
- oldbase = (byte*)gp->stackbase + sizeof(Stktop);
- oldsize = oldbase - oldstk;
- newsize = oldsize / 2;
- if(newsize < FixedStack)
- return; // don't shrink below the minimum-sized stack
- used = oldbase - (byte*)gp->sched.sp;
- if(used >= oldsize / 4)
- return; // still using at least 1/4 of the segment.
-
- // To shrink to less than 1/2 a page, we need to copy.
- if(newsize < PageSize/2) {
- if(gp->syscallstack != (uintptr)nil) // TODO: can we handle this case?
- return;
-#ifdef GOOS_windows
- if(gp->m != nil && gp->m->libcallsp != 0)
- return;
-#endif
- nframes = copyabletopsegment(gp);
- if(nframes == -1)
- return;
- copystack(gp, nframes, newsize);
- return;
- }
-
- // To shrink a stack of one page size or more, we can shrink it
- // without copying. Just deallocate the lower half.
- span = runtime·MHeap_LookupMaybe(&runtime·mheap, oldstk);
- if(span == nil)
- return; // stack allocated outside heap. Can't shrink it. Can happen if stack is allocated while inside malloc. TODO: shrink by copying?
- if(span->elemsize != oldsize)
- runtime·throw("span element size doesn't match stack size");
- if((uintptr)oldstk != span->start << PageShift)
- runtime·throw("stack not at start of span");
-
- if(StackDebug)
- runtime·printf("shrinking stack in place %p %X->%X\n", oldstk, oldsize, newsize);
-
- // new stack guard for smaller stack
- gp->stackguard = (uintptr)oldstk + newsize + StackGuard;
- gp->stackguard0 = (uintptr)oldstk + newsize + StackGuard;
- if(gp->stack0 == (uintptr)oldstk)
- gp->stack0 = (uintptr)oldstk + newsize;
- gp->stacksize -= oldsize - newsize;
-
- // Free bottom half of the stack.
- if(runtime·debug.efence || StackFromSystem) {
- if(runtime·debug.efence || StackFaultOnFree)
- runtime·SysFault(oldstk, newsize);
- else
- runtime·SysFree(oldstk, newsize, &mstats.stacks_sys);
- return;
- }
- // First, we trick malloc into thinking
- // we allocated the stack as two separate half-size allocs. Then the
- // free() call does the rest of the work for us.
- runtime·MSpan_EnsureSwept(span);
- runtime·MHeap_SplitSpan(&runtime·mheap, span);
- runtime·free(oldstk);
-}
diff --git a/src/pkg/runtime/stack_gen_test.go b/src/pkg/runtime/stack_gen_test.go
deleted file mode 100644
index 28101062c..000000000
--- a/src/pkg/runtime/stack_gen_test.go
+++ /dev/null
@@ -1,1473 +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_test
-
-import (
- . "runtime"
-)
-
-var splitTests = []func() (uintptr, uintptr){
- // Edit .+1,/^}/-1|seq 4 4 5000 | sed 's/.*/ stack&,/' | fmt
- stack4, stack8, stack12, stack16, stack20, stack24, stack28,
- stack32, stack36, stack40, stack44, stack48, stack52, stack56,
- stack60, stack64, stack68, stack72, stack76, stack80, stack84,
- stack88, stack92, stack96, stack100, stack104, stack108, stack112,
- stack116, stack120, stack124, stack128, stack132, stack136,
- stack140, stack144, stack148, stack152, stack156, stack160,
- stack164, stack168, stack172, stack176, stack180, stack184,
- stack188, stack192, stack196, stack200, stack204, stack208,
- stack212, stack216, stack220, stack224, stack228, stack232,
- stack236, stack240, stack244, stack248, stack252, stack256,
- stack260, stack264, stack268, stack272, stack276, stack280,
- stack284, stack288, stack292, stack296, stack300, stack304,
- stack308, stack312, stack316, stack320, stack324, stack328,
- stack332, stack336, stack340, stack344, stack348, stack352,
- stack356, stack360, stack364, stack368, stack372, stack376,
- stack380, stack384, stack388, stack392, stack396, stack400,
- stack404, stack408, stack412, stack416, stack420, stack424,
- stack428, stack432, stack436, stack440, stack444, stack448,
- stack452, stack456, stack460, stack464, stack468, stack472,
- stack476, stack480, stack484, stack488, stack492, stack496,
- stack500, stack504, stack508, stack512, stack516, stack520,
- stack524, stack528, stack532, stack536, stack540, stack544,
- stack548, stack552, stack556, stack560, stack564, stack568,
- stack572, stack576, stack580, stack584, stack588, stack592,
- stack596, stack600, stack604, stack608, stack612, stack616,
- stack620, stack624, stack628, stack632, stack636, stack640,
- stack644, stack648, stack652, stack656, stack660, stack664,
- stack668, stack672, stack676, stack680, stack684, stack688,
- stack692, stack696, stack700, stack704, stack708, stack712,
- stack716, stack720, stack724, stack728, stack732, stack736,
- stack740, stack744, stack748, stack752, stack756, stack760,
- stack764, stack768, stack772, stack776, stack780, stack784,
- stack788, stack792, stack796, stack800, stack804, stack808,
- stack812, stack816, stack820, stack824, stack828, stack832,
- stack836, stack840, stack844, stack848, stack852, stack856,
- stack860, stack864, stack868, stack872, stack876, stack880,
- stack884, stack888, stack892, stack896, stack900, stack904,
- stack908, stack912, stack916, stack920, stack924, stack928,
- stack932, stack936, stack940, stack944, stack948, stack952,
- stack956, stack960, stack964, stack968, stack972, stack976,
- stack980, stack984, stack988, stack992, stack996, stack1000,
- stack1004, stack1008, stack1012, stack1016, stack1020, stack1024,
- stack1028, stack1032, stack1036, stack1040, stack1044, stack1048,
- stack1052, stack1056, stack1060, stack1064, stack1068, stack1072,
- stack1076, stack1080, stack1084, stack1088, stack1092, stack1096,
- stack1100, stack1104, stack1108, stack1112, stack1116, stack1120,
- stack1124, stack1128, stack1132, stack1136, stack1140, stack1144,
- stack1148, stack1152, stack1156, stack1160, stack1164, stack1168,
- stack1172, stack1176, stack1180, stack1184, stack1188, stack1192,
- stack1196, stack1200, stack1204, stack1208, stack1212, stack1216,
- stack1220, stack1224, stack1228, stack1232, stack1236, stack1240,
- stack1244, stack1248, stack1252, stack1256, stack1260, stack1264,
- stack1268, stack1272, stack1276, stack1280, stack1284, stack1288,
- stack1292, stack1296, stack1300, stack1304, stack1308, stack1312,
- stack1316, stack1320, stack1324, stack1328, stack1332, stack1336,
- stack1340, stack1344, stack1348, stack1352, stack1356, stack1360,
- stack1364, stack1368, stack1372, stack1376, stack1380, stack1384,
- stack1388, stack1392, stack1396, stack1400, stack1404, stack1408,
- stack1412, stack1416, stack1420, stack1424, stack1428, stack1432,
- stack1436, stack1440, stack1444, stack1448, stack1452, stack1456,
- stack1460, stack1464, stack1468, stack1472, stack1476, stack1480,
- stack1484, stack1488, stack1492, stack1496, stack1500, stack1504,
- stack1508, stack1512, stack1516, stack1520, stack1524, stack1528,
- stack1532, stack1536, stack1540, stack1544, stack1548, stack1552,
- stack1556, stack1560, stack1564, stack1568, stack1572, stack1576,
- stack1580, stack1584, stack1588, stack1592, stack1596, stack1600,
- stack1604, stack1608, stack1612, stack1616, stack1620, stack1624,
- stack1628, stack1632, stack1636, stack1640, stack1644, stack1648,
- stack1652, stack1656, stack1660, stack1664, stack1668, stack1672,
- stack1676, stack1680, stack1684, stack1688, stack1692, stack1696,
- stack1700, stack1704, stack1708, stack1712, stack1716, stack1720,
- stack1724, stack1728, stack1732, stack1736, stack1740, stack1744,
- stack1748, stack1752, stack1756, stack1760, stack1764, stack1768,
- stack1772, stack1776, stack1780, stack1784, stack1788, stack1792,
- stack1796, stack1800, stack1804, stack1808, stack1812, stack1816,
- stack1820, stack1824, stack1828, stack1832, stack1836, stack1840,
- stack1844, stack1848, stack1852, stack1856, stack1860, stack1864,
- stack1868, stack1872, stack1876, stack1880, stack1884, stack1888,
- stack1892, stack1896, stack1900, stack1904, stack1908, stack1912,
- stack1916, stack1920, stack1924, stack1928, stack1932, stack1936,
- stack1940, stack1944, stack1948, stack1952, stack1956, stack1960,
- stack1964, stack1968, stack1972, stack1976, stack1980, stack1984,
- stack1988, stack1992, stack1996, stack2000, stack2004, stack2008,
- stack2012, stack2016, stack2020, stack2024, stack2028, stack2032,
- stack2036, stack2040, stack2044, stack2048, stack2052, stack2056,
- stack2060, stack2064, stack2068, stack2072, stack2076, stack2080,
- stack2084, stack2088, stack2092, stack2096, stack2100, stack2104,
- stack2108, stack2112, stack2116, stack2120, stack2124, stack2128,
- stack2132, stack2136, stack2140, stack2144, stack2148, stack2152,
- stack2156, stack2160, stack2164, stack2168, stack2172, stack2176,
- stack2180, stack2184, stack2188, stack2192, stack2196, stack2200,
- stack2204, stack2208, stack2212, stack2216, stack2220, stack2224,
- stack2228, stack2232, stack2236, stack2240, stack2244, stack2248,
- stack2252, stack2256, stack2260, stack2264, stack2268, stack2272,
- stack2276, stack2280, stack2284, stack2288, stack2292, stack2296,
- stack2300, stack2304, stack2308, stack2312, stack2316, stack2320,
- stack2324, stack2328, stack2332, stack2336, stack2340, stack2344,
- stack2348, stack2352, stack2356, stack2360, stack2364, stack2368,
- stack2372, stack2376, stack2380, stack2384, stack2388, stack2392,
- stack2396, stack2400, stack2404, stack2408, stack2412, stack2416,
- stack2420, stack2424, stack2428, stack2432, stack2436, stack2440,
- stack2444, stack2448, stack2452, stack2456, stack2460, stack2464,
- stack2468, stack2472, stack2476, stack2480, stack2484, stack2488,
- stack2492, stack2496, stack2500, stack2504, stack2508, stack2512,
- stack2516, stack2520, stack2524, stack2528, stack2532, stack2536,
- stack2540, stack2544, stack2548, stack2552, stack2556, stack2560,
- stack2564, stack2568, stack2572, stack2576, stack2580, stack2584,
- stack2588, stack2592, stack2596, stack2600, stack2604, stack2608,
- stack2612, stack2616, stack2620, stack2624, stack2628, stack2632,
- stack2636, stack2640, stack2644, stack2648, stack2652, stack2656,
- stack2660, stack2664, stack2668, stack2672, stack2676, stack2680,
- stack2684, stack2688, stack2692, stack2696, stack2700, stack2704,
- stack2708, stack2712, stack2716, stack2720, stack2724, stack2728,
- stack2732, stack2736, stack2740, stack2744, stack2748, stack2752,
- stack2756, stack2760, stack2764, stack2768, stack2772, stack2776,
- stack2780, stack2784, stack2788, stack2792, stack2796, stack2800,
- stack2804, stack2808, stack2812, stack2816, stack2820, stack2824,
- stack2828, stack2832, stack2836, stack2840, stack2844, stack2848,
- stack2852, stack2856, stack2860, stack2864, stack2868, stack2872,
- stack2876, stack2880, stack2884, stack2888, stack2892, stack2896,
- stack2900, stack2904, stack2908, stack2912, stack2916, stack2920,
- stack2924, stack2928, stack2932, stack2936, stack2940, stack2944,
- stack2948, stack2952, stack2956, stack2960, stack2964, stack2968,
- stack2972, stack2976, stack2980, stack2984, stack2988, stack2992,
- stack2996, stack3000, stack3004, stack3008, stack3012, stack3016,
- stack3020, stack3024, stack3028, stack3032, stack3036, stack3040,
- stack3044, stack3048, stack3052, stack3056, stack3060, stack3064,
- stack3068, stack3072, stack3076, stack3080, stack3084, stack3088,
- stack3092, stack3096, stack3100, stack3104, stack3108, stack3112,
- stack3116, stack3120, stack3124, stack3128, stack3132, stack3136,
- stack3140, stack3144, stack3148, stack3152, stack3156, stack3160,
- stack3164, stack3168, stack3172, stack3176, stack3180, stack3184,
- stack3188, stack3192, stack3196, stack3200, stack3204, stack3208,
- stack3212, stack3216, stack3220, stack3224, stack3228, stack3232,
- stack3236, stack3240, stack3244, stack3248, stack3252, stack3256,
- stack3260, stack3264, stack3268, stack3272, stack3276, stack3280,
- stack3284, stack3288, stack3292, stack3296, stack3300, stack3304,
- stack3308, stack3312, stack3316, stack3320, stack3324, stack3328,
- stack3332, stack3336, stack3340, stack3344, stack3348, stack3352,
- stack3356, stack3360, stack3364, stack3368, stack3372, stack3376,
- stack3380, stack3384, stack3388, stack3392, stack3396, stack3400,
- stack3404, stack3408, stack3412, stack3416, stack3420, stack3424,
- stack3428, stack3432, stack3436, stack3440, stack3444, stack3448,
- stack3452, stack3456, stack3460, stack3464, stack3468, stack3472,
- stack3476, stack3480, stack3484, stack3488, stack3492, stack3496,
- stack3500, stack3504, stack3508, stack3512, stack3516, stack3520,
- stack3524, stack3528, stack3532, stack3536, stack3540, stack3544,
- stack3548, stack3552, stack3556, stack3560, stack3564, stack3568,
- stack3572, stack3576, stack3580, stack3584, stack3588, stack3592,
- stack3596, stack3600, stack3604, stack3608, stack3612, stack3616,
- stack3620, stack3624, stack3628, stack3632, stack3636, stack3640,
- stack3644, stack3648, stack3652, stack3656, stack3660, stack3664,
- stack3668, stack3672, stack3676, stack3680, stack3684, stack3688,
- stack3692, stack3696, stack3700, stack3704, stack3708, stack3712,
- stack3716, stack3720, stack3724, stack3728, stack3732, stack3736,
- stack3740, stack3744, stack3748, stack3752, stack3756, stack3760,
- stack3764, stack3768, stack3772, stack3776, stack3780, stack3784,
- stack3788, stack3792, stack3796, stack3800, stack3804, stack3808,
- stack3812, stack3816, stack3820, stack3824, stack3828, stack3832,
- stack3836, stack3840, stack3844, stack3848, stack3852, stack3856,
- stack3860, stack3864, stack3868, stack3872, stack3876, stack3880,
- stack3884, stack3888, stack3892, stack3896, stack3900, stack3904,
- stack3908, stack3912, stack3916, stack3920, stack3924, stack3928,
- stack3932, stack3936, stack3940, stack3944, stack3948, stack3952,
- stack3956, stack3960, stack3964, stack3968, stack3972, stack3976,
- stack3980, stack3984, stack3988, stack3992, stack3996, stack4000,
- stack4004, stack4008, stack4012, stack4016, stack4020, stack4024,
- stack4028, stack4032, stack4036, stack4040, stack4044, stack4048,
- stack4052, stack4056, stack4060, stack4064, stack4068, stack4072,
- stack4076, stack4080, stack4084, stack4088, stack4092, stack4096,
- stack4100, stack4104, stack4108, stack4112, stack4116, stack4120,
- stack4124, stack4128, stack4132, stack4136, stack4140, stack4144,
- stack4148, stack4152, stack4156, stack4160, stack4164, stack4168,
- stack4172, stack4176, stack4180, stack4184, stack4188, stack4192,
- stack4196, stack4200, stack4204, stack4208, stack4212, stack4216,
- stack4220, stack4224, stack4228, stack4232, stack4236, stack4240,
- stack4244, stack4248, stack4252, stack4256, stack4260, stack4264,
- stack4268, stack4272, stack4276, stack4280, stack4284, stack4288,
- stack4292, stack4296, stack4300, stack4304, stack4308, stack4312,
- stack4316, stack4320, stack4324, stack4328, stack4332, stack4336,
- stack4340, stack4344, stack4348, stack4352, stack4356, stack4360,
- stack4364, stack4368, stack4372, stack4376, stack4380, stack4384,
- stack4388, stack4392, stack4396, stack4400, stack4404, stack4408,
- stack4412, stack4416, stack4420, stack4424, stack4428, stack4432,
- stack4436, stack4440, stack4444, stack4448, stack4452, stack4456,
- stack4460, stack4464, stack4468, stack4472, stack4476, stack4480,
- stack4484, stack4488, stack4492, stack4496, stack4500, stack4504,
- stack4508, stack4512, stack4516, stack4520, stack4524, stack4528,
- stack4532, stack4536, stack4540, stack4544, stack4548, stack4552,
- stack4556, stack4560, stack4564, stack4568, stack4572, stack4576,
- stack4580, stack4584, stack4588, stack4592, stack4596, stack4600,
- stack4604, stack4608, stack4612, stack4616, stack4620, stack4624,
- stack4628, stack4632, stack4636, stack4640, stack4644, stack4648,
- stack4652, stack4656, stack4660, stack4664, stack4668, stack4672,
- stack4676, stack4680, stack4684, stack4688, stack4692, stack4696,
- stack4700, stack4704, stack4708, stack4712, stack4716, stack4720,
- stack4724, stack4728, stack4732, stack4736, stack4740, stack4744,
- stack4748, stack4752, stack4756, stack4760, stack4764, stack4768,
- stack4772, stack4776, stack4780, stack4784, stack4788, stack4792,
- stack4796, stack4800, stack4804, stack4808, stack4812, stack4816,
- stack4820, stack4824, stack4828, stack4832, stack4836, stack4840,
- stack4844, stack4848, stack4852, stack4856, stack4860, stack4864,
- stack4868, stack4872, stack4876, stack4880, stack4884, stack4888,
- stack4892, stack4896, stack4900, stack4904, stack4908, stack4912,
- stack4916, stack4920, stack4924, stack4928, stack4932, stack4936,
- stack4940, stack4944, stack4948, stack4952, stack4956, stack4960,
- stack4964, stack4968, stack4972, stack4976, stack4980, stack4984,
- stack4988, stack4992, stack4996, stack5000,
-}
-
-// Edit .+1,$ | seq 4 4 5000 | sed 's/.*/func stack&()(uintptr, uintptr) { var buf [&]byte; use(buf[:]); return Stackguard() }/'
-func stack4() (uintptr, uintptr) { var buf [4]byte; use(buf[:]); return Stackguard() }
-func stack8() (uintptr, uintptr) { var buf [8]byte; use(buf[:]); return Stackguard() }
-func stack12() (uintptr, uintptr) { var buf [12]byte; use(buf[:]); return Stackguard() }
-func stack16() (uintptr, uintptr) { var buf [16]byte; use(buf[:]); return Stackguard() }
-func stack20() (uintptr, uintptr) { var buf [20]byte; use(buf[:]); return Stackguard() }
-func stack24() (uintptr, uintptr) { var buf [24]byte; use(buf[:]); return Stackguard() }
-func stack28() (uintptr, uintptr) { var buf [28]byte; use(buf[:]); return Stackguard() }
-func stack32() (uintptr, uintptr) { var buf [32]byte; use(buf[:]); return Stackguard() }
-func stack36() (uintptr, uintptr) { var buf [36]byte; use(buf[:]); return Stackguard() }
-func stack40() (uintptr, uintptr) { var buf [40]byte; use(buf[:]); return Stackguard() }
-func stack44() (uintptr, uintptr) { var buf [44]byte; use(buf[:]); return Stackguard() }
-func stack48() (uintptr, uintptr) { var buf [48]byte; use(buf[:]); return Stackguard() }
-func stack52() (uintptr, uintptr) { var buf [52]byte; use(buf[:]); return Stackguard() }
-func stack56() (uintptr, uintptr) { var buf [56]byte; use(buf[:]); return Stackguard() }
-func stack60() (uintptr, uintptr) { var buf [60]byte; use(buf[:]); return Stackguard() }
-func stack64() (uintptr, uintptr) { var buf [64]byte; use(buf[:]); return Stackguard() }
-func stack68() (uintptr, uintptr) { var buf [68]byte; use(buf[:]); return Stackguard() }
-func stack72() (uintptr, uintptr) { var buf [72]byte; use(buf[:]); return Stackguard() }
-func stack76() (uintptr, uintptr) { var buf [76]byte; use(buf[:]); return Stackguard() }
-func stack80() (uintptr, uintptr) { var buf [80]byte; use(buf[:]); return Stackguard() }
-func stack84() (uintptr, uintptr) { var buf [84]byte; use(buf[:]); return Stackguard() }
-func stack88() (uintptr, uintptr) { var buf [88]byte; use(buf[:]); return Stackguard() }
-func stack92() (uintptr, uintptr) { var buf [92]byte; use(buf[:]); return Stackguard() }
-func stack96() (uintptr, uintptr) { var buf [96]byte; use(buf[:]); return Stackguard() }
-func stack100() (uintptr, uintptr) { var buf [100]byte; use(buf[:]); return Stackguard() }
-func stack104() (uintptr, uintptr) { var buf [104]byte; use(buf[:]); return Stackguard() }
-func stack108() (uintptr, uintptr) { var buf [108]byte; use(buf[:]); return Stackguard() }
-func stack112() (uintptr, uintptr) { var buf [112]byte; use(buf[:]); return Stackguard() }
-func stack116() (uintptr, uintptr) { var buf [116]byte; use(buf[:]); return Stackguard() }
-func stack120() (uintptr, uintptr) { var buf [120]byte; use(buf[:]); return Stackguard() }
-func stack124() (uintptr, uintptr) { var buf [124]byte; use(buf[:]); return Stackguard() }
-func stack128() (uintptr, uintptr) { var buf [128]byte; use(buf[:]); return Stackguard() }
-func stack132() (uintptr, uintptr) { var buf [132]byte; use(buf[:]); return Stackguard() }
-func stack136() (uintptr, uintptr) { var buf [136]byte; use(buf[:]); return Stackguard() }
-func stack140() (uintptr, uintptr) { var buf [140]byte; use(buf[:]); return Stackguard() }
-func stack144() (uintptr, uintptr) { var buf [144]byte; use(buf[:]); return Stackguard() }
-func stack148() (uintptr, uintptr) { var buf [148]byte; use(buf[:]); return Stackguard() }
-func stack152() (uintptr, uintptr) { var buf [152]byte; use(buf[:]); return Stackguard() }
-func stack156() (uintptr, uintptr) { var buf [156]byte; use(buf[:]); return Stackguard() }
-func stack160() (uintptr, uintptr) { var buf [160]byte; use(buf[:]); return Stackguard() }
-func stack164() (uintptr, uintptr) { var buf [164]byte; use(buf[:]); return Stackguard() }
-func stack168() (uintptr, uintptr) { var buf [168]byte; use(buf[:]); return Stackguard() }
-func stack172() (uintptr, uintptr) { var buf [172]byte; use(buf[:]); return Stackguard() }
-func stack176() (uintptr, uintptr) { var buf [176]byte; use(buf[:]); return Stackguard() }
-func stack180() (uintptr, uintptr) { var buf [180]byte; use(buf[:]); return Stackguard() }
-func stack184() (uintptr, uintptr) { var buf [184]byte; use(buf[:]); return Stackguard() }
-func stack188() (uintptr, uintptr) { var buf [188]byte; use(buf[:]); return Stackguard() }
-func stack192() (uintptr, uintptr) { var buf [192]byte; use(buf[:]); return Stackguard() }
-func stack196() (uintptr, uintptr) { var buf [196]byte; use(buf[:]); return Stackguard() }
-func stack200() (uintptr, uintptr) { var buf [200]byte; use(buf[:]); return Stackguard() }
-func stack204() (uintptr, uintptr) { var buf [204]byte; use(buf[:]); return Stackguard() }
-func stack208() (uintptr, uintptr) { var buf [208]byte; use(buf[:]); return Stackguard() }
-func stack212() (uintptr, uintptr) { var buf [212]byte; use(buf[:]); return Stackguard() }
-func stack216() (uintptr, uintptr) { var buf [216]byte; use(buf[:]); return Stackguard() }
-func stack220() (uintptr, uintptr) { var buf [220]byte; use(buf[:]); return Stackguard() }
-func stack224() (uintptr, uintptr) { var buf [224]byte; use(buf[:]); return Stackguard() }
-func stack228() (uintptr, uintptr) { var buf [228]byte; use(buf[:]); return Stackguard() }
-func stack232() (uintptr, uintptr) { var buf [232]byte; use(buf[:]); return Stackguard() }
-func stack236() (uintptr, uintptr) { var buf [236]byte; use(buf[:]); return Stackguard() }
-func stack240() (uintptr, uintptr) { var buf [240]byte; use(buf[:]); return Stackguard() }
-func stack244() (uintptr, uintptr) { var buf [244]byte; use(buf[:]); return Stackguard() }
-func stack248() (uintptr, uintptr) { var buf [248]byte; use(buf[:]); return Stackguard() }
-func stack252() (uintptr, uintptr) { var buf [252]byte; use(buf[:]); return Stackguard() }
-func stack256() (uintptr, uintptr) { var buf [256]byte; use(buf[:]); return Stackguard() }
-func stack260() (uintptr, uintptr) { var buf [260]byte; use(buf[:]); return Stackguard() }
-func stack264() (uintptr, uintptr) { var buf [264]byte; use(buf[:]); return Stackguard() }
-func stack268() (uintptr, uintptr) { var buf [268]byte; use(buf[:]); return Stackguard() }
-func stack272() (uintptr, uintptr) { var buf [272]byte; use(buf[:]); return Stackguard() }
-func stack276() (uintptr, uintptr) { var buf [276]byte; use(buf[:]); return Stackguard() }
-func stack280() (uintptr, uintptr) { var buf [280]byte; use(buf[:]); return Stackguard() }
-func stack284() (uintptr, uintptr) { var buf [284]byte; use(buf[:]); return Stackguard() }
-func stack288() (uintptr, uintptr) { var buf [288]byte; use(buf[:]); return Stackguard() }
-func stack292() (uintptr, uintptr) { var buf [292]byte; use(buf[:]); return Stackguard() }
-func stack296() (uintptr, uintptr) { var buf [296]byte; use(buf[:]); return Stackguard() }
-func stack300() (uintptr, uintptr) { var buf [300]byte; use(buf[:]); return Stackguard() }
-func stack304() (uintptr, uintptr) { var buf [304]byte; use(buf[:]); return Stackguard() }
-func stack308() (uintptr, uintptr) { var buf [308]byte; use(buf[:]); return Stackguard() }
-func stack312() (uintptr, uintptr) { var buf [312]byte; use(buf[:]); return Stackguard() }
-func stack316() (uintptr, uintptr) { var buf [316]byte; use(buf[:]); return Stackguard() }
-func stack320() (uintptr, uintptr) { var buf [320]byte; use(buf[:]); return Stackguard() }
-func stack324() (uintptr, uintptr) { var buf [324]byte; use(buf[:]); return Stackguard() }
-func stack328() (uintptr, uintptr) { var buf [328]byte; use(buf[:]); return Stackguard() }
-func stack332() (uintptr, uintptr) { var buf [332]byte; use(buf[:]); return Stackguard() }
-func stack336() (uintptr, uintptr) { var buf [336]byte; use(buf[:]); return Stackguard() }
-func stack340() (uintptr, uintptr) { var buf [340]byte; use(buf[:]); return Stackguard() }
-func stack344() (uintptr, uintptr) { var buf [344]byte; use(buf[:]); return Stackguard() }
-func stack348() (uintptr, uintptr) { var buf [348]byte; use(buf[:]); return Stackguard() }
-func stack352() (uintptr, uintptr) { var buf [352]byte; use(buf[:]); return Stackguard() }
-func stack356() (uintptr, uintptr) { var buf [356]byte; use(buf[:]); return Stackguard() }
-func stack360() (uintptr, uintptr) { var buf [360]byte; use(buf[:]); return Stackguard() }
-func stack364() (uintptr, uintptr) { var buf [364]byte; use(buf[:]); return Stackguard() }
-func stack368() (uintptr, uintptr) { var buf [368]byte; use(buf[:]); return Stackguard() }
-func stack372() (uintptr, uintptr) { var buf [372]byte; use(buf[:]); return Stackguard() }
-func stack376() (uintptr, uintptr) { var buf [376]byte; use(buf[:]); return Stackguard() }
-func stack380() (uintptr, uintptr) { var buf [380]byte; use(buf[:]); return Stackguard() }
-func stack384() (uintptr, uintptr) { var buf [384]byte; use(buf[:]); return Stackguard() }
-func stack388() (uintptr, uintptr) { var buf [388]byte; use(buf[:]); return Stackguard() }
-func stack392() (uintptr, uintptr) { var buf [392]byte; use(buf[:]); return Stackguard() }
-func stack396() (uintptr, uintptr) { var buf [396]byte; use(buf[:]); return Stackguard() }
-func stack400() (uintptr, uintptr) { var buf [400]byte; use(buf[:]); return Stackguard() }
-func stack404() (uintptr, uintptr) { var buf [404]byte; use(buf[:]); return Stackguard() }
-func stack408() (uintptr, uintptr) { var buf [408]byte; use(buf[:]); return Stackguard() }
-func stack412() (uintptr, uintptr) { var buf [412]byte; use(buf[:]); return Stackguard() }
-func stack416() (uintptr, uintptr) { var buf [416]byte; use(buf[:]); return Stackguard() }
-func stack420() (uintptr, uintptr) { var buf [420]byte; use(buf[:]); return Stackguard() }
-func stack424() (uintptr, uintptr) { var buf [424]byte; use(buf[:]); return Stackguard() }
-func stack428() (uintptr, uintptr) { var buf [428]byte; use(buf[:]); return Stackguard() }
-func stack432() (uintptr, uintptr) { var buf [432]byte; use(buf[:]); return Stackguard() }
-func stack436() (uintptr, uintptr) { var buf [436]byte; use(buf[:]); return Stackguard() }
-func stack440() (uintptr, uintptr) { var buf [440]byte; use(buf[:]); return Stackguard() }
-func stack444() (uintptr, uintptr) { var buf [444]byte; use(buf[:]); return Stackguard() }
-func stack448() (uintptr, uintptr) { var buf [448]byte; use(buf[:]); return Stackguard() }
-func stack452() (uintptr, uintptr) { var buf [452]byte; use(buf[:]); return Stackguard() }
-func stack456() (uintptr, uintptr) { var buf [456]byte; use(buf[:]); return Stackguard() }
-func stack460() (uintptr, uintptr) { var buf [460]byte; use(buf[:]); return Stackguard() }
-func stack464() (uintptr, uintptr) { var buf [464]byte; use(buf[:]); return Stackguard() }
-func stack468() (uintptr, uintptr) { var buf [468]byte; use(buf[:]); return Stackguard() }
-func stack472() (uintptr, uintptr) { var buf [472]byte; use(buf[:]); return Stackguard() }
-func stack476() (uintptr, uintptr) { var buf [476]byte; use(buf[:]); return Stackguard() }
-func stack480() (uintptr, uintptr) { var buf [480]byte; use(buf[:]); return Stackguard() }
-func stack484() (uintptr, uintptr) { var buf [484]byte; use(buf[:]); return Stackguard() }
-func stack488() (uintptr, uintptr) { var buf [488]byte; use(buf[:]); return Stackguard() }
-func stack492() (uintptr, uintptr) { var buf [492]byte; use(buf[:]); return Stackguard() }
-func stack496() (uintptr, uintptr) { var buf [496]byte; use(buf[:]); return Stackguard() }
-func stack500() (uintptr, uintptr) { var buf [500]byte; use(buf[:]); return Stackguard() }
-func stack504() (uintptr, uintptr) { var buf [504]byte; use(buf[:]); return Stackguard() }
-func stack508() (uintptr, uintptr) { var buf [508]byte; use(buf[:]); return Stackguard() }
-func stack512() (uintptr, uintptr) { var buf [512]byte; use(buf[:]); return Stackguard() }
-func stack516() (uintptr, uintptr) { var buf [516]byte; use(buf[:]); return Stackguard() }
-func stack520() (uintptr, uintptr) { var buf [520]byte; use(buf[:]); return Stackguard() }
-func stack524() (uintptr, uintptr) { var buf [524]byte; use(buf[:]); return Stackguard() }
-func stack528() (uintptr, uintptr) { var buf [528]byte; use(buf[:]); return Stackguard() }
-func stack532() (uintptr, uintptr) { var buf [532]byte; use(buf[:]); return Stackguard() }
-func stack536() (uintptr, uintptr) { var buf [536]byte; use(buf[:]); return Stackguard() }
-func stack540() (uintptr, uintptr) { var buf [540]byte; use(buf[:]); return Stackguard() }
-func stack544() (uintptr, uintptr) { var buf [544]byte; use(buf[:]); return Stackguard() }
-func stack548() (uintptr, uintptr) { var buf [548]byte; use(buf[:]); return Stackguard() }
-func stack552() (uintptr, uintptr) { var buf [552]byte; use(buf[:]); return Stackguard() }
-func stack556() (uintptr, uintptr) { var buf [556]byte; use(buf[:]); return Stackguard() }
-func stack560() (uintptr, uintptr) { var buf [560]byte; use(buf[:]); return Stackguard() }
-func stack564() (uintptr, uintptr) { var buf [564]byte; use(buf[:]); return Stackguard() }
-func stack568() (uintptr, uintptr) { var buf [568]byte; use(buf[:]); return Stackguard() }
-func stack572() (uintptr, uintptr) { var buf [572]byte; use(buf[:]); return Stackguard() }
-func stack576() (uintptr, uintptr) { var buf [576]byte; use(buf[:]); return Stackguard() }
-func stack580() (uintptr, uintptr) { var buf [580]byte; use(buf[:]); return Stackguard() }
-func stack584() (uintptr, uintptr) { var buf [584]byte; use(buf[:]); return Stackguard() }
-func stack588() (uintptr, uintptr) { var buf [588]byte; use(buf[:]); return Stackguard() }
-func stack592() (uintptr, uintptr) { var buf [592]byte; use(buf[:]); return Stackguard() }
-func stack596() (uintptr, uintptr) { var buf [596]byte; use(buf[:]); return Stackguard() }
-func stack600() (uintptr, uintptr) { var buf [600]byte; use(buf[:]); return Stackguard() }
-func stack604() (uintptr, uintptr) { var buf [604]byte; use(buf[:]); return Stackguard() }
-func stack608() (uintptr, uintptr) { var buf [608]byte; use(buf[:]); return Stackguard() }
-func stack612() (uintptr, uintptr) { var buf [612]byte; use(buf[:]); return Stackguard() }
-func stack616() (uintptr, uintptr) { var buf [616]byte; use(buf[:]); return Stackguard() }
-func stack620() (uintptr, uintptr) { var buf [620]byte; use(buf[:]); return Stackguard() }
-func stack624() (uintptr, uintptr) { var buf [624]byte; use(buf[:]); return Stackguard() }
-func stack628() (uintptr, uintptr) { var buf [628]byte; use(buf[:]); return Stackguard() }
-func stack632() (uintptr, uintptr) { var buf [632]byte; use(buf[:]); return Stackguard() }
-func stack636() (uintptr, uintptr) { var buf [636]byte; use(buf[:]); return Stackguard() }
-func stack640() (uintptr, uintptr) { var buf [640]byte; use(buf[:]); return Stackguard() }
-func stack644() (uintptr, uintptr) { var buf [644]byte; use(buf[:]); return Stackguard() }
-func stack648() (uintptr, uintptr) { var buf [648]byte; use(buf[:]); return Stackguard() }
-func stack652() (uintptr, uintptr) { var buf [652]byte; use(buf[:]); return Stackguard() }
-func stack656() (uintptr, uintptr) { var buf [656]byte; use(buf[:]); return Stackguard() }
-func stack660() (uintptr, uintptr) { var buf [660]byte; use(buf[:]); return Stackguard() }
-func stack664() (uintptr, uintptr) { var buf [664]byte; use(buf[:]); return Stackguard() }
-func stack668() (uintptr, uintptr) { var buf [668]byte; use(buf[:]); return Stackguard() }
-func stack672() (uintptr, uintptr) { var buf [672]byte; use(buf[:]); return Stackguard() }
-func stack676() (uintptr, uintptr) { var buf [676]byte; use(buf[:]); return Stackguard() }
-func stack680() (uintptr, uintptr) { var buf [680]byte; use(buf[:]); return Stackguard() }
-func stack684() (uintptr, uintptr) { var buf [684]byte; use(buf[:]); return Stackguard() }
-func stack688() (uintptr, uintptr) { var buf [688]byte; use(buf[:]); return Stackguard() }
-func stack692() (uintptr, uintptr) { var buf [692]byte; use(buf[:]); return Stackguard() }
-func stack696() (uintptr, uintptr) { var buf [696]byte; use(buf[:]); return Stackguard() }
-func stack700() (uintptr, uintptr) { var buf [700]byte; use(buf[:]); return Stackguard() }
-func stack704() (uintptr, uintptr) { var buf [704]byte; use(buf[:]); return Stackguard() }
-func stack708() (uintptr, uintptr) { var buf [708]byte; use(buf[:]); return Stackguard() }
-func stack712() (uintptr, uintptr) { var buf [712]byte; use(buf[:]); return Stackguard() }
-func stack716() (uintptr, uintptr) { var buf [716]byte; use(buf[:]); return Stackguard() }
-func stack720() (uintptr, uintptr) { var buf [720]byte; use(buf[:]); return Stackguard() }
-func stack724() (uintptr, uintptr) { var buf [724]byte; use(buf[:]); return Stackguard() }
-func stack728() (uintptr, uintptr) { var buf [728]byte; use(buf[:]); return Stackguard() }
-func stack732() (uintptr, uintptr) { var buf [732]byte; use(buf[:]); return Stackguard() }
-func stack736() (uintptr, uintptr) { var buf [736]byte; use(buf[:]); return Stackguard() }
-func stack740() (uintptr, uintptr) { var buf [740]byte; use(buf[:]); return Stackguard() }
-func stack744() (uintptr, uintptr) { var buf [744]byte; use(buf[:]); return Stackguard() }
-func stack748() (uintptr, uintptr) { var buf [748]byte; use(buf[:]); return Stackguard() }
-func stack752() (uintptr, uintptr) { var buf [752]byte; use(buf[:]); return Stackguard() }
-func stack756() (uintptr, uintptr) { var buf [756]byte; use(buf[:]); return Stackguard() }
-func stack760() (uintptr, uintptr) { var buf [760]byte; use(buf[:]); return Stackguard() }
-func stack764() (uintptr, uintptr) { var buf [764]byte; use(buf[:]); return Stackguard() }
-func stack768() (uintptr, uintptr) { var buf [768]byte; use(buf[:]); return Stackguard() }
-func stack772() (uintptr, uintptr) { var buf [772]byte; use(buf[:]); return Stackguard() }
-func stack776() (uintptr, uintptr) { var buf [776]byte; use(buf[:]); return Stackguard() }
-func stack780() (uintptr, uintptr) { var buf [780]byte; use(buf[:]); return Stackguard() }
-func stack784() (uintptr, uintptr) { var buf [784]byte; use(buf[:]); return Stackguard() }
-func stack788() (uintptr, uintptr) { var buf [788]byte; use(buf[:]); return Stackguard() }
-func stack792() (uintptr, uintptr) { var buf [792]byte; use(buf[:]); return Stackguard() }
-func stack796() (uintptr, uintptr) { var buf [796]byte; use(buf[:]); return Stackguard() }
-func stack800() (uintptr, uintptr) { var buf [800]byte; use(buf[:]); return Stackguard() }
-func stack804() (uintptr, uintptr) { var buf [804]byte; use(buf[:]); return Stackguard() }
-func stack808() (uintptr, uintptr) { var buf [808]byte; use(buf[:]); return Stackguard() }
-func stack812() (uintptr, uintptr) { var buf [812]byte; use(buf[:]); return Stackguard() }
-func stack816() (uintptr, uintptr) { var buf [816]byte; use(buf[:]); return Stackguard() }
-func stack820() (uintptr, uintptr) { var buf [820]byte; use(buf[:]); return Stackguard() }
-func stack824() (uintptr, uintptr) { var buf [824]byte; use(buf[:]); return Stackguard() }
-func stack828() (uintptr, uintptr) { var buf [828]byte; use(buf[:]); return Stackguard() }
-func stack832() (uintptr, uintptr) { var buf [832]byte; use(buf[:]); return Stackguard() }
-func stack836() (uintptr, uintptr) { var buf [836]byte; use(buf[:]); return Stackguard() }
-func stack840() (uintptr, uintptr) { var buf [840]byte; use(buf[:]); return Stackguard() }
-func stack844() (uintptr, uintptr) { var buf [844]byte; use(buf[:]); return Stackguard() }
-func stack848() (uintptr, uintptr) { var buf [848]byte; use(buf[:]); return Stackguard() }
-func stack852() (uintptr, uintptr) { var buf [852]byte; use(buf[:]); return Stackguard() }
-func stack856() (uintptr, uintptr) { var buf [856]byte; use(buf[:]); return Stackguard() }
-func stack860() (uintptr, uintptr) { var buf [860]byte; use(buf[:]); return Stackguard() }
-func stack864() (uintptr, uintptr) { var buf [864]byte; use(buf[:]); return Stackguard() }
-func stack868() (uintptr, uintptr) { var buf [868]byte; use(buf[:]); return Stackguard() }
-func stack872() (uintptr, uintptr) { var buf [872]byte; use(buf[:]); return Stackguard() }
-func stack876() (uintptr, uintptr) { var buf [876]byte; use(buf[:]); return Stackguard() }
-func stack880() (uintptr, uintptr) { var buf [880]byte; use(buf[:]); return Stackguard() }
-func stack884() (uintptr, uintptr) { var buf [884]byte; use(buf[:]); return Stackguard() }
-func stack888() (uintptr, uintptr) { var buf [888]byte; use(buf[:]); return Stackguard() }
-func stack892() (uintptr, uintptr) { var buf [892]byte; use(buf[:]); return Stackguard() }
-func stack896() (uintptr, uintptr) { var buf [896]byte; use(buf[:]); return Stackguard() }
-func stack900() (uintptr, uintptr) { var buf [900]byte; use(buf[:]); return Stackguard() }
-func stack904() (uintptr, uintptr) { var buf [904]byte; use(buf[:]); return Stackguard() }
-func stack908() (uintptr, uintptr) { var buf [908]byte; use(buf[:]); return Stackguard() }
-func stack912() (uintptr, uintptr) { var buf [912]byte; use(buf[:]); return Stackguard() }
-func stack916() (uintptr, uintptr) { var buf [916]byte; use(buf[:]); return Stackguard() }
-func stack920() (uintptr, uintptr) { var buf [920]byte; use(buf[:]); return Stackguard() }
-func stack924() (uintptr, uintptr) { var buf [924]byte; use(buf[:]); return Stackguard() }
-func stack928() (uintptr, uintptr) { var buf [928]byte; use(buf[:]); return Stackguard() }
-func stack932() (uintptr, uintptr) { var buf [932]byte; use(buf[:]); return Stackguard() }
-func stack936() (uintptr, uintptr) { var buf [936]byte; use(buf[:]); return Stackguard() }
-func stack940() (uintptr, uintptr) { var buf [940]byte; use(buf[:]); return Stackguard() }
-func stack944() (uintptr, uintptr) { var buf [944]byte; use(buf[:]); return Stackguard() }
-func stack948() (uintptr, uintptr) { var buf [948]byte; use(buf[:]); return Stackguard() }
-func stack952() (uintptr, uintptr) { var buf [952]byte; use(buf[:]); return Stackguard() }
-func stack956() (uintptr, uintptr) { var buf [956]byte; use(buf[:]); return Stackguard() }
-func stack960() (uintptr, uintptr) { var buf [960]byte; use(buf[:]); return Stackguard() }
-func stack964() (uintptr, uintptr) { var buf [964]byte; use(buf[:]); return Stackguard() }
-func stack968() (uintptr, uintptr) { var buf [968]byte; use(buf[:]); return Stackguard() }
-func stack972() (uintptr, uintptr) { var buf [972]byte; use(buf[:]); return Stackguard() }
-func stack976() (uintptr, uintptr) { var buf [976]byte; use(buf[:]); return Stackguard() }
-func stack980() (uintptr, uintptr) { var buf [980]byte; use(buf[:]); return Stackguard() }
-func stack984() (uintptr, uintptr) { var buf [984]byte; use(buf[:]); return Stackguard() }
-func stack988() (uintptr, uintptr) { var buf [988]byte; use(buf[:]); return Stackguard() }
-func stack992() (uintptr, uintptr) { var buf [992]byte; use(buf[:]); return Stackguard() }
-func stack996() (uintptr, uintptr) { var buf [996]byte; use(buf[:]); return Stackguard() }
-func stack1000() (uintptr, uintptr) { var buf [1000]byte; use(buf[:]); return Stackguard() }
-func stack1004() (uintptr, uintptr) { var buf [1004]byte; use(buf[:]); return Stackguard() }
-func stack1008() (uintptr, uintptr) { var buf [1008]byte; use(buf[:]); return Stackguard() }
-func stack1012() (uintptr, uintptr) { var buf [1012]byte; use(buf[:]); return Stackguard() }
-func stack1016() (uintptr, uintptr) { var buf [1016]byte; use(buf[:]); return Stackguard() }
-func stack1020() (uintptr, uintptr) { var buf [1020]byte; use(buf[:]); return Stackguard() }
-func stack1024() (uintptr, uintptr) { var buf [1024]byte; use(buf[:]); return Stackguard() }
-func stack1028() (uintptr, uintptr) { var buf [1028]byte; use(buf[:]); return Stackguard() }
-func stack1032() (uintptr, uintptr) { var buf [1032]byte; use(buf[:]); return Stackguard() }
-func stack1036() (uintptr, uintptr) { var buf [1036]byte; use(buf[:]); return Stackguard() }
-func stack1040() (uintptr, uintptr) { var buf [1040]byte; use(buf[:]); return Stackguard() }
-func stack1044() (uintptr, uintptr) { var buf [1044]byte; use(buf[:]); return Stackguard() }
-func stack1048() (uintptr, uintptr) { var buf [1048]byte; use(buf[:]); return Stackguard() }
-func stack1052() (uintptr, uintptr) { var buf [1052]byte; use(buf[:]); return Stackguard() }
-func stack1056() (uintptr, uintptr) { var buf [1056]byte; use(buf[:]); return Stackguard() }
-func stack1060() (uintptr, uintptr) { var buf [1060]byte; use(buf[:]); return Stackguard() }
-func stack1064() (uintptr, uintptr) { var buf [1064]byte; use(buf[:]); return Stackguard() }
-func stack1068() (uintptr, uintptr) { var buf [1068]byte; use(buf[:]); return Stackguard() }
-func stack1072() (uintptr, uintptr) { var buf [1072]byte; use(buf[:]); return Stackguard() }
-func stack1076() (uintptr, uintptr) { var buf [1076]byte; use(buf[:]); return Stackguard() }
-func stack1080() (uintptr, uintptr) { var buf [1080]byte; use(buf[:]); return Stackguard() }
-func stack1084() (uintptr, uintptr) { var buf [1084]byte; use(buf[:]); return Stackguard() }
-func stack1088() (uintptr, uintptr) { var buf [1088]byte; use(buf[:]); return Stackguard() }
-func stack1092() (uintptr, uintptr) { var buf [1092]byte; use(buf[:]); return Stackguard() }
-func stack1096() (uintptr, uintptr) { var buf [1096]byte; use(buf[:]); return Stackguard() }
-func stack1100() (uintptr, uintptr) { var buf [1100]byte; use(buf[:]); return Stackguard() }
-func stack1104() (uintptr, uintptr) { var buf [1104]byte; use(buf[:]); return Stackguard() }
-func stack1108() (uintptr, uintptr) { var buf [1108]byte; use(buf[:]); return Stackguard() }
-func stack1112() (uintptr, uintptr) { var buf [1112]byte; use(buf[:]); return Stackguard() }
-func stack1116() (uintptr, uintptr) { var buf [1116]byte; use(buf[:]); return Stackguard() }
-func stack1120() (uintptr, uintptr) { var buf [1120]byte; use(buf[:]); return Stackguard() }
-func stack1124() (uintptr, uintptr) { var buf [1124]byte; use(buf[:]); return Stackguard() }
-func stack1128() (uintptr, uintptr) { var buf [1128]byte; use(buf[:]); return Stackguard() }
-func stack1132() (uintptr, uintptr) { var buf [1132]byte; use(buf[:]); return Stackguard() }
-func stack1136() (uintptr, uintptr) { var buf [1136]byte; use(buf[:]); return Stackguard() }
-func stack1140() (uintptr, uintptr) { var buf [1140]byte; use(buf[:]); return Stackguard() }
-func stack1144() (uintptr, uintptr) { var buf [1144]byte; use(buf[:]); return Stackguard() }
-func stack1148() (uintptr, uintptr) { var buf [1148]byte; use(buf[:]); return Stackguard() }
-func stack1152() (uintptr, uintptr) { var buf [1152]byte; use(buf[:]); return Stackguard() }
-func stack1156() (uintptr, uintptr) { var buf [1156]byte; use(buf[:]); return Stackguard() }
-func stack1160() (uintptr, uintptr) { var buf [1160]byte; use(buf[:]); return Stackguard() }
-func stack1164() (uintptr, uintptr) { var buf [1164]byte; use(buf[:]); return Stackguard() }
-func stack1168() (uintptr, uintptr) { var buf [1168]byte; use(buf[:]); return Stackguard() }
-func stack1172() (uintptr, uintptr) { var buf [1172]byte; use(buf[:]); return Stackguard() }
-func stack1176() (uintptr, uintptr) { var buf [1176]byte; use(buf[:]); return Stackguard() }
-func stack1180() (uintptr, uintptr) { var buf [1180]byte; use(buf[:]); return Stackguard() }
-func stack1184() (uintptr, uintptr) { var buf [1184]byte; use(buf[:]); return Stackguard() }
-func stack1188() (uintptr, uintptr) { var buf [1188]byte; use(buf[:]); return Stackguard() }
-func stack1192() (uintptr, uintptr) { var buf [1192]byte; use(buf[:]); return Stackguard() }
-func stack1196() (uintptr, uintptr) { var buf [1196]byte; use(buf[:]); return Stackguard() }
-func stack1200() (uintptr, uintptr) { var buf [1200]byte; use(buf[:]); return Stackguard() }
-func stack1204() (uintptr, uintptr) { var buf [1204]byte; use(buf[:]); return Stackguard() }
-func stack1208() (uintptr, uintptr) { var buf [1208]byte; use(buf[:]); return Stackguard() }
-func stack1212() (uintptr, uintptr) { var buf [1212]byte; use(buf[:]); return Stackguard() }
-func stack1216() (uintptr, uintptr) { var buf [1216]byte; use(buf[:]); return Stackguard() }
-func stack1220() (uintptr, uintptr) { var buf [1220]byte; use(buf[:]); return Stackguard() }
-func stack1224() (uintptr, uintptr) { var buf [1224]byte; use(buf[:]); return Stackguard() }
-func stack1228() (uintptr, uintptr) { var buf [1228]byte; use(buf[:]); return Stackguard() }
-func stack1232() (uintptr, uintptr) { var buf [1232]byte; use(buf[:]); return Stackguard() }
-func stack1236() (uintptr, uintptr) { var buf [1236]byte; use(buf[:]); return Stackguard() }
-func stack1240() (uintptr, uintptr) { var buf [1240]byte; use(buf[:]); return Stackguard() }
-func stack1244() (uintptr, uintptr) { var buf [1244]byte; use(buf[:]); return Stackguard() }
-func stack1248() (uintptr, uintptr) { var buf [1248]byte; use(buf[:]); return Stackguard() }
-func stack1252() (uintptr, uintptr) { var buf [1252]byte; use(buf[:]); return Stackguard() }
-func stack1256() (uintptr, uintptr) { var buf [1256]byte; use(buf[:]); return Stackguard() }
-func stack1260() (uintptr, uintptr) { var buf [1260]byte; use(buf[:]); return Stackguard() }
-func stack1264() (uintptr, uintptr) { var buf [1264]byte; use(buf[:]); return Stackguard() }
-func stack1268() (uintptr, uintptr) { var buf [1268]byte; use(buf[:]); return Stackguard() }
-func stack1272() (uintptr, uintptr) { var buf [1272]byte; use(buf[:]); return Stackguard() }
-func stack1276() (uintptr, uintptr) { var buf [1276]byte; use(buf[:]); return Stackguard() }
-func stack1280() (uintptr, uintptr) { var buf [1280]byte; use(buf[:]); return Stackguard() }
-func stack1284() (uintptr, uintptr) { var buf [1284]byte; use(buf[:]); return Stackguard() }
-func stack1288() (uintptr, uintptr) { var buf [1288]byte; use(buf[:]); return Stackguard() }
-func stack1292() (uintptr, uintptr) { var buf [1292]byte; use(buf[:]); return Stackguard() }
-func stack1296() (uintptr, uintptr) { var buf [1296]byte; use(buf[:]); return Stackguard() }
-func stack1300() (uintptr, uintptr) { var buf [1300]byte; use(buf[:]); return Stackguard() }
-func stack1304() (uintptr, uintptr) { var buf [1304]byte; use(buf[:]); return Stackguard() }
-func stack1308() (uintptr, uintptr) { var buf [1308]byte; use(buf[:]); return Stackguard() }
-func stack1312() (uintptr, uintptr) { var buf [1312]byte; use(buf[:]); return Stackguard() }
-func stack1316() (uintptr, uintptr) { var buf [1316]byte; use(buf[:]); return Stackguard() }
-func stack1320() (uintptr, uintptr) { var buf [1320]byte; use(buf[:]); return Stackguard() }
-func stack1324() (uintptr, uintptr) { var buf [1324]byte; use(buf[:]); return Stackguard() }
-func stack1328() (uintptr, uintptr) { var buf [1328]byte; use(buf[:]); return Stackguard() }
-func stack1332() (uintptr, uintptr) { var buf [1332]byte; use(buf[:]); return Stackguard() }
-func stack1336() (uintptr, uintptr) { var buf [1336]byte; use(buf[:]); return Stackguard() }
-func stack1340() (uintptr, uintptr) { var buf [1340]byte; use(buf[:]); return Stackguard() }
-func stack1344() (uintptr, uintptr) { var buf [1344]byte; use(buf[:]); return Stackguard() }
-func stack1348() (uintptr, uintptr) { var buf [1348]byte; use(buf[:]); return Stackguard() }
-func stack1352() (uintptr, uintptr) { var buf [1352]byte; use(buf[:]); return Stackguard() }
-func stack1356() (uintptr, uintptr) { var buf [1356]byte; use(buf[:]); return Stackguard() }
-func stack1360() (uintptr, uintptr) { var buf [1360]byte; use(buf[:]); return Stackguard() }
-func stack1364() (uintptr, uintptr) { var buf [1364]byte; use(buf[:]); return Stackguard() }
-func stack1368() (uintptr, uintptr) { var buf [1368]byte; use(buf[:]); return Stackguard() }
-func stack1372() (uintptr, uintptr) { var buf [1372]byte; use(buf[:]); return Stackguard() }
-func stack1376() (uintptr, uintptr) { var buf [1376]byte; use(buf[:]); return Stackguard() }
-func stack1380() (uintptr, uintptr) { var buf [1380]byte; use(buf[:]); return Stackguard() }
-func stack1384() (uintptr, uintptr) { var buf [1384]byte; use(buf[:]); return Stackguard() }
-func stack1388() (uintptr, uintptr) { var buf [1388]byte; use(buf[:]); return Stackguard() }
-func stack1392() (uintptr, uintptr) { var buf [1392]byte; use(buf[:]); return Stackguard() }
-func stack1396() (uintptr, uintptr) { var buf [1396]byte; use(buf[:]); return Stackguard() }
-func stack1400() (uintptr, uintptr) { var buf [1400]byte; use(buf[:]); return Stackguard() }
-func stack1404() (uintptr, uintptr) { var buf [1404]byte; use(buf[:]); return Stackguard() }
-func stack1408() (uintptr, uintptr) { var buf [1408]byte; use(buf[:]); return Stackguard() }
-func stack1412() (uintptr, uintptr) { var buf [1412]byte; use(buf[:]); return Stackguard() }
-func stack1416() (uintptr, uintptr) { var buf [1416]byte; use(buf[:]); return Stackguard() }
-func stack1420() (uintptr, uintptr) { var buf [1420]byte; use(buf[:]); return Stackguard() }
-func stack1424() (uintptr, uintptr) { var buf [1424]byte; use(buf[:]); return Stackguard() }
-func stack1428() (uintptr, uintptr) { var buf [1428]byte; use(buf[:]); return Stackguard() }
-func stack1432() (uintptr, uintptr) { var buf [1432]byte; use(buf[:]); return Stackguard() }
-func stack1436() (uintptr, uintptr) { var buf [1436]byte; use(buf[:]); return Stackguard() }
-func stack1440() (uintptr, uintptr) { var buf [1440]byte; use(buf[:]); return Stackguard() }
-func stack1444() (uintptr, uintptr) { var buf [1444]byte; use(buf[:]); return Stackguard() }
-func stack1448() (uintptr, uintptr) { var buf [1448]byte; use(buf[:]); return Stackguard() }
-func stack1452() (uintptr, uintptr) { var buf [1452]byte; use(buf[:]); return Stackguard() }
-func stack1456() (uintptr, uintptr) { var buf [1456]byte; use(buf[:]); return Stackguard() }
-func stack1460() (uintptr, uintptr) { var buf [1460]byte; use(buf[:]); return Stackguard() }
-func stack1464() (uintptr, uintptr) { var buf [1464]byte; use(buf[:]); return Stackguard() }
-func stack1468() (uintptr, uintptr) { var buf [1468]byte; use(buf[:]); return Stackguard() }
-func stack1472() (uintptr, uintptr) { var buf [1472]byte; use(buf[:]); return Stackguard() }
-func stack1476() (uintptr, uintptr) { var buf [1476]byte; use(buf[:]); return Stackguard() }
-func stack1480() (uintptr, uintptr) { var buf [1480]byte; use(buf[:]); return Stackguard() }
-func stack1484() (uintptr, uintptr) { var buf [1484]byte; use(buf[:]); return Stackguard() }
-func stack1488() (uintptr, uintptr) { var buf [1488]byte; use(buf[:]); return Stackguard() }
-func stack1492() (uintptr, uintptr) { var buf [1492]byte; use(buf[:]); return Stackguard() }
-func stack1496() (uintptr, uintptr) { var buf [1496]byte; use(buf[:]); return Stackguard() }
-func stack1500() (uintptr, uintptr) { var buf [1500]byte; use(buf[:]); return Stackguard() }
-func stack1504() (uintptr, uintptr) { var buf [1504]byte; use(buf[:]); return Stackguard() }
-func stack1508() (uintptr, uintptr) { var buf [1508]byte; use(buf[:]); return Stackguard() }
-func stack1512() (uintptr, uintptr) { var buf [1512]byte; use(buf[:]); return Stackguard() }
-func stack1516() (uintptr, uintptr) { var buf [1516]byte; use(buf[:]); return Stackguard() }
-func stack1520() (uintptr, uintptr) { var buf [1520]byte; use(buf[:]); return Stackguard() }
-func stack1524() (uintptr, uintptr) { var buf [1524]byte; use(buf[:]); return Stackguard() }
-func stack1528() (uintptr, uintptr) { var buf [1528]byte; use(buf[:]); return Stackguard() }
-func stack1532() (uintptr, uintptr) { var buf [1532]byte; use(buf[:]); return Stackguard() }
-func stack1536() (uintptr, uintptr) { var buf [1536]byte; use(buf[:]); return Stackguard() }
-func stack1540() (uintptr, uintptr) { var buf [1540]byte; use(buf[:]); return Stackguard() }
-func stack1544() (uintptr, uintptr) { var buf [1544]byte; use(buf[:]); return Stackguard() }
-func stack1548() (uintptr, uintptr) { var buf [1548]byte; use(buf[:]); return Stackguard() }
-func stack1552() (uintptr, uintptr) { var buf [1552]byte; use(buf[:]); return Stackguard() }
-func stack1556() (uintptr, uintptr) { var buf [1556]byte; use(buf[:]); return Stackguard() }
-func stack1560() (uintptr, uintptr) { var buf [1560]byte; use(buf[:]); return Stackguard() }
-func stack1564() (uintptr, uintptr) { var buf [1564]byte; use(buf[:]); return Stackguard() }
-func stack1568() (uintptr, uintptr) { var buf [1568]byte; use(buf[:]); return Stackguard() }
-func stack1572() (uintptr, uintptr) { var buf [1572]byte; use(buf[:]); return Stackguard() }
-func stack1576() (uintptr, uintptr) { var buf [1576]byte; use(buf[:]); return Stackguard() }
-func stack1580() (uintptr, uintptr) { var buf [1580]byte; use(buf[:]); return Stackguard() }
-func stack1584() (uintptr, uintptr) { var buf [1584]byte; use(buf[:]); return Stackguard() }
-func stack1588() (uintptr, uintptr) { var buf [1588]byte; use(buf[:]); return Stackguard() }
-func stack1592() (uintptr, uintptr) { var buf [1592]byte; use(buf[:]); return Stackguard() }
-func stack1596() (uintptr, uintptr) { var buf [1596]byte; use(buf[:]); return Stackguard() }
-func stack1600() (uintptr, uintptr) { var buf [1600]byte; use(buf[:]); return Stackguard() }
-func stack1604() (uintptr, uintptr) { var buf [1604]byte; use(buf[:]); return Stackguard() }
-func stack1608() (uintptr, uintptr) { var buf [1608]byte; use(buf[:]); return Stackguard() }
-func stack1612() (uintptr, uintptr) { var buf [1612]byte; use(buf[:]); return Stackguard() }
-func stack1616() (uintptr, uintptr) { var buf [1616]byte; use(buf[:]); return Stackguard() }
-func stack1620() (uintptr, uintptr) { var buf [1620]byte; use(buf[:]); return Stackguard() }
-func stack1624() (uintptr, uintptr) { var buf [1624]byte; use(buf[:]); return Stackguard() }
-func stack1628() (uintptr, uintptr) { var buf [1628]byte; use(buf[:]); return Stackguard() }
-func stack1632() (uintptr, uintptr) { var buf [1632]byte; use(buf[:]); return Stackguard() }
-func stack1636() (uintptr, uintptr) { var buf [1636]byte; use(buf[:]); return Stackguard() }
-func stack1640() (uintptr, uintptr) { var buf [1640]byte; use(buf[:]); return Stackguard() }
-func stack1644() (uintptr, uintptr) { var buf [1644]byte; use(buf[:]); return Stackguard() }
-func stack1648() (uintptr, uintptr) { var buf [1648]byte; use(buf[:]); return Stackguard() }
-func stack1652() (uintptr, uintptr) { var buf [1652]byte; use(buf[:]); return Stackguard() }
-func stack1656() (uintptr, uintptr) { var buf [1656]byte; use(buf[:]); return Stackguard() }
-func stack1660() (uintptr, uintptr) { var buf [1660]byte; use(buf[:]); return Stackguard() }
-func stack1664() (uintptr, uintptr) { var buf [1664]byte; use(buf[:]); return Stackguard() }
-func stack1668() (uintptr, uintptr) { var buf [1668]byte; use(buf[:]); return Stackguard() }
-func stack1672() (uintptr, uintptr) { var buf [1672]byte; use(buf[:]); return Stackguard() }
-func stack1676() (uintptr, uintptr) { var buf [1676]byte; use(buf[:]); return Stackguard() }
-func stack1680() (uintptr, uintptr) { var buf [1680]byte; use(buf[:]); return Stackguard() }
-func stack1684() (uintptr, uintptr) { var buf [1684]byte; use(buf[:]); return Stackguard() }
-func stack1688() (uintptr, uintptr) { var buf [1688]byte; use(buf[:]); return Stackguard() }
-func stack1692() (uintptr, uintptr) { var buf [1692]byte; use(buf[:]); return Stackguard() }
-func stack1696() (uintptr, uintptr) { var buf [1696]byte; use(buf[:]); return Stackguard() }
-func stack1700() (uintptr, uintptr) { var buf [1700]byte; use(buf[:]); return Stackguard() }
-func stack1704() (uintptr, uintptr) { var buf [1704]byte; use(buf[:]); return Stackguard() }
-func stack1708() (uintptr, uintptr) { var buf [1708]byte; use(buf[:]); return Stackguard() }
-func stack1712() (uintptr, uintptr) { var buf [1712]byte; use(buf[:]); return Stackguard() }
-func stack1716() (uintptr, uintptr) { var buf [1716]byte; use(buf[:]); return Stackguard() }
-func stack1720() (uintptr, uintptr) { var buf [1720]byte; use(buf[:]); return Stackguard() }
-func stack1724() (uintptr, uintptr) { var buf [1724]byte; use(buf[:]); return Stackguard() }
-func stack1728() (uintptr, uintptr) { var buf [1728]byte; use(buf[:]); return Stackguard() }
-func stack1732() (uintptr, uintptr) { var buf [1732]byte; use(buf[:]); return Stackguard() }
-func stack1736() (uintptr, uintptr) { var buf [1736]byte; use(buf[:]); return Stackguard() }
-func stack1740() (uintptr, uintptr) { var buf [1740]byte; use(buf[:]); return Stackguard() }
-func stack1744() (uintptr, uintptr) { var buf [1744]byte; use(buf[:]); return Stackguard() }
-func stack1748() (uintptr, uintptr) { var buf [1748]byte; use(buf[:]); return Stackguard() }
-func stack1752() (uintptr, uintptr) { var buf [1752]byte; use(buf[:]); return Stackguard() }
-func stack1756() (uintptr, uintptr) { var buf [1756]byte; use(buf[:]); return Stackguard() }
-func stack1760() (uintptr, uintptr) { var buf [1760]byte; use(buf[:]); return Stackguard() }
-func stack1764() (uintptr, uintptr) { var buf [1764]byte; use(buf[:]); return Stackguard() }
-func stack1768() (uintptr, uintptr) { var buf [1768]byte; use(buf[:]); return Stackguard() }
-func stack1772() (uintptr, uintptr) { var buf [1772]byte; use(buf[:]); return Stackguard() }
-func stack1776() (uintptr, uintptr) { var buf [1776]byte; use(buf[:]); return Stackguard() }
-func stack1780() (uintptr, uintptr) { var buf [1780]byte; use(buf[:]); return Stackguard() }
-func stack1784() (uintptr, uintptr) { var buf [1784]byte; use(buf[:]); return Stackguard() }
-func stack1788() (uintptr, uintptr) { var buf [1788]byte; use(buf[:]); return Stackguard() }
-func stack1792() (uintptr, uintptr) { var buf [1792]byte; use(buf[:]); return Stackguard() }
-func stack1796() (uintptr, uintptr) { var buf [1796]byte; use(buf[:]); return Stackguard() }
-func stack1800() (uintptr, uintptr) { var buf [1800]byte; use(buf[:]); return Stackguard() }
-func stack1804() (uintptr, uintptr) { var buf [1804]byte; use(buf[:]); return Stackguard() }
-func stack1808() (uintptr, uintptr) { var buf [1808]byte; use(buf[:]); return Stackguard() }
-func stack1812() (uintptr, uintptr) { var buf [1812]byte; use(buf[:]); return Stackguard() }
-func stack1816() (uintptr, uintptr) { var buf [1816]byte; use(buf[:]); return Stackguard() }
-func stack1820() (uintptr, uintptr) { var buf [1820]byte; use(buf[:]); return Stackguard() }
-func stack1824() (uintptr, uintptr) { var buf [1824]byte; use(buf[:]); return Stackguard() }
-func stack1828() (uintptr, uintptr) { var buf [1828]byte; use(buf[:]); return Stackguard() }
-func stack1832() (uintptr, uintptr) { var buf [1832]byte; use(buf[:]); return Stackguard() }
-func stack1836() (uintptr, uintptr) { var buf [1836]byte; use(buf[:]); return Stackguard() }
-func stack1840() (uintptr, uintptr) { var buf [1840]byte; use(buf[:]); return Stackguard() }
-func stack1844() (uintptr, uintptr) { var buf [1844]byte; use(buf[:]); return Stackguard() }
-func stack1848() (uintptr, uintptr) { var buf [1848]byte; use(buf[:]); return Stackguard() }
-func stack1852() (uintptr, uintptr) { var buf [1852]byte; use(buf[:]); return Stackguard() }
-func stack1856() (uintptr, uintptr) { var buf [1856]byte; use(buf[:]); return Stackguard() }
-func stack1860() (uintptr, uintptr) { var buf [1860]byte; use(buf[:]); return Stackguard() }
-func stack1864() (uintptr, uintptr) { var buf [1864]byte; use(buf[:]); return Stackguard() }
-func stack1868() (uintptr, uintptr) { var buf [1868]byte; use(buf[:]); return Stackguard() }
-func stack1872() (uintptr, uintptr) { var buf [1872]byte; use(buf[:]); return Stackguard() }
-func stack1876() (uintptr, uintptr) { var buf [1876]byte; use(buf[:]); return Stackguard() }
-func stack1880() (uintptr, uintptr) { var buf [1880]byte; use(buf[:]); return Stackguard() }
-func stack1884() (uintptr, uintptr) { var buf [1884]byte; use(buf[:]); return Stackguard() }
-func stack1888() (uintptr, uintptr) { var buf [1888]byte; use(buf[:]); return Stackguard() }
-func stack1892() (uintptr, uintptr) { var buf [1892]byte; use(buf[:]); return Stackguard() }
-func stack1896() (uintptr, uintptr) { var buf [1896]byte; use(buf[:]); return Stackguard() }
-func stack1900() (uintptr, uintptr) { var buf [1900]byte; use(buf[:]); return Stackguard() }
-func stack1904() (uintptr, uintptr) { var buf [1904]byte; use(buf[:]); return Stackguard() }
-func stack1908() (uintptr, uintptr) { var buf [1908]byte; use(buf[:]); return Stackguard() }
-func stack1912() (uintptr, uintptr) { var buf [1912]byte; use(buf[:]); return Stackguard() }
-func stack1916() (uintptr, uintptr) { var buf [1916]byte; use(buf[:]); return Stackguard() }
-func stack1920() (uintptr, uintptr) { var buf [1920]byte; use(buf[:]); return Stackguard() }
-func stack1924() (uintptr, uintptr) { var buf [1924]byte; use(buf[:]); return Stackguard() }
-func stack1928() (uintptr, uintptr) { var buf [1928]byte; use(buf[:]); return Stackguard() }
-func stack1932() (uintptr, uintptr) { var buf [1932]byte; use(buf[:]); return Stackguard() }
-func stack1936() (uintptr, uintptr) { var buf [1936]byte; use(buf[:]); return Stackguard() }
-func stack1940() (uintptr, uintptr) { var buf [1940]byte; use(buf[:]); return Stackguard() }
-func stack1944() (uintptr, uintptr) { var buf [1944]byte; use(buf[:]); return Stackguard() }
-func stack1948() (uintptr, uintptr) { var buf [1948]byte; use(buf[:]); return Stackguard() }
-func stack1952() (uintptr, uintptr) { var buf [1952]byte; use(buf[:]); return Stackguard() }
-func stack1956() (uintptr, uintptr) { var buf [1956]byte; use(buf[:]); return Stackguard() }
-func stack1960() (uintptr, uintptr) { var buf [1960]byte; use(buf[:]); return Stackguard() }
-func stack1964() (uintptr, uintptr) { var buf [1964]byte; use(buf[:]); return Stackguard() }
-func stack1968() (uintptr, uintptr) { var buf [1968]byte; use(buf[:]); return Stackguard() }
-func stack1972() (uintptr, uintptr) { var buf [1972]byte; use(buf[:]); return Stackguard() }
-func stack1976() (uintptr, uintptr) { var buf [1976]byte; use(buf[:]); return Stackguard() }
-func stack1980() (uintptr, uintptr) { var buf [1980]byte; use(buf[:]); return Stackguard() }
-func stack1984() (uintptr, uintptr) { var buf [1984]byte; use(buf[:]); return Stackguard() }
-func stack1988() (uintptr, uintptr) { var buf [1988]byte; use(buf[:]); return Stackguard() }
-func stack1992() (uintptr, uintptr) { var buf [1992]byte; use(buf[:]); return Stackguard() }
-func stack1996() (uintptr, uintptr) { var buf [1996]byte; use(buf[:]); return Stackguard() }
-func stack2000() (uintptr, uintptr) { var buf [2000]byte; use(buf[:]); return Stackguard() }
-func stack2004() (uintptr, uintptr) { var buf [2004]byte; use(buf[:]); return Stackguard() }
-func stack2008() (uintptr, uintptr) { var buf [2008]byte; use(buf[:]); return Stackguard() }
-func stack2012() (uintptr, uintptr) { var buf [2012]byte; use(buf[:]); return Stackguard() }
-func stack2016() (uintptr, uintptr) { var buf [2016]byte; use(buf[:]); return Stackguard() }
-func stack2020() (uintptr, uintptr) { var buf [2020]byte; use(buf[:]); return Stackguard() }
-func stack2024() (uintptr, uintptr) { var buf [2024]byte; use(buf[:]); return Stackguard() }
-func stack2028() (uintptr, uintptr) { var buf [2028]byte; use(buf[:]); return Stackguard() }
-func stack2032() (uintptr, uintptr) { var buf [2032]byte; use(buf[:]); return Stackguard() }
-func stack2036() (uintptr, uintptr) { var buf [2036]byte; use(buf[:]); return Stackguard() }
-func stack2040() (uintptr, uintptr) { var buf [2040]byte; use(buf[:]); return Stackguard() }
-func stack2044() (uintptr, uintptr) { var buf [2044]byte; use(buf[:]); return Stackguard() }
-func stack2048() (uintptr, uintptr) { var buf [2048]byte; use(buf[:]); return Stackguard() }
-func stack2052() (uintptr, uintptr) { var buf [2052]byte; use(buf[:]); return Stackguard() }
-func stack2056() (uintptr, uintptr) { var buf [2056]byte; use(buf[:]); return Stackguard() }
-func stack2060() (uintptr, uintptr) { var buf [2060]byte; use(buf[:]); return Stackguard() }
-func stack2064() (uintptr, uintptr) { var buf [2064]byte; use(buf[:]); return Stackguard() }
-func stack2068() (uintptr, uintptr) { var buf [2068]byte; use(buf[:]); return Stackguard() }
-func stack2072() (uintptr, uintptr) { var buf [2072]byte; use(buf[:]); return Stackguard() }
-func stack2076() (uintptr, uintptr) { var buf [2076]byte; use(buf[:]); return Stackguard() }
-func stack2080() (uintptr, uintptr) { var buf [2080]byte; use(buf[:]); return Stackguard() }
-func stack2084() (uintptr, uintptr) { var buf [2084]byte; use(buf[:]); return Stackguard() }
-func stack2088() (uintptr, uintptr) { var buf [2088]byte; use(buf[:]); return Stackguard() }
-func stack2092() (uintptr, uintptr) { var buf [2092]byte; use(buf[:]); return Stackguard() }
-func stack2096() (uintptr, uintptr) { var buf [2096]byte; use(buf[:]); return Stackguard() }
-func stack2100() (uintptr, uintptr) { var buf [2100]byte; use(buf[:]); return Stackguard() }
-func stack2104() (uintptr, uintptr) { var buf [2104]byte; use(buf[:]); return Stackguard() }
-func stack2108() (uintptr, uintptr) { var buf [2108]byte; use(buf[:]); return Stackguard() }
-func stack2112() (uintptr, uintptr) { var buf [2112]byte; use(buf[:]); return Stackguard() }
-func stack2116() (uintptr, uintptr) { var buf [2116]byte; use(buf[:]); return Stackguard() }
-func stack2120() (uintptr, uintptr) { var buf [2120]byte; use(buf[:]); return Stackguard() }
-func stack2124() (uintptr, uintptr) { var buf [2124]byte; use(buf[:]); return Stackguard() }
-func stack2128() (uintptr, uintptr) { var buf [2128]byte; use(buf[:]); return Stackguard() }
-func stack2132() (uintptr, uintptr) { var buf [2132]byte; use(buf[:]); return Stackguard() }
-func stack2136() (uintptr, uintptr) { var buf [2136]byte; use(buf[:]); return Stackguard() }
-func stack2140() (uintptr, uintptr) { var buf [2140]byte; use(buf[:]); return Stackguard() }
-func stack2144() (uintptr, uintptr) { var buf [2144]byte; use(buf[:]); return Stackguard() }
-func stack2148() (uintptr, uintptr) { var buf [2148]byte; use(buf[:]); return Stackguard() }
-func stack2152() (uintptr, uintptr) { var buf [2152]byte; use(buf[:]); return Stackguard() }
-func stack2156() (uintptr, uintptr) { var buf [2156]byte; use(buf[:]); return Stackguard() }
-func stack2160() (uintptr, uintptr) { var buf [2160]byte; use(buf[:]); return Stackguard() }
-func stack2164() (uintptr, uintptr) { var buf [2164]byte; use(buf[:]); return Stackguard() }
-func stack2168() (uintptr, uintptr) { var buf [2168]byte; use(buf[:]); return Stackguard() }
-func stack2172() (uintptr, uintptr) { var buf [2172]byte; use(buf[:]); return Stackguard() }
-func stack2176() (uintptr, uintptr) { var buf [2176]byte; use(buf[:]); return Stackguard() }
-func stack2180() (uintptr, uintptr) { var buf [2180]byte; use(buf[:]); return Stackguard() }
-func stack2184() (uintptr, uintptr) { var buf [2184]byte; use(buf[:]); return Stackguard() }
-func stack2188() (uintptr, uintptr) { var buf [2188]byte; use(buf[:]); return Stackguard() }
-func stack2192() (uintptr, uintptr) { var buf [2192]byte; use(buf[:]); return Stackguard() }
-func stack2196() (uintptr, uintptr) { var buf [2196]byte; use(buf[:]); return Stackguard() }
-func stack2200() (uintptr, uintptr) { var buf [2200]byte; use(buf[:]); return Stackguard() }
-func stack2204() (uintptr, uintptr) { var buf [2204]byte; use(buf[:]); return Stackguard() }
-func stack2208() (uintptr, uintptr) { var buf [2208]byte; use(buf[:]); return Stackguard() }
-func stack2212() (uintptr, uintptr) { var buf [2212]byte; use(buf[:]); return Stackguard() }
-func stack2216() (uintptr, uintptr) { var buf [2216]byte; use(buf[:]); return Stackguard() }
-func stack2220() (uintptr, uintptr) { var buf [2220]byte; use(buf[:]); return Stackguard() }
-func stack2224() (uintptr, uintptr) { var buf [2224]byte; use(buf[:]); return Stackguard() }
-func stack2228() (uintptr, uintptr) { var buf [2228]byte; use(buf[:]); return Stackguard() }
-func stack2232() (uintptr, uintptr) { var buf [2232]byte; use(buf[:]); return Stackguard() }
-func stack2236() (uintptr, uintptr) { var buf [2236]byte; use(buf[:]); return Stackguard() }
-func stack2240() (uintptr, uintptr) { var buf [2240]byte; use(buf[:]); return Stackguard() }
-func stack2244() (uintptr, uintptr) { var buf [2244]byte; use(buf[:]); return Stackguard() }
-func stack2248() (uintptr, uintptr) { var buf [2248]byte; use(buf[:]); return Stackguard() }
-func stack2252() (uintptr, uintptr) { var buf [2252]byte; use(buf[:]); return Stackguard() }
-func stack2256() (uintptr, uintptr) { var buf [2256]byte; use(buf[:]); return Stackguard() }
-func stack2260() (uintptr, uintptr) { var buf [2260]byte; use(buf[:]); return Stackguard() }
-func stack2264() (uintptr, uintptr) { var buf [2264]byte; use(buf[:]); return Stackguard() }
-func stack2268() (uintptr, uintptr) { var buf [2268]byte; use(buf[:]); return Stackguard() }
-func stack2272() (uintptr, uintptr) { var buf [2272]byte; use(buf[:]); return Stackguard() }
-func stack2276() (uintptr, uintptr) { var buf [2276]byte; use(buf[:]); return Stackguard() }
-func stack2280() (uintptr, uintptr) { var buf [2280]byte; use(buf[:]); return Stackguard() }
-func stack2284() (uintptr, uintptr) { var buf [2284]byte; use(buf[:]); return Stackguard() }
-func stack2288() (uintptr, uintptr) { var buf [2288]byte; use(buf[:]); return Stackguard() }
-func stack2292() (uintptr, uintptr) { var buf [2292]byte; use(buf[:]); return Stackguard() }
-func stack2296() (uintptr, uintptr) { var buf [2296]byte; use(buf[:]); return Stackguard() }
-func stack2300() (uintptr, uintptr) { var buf [2300]byte; use(buf[:]); return Stackguard() }
-func stack2304() (uintptr, uintptr) { var buf [2304]byte; use(buf[:]); return Stackguard() }
-func stack2308() (uintptr, uintptr) { var buf [2308]byte; use(buf[:]); return Stackguard() }
-func stack2312() (uintptr, uintptr) { var buf [2312]byte; use(buf[:]); return Stackguard() }
-func stack2316() (uintptr, uintptr) { var buf [2316]byte; use(buf[:]); return Stackguard() }
-func stack2320() (uintptr, uintptr) { var buf [2320]byte; use(buf[:]); return Stackguard() }
-func stack2324() (uintptr, uintptr) { var buf [2324]byte; use(buf[:]); return Stackguard() }
-func stack2328() (uintptr, uintptr) { var buf [2328]byte; use(buf[:]); return Stackguard() }
-func stack2332() (uintptr, uintptr) { var buf [2332]byte; use(buf[:]); return Stackguard() }
-func stack2336() (uintptr, uintptr) { var buf [2336]byte; use(buf[:]); return Stackguard() }
-func stack2340() (uintptr, uintptr) { var buf [2340]byte; use(buf[:]); return Stackguard() }
-func stack2344() (uintptr, uintptr) { var buf [2344]byte; use(buf[:]); return Stackguard() }
-func stack2348() (uintptr, uintptr) { var buf [2348]byte; use(buf[:]); return Stackguard() }
-func stack2352() (uintptr, uintptr) { var buf [2352]byte; use(buf[:]); return Stackguard() }
-func stack2356() (uintptr, uintptr) { var buf [2356]byte; use(buf[:]); return Stackguard() }
-func stack2360() (uintptr, uintptr) { var buf [2360]byte; use(buf[:]); return Stackguard() }
-func stack2364() (uintptr, uintptr) { var buf [2364]byte; use(buf[:]); return Stackguard() }
-func stack2368() (uintptr, uintptr) { var buf [2368]byte; use(buf[:]); return Stackguard() }
-func stack2372() (uintptr, uintptr) { var buf [2372]byte; use(buf[:]); return Stackguard() }
-func stack2376() (uintptr, uintptr) { var buf [2376]byte; use(buf[:]); return Stackguard() }
-func stack2380() (uintptr, uintptr) { var buf [2380]byte; use(buf[:]); return Stackguard() }
-func stack2384() (uintptr, uintptr) { var buf [2384]byte; use(buf[:]); return Stackguard() }
-func stack2388() (uintptr, uintptr) { var buf [2388]byte; use(buf[:]); return Stackguard() }
-func stack2392() (uintptr, uintptr) { var buf [2392]byte; use(buf[:]); return Stackguard() }
-func stack2396() (uintptr, uintptr) { var buf [2396]byte; use(buf[:]); return Stackguard() }
-func stack2400() (uintptr, uintptr) { var buf [2400]byte; use(buf[:]); return Stackguard() }
-func stack2404() (uintptr, uintptr) { var buf [2404]byte; use(buf[:]); return Stackguard() }
-func stack2408() (uintptr, uintptr) { var buf [2408]byte; use(buf[:]); return Stackguard() }
-func stack2412() (uintptr, uintptr) { var buf [2412]byte; use(buf[:]); return Stackguard() }
-func stack2416() (uintptr, uintptr) { var buf [2416]byte; use(buf[:]); return Stackguard() }
-func stack2420() (uintptr, uintptr) { var buf [2420]byte; use(buf[:]); return Stackguard() }
-func stack2424() (uintptr, uintptr) { var buf [2424]byte; use(buf[:]); return Stackguard() }
-func stack2428() (uintptr, uintptr) { var buf [2428]byte; use(buf[:]); return Stackguard() }
-func stack2432() (uintptr, uintptr) { var buf [2432]byte; use(buf[:]); return Stackguard() }
-func stack2436() (uintptr, uintptr) { var buf [2436]byte; use(buf[:]); return Stackguard() }
-func stack2440() (uintptr, uintptr) { var buf [2440]byte; use(buf[:]); return Stackguard() }
-func stack2444() (uintptr, uintptr) { var buf [2444]byte; use(buf[:]); return Stackguard() }
-func stack2448() (uintptr, uintptr) { var buf [2448]byte; use(buf[:]); return Stackguard() }
-func stack2452() (uintptr, uintptr) { var buf [2452]byte; use(buf[:]); return Stackguard() }
-func stack2456() (uintptr, uintptr) { var buf [2456]byte; use(buf[:]); return Stackguard() }
-func stack2460() (uintptr, uintptr) { var buf [2460]byte; use(buf[:]); return Stackguard() }
-func stack2464() (uintptr, uintptr) { var buf [2464]byte; use(buf[:]); return Stackguard() }
-func stack2468() (uintptr, uintptr) { var buf [2468]byte; use(buf[:]); return Stackguard() }
-func stack2472() (uintptr, uintptr) { var buf [2472]byte; use(buf[:]); return Stackguard() }
-func stack2476() (uintptr, uintptr) { var buf [2476]byte; use(buf[:]); return Stackguard() }
-func stack2480() (uintptr, uintptr) { var buf [2480]byte; use(buf[:]); return Stackguard() }
-func stack2484() (uintptr, uintptr) { var buf [2484]byte; use(buf[:]); return Stackguard() }
-func stack2488() (uintptr, uintptr) { var buf [2488]byte; use(buf[:]); return Stackguard() }
-func stack2492() (uintptr, uintptr) { var buf [2492]byte; use(buf[:]); return Stackguard() }
-func stack2496() (uintptr, uintptr) { var buf [2496]byte; use(buf[:]); return Stackguard() }
-func stack2500() (uintptr, uintptr) { var buf [2500]byte; use(buf[:]); return Stackguard() }
-func stack2504() (uintptr, uintptr) { var buf [2504]byte; use(buf[:]); return Stackguard() }
-func stack2508() (uintptr, uintptr) { var buf [2508]byte; use(buf[:]); return Stackguard() }
-func stack2512() (uintptr, uintptr) { var buf [2512]byte; use(buf[:]); return Stackguard() }
-func stack2516() (uintptr, uintptr) { var buf [2516]byte; use(buf[:]); return Stackguard() }
-func stack2520() (uintptr, uintptr) { var buf [2520]byte; use(buf[:]); return Stackguard() }
-func stack2524() (uintptr, uintptr) { var buf [2524]byte; use(buf[:]); return Stackguard() }
-func stack2528() (uintptr, uintptr) { var buf [2528]byte; use(buf[:]); return Stackguard() }
-func stack2532() (uintptr, uintptr) { var buf [2532]byte; use(buf[:]); return Stackguard() }
-func stack2536() (uintptr, uintptr) { var buf [2536]byte; use(buf[:]); return Stackguard() }
-func stack2540() (uintptr, uintptr) { var buf [2540]byte; use(buf[:]); return Stackguard() }
-func stack2544() (uintptr, uintptr) { var buf [2544]byte; use(buf[:]); return Stackguard() }
-func stack2548() (uintptr, uintptr) { var buf [2548]byte; use(buf[:]); return Stackguard() }
-func stack2552() (uintptr, uintptr) { var buf [2552]byte; use(buf[:]); return Stackguard() }
-func stack2556() (uintptr, uintptr) { var buf [2556]byte; use(buf[:]); return Stackguard() }
-func stack2560() (uintptr, uintptr) { var buf [2560]byte; use(buf[:]); return Stackguard() }
-func stack2564() (uintptr, uintptr) { var buf [2564]byte; use(buf[:]); return Stackguard() }
-func stack2568() (uintptr, uintptr) { var buf [2568]byte; use(buf[:]); return Stackguard() }
-func stack2572() (uintptr, uintptr) { var buf [2572]byte; use(buf[:]); return Stackguard() }
-func stack2576() (uintptr, uintptr) { var buf [2576]byte; use(buf[:]); return Stackguard() }
-func stack2580() (uintptr, uintptr) { var buf [2580]byte; use(buf[:]); return Stackguard() }
-func stack2584() (uintptr, uintptr) { var buf [2584]byte; use(buf[:]); return Stackguard() }
-func stack2588() (uintptr, uintptr) { var buf [2588]byte; use(buf[:]); return Stackguard() }
-func stack2592() (uintptr, uintptr) { var buf [2592]byte; use(buf[:]); return Stackguard() }
-func stack2596() (uintptr, uintptr) { var buf [2596]byte; use(buf[:]); return Stackguard() }
-func stack2600() (uintptr, uintptr) { var buf [2600]byte; use(buf[:]); return Stackguard() }
-func stack2604() (uintptr, uintptr) { var buf [2604]byte; use(buf[:]); return Stackguard() }
-func stack2608() (uintptr, uintptr) { var buf [2608]byte; use(buf[:]); return Stackguard() }
-func stack2612() (uintptr, uintptr) { var buf [2612]byte; use(buf[:]); return Stackguard() }
-func stack2616() (uintptr, uintptr) { var buf [2616]byte; use(buf[:]); return Stackguard() }
-func stack2620() (uintptr, uintptr) { var buf [2620]byte; use(buf[:]); return Stackguard() }
-func stack2624() (uintptr, uintptr) { var buf [2624]byte; use(buf[:]); return Stackguard() }
-func stack2628() (uintptr, uintptr) { var buf [2628]byte; use(buf[:]); return Stackguard() }
-func stack2632() (uintptr, uintptr) { var buf [2632]byte; use(buf[:]); return Stackguard() }
-func stack2636() (uintptr, uintptr) { var buf [2636]byte; use(buf[:]); return Stackguard() }
-func stack2640() (uintptr, uintptr) { var buf [2640]byte; use(buf[:]); return Stackguard() }
-func stack2644() (uintptr, uintptr) { var buf [2644]byte; use(buf[:]); return Stackguard() }
-func stack2648() (uintptr, uintptr) { var buf [2648]byte; use(buf[:]); return Stackguard() }
-func stack2652() (uintptr, uintptr) { var buf [2652]byte; use(buf[:]); return Stackguard() }
-func stack2656() (uintptr, uintptr) { var buf [2656]byte; use(buf[:]); return Stackguard() }
-func stack2660() (uintptr, uintptr) { var buf [2660]byte; use(buf[:]); return Stackguard() }
-func stack2664() (uintptr, uintptr) { var buf [2664]byte; use(buf[:]); return Stackguard() }
-func stack2668() (uintptr, uintptr) { var buf [2668]byte; use(buf[:]); return Stackguard() }
-func stack2672() (uintptr, uintptr) { var buf [2672]byte; use(buf[:]); return Stackguard() }
-func stack2676() (uintptr, uintptr) { var buf [2676]byte; use(buf[:]); return Stackguard() }
-func stack2680() (uintptr, uintptr) { var buf [2680]byte; use(buf[:]); return Stackguard() }
-func stack2684() (uintptr, uintptr) { var buf [2684]byte; use(buf[:]); return Stackguard() }
-func stack2688() (uintptr, uintptr) { var buf [2688]byte; use(buf[:]); return Stackguard() }
-func stack2692() (uintptr, uintptr) { var buf [2692]byte; use(buf[:]); return Stackguard() }
-func stack2696() (uintptr, uintptr) { var buf [2696]byte; use(buf[:]); return Stackguard() }
-func stack2700() (uintptr, uintptr) { var buf [2700]byte; use(buf[:]); return Stackguard() }
-func stack2704() (uintptr, uintptr) { var buf [2704]byte; use(buf[:]); return Stackguard() }
-func stack2708() (uintptr, uintptr) { var buf [2708]byte; use(buf[:]); return Stackguard() }
-func stack2712() (uintptr, uintptr) { var buf [2712]byte; use(buf[:]); return Stackguard() }
-func stack2716() (uintptr, uintptr) { var buf [2716]byte; use(buf[:]); return Stackguard() }
-func stack2720() (uintptr, uintptr) { var buf [2720]byte; use(buf[:]); return Stackguard() }
-func stack2724() (uintptr, uintptr) { var buf [2724]byte; use(buf[:]); return Stackguard() }
-func stack2728() (uintptr, uintptr) { var buf [2728]byte; use(buf[:]); return Stackguard() }
-func stack2732() (uintptr, uintptr) { var buf [2732]byte; use(buf[:]); return Stackguard() }
-func stack2736() (uintptr, uintptr) { var buf [2736]byte; use(buf[:]); return Stackguard() }
-func stack2740() (uintptr, uintptr) { var buf [2740]byte; use(buf[:]); return Stackguard() }
-func stack2744() (uintptr, uintptr) { var buf [2744]byte; use(buf[:]); return Stackguard() }
-func stack2748() (uintptr, uintptr) { var buf [2748]byte; use(buf[:]); return Stackguard() }
-func stack2752() (uintptr, uintptr) { var buf [2752]byte; use(buf[:]); return Stackguard() }
-func stack2756() (uintptr, uintptr) { var buf [2756]byte; use(buf[:]); return Stackguard() }
-func stack2760() (uintptr, uintptr) { var buf [2760]byte; use(buf[:]); return Stackguard() }
-func stack2764() (uintptr, uintptr) { var buf [2764]byte; use(buf[:]); return Stackguard() }
-func stack2768() (uintptr, uintptr) { var buf [2768]byte; use(buf[:]); return Stackguard() }
-func stack2772() (uintptr, uintptr) { var buf [2772]byte; use(buf[:]); return Stackguard() }
-func stack2776() (uintptr, uintptr) { var buf [2776]byte; use(buf[:]); return Stackguard() }
-func stack2780() (uintptr, uintptr) { var buf [2780]byte; use(buf[:]); return Stackguard() }
-func stack2784() (uintptr, uintptr) { var buf [2784]byte; use(buf[:]); return Stackguard() }
-func stack2788() (uintptr, uintptr) { var buf [2788]byte; use(buf[:]); return Stackguard() }
-func stack2792() (uintptr, uintptr) { var buf [2792]byte; use(buf[:]); return Stackguard() }
-func stack2796() (uintptr, uintptr) { var buf [2796]byte; use(buf[:]); return Stackguard() }
-func stack2800() (uintptr, uintptr) { var buf [2800]byte; use(buf[:]); return Stackguard() }
-func stack2804() (uintptr, uintptr) { var buf [2804]byte; use(buf[:]); return Stackguard() }
-func stack2808() (uintptr, uintptr) { var buf [2808]byte; use(buf[:]); return Stackguard() }
-func stack2812() (uintptr, uintptr) { var buf [2812]byte; use(buf[:]); return Stackguard() }
-func stack2816() (uintptr, uintptr) { var buf [2816]byte; use(buf[:]); return Stackguard() }
-func stack2820() (uintptr, uintptr) { var buf [2820]byte; use(buf[:]); return Stackguard() }
-func stack2824() (uintptr, uintptr) { var buf [2824]byte; use(buf[:]); return Stackguard() }
-func stack2828() (uintptr, uintptr) { var buf [2828]byte; use(buf[:]); return Stackguard() }
-func stack2832() (uintptr, uintptr) { var buf [2832]byte; use(buf[:]); return Stackguard() }
-func stack2836() (uintptr, uintptr) { var buf [2836]byte; use(buf[:]); return Stackguard() }
-func stack2840() (uintptr, uintptr) { var buf [2840]byte; use(buf[:]); return Stackguard() }
-func stack2844() (uintptr, uintptr) { var buf [2844]byte; use(buf[:]); return Stackguard() }
-func stack2848() (uintptr, uintptr) { var buf [2848]byte; use(buf[:]); return Stackguard() }
-func stack2852() (uintptr, uintptr) { var buf [2852]byte; use(buf[:]); return Stackguard() }
-func stack2856() (uintptr, uintptr) { var buf [2856]byte; use(buf[:]); return Stackguard() }
-func stack2860() (uintptr, uintptr) { var buf [2860]byte; use(buf[:]); return Stackguard() }
-func stack2864() (uintptr, uintptr) { var buf [2864]byte; use(buf[:]); return Stackguard() }
-func stack2868() (uintptr, uintptr) { var buf [2868]byte; use(buf[:]); return Stackguard() }
-func stack2872() (uintptr, uintptr) { var buf [2872]byte; use(buf[:]); return Stackguard() }
-func stack2876() (uintptr, uintptr) { var buf [2876]byte; use(buf[:]); return Stackguard() }
-func stack2880() (uintptr, uintptr) { var buf [2880]byte; use(buf[:]); return Stackguard() }
-func stack2884() (uintptr, uintptr) { var buf [2884]byte; use(buf[:]); return Stackguard() }
-func stack2888() (uintptr, uintptr) { var buf [2888]byte; use(buf[:]); return Stackguard() }
-func stack2892() (uintptr, uintptr) { var buf [2892]byte; use(buf[:]); return Stackguard() }
-func stack2896() (uintptr, uintptr) { var buf [2896]byte; use(buf[:]); return Stackguard() }
-func stack2900() (uintptr, uintptr) { var buf [2900]byte; use(buf[:]); return Stackguard() }
-func stack2904() (uintptr, uintptr) { var buf [2904]byte; use(buf[:]); return Stackguard() }
-func stack2908() (uintptr, uintptr) { var buf [2908]byte; use(buf[:]); return Stackguard() }
-func stack2912() (uintptr, uintptr) { var buf [2912]byte; use(buf[:]); return Stackguard() }
-func stack2916() (uintptr, uintptr) { var buf [2916]byte; use(buf[:]); return Stackguard() }
-func stack2920() (uintptr, uintptr) { var buf [2920]byte; use(buf[:]); return Stackguard() }
-func stack2924() (uintptr, uintptr) { var buf [2924]byte; use(buf[:]); return Stackguard() }
-func stack2928() (uintptr, uintptr) { var buf [2928]byte; use(buf[:]); return Stackguard() }
-func stack2932() (uintptr, uintptr) { var buf [2932]byte; use(buf[:]); return Stackguard() }
-func stack2936() (uintptr, uintptr) { var buf [2936]byte; use(buf[:]); return Stackguard() }
-func stack2940() (uintptr, uintptr) { var buf [2940]byte; use(buf[:]); return Stackguard() }
-func stack2944() (uintptr, uintptr) { var buf [2944]byte; use(buf[:]); return Stackguard() }
-func stack2948() (uintptr, uintptr) { var buf [2948]byte; use(buf[:]); return Stackguard() }
-func stack2952() (uintptr, uintptr) { var buf [2952]byte; use(buf[:]); return Stackguard() }
-func stack2956() (uintptr, uintptr) { var buf [2956]byte; use(buf[:]); return Stackguard() }
-func stack2960() (uintptr, uintptr) { var buf [2960]byte; use(buf[:]); return Stackguard() }
-func stack2964() (uintptr, uintptr) { var buf [2964]byte; use(buf[:]); return Stackguard() }
-func stack2968() (uintptr, uintptr) { var buf [2968]byte; use(buf[:]); return Stackguard() }
-func stack2972() (uintptr, uintptr) { var buf [2972]byte; use(buf[:]); return Stackguard() }
-func stack2976() (uintptr, uintptr) { var buf [2976]byte; use(buf[:]); return Stackguard() }
-func stack2980() (uintptr, uintptr) { var buf [2980]byte; use(buf[:]); return Stackguard() }
-func stack2984() (uintptr, uintptr) { var buf [2984]byte; use(buf[:]); return Stackguard() }
-func stack2988() (uintptr, uintptr) { var buf [2988]byte; use(buf[:]); return Stackguard() }
-func stack2992() (uintptr, uintptr) { var buf [2992]byte; use(buf[:]); return Stackguard() }
-func stack2996() (uintptr, uintptr) { var buf [2996]byte; use(buf[:]); return Stackguard() }
-func stack3000() (uintptr, uintptr) { var buf [3000]byte; use(buf[:]); return Stackguard() }
-func stack3004() (uintptr, uintptr) { var buf [3004]byte; use(buf[:]); return Stackguard() }
-func stack3008() (uintptr, uintptr) { var buf [3008]byte; use(buf[:]); return Stackguard() }
-func stack3012() (uintptr, uintptr) { var buf [3012]byte; use(buf[:]); return Stackguard() }
-func stack3016() (uintptr, uintptr) { var buf [3016]byte; use(buf[:]); return Stackguard() }
-func stack3020() (uintptr, uintptr) { var buf [3020]byte; use(buf[:]); return Stackguard() }
-func stack3024() (uintptr, uintptr) { var buf [3024]byte; use(buf[:]); return Stackguard() }
-func stack3028() (uintptr, uintptr) { var buf [3028]byte; use(buf[:]); return Stackguard() }
-func stack3032() (uintptr, uintptr) { var buf [3032]byte; use(buf[:]); return Stackguard() }
-func stack3036() (uintptr, uintptr) { var buf [3036]byte; use(buf[:]); return Stackguard() }
-func stack3040() (uintptr, uintptr) { var buf [3040]byte; use(buf[:]); return Stackguard() }
-func stack3044() (uintptr, uintptr) { var buf [3044]byte; use(buf[:]); return Stackguard() }
-func stack3048() (uintptr, uintptr) { var buf [3048]byte; use(buf[:]); return Stackguard() }
-func stack3052() (uintptr, uintptr) { var buf [3052]byte; use(buf[:]); return Stackguard() }
-func stack3056() (uintptr, uintptr) { var buf [3056]byte; use(buf[:]); return Stackguard() }
-func stack3060() (uintptr, uintptr) { var buf [3060]byte; use(buf[:]); return Stackguard() }
-func stack3064() (uintptr, uintptr) { var buf [3064]byte; use(buf[:]); return Stackguard() }
-func stack3068() (uintptr, uintptr) { var buf [3068]byte; use(buf[:]); return Stackguard() }
-func stack3072() (uintptr, uintptr) { var buf [3072]byte; use(buf[:]); return Stackguard() }
-func stack3076() (uintptr, uintptr) { var buf [3076]byte; use(buf[:]); return Stackguard() }
-func stack3080() (uintptr, uintptr) { var buf [3080]byte; use(buf[:]); return Stackguard() }
-func stack3084() (uintptr, uintptr) { var buf [3084]byte; use(buf[:]); return Stackguard() }
-func stack3088() (uintptr, uintptr) { var buf [3088]byte; use(buf[:]); return Stackguard() }
-func stack3092() (uintptr, uintptr) { var buf [3092]byte; use(buf[:]); return Stackguard() }
-func stack3096() (uintptr, uintptr) { var buf [3096]byte; use(buf[:]); return Stackguard() }
-func stack3100() (uintptr, uintptr) { var buf [3100]byte; use(buf[:]); return Stackguard() }
-func stack3104() (uintptr, uintptr) { var buf [3104]byte; use(buf[:]); return Stackguard() }
-func stack3108() (uintptr, uintptr) { var buf [3108]byte; use(buf[:]); return Stackguard() }
-func stack3112() (uintptr, uintptr) { var buf [3112]byte; use(buf[:]); return Stackguard() }
-func stack3116() (uintptr, uintptr) { var buf [3116]byte; use(buf[:]); return Stackguard() }
-func stack3120() (uintptr, uintptr) { var buf [3120]byte; use(buf[:]); return Stackguard() }
-func stack3124() (uintptr, uintptr) { var buf [3124]byte; use(buf[:]); return Stackguard() }
-func stack3128() (uintptr, uintptr) { var buf [3128]byte; use(buf[:]); return Stackguard() }
-func stack3132() (uintptr, uintptr) { var buf [3132]byte; use(buf[:]); return Stackguard() }
-func stack3136() (uintptr, uintptr) { var buf [3136]byte; use(buf[:]); return Stackguard() }
-func stack3140() (uintptr, uintptr) { var buf [3140]byte; use(buf[:]); return Stackguard() }
-func stack3144() (uintptr, uintptr) { var buf [3144]byte; use(buf[:]); return Stackguard() }
-func stack3148() (uintptr, uintptr) { var buf [3148]byte; use(buf[:]); return Stackguard() }
-func stack3152() (uintptr, uintptr) { var buf [3152]byte; use(buf[:]); return Stackguard() }
-func stack3156() (uintptr, uintptr) { var buf [3156]byte; use(buf[:]); return Stackguard() }
-func stack3160() (uintptr, uintptr) { var buf [3160]byte; use(buf[:]); return Stackguard() }
-func stack3164() (uintptr, uintptr) { var buf [3164]byte; use(buf[:]); return Stackguard() }
-func stack3168() (uintptr, uintptr) { var buf [3168]byte; use(buf[:]); return Stackguard() }
-func stack3172() (uintptr, uintptr) { var buf [3172]byte; use(buf[:]); return Stackguard() }
-func stack3176() (uintptr, uintptr) { var buf [3176]byte; use(buf[:]); return Stackguard() }
-func stack3180() (uintptr, uintptr) { var buf [3180]byte; use(buf[:]); return Stackguard() }
-func stack3184() (uintptr, uintptr) { var buf [3184]byte; use(buf[:]); return Stackguard() }
-func stack3188() (uintptr, uintptr) { var buf [3188]byte; use(buf[:]); return Stackguard() }
-func stack3192() (uintptr, uintptr) { var buf [3192]byte; use(buf[:]); return Stackguard() }
-func stack3196() (uintptr, uintptr) { var buf [3196]byte; use(buf[:]); return Stackguard() }
-func stack3200() (uintptr, uintptr) { var buf [3200]byte; use(buf[:]); return Stackguard() }
-func stack3204() (uintptr, uintptr) { var buf [3204]byte; use(buf[:]); return Stackguard() }
-func stack3208() (uintptr, uintptr) { var buf [3208]byte; use(buf[:]); return Stackguard() }
-func stack3212() (uintptr, uintptr) { var buf [3212]byte; use(buf[:]); return Stackguard() }
-func stack3216() (uintptr, uintptr) { var buf [3216]byte; use(buf[:]); return Stackguard() }
-func stack3220() (uintptr, uintptr) { var buf [3220]byte; use(buf[:]); return Stackguard() }
-func stack3224() (uintptr, uintptr) { var buf [3224]byte; use(buf[:]); return Stackguard() }
-func stack3228() (uintptr, uintptr) { var buf [3228]byte; use(buf[:]); return Stackguard() }
-func stack3232() (uintptr, uintptr) { var buf [3232]byte; use(buf[:]); return Stackguard() }
-func stack3236() (uintptr, uintptr) { var buf [3236]byte; use(buf[:]); return Stackguard() }
-func stack3240() (uintptr, uintptr) { var buf [3240]byte; use(buf[:]); return Stackguard() }
-func stack3244() (uintptr, uintptr) { var buf [3244]byte; use(buf[:]); return Stackguard() }
-func stack3248() (uintptr, uintptr) { var buf [3248]byte; use(buf[:]); return Stackguard() }
-func stack3252() (uintptr, uintptr) { var buf [3252]byte; use(buf[:]); return Stackguard() }
-func stack3256() (uintptr, uintptr) { var buf [3256]byte; use(buf[:]); return Stackguard() }
-func stack3260() (uintptr, uintptr) { var buf [3260]byte; use(buf[:]); return Stackguard() }
-func stack3264() (uintptr, uintptr) { var buf [3264]byte; use(buf[:]); return Stackguard() }
-func stack3268() (uintptr, uintptr) { var buf [3268]byte; use(buf[:]); return Stackguard() }
-func stack3272() (uintptr, uintptr) { var buf [3272]byte; use(buf[:]); return Stackguard() }
-func stack3276() (uintptr, uintptr) { var buf [3276]byte; use(buf[:]); return Stackguard() }
-func stack3280() (uintptr, uintptr) { var buf [3280]byte; use(buf[:]); return Stackguard() }
-func stack3284() (uintptr, uintptr) { var buf [3284]byte; use(buf[:]); return Stackguard() }
-func stack3288() (uintptr, uintptr) { var buf [3288]byte; use(buf[:]); return Stackguard() }
-func stack3292() (uintptr, uintptr) { var buf [3292]byte; use(buf[:]); return Stackguard() }
-func stack3296() (uintptr, uintptr) { var buf [3296]byte; use(buf[:]); return Stackguard() }
-func stack3300() (uintptr, uintptr) { var buf [3300]byte; use(buf[:]); return Stackguard() }
-func stack3304() (uintptr, uintptr) { var buf [3304]byte; use(buf[:]); return Stackguard() }
-func stack3308() (uintptr, uintptr) { var buf [3308]byte; use(buf[:]); return Stackguard() }
-func stack3312() (uintptr, uintptr) { var buf [3312]byte; use(buf[:]); return Stackguard() }
-func stack3316() (uintptr, uintptr) { var buf [3316]byte; use(buf[:]); return Stackguard() }
-func stack3320() (uintptr, uintptr) { var buf [3320]byte; use(buf[:]); return Stackguard() }
-func stack3324() (uintptr, uintptr) { var buf [3324]byte; use(buf[:]); return Stackguard() }
-func stack3328() (uintptr, uintptr) { var buf [3328]byte; use(buf[:]); return Stackguard() }
-func stack3332() (uintptr, uintptr) { var buf [3332]byte; use(buf[:]); return Stackguard() }
-func stack3336() (uintptr, uintptr) { var buf [3336]byte; use(buf[:]); return Stackguard() }
-func stack3340() (uintptr, uintptr) { var buf [3340]byte; use(buf[:]); return Stackguard() }
-func stack3344() (uintptr, uintptr) { var buf [3344]byte; use(buf[:]); return Stackguard() }
-func stack3348() (uintptr, uintptr) { var buf [3348]byte; use(buf[:]); return Stackguard() }
-func stack3352() (uintptr, uintptr) { var buf [3352]byte; use(buf[:]); return Stackguard() }
-func stack3356() (uintptr, uintptr) { var buf [3356]byte; use(buf[:]); return Stackguard() }
-func stack3360() (uintptr, uintptr) { var buf [3360]byte; use(buf[:]); return Stackguard() }
-func stack3364() (uintptr, uintptr) { var buf [3364]byte; use(buf[:]); return Stackguard() }
-func stack3368() (uintptr, uintptr) { var buf [3368]byte; use(buf[:]); return Stackguard() }
-func stack3372() (uintptr, uintptr) { var buf [3372]byte; use(buf[:]); return Stackguard() }
-func stack3376() (uintptr, uintptr) { var buf [3376]byte; use(buf[:]); return Stackguard() }
-func stack3380() (uintptr, uintptr) { var buf [3380]byte; use(buf[:]); return Stackguard() }
-func stack3384() (uintptr, uintptr) { var buf [3384]byte; use(buf[:]); return Stackguard() }
-func stack3388() (uintptr, uintptr) { var buf [3388]byte; use(buf[:]); return Stackguard() }
-func stack3392() (uintptr, uintptr) { var buf [3392]byte; use(buf[:]); return Stackguard() }
-func stack3396() (uintptr, uintptr) { var buf [3396]byte; use(buf[:]); return Stackguard() }
-func stack3400() (uintptr, uintptr) { var buf [3400]byte; use(buf[:]); return Stackguard() }
-func stack3404() (uintptr, uintptr) { var buf [3404]byte; use(buf[:]); return Stackguard() }
-func stack3408() (uintptr, uintptr) { var buf [3408]byte; use(buf[:]); return Stackguard() }
-func stack3412() (uintptr, uintptr) { var buf [3412]byte; use(buf[:]); return Stackguard() }
-func stack3416() (uintptr, uintptr) { var buf [3416]byte; use(buf[:]); return Stackguard() }
-func stack3420() (uintptr, uintptr) { var buf [3420]byte; use(buf[:]); return Stackguard() }
-func stack3424() (uintptr, uintptr) { var buf [3424]byte; use(buf[:]); return Stackguard() }
-func stack3428() (uintptr, uintptr) { var buf [3428]byte; use(buf[:]); return Stackguard() }
-func stack3432() (uintptr, uintptr) { var buf [3432]byte; use(buf[:]); return Stackguard() }
-func stack3436() (uintptr, uintptr) { var buf [3436]byte; use(buf[:]); return Stackguard() }
-func stack3440() (uintptr, uintptr) { var buf [3440]byte; use(buf[:]); return Stackguard() }
-func stack3444() (uintptr, uintptr) { var buf [3444]byte; use(buf[:]); return Stackguard() }
-func stack3448() (uintptr, uintptr) { var buf [3448]byte; use(buf[:]); return Stackguard() }
-func stack3452() (uintptr, uintptr) { var buf [3452]byte; use(buf[:]); return Stackguard() }
-func stack3456() (uintptr, uintptr) { var buf [3456]byte; use(buf[:]); return Stackguard() }
-func stack3460() (uintptr, uintptr) { var buf [3460]byte; use(buf[:]); return Stackguard() }
-func stack3464() (uintptr, uintptr) { var buf [3464]byte; use(buf[:]); return Stackguard() }
-func stack3468() (uintptr, uintptr) { var buf [3468]byte; use(buf[:]); return Stackguard() }
-func stack3472() (uintptr, uintptr) { var buf [3472]byte; use(buf[:]); return Stackguard() }
-func stack3476() (uintptr, uintptr) { var buf [3476]byte; use(buf[:]); return Stackguard() }
-func stack3480() (uintptr, uintptr) { var buf [3480]byte; use(buf[:]); return Stackguard() }
-func stack3484() (uintptr, uintptr) { var buf [3484]byte; use(buf[:]); return Stackguard() }
-func stack3488() (uintptr, uintptr) { var buf [3488]byte; use(buf[:]); return Stackguard() }
-func stack3492() (uintptr, uintptr) { var buf [3492]byte; use(buf[:]); return Stackguard() }
-func stack3496() (uintptr, uintptr) { var buf [3496]byte; use(buf[:]); return Stackguard() }
-func stack3500() (uintptr, uintptr) { var buf [3500]byte; use(buf[:]); return Stackguard() }
-func stack3504() (uintptr, uintptr) { var buf [3504]byte; use(buf[:]); return Stackguard() }
-func stack3508() (uintptr, uintptr) { var buf [3508]byte; use(buf[:]); return Stackguard() }
-func stack3512() (uintptr, uintptr) { var buf [3512]byte; use(buf[:]); return Stackguard() }
-func stack3516() (uintptr, uintptr) { var buf [3516]byte; use(buf[:]); return Stackguard() }
-func stack3520() (uintptr, uintptr) { var buf [3520]byte; use(buf[:]); return Stackguard() }
-func stack3524() (uintptr, uintptr) { var buf [3524]byte; use(buf[:]); return Stackguard() }
-func stack3528() (uintptr, uintptr) { var buf [3528]byte; use(buf[:]); return Stackguard() }
-func stack3532() (uintptr, uintptr) { var buf [3532]byte; use(buf[:]); return Stackguard() }
-func stack3536() (uintptr, uintptr) { var buf [3536]byte; use(buf[:]); return Stackguard() }
-func stack3540() (uintptr, uintptr) { var buf [3540]byte; use(buf[:]); return Stackguard() }
-func stack3544() (uintptr, uintptr) { var buf [3544]byte; use(buf[:]); return Stackguard() }
-func stack3548() (uintptr, uintptr) { var buf [3548]byte; use(buf[:]); return Stackguard() }
-func stack3552() (uintptr, uintptr) { var buf [3552]byte; use(buf[:]); return Stackguard() }
-func stack3556() (uintptr, uintptr) { var buf [3556]byte; use(buf[:]); return Stackguard() }
-func stack3560() (uintptr, uintptr) { var buf [3560]byte; use(buf[:]); return Stackguard() }
-func stack3564() (uintptr, uintptr) { var buf [3564]byte; use(buf[:]); return Stackguard() }
-func stack3568() (uintptr, uintptr) { var buf [3568]byte; use(buf[:]); return Stackguard() }
-func stack3572() (uintptr, uintptr) { var buf [3572]byte; use(buf[:]); return Stackguard() }
-func stack3576() (uintptr, uintptr) { var buf [3576]byte; use(buf[:]); return Stackguard() }
-func stack3580() (uintptr, uintptr) { var buf [3580]byte; use(buf[:]); return Stackguard() }
-func stack3584() (uintptr, uintptr) { var buf [3584]byte; use(buf[:]); return Stackguard() }
-func stack3588() (uintptr, uintptr) { var buf [3588]byte; use(buf[:]); return Stackguard() }
-func stack3592() (uintptr, uintptr) { var buf [3592]byte; use(buf[:]); return Stackguard() }
-func stack3596() (uintptr, uintptr) { var buf [3596]byte; use(buf[:]); return Stackguard() }
-func stack3600() (uintptr, uintptr) { var buf [3600]byte; use(buf[:]); return Stackguard() }
-func stack3604() (uintptr, uintptr) { var buf [3604]byte; use(buf[:]); return Stackguard() }
-func stack3608() (uintptr, uintptr) { var buf [3608]byte; use(buf[:]); return Stackguard() }
-func stack3612() (uintptr, uintptr) { var buf [3612]byte; use(buf[:]); return Stackguard() }
-func stack3616() (uintptr, uintptr) { var buf [3616]byte; use(buf[:]); return Stackguard() }
-func stack3620() (uintptr, uintptr) { var buf [3620]byte; use(buf[:]); return Stackguard() }
-func stack3624() (uintptr, uintptr) { var buf [3624]byte; use(buf[:]); return Stackguard() }
-func stack3628() (uintptr, uintptr) { var buf [3628]byte; use(buf[:]); return Stackguard() }
-func stack3632() (uintptr, uintptr) { var buf [3632]byte; use(buf[:]); return Stackguard() }
-func stack3636() (uintptr, uintptr) { var buf [3636]byte; use(buf[:]); return Stackguard() }
-func stack3640() (uintptr, uintptr) { var buf [3640]byte; use(buf[:]); return Stackguard() }
-func stack3644() (uintptr, uintptr) { var buf [3644]byte; use(buf[:]); return Stackguard() }
-func stack3648() (uintptr, uintptr) { var buf [3648]byte; use(buf[:]); return Stackguard() }
-func stack3652() (uintptr, uintptr) { var buf [3652]byte; use(buf[:]); return Stackguard() }
-func stack3656() (uintptr, uintptr) { var buf [3656]byte; use(buf[:]); return Stackguard() }
-func stack3660() (uintptr, uintptr) { var buf [3660]byte; use(buf[:]); return Stackguard() }
-func stack3664() (uintptr, uintptr) { var buf [3664]byte; use(buf[:]); return Stackguard() }
-func stack3668() (uintptr, uintptr) { var buf [3668]byte; use(buf[:]); return Stackguard() }
-func stack3672() (uintptr, uintptr) { var buf [3672]byte; use(buf[:]); return Stackguard() }
-func stack3676() (uintptr, uintptr) { var buf [3676]byte; use(buf[:]); return Stackguard() }
-func stack3680() (uintptr, uintptr) { var buf [3680]byte; use(buf[:]); return Stackguard() }
-func stack3684() (uintptr, uintptr) { var buf [3684]byte; use(buf[:]); return Stackguard() }
-func stack3688() (uintptr, uintptr) { var buf [3688]byte; use(buf[:]); return Stackguard() }
-func stack3692() (uintptr, uintptr) { var buf [3692]byte; use(buf[:]); return Stackguard() }
-func stack3696() (uintptr, uintptr) { var buf [3696]byte; use(buf[:]); return Stackguard() }
-func stack3700() (uintptr, uintptr) { var buf [3700]byte; use(buf[:]); return Stackguard() }
-func stack3704() (uintptr, uintptr) { var buf [3704]byte; use(buf[:]); return Stackguard() }
-func stack3708() (uintptr, uintptr) { var buf [3708]byte; use(buf[:]); return Stackguard() }
-func stack3712() (uintptr, uintptr) { var buf [3712]byte; use(buf[:]); return Stackguard() }
-func stack3716() (uintptr, uintptr) { var buf [3716]byte; use(buf[:]); return Stackguard() }
-func stack3720() (uintptr, uintptr) { var buf [3720]byte; use(buf[:]); return Stackguard() }
-func stack3724() (uintptr, uintptr) { var buf [3724]byte; use(buf[:]); return Stackguard() }
-func stack3728() (uintptr, uintptr) { var buf [3728]byte; use(buf[:]); return Stackguard() }
-func stack3732() (uintptr, uintptr) { var buf [3732]byte; use(buf[:]); return Stackguard() }
-func stack3736() (uintptr, uintptr) { var buf [3736]byte; use(buf[:]); return Stackguard() }
-func stack3740() (uintptr, uintptr) { var buf [3740]byte; use(buf[:]); return Stackguard() }
-func stack3744() (uintptr, uintptr) { var buf [3744]byte; use(buf[:]); return Stackguard() }
-func stack3748() (uintptr, uintptr) { var buf [3748]byte; use(buf[:]); return Stackguard() }
-func stack3752() (uintptr, uintptr) { var buf [3752]byte; use(buf[:]); return Stackguard() }
-func stack3756() (uintptr, uintptr) { var buf [3756]byte; use(buf[:]); return Stackguard() }
-func stack3760() (uintptr, uintptr) { var buf [3760]byte; use(buf[:]); return Stackguard() }
-func stack3764() (uintptr, uintptr) { var buf [3764]byte; use(buf[:]); return Stackguard() }
-func stack3768() (uintptr, uintptr) { var buf [3768]byte; use(buf[:]); return Stackguard() }
-func stack3772() (uintptr, uintptr) { var buf [3772]byte; use(buf[:]); return Stackguard() }
-func stack3776() (uintptr, uintptr) { var buf [3776]byte; use(buf[:]); return Stackguard() }
-func stack3780() (uintptr, uintptr) { var buf [3780]byte; use(buf[:]); return Stackguard() }
-func stack3784() (uintptr, uintptr) { var buf [3784]byte; use(buf[:]); return Stackguard() }
-func stack3788() (uintptr, uintptr) { var buf [3788]byte; use(buf[:]); return Stackguard() }
-func stack3792() (uintptr, uintptr) { var buf [3792]byte; use(buf[:]); return Stackguard() }
-func stack3796() (uintptr, uintptr) { var buf [3796]byte; use(buf[:]); return Stackguard() }
-func stack3800() (uintptr, uintptr) { var buf [3800]byte; use(buf[:]); return Stackguard() }
-func stack3804() (uintptr, uintptr) { var buf [3804]byte; use(buf[:]); return Stackguard() }
-func stack3808() (uintptr, uintptr) { var buf [3808]byte; use(buf[:]); return Stackguard() }
-func stack3812() (uintptr, uintptr) { var buf [3812]byte; use(buf[:]); return Stackguard() }
-func stack3816() (uintptr, uintptr) { var buf [3816]byte; use(buf[:]); return Stackguard() }
-func stack3820() (uintptr, uintptr) { var buf [3820]byte; use(buf[:]); return Stackguard() }
-func stack3824() (uintptr, uintptr) { var buf [3824]byte; use(buf[:]); return Stackguard() }
-func stack3828() (uintptr, uintptr) { var buf [3828]byte; use(buf[:]); return Stackguard() }
-func stack3832() (uintptr, uintptr) { var buf [3832]byte; use(buf[:]); return Stackguard() }
-func stack3836() (uintptr, uintptr) { var buf [3836]byte; use(buf[:]); return Stackguard() }
-func stack3840() (uintptr, uintptr) { var buf [3840]byte; use(buf[:]); return Stackguard() }
-func stack3844() (uintptr, uintptr) { var buf [3844]byte; use(buf[:]); return Stackguard() }
-func stack3848() (uintptr, uintptr) { var buf [3848]byte; use(buf[:]); return Stackguard() }
-func stack3852() (uintptr, uintptr) { var buf [3852]byte; use(buf[:]); return Stackguard() }
-func stack3856() (uintptr, uintptr) { var buf [3856]byte; use(buf[:]); return Stackguard() }
-func stack3860() (uintptr, uintptr) { var buf [3860]byte; use(buf[:]); return Stackguard() }
-func stack3864() (uintptr, uintptr) { var buf [3864]byte; use(buf[:]); return Stackguard() }
-func stack3868() (uintptr, uintptr) { var buf [3868]byte; use(buf[:]); return Stackguard() }
-func stack3872() (uintptr, uintptr) { var buf [3872]byte; use(buf[:]); return Stackguard() }
-func stack3876() (uintptr, uintptr) { var buf [3876]byte; use(buf[:]); return Stackguard() }
-func stack3880() (uintptr, uintptr) { var buf [3880]byte; use(buf[:]); return Stackguard() }
-func stack3884() (uintptr, uintptr) { var buf [3884]byte; use(buf[:]); return Stackguard() }
-func stack3888() (uintptr, uintptr) { var buf [3888]byte; use(buf[:]); return Stackguard() }
-func stack3892() (uintptr, uintptr) { var buf [3892]byte; use(buf[:]); return Stackguard() }
-func stack3896() (uintptr, uintptr) { var buf [3896]byte; use(buf[:]); return Stackguard() }
-func stack3900() (uintptr, uintptr) { var buf [3900]byte; use(buf[:]); return Stackguard() }
-func stack3904() (uintptr, uintptr) { var buf [3904]byte; use(buf[:]); return Stackguard() }
-func stack3908() (uintptr, uintptr) { var buf [3908]byte; use(buf[:]); return Stackguard() }
-func stack3912() (uintptr, uintptr) { var buf [3912]byte; use(buf[:]); return Stackguard() }
-func stack3916() (uintptr, uintptr) { var buf [3916]byte; use(buf[:]); return Stackguard() }
-func stack3920() (uintptr, uintptr) { var buf [3920]byte; use(buf[:]); return Stackguard() }
-func stack3924() (uintptr, uintptr) { var buf [3924]byte; use(buf[:]); return Stackguard() }
-func stack3928() (uintptr, uintptr) { var buf [3928]byte; use(buf[:]); return Stackguard() }
-func stack3932() (uintptr, uintptr) { var buf [3932]byte; use(buf[:]); return Stackguard() }
-func stack3936() (uintptr, uintptr) { var buf [3936]byte; use(buf[:]); return Stackguard() }
-func stack3940() (uintptr, uintptr) { var buf [3940]byte; use(buf[:]); return Stackguard() }
-func stack3944() (uintptr, uintptr) { var buf [3944]byte; use(buf[:]); return Stackguard() }
-func stack3948() (uintptr, uintptr) { var buf [3948]byte; use(buf[:]); return Stackguard() }
-func stack3952() (uintptr, uintptr) { var buf [3952]byte; use(buf[:]); return Stackguard() }
-func stack3956() (uintptr, uintptr) { var buf [3956]byte; use(buf[:]); return Stackguard() }
-func stack3960() (uintptr, uintptr) { var buf [3960]byte; use(buf[:]); return Stackguard() }
-func stack3964() (uintptr, uintptr) { var buf [3964]byte; use(buf[:]); return Stackguard() }
-func stack3968() (uintptr, uintptr) { var buf [3968]byte; use(buf[:]); return Stackguard() }
-func stack3972() (uintptr, uintptr) { var buf [3972]byte; use(buf[:]); return Stackguard() }
-func stack3976() (uintptr, uintptr) { var buf [3976]byte; use(buf[:]); return Stackguard() }
-func stack3980() (uintptr, uintptr) { var buf [3980]byte; use(buf[:]); return Stackguard() }
-func stack3984() (uintptr, uintptr) { var buf [3984]byte; use(buf[:]); return Stackguard() }
-func stack3988() (uintptr, uintptr) { var buf [3988]byte; use(buf[:]); return Stackguard() }
-func stack3992() (uintptr, uintptr) { var buf [3992]byte; use(buf[:]); return Stackguard() }
-func stack3996() (uintptr, uintptr) { var buf [3996]byte; use(buf[:]); return Stackguard() }
-func stack4000() (uintptr, uintptr) { var buf [4000]byte; use(buf[:]); return Stackguard() }
-func stack4004() (uintptr, uintptr) { var buf [4004]byte; use(buf[:]); return Stackguard() }
-func stack4008() (uintptr, uintptr) { var buf [4008]byte; use(buf[:]); return Stackguard() }
-func stack4012() (uintptr, uintptr) { var buf [4012]byte; use(buf[:]); return Stackguard() }
-func stack4016() (uintptr, uintptr) { var buf [4016]byte; use(buf[:]); return Stackguard() }
-func stack4020() (uintptr, uintptr) { var buf [4020]byte; use(buf[:]); return Stackguard() }
-func stack4024() (uintptr, uintptr) { var buf [4024]byte; use(buf[:]); return Stackguard() }
-func stack4028() (uintptr, uintptr) { var buf [4028]byte; use(buf[:]); return Stackguard() }
-func stack4032() (uintptr, uintptr) { var buf [4032]byte; use(buf[:]); return Stackguard() }
-func stack4036() (uintptr, uintptr) { var buf [4036]byte; use(buf[:]); return Stackguard() }
-func stack4040() (uintptr, uintptr) { var buf [4040]byte; use(buf[:]); return Stackguard() }
-func stack4044() (uintptr, uintptr) { var buf [4044]byte; use(buf[:]); return Stackguard() }
-func stack4048() (uintptr, uintptr) { var buf [4048]byte; use(buf[:]); return Stackguard() }
-func stack4052() (uintptr, uintptr) { var buf [4052]byte; use(buf[:]); return Stackguard() }
-func stack4056() (uintptr, uintptr) { var buf [4056]byte; use(buf[:]); return Stackguard() }
-func stack4060() (uintptr, uintptr) { var buf [4060]byte; use(buf[:]); return Stackguard() }
-func stack4064() (uintptr, uintptr) { var buf [4064]byte; use(buf[:]); return Stackguard() }
-func stack4068() (uintptr, uintptr) { var buf [4068]byte; use(buf[:]); return Stackguard() }
-func stack4072() (uintptr, uintptr) { var buf [4072]byte; use(buf[:]); return Stackguard() }
-func stack4076() (uintptr, uintptr) { var buf [4076]byte; use(buf[:]); return Stackguard() }
-func stack4080() (uintptr, uintptr) { var buf [4080]byte; use(buf[:]); return Stackguard() }
-func stack4084() (uintptr, uintptr) { var buf [4084]byte; use(buf[:]); return Stackguard() }
-func stack4088() (uintptr, uintptr) { var buf [4088]byte; use(buf[:]); return Stackguard() }
-func stack4092() (uintptr, uintptr) { var buf [4092]byte; use(buf[:]); return Stackguard() }
-func stack4096() (uintptr, uintptr) { var buf [4096]byte; use(buf[:]); return Stackguard() }
-func stack4100() (uintptr, uintptr) { var buf [4100]byte; use(buf[:]); return Stackguard() }
-func stack4104() (uintptr, uintptr) { var buf [4104]byte; use(buf[:]); return Stackguard() }
-func stack4108() (uintptr, uintptr) { var buf [4108]byte; use(buf[:]); return Stackguard() }
-func stack4112() (uintptr, uintptr) { var buf [4112]byte; use(buf[:]); return Stackguard() }
-func stack4116() (uintptr, uintptr) { var buf [4116]byte; use(buf[:]); return Stackguard() }
-func stack4120() (uintptr, uintptr) { var buf [4120]byte; use(buf[:]); return Stackguard() }
-func stack4124() (uintptr, uintptr) { var buf [4124]byte; use(buf[:]); return Stackguard() }
-func stack4128() (uintptr, uintptr) { var buf [4128]byte; use(buf[:]); return Stackguard() }
-func stack4132() (uintptr, uintptr) { var buf [4132]byte; use(buf[:]); return Stackguard() }
-func stack4136() (uintptr, uintptr) { var buf [4136]byte; use(buf[:]); return Stackguard() }
-func stack4140() (uintptr, uintptr) { var buf [4140]byte; use(buf[:]); return Stackguard() }
-func stack4144() (uintptr, uintptr) { var buf [4144]byte; use(buf[:]); return Stackguard() }
-func stack4148() (uintptr, uintptr) { var buf [4148]byte; use(buf[:]); return Stackguard() }
-func stack4152() (uintptr, uintptr) { var buf [4152]byte; use(buf[:]); return Stackguard() }
-func stack4156() (uintptr, uintptr) { var buf [4156]byte; use(buf[:]); return Stackguard() }
-func stack4160() (uintptr, uintptr) { var buf [4160]byte; use(buf[:]); return Stackguard() }
-func stack4164() (uintptr, uintptr) { var buf [4164]byte; use(buf[:]); return Stackguard() }
-func stack4168() (uintptr, uintptr) { var buf [4168]byte; use(buf[:]); return Stackguard() }
-func stack4172() (uintptr, uintptr) { var buf [4172]byte; use(buf[:]); return Stackguard() }
-func stack4176() (uintptr, uintptr) { var buf [4176]byte; use(buf[:]); return Stackguard() }
-func stack4180() (uintptr, uintptr) { var buf [4180]byte; use(buf[:]); return Stackguard() }
-func stack4184() (uintptr, uintptr) { var buf [4184]byte; use(buf[:]); return Stackguard() }
-func stack4188() (uintptr, uintptr) { var buf [4188]byte; use(buf[:]); return Stackguard() }
-func stack4192() (uintptr, uintptr) { var buf [4192]byte; use(buf[:]); return Stackguard() }
-func stack4196() (uintptr, uintptr) { var buf [4196]byte; use(buf[:]); return Stackguard() }
-func stack4200() (uintptr, uintptr) { var buf [4200]byte; use(buf[:]); return Stackguard() }
-func stack4204() (uintptr, uintptr) { var buf [4204]byte; use(buf[:]); return Stackguard() }
-func stack4208() (uintptr, uintptr) { var buf [4208]byte; use(buf[:]); return Stackguard() }
-func stack4212() (uintptr, uintptr) { var buf [4212]byte; use(buf[:]); return Stackguard() }
-func stack4216() (uintptr, uintptr) { var buf [4216]byte; use(buf[:]); return Stackguard() }
-func stack4220() (uintptr, uintptr) { var buf [4220]byte; use(buf[:]); return Stackguard() }
-func stack4224() (uintptr, uintptr) { var buf [4224]byte; use(buf[:]); return Stackguard() }
-func stack4228() (uintptr, uintptr) { var buf [4228]byte; use(buf[:]); return Stackguard() }
-func stack4232() (uintptr, uintptr) { var buf [4232]byte; use(buf[:]); return Stackguard() }
-func stack4236() (uintptr, uintptr) { var buf [4236]byte; use(buf[:]); return Stackguard() }
-func stack4240() (uintptr, uintptr) { var buf [4240]byte; use(buf[:]); return Stackguard() }
-func stack4244() (uintptr, uintptr) { var buf [4244]byte; use(buf[:]); return Stackguard() }
-func stack4248() (uintptr, uintptr) { var buf [4248]byte; use(buf[:]); return Stackguard() }
-func stack4252() (uintptr, uintptr) { var buf [4252]byte; use(buf[:]); return Stackguard() }
-func stack4256() (uintptr, uintptr) { var buf [4256]byte; use(buf[:]); return Stackguard() }
-func stack4260() (uintptr, uintptr) { var buf [4260]byte; use(buf[:]); return Stackguard() }
-func stack4264() (uintptr, uintptr) { var buf [4264]byte; use(buf[:]); return Stackguard() }
-func stack4268() (uintptr, uintptr) { var buf [4268]byte; use(buf[:]); return Stackguard() }
-func stack4272() (uintptr, uintptr) { var buf [4272]byte; use(buf[:]); return Stackguard() }
-func stack4276() (uintptr, uintptr) { var buf [4276]byte; use(buf[:]); return Stackguard() }
-func stack4280() (uintptr, uintptr) { var buf [4280]byte; use(buf[:]); return Stackguard() }
-func stack4284() (uintptr, uintptr) { var buf [4284]byte; use(buf[:]); return Stackguard() }
-func stack4288() (uintptr, uintptr) { var buf [4288]byte; use(buf[:]); return Stackguard() }
-func stack4292() (uintptr, uintptr) { var buf [4292]byte; use(buf[:]); return Stackguard() }
-func stack4296() (uintptr, uintptr) { var buf [4296]byte; use(buf[:]); return Stackguard() }
-func stack4300() (uintptr, uintptr) { var buf [4300]byte; use(buf[:]); return Stackguard() }
-func stack4304() (uintptr, uintptr) { var buf [4304]byte; use(buf[:]); return Stackguard() }
-func stack4308() (uintptr, uintptr) { var buf [4308]byte; use(buf[:]); return Stackguard() }
-func stack4312() (uintptr, uintptr) { var buf [4312]byte; use(buf[:]); return Stackguard() }
-func stack4316() (uintptr, uintptr) { var buf [4316]byte; use(buf[:]); return Stackguard() }
-func stack4320() (uintptr, uintptr) { var buf [4320]byte; use(buf[:]); return Stackguard() }
-func stack4324() (uintptr, uintptr) { var buf [4324]byte; use(buf[:]); return Stackguard() }
-func stack4328() (uintptr, uintptr) { var buf [4328]byte; use(buf[:]); return Stackguard() }
-func stack4332() (uintptr, uintptr) { var buf [4332]byte; use(buf[:]); return Stackguard() }
-func stack4336() (uintptr, uintptr) { var buf [4336]byte; use(buf[:]); return Stackguard() }
-func stack4340() (uintptr, uintptr) { var buf [4340]byte; use(buf[:]); return Stackguard() }
-func stack4344() (uintptr, uintptr) { var buf [4344]byte; use(buf[:]); return Stackguard() }
-func stack4348() (uintptr, uintptr) { var buf [4348]byte; use(buf[:]); return Stackguard() }
-func stack4352() (uintptr, uintptr) { var buf [4352]byte; use(buf[:]); return Stackguard() }
-func stack4356() (uintptr, uintptr) { var buf [4356]byte; use(buf[:]); return Stackguard() }
-func stack4360() (uintptr, uintptr) { var buf [4360]byte; use(buf[:]); return Stackguard() }
-func stack4364() (uintptr, uintptr) { var buf [4364]byte; use(buf[:]); return Stackguard() }
-func stack4368() (uintptr, uintptr) { var buf [4368]byte; use(buf[:]); return Stackguard() }
-func stack4372() (uintptr, uintptr) { var buf [4372]byte; use(buf[:]); return Stackguard() }
-func stack4376() (uintptr, uintptr) { var buf [4376]byte; use(buf[:]); return Stackguard() }
-func stack4380() (uintptr, uintptr) { var buf [4380]byte; use(buf[:]); return Stackguard() }
-func stack4384() (uintptr, uintptr) { var buf [4384]byte; use(buf[:]); return Stackguard() }
-func stack4388() (uintptr, uintptr) { var buf [4388]byte; use(buf[:]); return Stackguard() }
-func stack4392() (uintptr, uintptr) { var buf [4392]byte; use(buf[:]); return Stackguard() }
-func stack4396() (uintptr, uintptr) { var buf [4396]byte; use(buf[:]); return Stackguard() }
-func stack4400() (uintptr, uintptr) { var buf [4400]byte; use(buf[:]); return Stackguard() }
-func stack4404() (uintptr, uintptr) { var buf [4404]byte; use(buf[:]); return Stackguard() }
-func stack4408() (uintptr, uintptr) { var buf [4408]byte; use(buf[:]); return Stackguard() }
-func stack4412() (uintptr, uintptr) { var buf [4412]byte; use(buf[:]); return Stackguard() }
-func stack4416() (uintptr, uintptr) { var buf [4416]byte; use(buf[:]); return Stackguard() }
-func stack4420() (uintptr, uintptr) { var buf [4420]byte; use(buf[:]); return Stackguard() }
-func stack4424() (uintptr, uintptr) { var buf [4424]byte; use(buf[:]); return Stackguard() }
-func stack4428() (uintptr, uintptr) { var buf [4428]byte; use(buf[:]); return Stackguard() }
-func stack4432() (uintptr, uintptr) { var buf [4432]byte; use(buf[:]); return Stackguard() }
-func stack4436() (uintptr, uintptr) { var buf [4436]byte; use(buf[:]); return Stackguard() }
-func stack4440() (uintptr, uintptr) { var buf [4440]byte; use(buf[:]); return Stackguard() }
-func stack4444() (uintptr, uintptr) { var buf [4444]byte; use(buf[:]); return Stackguard() }
-func stack4448() (uintptr, uintptr) { var buf [4448]byte; use(buf[:]); return Stackguard() }
-func stack4452() (uintptr, uintptr) { var buf [4452]byte; use(buf[:]); return Stackguard() }
-func stack4456() (uintptr, uintptr) { var buf [4456]byte; use(buf[:]); return Stackguard() }
-func stack4460() (uintptr, uintptr) { var buf [4460]byte; use(buf[:]); return Stackguard() }
-func stack4464() (uintptr, uintptr) { var buf [4464]byte; use(buf[:]); return Stackguard() }
-func stack4468() (uintptr, uintptr) { var buf [4468]byte; use(buf[:]); return Stackguard() }
-func stack4472() (uintptr, uintptr) { var buf [4472]byte; use(buf[:]); return Stackguard() }
-func stack4476() (uintptr, uintptr) { var buf [4476]byte; use(buf[:]); return Stackguard() }
-func stack4480() (uintptr, uintptr) { var buf [4480]byte; use(buf[:]); return Stackguard() }
-func stack4484() (uintptr, uintptr) { var buf [4484]byte; use(buf[:]); return Stackguard() }
-func stack4488() (uintptr, uintptr) { var buf [4488]byte; use(buf[:]); return Stackguard() }
-func stack4492() (uintptr, uintptr) { var buf [4492]byte; use(buf[:]); return Stackguard() }
-func stack4496() (uintptr, uintptr) { var buf [4496]byte; use(buf[:]); return Stackguard() }
-func stack4500() (uintptr, uintptr) { var buf [4500]byte; use(buf[:]); return Stackguard() }
-func stack4504() (uintptr, uintptr) { var buf [4504]byte; use(buf[:]); return Stackguard() }
-func stack4508() (uintptr, uintptr) { var buf [4508]byte; use(buf[:]); return Stackguard() }
-func stack4512() (uintptr, uintptr) { var buf [4512]byte; use(buf[:]); return Stackguard() }
-func stack4516() (uintptr, uintptr) { var buf [4516]byte; use(buf[:]); return Stackguard() }
-func stack4520() (uintptr, uintptr) { var buf [4520]byte; use(buf[:]); return Stackguard() }
-func stack4524() (uintptr, uintptr) { var buf [4524]byte; use(buf[:]); return Stackguard() }
-func stack4528() (uintptr, uintptr) { var buf [4528]byte; use(buf[:]); return Stackguard() }
-func stack4532() (uintptr, uintptr) { var buf [4532]byte; use(buf[:]); return Stackguard() }
-func stack4536() (uintptr, uintptr) { var buf [4536]byte; use(buf[:]); return Stackguard() }
-func stack4540() (uintptr, uintptr) { var buf [4540]byte; use(buf[:]); return Stackguard() }
-func stack4544() (uintptr, uintptr) { var buf [4544]byte; use(buf[:]); return Stackguard() }
-func stack4548() (uintptr, uintptr) { var buf [4548]byte; use(buf[:]); return Stackguard() }
-func stack4552() (uintptr, uintptr) { var buf [4552]byte; use(buf[:]); return Stackguard() }
-func stack4556() (uintptr, uintptr) { var buf [4556]byte; use(buf[:]); return Stackguard() }
-func stack4560() (uintptr, uintptr) { var buf [4560]byte; use(buf[:]); return Stackguard() }
-func stack4564() (uintptr, uintptr) { var buf [4564]byte; use(buf[:]); return Stackguard() }
-func stack4568() (uintptr, uintptr) { var buf [4568]byte; use(buf[:]); return Stackguard() }
-func stack4572() (uintptr, uintptr) { var buf [4572]byte; use(buf[:]); return Stackguard() }
-func stack4576() (uintptr, uintptr) { var buf [4576]byte; use(buf[:]); return Stackguard() }
-func stack4580() (uintptr, uintptr) { var buf [4580]byte; use(buf[:]); return Stackguard() }
-func stack4584() (uintptr, uintptr) { var buf [4584]byte; use(buf[:]); return Stackguard() }
-func stack4588() (uintptr, uintptr) { var buf [4588]byte; use(buf[:]); return Stackguard() }
-func stack4592() (uintptr, uintptr) { var buf [4592]byte; use(buf[:]); return Stackguard() }
-func stack4596() (uintptr, uintptr) { var buf [4596]byte; use(buf[:]); return Stackguard() }
-func stack4600() (uintptr, uintptr) { var buf [4600]byte; use(buf[:]); return Stackguard() }
-func stack4604() (uintptr, uintptr) { var buf [4604]byte; use(buf[:]); return Stackguard() }
-func stack4608() (uintptr, uintptr) { var buf [4608]byte; use(buf[:]); return Stackguard() }
-func stack4612() (uintptr, uintptr) { var buf [4612]byte; use(buf[:]); return Stackguard() }
-func stack4616() (uintptr, uintptr) { var buf [4616]byte; use(buf[:]); return Stackguard() }
-func stack4620() (uintptr, uintptr) { var buf [4620]byte; use(buf[:]); return Stackguard() }
-func stack4624() (uintptr, uintptr) { var buf [4624]byte; use(buf[:]); return Stackguard() }
-func stack4628() (uintptr, uintptr) { var buf [4628]byte; use(buf[:]); return Stackguard() }
-func stack4632() (uintptr, uintptr) { var buf [4632]byte; use(buf[:]); return Stackguard() }
-func stack4636() (uintptr, uintptr) { var buf [4636]byte; use(buf[:]); return Stackguard() }
-func stack4640() (uintptr, uintptr) { var buf [4640]byte; use(buf[:]); return Stackguard() }
-func stack4644() (uintptr, uintptr) { var buf [4644]byte; use(buf[:]); return Stackguard() }
-func stack4648() (uintptr, uintptr) { var buf [4648]byte; use(buf[:]); return Stackguard() }
-func stack4652() (uintptr, uintptr) { var buf [4652]byte; use(buf[:]); return Stackguard() }
-func stack4656() (uintptr, uintptr) { var buf [4656]byte; use(buf[:]); return Stackguard() }
-func stack4660() (uintptr, uintptr) { var buf [4660]byte; use(buf[:]); return Stackguard() }
-func stack4664() (uintptr, uintptr) { var buf [4664]byte; use(buf[:]); return Stackguard() }
-func stack4668() (uintptr, uintptr) { var buf [4668]byte; use(buf[:]); return Stackguard() }
-func stack4672() (uintptr, uintptr) { var buf [4672]byte; use(buf[:]); return Stackguard() }
-func stack4676() (uintptr, uintptr) { var buf [4676]byte; use(buf[:]); return Stackguard() }
-func stack4680() (uintptr, uintptr) { var buf [4680]byte; use(buf[:]); return Stackguard() }
-func stack4684() (uintptr, uintptr) { var buf [4684]byte; use(buf[:]); return Stackguard() }
-func stack4688() (uintptr, uintptr) { var buf [4688]byte; use(buf[:]); return Stackguard() }
-func stack4692() (uintptr, uintptr) { var buf [4692]byte; use(buf[:]); return Stackguard() }
-func stack4696() (uintptr, uintptr) { var buf [4696]byte; use(buf[:]); return Stackguard() }
-func stack4700() (uintptr, uintptr) { var buf [4700]byte; use(buf[:]); return Stackguard() }
-func stack4704() (uintptr, uintptr) { var buf [4704]byte; use(buf[:]); return Stackguard() }
-func stack4708() (uintptr, uintptr) { var buf [4708]byte; use(buf[:]); return Stackguard() }
-func stack4712() (uintptr, uintptr) { var buf [4712]byte; use(buf[:]); return Stackguard() }
-func stack4716() (uintptr, uintptr) { var buf [4716]byte; use(buf[:]); return Stackguard() }
-func stack4720() (uintptr, uintptr) { var buf [4720]byte; use(buf[:]); return Stackguard() }
-func stack4724() (uintptr, uintptr) { var buf [4724]byte; use(buf[:]); return Stackguard() }
-func stack4728() (uintptr, uintptr) { var buf [4728]byte; use(buf[:]); return Stackguard() }
-func stack4732() (uintptr, uintptr) { var buf [4732]byte; use(buf[:]); return Stackguard() }
-func stack4736() (uintptr, uintptr) { var buf [4736]byte; use(buf[:]); return Stackguard() }
-func stack4740() (uintptr, uintptr) { var buf [4740]byte; use(buf[:]); return Stackguard() }
-func stack4744() (uintptr, uintptr) { var buf [4744]byte; use(buf[:]); return Stackguard() }
-func stack4748() (uintptr, uintptr) { var buf [4748]byte; use(buf[:]); return Stackguard() }
-func stack4752() (uintptr, uintptr) { var buf [4752]byte; use(buf[:]); return Stackguard() }
-func stack4756() (uintptr, uintptr) { var buf [4756]byte; use(buf[:]); return Stackguard() }
-func stack4760() (uintptr, uintptr) { var buf [4760]byte; use(buf[:]); return Stackguard() }
-func stack4764() (uintptr, uintptr) { var buf [4764]byte; use(buf[:]); return Stackguard() }
-func stack4768() (uintptr, uintptr) { var buf [4768]byte; use(buf[:]); return Stackguard() }
-func stack4772() (uintptr, uintptr) { var buf [4772]byte; use(buf[:]); return Stackguard() }
-func stack4776() (uintptr, uintptr) { var buf [4776]byte; use(buf[:]); return Stackguard() }
-func stack4780() (uintptr, uintptr) { var buf [4780]byte; use(buf[:]); return Stackguard() }
-func stack4784() (uintptr, uintptr) { var buf [4784]byte; use(buf[:]); return Stackguard() }
-func stack4788() (uintptr, uintptr) { var buf [4788]byte; use(buf[:]); return Stackguard() }
-func stack4792() (uintptr, uintptr) { var buf [4792]byte; use(buf[:]); return Stackguard() }
-func stack4796() (uintptr, uintptr) { var buf [4796]byte; use(buf[:]); return Stackguard() }
-func stack4800() (uintptr, uintptr) { var buf [4800]byte; use(buf[:]); return Stackguard() }
-func stack4804() (uintptr, uintptr) { var buf [4804]byte; use(buf[:]); return Stackguard() }
-func stack4808() (uintptr, uintptr) { var buf [4808]byte; use(buf[:]); return Stackguard() }
-func stack4812() (uintptr, uintptr) { var buf [4812]byte; use(buf[:]); return Stackguard() }
-func stack4816() (uintptr, uintptr) { var buf [4816]byte; use(buf[:]); return Stackguard() }
-func stack4820() (uintptr, uintptr) { var buf [4820]byte; use(buf[:]); return Stackguard() }
-func stack4824() (uintptr, uintptr) { var buf [4824]byte; use(buf[:]); return Stackguard() }
-func stack4828() (uintptr, uintptr) { var buf [4828]byte; use(buf[:]); return Stackguard() }
-func stack4832() (uintptr, uintptr) { var buf [4832]byte; use(buf[:]); return Stackguard() }
-func stack4836() (uintptr, uintptr) { var buf [4836]byte; use(buf[:]); return Stackguard() }
-func stack4840() (uintptr, uintptr) { var buf [4840]byte; use(buf[:]); return Stackguard() }
-func stack4844() (uintptr, uintptr) { var buf [4844]byte; use(buf[:]); return Stackguard() }
-func stack4848() (uintptr, uintptr) { var buf [4848]byte; use(buf[:]); return Stackguard() }
-func stack4852() (uintptr, uintptr) { var buf [4852]byte; use(buf[:]); return Stackguard() }
-func stack4856() (uintptr, uintptr) { var buf [4856]byte; use(buf[:]); return Stackguard() }
-func stack4860() (uintptr, uintptr) { var buf [4860]byte; use(buf[:]); return Stackguard() }
-func stack4864() (uintptr, uintptr) { var buf [4864]byte; use(buf[:]); return Stackguard() }
-func stack4868() (uintptr, uintptr) { var buf [4868]byte; use(buf[:]); return Stackguard() }
-func stack4872() (uintptr, uintptr) { var buf [4872]byte; use(buf[:]); return Stackguard() }
-func stack4876() (uintptr, uintptr) { var buf [4876]byte; use(buf[:]); return Stackguard() }
-func stack4880() (uintptr, uintptr) { var buf [4880]byte; use(buf[:]); return Stackguard() }
-func stack4884() (uintptr, uintptr) { var buf [4884]byte; use(buf[:]); return Stackguard() }
-func stack4888() (uintptr, uintptr) { var buf [4888]byte; use(buf[:]); return Stackguard() }
-func stack4892() (uintptr, uintptr) { var buf [4892]byte; use(buf[:]); return Stackguard() }
-func stack4896() (uintptr, uintptr) { var buf [4896]byte; use(buf[:]); return Stackguard() }
-func stack4900() (uintptr, uintptr) { var buf [4900]byte; use(buf[:]); return Stackguard() }
-func stack4904() (uintptr, uintptr) { var buf [4904]byte; use(buf[:]); return Stackguard() }
-func stack4908() (uintptr, uintptr) { var buf [4908]byte; use(buf[:]); return Stackguard() }
-func stack4912() (uintptr, uintptr) { var buf [4912]byte; use(buf[:]); return Stackguard() }
-func stack4916() (uintptr, uintptr) { var buf [4916]byte; use(buf[:]); return Stackguard() }
-func stack4920() (uintptr, uintptr) { var buf [4920]byte; use(buf[:]); return Stackguard() }
-func stack4924() (uintptr, uintptr) { var buf [4924]byte; use(buf[:]); return Stackguard() }
-func stack4928() (uintptr, uintptr) { var buf [4928]byte; use(buf[:]); return Stackguard() }
-func stack4932() (uintptr, uintptr) { var buf [4932]byte; use(buf[:]); return Stackguard() }
-func stack4936() (uintptr, uintptr) { var buf [4936]byte; use(buf[:]); return Stackguard() }
-func stack4940() (uintptr, uintptr) { var buf [4940]byte; use(buf[:]); return Stackguard() }
-func stack4944() (uintptr, uintptr) { var buf [4944]byte; use(buf[:]); return Stackguard() }
-func stack4948() (uintptr, uintptr) { var buf [4948]byte; use(buf[:]); return Stackguard() }
-func stack4952() (uintptr, uintptr) { var buf [4952]byte; use(buf[:]); return Stackguard() }
-func stack4956() (uintptr, uintptr) { var buf [4956]byte; use(buf[:]); return Stackguard() }
-func stack4960() (uintptr, uintptr) { var buf [4960]byte; use(buf[:]); return Stackguard() }
-func stack4964() (uintptr, uintptr) { var buf [4964]byte; use(buf[:]); return Stackguard() }
-func stack4968() (uintptr, uintptr) { var buf [4968]byte; use(buf[:]); return Stackguard() }
-func stack4972() (uintptr, uintptr) { var buf [4972]byte; use(buf[:]); return Stackguard() }
-func stack4976() (uintptr, uintptr) { var buf [4976]byte; use(buf[:]); return Stackguard() }
-func stack4980() (uintptr, uintptr) { var buf [4980]byte; use(buf[:]); return Stackguard() }
-func stack4984() (uintptr, uintptr) { var buf [4984]byte; use(buf[:]); return Stackguard() }
-func stack4988() (uintptr, uintptr) { var buf [4988]byte; use(buf[:]); return Stackguard() }
-func stack4992() (uintptr, uintptr) { var buf [4992]byte; use(buf[:]); return Stackguard() }
-func stack4996() (uintptr, uintptr) { var buf [4996]byte; use(buf[:]); return Stackguard() }
-func stack5000() (uintptr, uintptr) { var buf [5000]byte; use(buf[:]); return Stackguard() }
diff --git a/src/pkg/runtime/stack_test.go b/src/pkg/runtime/stack_test.go
deleted file mode 100644
index f0c599ac5..000000000
--- a/src/pkg/runtime/stack_test.go
+++ /dev/null
@@ -1,283 +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_test
-
-import (
- . "runtime"
- "sync"
- "testing"
- "time"
- "unsafe"
-)
-
-// See stack.h.
-const (
- StackGuard = 256
- StackLimit = 128
-)
-
-// Test stack split logic by calling functions of every frame size
-// from near 0 up to and beyond the default segment size (4k).
-// Each of those functions reports its SP + stack limit, and then
-// the test (the caller) checks that those make sense. By not
-// doing the actual checking and reporting from the suspect functions,
-// we minimize the possibility of crashes during the test itself.
-//
-// Exhaustive test for http://golang.org/issue/3310.
-// The linker used to get a few sizes near the segment size wrong:
-//
-// --- FAIL: TestStackSplit (0.01 seconds)
-// stack_test.go:22: after runtime_test.stack3812: sp=0x7f7818d5d078 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3816: sp=0x7f7818d5d078 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3820: sp=0x7f7818d5d070 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3824: sp=0x7f7818d5d070 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3828: sp=0x7f7818d5d068 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3832: sp=0x7f7818d5d068 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3836: sp=0x7f7818d5d060 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3840: sp=0x7f7818d5d060 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3844: sp=0x7f7818d5d058 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3848: sp=0x7f7818d5d058 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3852: sp=0x7f7818d5d050 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3856: sp=0x7f7818d5d050 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3860: sp=0x7f7818d5d048 < limit=0x7f7818d5d080
-// stack_test.go:22: after runtime_test.stack3864: sp=0x7f7818d5d048 < limit=0x7f7818d5d080
-// FAIL
-func TestStackSplit(t *testing.T) {
- for _, f := range splitTests {
- sp, guard := f()
- bottom := guard - StackGuard
- if sp < bottom+StackLimit {
- fun := FuncForPC(**(**uintptr)(unsafe.Pointer(&f)))
- t.Errorf("after %s: sp=%#x < limit=%#x (guard=%#x, bottom=%#x)",
- fun.Name(), sp, bottom+StackLimit, guard, bottom)
- }
- }
-}
-
-var Used byte
-
-func use(buf []byte) {
- for _, c := range buf {
- Used += c
- }
-}
-
-// TestStackMem measures per-thread stack segment cache behavior.
-// The test consumed up to 500MB in the past.
-func TestStackMem(t *testing.T) {
- const (
- BatchSize = 32
- BatchCount = 256
- ArraySize = 1024
- RecursionDepth = 128
- )
- if testing.Short() {
- return
- }
- defer GOMAXPROCS(GOMAXPROCS(BatchSize))
- s0 := new(MemStats)
- ReadMemStats(s0)
- for b := 0; b < BatchCount; b++ {
- c := make(chan bool, BatchSize)
- for i := 0; i < BatchSize; i++ {
- go func() {
- var f func(k int, a [ArraySize]byte)
- f = func(k int, a [ArraySize]byte) {
- if k == 0 {
- time.Sleep(time.Millisecond)
- return
- }
- f(k-1, a)
- }
- f(RecursionDepth, [ArraySize]byte{})
- c <- true
- }()
- }
- for i := 0; i < BatchSize; i++ {
- <-c
- }
-
- // The goroutines have signaled via c that they are ready to exit.
- // Give them a chance to exit by sleeping. If we don't wait, we
- // might not reuse them on the next batch.
- time.Sleep(10 * time.Millisecond)
- }
- s1 := new(MemStats)
- ReadMemStats(s1)
- consumed := s1.StackSys - s0.StackSys
- t.Logf("Consumed %vMB for stack mem", consumed>>20)
- estimate := uint64(8 * BatchSize * ArraySize * RecursionDepth) // 8 is to reduce flakiness.
- if consumed > estimate {
- t.Fatalf("Stack mem: want %v, got %v", estimate, consumed)
- }
- // Due to broken stack memory accounting (http://golang.org/issue/7468),
- // StackInuse can decrease during function execution, so we cast the values to int64.
- inuse := int64(s1.StackInuse) - int64(s0.StackInuse)
- t.Logf("Inuse %vMB for stack mem", inuse>>20)
- if inuse > 4<<20 {
- t.Fatalf("Stack inuse: want %v, got %v", 4<<20, inuse)
- }
-}
-
-// Test stack growing in different contexts.
-func TestStackGrowth(t *testing.T) {
- switch GOARCH {
- case "386", "arm":
- t.Skipf("skipping test on %q; see issue 8083", GOARCH)
- }
- t.Parallel()
- var wg sync.WaitGroup
-
- // in a normal goroutine
- wg.Add(1)
- go func() {
- defer wg.Done()
- growStack()
- }()
- wg.Wait()
-
- // in locked goroutine
- wg.Add(1)
- go func() {
- defer wg.Done()
- LockOSThread()
- growStack()
- UnlockOSThread()
- }()
- wg.Wait()
-
- // in finalizer
- wg.Add(1)
- go func() {
- defer wg.Done()
- done := make(chan bool)
- go func() {
- s := new(string)
- SetFinalizer(s, func(ss *string) {
- growStack()
- done <- true
- })
- s = nil
- done <- true
- }()
- <-done
- GC()
- select {
- case <-done:
- case <-time.After(20 * time.Second):
- t.Fatal("finalizer did not run")
- }
- }()
- wg.Wait()
-}
-
-// ... and in init
-//func init() {
-// growStack()
-//}
-
-func growStack() {
- n := 1 << 10
- if testing.Short() {
- n = 1 << 8
- }
- for i := 0; i < n; i++ {
- x := 0
- growStackIter(&x, i)
- if x != i+1 {
- panic("stack is corrupted")
- }
- }
- GC()
-}
-
-// This function is not an anonimous func, so that the compiler can do escape
-// analysis and place x on stack (and subsequently stack growth update the pointer).
-func growStackIter(p *int, n int) {
- if n == 0 {
- *p = n + 1
- GC()
- return
- }
- *p = n + 1
- x := 0
- growStackIter(&x, n-1)
- if x != n {
- panic("stack is corrupted")
- }
-}
-
-func TestStackGrowthCallback(t *testing.T) {
- t.Parallel()
- var wg sync.WaitGroup
-
- // test stack growth at chan op
- wg.Add(1)
- go func() {
- defer wg.Done()
- c := make(chan int, 1)
- growStackWithCallback(func() {
- c <- 1
- <-c
- })
- }()
-
- // test stack growth at map op
- wg.Add(1)
- go func() {
- defer wg.Done()
- m := make(map[int]int)
- growStackWithCallback(func() {
- _, _ = m[1]
- m[1] = 1
- })
- }()
-
- // test stack growth at goroutine creation
- wg.Add(1)
- go func() {
- defer wg.Done()
- growStackWithCallback(func() {
- done := make(chan bool)
- go func() {
- done <- true
- }()
- <-done
- })
- }()
-
- wg.Wait()
-}
-
-func growStackWithCallback(cb func()) {
- var f func(n int)
- f = func(n int) {
- if n == 0 {
- cb()
- return
- }
- f(n - 1)
- }
- for i := 0; i < 1<<10; i++ {
- f(i)
- }
-}
-
-// TestDeferPtrs tests the adjustment of Defer's argument pointers (p aka &y)
-// during a stack copy.
-func set(p *int, x int) {
- *p = x
-}
-func TestDeferPtrs(t *testing.T) {
- var y int
-
- defer func() {
- if y != 42 {
- t.Errorf("defer's stack references were not adjusted appropriately")
- }
- }()
- defer set(&y, 42)
- growStack()
-}
diff --git a/src/pkg/runtime/string.goc b/src/pkg/runtime/string.goc
deleted file mode 100644
index 97a69d07b..000000000
--- a/src/pkg/runtime/string.goc
+++ /dev/null
@@ -1,430 +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
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "race.h"
-#include "../../cmd/ld/textflag.h"
-
-String runtime·emptystring;
-
-#pragma textflag NOSPLIT
-intgo
-runtime·findnull(byte *s)
-{
- intgo l;
-
- if(s == nil)
- return 0;
- for(l=0; s[l]!=0; l++)
- ;
- return l;
-}
-
-intgo
-runtime·findnullw(uint16 *s)
-{
- intgo l;
-
- if(s == nil)
- return 0;
- for(l=0; s[l]!=0; l++)
- ;
- return l;
-}
-
-uintptr runtime·maxstring = 256; // a hint for print
-
-static String
-gostringsize(intgo l)
-{
- String s;
- uintptr ms;
-
- if(l == 0)
- return runtime·emptystring;
- s.str = runtime·mallocgc(l, 0, FlagNoScan|FlagNoZero);
- s.len = l;
- for(;;) {
- ms = runtime·maxstring;
- if((uintptr)l <= ms || runtime·casp((void**)&runtime·maxstring, (void*)ms, (void*)l))
- break;
- }
- return s;
-}
-
-String
-runtime·gostring(byte *str)
-{
- intgo l;
- String s;
-
- l = runtime·findnull(str);
- s = gostringsize(l);
- runtime·memmove(s.str, str, l);
- return s;
-}
-
-String
-runtime·gostringn(byte *str, intgo l)
-{
- String s;
-
- s = gostringsize(l);
- runtime·memmove(s.str, str, l);
- return s;
-}
-
-// used by cmd/cgo
-Slice
-runtime·gobytes(byte *p, intgo n)
-{
- Slice sl;
-
- sl.array = runtime·mallocgc(n, 0, FlagNoScan|FlagNoZero);
- sl.len = n;
- sl.cap = n;
- runtime·memmove(sl.array, p, n);
- return sl;
-}
-
-String
-runtime·gostringnocopy(byte *str)
-{
- String s;
-
- s.str = str;
- s.len = runtime·findnull(str);
- return s;
-}
-
-func cstringToGo(str *byte) (s String) {
- s = runtime·gostringnocopy(str);
-}
-
-String
-runtime·gostringw(uint16 *str)
-{
- intgo n1, n2, i;
- byte buf[8];
- String s;
-
- n1 = 0;
- for(i=0; str[i]; i++)
- n1 += runtime·runetochar(buf, str[i]);
- s = gostringsize(n1+4);
- n2 = 0;
- for(i=0; str[i]; i++) {
- // check for race
- if(n2 >= n1)
- break;
- n2 += runtime·runetochar(s.str+n2, str[i]);
- }
- s.len = n2;
- s.str[s.len] = 0;
- return s;
-}
-
-String
-runtime·catstring(String s1, String s2)
-{
- String s3;
-
- if(s1.len == 0)
- return s2;
- if(s2.len == 0)
- return s1;
-
- s3 = gostringsize(s1.len + s2.len);
- runtime·memmove(s3.str, s1.str, s1.len);
- runtime·memmove(s3.str+s1.len, s2.str, s2.len);
- return s3;
-}
-
-static String
-concatstring(intgo n, String *s)
-{
- intgo i, l, count;
- String out;
-
- l = 0;
- count = 0;
- for(i=0; i<n; i++) {
- if(l + s[i].len < l)
- runtime·throw("string concatenation too long");
- l += s[i].len;
- if(s[i].len > 0) {
- count++;
- out = s[i];
- }
- }
- if(count == 0)
- return runtime·emptystring;
- if(count == 1) // zero or one non-empty string in concatenation
- return out;
-
- out = gostringsize(l);
- l = 0;
- for(i=0; i<n; i++) {
- runtime·memmove(out.str+l, s[i].str, s[i].len);
- l += s[i].len;
- }
- return out;
-}
-
-#pragma textflag NOSPLIT
-func concatstring2(s1 String, s2 String) (res String) {
- USED(&s2);
- res = concatstring(2, &s1);
-}
-#pragma textflag NOSPLIT
-func concatstring3(s1 String, s2 String, s3 String) (res String) {
- USED(&s2);
- USED(&s3);
- res = concatstring(3, &s1);
-}
-#pragma textflag NOSPLIT
-func concatstring4(s1 String, s2 String, s3 String, s4 String) (res String) {
- USED(&s2);
- USED(&s3);
- USED(&s4);
- res = concatstring(4, &s1);
-}
-#pragma textflag NOSPLIT
-func concatstring5(s1 String, s2 String, s3 String, s4 String, s5 String) (res String) {
- USED(&s2);
- USED(&s3);
- USED(&s4);
- USED(&s5);
- res = concatstring(5, &s1);
-}
-#pragma textflag NOSPLIT
-func concatstrings(s Slice) (res String) {
- res = concatstring(s.len, (String*)s.array);
-}
-
-func eqstring(s1 String, s2 String) (v bool) {
- if(s1.len != s2.len) {
- v = false;
- return;
- }
- if(s1.str == s2.str) {
- v = true;
- return;
- }
- v = runtime·memeq(s1.str, s2.str, s1.len);
-}
-
-int32
-runtime·strcmp(byte *s1, byte *s2)
-{
- uintptr i;
- byte c1, c2;
-
- for(i=0;; i++) {
- c1 = s1[i];
- c2 = s2[i];
- if(c1 < c2)
- return -1;
- if(c1 > c2)
- return +1;
- if(c1 == 0)
- return 0;
- }
-}
-
-int32
-runtime·strncmp(byte *s1, byte *s2, uintptr n)
-{
- uintptr i;
- byte c1, c2;
-
- for(i=0; i<n; i++) {
- c1 = s1[i];
- c2 = s2[i];
- if(c1 < c2)
- return -1;
- if(c1 > c2)
- return +1;
- if(c1 == 0)
- break;
- }
- return 0;
-}
-
-byte*
-runtime·strstr(byte *s1, byte *s2)
-{
- byte *sp1, *sp2;
-
- if(*s2 == 0)
- return s1;
- for(; *s1; s1++) {
- if(*s1 != *s2)
- continue;
- sp1 = s1;
- sp2 = s2;
- for(;;) {
- if(*sp2 == 0)
- return s1;
- if(*sp1++ != *sp2++)
- break;
- }
- }
- return nil;
-}
-
-func intstring(v int64) (s String) {
- s = gostringsize(8);
- s.len = runtime·runetochar(s.str, v);
- s.str[s.len] = 0;
-}
-
-func slicebytetostring(b Slice) (s String) {
- void *pc;
-
- if(raceenabled) {
- pc = runtime·getcallerpc(&b);
- runtime·racereadrangepc(b.array, b.len, pc, runtime·slicebytetostring);
- }
- s = gostringsize(b.len);
- runtime·memmove(s.str, b.array, s.len);
-}
-
-func slicebytetostringtmp(b Slice) (s String) {
- void *pc;
-
- if(raceenabled) {
- pc = runtime·getcallerpc(&b);
- runtime·racereadrangepc(b.array, b.len, pc, runtime·slicebytetostringtmp);
- }
-
- // Return a "string" referring to the actual []byte bytes.
- // This is only for use by internal compiler optimizations
- // that know that the string form will be discarded before
- // the calling goroutine could possibly modify the original
- // slice or synchronize with another goroutine.
- // Today, the only such case is a m[string(k)] lookup where
- // m is a string-keyed map and k is a []byte.
- s.str = b.array;
- s.len = b.len;
-}
-
-func stringtoslicebyte(s String) (b Slice) {
- uintptr cap;
-
- cap = runtime·roundupsize(s.len);
- b.array = runtime·mallocgc(cap, 0, FlagNoScan|FlagNoZero);
- b.len = s.len;
- b.cap = cap;
- runtime·memmove(b.array, s.str, s.len);
- if(cap != b.len)
- runtime·memclr(b.array+b.len, cap-b.len);
-}
-
-func slicerunetostring(b Slice) (s String) {
- intgo siz1, siz2, i;
- int32 *a;
- byte dum[8];
- void *pc;
-
- if(raceenabled) {
- pc = runtime·getcallerpc(&b);
- runtime·racereadrangepc(b.array, b.len*sizeof(*a), pc, runtime·slicerunetostring);
- }
- a = (int32*)b.array;
- siz1 = 0;
- for(i=0; i<b.len; i++) {
- siz1 += runtime·runetochar(dum, a[i]);
- }
-
- s = gostringsize(siz1+4);
- siz2 = 0;
- for(i=0; i<b.len; i++) {
- // check for race
- if(siz2 >= siz1)
- break;
- siz2 += runtime·runetochar(s.str+siz2, a[i]);
- }
- s.len = siz2;
- s.str[s.len] = 0;
-}
-
-func stringtoslicerune(s String) (b Slice) {
- intgo n;
- int32 dum, *r;
- uint8 *p, *ep;
- uintptr mem;
-
- // two passes.
- // unlike slicerunetostring, no race because strings are immutable.
- p = s.str;
- ep = s.str+s.len;
- n = 0;
- while(p < ep) {
- p += runtime·charntorune(&dum, p, ep-p);
- n++;
- }
-
- if(n > MaxMem/sizeof(r[0]))
- runtime·throw("out of memory");
- mem = runtime·roundupsize(n*sizeof(r[0]));
- b.array = runtime·mallocgc(mem, 0, FlagNoScan|FlagNoZero);
- b.len = n;
- b.cap = mem/sizeof(r[0]);
- p = s.str;
- r = (int32*)b.array;
- while(p < ep)
- p += runtime·charntorune(r++, p, ep-p);
- if(b.cap > b.len)
- runtime·memclr(b.array+b.len*sizeof(r[0]), (b.cap-b.len)*sizeof(r[0]));
-}
-
-enum
-{
- Runeself = 0x80,
-};
-
-func stringiter(s String, k int) (retk int) {
- int32 l;
-
- if(k >= s.len) {
- // retk=0 is end of iteration
- retk = 0;
- goto out;
- }
-
- l = s.str[k];
- if(l < Runeself) {
- retk = k+1;
- goto out;
- }
-
- // multi-char rune
- retk = k + runtime·charntorune(&l, s.str+k, s.len-k);
-
-out:
-}
-
-func stringiter2(s String, k int) (retk int, retv int32) {
- if(k >= s.len) {
- // retk=0 is end of iteration
- retk = 0;
- retv = 0;
- goto out;
- }
-
- retv = s.str[k];
- if(retv < Runeself) {
- retk = k+1;
- goto out;
- }
-
- // multi-char rune
- retk = k + runtime·charntorune(&retv, s.str+k, s.len-k);
-
-out:
-}
diff --git a/src/pkg/runtime/string_test.go b/src/pkg/runtime/string_test.go
deleted file mode 100644
index df3ff06a7..000000000
--- a/src/pkg/runtime/string_test.go
+++ /dev/null
@@ -1,77 +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_test
-
-import (
- "testing"
-)
-
-func BenchmarkCompareStringEqual(b *testing.B) {
- bytes := []byte("Hello Gophers!")
- s1, s2 := string(bytes), string(bytes)
- for i := 0; i < b.N; i++ {
- if s1 != s2 {
- b.Fatal("s1 != s2")
- }
- }
-}
-
-func BenchmarkCompareStringIdentical(b *testing.B) {
- s1 := "Hello Gophers!"
- s2 := s1
- for i := 0; i < b.N; i++ {
- if s1 != s2 {
- b.Fatal("s1 != s2")
- }
- }
-}
-
-func BenchmarkCompareStringSameLength(b *testing.B) {
- s1 := "Hello Gophers!"
- s2 := "Hello, Gophers"
- for i := 0; i < b.N; i++ {
- if s1 == s2 {
- b.Fatal("s1 == s2")
- }
- }
-}
-
-func BenchmarkCompareStringDifferentLength(b *testing.B) {
- s1 := "Hello Gophers!"
- s2 := "Hello, Gophers!"
- for i := 0; i < b.N; i++ {
- if s1 == s2 {
- b.Fatal("s1 == s2")
- }
- }
-}
-
-func BenchmarkCompareStringBigUnaligned(b *testing.B) {
- bytes := make([]byte, 0, 1<<20)
- for len(bytes) < 1<<20 {
- bytes = append(bytes, "Hello Gophers!"...)
- }
- s1, s2 := string(bytes), "hello"+string(bytes)
- for i := 0; i < b.N; i++ {
- if s1 != s2[len("hello"):] {
- b.Fatal("s1 != s2")
- }
- }
- b.SetBytes(int64(len(s1)))
-}
-
-func BenchmarkCompareStringBig(b *testing.B) {
- bytes := make([]byte, 0, 1<<20)
- for len(bytes) < 1<<20 {
- bytes = append(bytes, "Hello Gophers!"...)
- }
- s1, s2 := string(bytes), string(bytes)
- for i := 0; i < b.N; i++ {
- if s1 != s2 {
- b.Fatal("s1 != s2")
- }
- }
- b.SetBytes(int64(len(s1)))
-}
diff --git a/src/pkg/runtime/symtab.goc b/src/pkg/runtime/symtab.goc
deleted file mode 100644
index 15e1d28fa..000000000
--- a/src/pkg/runtime/symtab.goc
+++ /dev/null
@@ -1,332 +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.
-
-// Runtime symbol table parsing.
-// See http://golang.org/s/go12symtab for an overview.
-
-package runtime
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "funcdata.h"
-
-typedef struct Ftab Ftab;
-struct Ftab
-{
- uintptr entry;
- uintptr funcoff;
-};
-
-extern byte pclntab[];
-
-static Ftab *ftab;
-static uintptr nftab;
-static uint32 *filetab;
-static uint32 nfiletab;
-
-static String end = { (uint8*)"end", 3 };
-
-void
-runtime·symtabinit(void)
-{
- int32 i, j;
- Func *f1, *f2;
-
- // See golang.org/s/go12symtab for header: 0xfffffffb,
- // two zero bytes, a byte giving the PC quantum,
- // and a byte giving the pointer width in bytes.
- if(*(uint32*)pclntab != 0xfffffffb || pclntab[4] != 0 || pclntab[5] != 0 || pclntab[6] != PCQuantum || pclntab[7] != sizeof(void*)) {
- runtime·printf("runtime: function symbol table header: %x %x\n", *(uint32*)pclntab, *(uint32*)(pclntab+4));
- runtime·throw("invalid function symbol table\n");
- }
-
- nftab = *(uintptr*)(pclntab+8);
- ftab = (Ftab*)(pclntab+8+sizeof(void*));
- for(i=0; i<nftab; i++) {
- // NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
- if(ftab[i].entry > ftab[i+1].entry) {
- f1 = (Func*)(pclntab + ftab[i].funcoff);
- f2 = (Func*)(pclntab + ftab[i+1].funcoff);
- runtime·printf("function symbol table not sorted by program counter: %p %s > %p %s", ftab[i].entry, runtime·funcname(f1), ftab[i+1].entry, i+1 == nftab ? "end" : runtime·funcname(f2));
- for(j=0; j<=i; j++)
- runtime·printf("\t%p %s\n", ftab[j].entry, runtime·funcname((Func*)(pclntab + ftab[j].funcoff)));
- runtime·throw("invalid runtime symbol table");
- }
- }
-
- filetab = (uint32*)(pclntab + *(uint32*)&ftab[nftab].funcoff);
- nfiletab = filetab[0];
-}
-
-static uint32
-readvarint(byte **pp)
-{
- byte *p;
- uint32 v;
- int32 shift;
-
- v = 0;
- p = *pp;
- for(shift = 0;; shift += 7) {
- v |= (*p & 0x7F) << shift;
- if(!(*p++ & 0x80))
- break;
- }
- *pp = p;
- return v;
-}
-
-void*
-runtime·funcdata(Func *f, int32 i)
-{
- byte *p;
-
- if(i < 0 || i >= f->nfuncdata)
- return nil;
- p = (byte*)&f->nfuncdata + 4 + f->npcdata*4;
- if(sizeof(void*) == 8 && ((uintptr)p & 4)) {
- if(((uintptr)f & 4))
- runtime·printf("misaligned func %p\n", f);
- p += 4;
- }
- return ((void**)p)[i];
-}
-
-static bool
-step(byte **pp, uintptr *pc, int32 *value, bool first)
-{
- uint32 uvdelta, pcdelta;
- int32 vdelta;
-
- uvdelta = readvarint(pp);
- if(uvdelta == 0 && !first)
- return 0;
- if(uvdelta&1)
- uvdelta = ~(uvdelta>>1);
- else
- uvdelta >>= 1;
- vdelta = (int32)uvdelta;
- pcdelta = readvarint(pp) * PCQuantum;
- *value += vdelta;
- *pc += pcdelta;
- return 1;
-}
-
-// Return associated data value for targetpc in func f.
-// (Source file is f->src.)
-static int32
-pcvalue(Func *f, int32 off, uintptr targetpc, bool strict)
-{
- byte *p;
- uintptr pc;
- int32 value;
-
- enum {
- debug = 0
- };
-
- // The table is a delta-encoded sequence of (value, pc) pairs.
- // Each pair states the given value is in effect up to pc.
- // The value deltas are signed, zig-zag encoded.
- // The pc deltas are unsigned.
- // The starting value is -1, the starting pc is the function entry.
- // The table ends at a value delta of 0 except in the first pair.
- if(off == 0)
- return -1;
- p = pclntab + off;
- pc = f->entry;
- value = -1;
-
- if(debug && !runtime·panicking)
- runtime·printf("pcvalue start f=%s [%p] pc=%p targetpc=%p value=%d tab=%p\n",
- runtime·funcname(f), f, pc, targetpc, value, p);
-
- while(step(&p, &pc, &value, pc == f->entry)) {
- if(debug)
- runtime·printf("\tvalue=%d until pc=%p\n", value, pc);
- if(targetpc < pc)
- return value;
- }
-
- // If there was a table, it should have covered all program counters.
- // If not, something is wrong.
- if(runtime·panicking || !strict)
- return -1;
- runtime·printf("runtime: invalid pc-encoded table f=%s pc=%p targetpc=%p tab=%p\n",
- runtime·funcname(f), pc, targetpc, p);
- p = (byte*)f + off;
- pc = f->entry;
- value = -1;
-
- while(step(&p, &pc, &value, pc == f->entry))
- runtime·printf("\tvalue=%d until pc=%p\n", value, pc);
-
- runtime·throw("invalid runtime symbol table");
- return -1;
-}
-
-static String unknown = { (uint8*)"?", 1 };
-
-int8*
-runtime·funcname(Func *f)
-{
- if(f == nil || f->nameoff == 0)
- return nil;
- return (int8*)(pclntab + f->nameoff);
-}
-
-static int32
-funcline(Func *f, uintptr targetpc, String *file, bool strict)
-{
- int32 line;
- int32 fileno;
-
- *file = unknown;
- fileno = pcvalue(f, f->pcfile, targetpc, strict);
- line = pcvalue(f, f->pcln, targetpc, strict);
- if(fileno == -1 || line == -1 || fileno >= nfiletab) {
- // runtime·printf("looking for %p in %S got file=%d line=%d\n", targetpc, *f->name, fileno, line);
- return 0;
- }
- *file = runtime·gostringnocopy(pclntab + filetab[fileno]);
- return line;
-}
-
-int32
-runtime·funcline(Func *f, uintptr targetpc, String *file)
-{
- return funcline(f, targetpc, file, true);
-}
-
-int32
-runtime·funcspdelta(Func *f, uintptr targetpc)
-{
- int32 x;
-
- x = pcvalue(f, f->pcsp, targetpc, true);
- if(x&(sizeof(void*)-1))
- runtime·printf("invalid spdelta %d %d\n", f->pcsp, x);
- return x;
-}
-
-int32
-runtime·pcdatavalue(Func *f, int32 table, uintptr targetpc)
-{
- if(table < 0 || table >= f->npcdata)
- return -1;
- return pcvalue(f, (&f->nfuncdata)[1+table], targetpc, true);
-}
-
-int32
-runtime·funcarglen(Func *f, uintptr targetpc)
-{
- if(targetpc == f->entry)
- return 0;
- return runtime·pcdatavalue(f, PCDATA_ArgSize, targetpc-PCQuantum);
-}
-
-func funcline_go(f *Func, targetpc uintptr) (retfile String, retline int) {
- // Pass strict=false here, because anyone can call this function,
- // and they might just be wrong about targetpc belonging to f.
- retline = funcline(f, targetpc, &retfile, false);
-}
-
-func funcname_go(f *Func) (ret String) {
- ret = runtime·gostringnocopy((uint8*)runtime·funcname(f));
-}
-
-func funcentry_go(f *Func) (ret uintptr) {
- ret = f->entry;
-}
-
-Func*
-runtime·findfunc(uintptr addr)
-{
- Ftab *f;
- int32 nf, n;
-
- if(nftab == 0)
- return nil;
- if(addr < ftab[0].entry || addr >= ftab[nftab].entry)
- return nil;
-
- // binary search to find func with entry <= addr.
- f = ftab;
- nf = nftab;
- while(nf > 0) {
- n = nf/2;
- if(f[n].entry <= addr && addr < f[n+1].entry)
- return (Func*)(pclntab + f[n].funcoff);
- else if(addr < f[n].entry)
- nf = n;
- else {
- f += n+1;
- nf -= n+1;
- }
- }
-
- // can't get here -- we already checked above
- // that the address was in the table bounds.
- // this can only happen if the table isn't sorted
- // by address or if the binary search above is buggy.
- runtime·prints("findfunc unreachable\n");
- return nil;
-}
-
-func FuncForPC(pc uintptr) (ret *Func) {
- ret = runtime·findfunc(pc);
-}
-
-static bool
-hasprefix(String s, int8 *p)
-{
- int32 i;
-
- for(i=0; i<s.len; i++) {
- if(p[i] == 0)
- return 1;
- if(p[i] != s.str[i])
- return 0;
- }
- return p[i] == 0;
-}
-
-static bool
-contains(String s, int8 *p)
-{
- int32 i;
-
- if(p[0] == 0)
- return 1;
- for(i=0; i<s.len; i++) {
- if(s.str[i] != p[0])
- continue;
- if(hasprefix((String){s.str + i, s.len - i}, p))
- return 1;
- }
- return 0;
-}
-
-bool
-runtime·showframe(Func *f, G *gp)
-{
- static int32 traceback = -1;
- String name;
-
- if(m->throwing > 0 && gp != nil && (gp == m->curg || gp == m->caughtsig))
- return 1;
- if(traceback < 0)
- traceback = runtime·gotraceback(nil);
- name = runtime·gostringnocopy((uint8*)runtime·funcname(f));
-
- // Special case: always show runtime.panic frame, so that we can
- // see where a panic started in the middle of a stack trace.
- // See golang.org/issue/5832.
- if(name.len == 7+1+5 && hasprefix(name, "runtime.panic"))
- return 1;
-
- return traceback > 1 || f != nil && contains(name, ".") && !hasprefix(name, "runtime.");
-}
diff --git a/src/pkg/runtime/syscall_solaris.goc b/src/pkg/runtime/syscall_solaris.goc
deleted file mode 100644
index 21bcce4d1..000000000
--- a/src/pkg/runtime/syscall_solaris.goc
+++ /dev/null
@@ -1,374 +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 syscall
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "cgocall.h"
-#include "../../cmd/ld/textflag.h"
-
-#pragma dynimport libc·chdir chdir "libc.so"
-#pragma dynimport libc·chroot chroot "libc.so"
-#pragma dynimport libc·close close "libc.so"
-#pragma dynimport libc·dlclose dlclose "libc.so"
-#pragma dynimport libc·dlopen dlopen "libc.so"
-#pragma dynimport libc·dlsym dlsym "libc.so"
-#pragma dynimport libc·execve execve "libc.so"
-#pragma dynimport libc·fcntl fcntl "libc.so"
-#pragma dynimport libc·gethostname gethostname "libc.so"
-#pragma dynimport libc·ioctl ioctl "libc.so"
-#pragma dynimport libc·pipe pipe "libc.so"
-#pragma dynimport libc·setgid setgid "libc.so"
-#pragma dynimport libc·setgroups setgroups "libc.so"
-#pragma dynimport libc·setsid setsid "libc.so"
-#pragma dynimport libc·setuid setuid "libc.so"
-#pragma dynimport libc·setpgid setsid "libc.so"
-#pragma dynimport libc·syscall syscall "libc.so"
-#pragma dynimport libc·forkx forkx "libc.so"
-#pragma dynimport libc·wait4 wait4 "libc.so"
-extern uintptr libc·chdir;
-extern uintptr libc·chroot;
-extern uintptr libc·close;
-extern uintptr libc·dlclose;
-extern uintptr libc·dlopen;
-extern uintptr libc·dlsym;
-extern uintptr libc·execve;
-extern uintptr libc·exit;
-extern uintptr libc·fcntl;
-extern uintptr libc·gethostname;
-extern uintptr libc·ioctl;
-extern uintptr libc·pipe;
-extern uintptr libc·setgid;
-extern uintptr libc·setgroups;
-extern uintptr libc·setsid;
-extern uintptr libc·setuid;
-extern uintptr libc·setpgid;
-extern uintptr libc·syscall;
-extern uintptr libc·forkx;
-extern uintptr libc·wait4;
-extern uintptr libc·write;
-
-func sysvicall6(func uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr)
-{
- LibCall c;
-
- USED(a2);
- USED(a3);
- USED(a4);
- USED(a5);
- USED(a6);
- c.fn = (void*)func;
- c.n = nargs;
- c.args = (void*)&a1;
- runtime·cgocall(runtime·asmsysvicall6, &c);
- err = c.err;
- r1 = c.r1;
- r2 = c.r2;
-}
-
-#pragma textflag NOSPLIT
-func rawSysvicall6(func uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr)
-{
- LibCall c;
-
- USED(a2);
- USED(a3);
- USED(a4);
- USED(a5);
- USED(a6);
- c.fn = (void*)func;
- c.n = nargs;
- c.args = (void*)&a1;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
- r1 = c.r1;
- r2 = c.r2;
-}
-
-#pragma textflag NOSPLIT
-func chdir(path uintptr) (err uintptr) {
- LibCall c;
-
- c.fn = (void*)libc·chdir;
- c.n = 1;
- c.args = (void*)&path;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
-}
-
-#pragma textflag NOSPLIT
-func chroot1(path uintptr) (err uintptr) {
- LibCall c;
-
- c.fn = (void*)libc·chroot;
- c.n = 1;
- c.args = (void*)&path;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
-}
-
-#pragma textflag NOSPLIT
-func close(fd uintptr) (err uintptr) {
- LibCall c;
-
- c.fn = (void*)libc·close;
- c.n = 1;
- c.args = (void*)&fd;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
-}
-
-func dlclose(handle uintptr) (err uintptr) {
- LibCall c;
-
- USED(handle);
- c.fn = (void*)libc·dlclose;
- c.n = 1;
- c.args = (void*)&handle;
- runtime·cgocall(runtime·asmsysvicall6, &c);
- err = c.r1;
-}
-
-func dlopen(name *uint8, mode uintptr) (handle uintptr, err uintptr) {
- LibCall c;
-
- USED(mode);
- c.fn = (void*)libc·dlopen;
- c.n = 2;
- c.args = (void*)&name;
- runtime·cgocall(runtime·asmsysvicall6, &c);
- handle = c.r1;
- if(handle == 0)
- err = c.err;
- else
- err = 0;
-}
-
-func dlsym(handle uintptr, name *uint8) (proc uintptr, err uintptr) {
- LibCall c;
-
- USED(name);
- c.fn = (void*)libc·dlsym;
- c.n = 2;
- c.args = &handle;
- runtime·cgocall(runtime·asmsysvicall6, &c);
- proc = c.r1;
- if(proc == 0)
- err = c.err;
- else
- err = 0;
-}
-
-#pragma textflag NOSPLIT
-func execve(path uintptr, argv uintptr, envp uintptr) (err uintptr) {
- LibCall c;
-
- USED(argv);
- USED(envp);
- c.fn = (void*)libc·execve;
- c.n = 3;
- c.args = (void*)&path;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
-}
-
-#pragma textflag NOSPLIT
-func exit(code uintptr) {
- LibCall c;
-
- c.fn = (void*)libc·exit;
- c.n = 1;
- c.args = (void*)&code;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
-}
-
-#pragma textflag NOSPLIT
-func fcntl1(fd uintptr, cmd uintptr, arg uintptr) (val uintptr, err uintptr) {
- LibCall c;
-
- USED(cmd);
- USED(arg);
- c.fn = (void*)libc·fcntl;
- c.n = 3;
- c.args = (void*)&fd;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
- val = c.r1;
-}
-
-func gethostname() (name String, err uintptr) {
- struct { uintptr v[2]; } args;
- uint8 cname[MAXHOSTNAMELEN];
- LibCall c;
-
- c.fn = (void*)libc·gethostname;
- c.n = 2;
- args.v[0] = (uintptr)&cname[0];
- args.v[1] = MAXHOSTNAMELEN;
- c.args = (void*)&args;
- runtime·cgocall(runtime·asmsysvicall6, &c);
- err = c.err;
- if(c.r1) {
- name = runtime·emptystring;
- return;
- }
- cname[MAXHOSTNAMELEN - 1] = 0;
- name = runtime·gostring(cname);
-}
-
-#pragma textflag NOSPLIT
-func ioctl(fd uintptr, req uintptr, arg uintptr) (err uintptr) {
- LibCall c;
-
- USED(req);
- USED(arg);
- c.fn = (void*)libc·ioctl;
- c.n = 3;
- c.args = (void*)&fd;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
-}
-
-func wait4(pid uintptr, wstatus *uint32, options uintptr, rusage *void) (wpid int, err uintptr) {
- LibCall c;
-
- USED(wstatus);
- USED(options);
- USED(rusage);
- c.fn = (void*)libc·wait4;
- c.n = 4;
- c.args = (void*)&pid;
- runtime·cgocall(runtime·asmsysvicall6, &c);
- err = c.err;
- wpid = c.r1;
-}
-
-#pragma textflag NOSPLIT
-func setgid(gid uintptr) (err uintptr) {
- LibCall c;
-
- c.fn = (void*)libc·setgid;
- c.n = 1;
- c.args = (void*)&gid;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
-}
-
-#pragma textflag NOSPLIT
-func setgroups1(ngid uintptr, gid uintptr) (err uintptr) {
- LibCall c;
-
- USED(gid);
- c.fn = (void*)libc·setgroups;
- c.n = 2;
- c.args = (void*)&ngid;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
-}
-
-#pragma textflag NOSPLIT
-func setsid() (pid uintptr, err uintptr) {
- LibCall c;
-
- c.fn = (void*)libc·setsid;
- c.n = 0;
- c.args = (void*)0;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
- pid = c.r1;
-}
-
-#pragma textflag NOSPLIT
-func setuid(uid uintptr) (err uintptr) {
- LibCall c;
-
- c.fn = (void*)libc·setuid;
- c.n = 1;
- c.args = (void*)&uid;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
-}
-
-#pragma textflag NOSPLIT
-func setpgid(pid uintptr, pgid uintptr) (err uintptr) {
- LibCall c;
-
- USED(pgid);
- c.fn = (void*)libc·setpgid;
- c.n = 2;
- c.args = (void*)&pid;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
-}
-
-#pragma textflag NOSPLIT
-func forkx(flags uintptr) (pid uintptr, err uintptr) {
- LibCall c;
-
- c.fn = (void*)libc·forkx;
- c.n = 1;
- c.args = (void*)&flags;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
- pid = c.r1;
-}
-
-void runtime·pipe1(void);
-
-func pipe() (r uintptr, w uintptr, err uintptr) {
- LibCall c;
-
- c.fn = (void*)runtime·pipe1;
- c.n = 0;
- c.args = (void*)0;
- runtime·cgocall(runtime·asmsysvicall6, &c);
- err = c.err;
- r = c.r1;
- w = c.r2;
-}
-
-#pragma textflag NOSPLIT
-func write1(fd uintptr, buf uintptr, nbyte uintptr) (n uintptr, err uintptr) {
- LibCall c;
-
- USED(buf);
- USED(nbyte);
- c.fn = (void*)libc·write;
- c.n = 3;
- c.args = (void*)fd;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
- n = c.r1;
-}
-
-func Syscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- LibCall c;
-
- USED(a1);
- USED(a2);
- USED(a3);
- c.fn = (void*)libc·syscall;
- c.n = 4;
- c.args = &trap;
- runtime·cgocall(runtime·asmsysvicall6, &c);
- err = c.err;
- r1 = c.r1;
- r2 = c.r2;
-}
-
-func RawSyscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- LibCall c;
-
- USED(a1);
- USED(a2);
- USED(a3);
- c.fn = (void*)libc·syscall;
- c.n = 4;
- c.args = &trap;
- runtime·asmcgocall(runtime·asmsysvicall6, &c);
- err = c.err;
- r1 = c.r1;
- r2 = c.r2;
-}
diff --git a/src/pkg/runtime/syscall_windows.goc b/src/pkg/runtime/syscall_windows.goc
deleted file mode 100644
index 528245363..000000000
--- a/src/pkg/runtime/syscall_windows.goc
+++ /dev/null
@@ -1,145 +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 syscall
-#include "runtime.h"
-#include "os_GOOS.h"
-#include "cgocall.h"
-
-func loadlibrary(filename *uint16) (handle uintptr, err uintptr) {
- LibCall c;
-
- c.fn = runtime·LoadLibrary;
- c.n = 1;
- c.args = &filename;
- runtime·cgocall(runtime·asmstdcall, &c);
- handle = c.r1;
- if(handle == 0)
- err = c.err;
- else
- err = 0;
-}
-
-func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err uintptr) {
- LibCall c;
-
- USED(procname);
- c.fn = runtime·GetProcAddress;
- c.n = 2;
- c.args = &handle;
- runtime·cgocall(runtime·asmstdcall, &c);
- proc = c.r1;
- if(proc == 0)
- err = c.err;
- else
- err = 0;
-}
-
-func NewCallback(fn Eface) (code uintptr) {
- code = (uintptr)runtime·compilecallback(fn, true);
-}
-
-func NewCallbackCDecl(fn Eface) (code uintptr) {
- code = (uintptr)runtime·compilecallback(fn, false);
-}
-
-func Syscall(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- LibCall c;
-
- USED(a2);
- USED(a3);
- c.fn = (void*)fn;
- c.n = nargs;
- c.args = &a1;
- runtime·cgocall(runtime·asmstdcall, &c);
- err = c.err;
- r1 = c.r1;
- r2 = c.r2;
-}
-
-func Syscall6(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- LibCall c;
-
- USED(a2);
- USED(a3);
- USED(a4);
- USED(a5);
- USED(a6);
- c.fn = (void*)fn;
- c.n = nargs;
- c.args = &a1;
- runtime·cgocall(runtime·asmstdcall, &c);
- err = c.err;
- r1 = c.r1;
- r2 = c.r2;
-}
-
-func Syscall9(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- LibCall c;
-
- USED(a2);
- USED(a3);
- USED(a4);
- USED(a5);
- USED(a6);
- USED(a7);
- USED(a8);
- USED(a9);
- c.fn = (void*)fn;
- c.n = nargs;
- c.args = &a1;
- runtime·cgocall(runtime·asmstdcall, &c);
- err = c.err;
- r1 = c.r1;
- r2 = c.r2;
-}
-
-func Syscall12(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr, a10 uintptr, a11 uintptr, a12 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- LibCall c;
-
- USED(a2);
- USED(a3);
- USED(a4);
- USED(a5);
- USED(a6);
- USED(a7);
- USED(a8);
- USED(a9);
- USED(a10);
- USED(a11);
- USED(a12);
- c.fn = (void*)fn;
- c.n = nargs;
- c.args = &a1;
- runtime·cgocall(runtime·asmstdcall, &c);
- err = c.err;
- r1 = c.r1;
- r2 = c.r2;
-}
-
-func Syscall15(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr, a10 uintptr, a11 uintptr, a12 uintptr, a13 uintptr, a14 uintptr, a15 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- LibCall c;
-
- USED(a2);
- USED(a3);
- USED(a4);
- USED(a5);
- USED(a6);
- USED(a7);
- USED(a8);
- USED(a9);
- USED(a10);
- USED(a11);
- USED(a12);
- USED(a13);
- USED(a14);
- USED(a15);
- c.fn = (void*)fn;
- c.n = nargs;
- c.args = &a1;
- runtime·cgocall(runtime·asmstdcall, &c);
- err = c.err;
- r1 = c.r1;
- r2 = c.r2;
-}
diff --git a/src/pkg/runtime/time.goc b/src/pkg/runtime/time.goc
deleted file mode 100644
index 712e03e83..000000000
--- a/src/pkg/runtime/time.goc
+++ /dev/null
@@ -1,344 +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.
-
-// Time-related runtime and pieces of package time.
-
-package time
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "race.h"
-
-enum {
- debug = 0,
-};
-
-static Timers timers;
-static void addtimer(Timer*);
-static void dumptimers(int8*);
-
-// nacl fake time support.
-int64 runtime·timens;
-
-// Package time APIs.
-// Godoc uses the comments in package time, not these.
-
-// time.now is implemented in assembly.
-
-// runtimeNano returns the current value of the runtime clock in nanoseconds.
-func runtimeNano() (ns int64) {
- ns = runtime·nanotime();
-}
-
-// Sleep puts the current goroutine to sleep for at least ns nanoseconds.
-func Sleep(ns int64) {
- runtime·tsleep(ns, "sleep");
-}
-
-// startTimer adds t to the timer heap.
-func startTimer(t *Timer) {
- if(raceenabled)
- runtime·racerelease(t);
- runtime·addtimer(t);
-}
-
-// stopTimer removes t from the timer heap if it is there.
-// It returns true if t was removed, false if t wasn't even there.
-func stopTimer(t *Timer) (stopped bool) {
- stopped = runtime·deltimer(t);
-}
-
-// C runtime.
-
-void runtime·gc_unixnanotime(int64 *now);
-
-int64 runtime·unixnanotime(void)
-{
- int64 now;
-
- runtime·gc_unixnanotime(&now);
- return now;
-}
-
-static void timerproc(void);
-static void siftup(int32);
-static void siftdown(int32);
-
-// Ready the goroutine e.data.
-static void
-ready(int64 now, Eface e)
-{
- USED(now);
-
- runtime·ready(e.data);
-}
-
-static FuncVal readyv = {(void(*)(void))ready};
-
-// Put the current goroutine to sleep for ns nanoseconds.
-void
-runtime·tsleep(int64 ns, int8 *reason)
-{
- Timer t;
-
- if(ns <= 0)
- return;
-
- t.when = runtime·nanotime() + ns;
- t.period = 0;
- t.fv = &readyv;
- t.arg.data = g;
- runtime·lock(&timers);
- addtimer(&t);
- runtime·parkunlock(&timers, reason);
-}
-
-static FuncVal timerprocv = {timerproc};
-
-void
-runtime·addtimer(Timer *t)
-{
- runtime·lock(&timers);
- addtimer(t);
- runtime·unlock(&timers);
-}
-
-// Add a timer to the heap and start or kick the timer proc
-// if the new timer is earlier than any of the others.
-static void
-addtimer(Timer *t)
-{
- int32 n;
- Timer **nt;
-
- // when must never be negative; otherwise timerproc will overflow
- // during its delta calculation and never expire other timers.
- if(t->when < 0)
- t->when = (1LL<<63)-1;
-
- if(timers.len >= timers.cap) {
- // Grow slice.
- n = 16;
- if(n <= timers.cap)
- n = timers.cap*3 / 2;
- nt = runtime·malloc(n*sizeof nt[0]);
- runtime·memmove(nt, timers.t, timers.len*sizeof nt[0]);
- runtime·free(timers.t);
- timers.t = nt;
- timers.cap = n;
- }
- t->i = timers.len++;
- timers.t[t->i] = t;
- siftup(t->i);
- if(t->i == 0) {
- // siftup moved to top: new earliest deadline.
- if(timers.sleeping) {
- timers.sleeping = false;
- runtime·notewakeup(&timers.waitnote);
- }
- if(timers.rescheduling) {
- timers.rescheduling = false;
- runtime·ready(timers.timerproc);
- }
- }
- if(timers.timerproc == nil) {
- timers.timerproc = runtime·newproc1(&timerprocv, nil, 0, 0, addtimer);
- timers.timerproc->issystem = true;
- }
- if(debug)
- dumptimers("addtimer");
-}
-
-// Delete timer t from the heap.
-// Do not need to update the timerproc:
-// if it wakes up early, no big deal.
-bool
-runtime·deltimer(Timer *t)
-{
- int32 i;
-
- // Dereference t so that any panic happens before the lock is held.
- // Discard result, because t might be moving in the heap.
- i = t->i;
- USED(i);
-
- runtime·lock(&timers);
-
- // t may not be registered anymore and may have
- // a bogus i (typically 0, if generated by Go).
- // Verify it before proceeding.
- i = t->i;
- if(i < 0 || i >= timers.len || timers.t[i] != t) {
- runtime·unlock(&timers);
- return false;
- }
-
- timers.len--;
- if(i == timers.len) {
- timers.t[i] = nil;
- } else {
- timers.t[i] = timers.t[timers.len];
- timers.t[timers.len] = nil;
- timers.t[i]->i = i;
- siftup(i);
- siftdown(i);
- }
- if(debug)
- dumptimers("deltimer");
- runtime·unlock(&timers);
- return true;
-}
-
-// Timerproc runs the time-driven events.
-// It sleeps until the next event in the timers heap.
-// If addtimer inserts a new earlier event, addtimer
-// wakes timerproc early.
-static void
-timerproc(void)
-{
- int64 delta, now;
- Timer *t;
- void (*f)(int64, Eface);
- Eface arg;
-
- for(;;) {
- runtime·lock(&timers);
- timers.sleeping = false;
- now = runtime·nanotime();
- for(;;) {
- if(timers.len == 0) {
- delta = -1;
- break;
- }
- t = timers.t[0];
- delta = t->when - now;
- if(delta > 0)
- break;
- if(t->period > 0) {
- // leave in heap but adjust next time to fire
- t->when += t->period * (1 + -delta/t->period);
- siftdown(0);
- } else {
- // remove from heap
- timers.t[0] = timers.t[--timers.len];
- timers.t[0]->i = 0;
- siftdown(0);
- t->i = -1; // mark as removed
- }
- f = (void*)t->fv->fn;
- arg = t->arg;
- runtime·unlock(&timers);
- if(raceenabled)
- runtime·raceacquire(t);
- f(now, arg);
-
- // clear f and arg to avoid leak while sleeping for next timer
- f = nil;
- USED(f);
- arg.type = nil;
- arg.data = nil;
- USED(&arg);
-
- runtime·lock(&timers);
- }
- if(delta < 0) {
- // No timers left - put goroutine to sleep.
- timers.rescheduling = true;
- g->isbackground = true;
- runtime·parkunlock(&timers, "timer goroutine (idle)");
- g->isbackground = false;
- continue;
- }
- // At least one timer pending. Sleep until then.
- timers.sleeping = true;
- runtime·noteclear(&timers.waitnote);
- runtime·unlock(&timers);
- runtime·notetsleepg(&timers.waitnote, delta);
- }
-}
-
-// heap maintenance algorithms.
-
-static void
-siftup(int32 i)
-{
- int32 p;
- int64 when;
- Timer **t, *tmp;
-
- t = timers.t;
- when = t[i]->when;
- tmp = t[i];
- while(i > 0) {
- p = (i-1)/4; // parent
- if(when >= t[p]->when)
- break;
- t[i] = t[p];
- t[i]->i = i;
- t[p] = tmp;
- tmp->i = p;
- i = p;
- }
-}
-
-static void
-siftdown(int32 i)
-{
- int32 c, c3, len;
- int64 when, w, w3;
- Timer **t, *tmp;
-
- t = timers.t;
- len = timers.len;
- when = t[i]->when;
- tmp = t[i];
- for(;;) {
- c = i*4 + 1; // left child
- c3 = c + 2; // mid child
- if(c >= len) {
- break;
- }
- w = t[c]->when;
- if(c+1 < len && t[c+1]->when < w) {
- w = t[c+1]->when;
- c++;
- }
- if(c3 < len) {
- w3 = t[c3]->when;
- if(c3+1 < len && t[c3+1]->when < w3) {
- w3 = t[c3+1]->when;
- c3++;
- }
- if(w3 < w) {
- w = w3;
- c = c3;
- }
- }
- if(w >= when)
- break;
- t[i] = t[c];
- t[i]->i = i;
- t[c] = tmp;
- tmp->i = c;
- i = c;
- }
-}
-
-static void
-dumptimers(int8 *msg)
-{
- Timer *t;
- int32 i;
-
- runtime·printf("timers: %s\n", msg);
- for(i = 0; i < timers.len; i++) {
- t = timers.t[i];
- runtime·printf("\t%d\t%p:\ti %d when %D period %D fn %p\n",
- i, t, t->i, t->when, t->period, t->fv->fn);
- }
- runtime·printf("\n");
-}
diff --git a/src/pkg/runtime/time_plan9_386.c b/src/pkg/runtime/time_plan9_386.c
deleted file mode 100644
index 71d54b764..000000000
--- a/src/pkg/runtime/time_plan9_386.c
+++ /dev/null
@@ -1,36 +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 "runtime.h"
-#include "os_GOOS.h"
-#include "../../cmd/ld/textflag.h"
-
-#pragma textflag NOSPLIT
-int64
-runtime·nanotime(void)
-{
- static int32 fd = -1;
- byte b[8];
- uint32 hi, lo;
-
- // As long as all goroutines share the same file
- // descriptor table we can get away with using
- // just a static fd. Without a lock the file can
- // be opened twice but that's okay.
- //
- // Using /dev/bintime gives us a latency on the
- // order of ten microseconds between two calls.
- //
- // The naïve implementation (without the cached
- // file descriptor) is roughly four times slower
- // in 9vx on a 2.16 GHz Intel Core 2 Duo.
-
- if(fd < 0 && (fd = runtime·open("/dev/bintime", OREAD|OCEXEC, 0)) < 0)
- return 0;
- if(runtime·pread(fd, b, sizeof b, 0) != sizeof b)
- return 0;
- hi = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
- lo = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
- return (int64)hi<<32 | (int64)lo;
-}
diff --git a/src/pkg/runtime/traceback_arm.c b/src/pkg/runtime/traceback_arm.c
deleted file mode 100644
index 30f43d54c..000000000
--- a/src/pkg/runtime/traceback_arm.c
+++ /dev/null
@@ -1,357 +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.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "funcdata.h"
-
-void runtime·sigpanic(void);
-void runtime·newproc(void);
-void runtime·deferproc(void);
-
-int32
-runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, bool (*callback)(Stkframe*, void*), void *v, bool printall)
-{
- int32 i, n, nprint, line, gotraceback;
- uintptr x, tracepc, sparg;
- bool waspanic, wasnewproc, printing;
- Func *f, *flr;
- Stkframe frame;
- Stktop *stk;
- String file;
- Panic *panic;
- Defer *defer;
-
- gotraceback = runtime·gotraceback(nil);
-
- if(pc0 == ~(uintptr)0 && sp0 == ~(uintptr)0) { // Signal to fetch saved values from gp.
- if(gp->syscallstack != (uintptr)nil) {
- pc0 = gp->syscallpc;
- sp0 = gp->syscallsp;
- lr0 = 0;
- } else {
- pc0 = gp->sched.pc;
- sp0 = gp->sched.sp;
- lr0 = gp->sched.lr;
- }
- }
-
- nprint = 0;
- runtime·memclr((byte*)&frame, sizeof frame);
- frame.pc = pc0;
- frame.lr = lr0;
- frame.sp = sp0;
- waspanic = false;
- wasnewproc = false;
- printing = pcbuf==nil && callback==nil;
-
- panic = gp->panic;
- defer = gp->defer;
-
- while(defer != nil && defer->argp == NoArgs)
- defer = defer->link;
- while(panic != nil && panic->defer == nil)
- panic = panic->link;
-
- // If the PC is zero, it's likely a nil function call.
- // Start in the caller's frame.
- if(frame.pc == 0) {
- frame.pc = frame.lr;
- frame.lr = 0;
- }
-
- f = runtime·findfunc(frame.pc);
- if(f == nil) {
- if(callback != nil) {
- runtime·printf("runtime: unknown pc %p\n", frame.pc);
- runtime·throw("unknown pc");
- }
- return 0;
- }
- frame.fn = f;
-
- n = 0;
- stk = (Stktop*)gp->stackbase;
- while(n < max) {
- // Typically:
- // pc is the PC of the running function.
- // sp is the stack pointer at that program counter.
- // fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown.
- // stk is the stack containing sp.
- // The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp.
-
- if(frame.pc == (uintptr)runtime·lessstack) {
- // Hit top of stack segment. Unwind to next segment.
- frame.pc = stk->gobuf.pc;
- frame.sp = stk->gobuf.sp;
- frame.lr = 0;
- frame.fp = 0;
- if(printing && runtime·showframe(nil, gp))
- runtime·printf("----- stack segment boundary -----\n");
- stk = (Stktop*)stk->stackbase;
-
- f = runtime·findfunc(frame.pc);
- if(f == nil) {
- runtime·printf("runtime: unknown pc %p after stack split\n", frame.pc);
- if(callback != nil)
- runtime·throw("unknown pc");
- }
- frame.fn = f;
- continue;
- }
- f = frame.fn;
-
- // Found an actual function.
- // Derive frame pointer and link register.
- if(frame.fp == 0)
- frame.fp = frame.sp + runtime·funcspdelta(f, frame.pc);
- if(runtime·topofstack(f)) {
- frame.lr = 0;
- flr = nil;
- } else if(f->entry == (uintptr)runtime·jmpdefer) {
- // jmpdefer modifies SP/LR/PC non-atomically.
- // If a profiling interrupt arrives during jmpdefer,
- // the stack unwind may see a mismatched register set
- // and get confused. Stop if we see PC within jmpdefer
- // to avoid that confusion.
- // See golang.org/issue/8153.
- // This check can be deleted if jmpdefer is changed
- // to restore all three atomically using pop.
- if(callback != nil)
- runtime·throw("traceback_arm: found jmpdefer when tracing with callback");
- frame.lr = 0;
- flr = nil;
- } else {
- if((n == 0 && frame.sp < frame.fp) || frame.lr == 0)
- frame.lr = *(uintptr*)frame.sp;
- flr = runtime·findfunc(frame.lr);
- if(flr == nil) {
- // This happens if you get a profiling interrupt at just the wrong time.
- // In that context it is okay to stop early.
- // But if callback is set, we're doing a garbage collection and must
- // get everything, so crash loudly.
- if(callback != nil) {
- runtime·printf("runtime: unexpected return pc for %s called from %p\n", runtime·funcname(f), frame.lr);
- runtime·throw("unknown caller pc");
- }
- }
- }
-
- frame.varp = (byte*)frame.fp;
-
- // Derive size of arguments.
- // Most functions have a fixed-size argument block,
- // so we can use metadata about the function f.
- // Not all, though: there are some variadic functions
- // in package runtime and reflect, and for those we use call-specific
- // metadata recorded by f's caller.
- if(callback != nil || printing) {
- frame.argp = (byte*)frame.fp + sizeof(uintptr);
- if(f->args != ArgsSizeUnknown)
- frame.arglen = f->args;
- else if(flr == nil)
- frame.arglen = 0;
- else if(frame.lr == (uintptr)runtime·lessstack)
- frame.arglen = stk->argsize;
- else if((i = runtime·funcarglen(flr, frame.lr)) >= 0)
- frame.arglen = i;
- else {
- runtime·printf("runtime: unknown argument frame size for %s called from %p [%s]\n",
- runtime·funcname(f), frame.lr, flr ? runtime·funcname(flr) : "?");
- if(callback != nil)
- runtime·throw("invalid stack");
- frame.arglen = 0;
- }
- }
-
- // Determine function SP where deferproc would find its arguments.
- // On ARM that's just the standard bottom-of-stack plus 1 word for
- // the saved LR. If the previous frame was a direct call to newproc/deferproc,
- // however, the SP is three words lower than normal.
- // If the function has no frame at all - perhaps it just started, or perhaps
- // it is a leaf with no local variables - then we cannot possibly find its
- // SP in a defer, and we might confuse its SP for its caller's SP, so
- // set sparg=0 in that case.
- sparg = 0;
- if(frame.fp != frame.sp) {
- sparg = frame.sp + sizeof(uintreg);
- if(wasnewproc)
- sparg += 3*sizeof(uintreg);
- }
-
- // Determine frame's 'continuation PC', where it can continue.
- // Normally this is the return address on the stack, but if sigpanic
- // is immediately below this function on the stack, then the frame
- // stopped executing due to a trap, and frame.pc is probably not
- // a safe point for looking up liveness information. In this panicking case,
- // the function either doesn't return at all (if it has no defers or if the
- // defers do not recover) or it returns from one of the calls to
- // deferproc a second time (if the corresponding deferred func recovers).
- // It suffices to assume that the most recent deferproc is the one that
- // returns; everything live at earlier deferprocs is still live at that one.
- frame.continpc = frame.pc;
- if(waspanic) {
- if(panic != nil && panic->defer->argp == (byte*)sparg)
- frame.continpc = (uintptr)panic->defer->pc;
- else if(defer != nil && defer->argp == (byte*)sparg)
- frame.continpc = (uintptr)defer->pc;
- else
- frame.continpc = 0;
- }
-
- // Unwind our local panic & defer stacks past this frame.
- while(panic != nil && (panic->defer == nil || panic->defer->argp == (byte*)sparg || panic->defer->argp == NoArgs))
- panic = panic->link;
- while(defer != nil && (defer->argp == (byte*)sparg || defer->argp == NoArgs))
- defer = defer->link;
-
- if(skip > 0) {
- skip--;
- goto skipped;
- }
-
- if(pcbuf != nil)
- pcbuf[n] = frame.pc;
- if(callback != nil) {
- if(!callback(&frame, v))
- return n;
- }
- if(printing) {
- if(printall || runtime·showframe(f, gp)) {
- // Print during crash.
- // main(0x1, 0x2, 0x3)
- // /home/rsc/go/src/runtime/x.go:23 +0xf
- tracepc = frame.pc; // back up to CALL instruction for funcline.
- if(n > 0 && frame.pc > f->entry && !waspanic)
- tracepc -= sizeof(uintptr);
- runtime·printf("%s(", runtime·funcname(f));
- for(i = 0; i < frame.arglen/sizeof(uintptr); i++) {
- if(i >= 10) {
- runtime·prints(", ...");
- break;
- }
- if(i != 0)
- runtime·prints(", ");
- runtime·printhex(((uintptr*)frame.argp)[i]);
- }
- runtime·prints(")\n");
- line = runtime·funcline(f, tracepc, &file);
- runtime·printf("\t%S:%d", file, line);
- if(frame.pc > f->entry)
- runtime·printf(" +%p", (uintptr)(frame.pc - f->entry));
- if(m->throwing > 0 && gp == m->curg || gotraceback >= 2)
- runtime·printf(" fp=%p sp=%p", frame.fp, frame.sp);
- runtime·printf("\n");
- nprint++;
- }
- }
- n++;
-
- skipped:
- waspanic = f->entry == (uintptr)runtime·sigpanic;
- wasnewproc = f->entry == (uintptr)runtime·newproc || f->entry == (uintptr)runtime·deferproc;
-
- // Do not unwind past the bottom of the stack.
- if(flr == nil)
- break;
-
- // Unwind to next frame.
- frame.pc = frame.lr;
- frame.fn = flr;
- frame.lr = 0;
- frame.sp = frame.fp;
- frame.fp = 0;
-
- // sighandler saves the lr on stack before faking a call to sigpanic
- if(waspanic) {
- x = *(uintptr*)frame.sp;
- frame.sp += 4;
- frame.fn = f = runtime·findfunc(frame.pc);
- if(f == nil)
- frame.pc = x;
- else if(f->frame == 0)
- frame.lr = x;
- }
- }
-
- if(pcbuf == nil && callback == nil)
- n = nprint;
-
- // For rationale, see long comment in traceback_x86.c.
- if(callback != nil && n < max && defer != nil) {
- if(defer != nil)
- runtime·printf("runtime: g%D: leftover defer argp=%p pc=%p\n", gp->goid, defer->argp, defer->pc);
- if(panic != nil)
- runtime·printf("runtime: g%D: leftover panic argp=%p pc=%p\n", gp->goid, panic->defer->argp, panic->defer->pc);
- for(defer = gp->defer; defer != nil; defer = defer->link)
- runtime·printf("\tdefer %p argp=%p pc=%p\n", defer, defer->argp, defer->pc);
- for(panic = gp->panic; panic != nil; panic = panic->link) {
- runtime·printf("\tpanic %p defer %p", panic, panic->defer);
- if(panic->defer != nil)
- runtime·printf(" argp=%p pc=%p", panic->defer->argp, panic->defer->pc);
- runtime·printf("\n");
- }
- runtime·throw("traceback has leftover defers or panics");
- }
-
- return n;
-}
-
-void
-runtime·printcreatedby(G *gp)
-{
- int32 line;
- uintptr pc, tracepc;
- Func *f;
- String file;
-
- // Show what created goroutine, except main goroutine (goid 1).
- if((pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil &&
- runtime·showframe(f, gp) && gp->goid != 1) {
- runtime·printf("created by %s\n", runtime·funcname(f));
- tracepc = pc; // back up to CALL instruction for funcline.
- if(pc > f->entry)
- tracepc -= PCQuantum;
- line = runtime·funcline(f, tracepc, &file);
- runtime·printf("\t%S:%d", file, line);
- if(pc > f->entry)
- runtime·printf(" +%p", (uintptr)(pc - f->entry));
- runtime·printf("\n");
- }
-}
-
-void
-runtime·traceback(uintptr pc, uintptr sp, uintptr lr, G *gp)
-{
- int32 n;
-
- if(gp->status == Gsyscall) {
- // Override signal registers if blocked in system call.
- pc = gp->syscallpc;
- sp = gp->syscallsp;
- lr = 0;
- }
-
- // Print traceback. By default, omits runtime frames.
- // If that means we print nothing at all, repeat forcing all frames printed.
- n = runtime·gentraceback(pc, sp, lr, gp, 0, nil, TracebackMaxFrames, nil, nil, false);
- if(n == 0)
- runtime·gentraceback(pc, sp, lr, gp, 0, nil, TracebackMaxFrames, nil, nil, true);
- if(n == TracebackMaxFrames)
- runtime·printf("...additional frames elided...\n");
- runtime·printcreatedby(gp);
-}
-
-// func caller(n int) (pc uintptr, file string, line int, ok bool)
-int32
-runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
-{
- uintptr pc, sp;
-
- sp = runtime·getcallersp(&skip);
- pc = (uintptr)runtime·getcallerpc(&skip);
-
- return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m, nil, nil, false);
-}
diff --git a/src/pkg/runtime/traceback_x86.c b/src/pkg/runtime/traceback_x86.c
deleted file mode 100644
index 7359cfcc9..000000000
--- a/src/pkg/runtime/traceback_x86.c
+++ /dev/null
@@ -1,430 +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 386
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "funcdata.h"
-#ifdef GOOS_windows
-#include "defs_GOOS_GOARCH.h"
-#endif
-
-void runtime·sigpanic(void);
-void runtime·newproc(void);
-void runtime·deferproc(void);
-
-#ifdef GOOS_windows
-void runtime·sigtramp(void);
-#endif
-
-// This code is also used for the 386 tracebacks.
-// Use uintptr for an appropriate word-sized integer.
-
-// Generic traceback. Handles runtime stack prints (pcbuf == nil),
-// the runtime.Callers function (pcbuf != nil), as well as the garbage
-// collector (callback != nil). A little clunky to merge these, but avoids
-// duplicating the code and all its subtlety.
-int32
-runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, bool (*callback)(Stkframe*, void*), void *v, bool printall)
-{
- int32 i, n, nprint, line, gotraceback;
- uintptr tracepc, sparg;
- bool waspanic, wasnewproc, printing;
- Func *f, *flr;
- Stkframe frame;
- Stktop *stk;
- String file;
- Panic *panic;
- Defer *defer;
-
- USED(lr0);
-
- gotraceback = runtime·gotraceback(nil);
-
- if(pc0 == ~(uintptr)0 && sp0 == ~(uintptr)0) { // Signal to fetch saved values from gp.
- if(gp->syscallstack != (uintptr)nil) {
- pc0 = gp->syscallpc;
- sp0 = gp->syscallsp;
- } else {
- pc0 = gp->sched.pc;
- sp0 = gp->sched.sp;
- }
- }
-
- nprint = 0;
- runtime·memclr((byte*)&frame, sizeof frame);
- frame.pc = pc0;
- frame.sp = sp0;
- waspanic = false;
- wasnewproc = false;
- printing = pcbuf==nil && callback==nil;
- panic = gp->panic;
- defer = gp->defer;
-
- while(defer != nil && defer->argp == NoArgs)
- defer = defer->link;
- while(panic != nil && panic->defer == nil)
- panic = panic->link;
-
- // If the PC is zero, it's likely a nil function call.
- // Start in the caller's frame.
- if(frame.pc == 0) {
- frame.pc = *(uintptr*)frame.sp;
- frame.sp += sizeof(uintreg);
- }
-
- f = runtime·findfunc(frame.pc);
- if(f == nil) {
- if(callback != nil) {
- runtime·printf("runtime: unknown pc %p\n", frame.pc);
- runtime·throw("unknown pc");
- }
- return 0;
- }
- frame.fn = f;
-
- n = 0;
- stk = (Stktop*)gp->stackbase;
- while(n < max) {
- // Typically:
- // pc is the PC of the running function.
- // sp is the stack pointer at that program counter.
- // fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown.
- // stk is the stack containing sp.
- // The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp.
-
- if(frame.pc == (uintptr)runtime·lessstack) {
- // Hit top of stack segment. Unwind to next segment.
- frame.pc = stk->gobuf.pc;
- frame.sp = stk->gobuf.sp;
- frame.lr = 0;
- frame.fp = 0;
- frame.fn = nil;
- if(printing && runtime·showframe(nil, gp))
- runtime·printf("----- stack segment boundary -----\n");
- stk = (Stktop*)stk->stackbase;
-
- f = runtime·findfunc(frame.pc);
- if(f == nil) {
- runtime·printf("runtime: unknown pc %p after stack split\n", frame.pc);
- if(callback != nil)
- runtime·throw("unknown pc");
- }
- frame.fn = f;
- continue;
- }
-
- f = frame.fn;
-
-#ifdef GOOS_windows
- // Windows exception handlers run on the actual g stack (there is room
- // dedicated to this below the usual "bottom of stack"), not on a separate
- // stack. As a result, we have to be able to unwind past the exception
- // handler when called to unwind during stack growth inside the handler.
- // Recognize the frame at the call to sighandler in sigtramp and unwind
- // using the context argument passed to the call. This is awful.
- if(f != nil && f->entry == (uintptr)runtime·sigtramp && frame.pc > f->entry) {
- Context *r;
-
- // Invoke callback so that stack copier sees an uncopyable frame.
- if(callback != nil) {
- frame.continpc = frame.pc;
- frame.argp = nil;
- frame.arglen = 0;
- if(!callback(&frame, v))
- return n;
- }
- r = (Context*)((uintptr*)frame.sp)[1];
-#ifdef GOARCH_amd64
- frame.pc = r->Rip;
- frame.sp = r->Rsp;
-#else
- frame.pc = r->Eip;
- frame.sp = r->Esp;
-#endif
- frame.lr = 0;
- frame.fp = 0;
- frame.fn = nil;
- if(printing && runtime·showframe(nil, gp))
- runtime·printf("----- exception handler -----\n");
- f = runtime·findfunc(frame.pc);
- if(f == nil) {
- runtime·printf("runtime: unknown pc %p after exception handler\n", frame.pc);
- if(callback != nil)
- runtime·throw("unknown pc");
- }
- frame.fn = f;
- continue;
- }
-#endif
-
- // Found an actual function.
- // Derive frame pointer and link register.
- if(frame.fp == 0) {
- frame.fp = frame.sp + runtime·funcspdelta(f, frame.pc);
- frame.fp += sizeof(uintreg); // caller PC
- }
- if(runtime·topofstack(f)) {
- frame.lr = 0;
- flr = nil;
- } else {
- if(frame.lr == 0)
- frame.lr = ((uintreg*)frame.fp)[-1];
- flr = runtime·findfunc(frame.lr);
- if(flr == nil) {
- runtime·printf("runtime: unexpected return pc for %s called from %p\n", runtime·funcname(f), frame.lr);
- if(callback != nil)
- runtime·throw("unknown caller pc");
- }
- }
-
- frame.varp = (byte*)frame.fp - sizeof(uintreg);
-
- // Derive size of arguments.
- // Most functions have a fixed-size argument block,
- // so we can use metadata about the function f.
- // Not all, though: there are some variadic functions
- // in package runtime and reflect, and for those we use call-specific
- // metadata recorded by f's caller.
- if(callback != nil || printing) {
- frame.argp = (byte*)frame.fp;
- if(f->args != ArgsSizeUnknown)
- frame.arglen = f->args;
- else if(flr == nil)
- frame.arglen = 0;
- else if(frame.lr == (uintptr)runtime·lessstack)
- frame.arglen = stk->argsize;
- else if((i = runtime·funcarglen(flr, frame.lr)) >= 0)
- frame.arglen = i;
- else {
- runtime·printf("runtime: unknown argument frame size for %s called from %p [%s]\n",
- runtime·funcname(f), frame.lr, flr ? runtime·funcname(flr) : "?");
- if(callback != nil)
- runtime·throw("invalid stack");
- frame.arglen = 0;
- }
- }
-
- // Determine function SP where deferproc would find its arguments.
- // On x86 that's just the standard bottom-of-stack, so SP exactly.
- // If the previous frame was a direct call to newproc/deferproc, however,
- // the SP is two words lower than normal.
- sparg = frame.sp;
- if(wasnewproc)
- sparg += 2*sizeof(uintptr);
-
- // Determine frame's 'continuation PC', where it can continue.
- // Normally this is the return address on the stack, but if sigpanic
- // is immediately below this function on the stack, then the frame
- // stopped executing due to a trap, and frame.pc is probably not
- // a safe point for looking up liveness information. In this panicking case,
- // the function either doesn't return at all (if it has no defers or if the
- // defers do not recover) or it returns from one of the calls to
- // deferproc a second time (if the corresponding deferred func recovers).
- // It suffices to assume that the most recent deferproc is the one that
- // returns; everything live at earlier deferprocs is still live at that one.
- frame.continpc = frame.pc;
- if(waspanic) {
- if(panic != nil && panic->defer->argp == (byte*)sparg)
- frame.continpc = (uintptr)panic->defer->pc;
- else if(defer != nil && defer->argp == (byte*)sparg)
- frame.continpc = (uintptr)defer->pc;
- else
- frame.continpc = 0;
- }
-
- // Unwind our local panic & defer stacks past this frame.
- while(panic != nil && (panic->defer == nil || panic->defer->argp == (byte*)sparg || panic->defer->argp == NoArgs))
- panic = panic->link;
- while(defer != nil && (defer->argp == (byte*)sparg || defer->argp == NoArgs))
- defer = defer->link;
-
- if(skip > 0) {
- skip--;
- goto skipped;
- }
-
- if(pcbuf != nil)
- pcbuf[n] = frame.pc;
- if(callback != nil) {
- if(!callback(&frame, v))
- return n;
- }
- if(printing) {
- if(printall || runtime·showframe(f, gp)) {
- // Print during crash.
- // main(0x1, 0x2, 0x3)
- // /home/rsc/go/src/runtime/x.go:23 +0xf
- //
- tracepc = frame.pc; // back up to CALL instruction for funcline.
- if(n > 0 && frame.pc > f->entry && !waspanic)
- tracepc--;
- runtime·printf("%s(", runtime·funcname(f));
- for(i = 0; i < frame.arglen/sizeof(uintptr); i++) {
- if(i >= 10) {
- runtime·prints(", ...");
- break;
- }
- if(i != 0)
- runtime·prints(", ");
- runtime·printhex(((uintptr*)frame.argp)[i]);
- }
- runtime·prints(")\n");
- line = runtime·funcline(f, tracepc, &file);
- runtime·printf("\t%S:%d", file, line);
- if(frame.pc > f->entry)
- runtime·printf(" +%p", (uintptr)(frame.pc - f->entry));
- if(m->throwing > 0 && gp == m->curg || gotraceback >= 2)
- runtime·printf(" fp=%p sp=%p", frame.fp, frame.sp);
- runtime·printf("\n");
- nprint++;
- }
- }
- n++;
-
- skipped:
- waspanic = f->entry == (uintptr)runtime·sigpanic;
- wasnewproc = f->entry == (uintptr)runtime·newproc || f->entry == (uintptr)runtime·deferproc;
-
- // Do not unwind past the bottom of the stack.
- if(flr == nil)
- break;
-
- // Unwind to next frame.
- frame.fn = flr;
- frame.pc = frame.lr;
- frame.lr = 0;
- frame.sp = frame.fp;
- frame.fp = 0;
- }
-
- if(pcbuf == nil && callback == nil)
- n = nprint;
-
- // If callback != nil, we're being called to gather stack information during
- // garbage collection or stack growth. In that context, require that we used
- // up the entire defer stack. If not, then there is a bug somewhere and the
- // garbage collection or stack growth may not have seen the correct picture
- // of the stack. Crash now instead of silently executing the garbage collection
- // or stack copy incorrectly and setting up for a mysterious crash later.
- //
- // Note that panic != nil is okay here: there can be leftover panics,
- // because the defers on the panic stack do not nest in frame order as
- // they do on the defer stack. If you have:
- //
- // frame 1 defers d1
- // frame 2 defers d2
- // frame 3 defers d3
- // frame 4 panics
- // frame 4's panic starts running defers
- // frame 5, running d3, defers d4
- // frame 5 panics
- // frame 5's panic starts running defers
- // frame 6, running d4, garbage collects
- // frame 6, running d2, garbage collects
- //
- // During the execution of d4, the panic stack is d4 -> d3, which
- // is nested properly, and we'll treat frame 3 as resumable, because we
- // can find d3. (And in fact frame 3 is resumable. If d4 recovers
- // and frame 5 continues running, d3, d3 can recover and we'll
- // resume execution in (returning from) frame 3.)
- //
- // During the execution of d2, however, the panic stack is d2 -> d3,
- // which is inverted. The scan will match d2 to frame 2 but having
- // d2 on the stack until then means it will not match d3 to frame 3.
- // This is okay: if we're running d2, then all the defers after d2 have
- // completed and their corresponding frames are dead. Not finding d3
- // for frame 3 means we'll set frame 3's continpc == 0, which is correct
- // (frame 3 is dead). At the end of the walk the panic stack can thus
- // contain defers (d3 in this case) for dead frames. The inversion here
- // always indicates a dead frame, and the effect of the inversion on the
- // scan is to hide those dead frames, so the scan is still okay:
- // what's left on the panic stack are exactly (and only) the dead frames.
- //
- // We require callback != nil here because only when callback != nil
- // do we know that gentraceback is being called in a "must be correct"
- // context as opposed to a "best effort" context. The tracebacks with
- // callbacks only happen when everything is stopped nicely.
- // At other times, such as when gathering a stack for a profiling signal
- // or when printing a traceback during a crash, everything may not be
- // stopped nicely, and the stack walk may not be able to complete.
- // It's okay in those situations not to use up the entire defer stack:
- // incomplete information then is still better than nothing.
- if(callback != nil && n < max && defer != nil) {
- if(defer != nil)
- runtime·printf("runtime: g%D: leftover defer argp=%p pc=%p\n", gp->goid, defer->argp, defer->pc);
- if(panic != nil)
- runtime·printf("runtime: g%D: leftover panic argp=%p pc=%p\n", gp->goid, panic->defer->argp, panic->defer->pc);
- for(defer = gp->defer; defer != nil; defer = defer->link)
- runtime·printf("\tdefer %p argp=%p pc=%p\n", defer, defer->argp, defer->pc);
- for(panic = gp->panic; panic != nil; panic = panic->link) {
- runtime·printf("\tpanic %p defer %p", panic, panic->defer);
- if(panic->defer != nil)
- runtime·printf(" argp=%p pc=%p", panic->defer->argp, panic->defer->pc);
- runtime·printf("\n");
- }
- runtime·throw("traceback has leftover defers or panics");
- }
-
- return n;
-}
-
-void
-runtime·printcreatedby(G *gp)
-{
- int32 line;
- uintptr pc, tracepc;
- Func *f;
- String file;
-
- // Show what created goroutine, except main goroutine (goid 1).
- if((pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil &&
- runtime·showframe(f, gp) && gp->goid != 1) {
- runtime·printf("created by %s\n", runtime·funcname(f));
- tracepc = pc; // back up to CALL instruction for funcline.
- if(pc > f->entry)
- tracepc -= PCQuantum;
- line = runtime·funcline(f, tracepc, &file);
- runtime·printf("\t%S:%d", file, line);
- if(pc > f->entry)
- runtime·printf(" +%p", (uintptr)(pc - f->entry));
- runtime·printf("\n");
- }
-}
-
-void
-runtime·traceback(uintptr pc, uintptr sp, uintptr lr, G *gp)
-{
- int32 n;
-
- USED(lr);
-
- if(gp->status == Gsyscall) {
- // Override signal registers if blocked in system call.
- pc = gp->syscallpc;
- sp = gp->syscallsp;
- }
-
- // Print traceback. By default, omits runtime frames.
- // If that means we print nothing at all, repeat forcing all frames printed.
- n = runtime·gentraceback(pc, sp, 0, gp, 0, nil, TracebackMaxFrames, nil, nil, false);
- if(n == 0)
- n = runtime·gentraceback(pc, sp, 0, gp, 0, nil, TracebackMaxFrames, nil, nil, true);
- if(n == TracebackMaxFrames)
- runtime·printf("...additional frames elided...\n");
- runtime·printcreatedby(gp);
-}
-
-int32
-runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
-{
- uintptr pc, sp;
-
- sp = runtime·getcallersp(&skip);
- pc = (uintptr)runtime·getcallerpc(&skip);
-
- return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m, nil, nil, false);
-}
diff --git a/src/pkg/runtime/type.go b/src/pkg/runtime/type.go
deleted file mode 100644
index 276dbc0c9..000000000
--- a/src/pkg/runtime/type.go
+++ /dev/null
@@ -1,56 +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.
-
-/*
- * Runtime type representation.
- * This file exists only to provide types that 6l can turn into
- * DWARF information for use by gdb. Nothing else uses these.
- * They should match the same types in ../reflect/type.go.
- * For comments see ../reflect/type.go.
- */
-
-package runtime
-
-import "unsafe"
-
-type rtype struct {
- size uintptr
- hash uint32
- _ uint8
- align uint8
- fieldAlign uint8
- kind uint8
- alg unsafe.Pointer
- gc unsafe.Pointer
- string *string
- *uncommonType
- ptrToThis *rtype
- zero unsafe.Pointer
-}
-
-type _method struct {
- name *string
- pkgPath *string
- mtyp *rtype
- typ *rtype
- ifn unsafe.Pointer
- tfn unsafe.Pointer
-}
-
-type uncommonType struct {
- name *string
- pkgPath *string
- methods []_method
-}
-
-type _imethod struct {
- name *string
- pkgPath *string
- typ *rtype
-}
-
-type interfaceType struct {
- rtype
- methods []_imethod
-}
diff --git a/src/pkg/runtime/vlrt_arm.c b/src/pkg/runtime/vlrt_arm.c
deleted file mode 100644
index 7dd71b40e..000000000
--- a/src/pkg/runtime/vlrt_arm.c
+++ /dev/null
@@ -1,807 +0,0 @@
-// Inferno's libkern/vlrt-arm.c
-// http://code.google.com/p/inferno-os/source/browse/libkern/vlrt-arm.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
-// 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 "../../cmd/ld/textflag.h"
-
-// declared here to avoid include of runtime.h
-void runtime·panicstring(char*);
-void runtime·panicdivide(void);
-
-typedef unsigned long ulong;
-typedef unsigned int uint;
-typedef unsigned short ushort;
-typedef unsigned char uchar;
-typedef signed char schar;
-
-#define SIGN(n) (1UL<<(n-1))
-
-typedef struct Vlong Vlong;
-struct Vlong
-{
- union
- {
- struct
- {
- ulong lo;
- ulong hi;
- };
- struct
- {
- ushort lols;
- ushort loms;
- ushort hils;
- ushort hims;
- };
- };
-};
-
-void runtime·abort(void);
-
-#pragma textflag NOSPLIT
-void
-_addv(Vlong *r, Vlong a, Vlong b)
-{
- r->lo = a.lo + b.lo;
- r->hi = a.hi + b.hi;
- if(r->lo < a.lo)
- r->hi++;
-}
-
-#pragma textflag NOSPLIT
-void
-_subv(Vlong *r, Vlong a, Vlong b)
-{
- r->lo = a.lo - b.lo;
- r->hi = a.hi - b.hi;
- if(r->lo > a.lo)
- r->hi--;
-}
-
-void
-_d2v(Vlong *y, double d)
-{
- union { double d; struct Vlong; } x;
- ulong xhi, xlo, ylo, yhi;
- int sh;
-
- x.d = d;
-
- xhi = (x.hi & 0xfffff) | 0x100000;
- xlo = x.lo;
- sh = 1075 - ((x.hi >> 20) & 0x7ff);
-
- ylo = 0;
- yhi = 0;
- if(sh >= 0) {
- /* v = (hi||lo) >> sh */
- if(sh < 32) {
- if(sh == 0) {
- ylo = xlo;
- yhi = xhi;
- } else {
- ylo = (xlo >> sh) | (xhi << (32-sh));
- yhi = xhi >> sh;
- }
- } else {
- if(sh == 32) {
- ylo = xhi;
- } else
- if(sh < 64) {
- ylo = xhi >> (sh-32);
- }
- }
- } else {
- /* v = (hi||lo) << -sh */
- sh = -sh;
- if(sh <= 11) {
- ylo = xlo << sh;
- yhi = (xhi << sh) | (xlo >> (32-sh));
- } else {
- /* overflow */
- yhi = d; /* causes something awful */
- }
- }
- if(x.hi & SIGN(32)) {
- if(ylo != 0) {
- ylo = -ylo;
- yhi = ~yhi;
- } else
- yhi = -yhi;
- }
-
- y->hi = yhi;
- y->lo = ylo;
-}
-
-void
-_f2v(Vlong *y, float f)
-{
- _d2v(y, f);
-}
-
-void
-runtime·float64toint64(double d, Vlong y)
-{
- _d2v(&y, d);
-}
-
-void
-runtime·float64touint64(double d, Vlong y)
-{
- _d2v(&y, d);
-}
-
-double
-_ul2d(ulong u)
-{
- // compensate for bug in c
- if(u & SIGN(32)) {
- u ^= SIGN(32);
- return 2147483648. + u;
- }
- return u;
-}
-
-double
-_v2d(Vlong x)
-{
- if(x.hi & SIGN(32)) {
- if(x.lo) {
- x.lo = -x.lo;
- x.hi = ~x.hi;
- } else
- x.hi = -x.hi;
- return -(_ul2d(x.hi)*4294967296. + _ul2d(x.lo));
- }
- return x.hi*4294967296. + _ul2d(x.lo);
-}
-
-float
-_v2f(Vlong x)
-{
- return _v2d(x);
-}
-
-void
-runtime·int64tofloat64(Vlong y, double d)
-{
- d = _v2d(y);
- USED(&d); // FLUSH
-}
-
-void
-runtime·uint64tofloat64(Vlong y, double d)
-{
- d = _ul2d(y.hi)*4294967296. + _ul2d(y.lo);
- USED(&d); // FLUSH
-}
-
-static void
-dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
-{
- ulong numlo, numhi, denhi, denlo, quohi, quolo, t;
- int i;
-
- numhi = num.hi;
- numlo = num.lo;
- denhi = den.hi;
- denlo = den.lo;
-
- /*
- * get a divide by zero
- */
- if(denlo==0 && denhi==0) {
- runtime·panicdivide();
- }
-
- /*
- * set up the divisor and find the number of iterations needed
- */
- if(numhi >= SIGN(32)) {
- quohi = SIGN(32);
- quolo = 0;
- } else {
- quohi = numhi;
- quolo = numlo;
- }
- i = 0;
- while(denhi < quohi || (denhi == quohi && denlo < quolo)) {
- denhi = (denhi<<1) | (denlo>>31);
- denlo <<= 1;
- i++;
- }
-
- quohi = 0;
- quolo = 0;
- for(; i >= 0; i--) {
- quohi = (quohi<<1) | (quolo>>31);
- quolo <<= 1;
- if(numhi > denhi || (numhi == denhi && numlo >= denlo)) {
- t = numlo;
- numlo -= denlo;
- if(numlo > t)
- numhi--;
- numhi -= denhi;
- quolo |= 1;
- }
- denlo = (denlo>>1) | (denhi<<31);
- denhi >>= 1;
- }
-
- if(q) {
- q->lo = quolo;
- q->hi = quohi;
- }
- if(r) {
- r->lo = numlo;
- r->hi = numhi;
- }
-}
-
-void
-_divvu(Vlong *q, Vlong n, Vlong d)
-{
-
- if(n.hi == 0 && d.hi == 0) {
- q->hi = 0;
- q->lo = n.lo / d.lo;
- return;
- }
- dodiv(n, d, q, 0);
-}
-
-void
-runtime·uint64div(Vlong n, Vlong d, Vlong q)
-{
- _divvu(&q, n, d);
-}
-
-void
-_modvu(Vlong *r, Vlong n, Vlong d)
-{
-
- if(n.hi == 0 && d.hi == 0) {
- r->hi = 0;
- r->lo = n.lo % d.lo;
- return;
- }
- dodiv(n, d, 0, r);
-}
-
-void
-runtime·uint64mod(Vlong n, Vlong d, Vlong q)
-{
- _modvu(&q, n, d);
-}
-
-static void
-vneg(Vlong *v)
-{
-
- if(v->lo == 0) {
- v->hi = -v->hi;
- return;
- }
- v->lo = -v->lo;
- v->hi = ~v->hi;
-}
-
-void
-_divv(Vlong *q, Vlong n, Vlong d)
-{
- long nneg, dneg;
-
- if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
- if((long)n.lo == -0x80000000 && (long)d.lo == -1) {
- // special case: 32-bit -0x80000000 / -1 causes wrong sign
- q->lo = 0x80000000;
- q->hi = 0;
- return;
- }
- q->lo = (long)n.lo / (long)d.lo;
- q->hi = ((long)q->lo) >> 31;
- return;
- }
- nneg = n.hi >> 31;
- if(nneg)
- vneg(&n);
- dneg = d.hi >> 31;
- if(dneg)
- vneg(&d);
- dodiv(n, d, q, 0);
- if(nneg != dneg)
- vneg(q);
-}
-
-void
-runtime·int64div(Vlong n, Vlong d, Vlong q)
-{
- _divv(&q, n, d);
-}
-
-void
-_modv(Vlong *r, Vlong n, Vlong d)
-{
- long nneg, dneg;
-
- if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
- r->lo = (long)n.lo % (long)d.lo;
- r->hi = ((long)r->lo) >> 31;
- return;
- }
- nneg = n.hi >> 31;
- if(nneg)
- vneg(&n);
- dneg = d.hi >> 31;
- if(dneg)
- vneg(&d);
- dodiv(n, d, 0, r);
- if(nneg)
- vneg(r);
-}
-
-void
-runtime·int64mod(Vlong n, Vlong d, Vlong q)
-{
- _modv(&q, n, d);
-}
-
-void
-_rshav(Vlong *r, Vlong a, int b)
-{
- long t;
-
- t = a.hi;
- if(b >= 32) {
- r->hi = t>>31;
- if(b >= 64) {
- /* this is illegal re C standard */
- r->lo = t>>31;
- return;
- }
- r->lo = t >> (b-32);
- return;
- }
- if(b <= 0) {
- r->hi = t;
- r->lo = a.lo;
- return;
- }
- r->hi = t >> b;
- r->lo = (t << (32-b)) | (a.lo >> b);
-}
-
-void
-_rshlv(Vlong *r, Vlong a, int b)
-{
- ulong t;
-
- t = a.hi;
- if(b >= 32) {
- r->hi = 0;
- if(b >= 64) {
- /* this is illegal re C standard */
- r->lo = 0;
- return;
- }
- r->lo = t >> (b-32);
- return;
- }
- if(b <= 0) {
- r->hi = t;
- r->lo = a.lo;
- return;
- }
- r->hi = t >> b;
- r->lo = (t << (32-b)) | (a.lo >> b);
-}
-
-#pragma textflag NOSPLIT
-void
-_lshv(Vlong *r, Vlong a, int b)
-{
- if(b >= 32) {
- r->lo = 0;
- if(b >= 64) {
- /* this is illegal re C standard */
- r->hi = 0;
- return;
- }
- r->hi = a.lo << (b-32);
- return;
- }
- if(b <= 0) {
- r->lo = a.lo;
- r->hi = a.hi;
- return;
- }
- r->lo = a.lo << b;
- r->hi = (a.lo >> (32-b)) | (a.hi << b);
-}
-
-void
-_andv(Vlong *r, Vlong a, Vlong b)
-{
- r->hi = a.hi & b.hi;
- r->lo = a.lo & b.lo;
-}
-
-void
-_orv(Vlong *r, Vlong a, Vlong b)
-{
- r->hi = a.hi | b.hi;
- r->lo = a.lo | b.lo;
-}
-
-void
-_xorv(Vlong *r, Vlong a, Vlong b)
-{
- r->hi = a.hi ^ b.hi;
- r->lo = a.lo ^ b.lo;
-}
-
-void
-_vpp(Vlong *l, Vlong *r)
-{
-
- l->hi = r->hi;
- l->lo = r->lo;
- r->lo++;
- if(r->lo == 0)
- r->hi++;
-}
-
-void
-_vmm(Vlong *l, Vlong *r)
-{
-
- l->hi = r->hi;
- l->lo = r->lo;
- if(r->lo == 0)
- r->hi--;
- r->lo--;
-}
-
-void
-_ppv(Vlong *l, Vlong *r)
-{
-
- r->lo++;
- if(r->lo == 0)
- r->hi++;
- l->hi = r->hi;
- l->lo = r->lo;
-}
-
-void
-_mmv(Vlong *l, Vlong *r)
-{
-
- if(r->lo == 0)
- r->hi--;
- r->lo--;
- l->hi = r->hi;
- l->lo = r->lo;
-}
-
-void
-_vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
-{
- Vlong t, u;
-
- u = *ret;
- switch(type) {
- default:
- runtime·abort();
- break;
-
- case 1: /* schar */
- t.lo = *(schar*)lv;
- t.hi = t.lo >> 31;
- fn(&u, t, rv);
- *(schar*)lv = u.lo;
- break;
-
- case 2: /* uchar */
- t.lo = *(uchar*)lv;
- t.hi = 0;
- fn(&u, t, rv);
- *(uchar*)lv = u.lo;
- break;
-
- case 3: /* short */
- t.lo = *(short*)lv;
- t.hi = t.lo >> 31;
- fn(&u, t, rv);
- *(short*)lv = u.lo;
- break;
-
- case 4: /* ushort */
- t.lo = *(ushort*)lv;
- t.hi = 0;
- fn(&u, t, rv);
- *(ushort*)lv = u.lo;
- break;
-
- case 9: /* int */
- t.lo = *(int*)lv;
- t.hi = t.lo >> 31;
- fn(&u, t, rv);
- *(int*)lv = u.lo;
- break;
-
- case 10: /* uint */
- t.lo = *(uint*)lv;
- t.hi = 0;
- fn(&u, t, rv);
- *(uint*)lv = u.lo;
- break;
-
- case 5: /* long */
- t.lo = *(long*)lv;
- t.hi = t.lo >> 31;
- fn(&u, t, rv);
- *(long*)lv = u.lo;
- break;
-
- case 6: /* ulong */
- t.lo = *(ulong*)lv;
- t.hi = 0;
- fn(&u, t, rv);
- *(ulong*)lv = u.lo;
- break;
-
- case 7: /* vlong */
- case 8: /* uvlong */
- fn(&u, *(Vlong*)lv, rv);
- *(Vlong*)lv = u;
- break;
- }
- *ret = u;
-}
-
-void
-_p2v(Vlong *ret, void *p)
-{
- long t;
-
- t = (ulong)p;
- ret->lo = t;
- ret->hi = 0;
-}
-
-void
-_sl2v(Vlong *ret, long sl)
-{
- long t;
-
- t = sl;
- ret->lo = t;
- ret->hi = t >> 31;
-}
-
-void
-_ul2v(Vlong *ret, ulong ul)
-{
- long t;
-
- t = ul;
- ret->lo = t;
- ret->hi = 0;
-}
-
-#pragma textflag NOSPLIT
-void
-_si2v(Vlong *ret, int si)
-{
- ret->lo = (long)si;
- ret->hi = (long)si >> 31;
-}
-
-void
-_ui2v(Vlong *ret, uint ui)
-{
- long t;
-
- t = ui;
- ret->lo = t;
- ret->hi = 0;
-}
-
-void
-_sh2v(Vlong *ret, long sh)
-{
- long t;
-
- t = (sh << 16) >> 16;
- ret->lo = t;
- ret->hi = t >> 31;
-}
-
-void
-_uh2v(Vlong *ret, ulong ul)
-{
- long t;
-
- t = ul & 0xffff;
- ret->lo = t;
- ret->hi = 0;
-}
-
-void
-_sc2v(Vlong *ret, long uc)
-{
- long t;
-
- t = (uc << 24) >> 24;
- ret->lo = t;
- ret->hi = t >> 31;
-}
-
-void
-_uc2v(Vlong *ret, ulong ul)
-{
- long t;
-
- t = ul & 0xff;
- ret->lo = t;
- ret->hi = 0;
-}
-
-long
-_v2sc(Vlong rv)
-{
- long t;
-
- t = rv.lo & 0xff;
- return (t << 24) >> 24;
-}
-
-long
-_v2uc(Vlong rv)
-{
-
- return rv.lo & 0xff;
-}
-
-long
-_v2sh(Vlong rv)
-{
- long t;
-
- t = rv.lo & 0xffff;
- return (t << 16) >> 16;
-}
-
-long
-_v2uh(Vlong rv)
-{
-
- return rv.lo & 0xffff;
-}
-
-long
-_v2sl(Vlong rv)
-{
-
- return rv.lo;
-}
-
-long
-_v2ul(Vlong rv)
-{
-
- return rv.lo;
-}
-
-#pragma textflag NOSPLIT
-long
-_v2si(Vlong rv)
-{
-
- return rv.lo;
-}
-
-long
-_v2ui(Vlong rv)
-{
-
- return rv.lo;
-}
-
-int
-_testv(Vlong rv)
-{
- return rv.lo || rv.hi;
-}
-
-int
-_eqv(Vlong lv, Vlong rv)
-{
- return lv.lo == rv.lo && lv.hi == rv.hi;
-}
-
-int
-_nev(Vlong lv, Vlong rv)
-{
- return lv.lo != rv.lo || lv.hi != rv.hi;
-}
-
-int
-_ltv(Vlong lv, Vlong rv)
-{
- return (long)lv.hi < (long)rv.hi ||
- (lv.hi == rv.hi && lv.lo < rv.lo);
-}
-
-int
-_lev(Vlong lv, Vlong rv)
-{
- return (long)lv.hi < (long)rv.hi ||
- (lv.hi == rv.hi && lv.lo <= rv.lo);
-}
-
-int
-_gtv(Vlong lv, Vlong rv)
-{
- return (long)lv.hi > (long)rv.hi ||
- (lv.hi == rv.hi && lv.lo > rv.lo);
-}
-
-#pragma textflag NOSPLIT
-int
-_gev(Vlong lv, Vlong rv)
-{
- return (long)lv.hi > (long)rv.hi ||
- (lv.hi == rv.hi && lv.lo >= rv.lo);
-}
-
-int
-_lov(Vlong lv, Vlong rv)
-{
- return lv.hi < rv.hi ||
- (lv.hi == rv.hi && lv.lo < rv.lo);
-}
-
-int
-_lsv(Vlong lv, Vlong rv)
-{
- return lv.hi < rv.hi ||
- (lv.hi == rv.hi && lv.lo <= rv.lo);
-}
-
-int
-_hiv(Vlong lv, Vlong rv)
-{
- return lv.hi > rv.hi ||
- (lv.hi == rv.hi && lv.lo > rv.lo);
-}
-
-int
-_hsv(Vlong lv, Vlong rv)
-{
- return lv.hi > rv.hi ||
- (lv.hi == rv.hi && lv.lo >= rv.lo);
-}
diff --git a/src/pkg/sync/atomic/race.go b/src/pkg/sync/atomic/race.go
deleted file mode 100644
index 6cbbf12cb..000000000
--- a/src/pkg/sync/atomic/race.go
+++ /dev/null
@@ -1,276 +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 race
-
-package atomic
-
-import (
- "runtime"
- "unsafe"
-)
-
-// We use runtime.RaceRead() inside of atomic operations to catch races
-// between atomic and non-atomic operations. It will also catch races
-// between Mutex.Lock() and mutex overwrite (mu = Mutex{}). Since we use
-// only RaceRead() we won't catch races with non-atomic loads.
-// Otherwise (if we use RaceWrite()) we will report races
-// between atomic operations (false positives).
-
-var mtx uint32 = 1 // same for all
-
-func SwapInt32(addr *int32, new int32) (old int32) {
- return int32(SwapUint32((*uint32)(unsafe.Pointer(addr)), uint32(new)))
-}
-
-func SwapUint32(addr *uint32, new uint32) (old uint32) {
- _ = *addr
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(addr))
- runtime.RaceAcquire(unsafe.Pointer(addr))
- old = *addr
- *addr = new
- runtime.RaceReleaseMerge(unsafe.Pointer(addr))
- runtime.RaceSemrelease(&mtx)
- return
-}
-
-func SwapInt64(addr *int64, new int64) (old int64) {
- return int64(SwapUint64((*uint64)(unsafe.Pointer(addr)), uint64(new)))
-}
-
-func SwapUint64(addr *uint64, new uint64) (old uint64) {
- _ = *addr
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(addr))
- runtime.RaceAcquire(unsafe.Pointer(addr))
- old = *addr
- *addr = new
- runtime.RaceReleaseMerge(unsafe.Pointer(addr))
- runtime.RaceSemrelease(&mtx)
- return
-}
-
-func SwapUintptr(addr *uintptr, new uintptr) (old uintptr) {
- return uintptr(SwapPointer((*unsafe.Pointer)(unsafe.Pointer(addr)), unsafe.Pointer(new)))
-}
-
-func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer) {
- _ = *addr
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(addr))
- runtime.RaceAcquire(unsafe.Pointer(addr))
- old = *addr
- *addr = new
- runtime.RaceReleaseMerge(unsafe.Pointer(addr))
- runtime.RaceSemrelease(&mtx)
- return
-}
-
-func CompareAndSwapInt32(val *int32, old, new int32) bool {
- return CompareAndSwapUint32((*uint32)(unsafe.Pointer(val)), uint32(old), uint32(new))
-}
-
-func CompareAndSwapUint32(val *uint32, old, new uint32) (swapped bool) {
- _ = *val
- swapped = false
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(val))
- runtime.RaceAcquire(unsafe.Pointer(val))
- if *val == old {
- *val = new
- swapped = true
- runtime.RaceReleaseMerge(unsafe.Pointer(val))
- }
- runtime.RaceSemrelease(&mtx)
- return
-}
-
-func CompareAndSwapInt64(val *int64, old, new int64) bool {
- return CompareAndSwapUint64((*uint64)(unsafe.Pointer(val)), uint64(old), uint64(new))
-}
-
-func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool) {
- _ = *val
- swapped = false
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(val))
- runtime.RaceAcquire(unsafe.Pointer(val))
- if *val == old {
- *val = new
- swapped = true
- runtime.RaceReleaseMerge(unsafe.Pointer(val))
- }
- runtime.RaceSemrelease(&mtx)
- return
-}
-
-func CompareAndSwapPointer(val *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) {
- _ = *val
- swapped = false
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(val))
- runtime.RaceAcquire(unsafe.Pointer(val))
- if *val == old {
- *val = new
- swapped = true
- runtime.RaceReleaseMerge(unsafe.Pointer(val))
- }
- runtime.RaceSemrelease(&mtx)
- return
-}
-
-func CompareAndSwapUintptr(val *uintptr, old, new uintptr) (swapped bool) {
- _ = *val
- swapped = false
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(val))
- runtime.RaceAcquire(unsafe.Pointer(val))
- if *val == old {
- *val = new
- swapped = true
- runtime.RaceReleaseMerge(unsafe.Pointer(val))
- }
- runtime.RaceSemrelease(&mtx)
- return
-}
-
-func AddInt32(val *int32, delta int32) int32 {
- return int32(AddUint32((*uint32)(unsafe.Pointer(val)), uint32(delta)))
-}
-
-func AddUint32(val *uint32, delta uint32) (new uint32) {
- _ = *val
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(val))
- runtime.RaceAcquire(unsafe.Pointer(val))
- *val = *val + delta
- new = *val
- runtime.RaceReleaseMerge(unsafe.Pointer(val))
- runtime.RaceSemrelease(&mtx)
-
- return
-}
-
-func AddInt64(val *int64, delta int64) int64 {
- return int64(AddUint64((*uint64)(unsafe.Pointer(val)), uint64(delta)))
-}
-
-func AddUint64(val *uint64, delta uint64) (new uint64) {
- _ = *val
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(val))
- runtime.RaceAcquire(unsafe.Pointer(val))
- *val = *val + delta
- new = *val
- runtime.RaceReleaseMerge(unsafe.Pointer(val))
- runtime.RaceSemrelease(&mtx)
-
- return
-}
-
-func AddUintptr(val *uintptr, delta uintptr) (new uintptr) {
- _ = *val
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(val))
- runtime.RaceAcquire(unsafe.Pointer(val))
- *val = *val + delta
- new = *val
- runtime.RaceReleaseMerge(unsafe.Pointer(val))
- runtime.RaceSemrelease(&mtx)
-
- return
-}
-
-func LoadInt32(addr *int32) int32 {
- return int32(LoadUint32((*uint32)(unsafe.Pointer(addr))))
-}
-
-func LoadUint32(addr *uint32) (val uint32) {
- _ = *addr
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(addr))
- runtime.RaceAcquire(unsafe.Pointer(addr))
- val = *addr
- runtime.RaceSemrelease(&mtx)
- return
-}
-
-func LoadInt64(addr *int64) int64 {
- return int64(LoadUint64((*uint64)(unsafe.Pointer(addr))))
-}
-
-func LoadUint64(addr *uint64) (val uint64) {
- _ = *addr
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(addr))
- runtime.RaceAcquire(unsafe.Pointer(addr))
- val = *addr
- runtime.RaceSemrelease(&mtx)
- return
-}
-
-func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) {
- _ = *addr
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(addr))
- runtime.RaceAcquire(unsafe.Pointer(addr))
- val = *addr
- runtime.RaceSemrelease(&mtx)
- return
-}
-
-func LoadUintptr(addr *uintptr) (val uintptr) {
- _ = *addr
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(addr))
- runtime.RaceAcquire(unsafe.Pointer(addr))
- val = *addr
- runtime.RaceSemrelease(&mtx)
- return
-}
-
-func StoreInt32(addr *int32, val int32) {
- StoreUint32((*uint32)(unsafe.Pointer(addr)), uint32(val))
-}
-
-func StoreUint32(addr *uint32, val uint32) {
- _ = *addr
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(addr))
- *addr = val
- runtime.RaceRelease(unsafe.Pointer(addr))
- runtime.RaceSemrelease(&mtx)
-}
-
-func StoreInt64(addr *int64, val int64) {
- StoreUint64((*uint64)(unsafe.Pointer(addr)), uint64(val))
-}
-
-func StoreUint64(addr *uint64, val uint64) {
- _ = *addr
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(addr))
- *addr = val
- runtime.RaceRelease(unsafe.Pointer(addr))
- runtime.RaceSemrelease(&mtx)
-}
-
-func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) {
- _ = *addr
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(addr))
- *addr = val
- runtime.RaceRelease(unsafe.Pointer(addr))
- runtime.RaceSemrelease(&mtx)
-}
-
-func StoreUintptr(addr *uintptr, val uintptr) {
- _ = *addr
- runtime.RaceSemacquire(&mtx)
- runtime.RaceRead(unsafe.Pointer(addr))
- *addr = val
- runtime.RaceRelease(unsafe.Pointer(addr))
- runtime.RaceSemrelease(&mtx)
-}
diff --git a/src/pkg/syscall/asm_windows_386.s b/src/pkg/syscall/asm_windows_386.s
deleted file mode 100644
index 8b52fa985..000000000
--- a/src/pkg/syscall/asm_windows_386.s
+++ /dev/null
@@ -1,7 +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.
-
-//
-// System calls for 386, Windows are implemented in ../runtime/syscall_windows.goc
-//
diff --git a/src/pkg/syscall/asm_windows_amd64.s b/src/pkg/syscall/asm_windows_amd64.s
deleted file mode 100644
index 5813404d1..000000000
--- a/src/pkg/syscall/asm_windows_amd64.s
+++ /dev/null
@@ -1,7 +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.
-
-//
-// System calls for amd64, Windows are implemented in ../runtime/syscall_windows.goc
-//
diff --git a/src/pkg/syscall/mkall_windows.bat b/src/pkg/syscall/mkall_windows.bat
deleted file mode 100644
index a4a3f1674..000000000
--- a/src/pkg/syscall/mkall_windows.bat
+++ /dev/null
@@ -1,21 +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.
-@echo off
-
-if exist mkall.sh goto dirok
-echo mkall_windows.bat must be run from src\pkg\syscall directory
-goto :end
-:dirok
-
-if "%1"=="386" goto :paramok
-if "%1"=="amd64" goto :paramok
-echo parameters must be 386 or amd64
-goto :end
-:paramok
-
-go build mksyscall_windows.go
-.\mksyscall_windows syscall_windows.go security_windows.go syscall_windows_%1.go |gofmt >zsyscall_windows_%1.go
-del mksyscall_windows.exe
-
-:end \ No newline at end of file
diff --git a/src/pkg/syscall/syscall_plan9_386.go b/src/pkg/syscall/syscall_plan9_386.go
deleted file mode 100644
index 7357e0ba6..000000000
--- a/src/pkg/syscall/syscall_plan9_386.go
+++ /dev/null
@@ -1,32 +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 syscall
-
-func Getpagesize() int { return 0x1000 }
-
-func nanotime() (nsec int64, err error) {
- // TODO(paulzhol):
- // avoid reopening a file descriptor for /dev/bintime on each call,
- // use lower-level calls to avoid allocation.
-
- var b [8]byte
- nsec = -1
-
- fd, err := Open("/dev/bintime", O_RDONLY)
- if err != nil {
- return
- }
- defer Close(fd)
-
- if _, err = Pread(fd, b[:], 0); err != nil {
- return
- }
-
- if nsec, err = DecodeBintime(b[:]); err != nil {
- return -1, err
- }
-
- return
-}
diff --git a/src/pkg/syscall/syscall_plan9_amd64.go b/src/pkg/syscall/syscall_plan9_amd64.go
deleted file mode 100644
index 9387db3e5..000000000
--- a/src/pkg/syscall/syscall_plan9_amd64.go
+++ /dev/null
@@ -1,14 +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 syscall
-
-func Getpagesize() int { return 0x200000 }
-
-// Used by Gettimeofday, which expects
-// an error return value.
-func nanotime() (int64, error) {
- r1, _, _ := RawSyscall(SYS_NANOTIME, 0, 0, 0)
- return int64(r1), nil
-}
diff --git a/src/pkg/syscall/zsyscall_windows_386.go b/src/pkg/syscall/zsyscall_windows_386.go
deleted file mode 100644
index 132adafef..000000000
--- a/src/pkg/syscall/zsyscall_windows_386.go
+++ /dev/null
@@ -1,1760 +0,0 @@
-// go build mksyscall_windows.go && ./mksyscall_windows syscall_windows.go security_windows.go syscall_windows_386.go
-// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
-
-package syscall
-
-import "unsafe"
-
-var (
- modkernel32 = NewLazyDLL("kernel32.dll")
- modadvapi32 = NewLazyDLL("advapi32.dll")
- modshell32 = NewLazyDLL("shell32.dll")
- modmswsock = NewLazyDLL("mswsock.dll")
- modcrypt32 = NewLazyDLL("crypt32.dll")
- modws2_32 = NewLazyDLL("ws2_32.dll")
- moddnsapi = NewLazyDLL("dnsapi.dll")
- modiphlpapi = NewLazyDLL("iphlpapi.dll")
- modsecur32 = NewLazyDLL("secur32.dll")
- modnetapi32 = NewLazyDLL("netapi32.dll")
- moduserenv = NewLazyDLL("userenv.dll")
-
- procGetLastError = modkernel32.NewProc("GetLastError")
- procLoadLibraryW = modkernel32.NewProc("LoadLibraryW")
- procFreeLibrary = modkernel32.NewProc("FreeLibrary")
- procGetProcAddress = modkernel32.NewProc("GetProcAddress")
- procGetVersion = modkernel32.NewProc("GetVersion")
- procFormatMessageW = modkernel32.NewProc("FormatMessageW")
- procExitProcess = modkernel32.NewProc("ExitProcess")
- procCreateFileW = modkernel32.NewProc("CreateFileW")
- procReadFile = modkernel32.NewProc("ReadFile")
- procWriteFile = modkernel32.NewProc("WriteFile")
- procSetFilePointer = modkernel32.NewProc("SetFilePointer")
- procCloseHandle = modkernel32.NewProc("CloseHandle")
- procGetStdHandle = modkernel32.NewProc("GetStdHandle")
- procFindFirstFileW = modkernel32.NewProc("FindFirstFileW")
- procFindNextFileW = modkernel32.NewProc("FindNextFileW")
- procFindClose = modkernel32.NewProc("FindClose")
- procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle")
- procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW")
- procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW")
- procCreateDirectoryW = modkernel32.NewProc("CreateDirectoryW")
- procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW")
- procDeleteFileW = modkernel32.NewProc("DeleteFileW")
- procMoveFileW = modkernel32.NewProc("MoveFileW")
- procGetComputerNameW = modkernel32.NewProc("GetComputerNameW")
- procSetEndOfFile = modkernel32.NewProc("SetEndOfFile")
- procGetSystemTimeAsFileTime = modkernel32.NewProc("GetSystemTimeAsFileTime")
- procGetTimeZoneInformation = modkernel32.NewProc("GetTimeZoneInformation")
- procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
- procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
- procPostQueuedCompletionStatus = modkernel32.NewProc("PostQueuedCompletionStatus")
- procCancelIo = modkernel32.NewProc("CancelIo")
- procCancelIoEx = modkernel32.NewProc("CancelIoEx")
- procCreateProcessW = modkernel32.NewProc("CreateProcessW")
- procOpenProcess = modkernel32.NewProc("OpenProcess")
- procTerminateProcess = modkernel32.NewProc("TerminateProcess")
- procGetExitCodeProcess = modkernel32.NewProc("GetExitCodeProcess")
- procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW")
- procGetCurrentProcess = modkernel32.NewProc("GetCurrentProcess")
- procGetProcessTimes = modkernel32.NewProc("GetProcessTimes")
- procDuplicateHandle = modkernel32.NewProc("DuplicateHandle")
- procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject")
- procGetTempPathW = modkernel32.NewProc("GetTempPathW")
- procCreatePipe = modkernel32.NewProc("CreatePipe")
- procGetFileType = modkernel32.NewProc("GetFileType")
- procCryptAcquireContextW = modadvapi32.NewProc("CryptAcquireContextW")
- procCryptReleaseContext = modadvapi32.NewProc("CryptReleaseContext")
- procCryptGenRandom = modadvapi32.NewProc("CryptGenRandom")
- procGetEnvironmentStringsW = modkernel32.NewProc("GetEnvironmentStringsW")
- procFreeEnvironmentStringsW = modkernel32.NewProc("FreeEnvironmentStringsW")
- procGetEnvironmentVariableW = modkernel32.NewProc("GetEnvironmentVariableW")
- procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW")
- procSetFileTime = modkernel32.NewProc("SetFileTime")
- procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW")
- procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW")
- procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW")
- procGetCommandLineW = modkernel32.NewProc("GetCommandLineW")
- procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW")
- procLocalFree = modkernel32.NewProc("LocalFree")
- procSetHandleInformation = modkernel32.NewProc("SetHandleInformation")
- procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers")
- procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW")
- procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW")
- procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW")
- procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW")
- procMapViewOfFile = modkernel32.NewProc("MapViewOfFile")
- procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile")
- procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile")
- procVirtualLock = modkernel32.NewProc("VirtualLock")
- procVirtualUnlock = modkernel32.NewProc("VirtualUnlock")
- procTransmitFile = modmswsock.NewProc("TransmitFile")
- procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW")
- procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW")
- procCertOpenStore = modcrypt32.NewProc("CertOpenStore")
- procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore")
- procCertAddCertificateContextToStore = modcrypt32.NewProc("CertAddCertificateContextToStore")
- procCertCloseStore = modcrypt32.NewProc("CertCloseStore")
- procCertGetCertificateChain = modcrypt32.NewProc("CertGetCertificateChain")
- procCertFreeCertificateChain = modcrypt32.NewProc("CertFreeCertificateChain")
- procCertCreateCertificateContext = modcrypt32.NewProc("CertCreateCertificateContext")
- procCertFreeCertificateContext = modcrypt32.NewProc("CertFreeCertificateContext")
- procCertVerifyCertificateChainPolicy = modcrypt32.NewProc("CertVerifyCertificateChainPolicy")
- procRegOpenKeyExW = modadvapi32.NewProc("RegOpenKeyExW")
- procRegCloseKey = modadvapi32.NewProc("RegCloseKey")
- procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW")
- procRegEnumKeyExW = modadvapi32.NewProc("RegEnumKeyExW")
- procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW")
- procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId")
- procGetConsoleMode = modkernel32.NewProc("GetConsoleMode")
- procWriteConsoleW = modkernel32.NewProc("WriteConsoleW")
- procReadConsoleW = modkernel32.NewProc("ReadConsoleW")
- procWSAStartup = modws2_32.NewProc("WSAStartup")
- procWSACleanup = modws2_32.NewProc("WSACleanup")
- procWSAIoctl = modws2_32.NewProc("WSAIoctl")
- procsocket = modws2_32.NewProc("socket")
- procsetsockopt = modws2_32.NewProc("setsockopt")
- procgetsockopt = modws2_32.NewProc("getsockopt")
- procbind = modws2_32.NewProc("bind")
- procconnect = modws2_32.NewProc("connect")
- procgetsockname = modws2_32.NewProc("getsockname")
- procgetpeername = modws2_32.NewProc("getpeername")
- proclisten = modws2_32.NewProc("listen")
- procshutdown = modws2_32.NewProc("shutdown")
- procclosesocket = modws2_32.NewProc("closesocket")
- procAcceptEx = modmswsock.NewProc("AcceptEx")
- procGetAcceptExSockaddrs = modmswsock.NewProc("GetAcceptExSockaddrs")
- procWSARecv = modws2_32.NewProc("WSARecv")
- procWSASend = modws2_32.NewProc("WSASend")
- procWSARecvFrom = modws2_32.NewProc("WSARecvFrom")
- procWSASendTo = modws2_32.NewProc("WSASendTo")
- procgethostbyname = modws2_32.NewProc("gethostbyname")
- procgetservbyname = modws2_32.NewProc("getservbyname")
- procntohs = modws2_32.NewProc("ntohs")
- procgetprotobyname = modws2_32.NewProc("getprotobyname")
- procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W")
- procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree")
- procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW")
- procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW")
- procGetIfEntry = modiphlpapi.NewProc("GetIfEntry")
- procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo")
- procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
- procWSAEnumProtocolsW = modws2_32.NewProc("WSAEnumProtocolsW")
- procTranslateNameW = modsecur32.NewProc("TranslateNameW")
- procGetUserNameExW = modsecur32.NewProc("GetUserNameExW")
- procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo")
- procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation")
- procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree")
- procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW")
- procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
- procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
- procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW")
- procGetLengthSid = modadvapi32.NewProc("GetLengthSid")
- procCopySid = modadvapi32.NewProc("CopySid")
- procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken")
- procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation")
- procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW")
-)
-
-func GetLastError() (lasterr error) {
- r0, _, _ := Syscall(procGetLastError.Addr(), 0, 0, 0, 0)
- if r0 != 0 {
- lasterr = Errno(r0)
- }
- return
-}
-
-func LoadLibrary(libname string) (handle Handle, err error) {
- var _p0 *uint16
- _p0, err = UTF16PtrFromString(libname)
- if err != nil {
- return
- }
- r0, _, e1 := Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0)
- handle = Handle(r0)
- if handle == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func FreeLibrary(handle Handle) (err error) {
- r1, _, e1 := Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetProcAddress(module Handle, procname string) (proc uintptr, err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(procname)
- if err != nil {
- return
- }
- r0, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(_p0)), 0)
- proc = uintptr(r0)
- if proc == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetVersion() (ver uint32, err error) {
- r0, _, e1 := Syscall(procGetVersion.Addr(), 0, 0, 0, 0)
- ver = uint32(r0)
- if ver == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) {
- var _p0 *uint16
- if len(buf) > 0 {
- _p0 = &buf[0]
- }
- r0, _, e1 := Syscall9(procFormatMessageW.Addr(), 7, uintptr(flags), uintptr(msgsrc), uintptr(msgid), uintptr(langid), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(args)), 0, 0)
- n = uint32(r0)
- if n == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func ExitProcess(exitcode uint32) {
- Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0)
- return
-}
-
-func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) {
- r0, _, e1 := Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
- handle = Handle(r0)
- if handle == InvalidHandle {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) {
- var _p0 *byte
- if len(buf) > 0 {
- _p0 = &buf[0]
- }
- r1, _, e1 := Syscall6(procReadFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) {
- var _p0 *byte
- if len(buf) > 0 {
- _p0 = &buf[0]
- }
- r1, _, e1 := Syscall6(procWriteFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) {
- r0, _, e1 := Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0)
- newlowoffset = uint32(r0)
- if newlowoffset == 0xffffffff {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CloseHandle(handle Handle) (err error) {
- r1, _, e1 := Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetStdHandle(stdhandle int) (handle Handle, err error) {
- r0, _, e1 := Syscall(procGetStdHandle.Addr(), 1, uintptr(stdhandle), 0, 0)
- handle = Handle(r0)
- if handle == InvalidHandle {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) {
- r0, _, e1 := Syscall(procFindFirstFileW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(data)), 0)
- handle = Handle(r0)
- if handle == InvalidHandle {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func findNextFile1(handle Handle, data *win32finddata1) (err error) {
- r1, _, e1 := Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func FindClose(handle Handle) (err error) {
- r1, _, e1 := Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) {
- r1, _, e1 := Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) {
- r0, _, e1 := Syscall(procGetCurrentDirectoryW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0)
- n = uint32(r0)
- if n == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func SetCurrentDirectory(path *uint16) (err error) {
- r1, _, e1 := Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) {
- r1, _, e1 := Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func RemoveDirectory(path *uint16) (err error) {
- r1, _, e1 := Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func DeleteFile(path *uint16) (err error) {
- r1, _, e1 := Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func MoveFile(from *uint16, to *uint16) (err error) {
- r1, _, e1 := Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetComputerName(buf *uint16, n *uint32) (err error) {
- r1, _, e1 := Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func SetEndOfFile(handle Handle) (err error) {
- r1, _, e1 := Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetSystemTimeAsFileTime(time *Filetime) {
- Syscall(procGetSystemTimeAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0)
- return
-}
-
-func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) {
- r0, _, e1 := Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0)
- rc = uint32(r0)
- if rc == 0xffffffff {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) {
- r0, _, e1 := Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0)
- handle = Handle(r0)
- if handle == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) {
- r1, _, e1 := Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) {
- r1, _, e1 := Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CancelIo(s Handle) (err error) {
- r1, _, e1 := Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CancelIoEx(s Handle, o *Overlapped) (err error) {
- r1, _, e1 := Syscall(procCancelIoEx.Addr(), 2, uintptr(s), uintptr(unsafe.Pointer(o)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) {
- var _p0 uint32
- if inheritHandles {
- _p0 = 1
- } else {
- _p0 = 0
- }
- r1, _, e1 := Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error) {
- var _p0 uint32
- if inheritHandle {
- _p0 = 1
- } else {
- _p0 = 0
- }
- r0, _, e1 := Syscall(procOpenProcess.Addr(), 3, uintptr(da), uintptr(_p0), uintptr(pid))
- handle = Handle(r0)
- if handle == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func TerminateProcess(handle Handle, exitcode uint32) (err error) {
- r1, _, e1 := Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) {
- r1, _, e1 := Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetStartupInfo(startupInfo *StartupInfo) (err error) {
- r1, _, e1 := Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetCurrentProcess() (pseudoHandle Handle, err error) {
- r0, _, e1 := Syscall(procGetCurrentProcess.Addr(), 0, 0, 0, 0)
- pseudoHandle = Handle(r0)
- if pseudoHandle == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) {
- r1, _, e1 := Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) {
- var _p0 uint32
- if bInheritHandle {
- _p0 = 1
- } else {
- _p0 = 0
- }
- r1, _, e1 := Syscall9(procDuplicateHandle.Addr(), 7, uintptr(hSourceProcessHandle), uintptr(hSourceHandle), uintptr(hTargetProcessHandle), uintptr(unsafe.Pointer(lpTargetHandle)), uintptr(dwDesiredAccess), uintptr(_p0), uintptr(dwOptions), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) {
- r0, _, e1 := Syscall(procWaitForSingleObject.Addr(), 2, uintptr(handle), uintptr(waitMilliseconds), 0)
- event = uint32(r0)
- if event == 0xffffffff {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) {
- r0, _, e1 := Syscall(procGetTempPathW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0)
- n = uint32(r0)
- if n == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) {
- r1, _, e1 := Syscall6(procCreatePipe.Addr(), 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetFileType(filehandle Handle) (n uint32, err error) {
- r0, _, e1 := Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0)
- n = uint32(r0)
- if n == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) {
- r1, _, e1 := Syscall6(procCryptAcquireContextW.Addr(), 5, uintptr(unsafe.Pointer(provhandle)), uintptr(unsafe.Pointer(container)), uintptr(unsafe.Pointer(provider)), uintptr(provtype), uintptr(flags), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CryptReleaseContext(provhandle Handle, flags uint32) (err error) {
- r1, _, e1 := Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) {
- r1, _, e1 := Syscall(procCryptGenRandom.Addr(), 3, uintptr(provhandle), uintptr(buflen), uintptr(unsafe.Pointer(buf)))
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetEnvironmentStrings() (envs *uint16, err error) {
- r0, _, e1 := Syscall(procGetEnvironmentStringsW.Addr(), 0, 0, 0, 0)
- envs = (*uint16)(unsafe.Pointer(r0))
- if envs == nil {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func FreeEnvironmentStrings(envs *uint16) (err error) {
- r1, _, e1 := Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) {
- r0, _, e1 := Syscall(procGetEnvironmentVariableW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size))
- n = uint32(r0)
- if n == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func SetEnvironmentVariable(name *uint16, value *uint16) (err error) {
- r1, _, e1 := Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) {
- r1, _, e1 := Syscall6(procSetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetFileAttributes(name *uint16) (attrs uint32, err error) {
- r0, _, e1 := Syscall(procGetFileAttributesW.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0)
- attrs = uint32(r0)
- if attrs == INVALID_FILE_ATTRIBUTES {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func SetFileAttributes(name *uint16, attrs uint32) (err error) {
- r1, _, e1 := Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) {
- r1, _, e1 := Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info)))
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetCommandLine() (cmd *uint16) {
- r0, _, _ := Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0)
- cmd = (*uint16)(unsafe.Pointer(r0))
- return
-}
-
-func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) {
- r0, _, e1 := Syscall(procCommandLineToArgvW.Addr(), 2, uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc)), 0)
- argv = (*[8192]*[8192]uint16)(unsafe.Pointer(r0))
- if argv == nil {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func LocalFree(hmem Handle) (handle Handle, err error) {
- r0, _, e1 := Syscall(procLocalFree.Addr(), 1, uintptr(hmem), 0, 0)
- handle = Handle(r0)
- if handle != 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) {
- r1, _, e1 := Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags))
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func FlushFileBuffers(handle Handle) (err error) {
- r1, _, e1 := Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) {
- r0, _, e1 := Syscall6(procGetFullPathNameW.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname)), 0, 0)
- n = uint32(r0)
- if n == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) {
- r0, _, e1 := Syscall(procGetLongPathNameW.Addr(), 3, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(buf)), uintptr(buflen))
- n = uint32(r0)
- if n == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) {
- r0, _, e1 := Syscall(procGetShortPathNameW.Addr(), 3, uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen))
- n = uint32(r0)
- if n == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) {
- r0, _, e1 := Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name)))
- handle = Handle(r0)
- if handle == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) {
- r0, _, e1 := Syscall6(procMapViewOfFile.Addr(), 5, uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length), 0)
- addr = uintptr(r0)
- if addr == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func UnmapViewOfFile(addr uintptr) (err error) {
- r1, _, e1 := Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func FlushViewOfFile(addr uintptr, length uintptr) (err error) {
- r1, _, e1 := Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func VirtualLock(addr uintptr, length uintptr) (err error) {
- r1, _, e1 := Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func VirtualUnlock(addr uintptr, length uintptr) (err error) {
- r1, _, e1 := Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) {
- r1, _, e1 := Syscall9(procTransmitFile.Addr(), 7, uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) {
- var _p0 uint32
- if watchSubTree {
- _p0 = 1
- } else {
- _p0 = 0
- }
- r1, _, e1 := Syscall9(procReadDirectoryChangesW.Addr(), 8, uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) {
- r0, _, e1 := Syscall(procCertOpenSystemStoreW.Addr(), 2, uintptr(hprov), uintptr(unsafe.Pointer(name)), 0)
- store = Handle(r0)
- if store == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) {
- r0, _, e1 := Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0)
- handle = Handle(r0)
- if handle == InvalidHandle {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) {
- r0, _, e1 := Syscall(procCertEnumCertificatesInStore.Addr(), 2, uintptr(store), uintptr(unsafe.Pointer(prevContext)), 0)
- context = (*CertContext)(unsafe.Pointer(r0))
- if context == nil {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) {
- r1, _, e1 := Syscall6(procCertAddCertificateContextToStore.Addr(), 4, uintptr(store), uintptr(unsafe.Pointer(certContext)), uintptr(addDisposition), uintptr(unsafe.Pointer(storeContext)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CertCloseStore(store Handle, flags uint32) (err error) {
- r1, _, e1 := Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) {
- r1, _, e1 := Syscall9(procCertGetCertificateChain.Addr(), 8, uintptr(engine), uintptr(unsafe.Pointer(leaf)), uintptr(unsafe.Pointer(time)), uintptr(additionalStore), uintptr(unsafe.Pointer(para)), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(chainCtx)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CertFreeCertificateChain(ctx *CertChainContext) {
- Syscall(procCertFreeCertificateChain.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0)
- return
-}
-
-func CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) {
- r0, _, e1 := Syscall(procCertCreateCertificateContext.Addr(), 3, uintptr(certEncodingType), uintptr(unsafe.Pointer(certEncoded)), uintptr(encodedLen))
- context = (*CertContext)(unsafe.Pointer(r0))
- if context == nil {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CertFreeCertificateContext(ctx *CertContext) (err error) {
- r1, _, e1 := Syscall(procCertFreeCertificateContext.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) {
- r1, _, e1 := Syscall6(procCertVerifyCertificateChainPolicy.Addr(), 4, uintptr(policyOID), uintptr(unsafe.Pointer(chain)), uintptr(unsafe.Pointer(para)), uintptr(unsafe.Pointer(status)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) {
- r0, _, _ := Syscall6(procRegOpenKeyExW.Addr(), 5, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(result)), 0)
- if r0 != 0 {
- regerrno = Errno(r0)
- }
- return
-}
-
-func RegCloseKey(key Handle) (regerrno error) {
- r0, _, _ := Syscall(procRegCloseKey.Addr(), 1, uintptr(key), 0, 0)
- if r0 != 0 {
- regerrno = Errno(r0)
- }
- return
-}
-
-func RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) {
- r0, _, _ := Syscall12(procRegQueryInfoKeyW.Addr(), 12, uintptr(key), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(subkeysLen)), uintptr(unsafe.Pointer(maxSubkeyLen)), uintptr(unsafe.Pointer(maxClassLen)), uintptr(unsafe.Pointer(valuesLen)), uintptr(unsafe.Pointer(maxValueNameLen)), uintptr(unsafe.Pointer(maxValueLen)), uintptr(unsafe.Pointer(saLen)), uintptr(unsafe.Pointer(lastWriteTime)))
- if r0 != 0 {
- regerrno = Errno(r0)
- }
- return
-}
-
-func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) {
- r0, _, _ := Syscall9(procRegEnumKeyExW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(lastWriteTime)), 0)
- if r0 != 0 {
- regerrno = Errno(r0)
- }
- return
-}
-
-func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) {
- r0, _, _ := Syscall6(procRegQueryValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen)))
- if r0 != 0 {
- regerrno = Errno(r0)
- }
- return
-}
-
-func getCurrentProcessId() (pid uint32) {
- r0, _, _ := Syscall(procGetCurrentProcessId.Addr(), 0, 0, 0, 0)
- pid = uint32(r0)
- return
-}
-
-func GetConsoleMode(console Handle, mode *uint32) (err error) {
- r1, _, e1 := Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) {
- r1, _, e1 := Syscall6(procWriteConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(towrite), uintptr(unsafe.Pointer(written)), uintptr(unsafe.Pointer(reserved)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) {
- r1, _, e1 := Syscall6(procReadConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)), uintptr(unsafe.Pointer(inputControl)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
- r0, _, _ := Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
- if r0 != 0 {
- sockerr = Errno(r0)
- }
- return
-}
-
-func WSACleanup() (err error) {
- r1, _, e1 := Syscall(procWSACleanup.Addr(), 0, 0, 0, 0)
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) {
- r1, _, e1 := Syscall9(procWSAIoctl.Addr(), 9, uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine))
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func socket(af int32, typ int32, protocol int32) (handle Handle, err error) {
- r0, _, e1 := Syscall(procsocket.Addr(), 3, uintptr(af), uintptr(typ), uintptr(protocol))
- handle = Handle(r0)
- if handle == InvalidHandle {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) {
- r1, _, e1 := Syscall6(procsetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen), 0)
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) {
- r1, _, e1 := Syscall6(procgetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(unsafe.Pointer(optlen)), 0)
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func bind(s Handle, name unsafe.Pointer, namelen int32) (err error) {
- r1, _, e1 := Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func connect(s Handle, name unsafe.Pointer, namelen int32) (err error) {
- r1, _, e1 := Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) {
- r1, _, e1 := Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) {
- r1, _, e1 := Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func listen(s Handle, backlog int32) (err error) {
- r1, _, e1 := Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0)
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func shutdown(s Handle, how int32) (err error) {
- r1, _, e1 := Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0)
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func Closesocket(s Handle) (err error) {
- r1, _, e1 := Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0)
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) {
- r1, _, e1 := Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) {
- Syscall9(procGetAcceptExSockaddrs.Addr(), 8, uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(lrsa)), uintptr(unsafe.Pointer(lrsalen)), uintptr(unsafe.Pointer(rrsa)), uintptr(unsafe.Pointer(rrsalen)), 0)
- return
-}
-
-func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) {
- r1, _, e1 := Syscall9(procWSARecv.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0)
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) {
- r1, _, e1 := Syscall9(procWSASend.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0)
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) {
- r1, _, e1 := Syscall9(procWSARecvFrom.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) {
- r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
- if r1 == socket_error {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetHostByName(name string) (h *Hostent, err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(name)
- if err != nil {
- return
- }
- r0, _, e1 := Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0)
- h = (*Hostent)(unsafe.Pointer(r0))
- if h == nil {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetServByName(name string, proto string) (s *Servent, err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(name)
- if err != nil {
- return
- }
- var _p1 *byte
- _p1, err = BytePtrFromString(proto)
- if err != nil {
- return
- }
- r0, _, e1 := Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
- s = (*Servent)(unsafe.Pointer(r0))
- if s == nil {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func Ntohs(netshort uint16) (u uint16) {
- r0, _, _ := Syscall(procntohs.Addr(), 1, uintptr(netshort), 0, 0)
- u = uint16(r0)
- return
-}
-
-func GetProtoByName(name string) (p *Protoent, err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(name)
- if err != nil {
- return
- }
- r0, _, e1 := Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0)
- p = (*Protoent)(unsafe.Pointer(r0))
- if p == nil {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) {
- var _p0 *uint16
- _p0, status = UTF16PtrFromString(name)
- if status != nil {
- return
- }
- r0, _, _ := Syscall6(procDnsQuery_W.Addr(), 6, uintptr(unsafe.Pointer(_p0)), uintptr(qtype), uintptr(options), uintptr(unsafe.Pointer(extra)), uintptr(unsafe.Pointer(qrs)), uintptr(unsafe.Pointer(pr)))
- if r0 != 0 {
- status = Errno(r0)
- }
- return
-}
-
-func DnsRecordListFree(rl *DNSRecord, freetype uint32) {
- Syscall(procDnsRecordListFree.Addr(), 2, uintptr(unsafe.Pointer(rl)), uintptr(freetype), 0)
- return
-}
-
-func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) {
- r0, _, _ := Syscall6(procGetAddrInfoW.Addr(), 4, uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result)), 0, 0)
- if r0 != 0 {
- sockerr = Errno(r0)
- }
- return
-}
-
-func FreeAddrInfoW(addrinfo *AddrinfoW) {
- Syscall(procFreeAddrInfoW.Addr(), 1, uintptr(unsafe.Pointer(addrinfo)), 0, 0)
- return
-}
-
-func GetIfEntry(pIfRow *MibIfRow) (errcode error) {
- r0, _, _ := Syscall(procGetIfEntry.Addr(), 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0)
- if r0 != 0 {
- errcode = Errno(r0)
- }
- return
-}
-
-func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) {
- r0, _, _ := Syscall(procGetAdaptersInfo.Addr(), 2, uintptr(unsafe.Pointer(ai)), uintptr(unsafe.Pointer(ol)), 0)
- if r0 != 0 {
- errcode = Errno(r0)
- }
- return
-}
-
-func SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) {
- r1, _, e1 := Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(handle), uintptr(flags), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) {
- r0, _, e1 := Syscall(procWSAEnumProtocolsW.Addr(), 3, uintptr(unsafe.Pointer(protocols)), uintptr(unsafe.Pointer(protocolBuffer)), uintptr(unsafe.Pointer(bufferLength)))
- n = int32(r0)
- if n == -1 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) {
- r1, _, e1 := Syscall6(procTranslateNameW.Addr(), 5, uintptr(unsafe.Pointer(accName)), uintptr(accNameFormat), uintptr(desiredNameFormat), uintptr(unsafe.Pointer(translatedName)), uintptr(unsafe.Pointer(nSize)), 0)
- if r1&0xff == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) {
- r1, _, e1 := Syscall(procGetUserNameExW.Addr(), 3, uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize)))
- if r1&0xff == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) {
- r0, _, _ := Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0)
- if r0 != 0 {
- neterr = Errno(r0)
- }
- return
-}
-
-func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) {
- r0, _, _ := Syscall(procNetGetJoinInformation.Addr(), 3, uintptr(unsafe.Pointer(server)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(bufType)))
- if r0 != 0 {
- neterr = Errno(r0)
- }
- return
-}
-
-func NetApiBufferFree(buf *byte) (neterr error) {
- r0, _, _ := Syscall(procNetApiBufferFree.Addr(), 1, uintptr(unsafe.Pointer(buf)), 0, 0)
- if r0 != 0 {
- neterr = Errno(r0)
- }
- return
-}
-
-func LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) {
- r1, _, e1 := Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) {
- r1, _, e1 := Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) {
- r1, _, e1 := Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(stringSid)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) {
- r1, _, e1 := Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(stringSid)), uintptr(unsafe.Pointer(sid)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetLengthSid(sid *SID) (len uint32) {
- r0, _, _ := Syscall(procGetLengthSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0)
- len = uint32(r0)
- return
-}
-
-func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) {
- r1, _, e1 := Syscall(procCopySid.Addr(), 3, uintptr(destSidLen), uintptr(unsafe.Pointer(destSid)), uintptr(unsafe.Pointer(srcSid)))
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func OpenProcessToken(h Handle, access uint32, token *Token) (err error) {
- r1, _, e1 := Syscall(procOpenProcessToken.Addr(), 3, uintptr(h), uintptr(access), uintptr(unsafe.Pointer(token)))
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) {
- r1, _, e1 := Syscall6(procGetTokenInformation.Addr(), 5, uintptr(t), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), uintptr(unsafe.Pointer(returnedLen)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
-
-func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) {
- r1, _, e1 := Syscall(procGetUserProfileDirectoryW.Addr(), 3, uintptr(t), uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen)))
- if r1 == 0 {
- if e1 != 0 {
- err = error(e1)
- } else {
- err = EINVAL
- }
- }
- return
-}
diff --git a/src/pkg/syscall/zsysnum_plan9_386.go b/src/pkg/syscall/zsysnum_plan9_386.go
deleted file mode 100644
index 4135b8d81..000000000
--- a/src/pkg/syscall/zsysnum_plan9_386.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// mksysnum_plan9.sh /media/sys/src/libc/9syscall/sys.h
-// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
-
-package syscall
-
-const (
- SYS_SYSR1 = 0
- SYS_BIND = 2
- SYS_CHDIR = 3
- SYS_CLOSE = 4
- SYS_DUP = 5
- SYS_ALARM = 6
- SYS_EXEC = 7
- SYS_EXITS = 8
- SYS_FAUTH = 10
- SYS_SEGBRK = 12
- SYS_OPEN = 14
- SYS_OSEEK = 16
- SYS_SLEEP = 17
- SYS_RFORK = 19
- SYS_PIPE = 21
- SYS_CREATE = 22
- SYS_FD2PATH = 23
- SYS_BRK_ = 24
- SYS_REMOVE = 25
- SYS_NOTIFY = 28
- SYS_NOTED = 29
- SYS_SEGATTACH = 30
- SYS_SEGDETACH = 31
- SYS_SEGFREE = 32
- SYS_SEGFLUSH = 33
- SYS_RENDEZVOUS = 34
- SYS_UNMOUNT = 35
- SYS_SEMACQUIRE = 37
- SYS_SEMRELEASE = 38
- SYS_SEEK = 39
- SYS_FVERSION = 40
- SYS_ERRSTR = 41
- SYS_STAT = 42
- SYS_FSTAT = 43
- SYS_WSTAT = 44
- SYS_FWSTAT = 45
- SYS_MOUNT = 46
- SYS_AWAIT = 47
- SYS_PREAD = 50
- SYS_PWRITE = 51
-)
diff --git a/src/pkg/syscall/zsysnum_plan9_amd64.go b/src/pkg/syscall/zsysnum_plan9_amd64.go
deleted file mode 100644
index c03864647..000000000
--- a/src/pkg/syscall/zsysnum_plan9_amd64.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// mksysnum_plan9.sh /media/sys/src/libc/9syscall/sys.h
-// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
-
-package syscall
-
-const (
- SYS_SYSR1 = 0
- SYS_BIND = 2
- SYS_CHDIR = 3
- SYS_CLOSE = 4
- SYS_DUP = 5
- SYS_ALARM = 6
- SYS_EXEC = 7
- SYS_EXITS = 8
- SYS_FAUTH = 10
- SYS_SEGBRK = 12
- SYS_OPEN = 14
- SYS_OSEEK = 16
- SYS_SLEEP = 17
- SYS_RFORK = 19
- SYS_PIPE = 21
- SYS_CREATE = 22
- SYS_FD2PATH = 23
- SYS_BRK_ = 24
- SYS_REMOVE = 25
- SYS_NOTIFY = 28
- SYS_NOTED = 29
- SYS_SEGATTACH = 30
- SYS_SEGDETACH = 31
- SYS_SEGFREE = 32
- SYS_SEGFLUSH = 33
- SYS_RENDEZVOUS = 34
- SYS_UNMOUNT = 35
- SYS_SEMACQUIRE = 37
- SYS_SEMRELEASE = 38
- SYS_SEEK = 39
- SYS_FVERSION = 40
- SYS_ERRSTR = 41
- SYS_STAT = 42
- SYS_FSTAT = 43
- SYS_WSTAT = 44
- SYS_FWSTAT = 45
- SYS_MOUNT = 46
- SYS_AWAIT = 47
- SYS_PREAD = 50
- SYS_PWRITE = 51
- SYS_NANOTIME = 60
-)
diff --git a/src/pkg/time/Makefile b/src/pkg/time/Makefile
deleted file mode 100644
index cba58e4e0..000000000
--- a/src/pkg/time/Makefile
+++ /dev/null
@@ -1,9 +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.
-
-genzabbrs: genzabbrs.go
- go build genzabbrs.go
-
-windows: genzabbrs
- ./genzabbrs | gofmt >zoneinfo_abbrs_windows.go
diff --git a/src/pkg/time/internal_test.go b/src/pkg/time/internal_test.go
deleted file mode 100644
index 2243d3668..000000000
--- a/src/pkg/time/internal_test.go
+++ /dev/null
@@ -1,92 +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 time
-
-import (
- "errors"
- "runtime"
-)
-
-func init() {
- // force US/Pacific for time zone tests
- ForceUSPacificForTesting()
-}
-
-var Interrupt = interrupt
-var DaysIn = daysIn
-
-func empty(now int64, arg interface{}) {}
-
-// Test that a runtimeTimer with a duration so large it overflows
-// does not cause other timers to hang.
-//
-// This test has to be in internal_test.go since it fiddles with
-// unexported data structures.
-func CheckRuntimeTimerOverflow() error {
- // We manually create a runtimeTimer to bypass the overflow
- // detection logic in NewTimer: we're testing the underlying
- // runtime.addtimer function.
- r := &runtimeTimer{
- when: runtimeNano() + (1<<63 - 1),
- f: empty,
- arg: nil,
- }
- startTimer(r)
-
- timeout := 100 * Millisecond
- switch runtime.GOOS {
- // Allow more time for gobuilder to succeed.
- case "windows":
- timeout = Second
- case "plan9":
- // TODO(0intro): We don't know why it is needed.
- timeout = 3 * Second
- }
-
- // Start a goroutine that should send on t.C before the timeout.
- t := NewTimer(1)
-
- defer func() {
- // Subsequent tests won't work correctly if we don't stop the
- // overflow timer and kick the timer proc back into service.
- //
- // The timer proc is now sleeping and can only be awoken by
- // adding a timer to the *beginning* of the heap. We can't
- // wake it up by calling NewTimer since other tests may have
- // left timers running that should have expired before ours.
- // Instead we zero the overflow timer duration and start it
- // once more.
- stopTimer(r)
- t.Stop()
- r.when = 0
- startTimer(r)
- }()
-
- // Try to receive from t.C before the timeout. It will succeed
- // iff the previous sleep was able to finish. We're forced to
- // spin and yield after trying to receive since we can't start
- // any more timers (they might hang due to the same bug we're
- // now testing).
- stop := Now().Add(timeout)
- for {
- select {
- case <-t.C:
- return nil // It worked!
- default:
- if Now().After(stop) {
- return errors.New("runtime timer stuck: overflow in addtimer")
- }
- // Issue 6874. This test previously called runtime.Gosched to try to yield
- // to the goroutine servicing t, however the scheduler has a bias towards the
- // previously running goroutine in an idle system. Combined with high load due
- // to all CPUs busy running tests t's goroutine could be delayed beyond the
- // timeout window.
- //
- // Calling runtime.GC() reduces the worst case lantency for scheduling t by 20x
- // under the current Go 1.3 scheduler.
- runtime.GC()
- }
- }
-}
diff --git a/src/pkg/unicode/Makefile b/src/pkg/unicode/Makefile
deleted file mode 100644
index 33b06ca10..000000000
--- a/src/pkg/unicode/Makefile
+++ /dev/null
@@ -1,16 +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.
-
-maketables: maketables.go
- go build maketables.go
-
-tables: maketables
- ./maketables --tables=all > tables.go
- gofmt -w tables.go
-
-# Downloads from www.unicode.org, so not part
-# of standard test scripts.
-testtables: maketables
- @echo '***' Be sure to make tables and go install first
- ./maketables -test
diff --git a/src/race.bash b/src/race.bash
index 1680c09e4..622584016 100755
--- a/src/race.bash
+++ b/src/race.bash
@@ -9,7 +9,7 @@
set -e
function usage {
- echo 'race detector is only supported on linux/amd64 and darwin/amd64' 1>&2
+ echo 'race detector is only supported on linux/amd64, freebsd/amd64 and darwin/amd64' 1>&2
exit 1
}
@@ -25,6 +25,11 @@ case $(uname) in
usage
fi
;;
+"FreeBSD")
+ if [ $(uname -m) != "amd64" ]; then
+ usage
+ fi
+ ;;
*)
usage
;;
diff --git a/src/pkg/reflect/all_test.go b/src/reflect/all_test.go
index e9949012c..7a01c95d8 100644
--- a/src/pkg/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -679,7 +679,7 @@ var deepEqualTests = []DeepEqualTest{
{1, nil, false},
{fn1, fn3, false},
{fn3, fn3, false},
- {[][]int{[]int{1}}, [][]int{[]int{2}}, false},
+ {[][]int{{1}}, [][]int{{2}}, false},
// Nil vs empty: not the same.
{[]int{}, []int(nil), false},
@@ -1543,7 +1543,17 @@ func TestMakeFuncVariadic(t *testing.T) {
fv := MakeFunc(TypeOf(fn), func(in []Value) []Value { return in[1:2] })
ValueOf(&fn).Elem().Set(fv)
- r := fv.Call([]Value{ValueOf(1), ValueOf(2), ValueOf(3)})[0].Interface().([]int)
+ r := fn(1, 2, 3)
+ if r[0] != 2 || r[1] != 3 {
+ t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+ }
+
+ r = fn(1, []int{2, 3}...)
+ if r[0] != 2 || r[1] != 3 {
+ t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+ }
+
+ r = fv.Call([]Value{ValueOf(1), ValueOf(2), ValueOf(3)})[0].Interface().([]int)
if r[0] != 2 || r[1] != 3 {
t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
}
@@ -1552,6 +1562,17 @@ func TestMakeFuncVariadic(t *testing.T) {
if r[0] != 2 || r[1] != 3 {
t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
}
+
+ f := fv.Interface().(func(int, ...int) []int)
+
+ r = f(1, 2, 3)
+ if r[0] != 2 || r[1] != 3 {
+ t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+ }
+ r = f(1, []int{2, 3}...)
+ if r[0] != 2 || r[1] != 3 {
+ t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+ }
}
type Point struct {
@@ -1569,6 +1590,24 @@ func (p Point) Dist(scale int) int {
return p.x*p.x*scale + p.y*p.y*scale
}
+// This will be index 2.
+func (p Point) GCMethod(k int) int {
+ runtime.GC()
+ return k + p.x
+}
+
+// This will be index 3.
+func (p Point) TotalDist(points ...Point) int {
+ tot := 0
+ for _, q := range points {
+ dx := q.x - p.x
+ dy := q.y - p.y
+ tot += dx*dx + dy*dy // Should call Sqrt, but it's just a test.
+
+ }
+ return tot
+}
+
func TestMethod(t *testing.T) {
// Non-curried method of type.
p := Point{3, 4}
@@ -1751,6 +1790,37 @@ func TestMethodValue(t *testing.T) {
}
}
+func TestVariadicMethodValue(t *testing.T) {
+ p := Point{3, 4}
+ points := []Point{{20, 21}, {22, 23}, {24, 25}}
+ want := int64(p.TotalDist(points[0], points[1], points[2]))
+
+ // Curried method of value.
+ tfunc := TypeOf((func(...Point) int)(nil))
+ v := ValueOf(p).Method(3)
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Variadic Method Type is %s; want %s", tt, tfunc)
+ }
+ i := ValueOf(v.Interface()).Call([]Value{ValueOf(points[0]), ValueOf(points[1]), ValueOf(points[2])})[0].Int()
+ if i != want {
+ t.Errorf("Variadic Method returned %d; want %d", i, want)
+ }
+ i = ValueOf(v.Interface()).CallSlice([]Value{ValueOf(points)})[0].Int()
+ if i != want {
+ t.Errorf("Variadic Method CallSlice returned %d; want %d", i, want)
+ }
+
+ f := v.Interface().(func(...Point) int)
+ i = int64(f(points[0], points[1], points[2]))
+ if i != want {
+ t.Errorf("Variadic Method Interface returned %d; want %d", i, want)
+ }
+ i = int64(f(points...))
+ if i != want {
+ t.Errorf("Variadic Method Interface Slice returned %d; want %d", i, want)
+ }
+}
+
// Reflect version of $GOROOT/test/method5.go
// Concrete types implementing M method.
@@ -2432,10 +2502,21 @@ func TestAllocations(t *testing.T) {
noAlloc(t, 100, func(j int) {
var i interface{}
var v Value
- i = 42 + j
+
+ // We can uncomment this when compiler escape analysis
+ // is good enough to see that the integer assigned to i
+ // does not escape and therefore need not be allocated.
+ //
+ // i = 42 + j
+ // v = ValueOf(i)
+ // if int(v.Int()) != 42+j {
+ // panic("wrong int")
+ // }
+
+ i = func(j int) int { return j }
v = ValueOf(i)
- if int(v.Int()) != 42+j {
- panic("wrong int")
+ if v.Interface().(func(int) int)(j) != j {
+ panic("wrong result")
}
})
}
@@ -2494,6 +2575,15 @@ func TestSlice(t *testing.T) {
if vs != s[3:5] {
t.Errorf("s.Slice(3, 5) = %q; expected %q", vs, s[3:5])
}
+
+ rv := ValueOf(&xs).Elem()
+ rv = rv.Slice(3, 4)
+ ptr2 := rv.Pointer()
+ rv = rv.Slice(5, 5)
+ ptr3 := rv.Pointer()
+ if ptr3 != ptr2 {
+ t.Errorf("xs.Slice(3,4).Slice3(5,5).Pointer() = %#x, want %#x", ptr3, ptr2)
+ }
}
func TestSlice3(t *testing.T) {
@@ -2532,6 +2622,15 @@ func TestSlice3(t *testing.T) {
s := "hello world"
rv = ValueOf(&s).Elem()
shouldPanic(func() { rv.Slice3(1, 2, 3) })
+
+ rv = ValueOf(&xs).Elem()
+ rv = rv.Slice3(3, 5, 7)
+ ptr2 := rv.Pointer()
+ rv = rv.Slice3(4, 4, 4)
+ ptr3 := rv.Pointer()
+ if ptr3 != ptr2 {
+ t.Errorf("xs.Slice3(3,5,7).Slice3(4,4,4).Pointer() = %#x, want %#x", ptr3, ptr2)
+ }
}
func TestSetLenCap(t *testing.T) {
@@ -2590,6 +2689,26 @@ func TestFuncArg(t *testing.T) {
}
}
+func TestStructArg(t *testing.T) {
+ type padded struct {
+ B string
+ C int32
+ }
+ var (
+ gotA padded
+ gotB uint32
+ wantA = padded{"3", 4}
+ wantB = uint32(5)
+ )
+ f := func(a padded, b uint32) {
+ gotA, gotB = a, b
+ }
+ ValueOf(f).Call([]Value{ValueOf(wantA), ValueOf(wantB)})
+ if gotA != wantA || gotB != wantB {
+ t.Errorf("function called with (%v, %v), want (%v, %v)", gotA, gotB, wantA, wantB)
+ }
+}
+
var tagGetTests = []struct {
Tag StructTag
Key string
@@ -3167,6 +3286,44 @@ func TestConvert(t *testing.T) {
}
}
+type ComparableStruct struct {
+ X int
+}
+
+type NonComparableStruct struct {
+ X int
+ Y map[string]int
+}
+
+var comparableTests = []struct {
+ typ Type
+ ok bool
+}{
+ {TypeOf(1), true},
+ {TypeOf("hello"), true},
+ {TypeOf(new(byte)), true},
+ {TypeOf((func())(nil)), false},
+ {TypeOf([]byte{}), false},
+ {TypeOf(map[string]int{}), false},
+ {TypeOf(make(chan int)), true},
+ {TypeOf(1.5), true},
+ {TypeOf(false), true},
+ {TypeOf(1i), true},
+ {TypeOf(ComparableStruct{}), true},
+ {TypeOf(NonComparableStruct{}), false},
+ {TypeOf([10]map[string]int{}), false},
+ {TypeOf([10]string{}), true},
+ {TypeOf(new(interface{})).Elem(), true},
+}
+
+func TestComparable(t *testing.T) {
+ for _, tt := range comparableTests {
+ if ok := tt.typ.Comparable(); ok != tt.ok {
+ t.Errorf("TypeOf(%v).Comparable() = %v, want %v", tt.typ, ok, tt.ok)
+ }
+ }
+}
+
func TestOverflow(t *testing.T) {
if ovf := V(float64(0)).OverflowFloat(1e300); ovf {
t.Errorf("%v wrongly overflows float64", 1e300)
@@ -3213,6 +3370,9 @@ func checkSameType(t *testing.T, x, y interface{}) {
}
func TestArrayOf(t *testing.T) {
+ // TODO(rsc): Finish ArrayOf and enable-test.
+ t.Skip("ArrayOf is not finished (and not exported)")
+
// check construction and use of type not in binary
type T int
at := ArrayOf(10, TypeOf(T(1)))
@@ -3711,11 +3871,6 @@ func TestReflectFuncTraceback(t *testing.T) {
f.Call([]Value{})
}
-func (p Point) GCMethod(k int) int {
- runtime.GC()
- return k + p.x
-}
-
func TestReflectMethodTraceback(t *testing.T) {
p := Point{3, 4}
m := ValueOf(p).MethodByName("GCMethod")
@@ -3839,3 +3994,165 @@ func TestCallMethodJump(t *testing.T) {
// Stop garbage collecting during reflect.call.
*CallGC = false
}
+
+func TestMakeFuncStackCopy(t *testing.T) {
+ target := func(in []Value) []Value {
+ runtime.GC()
+ useStack(16)
+ return []Value{ValueOf(9)}
+ }
+
+ var concrete func(*int, int) int
+ fn := MakeFunc(ValueOf(concrete).Type(), target)
+ ValueOf(&concrete).Elem().Set(fn)
+ x := concrete(nil, 7)
+ if x != 9 {
+ t.Errorf("have %#q want 9", x)
+ }
+}
+
+// use about n KB of stack
+func useStack(n int) {
+ if n == 0 {
+ return
+ }
+ var b [1024]byte // makes frame about 1KB
+ useStack(n - 1 + int(b[99]))
+}
+
+type Impl struct{}
+
+func (Impl) f() {}
+
+func TestValueString(t *testing.T) {
+ rv := ValueOf(Impl{})
+ if rv.String() != "<reflect_test.Impl Value>" {
+ t.Errorf("ValueOf(Impl{}).String() = %q, want %q", rv.String(), "<reflect_test.Impl Value>")
+ }
+
+ method := rv.Method(0)
+ if method.String() != "<func() Value>" {
+ t.Errorf("ValueOf(Impl{}).Method(0).String() = %q, want %q", method.String(), "<func() Value>")
+ }
+}
+
+func TestInvalid(t *testing.T) {
+ // Used to have inconsistency between IsValid() and Kind() != Invalid.
+ type T struct{ v interface{} }
+
+ v := ValueOf(T{}).Field(0)
+ if v.IsValid() != true || v.Kind() != Interface {
+ t.Errorf("field: IsValid=%v, Kind=%v, want true, Interface", v.IsValid(), v.Kind())
+ }
+ v = v.Elem()
+ if v.IsValid() != false || v.Kind() != Invalid {
+ t.Errorf("field elem: IsValid=%v, Kind=%v, want false, Invalid", v.IsValid(), v.Kind())
+ }
+}
+
+// Issue 8917.
+func TestLargeGCProg(t *testing.T) {
+ fv := ValueOf(func([256]*byte) {})
+ fv.Call([]Value{ValueOf([256]*byte{})})
+}
+
+// Issue 9179.
+func TestCallGC(t *testing.T) {
+ f := func(a, b, c, d, e string) {
+ }
+ g := func(in []Value) []Value {
+ runtime.GC()
+ return nil
+ }
+ typ := ValueOf(f).Type()
+ f2 := MakeFunc(typ, g).Interface().(func(string, string, string, string, string))
+ f2("four", "five5", "six666", "seven77", "eight888")
+}
+
+type funcLayoutTest struct {
+ rcvr, t Type
+ argsize, retOffset uintptr
+ stack []byte
+}
+
+var funcLayoutTests []funcLayoutTest
+
+func init() {
+ var argAlign = PtrSize
+ if runtime.GOARCH == "amd64p32" {
+ argAlign = 2 * PtrSize
+ }
+ roundup := func(x uintptr, a uintptr) uintptr {
+ return (x + a - 1) / a * a
+ }
+
+ funcLayoutTests = append(funcLayoutTests,
+ funcLayoutTest{
+ nil,
+ ValueOf(func(a, b string) string { return "" }).Type(),
+ 4 * PtrSize,
+ 4 * PtrSize,
+ []byte{BitsPointer, BitsScalar, BitsPointer},
+ })
+
+ var r []byte
+ if PtrSize == 4 {
+ r = []byte{BitsScalar, BitsScalar, BitsScalar, BitsPointer}
+ } else {
+ r = []byte{BitsScalar, BitsScalar, BitsPointer}
+ }
+ funcLayoutTests = append(funcLayoutTests,
+ funcLayoutTest{
+ nil,
+ ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
+ roundup(3*4, PtrSize) + PtrSize + 2,
+ roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
+ r,
+ })
+
+ funcLayoutTests = append(funcLayoutTests,
+ funcLayoutTest{
+ nil,
+ ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
+ 4 * PtrSize,
+ 4 * PtrSize,
+ []byte{BitsPointer, BitsScalar, BitsPointer, BitsPointer},
+ })
+
+ type S struct {
+ a, b uintptr
+ c, d *byte
+ }
+ funcLayoutTests = append(funcLayoutTests,
+ funcLayoutTest{
+ nil,
+ ValueOf(func(a S) {}).Type(),
+ 4 * PtrSize,
+ 4 * PtrSize,
+ []byte{BitsScalar, BitsScalar, BitsPointer, BitsPointer},
+ })
+
+ funcLayoutTests = append(funcLayoutTests,
+ funcLayoutTest{
+ ValueOf((*byte)(nil)).Type(),
+ ValueOf(func(a uintptr, b *int) {}).Type(),
+ 3 * PtrSize,
+ roundup(3*PtrSize, argAlign),
+ []byte{BitsPointer, BitsScalar, BitsPointer},
+ })
+}
+
+func TestFuncLayout(t *testing.T) {
+ for _, lt := range funcLayoutTests {
+ _, argsize, retOffset, stack := FuncLayout(lt.t, lt.rcvr)
+ if argsize != lt.argsize {
+ t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.t, lt.rcvr, argsize, lt.argsize)
+ }
+ if retOffset != lt.retOffset {
+ t.Errorf("funcLayout(%v, %v).retOffset=%d, want %d", lt.t, lt.rcvr, retOffset, lt.retOffset)
+ }
+ if !bytes.Equal(stack, lt.stack) {
+ t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.t, lt.rcvr, stack, lt.stack)
+ }
+ }
+}
diff --git a/src/pkg/reflect/asm_386.s b/src/reflect/asm_386.s
index 75413c752..0ffccf7d4 100644
--- a/src/pkg/reflect/asm_386.s
+++ b/src/reflect/asm_386.s
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
// 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 argsize here, gc generates argsize info at call site.
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
+ NO_LOCAL_POINTERS
MOVL DX, 0(SP)
LEAL argframe+0(FP), CX
MOVL CX, 4(SP)
@@ -20,6 +22,7 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
// for more details.
// No argsize here, gc generates argsize info at call site.
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
+ NO_LOCAL_POINTERS
MOVL DX, 0(SP)
LEAL argframe+0(FP), CX
MOVL CX, 4(SP)
diff --git a/src/pkg/reflect/asm_amd64.s b/src/reflect/asm_amd64.s
index 712959843..5a6c27ac9 100644
--- a/src/pkg/reflect/asm_amd64.s
+++ b/src/reflect/asm_amd64.s
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
// 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 argsize here, gc generates argsize info at call site.
+// No arg size here; runtime pulls arg map out of the func value.
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
+ NO_LOCAL_POINTERS
MOVQ DX, 0(SP)
LEAQ argframe+0(FP), CX
MOVQ CX, 8(SP)
@@ -18,8 +20,9 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
// 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 argsize here, gc generates argsize info at call site.
+// No arg size here; runtime pulls arg map out of the func value.
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
+ NO_LOCAL_POINTERS
MOVQ DX, 0(SP)
LEAQ argframe+0(FP), CX
MOVQ CX, 8(SP)
diff --git a/src/pkg/reflect/asm_amd64p32.s b/src/reflect/asm_amd64p32.s
index 75413c752..0ffccf7d4 100644
--- a/src/pkg/reflect/asm_amd64p32.s
+++ b/src/reflect/asm_amd64p32.s
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
// 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 argsize here, gc generates argsize info at call site.
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
+ NO_LOCAL_POINTERS
MOVL DX, 0(SP)
LEAL argframe+0(FP), CX
MOVL CX, 4(SP)
@@ -20,6 +22,7 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
// for more details.
// No argsize here, gc generates argsize info at call site.
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
+ NO_LOCAL_POINTERS
MOVL DX, 0(SP)
LEAL argframe+0(FP), CX
MOVL CX, 4(SP)
diff --git a/src/pkg/reflect/asm_arm.s b/src/reflect/asm_arm.s
index 68ded4ac6..5a14c6f81 100644
--- a/src/pkg/reflect/asm_arm.s
+++ b/src/reflect/asm_arm.s
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
// makeFuncStub is jumped to by the code generated by MakeFunc.
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No argsize here, gc generates argsize info at call site.
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
+ NO_LOCAL_POINTERS
MOVW R7, 4(R13)
MOVW $argframe+0(FP), R1
MOVW R1, 8(R13)
@@ -20,6 +22,7 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
// for more details.
// No argsize here, gc generates argsize info at call site.
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
+ NO_LOCAL_POINTERS
MOVW R7, 4(R13)
MOVW $argframe+0(FP), R1
MOVW R1, 8(R13)
diff --git a/src/pkg/reflect/deepequal.go b/src/reflect/deepequal.go
index f63715c9a..f63715c9a 100644
--- a/src/pkg/reflect/deepequal.go
+++ b/src/reflect/deepequal.go
diff --git a/src/pkg/reflect/example_test.go b/src/reflect/example_test.go
index cca28eeec..cca28eeec 100644
--- a/src/pkg/reflect/example_test.go
+++ b/src/reflect/example_test.go
diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go
new file mode 100644
index 000000000..caaf51a50
--- /dev/null
+++ b/src/reflect/export_test.go
@@ -0,0 +1,38 @@
+// 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 reflect
+
+// MakeRO returns a copy of v with the read-only flag set.
+func MakeRO(v Value) Value {
+ v.flag |= flagRO
+ return v
+}
+
+// IsRO reports whether v's read-only flag is set.
+func IsRO(v Value) bool {
+ return v.flag&flagRO != 0
+}
+
+var ArrayOf = arrayOf
+var CallGC = &callGC
+
+const PtrSize = ptrSize
+const BitsPointer = bitsPointer
+const BitsScalar = bitsScalar
+
+func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr, stack []byte) {
+ var ft *rtype
+ var s *bitVector
+ if rcvr != nil {
+ ft, argSize, retOffset, s = funcLayout(t.(*rtype), rcvr.(*rtype))
+ } else {
+ ft, argSize, retOffset, s = funcLayout(t.(*rtype), nil)
+ }
+ frametype = ft
+ for i := uint32(0); i < s.n; i += 2 {
+ stack = append(stack, s.data[i/8]>>(i%8)&3)
+ }
+ return
+}
diff --git a/src/pkg/reflect/makefunc.go b/src/reflect/makefunc.go
index 0e61fdea7..d89f7f681 100644
--- a/src/pkg/reflect/makefunc.go
+++ b/src/reflect/makefunc.go
@@ -13,9 +13,10 @@ import (
// makeFuncImpl is the closure value implementing the function
// returned by MakeFunc.
type makeFuncImpl struct {
- code uintptr
- typ *funcType
- fn func([]Value) []Value
+ code uintptr
+ stack *bitVector // stack bitmap for args - offset known to runtime
+ typ *funcType
+ fn func([]Value) []Value
}
// MakeFunc returns a new function of the given Type
@@ -54,9 +55,12 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
dummy := makeFuncStub
code := **(**uintptr)(unsafe.Pointer(&dummy))
- impl := &makeFuncImpl{code: code, typ: ftyp, fn: fn}
+ // makeFuncImpl contains a stack map for use by the runtime
+ _, _, _, stack := funcLayout(t, nil)
- return Value{t, unsafe.Pointer(impl), 0, flag(Func) << flagKindShift}
+ impl := &makeFuncImpl{code: code, stack: stack, typ: ftyp, fn: fn}
+
+ return Value{t, unsafe.Pointer(impl), flag(Func)}
}
// makeFuncStub is an assembly function that is the code half of
@@ -68,6 +72,7 @@ func makeFuncStub()
type methodValue struct {
fn uintptr
+ stack *bitVector // stack bitmap for args - offset known to runtime
method int
rcvr Value
}
@@ -86,8 +91,8 @@ func makeMethodValue(op string, v Value) Value {
// Ignoring the flagMethod bit, v describes the receiver, not the method type.
fl := v.flag & (flagRO | flagAddr | flagIndir)
- fl |= flag(v.typ.Kind()) << flagKindShift
- rcvr := Value{v.typ, v.ptr, v.scalar, fl}
+ fl |= flag(v.typ.Kind())
+ rcvr := Value{v.typ, v.ptr, fl}
// v.Type returns the actual type of the method value.
funcType := v.Type().(*rtype)
@@ -98,8 +103,12 @@ func makeMethodValue(op string, v Value) Value {
dummy := methodValueCall
code := **(**uintptr)(unsafe.Pointer(&dummy))
+ // methodValue contains a stack map for use by the runtime
+ _, _, _, stack := funcLayout(funcType, nil)
+
fv := &methodValue{
fn: code,
+ stack: stack,
method: int(v.flag) >> flagMethodShift,
rcvr: rcvr,
}
@@ -109,7 +118,7 @@ func makeMethodValue(op string, v Value) Value {
// but we want Interface() and other operations to fail early.
methodReceiver(op, fv.rcvr, fv.method)
- return Value{funcType, unsafe.Pointer(fv), 0, v.flag&flagRO | flag(Func)<<flagKindShift}
+ return Value{funcType, unsafe.Pointer(fv), v.flag&flagRO | flag(Func)}
}
// methodValueCall is an assembly function that is the code half of
diff --git a/src/pkg/reflect/set_test.go b/src/reflect/set_test.go
index 85dc55e68..85dc55e68 100644
--- a/src/pkg/reflect/set_test.go
+++ b/src/reflect/set_test.go
diff --git a/src/pkg/reflect/tostring_test.go b/src/reflect/tostring_test.go
index e416fd84d..e416fd84d 100644
--- a/src/pkg/reflect/tostring_test.go
+++ b/src/reflect/tostring_test.go
diff --git a/src/pkg/reflect/type.go b/src/reflect/type.go
index 40d76f99d..c0ddfcad0 100644
--- a/src/pkg/reflect/type.go
+++ b/src/reflect/type.go
@@ -96,6 +96,9 @@ type Type interface {
// ConvertibleTo returns true if a value of the type is convertible to type u.
ConvertibleTo(u Type) bool
+ // Comparable returns true if values of this type are comparable.
+ Comparable() bool
+
// Methods applicable only to some types, depending on Kind.
// The methods allowed for each kind are:
//
@@ -242,18 +245,27 @@ const (
// with a unique tag like `reflect:"array"` or `reflect:"ptr"`
// so that code cannot convert from, say, *arrayType to *ptrType.
type rtype struct {
- size uintptr // size in bytes
- 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 *uintptr // algorithm table (../runtime/runtime.h:/Alg)
- gc unsafe.Pointer // 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
+ size 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 (../runtime/runtime.h:/Alg)
+ gc [2]unsafe.Pointer // 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
+}
+
+type typeAlg struct {
+ // function for hashing objects of this type
+ // (ptr to object, size, seed) -> hash
+ hash func(unsafe.Pointer, uintptr, uintptr) uintptr
+ // function for comparing objects of this type
+ // (ptr to object A, ptr to object B, size) -> ==?
+ equal func(unsafe.Pointer, unsafe.Pointer, uintptr) bool
}
// Method on non-interface type
@@ -323,11 +335,16 @@ type interfaceType struct {
// mapType represents a map type.
type mapType struct {
- rtype `reflect:"map"`
- key *rtype // map key type
- elem *rtype // map element (value) type
- bucket *rtype // internal bucket structure
- hmap *rtype // internal map header
+ rtype `reflect:"map"`
+ key *rtype // map key type
+ elem *rtype // map element (value) type
+ bucket *rtype // internal bucket structure
+ hmap *rtype // internal map header
+ keysize uint8 // size of key slot
+ indirectkey uint8 // store ptr to key instead of key itself
+ valuesize uint8 // size of value slot
+ indirectvalue uint8 // store ptr to value instead of value itself
+ bucketsize uint16 // size of bucket
}
// ptrType represents a pointer type.
@@ -357,24 +374,6 @@ type structType struct {
fields []structField // sorted by offset
}
-// NOTE: These are copied from ../runtime/mgc0.h.
-// They must be kept in sync.
-const (
- _GC_END = iota
- _GC_PTR
- _GC_APTR
- _GC_ARRAY_START
- _GC_ARRAY_NEXT
- _GC_CALL
- _GC_CHAN_PTR
- _GC_STRING
- _GC_EFACE
- _GC_IFACE
- _GC_SLICE
- _GC_REGION
- _GC_NUM_INSTR
-)
-
/*
* The compiler knows the exact layout of all the data structures above.
* The compiler does not know about the data structures and methods below.
@@ -396,11 +395,11 @@ type Method struct {
Index int // index for Type.Method
}
-// High bit says whether type has
-// embedded pointers,to help garbage collector.
const (
- kindMask = 0x7f
- kindNoPointers = 0x80
+ kindDirectIface = 1 << 5
+ kindGCProg = 1 << 6 // Type.gc points to GC program
+ kindNoPointers = 1 << 7
+ kindMask = (1 << 5) - 1
)
func (k Kind) String() string {
@@ -491,7 +490,7 @@ func (t *uncommonType) Method(i int) (m Method) {
if p.name != nil {
m.Name = *p.name
}
- fl := flag(Func) << flagKindShift
+ fl := flag(Func)
if p.pkgPath != nil {
m.PkgPath = *p.pkgPath
fl |= flagRO
@@ -499,7 +498,7 @@ func (t *uncommonType) Method(i int) (m Method) {
mt := p.typ
m.Type = mt
fn := unsafe.Pointer(&p.tfn)
- m.Func = Value{mt, fn, 0, fl}
+ m.Func = Value{mt, fn, fl}
m.Index = i
return
}
@@ -1013,32 +1012,6 @@ var ptrMap struct {
m map[*rtype]*ptrType
}
-// garbage collection bytecode program for pointer to memory without pointers.
-// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
-type ptrDataGC struct {
- width uintptr // sizeof(ptr)
- op uintptr // _GC_APTR
- off uintptr // 0
- end uintptr // _GC_END
-}
-
-var ptrDataGCProg = ptrDataGC{
- width: unsafe.Sizeof((*byte)(nil)),
- op: _GC_APTR,
- off: 0,
- end: _GC_END,
-}
-
-// garbage collection bytecode program for pointer to memory with pointers.
-// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
-type ptrGC struct {
- width uintptr // sizeof(ptr)
- op uintptr // _GC_PTR
- off uintptr // 0
- elemgc unsafe.Pointer // element gc type
- end uintptr // _GC_END
-}
-
// PtrTo returns the pointer type with element t.
// For example, if t represents type Foo, PtrTo(t) represents *Foo.
func PtrTo(t Type) Type {
@@ -1096,20 +1069,6 @@ func (t *rtype) ptrTo() *rtype {
p.zero = unsafe.Pointer(&make([]byte, p.size)[0])
p.elem = t
- if t.kind&kindNoPointers != 0 {
- p.gc = unsafe.Pointer(&ptrDataGCProg)
- } else {
- p.gc = unsafe.Pointer(&ptrGC{
- width: p.size,
- op: _GC_PTR,
- off: 0,
- elemgc: t.gc,
- end: _GC_END,
- })
- }
- // INCORRECT. Uncomment to check that TestPtrToGC fails when p.gc is wrong.
- //p.gc = unsafe.Pointer(&badGC{width: p.size, end: _GC_END})
-
ptrMap.m[t] = p
ptrMap.Unlock()
return &p.rtype
@@ -1149,6 +1108,10 @@ func (t *rtype) ConvertibleTo(u Type) bool {
return convertOp(uu, t) != nil
}
+func (t *rtype) Comparable() bool {
+ return t.alg != nil && t.alg.equal != nil
+}
+
// implements returns true if the type V implements the interface type T.
func implements(T, V *rtype) bool {
if T.Kind() != Interface {
@@ -1414,21 +1377,6 @@ func cachePut(k cacheKey, t *rtype) Type {
return t
}
-// garbage collection bytecode program for chan.
-// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
-type chanGC struct {
- width uintptr // sizeof(map)
- op uintptr // _GC_CHAN_PTR
- off uintptr // 0
- typ *rtype // map type
- end uintptr // _GC_END
-}
-
-type badGC struct {
- width uintptr
- end uintptr
-}
-
// ChanOf returns the channel type with the given direction and element type.
// For example, if t represents int, ChanOf(RecvDir, t) represents <-chan int.
//
@@ -1482,17 +1430,6 @@ func ChanOf(dir ChanDir, t Type) Type {
ch.ptrToThis = nil
ch.zero = unsafe.Pointer(&make([]byte, ch.size)[0])
- ch.gc = unsafe.Pointer(&chanGC{
- width: ch.size,
- op: _GC_CHAN_PTR,
- off: 0,
- typ: &ch.rtype,
- end: _GC_END,
- })
-
- // INCORRECT. Uncomment to check that TestChanOfGC fails when ch.gc is wrong.
- //ch.gc = unsafe.Pointer(&badGC{width: ch.size, end: _GC_END})
-
return cachePut(ckey, &ch.rtype)
}
@@ -1537,166 +1474,177 @@ func MapOf(key, elem Type) Type {
mt.key = ktyp
mt.elem = etyp
mt.bucket = bucketOf(ktyp, etyp)
- mt.hmap = hMapOf(mt.bucket)
+ if ktyp.size > maxKeySize {
+ mt.keysize = uint8(ptrSize)
+ mt.indirectkey = 1
+ } else {
+ mt.keysize = uint8(ktyp.size)
+ mt.indirectkey = 0
+ }
+ if etyp.size > maxValSize {
+ mt.valuesize = uint8(ptrSize)
+ mt.indirectvalue = 1
+ } else {
+ mt.valuesize = uint8(etyp.size)
+ mt.indirectvalue = 0
+ }
+ mt.bucketsize = uint16(mt.bucket.size)
mt.uncommonType = nil
mt.ptrToThis = nil
mt.zero = unsafe.Pointer(&make([]byte, mt.size)[0])
- mt.gc = unsafe.Pointer(&ptrGC{
- width: unsafe.Sizeof(uintptr(0)),
- op: _GC_PTR,
- off: 0,
- elemgc: mt.hmap.gc,
- end: _GC_END,
- })
-
- // INCORRECT. Uncomment to check that TestMapOfGC and TestMapOfGCValues
- // fail when mt.gc is wrong.
- //mt.gc = unsafe.Pointer(&badGC{width: mt.size, end: _GC_END})
return cachePut(ckey, &mt.rtype)
}
-// Make sure these routines stay in sync with ../../pkg/runtime/hashmap.c!
+// gcProg is a helper type for generatation of GC pointer info.
+type gcProg struct {
+ gc []byte
+ size uintptr // size of type in bytes
+}
+
+func (gc *gcProg) append(v byte) {
+ gc.align(unsafe.Sizeof(uintptr(0)))
+ gc.appendWord(v)
+}
+
+// Appends t's type info to the current program.
+func (gc *gcProg) appendProg(t *rtype) {
+ gc.align(uintptr(t.align))
+ if !t.pointers() {
+ gc.size += t.size
+ return
+ }
+ switch t.Kind() {
+ default:
+ panic("reflect: non-pointer type marked as having pointers")
+ case Ptr, UnsafePointer, Chan, Func, Map:
+ gc.appendWord(bitsPointer)
+ case Slice:
+ gc.appendWord(bitsPointer)
+ gc.appendWord(bitsScalar)
+ gc.appendWord(bitsScalar)
+ case String:
+ gc.appendWord(bitsPointer)
+ gc.appendWord(bitsScalar)
+ case Array:
+ c := t.Len()
+ e := t.Elem().common()
+ for i := 0; i < c; i++ {
+ gc.appendProg(e)
+ }
+ case Interface:
+ gc.appendWord(bitsMultiWord)
+ if t.NumMethod() == 0 {
+ gc.appendWord(bitsEface)
+ } else {
+ gc.appendWord(bitsIface)
+ }
+ case Struct:
+ c := t.NumField()
+ for i := 0; i < c; i++ {
+ gc.appendProg(t.Field(i).Type.common())
+ }
+ gc.align(uintptr(t.align))
+ }
+}
+
+func (gc *gcProg) appendWord(v byte) {
+ ptrsize := unsafe.Sizeof(uintptr(0))
+ if gc.size%ptrsize != 0 {
+ panic("reflect: unaligned GC program")
+ }
+ nptr := gc.size / ptrsize
+ for uintptr(len(gc.gc)) < nptr/2+1 {
+ gc.gc = append(gc.gc, 0x44) // BitsScalar
+ }
+ gc.gc[nptr/2] &= ^(3 << ((nptr%2)*4 + 2))
+ gc.gc[nptr/2] |= v << ((nptr%2)*4 + 2)
+ gc.size += ptrsize
+}
+
+func (gc *gcProg) finalize() unsafe.Pointer {
+ if gc.size == 0 {
+ return nil
+ }
+ ptrsize := unsafe.Sizeof(uintptr(0))
+ gc.align(ptrsize)
+ nptr := gc.size / ptrsize
+ for uintptr(len(gc.gc)) < nptr/2+1 {
+ gc.gc = append(gc.gc, 0x44) // BitsScalar
+ }
+ // If number of words is odd, repeat the mask twice.
+ // Compiler does the same.
+ if nptr%2 != 0 {
+ for i := uintptr(0); i < nptr; i++ {
+ gc.appendWord(extractGCWord(gc.gc, i))
+ }
+ }
+ return unsafe.Pointer(&gc.gc[0])
+}
+
+func extractGCWord(gc []byte, i uintptr) byte {
+ return (gc[i/2] >> ((i%2)*4 + 2)) & 3
+}
+
+func (gc *gcProg) align(a uintptr) {
+ gc.size = align(gc.size, a)
+}
+
+// These constants must stay in sync with ../runtime/mgc0.h.
+const (
+ bitsScalar = 1
+ bitsPointer = 2
+ bitsMultiWord = 3
+
+ bitsIface = 2
+ bitsEface = 3
+)
+
+// 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
// for possible debugging use.
const (
- _BUCKETSIZE = 8
- _MAXKEYSIZE = 128
- _MAXVALSIZE = 128
+ bucketSize = 8
+ maxKeySize = 128
+ maxValSize = 128
)
func bucketOf(ktyp, etyp *rtype) *rtype {
- if ktyp.size > _MAXKEYSIZE {
+ if ktyp.size > maxKeySize {
ktyp = PtrTo(ktyp).(*rtype)
}
- if etyp.size > _MAXVALSIZE {
+ if etyp.size > maxValSize {
etyp = PtrTo(etyp).(*rtype)
}
ptrsize := unsafe.Sizeof(uintptr(0))
- gc := make([]uintptr, 1) // first entry is size, filled in at the end
- offset := _BUCKETSIZE * unsafe.Sizeof(uint8(0)) // topbits
- gc = append(gc, _GC_PTR, offset, 0 /*self pointer set below*/) // overflow
- offset += ptrsize
-
+ var gc gcProg
+ // topbits
+ for i := 0; i < int(bucketSize*unsafe.Sizeof(uint8(0))/ptrsize); i++ {
+ gc.append(bitsScalar)
+ }
+ gc.append(bitsPointer) // overflow
if runtime.GOARCH == "amd64p32" {
- offset += 4
+ gc.append(bitsScalar)
}
-
// keys
- if ktyp.kind&kindNoPointers == 0 {
- gc = append(gc, _GC_ARRAY_START, offset, _BUCKETSIZE, ktyp.size)
- gc = appendGCProgram(gc, ktyp)
- gc = append(gc, _GC_ARRAY_NEXT)
+ for i := 0; i < bucketSize; i++ {
+ gc.appendProg(ktyp)
}
- offset += _BUCKETSIZE * ktyp.size
-
// values
- if etyp.kind&kindNoPointers == 0 {
- gc = append(gc, _GC_ARRAY_START, offset, _BUCKETSIZE, etyp.size)
- gc = appendGCProgram(gc, etyp)
- gc = append(gc, _GC_ARRAY_NEXT)
+ for i := 0; i < bucketSize; i++ {
+ gc.appendProg(etyp)
}
- offset += _BUCKETSIZE * etyp.size
-
- gc = append(gc, _GC_END)
- gc[0] = offset
- gc[3] = uintptr(unsafe.Pointer(&gc[0])) // set self pointer
b := new(rtype)
- b.size = offset
- b.gc = unsafe.Pointer(&gc[0])
+ b.size = gc.size
+ b.gc[0] = gc.finalize()
s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
b.string = &s
return b
}
-// Take the GC program for "t" and append it to the GC program "gc".
-func appendGCProgram(gc []uintptr, t *rtype) []uintptr {
- p := t.gc
- p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0))) // skip size
-loop:
- for {
- var argcnt int
- switch *(*uintptr)(p) {
- case _GC_END:
- // Note: _GC_END not included in append
- break loop
- case _GC_ARRAY_NEXT:
- argcnt = 0
- case _GC_APTR, _GC_STRING, _GC_EFACE, _GC_IFACE:
- argcnt = 1
- case _GC_PTR, _GC_CALL, _GC_CHAN_PTR, _GC_SLICE:
- argcnt = 2
- case _GC_ARRAY_START, _GC_REGION:
- argcnt = 3
- default:
- panic("unknown GC program op for " + *t.string + ": " + strconv.FormatUint(*(*uint64)(p), 10))
- }
- for i := 0; i < argcnt+1; i++ {
- gc = append(gc, *(*uintptr)(p))
- p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0)))
- }
- }
- return gc
-}
-func hMapOf(bucket *rtype) *rtype {
- ptrsize := unsafe.Sizeof(uintptr(0))
-
- // make gc program & compute hmap size
- gc := make([]uintptr, 1) // first entry is size, filled in at the end
- offset := unsafe.Sizeof(uint(0)) // count
- offset += unsafe.Sizeof(uint32(0)) // flags
- offset += unsafe.Sizeof(uint32(0)) // hash0
- offset += unsafe.Sizeof(uint8(0)) // B
- offset += unsafe.Sizeof(uint8(0)) // keysize
- offset += unsafe.Sizeof(uint8(0)) // valuesize
- offset = (offset + 1) / 2 * 2
- offset += unsafe.Sizeof(uint16(0)) // bucketsize
- offset = (offset + ptrsize - 1) / ptrsize * ptrsize
- gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // buckets
- offset += ptrsize
- gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // oldbuckets
- offset += ptrsize
- offset += ptrsize // nevacuate
- gc = append(gc, _GC_END)
- gc[0] = offset
-
- h := new(rtype)
- h.size = offset
- h.gc = unsafe.Pointer(&gc[0])
- s := "hmap(" + *bucket.string + ")"
- h.string = &s
- return h
-}
-
-// garbage collection bytecode program for slice of non-zero-length values.
-// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
-type sliceGC struct {
- width uintptr // sizeof(slice)
- op uintptr // _GC_SLICE
- off uintptr // 0
- elemgc unsafe.Pointer // element gc program
- end uintptr // _GC_END
-}
-
-// garbage collection bytecode program for slice of zero-length values.
-// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
-type sliceEmptyGC struct {
- width uintptr // sizeof(slice)
- op uintptr // _GC_APTR
- off uintptr // 0
- end uintptr // _GC_END
-}
-
-var sliceEmptyGCProg = sliceEmptyGC{
- width: unsafe.Sizeof([]byte(nil)),
- op: _GC_APTR,
- off: 0,
- end: _GC_END,
-}
-
// SliceOf returns the slice type with element type t.
// For example, if t represents int, SliceOf(t) represents []int.
func SliceOf(t Type) Type {
@@ -1729,21 +1677,6 @@ func SliceOf(t Type) Type {
slice.ptrToThis = nil
slice.zero = unsafe.Pointer(&make([]byte, slice.size)[0])
- if typ.size == 0 {
- slice.gc = unsafe.Pointer(&sliceEmptyGCProg)
- } else {
- slice.gc = unsafe.Pointer(&sliceGC{
- width: slice.size,
- op: _GC_SLICE,
- off: 0,
- elemgc: typ.gc,
- end: _GC_END,
- })
- }
-
- // INCORRECT. Uncomment to check that TestSliceOfOfGC fails when slice.gc is wrong.
- //slice.gc = unsafe.Pointer(&badGC{width: slice.size, end: _GC_END})
-
return cachePut(ckey, &slice.rtype)
}
@@ -1755,6 +1688,8 @@ func SliceOf(t Type) Type {
//
// TODO(rsc): Unexported for now. Export once the alg field is set correctly
// for the type. This may require significant work.
+//
+// TODO(rsc): TestArrayOf is also disabled. Re-enable.
func arrayOf(count int, elem Type) Type {
typ := elem.(*rtype)
slice := SliceOf(elem)
@@ -1779,6 +1714,7 @@ func arrayOf(count int, elem Type) Type {
prototype := *(**arrayType)(unsafe.Pointer(&iarray))
array := new(arrayType)
*array = *prototype
+ // TODO: Set extra kind bits correctly.
array.string = &s
array.hash = fnv1(typ.hash, '[')
for n := uint32(count); n > 0; n >>= 8 {
@@ -1795,6 +1731,7 @@ func arrayOf(count int, elem Type) Type {
array.fieldAlign = typ.fieldAlign
// TODO: array.alg
// TODO: array.gc
+ // TODO:
array.uncommonType = nil
array.ptrToThis = nil
array.zero = unsafe.Pointer(&make([]byte, array.size)[0])
@@ -1825,6 +1762,7 @@ type layoutType struct {
t *rtype
argSize uintptr // size of arguments
retOffset uintptr // offset of return values.
+ stack *bitVector
}
var layoutCache struct {
@@ -1838,7 +1776,7 @@ var layoutCache struct {
// The returned type exists only for GC, so we only fill out GC relevant info.
// Currently, that's just size and the GC program. We also fill in
// the name for possible debugging use.
-func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uintptr) {
+func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uintptr, stack *bitVector) {
if t.Kind() != Func {
panic("reflect: funcLayout of non-func type")
}
@@ -1849,61 +1787,60 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
layoutCache.RLock()
if x := layoutCache.m[k]; x.t != nil {
layoutCache.RUnlock()
- return x.t, x.argSize, x.retOffset
+ return x.t, x.argSize, x.retOffset, x.stack
}
layoutCache.RUnlock()
layoutCache.Lock()
if x := layoutCache.m[k]; x.t != nil {
layoutCache.Unlock()
- return x.t, x.argSize, x.retOffset
+ return x.t, x.argSize, x.retOffset, x.stack
}
tt := (*funcType)(unsafe.Pointer(t))
- // compute gc program for arguments
- gc := make([]uintptr, 1) // first entry is size, filled in at the end
- offset := uintptr(0)
+ // compute gc program & stack bitmap for arguments
+ stack = new(bitVector)
+ var gc gcProg
+ var offset uintptr
if rcvr != nil {
// Reflect uses the "interface" calling convention for
// methods, where receivers take one word of argument
// space no matter how big they actually are.
- if rcvr.size > ptrSize {
+ if ifaceIndir(rcvr) {
// we pass a pointer to the receiver.
- gc = append(gc, _GC_PTR, offset, uintptr(rcvr.gc))
+ gc.append(bitsPointer)
+ stack.append2(bitsPointer)
} else if rcvr.pointers() {
// rcvr is a one-word pointer object. Its gc program
// is just what we need here.
- gc = appendGCProgram(gc, rcvr)
+ gc.append(bitsPointer)
+ stack.append2(bitsPointer)
+ } else {
+ gc.append(bitsScalar)
+ stack.append2(bitsScalar)
}
offset += ptrSize
}
for _, arg := range tt.in {
- offset = align(offset, uintptr(arg.align))
- if arg.pointers() {
- gc = append(gc, _GC_REGION, offset, arg.size, uintptr(arg.gc))
- }
- offset += arg.size
+ gc.appendProg(arg)
+ addTypeBits(stack, &offset, arg)
}
- argSize = offset
+ argSize = gc.size
if runtime.GOARCH == "amd64p32" {
- offset = align(offset, 8)
+ gc.align(8)
}
- offset = align(offset, ptrSize)
- retOffset = offset
+ gc.align(ptrSize)
+ retOffset = gc.size
for _, res := range tt.out {
- offset = align(offset, uintptr(res.align))
- if res.pointers() {
- gc = append(gc, _GC_REGION, offset, res.size, uintptr(res.gc))
- }
- offset += res.size
+ gc.appendProg(res)
+ // stack map does not need result bits
}
- gc = append(gc, _GC_END)
- gc[0] = offset
+ gc.align(ptrSize)
// build dummy rtype holding gc program
x := new(rtype)
- x.size = offset
- x.gc = unsafe.Pointer(&gc[0])
+ x.size = gc.size
+ x.gc[0] = gc.finalize()
var s string
if rcvr != nil {
s = "methodargs(" + *rcvr.string + ")(" + *t.string + ")"
@@ -1920,7 +1857,73 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
t: x,
argSize: argSize,
retOffset: retOffset,
+ stack: stack,
}
layoutCache.Unlock()
- return x, argSize, retOffset
+ return x, argSize, retOffset, stack
+}
+
+// ifaceIndir reports whether t is stored indirectly in an interface value.
+func ifaceIndir(t *rtype) bool {
+ return t.kind&kindDirectIface == 0
+}
+
+// Layout matches runtime.BitVector (well enough).
+type bitVector struct {
+ n uint32 // number of bits
+ data []byte
+}
+
+// append a bit pair to the bitmap.
+func (bv *bitVector) append2(bits uint8) {
+ // assume bv.n is a multiple of 2, since append2 is the only operation.
+ if bv.n%8 == 0 {
+ bv.data = append(bv.data, 0)
+ }
+ bv.data[bv.n/8] |= bits << (bv.n % 8)
+ bv.n += 2
+}
+
+func addTypeBits(bv *bitVector, offset *uintptr, t *rtype) {
+ *offset = align(*offset, uintptr(t.align))
+ if t.kind&kindNoPointers != 0 {
+ *offset += t.size
+ return
+ }
+
+ switch Kind(t.kind & kindMask) {
+ case Chan, Func, Map, Ptr, Slice, String, UnsafePointer:
+ // 1 pointer at start of representation
+ for bv.n < 2*uint32(*offset/uintptr(ptrSize)) {
+ bv.append2(bitsScalar)
+ }
+ bv.append2(bitsPointer)
+
+ case Interface:
+ // 2 pointers
+ for bv.n < 2*uint32(*offset/uintptr(ptrSize)) {
+ bv.append2(bitsScalar)
+ }
+ bv.append2(bitsPointer)
+ bv.append2(bitsPointer)
+
+ case Array:
+ // repeat inner type
+ tt := (*arrayType)(unsafe.Pointer(t))
+ for i := 0; i < int(tt.len); i++ {
+ addTypeBits(bv, offset, tt.elem)
+ }
+
+ case Struct:
+ // apply fields
+ tt := (*structType)(unsafe.Pointer(t))
+ start := *offset
+ for i := range tt.fields {
+ f := &tt.fields[i]
+ off := start + f.offset
+ addTypeBits(bv, &off, f.typ)
+ }
+ }
+
+ *offset += t.size
}
diff --git a/src/pkg/reflect/value.go b/src/reflect/value.go
index 576cbc398..43843e963 100644
--- a/src/pkg/reflect/value.go
+++ b/src/reflect/value.go
@@ -7,40 +7,12 @@ package reflect
import (
"math"
"runtime"
- "strconv"
"unsafe"
)
-const bigEndian = false // can be smarter if we find a big-endian machine
const ptrSize = unsafe.Sizeof((*byte)(nil))
const cannotSet = "cannot set value obtained from unexported struct field"
-// TODO: This will have to go away when
-// the new gc goes in.
-func memmove(adst, asrc unsafe.Pointer, n uintptr) {
- dst := uintptr(adst)
- src := uintptr(asrc)
- switch {
- case src < dst && src+n > dst:
- // byte copy backward
- // careful: i is unsigned
- for i := n; i > 0; {
- i--
- *(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
- }
- case (n|src|dst)&(ptrSize-1) != 0:
- // byte copy forward
- for i := uintptr(0); i < n; i++ {
- *(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
- }
- default:
- // word copy forward
- for i := uintptr(0); i < n; i += ptrSize {
- *(*uintptr)(unsafe.Pointer(dst + i)) = *(*uintptr)(unsafe.Pointer(src + i))
- }
- }
-}
-
// Value is the reflection interface to a Go value.
//
// Not all methods apply to all kinds of values. Restrictions,
@@ -66,12 +38,6 @@ type Value struct {
// Valid when either flagIndir is set or typ.pointers() is true.
ptr unsafe.Pointer
- // Non-pointer-valued data. When the data is smaller
- // than a word, it begins at the first byte (in the memory
- // address sense) of this field.
- // Valid when flagIndir is not set and typ.pointers() is false.
- scalar uintptr
-
// flag holds metadata about the value.
// The lowest bits are flag bits:
// - flagRO: obtained via unexported field, so read-only
@@ -82,7 +48,7 @@ type Value struct {
// This repeats typ.Kind() except for method values.
// The remaining 23+ bits give a method number for method values.
// If flag.kind() != Func, code can assume that flagMethod is unset.
- // If typ.size > ptrSize, code can assume that flagIndir is set.
+ // If ifaceIndir(typ), code can assume that flagIndir is set.
flag
// A method value represents a curried method invocation
@@ -95,18 +61,17 @@ type Value struct {
type flag uintptr
const (
- flagRO flag = 1 << iota
- flagIndir
- flagAddr
- flagMethod
- flagKindShift = iota
flagKindWidth = 5 // there are 27 kinds
flagKindMask flag = 1<<flagKindWidth - 1
- flagMethodShift = flagKindShift + flagKindWidth
+ flagRO flag = 1 << 5
+ flagIndir flag = 1 << 6
+ flagAddr flag = 1 << 7
+ flagMethod flag = 1 << 8
+ flagMethodShift = 9
)
func (f flag) kind() Kind {
- return Kind((f >> flagKindShift) & flagKindMask)
+ return Kind(f & flagKindMask)
}
// pointer returns the underlying pointer represented by v.
@@ -128,7 +93,10 @@ func packEface(v Value) interface{} {
e := (*emptyInterface)(unsafe.Pointer(&i))
// First, fill in the data portion of the interface.
switch {
- case t.size > ptrSize:
+ case ifaceIndir(t):
+ if v.flag&flagIndir == 0 {
+ panic("bad indir")
+ }
// Value is indirect, and so is the interface we're making.
ptr := v.ptr
if v.flag&flagAddr != 0 {
@@ -138,22 +106,14 @@ func packEface(v Value) interface{} {
memmove(c, ptr, t.size)
ptr = c
}
- e.word = iword(ptr)
+ e.word = ptr
case v.flag&flagIndir != 0:
// Value is indirect, but interface is direct. We need
// to load the data at v.ptr into the interface data word.
- if t.pointers() {
- e.word = iword(*(*unsafe.Pointer)(v.ptr))
- } else {
- e.word = iword(loadScalar(v.ptr, t.size))
- }
+ e.word = *(*unsafe.Pointer)(v.ptr)
default:
// Value is direct, and so is the interface.
- if t.pointers() {
- e.word = iword(v.ptr)
- } else {
- e.word = iword(v.scalar)
- }
+ e.word = v.ptr
}
// Now, fill in the type portion. We're very careful here not
// to have any operation between the e.word and e.typ assignments
@@ -171,14 +131,11 @@ func unpackEface(i interface{}) Value {
if t == nil {
return Value{}
}
- f := flag(t.Kind()) << flagKindShift
- if t.size > ptrSize {
- return Value{t, unsafe.Pointer(e.word), 0, f | flagIndir}
- }
- if t.pointers() {
- return Value{t, unsafe.Pointer(e.word), 0, f}
+ f := flag(t.Kind())
+ if ifaceIndir(t) {
+ f |= flagIndir
}
- return Value{t, nil, uintptr(e.word), f}
+ return Value{t, unsafe.Pointer(e.word), f}
}
// A ValueError occurs when a Value method is invoked on
@@ -207,78 +164,10 @@ func methodName() string {
return f.Name()
}
-// An iword is the word that would be stored in an
-// interface to represent a given value v. Specifically, if v is
-// bigger than a pointer, its word is a pointer to v's data.
-// Otherwise, its word holds the data stored
-// in its leading bytes (so is not a pointer).
-// This type is very dangerous for the garbage collector because
-// it must be treated conservatively. We try to never expose it
-// to the GC here so that GC remains precise.
-type iword unsafe.Pointer
-
-// loadScalar loads n bytes at p from memory into a uintptr
-// that forms the second word of an interface. The data
-// must be non-pointer in nature.
-func loadScalar(p unsafe.Pointer, n uintptr) uintptr {
- // Run the copy ourselves instead of calling memmove
- // to avoid moving w to the heap.
- var w uintptr
- switch n {
- default:
- panic("reflect: internal error: loadScalar of " + strconv.Itoa(int(n)) + "-byte value")
- case 0:
- case 1:
- *(*uint8)(unsafe.Pointer(&w)) = *(*uint8)(p)
- case 2:
- *(*uint16)(unsafe.Pointer(&w)) = *(*uint16)(p)
- case 3:
- *(*[3]byte)(unsafe.Pointer(&w)) = *(*[3]byte)(p)
- case 4:
- *(*uint32)(unsafe.Pointer(&w)) = *(*uint32)(p)
- case 5:
- *(*[5]byte)(unsafe.Pointer(&w)) = *(*[5]byte)(p)
- case 6:
- *(*[6]byte)(unsafe.Pointer(&w)) = *(*[6]byte)(p)
- case 7:
- *(*[7]byte)(unsafe.Pointer(&w)) = *(*[7]byte)(p)
- case 8:
- *(*uint64)(unsafe.Pointer(&w)) = *(*uint64)(p)
- }
- return w
-}
-
-// storeScalar stores n bytes from w into p.
-func storeScalar(p unsafe.Pointer, w uintptr, n uintptr) {
- // Run the copy ourselves instead of calling memmove
- // to avoid moving w to the heap.
- switch n {
- default:
- panic("reflect: internal error: storeScalar of " + strconv.Itoa(int(n)) + "-byte value")
- case 0:
- case 1:
- *(*uint8)(p) = *(*uint8)(unsafe.Pointer(&w))
- case 2:
- *(*uint16)(p) = *(*uint16)(unsafe.Pointer(&w))
- case 3:
- *(*[3]byte)(p) = *(*[3]byte)(unsafe.Pointer(&w))
- case 4:
- *(*uint32)(p) = *(*uint32)(unsafe.Pointer(&w))
- case 5:
- *(*[5]byte)(p) = *(*[5]byte)(unsafe.Pointer(&w))
- case 6:
- *(*[6]byte)(p) = *(*[6]byte)(unsafe.Pointer(&w))
- case 7:
- *(*[7]byte)(p) = *(*[7]byte)(unsafe.Pointer(&w))
- case 8:
- *(*uint64)(p) = *(*uint64)(unsafe.Pointer(&w))
- }
-}
-
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
typ *rtype
- word iword
+ word unsafe.Pointer
}
// nonEmptyInterface is the header for a interface value with methods.
@@ -292,7 +181,7 @@ type nonEmptyInterface struct {
unused int32
fun [100000]unsafe.Pointer // method table
}
- word iword
+ word unsafe.Pointer
}
// mustBe panics if f's kind is not expected.
@@ -302,9 +191,8 @@ type nonEmptyInterface struct {
// v.flag.mustBe(Bool), which will only bother to copy the
// single important word for the receiver.
func (f flag) mustBe(expected Kind) {
- k := f.kind()
- if k != expected {
- panic(&ValueError{methodName(), k})
+ if f.kind() != expected {
+ panic(&ValueError{methodName(), f.kind()})
}
}
@@ -344,17 +232,14 @@ func (v Value) Addr() Value {
if v.flag&flagAddr == 0 {
panic("reflect.Value.Addr of unaddressable value")
}
- return Value{v.typ.ptrTo(), v.ptr, 0, (v.flag & flagRO) | flag(Ptr)<<flagKindShift}
+ return Value{v.typ.ptrTo(), v.ptr, (v.flag & flagRO) | flag(Ptr)}
}
// Bool returns v's underlying value.
// It panics if v's kind is not Bool.
func (v Value) Bool() bool {
v.mustBe(Bool)
- if v.flag&flagIndir != 0 {
- return *(*bool)(v.ptr)
- }
- return *(*bool)(unsafe.Pointer(&v.scalar))
+ return *(*bool)(v.ptr)
}
// Bytes returns v's underlying value.
@@ -426,11 +311,6 @@ func (v Value) CallSlice(in []Value) []Value {
var callGC bool // for testing; see TestCallMethodJump
-var makeFuncStubFn = makeFuncStub
-var makeFuncStubCode = **(**uintptr)(unsafe.Pointer(&makeFuncStubFn))
-var methodValueCallFn = methodValueCall
-var methodValueCallCode = **(**uintptr)(unsafe.Pointer(&methodValueCallFn))
-
func (v Value) call(op string, in []Value) []Value {
// Get function pointer, type.
t := v.typ
@@ -509,30 +389,8 @@ func (v Value) call(op string, in []Value) []Value {
}
nout := t.NumOut()
- // If target is makeFuncStub, short circuit the unpack onto stack /
- // pack back into []Value for the args and return values. Just do the
- // call directly.
- // We need to do this here because otherwise we have a situation where
- // reflect.callXX calls makeFuncStub, neither of which knows the
- // layout of the args. That's bad for precise gc & stack copying.
- x := (*makeFuncImpl)(fn)
- if x.code == makeFuncStubCode {
- return x.fn(in)
- }
-
- // If the target is methodValueCall, do its work here: add the receiver
- // argument and call the real target directly.
- // We need to do this here because otherwise we have a situation where
- // reflect.callXX calls methodValueCall, neither of which knows the
- // layout of the args. That's bad for precise gc & stack copying.
- y := (*methodValue)(fn)
- if y.fn == methodValueCallCode {
- rcvr = y.rcvr
- rcvrtype, t, fn = methodReceiver("call", rcvr, y.method)
- }
-
// Compute frame type, allocate a chunk of memory for frame
- frametype, _, retOffset := funcLayout(t, rcvrtype)
+ frametype, _, retOffset, _ := funcLayout(t, rcvrtype)
args := unsafe_New(frametype)
off := uintptr(0)
@@ -548,13 +406,11 @@ func (v Value) call(op string, in []Value) []Value {
off = (off + a - 1) &^ (a - 1)
n := targ.size
addr := unsafe.Pointer(uintptr(args) + off)
- v = v.assignTo("reflect.Value.Call", targ, (*interface{})(addr))
+ v = v.assignTo("reflect.Value.Call", targ, addr)
if v.flag&flagIndir != 0 {
memmove(addr, v.ptr, n)
- } else if targ.pointers() {
- *(*unsafe.Pointer)(addr) = v.ptr
} else {
- storeScalar(addr, v.scalar, n)
+ *(*unsafe.Pointer)(addr) = v.ptr
}
off += n
}
@@ -574,8 +430,8 @@ func (v Value) call(op string, in []Value) []Value {
tv := t.Out(i)
a := uintptr(tv.Align())
off = (off + a - 1) &^ (a - 1)
- fl := flagIndir | flag(tv.Kind())<<flagKindShift
- ret[i] = Value{tv.common(), unsafe.Pointer(uintptr(args) + off), 0, fl}
+ fl := flagIndir | flag(tv.Kind())
+ ret[i] = Value{tv.common(), unsafe.Pointer(uintptr(args) + off), fl}
off += tv.Size()
}
@@ -606,19 +462,17 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
typ := arg
off += -off & uintptr(typ.align-1)
addr := unsafe.Pointer(uintptr(ptr) + off)
- v := Value{typ, nil, 0, flag(typ.Kind()) << flagKindShift}
- if typ.size > ptrSize {
- // value does not fit in word.
+ v := Value{typ, nil, flag(typ.Kind())}
+ if ifaceIndir(typ) {
+ // value cannot be inlined in interface data.
// Must make a copy, because f might keep a reference to it,
// and we cannot let f keep a reference to the stack frame
// after this function returns, not even a read-only reference.
v.ptr = unsafe_New(typ)
memmove(v.ptr, addr, typ.size)
v.flag |= flagIndir
- } else if typ.pointers() {
- v.ptr = *(*unsafe.Pointer)(addr)
} else {
- v.scalar = loadScalar(addr, typ.size)
+ v.ptr = *(*unsafe.Pointer)(addr)
}
in = append(in, v)
off += typ.size
@@ -652,10 +506,8 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
addr := unsafe.Pointer(uintptr(ptr) + off)
if v.flag&flagIndir != 0 {
memmove(addr, v.ptr, typ.size)
- } else if typ.pointers() {
- *(*unsafe.Pointer)(addr) = v.ptr
} else {
- storeScalar(addr, v.scalar, typ.size)
+ *(*unsafe.Pointer)(addr) = v.ptr
}
off += typ.size
}
@@ -673,7 +525,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
i := methodIndex
if v.typ.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(v.typ))
- if i < 0 || i >= len(tt.methods) {
+ if uint(i) >= uint(len(tt.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &tt.methods[i]
@@ -690,7 +542,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
} else {
rcvrtype = v.typ
ut := v.typ.uncommon()
- if ut == nil || i < 0 || i >= len(ut.methods) {
+ if ut == nil || uint(i) >= uint(len(ut.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &ut.methods[i]
@@ -713,18 +565,10 @@ func storeRcvr(v Value, p unsafe.Pointer) {
// the interface data word becomes the receiver word
iface := (*nonEmptyInterface)(v.ptr)
*(*unsafe.Pointer)(p) = unsafe.Pointer(iface.word)
- } else if v.flag&flagIndir != 0 {
- if t.size > ptrSize {
- *(*unsafe.Pointer)(p) = v.ptr
- } else if t.pointers() {
- *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr)
- } else {
- *(*uintptr)(p) = loadScalar(v.ptr, t.size)
- }
- } else if t.pointers() {
- *(*unsafe.Pointer)(p) = v.ptr
+ } else if v.flag&flagIndir != 0 && !ifaceIndir(t) {
+ *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr)
} else {
- *(*uintptr)(p) = v.scalar
+ *(*unsafe.Pointer)(p) = v.ptr
}
}
@@ -748,7 +592,7 @@ func align(x, n uintptr) uintptr {
func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
rcvr := ctxt.rcvr
rcvrtype, t, fn := methodReceiver("call", rcvr, ctxt.method)
- frametype, argSize, retOffset := funcLayout(t, rcvrtype)
+ frametype, argSize, retOffset, _ := funcLayout(t, rcvrtype)
// Make a new frame that is one word bigger so we can store the receiver.
args := unsafe_New(frametype)
@@ -796,7 +640,7 @@ func (v Value) Cap() int {
// Slice is always bigger than a word; assume flagIndir.
return (*sliceHeader)(v.ptr).Cap
}
- panic(&ValueError{"reflect.Value.Cap", k})
+ panic(&ValueError{"reflect.Value.Cap", v.kind()})
}
// Close closes the channel v.
@@ -813,15 +657,11 @@ func (v Value) Complex() complex128 {
k := v.kind()
switch k {
case Complex64:
- if v.flag&flagIndir != 0 {
- return complex128(*(*complex64)(v.ptr))
- }
- return complex128(*(*complex64)(unsafe.Pointer(&v.scalar)))
+ return complex128(*(*complex64)(v.ptr))
case Complex128:
- // complex128 is always bigger than a word; assume flagIndir.
return *(*complex128)(v.ptr)
}
- panic(&ValueError{"reflect.Value.Complex", k})
+ panic(&ValueError{"reflect.Value.Complex", v.kind()})
}
// Elem returns the value that the interface v contains
@@ -841,7 +681,9 @@ func (v Value) Elem() Value {
})(v.ptr))
}
x := unpackEface(eface)
- x.flag |= v.flag & flagRO
+ if x.flag != 0 {
+ x.flag |= v.flag & flagRO
+ }
return x
case Ptr:
ptr := v.ptr
@@ -855,56 +697,46 @@ func (v Value) Elem() Value {
tt := (*ptrType)(unsafe.Pointer(v.typ))
typ := tt.elem
fl := v.flag&flagRO | flagIndir | flagAddr
- fl |= flag(typ.Kind() << flagKindShift)
- return Value{typ, ptr, 0, fl}
+ fl |= flag(typ.Kind())
+ return Value{typ, ptr, fl}
}
- panic(&ValueError{"reflect.Value.Elem", k})
+ panic(&ValueError{"reflect.Value.Elem", v.kind()})
}
// Field returns the i'th field of the struct v.
// It panics if v's Kind is not Struct or i is out of range.
func (v Value) Field(i int) Value {
- v.mustBe(Struct)
+ if v.kind() != Struct {
+ panic(&ValueError{"reflect.Value.Field", v.kind()})
+ }
tt := (*structType)(unsafe.Pointer(v.typ))
- if i < 0 || i >= len(tt.fields) {
+ if uint(i) >= uint(len(tt.fields)) {
panic("reflect: Field index out of range")
}
field := &tt.fields[i]
typ := field.typ
// Inherit permission bits from v.
- fl := v.flag & (flagRO | flagIndir | flagAddr)
+ fl := v.flag&(flagRO|flagIndir|flagAddr) | flag(typ.Kind())
// Using an unexported field forces flagRO.
if field.pkgPath != nil {
fl |= flagRO
}
- fl |= flag(typ.Kind()) << flagKindShift
-
- var ptr unsafe.Pointer
- var scalar uintptr
- switch {
- case fl&flagIndir != 0:
- // Indirect. Just bump pointer.
- ptr = unsafe.Pointer(uintptr(v.ptr) + field.offset)
- case typ.pointers():
- if field.offset != 0 {
- panic("field access of ptr value isn't at offset 0")
- }
- ptr = v.ptr
- case bigEndian:
- // Must be scalar. Discard leading bytes.
- scalar = v.scalar << (field.offset * 8)
- default:
- // Must be scalar. Discard leading bytes.
- scalar = v.scalar >> (field.offset * 8)
- }
-
- return Value{typ, ptr, scalar, fl}
+ // Either flagIndir is set and v.ptr points at struct,
+ // or flagIndir is not set and v.ptr is the actual struct data.
+ // In the former case, we want v.ptr + offset.
+ // In the latter case, we must be have field.offset = 0,
+ // so v.ptr + field.offset is still okay.
+ ptr := unsafe.Pointer(uintptr(v.ptr) + field.offset)
+ return Value{typ, ptr, fl}
}
// FieldByIndex returns the nested field corresponding to index.
// It panics if v's Kind is not struct.
func (v Value) FieldByIndex(index []int) Value {
+ if len(index) == 1 {
+ return v.Field(index[0])
+ }
v.mustBe(Struct)
for i, x := range index {
if i > 0 {
@@ -936,7 +768,6 @@ func (v Value) FieldByName(name string) Value {
// It panics if v's Kind is not struct.
// It returns the zero Value if no field was found.
func (v Value) FieldByNameFunc(match func(string) bool) Value {
- v.mustBe(Struct)
if f, ok := v.typ.FieldByNameFunc(match); ok {
return v.FieldByIndex(f.Index)
}
@@ -949,17 +780,11 @@ func (v Value) Float() float64 {
k := v.kind()
switch k {
case Float32:
- if v.flag&flagIndir != 0 {
- return float64(*(*float32)(v.ptr))
- }
- return float64(*(*float32)(unsafe.Pointer(&v.scalar)))
+ return float64(*(*float32)(v.ptr))
case Float64:
- if v.flag&flagIndir != 0 {
- return *(*float64)(v.ptr)
- }
- return *(*float64)(unsafe.Pointer(&v.scalar))
+ return *(*float64)(v.ptr)
}
- panic(&ValueError{"reflect.Value.Float", k})
+ panic(&ValueError{"reflect.Value.Float", v.kind()})
}
var uint8Type = TypeOf(uint8(0)).(*rtype)
@@ -967,77 +792,54 @@ var uint8Type = TypeOf(uint8(0)).(*rtype)
// Index returns v's i'th element.
// It panics if v's Kind is not Array, Slice, or String or i is out of range.
func (v Value) Index(i int) Value {
- k := v.kind()
- switch k {
+ switch v.kind() {
case Array:
tt := (*arrayType)(unsafe.Pointer(v.typ))
- if i < 0 || i > int(tt.len) {
+ if uint(i) >= uint(tt.len) {
panic("reflect: array index out of range")
}
typ := tt.elem
- fl := v.flag & (flagRO | flagIndir | flagAddr) // bits same as overall array
- fl |= flag(typ.Kind()) << flagKindShift
offset := uintptr(i) * typ.size
- var val unsafe.Pointer
- var scalar uintptr
- switch {
- case fl&flagIndir != 0:
- // Indirect. Just bump pointer.
- val = unsafe.Pointer(uintptr(v.ptr) + offset)
- case typ.pointers():
- if offset != 0 {
- panic("can't Index(i) with i!=0 on ptrLike value")
- }
- val = v.ptr
- case bigEndian:
- // Direct. Discard leading bytes.
- scalar = v.scalar << (offset * 8)
- default:
- // Direct. Discard leading bytes.
- scalar = v.scalar >> (offset * 8)
- }
- return Value{typ, val, scalar, fl}
+ // Either flagIndir is set and v.ptr points at array,
+ // or flagIndir is not set and v.ptr is the actual array data.
+ // In the former case, we want v.ptr + offset.
+ // In the latter case, we must be doing Index(0), so offset = 0,
+ // so v.ptr + offset is still okay.
+ val := unsafe.Pointer(uintptr(v.ptr) + offset)
+ fl := v.flag&(flagRO|flagIndir|flagAddr) | flag(typ.Kind()) // bits same as overall array
+ return Value{typ, val, fl}
case Slice:
// Element flag same as Elem of Ptr.
// Addressable, indirect, possibly read-only.
- fl := flagAddr | flagIndir | v.flag&flagRO
s := (*sliceHeader)(v.ptr)
- if i < 0 || i >= s.Len {
+ if uint(i) >= uint(s.Len) {
panic("reflect: slice index out of range")
}
tt := (*sliceType)(unsafe.Pointer(v.typ))
typ := tt.elem
- fl |= flag(typ.Kind()) << flagKindShift
val := unsafe.Pointer(uintptr(s.Data) + uintptr(i)*typ.size)
- return Value{typ, val, 0, fl}
+ fl := flagAddr | flagIndir | v.flag&flagRO | flag(typ.Kind())
+ return Value{typ, val, fl}
case String:
- fl := v.flag&flagRO | flag(Uint8<<flagKindShift)
s := (*stringHeader)(v.ptr)
- if i < 0 || i >= s.Len {
+ if uint(i) >= uint(s.Len) {
panic("reflect: string index out of range")
}
- b := uintptr(0)
- *(*byte)(unsafe.Pointer(&b)) = *(*byte)(unsafe.Pointer(uintptr(s.Data) + uintptr(i)))
- return Value{uint8Type, nil, b, fl}
+ p := unsafe.Pointer(uintptr(s.Data) + uintptr(i))
+ fl := v.flag&flagRO | flag(Uint8) | flagIndir
+ return Value{uint8Type, p, fl}
}
- panic(&ValueError{"reflect.Value.Index", k})
+ panic(&ValueError{"reflect.Value.Index", v.kind()})
}
// Int returns v's underlying value, as an int64.
// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64.
func (v Value) Int() int64 {
k := v.kind()
- var p unsafe.Pointer
- if v.flag&flagIndir != 0 {
- p = v.ptr
- } else {
- // The escape analysis is good enough that &v.scalar
- // does not trigger a heap allocation.
- p = unsafe.Pointer(&v.scalar)
- }
+ p := v.ptr
switch k {
case Int:
return int64(*(*int)(p))
@@ -1050,7 +852,7 @@ func (v Value) Int() int64 {
case Int64:
return int64(*(*int64)(p))
}
- panic(&ValueError{"reflect.Value.Int", k})
+ panic(&ValueError{"reflect.Value.Int", v.kind()})
}
// CanInterface returns true if Interface can be used without panicking.
@@ -1137,7 +939,7 @@ func (v Value) IsNil() bool {
// Both are always bigger than a word; assume flagIndir.
return *(*unsafe.Pointer)(v.ptr) == nil
}
- panic(&ValueError{"reflect.Value.IsNil", k})
+ panic(&ValueError{"reflect.Value.IsNil", v.kind()})
}
// IsValid returns true if v represents a value.
@@ -1174,7 +976,7 @@ func (v Value) Len() int {
// String is bigger than a word; assume flagIndir.
return (*stringHeader)(v.ptr).Len
}
- panic(&ValueError{"reflect.Value.Len", k})
+ panic(&ValueError{"reflect.Value.Len", v.kind()})
}
// MapIndex returns the value associated with key in the map v.
@@ -1197,10 +999,8 @@ func (v Value) MapIndex(key Value) Value {
var k unsafe.Pointer
if key.flag&flagIndir != 0 {
k = key.ptr
- } else if key.typ.pointers() {
- k = unsafe.Pointer(&key.ptr)
} else {
- k = unsafe.Pointer(&key.scalar)
+ k = unsafe.Pointer(&key.ptr)
}
e := mapaccess(v.typ, v.pointer(), k)
if e == nil {
@@ -1208,17 +1008,15 @@ func (v Value) MapIndex(key Value) Value {
}
typ := tt.elem
fl := (v.flag | key.flag) & flagRO
- fl |= flag(typ.Kind()) << flagKindShift
- if typ.size > ptrSize {
+ fl |= flag(typ.Kind())
+ if ifaceIndir(typ) {
// Copy result so future changes to the map
// won't change the underlying value.
c := unsafe_New(typ)
memmove(c, e, typ.size)
- return Value{typ, c, 0, fl | flagIndir}
- } else if typ.pointers() {
- return Value{typ, *(*unsafe.Pointer)(e), 0, fl}
+ return Value{typ, c, fl | flagIndir}
} else {
- return Value{typ, nil, loadScalar(e, typ.size), fl}
+ return Value{typ, *(*unsafe.Pointer)(e), fl}
}
}
@@ -1231,7 +1029,7 @@ func (v Value) MapKeys() []Value {
tt := (*mapType)(unsafe.Pointer(v.typ))
keyType := tt.key
- fl := v.flag&flagRO | flag(keyType.Kind())<<flagKindShift
+ fl := v.flag&flagRO | flag(keyType.Kind())
m := v.pointer()
mlen := int(0)
@@ -1249,16 +1047,14 @@ func (v Value) MapKeys() []Value {
// we can do about it.
break
}
- if keyType.size > ptrSize {
+ if ifaceIndir(keyType) {
// Copy result so future changes to the map
// won't change the underlying value.
c := unsafe_New(keyType)
memmove(c, key, keyType.size)
- a[i] = Value{keyType, c, 0, fl | flagIndir}
- } else if keyType.pointers() {
- a[i] = Value{keyType, *(*unsafe.Pointer)(key), 0, fl}
+ a[i] = Value{keyType, c, fl | flagIndir}
} else {
- a[i] = Value{keyType, nil, loadScalar(key, keyType.size), fl}
+ a[i] = Value{keyType, *(*unsafe.Pointer)(key), fl}
}
mapiternext(it)
}
@@ -1273,16 +1069,16 @@ func (v Value) Method(i int) Value {
if v.typ == nil {
panic(&ValueError{"reflect.Value.Method", Invalid})
}
- if v.flag&flagMethod != 0 || i < 0 || i >= v.typ.NumMethod() {
+ if v.flag&flagMethod != 0 || uint(i) >= uint(v.typ.NumMethod()) {
panic("reflect: Method index out of range")
}
if v.typ.Kind() == Interface && v.IsNil() {
panic("reflect: Method on nil interface value")
}
fl := v.flag & (flagRO | flagIndir)
- fl |= flag(Func) << flagKindShift
+ fl |= flag(Func)
fl |= flag(i)<<flagMethodShift | flagMethod
- return Value{v.typ, v.ptr, v.scalar, fl}
+ return Value{v.typ, v.ptr, fl}
}
// NumMethod returns the number of methods in the value's method set.
@@ -1333,7 +1129,7 @@ func (v Value) OverflowComplex(x complex128) bool {
case Complex128:
return false
}
- panic(&ValueError{"reflect.Value.OverflowComplex", k})
+ panic(&ValueError{"reflect.Value.OverflowComplex", v.kind()})
}
// OverflowFloat returns true if the float64 x cannot be represented by v's type.
@@ -1346,7 +1142,7 @@ func (v Value) OverflowFloat(x float64) bool {
case Float64:
return false
}
- panic(&ValueError{"reflect.Value.OverflowFloat", k})
+ panic(&ValueError{"reflect.Value.OverflowFloat", v.kind()})
}
func overflowFloat32(x float64) bool {
@@ -1366,7 +1162,7 @@ func (v Value) OverflowInt(x int64) bool {
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
return x != trunc
}
- panic(&ValueError{"reflect.Value.OverflowInt", k})
+ panic(&ValueError{"reflect.Value.OverflowInt", v.kind()})
}
// OverflowUint returns true if the uint64 x cannot be represented by v's type.
@@ -1379,7 +1175,7 @@ func (v Value) OverflowUint(x uint64) bool {
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
return x != trunc
}
- panic(&ValueError{"reflect.Value.OverflowUint", k})
+ panic(&ValueError{"reflect.Value.OverflowUint", v.kind()})
}
// Pointer returns v's value as a uintptr.
@@ -1424,7 +1220,7 @@ func (v Value) Pointer() uintptr {
case Slice:
return (*SliceHeader)(v.ptr).Data
}
- panic(&ValueError{"reflect.Value.Pointer", k})
+ panic(&ValueError{"reflect.Value.Pointer", v.kind()})
}
// Recv receives and returns a value from the channel v.
@@ -1446,16 +1242,14 @@ func (v Value) recv(nb bool) (val Value, ok bool) {
panic("reflect: recv on send-only channel")
}
t := tt.elem
- val = Value{t, nil, 0, flag(t.Kind()) << flagKindShift}
+ val = Value{t, nil, flag(t.Kind())}
var p unsafe.Pointer
- if t.size > ptrSize {
+ if ifaceIndir(t) {
p = unsafe_New(t)
val.ptr = p
val.flag |= flagIndir
- } else if t.pointers() {
- p = unsafe.Pointer(&val.ptr)
} else {
- p = unsafe.Pointer(&val.scalar)
+ p = unsafe.Pointer(&val.ptr)
}
selected, ok := chanrecv(v.typ, v.pointer(), nb, p)
if !selected {
@@ -1485,10 +1279,8 @@ func (v Value) send(x Value, nb bool) (selected bool) {
var p unsafe.Pointer
if x.flag&flagIndir != 0 {
p = x.ptr
- } else if x.typ.pointers() {
- p = unsafe.Pointer(&x.ptr)
} else {
- p = unsafe.Pointer(&x.scalar)
+ p = unsafe.Pointer(&x.ptr)
}
return chansend(v.typ, v.pointer(), p, nb)
}
@@ -1499,17 +1291,15 @@ func (v Value) send(x Value, nb bool) (selected bool) {
func (v Value) Set(x Value) {
v.mustBeAssignable()
x.mustBeExported() // do not let unexported x leak
- var target *interface{}
+ var target unsafe.Pointer
if v.kind() == Interface {
- target = (*interface{})(v.ptr)
+ target = v.ptr
}
x = x.assignTo("reflect.Set", v.typ, target)
if x.flag&flagIndir != 0 {
memmove(v.ptr, x.ptr, v.typ.size)
- } else if x.typ.pointers() {
- *(*unsafe.Pointer)(v.ptr) = x.ptr
} else {
- memmove(v.ptr, unsafe.Pointer(&x.scalar), v.typ.size)
+ *(*unsafe.Pointer)(v.ptr) = x.ptr
}
}
@@ -1549,7 +1339,7 @@ func (v Value) SetComplex(x complex128) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
- panic(&ValueError{"reflect.Value.SetComplex", k})
+ panic(&ValueError{"reflect.Value.SetComplex", v.kind()})
case Complex64:
*(*complex64)(v.ptr) = complex64(x)
case Complex128:
@@ -1563,7 +1353,7 @@ func (v Value) SetFloat(x float64) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
- panic(&ValueError{"reflect.Value.SetFloat", k})
+ panic(&ValueError{"reflect.Value.SetFloat", v.kind()})
case Float32:
*(*float32)(v.ptr) = float32(x)
case Float64:
@@ -1577,7 +1367,7 @@ func (v Value) SetInt(x int64) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
- panic(&ValueError{"reflect.Value.SetInt", k})
+ panic(&ValueError{"reflect.Value.SetInt", v.kind()})
case Int:
*(*int)(v.ptr) = int(x)
case Int8:
@@ -1598,7 +1388,7 @@ func (v Value) SetLen(n int) {
v.mustBeAssignable()
v.mustBe(Slice)
s := (*sliceHeader)(v.ptr)
- if n < 0 || n > int(s.Cap) {
+ if uint(n) > uint(s.Cap) {
panic("reflect: slice length out of range in SetLen")
}
s.Len = n
@@ -1632,10 +1422,8 @@ func (v Value) SetMapIndex(key, val Value) {
var k unsafe.Pointer
if key.flag&flagIndir != 0 {
k = key.ptr
- } else if key.typ.pointers() {
- k = unsafe.Pointer(&key.ptr)
} else {
- k = unsafe.Pointer(&key.scalar)
+ k = unsafe.Pointer(&key.ptr)
}
if val.typ == nil {
mapdelete(v.typ, v.pointer(), k)
@@ -1646,10 +1434,8 @@ func (v Value) SetMapIndex(key, val Value) {
var e unsafe.Pointer
if val.flag&flagIndir != 0 {
e = val.ptr
- } else if val.typ.pointers() {
- e = unsafe.Pointer(&val.ptr)
} else {
- e = unsafe.Pointer(&val.scalar)
+ e = unsafe.Pointer(&val.ptr)
}
mapassign(v.typ, v.pointer(), k, e)
}
@@ -1660,7 +1446,7 @@ func (v Value) SetUint(x uint64) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
- panic(&ValueError{"reflect.Value.SetUint", k})
+ panic(&ValueError{"reflect.Value.SetUint", v.kind()})
case Uint:
*(*uint)(v.ptr) = uint(x)
case Uint8:
@@ -1703,7 +1489,7 @@ func (v Value) Slice(i, j int) Value {
)
switch kind := v.kind(); kind {
default:
- panic(&ValueError{"reflect.Value.Slice", kind})
+ panic(&ValueError{"reflect.Value.Slice", v.kind()})
case Array:
if v.flag&flagAddr == 0 {
@@ -1726,7 +1512,7 @@ func (v Value) Slice(i, j int) Value {
panic("reflect.Value.Slice: string slice index out of bounds")
}
t := stringHeader{unsafe.Pointer(uintptr(s.Data) + uintptr(i)), j - i}
- return Value{v.typ, unsafe.Pointer(&t), 0, v.flag}
+ return Value{v.typ, unsafe.Pointer(&t), v.flag}
}
if i < 0 || j < i || j > cap {
@@ -1738,12 +1524,17 @@ func (v Value) Slice(i, j int) Value {
// Reinterpret as *sliceHeader to edit.
s := (*sliceHeader)(unsafe.Pointer(&x))
- s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
s.Len = j - i
s.Cap = cap - i
+ if cap-i > 0 {
+ s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
+ } else {
+ // do not advance pointer, to avoid pointing beyond end of slice
+ s.Data = base
+ }
- fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
- return Value{typ.common(), unsafe.Pointer(&x), 0, fl}
+ fl := v.flag&flagRO | flagIndir | flag(Slice)
+ return Value{typ.common(), unsafe.Pointer(&x), fl}
}
// Slice3 is the 3-index form of the slice operation: it returns v[i:j:k].
@@ -1757,7 +1548,7 @@ func (v Value) Slice3(i, j, k int) Value {
)
switch kind := v.kind(); kind {
default:
- panic(&ValueError{"reflect.Value.Slice3", kind})
+ panic(&ValueError{"reflect.Value.Slice3", v.kind()})
case Array:
if v.flag&flagAddr == 0 {
@@ -1785,12 +1576,17 @@ func (v Value) Slice3(i, j, k int) Value {
// Reinterpret as *sliceHeader to edit.
s := (*sliceHeader)(unsafe.Pointer(&x))
- s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
s.Len = j - i
s.Cap = k - i
+ if k-i > 0 {
+ s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
+ } else {
+ // do not advance pointer, to avoid pointing beyond end of slice
+ s.Data = base
+ }
- fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
- return Value{typ.common(), unsafe.Pointer(&x), 0, fl}
+ fl := v.flag&flagRO | flagIndir | flag(Slice)
+ return Value{typ.common(), unsafe.Pointer(&x), fl}
}
// String returns the string v's underlying value, as a string.
@@ -1806,7 +1602,7 @@ func (v Value) String() string {
}
// If you call String on a reflect.Value of other type, it's better to
// print something than to panic. Useful in debugging.
- return "<" + v.typ.String() + " Value>"
+ return "<" + v.Type().String() + " Value>"
}
// TryRecv attempts to receive a value from the channel v but will not block.
@@ -1847,7 +1643,7 @@ func (v Value) Type() Type {
if v.typ.Kind() == Interface {
// Method on interface.
tt := (*interfaceType)(unsafe.Pointer(v.typ))
- if i < 0 || i >= len(tt.methods) {
+ if uint(i) >= uint(len(tt.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &tt.methods[i]
@@ -1855,7 +1651,7 @@ func (v Value) Type() Type {
}
// Method on concrete type.
ut := v.typ.uncommon()
- if ut == nil || i < 0 || i >= len(ut.methods) {
+ if ut == nil || uint(i) >= uint(len(ut.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &ut.methods[i]
@@ -1866,14 +1662,7 @@ func (v Value) Type() Type {
// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
func (v Value) Uint() uint64 {
k := v.kind()
- var p unsafe.Pointer
- if v.flag&flagIndir != 0 {
- p = v.ptr
- } else {
- // The escape analysis is good enough that &v.scalar
- // does not trigger a heap allocation.
- p = unsafe.Pointer(&v.scalar)
- }
+ p := v.ptr
switch k {
case Uint:
return uint64(*(*uint)(p))
@@ -1888,7 +1677,7 @@ func (v Value) Uint() uint64 {
case Uintptr:
return uint64(*(*uintptr)(p))
}
- panic(&ValueError{"reflect.Value.Uint", k})
+ panic(&ValueError{"reflect.Value.Uint", v.kind()})
}
// UnsafeAddr returns a pointer to v's data.
@@ -2027,17 +1816,6 @@ func Copy(dst, src Value) int {
n = sn
}
- // If sk is an in-line array, cannot take its address.
- // Instead, copy element by element.
- // TODO: memmove would be ok for this (sa = unsafe.Pointer(&v.scalar))
- // if we teach the compiler that ptrs don't escape from memmove.
- if src.flag&flagIndir == 0 {
- for i := 0; i < n; i++ {
- dst.Index(i).Set(src.Index(i))
- }
- return n
- }
-
// Copy via memmove.
var da, sa unsafe.Pointer
if dk == Array {
@@ -2045,7 +1823,9 @@ func Copy(dst, src Value) int {
} else {
da = (*sliceHeader)(dst.ptr).Data
}
- if sk == Array {
+ if src.flag&flagIndir == 0 {
+ sa = unsafe.Pointer(&src.ptr)
+ } else if sk == Array {
sa = src.ptr
} else {
sa = (*sliceHeader)(src.ptr).Data
@@ -2055,7 +1835,7 @@ func Copy(dst, src Value) int {
}
// A runtimeSelect is a single case passed to rselect.
-// This must match ../runtime/chan.c:/runtimeSelect
+// This must match ../runtime/select.go:/runtimeSelect
type runtimeSelect struct {
dir uintptr // 0, SendDir, or RecvDir
typ *rtype // channel type
@@ -2073,7 +1853,7 @@ func rselect([]runtimeSelect) (chosen int, recvOK bool)
// A SelectDir describes the communication direction of a select case.
type SelectDir int
-// NOTE: These values must match ../runtime/chan.c:/SelectDir.
+// NOTE: These values must match ../runtime/select.go:/selectDir.
const (
_ SelectDir = iota
@@ -2158,10 +1938,8 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
v = v.assignTo("reflect.Select", tt.elem, nil)
if v.flag&flagIndir != 0 {
rc.val = v.ptr
- } else if v.typ.pointers() {
- rc.val = unsafe.Pointer(&v.ptr)
} else {
- rc.val = unsafe.Pointer(&v.scalar)
+ rc.val = unsafe.Pointer(&v.ptr)
}
case SelectRecv:
@@ -2189,13 +1967,11 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
tt := (*chanType)(unsafe.Pointer(runcases[chosen].typ))
t := tt.elem
p := runcases[chosen].val
- fl := flag(t.Kind()) << flagKindShift
- if t.size > ptrSize {
- recv = Value{t, p, 0, fl | flagIndir}
- } else if t.pointers() {
- recv = Value{t, *(*unsafe.Pointer)(p), 0, fl}
+ fl := flag(t.Kind())
+ if ifaceIndir(t) {
+ recv = Value{t, p, fl | flagIndir}
} else {
- recv = Value{t, nil, loadScalar(p, t.size), fl}
+ recv = Value{t, *(*unsafe.Pointer)(p), fl}
}
}
return chosen, recv, recvOK
@@ -2226,7 +2002,7 @@ func MakeSlice(typ Type, len, cap int) Value {
}
s := sliceHeader{unsafe_NewArray(typ.Elem().(*rtype), cap), len, cap}
- return Value{typ.common(), unsafe.Pointer(&s), 0, flagIndir | flag(Slice)<<flagKindShift}
+ return Value{typ.common(), unsafe.Pointer(&s), flagIndir | flag(Slice)}
}
// MakeChan creates a new channel with the specified type and buffer size.
@@ -2241,7 +2017,7 @@ func MakeChan(typ Type, buffer int) Value {
panic("reflect.MakeChan: unidirectional channel type")
}
ch := makechan(typ.(*rtype), uint64(buffer))
- return Value{typ.common(), ch, 0, flag(Chan) << flagKindShift}
+ return Value{typ.common(), ch, flag(Chan)}
}
// MakeMap creates a new map of the specified type.
@@ -2250,7 +2026,7 @@ func MakeMap(typ Type) Value {
panic("reflect.MakeMap of non-map type")
}
m := makemap(typ.(*rtype))
- return Value{typ.common(), m, 0, flag(Map) << flagKindShift}
+ return Value{typ.common(), m, flag(Map)}
}
// Indirect returns the value that v points to.
@@ -2290,11 +2066,11 @@ func Zero(typ Type) Value {
panic("reflect: Zero(nil)")
}
t := typ.common()
- fl := flag(t.Kind()) << flagKindShift
- if t.size <= ptrSize {
- return Value{t, nil, 0, fl}
+ fl := flag(t.Kind())
+ if ifaceIndir(t) {
+ return Value{t, unsafe_New(typ.(*rtype)), fl | flagIndir}
}
- return Value{t, unsafe_New(typ.(*rtype)), 0, fl | flagIndir}
+ return Value{t, nil, fl}
}
// New returns a Value representing a pointer to a new zero value
@@ -2304,21 +2080,21 @@ func New(typ Type) Value {
panic("reflect: New(nil)")
}
ptr := unsafe_New(typ.(*rtype))
- fl := flag(Ptr) << flagKindShift
- return Value{typ.common().ptrTo(), ptr, 0, fl}
+ fl := flag(Ptr)
+ return Value{typ.common().ptrTo(), ptr, fl}
}
// NewAt returns a Value representing a pointer to a value of the
// specified type, using p as that pointer.
func NewAt(typ Type, p unsafe.Pointer) Value {
- fl := flag(Ptr) << flagKindShift
- return Value{typ.common().ptrTo(), p, 0, fl}
+ fl := flag(Ptr)
+ return Value{typ.common().ptrTo(), p, fl}
}
// assignTo returns a value v that can be assigned directly to typ.
// It panics if v is not assignable to typ.
// For a conversion to an interface type, target is a suggested scratch space to use.
-func (v Value) assignTo(context string, dst *rtype, target *interface{}) Value {
+func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value {
if v.flag&flagMethod != 0 {
v = makeMethodValue(context, v)
}
@@ -2329,20 +2105,20 @@ func (v Value) assignTo(context string, dst *rtype, target *interface{}) Value {
// Same memory layout, so no harm done.
v.typ = dst
fl := v.flag & (flagRO | flagAddr | flagIndir)
- fl |= flag(dst.Kind()) << flagKindShift
- return Value{dst, v.ptr, v.scalar, fl}
+ fl |= flag(dst.Kind())
+ return Value{dst, v.ptr, fl}
case implements(dst, v.typ):
if target == nil {
- target = new(interface{})
+ target = unsafe_New(dst)
}
x := valueInterface(v, false)
if dst.NumMethod() == 0 {
- *target = x
+ *(*interface{})(target) = x
} else {
- ifaceE2I(dst, x, unsafe.Pointer(target))
+ ifaceE2I(dst, x, target)
}
- return Value{dst, unsafe.Pointer(target), 0, flagIndir | flag(Interface)<<flagKindShift}
+ return Value{dst, target, flagIndir | flag(Interface)}
}
// Failed.
@@ -2450,66 +2226,46 @@ func convertOp(dst, src *rtype) func(Value, Type) Value {
// where t is a signed or unsigned int type.
func makeInt(f flag, bits uint64, t Type) Value {
typ := t.common()
- if typ.size > ptrSize {
- // Assume ptrSize >= 4, so this must be uint64.
- ptr := unsafe_New(typ)
- *(*uint64)(unsafe.Pointer(ptr)) = bits
- return Value{typ, ptr, 0, f | flagIndir | flag(typ.Kind())<<flagKindShift}
- }
- var s uintptr
+ ptr := unsafe_New(typ)
switch typ.size {
case 1:
- *(*uint8)(unsafe.Pointer(&s)) = uint8(bits)
+ *(*uint8)(unsafe.Pointer(ptr)) = uint8(bits)
case 2:
- *(*uint16)(unsafe.Pointer(&s)) = uint16(bits)
+ *(*uint16)(unsafe.Pointer(ptr)) = uint16(bits)
case 4:
- *(*uint32)(unsafe.Pointer(&s)) = uint32(bits)
+ *(*uint32)(unsafe.Pointer(ptr)) = uint32(bits)
case 8:
- *(*uint64)(unsafe.Pointer(&s)) = uint64(bits)
+ *(*uint64)(unsafe.Pointer(ptr)) = bits
}
- return Value{typ, nil, s, f | flag(typ.Kind())<<flagKindShift}
+ return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
}
// makeFloat returns a Value of type t equal to v (possibly truncated to float32),
// where t is a float32 or float64 type.
func makeFloat(f flag, v float64, t Type) Value {
typ := t.common()
- if typ.size > ptrSize {
- // Assume ptrSize >= 4, so this must be float64.
- ptr := unsafe_New(typ)
- *(*float64)(unsafe.Pointer(ptr)) = v
- return Value{typ, ptr, 0, f | flagIndir | flag(typ.Kind())<<flagKindShift}
- }
-
- var s uintptr
+ ptr := unsafe_New(typ)
switch typ.size {
case 4:
- *(*float32)(unsafe.Pointer(&s)) = float32(v)
+ *(*float32)(unsafe.Pointer(ptr)) = float32(v)
case 8:
- *(*float64)(unsafe.Pointer(&s)) = v
+ *(*float64)(unsafe.Pointer(ptr)) = v
}
- return Value{typ, nil, s, f | flag(typ.Kind())<<flagKindShift}
+ return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
}
// makeComplex returns a Value of type t equal to v (possibly truncated to complex64),
// where t is a complex64 or complex128 type.
func makeComplex(f flag, v complex128, t Type) Value {
typ := t.common()
- if typ.size > ptrSize {
- ptr := unsafe_New(typ)
- switch typ.size {
- case 8:
- *(*complex64)(unsafe.Pointer(ptr)) = complex64(v)
- case 16:
- *(*complex128)(unsafe.Pointer(ptr)) = v
- }
- return Value{typ, ptr, 0, f | flagIndir | flag(typ.Kind())<<flagKindShift}
+ ptr := unsafe_New(typ)
+ switch typ.size {
+ case 8:
+ *(*complex64)(unsafe.Pointer(ptr)) = complex64(v)
+ case 16:
+ *(*complex128)(unsafe.Pointer(ptr)) = v
}
-
- // Assume ptrSize <= 8 so this must be complex64.
- var s uintptr
- *(*complex64)(unsafe.Pointer(&s)) = complex64(v)
- return Value{typ, nil, s, f | flag(typ.Kind())<<flagKindShift}
+ return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
}
func makeString(f flag, v string, t Type) Value {
@@ -2620,19 +2376,19 @@ func cvtDirect(v Value, typ Type) Value {
ptr = c
f &^= flagAddr
}
- return Value{t, ptr, v.scalar, v.flag&flagRO | f} // v.flag&flagRO|f == f?
+ return Value{t, ptr, v.flag&flagRO | f} // v.flag&flagRO|f == f?
}
// convertOp: concrete -> interface
func cvtT2I(v Value, typ Type) Value {
- target := new(interface{})
+ target := unsafe_New(typ.common())
x := valueInterface(v, false)
if typ.NumMethod() == 0 {
- *target = x
+ *(*interface{})(target) = x
} else {
- ifaceE2I(typ.(*rtype), x, unsafe.Pointer(target))
+ ifaceE2I(typ.(*rtype), x, target)
}
- return Value{typ.common(), unsafe.Pointer(target), 0, v.flag&flagRO | flagIndir | flag(Interface)<<flagKindShift}
+ return Value{typ.common(), target, v.flag&flagRO | flagIndir | flag(Interface)}
}
// convertOp: interface -> interface
@@ -2645,7 +2401,7 @@ func cvtI2I(v Value, typ Type) Value {
return cvtT2I(v.Elem(), typ)
}
-// implemented in ../pkg/runtime
+// implemented in ../runtime
func chancap(ch unsafe.Pointer) int
func chanclose(ch unsafe.Pointer)
func chanlen(ch unsafe.Pointer) int
@@ -2665,10 +2421,13 @@ func mapiterinit(t *rtype, m unsafe.Pointer) unsafe.Pointer
func mapiterkey(it unsafe.Pointer) (key unsafe.Pointer)
func mapiternext(it unsafe.Pointer)
func maplen(m unsafe.Pointer) int
-
func call(fn, arg unsafe.Pointer, n uint32, retoffset uint32)
+
func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
+//go:noescape
+func memmove(adst, asrc unsafe.Pointer, n uintptr)
+
// Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that
// the compiler cannot follow.
diff --git a/src/pkg/regexp/all_test.go b/src/regexp/all_test.go
index 301a1dfcd..01ea3742a 100644
--- a/src/pkg/regexp/all_test.go
+++ b/src/regexp/all_test.go
@@ -6,6 +6,7 @@ package regexp
import (
"reflect"
+ "regexp/syntax"
"strings"
"testing"
)
@@ -473,9 +474,19 @@ func TestSplit(t *testing.T) {
}
}
-// This ran out of stack before issue 7608 was fixed.
+// Check that one-pass cutoff does trigger.
func TestOnePassCutoff(t *testing.T) {
- MustCompile(`^(?:x{1,1000}){1,1000}$`)
+ re, err := syntax.Parse(`^x{1,1000}y{1,1000}$`, syntax.Perl)
+ if err != nil {
+ t.Fatalf("parse: %v", err)
+ }
+ p, err := syntax.Compile(re.Simplify())
+ if err != nil {
+ t.Fatalf("compile: %v", err)
+ }
+ if compileOnePass(p) != notOnePass {
+ t.Fatalf("makeOnePass succeeded; wanted notOnePass")
+ }
}
func BenchmarkLiteral(b *testing.B) {
diff --git a/src/pkg/regexp/example_test.go b/src/regexp/example_test.go
index a4e0da8ea..a4e0da8ea 100644
--- a/src/pkg/regexp/example_test.go
+++ b/src/regexp/example_test.go
diff --git a/src/pkg/regexp/exec.go b/src/regexp/exec.go
index c4cb201f6..c4cb201f6 100644
--- a/src/pkg/regexp/exec.go
+++ b/src/regexp/exec.go
diff --git a/src/pkg/regexp/exec2_test.go b/src/regexp/exec2_test.go
index 7b86b4115..7b86b4115 100644
--- a/src/pkg/regexp/exec2_test.go
+++ b/src/regexp/exec2_test.go
diff --git a/src/pkg/regexp/exec_test.go b/src/regexp/exec_test.go
index 70d069c06..70d069c06 100644
--- a/src/pkg/regexp/exec_test.go
+++ b/src/regexp/exec_test.go
diff --git a/src/pkg/regexp/find_test.go b/src/regexp/find_test.go
index e07eb7d5c..e07eb7d5c 100644
--- a/src/pkg/regexp/find_test.go
+++ b/src/regexp/find_test.go
diff --git a/src/pkg/regexp/onepass.go b/src/regexp/onepass.go
index 501fb28af..e6f428563 100644
--- a/src/pkg/regexp/onepass.go
+++ b/src/regexp/onepass.go
@@ -1,4 +1,6 @@
// 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 regexp
@@ -9,9 +11,6 @@ import (
"unicode"
)
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
// "One-pass" regexp execution.
// Some regexps can be analyzed to determine that they never need
// backtracking: they are guaranteed to run in one pass over the string
@@ -484,7 +483,7 @@ func makeOnePass(p *onePassProg) *onePassProg {
}
}
if p != notOnePass {
- for i, _ := range p.Inst {
+ for i := range p.Inst {
p.Inst[i].Rune = onePassRunes[i]
}
}
diff --git a/src/pkg/regexp/onepass_test.go b/src/regexp/onepass_test.go
index 7b2beea67..7b2beea67 100644
--- a/src/pkg/regexp/onepass_test.go
+++ b/src/regexp/onepass_test.go
diff --git a/src/pkg/regexp/regexp.go b/src/regexp/regexp.go
index 0b8336a04..b615acdf0 100644
--- a/src/pkg/regexp/regexp.go
+++ b/src/regexp/regexp.go
@@ -452,7 +452,7 @@ func (re *Regexp) ReplaceAllString(src, repl string) string {
return string(b)
}
-// ReplaceAllStringLiteral returns a copy of src, replacing matches of the Regexp
+// ReplaceAllLiteralString returns a copy of src, replacing matches of the Regexp
// with the replacement string repl. The replacement repl is substituted directly,
// without using Expand.
func (re *Regexp) ReplaceAllLiteralString(src, repl string) string {
diff --git a/src/pkg/regexp/syntax/compile.go b/src/regexp/syntax/compile.go
index 95f6f1569..95f6f1569 100644
--- a/src/pkg/regexp/syntax/compile.go
+++ b/src/regexp/syntax/compile.go
diff --git a/src/pkg/regexp/syntax/doc.go b/src/regexp/syntax/doc.go
index 8e72c90d3..e5e71f14f 100644
--- a/src/pkg/regexp/syntax/doc.go
+++ b/src/regexp/syntax/doc.go
@@ -21,8 +21,8 @@ Single characters:
[^xyz] negated character class
\d Perl character class
\D negated Perl character class
- [:alpha:] ASCII character class
- [:^alpha:] negated ASCII character class
+ [[:alpha:]] ASCII character class
+ [[:^alpha:]] negated ASCII character class
\pN Unicode character class (one-letter name)
\p{Greek} Unicode character class
\PN negated Unicode character class (one-letter name)
@@ -46,14 +46,14 @@ Repetitions:
x{n,}? n or more x, prefer fewer
x{n}? exactly n x
-Implementation restriction: The counting forms x{n} etc. (but not the other
-forms x* etc.) have an upper limit of n=1000. Negative or higher explicit
-counts yield the parse error ErrInvalidRepeatSize.
+Implementation restriction: The counting forms x{n,m}, x{n,}, and x{n}
+reject forms that create a minimum or maximum repetition count above 1000.
+Unlimited repetitions are not subject to this restriction.
Grouping:
(re) numbered capturing group (submatch)
(?P<name>re) named & numbered capturing group (submatch)
- (?:re) non-capturing group (submatch)
+ (?:re) non-capturing group
(?flags) set flags within current group; non-capturing
(?flags:re) set flags during re; non-capturing
@@ -69,7 +69,7 @@ Empty strings:
$ at end of text (like \z not \Z) or line (flag m=true)
\A at beginning of text
\b at ASCII word boundary (\w on one side and \W, \A, or \z on the other)
- \B not an ASCII word boundary
+ \B not at ASCII word boundary
\z at end of text
Escape sequences:
@@ -103,29 +103,29 @@ Named character classes as character class elements:
[\p{Name}] named Unicode property inside character class (== \p{Name})
[^\p{Name}] named Unicode property inside negated character class (== \P{Name})
-Perl character classes:
+Perl character classes (all ASCII-only):
\d digits (== [0-9])
\D not digits (== [^0-9])
\s whitespace (== [\t\n\f\r ])
\S not whitespace (== [^\t\n\f\r ])
- \w ASCII word characters (== [0-9A-Za-z_])
- \W not ASCII word characters (== [^0-9A-Za-z_])
+ \w word characters (== [0-9A-Za-z_])
+ \W not word characters (== [^0-9A-Za-z_])
ASCII character classes:
- [:alnum:] alphanumeric (== [0-9A-Za-z])
- [:alpha:] alphabetic (== [A-Za-z])
- [:ascii:] ASCII (== [\x00-\x7F])
- [:blank:] blank (== [\t ])
- [:cntrl:] control (== [\x00-\x1F\x7F])
- [:digit:] digits (== [0-9])
- [:graph:] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])
- [:lower:] lower case (== [a-z])
- [:print:] printable (== [ -~] == [ [:graph:]])
- [:punct:] punctuation (== [!-/:-@[-`{-~])
- [:space:] whitespace (== [\t\n\v\f\r ])
- [:upper:] upper case (== [A-Z])
- [:word:] word characters (== [0-9A-Za-z_])
- [:xdigit:] hex digit (== [0-9A-Fa-f])
+ [[:alnum:]] alphanumeric (== [0-9A-Za-z])
+ [[:alpha:]] alphabetic (== [A-Za-z])
+ [[:ascii:]] ASCII (== [\x00-\x7F])
+ [[:blank:]] blank (== [\t ])
+ [[:cntrl:]] control (== [\x00-\x1F\x7F])
+ [[:digit:]] digits (== [0-9])
+ [[:graph:]] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])
+ [[:lower:]] lower case (== [a-z])
+ [[:print:]] printable (== [ -~] == [ [:graph:]])
+ [[:punct:]] punctuation (== [!-/:-@[-`{-~])
+ [[:space:]] whitespace (== [\t\n\v\f\r ])
+ [[:upper:]] upper case (== [A-Z])
+ [[:word:]] word characters (== [0-9A-Za-z_])
+ [[:xdigit:]] hex digit (== [0-9A-Fa-f])
*/
package syntax
diff --git a/src/pkg/regexp/syntax/make_perl_groups.pl b/src/regexp/syntax/make_perl_groups.pl
index 90040fcb4..90040fcb4 100755
--- a/src/pkg/regexp/syntax/make_perl_groups.pl
+++ b/src/regexp/syntax/make_perl_groups.pl
diff --git a/src/pkg/regexp/syntax/parse.go b/src/regexp/syntax/parse.go
index cb25dca39..d579a4069 100644
--- a/src/pkg/regexp/syntax/parse.go
+++ b/src/regexp/syntax/parse.go
@@ -244,6 +244,7 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (
if sub.Op >= opPseudo {
return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]}
}
+
re := p.newRegexp(op)
re.Min = min
re.Max = max
@@ -251,9 +252,47 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (
re.Sub = re.Sub0[:1]
re.Sub[0] = sub
p.stack[n-1] = re
+
+ if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) {
+ return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
+ }
+
return after, nil
}
+// repeatIsValid reports whether the repetition re is valid.
+// Valid means that the combination of the top-level repetition
+// and any inner repetitions does not exceed n copies of the
+// innermost thing.
+// This function rewalks the regexp tree and is called for every repetition,
+// so we have to worry about inducing quadratic behavior in the parser.
+// We avoid this by only calling repeatIsValid when min or max >= 2.
+// In that case the depth of any >= 2 nesting can only get to 9 without
+// triggering a parse error, so each subtree can only be rewalked 9 times.
+func repeatIsValid(re *Regexp, n int) bool {
+ if re.Op == OpRepeat {
+ m := re.Max
+ if m == 0 {
+ return true
+ }
+ if m < 0 {
+ m = re.Min
+ }
+ if m > n {
+ return false
+ }
+ if m > 0 {
+ n /= m
+ }
+ }
+ for _, sub := range re.Sub {
+ if !repeatIsValid(sub, n) {
+ return false
+ }
+ }
+ return true
+}
+
// concat replaces the top of the stack (above the topmost '|' or '(') with its concatenation.
func (p *parser) concat() *Regexp {
p.maybeConcat(-1, 0)
@@ -1639,7 +1678,7 @@ const (
// minimum and maximum runes involved in folding.
// checked during test.
minFold = 0x0041
- maxFold = 0x1044f
+ maxFold = 0x118df
)
// appendFoldedRange returns the result of appending the range lo-hi
diff --git a/src/pkg/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go
index f3089294c..c4a1117ff 100644
--- a/src/pkg/regexp/syntax/parse_test.go
+++ b/src/regexp/syntax/parse_test.go
@@ -200,6 +200,10 @@ var parseTests = []parseTest{
`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}}}}`},
+
+ // Valid repetitions.
+ {`((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}))`, ``},
+ {`((((((((((x{1}){2}){2}){2}){2}){2}){2}){2}){2}){2})`, ``},
}
const testFlags = MatchNL | PerlX | UnicodeGroups
@@ -262,6 +266,10 @@ func testParseDump(t *testing.T, tests []parseTest, flags Flags) {
t.Errorf("Parse(%#q): %v", tt.Regexp, err)
continue
}
+ if tt.Dump == "" {
+ // It parsed. That's all we care about.
+ continue
+ }
d := dump(re)
if d != tt.Dump {
t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump)
@@ -470,6 +478,7 @@ var invalidRegexps = []string{
`(?i)[a-Z]`,
`a{100000}`,
`a{100000,}`,
+ "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
}
var onlyPerl = []string{
@@ -527,6 +536,10 @@ func TestToStringEquivalentParse(t *testing.T) {
t.Errorf("Parse(%#q): %v", tt.Regexp, err)
continue
}
+ if tt.Dump == "" {
+ // It parsed. That's all we care about.
+ continue
+ }
d := dump(re)
if d != tt.Dump {
t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump)
diff --git a/src/pkg/regexp/syntax/perl_groups.go b/src/regexp/syntax/perl_groups.go
index effe4e686..effe4e686 100644
--- a/src/pkg/regexp/syntax/perl_groups.go
+++ b/src/regexp/syntax/perl_groups.go
diff --git a/src/pkg/regexp/syntax/prog.go b/src/regexp/syntax/prog.go
index 29bd282d0..29bd282d0 100644
--- a/src/pkg/regexp/syntax/prog.go
+++ b/src/regexp/syntax/prog.go
diff --git a/src/pkg/regexp/syntax/prog_test.go b/src/regexp/syntax/prog_test.go
index 50bfa3d4b..50bfa3d4b 100644
--- a/src/pkg/regexp/syntax/prog_test.go
+++ b/src/regexp/syntax/prog_test.go
diff --git a/src/pkg/regexp/syntax/regexp.go b/src/regexp/syntax/regexp.go
index 329a90e01..cea7d9e04 100644
--- a/src/pkg/regexp/syntax/regexp.go
+++ b/src/regexp/syntax/regexp.go
@@ -39,7 +39,7 @@ const (
OpEmptyMatch // matches empty string
OpLiteral // matches Runes sequence
OpCharClass // matches Runes interpreted as range pair list
- OpAnyCharNotNL // matches any character
+ OpAnyCharNotNL // matches any character except newline
OpAnyChar // matches any character
OpBeginLine // matches empty string at beginning of line
OpEndLine // matches empty string at end of line
diff --git a/src/pkg/regexp/syntax/simplify.go b/src/regexp/syntax/simplify.go
index 72390417b..72390417b 100644
--- a/src/pkg/regexp/syntax/simplify.go
+++ b/src/regexp/syntax/simplify.go
diff --git a/src/pkg/regexp/syntax/simplify_test.go b/src/regexp/syntax/simplify_test.go
index 879eff5be..879eff5be 100644
--- a/src/pkg/regexp/syntax/simplify_test.go
+++ b/src/regexp/syntax/simplify_test.go
diff --git a/src/pkg/regexp/testdata/README b/src/regexp/testdata/README
index b1b301be8..b1b301be8 100644
--- a/src/pkg/regexp/testdata/README
+++ b/src/regexp/testdata/README
diff --git a/src/pkg/regexp/testdata/basic.dat b/src/regexp/testdata/basic.dat
index 7859290ba..7859290ba 100644
--- a/src/pkg/regexp/testdata/basic.dat
+++ b/src/regexp/testdata/basic.dat
diff --git a/src/pkg/regexp/testdata/nullsubexpr.dat b/src/regexp/testdata/nullsubexpr.dat
index 2e18fbb91..2e18fbb91 100644
--- a/src/pkg/regexp/testdata/nullsubexpr.dat
+++ b/src/regexp/testdata/nullsubexpr.dat
diff --git a/src/pkg/regexp/testdata/re2-exhaustive.txt.bz2 b/src/regexp/testdata/re2-exhaustive.txt.bz2
index a357f2801..a357f2801 100644
--- a/src/pkg/regexp/testdata/re2-exhaustive.txt.bz2
+++ b/src/regexp/testdata/re2-exhaustive.txt.bz2
Binary files differ
diff --git a/src/pkg/regexp/testdata/re2-search.txt b/src/regexp/testdata/re2-search.txt
index f648e5527..f648e5527 100644
--- a/src/pkg/regexp/testdata/re2-search.txt
+++ b/src/regexp/testdata/re2-search.txt
diff --git a/src/pkg/regexp/testdata/repetition.dat b/src/regexp/testdata/repetition.dat
index e6361f51a..e6361f51a 100644
--- a/src/pkg/regexp/testdata/repetition.dat
+++ b/src/regexp/testdata/repetition.dat
diff --git a/src/pkg/regexp/testdata/testregex.c b/src/regexp/testdata/testregex.c
index 37545d057..37545d057 100644
--- a/src/pkg/regexp/testdata/testregex.c
+++ b/src/regexp/testdata/testregex.c
diff --git a/src/run.bash b/src/run.bash
index 8590ea8d4..5f20451a2 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -52,7 +52,7 @@ timeout_scale=1
[ "$GOARCH" == "arm" ] && timeout_scale=3
echo '# Testing packages.'
-time go test std -short -timeout=$(expr 120 \* $timeout_scale)s
+time go test std -short -timeout=$(expr 120 \* $timeout_scale)s -gcflags "$GO_GCFLAGS"
echo
# We set GOMAXPROCS=2 in addition to -cpu=1,2,4 in order to test runtime bootstrap code,
@@ -64,17 +64,6 @@ echo
echo '# sync -cpu=10'
go test sync -short -timeout=$(expr 120 \* $timeout_scale)s -cpu=10
-# Race detector only supported on Linux and OS X,
-# and only on amd64, and only when cgo is enabled.
-case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED" in
-linux-linux-amd64-1 | darwin-darwin-amd64-1)
- echo
- echo '# Testing race detector.'
- go test -race -i runtime/race flag
- go test -race -run=Output runtime/race
- go test -race -short flag
-esac
-
xcd() {
echo
echo '#' $1
@@ -99,6 +88,13 @@ xcd() {
# Strictly speaking, the test may be unnecessary on the final command of
# the subshell, but it aids later editing and may avoid future bash bugs.
+if [ "$GOOS" == "android" ]; then
+ # Disable cgo tests on android.
+ # They are not designed to run off the host.
+ # golang.org/issue/8345
+ CGO_ENABLED=0
+fi
+
[ "$CGO_ENABLED" != 1 ] ||
[ "$GOHOSTOS" == windows ] ||
(xcd ../misc/cgo/stdio
@@ -113,6 +109,7 @@ go run $GOROOT/test/run.go - . || exit 1
[ "$CGO_ENABLED" != 1 ] ||
(xcd ../misc/cgo/test
# cgo tests inspect the traceback for runtime functions
+extlink=0
export GOTRACEBACK=2
go test -ldflags '-linkmode=auto' || exit 1
# linkmode=internal fails on dragonfly since errno is a TLS relocation.
@@ -121,19 +118,24 @@ case "$GOHOSTOS-$GOARCH" in
openbsd-386 | openbsd-amd64)
# test linkmode=external, but __thread not supported, so skip testtls.
go test -ldflags '-linkmode=external' || exit 1
+ extlink=1
;;
darwin-386 | darwin-amd64)
# linkmode=external fails on OS X 10.6 and earlier == Darwin
# 10.8 and earlier.
case $(uname -r) in
[0-9].* | 10.*) ;;
- *) go test -ldflags '-linkmode=external' || exit 1;;
+ *)
+ go test -ldflags '-linkmode=external' || exit 1
+ extlink=1
+ ;;
esac
;;
-dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | freebsd-arm | linux-386 | linux-amd64 | linux-arm | netbsd-386 | netbsd-amd64)
+android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | freebsd-arm | linux-386 | linux-amd64 | linux-arm | netbsd-386 | netbsd-amd64)
go test -ldflags '-linkmode=external' || exit 1
go test -ldflags '-linkmode=auto' ../testtls || exit 1
go test -ldflags '-linkmode=external' ../testtls || exit 1
+ extlink=1
case "$GOHOSTOS-$GOARCH" in
netbsd-386 | netbsd-amd64) ;; # no static linking
@@ -157,11 +159,36 @@ dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | freebsd-arm | li
esac
) || exit $?
-# This tests cgo -godefs. That mode is not supported,
+# Race detector only supported on Linux, FreeBSD and OS X,
+# and only on amd64, and only when cgo is enabled.
+# Delayed until here so we know whether to try external linking.
+case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED" in
+linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
+ echo
+ echo '# Testing race detector.'
+ go test -race -i runtime/race flag os/exec
+ go test -race -run=Output runtime/race
+ go test -race -short flag os/exec
+
+ # Test with external linking; see issue 9133.
+ if [ "$extlink" = 1 ]; then
+ go test -race -short -ldflags=-linkmode=external flag os/exec
+ fi
+esac
+
+# This tests cgo -cdefs. That mode is not supported,
# so it's okay if it doesn't work on some systems.
# In particular, it works badly with clang on OS X.
+# It doesn't work at all now that we disallow C code
+# outside runtime. Once runtime has no C code it won't
+# even be necessary.
+# [ "$CGO_ENABLED" != 1 ] || [ "$GOOS" == darwin ] ||
+# (xcd ../misc/cgo/testcdefs
+# ./test.bash || exit 1
+# ) || exit $?
+
[ "$CGO_ENABLED" != 1 ] || [ "$GOOS" == darwin ] ||
-(xcd ../misc/cgo/testcdefs
+(xcd ../misc/cgo/testgodefs
./test.bash || exit 1
) || exit $?
@@ -184,16 +211,19 @@ go run main.go || exit 1
) || exit $?
[ "$GOOS" == nacl ] ||
+[ "$GOOS" == android ] ||
(xcd ../doc/progs
time ./run || exit 1
) || exit $?
+[ "$GOOS" == android ] ||
[ "$GOOS" == nacl ] ||
[ "$GOARCH" == arm ] || # uses network, fails under QEMU
(xcd ../doc/articles/wiki
./test.bash || exit 1
) || exit $?
+[ "$GOOS" == android ] ||
[ "$GOOS" == nacl ] ||
(xcd ../doc/codewalk
time ./run || exit 1
@@ -205,6 +235,7 @@ time ./run || exit 1
time ./timing.sh -test || exit 1
) || exit $?
+[ "$GOOS" == android ] || # TODO(crawshaw): get this working
[ "$GOOS" == openbsd ] || # golang.org/issue/5057
(
echo
@@ -212,6 +243,7 @@ echo '#' ../test/bench/go1
go test ../test/bench/go1 || exit 1
) || exit $?
+[ "$GOOS" == android ] ||
(xcd ../test
unset GOMAXPROCS
GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH go build -o runtest run.go || exit 1
@@ -219,6 +251,7 @@ time ./runtest || exit 1
rm -f runtest
) || exit $?
+[ "$GOOS" == android ] ||
[ "$GOOS" == nacl ] ||
(
echo
diff --git a/src/run.rc b/src/run.rc
index 65e2c07e5..b0995d878 100755
--- a/src/run.rc
+++ b/src/run.rc
@@ -54,7 +54,7 @@ go test ../test/bench/go1
@{
xcd ../test
- GOMAXPROCS='' time go run run.go
+ GOMAXPROCS='' time go run run.go -v
}
echo
diff --git a/src/pkg/runtime/Makefile b/src/runtime/Makefile
index 5827ce134..55087def0 100644
--- a/src/pkg/runtime/Makefile
+++ b/src/runtime/Makefile
@@ -2,4 +2,4 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
-include ../../Make.dist
+include ../Make.dist
diff --git a/src/runtime/alg.go b/src/runtime/alg.go
new file mode 100644
index 000000000..e9ed59503
--- /dev/null
+++ b/src/runtime/alg.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 runtime
+
+import "unsafe"
+
+const (
+ c0 = uintptr((8-ptrSize)/4*2860486313 + (ptrSize-4)/4*33054211828000289)
+ c1 = uintptr((8-ptrSize)/4*3267000013 + (ptrSize-4)/4*23344194077549503)
+)
+
+// type algorithms - known to compiler
+const (
+ alg_MEM = iota
+ alg_MEM0
+ alg_MEM8
+ alg_MEM16
+ alg_MEM32
+ alg_MEM64
+ alg_MEM128
+ alg_NOEQ
+ alg_NOEQ0
+ alg_NOEQ8
+ alg_NOEQ16
+ alg_NOEQ32
+ alg_NOEQ64
+ alg_NOEQ128
+ alg_STRING
+ alg_INTER
+ alg_NILINTER
+ alg_SLICE
+ alg_FLOAT32
+ alg_FLOAT64
+ alg_CPLX64
+ alg_CPLX128
+ alg_max
+)
+
+type typeAlg struct {
+ // function for hashing objects of this type
+ // (ptr to object, size, seed) -> hash
+ hash func(unsafe.Pointer, uintptr, uintptr) uintptr
+ // function for comparing objects of this type
+ // (ptr to object A, ptr to object B, size) -> ==?
+ equal func(unsafe.Pointer, unsafe.Pointer, uintptr) bool
+}
+
+var algarray = [alg_max]typeAlg{
+ alg_MEM: {memhash, memequal},
+ alg_MEM0: {memhash, memequal0},
+ alg_MEM8: {memhash, memequal8},
+ alg_MEM16: {memhash, memequal16},
+ alg_MEM32: {memhash, memequal32},
+ alg_MEM64: {memhash, memequal64},
+ alg_MEM128: {memhash, memequal128},
+ alg_NOEQ: {nil, nil},
+ alg_NOEQ0: {nil, nil},
+ alg_NOEQ8: {nil, nil},
+ alg_NOEQ16: {nil, nil},
+ alg_NOEQ32: {nil, nil},
+ alg_NOEQ64: {nil, nil},
+ alg_NOEQ128: {nil, nil},
+ alg_STRING: {strhash, strequal},
+ alg_INTER: {interhash, interequal},
+ alg_NILINTER: {nilinterhash, nilinterequal},
+ alg_SLICE: {nil, nil},
+ alg_FLOAT32: {f32hash, f32equal},
+ alg_FLOAT64: {f64hash, f64equal},
+ alg_CPLX64: {c64hash, c64equal},
+ alg_CPLX128: {c128hash, c128equal},
+}
+
+const nacl = GOOS == "nacl"
+
+var useAeshash bool
+
+// in asm_*.s
+func aeshash(p unsafe.Pointer, s, h uintptr) uintptr
+func aeshash32(p unsafe.Pointer, s, h uintptr) uintptr
+func aeshash64(p unsafe.Pointer, s, h uintptr) uintptr
+func aeshashstr(p unsafe.Pointer, s, h uintptr) uintptr
+
+func memhash(p unsafe.Pointer, s, h uintptr) uintptr {
+ if !nacl && useAeshash {
+ return aeshash(p, s, h)
+ }
+
+ h ^= c0
+ for s > 0 {
+ h = (h ^ uintptr(*(*byte)(p))) * c1
+ p = add(p, 1)
+ s--
+ }
+ return h
+}
+
+func strhash(a unsafe.Pointer, s, h uintptr) uintptr {
+ return memhash((*stringStruct)(a).str, uintptr(len(*(*string)(a))), h)
+}
+
+// NOTE: Because NaN != NaN, a map can contain any
+// number of (mostly useless) entries keyed with NaNs.
+// To avoid long hash chains, we assign a random number
+// as the hash value for a NaN.
+
+func f32hash(p unsafe.Pointer, s, h uintptr) uintptr {
+ f := *(*float32)(p)
+ switch {
+ case f == 0:
+ return c1 * (c0 ^ h) // +0, -0
+ case f != f:
+ return c1 * (c0 ^ h ^ uintptr(fastrand1())) // any kind of NaN
+ default:
+ return memhash(p, 4, h)
+ }
+}
+
+func f64hash(p unsafe.Pointer, s, h uintptr) uintptr {
+ f := *(*float64)(p)
+ switch {
+ case f == 0:
+ return c1 * (c0 ^ h) // +0, -0
+ case f != f:
+ return c1 * (c0 ^ h ^ uintptr(fastrand1())) // any kind of NaN
+ default:
+ return memhash(p, 8, h)
+ }
+}
+
+func c64hash(p unsafe.Pointer, s, h uintptr) uintptr {
+ x := (*[2]float32)(p)
+ return f32hash(unsafe.Pointer(&x[1]), 4, f32hash(unsafe.Pointer(&x[0]), 4, h))
+}
+
+func c128hash(p unsafe.Pointer, s, h uintptr) uintptr {
+ x := (*[2]float64)(p)
+ return f64hash(unsafe.Pointer(&x[1]), 8, f64hash(unsafe.Pointer(&x[0]), 8, h))
+}
+
+func interhash(p unsafe.Pointer, s, h uintptr) uintptr {
+ a := (*iface)(p)
+ tab := a.tab
+ if tab == nil {
+ return h
+ }
+ t := tab._type
+ fn := goalg(t.alg).hash
+ if fn == nil {
+ panic(errorString("hash of unhashable type " + *t._string))
+ }
+ if isDirectIface(t) {
+ return c1 * fn(unsafe.Pointer(&a.data), uintptr(t.size), h^c0)
+ } else {
+ return c1 * fn(a.data, uintptr(t.size), h^c0)
+ }
+}
+
+func nilinterhash(p unsafe.Pointer, s, h uintptr) uintptr {
+ a := (*eface)(p)
+ t := a._type
+ if t == nil {
+ return h
+ }
+ fn := goalg(t.alg).hash
+ if fn == nil {
+ panic(errorString("hash of unhashable type " + *t._string))
+ }
+ if isDirectIface(t) {
+ return c1 * fn(unsafe.Pointer(&a.data), uintptr(t.size), h^c0)
+ } else {
+ return c1 * fn(a.data, uintptr(t.size), h^c0)
+ }
+}
+
+func memequal(p, q unsafe.Pointer, size uintptr) bool {
+ if p == q {
+ return true
+ }
+ return memeq(p, q, size)
+}
+
+func memequal0(p, q unsafe.Pointer, size uintptr) bool {
+ return true
+}
+func memequal8(p, q unsafe.Pointer, size uintptr) bool {
+ return *(*int8)(p) == *(*int8)(q)
+}
+func memequal16(p, q unsafe.Pointer, size uintptr) bool {
+ return *(*int16)(p) == *(*int16)(q)
+}
+func memequal32(p, q unsafe.Pointer, size uintptr) bool {
+ return *(*int32)(p) == *(*int32)(q)
+}
+func memequal64(p, q unsafe.Pointer, size uintptr) bool {
+ return *(*int64)(p) == *(*int64)(q)
+}
+func memequal128(p, q unsafe.Pointer, size uintptr) bool {
+ return *(*[2]int64)(p) == *(*[2]int64)(q)
+}
+func f32equal(p, q unsafe.Pointer, size uintptr) bool {
+ return *(*float32)(p) == *(*float32)(q)
+}
+func f64equal(p, q unsafe.Pointer, size uintptr) bool {
+ return *(*float64)(p) == *(*float64)(q)
+}
+func c64equal(p, q unsafe.Pointer, size uintptr) bool {
+ return *(*complex64)(p) == *(*complex64)(q)
+}
+func c128equal(p, q unsafe.Pointer, size uintptr) bool {
+ return *(*complex128)(p) == *(*complex128)(q)
+}
+func strequal(p, q unsafe.Pointer, size uintptr) bool {
+ return *(*string)(p) == *(*string)(q)
+}
+func interequal(p, q unsafe.Pointer, size uintptr) bool {
+ return ifaceeq(*(*interface {
+ f()
+ })(p), *(*interface {
+ f()
+ })(q))
+}
+func nilinterequal(p, q unsafe.Pointer, size uintptr) bool {
+ return efaceeq(*(*interface{})(p), *(*interface{})(q))
+}
+func efaceeq(p, q interface{}) bool {
+ x := (*eface)(unsafe.Pointer(&p))
+ y := (*eface)(unsafe.Pointer(&q))
+ t := x._type
+ if t != y._type {
+ return false
+ }
+ if t == nil {
+ return true
+ }
+ eq := goalg(t.alg).equal
+ if eq == nil {
+ panic(errorString("comparing uncomparable type " + *t._string))
+ }
+ if isDirectIface(t) {
+ return eq(noescape(unsafe.Pointer(&x.data)), noescape(unsafe.Pointer(&y.data)), uintptr(t.size))
+ }
+ return eq(x.data, y.data, uintptr(t.size))
+}
+func ifaceeq(p, q interface {
+ f()
+}) bool {
+ x := (*iface)(unsafe.Pointer(&p))
+ y := (*iface)(unsafe.Pointer(&q))
+ xtab := x.tab
+ if xtab != y.tab {
+ return false
+ }
+ if xtab == nil {
+ return true
+ }
+ t := xtab._type
+ eq := goalg(t.alg).equal
+ if eq == nil {
+ panic(errorString("comparing uncomparable type " + *t._string))
+ }
+ if isDirectIface(t) {
+ return eq(noescape(unsafe.Pointer(&x.data)), noescape(unsafe.Pointer(&y.data)), uintptr(t.size))
+ }
+ return eq(x.data, y.data, uintptr(t.size))
+}
+
+// Testing adapters for hash quality tests (see hash_test.go)
+func haveGoodHash() bool {
+ return useAeshash
+}
+
+func stringHash(s string, seed uintptr) uintptr {
+ return algarray[alg_STRING].hash(noescape(unsafe.Pointer(&s)), unsafe.Sizeof(s), seed)
+}
+
+func bytesHash(b []byte, seed uintptr) uintptr {
+ s := (*sliceStruct)(unsafe.Pointer(&b))
+ return algarray[alg_MEM].hash(s.array, uintptr(s.len), seed)
+}
+
+func int32Hash(i uint32, seed uintptr) uintptr {
+ return algarray[alg_MEM32].hash(noescape(unsafe.Pointer(&i)), 4, seed)
+}
+
+func int64Hash(i uint64, seed uintptr) uintptr {
+ return algarray[alg_MEM64].hash(noescape(unsafe.Pointer(&i)), 8, seed)
+}
+
+func efaceHash(i interface{}, seed uintptr) uintptr {
+ return algarray[alg_NILINTER].hash(noescape(unsafe.Pointer(&i)), unsafe.Sizeof(i), seed)
+}
+
+func ifaceHash(i interface {
+ F()
+}, seed uintptr) uintptr {
+ return algarray[alg_INTER].hash(noescape(unsafe.Pointer(&i)), unsafe.Sizeof(i), seed)
+}
+
+// Testing adapter for memclr
+func memclrBytes(b []byte) {
+ s := (*sliceStruct)(unsafe.Pointer(&b))
+ memclr(s.array, uintptr(s.len))
+}
+
+// TODO(dvyukov): remove when Type is converted to Go and contains *typeAlg.
+func goalg(a unsafe.Pointer) *typeAlg {
+ return (*typeAlg)(a)
+}
+
+// used in asm_{386,amd64}.s
+const hashRandomBytes = 32
+
+var aeskeysched [hashRandomBytes]byte
+
+//go:noescape
+func get_random_data(rnd *unsafe.Pointer, n *int32)
+
+func init() {
+ if theGoos == "nacl" {
+ return
+ }
+
+ // Install aes hash algorithm if we have the instructions we need
+ if (cpuid_ecx&(1<<25)) != 0 && // aes (aesenc)
+ (cpuid_ecx&(1<<9)) != 0 && // sse3 (pshufb)
+ (cpuid_ecx&(1<<19)) != 0 { // sse4.1 (pinsr{d,q})
+ useAeshash = true
+ algarray[alg_MEM].hash = aeshash
+ algarray[alg_MEM8].hash = aeshash
+ algarray[alg_MEM16].hash = aeshash
+ algarray[alg_MEM32].hash = aeshash32
+ algarray[alg_MEM64].hash = aeshash64
+ algarray[alg_MEM128].hash = aeshash
+ algarray[alg_STRING].hash = aeshashstr
+ // Initialize with random data so hash collisions will be hard to engineer.
+ var rnd unsafe.Pointer
+ var n int32
+ get_random_data(&rnd, &n)
+ if n > hashRandomBytes {
+ n = hashRandomBytes
+ }
+ memmove(unsafe.Pointer(&aeskeysched[0]), rnd, uintptr(n))
+ if n < hashRandomBytes {
+ // Not very random, but better than nothing.
+ for t := nanotime(); n < hashRandomBytes; n++ {
+ aeskeysched[n] = byte(t >> uint(8*(n%8)))
+ }
+ }
+ }
+}
diff --git a/src/pkg/runtime/append_test.go b/src/runtime/append_test.go
index a67dc9b49..a67dc9b49 100644
--- a/src/pkg/runtime/append_test.go
+++ b/src/runtime/append_test.go
diff --git a/src/pkg/syscall/asm_solaris_amd64.s b/src/runtime/arch_386.go
index 3735890fa..79d38c7ab 100644
--- a/src/pkg/syscall/asm_solaris_amd64.s
+++ b/src/runtime/arch_386.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//
-// System calls for amd64, Solaris are implemented in ../runtime/syscall_solaris.goc
-//
+package runtime
+
+type uintreg uint32
+type intptr int32 // TODO(rsc): remove
diff --git a/src/pkg/runtime/arch_386.h b/src/runtime/arch_386.h
index 5c0a54f8c..75a5ba77f 100644
--- a/src/pkg/runtime/arch_386.h
+++ b/src/runtime/arch_386.h
@@ -12,5 +12,6 @@ enum {
#else
PhysPageSize = 4096,
#endif
- PCQuantum = 1
+ PCQuantum = 1,
+ Int64Align = 4
};
diff --git a/src/runtime/arch_amd64.go b/src/runtime/arch_amd64.go
new file mode 100644
index 000000000..270cd7b95
--- /dev/null
+++ b/src/runtime/arch_amd64.go
@@ -0,0 +1,8 @@
+// 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/pkg/runtime/arch_amd64.h b/src/runtime/arch_amd64.h
index c8a21847c..d7b81ee90 100644
--- a/src/pkg/runtime/arch_amd64.h
+++ b/src/runtime/arch_amd64.h
@@ -12,9 +12,14 @@ enum {
#ifdef GOOS_windows
RuntimeGogoBytes = 80,
#else
+#ifdef GOOS_plan9
+ RuntimeGogoBytes = 80,
+#else
RuntimeGogoBytes = 64,
+#endif // Plan 9
#endif // Windows
#endif // Solaris
PhysPageSize = 4096,
- PCQuantum = 1
+ PCQuantum = 1,
+ Int64Align = 8
};
diff --git a/src/runtime/arch_amd64p32.go b/src/runtime/arch_amd64p32.go
new file mode 100644
index 000000000..5c636aeab
--- /dev/null
+++ b/src/runtime/arch_amd64p32.go
@@ -0,0 +1,8 @@
+// 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/pkg/runtime/arch_amd64p32.h b/src/runtime/arch_amd64p32.h
index 073a9e30e..d3e864987 100644
--- a/src/pkg/runtime/arch_amd64p32.h
+++ b/src/runtime/arch_amd64p32.h
@@ -12,5 +12,6 @@ enum {
#else
PhysPageSize = 4096,
#endif
- PCQuantum = 1
+ PCQuantum = 1,
+ Int64Align = 8
};
diff --git a/src/runtime/arch_arm.go b/src/runtime/arch_arm.go
new file mode 100644
index 000000000..79d38c7ab
--- /dev/null
+++ b/src/runtime/arch_arm.go
@@ -0,0 +1,8 @@
+// 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/pkg/runtime/arch_arm.h b/src/runtime/arch_arm.h
index b9711289f..637a334a0 100644
--- a/src/pkg/runtime/arch_arm.h
+++ b/src/runtime/arch_arm.h
@@ -6,7 +6,12 @@ enum {
thechar = '5',
BigEndian = 0,
CacheLineSize = 32,
- RuntimeGogoBytes = 80,
+ RuntimeGogoBytes = 60,
+#ifdef GOOS_nacl
+ PhysPageSize = 65536,
+#else
PhysPageSize = 4096,
- PCQuantum = 4
+#endif
+ PCQuantum = 4,
+ Int64Align = 4
};
diff --git a/src/runtime/asm.s b/src/runtime/asm.s
new file mode 100644
index 000000000..e6d782f37
--- /dev/null
+++ b/src/runtime/asm.s
@@ -0,0 +1,14 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// funcdata for functions with no local variables in frame.
+// Define two zero-length bitmaps, because the same index is used
+// for the local variables as for the argument frame, and assembly
+// frames have two argument bitmaps, one without results and one with results.
+DATA runtime·no_pointers_stackmap+0x00(SB)/4, $2
+DATA runtime·no_pointers_stackmap+0x04(SB)/4, $0
+GLOBL runtime·no_pointers_stackmap(SB),RODATA, $8
+
diff --git a/src/pkg/runtime/asm_386.s b/src/runtime/asm_386.s
index 95312089d..b4b81d739 100644
--- a/src/pkg/runtime/asm_386.s
+++ b/src/runtime/asm_386.s
@@ -4,9 +4,9 @@
#include "zasm_GOOS_GOARCH.h"
#include "funcdata.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
-TEXT _rt0_go(SB),NOSPLIT,$0
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
// copy arguments forward on an even stack
MOVL argc+0(FP), AX
MOVL argv+4(FP), BX
@@ -19,9 +19,10 @@ TEXT _rt0_go(SB),NOSPLIT,$0
// _cgo_init may update stackguard.
MOVL $runtime·g0(SB), BP
LEAL (-64*1024+104)(SP), BX
- MOVL BX, g_stackguard(BP)
MOVL BX, g_stackguard0(BP)
- MOVL SP, g_stackbase(BP)
+ MOVL BX, g_stackguard1(BP)
+ MOVL BX, (g_stack+stack_lo)(BP)
+ MOVL SP, (g_stack+stack_hi)(BP)
// find out information about the processor we're on
MOVL $0, AX
@@ -40,14 +41,18 @@ nocpuinfo:
MOVL _cgo_init(SB), AX
TESTL AX, AX
JZ needtls
- MOVL $setmg_gcc<>(SB), BX
+ MOVL $setg_gcc<>(SB), BX
MOVL BX, 4(SP)
MOVL BP, 0(SP)
CALL AX
+
// update stackguard after _cgo_init
MOVL $runtime·g0(SB), CX
- MOVL g_stackguard0(CX), AX
- MOVL AX, g_stackguard(CX)
+ MOVL (g_stack+stack_lo)(CX), AX
+ ADDL $const_StackGuard, AX
+ MOVL AX, g_stackguard0(CX)
+ MOVL AX, g_stackguard1(CX)
+
// skip runtime·ldt0setup(SB) and tls test after _cgo_init for non-windows
CMPL runtime·iswindows(SB), $0
JEQ ok
@@ -72,10 +77,11 @@ ok:
LEAL runtime·g0(SB), CX
MOVL CX, g(BX)
LEAL runtime·m0(SB), AX
- MOVL AX, m(BX)
// save m->g0 = g0
MOVL CX, m_g0(AX)
+ // save g0->m = m0
+ MOVL AX, g_m(CX)
CALL runtime·emptyfunc(SB) // fault if stack check is wrong
@@ -91,15 +97,12 @@ ok:
MOVL AX, 4(SP)
CALL runtime·args(SB)
CALL runtime·osinit(SB)
- CALL runtime·hashinit(SB)
CALL runtime·schedinit(SB)
// create a new goroutine to start program
PUSHL $runtime·main·f(SB) // entry
PUSHL $0 // arg size
- ARGSIZE(8)
CALL runtime·newproc(SB)
- ARGSIZE(-1)
POPL AX
POPL AX
@@ -133,8 +136,8 @@ TEXT runtime·asminit(SB),NOSPLIT,$0-0
// void gosave(Gobuf*)
// save state in Gobuf; setjmp
TEXT runtime·gosave(SB), NOSPLIT, $0-4
- MOVL 4(SP), AX // gobuf
- LEAL 4(SP), BX // caller's SP
+ MOVL buf+0(FP), AX // gobuf
+ LEAL buf+0(FP), BX // caller's SP
MOVL BX, gobuf_sp(AX)
MOVL 0(SP), BX // caller's PC
MOVL BX, gobuf_pc(AX)
@@ -148,7 +151,7 @@ TEXT runtime·gosave(SB), NOSPLIT, $0-4
// void gogo(Gobuf*)
// restore state from Gobuf; longjmp
TEXT runtime·gogo(SB), NOSPLIT, $0-4
- MOVL 4(SP), BX // gobuf
+ MOVL buf+0(FP), BX // gobuf
MOVL gobuf_g(BX), DX
MOVL 0(DX), CX // make sure g != nil
get_tls(CX)
@@ -162,7 +165,7 @@ TEXT runtime·gogo(SB), NOSPLIT, $0-4
MOVL gobuf_pc(BX), BX
JMP BX
-// void mcall(void (*fn)(G*))
+// func 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.
@@ -173,12 +176,13 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
MOVL g(CX), AX // save state in g->sched
MOVL 0(SP), BX // caller's PC
MOVL BX, (g_sched+gobuf_pc)(AX)
- LEAL 4(SP), BX // caller's SP
+ LEAL fn+0(FP), BX // caller's SP
MOVL BX, (g_sched+gobuf_sp)(AX)
MOVL AX, (g_sched+gobuf_g)(AX)
// switch to m->g0 & its stack, call fn
- MOVL m(CX), BX
+ MOVL g(CX), BX
+ MOVL g_m(BX), BX
MOVL m_g0(BX), SI
CMPL SI, AX // if g == m->g0 call badmcall
JNE 3(PC)
@@ -187,12 +191,97 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
MOVL SI, g(CX) // g = m->g0
MOVL (g_sched+gobuf_sp)(SI), SP // sp = m->g0->sched.sp
PUSHL AX
+ MOVL DI, DX
+ MOVL 0(DI), DI
CALL DI
POPL AX
MOVL $runtime·badmcall2(SB), AX
JMP AX
RET
+// switchtoM is a dummy routine that onM 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 M stack because the one at the top of
+// the M stack terminates the stack walk (see topofstack()).
+TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
+ RET
+
+// func onM_signalok(fn func())
+TEXT runtime·onM_signalok(SB), NOSPLIT, $0-4
+ get_tls(CX)
+ MOVL g(CX), AX // AX = g
+ MOVL g_m(AX), BX // BX = m
+ MOVL m_gsignal(BX), DX // DX = gsignal
+ CMPL AX, DX
+ JEQ ongsignal
+ JMP runtime·onM(SB)
+
+ongsignal:
+ MOVL fn+0(FP), DI // DI = fn
+ MOVL DI, DX
+ MOVL 0(DI), DI
+ CALL DI
+ RET
+
+// func onM(fn func())
+TEXT runtime·onM(SB), NOSPLIT, $0-4
+ MOVL fn+0(FP), DI // DI = fn
+ get_tls(CX)
+ MOVL g(CX), AX // AX = g
+ MOVL g_m(AX), BX // BX = m
+
+ MOVL m_g0(BX), DX // DX = g0
+ CMPL AX, DX
+ JEQ onm
+
+ MOVL m_curg(BX), BP
+ CMPL AX, BP
+ JEQ oncurg
+
+ // Not g0, not curg. Must be gsignal, but that's not allowed.
+ // Hide call from linker nosplit analysis.
+ MOVL $runtime·badonm(SB), AX
+ CALL AX
+
+oncurg:
+ // save our state in g->sched. Pretend to
+ // be switchtoM if the G stack is scanned.
+ MOVL $runtime·switchtoM(SB), (g_sched+gobuf_pc)(AX)
+ MOVL SP, (g_sched+gobuf_sp)(AX)
+ MOVL AX, (g_sched+gobuf_g)(AX)
+
+ // switch to g0
+ MOVL DX, g(CX)
+ MOVL (g_sched+gobuf_sp)(DX), BX
+ // make it look like mstart called onM on g0, to stop traceback
+ SUBL $4, BX
+ MOVL $runtime·mstart(SB), DX
+ MOVL DX, 0(BX)
+ MOVL BX, SP
+
+ // call target function
+ MOVL DI, DX
+ MOVL 0(DI), DI
+ CALL DI
+
+ // switch back to g
+ get_tls(CX)
+ MOVL g(CX), AX
+ MOVL g_m(AX), BX
+ MOVL m_curg(BX), AX
+ MOVL AX, g(CX)
+ MOVL (g_sched+gobuf_sp)(AX), SP
+ MOVL $0, (g_sched+gobuf_sp)(AX)
+ RET
+
+onm:
+ // already on m stack, just call directly
+ MOVL DI, DX
+ MOVL 0(DI), DI
+ CALL DI
+ RET
+
/*
* support for morestack
*/
@@ -206,17 +295,18 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
TEXT runtime·morestack(SB),NOSPLIT,$0-0
// Cannot grow scheduler stack (m->g0).
get_tls(CX)
- MOVL m(CX), BX
+ MOVL g(CX), BX
+ MOVL g_m(BX), BX
MOVL m_g0(BX), SI
CMPL g(CX), SI
JNE 2(PC)
INT $3
- // frame size in DI
- // arg size in AX
- // Save in m.
- MOVL DI, m_moreframesize(BX)
- MOVL AX, m_moreargsize(BX)
+ // Cannot grow signal stack.
+ MOVL m_gsignal(BX), SI
+ CMPL g(CX), SI
+ JNE 2(PC)
+ INT $3
// Called from f.
// Set m->morebuf to f's caller.
@@ -224,7 +314,6 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0
MOVL DI, (m_morebuf+gobuf_pc)(BX)
LEAL 8(SP), CX // f's caller's SP
MOVL CX, (m_morebuf+gobuf_sp)(BX)
- MOVL CX, m_moreargp(BX)
get_tls(CX)
MOVL g(CX), SI
MOVL SI, (m_morebuf+gobuf_g)(BX)
@@ -251,55 +340,8 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0
MOVL $0, DX
JMP runtime·morestack(SB)
-// Called from panic. Mimics morestack,
-// reuses stack growth code to create a frame
-// with the desired args running the desired function.
-//
-// func call(fn *byte, arg *byte, argsize uint32).
-TEXT runtime·newstackcall(SB), NOSPLIT, $0-12
- get_tls(CX)
- MOVL m(CX), BX
-
- // Save our caller's state as the PC and SP to
- // restore when returning from f.
- MOVL 0(SP), AX // our caller's PC
- MOVL AX, (m_morebuf+gobuf_pc)(BX)
- LEAL 4(SP), AX // our caller's SP
- MOVL AX, (m_morebuf+gobuf_sp)(BX)
- MOVL g(CX), AX
- MOVL AX, (m_morebuf+gobuf_g)(BX)
-
- // Save our own state as the PC and SP to restore
- // if this goroutine needs to be restarted.
- MOVL $runtime·newstackcall(SB), (g_sched+gobuf_pc)(AX)
- MOVL SP, (g_sched+gobuf_sp)(AX)
-
- // Set up morestack arguments to call f on a new stack.
- // We set f's frame size to 1, as a hint to newstack
- // that this is a call from runtime·newstackcall.
- // If it turns out that f needs a larger frame than
- // the default stack, f's usual stack growth prolog will
- // allocate a new segment (and recopy the arguments).
- MOVL 4(SP), AX // fn
- MOVL 8(SP), DX // arg frame
- MOVL 12(SP), CX // arg size
-
- MOVL AX, m_cret(BX) // f's PC
- MOVL DX, m_moreargp(BX) // f's argument pointer
- MOVL CX, m_moreargsize(BX) // f's argument size
- MOVL $1, m_moreframesize(BX) // f's frame size
-
- // Call newstack on m->g0's stack.
- MOVL m_g0(BX), BP
- get_tls(CX)
- MOVL BP, g(CX)
- MOVL (g_sched+gobuf_sp)(BP), SP
- CALL runtime·newstack(SB)
- MOVL $0, 0x1103 // crash if newstack returns
- RET
-
-// reflect·call: call a function with the given argument list
-// func call(f *FuncVal, arg *byte, argsize uint32).
+// reflectcall: call a function with the given argument list
+// func call(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!
@@ -307,58 +349,45 @@ TEXT runtime·newstackcall(SB), NOSPLIT, $0-12
#define DISPATCH(NAME,MAXSIZE) \
CMPL CX, $MAXSIZE; \
JA 3(PC); \
- MOVL $runtime·NAME(SB), AX; \
+ MOVL $NAME(SB), AX; \
JMP AX
-// Note: can't just "JMP runtime·NAME(SB)" - bad inlining results.
+// Note: can't just "JMP NAME(SB)" - bad inlining results.
-TEXT reflect·call(SB), NOSPLIT, $0-16
+TEXT ·reflectcall(SB), NOSPLIT, $0-16
MOVL argsize+8(FP), CX
- DISPATCH(call16, 16)
- DISPATCH(call32, 32)
- DISPATCH(call64, 64)
- DISPATCH(call128, 128)
- DISPATCH(call256, 256)
- DISPATCH(call512, 512)
- DISPATCH(call1024, 1024)
- DISPATCH(call2048, 2048)
- DISPATCH(call4096, 4096)
- DISPATCH(call8192, 8192)
- DISPATCH(call16384, 16384)
- DISPATCH(call32768, 32768)
- DISPATCH(call65536, 65536)
- DISPATCH(call131072, 131072)
- DISPATCH(call262144, 262144)
- DISPATCH(call524288, 524288)
- DISPATCH(call1048576, 1048576)
- DISPATCH(call2097152, 2097152)
- DISPATCH(call4194304, 4194304)
- DISPATCH(call8388608, 8388608)
- DISPATCH(call16777216, 16777216)
- DISPATCH(call33554432, 33554432)
- DISPATCH(call67108864, 67108864)
- DISPATCH(call134217728, 134217728)
- DISPATCH(call268435456, 268435456)
- DISPATCH(call536870912, 536870912)
- DISPATCH(call1073741824, 1073741824)
+ DISPATCH(runtime·call16, 16)
+ 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)
MOVL $runtime·badreflectcall(SB), AX
JMP AX
-// Argument map for the callXX frames. Each has one
-// stack map (for the single call) with 3 arguments.
-DATA gcargs_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
-DATA gcargs_reflectcall<>+0x04(SB)/4, $6 // 3 args
-DATA gcargs_reflectcall<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsScalar<<4))
-GLOBL gcargs_reflectcall<>(SB),RODATA,$12
-
-// callXX frames have no locals
-DATA gclocals_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
-DATA gclocals_reflectcall<>+0x04(SB)/4, $0 // 0 locals
-GLOBL gclocals_reflectcall<>(SB),RODATA,$8
-
#define CALLFN(NAME,MAXSIZE) \
-TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-16; \
- FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_reflectcall<>(SB); \
- FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_reflectcall<>(SB);\
+TEXT NAME(SB), WRAPPER, $MAXSIZE-16; \
+ NO_LOCAL_POINTERS; \
/* copy arguments to stack */ \
MOVL argptr+4(FP), SI; \
MOVL argsize+8(FP), CX; \
@@ -380,52 +409,33 @@ TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-16; \
REP;MOVSB; \
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)
-
-// Return point when leaving stack.
-//
-// Lessstack can appear in stack traces for the same reason
-// as morestack; in that context, it has 0 arguments.
-TEXT runtime·lessstack(SB), NOSPLIT, $0-0
- // Save return value in m->cret
- get_tls(CX)
- MOVL m(CX), BX
- MOVL AX, m_cret(BX)
-
- // Call oldstack on m->g0's stack.
- MOVL m_g0(BX), BP
- MOVL BP, g(CX)
- MOVL (g_sched+gobuf_sp)(BP), SP
- CALL runtime·oldstack(SB)
- MOVL $0, 0x1004 // crash if oldstack returns
- 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)
// bool cas(int32 *val, int32 old, int32 new)
// Atomically:
@@ -434,18 +444,32 @@ TEXT runtime·lessstack(SB), NOSPLIT, $0-0
// return 1;
// }else
// return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-12
- MOVL 4(SP), BX
- MOVL 8(SP), AX
- MOVL 12(SP), CX
+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)
- JZ 3(PC)
+ JZ 4(PC)
MOVL $0, AX
+ MOVB AX, ret+12(FP)
RET
MOVL $1, AX
+ MOVB AX, 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){
@@ -454,19 +478,21 @@ TEXT runtime·cas(SB), NOSPLIT, $0-12
// } else {
// return 0;
// }
-TEXT runtime·cas64(SB), NOSPLIT, $0-20
- MOVL 4(SP), BP
- MOVL 8(SP), AX
- MOVL 12(SP), DX
- MOVL 16(SP), BX
- MOVL 20(SP), CX
+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)
JNZ cas64_fail
MOVL $1, AX
+ MOVB AX, ret+20(FP)
RET
cas64_fail:
MOVL $0, AX
+ MOVB AX, ret+20(FP)
RET
// bool casp(void **p, void *old, void *new)
@@ -476,45 +502,53 @@ cas64_fail:
// return 1;
// }else
// return 0;
-TEXT runtime·casp(SB), NOSPLIT, $0-12
- MOVL 4(SP), BX
- MOVL 8(SP), AX
- MOVL 12(SP), CX
+TEXT runtime·casp(SB), NOSPLIT, $0-13
+ MOVL ptr+0(FP), BX
+ MOVL old+4(FP), AX
+ MOVL new+8(FP), CX
LOCK
CMPXCHGL CX, 0(BX)
- JZ 3(PC)
+ JZ 4(PC)
MOVL $0, AX
+ MOVB AX, ret+12(FP)
RET
MOVL $1, AX
+ MOVB AX, ret+12(FP)
RET
// uint32 xadd(uint32 volatile *val, int32 delta)
// Atomically:
// *val += delta;
// return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-8
- MOVL 4(SP), BX
- MOVL 8(SP), AX
+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-8
- MOVL 4(SP), BX
- MOVL 8(SP), AX
+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·xchgp(SB), NOSPLIT, $0-8
- MOVL 4(SP), BX
- MOVL 8(SP), AX
+TEXT runtime·xchgp(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 4(SP), AX
+ MOVL cycles+0(FP), AX
again:
PAUSE
SUBL $1, AX
@@ -522,23 +556,21 @@ again:
RET
TEXT runtime·atomicstorep(SB), NOSPLIT, $0-8
- MOVL 4(SP), BX
- MOVL 8(SP), AX
+ MOVL ptr+0(FP), BX
+ MOVL val+4(FP), AX
XCHGL AX, 0(BX)
RET
TEXT runtime·atomicstore(SB), NOSPLIT, $0-8
- MOVL 4(SP), BX
- MOVL 8(SP), AX
+ MOVL ptr+0(FP), BX
+ MOVL val+4(FP), AX
XCHGL AX, 0(BX)
RET
// uint64 atomicload64(uint64 volatile* addr);
-// so actually
-// void atomicload64(uint64 *res, uint64 volatile *addr);
-TEXT runtime·atomicload64(SB), NOSPLIT, $0-8
- MOVL 4(SP), BX
- MOVL 8(SP), AX
+TEXT runtime·atomicload64(SB), NOSPLIT, $0-12
+ MOVL ptr+0(FP), AX
+ LEAL ret_lo+4(FP), BX
// MOVQ (%EAX), %MM0
BYTE $0x0f; BYTE $0x6f; BYTE $0x00
// MOVQ %MM0, 0(%EBX)
@@ -549,7 +581,7 @@ TEXT runtime·atomicload64(SB), NOSPLIT, $0-8
// void runtime·atomicstore64(uint64 volatile* addr, uint64 v);
TEXT runtime·atomicstore64(SB), NOSPLIT, $0-12
- MOVL 4(SP), AX
+ MOVL ptr+0(FP), AX
// MOVQ and EMMS were introduced on the Pentium MMX.
// MOVQ 0x8(%ESP), %MM0
BYTE $0x0f; BYTE $0x6f; BYTE $0x44; BYTE $0x24; BYTE $0x08
@@ -564,14 +596,22 @@ TEXT runtime·atomicstore64(SB), NOSPLIT, $0-12
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 jmpdefer(fn, sp);
// called from deferreturn.
// 1. pop the caller
// 2. sub 5 bytes from the callers return
// 3. jmp to the argument
TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8
- MOVL 4(SP), DX // fn
- MOVL 8(SP), BX // caller sp
+ MOVL fv+0(FP), DX // fn
+ MOVL argp+4(FP), BX // caller sp
LEAL -4(BX), SP // caller sp after CALL
SUBL $5, (SP) // return to CALL again
MOVL 0(DX), BX
@@ -597,16 +637,29 @@ TEXT gosave<>(SB),NOSPLIT,$0
// Call fn(arg) on the scheduler stack,
// aligned appropriately for the gcc ABI.
// See cgocall.c for more details.
-TEXT runtime·asmcgocall(SB),NOSPLIT,$0-8
+TEXT ·asmcgocall(SB),NOSPLIT,$0-8
MOVL fn+0(FP), AX
MOVL arg+4(FP), BX
+ CALL asmcgocall<>(SB)
+ RET
+
+TEXT ·asmcgocall_errno(SB),NOSPLIT,$0-12
+ MOVL fn+0(FP), AX
+ MOVL arg+4(FP), BX
+ CALL asmcgocall<>(SB)
+ MOVL AX, ret+8(FP)
+ RET
+
+TEXT asmcgocall<>(SB),NOSPLIT,$0-0
+ // fn in AX, arg in BX
MOVL SP, DX
// Figure out if we need to switch to m->g0 stack.
// We get called to create new OS threads too, and those
// come in on the m->g0 stack already.
get_tls(CX)
- MOVL m(CX), BP
+ MOVL g(CX), BP
+ MOVL g_m(BP), BP
MOVL m_g0(BP), SI
MOVL g(CX), DI
CMPL SI, DI
@@ -619,15 +672,19 @@ TEXT runtime·asmcgocall(SB),NOSPLIT,$0-8
SUBL $32, SP
ANDL $~15, SP // alignment, perhaps unnecessary
MOVL DI, 8(SP) // save g
- MOVL DX, 4(SP) // save SP
+ MOVL (g_stack+stack_hi)(DI), DI
+ SUBL DX, DI
+ MOVL DI, 4(SP) // save depth in stack (can't just save SP, as stack might be copied during a callback)
MOVL BX, 0(SP) // first argument in x86-32 ABI
CALL AX
// Restore registers, g, stack pointer.
get_tls(CX)
MOVL 8(SP), DI
+ MOVL (g_stack+stack_hi)(DI), SI
+ SUBL 4(SP), SI
MOVL DI, g(CX)
- MOVL 4(SP), SP
+ MOVL SI, SP
RET
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
@@ -646,8 +703,10 @@ TEXT runtime·cgocallback(SB),NOSPLIT,$12-12
// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
// See cgocall.c for more details.
-TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$12-12
- // If m is nil, Go did not create the current thread.
+TEXT ·cgocallback_gofunc(SB),NOSPLIT,$12-12
+ NO_LOCAL_POINTERS
+
+ // 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
@@ -656,19 +715,36 @@ TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$12-12
#ifdef GOOS_windows
MOVL $0, BP
CMPL CX, $0
- JEQ 2(PC)
+ JEQ 2(PC) // TODO
#endif
- MOVL m(CX), BP
- MOVL BP, DX // saved copy of oldm
+ MOVL g(CX), BP
CMPL BP, $0
- JNE havem
+ JEQ needm
+ MOVL g_m(BP), BP
+ MOVL BP, DX // saved copy of oldm
+ JMP havem
needm:
- MOVL DX, 0(SP)
+ MOVL $0, 0(SP)
MOVL $runtime·needm(SB), AX
CALL AX
MOVL 0(SP), DX
get_tls(CX)
- MOVL m(CX), BP
+ MOVL g(CX), BP
+ MOVL g_m(BP), BP
+
+ // 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 onM 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.
+ MOVL m_g0(BP), SI
+ MOVL SP, (g_sched+gobuf_sp)(SI)
havem:
// Now there's a valid m, and we're running on its m->g0.
@@ -718,7 +794,8 @@ havem:
// 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.)
- MOVL m(CX), BP
+ MOVL g(CX), BP
+ MOVL g_m(BP), BP
MOVL m_g0(BP), SI
MOVL SI, g(CX)
MOVL (g_sched+gobuf_sp)(SI), SP
@@ -735,69 +812,77 @@ havem:
// Done!
RET
-// void setmg(M*, G*); set m and g. for use by needm.
-TEXT runtime·setmg(SB), NOSPLIT, $0-8
+// void setg(G*); set g. for use by needm.
+TEXT runtime·setg(SB), NOSPLIT, $0-4
+ MOVL gg+0(FP), BX
#ifdef GOOS_windows
- MOVL mm+0(FP), AX
- CMPL AX, $0
+ CMPL BX, $0
JNE settls
MOVL $0, 0x14(FS)
RET
settls:
+ MOVL g_m(BX), AX
LEAL m_tls(AX), AX
MOVL AX, 0x14(FS)
#endif
- MOVL mm+0(FP), AX
get_tls(CX)
- MOVL mm+0(FP), AX
- MOVL AX, m(CX)
- MOVL gg+4(FP), BX
MOVL BX, g(CX)
RET
-// void setmg_gcc(M*, G*); set m and g. for use by gcc
-TEXT setmg_gcc<>(SB), NOSPLIT, $0
+// void setg_gcc(G*); set g. for use by gcc
+TEXT setg_gcc<>(SB), NOSPLIT, $0
get_tls(AX)
- MOVL mm+0(FP), DX
- MOVL DX, m(AX)
- MOVL gg+4(FP), DX
- MOVL DX,g (AX)
+ MOVL gg+0(FP), DX
+ MOVL DX, g(AX)
RET
-// check that SP is in range [g->stackbase, g->stackguard)
+// check that SP is in range [g->stack.lo, g->stack.hi)
TEXT runtime·stackcheck(SB), NOSPLIT, $0-0
get_tls(CX)
MOVL g(CX), AX
- CMPL g_stackbase(AX), SP
+ CMPL (g_stack+stack_hi)(AX), SP
JHI 2(PC)
INT $3
- CMPL SP, g_stackguard(AX)
+ CMPL SP, (g_stack+stack_lo)(AX)
JHI 2(PC)
INT $3
RET
-TEXT runtime·getcallerpc(SB),NOSPLIT,$0-4
- MOVL x+0(FP),AX // addr of first arg
+TEXT runtime·getcallerpc(SB),NOSPLIT,$0-8
+ MOVL argp+0(FP),AX // addr of first arg
+ MOVL -4(AX),AX // get calling pc
+ MOVL AX, ret+4(FP)
+ RET
+
+TEXT runtime·gogetcallerpc(SB),NOSPLIT,$0-8
+ MOVL p+0(FP),AX // addr of first arg
MOVL -4(AX),AX // get calling pc
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·setcallerpc(SB),NOSPLIT,$0-8
- MOVL x+0(FP),AX // addr of first arg
- MOVL x+4(FP), BX
+ MOVL argp+0(FP),AX // addr of first arg
+ MOVL pc+4(FP), BX
MOVL BX, -4(AX) // set calling pc
RET
-TEXT runtime·getcallersp(SB), NOSPLIT, $0-4
- MOVL sp+0(FP), AX
+TEXT runtime·getcallersp(SB), NOSPLIT, $0-8
+ MOVL argp+0(FP), AX
+ MOVL AX, ret+4(FP)
+ RET
+
+// func gogetcallersp(p unsafe.Pointer) uintptr
+TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-8
+ MOVL p+0(FP),AX // addr of first arg
+ MOVL AX, ret+4(FP)
RET
// int64 runtime·cputicks(void), so really
// void runtime·cputicks(int64 *ticks)
-TEXT runtime·cputicks(SB),NOSPLIT,$0-4
+TEXT runtime·cputicks(SB),NOSPLIT,$0-8
RDTSC
- MOVL ret+0(FP), DI
- MOVL AX, 0(DI)
- MOVL DX, 4(DI)
+ MOVL AX, ret_lo+0(FP)
+ MOVL DX, ret_hi+4(FP)
RET
TEXT runtime·ldt0setup(SB),NOSPLIT,$16-0
@@ -817,36 +902,23 @@ TEXT runtime·emptyfunc(SB),0,$0-0
TEXT runtime·abort(SB),NOSPLIT,$0-0
INT $0x3
-TEXT runtime·stackguard(SB),NOSPLIT,$0-8
- MOVL SP, DX
- MOVL DX, sp+0(FP)
- get_tls(CX)
- MOVL g(CX), BX
- MOVL g_stackguard(BX), DX
- MOVL DX, limit+4(FP)
- RET
-
-GLOBL runtime·tls0(SB), $32
-
// hash function using AES hardware instructions
-TEXT runtime·aeshash(SB),NOSPLIT,$0-12
- MOVL 4(SP), DX // ptr to hash value
- MOVL 8(SP), CX // size
- MOVL 12(SP), AX // ptr to data
+TEXT runtime·aeshash(SB),NOSPLIT,$0-16
+ MOVL p+0(FP), AX // ptr to data
+ MOVL s+4(FP), CX // size
JMP runtime·aeshashbody(SB)
-TEXT runtime·aeshashstr(SB),NOSPLIT,$0-12
- MOVL 4(SP), DX // ptr to hash value
- MOVL 12(SP), AX // ptr to string struct
+TEXT runtime·aeshashstr(SB),NOSPLIT,$0-16
+ MOVL p+0(FP), AX // ptr to string object
+ // s+4(FP) is ignored, it is always sizeof(String)
MOVL 4(AX), CX // length of string
MOVL (AX), AX // string data
JMP runtime·aeshashbody(SB)
// AX: data
// CX: length
-// DX: ptr to seed input / hash output
-TEXT runtime·aeshashbody(SB),NOSPLIT,$0-12
- MOVL (DX), X0 // seed to low 32 bits of xmm0
+TEXT runtime·aeshashbody(SB),NOSPLIT,$0-16
+ MOVL h+8(FP), X0 // seed to low 32 bits of xmm0
PINSRD $1, CX, X0 // size to next 32 bits of xmm0
MOVO runtime·aeskeysched+0(SB), X2
MOVO runtime·aeskeysched+16(SB), X3
@@ -897,29 +969,29 @@ finalize:
AESENC X2, X0
AESENC X3, X0
AESENC X2, X0
- MOVL X0, (DX)
+ MOVL X0, ret+12(FP)
RET
-TEXT runtime·aeshash32(SB),NOSPLIT,$0-12
- MOVL 4(SP), DX // ptr to hash value
- MOVL 12(SP), AX // ptr to data
- MOVL (DX), X0 // seed
+TEXT runtime·aeshash32(SB),NOSPLIT,$0-16
+ MOVL p+0(FP), AX // ptr to data
+ // s+4(FP) is ignored, it is always sizeof(int32)
+ MOVL h+8(FP), X0 // seed
PINSRD $1, (AX), X0 // data
AESENC runtime·aeskeysched+0(SB), X0
AESENC runtime·aeskeysched+16(SB), X0
AESENC runtime·aeskeysched+0(SB), X0
- MOVL X0, (DX)
+ MOVL X0, ret+12(FP)
RET
-TEXT runtime·aeshash64(SB),NOSPLIT,$0-12
- MOVL 4(SP), DX // ptr to hash value
- MOVL 12(SP), AX // ptr to data
+TEXT runtime·aeshash64(SB),NOSPLIT,$0-16
+ MOVL p+0(FP), AX // ptr to data
+ // s+4(FP) is ignored, it is always sizeof(int64)
MOVQ (AX), X0 // data
- PINSRD $2, (DX), X0 // seed
+ PINSRD $2, h+8(FP), X0 // seed
AESENC runtime·aeskeysched+0(SB), X0
AESENC runtime·aeskeysched+16(SB), X0
AESENC runtime·aeskeysched+0(SB), X0
- MOVL X0, (DX)
+ MOVL X0, ret+12(FP)
RET
// simple mask to get rid of data in the high part of the register.
@@ -1090,11 +1162,35 @@ DATA shifts<>+0xfc(SB)/4, $0xff0f0e0d
GLOBL shifts<>(SB),RODATA,$256
-TEXT runtime·memeq(SB),NOSPLIT,$0-12
+TEXT runtime·memeq(SB),NOSPLIT,$0-13
MOVL a+0(FP), SI
MOVL b+4(FP), DI
- MOVL count+8(FP), BX
- JMP runtime·memeqbody(SB)
+ MOVL size+8(FP), BX
+ CALL runtime·memeqbody(SB)
+ MOVB AX, ret+12(FP)
+ RET
+
+// eqstring tests whether two strings are equal.
+// See runtime_test.go:eqstring_generic for
+// equivalent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$0-17
+ MOVL s1len+4(FP), AX
+ MOVL s2len+12(FP), BX
+ CMPL AX, BX
+ JNE different
+ MOVL s1str+0(FP), SI
+ MOVL s2str+8(FP), DI
+ CMPL SI, DI
+ JEQ same
+ CALL runtime·memeqbody(SB)
+ MOVB AX, v+16(FP)
+ RET
+same:
+ MOVB $1, v+16(FP)
+ RET
+different:
+ MOVB $0, v+16(FP)
+ RET
TEXT bytes·Equal(SB),NOSPLIT,$0-25
MOVL a_len+4(FP), BX
@@ -1206,21 +1302,21 @@ equal:
RET
TEXT runtime·cmpstring(SB),NOSPLIT,$0-20
- MOVL s1+0(FP), SI
- MOVL s1+4(FP), BX
- MOVL s2+8(FP), DI
- MOVL s2+12(FP), DX
+ MOVL s1_base+0(FP), SI
+ MOVL s1_len+4(FP), BX
+ MOVL s2_base+8(FP), DI
+ MOVL s2_len+12(FP), DX
CALL runtime·cmpbody(SB)
- MOVL AX, res+16(FP)
+ MOVL AX, ret+16(FP)
RET
-TEXT bytes·Compare(SB),NOSPLIT,$0-28
+TEXT runtime·cmpbytes(SB),NOSPLIT,$0-28
MOVL s1+0(FP), SI
MOVL s1+4(FP), BX
MOVL s2+12(FP), DI
MOVL s2+16(FP), DX
CALL runtime·cmpbody(SB)
- MOVL AX, res+24(FP)
+ MOVL AX, ret+24(FP)
RET
TEXT bytes·IndexByte(SB),NOSPLIT,$0
@@ -2162,5 +2258,35 @@ TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
RET
-TEXT runtime·timenow(SB), NOSPLIT, $0-0
- JMP time·now(SB)
+TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
+ get_tls(CX)
+ MOVL g(CX), AX
+ MOVL g_m(AX), AX
+ MOVL m_fastrand(AX), DX
+ ADDL DX, DX
+ MOVL DX, BX
+ XORL $0x88888eef, DX
+ CMOVLMI BX, DX
+ MOVL DX, m_fastrand(AX)
+ MOVL DX, ret+0(FP)
+ RET
+
+TEXT runtime·return0(SB), NOSPLIT, $0
+ MOVL $0, AX
+ RET
+
+// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
+// Must obey the gcc calling convention.
+TEXT _cgo_topofstack(SB),NOSPLIT,$0
+ get_tls(CX)
+ MOVL g(CX), AX
+ MOVL g_m(AX), AX
+ MOVL m_curg(AX), AX
+ MOVL (g_stack+stack_hi)(AX), AX
+ RET
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$0-0
+ BYTE $0x90 // NOP
+ CALL runtime·goexit1(SB) // does not return
diff --git a/src/pkg/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index 2e2886609..39d7c78f2 100644
--- a/src/pkg/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -4,9 +4,9 @@
#include "zasm_GOOS_GOARCH.h"
#include "funcdata.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
-TEXT _rt0_go(SB),NOSPLIT,$0
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
// copy arguments forward on an even stack
MOVQ DI, AX // argc
MOVQ SI, BX // argv
@@ -19,9 +19,10 @@ TEXT _rt0_go(SB),NOSPLIT,$0
// _cgo_init may update stackguard.
MOVQ $runtime·g0(SB), DI
LEAQ (-64*1024+104)(SP), BX
- MOVQ BX, g_stackguard(DI)
MOVQ BX, g_stackguard0(DI)
- MOVQ SP, g_stackbase(DI)
+ MOVQ BX, g_stackguard1(DI)
+ MOVQ BX, (g_stack+stack_lo)(DI)
+ MOVQ SP, (g_stack+stack_hi)(DI)
// find out information about the processor we're on
MOVQ $0, AX
@@ -40,15 +41,18 @@ nocpuinfo:
JZ needtls
// g0 already in DI
MOVQ DI, CX // Win64 uses CX for first parameter
- MOVQ $setmg_gcc<>(SB), SI
+ MOVQ $setg_gcc<>(SB), SI
CALL AX
+
// update stackguard after _cgo_init
MOVQ $runtime·g0(SB), CX
- MOVQ g_stackguard0(CX), AX
- MOVQ AX, g_stackguard(CX)
+ MOVQ (g_stack+stack_lo)(CX), AX
+ ADDQ $const_StackGuard, AX
+ MOVQ AX, g_stackguard0(CX)
+ MOVQ AX, g_stackguard1(CX)
+
CMPL runtime·iswindows(SB), $0
JEQ ok
-
needtls:
// skip TLS setup on Plan 9
CMPL runtime·isplan9(SB), $1
@@ -73,10 +77,11 @@ ok:
LEAQ runtime·g0(SB), CX
MOVQ CX, g(BX)
LEAQ runtime·m0(SB), AX
- MOVQ AX, m(BX)
// save m->g0 = g0
MOVQ CX, m_g0(AX)
+ // save m0 to g0->m
+ MOVQ AX, g_m(CX)
CLD // convention is D is always left cleared
CALL runtime·check(SB)
@@ -87,15 +92,13 @@ ok:
MOVQ AX, 8(SP)
CALL runtime·args(SB)
CALL runtime·osinit(SB)
- CALL runtime·hashinit(SB)
CALL runtime·schedinit(SB)
// create a new goroutine to start program
- PUSHQ $runtime·main·f(SB) // entry
+ MOVQ $runtime·main·f(SB), BP // entry
+ PUSHQ BP
PUSHQ $0 // arg size
- ARGSIZE(16)
CALL runtime·newproc(SB)
- ARGSIZE(-1)
POPQ AX
POPQ AX
@@ -123,8 +126,8 @@ TEXT runtime·asminit(SB),NOSPLIT,$0-0
// void gosave(Gobuf*)
// save state in Gobuf; setjmp
TEXT runtime·gosave(SB), NOSPLIT, $0-8
- MOVQ 8(SP), AX // gobuf
- LEAQ 8(SP), BX // caller's SP
+ MOVQ buf+0(FP), AX // gobuf
+ LEAQ buf+0(FP), BX // caller's SP
MOVQ BX, gobuf_sp(AX)
MOVQ 0(SP), BX // caller's PC
MOVQ BX, gobuf_pc(AX)
@@ -138,7 +141,7 @@ TEXT runtime·gosave(SB), NOSPLIT, $0-8
// void gogo(Gobuf*)
// restore state from Gobuf; longjmp
TEXT runtime·gogo(SB), NOSPLIT, $0-8
- MOVQ 8(SP), BX // gobuf
+ MOVQ buf+0(FP), BX // gobuf
MOVQ gobuf_g(BX), DX
MOVQ 0(DX), CX // make sure g != nil
get_tls(CX)
@@ -152,7 +155,7 @@ TEXT runtime·gogo(SB), NOSPLIT, $0-8
MOVQ gobuf_pc(BX), BX
JMP BX
-// void mcall(void (*fn)(G*))
+// func 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.
@@ -163,12 +166,13 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-8
MOVQ g(CX), AX // save state in g->sched
MOVQ 0(SP), BX // caller's PC
MOVQ BX, (g_sched+gobuf_pc)(AX)
- LEAQ 8(SP), BX // caller's SP
+ LEAQ fn+0(FP), BX // caller's SP
MOVQ BX, (g_sched+gobuf_sp)(AX)
MOVQ AX, (g_sched+gobuf_g)(AX)
// switch to m->g0 & its stack, call fn
- MOVQ m(CX), BX
+ MOVQ g(CX), BX
+ MOVQ g_m(BX), BX
MOVQ m_g0(BX), SI
CMPQ SI, AX // if g == m->g0 call badmcall
JNE 3(PC)
@@ -177,19 +181,103 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-8
MOVQ SI, g(CX) // g = m->g0
MOVQ (g_sched+gobuf_sp)(SI), SP // sp = m->g0->sched.sp
PUSHQ AX
- ARGSIZE(8)
+ MOVQ DI, DX
+ MOVQ 0(DI), DI
CALL DI
POPQ AX
MOVQ $runtime·badmcall2(SB), AX
JMP AX
RET
+// switchtoM is a dummy routine that onM 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 M stack because the one at the top of
+// the M stack terminates the stack walk (see topofstack()).
+TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
+ RET
+
+// func onM_signalok(fn func())
+TEXT runtime·onM_signalok(SB), NOSPLIT, $0-8
+ get_tls(CX)
+ MOVQ g(CX), AX // AX = g
+ MOVQ g_m(AX), BX // BX = m
+ MOVQ m_gsignal(BX), DX // DX = gsignal
+ CMPQ AX, DX
+ JEQ ongsignal
+ JMP runtime·onM(SB)
+
+ongsignal:
+ MOVQ fn+0(FP), DI // DI = fn
+ MOVQ DI, DX
+ MOVQ 0(DI), DI
+ CALL DI
+ RET
+
+// func onM(fn func())
+TEXT runtime·onM(SB), NOSPLIT, $0-8
+ MOVQ fn+0(FP), DI // DI = fn
+ get_tls(CX)
+ MOVQ g(CX), AX // AX = g
+ MOVQ g_m(AX), BX // BX = m
+
+ MOVQ m_g0(BX), DX // DX = g0
+ CMPQ AX, DX
+ JEQ onm
+
+ MOVQ m_curg(BX), BP
+ CMPQ AX, BP
+ JEQ oncurg
+
+ // Not g0, not curg. Must be gsignal, but that's not allowed.
+ // Hide call from linker nosplit analysis.
+ MOVQ $runtime·badonm(SB), AX
+ CALL AX
+
+oncurg:
+ // save our state in g->sched. Pretend to
+ // be switchtoM if the G stack is scanned.
+ MOVQ $runtime·switchtoM(SB), BP
+ MOVQ BP, (g_sched+gobuf_pc)(AX)
+ MOVQ SP, (g_sched+gobuf_sp)(AX)
+ MOVQ AX, (g_sched+gobuf_g)(AX)
+
+ // switch to g0
+ MOVQ DX, g(CX)
+ MOVQ (g_sched+gobuf_sp)(DX), BX
+ // make it look like mstart called onM on g0, to stop traceback
+ SUBQ $8, BX
+ MOVQ $runtime·mstart(SB), DX
+ MOVQ DX, 0(BX)
+ MOVQ BX, SP
+
+ // call target function
+ MOVQ DI, DX
+ MOVQ 0(DI), DI
+ CALL DI
+
+ // switch back to g
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), BX
+ MOVQ m_curg(BX), AX
+ MOVQ AX, g(CX)
+ MOVQ (g_sched+gobuf_sp)(AX), SP
+ MOVQ $0, (g_sched+gobuf_sp)(AX)
+ RET
+
+onm:
+ // already on m stack, just call directly
+ MOVQ DI, DX
+ MOVQ 0(DI), DI
+ CALL DI
+ RET
+
/*
* support for morestack
*/
// Called during function prolog when more stack is needed.
-// Caller has already done get_tls(CX); MOVQ m(CX), BX.
//
// The traceback routines see morestack on a g0 as being
// the top of a stack (for example, morestack calling newstack
@@ -197,18 +285,26 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-8
// record an argument size. For that purpose, it has no arguments.
TEXT runtime·morestack(SB),NOSPLIT,$0-0
// Cannot grow scheduler stack (m->g0).
+ get_tls(CX)
+ MOVQ g(CX), BX
+ MOVQ g_m(BX), BX
MOVQ m_g0(BX), SI
CMPQ g(CX), SI
JNE 2(PC)
INT $3
+ // Cannot grow signal stack (m->gsignal).
+ MOVQ m_gsignal(BX), SI
+ CMPQ g(CX), SI
+ JNE 2(PC)
+ INT $3
+
// Called from f.
// Set m->morebuf to f's caller.
MOVQ 8(SP), AX // f's caller's PC
MOVQ AX, (m_morebuf+gobuf_pc)(BX)
LEAQ 16(SP), AX // f's caller's SP
MOVQ AX, (m_morebuf+gobuf_sp)(BX)
- MOVQ AX, m_moreargp(BX)
get_tls(CX)
MOVQ g(CX), SI
MOVQ SI, (m_morebuf+gobuf_g)(BX)
@@ -229,55 +325,13 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0
MOVQ $0, 0x1003 // crash if newstack returns
RET
-// Called from panic. Mimics morestack,
-// reuses stack growth code to create a frame
-// with the desired args running the desired function.
-//
-// func call(fn *byte, arg *byte, argsize uint32).
-TEXT runtime·newstackcall(SB), NOSPLIT, $0-20
- get_tls(CX)
- MOVQ m(CX), BX
-
- // Save our caller's state as the PC and SP to
- // restore when returning from f.
- MOVQ 0(SP), AX // our caller's PC
- MOVQ AX, (m_morebuf+gobuf_pc)(BX)
- LEAQ 8(SP), AX // our caller's SP
- MOVQ AX, (m_morebuf+gobuf_sp)(BX)
- MOVQ g(CX), AX
- MOVQ AX, (m_morebuf+gobuf_g)(BX)
-
- // Save our own state as the PC and SP to restore
- // if this goroutine needs to be restarted.
- MOVQ $runtime·newstackcall(SB), (g_sched+gobuf_pc)(AX)
- MOVQ SP, (g_sched+gobuf_sp)(AX)
-
- // Set up morestack arguments to call f on a new stack.
- // We set f's frame size to 1, as a hint to newstack
- // that this is a call from runtime·newstackcall.
- // If it turns out that f needs a larger frame than
- // the default stack, f's usual stack growth prolog will
- // allocate a new segment (and recopy the arguments).
- MOVQ 8(SP), AX // fn
- MOVQ 16(SP), DX // arg frame
- MOVL 24(SP), CX // arg size
-
- MOVQ AX, m_cret(BX) // f's PC
- MOVQ DX, m_moreargp(BX) // argument frame pointer
- MOVL CX, m_moreargsize(BX) // f's argument size
- MOVL $1, m_moreframesize(BX) // f's frame size
-
- // Call newstack on m->g0's stack.
- MOVQ m_g0(BX), BP
- get_tls(CX)
- MOVQ BP, g(CX)
- MOVQ (g_sched+gobuf_sp)(BP), SP
- CALL runtime·newstack(SB)
- MOVQ $0, 0x1103 // crash if newstack returns
- RET
+// morestack but not preserving ctxt.
+TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack(SB)
-// reflect·call: call a function with the given argument list
-// func call(f *FuncVal, arg *byte, argsize uint32).
+// reflectcall: call a function with the given argument list
+// func call(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!
@@ -285,58 +339,45 @@ TEXT runtime·newstackcall(SB), NOSPLIT, $0-20
#define DISPATCH(NAME,MAXSIZE) \
CMPQ CX, $MAXSIZE; \
JA 3(PC); \
- MOVQ $runtime·NAME(SB), AX; \
+ MOVQ $NAME(SB), AX; \
JMP AX
-// Note: can't just "JMP runtime·NAME(SB)" - bad inlining results.
+// Note: can't just "JMP NAME(SB)" - bad inlining results.
-TEXT reflect·call(SB), NOSPLIT, $0-24
+TEXT ·reflectcall(SB), NOSPLIT, $0-24
MOVLQZX argsize+16(FP), CX
- DISPATCH(call16, 16)
- DISPATCH(call32, 32)
- DISPATCH(call64, 64)
- DISPATCH(call128, 128)
- DISPATCH(call256, 256)
- DISPATCH(call512, 512)
- DISPATCH(call1024, 1024)
- DISPATCH(call2048, 2048)
- DISPATCH(call4096, 4096)
- DISPATCH(call8192, 8192)
- DISPATCH(call16384, 16384)
- DISPATCH(call32768, 32768)
- DISPATCH(call65536, 65536)
- DISPATCH(call131072, 131072)
- DISPATCH(call262144, 262144)
- DISPATCH(call524288, 524288)
- DISPATCH(call1048576, 1048576)
- DISPATCH(call2097152, 2097152)
- DISPATCH(call4194304, 4194304)
- DISPATCH(call8388608, 8388608)
- DISPATCH(call16777216, 16777216)
- DISPATCH(call33554432, 33554432)
- DISPATCH(call67108864, 67108864)
- DISPATCH(call134217728, 134217728)
- DISPATCH(call268435456, 268435456)
- DISPATCH(call536870912, 536870912)
- DISPATCH(call1073741824, 1073741824)
+ DISPATCH(runtime·call16, 16)
+ 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)
MOVQ $runtime·badreflectcall(SB), AX
JMP AX
-// Argument map for the callXX frames. Each has one
-// stack map (for the single call) with 3 arguments.
-DATA gcargs_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
-DATA gcargs_reflectcall<>+0x04(SB)/4, $6 // 3 args
-DATA gcargs_reflectcall<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsScalar<<4))
-GLOBL gcargs_reflectcall<>(SB),RODATA,$12
-
-// callXX frames have no locals
-DATA gclocals_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
-DATA gclocals_reflectcall<>+0x04(SB)/4, $0 // 0 locals
-GLOBL gclocals_reflectcall<>(SB),RODATA,$8
-
#define CALLFN(NAME,MAXSIZE) \
-TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-24; \
- FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_reflectcall<>(SB); \
- FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_reflectcall<>(SB);\
+TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \
+ NO_LOCAL_POINTERS; \
/* copy arguments to stack */ \
MOVQ argptr+8(FP), SI; \
MOVLQZX argsize+16(FP), CX; \
@@ -357,163 +398,33 @@ TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-24; \
REP;MOVSB; \
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)
-
-// Return point when leaving stack.
-//
-// Lessstack can appear in stack traces for the same reason
-// as morestack; in that context, it has 0 arguments.
-TEXT runtime·lessstack(SB), NOSPLIT, $0-0
- // Save return value in m->cret
- get_tls(CX)
- MOVQ m(CX), BX
- MOVQ AX, m_cret(BX)
-
- // Call oldstack on m->g0's stack.
- MOVQ m_g0(BX), BP
- MOVQ BP, g(CX)
- MOVQ (g_sched+gobuf_sp)(BP), SP
- CALL runtime·oldstack(SB)
- MOVQ $0, 0x1004 // crash if oldstack returns
- RET
-
-// morestack trampolines
-TEXT runtime·morestack00(SB),NOSPLIT,$0
- get_tls(CX)
- MOVQ m(CX), BX
- MOVQ $0, AX
- MOVQ AX, m_moreframesize(BX)
- MOVQ $runtime·morestack(SB), AX
- JMP AX
-
-TEXT runtime·morestack01(SB),NOSPLIT,$0
- get_tls(CX)
- MOVQ m(CX), BX
- SHLQ $32, AX
- MOVQ AX, m_moreframesize(BX)
- MOVQ $runtime·morestack(SB), AX
- JMP AX
-
-TEXT runtime·morestack10(SB),NOSPLIT,$0
- get_tls(CX)
- MOVQ m(CX), BX
- MOVLQZX AX, AX
- MOVQ AX, m_moreframesize(BX)
- MOVQ $runtime·morestack(SB), AX
- JMP AX
-
-TEXT runtime·morestack11(SB),NOSPLIT,$0
- get_tls(CX)
- MOVQ m(CX), BX
- MOVQ AX, m_moreframesize(BX)
- MOVQ $runtime·morestack(SB), AX
- JMP AX
-
-// subcases of morestack01
-// with const of 8,16,...48
-TEXT runtime·morestack8(SB),NOSPLIT,$0
- MOVQ $1, R8
- MOVQ $morestack<>(SB), AX
- JMP AX
-
-TEXT runtime·morestack16(SB),NOSPLIT,$0
- MOVQ $2, R8
- MOVQ $morestack<>(SB), AX
- JMP AX
-
-TEXT runtime·morestack24(SB),NOSPLIT,$0
- MOVQ $3, R8
- MOVQ $morestack<>(SB), AX
- JMP AX
-
-TEXT runtime·morestack32(SB),NOSPLIT,$0
- MOVQ $4, R8
- MOVQ $morestack<>(SB), AX
- JMP AX
-
-TEXT runtime·morestack40(SB),NOSPLIT,$0
- MOVQ $5, R8
- MOVQ $morestack<>(SB), AX
- JMP AX
-
-TEXT runtime·morestack48(SB),NOSPLIT,$0
- MOVQ $6, R8
- MOVQ $morestack<>(SB), AX
- JMP AX
-
-TEXT morestack<>(SB),NOSPLIT,$0
- get_tls(CX)
- MOVQ m(CX), BX
- SHLQ $35, R8
- MOVQ R8, m_moreframesize(BX)
- MOVQ $runtime·morestack(SB), AX
- JMP AX
-
-TEXT runtime·morestack00_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack00(SB)
-
-TEXT runtime·morestack01_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack01(SB)
-
-TEXT runtime·morestack10_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack10(SB)
-
-TEXT runtime·morestack11_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack11(SB)
-
-TEXT runtime·morestack8_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack8(SB)
-
-TEXT runtime·morestack16_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack16(SB)
-
-TEXT runtime·morestack24_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack24(SB)
-
-TEXT runtime·morestack32_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack32(SB)
-
-TEXT runtime·morestack40_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack40(SB)
-
-TEXT runtime·morestack48_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack48(SB)
+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)
// bool cas(int32 *val, int32 old, int32 new)
// Atomically:
@@ -522,16 +433,18 @@ TEXT runtime·morestack48_noctxt(SB),NOSPLIT,$0
// return 1;
// } else
// return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-16
- MOVQ 8(SP), BX
- MOVL 16(SP), AX
- MOVL 20(SP), CX
+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)
- JZ 3(PC)
+ JZ 4(PC)
MOVL $0, AX
+ MOVB AX, ret+16(FP)
RET
MOVL $1, AX
+ MOVB AX, ret+16(FP)
RET
// bool runtime·cas64(uint64 *val, uint64 old, uint64 new)
@@ -542,18 +455,32 @@ TEXT runtime·cas(SB), NOSPLIT, $0-16
// } else {
// return 0;
// }
-TEXT runtime·cas64(SB), NOSPLIT, $0-24
- MOVQ 8(SP), BX
- MOVQ 16(SP), AX
- MOVQ 24(SP), CX
+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)
JNZ cas64_fail
MOVL $1, AX
+ MOVB AX, ret+24(FP)
RET
cas64_fail:
MOVL $0, AX
+ MOVB AX, 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:
@@ -562,60 +489,70 @@ cas64_fail:
// return 1;
// } else
// return 0;
-TEXT runtime·casp(SB), NOSPLIT, $0-24
- MOVQ 8(SP), BX
- MOVQ 16(SP), AX
- MOVQ 24(SP), CX
+TEXT runtime·casp(SB), NOSPLIT, $0-25
+ MOVQ ptr+0(FP), BX
+ MOVQ old+8(FP), AX
+ MOVQ new+16(FP), CX
LOCK
CMPXCHGQ CX, 0(BX)
- JZ 3(PC)
+ JZ 4(PC)
MOVL $0, AX
+ MOVB AX, ret+24(FP)
RET
MOVL $1, AX
+ MOVB AX, ret+24(FP)
RET
// uint32 xadd(uint32 volatile *val, int32 delta)
// Atomically:
// *val += delta;
// return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-12
- MOVQ 8(SP), BX
- MOVL 16(SP), AX
+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-16
- MOVQ 8(SP), BX
- MOVQ 16(SP), AX
+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·xchg(SB), NOSPLIT, $0-12
- MOVQ 8(SP), BX
- MOVL 16(SP), AX
+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-16
- MOVQ 8(SP), BX
- MOVQ 16(SP), AX
+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·xchgp(SB), NOSPLIT, $0-16
- MOVQ 8(SP), BX
- MOVQ 16(SP), AX
+TEXT runtime·xchgp(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 8(SP), AX
+ MOVL cycles+0(FP), AX
again:
PAUSE
SUBL $1, AX
@@ -623,31 +560,39 @@ again:
RET
TEXT runtime·atomicstorep(SB), NOSPLIT, $0-16
- MOVQ 8(SP), BX
- MOVQ 16(SP), AX
+ MOVQ ptr+0(FP), BX
+ MOVQ val+8(FP), AX
XCHGQ AX, 0(BX)
RET
TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
- MOVQ 8(SP), BX
- MOVL 16(SP), AX
+ MOVQ ptr+0(FP), BX
+ MOVL val+8(FP), AX
XCHGL AX, 0(BX)
RET
TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
- MOVQ 8(SP), BX
- MOVQ 16(SP), AX
+ 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 jmpdefer(fn, sp);
// called from deferreturn.
// 1. pop the caller
// 2. sub 5 bytes from the callers return
// 3. jmp to the argument
TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16
- MOVQ 8(SP), DX // fn
- MOVQ 16(SP), BX // caller sp
+ MOVQ fv+0(FP), DX // fn
+ MOVQ argp+8(FP), BX // caller sp
LEAQ -8(BX), SP // caller sp after CALL
SUBQ $5, (SP) // return to CALL again
MOVQ 0(DX), BX
@@ -669,16 +614,29 @@ TEXT gosave<>(SB),NOSPLIT,$0
// Call fn(arg) on the scheduler stack,
// aligned appropriately for the gcc ABI.
// See cgocall.c for more details.
-TEXT runtime·asmcgocall(SB),NOSPLIT,$0-16
+TEXT ·asmcgocall(SB),NOSPLIT,$0-16
+ MOVQ fn+0(FP), AX
+ MOVQ arg+8(FP), BX
+ CALL asmcgocall<>(SB)
+ RET
+
+TEXT ·asmcgocall_errno(SB),NOSPLIT,$0-20
MOVQ fn+0(FP), AX
MOVQ arg+8(FP), BX
+ CALL asmcgocall<>(SB)
+ MOVL AX, ret+16(FP)
+ RET
+
+// asmcgocall common code. fn in AX, arg in BX. returns errno in AX.
+TEXT asmcgocall<>(SB),NOSPLIT,$0-0
MOVQ SP, DX
// Figure out if we need to switch to m->g0 stack.
// We get called to create new OS threads too, and those
// come in on the m->g0 stack already.
get_tls(CX)
- MOVQ m(CX), BP
+ MOVQ g(CX), BP
+ MOVQ g_m(BP), BP
MOVQ m_g0(BP), SI
MOVQ g(CX), DI
CMPQ SI, DI
@@ -699,7 +657,9 @@ nosave:
SUBQ $64, SP
ANDQ $~15, SP // alignment for gcc ABI
MOVQ DI, 48(SP) // save g
- MOVQ DX, 40(SP) // save SP
+ MOVQ (g_stack+stack_hi)(DI), DI
+ SUBQ DX, DI
+ MOVQ DI, 40(SP) // save depth in stack (can't just save SP, as stack might be copied during a callback)
MOVQ BX, DI // DI = first argument in AMD64 ABI
MOVQ BX, CX // CX = first argument in Win64
CALL AX
@@ -707,8 +667,10 @@ nosave:
// Restore registers, g, stack pointer.
get_tls(CX)
MOVQ 48(SP), DI
+ MOVQ (g_stack+stack_hi)(DI), SI
+ SUBQ 40(SP), SI
MOVQ DI, g(CX)
- MOVQ 40(SP), SP
+ MOVQ SI, SP
RET
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
@@ -727,9 +689,11 @@ TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
// See cgocall.c for more details.
-TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$8-24
- // If m is nil, Go did not create the current thread.
- // Call needm to obtain one for temporary use.
+TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-24
+ NO_LOCAL_POINTERS
+
+ // If g is nil, Go did not create the current thread.
+ // Call needm to obtain one m 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 through AX.
@@ -739,17 +703,34 @@ TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$8-24
CMPQ CX, $0
JEQ 2(PC)
#endif
- MOVQ m(CX), BP
- MOVQ BP, R8 // holds oldm until end of function
+ MOVQ g(CX), BP
CMPQ BP, $0
- JNE havem
+ JEQ needm
+ MOVQ g_m(BP), BP
+ MOVQ BP, R8 // holds oldm until end of function
+ JMP havem
needm:
- MOVQ R8, 0(SP)
+ MOVQ $0, 0(SP)
MOVQ $runtime·needm(SB), AX
CALL AX
MOVQ 0(SP), R8
get_tls(CX)
- MOVQ m(CX), BP
+ MOVQ g(CX), BP
+ MOVQ g_m(BP), BP
+
+ // 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 onM 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.
+ MOVQ m_g0(BP), SI
+ MOVQ SP, (g_sched+gobuf_sp)(SI)
havem:
// Now there's a valid m, and we're running on its m->g0.
@@ -784,8 +765,7 @@ havem:
MOVQ BP, -8(DI)
LEAQ -(8+8)(DI), SP
MOVQ R8, 0(SP)
- MOVQ $runtime·cgocallbackg(SB), AX // hide function call from linker
- CALL AX
+ CALL runtime·cgocallbackg(SB)
MOVQ 0(SP), R8
// Restore g->sched (== m->curg->sched) from saved values.
@@ -799,7 +779,8 @@ havem:
// 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.)
- MOVQ m(CX), BP
+ MOVQ g(CX), BP
+ MOVQ g_m(BP), BP
MOVQ m_g0(BP), SI
MOVQ SI, g(CX)
MOVQ (g_sched+gobuf_sp)(SI), SP
@@ -816,57 +797,68 @@ havem:
// Done!
RET
-// void setmg(M*, G*); set m and g. for use by needm.
-TEXT runtime·setmg(SB), NOSPLIT, $0-16
- MOVQ mm+0(FP), AX
+// void setg(G*); set g. for use by needm.
+TEXT runtime·setg(SB), NOSPLIT, $0-8
+ MOVQ gg+0(FP), BX
#ifdef GOOS_windows
- CMPQ AX, $0
+ CMPQ BX, $0
JNE settls
MOVQ $0, 0x28(GS)
RET
settls:
+ MOVQ g_m(BX), AX
LEAQ m_tls(AX), AX
MOVQ AX, 0x28(GS)
#endif
get_tls(CX)
- MOVQ mm+0(FP), AX
- MOVQ AX, m(CX)
- MOVQ gg+8(FP), BX
MOVQ BX, g(CX)
RET
-// void setmg_gcc(M*, G*); set m and g called from gcc.
-TEXT setmg_gcc<>(SB),NOSPLIT,$0
+// void setg_gcc(G*); set g called from gcc.
+TEXT setg_gcc<>(SB),NOSPLIT,$0
get_tls(AX)
- MOVQ DI, m(AX)
- MOVQ SI, g(AX)
+ MOVQ DI, g(AX)
RET
-// check that SP is in range [g->stackbase, g->stackguard)
+// check that SP is in range [g->stack.lo, g->stack.hi)
TEXT runtime·stackcheck(SB), NOSPLIT, $0-0
get_tls(CX)
MOVQ g(CX), AX
- CMPQ g_stackbase(AX), SP
+ CMPQ (g_stack+stack_hi)(AX), SP
JHI 2(PC)
INT $3
- CMPQ SP, g_stackguard(AX)
+ CMPQ SP, (g_stack+stack_lo)(AX)
JHI 2(PC)
INT $3
RET
-TEXT runtime·getcallerpc(SB),NOSPLIT,$0-8
- MOVQ x+0(FP),AX // addr of first arg
+TEXT runtime·getcallerpc(SB),NOSPLIT,$0-16
+ MOVQ argp+0(FP),AX // addr of first arg
MOVQ -8(AX),AX // get calling pc
+ MOVQ AX, ret+8(FP)
+ RET
+
+TEXT runtime·gogetcallerpc(SB),NOSPLIT,$0-16
+ MOVQ p+0(FP),AX // addr of first arg
+ MOVQ -8(AX),AX // get calling pc
+ MOVQ AX,ret+8(FP)
RET
TEXT runtime·setcallerpc(SB),NOSPLIT,$0-16
- MOVQ x+0(FP),AX // addr of first arg
- MOVQ x+8(FP), BX
+ MOVQ argp+0(FP),AX // addr of first arg
+ MOVQ pc+8(FP), BX
MOVQ BX, -8(AX) // set calling pc
RET
-TEXT runtime·getcallersp(SB),NOSPLIT,$0-8
- MOVQ sp+0(FP), AX
+TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
+ MOVQ argp+0(FP), AX
+ MOVQ AX, ret+8(FP)
+ RET
+
+// func gogetcallersp(p unsafe.Pointer) uintptr
+TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-16
+ MOVQ p+0(FP),AX // addr of first arg
+ MOVQ AX, ret+8(FP)
RET
// int64 runtime·cputicks(void)
@@ -874,38 +866,26 @@ TEXT runtime·cputicks(SB),NOSPLIT,$0-0
RDTSC
SHLQ $32, DX
ADDQ DX, AX
+ MOVQ AX, ret+0(FP)
RET
-TEXT runtime·stackguard(SB),NOSPLIT,$0-16
- MOVQ SP, DX
- MOVQ DX, sp+0(FP)
- get_tls(CX)
- MOVQ g(CX), BX
- MOVQ g_stackguard(BX), DX
- MOVQ DX, limit+8(FP)
- RET
-
-GLOBL runtime·tls0(SB), $64
-
// hash function using AES hardware instructions
-TEXT runtime·aeshash(SB),NOSPLIT,$0-24
- MOVQ 8(SP), DX // ptr to hash value
- MOVQ 16(SP), CX // size
- MOVQ 24(SP), AX // ptr to data
+TEXT runtime·aeshash(SB),NOSPLIT,$0-32
+ MOVQ p+0(FP), AX // ptr to data
+ MOVQ s+8(FP), CX // size
JMP runtime·aeshashbody(SB)
-TEXT runtime·aeshashstr(SB),NOSPLIT,$0-24
- MOVQ 8(SP), DX // ptr to hash value
- MOVQ 24(SP), AX // ptr to string struct
+TEXT runtime·aeshashstr(SB),NOSPLIT,$0-32
+ MOVQ p+0(FP), AX // ptr to string struct
+ // s+8(FP) is ignored, it is always sizeof(String)
MOVQ 8(AX), CX // length of string
MOVQ (AX), AX // string data
JMP runtime·aeshashbody(SB)
// AX: data
// CX: length
-// DX: ptr to seed input / hash output
-TEXT runtime·aeshashbody(SB),NOSPLIT,$0-24
- MOVQ (DX), X0 // seed to low 64 bits of xmm0
+TEXT runtime·aeshashbody(SB),NOSPLIT,$0-32
+ MOVQ h+16(FP), X0 // seed to low 64 bits of xmm0
PINSRQ $1, CX, X0 // size to high 64 bits of xmm0
MOVO runtime·aeskeysched+0(SB), X2
MOVO runtime·aeskeysched+16(SB), X3
@@ -938,7 +918,8 @@ aessmall:
// a page boundary, so we can load it directly.
MOVOU (AX), X1
ADDQ CX, CX
- PAND masks<>(SB)(CX*8), X1
+ MOVQ $masks<>(SB), BP
+ PAND (BP)(CX*8), X1
JMP partial
highpartial:
// address ends in 1111xxxx. Might be up against
@@ -946,7 +927,8 @@ highpartial:
// Then shift bytes down using pshufb.
MOVOU -16(AX)(CX*1), X1
ADDQ CX, CX
- PSHUFB shifts<>(SB)(CX*8), X1
+ MOVQ $shifts<>(SB), BP
+ PSHUFB (BP)(CX*8), X1
partial:
// incorporate partial block into hash
AESENC X3, X0
@@ -956,29 +938,29 @@ finalize:
AESENC X2, X0
AESENC X3, X0
AESENC X2, X0
- MOVQ X0, (DX)
+ MOVQ X0, res+24(FP)
RET
-TEXT runtime·aeshash32(SB),NOSPLIT,$0-24
- MOVQ 8(SP), DX // ptr to hash value
- MOVQ 24(SP), AX // ptr to data
- MOVQ (DX), X0 // seed
+TEXT runtime·aeshash32(SB),NOSPLIT,$0-32
+ MOVQ p+0(FP), AX // ptr to data
+ // s+8(FP) is ignored, it is always sizeof(int32)
+ MOVQ h+16(FP), X0 // seed
PINSRD $2, (AX), X0 // data
AESENC runtime·aeskeysched+0(SB), X0
AESENC runtime·aeskeysched+16(SB), X0
AESENC runtime·aeskeysched+0(SB), X0
- MOVQ X0, (DX)
+ MOVQ X0, ret+24(FP)
RET
-TEXT runtime·aeshash64(SB),NOSPLIT,$0-24
- MOVQ 8(SP), DX // ptr to hash value
- MOVQ 24(SP), AX // ptr to data
- MOVQ (DX), X0 // seed
+TEXT runtime·aeshash64(SB),NOSPLIT,$0-32
+ MOVQ p+0(FP), AX // ptr to data
+ // s+8(FP) is ignored, it is always sizeof(int64)
+ MOVQ h+16(FP), X0 // seed
PINSRQ $1, (AX), X0 // data
AESENC runtime·aeskeysched+0(SB), X0
AESENC runtime·aeskeysched+16(SB), X0
AESENC runtime·aeskeysched+0(SB), X0
- MOVQ X0, (DX)
+ MOVQ X0, ret+24(FP)
RET
// simple mask to get rid of data in the high part of the register.
@@ -1053,11 +1035,35 @@ DATA shifts<>+0xf0(SB)/8, $0x0807060504030201
DATA shifts<>+0xf8(SB)/8, $0xff0f0e0d0c0b0a09
GLOBL shifts<>(SB),RODATA,$256
-TEXT runtime·memeq(SB),NOSPLIT,$0-24
+TEXT runtime·memeq(SB),NOSPLIT,$0-25
MOVQ a+0(FP), SI
MOVQ b+8(FP), DI
- MOVQ count+16(FP), BX
- JMP runtime·memeqbody(SB)
+ MOVQ size+16(FP), BX
+ CALL runtime·memeqbody(SB)
+ MOVB AX, ret+24(FP)
+ RET
+
+// eqstring tests whether two strings are equal.
+// See runtime_test.go:eqstring_generic for
+// equivalent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$0-33
+ MOVQ s1len+8(FP), AX
+ MOVQ s2len+24(FP), BX
+ CMPQ AX, BX
+ JNE different
+ MOVQ s1str+0(FP), SI
+ MOVQ s2str+16(FP), DI
+ CMPQ SI, DI
+ JEQ same
+ CALL runtime·memeqbody(SB)
+ MOVB AX, v+32(FP)
+ RET
+same:
+ MOVB $1, v+32(FP)
+ RET
+different:
+ MOVB $0, v+32(FP)
+ RET
// a in SI
// b in DI
@@ -1152,15 +1158,15 @@ equal:
RET
TEXT runtime·cmpstring(SB),NOSPLIT,$0-40
- MOVQ s1+0(FP), SI
- MOVQ s1+8(FP), BX
- MOVQ s2+16(FP), DI
- MOVQ s2+24(FP), DX
+ MOVQ s1_base+0(FP), SI
+ MOVQ s1_len+8(FP), BX
+ MOVQ s2_base+16(FP), DI
+ MOVQ s2_len+24(FP), DX
CALL runtime·cmpbody(SB)
- MOVQ AX, res+32(FP)
+ MOVQ AX, ret+32(FP)
RET
-TEXT bytes·Compare(SB),NOSPLIT,$0-56
+TEXT runtime·cmpbytes(SB),NOSPLIT,$0-56
MOVQ s1+0(FP), SI
MOVQ s1+8(FP), BX
MOVQ s2+24(FP), DI
@@ -2196,5 +2202,36 @@ TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
RET
-TEXT runtime·timenow(SB), NOSPLIT, $0-0
- JMP time·now(SB)
+TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), AX
+ MOVL m_fastrand(AX), DX
+ ADDL DX, DX
+ MOVL DX, BX
+ XORL $0x88888eef, DX
+ CMOVLMI BX, DX
+ MOVL DX, m_fastrand(AX)
+ MOVL DX, ret+0(FP)
+ RET
+
+TEXT runtime·return0(SB), NOSPLIT, $0
+ MOVL $0, AX
+ RET
+
+
+// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
+// Must obey the gcc calling convention.
+TEXT _cgo_topofstack(SB),NOSPLIT,$0
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), AX
+ MOVQ m_curg(AX), AX
+ MOVQ (g_stack+stack_hi)(AX), AX
+ RET
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$0-0
+ BYTE $0x90 // NOP
+ CALL runtime·goexit1(SB) // does not return
diff --git a/src/pkg/runtime/asm_amd64p32.s b/src/runtime/asm_amd64p32.s
index d47f12283..a1116b5d4 100644
--- a/src/pkg/runtime/asm_amd64p32.s
+++ b/src/runtime/asm_amd64p32.s
@@ -4,9 +4,9 @@
#include "zasm_GOOS_GOARCH.h"
#include "funcdata.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
-TEXT _rt0_go(SB),NOSPLIT,$0
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
// copy arguments forward on an even stack
MOVL argc+0(FP), AX
MOVL argv+4(FP), BX
@@ -20,10 +20,11 @@ TEXT _rt0_go(SB),NOSPLIT,$0
// create istack out of the given (operating system) stack.
MOVL $runtime·g0(SB), DI
- LEAL (-64*1024+104)(SP), DI
- MOVL BX, g_stackguard(DI)
+ LEAL (-64*1024+104)(SP), BX
MOVL BX, g_stackguard0(DI)
- MOVL SP, g_stackbase(DI)
+ MOVL BX, g_stackguard1(DI)
+ MOVL BX, (g_stack+stack_lo)(DI)
+ MOVL SP, (g_stack+stack_hi)(DI)
// find out information about the processor we're on
MOVQ $0, AX
@@ -53,10 +54,11 @@ ok:
LEAL runtime·g0(SB), CX
MOVL CX, g(BX)
LEAL runtime·m0(SB), AX
- MOVL AX, m(BX)
// save m->g0 = g0
MOVL CX, m_g0(AX)
+ // save m0 to g0->m
+ MOVL AX, g_m(CX)
CLD // convention is D is always left cleared
CALL runtime·check(SB)
@@ -67,16 +69,13 @@ ok:
MOVL AX, 4(SP)
CALL runtime·args(SB)
CALL runtime·osinit(SB)
- CALL runtime·hashinit(SB)
CALL runtime·schedinit(SB)
// create a new goroutine to start program
MOVL $runtime·main·f(SB), AX // entry
MOVL $0, 0(SP)
MOVL AX, 4(SP)
- ARGSIZE(8)
CALL runtime·newproc(SB)
- ARGSIZE(-1)
// start this M
CALL runtime·mstart(SB)
@@ -102,8 +101,8 @@ TEXT runtime·asminit(SB),NOSPLIT,$0-0
// void gosave(Gobuf*)
// save state in Gobuf; setjmp
TEXT runtime·gosave(SB), NOSPLIT, $0-4
- MOVL b+0(FP), AX // gobuf
- LEAL b+0(FP), BX // caller's SP
+ MOVL buf+0(FP), AX // gobuf
+ LEAL buf+0(FP), BX // caller's SP
MOVL BX, gobuf_sp(AX)
MOVL 0(SP), BX // caller's PC
MOVL BX, gobuf_pc(AX)
@@ -117,7 +116,7 @@ TEXT runtime·gosave(SB), NOSPLIT, $0-4
// void gogo(Gobuf*)
// restore state from Gobuf; longjmp
TEXT runtime·gogo(SB), NOSPLIT, $0-4
- MOVL b+0(FP), BX // gobuf
+ MOVL buf+0(FP), BX // gobuf
MOVL gobuf_g(BX), DX
MOVL 0(DX), CX // make sure g != nil
get_tls(CX)
@@ -131,7 +130,7 @@ TEXT runtime·gogo(SB), NOSPLIT, $0-4
MOVL gobuf_pc(BX), BX
JMP BX
-// void mcall(void (*fn)(G*))
+// func 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.
@@ -147,7 +146,8 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
MOVL AX, (g_sched+gobuf_g)(AX)
// switch to m->g0 & its stack, call fn
- MOVL m(CX), BX
+ MOVL g(CX), BX
+ MOVL g_m(BX), BX
MOVL m_g0(BX), SI
CMPL SI, AX // if g == m->g0 call badmcall
JNE 3(PC)
@@ -156,38 +156,126 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
MOVL SI, g(CX) // g = m->g0
MOVL (g_sched+gobuf_sp)(SI), SP // sp = m->g0->sched.sp
PUSHQ AX
- ARGSIZE(8)
+ MOVL DI, DX
+ MOVL 0(DI), DI
CALL DI
POPQ AX
MOVL $runtime·badmcall2(SB), AX
JMP AX
RET
+// switchtoM is a dummy routine that onM 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 M stack because the one at the top of
+// the M stack terminates the stack walk (see topofstack()).
+TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
+ RET
+
+// func onM_signalok(fn func())
+TEXT runtime·onM_signalok(SB), NOSPLIT, $0-4
+ get_tls(CX)
+ MOVL g(CX), AX // AX = g
+ MOVL g_m(AX), BX // BX = m
+ MOVL m_gsignal(BX), DX // DX = gsignal
+ CMPL AX, DX
+ JEQ ongsignal
+ JMP runtime·onM(SB)
+
+ongsignal:
+ MOVL fn+0(FP), DI // DI = fn
+ MOVL DI, DX
+ MOVL 0(DI), DI
+ CALL DI
+ RET
+
+// func onM(fn func())
+TEXT runtime·onM(SB), NOSPLIT, $0-4
+ MOVL fn+0(FP), DI // DI = fn
+ get_tls(CX)
+ MOVL g(CX), AX // AX = g
+ MOVL g_m(AX), BX // BX = m
+
+ MOVL m_g0(BX), DX // DX = g0
+ CMPL AX, DX
+ JEQ onm
+
+ MOVL m_curg(BX), R8
+ CMPL AX, R8
+ JEQ oncurg
+
+ // Not g0, not curg. Must be gsignal, but that's not allowed.
+ // Hide call from linker nosplit analysis.
+ MOVL $runtime·badonm(SB), AX
+ CALL AX
+
+oncurg:
+ // save our state in g->sched. Pretend to
+ // be switchtoM if the G stack is scanned.
+ MOVL $runtime·switchtoM(SB), SI
+ MOVL SI, (g_sched+gobuf_pc)(AX)
+ MOVL SP, (g_sched+gobuf_sp)(AX)
+ MOVL AX, (g_sched+gobuf_g)(AX)
+
+ // switch to g0
+ MOVL DX, g(CX)
+ MOVL (g_sched+gobuf_sp)(DX), SP
+
+ // call target function
+ MOVL DI, DX
+ MOVL 0(DI), DI
+ CALL DI
+
+ // switch back to g
+ get_tls(CX)
+ MOVL g(CX), AX
+ MOVL g_m(AX), BX
+ MOVL m_curg(BX), AX
+ MOVL AX, g(CX)
+ MOVL (g_sched+gobuf_sp)(AX), SP
+ MOVL $0, (g_sched+gobuf_sp)(AX)
+ RET
+
+onm:
+ // already on m stack, just call directly
+ MOVL DI, DX
+ MOVL 0(DI), DI
+ CALL DI
+ RET
+
/*
* support for morestack
*/
// Called during function prolog when more stack is needed.
-// Caller has already done get_tls(CX); MOVQ m(CX), BX.
//
// 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,$0-0
+ get_tls(CX)
+ MOVL g(CX), BX
+ MOVL g_m(BX), BX
+
// Cannot grow scheduler stack (m->g0).
MOVL m_g0(BX), SI
CMPL g(CX), SI
JNE 2(PC)
MOVL 0, AX
+ // Cannot grow signal stack (m->gsignal).
+ MOVL m_gsignal(BX), SI
+ CMPL g(CX), SI
+ JNE 2(PC)
+ MOVL 0, AX
+
// Called from f.
// Set m->morebuf to f's caller.
MOVL 8(SP), AX // f's caller's PC
MOVL AX, (m_morebuf+gobuf_pc)(BX)
LEAL 16(SP), AX // f's caller's SP
MOVL AX, (m_morebuf+gobuf_sp)(BX)
- MOVL AX, m_moreargp(BX)
get_tls(CX)
MOVL g(CX), SI
MOVL SI, (m_morebuf+gobuf_g)(BX)
@@ -208,56 +296,13 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0
MOVL $0, 0x1003 // crash if newstack returns
RET
-// Called from panic. Mimics morestack,
-// reuses stack growth code to create a frame
-// with the desired args running the desired function.
-//
-// func call(fn *byte, arg *byte, argsize uint32).
-TEXT runtime·newstackcall(SB), NOSPLIT, $0-20
- get_tls(CX)
- MOVL m(CX), BX
-
- // Save our caller's state as the PC and SP to
- // restore when returning from f.
- MOVL 0(SP), AX // our caller's PC
- MOVL AX, (m_morebuf+gobuf_pc)(BX)
- LEAL 8(SP), AX // our caller's SP
- MOVL AX, (m_morebuf+gobuf_sp)(BX)
- MOVL g(CX), AX
- MOVL AX, (m_morebuf+gobuf_g)(BX)
-
- // Save our own state as the PC and SP to restore
- // if this goroutine needs to be restarted.
- MOVL $runtime·newstackcall(SB), DI
- MOVL DI, (g_sched+gobuf_pc)(AX)
- MOVL SP, (g_sched+gobuf_sp)(AX)
-
- // Set up morestack arguments to call f on a new stack.
- // We set f's frame size to 1, as a hint to newstack
- // that this is a call from runtime·newstackcall.
- // If it turns out that f needs a larger frame than
- // the default stack, f's usual stack growth prolog will
- // allocate a new segment (and recopy the arguments).
- MOVL 8(SP), AX // fn
- MOVL 12(SP), DX // arg frame
- MOVL 16(SP), CX // arg size
-
- MOVQ AX, m_cret(BX) // f's PC
- MOVL DX, m_moreargp(BX) // argument frame pointer
- MOVL CX, m_moreargsize(BX) // f's argument size
- MOVL $1, m_moreframesize(BX) // f's frame size
-
- // Call newstack on m->g0's stack.
- MOVL m_g0(BX), BX
- get_tls(CX)
- MOVL BX, g(CX)
- MOVL (g_sched+gobuf_sp)(BX), SP
- CALL runtime·newstack(SB)
- MOVL $0, 0x1103 // crash if newstack returns
- RET
+// morestack trampolines
+TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack(SB)
-// reflect·call: call a function with the given argument list
-// func call(f *FuncVal, arg *byte, argsize uint32).
+// reflectcall: call a function with the given argument list
+// func call(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!
@@ -265,44 +310,45 @@ TEXT runtime·newstackcall(SB), NOSPLIT, $0-20
#define DISPATCH(NAME,MAXSIZE) \
CMPL CX, $MAXSIZE; \
JA 3(PC); \
- MOVL $runtime·NAME(SB), AX; \
+ MOVL $NAME(SB), AX; \
JMP AX
-// Note: can't just "JMP runtime·NAME(SB)" - bad inlining results.
+// Note: can't just "JMP NAME(SB)" - bad inlining results.
-TEXT reflect·call(SB), NOSPLIT, $0-20
+TEXT ·reflectcall(SB), NOSPLIT, $0-16
MOVLQZX argsize+8(FP), CX
- DISPATCH(call16, 16)
- DISPATCH(call32, 32)
- DISPATCH(call64, 64)
- DISPATCH(call128, 128)
- DISPATCH(call256, 256)
- DISPATCH(call512, 512)
- DISPATCH(call1024, 1024)
- DISPATCH(call2048, 2048)
- DISPATCH(call4096, 4096)
- DISPATCH(call8192, 8192)
- DISPATCH(call16384, 16384)
- DISPATCH(call32768, 32768)
- DISPATCH(call65536, 65536)
- DISPATCH(call131072, 131072)
- DISPATCH(call262144, 262144)
- DISPATCH(call524288, 524288)
- DISPATCH(call1048576, 1048576)
- DISPATCH(call2097152, 2097152)
- DISPATCH(call4194304, 4194304)
- DISPATCH(call8388608, 8388608)
- DISPATCH(call16777216, 16777216)
- DISPATCH(call33554432, 33554432)
- DISPATCH(call67108864, 67108864)
- DISPATCH(call134217728, 134217728)
- DISPATCH(call268435456, 268435456)
- DISPATCH(call536870912, 536870912)
- DISPATCH(call1073741824, 1073741824)
+ DISPATCH(runtime·call16, 16)
+ 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)
MOVL $runtime·badreflectcall(SB), AX
JMP AX
#define CALLFN(NAME,MAXSIZE) \
-TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-16; \
+TEXT NAME(SB), WRAPPER, $MAXSIZE-16; \
+ NO_LOCAL_POINTERS; \
/* copy arguments to stack */ \
MOVL argptr+4(FP), SI; \
MOVL argsize+8(FP), CX; \
@@ -310,8 +356,8 @@ TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-16; \
REP;MOVSB; \
/* call function */ \
MOVL f+0(FP), DX; \
- MOVL (DX), AX; \
- CALL AX; \
+ MOVL (DX), AX; \
+ CALL AX; \
/* copy return values back */ \
MOVL argptr+4(FP), DI; \
MOVL argsize+8(FP), CX; \
@@ -323,163 +369,33 @@ TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-16; \
REP;MOVSB; \
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)
-
-// Return point when leaving stack.
-//
-// Lessstack can appear in stack traces for the same reason
-// as morestack; in that context, it has 0 arguments.
-TEXT runtime·lessstack(SB), NOSPLIT, $0-0
- // Save return value in m->cret
- get_tls(CX)
- MOVL m(CX), BX
- MOVQ AX, m_cret(BX) // MOVQ, to save all 64 bits
-
- // Call oldstack on m->g0's stack.
- MOVL m_g0(BX), BX
- MOVL BX, g(CX)
- MOVL (g_sched+gobuf_sp)(BX), SP
- CALL runtime·oldstack(SB)
- MOVL $0, 0x1004 // crash if oldstack returns
- RET
-
-// morestack trampolines
-TEXT runtime·morestack00(SB),NOSPLIT,$0
- get_tls(CX)
- MOVL m(CX), BX
- MOVQ $0, AX
- MOVQ AX, m_moreframesize(BX)
- MOVL $runtime·morestack(SB), AX
- JMP AX
-
-TEXT runtime·morestack01(SB),NOSPLIT,$0
- get_tls(CX)
- MOVL m(CX), BX
- SHLQ $32, AX
- MOVQ AX, m_moreframesize(BX)
- MOVL $runtime·morestack(SB), AX
- JMP AX
-
-TEXT runtime·morestack10(SB),NOSPLIT,$0
- get_tls(CX)
- MOVL m(CX), BX
- MOVLQZX AX, AX
- MOVQ AX, m_moreframesize(BX)
- MOVL $runtime·morestack(SB), AX
- JMP AX
-
-TEXT runtime·morestack11(SB),NOSPLIT,$0
- get_tls(CX)
- MOVL m(CX), BX
- MOVQ AX, m_moreframesize(BX)
- MOVL $runtime·morestack(SB), AX
- JMP AX
-
-// subcases of morestack01
-// with const of 8,16,...48
-TEXT runtime·morestack8(SB),NOSPLIT,$0
- MOVQ $1, R8
- MOVL $morestack<>(SB), AX
- JMP AX
-
-TEXT runtime·morestack16(SB),NOSPLIT,$0
- MOVQ $2, R8
- MOVL $morestack<>(SB), AX
- JMP AX
-
-TEXT runtime·morestack24(SB),NOSPLIT,$0
- MOVQ $3, R8
- MOVL $morestack<>(SB), AX
- JMP AX
-
-TEXT runtime·morestack32(SB),NOSPLIT,$0
- MOVQ $4, R8
- MOVL $morestack<>(SB), AX
- JMP AX
-
-TEXT runtime·morestack40(SB),NOSPLIT,$0
- MOVQ $5, R8
- MOVL $morestack<>(SB), AX
- JMP AX
-
-TEXT runtime·morestack48(SB),NOSPLIT,$0
- MOVQ $6, R8
- MOVL $morestack<>(SB), AX
- JMP AX
-
-TEXT morestack<>(SB),NOSPLIT,$0
- get_tls(CX)
- MOVL m(CX), BX
- SHLQ $35, R8
- MOVQ R8, m_moreframesize(BX)
- MOVL $runtime·morestack(SB), AX
- JMP AX
-
-TEXT runtime·morestack00_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack00(SB)
-
-TEXT runtime·morestack01_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack01(SB)
-
-TEXT runtime·morestack10_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack10(SB)
-
-TEXT runtime·morestack11_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack11(SB)
-
-TEXT runtime·morestack8_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack8(SB)
-
-TEXT runtime·morestack16_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack16(SB)
-
-TEXT runtime·morestack24_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack24(SB)
-
-TEXT runtime·morestack32_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack32(SB)
-
-TEXT runtime·morestack40_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack40(SB)
-
-TEXT runtime·morestack48_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack48(SB)
+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)
// bool cas(int32 *val, int32 old, int32 new)
// Atomically:
@@ -488,18 +404,32 @@ TEXT runtime·morestack48_noctxt(SB),NOSPLIT,$0
// return 1;
// } else
// return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-12
- MOVL val+0(FP), BX
+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)
- JZ 3(PC)
+ JZ 4(PC)
MOVL $0, AX
+ MOVB AX, ret+16(FP)
RET
MOVL $1, AX
+ MOVB AX, 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){
@@ -508,17 +438,19 @@ TEXT runtime·cas(SB), NOSPLIT, $0-12
// } else {
// return 0;
// }
-TEXT runtime·cas64(SB), NOSPLIT, $0-24
- MOVL val+0(FP), BX
+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)
JNZ cas64_fail
MOVL $1, AX
+ MOVB AX, ret+24(FP)
RET
cas64_fail:
MOVL $0, AX
+ MOVB AX, ret+24(FP)
RET
// bool casp(void **val, void *old, void *new)
@@ -528,54 +460,70 @@ cas64_fail:
// return 1;
// } else
// return 0;
-TEXT runtime·casp(SB), NOSPLIT, $0-12
- MOVL val+0(FP), BX
+TEXT runtime·casp(SB), NOSPLIT, $0-17
+ MOVL ptr+0(FP), BX
MOVL old+4(FP), AX
MOVL new+8(FP), CX
LOCK
CMPXCHGL CX, 0(BX)
- JZ 3(PC)
+ JZ 4(PC)
MOVL $0, AX
+ MOVB AX, ret+16(FP)
RET
MOVL $1, AX
+ MOVB AX, ret+16(FP)
RET
// uint32 xadd(uint32 volatile *val, int32 delta)
// Atomically:
// *val += delta;
// return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-8
- MOVL val+0(FP), BX
+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-16
- MOVL val+0(FP), BX
+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·xchg(SB), NOSPLIT, $0-8
- MOVL val+0(FP), BX
+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-16
- MOVL val+0(FP), BX
+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·xchgp(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 val+0(FP), AX
+ MOVL cycles+0(FP), AX
again:
PAUSE
SUBL $1, AX
@@ -600,14 +548,22 @@ TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
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 jmpdefer(fn, sp);
// called from deferreturn.
// 1. pop the caller
// 2. sub 5 bytes from the callers return
// 3. jmp to the argument
-TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16
- MOVL fn+0(FP), DX
- MOVL callersp+4(FP), BX
+TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8
+ MOVL fv+0(FP), DX
+ MOVL argp+4(FP), BX
LEAL -8(BX), SP // caller sp after CALL
SUBL $5, (SP) // return to CALL again
MOVL 0(DX), BX
@@ -619,33 +575,39 @@ TEXT runtime·asmcgocall(SB),NOSPLIT,$0-8
MOVL 0, AX
RET
+// asmcgocall(void(*fn)(void*), void *arg)
+// Not implemented.
+TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12
+ MOVL 0, AX
+ RET
+
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
// Not implemented.
TEXT runtime·cgocallback(SB),NOSPLIT,$0-12
MOVL 0, AX
RET
-// void setmg(M*, G*); set m and g. for use by needm.
+// void setg(G*); set g. for use by needm.
// Not implemented.
-TEXT runtime·setmg(SB), NOSPLIT, $0-8
+TEXT runtime·setg(SB), NOSPLIT, $0-4
MOVL 0, AX
RET
-// check that SP is in range [g->stackbase, g->stackguard)
+// check that SP is in range [g->stack.lo, g->stack.hi)
TEXT runtime·stackcheck(SB), NOSPLIT, $0-0
get_tls(CX)
MOVL g(CX), AX
- CMPL g_stackbase(AX), SP
+ CMPL (g_stack+stack_hi)(AX), SP
JHI 2(PC)
MOVL 0, AX
- CMPL SP, g_stackguard(AX)
+ CMPL SP, (g_stack+stack_lo)(AX)
JHI 2(PC)
MOVL 0, AX
RET
TEXT runtime·memclr(SB),NOSPLIT,$0-8
- MOVL addr+0(FP), DI
- MOVL count+4(FP), CX
+ MOVL ptr+0(FP), DI
+ MOVL n+4(FP), CX
MOVQ CX, BX
ANDQ $7, BX
SHRQ $3, CX
@@ -658,19 +620,33 @@ TEXT runtime·memclr(SB),NOSPLIT,$0-8
STOSB
RET
-TEXT runtime·getcallerpc(SB),NOSPLIT,$0-8
- MOVL x+0(FP),AX // addr of first arg
+TEXT runtime·getcallerpc(SB),NOSPLIT,$0-12
+ MOVL argp+0(FP),AX // addr of first arg
+ MOVL -8(AX),AX // get calling pc
+ MOVL AX, ret+8(FP)
+ RET
+
+TEXT runtime·gogetcallerpc(SB),NOSPLIT,$0-12
+ MOVL p+0(FP),AX // addr of first arg
MOVL -8(AX),AX // get calling pc
+ MOVL AX, ret+8(FP)
RET
-TEXT runtime·setcallerpc(SB),NOSPLIT,$0-16
- MOVL x+0(FP),AX // addr of first arg
+TEXT runtime·setcallerpc(SB),NOSPLIT,$0-8
+ MOVL argp+0(FP),AX // addr of first arg
MOVL pc+4(FP), BX // pc to set
MOVQ BX, -8(AX) // set calling pc
RET
-TEXT runtime·getcallersp(SB),NOSPLIT,$0-8
- MOVL sp+0(FP), AX
+TEXT runtime·getcallersp(SB),NOSPLIT,$0-12
+ MOVL argp+0(FP), AX
+ MOVL AX, ret+8(FP)
+ RET
+
+// func gogetcallersp(p unsafe.Pointer) uintptr
+TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-12
+ MOVL p+0(FP),AX // addr of first arg
+ MOVL AX, ret+8(FP)
RET
// int64 runtime·cputicks(void)
@@ -678,42 +654,60 @@ TEXT runtime·cputicks(SB),NOSPLIT,$0-0
RDTSC
SHLQ $32, DX
ADDQ DX, AX
+ MOVQ AX, ret+0(FP)
RET
-TEXT runtime·stackguard(SB),NOSPLIT,$0-16
- MOVL SP, DX
- MOVL DX, sp+0(FP)
- get_tls(CX)
- MOVL g(CX), BX
- MOVL g_stackguard(BX), DX
- MOVL DX, limit+4(FP)
- RET
-
-GLOBL runtime·tls0(SB), $64
-
// hash function using AES hardware instructions
// For now, our one amd64p32 system (NaCl) does not
// support using AES instructions, so have not bothered to
// write the implementations. Can copy and adjust the ones
// in asm_amd64.s when the time comes.
-TEXT runtime·aeshash(SB),NOSPLIT,$0-24
+TEXT runtime·aeshash(SB),NOSPLIT,$0-20
+ MOVL AX, ret+16(FP)
RET
-TEXT runtime·aeshashstr(SB),NOSPLIT,$0-24
+TEXT runtime·aeshashstr(SB),NOSPLIT,$0-20
+ MOVL AX, ret+16(FP)
RET
-TEXT runtime·aeshash32(SB),NOSPLIT,$0-24
+TEXT runtime·aeshash32(SB),NOSPLIT,$0-20
+ MOVL AX, ret+16(FP)
RET
-TEXT runtime·aeshash64(SB),NOSPLIT,$0-24
+TEXT runtime·aeshash64(SB),NOSPLIT,$0-20
+ MOVL AX, ret+16(FP)
RET
-TEXT runtime·memeq(SB),NOSPLIT,$0-12
+TEXT runtime·memeq(SB),NOSPLIT,$0-17
MOVL a+0(FP), SI
MOVL b+4(FP), DI
- MOVL count+8(FP), BX
- JMP runtime·memeqbody(SB)
+ MOVL size+8(FP), BX
+ CALL runtime·memeqbody(SB)
+ MOVB AX, ret+16(FP)
+ RET
+
+// eqstring tests whether two strings are equal.
+// See runtime_test.go:eqstring_generic for
+// equivalent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$0-17
+ MOVL s1len+4(FP), AX
+ MOVL s2len+12(FP), BX
+ CMPL AX, BX
+ JNE different
+ MOVL s1str+0(FP), SI
+ MOVL s2str+8(FP), DI
+ CMPL SI, DI
+ JEQ same
+ CALL runtime·memeqbody(SB)
+ MOVB AX, v+16(FP)
+ RET
+same:
+ MOVB $1, v+16(FP)
+ RET
+different:
+ MOVB $0, v+16(FP)
+ RET
// a in SI
// b in DI
@@ -814,15 +808,15 @@ equal:
RET
TEXT runtime·cmpstring(SB),NOSPLIT,$0-20
- MOVL s1+0(FP), SI
- MOVL s1+4(FP), BX
- MOVL s2+8(FP), DI
- MOVL s2+12(FP), DX
+ MOVL s1_base+0(FP), SI
+ MOVL s1_len+4(FP), BX
+ MOVL s2_base+8(FP), DI
+ MOVL s2_len+12(FP), DX
CALL runtime·cmpbody(SB)
- MOVL AX, res+16(FP)
+ MOVL AX, ret+16(FP)
RET
-TEXT bytes·Compare(SB),NOSPLIT,$0-28
+TEXT runtime·cmpbytes(SB),NOSPLIT,$0-28
MOVL s1+0(FP), SI
MOVL s1+4(FP), BX
MOVL s2+12(FP), DI
@@ -1069,5 +1063,25 @@ eqret:
MOVB AX, ret+24(FP)
RET
-TEXT runtime·timenow(SB), NOSPLIT, $0-0
- JMP time·now(SB)
+TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
+ get_tls(CX)
+ MOVL g(CX), AX
+ MOVL g_m(AX), AX
+ MOVL m_fastrand(AX), DX
+ ADDL DX, DX
+ MOVL DX, BX
+ XORL $0x88888eef, DX
+ CMOVLMI BX, DX
+ MOVL DX, m_fastrand(AX)
+ MOVL DX, ret+0(FP)
+ RET
+
+TEXT runtime·return0(SB), NOSPLIT, $0
+ MOVL $0, AX
+ RET
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$0-0
+ BYTE $0x90 // NOP
+ CALL runtime·goexit1(SB) // does not return
diff --git a/src/pkg/runtime/asm_arm.s b/src/runtime/asm_arm.s
index 1aea9036a..0f3b5eeb8 100644
--- a/src/pkg/runtime/asm_arm.s
+++ b/src/runtime/asm_arm.s
@@ -4,10 +4,10 @@
#include "zasm_GOOS_GOARCH.h"
#include "funcdata.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// using frame size $-4 means do not save LR on stack.
-TEXT _rt0_go(SB),NOSPLIT,$-4
+TEXT runtime·rt0_go(SB),NOSPLIT,$-4
MOVW $0xcafebabe, R12
// copy arguments forward on an even stack
@@ -19,34 +19,44 @@ TEXT _rt0_go(SB),NOSPLIT,$-4
MOVW R0, 60(R13) // save argc, argv away
MOVW R1, 64(R13)
- // set up m and g registers
- // g is R10, m is R9
+ // set up g register
+ // g is R10
MOVW $runtime·g0(SB), g
- MOVW $runtime·m0(SB), m
+ MOVW $runtime·m0(SB), R8
// save m->g0 = g0
- MOVW g, m_g0(m)
+ MOVW g, m_g0(R8)
+ // save g->m = m0
+ MOVW R8, g_m(g)
// create istack out of the OS stack
MOVW $(-8192+104)(R13), R0
- MOVW R0, g_stackguard(g) // (w 104b guard)
MOVW R0, g_stackguard0(g)
- MOVW R13, g_stackbase(g)
+ MOVW R0, g_stackguard1(g)
+ MOVW R0, (g_stack+stack_lo)(g)
+ MOVW R13, (g_stack+stack_hi)(g)
+
BL runtime·emptyfunc(SB) // fault if stack check is wrong
+#ifndef GOOS_nacl
// if there is an _cgo_init, call it.
MOVW _cgo_init(SB), R4
CMP $0, R4
B.EQ nocgo
- BL runtime·save_gm(SB);
- MOVW g, R0 // first argument of _cgo_init is g
- MOVW $setmg_gcc<>(SB), R1 // second argument is address of save_gm
- BL (R4) // will clobber R0-R3
+ 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
+ MOVW $setg_gcc<>(SB), R1 // arg 1: setg
+ MOVW g, R0 // arg 0: G
+ BL (R4) // will clobber R0-R3
+#endif
nocgo:
// update stackguard after _cgo_init
- MOVW g_stackguard0(g), R0
- MOVW R0, g_stackguard(g)
+ MOVW (g_stack+stack_lo)(g), R0
+ ADD $const_StackGuard, R0
+ MOVW R0, g_stackguard0(g)
+ MOVW R0, g_stackguard1(g)
BL runtime·checkgoarm(SB)
BL runtime·check(SB)
@@ -58,7 +68,6 @@ nocgo:
MOVW R1, 8(R13)
BL runtime·args(SB)
BL runtime·osinit(SB)
- BL runtime·hashinit(SB)
BL runtime·schedinit(SB)
// create a new goroutine to start program
@@ -68,9 +77,7 @@ nocgo:
MOVW.W R0, -4(R13)
MOVW $0, R0
MOVW.W R0, -4(R13) // push $0 as guard
- ARGSIZE(12)
BL runtime·newproc(SB)
- ARGSIZE(-1)
MOVW $12(R13), R13 // pop args and LR
// start this M
@@ -86,7 +93,11 @@ GLOBL runtime·main·f(SB),RODATA,$4
TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
// gdb won't skip this breakpoint instruction automatically,
// so you must manually "set $pc+=4" to skip it and continue.
- WORD $0xe1200071 // BKPT 0x0001
+#ifdef GOOS_nacl
+ WORD $0xe125be7f // BKPT 0x5bef, NACL_INSTR_ARM_BREAKPOINT
+#else
+ WORD $0xe7f001f0 // undefined instruction that gdb understands is a software breakpoint
+#endif
RET
TEXT runtime·asminit(SB),NOSPLIT,$0-0
@@ -105,7 +116,7 @@ TEXT runtime·asminit(SB),NOSPLIT,$0-0
// void gosave(Gobuf*)
// save state in Gobuf; setjmp
-TEXT runtime·gosave(SB), NOSPLIT, $-4-4
+TEXT runtime·gosave(SB),NOSPLIT,$-4-4
MOVW 0(FP), R0 // gobuf
MOVW SP, gobuf_sp(R0)
MOVW LR, gobuf_pc(R0)
@@ -118,13 +129,21 @@ TEXT runtime·gosave(SB), NOSPLIT, $-4-4
// void gogo(Gobuf*)
// restore state from Gobuf; longjmp
-TEXT runtime·gogo(SB), NOSPLIT, $-4-4
+TEXT runtime·gogo(SB),NOSPLIT,$-4-4
MOVW 0(FP), R1 // gobuf
- MOVW gobuf_g(R1), g
- MOVW 0(g), R2 // make sure g != nil
- MOVB runtime·iscgo(SB), R2
- CMP $0, R2 // if in Cgo, we have to save g and m
- BL.NE runtime·save_gm(SB) // this call will clobber R0
+ MOVW gobuf_g(R1), R0
+ BL setg<>(SB)
+
+ // NOTE: We updated g above, and we are about to update SP.
+ // Until LR and PC are also updated, the g/SP/LR/PC quadruple
+ // are out of sync and must not be used as the basis of a traceback.
+ // Sigprof skips the traceback when SP is not within g's bounds,
+ // and when the PC is inside this function, runtime.gogo.
+ // Since we are about to update SP, until we complete runtime.gogo
+ // we must not leave this function. In particular, no calls
+ // after this point: it must be straight-line code until the
+ // final B instruction.
+ // See large comment in sigprof for more details.
MOVW gobuf_sp(R1), SP // restore SP
MOVW gobuf_lr(R1), LR
MOVW gobuf_ret(R1), R0
@@ -134,16 +153,15 @@ TEXT runtime·gogo(SB), NOSPLIT, $-4-4
MOVW R11, gobuf_ret(R1)
MOVW R11, gobuf_lr(R1)
MOVW R11, gobuf_ctxt(R1)
+ MOVW gobuf_pc(R1), R11
CMP R11, R11 // set condition codes for == test, needed by stack split
- MOVW gobuf_pc(R1), PC
+ B (R11)
-// void mcall(void (*fn)(G*))
+// func 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, $-4-4
- MOVW fn+0(FP), R0
-
+TEXT runtime·mcall(SB),NOSPLIT,$-4-4
// Save caller state in g->sched.
MOVW SP, (g_sched+gobuf_sp)(g)
MOVW LR, (g_sched+gobuf_pc)(g)
@@ -153,17 +171,110 @@ TEXT runtime·mcall(SB), NOSPLIT, $-4-4
// Switch to m->g0 & its stack, call fn.
MOVW g, R1
- MOVW m_g0(m), g
+ MOVW g_m(g), R8
+ MOVW m_g0(R8), R0
+ BL setg<>(SB)
CMP g, R1
B.NE 2(PC)
B runtime·badmcall(SB)
+ MOVB runtime·iscgo(SB), R11
+ CMP $0, R11
+ BL.NE runtime·save_g(SB)
+ MOVW fn+0(FP), R0
MOVW (g_sched+gobuf_sp)(g), SP
SUB $8, SP
MOVW R1, 4(SP)
+ MOVW R0, R7
+ MOVW 0(R0), R0
BL (R0)
B runtime·badmcall2(SB)
RET
+// switchtoM is a dummy routine that onM 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 M stack because the one at the top of
+// the M stack terminates the stack walk (see topofstack()).
+TEXT runtime·switchtoM(SB),NOSPLIT,$0-0
+ MOVW $0, R0
+ BL (R0) // clobber lr to ensure push {lr} is kept
+ RET
+
+// func onM_signalok(fn func())
+TEXT runtime·onM_signalok(SB), NOSPLIT, $-4-4
+ MOVW g_m(g), R1
+ MOVW m_gsignal(R1), R2
+ CMP g, R2
+ B.EQ ongsignal
+ B runtime·onM(SB)
+
+ongsignal:
+ MOVW fn+0(FP), R0
+ MOVW R0, R7
+ MOVW 0(R0), R0
+ BL (R0)
+ RET
+
+// func onM(fn func())
+TEXT runtime·onM(SB),NOSPLIT,$0-4
+ MOVW fn+0(FP), R0 // R0 = fn
+ MOVW g_m(g), R1 // R1 = m
+
+ MOVW m_g0(R1), R2 // R2 = g0
+ CMP g, R2
+ B.EQ onm
+
+ MOVW m_curg(R1), R3
+ CMP g, R3
+ B.EQ oncurg
+
+ // Not g0, not curg. Must be gsignal, but that's not allowed.
+ // Hide call from linker nosplit analysis.
+ MOVW $runtime·badonm(SB), R0
+ BL (R0)
+
+oncurg:
+ // save our state in g->sched. Pretend to
+ // be switchtoM if the G stack is scanned.
+ MOVW $runtime·switchtoM(SB), R3
+ ADD $4, R3, R3 // get past push {lr}
+ MOVW R3, (g_sched+gobuf_pc)(g)
+ MOVW SP, (g_sched+gobuf_sp)(g)
+ MOVW LR, (g_sched+gobuf_lr)(g)
+ MOVW g, (g_sched+gobuf_g)(g)
+
+ // switch to g0
+ MOVW R0, R5
+ MOVW R2, R0
+ BL setg<>(SB)
+ MOVW R5, R0
+ MOVW (g_sched+gobuf_sp)(R2), R3
+ // make it look like mstart called onM on g0, to stop traceback
+ SUB $4, R3, R3
+ MOVW $runtime·mstart(SB), R4
+ MOVW R4, 0(R3)
+ MOVW R3, SP
+
+ // call target function
+ MOVW R0, R7
+ MOVW 0(R0), R0
+ BL (R0)
+
+ // switch back to g
+ MOVW g_m(g), R1
+ MOVW m_curg(R1), R0
+ BL setg<>(SB)
+ MOVW (g_sched+gobuf_sp)(g), SP
+ MOVW $0, R3
+ MOVW R3, (g_sched+gobuf_sp)(g)
+ RET
+
+onm:
+ MOVW R0, R7
+ MOVW 0(R0), R0
+ BL (R0)
+ RET
+
/*
* support for morestack
*/
@@ -182,12 +293,15 @@ TEXT runtime·mcall(SB), NOSPLIT, $-4-4
// record an argument size. For that purpose, it has no arguments.
TEXT runtime·morestack(SB),NOSPLIT,$-4-0
// Cannot grow scheduler stack (m->g0).
- MOVW m_g0(m), R4
+ MOVW g_m(g), R8
+ MOVW m_g0(R8), R4
CMP g, R4
BL.EQ runtime·abort(SB)
- MOVW R1, m_moreframesize(m)
- MOVW R2, m_moreargsize(m)
+ // Cannot grow signal stack (m->gsignal).
+ MOVW m_gsignal(R8), R4
+ CMP g, R4
+ BL.EQ runtime·abort(SB)
// Called from f.
// Set g->sched to context in f.
@@ -198,14 +312,14 @@ TEXT runtime·morestack(SB),NOSPLIT,$-4-0
// Called from f.
// Set m->morebuf to f's caller.
- MOVW R3, (m_morebuf+gobuf_pc)(m) // f's caller's PC
- MOVW SP, (m_morebuf+gobuf_sp)(m) // f's caller's SP
+ MOVW R3, (m_morebuf+gobuf_pc)(R8) // f's caller's PC
+ MOVW SP, (m_morebuf+gobuf_sp)(R8) // f's caller's SP
MOVW $4(SP), R3 // f's argument pointer
- MOVW R3, m_moreargp(m)
- MOVW g, (m_morebuf+gobuf_g)(m)
+ MOVW g, (m_morebuf+gobuf_g)(R8)
// Call newstack on m->g0's stack.
- MOVW m_g0(m), g
+ MOVW m_g0(R8), R0
+ BL setg<>(SB)
MOVW (g_sched+gobuf_sp)(g), SP
BL runtime·newstack(SB)
@@ -217,48 +331,8 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-4-0
MOVW $0, R7
B runtime·morestack(SB)
-// Called from panic. Mimics morestack,
-// reuses stack growth code to create a frame
-// with the desired args running the desired function.
-//
-// func call(fn *byte, arg *byte, argsize uint32).
-TEXT runtime·newstackcall(SB), NOSPLIT, $-4-12
- // Save our caller's state as the PC and SP to
- // restore when returning from f.
- MOVW LR, (m_morebuf+gobuf_pc)(m) // our caller's PC
- MOVW SP, (m_morebuf+gobuf_sp)(m) // our caller's SP
- MOVW g, (m_morebuf+gobuf_g)(m)
-
- // Save our own state as the PC and SP to restore
- // if this goroutine needs to be restarted.
- MOVW $runtime·newstackcall(SB), R11
- MOVW R11, (g_sched+gobuf_pc)(g)
- MOVW LR, (g_sched+gobuf_lr)(g)
- MOVW SP, (g_sched+gobuf_sp)(g)
-
- // Set up morestack arguments to call f on a new stack.
- // We set f's frame size to 1, as a hint to newstack
- // that this is a call from runtime·newstackcall.
- // If it turns out that f needs a larger frame than
- // the default stack, f's usual stack growth prolog will
- // allocate a new segment (and recopy the arguments).
- MOVW 4(SP), R0 // fn
- MOVW 8(SP), R1 // arg frame
- MOVW 12(SP), R2 // arg size
-
- MOVW R0, m_cret(m) // f's PC
- MOVW R1, m_moreargp(m) // f's argument pointer
- MOVW R2, m_moreargsize(m) // f's argument size
- MOVW $1, R3
- MOVW R3, m_moreframesize(m) // f's frame size
-
- // Call newstack on m->g0's stack.
- MOVW m_g0(m), g
- MOVW (g_sched+gobuf_sp)(g), SP
- B runtime·newstack(SB)
-
-// reflect·call: call a function with the given argument list
-// func call(f *FuncVal, arg *byte, argsize uint32).
+// reflectcall: call a function with the given argument list
+// func call(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!
@@ -266,57 +340,44 @@ TEXT runtime·newstackcall(SB), NOSPLIT, $-4-12
#define DISPATCH(NAME,MAXSIZE) \
CMP $MAXSIZE, R0; \
B.HI 3(PC); \
- MOVW $runtime·NAME(SB), R1; \
+ MOVW $NAME(SB), R1; \
B (R1)
-TEXT reflect·call(SB), NOSPLIT, $-4-16
+TEXT ·reflectcall(SB),NOSPLIT,$-4-16
MOVW argsize+8(FP), R0
- DISPATCH(call16, 16)
- DISPATCH(call32, 32)
- DISPATCH(call64, 64)
- DISPATCH(call128, 128)
- DISPATCH(call256, 256)
- DISPATCH(call512, 512)
- DISPATCH(call1024, 1024)
- DISPATCH(call2048, 2048)
- DISPATCH(call4096, 4096)
- DISPATCH(call8192, 8192)
- DISPATCH(call16384, 16384)
- DISPATCH(call32768, 32768)
- DISPATCH(call65536, 65536)
- DISPATCH(call131072, 131072)
- DISPATCH(call262144, 262144)
- DISPATCH(call524288, 524288)
- DISPATCH(call1048576, 1048576)
- DISPATCH(call2097152, 2097152)
- DISPATCH(call4194304, 4194304)
- DISPATCH(call8388608, 8388608)
- DISPATCH(call16777216, 16777216)
- DISPATCH(call33554432, 33554432)
- DISPATCH(call67108864, 67108864)
- DISPATCH(call134217728, 134217728)
- DISPATCH(call268435456, 268435456)
- DISPATCH(call536870912, 536870912)
- DISPATCH(call1073741824, 1073741824)
+ DISPATCH(runtime·call16, 16)
+ 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)
MOVW $runtime·badreflectcall(SB), R1
B (R1)
-// Argument map for the callXX frames. Each has one
-// stack map (for the single call) with 3 arguments.
-DATA gcargs_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
-DATA gcargs_reflectcall<>+0x04(SB)/4, $6 // 3 args
-DATA gcargs_reflectcall<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsScalar<<4))
-GLOBL gcargs_reflectcall<>(SB),RODATA,$12
-
-// callXX frames have no locals
-DATA gclocals_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
-DATA gclocals_reflectcall<>+0x04(SB)/4, $0 // 0 locals
-GLOBL gclocals_reflectcall<>(SB),RODATA,$8
-
#define CALLFN(NAME,MAXSIZE) \
-TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-16; \
- FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_reflectcall<>(SB); \
- FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_reflectcall<>(SB);\
+TEXT NAME(SB), WRAPPER, $MAXSIZE-16; \
+ NO_LOCAL_POINTERS; \
/* copy arguments to stack */ \
MOVW argptr+4(FP), R0; \
MOVW argsize+8(FP), R2; \
@@ -347,47 +408,33 @@ TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-16; \
SUB $1, R2, R2; \
B -5(PC) \
-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)
-
-// Return point when leaving stack.
-// using frame size $-4 means do not save LR on stack.
-//
-// Lessstack can appear in stack traces for the same reason
-// as morestack; in that context, it has 0 arguments.
-TEXT runtime·lessstack(SB), NOSPLIT, $-4-0
- // Save return value in m->cret
- MOVW R0, m_cret(m)
-
- // Call oldstack on m->g0's stack.
- MOVW m_g0(m), g
- MOVW (g_sched+gobuf_sp)(g), SP
- BL runtime·oldstack(SB)
+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)
// void jmpdefer(fn, sp);
// called from deferreturn.
@@ -398,10 +445,10 @@ TEXT runtime·lessstack(SB), NOSPLIT, $-4-0
// to load all registers simultaneously, so that a profiling
// interrupt can never see mismatched SP/LR/PC.
// (And double-check that pop is atomic in that way.)
-TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8
+TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8
MOVW 0(SP), LR
MOVW $-4(LR), LR // BL deferreturn
- MOVW fn+0(FP), R7
+ MOVW fv+0(FP), R7
MOVW argp+4(FP), SP
MOVW $-4(SP), SP // SP is 4 below argp, due to saved LR
MOVW 0(R7), R1
@@ -421,33 +468,57 @@ TEXT gosave<>(SB),NOSPLIT,$0
// Call fn(arg) on the scheduler stack,
// aligned appropriately for the gcc ABI.
// See cgocall.c for more details.
-TEXT runtime·asmcgocall(SB),NOSPLIT,$0-8
+TEXT ·asmcgocall(SB),NOSPLIT,$0-8
+ MOVW fn+0(FP), R1
+ MOVW arg+4(FP), R0
+ BL asmcgocall<>(SB)
+ RET
+
+TEXT ·asmcgocall_errno(SB),NOSPLIT,$0-12
MOVW fn+0(FP), R1
MOVW arg+4(FP), R0
+ BL asmcgocall<>(SB)
+ MOVW R0, ret+8(FP)
+ RET
+
+TEXT asmcgocall<>(SB),NOSPLIT,$0-0
+ // fn in R1, arg in R0.
MOVW R13, R2
- MOVW g, R5
+ MOVW g, R4
// Figure out if we need to switch to m->g0 stack.
// We get called to create new OS threads too, and those
// come in on the m->g0 stack already.
- MOVW m_g0(m), R3
+ MOVW g_m(g), R8
+ MOVW m_g0(R8), R3
CMP R3, g
- BEQ 4(PC)
+ BEQ asmcgocall_g0
BL gosave<>(SB)
- MOVW R3, g
+ MOVW R0, R5
+ MOVW R3, R0
+ BL setg<>(SB)
+ MOVW R5, R0
MOVW (g_sched+gobuf_sp)(g), R13
// Now on a scheduling stack (a pthread-created stack).
+asmcgocall_g0:
SUB $24, R13
BIC $0x7, R13 // alignment for gcc ABI
- MOVW R5, 20(R13) // save old g
- MOVW R2, 16(R13) // save old SP
- // R0 already contains the first argument
+ MOVW R4, 20(R13) // save old g
+ MOVW (g_stack+stack_hi)(R4), R4
+ SUB R2, R4
+ MOVW R4, 16(R13) // save depth in stack (can't just save SP, as stack might be copied during a callback)
BL (R1)
// Restore registers, g, stack pointer.
- MOVW 20(R13), g
- MOVW 16(R13), R13
+ MOVW R0, R5
+ MOVW 20(R13), R0
+ BL setg<>(SB)
+ MOVW (g_stack+stack_hi)(g), R1
+ MOVW 16(R13), R2
+ SUB R2, R1
+ MOVW R5, R0
+ MOVW R1, R13
RET
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
@@ -466,30 +537,49 @@ TEXT runtime·cgocallback(SB),NOSPLIT,$12-12
// cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize)
// See cgocall.c for more details.
-TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$8-12
+TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-12
+ NO_LOCAL_POINTERS
+
// Load m and g from thread-local storage.
MOVB runtime·iscgo(SB), R0
CMP $0, R0
- BL.NE runtime·load_gm(SB)
+ BL.NE runtime·load_g(SB)
- // If m is nil, Go did not create the current thread.
+ // 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.
- MOVW m, savedm-4(SP)
- CMP $0, m
+ CMP $0, g
B.NE havem
+ MOVW g, savedm-4(SP) // g is zero, so is m.
MOVW $runtime·needm(SB), R0
BL (R0)
+ // 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 onM 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.
+ MOVW g_m(g), R8
+ MOVW m_g0(R8), R3
+ 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
// switch back to m->curg stack.
// NOTE: unwindm knows that the saved g->sched.sp is at 4(R13) aka savedsp-8(SP).
- MOVW m_g0(m), R3
+ MOVW m_g0(R8), R3
MOVW (g_sched+gobuf_sp)(R3), R4
MOVW R4, savedsp-8(SP)
MOVW R13, (g_sched+gobuf_sp)(R3)
@@ -509,10 +599,8 @@ havem:
// the earlier calls.
//
// In the new goroutine, -8(SP) and -4(SP) are unused.
- MOVW fn+4(FP), R0
- MOVW frame+8(FP), R1
- MOVW framesize+12(FP), R2
- MOVW m_curg(m), g
+ MOVW m_curg(R8), R0
+ BL setg<>(SB)
MOVW (g_sched+gobuf_sp)(g), R4 // prepare stack as R4
MOVW (g_sched+gobuf_pc)(g), R5
MOVW R5, -12(R4)
@@ -528,7 +616,9 @@ havem:
// 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.)
- MOVW m_g0(m), g
+ MOVW g_m(g), R8
+ MOVW m_g0(R8), R0
+ BL setg<>(SB)
MOVW (g_sched+gobuf_sp)(g), R13
MOVW savedsp-8(SP), R4
MOVW R4, (g_sched+gobuf_sp)(g)
@@ -544,30 +634,48 @@ havem:
// Done!
RET
-// void setmg(M*, G*); set m and g. for use by needm.
-TEXT runtime·setmg(SB), NOSPLIT, $0-8
- MOVW mm+0(FP), m
- MOVW gg+4(FP), g
+// void setg(G*); set g. for use by needm.
+TEXT runtime·setg(SB),NOSPLIT,$-4-4
+ MOVW gg+0(FP), R0
+ B setg<>(SB)
+
+TEXT setg<>(SB),NOSPLIT,$-4-0
+ MOVW R0, g
- // Save m and g to thread-local storage.
+ // Save g to thread-local storage.
MOVB runtime·iscgo(SB), R0
CMP $0, R0
- BL.NE runtime·save_gm(SB)
+ B.EQ 2(PC)
+ B runtime·save_g(SB)
+ MOVW g, R0
RET
TEXT runtime·getcallerpc(SB),NOSPLIT,$-4-4
MOVW 0(SP), R0
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·gogetcallerpc(SB),NOSPLIT,$-4-8
+ MOVW R14, ret+4(FP)
RET
TEXT runtime·setcallerpc(SB),NOSPLIT,$-4-8
- MOVW x+4(FP), R0
+ MOVW pc+4(FP), R0
MOVW R0, 0(SP)
RET
TEXT runtime·getcallersp(SB),NOSPLIT,$-4-4
MOVW 0(FP), R0
MOVW $-4(R0), R0
+ MOVW R0, ret+4(FP)
+ RET
+
+// func gogetcallersp(p unsafe.Pointer) uintptr
+TEXT runtime·gogetcallersp(SB),NOSPLIT,$-4-8
+ MOVW 0(FP), R0
+ MOVW $-4(R0), R0
+ MOVW R0, ret+4(FP)
RET
TEXT runtime·emptyfunc(SB),0,$0-0
@@ -591,7 +699,7 @@ TEXT runtime·abort(SB),NOSPLIT,$-4-0
// TEXT runtime·cas(SB),NOSPLIT,$0
// B runtime·armcas(SB)
//
-TEXT runtime·armcas(SB),NOSPLIT,$0-12
+TEXT runtime·armcas(SB),NOSPLIT,$0-13
MOVW valptr+0(FP), R1
MOVW old+4(FP), R2
MOVW new+8(FP), R3
@@ -603,17 +711,24 @@ casl:
CMP $0, R0
BNE casl
MOVW $1, R0
+ MOVB R0, ret+12(FP)
RET
casfail:
MOVW $0, R0
+ MOVB R0, ret+12(FP)
RET
-TEXT runtime·stackguard(SB),NOSPLIT,$0-8
- MOVW R13, R1
- MOVW g_stackguard(g), R2
- MOVW R1, sp+0(FP)
- MOVW R2, limit+4(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)
// AES hashing not implemented for ARM
TEXT runtime·aeshash(SB),NOSPLIT,$-4-0
@@ -629,65 +744,56 @@ TEXT runtime·aeshashstr(SB),NOSPLIT,$-4-0
MOVW $0, R0
MOVW (R0), R1
-TEXT runtime·memeq(SB),NOSPLIT,$-4-12
+TEXT runtime·memeq(SB),NOSPLIT,$-4-13
MOVW a+0(FP), R1
MOVW b+4(FP), R2
- MOVW n+8(FP), R3
+ MOVW size+8(FP), R3
ADD R1, R3, R6
MOVW $1, R0
-_next:
+ MOVB R0, ret+12(FP)
+_next2:
CMP R1, R6
RET.EQ
MOVBU.P 1(R1), R4
MOVBU.P 1(R2), R5
CMP R4, R5
- BEQ _next
+ BEQ _next2
MOVW $0, R0
+ MOVB R0, ret+12(FP)
RET
-// We have to resort to TLS variable to save g(R10) and
-// m(R9). One reason is that external code might trigger
-// SIGSEGV, and our runtime.sigtramp don't even know we
-// are in external code, and will continue to use R10/R9,
-// this might as well result in another SIGSEGV.
-// Note: all three functions will clobber R0, and the last
-// two can be called from 5c ABI code.
-
-// save_gm saves the g and m registers into pthread-provided
-// thread-local memory, so that we can call externally compiled
-// ARM code that will overwrite those registers.
-// NOTE: runtime.gogo assumes that R1 is preserved by this function.
-TEXT runtime·save_gm(SB),NOSPLIT,$0
- MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
- // $runtime.tlsgm(SB) is a special linker symbol.
- // It is the offset from the TLS base pointer to our
- // thread-local storage for g and m.
- MOVW $runtime·tlsgm(SB), R11
- ADD R11, R0
- MOVW g, 0(R0)
- MOVW m, 4(R0)
- RET
-
-// load_gm loads the g and m registers from pthread-provided
-// thread-local memory, for use after calling externally compiled
-// ARM code that overwrote those registers.
-TEXT runtime·load_gm(SB),NOSPLIT,$0
- MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
- // $runtime.tlsgm(SB) is a special linker symbol.
- // It is the offset from the TLS base pointer to our
- // thread-local storage for g and m.
- MOVW $runtime·tlsgm(SB), R11
- ADD R11, R0
- MOVW 0(R0), g
- MOVW 4(R0), m
+// eqstring tests whether two strings are equal.
+// See runtime_test.go:eqstring_generic for
+// equivalent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$-4-17
+ MOVW s1len+4(FP), R0
+ MOVW s2len+12(FP), R1
+ MOVW $0, R7
+ CMP R0, R1
+ MOVB.NE R7, v+16(FP)
+ RET.NE
+ MOVW s1str+0(FP), R2
+ MOVW s2str+8(FP), R3
+ MOVW $1, R8
+ MOVB R8, v+16(FP)
+ CMP R2, R3
+ RET.EQ
+ ADD R2, R0, R6
+_eqnext:
+ CMP R2, R6
+ RET.EQ
+ MOVBU.P 1(R2), R4
+ MOVBU.P 1(R3), R5
+ CMP R4, R5
+ BEQ _eqnext
+ MOVB R7, v+16(FP)
RET
-// void setmg_gcc(M*, G*); set m and g called from gcc.
-TEXT setmg_gcc<>(SB),NOSPLIT,$0
- MOVW R0, m
- MOVW R1, g
- B runtime·save_gm(SB)
+// void setg_gcc(G*); set g called from gcc.
+TEXT setg_gcc<>(SB),NOSPLIT,$0
+ MOVW R0, g
+ B runtime·save_g(SB)
// TODO: share code with memeq?
TEXT bytes·Equal(SB),NOSPLIT,$0
@@ -767,9 +873,6 @@ _sib_notfound:
MOVW R0, ret+12(FP)
RET
-TEXT runtime·timenow(SB), NOSPLIT, $0-0
- B time·now(SB)
-
// A Duff's device for zeroing memory.
// The compiler jumps to computed addresses within
// this routine to zero chunks of memory. Do not
@@ -778,7 +881,7 @@ TEXT runtime·timenow(SB), NOSPLIT, $0-0
// R0: zero
// R1: ptr to memory to be zeroed
// R1 is updated as a side effect.
-TEXT runtime·duffzero(SB), NOSPLIT, $0-0
+TEXT runtime·duffzero(SB),NOSPLIT,$0-0
MOVW.P R0, 4(R1)
MOVW.P R0, 4(R1)
MOVW.P R0, 4(R1)
@@ -919,7 +1022,7 @@ TEXT runtime·duffzero(SB), NOSPLIT, $0-0
// R1: ptr to source memory
// R2: ptr to destination memory
// R1 and R2 are updated as a side effect
-TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
+TEXT runtime·duffcopy(SB),NOSPLIT,$0-0
MOVW.P 4(R1), R0
MOVW.P R0, 4(R2)
MOVW.P 4(R1), R0
@@ -1177,3 +1280,49 @@ TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
MOVW.P 4(R1), R0
MOVW.P R0, 4(R2)
RET
+
+TEXT runtime·fastrand1(SB),NOSPLIT,$-4-4
+ MOVW g_m(g), R1
+ MOVW m_fastrand(R1), R0
+ ADD.S R0, R0
+ EOR.MI $0x88888eef, R0
+ MOVW R0, m_fastrand(R1)
+ MOVW R0, ret+0(FP)
+ RET
+
+TEXT runtime·return0(SB),NOSPLIT,$0
+ MOVW $0, R0
+ RET
+
+TEXT runtime·procyield(SB),NOSPLIT,$-4
+ MOVW cycles+0(FP), R1
+ MOVW $0, R0
+yieldloop:
+ CMP R0, R1
+ B.NE 2(PC)
+ RET
+ SUB $1, R1
+ B yieldloop
+
+// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
+// Must obey the gcc calling convention.
+TEXT _cgo_topofstack(SB),NOSPLIT,$8
+ // R11 and g register are clobbered by load_g. They are
+ // callee-save in the gcc calling convention, so save them here.
+ MOVW R11, saveR11-4(SP)
+ MOVW g, saveG-8(SP)
+
+ BL runtime·load_g(SB)
+ MOVW g_m(g), R0
+ MOVW m_curg(R0), R0
+ MOVW (g_stack+stack_hi)(R0), R0
+
+ MOVW saveG-8(SP), g
+ MOVW saveR11-4(SP), R11
+ RET
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$-4-0
+ MOVW R0, R0 // NOP
+ BL runtime·goexit1(SB) // does not return
diff --git a/src/runtime/atomic.go b/src/runtime/atomic.go
new file mode 100644
index 000000000..7e9d9b3aa
--- /dev/null
+++ b/src/runtime/atomic.go
@@ -0,0 +1,51 @@
+// 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 !arm
+
+package runtime
+
+import "unsafe"
+
+//go:noescape
+func xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func xadd64(ptr *uint64, delta int64) uint64
+
+//go:noescape
+func xchg(ptr *uint32, new uint32) uint32
+
+//go:noescape
+func xchg64(ptr *uint64, new uint64) uint64
+
+//go:noescape
+func xchgp(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 atomicor8(ptr *uint8, val uint8)
+
+//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)
+
+//go:noescape
+func atomicstorep(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/pkg/runtime/atomic_386.c b/src/runtime/atomic_386.c
index d7162a1b8..82d36f2d9 100644
--- a/src/pkg/runtime/atomic_386.c
+++ b/src/runtime/atomic_386.c
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
#include "runtime.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#pragma textflag NOSPLIT
uint32
diff --git a/src/pkg/runtime/atomic_amd64x.c b/src/runtime/atomic_amd64x.c
index 11b578936..7be57ac95 100644
--- a/src/pkg/runtime/atomic_amd64x.c
+++ b/src/runtime/atomic_amd64x.c
@@ -5,7 +5,7 @@
// +build amd64 amd64p32
#include "runtime.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#pragma textflag NOSPLIT
uint32
diff --git a/src/runtime/atomic_arm.go b/src/runtime/atomic_arm.go
new file mode 100644
index 000000000..b1632cdd1
--- /dev/null
+++ b/src/runtime/atomic_arm.go
@@ -0,0 +1,155 @@
+// 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:nosplit
+func xchg(addr *uint32, v uint32) uint32 {
+ for {
+ old := *addr
+ if cas(addr, old, v) {
+ return old
+ }
+ }
+}
+
+//go:nosplit
+func xchgp(addr *unsafe.Pointer, v unsafe.Pointer) unsafe.Pointer {
+ for {
+ old := *addr
+ if casp(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 atomicstorep(addr unsafe.Pointer, v unsafe.Pointer) {
+ for {
+ old := *(*unsafe.Pointer)(addr)
+ if casp((*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
+ onM(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
+ onM(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
+ onM(func() {
+ lock(addrLock(addr))
+ r = *addr
+ *addr = v
+ unlock(addrLock(addr))
+ })
+ return r
+}
+
+//go:nosplit
+func atomicload64(addr *uint64) uint64 {
+ var r uint64
+ onM(func() {
+ lock(addrLock(addr))
+ r = *addr
+ unlock(addrLock(addr))
+ })
+ return r
+}
+
+//go:nosplit
+func atomicstore64(addr *uint64, v uint64) {
+ onM(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
+ }
+ }
+}
diff --git a/src/pkg/runtime/cgo/asm_386.s b/src/runtime/cgo/asm_386.s
index ab2f1d17a..a895083f1 100644
--- a/src/pkg/runtime/cgo/asm_386.s
+++ b/src/runtime/cgo/asm_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
/*
* void crosscall2(void (*fn)(void*, int32), void*, int32)
diff --git a/src/pkg/runtime/cgo/asm_amd64.s b/src/runtime/cgo/asm_amd64.s
index 64f719ab1..6095bd133 100644
--- a/src/pkg/runtime/cgo/asm_amd64.s
+++ b/src/runtime/cgo/asm_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
/*
* void crosscall2(void (*fn)(void*, int32), void*, int32)
diff --git a/src/pkg/runtime/cgo/asm_arm.s b/src/runtime/cgo/asm_arm.s
index 850b1c6b6..6e57432e3 100644
--- a/src/pkg/runtime/cgo/asm_arm.s
+++ b/src/runtime/cgo/asm_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
/*
* void crosscall2(void (*fn)(void*, int32), void*, int32)
@@ -14,11 +14,11 @@ TEXT crosscall2(SB),NOSPLIT,$-4
* push 2 args for fn (R1 and R2).
* Also note that at procedure entry in 5c/5g world, 4(R13) will be the
* first arg, so we must push another dummy reg (R0) for 0(R13).
- * Additionally, runtime·load_gm will clobber R0, so we need to save R0
+ * Additionally, runtime·load_g will clobber R0, so we need to save R0
* nevertheless.
*/
- MOVM.WP [R0, R1, R2, R4, R5, R6, R7, R8, m, g, R11, R12, R14], (R13)
- BL runtime·load_gm(SB)
+ MOVM.WP [R0, R1, R2, R4, R5, R6, R7, R8, R9, g, R11, R12, R14], (R13)
+ BL runtime·load_g(SB)
MOVW PC, R14
MOVW 0(R13), PC
- MOVM.IAW (R13), [R0, R1, R2, R4, R5, R6, R7, R8, m, g, R11, R12, PC]
+ MOVM.IAW (R13), [R0, R1, R2, R4, R5, R6, R7, R8, R9, g, R11, R12, PC]
diff --git a/src/pkg/runtime/cgo/asm_nacl_amd64p32.s b/src/runtime/cgo/asm_nacl_amd64p32.s
index 377cf72a3..eb92014ed 100644
--- a/src/pkg/runtime/cgo/asm_nacl_amd64p32.s
+++ b/src/runtime/cgo/asm_nacl_amd64p32.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
/*
* void crosscall2(void (*fn)(void*, int32), void*, int32)
diff --git a/src/pkg/runtime/cgo/callbacks.c b/src/runtime/cgo/callbacks.c
index e91c8bf8a..282beeea8 100644
--- a/src/pkg/runtime/cgo/callbacks.c
+++ b/src/runtime/cgo/callbacks.c
@@ -4,7 +4,7 @@
#include "../runtime.h"
#include "../cgocall.h"
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// These utility functions are available to be called from code
// compiled with gcc via crosscall2.
@@ -33,18 +33,7 @@
// crosscall2(_cgo_allocate, &a, sizeof a);
// /* Here a.ret is a pointer to the allocated memory. */
-static void
-_cgo_allocate_internal(uintptr len, byte *ret)
-{
- CgoMal *c;
-
- ret = runtime·mal(len);
- c = runtime·mal(sizeof(*c));
- c->next = m->cgomal;
- c->alloc = ret;
- m->cgomal = c;
- FLUSH(&ret);
-}
+void runtime·_cgo_allocate_internal(void);
#pragma cgo_export_static _cgo_allocate
#pragma cgo_export_dynamic _cgo_allocate
@@ -52,7 +41,7 @@ _cgo_allocate_internal(uintptr len, byte *ret)
void
_cgo_allocate(void *a, int32 n)
{
- runtime·cgocallback((void(*)(void))_cgo_allocate_internal, a, n);
+ runtime·cgocallback((void(*)(void))runtime·_cgo_allocate_internal, a, n);
}
// Panic. The argument is converted into a Go string.
@@ -63,18 +52,7 @@ _cgo_allocate(void *a, int32 n)
// crosscall2(_cgo_panic, &a, sizeof a);
// /* The function call will not return. */
-extern void ·cgoStringToEface(String, Eface*);
-
-static void
-_cgo_panic_internal(byte *p)
-{
- String s;
- Eface err;
-
- s = runtime·gostring(p);
- ·cgoStringToEface(s, &err);
- runtime·panic(err);
-}
+void runtime·_cgo_panic_internal(void);
#pragma cgo_export_static _cgo_panic
#pragma cgo_export_dynamic _cgo_panic
@@ -82,7 +60,7 @@ _cgo_panic_internal(byte *p)
void
_cgo_panic(void *a, int32 n)
{
- runtime·cgocallback((void(*)(void))_cgo_panic_internal, a, n);
+ runtime·cgocallback((void(*)(void))runtime·_cgo_panic_internal, a, n);
}
#pragma cgo_import_static x_cgo_init
@@ -100,3 +78,6 @@ void (*_cgo_free)(void*) = x_cgo_free;
#pragma cgo_import_static x_cgo_thread_start
extern void x_cgo_thread_start(void*);
void (*_cgo_thread_start)(void*) = x_cgo_thread_start;
+
+#pragma cgo_export_static _cgo_topofstack
+#pragma cgo_export_dynamic _cgo_topofstack
diff --git a/src/pkg/runtime/cgo/cgo.go b/src/runtime/cgo/cgo.go
index 258b6fba1..8528692f7 100644
--- a/src/pkg/runtime/cgo/cgo.go
+++ b/src/runtime/cgo/cgo.go
@@ -14,7 +14,8 @@ package cgo
#cgo darwin LDFLAGS: -lpthread
#cgo dragonfly LDFLAGS: -lpthread
#cgo freebsd LDFLAGS: -lpthread
-#cgo linux LDFLAGS: -lpthread
+#cgo android LDFLAGS: -llog
+#cgo !android,linux LDFLAGS: -lpthread
#cgo netbsd LDFLAGS: -lpthread
#cgo openbsd LDFLAGS: -lpthread
#cgo windows LDFLAGS: -lm -mthreads
@@ -23,10 +24,3 @@ package cgo
*/
import "C"
-
-// Supports _cgo_panic by converting a string constant to an empty
-// interface.
-
-func cgoStringToEface(s string, ret *interface{}) {
- *ret = s
-}
diff --git a/src/pkg/runtime/cgo/dragonfly.c b/src/runtime/cgo/dragonfly.c
index acf53e265..c233c8ba9 100644
--- a/src/pkg/runtime/cgo/dragonfly.c
+++ b/src/runtime/cgo/dragonfly.c
@@ -2,11 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build dragonfly
+
+#include "textflag.h"
+
// Supply environ and __progname, because we don't
// link against the standard DragonFly crt0.o and the
// libc dynamic library needs them.
+#pragma dataflag NOPTR
char *environ[1];
+#pragma dataflag NOPTR
char *__progname;
#pragma dynexport environ environ
diff --git a/src/pkg/runtime/cgo/freebsd.c b/src/runtime/cgo/freebsd.c
index dfcfa3a21..4876b2abe 100644
--- a/src/pkg/runtime/cgo/freebsd.c
+++ b/src/runtime/cgo/freebsd.c
@@ -2,11 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build freebsd
+
+#include "textflag.h"
+
// Supply environ and __progname, because we don't
// link against the standard FreeBSD crt0.o and the
// libc dynamic library needs them.
+#pragma dataflag NOPTR
char *environ[1];
+#pragma dataflag NOPTR
char *__progname;
#pragma dynexport environ environ
diff --git a/src/pkg/runtime/cgo/gcc_386.S b/src/runtime/cgo/gcc_386.S
index bf4142793..bf4142793 100644
--- a/src/pkg/runtime/cgo/gcc_386.S
+++ b/src/runtime/cgo/gcc_386.S
diff --git a/src/pkg/runtime/cgo/gcc_amd64.S b/src/runtime/cgo/gcc_amd64.S
index 32d0200cf..32d0200cf 100644
--- a/src/pkg/runtime/cgo/gcc_amd64.S
+++ b/src/runtime/cgo/gcc_amd64.S
diff --git a/src/runtime/cgo/gcc_android.c b/src/runtime/cgo/gcc_android.c
new file mode 100644
index 000000000..be2772568
--- /dev/null
+++ b/src/runtime/cgo/gcc_android.c
@@ -0,0 +1,31 @@
+// 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 <stdarg.h>
+#include <android/log.h>
+#include "libcgo.h"
+
+void
+fatalf(const char* format, ...)
+{
+ va_list ap;
+
+ // Write to both stderr and logcat.
+ //
+ // When running from an .apk, /dev/stderr and /dev/stdout
+ // redirect to /dev/null. And when running a test binary
+ // via adb shell, it's easy to miss logcat.
+
+ fprintf(stderr, "runtime/cgo: ");
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+
+ va_start(ap, format);
+ __android_log_vprint(ANDROID_LOG_FATAL, "runtime/cgo", format, ap);
+ va_end(ap);
+
+ abort();
+}
diff --git a/src/runtime/cgo/gcc_android_arm.c b/src/runtime/cgo/gcc_android_arm.c
new file mode 100644
index 000000000..07f7e72e3
--- /dev/null
+++ b/src/runtime/cgo/gcc_android_arm.c
@@ -0,0 +1,43 @@
+// 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 <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/limits.h>
+#include "libcgo.h"
+
+#define magic1 (0x23581321U)
+
+// PTHREAD_KEYS_MAX has been added to sys/limits.h at head in bionic:
+// https://android.googlesource.com/platform/bionic/+/master/libc/include/sys/limits.h
+// TODO(crawshaw): remove this definition when a new NDK is released.
+#define PTHREAD_KEYS_MAX 128
+
+// 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/pkg/runtime/cgo/gcc_arm.S b/src/runtime/cgo/gcc_arm.S
index 17e98d91f..d5833bfad 100644
--- a/src/pkg/runtime/cgo/gcc_arm.S
+++ b/src/runtime/cgo/gcc_arm.S
@@ -12,28 +12,24 @@
#endif
/*
- * Because the assembler might target an earlier revision of the ISA
- * by default, we must explicitly specify the ISA revision to ensure
- * BLX is recognized as a valid instruction.
- */
-.arch armv5t
-
-/*
- * void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void *m, void *g), void *m, void *g)
+ * void crosscall_arm1(void (*fn)(void), void (*setg_gcc)(void *g), void *g)
*
* Calling into the 5c tool chain, where all registers are caller save.
* Called from standard ARM EABI, where r4-r11 are callee-save, so they
* must be saved explicitly.
*/
-.globl EXT(crosscall_arm2)
-EXT(crosscall_arm2):
+.globl EXT(crosscall_arm1)
+EXT(crosscall_arm1):
push {r4, r5, r6, r7, r8, r9, r10, r11, ip, lr}
mov r4, r0
mov r5, r1
mov r0, r2
- mov r1, r3
- blx r5 // setmg(m, g)
- blx r4 // fn()
+
+ // Because the assembler might target an earlier revision of the ISA
+ // by default, we encode BLX as a .word.
+ .word 0xe12fff35 // blx r5 // setg(g)
+ .word 0xe12fff34 // blx r4 // fn()
+
pop {r4, r5, r6, r7, r8, r9, r10, r11, ip, pc}
.globl EXT(__stack_chk_fail_local)
diff --git a/src/pkg/runtime/cgo/gcc_darwin_386.c b/src/runtime/cgo/gcc_darwin_386.c
index ad9fb5abf..6668ba4a2 100644
--- a/src/pkg/runtime/cgo/gcc_darwin_386.c
+++ b/src/runtime/cgo/gcc_darwin_386.c
@@ -8,46 +8,44 @@
#include "libcgo.h"
static void* threadentry(void*);
-static pthread_key_t k1, k2;
+static pthread_key_t k1;
#define magic1 (0x23581321U)
static void
inittls(void)
{
- uint32 x, y;
+ uint32 x;
pthread_key_t tofree[128], k;
int i, ntofree;
- int havek1, havek2;
/*
- * Allocate thread-local storage slots for m, g.
+ * Allocate thread-local storage slot for g.
* The key numbers start at 0x100, and we expect to be
* one of the early calls to pthread_key_create, so we
- * should be able to get pretty low numbers.
+ * should be able to get a pretty low number.
*
* In Darwin/386 pthreads, %gs points at the thread
* structure, and each key is an index into the thread-local
* storage array that begins at offset 0x48 within in that structure.
* It may happen that we are not quite the first function to try
* to allocate thread-local storage keys, so instead of depending
- * on getting 0x100 and 0x101, we try for 0x108 and 0x109,
- * allocating keys until we get the ones we want and then freeing
- * the ones we didn't want.
+ * on getting 0x100, we try for 0x108, allocating keys until
+ * we get the one we want and then freeing the ones we didn't want.
*
- * Thus the final offsets to use in %gs references are
- * 0x48+4*0x108 = 0x468 and 0x48+4*0x109 = 0x46c.
+ * Thus the final offset to use in %gs references is
+ * 0x48+4*0x108 = 0x468.
*
- * The linker and runtime hard-code these constant offsets
- * from %gs where we expect to find m and g.
- * Known to ../../../cmd/8l/obj.c:/468
+ * The linker and runtime hard-code this constant offset
+ * from %gs where we expect to find g.
+ * Known to ../../../liblink/sym.c:/468
* and to ../sys_darwin_386.s:/468
*
* This is truly disgusting and a bit fragile, but taking care
* of it here protects the rest of the system from damage.
* The alternative would be to use a global variable that
* held the offset and refer to that variable each time we
- * need a %gs variable (m or g). That approach would
+ * need a %gs variable (g). That approach would
* require an extra instruction and memory reference in
* every stack growth prolog and would also require
* rewriting the code that 8c generates for extern registers.
@@ -63,39 +61,32 @@ inittls(void)
* storage until we find a key that writes to the memory location
* we want. Then keep that key.
*/
- havek1 = 0;
- havek2 = 0;
ntofree = 0;
- while(!havek1 || !havek2) {
+ 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:0x468, %0" : "=r"(x));
- asm volatile("movl %%gs:0x46c, %0" : "=r"(y));
+ pthread_setspecific(k, 0);
if(x == magic1) {
- havek1 = 1;
k1 = k;
- } else if(y == magic1) {
- havek2 = 1;
- k2 = k;
- } else {
- 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;
+ break;
}
- pthread_setspecific(k, 0);
+ 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;
}
/*
- * We got the keys we wanted. Free the others.
+ * We got the key we wanted. Free the others.
*/
for(i=0; i<ntofree; i++)
pthread_key_delete(tofree[i]);
@@ -109,7 +100,7 @@ x_cgo_init(G *g)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
inittls();
@@ -130,7 +121,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -149,16 +141,7 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
pthread_setspecific(k1, (void*)ts.g);
- pthread_setspecific(k2, (void*)ts.m);
crosscall_386(ts.fn);
return nil;
diff --git a/src/pkg/runtime/cgo/gcc_darwin_amd64.c b/src/runtime/cgo/gcc_darwin_amd64.c
index 65d381633..dc679acab 100644
--- a/src/pkg/runtime/cgo/gcc_darwin_amd64.c
+++ b/src/runtime/cgo/gcc_darwin_amd64.c
@@ -8,64 +8,56 @@
#include "libcgo.h"
static void* threadentry(void*);
-static pthread_key_t k1, k2;
+static pthread_key_t k1;
#define magic1 (0x23581321345589ULL)
static void
inittls(void)
{
- uint64 x, y;
+ uint64 x;
pthread_key_t tofree[128], k;
int i, ntofree;
- int havek1, havek2;
/*
* Same logic, code as darwin_386.c:/inittls, except that words
* are 8 bytes long now, and the thread-local storage starts
- * at 0x60 on Leopard / Snow Leopard. So the offsets are
- * 0x60+8*0x108 = 0x8a0 and 0x60+8*0x109 = 0x8a8.
+ * at 0x60 on Leopard / Snow Leopard. So the offset is
+ * 0x60+8*0x108 = 0x8a0.
*
- * The linker and runtime hard-code these constant offsets
- * from %gs where we expect to find m and g.
- * Known to ../../../cmd/6l/obj.c:/8a0
+ * The linker and runtime hard-code this constant offset
+ * from %gs where we expect to find g.
+ * Known to ../../../liblink/sym.c:/8a0
* and to ../sys_darwin_amd64.s:/8a0
*
* As disgusting as on the 386; same justification.
*/
- havek1 = 0;
- havek2 = 0;
ntofree = 0;
- while(!havek1 || !havek2) {
+ 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 %%gs:0x8a0, %0" : "=r"(x));
- asm volatile("movq %%gs:0x8a8, %0" : "=r"(y));
+ pthread_setspecific(k, 0);
if(x == magic1) {
- havek1 = 1;
k1 = k;
- } else if(y == magic1) {
- havek2 = 1;
- k2 = k;
- } else {
- 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;
+ break;
}
- pthread_setspecific(k, 0);
+ 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;
}
/*
- * We got the keys we wanted. Free the others.
+ * We got the key we wanted. Free the others.
*/
for(i=0; i<ntofree; i++)
pthread_key_delete(tofree[i]);
@@ -79,7 +71,7 @@ x_cgo_init(G *g)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
inittls();
@@ -100,7 +92,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -119,16 +112,7 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
pthread_setspecific(k1, (void*)ts.g);
- pthread_setspecific(k2, (void*)ts.m);
crosscall_amd64(ts.fn);
return nil;
diff --git a/src/pkg/runtime/cgo/gcc_dragonfly_386.c b/src/runtime/cgo/gcc_dragonfly_386.c
index 695c16634..074418f77 100644
--- a/src/pkg/runtime/cgo/gcc_dragonfly_386.c
+++ b/src/runtime/cgo/gcc_dragonfly_386.c
@@ -10,18 +10,18 @@
#include "libcgo.h"
static void* threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
+x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
@@ -40,7 +40,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -59,18 +60,10 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
/*
* Set specific keys.
*/
- setmg_gcc((void*)ts.m, (void*)ts.g);
+ setg_gcc((void*)ts.g);
crosscall_386(ts.fn);
return nil;
diff --git a/src/pkg/runtime/cgo/gcc_dragonfly_amd64.c b/src/runtime/cgo/gcc_dragonfly_amd64.c
index a46c121ad..f79f652e4 100644
--- a/src/pkg/runtime/cgo/gcc_dragonfly_amd64.c
+++ b/src/runtime/cgo/gcc_dragonfly_amd64.c
@@ -10,18 +10,18 @@
#include "libcgo.h"
static void* threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
+x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
@@ -40,7 +40,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -59,18 +60,10 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
/*
* Set specific keys.
*/
- setmg_gcc((void*)ts.m, (void*)ts.g);
+ setg_gcc((void*)ts.g);
crosscall_amd64(ts.fn);
return nil;
diff --git a/src/runtime/cgo/gcc_fatalf.c b/src/runtime/cgo/gcc_fatalf.c
new file mode 100644
index 000000000..21c1acfaa
--- /dev/null
+++ b/src/runtime/cgo/gcc_fatalf.c
@@ -0,0 +1,23 @@
+// 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 !android,linux
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "libcgo.h"
+
+void
+fatalf(const char* format, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "runtime/cgo: ");
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+ abort();
+}
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_386.c b/src/runtime/cgo/gcc_freebsd_386.c
index 695c16634..074418f77 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_386.c
+++ b/src/runtime/cgo/gcc_freebsd_386.c
@@ -10,18 +10,18 @@
#include "libcgo.h"
static void* threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
+x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
@@ -40,7 +40,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -59,18 +60,10 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
/*
* Set specific keys.
*/
- setmg_gcc((void*)ts.m, (void*)ts.g);
+ setg_gcc((void*)ts.g);
crosscall_386(ts.fn);
return nil;
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_amd64.c b/src/runtime/cgo/gcc_freebsd_amd64.c
index a46c121ad..f79f652e4 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_amd64.c
+++ b/src/runtime/cgo/gcc_freebsd_amd64.c
@@ -10,18 +10,18 @@
#include "libcgo.h"
static void* threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
+x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
@@ -40,7 +40,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -59,18 +60,10 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
/*
* Set specific keys.
*/
- setmg_gcc((void*)ts.m, (void*)ts.g);
+ setg_gcc((void*)ts.g);
crosscall_amd64(ts.fn);
return nil;
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_arm.c b/src/runtime/cgo/gcc_freebsd_arm.c
index 6175e1d9c..2a86a9117 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c
+++ b/src/runtime/cgo/gcc_freebsd_arm.c
@@ -21,18 +21,18 @@
static void *threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
+x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
@@ -56,7 +56,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
size = 0;
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -67,7 +68,7 @@ _cgo_sys_thread_start(ThreadStart *ts)
}
}
-extern void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void*, void*), void *g, void *m);
+extern void crosscall_arm1(void (*fn)(void), void (*setg_gcc)(void*), void *g);
static void*
threadentry(void *v)
{
@@ -76,14 +77,6 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2;
-
- crosscall_arm2(ts.fn, setmg_gcc, (void*)ts.m, (void*)ts.g);
+ crosscall_arm1(ts.fn, setg_gcc, (void*)ts.g);
return nil;
}
diff --git a/src/pkg/runtime/cgo/gcc_linux_386.c b/src/runtime/cgo/gcc_linux_386.c
index 0a46c9b7a..9801c87bd 100644
--- a/src/pkg/runtime/cgo/gcc_linux_386.c
+++ b/src/runtime/cgo/gcc_linux_386.c
@@ -8,18 +8,18 @@
#include "libcgo.h"
static void *threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
+x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
@@ -43,14 +43,14 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
size = 0;
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
if (err != 0) {
- fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
- abort();
+ fatalf("pthread_create failed: %s", strerror(err));
}
}
@@ -62,18 +62,10 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
/*
* Set specific keys.
*/
- setmg_gcc((void*)ts.m, (void*)ts.g);
+ setg_gcc((void*)ts.g);
crosscall_386(ts.fn);
return nil;
diff --git a/src/pkg/runtime/cgo/gcc_linux_amd64.c b/src/runtime/cgo/gcc_linux_amd64.c
index c530183b7..275d5ddac 100644
--- a/src/pkg/runtime/cgo/gcc_linux_amd64.c
+++ b/src/runtime/cgo/gcc_linux_amd64.c
@@ -8,18 +8,18 @@
#include "libcgo.h"
static void* threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
void
-x_cgo_init(G* g, void (*setmg)(void*, void*))
+x_cgo_init(G* g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
@@ -38,14 +38,14 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
if (err != 0) {
- fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
- abort();
+ fatalf("pthread_create failed: %s", strerror(err));
}
}
@@ -57,18 +57,10 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
/*
* Set specific keys.
*/
- setmg_gcc((void*)ts.m, (void*)ts.g);
+ setg_gcc((void*)ts.g);
crosscall_amd64(ts.fn);
return nil;
diff --git a/src/pkg/runtime/cgo/gcc_linux_arm.c b/src/runtime/cgo/gcc_linux_arm.c
index 032568155..7d4b4d6d4 100644
--- a/src/pkg/runtime/cgo/gcc_linux_arm.c
+++ b/src/runtime/cgo/gcc_linux_arm.c
@@ -9,21 +9,8 @@
static void *threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
-
-void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
-{
- pthread_attr_t attr;
- size_t size;
-
- setmg_gcc = setmg;
- pthread_attr_init(&attr);
- pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
- pthread_attr_destroy(&attr);
-}
-
+void (*x_cgo_inittls)(void **tlsg, void **tlsbase);
+void (*setg_gcc)(void*);
void
_cgo_sys_thread_start(ThreadStart *ts)
@@ -44,18 +31,18 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
size = 0;
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
if (err != 0) {
- fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
- abort();
+ fatalf("pthread_create failed: %s", strerror(err));
}
}
-extern void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void*, void*), void*, void*);
+extern void crosscall_arm1(void (*fn)(void), void (*setg_gcc)(void*), void *g);
static void*
threadentry(void *v)
{
@@ -64,14 +51,23 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
+ crosscall_arm1(ts.fn, setg_gcc, (void*)ts.g);
+ return nil;
+}
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2;
+void
+x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase)
+{
+ pthread_attr_t attr;
+ size_t size;
- crosscall_arm2(ts.fn, setmg_gcc, (void*)ts.m, (void*)ts.g);
- return nil;
+ setg_gcc = setg;
+ pthread_attr_init(&attr);
+ pthread_attr_getstacksize(&attr, &size);
+ g->stacklo = (uintptr)&attr - size + 4096;
+ pthread_attr_destroy(&attr);
+
+ if (x_cgo_inittls) {
+ x_cgo_inittls(tlsg, tlsbase);
+ }
}
diff --git a/src/pkg/runtime/cgo/gcc_netbsd_386.c b/src/runtime/cgo/gcc_netbsd_386.c
index 28690ccbd..2505e6dc7 100644
--- a/src/pkg/runtime/cgo/gcc_netbsd_386.c
+++ b/src/runtime/cgo/gcc_netbsd_386.c
@@ -9,18 +9,18 @@
#include "libcgo.h"
static void* threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
+x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
@@ -39,7 +39,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -58,18 +59,10 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
/*
* Set specific keys.
*/
- setmg_gcc((void*)ts.m, (void*)ts.g);
+ setg_gcc((void*)ts.g);
crosscall_386(ts.fn);
return nil;
diff --git a/src/pkg/runtime/cgo/gcc_netbsd_amd64.c b/src/runtime/cgo/gcc_netbsd_amd64.c
index 6e0482d5b..8f646502d 100644
--- a/src/pkg/runtime/cgo/gcc_netbsd_amd64.c
+++ b/src/runtime/cgo/gcc_netbsd_amd64.c
@@ -9,18 +9,18 @@
#include "libcgo.h"
static void* threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
+x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
@@ -40,7 +40,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -59,18 +60,10 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
/*
* Set specific keys.
*/
- setmg_gcc((void*)ts.m, (void*)ts.g);
+ setg_gcc((void*)ts.g);
crosscall_amd64(ts.fn);
return nil;
diff --git a/src/pkg/runtime/cgo/gcc_netbsd_arm.c b/src/runtime/cgo/gcc_netbsd_arm.c
index ba2ae2568..7a98c0de2 100644
--- a/src/pkg/runtime/cgo/gcc_netbsd_arm.c
+++ b/src/runtime/cgo/gcc_netbsd_arm.c
@@ -10,18 +10,18 @@
static void *threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
+x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
@@ -40,7 +40,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -51,7 +52,7 @@ _cgo_sys_thread_start(ThreadStart *ts)
}
}
-extern void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void*, void*), void *g, void *m);
+extern void crosscall_arm1(void (*fn)(void), void (*setg_gcc)(void*), void *g);
static void*
threadentry(void *v)
{
@@ -60,14 +61,6 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2;
-
- crosscall_arm2(ts.fn, setmg_gcc, (void*)ts.m, (void*)ts.g);
+ crosscall_arm1(ts.fn, setg_gcc, (void*)ts.g);
return nil;
}
diff --git a/src/pkg/runtime/cgo/gcc_openbsd_386.c b/src/runtime/cgo/gcc_openbsd_386.c
index e682c3725..582e943f3 100644
--- a/src/pkg/runtime/cgo/gcc_openbsd_386.c
+++ b/src/runtime/cgo/gcc_openbsd_386.c
@@ -11,7 +11,7 @@
#include "libcgo.h"
static void* threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
// TCB_SIZE is sizeof(struct thread_control_block),
// as defined in /usr/src/lib/librthread/tcb.h
@@ -83,16 +83,16 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
}
void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
+x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
void *handle;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
// Locate symbol for the system pthread_create function.
@@ -126,7 +126,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = sys_pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -147,18 +148,10 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
/*
* Set specific keys.
*/
- setmg_gcc((void*)ts.m, (void*)ts.g);
+ setg_gcc((void*)ts.g);
crosscall_386(ts.fn);
return nil;
diff --git a/src/pkg/runtime/cgo/gcc_openbsd_amd64.c b/src/runtime/cgo/gcc_openbsd_amd64.c
index 64d29a935..35b359bba 100644
--- a/src/pkg/runtime/cgo/gcc_openbsd_amd64.c
+++ b/src/runtime/cgo/gcc_openbsd_amd64.c
@@ -11,7 +11,7 @@
#include "libcgo.h"
static void* threadentry(void*);
-static void (*setmg_gcc)(void*, void*);
+static void (*setg_gcc)(void*);
// TCB_SIZE is sizeof(struct thread_control_block),
// as defined in /usr/src/lib/librthread/tcb.h
@@ -83,16 +83,16 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
}
void
-x_cgo_init(G *g, void (*setmg)(void*, void*))
+x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
void *handle;
- setmg_gcc = setmg;
+ setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- g->stackguard = (uintptr)&attr - size + 4096;
+ g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
// Locate symbol for the system pthread_create function.
@@ -127,7 +127,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
- ts->g->stackguard = size;
+ // Leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
err = sys_pthread_create(&p, &attr, threadentry, ts);
pthread_sigmask(SIG_SETMASK, &oset, nil);
@@ -148,18 +149,10 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
-
- /*
- * _cgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
/*
* Set specific keys.
*/
- setmg_gcc((void*)ts.m, (void*)ts.g);
+ setg_gcc((void*)ts.g);
crosscall_amd64(ts.fn);
return nil;
diff --git a/src/pkg/runtime/cgo/gcc_setenv.c b/src/runtime/cgo/gcc_setenv.c
index 8b128b946..af0fc5d8d 100644
--- a/src/pkg/runtime/cgo/gcc_setenv.c
+++ b/src/runtime/cgo/gcc_setenv.c
@@ -14,3 +14,10 @@ x_cgo_setenv(char **arg)
{
setenv(arg[0], arg[1], 1);
}
+
+/* Stub for calling unsetenv */
+void
+x_cgo_unsetenv(char *arg)
+{
+ unsetenv(arg);
+}
diff --git a/src/pkg/runtime/cgo/gcc_util.c b/src/runtime/cgo/gcc_util.c
index 143734e94..143734e94 100644
--- a/src/pkg/runtime/cgo/gcc_util.c
+++ b/src/runtime/cgo/gcc_util.c
diff --git a/src/pkg/runtime/cgo/gcc_windows_386.c b/src/runtime/cgo/gcc_windows_386.c
index cdc866468..acd038ccd 100644
--- a/src/pkg/runtime/cgo/gcc_windows_386.c
+++ b/src/runtime/cgo/gcc_windows_386.c
@@ -20,7 +20,7 @@ void
x_cgo_init(G *g)
{
int tmp;
- g->stackguard = (uintptr)&tmp - STACKSIZE + 8*1024;
+ g->stacklo = (uintptr)&tmp - STACKSIZE + 8*1024;
}
@@ -44,8 +44,8 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
- ts.g->stackguard = (uintptr)&ts - STACKSIZE + 8*1024;
+ ts.g->stackhi = (uintptr)&ts;
+ ts.g->stacklo = (uintptr)&ts - STACKSIZE + 8*1024;
/*
* Set specific keys in thread local storage.
@@ -54,8 +54,7 @@ threadentry(void *v)
"movl %0, %%fs:0x14\n" // MOVL tls0, 0x14(FS)
"movl %%fs:0x14, %%eax\n" // MOVL 0x14(FS), tmp
"movl %1, 0(%%eax)\n" // MOVL g, 0(FS)
- "movl %2, 4(%%eax)\n" // MOVL m, 4(FS)
- :: "r"(ts.tls), "r"(ts.g), "r"(ts.m) : "%eax"
+ :: "r"(ts.tls), "r"(ts.g) : "%eax"
);
crosscall_386(ts.fn);
diff --git a/src/pkg/runtime/cgo/gcc_windows_amd64.c b/src/runtime/cgo/gcc_windows_amd64.c
index d8dd69b4a..ce7e06b3d 100644
--- a/src/pkg/runtime/cgo/gcc_windows_amd64.c
+++ b/src/runtime/cgo/gcc_windows_amd64.c
@@ -20,7 +20,7 @@ void
x_cgo_init(G *g)
{
int tmp;
- g->stackguard = (uintptr)&tmp - STACKSIZE + 8*1024;
+ g->stacklo = (uintptr)&tmp - STACKSIZE + 8*1024;
}
@@ -44,8 +44,8 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
- ts.g->stackbase = (uintptr)&ts;
- ts.g->stackguard = (uintptr)&ts - STACKSIZE + 8*1024;
+ ts.g->stackhi = (uintptr)&ts;
+ ts.g->stacklo = (uintptr)&ts - STACKSIZE + 8*1024;
/*
* Set specific keys in thread local storage.
@@ -54,8 +54,7 @@ threadentry(void *v)
"movq %0, %%gs:0x28\n" // MOVL tls0, 0x28(GS)
"movq %%gs:0x28, %%rax\n" // MOVQ 0x28(GS), tmp
"movq %1, 0(%%rax)\n" // MOVQ g, 0(GS)
- "movq %2, 8(%%rax)\n" // MOVQ m, 8(GS)
- :: "r"(ts.tls), "r"(ts.g), "r"(ts.m) : "%rax"
+ :: "r"(ts.tls), "r"(ts.g) : "%rax"
);
crosscall_amd64(ts.fn);
diff --git a/src/pkg/runtime/cgo/iscgo.c b/src/runtime/cgo/iscgo.c
index 0907a1958..0907a1958 100644
--- a/src/pkg/runtime/cgo/iscgo.c
+++ b/src/runtime/cgo/iscgo.c
diff --git a/src/pkg/runtime/cgo/libcgo.h b/src/runtime/cgo/libcgo.h
index 65ea3f372..9d918fd7a 100644
--- a/src/pkg/runtime/cgo/libcgo.h
+++ b/src/runtime/cgo/libcgo.h
@@ -21,8 +21,8 @@ typedef uintptr_t uintptr;
typedef struct G G;
struct G
{
- uintptr stackguard;
- uintptr stackbase;
+ uintptr stacklo;
+ uintptr stackhi;
};
/*
@@ -32,7 +32,6 @@ struct G
typedef struct ThreadStart ThreadStart;
struct ThreadStart
{
- uintptr m;
G *g;
uintptr *tls;
void (*fn)(void);
@@ -59,3 +58,8 @@ void crosscall_amd64(void (*fn)(void));
* Call fn in the 8c world.
*/
void crosscall_386(void (*fn)(void));
+
+/*
+ * Prints error then calls abort. For linux and android.
+ */
+void fatalf(const char* format, ...);
diff --git a/src/pkg/runtime/cgo/netbsd.c b/src/runtime/cgo/netbsd.c
index b6403f686..076cc87f1 100644
--- a/src/pkg/runtime/cgo/netbsd.c
+++ b/src/runtime/cgo/netbsd.c
@@ -2,11 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build netbsd
+
+#include "textflag.h"
+
// Supply environ and __progname, because we don't
// link against the standard NetBSD crt0.o and the
// libc dynamic library needs them.
+#pragma dataflag NOPTR
char *environ[1];
+#pragma dataflag NOPTR
char *__progname;
#pragma dynexport environ environ
diff --git a/src/pkg/runtime/cgo/openbsd.c b/src/runtime/cgo/openbsd.c
index 84e9f9eff..476649544 100644
--- a/src/pkg/runtime/cgo/openbsd.c
+++ b/src/runtime/cgo/openbsd.c
@@ -2,11 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build openbsd
+
+#include "textflag.h"
+
// Supply environ, __progname and __guard_local, because
// we don't link against the standard OpenBSD crt0.o and
// the libc dynamic library needs them.
+#pragma dataflag NOPTR
char *environ[1];
+#pragma dataflag NOPTR
char *__progname;
long __guard_local;
diff --git a/src/pkg/runtime/cgo/setenv.c b/src/runtime/cgo/setenv.c
index 2d03db09f..76d88cbf1 100644
--- a/src/pkg/runtime/cgo/setenv.c
+++ b/src/runtime/cgo/setenv.c
@@ -5,6 +5,9 @@
// +build darwin dragonfly freebsd linux netbsd openbsd
#pragma cgo_import_static x_cgo_setenv
+#pragma cgo_import_static x_cgo_unsetenv
void x_cgo_setenv(char**);
-void (*_cgo_setenv)(char**) = x_cgo_setenv;
+void (*runtime·_cgo_setenv)(char**) = x_cgo_setenv;
+void x_cgo_unsetenv(char**);
+void (*runtime·_cgo_unsetenv)(char**) = x_cgo_unsetenv;
diff --git a/src/pkg/runtime/cgocall.c b/src/runtime/cgocall.go
index 75d3850ef..7fd91469e 100644
--- a/src/pkg/runtime/cgocall.c
+++ b/src/runtime/cgocall.go
@@ -2,13 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "stack.h"
-#include "cgocall.h"
-#include "race.h"
-#include "../../cmd/ld/textflag.h"
-
// Cgo call and callback support.
//
// To call into the C function f from Go, the cgo-generated code calls
@@ -17,7 +10,7 @@
//
// runtime.cgocall (below) locks g to m, calls entersyscall
// so as not to block other goroutines or the garbage collector,
-// and then calls runtime.asmcgocall(_cgo_Cfunc_f, frame).
+// and then calls runtime.asmcgocall(_cgo_Cfunc_f, frame).
//
// runtime.asmcgocall (in asm_$GOARCH.s) switches to the m->g0 stack
// (assumed to be an operating system-allocated stack, so safe to run
@@ -84,49 +77,44 @@
// _cgoexp_GoF immediately returns to crosscall2, which restores the
// callee-save registers for gcc and returns to GoF, which returns to f.
-void *_cgo_init; /* filled in by dynamic linker when Cgo is available */
-static int64 cgosync; /* represents possible synchronization in C code */
+package runtime
-static void unwindm(void);
+import "unsafe"
// Call from Go to C.
+//go:nosplit
+func cgocall(fn, arg unsafe.Pointer) {
+ cgocall_errno(fn, arg)
+}
-static void endcgo(void);
-static FuncVal endcgoV = { endcgo };
-
-void
-runtime·cgocall(void (*fn)(void*), void *arg)
-{
- Defer d;
-
- if(!runtime·iscgo && !Solaris && !Windows)
- runtime·throw("cgocall unavailable");
+//go:nosplit
+func cgocall_errno(fn, arg unsafe.Pointer) int32 {
+ if !iscgo && GOOS != "solaris" && GOOS != "windows" {
+ gothrow("cgocall unavailable")
+ }
- if(fn == 0)
- runtime·throw("cgocall nil");
+ if fn == nil {
+ gothrow("cgocall nil")
+ }
- if(raceenabled)
- runtime·racereleasemerge(&cgosync);
+ if raceenabled {
+ racereleasemerge(unsafe.Pointer(&racecgosync))
+ }
// Create an extra M for callbacks on threads not created by Go on first cgo call.
- if(runtime·needextram && runtime·cas(&runtime·needextram, 1, 0))
- runtime·newextram();
-
- m->ncgocall++;
+ if needextram == 1 && cas(&needextram, 1, 0) {
+ onM(newextram)
+ }
/*
* Lock g to m to ensure we stay on the same stack if we do a
* cgo callback. Add entry to defer stack in case of panic.
*/
- runtime·lockOSThread();
- d.fn = &endcgoV;
- d.siz = 0;
- d.link = g->defer;
- d.argp = NoArgs;
- d.special = true;
- g->defer = &d;
-
- m->ncgo++;
+ lockOSThread()
+ mp := getg().m
+ mp.ncgocall++
+ mp.ncgo++
+ defer endcgo(mp)
/*
* Announce we are entering a system call
@@ -139,184 +127,153 @@ runtime·cgocall(void (*fn)(void*), void *arg)
* so it is safe to call while "in a system call", outside
* the $GOMAXPROCS accounting.
*/
- runtime·entersyscall();
- runtime·asmcgocall(fn, arg);
- runtime·exitsyscall();
-
- if(g->defer != &d || d.fn != &endcgoV)
- runtime·throw("runtime: bad defer entry in cgocallback");
- g->defer = d.link;
- endcgo();
+ entersyscall()
+ errno := asmcgocall_errno(fn, arg)
+ exitsyscall()
+
+ return errno
}
-static void
-endcgo(void)
-{
- runtime·unlockOSThread();
- m->ncgo--;
- if(m->ncgo == 0) {
+//go:nosplit
+func endcgo(mp *m) {
+ mp.ncgo--
+ if mp.ncgo == 0 {
// We are going back to Go and are not in a recursive
// call. Let the GC collect any memory allocated via
// _cgo_allocate that is no longer referenced.
- m->cgomal = nil;
+ mp.cgomal = nil
}
- if(raceenabled)
- runtime·raceacquire(&cgosync);
+ if raceenabled {
+ raceacquire(unsafe.Pointer(&racecgosync))
+ }
+
+ unlockOSThread() // invalidates mp
}
// Helper functions for cgo code.
-void (*_cgo_malloc)(void*);
-void (*_cgo_free)(void*);
-
-void*
-runtime·cmalloc(uintptr n)
-{
- struct {
- uint64 n;
- void *ret;
- } a;
-
- a.n = n;
- a.ret = nil;
- runtime·cgocall(_cgo_malloc, &a);
- if(a.ret == nil)
- runtime·throw("runtime: C malloc failed");
- return a.ret;
+// Filled by schedinit from corresponding C variables,
+// which are in turn filled in by dynamic linker when Cgo is available.
+var cgoMalloc, cgoFree unsafe.Pointer
+
+func cmalloc(n uintptr) unsafe.Pointer {
+ var args struct {
+ n uint64
+ ret unsafe.Pointer
+ }
+ args.n = uint64(n)
+ cgocall(cgoMalloc, unsafe.Pointer(&args))
+ if args.ret == nil {
+ gothrow("C malloc failed")
+ }
+ return args.ret
}
-void
-runtime·cfree(void *p)
-{
- runtime·cgocall(_cgo_free, p);
+func cfree(p unsafe.Pointer) {
+ cgocall(cgoFree, p)
}
// Call from C back to Go.
-
-static FuncVal unwindmf = {unwindm};
-
-typedef struct CallbackArgs CallbackArgs;
-struct CallbackArgs
-{
- FuncVal *fn;
- void *arg;
- uintptr argsize;
-};
-
-// Location of callback arguments depends on stack frame layout
-// and size of stack frame of cgocallback_gofunc.
-
-// 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.
-#ifdef GOARCH_arm
-#define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*))
-#endif
-
-// On amd64, stack frame is one word, plus caller PC.
-#ifdef GOARCH_amd64
-#define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+2*sizeof(void*))
-#endif
-
-// Unimplemented on amd64p32
-#ifdef GOARCH_amd64p32
-#define CBARGS (CallbackArgs*)(nil)
-#endif
-
-// On 386, stack frame is three words, plus caller PC.
-#ifdef GOARCH_386
-#define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*))
-#endif
-
-void runtime·cgocallbackg1(void);
-
-#pragma textflag NOSPLIT
-void
-runtime·cgocallbackg(void)
-{
- uintptr pc, sp;
-
- if(g != m->curg) {
- runtime·prints("runtime: bad g in cgocallback");
- runtime·exit(2);
+//go:nosplit
+func cgocallbackg() {
+ gp := getg()
+ if gp != gp.m.curg {
+ println("runtime: bad g in cgocallback")
+ exit(2)
}
- pc = g->syscallpc;
- sp = g->syscallsp;
- runtime·exitsyscall(); // coming out of cgo call
- runtime·cgocallbackg1();
- runtime·reentersyscall((void*)pc, sp); // going back to cgo call
+ // entersyscall saves the caller's SP to allow the GC to trace the Go
+ // stack. However, since we're returning to an earlier stack frame and
+ // need to pair with the entersyscall() call made by cgocall, we must
+ // save syscall* and let reentersyscall restore them.
+ savedsp := unsafe.Pointer(gp.syscallsp)
+ savedpc := gp.syscallpc
+ exitsyscall() // coming out of cgo call
+ cgocallbackg1()
+ // going back to cgo call
+ reentersyscall(savedpc, savedsp)
}
-void
-runtime·cgocallbackg1(void)
-{
- CallbackArgs *cb;
- Defer d;
-
- if(m->needextram) {
- m->needextram = 0;
- runtime·newextram();
+func cgocallbackg1() {
+ gp := getg()
+ if gp.m.needextram {
+ gp.m.needextram = false
+ onM(newextram)
}
// Add entry to defer stack in case of panic.
- d.fn = &unwindmf;
- d.siz = 0;
- d.link = g->defer;
- d.argp = NoArgs;
- d.special = true;
- g->defer = &d;
+ restore := true
+ defer unwindm(&restore)
+
+ if raceenabled {
+ raceacquire(unsafe.Pointer(&racecgosync))
+ }
- if(raceenabled)
- runtime·raceacquire(&cgosync);
+ type args struct {
+ fn *funcval
+ arg unsafe.Pointer
+ argsize uintptr
+ }
+ var cb *args
+
+ // Location of callback arguments depends on stack frame layout
+ // and size of stack frame of cgocallback_gofunc.
+ sp := gp.m.g0.sched.sp
+ switch GOARCH {
+ default:
+ gothrow("cgocallbackg is unimplemented on arch")
+ 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))
+ case "amd64":
+ // On amd64, stack frame is one word, plus caller PC.
+ cb = (*args)(unsafe.Pointer(sp + 2*ptrSize))
+ case "386":
+ // On 386, stack frame is three words, plus caller PC.
+ cb = (*args)(unsafe.Pointer(sp + 4*ptrSize))
+ }
// Invoke callback.
- cb = CBARGS;
- runtime·newstackcall(cb->fn, cb->arg, cb->argsize);
+ reflectcall(unsafe.Pointer(cb.fn), unsafe.Pointer(cb.arg), uint32(cb.argsize), 0)
- if(raceenabled)
- runtime·racereleasemerge(&cgosync);
+ if raceenabled {
+ racereleasemerge(unsafe.Pointer(&racecgosync))
+ }
- // Pop defer.
// Do not unwind m->g0->sched.sp.
// Our caller, cgocallback, will do that.
- if(g->defer != &d || d.fn != &unwindmf)
- runtime·throw("runtime: bad defer entry in cgocallback");
- g->defer = d.link;
+ restore = false
}
-static void
-unwindm(void)
-{
+func unwindm(restore *bool) {
+ if !*restore {
+ return
+ }
// Restore sp saved by cgocallback during
// unwind of g's stack (see comment at top of file).
- switch(thechar){
+ mp := acquirem()
+ sched := &mp.g0.sched
+ switch GOARCH {
default:
- runtime·throw("runtime: unwindm not implemented");
- case '8':
- case '6':
- m->g0->sched.sp = *(uintptr*)m->g0->sched.sp;
- break;
- case '5':
- m->g0->sched.sp = *(uintptr*)((byte*)m->g0->sched.sp + 4);
- break;
+ gothrow("unwindm not implemented")
+ case "386", "amd64":
+ sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp))
+ case "arm":
+ sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 4))
}
+ releasem(mp)
}
-void
-runtime·badcgocallback(void) // called from assembly
-{
- runtime·throw("runtime: misaligned stack in cgocallback");
+// called from assembly
+func badcgocallback() {
+ gothrow("misaligned stack in cgocallback")
}
-void
-runtime·cgounimpl(void) // called from (incomplete) assembly
-{
- runtime·throw("runtime: cgo not implemented");
+// called from (incomplete) assembly
+func cgounimpl() {
+ gothrow("cgo not implemented")
}
-// For cgo-using programs with external linking,
-// export "main" (defined in assembly) so that libc can handle basic
-// C runtime startup and call the Go program as if it were
-// the C main function.
-#pragma cgo_export_static main
+var racecgosync uint64 // represents possible synchronization in C code
diff --git a/src/pkg/runtime/cgocall.h b/src/runtime/cgocall.h
index 253661a7e..c87a9cdc5 100644
--- a/src/pkg/runtime/cgocall.h
+++ b/src/runtime/cgocall.h
@@ -7,6 +7,7 @@
*/
void runtime·cgocall(void (*fn)(void*), void*);
+int32 runtime·cgocall_errno(void (*fn)(void*), void*);
void runtime·cgocallback(void (*fn)(void), void*, uintptr);
void *runtime·cmalloc(uintptr);
void runtime·cfree(void*);
diff --git a/src/runtime/cgocallback.go b/src/runtime/cgocallback.go
new file mode 100644
index 000000000..2c8914320
--- /dev/null
+++ b/src/runtime/cgocallback.go
@@ -0,0 +1,40 @@
+// 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
+
+import "unsafe"
+
+// These functions are called from C code via cgo/callbacks.c.
+
+// Allocate memory. This allocates the requested number of bytes in
+// memory controlled by the Go runtime. The allocated memory will be
+// zeroed. You are responsible for ensuring that the Go garbage
+// collector can see a pointer to the allocated memory for as long as
+// it is valid, e.g., by storing a pointer in a local variable in your
+// C function, or in memory allocated by the Go runtime. If the only
+// pointers are in a C global variable or in memory allocated via
+// malloc, then the Go garbage collector may collect the memory.
+//
+// TODO(rsc,iant): This memory is untyped.
+// Either we need to add types or we need to stop using it.
+
+func _cgo_allocate_internal(len uintptr) unsafe.Pointer {
+ if len == 0 {
+ len = 1
+ }
+ ret := unsafe.Pointer(&make([]unsafe.Pointer, (len+ptrSize-1)/ptrSize)[0])
+ c := new(cgomal)
+ c.alloc = ret
+ gp := getg()
+ c.next = gp.m.cgomal
+ gp.m.cgomal = c
+ return ret
+}
+
+// Panic.
+
+func _cgo_panic_internal(p *byte) {
+ panic(gostringnocopy(p))
+}
diff --git a/src/runtime/chan.go b/src/runtime/chan.go
new file mode 100644
index 000000000..0eb87df74
--- /dev/null
+++ b/src/runtime/chan.go
@@ -0,0 +1,655 @@
+// 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
+
+// This file contains the implementation of Go channels.
+
+import "unsafe"
+
+const (
+ maxAlign = 8
+ hchanSize = unsafe.Sizeof(hchan{}) + uintptr(-int(unsafe.Sizeof(hchan{}))&(maxAlign-1))
+ debugChan = false
+)
+
+// TODO(khr): make hchan.buf an unsafe.Pointer, not a *uint8
+
+func makechan(t *chantype, size int64) *hchan {
+ elem := t.elem
+
+ // compiler checks this but be safe.
+ if elem.size >= 1<<16 {
+ gothrow("makechan: invalid channel element type")
+ }
+ if hchanSize%maxAlign != 0 || elem.align > maxAlign {
+ gothrow("makechan: bad alignment")
+ }
+ if size < 0 || int64(uintptr(size)) != size || (elem.size > 0 && uintptr(size) > (maxmem-hchanSize)/uintptr(elem.size)) {
+ panic("makechan: size out of range")
+ }
+
+ var c *hchan
+ if elem.kind&kindNoPointers != 0 || size == 0 {
+ // Allocate memory in one call.
+ // Hchan does not contain pointers interesting for GC in this case:
+ // buf points into the same allocation, elemtype is persistent.
+ // SudoG's are referenced from their owning thread so they can't be collected.
+ // TODO(dvyukov,rlh): Rethink when collector can move allocated objects.
+ c = (*hchan)(mallocgc(hchanSize+uintptr(size)*uintptr(elem.size), nil, flagNoScan))
+ if size > 0 && elem.size != 0 {
+ c.buf = (*uint8)(add(unsafe.Pointer(c), hchanSize))
+ } else {
+ c.buf = (*uint8)(unsafe.Pointer(c)) // race detector uses this location for synchronization
+ }
+ } else {
+ c = new(hchan)
+ c.buf = (*uint8)(newarray(elem, uintptr(size)))
+ }
+ c.elemsize = uint16(elem.size)
+ c.elemtype = elem
+ c.dataqsiz = uint(size)
+
+ if debugChan {
+ print("makechan: chan=", c, "; elemsize=", elem.size, "; elemalg=", elem.alg, "; dataqsiz=", size, "\n")
+ }
+ return c
+}
+
+// chanbuf(c, i) is pointer to the i'th slot in the buffer.
+func chanbuf(c *hchan, i uint) unsafe.Pointer {
+ return add(unsafe.Pointer(c.buf), uintptr(i)*uintptr(c.elemsize))
+}
+
+// entry point for c <- x from compiled code
+//go:nosplit
+func chansend1(t *chantype, c *hchan, elem unsafe.Pointer) {
+ chansend(t, c, elem, true, getcallerpc(unsafe.Pointer(&t)))
+}
+
+/*
+ * generic single channel send/recv
+ * If block is not nil,
+ * then the protocol will not
+ * sleep but return if it could
+ * not complete.
+ *
+ * sleep can wake up with g.param == nil
+ * when a channel involved in the sleep has
+ * been closed. it is easiest to loop and re-run
+ * the operation; we'll see that it's now closed.
+ */
+func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
+ if raceenabled {
+ raceReadObjectPC(t.elem, ep, callerpc, funcPC(chansend))
+ }
+
+ if c == nil {
+ if !block {
+ return false
+ }
+ gopark(nil, nil, "chan send (nil chan)")
+ gothrow("unreachable")
+ }
+
+ if debugChan {
+ print("chansend: chan=", c, "\n")
+ }
+
+ if raceenabled {
+ racereadpc(unsafe.Pointer(c), callerpc, funcPC(chansend))
+ }
+
+ // Fast path: check for failed non-blocking operation without acquiring the lock.
+ //
+ // After observing that the channel is not closed, we observe that the channel is
+ // not ready for sending. Each of these observations is a single word-sized read
+ // (first c.closed and second c.recvq.first or c.qcount depending on kind of channel).
+ // Because a closed channel cannot transition from 'ready for sending' to
+ // 'not ready for sending', even if the channel is closed between the two observations,
+ // they imply a moment between the two when the channel was both not yet closed
+ // and not ready for sending. We behave as if we observed the channel at that moment,
+ // and report that the send cannot proceed.
+ //
+ // It is okay if the reads are reordered here: if we observe that the channel is not
+ // ready for sending and then observe that it is not closed, that implies that the
+ // channel wasn't closed during the first observation.
+ if !block && c.closed == 0 && ((c.dataqsiz == 0 && c.recvq.first == nil) ||
+ (c.dataqsiz > 0 && c.qcount == c.dataqsiz)) {
+ return false
+ }
+
+ var t0 int64
+ if blockprofilerate > 0 {
+ t0 = cputicks()
+ }
+
+ 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 {
+ memmove(unsafe.Pointer(sg.elem), ep, uintptr(c.elemsize))
+ sg.elem = nil
+ }
+ recvg.param = unsafe.Pointer(sg)
+ if sg.releasetime != 0 {
+ sg.releasetime = cputicks()
+ }
+ goready(recvg)
+ 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")
+
+ // someone woke us up.
+ if mysg != gp.waiting {
+ gothrow("G waiting list is corrupted!")
+ }
+ gp.waiting = nil
+ if gp.param == nil {
+ if c.closed == 0 {
+ gothrow("chansend: spurious wakeup")
+ }
+ panic("send on closed channel")
+ }
+ gp.param = nil
+ if mysg.releasetime > 0 {
+ blockevent(int64(mysg.releasetime)-t0, 2)
+ }
+ releaseSudog(mysg)
+ return true
+ }
+
+ // asynchronous channel
+ // wait for some space to write our data
+ var t1 int64
+ for c.qcount >= c.dataqsiz {
+ 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")
+
+ // 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")
+ }
+ }
+
+ // write our data into the channel buffer
+ if raceenabled {
+ raceacquire(chanbuf(c, c.sendx))
+ racerelease(chanbuf(c, c.sendx))
+ }
+ memmove(chanbuf(c, c.sendx), ep, uintptr(c.elemsize))
+ c.sendx++
+ if c.sendx == c.dataqsiz {
+ c.sendx = 0
+ }
+ c.qcount++
+
+ // 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()
+ }
+ goready(recvg)
+ } else {
+ unlock(&c.lock)
+ }
+ if t1 > 0 {
+ blockevent(t1-t0, 2)
+ }
+ return true
+}
+
+func closechan(c *hchan) {
+ if c == nil {
+ panic("close of nil channel")
+ }
+
+ lock(&c.lock)
+ if c.closed != 0 {
+ unlock(&c.lock)
+ panic("close of closed channel")
+ }
+
+ if raceenabled {
+ callerpc := getcallerpc(unsafe.Pointer(&c))
+ racewritepc(unsafe.Pointer(c), callerpc, funcPC(closechan))
+ racerelease(unsafe.Pointer(c))
+ }
+
+ c.closed = 1
+
+ // release all readers
+ for {
+ sg := c.recvq.dequeue()
+ if sg == nil {
+ break
+ }
+ gp := sg.g
+ sg.elem = nil
+ gp.param = nil
+ if sg.releasetime != 0 {
+ sg.releasetime = cputicks()
+ }
+ goready(gp)
+ }
+
+ // release all writers
+ 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()
+ }
+ goready(gp)
+ }
+ unlock(&c.lock)
+}
+
+// entry points for <- c from compiled code
+//go:nosplit
+func chanrecv1(t *chantype, c *hchan, elem unsafe.Pointer) {
+ chanrecv(t, c, elem, true)
+}
+
+//go:nosplit
+func chanrecv2(t *chantype, c *hchan, elem unsafe.Pointer) (received bool) {
+ _, received = chanrecv(t, c, elem, true)
+ return
+}
+
+// chanrecv receives on channel c and writes the received data to ep.
+// ep may be nil, in which case received data is ignored.
+// 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).
+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.
+
+ if debugChan {
+ print("chanrecv: chan=", c, "\n")
+ }
+
+ if c == nil {
+ if !block {
+ return
+ }
+ gopark(nil, nil, "chan receive (nil chan)")
+ gothrow("unreachable")
+ }
+
+ // Fast path: check for failed non-blocking operation without acquiring the lock.
+ //
+ // After observing that the channel is not ready for receiving, we observe that the
+ // channel is not closed. Each of these observations is a single word-sized read
+ // (first c.sendq.first or c.qcount, and second c.closed).
+ // Because a channel cannot be reopened, the later observation of the channel
+ // being not closed implies that it was also not closed at the moment of the
+ // first observation. We behave as if we observed the channel at that moment
+ // and report that the receive cannot proceed.
+ //
+ // 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 {
+ return
+ }
+
+ var t0 int64
+ if blockprofilerate > 0 {
+ t0 = cputicks()
+ }
+
+ 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 {
+ memmove(ep, sg.elem, uintptr(c.elemsize))
+ }
+ sg.elem = nil
+ gp := sg.g
+ gp.param = unsafe.Pointer(sg)
+ if sg.releasetime != 0 {
+ sg.releasetime = cputicks()
+ }
+ goready(gp)
+ 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")
+
+ // someone woke us up
+ if mysg != gp.waiting {
+ gothrow("G waiting list is corrupted!")
+ }
+ 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 {
+ gothrow("chanrecv: spurious wakeup")
+ }
+ return recvclosed(c, ep)
+ }
+
+ // asynchronous channel
+ // wait for some data to appear
+ var t1 int64
+ for c.qcount <= 0 {
+ if c.closed != 0 {
+ selected, received = recvclosed(c, ep)
+ if t1 > 0 {
+ blockevent(t1-t0, 2)
+ }
+ return
+ }
+
+ if !block {
+ unlock(&c.lock)
+ return
+ }
+
+ // wait for someone to send an element
+ gp := getg()
+ mysg := acquireSudog()
+ mysg.releasetime = 0
+ if t0 != 0 {
+ mysg.releasetime = -1
+ }
+ mysg.elem = nil
+ mysg.g = gp
+ mysg.selectdone = nil
+
+ c.recvq.enqueue(mysg)
+ goparkunlock(&c.lock, "chan receive")
+
+ // someone woke us up - try again
+ if mysg.releasetime > 0 {
+ t1 = mysg.releasetime
+ }
+ releaseSudog(mysg)
+ lock(&c.lock)
+ }
+
+ if raceenabled {
+ raceacquire(chanbuf(c, c.recvx))
+ racerelease(chanbuf(c, c.recvx))
+ }
+ if ep != nil {
+ memmove(ep, chanbuf(c, c.recvx), uintptr(c.elemsize))
+ }
+ 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)
+ } else {
+ unlock(&c.lock)
+ }
+
+ if t1 > 0 {
+ blockevent(t1-t0, 2)
+ }
+ selected = true
+ received = true
+ return
+}
+
+// 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))
+ }
+ unlock(&c.lock)
+ if ep != nil {
+ memclr(ep, uintptr(c.elemsize))
+ }
+ return true, false
+}
+
+// compiler implements
+//
+// select {
+// case c <- v:
+// ... foo
+// default:
+// ... bar
+// }
+//
+// as
+//
+// if selectnbsend(c, v) {
+// ... foo
+// } else {
+// ... bar
+// }
+//
+func selectnbsend(t *chantype, c *hchan, elem unsafe.Pointer) (selected bool) {
+ return chansend(t, c, elem, false, getcallerpc(unsafe.Pointer(&t)))
+}
+
+// compiler implements
+//
+// select {
+// case v = <-c:
+// ... foo
+// default:
+// ... bar
+// }
+//
+// as
+//
+// if selectnbrecv(&v, c) {
+// ... foo
+// } else {
+// ... bar
+// }
+//
+func selectnbrecv(t *chantype, elem unsafe.Pointer, c *hchan) (selected bool) {
+ selected, _ = chanrecv(t, c, elem, false)
+ return
+}
+
+// compiler implements
+//
+// select {
+// case v, ok = <-c:
+// ... foo
+// default:
+// ... bar
+// }
+//
+// as
+//
+// if c != nil && selectnbrecv2(&v, &ok, c) {
+// ... foo
+// } else {
+// ... bar
+// }
+//
+func selectnbrecv2(t *chantype, elem unsafe.Pointer, received *bool, c *hchan) (selected bool) {
+ // TODO(khr): just return 2 values from this function, now that it is in Go.
+ selected, *received = chanrecv(t, c, elem, false)
+ return
+}
+
+func reflect_chansend(t *chantype, c *hchan, elem unsafe.Pointer, nb bool) (selected bool) {
+ return chansend(t, c, elem, !nb, getcallerpc(unsafe.Pointer(&t)))
+}
+
+func reflect_chanrecv(t *chantype, c *hchan, nb bool, elem unsafe.Pointer) (selected bool, received bool) {
+ return chanrecv(t, c, elem, !nb)
+}
+
+func reflect_chanlen(c *hchan) int {
+ if c == nil {
+ return 0
+ }
+ return int(c.qcount)
+}
+
+func reflect_chancap(c *hchan) int {
+ if c == nil {
+ return 0
+ }
+ return int(c.dataqsiz)
+}
+
+func (q *waitq) enqueue(sgp *sudog) {
+ sgp.next = nil
+ if q.first == nil {
+ q.first = sgp
+ q.last = sgp
+ return
+ }
+ q.last.next = sgp
+ q.last = sgp
+}
+
+func (q *waitq) dequeue() *sudog {
+ for {
+ sgp := q.first
+ if sgp == nil {
+ return nil
+ }
+ q.first = sgp.next
+ sgp.next = nil
+ if q.last == sgp {
+ q.last = nil
+ }
+
+ // 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) {
+ continue
+ }
+ }
+
+ return sgp
+ }
+}
+
+func racesync(c *hchan, sg *sudog) {
+ racerelease(chanbuf(c, 0))
+ raceacquireg(sg.g, chanbuf(c, 0))
+ racereleaseg(sg.g, chanbuf(c, 0))
+ raceacquire(chanbuf(c, 0))
+}
diff --git a/src/pkg/runtime/chan.h b/src/runtime/chan.h
index ce2eb9f4e..c34ff1533 100644
--- a/src/pkg/runtime/chan.h
+++ b/src/runtime/chan.h
@@ -5,45 +5,33 @@
#define MAXALIGN 8
typedef struct WaitQ WaitQ;
-typedef struct SudoG SudoG;
typedef struct Select Select;
typedef struct Scase Scase;
-struct SudoG
-{
- G* g;
- uint32* selectdone;
- SudoG* link;
- int64 releasetime;
- byte* elem; // data element
-};
-
struct WaitQ
{
SudoG* first;
SudoG* last;
};
-// The garbage collector is assuming that Hchan can only contain pointers into the stack
-// and cannot contain pointers into the heap.
struct Hchan
{
uintgo qcount; // total data in the q
uintgo dataqsiz; // size of the circular q
+ byte* buf;
uint16 elemsize;
- uint16 pad; // ensures proper alignment of the buffer that follows Hchan in memory
- bool closed;
+ uint32 closed;
Type* elemtype; // element type
uintgo sendx; // send index
uintgo recvx; // receive index
WaitQ recvq; // list of recv waiters
WaitQ sendq; // list of send waiters
- Lock;
+ Mutex lock;
};
// Buffer follows Hchan immediately in memory.
// chanbuf(c, i) is pointer to the i'th slot in the buffer.
-#define chanbuf(c, i) ((byte*)((c)+1)+(uintptr)(c)->elemsize*(i))
+#define chanbuf(c, i) ((byte*)((c)->buf)+(uintptr)(c)->elemsize*(i))
enum
{
@@ -55,16 +43,21 @@ enum
CaseDefault,
};
+// Known to compiler.
+// Changes here must also be made in src/cmd/gc/select.c's selecttype.
struct Scase
{
- SudoG sg; // must be first member (cast to Scase)
+ void* elem; // data element
Hchan* chan; // chan
- byte* pc; // return pc
+ uintptr pc; // return pc
uint16 kind;
uint16 so; // vararg of selected bool
bool* receivedp; // pointer to received bool (recv2)
+ int64 releasetime;
};
+// Known to compiler.
+// Changes here must also be made in src/cmd/gc/select.c's selecttype.
struct Select
{
uint16 tcase; // total count of scase[]
diff --git a/src/pkg/runtime/chan_test.go b/src/runtime/chan_test.go
index ce4b39627..e689ceaed 100644
--- a/src/pkg/runtime/chan_test.go
+++ b/src/runtime/chan_test.go
@@ -198,6 +198,26 @@ func TestChan(t *testing.T) {
}
}
+func TestNonblockRecvRace(t *testing.T) {
+ n := 10000
+ if testing.Short() {
+ n = 100
+ }
+ for i := 0; i < n; i++ {
+ c := make(chan int, 1)
+ c <- 1
+ go func() {
+ select {
+ case <-c:
+ default:
+ t.Fatal("chan is not ready")
+ }
+ }()
+ close(c)
+ <-c
+ }
+}
+
func TestSelfSelect(t *testing.T) {
// Ensure that send/recv on the same chan in select
// does not crash nor deadlock.
@@ -430,6 +450,67 @@ func TestMultiConsumer(t *testing.T) {
}
}
+func TestShrinkStackDuringBlockedSend(t *testing.T) {
+ // make sure that channel operations still work when we are
+ // blocked on a channel send and we shrink the stack.
+ // NOTE: this test probably won't fail unless stack.c:StackDebug
+ // is set to >= 1.
+ const n = 10
+ c := make(chan int)
+ done := make(chan struct{})
+
+ go func() {
+ for i := 0; i < n; i++ {
+ c <- i
+ // use lots of stack, briefly.
+ stackGrowthRecursive(20)
+ }
+ done <- struct{}{}
+ }()
+
+ for i := 0; i < n; i++ {
+ x := <-c
+ if x != i {
+ t.Errorf("bad channel read: want %d, got %d", i, x)
+ }
+ // Waste some time so sender can finish using lots of stack
+ // and block in channel send.
+ time.Sleep(1 * time.Millisecond)
+ // trigger GC which will shrink the stack of the sender.
+ runtime.GC()
+ }
+ <-done
+}
+
+func TestSelectDuplicateChannel(t *testing.T) {
+ // This test makes sure we can queue a G on
+ // the same channel multiple times.
+ c := make(chan int)
+ d := make(chan int)
+ e := make(chan int)
+
+ // goroutine A
+ go func() {
+ select {
+ case <-c:
+ case <-c:
+ case <-d:
+ }
+ e <- 9
+ }()
+ time.Sleep(time.Millisecond) // make sure goroutine A gets qeueued first on c
+
+ // goroutine B
+ go func() {
+ <-c
+ }()
+ time.Sleep(time.Millisecond) // make sure goroutine B gets queued on c before continuing
+
+ d <- 7 // wake up A, it dequeues itself from c. This operation used to corrupt c.recvq.
+ <-e // A tells us it's done
+ c <- 8 // wake up B. This operation used to fail because c.recvq was corrupted (it tries to wake up an already running G instead of B)
+}
+
func BenchmarkChanNonblocking(b *testing.B) {
myc := make(chan int)
b.RunParallel(func(pb *testing.PB) {
@@ -458,7 +539,35 @@ func BenchmarkSelectUncontended(b *testing.B) {
})
}
-func BenchmarkSelectContended(b *testing.B) {
+func BenchmarkSelectSyncContended(b *testing.B) {
+ myc1 := make(chan int)
+ myc2 := make(chan int)
+ myc3 := make(chan int)
+ done := make(chan int)
+ b.RunParallel(func(pb *testing.PB) {
+ go func() {
+ for {
+ select {
+ case myc1 <- 0:
+ case myc2 <- 0:
+ case myc3 <- 0:
+ case <-done:
+ return
+ }
+ }
+ }()
+ for pb.Next() {
+ select {
+ case <-myc1:
+ case <-myc2:
+ case <-myc3:
+ }
+ }
+ })
+ close(done)
+}
+
+func BenchmarkSelectAsyncContended(b *testing.B) {
procs := runtime.GOMAXPROCS(0)
myc1 := make(chan int, procs)
myc2 := make(chan int, procs)
@@ -476,11 +585,11 @@ func BenchmarkSelectContended(b *testing.B) {
}
func BenchmarkSelectNonblock(b *testing.B) {
+ myc1 := make(chan int)
+ myc2 := make(chan int)
+ myc3 := make(chan int, 1)
+ myc4 := make(chan int, 1)
b.RunParallel(func(pb *testing.PB) {
- myc1 := make(chan int)
- myc2 := make(chan int)
- myc3 := make(chan int, 1)
- myc4 := make(chan int, 1)
for pb.Next() {
select {
case <-myc1:
diff --git a/src/pkg/runtime/closure_test.go b/src/runtime/closure_test.go
index ea65fbd5f..ea65fbd5f 100644
--- a/src/pkg/runtime/closure_test.go
+++ b/src/runtime/closure_test.go
diff --git a/src/pkg/runtime/compiler.go b/src/runtime/compiler.go
index 562a46022..562a46022 100644
--- a/src/pkg/runtime/compiler.go
+++ b/src/runtime/compiler.go
diff --git a/src/runtime/complex.go b/src/runtime/complex.go
new file mode 100644
index 000000000..ec50f8947
--- /dev/null
+++ b/src/runtime/complex.go
@@ -0,0 +1,52 @@
+// 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.
+
+package runtime
+
+func complex128div(n complex128, d complex128) complex128 {
+ // Special cases as in C99.
+ ninf := real(n) == posinf || real(n) == neginf ||
+ imag(n) == posinf || imag(n) == neginf
+ dinf := real(d) == posinf || real(d) == neginf ||
+ imag(d) == posinf || imag(d) == neginf
+
+ nnan := !ninf && (real(n) != real(n) || imag(n) != imag(n))
+ dnan := !dinf && (real(d) != real(d) || imag(d) != imag(d))
+
+ switch {
+ case nnan || dnan:
+ return complex(nan, nan)
+ case ninf && !dinf:
+ return complex(posinf, posinf)
+ case !ninf && dinf:
+ return complex(0, 0)
+ case real(d) == 0 && imag(d) == 0:
+ if real(n) == 0 && imag(n) == 0 {
+ return complex(nan, nan)
+ } else {
+ return complex(posinf, posinf)
+ }
+ default:
+ // Standard complex arithmetic, factored to avoid unnecessary overflow.
+ a := real(d)
+ if a < 0 {
+ a = -a
+ }
+ b := imag(d)
+ if b < 0 {
+ b = -b
+ }
+ if a <= b {
+ ratio := real(d) / imag(d)
+ denom := real(d)*ratio + imag(d)
+ return complex((real(n)*ratio+imag(n))/denom,
+ (imag(n)*ratio-real(n))/denom)
+ } else {
+ ratio := imag(d) / real(d)
+ denom := imag(d)*ratio + real(d)
+ return complex((imag(n)*ratio+real(n))/denom,
+ (imag(n)-real(n)*ratio)/denom)
+ }
+ }
+}
diff --git a/src/pkg/runtime/complex_test.go b/src/runtime/complex_test.go
index f41e6a357..f41e6a357 100644
--- a/src/pkg/runtime/complex_test.go
+++ b/src/runtime/complex_test.go
diff --git a/src/runtime/cpuprof.go b/src/runtime/cpuprof.go
new file mode 100644
index 000000000..8b1c1c632
--- /dev/null
+++ b/src/runtime/cpuprof.go
@@ -0,0 +1,425 @@
+// 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.
+
+// CPU profiling.
+// Based on algorithms and data structures used in
+// http://code.google.com/p/google-perftools/.
+//
+// The main difference between this code and the google-perftools
+// code is that this code is written to allow copying the profile data
+// to an arbitrary io.Writer, while the google-perftools code always
+// writes to an operating system file.
+//
+// The signal handler for the profiling clock tick adds a new stack trace
+// to a hash table tracking counts for recent traces. Most clock ticks
+// hit in the cache. In the event of a cache miss, an entry must be
+// evicted from the hash table, copied to a log that will eventually be
+// written as profile data. The google-perftools code flushed the
+// log itself during the signal handler. This code cannot do that, because
+// the io.Writer might block or need system calls or locks that are not
+// safe to use from within the signal handler. Instead, we split the log
+// into two halves and let the signal handler fill one half while a goroutine
+// is writing out the other half. When the signal handler fills its half, it
+// offers to swap with the goroutine. If the writer is not done with its half,
+// we lose the stack trace for this clock tick (and record that loss).
+// The goroutine interacts with the signal handler by calling getprofile() to
+// get the next log piece to write, implicitly handing back the last log
+// piece it obtained.
+//
+// The state of this dance between the signal handler and the goroutine
+// is encoded in the Profile.handoff field. If handoff == 0, then the goroutine
+// is not using either log half and is waiting (or will soon be waiting) for
+// a new piece by calling notesleep(&p->wait). If the signal handler
+// changes handoff from 0 to non-zero, it must call notewakeup(&p->wait)
+// to wake the goroutine. The value indicates the number of entries in the
+// log half being handed off. The goroutine leaves the non-zero value in
+// place until it has finished processing the log half and then flips the number
+// back to zero. Setting the high bit in handoff means that the profiling is over,
+// and the goroutine is now in charge of flushing the data left in the hash table
+// to the log and returning that data.
+//
+// The handoff field is manipulated using atomic operations.
+// For the most part, the manipulation of handoff is orderly: if handoff == 0
+// then the signal handler owns it and can change it to non-zero.
+// If handoff != 0 then the goroutine owns it and can change it to zero.
+// If that were the end of the story then we would not need to manipulate
+// handoff using atomic operations. The operations are needed, however,
+// in order to let the log closer set the high bit to indicate "EOF" safely
+// in the situation when normally the goroutine "owns" handoff.
+
+package runtime
+
+import "unsafe"
+
+const (
+ numBuckets = 1 << 10
+ logSize = 1 << 17
+ assoc = 4
+ maxCPUProfStack = 64
+)
+
+type cpuprofEntry struct {
+ count uintptr
+ depth uintptr
+ stack [maxCPUProfStack]uintptr
+}
+
+type cpuProfile struct {
+ on bool // profiling is on
+ wait note // goroutine waits here
+ count uintptr // tick count
+ evicts uintptr // eviction count
+ lost uintptr // lost ticks that need to be logged
+
+ // Active recent stack traces.
+ hash [numBuckets]struct {
+ entry [assoc]cpuprofEntry
+ }
+
+ // Log of traces evicted from hash.
+ // Signal handler has filled log[toggle][:nlog].
+ // Goroutine is writing log[1-toggle][:handoff].
+ log [2][logSize / 2]uintptr
+ nlog uintptr
+ toggle int32
+ handoff uint32
+
+ // Writer state.
+ // Writer maintains its own toggle to avoid races
+ // looking at signal handler's toggle.
+ wtoggle uint32
+ wholding bool // holding & need to release a log half
+ flushing bool // flushing hash table - profile is over
+ eodSent bool // special end-of-data record sent; => flushing
+}
+
+var (
+ cpuprofLock mutex
+ cpuprof *cpuProfile
+
+ eod = [3]uintptr{0, 1, 0}
+)
+
+func setcpuprofilerate_m() // proc.c
+
+func setcpuprofilerate(hz int32) {
+ g := getg()
+ g.m.scalararg[0] = uintptr(hz)
+ onM(setcpuprofilerate_m)
+}
+
+// lostProfileData is a no-op function used in profiles
+// to mark the number of profiling stack traces that were
+// discarded due to slow data writers.
+func lostProfileData() {}
+
+// SetCPUProfileRate sets the CPU profiling rate to hz samples per second.
+// If hz <= 0, SetCPUProfileRate turns off profiling.
+// If the profiler is on, the rate cannot be changed without first turning it off.
+//
+// Most clients should use the runtime/pprof package or
+// the testing package's -test.cpuprofile flag instead of calling
+// SetCPUProfileRate directly.
+func SetCPUProfileRate(hz int) {
+ // Clamp hz to something reasonable.
+ if hz < 0 {
+ hz = 0
+ }
+ if hz > 1000000 {
+ hz = 1000000
+ }
+
+ lock(&cpuprofLock)
+ if hz > 0 {
+ if cpuprof == nil {
+ cpuprof = (*cpuProfile)(sysAlloc(unsafe.Sizeof(cpuProfile{}), &memstats.other_sys))
+ if cpuprof == nil {
+ print("runtime: cpu profiling cannot allocate memory\n")
+ unlock(&cpuprofLock)
+ return
+ }
+ }
+ if cpuprof.on || cpuprof.handoff != 0 {
+ print("runtime: cannot set cpu profile rate until previous profile has finished.\n")
+ unlock(&cpuprofLock)
+ return
+ }
+
+ cpuprof.on = true
+ // pprof binary header format.
+ // http://code.google.com/p/google-perftools/source/browse/trunk/src/profiledata.cc#117
+ p := &cpuprof.log[0]
+ p[0] = 0 // count for header
+ p[1] = 3 // depth for header
+ p[2] = 0 // version number
+ p[3] = uintptr(1e6 / hz) // period (microseconds)
+ p[4] = 0
+ cpuprof.nlog = 5
+ cpuprof.toggle = 0
+ cpuprof.wholding = false
+ cpuprof.wtoggle = 0
+ cpuprof.flushing = false
+ cpuprof.eodSent = false
+ noteclear(&cpuprof.wait)
+
+ setcpuprofilerate(int32(hz))
+ } else if cpuprof != nil && cpuprof.on {
+ setcpuprofilerate(0)
+ cpuprof.on = false
+
+ // Now add is not running anymore, and getprofile owns the entire log.
+ // Set the high bit in prof->handoff to tell getprofile.
+ for {
+ n := cpuprof.handoff
+ if n&0x80000000 != 0 {
+ print("runtime: setcpuprofile(off) twice\n")
+ }
+ if cas(&cpuprof.handoff, n, n|0x80000000) {
+ if n == 0 {
+ // we did the transition from 0 -> nonzero so we wake getprofile
+ notewakeup(&cpuprof.wait)
+ }
+ break
+ }
+ }
+ }
+ unlock(&cpuprofLock)
+}
+
+func cpuproftick(pc *uintptr, n int32) {
+ if n > maxCPUProfStack {
+ n = maxCPUProfStack
+ }
+ s := (*[maxCPUProfStack]uintptr)(unsafe.Pointer(pc))[:n]
+ cpuprof.add(s)
+}
+
+// add adds the stack trace to the profile.
+// It is called from signal handlers and other limited environments
+// and cannot allocate memory or acquire locks that might be
+// held at the time of the signal, nor can it use substantial amounts
+// of stack. It is allowed to call evict.
+func (p *cpuProfile) add(pc []uintptr) {
+ // Compute hash.
+ h := uintptr(0)
+ for _, x := range pc {
+ h = h<<8 | (h >> (8 * (unsafe.Sizeof(h) - 1)))
+ h += x*31 + x*7 + x*3
+ }
+ p.count++
+
+ // Add to entry count if already present in table.
+ b := &p.hash[h%numBuckets]
+Assoc:
+ for i := range b.entry {
+ e := &b.entry[i]
+ if e.depth != uintptr(len(pc)) {
+ continue
+ }
+ for j := range pc {
+ if e.stack[j] != pc[j] {
+ continue Assoc
+ }
+ }
+ e.count++
+ return
+ }
+
+ // Evict entry with smallest count.
+ var e *cpuprofEntry
+ for i := range b.entry {
+ if e == nil || b.entry[i].count < e.count {
+ e = &b.entry[i]
+ }
+ }
+ if e.count > 0 {
+ if !p.evict(e) {
+ // Could not evict entry. Record lost stack.
+ p.lost++
+ return
+ }
+ p.evicts++
+ }
+
+ // Reuse the newly evicted entry.
+ e.depth = uintptr(len(pc))
+ e.count = 1
+ copy(e.stack[:], pc)
+}
+
+// evict copies the given entry's data into the log, so that
+// the entry can be reused. evict is called from add, which
+// is called from the profiling signal handler, so it must not
+// allocate memory or block. It is safe to call flushlog.
+// evict returns true if the entry was copied to the log,
+// false if there was no room available.
+func (p *cpuProfile) evict(e *cpuprofEntry) bool {
+ d := e.depth
+ nslot := d + 2
+ log := &p.log[p.toggle]
+ if p.nlog+nslot > uintptr(len(p.log[0])) {
+ if !p.flushlog() {
+ return false
+ }
+ log = &p.log[p.toggle]
+ }
+
+ q := p.nlog
+ log[q] = e.count
+ q++
+ log[q] = d
+ q++
+ copy(log[q:], e.stack[:d])
+ q += d
+ p.nlog = q
+ e.count = 0
+ return true
+}
+
+// flushlog tries to flush the current log and switch to the other one.
+// flushlog is called from evict, called from add, called from the signal handler,
+// 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)) {
+ return false
+ }
+ notewakeup(&p.wait)
+
+ p.toggle = 1 - p.toggle
+ log := &p.log[p.toggle]
+ q := uintptr(0)
+ if p.lost > 0 {
+ lostPC := funcPC(lostProfileData)
+ log[0] = p.lost
+ log[1] = 1
+ log[2] = lostPC
+ q = 3
+ p.lost = 0
+ }
+ p.nlog = q
+ return true
+}
+
+// getprofile blocks until the next block of profiling data is available
+// and returns it as a []byte. It is called from the writing goroutine.
+func (p *cpuProfile) getprofile() []byte {
+ if p == nil {
+ return nil
+ }
+
+ if p.wholding {
+ // Release previous log to signal handling side.
+ // Loop because we are racing against SetCPUProfileRate(0).
+ for {
+ n := p.handoff
+ if n == 0 {
+ print("runtime: phase error during cpu profile handoff\n")
+ return nil
+ }
+ if n&0x80000000 != 0 {
+ p.wtoggle = 1 - p.wtoggle
+ p.wholding = false
+ p.flushing = true
+ goto Flush
+ }
+ if cas(&p.handoff, n, 0) {
+ break
+ }
+ }
+ p.wtoggle = 1 - p.wtoggle
+ p.wholding = false
+ }
+
+ if p.flushing {
+ goto Flush
+ }
+
+ if !p.on && p.handoff == 0 {
+ return nil
+ }
+
+ // Wait for new log.
+ notetsleepg(&p.wait, -1)
+ noteclear(&p.wait)
+
+ switch n := p.handoff; {
+ case n == 0:
+ print("runtime: phase error during cpu profile wait\n")
+ return nil
+ case n == 0x80000000:
+ p.flushing = true
+ goto Flush
+ default:
+ n &^= 0x80000000
+
+ // Return new log to caller.
+ p.wholding = true
+
+ return uintptrBytes(p.log[p.wtoggle][:n])
+ }
+
+ // In flush mode.
+ // Add is no longer being called. We own the log.
+ // Also, p->handoff is non-zero, so flushlog will return false.
+ // Evict the hash table into the log and return it.
+Flush:
+ for i := range p.hash {
+ b := &p.hash[i]
+ for j := range b.entry {
+ e := &b.entry[j]
+ if e.count > 0 && !p.evict(e) {
+ // Filled the log. Stop the loop and return what we've got.
+ break Flush
+ }
+ }
+ }
+
+ // Return pending log data.
+ if p.nlog > 0 {
+ // Note that we're using toggle now, not wtoggle,
+ // because we're working on the log directly.
+ n := p.nlog
+ p.nlog = 0
+ return uintptrBytes(p.log[p.toggle][:n])
+ }
+
+ // Made it through the table without finding anything to log.
+ if !p.eodSent {
+ // We may not have space to append this to the partial log buf,
+ // so we always return a new slice for the end-of-data marker.
+ p.eodSent = true
+ return uintptrBytes(eod[:])
+ }
+
+ // Finally done. Clean up and return nil.
+ p.flushing = false
+ if !cas(&p.handoff, p.handoff, 0) {
+ print("runtime: profile flush racing with something\n")
+ }
+ return nil
+}
+
+func uintptrBytes(p []uintptr) (ret []byte) {
+ pp := (*sliceStruct)(unsafe.Pointer(&p))
+ rp := (*sliceStruct)(unsafe.Pointer(&ret))
+
+ rp.array = pp.array
+ rp.len = pp.len * int(unsafe.Sizeof(p[0]))
+ rp.cap = rp.len
+
+ return
+}
+
+// CPUProfile returns the next chunk of binary CPU profiling stack trace data,
+// blocking until data is available. If profiling is turned off and all the profile
+// data accumulated while it was on has been returned, CPUProfile returns nil.
+// The caller must save the returned data before calling CPUProfile again.
+//
+// Most clients should use the runtime/pprof package or
+// the testing package's -test.cpuprofile flag instead of calling
+// CPUProfile directly.
+func CPUProfile() []byte {
+ return cpuprof.getprofile()
+}
diff --git a/src/pkg/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index 4ff0084c2..972eedc62 100644
--- a/src/pkg/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -8,6 +8,7 @@ package runtime_test
import (
"runtime"
+ "strings"
"testing"
)
@@ -34,6 +35,21 @@ func TestCgoTraceback(t *testing.T) {
}
}
+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)
+ want := "panic: BOOM"
+ if !strings.Contains(got, want) {
+ t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
+ }
+}
+
const cgoSignalDeadlockSource = `
package main
@@ -117,3 +133,64 @@ func main() {
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");
+}
+`
diff --git a/src/pkg/runtime/crash_test.go b/src/runtime/crash_test.go
index b0277f293..211a0476f 100644
--- a/src/pkg/runtime/crash_test.go
+++ b/src/runtime/crash_test.go
@@ -31,9 +31,10 @@ func testEnv(cmd *exec.Cmd) *exec.Cmd {
return cmd
}
-func executeTest(t *testing.T, templ string, data interface{}) string {
- if runtime.GOOS == "nacl" {
- t.Skip("skipping on nacl")
+func executeTest(t *testing.T, templ string, data interface{}, extra ...string) string {
+ switch runtime.GOOS {
+ case "android", "nacl":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
checkStaleRuntime(t)
@@ -60,7 +61,20 @@ func executeTest(t *testing.T, templ string, data interface{}) string {
t.Fatalf("failed to close file: %v", err)
}
- got, _ := testEnv(exec.Command("go", "run", src)).CombinedOutput()
+ for i := 0; i < len(extra); i += 2 {
+ if err := ioutil.WriteFile(filepath.Join(dir, extra[i]), []byte(extra[i+1]), 0666); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ cmd := exec.Command("go", "build", "-o", "a.exe")
+ cmd.Dir = dir
+ out, err := testEnv(cmd).CombinedOutput()
+ if err != nil {
+ t.Fatalf("building source: %v\n%s", err, out)
+ }
+
+ got, _ := testEnv(exec.Command(filepath.Join(dir, "a.exe"))).CombinedOutput()
return string(got)
}
@@ -158,6 +172,22 @@ func TestGoexitCrash(t *testing.T) {
}
}
+func TestGoexitDefer(t *testing.T) {
+ c := make(chan struct{})
+ go func() {
+ defer func() {
+ r := recover()
+ if r != nil {
+ t.Errorf("non-nil recover during Goexit")
+ }
+ c <- struct{}{}
+ }()
+ runtime.Goexit()
+ }()
+ // Note: if the defer fails to run, we will get a deadlock here
+ <-c
+}
+
func TestGoNil(t *testing.T) {
output := executeTest(t, goNilSource, nil)
want := "go of nil func value"
@@ -166,6 +196,22 @@ func TestGoNil(t *testing.T) {
}
}
+func TestMainGoroutineId(t *testing.T) {
+ output := executeTest(t, mainGoroutineIdSource, nil)
+ 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)
+ }
+}
+
+func TestBreakpoint(t *testing.T) {
+ output := executeTest(t, breakpointSource, nil)
+ want := "runtime.Breakpoint()"
+ if !strings.Contains(output, want) {
+ t.Fatalf("output:\n%s\n\nwant output containing: %s", output, want)
+ }
+}
+
const crashSource = `
package main
@@ -364,3 +410,106 @@ func main() {
select{}
}
`
+
+const mainGoroutineIdSource = `
+package main
+func main() {
+ panic("test")
+}
+`
+
+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)
+ 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)
+ 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)
+ 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
+ // 3. call goexit
+ // Goexit should run the #2 defer. Its panic
+ // should be caught by the #1 defer, and execution
+ // should resume in the caller. Like the Goexit
+ // never happened!
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("bad recover")
+ }
+ }()
+ defer func() {
+ panic("hello")
+ }()
+ runtime.Goexit()
+}
diff --git a/src/runtime/debug.go b/src/runtime/debug.go
new file mode 100644
index 000000000..4414dd55d
--- /dev/null
+++ b/src/runtime/debug.go
@@ -0,0 +1,70 @@
+// 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"
+
+// Breakpoint executes a breakpoint trap.
+func Breakpoint()
+
+// 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()
+
+// 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()
+
+// GOMAXPROCS sets the maximum number of CPUs that can be executing
+// simultaneously and returns the previous setting. If n < 1, it does not
+// change the current setting.
+// The number of logical CPUs on the local machine can be queried with NumCPU.
+// This call will go away when the scheduler improves.
+func GOMAXPROCS(n int) int {
+ if n > _MaxGomaxprocs {
+ n = _MaxGomaxprocs
+ }
+ lock(&sched.lock)
+ ret := int(gomaxprocs)
+ unlock(&sched.lock)
+ if n <= 0 || n == ret {
+ return ret
+ }
+
+ semacquire(&worldsema, false)
+ gp := getg()
+ gp.m.gcing = 1
+ onM(stoptheworld)
+
+ // newprocs will be processed by starttheworld
+ newprocs = int32(n)
+
+ gp.m.gcing = 0
+ semrelease(&worldsema)
+ onM(starttheworld)
+ return ret
+}
+
+// NumCPU returns the number of logical CPUs on the local machine.
+func NumCPU() int {
+ return int(ncpu)
+}
+
+// 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 {
+ n += int64(mp.ncgocall)
+ }
+ return n
+}
+
+// NumGoroutine returns the number of goroutines that currently exist.
+func NumGoroutine() int {
+ return int(gcount())
+}
+
+func gcount() int32
diff --git a/src/pkg/runtime/debug/debug.c b/src/runtime/debug/debug.s
index a7292c477..a7292c477 100644
--- a/src/pkg/runtime/debug/debug.c
+++ b/src/runtime/debug/debug.s
diff --git a/src/pkg/runtime/debug/garbage.go b/src/runtime/debug/garbage.go
index edb364387..4a77dcfcd 100644
--- a/src/pkg/runtime/debug/garbage.go
+++ b/src/runtime/debug/garbage.go
@@ -16,17 +16,10 @@ type GCStats struct {
NumGC int64 // number of garbage collections
PauseTotal time.Duration // total pause for all collections
Pause []time.Duration // pause history, most recent first
+ PauseEnd []time.Time // pause end times history, most recent first
PauseQuantiles []time.Duration
}
-// Implemented in package runtime.
-func readGCStats(*[]time.Duration)
-func enableGC(bool) bool
-func setGCPercent(int) int
-func freeOSMemory()
-func setMaxStack(int) int
-func setMaxThreads(int) int
-
// ReadGCStats reads statistics about garbage collection into stats.
// The number of entries in the pause history is system-dependent;
// stats.Pause slice will be reused if large enough, reallocated otherwise.
@@ -38,25 +31,36 @@ func setMaxThreads(int) int
func ReadGCStats(stats *GCStats) {
// Create a buffer with space for at least two copies of the
// pause history tracked by the runtime. One will be returned
- // to the caller and the other will be used as a temporary buffer
- // for computing quantiles.
+ // to the caller and the other will be used as transfer buffer
+ // for end times history and as a temporary buffer for
+ // computing quantiles.
const maxPause = len(((*runtime.MemStats)(nil)).PauseNs)
- if cap(stats.Pause) < 2*maxPause {
- stats.Pause = make([]time.Duration, 2*maxPause)
+ if cap(stats.Pause) < 2*maxPause+3 {
+ stats.Pause = make([]time.Duration, 2*maxPause+3)
}
- // readGCStats fills in the pause history (up to maxPause entries)
- // and then three more: Unix ns time of last GC, number of GC,
- // and total pause time in nanoseconds. Here we depend on the
- // fact that time.Duration's native unit is nanoseconds, so the
- // pauses and the total pause time do not need any conversion.
+ // readGCStats fills in the pause and end times histories (up to
+ // maxPause entries) and then three more: Unix ns time of last GC,
+ // number of GC, and total pause time in nanoseconds. Here we
+ // depend on the fact that time.Duration's native unit is
+ // nanoseconds, so the pauses and the total pause time do not need
+ // any conversion.
readGCStats(&stats.Pause)
n := len(stats.Pause) - 3
stats.LastGC = time.Unix(0, int64(stats.Pause[n]))
stats.NumGC = int64(stats.Pause[n+1])
stats.PauseTotal = stats.Pause[n+2]
+ n /= 2 // buffer holds pauses and end times
stats.Pause = stats.Pause[:n]
+ if cap(stats.PauseEnd) < maxPause {
+ stats.PauseEnd = make([]time.Time, 0, maxPause)
+ }
+ stats.PauseEnd = stats.PauseEnd[:0]
+ for _, ns := range stats.Pause[n : n+n] {
+ stats.PauseEnd = append(stats.PauseEnd, time.Unix(0, int64(ns)))
+ }
+
if len(stats.PauseQuantiles) > 0 {
if n == 0 {
for i := range stats.PauseQuantiles {
@@ -91,9 +95,9 @@ func (x byDuration) Less(i, j int) bool { return x[i] < x[j] }
// at startup, or 100 if the variable is not set.
// A negative percentage disables garbage collection.
func SetGCPercent(percent int) int {
- old := setGCPercent(percent)
+ old := setGCPercent(int32(percent))
runtime.GC()
- return old
+ return int(old)
}
// FreeOSMemory forces a garbage collection followed by an
@@ -145,7 +149,9 @@ func SetMaxThreads(threads int) int {
// that the runtime trigger only a panic, not a crash.
// SetPanicOnFault applies only to the current goroutine.
// It returns the previous setting.
-func SetPanicOnFault(enabled bool) bool
+func SetPanicOnFault(enabled bool) bool {
+ return setPanicOnFault(enabled)
+}
// WriteHeapDump writes a description of the heap and the objects in
// it to the given file descriptor.
diff --git a/src/pkg/runtime/debug/garbage_test.go b/src/runtime/debug/garbage_test.go
index 149bafc6f..54c33bd4f 100644
--- a/src/pkg/runtime/debug/garbage_test.go
+++ b/src/runtime/debug/garbage_test.go
@@ -70,6 +70,19 @@ func TestReadGCStats(t *testing.T) {
t.Errorf("stats.PauseQuantiles[%d]=%d > stats.PauseQuantiles[%d]=%d", i, q[i], i+1, q[i+1])
}
}
+
+ // compare memory stats with gc stats:
+ if len(stats.PauseEnd) != n {
+ t.Fatalf("len(stats.PauseEnd) = %d, want %d", len(stats.PauseEnd), n)
+ }
+ off := (int(mstats.NumGC) + len(mstats.PauseEnd) - 1) % len(mstats.PauseEnd)
+ for i := 0; i < n; i++ {
+ dt := stats.PauseEnd[i]
+ if dt.UnixNano() != int64(mstats.PauseEnd[off]) {
+ t.Errorf("stats.PauseEnd[%d] = %d, want %d", i, dt, mstats.PauseEnd[off])
+ }
+ off = (off + len(mstats.PauseEnd) - 1) % len(mstats.PauseEnd)
+ }
}
var big = make([]byte, 1<<20)
diff --git a/src/pkg/runtime/debug/heapdump_test.go b/src/runtime/debug/heapdump_test.go
index 920190115..920190115 100644
--- a/src/pkg/runtime/debug/heapdump_test.go
+++ b/src/runtime/debug/heapdump_test.go
diff --git a/src/pkg/runtime/debug/stack.go b/src/runtime/debug/stack.go
index c29b0a226..c29b0a226 100644
--- a/src/pkg/runtime/debug/stack.go
+++ b/src/runtime/debug/stack.go
diff --git a/src/pkg/runtime/debug/stack_test.go b/src/runtime/debug/stack_test.go
index bbd662618..28691ee4d 100644
--- a/src/pkg/runtime/debug/stack_test.go
+++ b/src/runtime/debug/stack_test.go
@@ -22,15 +22,15 @@ 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/pkg/runtime/debug/stack_test.go:15 (0x13878)
+ /Users/r/go/src/runtime/debug/stack_test.go:15 (0x13878)
(*T).ptrmethod: return Stack()
- /Users/r/go/src/pkg/runtime/debug/stack_test.go:18 (0x138dd)
+ /Users/r/go/src/runtime/debug/stack_test.go:18 (0x138dd)
T.method: return t.ptrmethod()
- /Users/r/go/src/pkg/runtime/debug/stack_test.go:23 (0x13920)
+ /Users/r/go/src/runtime/debug/stack_test.go:23 (0x13920)
TestStack: b := T(0).method()
- /Users/r/go/src/pkg/testing/testing.go:132 (0x14a7a)
+ /Users/r/go/src/testing/testing.go:132 (0x14a7a)
tRunner: test.F(t)
- /Users/r/go/src/pkg/runtime/proc.c:145 (0xc970)
+ /Users/r/go/src/runtime/proc.c:145 (0xc970)
???: runtime·unlock(&runtime·sched);
*/
func TestStack(t *testing.T) {
@@ -49,10 +49,10 @@ func TestStack(t *testing.T) {
n++
}
}
- frame("src/pkg/runtime/debug/stack_test.go", "\t(*T).ptrmethod: return Stack()")
- frame("src/pkg/runtime/debug/stack_test.go", "\tT.method: return t.ptrmethod()")
- frame("src/pkg/runtime/debug/stack_test.go", "\tTestStack: b := T(0).method()")
- frame("src/pkg/testing/testing.go", "")
+ 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()")
+ frame("src/testing/testing.go", "")
}
func check(t *testing.T, line, has string) {
diff --git a/src/runtime/debug/stubs.go b/src/runtime/debug/stubs.go
new file mode 100644
index 000000000..8fba6cf34
--- /dev/null
+++ b/src/runtime/debug/stubs.go
@@ -0,0 +1,20 @@
+// 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 debug
+
+import (
+ "time"
+)
+
+// Uses assembly to call corresponding runtime-internal functions.
+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 enableGC(bool) bool
+func freeOSMemory()
diff --git a/src/runtime/debug/stubs.s b/src/runtime/debug/stubs.s
new file mode 100644
index 000000000..d56274f2d
--- /dev/null
+++ b/src/runtime/debug/stubs.s
@@ -0,0 +1,21 @@
+// 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
+
+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/pkg/runtime/defs.c b/src/runtime/defs.c
index 1c76198fc..b0a9b20d7 100644
--- a/src/pkg/runtime/defs.c
+++ b/src/runtime/defs.c
@@ -10,5 +10,6 @@
#include "malloc.h"
#include "type.h"
#include "race.h"
-#include "hashmap.h"
#include "chan.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
diff --git a/src/pkg/runtime/defs1_linux.go b/src/runtime/defs1_linux.go
index 451817a67..392cc4ab5 100644
--- a/src/pkg/runtime/defs1_linux.go
+++ b/src/runtime/defs1_linux.go
@@ -31,7 +31,7 @@ type Fpxreg1 C.struct__fpxreg
type Xmmreg1 C.struct__xmmreg
type Fpstate1 C.struct__fpstate
type Fpreg1 C.struct__fpreg
-type Sigaltstack C.struct_sigaltstack
+type SigaltstackT C.struct_sigaltstack
type Mcontext C.mcontext_t
type Ucontext C.ucontext_t
type Sigcontext C.struct_sigcontext
diff --git a/src/pkg/runtime/defs2_linux.go b/src/runtime/defs2_linux.go
index 60ecc69bb..980df9ec3 100644
--- a/src/pkg/runtime/defs2_linux.go
+++ b/src/runtime/defs2_linux.go
@@ -139,7 +139,7 @@ type Timespec C.struct_timespec
type Timeval C.struct_timeval
type Sigaction C.struct_kernel_sigaction
type Siginfo C.siginfo_t
-type Sigaltstack C.struct_sigaltstack
+type SigaltstackT C.struct_sigaltstack
type Sigcontext C.struct_sigcontext
type Ucontext C.struct_ucontext
type Itimerval C.struct_itimerval
diff --git a/src/runtime/defs_android_arm.h b/src/runtime/defs_android_arm.h
new file mode 100644
index 000000000..3611b3a10
--- /dev/null
+++ b/src/runtime/defs_android_arm.h
@@ -0,0 +1,3 @@
+// TODO: Generate using cgo like defs_linux_{386,amd64}.h
+
+#include "defs_linux_arm.h"
diff --git a/src/pkg/runtime/defs_arm_linux.go b/src/runtime/defs_arm_linux.go
index db0a19154..afd6897e3 100644
--- a/src/pkg/runtime/defs_arm_linux.go
+++ b/src/runtime/defs_arm_linux.go
@@ -115,7 +115,7 @@ const (
)
type Timespec C.struct_timespec
-type Sigaltstack C.struct_sigaltstack
+type SigaltstackT C.struct_sigaltstack
type Sigcontext C.struct_sigcontext
type Ucontext C.struct_ucontext
type Timeval C.struct_timeval
diff --git a/src/pkg/runtime/defs_darwin.go b/src/runtime/defs_darwin.go
index 722013ba9..722013ba9 100644
--- a/src/pkg/runtime/defs_darwin.go
+++ b/src/runtime/defs_darwin.go
diff --git a/src/pkg/runtime/defs_darwin_386.h b/src/runtime/defs_darwin_386.h
index 7b210eebf..0e0b4fbf7 100644
--- a/src/pkg/runtime/defs_darwin_386.h
+++ b/src/runtime/defs_darwin_386.h
@@ -124,7 +124,7 @@ typedef struct MachHeader MachHeader;
typedef struct MachNDR MachNDR;
typedef struct MachPort MachPort;
typedef struct StackT StackT;
-typedef struct Sigaction Sigaction;
+typedef struct SigactionT SigactionT;
typedef struct Siginfo Siginfo;
typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
@@ -142,7 +142,7 @@ typedef struct FloatState32 FloatState32;
typedef struct ExceptionState32 ExceptionState32;
typedef struct Mcontext32 Mcontext32;
typedef struct Ucontext Ucontext;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
@@ -182,7 +182,7 @@ struct StackT {
};
typedef byte Sighandler[4];
-struct Sigaction {
+struct SigactionT {
byte __sigaction_u[4];
void *sa_tramp;
uint32 sa_mask;
@@ -379,7 +379,7 @@ struct Ucontext {
Mcontext32 *uc_mcontext;
};
-struct Kevent {
+struct KeventT {
uint32 ident;
int16 filter;
uint16 flags;
diff --git a/src/pkg/runtime/defs_darwin_amd64.h b/src/runtime/defs_darwin_amd64.h
index 2d464a9e5..4bf83c1cb 100644
--- a/src/pkg/runtime/defs_darwin_amd64.h
+++ b/src/runtime/defs_darwin_amd64.h
@@ -124,7 +124,7 @@ typedef struct MachHeader MachHeader;
typedef struct MachNDR MachNDR;
typedef struct MachPort MachPort;
typedef struct StackT StackT;
-typedef struct Sigaction Sigaction;
+typedef struct SigactionT SigactionT;
typedef struct Siginfo Siginfo;
typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
@@ -142,7 +142,7 @@ typedef struct FloatState32 FloatState32;
typedef struct ExceptionState32 ExceptionState32;
typedef struct Mcontext32 Mcontext32;
typedef struct Ucontext Ucontext;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
@@ -183,7 +183,7 @@ struct StackT {
};
typedef byte Sighandler[8];
-struct Sigaction {
+struct SigactionT {
byte __sigaction_u[8];
void *sa_tramp;
uint32 sa_mask;
@@ -382,7 +382,7 @@ struct Ucontext {
Mcontext64 *uc_mcontext;
};
-struct Kevent {
+struct KeventT {
uint64 ident;
int16 filter;
uint16 flags;
diff --git a/src/pkg/runtime/defs_dragonfly.go b/src/runtime/defs_dragonfly.go
index 8ebc3a9e1..555b8f595 100644
--- a/src/pkg/runtime/defs_dragonfly.go
+++ b/src/runtime/defs_dragonfly.go
@@ -110,7 +110,7 @@ const (
type Rtprio C.struct_rtprio
type Lwpparams C.struct_lwp_params
-type Sigaltstack C.struct_sigaltstack
+type SigaltstackT C.struct_sigaltstack
type Sigset C.struct___sigset
type StackT C.stack_t
diff --git a/src/pkg/runtime/defs_dragonfly_386.h b/src/runtime/defs_dragonfly_386.h
index 696dcd887..f86b9c6b9 100644
--- a/src/pkg/runtime/defs_dragonfly_386.h
+++ b/src/runtime/defs_dragonfly_386.h
@@ -85,7 +85,7 @@ enum {
typedef struct Rtprio Rtprio;
typedef struct Lwpparams Lwpparams;
-typedef struct Sigaltstack Sigaltstack;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigset Sigset;
typedef struct StackT StackT;
typedef struct Siginfo Siginfo;
@@ -94,7 +94,7 @@ typedef struct Ucontext Ucontext;
typedef struct Timespec Timespec;
typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
@@ -109,7 +109,7 @@ struct Lwpparams {
int32 *tid1;
int32 *tid2;
};
-struct Sigaltstack {
+struct SigaltstackT {
int8 *ss_sp;
uint32 ss_size;
int32 ss_flags;
@@ -185,7 +185,7 @@ struct Itimerval {
Timeval it_value;
};
-struct Kevent {
+struct KeventT {
uint32 ident;
int16 filter;
uint16 flags;
diff --git a/src/pkg/runtime/defs_dragonfly_amd64.h b/src/runtime/defs_dragonfly_amd64.h
index 74581cc94..671555241 100644
--- a/src/pkg/runtime/defs_dragonfly_amd64.h
+++ b/src/runtime/defs_dragonfly_amd64.h
@@ -85,7 +85,7 @@ enum {
typedef struct Rtprio Rtprio;
typedef struct Lwpparams Lwpparams;
-typedef struct Sigaltstack Sigaltstack;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigset Sigset;
typedef struct StackT StackT;
typedef struct Siginfo Siginfo;
@@ -94,7 +94,7 @@ typedef struct Ucontext Ucontext;
typedef struct Timespec Timespec;
typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
@@ -109,7 +109,7 @@ struct Lwpparams {
int32 *tid1;
int32 *tid2;
};
-struct Sigaltstack {
+struct SigaltstackT {
int8 *ss_sp;
uint64 ss_size;
int32 ss_flags;
@@ -195,7 +195,7 @@ struct Itimerval {
Timeval it_value;
};
-struct Kevent {
+struct KeventT {
uint64 ident;
int16 filter;
uint16 flags;
diff --git a/src/pkg/runtime/defs_freebsd.go b/src/runtime/defs_freebsd.go
index 2832583e0..0253685aa 100644
--- a/src/pkg/runtime/defs_freebsd.go
+++ b/src/runtime/defs_freebsd.go
@@ -117,7 +117,7 @@ const (
type Rtprio C.struct_rtprio
type ThrParam C.struct_thr_param
-type Sigaltstack C.struct_sigaltstack
+type SigaltstackT C.struct_sigaltstack
type Sigset C.struct___sigset
type StackT C.stack_t
diff --git a/src/pkg/runtime/defs_freebsd_386.h b/src/runtime/defs_freebsd_386.h
index fab938526..156dccba4 100644
--- a/src/pkg/runtime/defs_freebsd_386.h
+++ b/src/runtime/defs_freebsd_386.h
@@ -89,7 +89,7 @@ enum {
typedef struct Rtprio Rtprio;
typedef struct ThrParam ThrParam;
-typedef struct Sigaltstack Sigaltstack;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigset Sigset;
typedef struct StackT StackT;
typedef struct Siginfo Siginfo;
@@ -98,7 +98,7 @@ typedef struct Ucontext Ucontext;
typedef struct Timespec Timespec;
typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
@@ -119,7 +119,7 @@ struct ThrParam {
Rtprio *rtp;
void *spare[3];
};
-struct Sigaltstack {
+struct SigaltstackT {
int8 *ss_sp;
uint32 ss_size;
int32 ss_flags;
@@ -200,7 +200,7 @@ struct Itimerval {
Timeval it_value;
};
-struct Kevent {
+struct KeventT {
uint32 ident;
int16 filter;
uint16 flags;
diff --git a/src/pkg/runtime/defs_freebsd_amd64.h b/src/runtime/defs_freebsd_amd64.h
index c1db91803..4ba8956a2 100644
--- a/src/pkg/runtime/defs_freebsd_amd64.h
+++ b/src/runtime/defs_freebsd_amd64.h
@@ -89,7 +89,7 @@ enum {
typedef struct Rtprio Rtprio;
typedef struct ThrParam ThrParam;
-typedef struct Sigaltstack Sigaltstack;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigset Sigset;
typedef struct StackT StackT;
typedef struct Siginfo Siginfo;
@@ -98,7 +98,7 @@ typedef struct Ucontext Ucontext;
typedef struct Timespec Timespec;
typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
@@ -120,7 +120,7 @@ struct ThrParam {
Rtprio *rtp;
void *spare[3];
};
-struct Sigaltstack {
+struct SigaltstackT {
int8 *ss_sp;
uint64 ss_size;
int32 ss_flags;
@@ -211,7 +211,7 @@ struct Itimerval {
Timeval it_value;
};
-struct Kevent {
+struct KeventT {
uint64 ident;
int16 filter;
uint16 flags;
diff --git a/src/pkg/runtime/defs_freebsd_arm.h b/src/runtime/defs_freebsd_arm.h
index 4fc452e45..17deba68d 100644
--- a/src/pkg/runtime/defs_freebsd_arm.h
+++ b/src/runtime/defs_freebsd_arm.h
@@ -89,7 +89,7 @@ enum {
typedef struct Rtprio Rtprio;
typedef struct ThrParam ThrParam;
-typedef struct Sigaltstack Sigaltstack;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigset Sigset;
typedef struct StackT StackT;
typedef struct Siginfo Siginfo;
@@ -98,7 +98,7 @@ typedef struct Ucontext Ucontext;
typedef struct Timespec Timespec;
typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
@@ -119,7 +119,7 @@ struct ThrParam {
Rtprio *rtp;
void *spare[3];
};
-struct Sigaltstack {
+struct SigaltstackT {
uint8 *ss_sp;
uint32 ss_size;
int32 ss_flags;
@@ -173,7 +173,7 @@ struct Itimerval {
Timeval it_value;
};
-struct Kevent {
+struct KeventT {
uint32 ident;
int16 filter;
uint16 flags;
diff --git a/src/pkg/runtime/defs_linux.go b/src/runtime/defs_linux.go
index 2f4e03a01..8657dbb0e 100644
--- a/src/pkg/runtime/defs_linux.go
+++ b/src/runtime/defs_linux.go
@@ -28,6 +28,7 @@ package runtime
#include <asm-generic/errno.h>
#include <asm-generic/poll.h>
#include <linux/eventpoll.h>
+#undef size_t
*/
import "C"
diff --git a/src/pkg/runtime/defs_linux_386.h b/src/runtime/defs_linux_386.h
index 27dae9e82..24a05d862 100644
--- a/src/pkg/runtime/defs_linux_386.h
+++ b/src/runtime/defs_linux_386.h
@@ -95,9 +95,9 @@ typedef struct Xmmreg Xmmreg;
typedef struct Fpstate Fpstate;
typedef struct Timespec Timespec;
typedef struct Timeval Timeval;
-typedef struct Sigaction Sigaction;
+typedef struct SigactionT SigactionT;
typedef struct Siginfo Siginfo;
-typedef struct Sigaltstack Sigaltstack;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigcontext Sigcontext;
typedef struct Ucontext Ucontext;
typedef struct Itimerval Itimerval;
@@ -144,7 +144,7 @@ struct Timeval {
int32 tv_sec;
int32 tv_usec;
};
-struct Sigaction {
+struct SigactionT {
void *k_sa_handler;
uint32 sa_flags;
void *sa_restorer;
@@ -156,7 +156,7 @@ struct Siginfo {
int32 si_code;
byte _sifields[116];
};
-struct Sigaltstack {
+struct SigaltstackT {
byte *ss_sp;
int32 ss_flags;
uint32 ss_size;
@@ -194,7 +194,7 @@ struct Sigcontext {
struct Ucontext {
uint32 uc_flags;
Ucontext *uc_link;
- Sigaltstack uc_stack;
+ SigaltstackT uc_stack;
Sigcontext uc_mcontext;
uint32 uc_sigmask;
};
@@ -204,7 +204,7 @@ struct Itimerval {
};
struct EpollEvent {
uint32 events;
- uint64 data;
+ byte data[8]; // to match amd64
};
diff --git a/src/pkg/runtime/defs_linux_amd64.h b/src/runtime/defs_linux_amd64.h
index 3e87df68a..14616dffe 100644
--- a/src/pkg/runtime/defs_linux_amd64.h
+++ b/src/runtime/defs_linux_amd64.h
@@ -88,7 +88,7 @@ enum {
typedef struct Timespec Timespec;
typedef struct Timeval Timeval;
-typedef struct Sigaction Sigaction;
+typedef struct SigactionT SigactionT;
typedef struct Siginfo Siginfo;
typedef struct Itimerval Itimerval;
typedef struct EpollEvent EpollEvent;
@@ -103,7 +103,7 @@ struct Timeval {
int64 tv_sec;
int64 tv_usec;
};
-struct Sigaction {
+struct SigactionT {
void *sa_handler;
uint64 sa_flags;
void *sa_restorer;
@@ -122,7 +122,7 @@ struct Itimerval {
};
struct EpollEvent {
uint32 events;
- uint64 data;
+ byte data[8]; // unaligned uintptr
};
@@ -144,7 +144,7 @@ typedef struct Fpxreg1 Fpxreg1;
typedef struct Xmmreg1 Xmmreg1;
typedef struct Fpstate1 Fpstate1;
typedef struct Fpreg1 Fpreg1;
-typedef struct Sigaltstack Sigaltstack;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Mcontext Mcontext;
typedef struct Ucontext Ucontext;
typedef struct Sigcontext Sigcontext;
@@ -200,7 +200,7 @@ struct Fpreg1 {
uint16 significand[4];
uint16 exponent;
};
-struct Sigaltstack {
+struct SigaltstackT {
byte *ss_sp;
int32 ss_flags;
byte Pad_cgo_0[4];
@@ -214,7 +214,7 @@ struct Mcontext {
struct Ucontext {
uint64 uc_flags;
Ucontext *uc_link;
- Sigaltstack uc_stack;
+ SigaltstackT uc_stack;
Mcontext uc_mcontext;
Usigset uc_sigmask;
Fpstate __fpregs_mem;
diff --git a/src/pkg/runtime/defs_linux_arm.h b/src/runtime/defs_linux_arm.h
index 92160966e..50b3c919e 100644
--- a/src/pkg/runtime/defs_linux_arm.h
+++ b/src/runtime/defs_linux_arm.h
@@ -16,7 +16,7 @@ enum {
MADV_DONTNEED = 0x4,
SA_RESTART = 0x10000000,
SA_ONSTACK = 0x8000000,
- SA_RESTORER = 0x4000000,
+ SA_RESTORER = 0, // unused on ARM
SA_SIGINFO = 0x4,
SIGHUP = 0x1,
SIGINT = 0x2,
@@ -88,8 +88,8 @@ struct Timespec {
int32 tv_nsec;
};
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
+typedef struct SigaltstackT SigaltstackT;
+struct SigaltstackT {
void *ss_sp;
int32 ss_flags;
uint32 ss_size;
@@ -124,7 +124,7 @@ typedef struct Ucontext Ucontext;
struct Ucontext {
uint32 uc_flags;
Ucontext *uc_link;
- Sigaltstack uc_stack;
+ SigaltstackT uc_stack;
Sigcontext uc_mcontext;
uint32 uc_sigmask;
int32 __unused[31];
@@ -151,8 +151,8 @@ struct Siginfo {
uint8 _sifields[4];
};
-typedef struct Sigaction Sigaction;
-struct Sigaction {
+typedef struct SigactionT SigactionT;
+struct SigactionT {
void *sa_handler;
uint32 sa_flags;
void *sa_restorer;
@@ -163,6 +163,6 @@ typedef struct EpollEvent EpollEvent;
struct EpollEvent {
uint32 events;
uint32 _pad;
- uint64 data;
+ byte data[8]; // to match amd64
};
#pragma pack off
diff --git a/src/pkg/runtime/defs_nacl_386.h b/src/runtime/defs_nacl_386.h
index e8fbb38e1..e8fbb38e1 100644
--- a/src/pkg/runtime/defs_nacl_386.h
+++ b/src/runtime/defs_nacl_386.h
diff --git a/src/pkg/runtime/defs_nacl_amd64p32.h b/src/runtime/defs_nacl_amd64p32.h
index 8d3068bf8..45663d40a 100644
--- a/src/pkg/runtime/defs_nacl_amd64p32.h
+++ b/src/runtime/defs_nacl_amd64p32.h
@@ -79,7 +79,7 @@ struct ExcContext
union {
ExcRegs386 regs;
ExcRegsAmd64 regs64;
- };
+ } regs;
};
struct ExcPortableContext
diff --git a/src/runtime/defs_nacl_arm.h b/src/runtime/defs_nacl_arm.h
new file mode 100644
index 000000000..9ce07ccb2
--- /dev/null
+++ b/src/runtime/defs_nacl_arm.h
@@ -0,0 +1,70 @@
+// 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.
+
+// Created by hand, not machine generated.
+
+enum
+{
+ // These values are referred to in the source code
+ // but really don't matter. Even so, use the standard numbers.
+ SIGSEGV = 11,
+ SIGPROF = 27,
+};
+
+typedef struct Siginfo Siginfo;
+
+// native_client/src/trusted/service_runtime/include/machine/_types.h
+typedef struct Timespec Timespec;
+
+struct Timespec
+{
+ int64 tv_sec;
+ int32 tv_nsec;
+};
+
+// native_client/src/trusted/service_runtime/nacl_exception.h
+// native_client/src/include/nacl/nacl_exception.h
+
+typedef struct ExcContext ExcContext;
+typedef struct ExcPortable ExcPortable;
+typedef struct ExcRegsARM ExcRegsARM;
+
+struct ExcRegsARM
+{
+ uint32 r0;
+ uint32 r1;
+ uint32 r2;
+ uint32 r3;
+ uint32 r4;
+ uint32 r5;
+ uint32 r6;
+ uint32 r7;
+ uint32 r8;
+ uint32 r9; // the value reported here is undefined.
+ uint32 r10;
+ uint32 r11;
+ uint32 r12;
+ uint32 sp; /* r13 */
+ uint32 lr; /* r14 */
+ uint32 pc; /* r15 */
+ uint32 cpsr;
+};
+
+struct ExcContext
+{
+ uint32 size;
+ uint32 portable_context_offset;
+ uint32 portable_context_size;
+ uint32 arch;
+ uint32 regs_size;
+ uint32 reserved[11];
+ ExcRegsARM regs;
+};
+
+struct ExcPortableContext
+{
+ uint32 pc;
+ uint32 sp;
+ uint32 fp;
+};
diff --git a/src/pkg/runtime/defs_netbsd.go b/src/runtime/defs_netbsd.go
index d1c4cbe96..b27949e42 100644
--- a/src/pkg/runtime/defs_netbsd.go
+++ b/src/runtime/defs_netbsd.go
@@ -109,7 +109,7 @@ const (
EVFILT_WRITE = C.EVFILT_WRITE
)
-type Sigaltstack C.struct_sigaltstack
+type SigaltstackT C.struct_sigaltstack
type Sigset C.sigset_t
type Siginfo C.struct__ksiginfo
diff --git a/src/pkg/runtime/defs_netbsd_386.go b/src/runtime/defs_netbsd_386.go
index c26f24607..c26f24607 100644
--- a/src/pkg/runtime/defs_netbsd_386.go
+++ b/src/runtime/defs_netbsd_386.go
diff --git a/src/pkg/runtime/defs_netbsd_386.h b/src/runtime/defs_netbsd_386.h
index 7fd66959f..fd87804f9 100644
--- a/src/pkg/runtime/defs_netbsd_386.h
+++ b/src/runtime/defs_netbsd_386.h
@@ -82,7 +82,7 @@ enum {
EVFILT_WRITE = 0x1,
};
-typedef struct Sigaltstack Sigaltstack;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigset Sigset;
typedef struct Siginfo Siginfo;
typedef struct StackT StackT;
@@ -91,11 +91,11 @@ typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
typedef struct McontextT McontextT;
typedef struct UcontextT UcontextT;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
-struct Sigaltstack {
+struct SigaltstackT {
byte *ss_sp;
uint32 ss_size;
int32 ss_flags;
@@ -143,13 +143,13 @@ struct UcontextT {
int32 __uc_pad[4];
};
-struct Kevent {
+struct KeventT {
uint32 ident;
uint32 filter;
uint32 flags;
uint32 fflags;
int64 data;
- int32 udata;
+ byte *udata;
};
diff --git a/src/pkg/runtime/defs_netbsd_amd64.go b/src/runtime/defs_netbsd_amd64.go
index f18a7b1fe..f18a7b1fe 100644
--- a/src/pkg/runtime/defs_netbsd_amd64.go
+++ b/src/runtime/defs_netbsd_amd64.go
diff --git a/src/pkg/runtime/defs_netbsd_amd64.h b/src/runtime/defs_netbsd_amd64.h
index 972af165b..dac94b113 100644
--- a/src/pkg/runtime/defs_netbsd_amd64.h
+++ b/src/runtime/defs_netbsd_amd64.h
@@ -82,7 +82,7 @@ enum {
EVFILT_WRITE = 0x1,
};
-typedef struct Sigaltstack Sigaltstack;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigset Sigset;
typedef struct Siginfo Siginfo;
typedef struct StackT StackT;
@@ -91,11 +91,11 @@ typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
typedef struct McontextT McontextT;
typedef struct UcontextT UcontextT;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
-struct Sigaltstack {
+struct SigaltstackT {
byte *ss_sp;
uint64 ss_size;
int32 ss_flags;
@@ -147,14 +147,14 @@ struct UcontextT {
McontextT uc_mcontext;
};
-struct Kevent {
+struct KeventT {
uint64 ident;
uint32 filter;
uint32 flags;
uint32 fflags;
byte Pad_cgo_0[4];
int64 data;
- int64 udata;
+ byte *udata;
};
diff --git a/src/pkg/runtime/defs_netbsd_arm.go b/src/runtime/defs_netbsd_arm.go
index cb0dce66b..cb0dce66b 100644
--- a/src/pkg/runtime/defs_netbsd_arm.go
+++ b/src/runtime/defs_netbsd_arm.go
diff --git a/src/pkg/runtime/defs_netbsd_arm.h b/src/runtime/defs_netbsd_arm.h
index c6f5b1c47..70f34af47 100644
--- a/src/pkg/runtime/defs_netbsd_arm.h
+++ b/src/runtime/defs_netbsd_arm.h
@@ -82,7 +82,7 @@ enum {
EVFILT_WRITE = 0x1,
};
-typedef struct Sigaltstack Sigaltstack;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigset Sigset;
typedef struct Siginfo Siginfo;
typedef struct StackT StackT;
@@ -91,11 +91,11 @@ typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
typedef struct McontextT McontextT;
typedef struct UcontextT UcontextT;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
-struct Sigaltstack {
+struct SigaltstackT {
byte *ss_sp;
uint32 ss_size;
int32 ss_flags;
@@ -147,13 +147,13 @@ struct UcontextT {
int32 __uc_pad[2];
};
-struct Kevent {
+struct KeventT {
uint32 ident;
uint32 filter;
uint32 flags;
uint32 fflags;
int64 data;
- int32 udata;
+ byte *udata;
};
diff --git a/src/pkg/runtime/defs_openbsd.go b/src/runtime/defs_openbsd.go
index 4a705796f..39224c988 100644
--- a/src/pkg/runtime/defs_openbsd.go
+++ b/src/runtime/defs_openbsd.go
@@ -104,9 +104,9 @@ const (
EVFILT_WRITE = C.EVFILT_WRITE
)
-type Tfork C.struct___tfork
+type TforkT C.struct___tfork
-type Sigaltstack C.struct_sigaltstack
+type SigaltstackT C.struct_sigaltstack
type Sigcontext C.struct_sigcontext
type Siginfo C.siginfo_t
type Sigset C.sigset_t
@@ -118,4 +118,4 @@ type Timespec C.struct_timespec
type Timeval C.struct_timeval
type Itimerval C.struct_itimerval
-type Kevent C.struct_kevent
+type KeventT C.struct_kevent
diff --git a/src/pkg/runtime/defs_openbsd_386.h b/src/runtime/defs_openbsd_386.h
index b8f993e2b..6b77e0084 100644
--- a/src/pkg/runtime/defs_openbsd_386.h
+++ b/src/runtime/defs_openbsd_386.h
@@ -81,25 +81,25 @@ enum {
EVFILT_WRITE = -0x2,
};
-typedef struct Tfork Tfork;
-typedef struct Sigaltstack Sigaltstack;
+typedef struct TforkT TforkT;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigcontext Sigcontext;
typedef struct Siginfo Siginfo;
typedef struct StackT StackT;
typedef struct Timespec Timespec;
typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
-struct Tfork {
+struct TforkT {
byte *tf_tcb;
int32 *tf_tid;
byte *tf_stack;
};
-struct Sigaltstack {
+struct SigaltstackT {
byte *ss_sp;
uint32 ss_size;
int32 ss_flags;
@@ -155,7 +155,7 @@ struct Itimerval {
Timeval it_value;
};
-struct Kevent {
+struct KeventT {
uint32 ident;
int16 filter;
uint16 flags;
diff --git a/src/pkg/runtime/defs_openbsd_amd64.h b/src/runtime/defs_openbsd_amd64.h
index a1ae2ef65..761e8e47d 100644
--- a/src/pkg/runtime/defs_openbsd_amd64.h
+++ b/src/runtime/defs_openbsd_amd64.h
@@ -81,25 +81,25 @@ enum {
EVFILT_WRITE = -0x2,
};
-typedef struct Tfork Tfork;
-typedef struct Sigaltstack Sigaltstack;
+typedef struct TforkT TforkT;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigcontext Sigcontext;
typedef struct Siginfo Siginfo;
typedef struct StackT StackT;
typedef struct Timespec Timespec;
typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
-typedef struct Kevent Kevent;
+typedef struct KeventT KeventT;
#pragma pack on
-struct Tfork {
+struct TforkT {
byte *tf_tcb;
int32 *tf_tid;
byte *tf_stack;
};
-struct Sigaltstack {
+struct SigaltstackT {
byte *ss_sp;
uint64 ss_size;
int32 ss_flags;
@@ -166,7 +166,7 @@ struct Itimerval {
Timeval it_value;
};
-struct Kevent {
+struct KeventT {
uint64 ident;
int16 filter;
uint16 flags;
diff --git a/src/pkg/runtime/defs_plan9_386.h b/src/runtime/defs_plan9_386.h
index bde299dee..a762b8589 100644
--- a/src/pkg/runtime/defs_plan9_386.h
+++ b/src/runtime/defs_plan9_386.h
@@ -21,9 +21,6 @@ struct Ureg
uint32 pc; /* pc */
uint32 cs; /* old context */
uint32 flags; /* old flags */
- union {
- uint32 usp;
- uint32 sp;
- };
+ uint32 sp;
uint32 ss; /* old stack segment */
};
diff --git a/src/pkg/runtime/defs_plan9_amd64.h b/src/runtime/defs_plan9_amd64.h
index d8fec67eb..20bca479c 100644
--- a/src/pkg/runtime/defs_plan9_amd64.h
+++ b/src/runtime/defs_plan9_amd64.h
@@ -1,4 +1,4 @@
-#define PAGESIZE 0x200000ULL
+#define PAGESIZE 0x1000
typedef struct Ureg Ureg;
diff --git a/src/pkg/runtime/defs_solaris.go b/src/runtime/defs_solaris.go
index 8dcbb08b7..ba44e5fd4 100644
--- a/src/pkg/runtime/defs_solaris.go
+++ b/src/runtime/defs_solaris.go
@@ -133,7 +133,7 @@ const (
type SemT C.sem_t
-type Sigaltstack C.struct_sigaltstack
+type SigaltstackT C.struct_sigaltstack
type Sigset C.sigset_t
type StackT C.stack_t
diff --git a/src/pkg/runtime/defs_solaris_amd64.go b/src/runtime/defs_solaris_amd64.go
index 049317888..049317888 100644
--- a/src/pkg/runtime/defs_solaris_amd64.go
+++ b/src/runtime/defs_solaris_amd64.go
diff --git a/src/pkg/runtime/defs_solaris_amd64.h b/src/runtime/defs_solaris_amd64.h
index 799724fad..cb1cfeadc 100644
--- a/src/pkg/runtime/defs_solaris_amd64.h
+++ b/src/runtime/defs_solaris_amd64.h
@@ -101,11 +101,11 @@ enum {
};
typedef struct SemT SemT;
-typedef struct Sigaltstack Sigaltstack;
+typedef struct SigaltstackT SigaltstackT;
typedef struct Sigset Sigset;
typedef struct StackT StackT;
typedef struct Siginfo Siginfo;
-typedef struct Sigaction Sigaction;
+typedef struct SigactionT SigactionT;
typedef struct Fpregset Fpregset;
typedef struct Mcontext Mcontext;
typedef struct Ucontext Ucontext;
@@ -126,7 +126,7 @@ struct SemT {
uint64 sem_pad2[2];
};
-struct Sigaltstack {
+struct SigaltstackT {
byte *ss_sp;
uint64 ss_size;
int32 ss_flags;
@@ -149,7 +149,7 @@ struct Siginfo {
int32 si_pad;
byte __data[240];
};
-struct Sigaction {
+struct SigactionT {
int32 sa_flags;
byte Pad_cgo_0[4];
byte _funcptr[8];
diff --git a/src/pkg/runtime/defs_windows.go b/src/runtime/defs_windows.go
index 01aea92de..7ce679741 100644
--- a/src/pkg/runtime/defs_windows.go
+++ b/src/runtime/defs_windows.go
@@ -60,6 +60,9 @@ const (
INFINITE = C.INFINITE
WAIT_TIMEOUT = C.WAIT_TIMEOUT
+
+ EXCEPTION_CONTINUE_EXECUTION = C.EXCEPTION_CONTINUE_EXECUTION
+ EXCEPTION_CONTINUE_SEARCH = C.EXCEPTION_CONTINUE_SEARCH
)
type SystemInfo C.SYSTEM_INFO
diff --git a/src/pkg/runtime/defs_windows_386.h b/src/runtime/defs_windows_386.h
index db3629a1d..2317c04f6 100644
--- a/src/pkg/runtime/defs_windows_386.h
+++ b/src/runtime/defs_windows_386.h
@@ -33,6 +33,9 @@ enum {
INFINITE = 0xffffffff,
WAIT_TIMEOUT = 0x102,
+
+ EXCEPTION_CONTINUE_EXECUTION = -0x1,
+ EXCEPTION_CONTINUE_SEARCH = 0x0,
};
typedef struct SystemInfo SystemInfo;
diff --git a/src/pkg/runtime/defs_windows_amd64.h b/src/runtime/defs_windows_amd64.h
index fe26f5a84..7f37a7a8c 100644
--- a/src/pkg/runtime/defs_windows_amd64.h
+++ b/src/runtime/defs_windows_amd64.h
@@ -33,6 +33,9 @@ enum {
INFINITE = 0xffffffff,
WAIT_TIMEOUT = 0x102,
+
+ EXCEPTION_CONTINUE_EXECUTION = -0x1,
+ EXCEPTION_CONTINUE_SEARCH = 0x0,
};
typedef struct SystemInfo SystemInfo;
diff --git a/src/runtime/env_plan9.go b/src/runtime/env_plan9.go
new file mode 100644
index 000000000..e442c3483
--- /dev/null
+++ b/src/runtime/env_plan9.go
@@ -0,0 +1,56 @@
+// 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
+
+import "unsafe"
+
+func getenv(s *byte) *byte {
+ val := gogetenv(gostringnocopy(s))
+ if val == "" {
+ return nil
+ }
+ // Strings found in environment are NUL-terminated.
+ return &bytes(val)[0]
+}
+
+var tracebackbuf [128]byte
+
+func gogetenv(key string) string {
+ var file [128]byte
+ if len(key) > len(file)-6 {
+ return ""
+ }
+
+ copy(file[:], "/env/")
+ copy(file[5:], key)
+
+ fd := open(&file[0], _OREAD, 0)
+ if fd < 0 {
+ return ""
+ }
+ n := seek(fd, 0, 2)
+ if n <= 0 {
+ close(fd)
+ return ""
+ }
+
+ p := make([]byte, n)
+
+ r := pread(fd, unsafe.Pointer(&p[0]), int32(n), 0)
+ close(fd)
+ if r < 0 {
+ return ""
+ }
+
+ if p[r-1] == 0 {
+ r--
+ }
+
+ var s string
+ sp := (*_string)(unsafe.Pointer(&s))
+ sp.str = &p[0]
+ sp.len = int(r)
+ return s
+}
diff --git a/src/runtime/env_posix.go b/src/runtime/env_posix.go
new file mode 100644
index 000000000..dd57872d7
--- /dev/null
+++ b/src/runtime/env_posix.go
@@ -0,0 +1,63 @@
+// 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 nacl netbsd openbsd solaris windows
+
+package runtime
+
+import "unsafe"
+
+func environ() []string
+
+func getenv(s *byte) *byte {
+ val := gogetenv(gostringnocopy(s))
+ if val == "" {
+ return nil
+ }
+ // Strings found in environment are NUL-terminated.
+ return &bytes(val)[0]
+}
+
+func gogetenv(key string) string {
+ env := environ()
+ if env == nil {
+ gothrow("getenv before env init")
+ }
+ for _, s := range environ() {
+ if len(s) > len(key) && s[len(key)] == '=' && s[:len(key)] == key {
+ return s[len(key)+1:]
+ }
+ }
+ return ""
+}
+
+var _cgo_setenv uintptr // pointer to C function
+var _cgo_unsetenv uintptr // pointer to C function
+
+// Update the C environment if cgo is loaded.
+// Called from syscall.Setenv.
+func syscall_setenv_c(k string, v string) {
+ if _cgo_setenv == 0 {
+ return
+ }
+ arg := [2]unsafe.Pointer{cstring(k), cstring(v)}
+ asmcgocall(unsafe.Pointer(_cgo_setenv), unsafe.Pointer(&arg))
+}
+
+// Update the C environment if cgo is loaded.
+// Called from syscall.unsetenv.
+func syscall_unsetenv_c(k string) {
+ if _cgo_unsetenv == 0 {
+ return
+ }
+ arg := [1]unsafe.Pointer{cstring(k)}
+ asmcgocall(unsafe.Pointer(_cgo_unsetenv), unsafe.Pointer(&arg))
+}
+
+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)))
+ return unsafe.Pointer(&p[0])
+}
diff --git a/src/pkg/runtime/error.go b/src/runtime/error.go
index e704ff872..0b40c702b 100644
--- a/src/pkg/runtime/error.go
+++ b/src/runtime/error.go
@@ -4,6 +4,8 @@
package runtime
+import "unsafe"
+
// The Error interface identifies a run time error.
type Error interface {
error
@@ -69,33 +71,14 @@ func (e errorString) Error() string {
return "runtime error: " + string(e)
}
-// For calling from C.
-func newErrorString(s string, ret *interface{}) {
- *ret = errorString(s)
-}
-
-// An errorCString represents a runtime error described by a single C string.
-// Not "type errorCString uintptr" because of http://golang.org/issue/7084.
-type errorCString struct{ cstr uintptr }
-
-func (e errorCString) RuntimeError() {}
-
-func cstringToGo(uintptr) string
-
-func (e errorCString) Error() string {
- return "runtime error: " + cstringToGo(e.cstr)
-}
-
-// For calling from C.
-func newErrorCString(s uintptr, ret *interface{}) {
- *ret = errorCString{s}
-}
-
type stringer interface {
String() string
}
-func typestring(interface{}) string
+func typestring(x interface{}) string {
+ e := (*eface)(unsafe.Pointer(&x))
+ return *e._type._string
+}
// For calling from C.
// Prints an argument passed to panic.
diff --git a/src/pkg/runtime/export_futex_test.go b/src/runtime/export_futex_test.go
index 1477828a7..96281f650 100644
--- a/src/pkg/runtime/export_futex_test.go
+++ b/src/runtime/export_futex_test.go
@@ -6,8 +6,5 @@
package runtime
-func futexsleep(addr *uint32, val uint32, ns int64)
-func futexwakeup(addr *uint32, val uint32)
-
var Futexsleep = futexsleep
var Futexwakeup = futexwakeup
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
new file mode 100644
index 000000000..be352557f
--- /dev/null
+++ b/src/runtime/export_test.go
@@ -0,0 +1,165 @@
+// 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.
+
+// Export guts for testing.
+
+package runtime
+
+import "unsafe"
+
+var Fadd64 = fadd64
+var Fsub64 = fsub64
+var Fmul64 = fmul64
+var Fdiv64 = fdiv64
+var F64to32 = f64to32
+var F32to64 = f32to64
+var Fcmp64 = fcmp64
+var Fintto64 = fintto64
+var F64toint = f64toint
+
+// in asm_*.s
+func stackguard() (sp, limit uintptr)
+
+var Entersyscall = entersyscall
+var Exitsyscall = exitsyscall
+var LockedOSThread = lockedOSThread
+
+type LFNode struct {
+ Next *LFNode
+ Pushcnt uintptr
+}
+
+func lfstackpush_m()
+func lfstackpop_m()
+
+func LFStackPush(head *uint64, node *LFNode) {
+ mp := acquirem()
+ mp.ptrarg[0] = unsafe.Pointer(head)
+ mp.ptrarg[1] = unsafe.Pointer(node)
+ onM(lfstackpush_m)
+ releasem(mp)
+}
+
+func LFStackPop(head *uint64) *LFNode {
+ mp := acquirem()
+ mp.ptrarg[0] = unsafe.Pointer(head)
+ onM(lfstackpop_m)
+ node := (*LFNode)(unsafe.Pointer(mp.ptrarg[0]))
+ mp.ptrarg[0] = nil
+ releasem(mp)
+ return node
+}
+
+type ParFor struct {
+ body *byte
+ done uint32
+ Nthr uint32
+ nthrmax uint32
+ thrseq uint32
+ Cnt uint32
+ Ctx *byte
+ wait bool
+}
+
+func newparfor_m()
+func parforsetup_m()
+func parfordo_m()
+func parforiters_m()
+
+func NewParFor(nthrmax uint32) *ParFor {
+ mp := acquirem()
+ mp.scalararg[0] = uintptr(nthrmax)
+ onM(newparfor_m)
+ desc := (*ParFor)(mp.ptrarg[0])
+ mp.ptrarg[0] = nil
+ releasem(mp)
+ return desc
+}
+
+func ParForSetup(desc *ParFor, nthr, n uint32, ctx *byte, wait bool, body func(*ParFor, uint32)) {
+ mp := acquirem()
+ mp.ptrarg[0] = unsafe.Pointer(desc)
+ mp.ptrarg[1] = unsafe.Pointer(ctx)
+ mp.ptrarg[2] = unsafe.Pointer(funcPC(body)) // TODO(rsc): Should be a scalar.
+ mp.scalararg[0] = uintptr(nthr)
+ mp.scalararg[1] = uintptr(n)
+ mp.scalararg[2] = 0
+ if wait {
+ mp.scalararg[2] = 1
+ }
+ onM(parforsetup_m)
+ releasem(mp)
+}
+
+func ParForDo(desc *ParFor) {
+ mp := acquirem()
+ mp.ptrarg[0] = unsafe.Pointer(desc)
+ onM(parfordo_m)
+ releasem(mp)
+}
+
+func ParForIters(desc *ParFor, tid uint32) (uint32, uint32) {
+ mp := acquirem()
+ mp.ptrarg[0] = unsafe.Pointer(desc)
+ mp.scalararg[0] = uintptr(tid)
+ onM(parforiters_m)
+ begin := uint32(mp.scalararg[0])
+ end := uint32(mp.scalararg[1])
+ releasem(mp)
+ return begin, end
+}
+
+// in mgc0.c
+//go:noescape
+func getgcmask(data unsafe.Pointer, typ *_type, array **byte, len *uint)
+
+func GCMask(x interface{}) (ret []byte) {
+ e := (*eface)(unsafe.Pointer(&x))
+ s := (*slice)(unsafe.Pointer(&ret))
+ onM(func() {
+ getgcmask(e.data, e._type, &s.array, &s.len)
+ s.cap = s.len
+ })
+ return
+}
+
+func testSchedLocalQueue()
+func testSchedLocalQueueSteal()
+func RunSchedLocalQueueTest() {
+ onM(testSchedLocalQueue)
+}
+func RunSchedLocalQueueStealTest() {
+ onM(testSchedLocalQueueSteal)
+}
+
+var HaveGoodHash = haveGoodHash
+var StringHash = stringHash
+var BytesHash = bytesHash
+var Int32Hash = int32Hash
+var Int64Hash = int64Hash
+var EfaceHash = efaceHash
+var IfaceHash = ifaceHash
+var MemclrBytes = memclrBytes
+
+var HashLoad = &hashLoad
+
+// For testing.
+func GogoBytes() int32 {
+ return _RuntimeGogoBytes
+}
+
+// in string.c
+//go:noescape
+func gostringw(w *uint16) string
+
+// entry point for testing
+func GostringW(w []uint16) (s string) {
+ onM(func() {
+ s = gostringw(&w[0])
+ })
+ return
+}
+
+var Gostringnocopy = gostringnocopy
+var Maxstring = &maxstring
diff --git a/src/pkg/runtime/extern.go b/src/runtime/extern.go
index 053dc1014..6cc5df810 100644
--- a/src/pkg/runtime/extern.go
+++ b/src/runtime/extern.go
@@ -39,6 +39,12 @@ a comma-separated list of name=val pairs. Supported names are:
gcdead: setting gcdead=1 causes the garbage collector to clobber all stack slots
that it thinks are dead.
+ invalidptr: defaults to invalidptr=1, causing the garbage collector and stack
+ copier to crash the program if an invalid pointer value (for example, 1)
+ is found in a pointer-typed location. Setting invalidptr=0 disables this check.
+ This should only be used as a temporary workaround to diagnose buggy code.
+ The real fix is to not store integers in pointer-typed locations.
+
scheddetail: setting schedtrace=X and scheddetail=1 causes the scheduler to emit
detailed multiline info every X milliseconds, describing state of the scheduler,
processors, threads and goroutines.
@@ -46,6 +52,8 @@ a comma-separated list of name=val pairs. Supported names are:
schedtrace: setting schedtrace=X causes the scheduler to emit a single line to standard
error every X milliseconds, summarizing the scheduler state.
+ scavenge: scavenge=1 enables debugging mode of heap scavenger.
+
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
@@ -73,116 +81,71 @@ of the run-time system.
*/
package runtime
-// Gosched yields the processor, allowing other goroutines to run. It does not
-// suspend the current goroutine, so execution resumes automatically.
-func Gosched()
-
-// Goexit terminates the goroutine that calls it. No other goroutine is affected.
-// Goexit runs all deferred calls before terminating the goroutine.
-//
-// Calling Goexit from the main goroutine terminates that goroutine
-// without func main returning. Since func main has not returned,
-// the program continues execution of other goroutines.
-// If all other goroutines exit, the program crashes.
-func Goexit()
-
// 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
// meaning of skip differs between Caller and Callers.) The return values report the
// program counter, file name, and line number within the file of the corresponding
// call. The boolean ok is false if it was not possible to recover the information.
-func Caller(skip int) (pc uintptr, file string, line int, ok bool)
+func Caller(skip int) (pc uintptr, file string, line int, ok bool) {
+ // Ask for two PCs: the one we were asked for
+ // and what it called, so that we can see if it
+ // "called" sigpanic.
+ var rpc [2]uintptr
+ if callers(1+skip-1, &rpc[0], 2) < 2 {
+ return
+ }
+ f := findfunc(rpc[1])
+ if f == nil {
+ // TODO(rsc): Probably a bug?
+ // The C version said "have retpc at least"
+ // but actually returned pc=0.
+ ok = true
+ return
+ }
+ pc = rpc[1]
+ xpc := pc
+ g := findfunc(rpc[0])
+ // All architectures turn faults into apparent calls to sigpanic.
+ // If we see a call to sigpanic, we do not back up the PC to find
+ // the line number of the call instruction, because there is no call.
+ if xpc > f.entry && (g == nil || g.entry != funcPC(sigpanic)) {
+ xpc--
+ }
+ line = int(funcline(f, xpc, &file))
+ ok = true
+ return
+}
-// Callers fills the slice pc with the program counters of function invocations
+// Callers fills the slice pc with the return program counters of function invocations
// on the calling goroutine's stack. The argument skip is the number of stack frames
// to skip before recording in pc, with 0 identifying the frame for Callers itself and
// 1 identifying the caller of Callers.
// It returns the number of entries written to pc.
-func Callers(skip int, pc []uintptr) int
-
-type Func struct {
- opaque struct{} // unexported field to disallow conversions
-}
-
-// FuncForPC returns a *Func describing the function that contains the
-// given program counter address, or else nil.
-func FuncForPC(pc uintptr) *Func
-
-// Name returns the name of the function.
-func (f *Func) Name() string {
- return funcname_go(f)
-}
-
-// Entry returns the entry address of the function.
-func (f *Func) Entry() uintptr {
- return funcentry_go(f)
-}
-
-// FileLine returns the file name and line number of the
-// source code corresponding to the program counter pc.
-// The result will not be accurate if pc is not a program
-// counter within f.
-func (f *Func) FileLine(pc uintptr) (file string, line int) {
- return funcline_go(f, pc)
-}
-
-// implemented in symtab.c
-func funcline_go(*Func, uintptr) (string, int)
-func funcname_go(*Func) string
-func funcentry_go(*Func) uintptr
-
-// SetFinalizer sets the finalizer associated with x to f.
-// When the garbage collector finds an unreachable block
-// with an associated finalizer, it clears the association and runs
-// f(x) in a separate goroutine. This makes x reachable again, but
-// now without an associated finalizer. Assuming that SetFinalizer
-// is not called again, the next time the garbage collector sees
-// that x is unreachable, it will free x.
-//
-// SetFinalizer(x, nil) clears any finalizer associated with x.
-//
-// The argument x must be a pointer to an object allocated by
-// calling new or by taking the address of a composite literal.
-// The argument f must be a function that takes a single argument
-// to which x's type can be assigned, and can have arbitrary ignored return
-// values. If either of these is not true, SetFinalizer aborts the
-// program.
//
-// Finalizers are run in dependency order: if A points at B, both have
-// finalizers, and they are otherwise unreachable, only the finalizer
-// for A runs; once A is freed, the finalizer for B can run.
-// If a cyclic structure includes a block with a finalizer, that
-// cycle is not guaranteed to be garbage collected and the finalizer
-// is not guaranteed to run, because there is no ordering that
-// respects the dependencies.
-//
-// The finalizer for x is scheduled to run at some arbitrary time after
-// x becomes unreachable.
-// There is no guarantee that finalizers will run before a program exits,
-// so typically they are useful only for releasing non-memory resources
-// associated with an object during a long-running program.
-// For example, an os.File object could use a finalizer to close the
-// associated operating system file descriptor when a program discards
-// an os.File without calling Close, but it would be a mistake
-// to depend on a finalizer to flush an in-memory I/O buffer such as a
-// bufio.Writer, because the buffer would not be flushed at program exit.
-//
-// It is not guaranteed that a finalizer will run if the size of *x is
-// zero bytes.
-//
-// A single goroutine runs all finalizers for a program, sequentially.
-// If a finalizer must run for a long time, it should do so by starting
-// a new goroutine.
-func SetFinalizer(x, f interface{})
-
-func getgoroot() string
+// Note that since each slice entry pc[i] is a return program counter,
+// looking up the file and line for pc[i] (for example, using (*Func).FileLine)
+// will return the file and line number of the instruction immediately
+// following the call.
+// To look up the file and line number of the call itself, use pc[i]-1.
+// As an exception to this rule, if pc[i-1] corresponds to the function
+// runtime.sigpanic, then pc[i] is the program counter of a faulting
+// instruction and should be used without any subtraction.
+func Callers(skip int, pc []uintptr) int {
+ // runtime.callers uses pc.array==nil as a signal
+ // to print a stack trace. Pick off 0-length pc here
+ // so that we don't let a nil pc slice get to it.
+ if len(pc) == 0 {
+ return 0
+ }
+ return callers(skip, &pc[0], len(pc))
+}
// GOROOT returns the root of the Go tree.
// It uses the GOROOT environment variable, if set,
// or else the root used during the Go build.
func GOROOT() string {
- s := getgoroot()
+ s := gogetenv("GOROOT")
if s != "" {
return s
}
diff --git a/src/pkg/runtime/float.c b/src/runtime/float.c
index 42082e434..42082e434 100644
--- a/src/pkg/runtime/float.c
+++ b/src/runtime/float.c
diff --git a/src/runtime/funcdata.h b/src/runtime/funcdata.h
new file mode 100644
index 000000000..d6c14fcb4
--- /dev/null
+++ b/src/runtime/funcdata.h
@@ -0,0 +1,60 @@
+// 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.
+
+// This file defines the IDs for PCDATA and FUNCDATA instructions
+// in Go binaries. It is included by both C and assembly, so it must
+// be written using #defines. It is included by the runtime package
+// as well as the compilers.
+//
+// symtab.go also contains a copy of these constants.
+
+#define PCDATA_StackMapIndex 0
+
+#define FUNCDATA_ArgsPointerMaps 0 /* garbage collector blocks */
+#define FUNCDATA_LocalsPointerMaps 1
+#define FUNCDATA_DeadValueMaps 2
+
+// Pseudo-assembly statements.
+
+// GO_ARGS, GO_RESULTS_INITIALIZED, and NO_LOCAL_POINTERS are macros
+// that communicate to the runtime information about the location and liveness
+// of pointers in an assembly function's arguments, results, and stack frame.
+// This communication is only required in assembly functions that make calls
+// to other functions that might be preempted or grow the stack.
+// NOSPLIT functions that make no calls do not need to use these macros.
+
+// GO_ARGS indicates that the Go prototype for this assembly function
+// defines the pointer map for the function's arguments.
+// GO_ARGS should be the first instruction in a function that uses it.
+// It can be omitted if there are no arguments at all.
+// GO_ARGS is inserted implicitly by the linker for any function
+// that also has a Go prototype and therefore is usually not necessary
+// to write explicitly.
+#define GO_ARGS FUNCDATA $FUNCDATA_ArgsPointerMaps, go_args_stackmap(SB)
+
+// GO_RESULTS_INITIALIZED indicates that the assembly function
+// has initialized the stack space for its results and that those results
+// should be considered live for the remainder of the function.
+#define GO_RESULTS_INITIALIZED FUNCDATA PCDATA $PCDATA_StackMapIndex, 1
+
+// NO_LOCAL_POINTERS indicates that the assembly function stores
+// no pointers to heap objects in its local stack variables.
+#define NO_LOCAL_POINTERS FUNCDATA $FUNCDATA_LocalsPointerMaps, runtime·no_pointers_stackmap(SB)
+
+// ArgsSizeUnknown is set in Func.argsize to mark all functions
+// whose argument size is unknown (C vararg functions, and
+// assembly code without an explicit specification).
+// This value is generated by the compiler, assembler, or linker.
+#define ArgsSizeUnknown 0x80000000
+
+/*c2go
+enum {
+ PCDATA_ArgSize = 0,
+ PCDATA_StackMapIndex = 1,
+ FUNCDATA_ArgsPointerMaps = 0,
+ FUNCDATA_LocalsPointerMaps = 1,
+ FUNCDATA_DeadValueMaps = 2,
+ ArgsSizeUnknown = 0x80000000,
+};
+*/
diff --git a/src/pkg/runtime/futex_test.go b/src/runtime/futex_test.go
index f57fc52b8..f57fc52b8 100644
--- a/src/pkg/runtime/futex_test.go
+++ b/src/runtime/futex_test.go
diff --git a/src/pkg/runtime/gc_test.go b/src/runtime/gc_test.go
index 58717ecf7..6abec4cca 100644
--- a/src/pkg/runtime/gc_test.go
+++ b/src/runtime/gc_test.go
@@ -10,6 +10,7 @@ import (
"runtime/debug"
"testing"
"time"
+ "unsafe"
)
func TestGcSys(t *testing.T) {
@@ -163,6 +164,37 @@ func TestGcLastTime(t *testing.T) {
if t0 > last || last > t1 {
t.Fatalf("bad last GC time: got %v, want [%v, %v]", last, t0, t1)
}
+ pause := ms.PauseNs[(ms.NumGC+255)%256]
+ // Due to timer granularity, pause can actually be 0 on windows
+ // or on virtualized environments.
+ if pause == 0 {
+ t.Logf("last GC pause was 0")
+ } else if pause > 10e9 {
+ t.Logf("bad last GC pause: got %v, want [0, 10e9]", pause)
+ }
+}
+
+var hugeSink interface{}
+
+func TestHugeGCInfo(t *testing.T) {
+ // The test ensures that compiler can chew these huge types even on weakest machines.
+ // The types are not allocated at runtime.
+ if hugeSink != nil {
+ // 400MB on 32 bots, 4TB on 64-bits.
+ const n = (400 << 20) + (unsafe.Sizeof(uintptr(0))-4)<<40
+ hugeSink = new([n]*byte)
+ hugeSink = new([n]uintptr)
+ hugeSink = new(struct {
+ x float64
+ y [n]*byte
+ z []string
+ })
+ hugeSink = new(struct {
+ x float64
+ y [n]uintptr
+ z []string
+ })
+ }
}
func BenchmarkSetTypeNoPtr1(b *testing.B) {
@@ -234,3 +266,27 @@ func BenchmarkAllocation(b *testing.B) {
<-result
}
}
+
+func TestPrintGC(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping in short mode")
+ }
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+ done := make(chan bool)
+ go func() {
+ for {
+ select {
+ case <-done:
+ return
+ default:
+ runtime.GC()
+ }
+ }
+ }()
+ for i := 0; i < 1e4; i++ {
+ func() {
+ defer print("")
+ }()
+ }
+ close(done)
+}
diff --git a/src/runtime/gcinfo_test.go b/src/runtime/gcinfo_test.go
new file mode 100644
index 000000000..88f6703f9
--- /dev/null
+++ b/src/runtime/gcinfo_test.go
@@ -0,0 +1,193 @@
+// 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_test
+
+import (
+ "bytes"
+ "runtime"
+ "testing"
+)
+
+// TestGCInfo tests that various objects in heap, data and bss receive correct GC pointer type info.
+func TestGCInfo(t *testing.T) {
+ verifyGCInfo(t, "bss ScalarPtr", &bssScalarPtr, nonStackInfo(infoScalarPtr))
+ verifyGCInfo(t, "bss PtrScalar", &bssPtrScalar, nonStackInfo(infoPtrScalar))
+ verifyGCInfo(t, "bss BigStruct", &bssBigStruct, nonStackInfo(infoBigStruct()))
+ verifyGCInfo(t, "bss string", &bssString, nonStackInfo(infoString))
+ verifyGCInfo(t, "bss slice", &bssSlice, nonStackInfo(infoSlice))
+ verifyGCInfo(t, "bss eface", &bssEface, nonStackInfo(infoEface))
+ verifyGCInfo(t, "bss iface", &bssIface, nonStackInfo(infoIface))
+
+ verifyGCInfo(t, "data ScalarPtr", &dataScalarPtr, nonStackInfo(infoScalarPtr))
+ verifyGCInfo(t, "data PtrScalar", &dataPtrScalar, nonStackInfo(infoPtrScalar))
+ verifyGCInfo(t, "data BigStruct", &dataBigStruct, nonStackInfo(infoBigStruct()))
+ verifyGCInfo(t, "data string", &dataString, nonStackInfo(infoString))
+ verifyGCInfo(t, "data slice", &dataSlice, nonStackInfo(infoSlice))
+ verifyGCInfo(t, "data eface", &dataEface, nonStackInfo(infoEface))
+ verifyGCInfo(t, "data iface", &dataIface, nonStackInfo(infoIface))
+
+ verifyGCInfo(t, "stack ScalarPtr", new(ScalarPtr), infoScalarPtr)
+ verifyGCInfo(t, "stack PtrScalar", new(PtrScalar), infoPtrScalar)
+ verifyGCInfo(t, "stack BigStruct", new(BigStruct), infoBigStruct())
+ verifyGCInfo(t, "stack string", new(string), infoString)
+ verifyGCInfo(t, "stack slice", new([]string), infoSlice)
+ verifyGCInfo(t, "stack eface", new(interface{}), infoEface)
+ verifyGCInfo(t, "stack iface", new(Iface), infoIface)
+
+ for i := 0; i < 10; i++ {
+ verifyGCInfo(t, "heap ScalarPtr", escape(new(ScalarPtr)), nonStackInfo(infoScalarPtr))
+ verifyGCInfo(t, "heap PtrScalar", escape(new(PtrScalar)), nonStackInfo(infoPtrScalar))
+ verifyGCInfo(t, "heap BigStruct", escape(new(BigStruct)), nonStackInfo(infoBigStruct()))
+ verifyGCInfo(t, "heap string", escape(new(string)), nonStackInfo(infoString))
+ verifyGCInfo(t, "heap eface", escape(new(interface{})), nonStackInfo(infoEface))
+ verifyGCInfo(t, "heap iface", escape(new(Iface)), nonStackInfo(infoIface))
+ }
+
+}
+
+func verifyGCInfo(t *testing.T, name string, p interface{}, mask0 []byte) {
+ mask := runtime.GCMask(p)
+ if len(mask) > len(mask0) {
+ mask0 = append(mask0, BitsDead)
+ mask = mask[:len(mask0)]
+ }
+ if bytes.Compare(mask, mask0) != 0 {
+ t.Errorf("bad GC program for %v:\nwant %+v\ngot %+v", name, mask0, mask)
+ return
+ }
+}
+
+func nonStackInfo(mask []byte) []byte {
+ // BitsDead is replaced with BitsScalar everywhere except stacks.
+ mask1 := make([]byte, len(mask))
+ mw := false
+ for i, v := range mask {
+ if !mw && v == BitsDead {
+ v = BitsScalar
+ }
+ mw = !mw && v == BitsMultiWord
+ mask1[i] = v
+ }
+ return mask1
+}
+
+var gcinfoSink interface{}
+
+func escape(p interface{}) interface{} {
+ gcinfoSink = p
+ return p
+}
+
+const (
+ BitsDead = iota
+ BitsScalar
+ BitsPointer
+ BitsMultiWord
+)
+
+const (
+ BitsString = iota // unused
+ BitsSlice // unused
+ BitsIface
+ BitsEface
+)
+
+type ScalarPtr struct {
+ q int
+ w *int
+ e int
+ r *int
+ t int
+ y *int
+}
+
+var infoScalarPtr = []byte{BitsScalar, BitsPointer, BitsScalar, BitsPointer, BitsScalar, BitsPointer}
+
+type PtrScalar struct {
+ q *int
+ w int
+ e *int
+ r int
+ t *int
+ y int
+}
+
+var infoPtrScalar = []byte{BitsPointer, BitsScalar, BitsPointer, BitsScalar, BitsPointer, BitsScalar}
+
+type BigStruct struct {
+ q *int
+ w byte
+ e [17]byte
+ r []byte
+ t int
+ y uint16
+ u uint64
+ i string
+}
+
+func infoBigStruct() []byte {
+ switch runtime.GOARCH {
+ case "386", "arm":
+ return []byte{
+ BitsPointer, // q *int
+ BitsScalar, BitsScalar, BitsScalar, BitsScalar, BitsScalar, // w byte; e [17]byte
+ BitsPointer, BitsDead, BitsDead, // r []byte
+ BitsScalar, BitsScalar, BitsScalar, BitsScalar, // t int; y uint16; u uint64
+ BitsPointer, BitsDead, // i string
+ }
+ case "amd64":
+ return []byte{
+ BitsPointer, // q *int
+ BitsScalar, BitsScalar, BitsScalar, // w byte; e [17]byte
+ BitsPointer, BitsDead, BitsDead, // r []byte
+ BitsScalar, BitsScalar, BitsScalar, // t int; y uint16; u uint64
+ BitsPointer, BitsDead, // i string
+ }
+ case "amd64p32":
+ return []byte{
+ BitsPointer, // q *int
+ BitsScalar, BitsScalar, BitsScalar, BitsScalar, BitsScalar, // w byte; e [17]byte
+ BitsPointer, BitsDead, BitsDead, // r []byte
+ BitsScalar, BitsScalar, BitsDead, BitsScalar, BitsScalar, // t int; y uint16; u uint64
+ BitsPointer, BitsDead, // i string
+ }
+ default:
+ panic("unknown arch")
+ }
+}
+
+type Iface interface {
+ f()
+}
+
+type IfaceImpl int
+
+func (IfaceImpl) f() {
+}
+
+var (
+ // BSS
+ bssScalarPtr ScalarPtr
+ bssPtrScalar PtrScalar
+ bssBigStruct BigStruct
+ bssString string
+ bssSlice []string
+ bssEface interface{}
+ bssIface Iface
+
+ // DATA
+ dataScalarPtr = ScalarPtr{q: 1}
+ dataPtrScalar = PtrScalar{w: 1}
+ dataBigStruct = BigStruct{w: 1}
+ dataString = "foo"
+ dataSlice = []string{"foo"}
+ dataEface interface{} = 42
+ dataIface Iface = IfaceImpl(42)
+
+ infoString = []byte{BitsPointer, BitsDead}
+ infoSlice = []byte{BitsPointer, BitsDead, BitsDead}
+ infoEface = []byte{BitsMultiWord, BitsEface}
+ infoIface = []byte{BitsMultiWord, BitsIface}
+)
diff --git a/src/pkg/runtime/hash_test.go b/src/runtime/hash_test.go
index 1c11e0538..41fff98eb 100644
--- a/src/pkg/runtime/hash_test.go
+++ b/src/runtime/hash_test.go
@@ -344,6 +344,64 @@ func (k *Int64Key) name() string {
return "int64"
}
+type EfaceKey struct {
+ i interface{}
+}
+
+func (k *EfaceKey) clear() {
+ k.i = nil
+}
+func (k *EfaceKey) random(r *rand.Rand) {
+ k.i = uint64(r.Int63())
+}
+func (k *EfaceKey) bits() int {
+ // use 64 bits. This tests inlined interfaces
+ // on 64-bit targets and indirect interfaces on
+ // 32-bit targets.
+ return 64
+}
+func (k *EfaceKey) flipBit(i int) {
+ k.i = k.i.(uint64) ^ uint64(1)<<uint(i)
+}
+func (k *EfaceKey) hash() uintptr {
+ return EfaceHash(k.i, 0)
+}
+func (k *EfaceKey) name() string {
+ return "Eface"
+}
+
+type IfaceKey struct {
+ i interface {
+ F()
+ }
+}
+type fInter uint64
+
+func (x fInter) F() {
+}
+
+func (k *IfaceKey) clear() {
+ k.i = nil
+}
+func (k *IfaceKey) random(r *rand.Rand) {
+ k.i = fInter(r.Int63())
+}
+func (k *IfaceKey) bits() int {
+ // use 64 bits. This tests inlined interfaces
+ // on 64-bit targets and indirect interfaces on
+ // 32-bit targets.
+ return 64
+}
+func (k *IfaceKey) flipBit(i int) {
+ k.i = k.i.(fInter) ^ fInter(1)<<uint(i)
+}
+func (k *IfaceKey) hash() uintptr {
+ return IfaceHash(k.i, 0)
+}
+func (k *IfaceKey) name() string {
+ return "Iface"
+}
+
// Flipping a single bit of a key should flip each output bit with 50% probability.
func TestSmhasherAvalanche(t *testing.T) {
if !HaveGoodHash() {
@@ -360,6 +418,8 @@ func TestSmhasherAvalanche(t *testing.T) {
avalancheTest1(t, &BytesKey{make([]byte, 200)})
avalancheTest1(t, &Int32Key{})
avalancheTest1(t, &Int64Key{})
+ avalancheTest1(t, &EfaceKey{})
+ avalancheTest1(t, &IfaceKey{})
}
func avalancheTest1(t *testing.T, k Key) {
const REP = 100000
diff --git a/src/runtime/hashmap.go b/src/runtime/hashmap.go
new file mode 100644
index 000000000..b4e624423
--- /dev/null
+++ b/src/runtime/hashmap.go
@@ -0,0 +1,953 @@
+// 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
+
+// This file contains the implementation of Go's map type.
+//
+// A map is just a hash table. The data is arranged
+// into an array of buckets. Each bucket contains up to
+// 8 key/value pairs. The low-order bits of the hash are
+// used to select a bucket. Each bucket contains a few
+// high-order bits of each hash to distinguish the entries
+// within a single bucket.
+//
+// If more than 8 keys hash to a bucket, we chain on
+// extra buckets.
+//
+// When the hashtable grows, we allocate a new array
+// of buckets twice as big. Buckets are incrementally
+// copied from the old bucket array to the new bucket array.
+//
+// Map iterators walk through the array of buckets and
+// return the keys in walk order (bucket #, then overflow
+// chain order, then bucket index). To maintain iteration
+// semantics, we never move keys within their bucket (if
+// we did, keys might be returned 0 or 2 times). When
+// growing the table, iterators remain iterating through the
+// old table and must check the new table if the bucket
+// they are iterating through has been moved ("evacuated")
+// to the new table.
+
+// Picking loadFactor: too large and we have lots of overflow
+// buckets, too small and we waste a lot of space. I wrote
+// a simple program to check some stats for different loads:
+// (64-bit, 8 byte keys and values)
+// loadFactor %overflow bytes/entry hitprobe missprobe
+// 4.00 2.13 20.77 3.00 4.00
+// 4.50 4.05 17.30 3.25 4.50
+// 5.00 6.85 14.77 3.50 5.00
+// 5.50 10.55 12.94 3.75 5.50
+// 6.00 15.27 11.67 4.00 6.00
+// 6.50 20.90 10.79 4.25 6.50
+// 7.00 27.14 10.15 4.50 7.00
+// 7.50 34.03 9.73 4.75 7.50
+// 8.00 41.10 9.40 5.00 8.00
+//
+// %overflow = percentage of buckets which have an overflow bucket
+// bytes/entry = overhead bytes used per key/value pair
+// hitprobe = # of entries to check when looking up a present key
+// missprobe = # of entries to check when looking up an absent key
+//
+// Keep in mind this data is for maximally loaded tables, i.e. just
+// before the table grows. Typical tables will be somewhat less loaded.
+
+import (
+ "unsafe"
+)
+
+const (
+ // Maximum number of key/value pairs a bucket can hold.
+ bucketCntBits = 3
+ bucketCnt = 1 << bucketCntBits
+
+ // Maximum average load of a bucket that triggers growth.
+ loadFactor = 6.5
+
+ // Maximum key or value size to keep inline (instead of mallocing per element).
+ // Must fit in a uint8.
+ // Fast versions cannot handle big values - the cutoff size for
+ // fast versions in ../../cmd/gc/walk.c must be at most this value.
+ maxKeySize = 128
+ maxValueSize = 128
+
+ // data offset should be the size of the bmap struct, but needs to be
+ // aligned correctly. For amd64p32 this means 64-bit alignment
+ // even though pointers are 32 bit.
+ dataOffset = unsafe.Offsetof(struct {
+ b bmap
+ v int64
+ }{}.v)
+
+ // Possible tophash values. We reserve a few possibilities for special marks.
+ // Each bucket (including its overflow buckets, if any) will have either all or none of its
+ // entries in the evacuated* states (except during the evacuate() method, which only happens
+ // during map writes and thus no one else can observe the map during that time).
+ empty = 0 // cell is empty
+ evacuatedEmpty = 1 // cell is empty, bucket is evacuated.
+ evacuatedX = 2 // key/value is valid. Entry has been evacuated to first half of larger table.
+ evacuatedY = 3 // same as above, but evacuated to second half of larger table.
+ minTopHash = 4 // minimum tophash for a normal filled cell.
+
+ // flags
+ iterator = 1 // there may be an iterator using buckets
+ oldIterator = 2 // there may be an iterator using oldbuckets
+
+ // sentinel bucket ID for iterator checks
+ noCheck = 1<<(8*ptrSize) - 1
+
+ // trigger a garbage collection at every alloc called from this code
+ checkgc = false
+)
+
+// A header for a Go map.
+type hmap struct {
+ // Note: the format of the Hmap is encoded in ../../cmd/gc/reflect.c and
+ // ../reflect/type.go. Don't change this structure without also changing that code!
+ count int // # live cells == size of map. Must be first (used by len() builtin)
+ flags uint32
+ hash0 uint32 // hash seed
+ B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
+
+ buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
+ oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
+ nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
+}
+
+// A bucket for a Go map.
+type bmap struct {
+ tophash [bucketCnt]uint8
+ overflow *bmap
+ // Followed by bucketCnt keys and then bucketCnt values.
+ // NOTE: packing all the keys together and then all the values together makes the
+ // code a bit more complicated than alternating key/value/key/value/... but it allows
+ // us to eliminate padding which would be needed for, e.g., map[int64]int8.
+}
+
+// A hash iteration structure.
+// If you modify hiter, also change cmd/gc/reflect.c to indicate
+// the layout of this structure.
+type hiter struct {
+ key unsafe.Pointer // Must be in first position. Write nil to indicate iteration end (see cmd/gc/range.c).
+ value unsafe.Pointer // Must be in second position (see cmd/gc/range.c).
+ t *maptype
+ h *hmap
+ buckets unsafe.Pointer // bucket ptr at hash_iter initialization time
+ bptr *bmap // current bucket
+ startBucket uintptr // bucket iteration started at
+ offset uint8 // intra-bucket offset to start from during iteration (should be big enough to hold bucketCnt-1)
+ wrapped bool // already wrapped around from end of bucket array to beginning
+ B uint8
+ i uint8
+ bucket uintptr
+ checkBucket uintptr
+}
+
+func evacuated(b *bmap) bool {
+ h := b.tophash[0]
+ return h > empty && h < minTopHash
+}
+
+func makemap(t *maptype, hint int64) *hmap {
+ if sz := unsafe.Sizeof(hmap{}); sz > 48 || sz != uintptr(t.hmap.size) {
+ gothrow("bad hmap size")
+ }
+
+ if hint < 0 || int64(int32(hint)) != hint {
+ panic("makemap: size out of range")
+ // TODO: make hint an int, then none of this nonsense
+ }
+
+ if !ismapkey(t.key) {
+ gothrow("runtime.makemap: unsupported map key type")
+ }
+
+ // check compiler's and reflect's math
+ if t.key.size > maxKeySize && (!t.indirectkey || t.keysize != uint8(ptrSize)) ||
+ t.key.size <= maxKeySize && (t.indirectkey || t.keysize != uint8(t.key.size)) {
+ gothrow("key size wrong")
+ }
+ if t.elem.size > maxValueSize && (!t.indirectvalue || t.valuesize != uint8(ptrSize)) ||
+ t.elem.size <= maxValueSize && (t.indirectvalue || t.valuesize != uint8(t.elem.size)) {
+ gothrow("value size wrong")
+ }
+
+ // invariants we depend on. We should probably check these at compile time
+ // somewhere, but for now we'll do it here.
+ if t.key.align > bucketCnt {
+ gothrow("key align too big")
+ }
+ if t.elem.align > bucketCnt {
+ gothrow("value align too big")
+ }
+ if uintptr(t.key.size)%uintptr(t.key.align) != 0 {
+ gothrow("key size not a multiple of key align")
+ }
+ if uintptr(t.elem.size)%uintptr(t.elem.align) != 0 {
+ gothrow("value size not a multiple of value align")
+ }
+ if bucketCnt < 8 {
+ gothrow("bucketsize too small for proper alignment")
+ }
+ if dataOffset%uintptr(t.key.align) != 0 {
+ gothrow("need padding in bucket (key)")
+ }
+ if dataOffset%uintptr(t.elem.align) != 0 {
+ gothrow("need padding in bucket (value)")
+ }
+
+ // find size parameter which will hold the requested # of elements
+ B := uint8(0)
+ for ; hint > bucketCnt && float32(hint) > loadFactor*float32(uintptr(1)<<B); B++ {
+ }
+
+ // allocate initial hash table
+ // if B == 0, the buckets field is allocated lazily later (in mapassign)
+ // If hint is large zeroing this memory could take a while.
+ var buckets unsafe.Pointer
+ if B != 0 {
+ if checkgc {
+ memstats.next_gc = memstats.heap_alloc
+ }
+ buckets = newarray(t.bucket, uintptr(1)<<B)
+ }
+
+ // initialize Hmap
+ if checkgc {
+ memstats.next_gc = memstats.heap_alloc
+ }
+ h := (*hmap)(newobject(t.hmap))
+ h.count = 0
+ h.B = B
+ h.flags = 0
+ h.hash0 = fastrand1()
+ h.buckets = buckets
+ h.oldbuckets = nil
+ h.nevacuate = 0
+
+ return h
+}
+
+// mapaccess1 returns a pointer to h[key]. Never returns nil, instead
+// it will return a reference to the zero object for the value type if
+// the key is not in the map.
+// NOTE: The returned pointer may keep the whole map live, so don't
+// hold onto it for very long.
+func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
+ if raceenabled && h != nil {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ pc := funcPC(mapaccess1)
+ racereadpc(unsafe.Pointer(h), callerpc, pc)
+ raceReadObjectPC(t.key, key, callerpc, pc)
+ }
+ if h == nil || h.count == 0 {
+ return unsafe.Pointer(t.elem.zero)
+ }
+ alg := goalg(t.key.alg)
+ hash := alg.hash(key, uintptr(t.key.size), uintptr(h.hash0))
+ m := uintptr(1)<<h.B - 1
+ b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
+ if c := h.oldbuckets; c != nil {
+ oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !evacuated(oldb) {
+ b = oldb
+ }
+ }
+ top := uint8(hash >> (ptrSize*8 - 8))
+ if top < minTopHash {
+ top += minTopHash
+ }
+ for {
+ for i := uintptr(0); i < bucketCnt; i++ {
+ if b.tophash[i] != top {
+ continue
+ }
+ k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
+ if t.indirectkey {
+ k = *((*unsafe.Pointer)(k))
+ }
+ if alg.equal(key, k, uintptr(t.key.size)) {
+ v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
+ if t.indirectvalue {
+ v = *((*unsafe.Pointer)(v))
+ }
+ return v
+ }
+ }
+ b = b.overflow
+ if b == nil {
+ return unsafe.Pointer(t.elem.zero)
+ }
+ }
+}
+
+func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool) {
+ if raceenabled && h != nil {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ pc := funcPC(mapaccess2)
+ racereadpc(unsafe.Pointer(h), callerpc, pc)
+ raceReadObjectPC(t.key, key, callerpc, pc)
+ }
+ if h == nil || h.count == 0 {
+ return unsafe.Pointer(t.elem.zero), false
+ }
+ alg := goalg(t.key.alg)
+ hash := alg.hash(key, uintptr(t.key.size), uintptr(h.hash0))
+ m := uintptr(1)<<h.B - 1
+ b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + (hash&m)*uintptr(t.bucketsize)))
+ if c := h.oldbuckets; c != nil {
+ oldb := (*bmap)(unsafe.Pointer(uintptr(c) + (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !evacuated(oldb) {
+ b = oldb
+ }
+ }
+ top := uint8(hash >> (ptrSize*8 - 8))
+ if top < minTopHash {
+ top += minTopHash
+ }
+ for {
+ for i := uintptr(0); i < bucketCnt; i++ {
+ if b.tophash[i] != top {
+ continue
+ }
+ k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
+ if t.indirectkey {
+ k = *((*unsafe.Pointer)(k))
+ }
+ if alg.equal(key, k, uintptr(t.key.size)) {
+ v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
+ if t.indirectvalue {
+ v = *((*unsafe.Pointer)(v))
+ }
+ return v, true
+ }
+ }
+ b = b.overflow
+ if b == nil {
+ return unsafe.Pointer(t.elem.zero), false
+ }
+ }
+}
+
+// returns both key and value. Used by map iterator
+func mapaccessK(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, unsafe.Pointer) {
+ if h == nil || h.count == 0 {
+ return nil, nil
+ }
+ alg := goalg(t.key.alg)
+ hash := alg.hash(key, uintptr(t.key.size), uintptr(h.hash0))
+ m := uintptr(1)<<h.B - 1
+ b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + (hash&m)*uintptr(t.bucketsize)))
+ if c := h.oldbuckets; c != nil {
+ oldb := (*bmap)(unsafe.Pointer(uintptr(c) + (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !evacuated(oldb) {
+ b = oldb
+ }
+ }
+ top := uint8(hash >> (ptrSize*8 - 8))
+ if top < minTopHash {
+ top += minTopHash
+ }
+ for {
+ for i := uintptr(0); i < bucketCnt; i++ {
+ if b.tophash[i] != top {
+ continue
+ }
+ k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
+ if t.indirectkey {
+ k = *((*unsafe.Pointer)(k))
+ }
+ if alg.equal(key, k, uintptr(t.key.size)) {
+ v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
+ if t.indirectvalue {
+ v = *((*unsafe.Pointer)(v))
+ }
+ return k, v
+ }
+ }
+ b = b.overflow
+ if b == nil {
+ return nil, nil
+ }
+ }
+}
+
+func mapassign1(t *maptype, h *hmap, key unsafe.Pointer, val unsafe.Pointer) {
+ if h == nil {
+ panic("assignment to entry in nil map")
+ }
+ if raceenabled {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ pc := funcPC(mapassign1)
+ racewritepc(unsafe.Pointer(h), callerpc, pc)
+ raceReadObjectPC(t.key, key, callerpc, pc)
+ raceReadObjectPC(t.elem, val, callerpc, pc)
+ }
+
+ alg := goalg(t.key.alg)
+ hash := alg.hash(key, uintptr(t.key.size), uintptr(h.hash0))
+
+ if h.buckets == nil {
+ if checkgc {
+ memstats.next_gc = memstats.heap_alloc
+ }
+ h.buckets = newarray(t.bucket, 1)
+ }
+
+again:
+ bucket := hash & (uintptr(1)<<h.B - 1)
+ if h.oldbuckets != nil {
+ growWork(t, h, bucket)
+ }
+ b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
+ top := uint8(hash >> (ptrSize*8 - 8))
+ if top < minTopHash {
+ top += minTopHash
+ }
+
+ var inserti *uint8
+ var insertk unsafe.Pointer
+ var insertv unsafe.Pointer
+ for {
+ for i := uintptr(0); i < bucketCnt; i++ {
+ if b.tophash[i] != top {
+ if b.tophash[i] == empty && inserti == nil {
+ inserti = &b.tophash[i]
+ insertk = add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
+ insertv = add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
+ }
+ continue
+ }
+ k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
+ k2 := k
+ if t.indirectkey {
+ k2 = *((*unsafe.Pointer)(k2))
+ }
+ if !alg.equal(key, k2, uintptr(t.key.size)) {
+ continue
+ }
+ // already have a mapping for key. Update it.
+ memmove(k2, key, uintptr(t.key.size))
+ v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
+ v2 := v
+ if t.indirectvalue {
+ v2 = *((*unsafe.Pointer)(v2))
+ }
+ memmove(v2, val, uintptr(t.elem.size))
+ return
+ }
+ if b.overflow == nil {
+ break
+ }
+ b = b.overflow
+ }
+
+ // did not find mapping for key. Allocate new cell & add entry.
+ if float32(h.count) >= loadFactor*float32((uintptr(1)<<h.B)) && h.count >= bucketCnt {
+ hashGrow(t, h)
+ goto again // Growing the table invalidates everything, so try again
+ }
+
+ if inserti == nil {
+ // all current buckets are full, allocate a new one.
+ if checkgc {
+ memstats.next_gc = memstats.heap_alloc
+ }
+ newb := (*bmap)(newobject(t.bucket))
+ b.overflow = newb
+ inserti = &newb.tophash[0]
+ insertk = add(unsafe.Pointer(newb), dataOffset)
+ insertv = add(insertk, bucketCnt*uintptr(t.keysize))
+ }
+
+ // store new key/value at insert position
+ if t.indirectkey {
+ if checkgc {
+ memstats.next_gc = memstats.heap_alloc
+ }
+ kmem := newobject(t.key)
+ *(*unsafe.Pointer)(insertk) = kmem
+ insertk = kmem
+ }
+ if t.indirectvalue {
+ if checkgc {
+ memstats.next_gc = memstats.heap_alloc
+ }
+ vmem := newobject(t.elem)
+ *(*unsafe.Pointer)(insertv) = vmem
+ insertv = vmem
+ }
+ memmove(insertk, key, uintptr(t.key.size))
+ memmove(insertv, val, uintptr(t.elem.size))
+ *inserti = top
+ h.count++
+}
+
+func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
+ if raceenabled && h != nil {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ pc := funcPC(mapdelete)
+ racewritepc(unsafe.Pointer(h), callerpc, pc)
+ raceReadObjectPC(t.key, key, callerpc, pc)
+ }
+ if h == nil || h.count == 0 {
+ return
+ }
+ alg := goalg(t.key.alg)
+ hash := alg.hash(key, uintptr(t.key.size), uintptr(h.hash0))
+ bucket := hash & (uintptr(1)<<h.B - 1)
+ if h.oldbuckets != nil {
+ growWork(t, h, bucket)
+ }
+ b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
+ top := uint8(hash >> (ptrSize*8 - 8))
+ if top < minTopHash {
+ top += minTopHash
+ }
+ for {
+ for i := uintptr(0); i < bucketCnt; i++ {
+ if b.tophash[i] != top {
+ continue
+ }
+ k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
+ k2 := k
+ if t.indirectkey {
+ k2 = *((*unsafe.Pointer)(k2))
+ }
+ if !alg.equal(key, k2, uintptr(t.key.size)) {
+ continue
+ }
+ memclr(k, uintptr(t.keysize))
+ v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*uintptr(t.keysize) + i*uintptr(t.valuesize))
+ memclr(v, uintptr(t.valuesize))
+ b.tophash[i] = empty
+ h.count--
+ return
+ }
+ b = b.overflow
+ if b == nil {
+ return
+ }
+ }
+}
+
+func mapiterinit(t *maptype, h *hmap, it *hiter) {
+ // Clear pointer fields so garbage collector does not complain.
+ it.key = nil
+ it.value = nil
+ it.t = nil
+ it.h = nil
+ it.buckets = nil
+ it.bptr = nil
+
+ if raceenabled && h != nil {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapiterinit))
+ }
+
+ if h == nil || h.count == 0 {
+ it.key = nil
+ it.value = nil
+ return
+ }
+
+ if unsafe.Sizeof(hiter{})/ptrSize != 10 {
+ gothrow("hash_iter size incorrect") // see ../../cmd/gc/reflect.c
+ }
+ it.t = t
+ it.h = h
+
+ // grab snapshot of bucket state
+ it.B = h.B
+ it.buckets = h.buckets
+
+ // decide where to start
+ r := uintptr(fastrand1())
+ if h.B > 31-bucketCntBits {
+ r += uintptr(fastrand1()) << 31
+ }
+ it.startBucket = r & (uintptr(1)<<h.B - 1)
+ it.offset = uint8(r >> h.B & (bucketCnt - 1))
+
+ // iterator state
+ it.bucket = it.startBucket
+ it.wrapped = false
+ it.bptr = nil
+
+ // Remember we have an iterator.
+ // Can run concurrently with another hash_iter_init().
+ for {
+ old := h.flags
+ if old == old|iterator|oldIterator {
+ break
+ }
+ if cas(&h.flags, old, old|iterator|oldIterator) {
+ break
+ }
+ }
+
+ mapiternext(it)
+}
+
+func mapiternext(it *hiter) {
+ h := it.h
+ if raceenabled {
+ callerpc := getcallerpc(unsafe.Pointer(&it))
+ racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapiternext))
+ }
+ t := it.t
+ bucket := it.bucket
+ b := it.bptr
+ i := it.i
+ checkBucket := it.checkBucket
+ alg := goalg(t.key.alg)
+
+next:
+ if b == nil {
+ if bucket == it.startBucket && it.wrapped {
+ // end of iteration
+ it.key = nil
+ it.value = nil
+ return
+ }
+ if h.oldbuckets != nil && it.B == h.B {
+ // Iterator was started in the middle of a grow, and the grow isn't done yet.
+ // If the bucket we're looking at hasn't been filled in yet (i.e. the old
+ // bucket hasn't been evacuated) then we need to iterate through the old
+ // bucket and only return the ones that will be migrated to this bucket.
+ oldbucket := bucket & (uintptr(1)<<(it.B-1) - 1)
+ b = (*bmap)(add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)))
+ if !evacuated(b) {
+ checkBucket = bucket
+ } else {
+ b = (*bmap)(add(it.buckets, bucket*uintptr(t.bucketsize)))
+ checkBucket = noCheck
+ }
+ } else {
+ b = (*bmap)(add(it.buckets, bucket*uintptr(t.bucketsize)))
+ checkBucket = noCheck
+ }
+ bucket++
+ if bucket == uintptr(1)<<it.B {
+ bucket = 0
+ it.wrapped = true
+ }
+ i = 0
+ }
+ for ; i < bucketCnt; i++ {
+ offi := (i + it.offset) & (bucketCnt - 1)
+ k := add(unsafe.Pointer(b), dataOffset+uintptr(offi)*uintptr(t.keysize))
+ v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+uintptr(offi)*uintptr(t.valuesize))
+ if b.tophash[offi] != empty && b.tophash[offi] != evacuatedEmpty {
+ if checkBucket != noCheck {
+ // Special case: iterator was started during a grow and the
+ // grow is not done yet. We're working on a bucket whose
+ // oldbucket has not been evacuated yet. Or at least, it wasn't
+ // evacuated when we started the bucket. So we're iterating
+ // through the oldbucket, skipping any keys that will go
+ // to the other new bucket (each oldbucket expands to two
+ // buckets during a grow).
+ k2 := k
+ if t.indirectkey {
+ k2 = *((*unsafe.Pointer)(k2))
+ }
+ if alg.equal(k2, k2, uintptr(t.key.size)) {
+ // If the item in the oldbucket is not destined for
+ // the current new bucket in the iteration, skip it.
+ hash := alg.hash(k2, uintptr(t.key.size), uintptr(h.hash0))
+ if hash&(uintptr(1)<<it.B-1) != checkBucket {
+ continue
+ }
+ } else {
+ // Hash isn't repeatable if k != k (NaNs). We need a
+ // repeatable and randomish choice of which direction
+ // to send NaNs during evacuation. We'll use the low
+ // bit of tophash to decide which way NaNs go.
+ // NOTE: this case is why we need two evacuate tophash
+ // values, evacuatedX and evacuatedY, that differ in
+ // their low bit.
+ if checkBucket>>(it.B-1) != uintptr(b.tophash[offi]&1) {
+ continue
+ }
+ }
+ }
+ if b.tophash[offi] != evacuatedX && b.tophash[offi] != evacuatedY {
+ // this is the golden data, we can return it.
+ if t.indirectkey {
+ k = *((*unsafe.Pointer)(k))
+ }
+ it.key = k
+ if t.indirectvalue {
+ v = *((*unsafe.Pointer)(v))
+ }
+ it.value = v
+ } else {
+ // The hash table has grown since the iterator was started.
+ // The golden data for this key is now somewhere else.
+ k2 := k
+ if t.indirectkey {
+ k2 = *((*unsafe.Pointer)(k2))
+ }
+ if alg.equal(k2, k2, uintptr(t.key.size)) {
+ // Check the current hash table for the data.
+ // This code handles the case where the key
+ // has been deleted, updated, or deleted and reinserted.
+ // NOTE: we need to regrab the key as it has potentially been
+ // updated to an equal() but not identical key (e.g. +0.0 vs -0.0).
+ rk, rv := mapaccessK(t, h, k2)
+ if rk == nil {
+ continue // key has been deleted
+ }
+ it.key = rk
+ it.value = rv
+ } else {
+ // if key!=key then the entry can't be deleted or
+ // updated, so we can just return it. That's lucky for
+ // us because when key!=key we can't look it up
+ // successfully in the current table.
+ it.key = k2
+ if t.indirectvalue {
+ v = *((*unsafe.Pointer)(v))
+ }
+ it.value = v
+ }
+ }
+ it.bucket = bucket
+ it.bptr = b
+ it.i = i + 1
+ it.checkBucket = checkBucket
+ return
+ }
+ }
+ b = b.overflow
+ i = 0
+ goto next
+}
+
+func hashGrow(t *maptype, h *hmap) {
+ if h.oldbuckets != nil {
+ gothrow("evacuation not done in time")
+ }
+ oldbuckets := h.buckets
+ if checkgc {
+ memstats.next_gc = memstats.heap_alloc
+ }
+ newbuckets := newarray(t.bucket, uintptr(1)<<(h.B+1))
+ flags := h.flags &^ (iterator | oldIterator)
+ if h.flags&iterator != 0 {
+ flags |= oldIterator
+ }
+ // commit the grow (atomic wrt gc)
+ h.B++
+ h.flags = flags
+ h.oldbuckets = oldbuckets
+ h.buckets = newbuckets
+ h.nevacuate = 0
+
+ // the actual copying of the hash table data is done incrementally
+ // by growWork() and evacuate().
+}
+
+func growWork(t *maptype, h *hmap, bucket uintptr) {
+ noldbuckets := uintptr(1) << (h.B - 1)
+
+ // make sure we evacuate the oldbucket corresponding
+ // to the bucket we're about to use
+ evacuate(t, h, bucket&(noldbuckets-1))
+
+ // evacuate one more oldbucket to make progress on growing
+ if h.oldbuckets != nil {
+ evacuate(t, h, h.nevacuate)
+ }
+}
+
+func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
+ b := (*bmap)(add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)))
+ newbit := uintptr(1) << (h.B - 1)
+ alg := goalg(t.key.alg)
+ if !evacuated(b) {
+ // TODO: reuse overflow buckets instead of using new ones, if there
+ // is no iterator using the old buckets. (If !oldIterator.)
+
+ x := (*bmap)(add(h.buckets, oldbucket*uintptr(t.bucketsize)))
+ y := (*bmap)(add(h.buckets, (oldbucket+newbit)*uintptr(t.bucketsize)))
+ xi := 0
+ yi := 0
+ xk := add(unsafe.Pointer(x), dataOffset)
+ yk := add(unsafe.Pointer(y), dataOffset)
+ xv := add(xk, bucketCnt*uintptr(t.keysize))
+ yv := add(yk, bucketCnt*uintptr(t.keysize))
+ for ; b != nil; b = b.overflow {
+ k := add(unsafe.Pointer(b), dataOffset)
+ v := add(k, bucketCnt*uintptr(t.keysize))
+ for i := 0; i < bucketCnt; i, k, v = i+1, add(k, uintptr(t.keysize)), add(v, uintptr(t.valuesize)) {
+ top := b.tophash[i]
+ if top == empty {
+ b.tophash[i] = evacuatedEmpty
+ continue
+ }
+ if top < minTopHash {
+ gothrow("bad map state")
+ }
+ k2 := k
+ if t.indirectkey {
+ k2 = *((*unsafe.Pointer)(k2))
+ }
+ // Compute hash to make our evacuation decision (whether we need
+ // to send this key/value to bucket x or bucket y).
+ hash := alg.hash(k2, uintptr(t.key.size), uintptr(h.hash0))
+ if h.flags&iterator != 0 {
+ if !alg.equal(k2, k2, uintptr(t.key.size)) {
+ // If key != key (NaNs), then the hash could be (and probably
+ // will be) entirely different from the old hash. Moreover,
+ // it isn't reproducible. Reproducibility is required in the
+ // presence of iterators, as our evacuation decision must
+ // match whatever decision the iterator made.
+ // Fortunately, we have the freedom to send these keys either
+ // way. Also, tophash is meaningless for these kinds of keys.
+ // We let the low bit of tophash drive the evacuation decision.
+ // We recompute a new random tophash for the next level so
+ // these keys will get evenly distributed across all buckets
+ // after multiple grows.
+ if (top & 1) != 0 {
+ hash |= newbit
+ } else {
+ hash &^= newbit
+ }
+ top = uint8(hash >> (ptrSize*8 - 8))
+ if top < minTopHash {
+ top += minTopHash
+ }
+ }
+ }
+ if (hash & newbit) == 0 {
+ b.tophash[i] = evacuatedX
+ if xi == bucketCnt {
+ if checkgc {
+ memstats.next_gc = memstats.heap_alloc
+ }
+ newx := (*bmap)(newobject(t.bucket))
+ x.overflow = newx
+ x = newx
+ xi = 0
+ xk = add(unsafe.Pointer(x), dataOffset)
+ xv = add(xk, bucketCnt*uintptr(t.keysize))
+ }
+ x.tophash[xi] = top
+ if t.indirectkey {
+ *(*unsafe.Pointer)(xk) = k2 // copy pointer
+ } else {
+ memmove(xk, k, uintptr(t.key.size)) // copy value
+ }
+ if t.indirectvalue {
+ *(*unsafe.Pointer)(xv) = *(*unsafe.Pointer)(v)
+ } else {
+ memmove(xv, v, uintptr(t.elem.size))
+ }
+ xi++
+ xk = add(xk, uintptr(t.keysize))
+ xv = add(xv, uintptr(t.valuesize))
+ } else {
+ b.tophash[i] = evacuatedY
+ if yi == bucketCnt {
+ if checkgc {
+ memstats.next_gc = memstats.heap_alloc
+ }
+ newy := (*bmap)(newobject(t.bucket))
+ y.overflow = newy
+ y = newy
+ yi = 0
+ yk = add(unsafe.Pointer(y), dataOffset)
+ yv = add(yk, bucketCnt*uintptr(t.keysize))
+ }
+ y.tophash[yi] = top
+ if t.indirectkey {
+ *(*unsafe.Pointer)(yk) = k2
+ } else {
+ memmove(yk, k, uintptr(t.key.size))
+ }
+ if t.indirectvalue {
+ *(*unsafe.Pointer)(yv) = *(*unsafe.Pointer)(v)
+ } else {
+ memmove(yv, v, uintptr(t.elem.size))
+ }
+ yi++
+ yk = add(yk, uintptr(t.keysize))
+ yv = add(yv, uintptr(t.valuesize))
+ }
+ }
+ }
+ // Unlink the overflow buckets & clear key/value to help GC.
+ if h.flags&oldIterator == 0 {
+ b = (*bmap)(add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)))
+ b.overflow = nil
+ memclr(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset)
+ }
+ }
+
+ // Advance evacuation mark
+ if oldbucket == h.nevacuate {
+ h.nevacuate = oldbucket + 1
+ if oldbucket+1 == newbit { // newbit == # of oldbuckets
+ // Growing is all done. Free old main bucket array.
+ h.oldbuckets = nil
+ }
+ }
+}
+
+func ismapkey(t *_type) bool {
+ return goalg(t.alg).hash != nil
+}
+
+// Reflect stubs. Called from ../reflect/asm_*.s
+
+func reflect_makemap(t *maptype) *hmap {
+ return makemap(t, 0)
+}
+
+func reflect_mapaccess(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
+ val, ok := mapaccess2(t, h, key)
+ if !ok {
+ // reflect wants nil for a missing element
+ val = nil
+ }
+ return val
+}
+
+func reflect_mapassign(t *maptype, h *hmap, key unsafe.Pointer, val unsafe.Pointer) {
+ mapassign1(t, h, key, val)
+}
+
+func reflect_mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
+ mapdelete(t, h, key)
+}
+
+func reflect_mapiterinit(t *maptype, h *hmap) *hiter {
+ it := new(hiter)
+ mapiterinit(t, h, it)
+ return it
+}
+
+func reflect_mapiternext(it *hiter) {
+ mapiternext(it)
+}
+
+func reflect_mapiterkey(it *hiter) unsafe.Pointer {
+ return it.key
+}
+
+func reflect_maplen(h *hmap) int {
+ if h == nil {
+ return 0
+ }
+ if raceenabled {
+ callerpc := getcallerpc(unsafe.Pointer(&h))
+ racereadpc(unsafe.Pointer(h), callerpc, funcPC(reflect_maplen))
+ }
+ return h.count
+}
+
+func reflect_ismapkey(t *_type) bool {
+ return ismapkey(t)
+}
diff --git a/src/runtime/hashmap_fast.go b/src/runtime/hashmap_fast.go
new file mode 100644
index 000000000..8e21e02d6
--- /dev/null
+++ b/src/runtime/hashmap_fast.go
@@ -0,0 +1,379 @@
+// 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"
+)
+
+func mapaccess1_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer {
+ if raceenabled && h != nil {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_fast32))
+ }
+ if h == nil || h.count == 0 {
+ return unsafe.Pointer(t.elem.zero)
+ }
+ var b *bmap
+ if h.B == 0 {
+ // One-bucket table. No need to hash.
+ b = (*bmap)(h.buckets)
+ } else {
+ hash := goalg(t.key.alg).hash(noescape(unsafe.Pointer(&key)), 4, uintptr(h.hash0))
+ m := uintptr(1)<<h.B - 1
+ b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
+ if c := h.oldbuckets; c != nil {
+ oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !evacuated(oldb) {
+ b = oldb
+ }
+ }
+ }
+ for {
+ for i := uintptr(0); i < bucketCnt; i++ {
+ k := *((*uint32)(add(unsafe.Pointer(b), dataOffset+i*4)))
+ if k != key {
+ continue
+ }
+ x := *((*uint8)(add(unsafe.Pointer(b), i))) // b.topbits[i] without the bounds check
+ if x == empty {
+ continue
+ }
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize))
+ }
+ b = b.overflow
+ if b == nil {
+ return unsafe.Pointer(t.elem.zero)
+ }
+ }
+}
+
+func mapaccess2_fast32(t *maptype, h *hmap, key uint32) (unsafe.Pointer, bool) {
+ if raceenabled && h != nil {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_fast32))
+ }
+ if h == nil || h.count == 0 {
+ return unsafe.Pointer(t.elem.zero), false
+ }
+ var b *bmap
+ if h.B == 0 {
+ // One-bucket table. No need to hash.
+ b = (*bmap)(h.buckets)
+ } else {
+ hash := goalg(t.key.alg).hash(noescape(unsafe.Pointer(&key)), 4, uintptr(h.hash0))
+ m := uintptr(1)<<h.B - 1
+ b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
+ if c := h.oldbuckets; c != nil {
+ oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !evacuated(oldb) {
+ b = oldb
+ }
+ }
+ }
+ for {
+ for i := uintptr(0); i < bucketCnt; i++ {
+ k := *((*uint32)(add(unsafe.Pointer(b), dataOffset+i*4)))
+ if k != key {
+ continue
+ }
+ x := *((*uint8)(add(unsafe.Pointer(b), i))) // b.topbits[i] without the bounds check
+ if x == empty {
+ continue
+ }
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize)), true
+ }
+ b = b.overflow
+ if b == nil {
+ return unsafe.Pointer(t.elem.zero), false
+ }
+ }
+}
+
+func mapaccess1_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
+ if raceenabled && h != nil {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_fast64))
+ }
+ if h == nil || h.count == 0 {
+ return unsafe.Pointer(t.elem.zero)
+ }
+ var b *bmap
+ if h.B == 0 {
+ // One-bucket table. No need to hash.
+ b = (*bmap)(h.buckets)
+ } else {
+ hash := goalg(t.key.alg).hash(noescape(unsafe.Pointer(&key)), 8, uintptr(h.hash0))
+ m := uintptr(1)<<h.B - 1
+ b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
+ if c := h.oldbuckets; c != nil {
+ oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !evacuated(oldb) {
+ b = oldb
+ }
+ }
+ }
+ for {
+ for i := uintptr(0); i < bucketCnt; i++ {
+ k := *((*uint64)(add(unsafe.Pointer(b), dataOffset+i*8)))
+ if k != key {
+ continue
+ }
+ x := *((*uint8)(add(unsafe.Pointer(b), i))) // b.topbits[i] without the bounds check
+ if x == empty {
+ continue
+ }
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize))
+ }
+ b = b.overflow
+ if b == nil {
+ return unsafe.Pointer(t.elem.zero)
+ }
+ }
+}
+
+func mapaccess2_fast64(t *maptype, h *hmap, key uint64) (unsafe.Pointer, bool) {
+ if raceenabled && h != nil {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_fast64))
+ }
+ if h == nil || h.count == 0 {
+ return unsafe.Pointer(t.elem.zero), false
+ }
+ var b *bmap
+ if h.B == 0 {
+ // One-bucket table. No need to hash.
+ b = (*bmap)(h.buckets)
+ } else {
+ hash := goalg(t.key.alg).hash(noescape(unsafe.Pointer(&key)), 8, uintptr(h.hash0))
+ m := uintptr(1)<<h.B - 1
+ b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
+ if c := h.oldbuckets; c != nil {
+ oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !evacuated(oldb) {
+ b = oldb
+ }
+ }
+ }
+ for {
+ for i := uintptr(0); i < bucketCnt; i++ {
+ k := *((*uint64)(add(unsafe.Pointer(b), dataOffset+i*8)))
+ if k != key {
+ continue
+ }
+ x := *((*uint8)(add(unsafe.Pointer(b), i))) // b.topbits[i] without the bounds check
+ if x == empty {
+ continue
+ }
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize)), true
+ }
+ b = b.overflow
+ if b == nil {
+ return unsafe.Pointer(t.elem.zero), false
+ }
+ }
+}
+
+func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer {
+ if raceenabled && h != nil {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_faststr))
+ }
+ if h == nil || h.count == 0 {
+ return unsafe.Pointer(t.elem.zero)
+ }
+ key := (*stringStruct)(unsafe.Pointer(&ky))
+ if h.B == 0 {
+ // One-bucket table.
+ b := (*bmap)(h.buckets)
+ if key.len < 32 {
+ // short key, doing lots of comparisons is ok
+ for i := uintptr(0); i < bucketCnt; i++ {
+ x := *((*uint8)(add(unsafe.Pointer(b), i))) // b.topbits[i] without the bounds check
+ if x == empty {
+ continue
+ }
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*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 unsafe.Pointer(t.elem.zero)
+ }
+ // long key, try not to do more comparisons than necessary
+ keymaybe := uintptr(bucketCnt)
+ for i := uintptr(0); i < bucketCnt; i++ {
+ x := *((*uint8)(add(unsafe.Pointer(b), i))) // b.topbits[i] without the bounds check
+ if x == empty {
+ continue
+ }
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*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))
+ }
+ // check first 4 bytes
+ // TODO: on amd64/386 at least, make this compile to one 4-byte comparison instead of
+ // four 1-byte comparisons.
+ if *((*[4]byte)(key.str)) != *((*[4]byte)(k.str)) {
+ continue
+ }
+ // check last 4 bytes
+ if *((*[4]byte)(add(key.str, uintptr(key.len)-4))) != *((*[4]byte)(add(k.str, uintptr(key.len)-4))) {
+ continue
+ }
+ if keymaybe != bucketCnt {
+ // Two keys are potential matches. Use hash to distinguish them.
+ goto dohash
+ }
+ keymaybe = i
+ }
+ if keymaybe != bucketCnt {
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*ptrSize))
+ if memeq(k.str, key.str, uintptr(key.len)) {
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+keymaybe*uintptr(t.valuesize))
+ }
+ }
+ return unsafe.Pointer(t.elem.zero)
+ }
+dohash:
+ hash := goalg(t.key.alg).hash(noescape(unsafe.Pointer(&ky)), 2*ptrSize, uintptr(h.hash0))
+ m := uintptr(1)<<h.B - 1
+ b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
+ if c := h.oldbuckets; c != nil {
+ oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !evacuated(oldb) {
+ b = oldb
+ }
+ }
+ top := uint8(hash >> (ptrSize*8 - 8))
+ if top < minTopHash {
+ top += minTopHash
+ }
+ for {
+ for i := uintptr(0); i < bucketCnt; i++ {
+ x := *((*uint8)(add(unsafe.Pointer(b), i))) // b.topbits[i] without the bounds check
+ if x != top {
+ continue
+ }
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*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))
+ }
+ }
+ b = b.overflow
+ if b == nil {
+ return unsafe.Pointer(t.elem.zero)
+ }
+ }
+}
+
+func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) {
+ if raceenabled && h != nil {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_faststr))
+ }
+ if h == nil || h.count == 0 {
+ return unsafe.Pointer(t.elem.zero), false
+ }
+ key := (*stringStruct)(unsafe.Pointer(&ky))
+ if h.B == 0 {
+ // One-bucket table.
+ b := (*bmap)(h.buckets)
+ if key.len < 32 {
+ // short key, doing lots of comparisons is ok
+ for i := uintptr(0); i < bucketCnt; i++ {
+ x := *((*uint8)(add(unsafe.Pointer(b), i))) // b.topbits[i] without the bounds check
+ if x == empty {
+ continue
+ }
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*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 unsafe.Pointer(t.elem.zero), false
+ }
+ // long key, try not to do more comparisons than necessary
+ keymaybe := uintptr(bucketCnt)
+ for i := uintptr(0); i < bucketCnt; i++ {
+ x := *((*uint8)(add(unsafe.Pointer(b), i))) // b.topbits[i] without the bounds check
+ if x == empty {
+ continue
+ }
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*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
+ }
+ // check first 4 bytes
+ if *((*[4]byte)(key.str)) != *((*[4]byte)(k.str)) {
+ continue
+ }
+ // check last 4 bytes
+ if *((*[4]byte)(add(key.str, uintptr(key.len)-4))) != *((*[4]byte)(add(k.str, uintptr(key.len)-4))) {
+ continue
+ }
+ if keymaybe != bucketCnt {
+ // Two keys are potential matches. Use hash to distinguish them.
+ goto dohash
+ }
+ keymaybe = i
+ }
+ if keymaybe != bucketCnt {
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*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 unsafe.Pointer(t.elem.zero), false
+ }
+dohash:
+ hash := goalg(t.key.alg).hash(noescape(unsafe.Pointer(&ky)), 2*ptrSize, uintptr(h.hash0))
+ m := uintptr(1)<<h.B - 1
+ b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
+ if c := h.oldbuckets; c != nil {
+ oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !evacuated(oldb) {
+ b = oldb
+ }
+ }
+ top := uint8(hash >> (ptrSize*8 - 8))
+ if top < minTopHash {
+ top += minTopHash
+ }
+ for {
+ for i := uintptr(0); i < bucketCnt; i++ {
+ x := *((*uint8)(add(unsafe.Pointer(b), i))) // b.topbits[i] without the bounds check
+ if x != top {
+ continue
+ }
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*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
+ }
+ }
+ b = b.overflow
+ if b == nil {
+ return unsafe.Pointer(t.elem.zero), false
+ }
+ }
+}
diff --git a/src/pkg/runtime/heapdump.c b/src/runtime/heapdump.c
index 744c59f9b..7eba8c005 100644
--- a/src/pkg/runtime/heapdump.c
+++ b/src/runtime/heapdump.c
@@ -7,7 +7,7 @@
// finalizers, etc.) to a file.
// The format of the dumped file is described at
-// http://code.google.com/p/go-wiki/wiki/heapdump13
+// http://golang.org/s/go14heapdump.
#include "runtime.h"
#include "arch_GOARCH.h"
@@ -17,22 +17,18 @@
#include "typekind.h"
#include "funcdata.h"
#include "zaexperiment.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
-extern byte data[];
-extern byte edata[];
-extern byte bss[];
-extern byte ebss[];
-extern byte gcdata[];
-extern byte gcbss[];
+extern byte runtime·data[];
+extern byte runtime·edata[];
+extern byte runtime·bss[];
+extern byte runtime·ebss[];
enum {
FieldKindEol = 0,
FieldKindPtr = 1,
- FieldKindString = 2,
- FieldKindSlice = 3,
- FieldKindIface = 4,
- FieldKindEface = 5,
+ FieldKindIface = 2,
+ FieldKindEface = 3,
TagEOF = 0,
TagObject = 1,
@@ -52,17 +48,19 @@ enum {
TagPanic = 15,
TagMemProf = 16,
TagAllocSample = 17,
-
- TypeInfo_Conservative = 127,
};
static uintptr* playgcprog(uintptr offset, uintptr *prog, void (*callback)(void*,uintptr,uintptr), void *arg);
-static void dumpfields(uintptr *prog);
-static void dumpefacetypes(void *obj, uintptr size, Type *type, uintptr kind);
+static void dumpfields(BitVector bv);
static void dumpbvtypes(BitVector *bv, byte *base);
+static BitVector makeheapobjbv(byte *p, uintptr size);
// fd to write the dump to.
-static uintptr dumpfd;
+static uintptr dumpfd;
+
+#pragma dataflag NOPTR /* tmpbuf not a heap pointer at least */
+static byte *tmpbuf;
+static uintptr tmpbufsize;
// buffer of pending write data
enum {
@@ -111,6 +109,7 @@ typedef struct TypeCacheBucket TypeCacheBucket;
struct TypeCacheBucket {
Type *t[TypeCacheAssoc];
};
+#pragma dataflag NOPTR /* only initialized and used while world is stopped */
static TypeCacheBucket typecache[TypeCacheBuckets];
// dump a uint64 in a varint format parseable by encoding/binary
@@ -198,36 +197,18 @@ dumptype(Type *t)
write((byte*)".", 1);
write(t->x->name->str, t->x->name->len);
}
- dumpbool(t->size > PtrSize || (t->kind & KindNoPointers) == 0);
- dumpfields((uintptr*)t->gc + 1);
-}
-
-// returns true if object is scannable
-static bool
-scannable(byte *obj)
-{
- uintptr *b, off, shift;
-
- off = (uintptr*)obj - (uintptr*)runtime·mheap.arena_start; // word offset
- b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- return ((*b >> shift) & bitScan) != 0;
+ dumpbool((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0);
}
// dump an object
static void
-dumpobj(byte *obj, uintptr size, Type *type, uintptr kind)
+dumpobj(byte *obj, uintptr size, BitVector bv)
{
- if(type != nil) {
- dumptype(type);
- dumpefacetypes(obj, size, type, kind);
- }
-
+ dumpbvtypes(&bv, obj);
dumpint(TagObject);
dumpint((uintptr)obj);
- dumpint((uintptr)type);
- dumpint(kind);
dumpmemrange(obj, size);
+ dumpfields(bv);
}
static void
@@ -268,8 +249,11 @@ dumpbv(BitVector *bv, uintptr offset)
uintptr i;
for(i = 0; i < bv->n; i += BitsPerPointer) {
- switch(bv->data[i/32] >> i%32 & 3) {
+ switch(bv->bytedata[i/8] >> i%8 & 3) {
case BitsDead:
+ // BitsDead has already been processed in makeheapobjbv.
+ // We should only see it in stack maps, in which case we should continue processing.
+ break;
case BitsScalar:
break;
case BitsPointer:
@@ -277,17 +261,9 @@ dumpbv(BitVector *bv, uintptr offset)
dumpint(offset + i / BitsPerPointer * PtrSize);
break;
case BitsMultiWord:
- switch(bv->data[(i+BitsPerPointer)/32] >> (i+BitsPerPointer)%32 & 3) {
- case BitsString:
- dumpint(FieldKindString);
- dumpint(offset + i / BitsPerPointer * PtrSize);
- i += BitsPerPointer;
- break;
- case BitsSlice:
- dumpint(FieldKindSlice);
- dumpint(offset + i / BitsPerPointer * PtrSize);
- i += 2 * BitsPerPointer;
- break;
+ switch(bv->bytedata[(i+BitsPerPointer)/8] >> (i+BitsPerPointer)%8 & 3) {
+ default:
+ runtime·throw("unexpected garbage collection bits");
case BitsIface:
dumpint(FieldKindIface);
dumpint(offset + i / BitsPerPointer * PtrSize);
@@ -335,7 +311,7 @@ dumpframe(Stkframe *s, void *arg)
dumpbvtypes(&child->args, (byte*)s->sp + child->argoff);
if(stackmap != nil && stackmap->n > 0) {
bv = runtime·stackmapdata(stackmap, pcdata);
- dumpbvtypes(&bv, s->varp - bv.n / BitsPerPointer * PtrSize);
+ dumpbvtypes(&bv, (byte*)(s->varp - bv.n / BitsPerPointer * PtrSize));
} else {
bv.n = -1;
}
@@ -368,26 +344,26 @@ dumpframe(Stkframe *s, void *arg)
// Dump fields in the local vars section
if(stackmap == nil) {
// No locals information, dump everything.
- for(off = child->arglen; off < s->varp - (byte*)s->sp; off += PtrSize) {
+ for(off = child->arglen; off < s->varp - s->sp; off += PtrSize) {
dumpint(FieldKindPtr);
dumpint(off);
}
} else if(stackmap->n < 0) {
// Locals size information, dump just the locals.
size = -stackmap->n;
- for(off = s->varp - size - (byte*)s->sp; off < s->varp - (byte*)s->sp; off += PtrSize) {
+ for(off = s->varp - size - s->sp; off < s->varp - s->sp; off += PtrSize) {
dumpint(FieldKindPtr);
dumpint(off);
}
} else if(stackmap->n > 0) {
// Locals bitmap information, scan just the pointers in
// locals.
- dumpbv(&bv, s->varp - bv.n / BitsPerPointer * PtrSize - (byte*)s->sp);
+ dumpbv(&bv, s->varp - bv.n / BitsPerPointer * PtrSize - s->sp);
}
dumpint(FieldKindEol);
// Record arg info for parent.
- child->argoff = s->argp - (byte*)s->fp;
+ child->argoff = s->argp - s->fp;
child->arglen = s->arglen;
child->sp = (byte*)s->sp;
child->depth++;
@@ -406,8 +382,9 @@ dumpgoroutine(G *gp)
ChildInfo child;
Defer *d;
Panic *p;
+ bool (*fn)(Stkframe*, void*);
- if(gp->syscallstack != (uintptr)nil) {
+ if(gp->syscallsp != (uintptr)nil) {
sp = gp->syscallsp;
pc = gp->syscallpc;
lr = 0;
@@ -422,11 +399,11 @@ dumpgoroutine(G *gp)
dumpint((uintptr)sp);
dumpint(gp->goid);
dumpint(gp->gopc);
- dumpint(gp->status);
+ dumpint(runtime·readgstatus(gp));
dumpbool(gp->issystem);
- dumpbool(gp->isbackground);
+ dumpbool(false); // isbackground
dumpint(gp->waitsince);
- dumpcstr(gp->waitreason);
+ dumpstr(gp->waitreason);
dumpint((uintptr)gp->sched.ctxt);
dumpint((uintptr)gp->m);
dumpint((uintptr)gp->defer);
@@ -437,9 +414,8 @@ dumpgoroutine(G *gp)
child.arglen = 0;
child.sp = nil;
child.depth = 0;
- if(!ScanStackByFrames)
- runtime·throw("need frame info to dump stacks");
- runtime·gentraceback(pc, sp, lr, gp, 0, nil, 0x7fffffff, dumpframe, &child, false);
+ fn = dumpframe;
+ runtime·gentraceback(pc, sp, lr, gp, 0, nil, 0x7fffffff, &fn, &child, 0);
// dump defer & panic records
for(d = gp->defer; d != nil; d = d->link) {
@@ -458,7 +434,7 @@ dumpgoroutine(G *gp)
dumpint((uintptr)gp);
dumpint((uintptr)p->arg.type);
dumpint((uintptr)p->arg.data);
- dumpint((uintptr)p->defer);
+ dumpint(0); // was p->defer, no longer recorded
dumpint((uintptr)p->link);
}
}
@@ -468,14 +444,16 @@ dumpgs(void)
{
G *gp;
uint32 i;
+ uint32 status;
// goroutines & stacks
for(i = 0; i < runtime·allglen; i++) {
gp = runtime·allg[i];
- switch(gp->status){
+ status = runtime·readgstatus(gp); // The world is stopped so gp will not be in a scan state.
+ switch(status){
default:
- runtime·printf("unexpected G.status %d\n", gp->status);
- runtime·throw("mark - bad status");
+ runtime·printf("runtime: unexpected G.status %d\n", status);
+ runtime·throw("dumpgs in STW - bad status");
case Gdead:
break;
case Grunnable:
@@ -510,42 +488,30 @@ dumproots(void)
byte *p;
// data segment
+ dumpbvtypes(&runtime·gcdatamask, runtime·data);
dumpint(TagData);
- dumpint((uintptr)data);
- dumpmemrange(data, edata - data);
- dumpfields((uintptr*)gcdata + 1);
+ dumpint((uintptr)runtime·data);
+ dumpmemrange(runtime·data, runtime·edata - runtime·data);
+ dumpfields(runtime·gcdatamask);
// bss segment
+ dumpbvtypes(&runtime·gcbssmask, runtime·bss);
dumpint(TagBss);
- dumpint((uintptr)bss);
- dumpmemrange(bss, ebss - bss);
- dumpfields((uintptr*)gcbss + 1);
-
+ dumpint((uintptr)runtime·bss);
+ dumpmemrange(runtime·bss, runtime·ebss - runtime·bss);
+ dumpfields(runtime·gcbssmask);
+
// MSpan.types
allspans = runtime·mheap.allspans;
for(spanidx=0; spanidx<runtime·mheap.nspan; spanidx++) {
s = allspans[spanidx];
if(s->state == MSpanInUse) {
- // The garbage collector ignores type pointers stored in MSpan.types:
- // - Compiler-generated types are stored outside of heap.
- // - The reflect package has runtime-generated types cached in its data structures.
- // The garbage collector relies on finding the references via that cache.
- switch(s->types.compression) {
- case MTypes_Empty:
- case MTypes_Single:
- break;
- case MTypes_Words:
- case MTypes_Bytes:
- dumpotherroot("runtime type info", (byte*)s->types.data);
- break;
- }
-
// Finalizers
for(sp = s->specials; sp != nil; sp = sp->next) {
if(sp->kind != KindSpecialFinalizer)
continue;
spf = (SpecialFinalizer*)sp;
- p = (byte*)((s->start << PageShift) + spf->offset);
+ p = (byte*)((s->start << PageShift) + spf->special.offset);
dumpfinalizer(p, spf->fn, spf->fint, spf->ot);
}
}
@@ -555,18 +521,18 @@ dumproots(void)
runtime·iterate_finq(finq_callback);
}
-// Bit vector of free marks.
-// Needs to be as big as the largest number of objects per span.
-static byte free[PageSize/8];
+// Bit vector of free marks.
+// Needs to be as big as the largest number of objects per span.
+#pragma dataflag NOPTR
+static byte free[PageSize/8];
static void
dumpobjs(void)
{
- uintptr i, j, size, n, off, shift, *bitp, bits, ti, kind;
+ uintptr i, j, size, n;
MSpan *s;
MLink *l;
byte *p;
- Type *t;
for(i = 0; i < runtime·mheap.nspan; i++) {
s = runtime·mheap.allspans[i];
@@ -575,36 +541,16 @@ dumpobjs(void)
p = (byte*)(s->start << PageShift);
size = s->elemsize;
n = (s->npages << PageShift) / size;
- if(n > PageSize/8)
- runtime·throw("free array doesn't have enough entries");
- for(l = s->freelist; l != nil; l = l->next) {
- free[((byte*)l - p) / size] = true;
- }
+ if(n > nelem(free))
+ runtime·throw("free array doesn't have enough entries");
+ for(l = s->freelist; l != nil; l = l->next)
+ free[((byte*)l - p) / size] = true;
for(j = 0; j < n; j++, p += size) {
- if(free[j]) {
- free[j] = false;
- continue;
+ if(free[j]) {
+ free[j] = false;
+ continue;
}
- off = (uintptr*)p - (uintptr*)runtime·mheap.arena_start;
- bitp = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
- shift = off % wordsPerBitmapWord;
- bits = *bitp >> shift;
-
- // Skip FlagNoGC allocations (stacks)
- if((bits & bitAllocated) == 0)
- continue;
-
- // extract type and kind
- ti = runtime·gettype(p);
- t = (Type*)(ti & ~(uintptr)(PtrSize-1));
- kind = ti & (PtrSize-1);
-
- // dump it
- if(kind == TypeInfo_Chan)
- t = ((ChanType*)t)->elem; // use element type for chan encoding
- if(t == nil && scannable(p))
- kind = TypeInfo_Conservative; // special kind for conservatively scanned objects
- dumpobj(p, size, t, kind);
+ dumpobj(p, size, makeheapobjbv(p, size));
}
}
}
@@ -621,7 +567,6 @@ dumpparams(void)
else
dumpbool(true); // big-endian ptrs
dumpint(PtrSize);
- dumpint(runtime·Hchansize);
dumpint((uintptr)runtime·mheap.arena_start);
dumpint((uintptr)runtime·mheap.arena_used);
dumpint(thechar);
@@ -634,16 +579,38 @@ itab_callback(Itab *tab)
{
Type *t;
- dumpint(TagItab);
- dumpint((uintptr)tab);
t = tab->type;
- dumpbool(t->size > PtrSize || (t->kind & KindNoPointers) == 0);
+ // Dump a map from itab* to the type of its data field.
+ // We want this map so we can deduce types of interface referents.
+ if((t->kind & KindDirectIface) == 0) {
+ // indirect - data slot is a pointer to t.
+ dumptype(t->ptrto);
+ dumpint(TagItab);
+ dumpint((uintptr)tab);
+ dumpint((uintptr)t->ptrto);
+ } else if((t->kind & KindNoPointers) == 0) {
+ // t is pointer-like - data slot is a t.
+ dumptype(t);
+ dumpint(TagItab);
+ dumpint((uintptr)tab);
+ dumpint((uintptr)t);
+ } else {
+ // Data slot is a scalar. Dump type just for fun.
+ // With pointer-only interfaces, this shouldn't happen.
+ dumptype(t);
+ dumpint(TagItab);
+ dumpint((uintptr)tab);
+ dumpint((uintptr)t);
+ }
}
static void
dumpitabs(void)
{
- runtime·iterate_itabs(itab_callback);
+ void (*fn)(Itab*);
+
+ fn = itab_callback;
+ runtime·iterate_itabs(&fn);
}
static void
@@ -742,8 +709,10 @@ dumpmemprof(void)
Special *sp;
SpecialProfile *spp;
byte *p;
-
- runtime·iterate_memprof(dumpmemprof_callback);
+ void (*fn)(Bucket*, uintptr, uintptr*, uintptr, uintptr, uintptr);
+
+ fn = dumpmemprof_callback;
+ runtime·iterate_memprof(&fn);
allspans = runtime·mheap.allspans;
for(spanidx=0; spanidx<runtime·mheap.nspan; spanidx++) {
@@ -754,7 +723,7 @@ dumpmemprof(void)
if(sp->kind != KindSpecialProfile)
continue;
spp = (SpecialProfile*)sp;
- p = (byte*)((s->start << PageShift) + spp->offset);
+ p = (byte*)((s->start << PageShift) + spp->special.offset);
dumpint(TagAllocSample);
dumpint((uintptr)p);
dumpint((uintptr)spp->b);
@@ -763,7 +732,7 @@ dumpmemprof(void)
}
static void
-mdump(G *gp)
+mdump(void)
{
byte *hdr;
uintptr i;
@@ -777,7 +746,7 @@ mdump(G *gp)
}
runtime·memclr((byte*)&typecache[0], sizeof(typecache));
- hdr = (byte*)"go1.3 heap dump\n";
+ hdr = (byte*)"go1.4 heap dump\n";
write(hdr, runtime·findnull(hdr));
dumpparams();
dumpitabs();
@@ -789,20 +758,18 @@ mdump(G *gp)
dumpmemprof();
dumpint(TagEOF);
flush();
-
- gp->param = nil;
- gp->status = Grunning;
- runtime·gogo(&gp->sched);
}
void
-runtime∕debug·WriteHeapDump(uintptr fd)
+runtime·writeheapdump_m(void)
{
- // Stop the world.
- runtime·semacquire(&runtime·worldsema, false);
- m->gcing = 1;
- m->locks++;
- runtime·stoptheworld();
+ uintptr fd;
+
+ fd = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+
+ runtime·casgstatus(g->m->curg, Grunning, Gwaiting);
+ g->waitreason = runtime·gostringnocopy((byte*)"dumping heap");
// Update stats so we can dump them.
// As a side effect, flushes all the MCaches so the MSpan.freelist
@@ -812,147 +779,31 @@ runtime∕debug·WriteHeapDump(uintptr fd)
// Set dump file.
dumpfd = fd;
- // Call dump routine on M stack.
- g->status = Gwaiting;
- g->waitreason = "dumping heap";
- runtime·mcall(mdump);
+ // Call dump routine.
+ mdump();
// Reset dump file.
dumpfd = 0;
-
- // Start up the world again.
- m->gcing = 0;
- runtime·semrelease(&runtime·worldsema);
- runtime·starttheworld();
- m->locks--;
-}
-
-// Runs the specified gc program. Calls the callback for every
-// pointer-like field specified by the program and passes to the
-// callback the kind and offset of that field within the object.
-// offset is the offset in the object of the start of the program.
-// Returns a pointer to the opcode that ended the gc program (either
-// GC_END or GC_ARRAY_NEXT).
-static uintptr*
-playgcprog(uintptr offset, uintptr *prog, void (*callback)(void*,uintptr,uintptr), void *arg)
-{
- uintptr len, elemsize, i, *end;
-
- for(;;) {
- switch(prog[0]) {
- case GC_END:
- return prog;
- case GC_PTR:
- callback(arg, FieldKindPtr, offset + prog[1]);
- prog += 3;
- break;
- case GC_APTR:
- callback(arg, FieldKindPtr, offset + prog[1]);
- prog += 2;
- break;
- case GC_ARRAY_START:
- len = prog[2];
- elemsize = prog[3];
- end = nil;
- for(i = 0; i < len; i++) {
- end = playgcprog(offset + prog[1] + i * elemsize, prog + 4, callback, arg);
- if(end[0] != GC_ARRAY_NEXT)
- runtime·throw("GC_ARRAY_START did not have matching GC_ARRAY_NEXT");
- }
- prog = end + 1;
- break;
- case GC_ARRAY_NEXT:
- return prog;
- case GC_CALL:
- playgcprog(offset + prog[1], (uintptr*)((byte*)prog + *(int32*)&prog[2]), callback, arg);
- prog += 3;
- break;
- case GC_CHAN_PTR:
- callback(arg, FieldKindPtr, offset + prog[1]);
- prog += 3;
- break;
- case GC_STRING:
- callback(arg, FieldKindString, offset + prog[1]);
- prog += 2;
- break;
- case GC_EFACE:
- callback(arg, FieldKindEface, offset + prog[1]);
- prog += 2;
- break;
- case GC_IFACE:
- callback(arg, FieldKindIface, offset + prog[1]);
- prog += 2;
- break;
- case GC_SLICE:
- callback(arg, FieldKindSlice, offset + prog[1]);
- prog += 3;
- break;
- case GC_REGION:
- playgcprog(offset + prog[1], (uintptr*)prog[3] + 1, callback, arg);
- prog += 4;
- break;
- default:
- runtime·printf("%D\n", (uint64)prog[0]);
- runtime·throw("bad gc op");
- }
+ if(tmpbuf != nil) {
+ runtime·SysFree(tmpbuf, tmpbufsize, &mstats.other_sys);
+ tmpbuf = nil;
+ tmpbufsize = 0;
}
-}
-static void
-dump_callback(void *p, uintptr kind, uintptr offset)
-{
- USED(&p);
- dumpint(kind);
- dumpint(offset);
+ runtime·casgstatus(g->m->curg, Gwaiting, Grunning);
}
// dumpint() the kind & offset of each field in an object.
static void
-dumpfields(uintptr *prog)
+dumpfields(BitVector bv)
{
- playgcprog(0, prog, dump_callback, nil);
+ dumpbv(&bv, 0);
dumpint(FieldKindEol);
}
-static void
-dumpeface_callback(void *p, uintptr kind, uintptr offset)
-{
- Eface *e;
-
- if(kind != FieldKindEface)
- return;
- e = (Eface*)((byte*)p + offset);
- dumptype(e->type);
-}
-
// The heap dump reader needs to be able to disambiguate
// Eface entries. So it needs to know every type that might
-// appear in such an entry. The following two routines accomplish
-// that.
-
-// Dump all the types that appear in the type field of
-// any Eface contained in obj.
-static void
-dumpefacetypes(void *obj, uintptr size, Type *type, uintptr kind)
-{
- uintptr i;
-
- switch(kind) {
- case TypeInfo_SingleObject:
- playgcprog(0, (uintptr*)type->gc + 1, dumpeface_callback, obj);
- break;
- case TypeInfo_Array:
- for(i = 0; i <= size - type->size; i += type->size)
- playgcprog(i, (uintptr*)type->gc + 1, dumpeface_callback, obj);
- break;
- case TypeInfo_Chan:
- if(type->size == 0) // channels may have zero-sized objects in them
- break;
- for(i = runtime·Hchansize; i <= size - type->size; i += type->size)
- playgcprog(i, (uintptr*)type->gc + 1, dumpeface_callback, obj);
- break;
- }
-}
+// appear in such an entry. The following routine accomplishes that.
// Dump all the types that appear in the type field of
// any Eface described by this bit vector.
@@ -962,16 +813,14 @@ dumpbvtypes(BitVector *bv, byte *base)
uintptr i;
for(i = 0; i < bv->n; i += BitsPerPointer) {
- if((bv->data[i/32] >> i%32 & 3) != BitsMultiWord)
+ if((bv->bytedata[i/8] >> i%8 & 3) != BitsMultiWord)
continue;
- switch(bv->data[(i+BitsPerPointer)/32] >> (i+BitsPerPointer)%32 & 3) {
- case BitsString:
+ switch(bv->bytedata[(i+BitsPerPointer)/8] >> (i+BitsPerPointer)%8 & 3) {
+ default:
+ runtime·throw("unexpected garbage collection bits");
case BitsIface:
i += BitsPerPointer;
break;
- case BitsSlice:
- i += 2 * BitsPerPointer;
- break;
case BitsEface:
dumptype(*(Type**)(base + i / BitsPerPointer * PtrSize));
i += BitsPerPointer;
@@ -979,3 +828,37 @@ dumpbvtypes(BitVector *bv, byte *base)
}
}
}
+
+static BitVector
+makeheapobjbv(byte *p, uintptr size)
+{
+ uintptr off, nptr, i;
+ byte shift, *bitp, bits;
+ bool mw;
+
+ // Extend the temp buffer if necessary.
+ nptr = size/PtrSize;
+ if(tmpbufsize < nptr*BitsPerPointer/8+1) {
+ if(tmpbuf != nil)
+ runtime·SysFree(tmpbuf, tmpbufsize, &mstats.other_sys);
+ tmpbufsize = nptr*BitsPerPointer/8+1;
+ tmpbuf = runtime·sysAlloc(tmpbufsize, &mstats.other_sys);
+ if(tmpbuf == nil)
+ runtime·throw("heapdump: out of memory");
+ }
+
+ // Copy and compact the bitmap.
+ mw = false;
+ for(i = 0; i < nptr; i++) {
+ off = (uintptr*)(p + i*PtrSize) - (uintptr*)runtime·mheap.arena_start;
+ bitp = runtime·mheap.arena_start - off/wordsPerBitmapByte - 1;
+ shift = (off % wordsPerBitmapByte) * gcBits;
+ bits = (*bitp >> (shift + 2)) & BitsMask;
+ if(!mw && bits == BitsDead)
+ break; // end of heap object
+ mw = !mw && bits == BitsMultiWord;
+ tmpbuf[i*BitsPerPointer/8] &= ~(BitsMask<<((i*BitsPerPointer)%8));
+ tmpbuf[i*BitsPerPointer/8] |= bits<<((i*BitsPerPointer)%8);
+ }
+ return (BitVector){i*BitsPerPointer, tmpbuf};
+}
diff --git a/src/runtime/iface.go b/src/runtime/iface.go
new file mode 100644
index 000000000..f60b6a79c
--- /dev/null
+++ b/src/runtime/iface.go
@@ -0,0 +1,439 @@
+// 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"
+)
+
+const (
+ hashSize = 1009
+)
+
+var (
+ ifaceLock mutex // lock for accessing hash
+ 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 {
+ gothrow("internal error - misuse of itab")
+ }
+
+ // easy case
+ x := typ.x
+ if x == nil {
+ if canfail {
+ return nil
+ }
+ i := (*imethod)(add(unsafe.Pointer(inter), unsafe.Sizeof(interfacetype{})))
+ panic(&TypeAssertionError{"", *typ._string, *inter.typ._string, *i.name})
+ }
+
+ // compiler has provided some good hash codes for us.
+ h := inter.typ.hash
+ h += 17 * typ.hash
+ // TODO(rsc): h += 23 * x.mhash ?
+ h %= hashSize
+
+ // look twice - once without lock, once with.
+ // common case will be no lock contention.
+ var m *itab
+ var locked int
+ for locked = 0; locked < 2; locked++ {
+ if locked != 0 {
+ lock(&ifaceLock)
+ }
+ for m = (*itab)(atomicloadp(unsafe.Pointer(&hash[h]))); m != nil; m = m.link {
+ if m.inter == inter && m._type == typ {
+ if m.bad != 0 {
+ m = nil
+ if !canfail {
+ // this can only happen if the conversion
+ // was already done once using the , ok form
+ // and we have a cached negative result.
+ // the cached result doesn't record which
+ // interface function was missing, so jump
+ // down to the interface check, which will
+ // do more work but give a better error.
+ goto search
+ }
+ }
+ if locked != 0 {
+ unlock(&ifaceLock)
+ }
+ return m
+ }
+ }
+ }
+
+ m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr))*ptrSize, 0, &memstats.other_sys))
+ m.inter = inter
+ m._type = typ
+
+search:
+ // both inter and typ have method sorted by name,
+ // and interface names are unique,
+ // so can iterate over both in lock step;
+ // the loop is O(ni+nt) not O(ni*nt).
+ ni := len(inter.mhdr)
+ nt := len(x.mhdr)
+ j := 0
+ for k := 0; k < ni; k++ {
+ i := (*imethod)(add(unsafe.Pointer(inter), unsafe.Sizeof(interfacetype{})+uintptr(k)*unsafe.Sizeof(imethod{})))
+ iname := i.name
+ ipkgpath := i.pkgpath
+ itype := i._type
+ for ; j < nt; j++ {
+ t := (*method)(add(unsafe.Pointer(x), unsafe.Sizeof(uncommontype{})+uintptr(j)*unsafe.Sizeof(method{})))
+ if t.mtyp == itype && t.name == iname && t.pkgpath == ipkgpath {
+ if m != nil {
+ *(*unsafe.Pointer)(add(unsafe.Pointer(m), unsafe.Sizeof(itab{})+uintptr(k)*ptrSize)) = t.ifn
+ }
+ goto nextimethod
+ }
+ }
+ // didn't find method
+ if !canfail {
+ if locked != 0 {
+ unlock(&ifaceLock)
+ }
+ panic(&TypeAssertionError{"", *typ._string, *inter.typ._string, *iname})
+ }
+ m.bad = 1
+ break
+ nextimethod:
+ }
+ if locked == 0 {
+ gothrow("invalid itab locking")
+ }
+ m.link = hash[h]
+ atomicstorep(unsafe.Pointer(&hash[h]), unsafe.Pointer(m))
+ unlock(&ifaceLock)
+ if m.bad != 0 {
+ return nil
+ }
+ return m
+}
+
+func typ2Itab(t *_type, inter *interfacetype, cache **itab) *itab {
+ tab := getitab(inter, t, false)
+ atomicstorep(unsafe.Pointer(cache), unsafe.Pointer(tab))
+ return tab
+}
+
+func convT2E(t *_type, elem unsafe.Pointer) (e interface{}) {
+ size := uintptr(t.size)
+ ep := (*eface)(unsafe.Pointer(&e))
+ if isDirectIface(t) {
+ ep._type = t
+ memmove(unsafe.Pointer(&ep.data), elem, size)
+ } else {
+ x := newobject(t)
+ // TODO: We allocate a zeroed object only to overwrite it with
+ // actual data. Figure out how to avoid zeroing. Also below in convT2I.
+ memmove(x, elem, size)
+ ep._type = t
+ ep.data = x
+ }
+ return
+}
+
+func convT2I(t *_type, inter *interfacetype, cache **itab, elem unsafe.Pointer) (i fInterface) {
+ tab := (*itab)(atomicloadp(unsafe.Pointer(cache)))
+ if tab == nil {
+ tab = getitab(inter, t, false)
+ atomicstorep(unsafe.Pointer(cache), unsafe.Pointer(tab))
+ }
+ size := uintptr(t.size)
+ pi := (*iface)(unsafe.Pointer(&i))
+ if isDirectIface(t) {
+ pi.tab = tab
+ memmove(unsafe.Pointer(&pi.data), elem, size)
+ } else {
+ x := newobject(t)
+ memmove(x, elem, size)
+ pi.tab = tab
+ pi.data = x
+ }
+ return
+}
+
+// TODO: give these routines a pointer to the result area instead of writing
+// extra data in the outargs section. Then we can get rid of go:nosplit.
+//go:nosplit
+func assertI2T(t *_type, i fInterface) (r struct{}) {
+ ip := (*iface)(unsafe.Pointer(&i))
+ tab := ip.tab
+ if tab == nil {
+ panic(&TypeAssertionError{"", "", *t._string, ""})
+ }
+ if tab._type != t {
+ panic(&TypeAssertionError{*tab.inter.typ._string, *tab._type._string, *t._string, ""})
+ }
+ size := uintptr(t.size)
+ if isDirectIface(t) {
+ memmove(unsafe.Pointer(&r), unsafe.Pointer(&ip.data), size)
+ } else {
+ memmove(unsafe.Pointer(&r), ip.data, size)
+ }
+ return
+}
+
+//go:nosplit
+func assertI2T2(t *_type, i fInterface) (r byte) {
+ ip := (*iface)(unsafe.Pointer(&i))
+ size := uintptr(t.size)
+ ok := (*bool)(add(unsafe.Pointer(&r), size))
+ tab := ip.tab
+ if tab == nil || tab._type != t {
+ *ok = false
+ memclr(unsafe.Pointer(&r), size)
+ return
+ }
+ *ok = true
+ if isDirectIface(t) {
+ memmove(unsafe.Pointer(&r), unsafe.Pointer(&ip.data), size)
+ } else {
+ memmove(unsafe.Pointer(&r), ip.data, size)
+ }
+ return
+}
+
+func assertI2TOK(t *_type, i fInterface) bool {
+ ip := (*iface)(unsafe.Pointer(&i))
+ tab := ip.tab
+ return tab != nil && tab._type == t
+}
+
+//go:nosplit
+func assertE2T(t *_type, e interface{}) (r struct{}) {
+ ep := (*eface)(unsafe.Pointer(&e))
+ if ep._type == nil {
+ panic(&TypeAssertionError{"", "", *t._string, ""})
+ }
+ if ep._type != t {
+ panic(&TypeAssertionError{"", *ep._type._string, *t._string, ""})
+ }
+ size := uintptr(t.size)
+ if isDirectIface(t) {
+ memmove(unsafe.Pointer(&r), unsafe.Pointer(&ep.data), size)
+ } else {
+ memmove(unsafe.Pointer(&r), ep.data, size)
+ }
+ return
+}
+
+//go:nosplit
+func assertE2T2(t *_type, e interface{}) (r byte) {
+ ep := (*eface)(unsafe.Pointer(&e))
+ size := uintptr(t.size)
+ ok := (*bool)(add(unsafe.Pointer(&r), size))
+ if ep._type != t {
+ *ok = false
+ memclr(unsafe.Pointer(&r), size)
+ return
+ }
+ *ok = true
+ if isDirectIface(t) {
+ memmove(unsafe.Pointer(&r), unsafe.Pointer(&ep.data), size)
+ } else {
+ memmove(unsafe.Pointer(&r), ep.data, size)
+ }
+ return
+}
+
+func assertE2TOK(t *_type, e interface{}) bool {
+ ep := (*eface)(unsafe.Pointer(&e))
+ return t == ep._type
+}
+
+func convI2E(i fInterface) (r interface{}) {
+ ip := (*iface)(unsafe.Pointer(&i))
+ tab := ip.tab
+ if tab == nil {
+ return
+ }
+ rp := (*eface)(unsafe.Pointer(&r))
+ rp._type = tab._type
+ rp.data = ip.data
+ return
+}
+
+func assertI2E(inter *interfacetype, i fInterface) (r interface{}) {
+ ip := (*iface)(unsafe.Pointer(&i))
+ tab := ip.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
+ return
+}
+
+func assertI2E2(inter *interfacetype, i fInterface) (r interface{}, ok bool) {
+ ip := (*iface)(unsafe.Pointer(&i))
+ tab := ip.tab
+ if tab == nil {
+ return
+ }
+ rp := (*eface)(unsafe.Pointer(&r))
+ rp._type = tab._type
+ rp.data = ip.data
+ ok = true
+ return
+}
+
+func convI2I(inter *interfacetype, i fInterface) (r fInterface) {
+ ip := (*iface)(unsafe.Pointer(&i))
+ tab := ip.tab
+ if tab == nil {
+ return
+ }
+ rp := (*iface)(unsafe.Pointer(&r))
+ if tab.inter == inter {
+ rp.tab = tab
+ rp.data = ip.data
+ return
+ }
+ rp.tab = getitab(inter, tab._type, false)
+ rp.data = ip.data
+ return
+}
+
+func assertI2I(inter *interfacetype, i fInterface) (r fInterface) {
+ ip := (*iface)(unsafe.Pointer(&i))
+ tab := ip.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
+ return
+ }
+ rp.tab = getitab(inter, tab._type, false)
+ rp.data = ip.data
+ return
+}
+
+func assertI2I2(inter *interfacetype, i fInterface) (r fInterface, ok bool) {
+ ip := (*iface)(unsafe.Pointer(&i))
+ tab := ip.tab
+ if tab == nil {
+ return
+ }
+ rp := (*iface)(unsafe.Pointer(&r))
+ if tab.inter == inter {
+ rp.tab = tab
+ rp.data = ip.data
+ ok = true
+ return
+ }
+ tab = getitab(inter, tab._type, true)
+ if tab == nil {
+ rp.data = nil
+ rp.tab = nil
+ ok = false
+ return
+ }
+ rp.tab = tab
+ rp.data = ip.data
+ ok = true
+ return
+}
+
+func assertE2I(inter *interfacetype, e interface{}) (r fInterface) {
+ ep := (*eface)(unsafe.Pointer(&e))
+ t := ep._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
+ return
+}
+
+func assertE2I2(inter *interfacetype, e interface{}) (r fInterface, ok bool) {
+ ep := (*eface)(unsafe.Pointer(&e))
+ t := ep._type
+ if t == nil {
+ return
+ }
+ tab := getitab(inter, t, true)
+ if tab == nil {
+ return
+ }
+ rp := (*iface)(unsafe.Pointer(&r))
+ rp.tab = tab
+ rp.data = ep.data
+ ok = true
+ return
+}
+
+func reflect_ifaceE2I(inter *interfacetype, e interface{}, dst *fInterface) {
+ *dst = assertE2I(inter, e)
+}
+
+func assertE2E(inter *interfacetype, e interface{}) interface{} {
+ ep := (*eface)(unsafe.Pointer(&e))
+ if ep._type == nil {
+ // explicit conversions require non-nil interface value.
+ panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
+ }
+ return e
+}
+
+func assertE2E2(inter *interfacetype, e interface{}) (interface{}, bool) {
+ ep := (*eface)(unsafe.Pointer(&e))
+ if ep._type == nil {
+ return nil, false
+ }
+ return e, true
+}
+
+func ifacethash(i fInterface) uint32 {
+ ip := (*iface)(unsafe.Pointer(&i))
+ tab := ip.tab
+ if tab == nil {
+ return 0
+ }
+ return tab._type.hash
+}
+
+func efacethash(e interface{}) uint32 {
+ ep := (*eface)(unsafe.Pointer(&e))
+ t := ep._type
+ if t == nil {
+ return 0
+ }
+ return t.hash
+}
+
+func iterate_itabs(fn func(*itab)) {
+ for _, h := range &hash {
+ for ; h != nil; h = h.link {
+ fn(h)
+ }
+ }
+}
+
+func ifaceE2I2(inter *interfacetype, e interface{}, r *fInterface) (ok bool) {
+ *r, ok = assertE2I2(inter, e)
+ return
+}
diff --git a/src/pkg/runtime/iface_test.go b/src/runtime/iface_test.go
index bca0ea0ee..bca0ea0ee 100644
--- a/src/pkg/runtime/iface_test.go
+++ b/src/runtime/iface_test.go
diff --git a/src/pkg/runtime/lfstack.goc b/src/runtime/lfstack.c
index f7b8effa0..57e0af282 100644
--- a/src/pkg/runtime/lfstack.goc
+++ b/src/runtime/lfstack.c
@@ -3,8 +3,8 @@
// license that can be found in the LICENSE file.
// Lock-free stack.
+// The following code runs only on g0 stack.
-package runtime
#include "runtime.h"
#include "arch_GOARCH.h"
@@ -72,10 +72,16 @@ runtime·lfstackpop(uint64 *head)
}
}
-func lfstackpush_go(head *uint64, node *LFNode) {
- runtime·lfstackpush(head, node);
+void
+runtime·lfstackpush_m(void)
+{
+ runtime·lfstackpush(g->m->ptrarg[0], g->m->ptrarg[1]);
+ g->m->ptrarg[0] = nil;
+ g->m->ptrarg[1] = nil;
}
-func lfstackpop_go(head *uint64) (node *LFNode) {
- node = runtime·lfstackpop(head);
+void
+runtime·lfstackpop_m(void)
+{
+ g->m->ptrarg[0] = runtime·lfstackpop(g->m->ptrarg[0]);
}
diff --git a/src/pkg/runtime/lfstack_test.go b/src/runtime/lfstack_test.go
index e51877704..e51877704 100644
--- a/src/pkg/runtime/lfstack_test.go
+++ b/src/runtime/lfstack_test.go
diff --git a/src/runtime/lock_futex.go b/src/runtime/lock_futex.go
new file mode 100644
index 000000000..725962341
--- /dev/null
+++ b/src/runtime/lock_futex.go
@@ -0,0 +1,205 @@
+// 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 dragonfly freebsd linux
+
+package runtime
+
+import "unsafe"
+
+// This implementation depends on OS-specific implementations of
+//
+// runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
+// Atomically,
+// if(*addr == val) sleep
+// Might be woken up spuriously; that's allowed.
+// Don't sleep longer than ns; ns < 0 means forever.
+//
+// runtime·futexwakeup(uint32 *addr, uint32 cnt)
+// If any procs are sleeping on addr, wake up at most cnt.
+
+const (
+ mutex_unlocked = 0
+ mutex_locked = 1
+ mutex_sleeping = 2
+
+ active_spin = 4
+ active_spin_cnt = 30
+ passive_spin = 1
+)
+
+// Possible lock states are mutex_unlocked, mutex_locked and mutex_sleeping.
+// mutex_sleeping means that there is presumably at least one sleeping thread.
+// Note that there can be spinning threads during all states - they do not
+// affect mutex's state.
+
+func futexsleep(addr *uint32, val uint32, ns int64)
+func futexwakeup(addr *uint32, cnt uint32)
+
+// We use the uintptr mutex.key and note.key as a uint32.
+func key32(p *uintptr) *uint32 {
+ return (*uint32)(unsafe.Pointer(p))
+}
+
+func lock(l *mutex) {
+ gp := getg()
+
+ if gp.m.locks < 0 {
+ gothrow("runtime·lock: lock count")
+ }
+ gp.m.locks++
+
+ // Speculative grab for lock.
+ v := xchg(key32(&l.key), mutex_locked)
+ if v == mutex_unlocked {
+ return
+ }
+
+ // wait is either MUTEX_LOCKED or MUTEX_SLEEPING
+ // depending on whether there is a thread sleeping
+ // on this mutex. If we ever change l->key from
+ // MUTEX_SLEEPING to some other value, we must be
+ // careful to change it back to MUTEX_SLEEPING before
+ // returning, to ensure that the sleeping thread gets
+ // its wakeup call.
+ wait := v
+
+ // On uniprocessors, no point spinning.
+ // On multiprocessors, spin for ACTIVE_SPIN attempts.
+ spin := 0
+ if ncpu > 1 {
+ spin = active_spin
+ }
+ for {
+ // Try for lock, spinning.
+ for i := 0; i < spin; i++ {
+ for l.key == mutex_unlocked {
+ if cas(key32(&l.key), mutex_unlocked, wait) {
+ return
+ }
+ }
+ procyield(active_spin_cnt)
+ }
+
+ // Try for lock, rescheduling.
+ for i := 0; i < passive_spin; i++ {
+ for l.key == mutex_unlocked {
+ if cas(key32(&l.key), mutex_unlocked, wait) {
+ return
+ }
+ }
+ osyield()
+ }
+
+ // Sleep.
+ v = xchg(key32(&l.key), mutex_sleeping)
+ if v == mutex_unlocked {
+ return
+ }
+ wait = mutex_sleeping
+ futexsleep(key32(&l.key), mutex_sleeping, -1)
+ }
+}
+
+func unlock(l *mutex) {
+ v := xchg(key32(&l.key), mutex_unlocked)
+ if v == mutex_unlocked {
+ gothrow("unlock of unlocked lock")
+ }
+ if v == mutex_sleeping {
+ futexwakeup(key32(&l.key), 1)
+ }
+
+ gp := getg()
+ gp.m.locks--
+ if gp.m.locks < 0 {
+ gothrow("runtime·unlock: lock count")
+ }
+ if gp.m.locks == 0 && gp.preempt { // restore the preemption request in case we've cleared it in newstack
+ gp.stackguard0 = stackPreempt
+ }
+}
+
+// One-time notifications.
+func noteclear(n *note) {
+ n.key = 0
+}
+
+func notewakeup(n *note) {
+ old := xchg(key32(&n.key), 1)
+ if old != 0 {
+ print("notewakeup - double wakeup (", old, ")\n")
+ gothrow("notewakeup - double wakeup")
+ }
+ futexwakeup(key32(&n.key), 1)
+}
+
+func notesleep(n *note) {
+ gp := getg()
+ if gp != gp.m.g0 {
+ gothrow("notesleep not on g0")
+ }
+ for atomicload(key32(&n.key)) == 0 {
+ gp.m.blocked = true
+ futexsleep(key32(&n.key), 0, -1)
+ gp.m.blocked = false
+ }
+}
+
+//go:nosplit
+func notetsleep_internal(n *note, ns int64) bool {
+ gp := getg()
+
+ if ns < 0 {
+ for atomicload(key32(&n.key)) == 0 {
+ gp.m.blocked = true
+ futexsleep(key32(&n.key), 0, -1)
+ gp.m.blocked = false
+ }
+ return true
+ }
+
+ if atomicload(key32(&n.key)) != 0 {
+ return true
+ }
+
+ deadline := nanotime() + ns
+ for {
+ gp.m.blocked = true
+ futexsleep(key32(&n.key), 0, ns)
+ gp.m.blocked = false
+ if atomicload(key32(&n.key)) != 0 {
+ break
+ }
+ now := nanotime()
+ if now >= deadline {
+ break
+ }
+ ns = deadline - now
+ }
+ return atomicload(key32(&n.key)) != 0
+}
+
+func notetsleep(n *note, ns int64) bool {
+ gp := getg()
+ if gp != gp.m.g0 && gp.m.gcing == 0 {
+ gothrow("notetsleep not on g0")
+ }
+
+ return notetsleep_internal(n, ns)
+}
+
+// same as runtime·notetsleep, but called on user g (not g0)
+// calls only nosplit functions between entersyscallblock/exitsyscall
+func notetsleepg(n *note, ns int64) bool {
+ gp := getg()
+ if gp == gp.m.g0 {
+ gothrow("notetsleepg on g0")
+ }
+
+ entersyscallblock()
+ ok := notetsleep_internal(n, ns)
+ exitsyscall()
+ return ok
+}
diff --git a/src/runtime/lock_sema.go b/src/runtime/lock_sema.go
new file mode 100644
index 000000000..d136b8280
--- /dev/null
+++ b/src/runtime/lock_sema.go
@@ -0,0 +1,270 @@
+// 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 darwin nacl netbsd openbsd plan9 solaris windows
+
+package runtime
+
+import "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.
+//
+// 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.
+// 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.
+//
+const (
+ locked uintptr = 1
+
+ active_spin = 4
+ active_spin_cnt = 30
+ passive_spin = 1
+)
+
+func semacreate() uintptr
+func semasleep(int64) int32
+func semawakeup(mp *m)
+
+func lock(l *mutex) {
+ gp := getg()
+ if gp.m.locks < 0 {
+ gothrow("runtime·lock: lock count")
+ }
+ gp.m.locks++
+
+ // Speculative grab for lock.
+ if casuintptr(&l.key, 0, locked) {
+ return
+ }
+ if gp.m.waitsema == 0 {
+ gp.m.waitsema = semacreate()
+ }
+
+ // On uniprocessor's, no point spinning.
+ // On multiprocessors, spin for ACTIVE_SPIN attempts.
+ spin := 0
+ if ncpu > 1 {
+ spin = active_spin
+ }
+Loop:
+ for i := 0; ; i++ {
+ v := atomicloaduintptr(&l.key)
+ if v&locked == 0 {
+ // Unlocked. Try to lock.
+ if casuintptr(&l.key, v, v|locked) {
+ return
+ }
+ i = 0
+ }
+ if i < spin {
+ procyield(active_spin_cnt)
+ } else if i < spin+passive_spin {
+ osyield()
+ } else {
+ // Someone else has it.
+ // l->waitm points to a linked list of M's waiting
+ // for this lock, chained through m->nextwaitm.
+ // Queue this M.
+ for {
+ gp.m.nextwaitm = (*m)((unsafe.Pointer)(v &^ locked))
+ if casuintptr(&l.key, v, uintptr(unsafe.Pointer(gp.m))|locked) {
+ break
+ }
+ v = atomicloaduintptr(&l.key)
+ if v&locked == 0 {
+ continue Loop
+ }
+ }
+ if v&locked != 0 {
+ // Queued. Wait.
+ semasleep(-1)
+ i = 0
+ }
+ }
+ }
+}
+
+func unlock(l *mutex) {
+ gp := getg()
+ var mp *m
+ for {
+ v := atomicloaduintptr(&l.key)
+ if v == locked {
+ if 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, uintptr(unsafe.Pointer(mp.nextwaitm))) {
+ // Dequeued an M. Wake it.
+ semawakeup(mp)
+ break
+ }
+ }
+ }
+ gp.m.locks--
+ if gp.m.locks < 0 {
+ gothrow("runtime·unlock: lock count")
+ }
+ if gp.m.locks == 0 && gp.preempt { // restore the preemption request in case we've cleared it in newstack
+ gp.stackguard0 = stackPreempt
+ }
+}
+
+// One-time notifications.
+func noteclear(n *note) {
+ n.key = 0
+}
+
+func notewakeup(n *note) {
+ var v uintptr
+ for {
+ v = atomicloaduintptr(&n.key)
+ if casuintptr(&n.key, v, locked) {
+ break
+ }
+ }
+
+ // Successfully set waitm to locked.
+ // What was it before?
+ switch {
+ case v == 0:
+ // Nothing was waiting. Done.
+ case v == locked:
+ // Two notewakeups! Not allowed.
+ gothrow("notewakeup - double wakeup")
+ default:
+ // Must be the waiting m. Wake it up.
+ semawakeup((*m)(unsafe.Pointer(v)))
+ }
+}
+
+func notesleep(n *note) {
+ gp := getg()
+ if gp != gp.m.g0 {
+ gothrow("notesleep not on g0")
+ }
+ if gp.m.waitsema == 0 {
+ gp.m.waitsema = semacreate()
+ }
+ if !casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
+ // Must be locked (got wakeup).
+ if n.key != locked {
+ gothrow("notesleep - waitm out of sync")
+ }
+ return
+ }
+ // Queued. Sleep.
+ gp.m.blocked = true
+ semasleep(-1)
+ gp.m.blocked = false
+}
+
+//go:nosplit
+func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
+ // gp and deadline are logically local variables, but they are written
+ // as parameters so that the stack space they require is charged
+ // to the caller.
+ // This reduces the nosplit footprint of notetsleep_internal.
+ gp = getg()
+
+ // Register for wakeup on n->waitm.
+ if !casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
+ // Must be locked (got wakeup).
+ if n.key != locked {
+ gothrow("notetsleep - waitm out of sync")
+ }
+ return true
+ }
+ if ns < 0 {
+ // Queued. Sleep.
+ gp.m.blocked = true
+ semasleep(-1)
+ gp.m.blocked = false
+ return true
+ }
+
+ deadline = nanotime() + ns
+ for {
+ // Registered. Sleep.
+ gp.m.blocked = true
+ if semasleep(ns) >= 0 {
+ gp.m.blocked = false
+ // Acquired semaphore, semawakeup unregistered us.
+ // Done.
+ return true
+ }
+ gp.m.blocked = false
+ // Interrupted or timed out. Still registered. Semaphore not acquired.
+ ns = deadline - nanotime()
+ if ns <= 0 {
+ break
+ }
+ // Deadline hasn't arrived. Keep sleeping.
+ }
+
+ // Deadline arrived. Still registered. Semaphore not acquired.
+ // Want to give up and return, but have to unregister first,
+ // 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)
+ switch v {
+ case uintptr(unsafe.Pointer(gp.m)):
+ // No wakeup yet; unregister if possible.
+ if casuintptr(&n.key, v, 0) {
+ return false
+ }
+ case locked:
+ // Wakeup happened so semaphore is available.
+ // Grab it to avoid getting out of sync.
+ gp.m.blocked = true
+ if semasleep(-1) < 0 {
+ gothrow("runtime: unable to acquire - semaphore out of sync")
+ }
+ gp.m.blocked = false
+ return true
+ default:
+ gothrow("runtime: unexpected waitm - semaphore out of sync")
+ }
+ }
+}
+
+func notetsleep(n *note, ns int64) bool {
+ gp := getg()
+ if gp != gp.m.g0 && gp.m.gcing == 0 {
+ gothrow("notetsleep not on g0")
+ }
+ if gp.m.waitsema == 0 {
+ gp.m.waitsema = semacreate()
+ }
+ return notetsleep_internal(n, ns, nil, 0)
+}
+
+// same as runtime·notetsleep, but called on user g (not g0)
+// calls only nosplit functions between entersyscallblock/exitsyscall
+func notetsleepg(n *note, ns int64) bool {
+ gp := getg()
+ if gp == gp.m.g0 {
+ gothrow("notetsleepg on g0")
+ }
+ if gp.m.waitsema == 0 {
+ gp.m.waitsema = semacreate()
+ }
+ entersyscallblock()
+ ok := notetsleep_internal(n, ns, nil, 0)
+ exitsyscall()
+ return ok
+}
diff --git a/src/runtime/malloc.c b/src/runtime/malloc.c
new file mode 100644
index 000000000..b79c30b72
--- /dev/null
+++ b/src/runtime/malloc.c
@@ -0,0 +1,396 @@
+// 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.
+
+// See malloc.h for overview.
+//
+// TODO(rsc): double-check stats.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
+#include "type.h"
+#include "typekind.h"
+#include "race.h"
+#include "stack.h"
+#include "textflag.h"
+
+// Mark mheap as 'no pointers', it does not contain interesting pointers but occupies ~45K.
+#pragma dataflag NOPTR
+MHeap runtime·mheap;
+#pragma dataflag NOPTR
+MStats runtime·memstats;
+
+int32
+runtime·mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
+{
+ uintptr n, i;
+ byte *p;
+ MSpan *s;
+
+ g->m->mcache->local_nlookup++;
+ if (sizeof(void*) == 4 && g->m->mcache->local_nlookup >= (1<<30)) {
+ // purge cache stats to prevent overflow
+ runtime·lock(&runtime·mheap.lock);
+ runtime·purgecachedstats(g->m->mcache);
+ runtime·unlock(&runtime·mheap.lock);
+ }
+
+ s = runtime·MHeap_LookupMaybe(&runtime·mheap, v);
+ if(sp)
+ *sp = s;
+ if(s == nil) {
+ if(base)
+ *base = nil;
+ if(size)
+ *size = 0;
+ return 0;
+ }
+
+ p = (byte*)((uintptr)s->start<<PageShift);
+ if(s->sizeclass == 0) {
+ // Large object.
+ if(base)
+ *base = p;
+ if(size)
+ *size = s->npages<<PageShift;
+ return 1;
+ }
+
+ n = s->elemsize;
+ if(base) {
+ i = ((byte*)v - p)/n;
+ *base = p + i*n;
+ }
+ if(size)
+ *size = n;
+
+ return 1;
+}
+
+#pragma textflag NOSPLIT
+void
+runtime·purgecachedstats(MCache *c)
+{
+ MHeap *h;
+ int32 i;
+
+ // Protected by either heap or GC lock.
+ h = &runtime·mheap;
+ mstats.heap_alloc += c->local_cachealloc;
+ c->local_cachealloc = 0;
+ mstats.tinyallocs += c->local_tinyallocs;
+ c->local_tinyallocs = 0;
+ mstats.nlookup += c->local_nlookup;
+ c->local_nlookup = 0;
+ h->largefree += c->local_largefree;
+ c->local_largefree = 0;
+ h->nlargefree += c->local_nlargefree;
+ c->local_nlargefree = 0;
+ for(i=0; i<nelem(c->local_nsmallfree); i++) {
+ h->nsmallfree[i] += c->local_nsmallfree[i];
+ c->local_nsmallfree[i] = 0;
+ }
+}
+
+// Size of the trailing by_size array differs between Go and C,
+// and all data after by_size is local to C, not exported to Go.
+// NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
+// sizeof_C_MStats is what C thinks about size of Go struct.
+uintptr runtime·sizeof_C_MStats = offsetof(MStats, by_size[61]);
+
+#define MaxArena32 (2U<<30)
+
+// For use by Go. If it were a C enum it would be made available automatically,
+// but the value of MaxMem is too large for enum.
+uintptr runtime·maxmem = MaxMem;
+
+void
+runtime·mallocinit(void)
+{
+ byte *p, *p1;
+ uintptr arena_size, bitmap_size, spans_size, p_size;
+ extern byte runtime·end[];
+ uintptr limit;
+ uint64 i;
+ bool reserved;
+
+ p = nil;
+ p_size = 0;
+ arena_size = 0;
+ bitmap_size = 0;
+ spans_size = 0;
+ reserved = false;
+
+ // for 64-bit build
+ USED(p);
+ USED(p_size);
+ USED(arena_size);
+ USED(bitmap_size);
+ USED(spans_size);
+
+ runtime·InitSizes();
+
+ if(runtime·class_to_size[TinySizeClass] != TinySize)
+ runtime·throw("bad TinySizeClass");
+
+ // limit = runtime·memlimit();
+ // See https://code.google.com/p/go/issues/detail?id=5049
+ // TODO(rsc): Fix after 1.1.
+ limit = 0;
+
+ // 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(sizeof(void*) == 8 && (limit == 0 || limit > (1<<30))) {
+ // On a 64-bit machine, allocate from a single contiguous reservation.
+ // 128 GB (MaxMem) should be big enough for now.
+ //
+ // The code will work with the reservation at any address, but ask
+ // SysReserve to use 0x0000XXc000000000 if possible (XX=00...7f).
+ // Allocating a 128 GB region takes away 37 bits, and the amd64
+ // doesn't let us choose the top 17 bits, so that leaves the 11 bits
+ // in the middle of 0x00c0 for us to choose. Choosing 0x00c0 means
+ // that the valid memory addresses will begin 0x00c0, 0x00c1, ..., 0x00df.
+ // In little-endian, that's c0 00, c1 00, ..., df 00. None of those are valid
+ // UTF-8 sequences, and they are otherwise as far away from
+ // ff (likely a common byte) as possible. If that fails, we try other 0xXXc0
+ // addresses. An earlier attempt to use 0x11f8 caused out of memory errors
+ // on OS X during thread allocations. 0x00c0 causes conflicts with
+ // AddressSanitizer which reserves all memory up to 0x0100.
+ // These choices are both for debuggability and to reduce the
+ // odds of the conservative garbage collector not collecting memory
+ // because some non-pointer block of memory had a bit pattern
+ // that matched a memory address.
+ //
+ // Actually we reserve 136 GB (because the bitmap ends up being 8 GB)
+ // but it hardly matters: e0 00 is not valid UTF-8 either.
+ //
+ // If this fails we fall back to the 32 bit memory mechanism
+ arena_size = MaxMem;
+ bitmap_size = arena_size / (sizeof(void*)*8/4);
+ spans_size = arena_size / PageSize * sizeof(runtime·mheap.spans[0]);
+ spans_size = ROUND(spans_size, PageSize);
+ for(i = 0; i <= 0x7f; i++) {
+ p = (void*)(i<<40 | 0x00c0ULL<<32);
+ p_size = bitmap_size + spans_size + arena_size + PageSize;
+ p = runtime·SysReserve(p, p_size, &reserved);
+ if(p != nil)
+ break;
+ }
+ }
+ if (p == nil) {
+ // On a 32-bit machine, we can't typically get away
+ // with a giant virtual address space reservation.
+ // Instead we map the memory information bitmap
+ // immediately after the data segment, large enough
+ // to handle another 2GB of mappings (256 MB),
+ // along with a reservation for another 512 MB of memory.
+ // When that gets used up, we'll start asking the kernel
+ // for any memory anywhere and hope it's in the 2GB
+ // following the bitmap (presumably the executable begins
+ // near the bottom of memory, so we'll have to use up
+ // most of memory before the kernel resorts to giving out
+ // memory before the beginning of the text segment).
+ //
+ // Alternatively we could reserve 512 MB bitmap, enough
+ // for 4GB of mappings, and then accept any memory the
+ // kernel threw at us, but normally that's a waste of 512 MB
+ // of address space, which is probably too much in a 32-bit world.
+ bitmap_size = MaxArena32 / (sizeof(void*)*8/4);
+ arena_size = 512<<20;
+ spans_size = MaxArena32 / PageSize * sizeof(runtime·mheap.spans[0]);
+ if(limit > 0 && arena_size+bitmap_size+spans_size > limit) {
+ bitmap_size = (limit / 9) & ~((1<<PageShift) - 1);
+ arena_size = bitmap_size * 8;
+ spans_size = arena_size / PageSize * sizeof(runtime·mheap.spans[0]);
+ }
+ spans_size = ROUND(spans_size, PageSize);
+
+ // SysReserve treats the address we ask for, end, as a hint,
+ // not as an absolute requirement. If we ask for the end
+ // of the data segment but the operating system requires
+ // a little more space before we can start allocating, it will
+ // give out a slightly higher pointer. Except QEMU, which
+ // is buggy, as usual: it won't adjust the pointer upward.
+ // So adjust it upward a little bit ourselves: 1/4 MB to get
+ // away from the running binary image and then round up
+ // to a MB boundary.
+ p = (byte*)ROUND((uintptr)runtime·end + (1<<18), 1<<20);
+ p_size = bitmap_size + spans_size + arena_size + PageSize;
+ p = runtime·SysReserve(p, p_size, &reserved);
+ if(p == nil)
+ runtime·throw("runtime: cannot reserve arena virtual address space");
+ }
+
+ // PageSize can be larger than OS definition of page size,
+ // so SysReserve can give us a PageSize-unaligned pointer.
+ // To overcome this we ask for PageSize more and round up the pointer.
+ p1 = (byte*)ROUND((uintptr)p, PageSize);
+
+ runtime·mheap.spans = (MSpan**)p1;
+ runtime·mheap.bitmap = p1 + spans_size;
+ runtime·mheap.arena_start = p1 + spans_size + bitmap_size;
+ runtime·mheap.arena_used = runtime·mheap.arena_start;
+ runtime·mheap.arena_end = p + p_size;
+ runtime·mheap.arena_reserved = reserved;
+
+ if(((uintptr)runtime·mheap.arena_start & (PageSize-1)) != 0)
+ runtime·throw("misrounded allocation in mallocinit");
+
+ // Initialize the rest of the allocator.
+ runtime·MHeap_Init(&runtime·mheap);
+ g->m->mcache = runtime·allocmcache();
+}
+
+void*
+runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
+{
+ byte *p, *p_end;
+ uintptr p_size;
+ bool reserved;
+
+ 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.
+ byte *new_end;
+
+ p_size = ROUND(n + PageSize, 256<<20);
+ new_end = h->arena_end + p_size;
+ if(new_end <= h->arena_start + MaxArena32) {
+ // TODO: It would be bad if part of the arena
+ // is reserved and part is not.
+ p = runtime·SysReserve(h->arena_end, p_size, &reserved);
+ if(p == h->arena_end) {
+ h->arena_end = new_end;
+ h->arena_reserved = reserved;
+ }
+ else if(p+p_size <= h->arena_start + MaxArena32) {
+ // Keep everything page-aligned.
+ // Our pages are bigger than hardware pages.
+ h->arena_end = p+p_size;
+ h->arena_used = p + (-(uintptr)p&(PageSize-1));
+ h->arena_reserved = reserved;
+ } else {
+ uint64 stat;
+ stat = 0;
+ runtime·SysFree(p, p_size, &stat);
+ }
+ }
+ }
+ if(n <= h->arena_end - h->arena_used) {
+ // Keep taking from our reservation.
+ p = h->arena_used;
+ runtime·SysMap(p, n, h->arena_reserved, &mstats.heap_sys);
+ h->arena_used += n;
+ runtime·MHeap_MapBits(h);
+ runtime·MHeap_MapSpans(h);
+ if(raceenabled)
+ runtime·racemapshadow(p, n);
+
+ if(((uintptr)p & (PageSize-1)) != 0)
+ runtime·throw("misrounded allocation in MHeap_SysAlloc");
+ return p;
+ }
+
+ // If using 64-bit, our reservation is all we have.
+ if(h->arena_end - h->arena_start >= MaxArena32)
+ return nil;
+
+ // On 32-bit, once the reservation is gone we can
+ // try to get memory at a location chosen by the OS
+ // and hope that it is in the range we allocated bitmap for.
+ p_size = ROUND(n, PageSize) + PageSize;
+ p = runtime·sysAlloc(p_size, &mstats.heap_sys);
+ if(p == nil)
+ return nil;
+
+ if(p < h->arena_start || p+p_size - h->arena_start >= MaxArena32) {
+ runtime·printf("runtime: memory allocated by OS (%p) not in usable range [%p,%p)\n",
+ p, h->arena_start, h->arena_start+MaxArena32);
+ runtime·SysFree(p, p_size, &mstats.heap_sys);
+ return nil;
+ }
+
+ p_end = p + p_size;
+ p += -(uintptr)p & (PageSize-1);
+ if(p+n > h->arena_used) {
+ h->arena_used = p+n;
+ if(p_end > h->arena_end)
+ h->arena_end = p_end;
+ runtime·MHeap_MapBits(h);
+ runtime·MHeap_MapSpans(h);
+ if(raceenabled)
+ runtime·racemapshadow(p, n);
+ }
+
+ if(((uintptr)p & (PageSize-1)) != 0)
+ runtime·throw("misrounded allocation in MHeap_SysAlloc");
+ return p;
+}
+
+void
+runtime·setFinalizer_m(void)
+{
+ FuncVal *fn;
+ void *arg;
+ uintptr nret;
+ Type *fint;
+ PtrType *ot;
+
+ fn = g->m->ptrarg[0];
+ arg = g->m->ptrarg[1];
+ nret = g->m->scalararg[0];
+ fint = g->m->ptrarg[2];
+ ot = g->m->ptrarg[3];
+ g->m->ptrarg[0] = nil;
+ g->m->ptrarg[1] = nil;
+ g->m->ptrarg[2] = nil;
+ g->m->ptrarg[3] = nil;
+
+ g->m->scalararg[0] = runtime·addfinalizer(arg, fn, nret, fint, ot);
+}
+
+void
+runtime·removeFinalizer_m(void)
+{
+ void *p;
+
+ p = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ runtime·removefinalizer(p);
+}
+
+// mcallable cache refill
+void
+runtime·mcacheRefill_m(void)
+{
+ runtime·MCache_Refill(g->m->mcache, (int32)g->m->scalararg[0]);
+}
+
+void
+runtime·largeAlloc_m(void)
+{
+ uintptr npages, size;
+ MSpan *s;
+ void *v;
+ int32 flag;
+
+ //runtime·printf("largeAlloc size=%D\n", g->m->scalararg[0]);
+ // Allocate directly from heap.
+ size = g->m->scalararg[0];
+ flag = (int32)g->m->scalararg[1];
+ if(size + PageSize < size)
+ runtime·throw("out of memory");
+ npages = size >> PageShift;
+ if((size & PageMask) != 0)
+ npages++;
+ s = runtime·MHeap_Alloc(&runtime·mheap, npages, 0, 1, !(flag & FlagNoZero));
+ if(s == nil)
+ runtime·throw("out of memory");
+ s->limit = (byte*)(s->start<<PageShift) + size;
+ v = (void*)(s->start << PageShift);
+ // setup for mark sweep
+ runtime·markspan(v, 0, 0, true);
+ g->m->ptrarg[0] = s;
+}
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
new file mode 100644
index 000000000..117044944
--- /dev/null
+++ b/src/runtime/malloc.go
@@ -0,0 +1,837 @@
+// 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"
+)
+
+const (
+ debugMalloc = false
+
+ flagNoScan = _FlagNoScan
+ flagNoZero = _FlagNoZero
+
+ maxTinySize = _TinySize
+ tinySizeClass = _TinySizeClass
+ maxSmallSize = _MaxSmallSize
+
+ pageShift = _PageShift
+ pageSize = _PageSize
+ pageMask = _PageMask
+
+ bitsPerPointer = _BitsPerPointer
+ bitsMask = _BitsMask
+ pointersPerByte = _PointersPerByte
+ maxGCMask = _MaxGCMask
+ bitsDead = _BitsDead
+ bitsPointer = _BitsPointer
+
+ mSpanInUse = _MSpanInUse
+
+ concurrentSweep = _ConcurrentSweep != 0
+)
+
+// Page number (address>>pageShift)
+type pageID uintptr
+
+// base address for all 0-byte allocations
+var zerobase uintptr
+
+// Allocate an object of size bytes.
+// Small objects are allocated from the per-P cache's free lists.
+// Large objects (> 32 kB) are allocated straight from the heap.
+func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
+ if size == 0 {
+ return unsafe.Pointer(&zerobase)
+ }
+ size0 := size
+
+ if flags&flagNoScan == 0 && typ == nil {
+ gothrow("malloc missing type")
+ }
+
+ // This function must be atomic wrt GC, but for performance reasons
+ // we don't acquirem/releasem on fast path. The code below does not have
+ // split stack checks, so it can't be preempted by GC.
+ // Functions like roundup/add are inlined. And onM/racemalloc are nosplit.
+ // If debugMalloc = true, these assumptions are checked below.
+ if debugMalloc {
+ mp := acquirem()
+ if mp.mallocing != 0 {
+ gothrow("malloc deadlock")
+ }
+ mp.mallocing = 1
+ if mp.curg != nil {
+ mp.curg.stackguard0 = ^uintptr(0xfff) | 0xbad
+ }
+ }
+
+ c := gomcache()
+ var s *mspan
+ var x unsafe.Pointer
+ if size <= maxSmallSize {
+ if flags&flagNoScan != 0 && size < maxTinySize {
+ // Tiny allocator.
+ //
+ // Tiny allocator combines several tiny allocation requests
+ // into a single memory block. The resulting memory block
+ // is freed when all subobjects are unreachable. The subobjects
+ // must be FlagNoScan (don't have pointers), this ensures that
+ // the amount of potentially wasted memory is bounded.
+ //
+ // Size of the memory block used for combining (maxTinySize) is tunable.
+ // Current setting is 16 bytes, which relates to 2x worst case memory
+ // wastage (when all but one subobjects are unreachable).
+ // 8 bytes would result in no wastage at all, but provides less
+ // opportunities for combining.
+ // 32 bytes provides more opportunities for combining,
+ // but can lead to 4x worst case wastage.
+ // The best case winning is 8x regardless of block size.
+ //
+ // Objects obtained from tiny allocator must not be freed explicitly.
+ // So when an object will be freed explicitly, we ensure that
+ // its size >= maxTinySize.
+ //
+ // SetFinalizer has a special case for objects potentially coming
+ // from tiny allocator, it such case it allows to set finalizers
+ // for an inner byte of a memory block.
+ //
+ // The main targets of tiny allocator are small strings and
+ // standalone escaping variables. On a json benchmark
+ // the allocator reduces number of allocations by ~12% and
+ // reduces heap size by ~20%.
+ tinysize := uintptr(c.tinysize)
+ if size <= tinysize {
+ tiny := unsafe.Pointer(c.tiny)
+ // Align tiny pointer for required (conservative) alignment.
+ if size&7 == 0 {
+ tiny = roundup(tiny, 8)
+ } else if size&3 == 0 {
+ tiny = roundup(tiny, 4)
+ } else if size&1 == 0 {
+ tiny = roundup(tiny, 2)
+ }
+ size1 := size + (uintptr(tiny) - uintptr(unsafe.Pointer(c.tiny)))
+ if size1 <= tinysize {
+ // The object fits into existing tiny block.
+ x = tiny
+ c.tiny = (*byte)(add(x, size))
+ c.tinysize -= uintptr(size1)
+ c.local_tinyallocs++
+ if debugMalloc {
+ mp := acquirem()
+ if mp.mallocing == 0 {
+ gothrow("bad malloc")
+ }
+ mp.mallocing = 0
+ if mp.curg != nil {
+ mp.curg.stackguard0 = mp.curg.stack.lo + _StackGuard
+ }
+ // Note: one releasem for the acquirem just above.
+ // The other for the acquirem at start of malloc.
+ releasem(mp)
+ releasem(mp)
+ }
+ return x
+ }
+ }
+ // Allocate a new maxTinySize block.
+ s = c.alloc[tinySizeClass]
+ v := s.freelist
+ if v == nil {
+ mp := acquirem()
+ mp.scalararg[0] = tinySizeClass
+ onM(mcacheRefill_m)
+ releasem(mp)
+ s = c.alloc[tinySizeClass]
+ v = s.freelist
+ }
+ s.freelist = v.next
+ s.ref++
+ //TODO: prefetch v.next
+ x = unsafe.Pointer(v)
+ (*[2]uint64)(x)[0] = 0
+ (*[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 maxTinySize-size > tinysize {
+ c.tiny = (*byte)(add(x, size))
+ c.tinysize = uintptr(maxTinySize - size)
+ }
+ size = maxTinySize
+ } else {
+ var sizeclass int8
+ if size <= 1024-8 {
+ sizeclass = size_to_class8[(size+7)>>3]
+ } else {
+ sizeclass = size_to_class128[(size-1024+127)>>7]
+ }
+ size = uintptr(class_to_size[sizeclass])
+ s = c.alloc[sizeclass]
+ v := s.freelist
+ if v == nil {
+ mp := acquirem()
+ mp.scalararg[0] = uintptr(sizeclass)
+ onM(mcacheRefill_m)
+ releasem(mp)
+ s = c.alloc[sizeclass]
+ v = s.freelist
+ }
+ s.freelist = v.next
+ s.ref++
+ //TODO: prefetch
+ x = unsafe.Pointer(v)
+ if flags&flagNoZero == 0 {
+ v.next = nil
+ if size > 2*ptrSize && ((*[2]uintptr)(x))[1] != 0 {
+ memclr(unsafe.Pointer(v), size)
+ }
+ }
+ }
+ c.local_cachealloc += intptr(size)
+ } else {
+ mp := acquirem()
+ mp.scalararg[0] = uintptr(size)
+ mp.scalararg[1] = uintptr(flags)
+ onM(largeAlloc_m)
+ s = (*mspan)(mp.ptrarg[0])
+ mp.ptrarg[0] = nil
+ releasem(mp)
+ x = unsafe.Pointer(uintptr(s.start << pageShift))
+ size = uintptr(s.elemsize)
+ }
+
+ if flags&flagNoScan != 0 {
+ // All objects are pre-marked as noscan.
+ goto marked
+ }
+
+ // If allocating a defer+arg block, now that we've picked a malloc size
+ // large enough to hold everything, cut the "asked for" size down to
+ // just the defer header, so that the GC bitmap will record the arg block
+ // as containing nothing at all (as if it were unused space at the end of
+ // a malloc block caused by size rounding).
+ // The defer arg areas are scanned as part of scanstack.
+ if typ == deferType {
+ size0 = unsafe.Sizeof(_defer{})
+ }
+
+ // From here till marked label marking the object as allocated
+ // and storing type info in the GC bitmap.
+ {
+ arena_start := uintptr(unsafe.Pointer(mheap_.arena_start))
+ off := (uintptr(x) - arena_start) / ptrSize
+ xbits := (*uint8)(unsafe.Pointer(arena_start - off/wordsPerBitmapByte - 1))
+ shift := (off % wordsPerBitmapByte) * gcBits
+ if debugMalloc && ((*xbits>>shift)&(bitMask|bitPtrMask)) != bitBoundary {
+ println("runtime: bits =", (*xbits>>shift)&(bitMask|bitPtrMask))
+ gothrow("bad bits in markallocated")
+ }
+
+ var ti, te uintptr
+ var ptrmask *uint8
+ if size == ptrSize {
+ // It's one word and it has pointers, it must be a pointer.
+ *xbits |= (bitsPointer << 2) << shift
+ goto marked
+ }
+ if typ.kind&kindGCProg != 0 {
+ nptr := (uintptr(typ.size) + ptrSize - 1) / ptrSize
+ masksize := nptr
+ if masksize%2 != 0 {
+ masksize *= 2 // repeated
+ }
+ masksize = masksize * pointersPerByte / 8 // 4 bits per word
+ masksize++ // unroll flag in the beginning
+ if masksize > maxGCMask && typ.gc[1] != 0 {
+ // If the mask is too large, unroll the program directly
+ // into the GC bitmap. It's 7 times slower than copying
+ // from the pre-unrolled mask, but saves 1/16 of type size
+ // memory for the mask.
+ mp := acquirem()
+ mp.ptrarg[0] = x
+ mp.ptrarg[1] = unsafe.Pointer(typ)
+ mp.scalararg[0] = uintptr(size)
+ mp.scalararg[1] = uintptr(size0)
+ onM(unrollgcproginplace_m)
+ releasem(mp)
+ goto marked
+ }
+ ptrmask = (*uint8)(unsafe.Pointer(uintptr(typ.gc[0])))
+ // Check whether the program is already unrolled.
+ if uintptr(atomicloadp(unsafe.Pointer(ptrmask)))&0xff == 0 {
+ mp := acquirem()
+ mp.ptrarg[0] = unsafe.Pointer(typ)
+ onM(unrollgcprog_m)
+ releasem(mp)
+ }
+ ptrmask = (*uint8)(add(unsafe.Pointer(ptrmask), 1)) // skip the unroll flag byte
+ } else {
+ ptrmask = (*uint8)(unsafe.Pointer(typ.gc[0])) // pointer to unrolled mask
+ }
+ if size == 2*ptrSize {
+ *xbits = *ptrmask | bitBoundary
+ goto marked
+ }
+ te = uintptr(typ.size) / ptrSize
+ // If the type occupies odd number of words, its mask is repeated.
+ if te%2 == 0 {
+ te /= 2
+ }
+ // Copy pointer bitmask into the bitmap.
+ for i := uintptr(0); i < size0; i += 2 * ptrSize {
+ v := *(*uint8)(add(unsafe.Pointer(ptrmask), ti))
+ ti++
+ if ti == te {
+ ti = 0
+ }
+ if i == 0 {
+ v |= bitBoundary
+ }
+ if i+ptrSize == size0 {
+ v &^= uint8(bitPtrMask << 4)
+ }
+
+ *xbits = v
+ xbits = (*byte)(add(unsafe.Pointer(xbits), ^uintptr(0)))
+ }
+ if size0%(2*ptrSize) == 0 && size0 < size {
+ // Mark the word after last object's word as bitsDead.
+ *xbits = bitsDead << 2
+ }
+ }
+marked:
+ if raceenabled {
+ racemalloc(x, size)
+ }
+
+ if debugMalloc {
+ mp := acquirem()
+ if mp.mallocing == 0 {
+ gothrow("bad malloc")
+ }
+ mp.mallocing = 0
+ if mp.curg != nil {
+ mp.curg.stackguard0 = mp.curg.stack.lo + _StackGuard
+ }
+ // Note: one releasem for the acquirem just above.
+ // The other for the acquirem at start of malloc.
+ releasem(mp)
+ releasem(mp)
+ }
+
+ if debug.allocfreetrace != 0 {
+ tracealloc(x, size, typ)
+ }
+
+ if rate := MemProfileRate; rate > 0 {
+ if size < uintptr(rate) && int32(size) < c.next_sample {
+ c.next_sample -= int32(size)
+ } else {
+ mp := acquirem()
+ profilealloc(mp, x, size)
+ releasem(mp)
+ }
+ }
+
+ if memstats.heap_alloc >= memstats.next_gc {
+ gogc(0)
+ }
+
+ return x
+}
+
+// implementation of new builtin
+func newobject(typ *_type) unsafe.Pointer {
+ flags := uint32(0)
+ if typ.kind&kindNoPointers != 0 {
+ flags |= flagNoScan
+ }
+ return mallocgc(uintptr(typ.size), typ, flags)
+}
+
+// implementation of make builtin for slices
+func newarray(typ *_type, n uintptr) unsafe.Pointer {
+ flags := uint32(0)
+ if typ.kind&kindNoPointers != 0 {
+ flags |= flagNoScan
+ }
+ if int(n) < 0 || (typ.size > 0 && n > maxmem/uintptr(typ.size)) {
+ panic("runtime: allocation size out of range")
+ }
+ return mallocgc(uintptr(typ.size)*n, typ, flags)
+}
+
+// rawmem returns a chunk of pointerless memory. It is
+// not zeroed.
+func rawmem(size uintptr) unsafe.Pointer {
+ return mallocgc(size, nil, flagNoScan|flagNoZero)
+}
+
+// round size up to next size class
+func goroundupsize(size uintptr) uintptr {
+ if size < maxSmallSize {
+ if size <= 1024-8 {
+ return uintptr(class_to_size[size_to_class8[(size+7)>>3]])
+ }
+ return uintptr(class_to_size[size_to_class128[(size-1024+127)>>7]])
+ }
+ if size+pageSize < size {
+ return size
+ }
+ return (size + pageSize - 1) &^ pageMask
+}
+
+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
+ }
+ c.next_sample = next
+ }
+
+ mProf_Malloc(x, size)
+}
+
+// force = 1 - do GC regardless of current heap usage
+// force = 2 - go GC and eager sweep
+func gogc(force int32) {
+ // 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 stoptheworld, don't bother
+ // trying to run gc while holding a lock. The next mallocgc without a lock
+ // will do the gc instead.
+ mp := acquirem()
+ if gp := getg(); gp == mp.g0 || mp.locks > 1 || !memstats.enablegc || panicking != 0 || gcpercent < 0 {
+ releasem(mp)
+ return
+ }
+ releasem(mp)
+ mp = nil
+
+ semacquire(&worldsema, false)
+
+ if force == 0 && memstats.heap_alloc < memstats.next_gc {
+ // typically threads which lost the race to grab
+ // worldsema exit here when gc is done.
+ semrelease(&worldsema)
+ return
+ }
+
+ // Ok, we're doing it! Stop everybody else
+ startTime := nanotime()
+ mp = acquirem()
+ mp.gcing = 1
+ releasem(mp)
+ onM(stoptheworld)
+ if mp != acquirem() {
+ gothrow("gogc: rescheduled")
+ }
+
+ clearpools()
+
+ // Run gc on the g0 stack. We do this so that the g stack
+ // we're currently running on will no longer change. Cuts
+ // the root set down a bit (g0 stacks are not scanned, and
+ // we don't need to scan gc's internal state). We also
+ // need to switch to g0 so we can shrink the stack.
+ n := 1
+ if debug.gctrace > 1 {
+ n = 2
+ }
+ for i := 0; i < n; i++ {
+ if i > 0 {
+ startTime = nanotime()
+ }
+ // switch to g0, call gc, then switch back
+ mp.scalararg[0] = uintptr(uint32(startTime)) // low 32 bits
+ mp.scalararg[1] = uintptr(startTime >> 32) // high 32 bits
+ if force >= 2 {
+ mp.scalararg[2] = 1 // eagersweep
+ } else {
+ mp.scalararg[2] = 0
+ }
+ onM(gc_m)
+ }
+
+ // all done
+ mp.gcing = 0
+ semrelease(&worldsema)
+ onM(starttheworld)
+ releasem(mp)
+ mp = nil
+
+ // now that gc is done, kick off finalizer thread if needed
+ if !concurrentSweep {
+ // give the queued finalizers, if any, a chance to run
+ Gosched()
+ }
+}
+
+// GC runs a garbage collection.
+func GC() {
+ gogc(2)
+}
+
+// linker-provided
+var noptrdata struct{}
+var enoptrdata struct{}
+var noptrbss struct{}
+var enoptrbss struct{}
+
+// SetFinalizer sets the finalizer associated with x to f.
+// When the garbage collector finds an unreachable block
+// with an associated finalizer, it clears the association and runs
+// f(x) in a separate goroutine. This makes x reachable again, but
+// now without an associated finalizer. Assuming that SetFinalizer
+// is not called again, the next time the garbage collector sees
+// that x is unreachable, it will free x.
+//
+// SetFinalizer(x, nil) clears any finalizer associated with x.
+//
+// The argument x must be a pointer to an object allocated by
+// calling new or by taking the address of a composite literal.
+// The argument f must be a function that takes a single argument
+// to which x's type can be assigned, and can have arbitrary ignored return
+// values. If either of these is not true, SetFinalizer aborts the
+// program.
+//
+// Finalizers are run in dependency order: if A points at B, both have
+// finalizers, and they are otherwise unreachable, only the finalizer
+// for A runs; once A is freed, the finalizer for B can run.
+// If a cyclic structure includes a block with a finalizer, that
+// cycle is not guaranteed to be garbage collected and the finalizer
+// is not guaranteed to run, because there is no ordering that
+// respects the dependencies.
+//
+// The finalizer for x is scheduled to run at some arbitrary time after
+// x becomes unreachable.
+// There is no guarantee that finalizers will run before a program exits,
+// so typically they are useful only for releasing non-memory resources
+// associated with an object during a long-running program.
+// For example, an os.File object could use a finalizer to close the
+// associated operating system file descriptor when a program discards
+// an os.File without calling Close, but it would be a mistake
+// to depend on a finalizer to flush an in-memory I/O buffer such as a
+// bufio.Writer, because the buffer would not be flushed at program exit.
+//
+// It is not guaranteed that a finalizer will run if the size of *x is
+// zero bytes.
+//
+// It is not guaranteed that a finalizer will run for objects allocated
+// in initializers for package-level variables. Such objects may be
+// linker-allocated, not heap-allocated.
+//
+// A single goroutine runs all finalizers for a program, sequentially.
+// If a finalizer must run for a long time, it should do so by starting
+// a new goroutine.
+func SetFinalizer(obj interface{}, finalizer interface{}) {
+ e := (*eface)(unsafe.Pointer(&obj))
+ etyp := e._type
+ if etyp == nil {
+ gothrow("runtime.SetFinalizer: first argument is nil")
+ }
+ if etyp.kind&kindMask != kindPtr {
+ gothrow("runtime.SetFinalizer: first argument is " + *etyp._string + ", not pointer")
+ }
+ ot := (*ptrtype)(unsafe.Pointer(etyp))
+ if ot.elem == nil {
+ gothrow("nil elem type!")
+ }
+
+ // find the containing object
+ _, base, _ := findObject(e.data)
+
+ if base == nil {
+ // 0-length objects are okay.
+ if e.data == unsafe.Pointer(&zerobase) {
+ return
+ }
+
+ // Global initializers might be linker-allocated.
+ // var Foo = &Object{}
+ // func main() {
+ // runtime.SetFinalizer(Foo, nil)
+ // }
+ // The relevant segments are: noptrdata, data, bss, noptrbss.
+ // We cannot assume they are in any order or even contiguous,
+ // due to external linking.
+ if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrdata)) ||
+ uintptr(unsafe.Pointer(&data)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&edata)) ||
+ uintptr(unsafe.Pointer(&bss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&ebss)) ||
+ uintptr(unsafe.Pointer(&noptrbss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) {
+ return
+ }
+ gothrow("runtime.SetFinalizer: pointer not in allocated block")
+ }
+
+ if e.data != base {
+ // As an implementation detail we allow to set finalizers for an inner byte
+ // of an object if it could come from tiny alloc (see mallocgc for details).
+ if ot.elem == nil || ot.elem.kind&kindNoPointers == 0 || ot.elem.size >= maxTinySize {
+ gothrow("runtime.SetFinalizer: pointer not at beginning of allocated block")
+ }
+ }
+
+ f := (*eface)(unsafe.Pointer(&finalizer))
+ ftyp := f._type
+ if ftyp == nil {
+ // switch to M stack and remove finalizer
+ mp := acquirem()
+ mp.ptrarg[0] = e.data
+ onM(removeFinalizer_m)
+ releasem(mp)
+ return
+ }
+
+ if ftyp.kind&kindMask != kindFunc {
+ gothrow("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 {
+ gothrow("runtime.SetFinalizer: cannot pass " + *etyp._string + " to finalizer " + *ftyp._string)
+ }
+ fint := ins[0]
+ switch {
+ case fint == etyp:
+ // ok - same type
+ goto okarg
+ case fint.kind&kindMask == kindPtr:
+ if (fint.x == nil || fint.x.name == nil || etyp.x == nil || etyp.x.name == nil) && (*ptrtype)(unsafe.Pointer(fint)).elem == ot.elem {
+ // ok - not same type, but both pointers,
+ // one or the other is unnamed, and same element type, so assignable.
+ goto okarg
+ }
+ case fint.kind&kindMask == kindInterface:
+ ityp := (*interfacetype)(unsafe.Pointer(fint))
+ if len(ityp.mhdr) == 0 {
+ // ok - satisfies empty interface
+ goto okarg
+ }
+ if _, ok := assertE2I2(ityp, obj); ok {
+ goto okarg
+ }
+ }
+ gothrow("runtime.SetFinalizer: cannot pass " + *etyp._string + " to finalizer " + *ftyp._string)
+okarg:
+ // compute size needed for return parameters
+ nret := uintptr(0)
+ for _, t := range *(*[]*_type)(unsafe.Pointer(&ft.out)) {
+ nret = round(nret, uintptr(t.align)) + uintptr(t.size)
+ }
+ nret = round(nret, ptrSize)
+
+ // make sure we have a finalizer goroutine
+ createfing()
+
+ // switch to M stack to add finalizer record
+ mp := acquirem()
+ mp.ptrarg[0] = f.data
+ mp.ptrarg[1] = e.data
+ mp.scalararg[0] = nret
+ mp.ptrarg[2] = unsafe.Pointer(fint)
+ mp.ptrarg[3] = unsafe.Pointer(ot)
+ onM(setFinalizer_m)
+ if mp.scalararg[0] != 1 {
+ gothrow("runtime.SetFinalizer: finalizer already set")
+ }
+ releasem(mp)
+}
+
+// round n up to a multiple of a. a must be a power of 2.
+func round(n, a uintptr) uintptr {
+ return (n + a - 1) &^ (a - 1)
+}
+
+// Look up pointer v in heap. Return the span containing the object,
+// the start of the object, and the size of the object. If the object
+// does not exist, return nil, nil, 0.
+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 {
+ // purge cache stats to prevent overflow
+ lock(&mheap_.lock)
+ purgecachedstats(c)
+ unlock(&mheap_.lock)
+ }
+
+ // find span
+ arena_start := uintptr(unsafe.Pointer(mheap_.arena_start))
+ arena_used := uintptr(unsafe.Pointer(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))
+ if s == nil {
+ return
+ }
+ x = unsafe.Pointer(uintptr(s.start) << pageShift)
+
+ if uintptr(v) < uintptr(x) || uintptr(v) >= uintptr(unsafe.Pointer(s.limit)) || s.state != mSpanInUse {
+ s = nil
+ x = nil
+ return
+ }
+
+ n = uintptr(s.elemsize)
+ if s.sizeclass != 0 {
+ x = add(x, (uintptr(v)-uintptr(x))/n*n)
+ }
+ return
+}
+
+var fingCreate uint32
+
+func createfing() {
+ // start the finalizer goroutine exactly once
+ if fingCreate == 0 && cas(&fingCreate, 0, 1) {
+ go runfinq()
+ }
+}
+
+// This is the goroutine that runs all of the finalizers
+func runfinq() {
+ var (
+ frame unsafe.Pointer
+ framecap uintptr
+ )
+
+ for {
+ lock(&finlock)
+ fb := finq
+ finq = nil
+ if fb == nil {
+ gp := getg()
+ fing = gp
+ fingwait = true
+ gp.issystem = true
+ goparkunlock(&finlock, "finalizer wait")
+ gp.issystem = false
+ continue
+ }
+ unlock(&finlock)
+ if raceenabled {
+ racefingo()
+ }
+ for fb != nil {
+ for i := int32(0); i < fb.cnt; i++ {
+ f := (*finalizer)(add(unsafe.Pointer(&fb.fin), uintptr(i)*unsafe.Sizeof(finalizer{})))
+
+ framesz := unsafe.Sizeof((interface{})(nil)) + uintptr(f.nret)
+ if framecap < framesz {
+ // The frame does not contain pointers interesting for GC,
+ // all not yet finalized objects are stored in finq.
+ // If we do not mark it as FlagNoScan,
+ // the last finalized object is not collected.
+ frame = mallocgc(framesz, nil, flagNoScan)
+ framecap = framesz
+ }
+
+ if f.fint == nil {
+ gothrow("missing type in runfinq")
+ }
+ switch f.fint.kind & kindMask {
+ case kindPtr:
+ // direct use of pointer
+ *(*unsafe.Pointer)(frame) = f.arg
+ case kindInterface:
+ ityp := (*interfacetype)(unsafe.Pointer(f.fint))
+ // set up with empty interface
+ (*eface)(frame)._type = &f.ot.typ
+ (*eface)(frame).data = f.arg
+ if len(ityp.mhdr) != 0 {
+ // convert to interface with methods
+ // this conversion is guaranteed to succeed - we checked in SetFinalizer
+ *(*fInterface)(frame) = assertE2I(ityp, *(*interface{})(frame))
+ }
+ default:
+ gothrow("bad kind in runfinq")
+ }
+ reflectcall(unsafe.Pointer(f.fn), frame, uint32(framesz), uint32(framesz))
+
+ // drop finalizer queue references to finalized object
+ f.fn = nil
+ f.arg = nil
+ f.ot = nil
+ }
+ fb.cnt = 0
+ next := fb.next
+ lock(&finlock)
+ fb.next = finc
+ finc = fb
+ unlock(&finlock)
+ fb = next
+ }
+ }
+}
+
+var persistent struct {
+ lock mutex
+ pos unsafe.Pointer
+ end unsafe.Pointer
+}
+
+// Wrapper around sysAlloc that can allocate small chunks.
+// There is no associated free operation.
+// Intended for things like function/type/debug-related persistent data.
+// If align is 0, uses default align (currently 8).
+func persistentalloc(size, align uintptr, stat *uint64) unsafe.Pointer {
+ const (
+ chunk = 256 << 10
+ maxBlock = 64 << 10 // VM reservation granularity is 64K on windows
+ )
+
+ if align != 0 {
+ if align&(align-1) != 0 {
+ gothrow("persistentalloc: align is not a power of 2")
+ }
+ if align > _PageSize {
+ gothrow("persistentalloc: align is too large")
+ }
+ } else {
+ align = 8
+ }
+
+ if size >= maxBlock {
+ return sysAlloc(size, stat)
+ }
+
+ lock(&persistent.lock)
+ persistent.pos = roundup(persistent.pos, align)
+ if uintptr(persistent.pos)+size > uintptr(persistent.end) {
+ persistent.pos = sysAlloc(chunk, &memstats.other_sys)
+ if persistent.pos == nil {
+ unlock(&persistent.lock)
+ gothrow("runtime: cannot allocate memory")
+ }
+ persistent.end = add(persistent.pos, chunk)
+ }
+ p := persistent.pos
+ persistent.pos = add(persistent.pos, size)
+ unlock(&persistent.lock)
+
+ if stat != &memstats.other_sys {
+ xadd64(stat, int64(size))
+ xadd64(&memstats.other_sys, -int64(size))
+ }
+ return p
+}
diff --git a/src/pkg/runtime/malloc.h b/src/runtime/malloc.h
index 798c130ad..adb8d3d67 100644
--- a/src/pkg/runtime/malloc.h
+++ b/src/runtime/malloc.h
@@ -85,7 +85,6 @@ typedef struct MHeap MHeap;
typedef struct MSpan MSpan;
typedef struct MStats MStats;
typedef struct MLink MLink;
-typedef struct MTypes MTypes;
typedef struct GCStats GCStats;
enum
@@ -94,7 +93,7 @@ enum
PageSize = 1<<PageShift,
PageMask = PageSize - 1,
};
-typedef uintptr PageID; // address >> PageShift
+typedef uintptr pageID; // address >> PageShift
enum
{
@@ -116,6 +115,12 @@ enum
MaxMHeapList = 1<<(20 - PageShift), // Maximum page length for fixed-size list in MHeap.
HeapAllocChunk = 1<<20, // Chunk size for heap growth
+ // Per-P, per order stack segment cache size.
+ StackCacheSize = 32*1024,
+ // Number of orders that get caching. Order 0 is FixedStack
+ // and each successive order is twice as large.
+ NumStackOrders = 3,
+
// Number of bits in page to span calculations (4k pages).
// On Windows 64-bit we limit the arena to 32GB or 35 bits (see below for reason).
// On other 64-bit platforms, we limit the arena to 128GB, or 37 bits.
@@ -136,8 +141,8 @@ enum
// Max number of threads to run garbage collection.
// 2, 3, and 4 are all plausible maximums depending
// on the hardware details of the machine. The garbage
- // collector scales well to 8 cpus.
- MaxGcproc = 8,
+ // collector scales well to 32 cpus.
+ MaxGcproc = 32,
};
// Maximum memory allocation size, a hint for callers.
@@ -155,12 +160,12 @@ struct MLink
MLink *next;
};
-// SysAlloc obtains a large chunk of zeroed memory from the
+// sysAlloc obtains a large chunk of zeroed memory from the
// operating system, typically on the order of a hundred kilobytes
// or a megabyte.
-// NOTE: SysAlloc returns OS-aligned memory, but the heap allocator
+// NOTE: sysAlloc returns OS-aligned memory, but the heap allocator
// may use larger alignment, so the caller must be careful to realign the
-// memory obtained by SysAlloc.
+// memory obtained by sysAlloc.
//
// SysUnused notifies the operating system that the contents
// of the memory region are no longer needed and can be reused
@@ -182,16 +187,16 @@ struct MLink
// reserved, false if it has merely been checked.
// NOTE: SysReserve returns OS-aligned memory, but the heap allocator
// may use larger alignment, so the caller must be careful to realign the
-// memory obtained by SysAlloc.
+// memory obtained by sysAlloc.
//
// SysMap maps previously reserved address space for use.
// The reserved argument is true if the address space was really
// reserved, not merely checked.
//
-// SysFault marks a (already SysAlloc'd) region to fault
+// SysFault marks a (already sysAlloc'd) region to fault
// if accessed. Used only for debugging the runtime.
-void* runtime·SysAlloc(uintptr nbytes, uint64 *stat);
+void* runtime·sysAlloc(uintptr nbytes, uint64 *stat);
void runtime·SysFree(void *v, uintptr nbytes, uint64 *stat);
void runtime·SysUnused(void *v, uintptr nbytes);
void runtime·SysUsed(void *v, uintptr nbytes);
@@ -200,7 +205,7 @@ void* runtime·SysReserve(void *v, uintptr nbytes, bool *reserved);
void runtime·SysFault(void *v, uintptr nbytes);
// FixAlloc is a simple free-list allocator for fixed size objects.
-// Malloc uses a FixAlloc wrapped around SysAlloc to manages its
+// Malloc uses a FixAlloc wrapped around sysAlloc to manages its
// MCache and MSpan objects.
//
// Memory returned by FixAlloc_Alloc is not zeroed.
@@ -237,7 +242,7 @@ struct MStats
uint64 nfree; // number of frees
// Statistics about malloc heap.
- // protected by mheap.Lock
+ // protected by mheap.lock
uint64 heap_alloc; // bytes allocated and still in use
uint64 heap_sys; // bytes obtained from system
uint64 heap_idle; // bytes in idle spans
@@ -247,8 +252,8 @@ struct MStats
// Statistics about allocation of low-level fixed-size structures.
// Protected by FixAlloc locks.
- uint64 stacks_inuse; // bootstrap stacks
- uint64 stacks_sys;
+ uint64 stacks_inuse; // this number is included in heap_inuse above
+ uint64 stacks_sys; // always 0 in mstats
uint64 mspan_inuse; // MSpan structures
uint64 mspan_sys;
uint64 mcache_inuse; // MCache structures
@@ -262,22 +267,28 @@ struct MStats
uint64 next_gc; // next GC (in heap_alloc time)
uint64 last_gc; // last GC (in absolute time)
uint64 pause_total_ns;
- uint64 pause_ns[256];
+ uint64 pause_ns[256]; // circular buffer of recent GC pause lengths
+ uint64 pause_end[256]; // circular buffer of recent GC end times (nanoseconds since 1970)
uint32 numgc;
bool enablegc;
bool debuggc;
// Statistics about allocation size classes.
- struct {
+
+ struct MStatsBySize {
uint32 size;
uint64 nmalloc;
uint64 nfree;
} by_size[NumSizeClasses];
+
+ uint64 tinyallocs; // number of tiny allocations that didn't cause actual allocation; not exported to Go directly
};
-#define mstats runtime·memStats
+
+#define mstats runtime·memstats
extern MStats mstats;
void runtime·updatememstats(GCStats *stats);
+void runtime·ReadMemStats(MStats *stats);
// Size classes. Computed and initialized by InitSizes.
//
@@ -297,7 +308,6 @@ extern int8 runtime·size_to_class8[1024/8 + 1];
extern int8 runtime·size_to_class128[(MaxSmallSize-1024)/128 + 1];
extern void runtime·InitSizes(void);
-
typedef struct MCacheList MCacheList;
struct MCacheList
{
@@ -305,6 +315,15 @@ struct MCacheList
uint32 nlist;
};
+typedef struct StackFreeList StackFreeList;
+struct StackFreeList
+{
+ MLink *list; // linked list of free stacks
+ uintptr size; // total size of stacks in list
+};
+
+typedef struct SudoG SudoG;
+
// Per-thread (in Go, per-P) cache for small objects.
// No locking needed because it is per-thread (per-P).
struct MCache
@@ -317,9 +336,16 @@ struct MCache
// See "Tiny allocator" comment in malloc.goc.
byte* tiny;
uintptr tinysize;
+ uintptr local_tinyallocs; // number of tiny allocs not counted in other stats
// The rest is not accessed on every malloc.
MSpan* alloc[NumSizeClasses]; // spans to allocate from
- MCacheList free[NumSizeClasses];// lists of explicitly freed objects
+
+ StackFreeList stackcache[NumStackOrders];
+
+ SudoG* sudogcache;
+
+ void* gcworkbuf;
+
// Local allocator stats, flushed during GC.
uintptr local_nlookup; // number of pointer lookups
uintptr local_largefree; // bytes freed for large objects (>MaxSmallSize)
@@ -328,45 +354,9 @@ struct MCache
};
MSpan* runtime·MCache_Refill(MCache *c, int32 sizeclass);
-void runtime·MCache_Free(MCache *c, MLink *p, int32 sizeclass, uintptr size);
void runtime·MCache_ReleaseAll(MCache *c);
-
-// MTypes describes the types of blocks allocated within a span.
-// The compression field describes the layout of the data.
-//
-// MTypes_Empty:
-// All blocks are free, or no type information is available for
-// allocated blocks.
-// The data field has no meaning.
-// MTypes_Single:
-// The span contains just one block.
-// The data field holds the type information.
-// The sysalloc field has no meaning.
-// MTypes_Words:
-// The span contains multiple blocks.
-// The data field points to an array of type [NumBlocks]uintptr,
-// and each element of the array holds the type of the corresponding
-// block.
-// MTypes_Bytes:
-// The span contains at most seven different types of blocks.
-// The data field points to the following structure:
-// struct {
-// type [8]uintptr // type[0] is always 0
-// index [NumBlocks]byte
-// }
-// The type of the i-th block is: data.type[data.index[i]]
-enum
-{
- MTypes_Empty = 0,
- MTypes_Single = 1,
- MTypes_Words = 2,
- MTypes_Bytes = 3,
-};
-struct MTypes
-{
- byte compression; // one of MTypes_*
- uintptr data;
-};
+void runtime·stackcache_clear(MCache *c);
+void runtime·gcworkbuffree(void *b);
enum
{
@@ -390,7 +380,7 @@ struct Special
typedef struct SpecialFinalizer SpecialFinalizer;
struct SpecialFinalizer
{
- Special;
+ Special special;
FuncVal* fn;
uintptr nret;
Type* fint;
@@ -398,18 +388,19 @@ struct SpecialFinalizer
};
// The described object is being heap profiled.
-typedef struct Bucket Bucket; // from mprof.goc
+typedef struct Bucket Bucket; // from mprof.h
typedef struct SpecialProfile SpecialProfile;
struct SpecialProfile
{
- Special;
+ Special special;
Bucket* b;
};
// An MSpan is a run of pages.
enum
{
- MSpanInUse = 0,
+ MSpanInUse = 0, // allocated for garbage collected heap
+ MSpanStack, // allocated for use by stack allocator
MSpanFree,
MSpanListHead,
MSpanDead,
@@ -418,7 +409,7 @@ struct MSpan
{
MSpan *next; // in a span linked list
MSpan *prev; // in a span linked list
- PageID start; // starting page number
+ pageID start; // starting page number
uintptr npages; // number of pages in span
MLink *freelist; // list of free objects
// sweep generation:
@@ -436,15 +427,13 @@ struct MSpan
int64 unusedsince; // First time spotted by GC in MSpanFree state
uintptr npreleased; // number of pages released to the OS
byte *limit; // end of data in span
- MTypes types; // types of allocated objects in this span
- Lock specialLock; // guards specials list
+ Mutex specialLock; // guards specials list
Special *specials; // linked list of special records sorted by offset.
- MLink *freebuf; // objects freed explicitly, not incorporated into freelist yet
};
-void runtime·MSpan_Init(MSpan *span, PageID start, uintptr npages);
+void runtime·MSpan_Init(MSpan *span, pageID start, uintptr npages);
void runtime·MSpan_EnsureSwept(MSpan *span);
-bool runtime·MSpan_Sweep(MSpan *span);
+bool runtime·MSpan_Sweep(MSpan *span, bool preserve);
// Every MSpan is in one doubly-linked list,
// either one of the MHeap's free lists or one of the
@@ -459,31 +448,29 @@ void runtime·MSpanList_Remove(MSpan *span); // from whatever list it is in
// Central list of free objects of a given size.
struct MCentral
{
- Lock;
+ Mutex lock;
int32 sizeclass;
MSpan nonempty; // list of spans with a free object
MSpan empty; // list of spans with no free objects (or cached in an MCache)
- int32 nfree; // # of objects available in nonempty spans
};
void runtime·MCentral_Init(MCentral *c, int32 sizeclass);
MSpan* runtime·MCentral_CacheSpan(MCentral *c);
void runtime·MCentral_UncacheSpan(MCentral *c, MSpan *s);
-bool runtime·MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end);
-void runtime·MCentral_FreeList(MCentral *c, MLink *start); // TODO: need this?
+bool runtime·MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end, bool preserve);
// Main malloc heap.
// The heap itself is the "free[]" and "large" arrays,
// but all the other global data is here too.
struct MHeap
{
- Lock;
+ Mutex lock;
MSpan free[MaxMHeapList]; // free lists of given length
MSpan freelarge; // free lists length >= MaxMHeapList
MSpan busy[MaxMHeapList]; // busy lists of large objects of given length
MSpan busylarge; // busy lists of large objects length >= MaxMHeapList
MSpan **allspans; // all spans out there
- MSpan **sweepspans; // copy of allspans referenced by sweeper
+ MSpan **gcspans; // copy of allspans referenced by GC marker or sweeper
uint32 nspan;
uint32 nspancap;
uint32 sweepgen; // sweep generation, see comment in MSpan
@@ -503,10 +490,10 @@ struct MHeap
// central free lists for small size classes.
// the padding makes sure that the MCentrals are
- // spaced CacheLineSize bytes apart, so that each MCentral.Lock
+ // spaced CacheLineSize bytes apart, so that each MCentral.lock
// gets its own cache line.
- struct {
- MCentral;
+ struct MHeapCentral {
+ MCentral mcentral;
byte pad[CacheLineSize];
} central[NumSizeClasses];
@@ -514,129 +501,120 @@ struct MHeap
FixAlloc cachealloc; // allocator for MCache*
FixAlloc specialfinalizeralloc; // allocator for SpecialFinalizer*
FixAlloc specialprofilealloc; // allocator for SpecialProfile*
- Lock speciallock; // lock for sepcial record allocators.
+ Mutex speciallock; // lock for sepcial record allocators.
// Malloc stats.
uint64 largefree; // bytes freed for large objects (>MaxSmallSize)
uint64 nlargefree; // number of frees for large objects (>MaxSmallSize)
uint64 nsmallfree[NumSizeClasses]; // number of frees for small objects (<=MaxSmallSize)
};
+#define runtime·mheap runtime·mheap_
extern MHeap runtime·mheap;
void runtime·MHeap_Init(MHeap *h);
MSpan* runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large, bool needzero);
+MSpan* runtime·MHeap_AllocStack(MHeap *h, uintptr npage);
void runtime·MHeap_Free(MHeap *h, MSpan *s, int32 acct);
+void runtime·MHeap_FreeStack(MHeap *h, MSpan *s);
MSpan* runtime·MHeap_Lookup(MHeap *h, void *v);
MSpan* runtime·MHeap_LookupMaybe(MHeap *h, void *v);
-void runtime·MGetSizeClassInfo(int32 sizeclass, uintptr *size, int32 *npages, int32 *nobj);
void* runtime·MHeap_SysAlloc(MHeap *h, uintptr n);
void runtime·MHeap_MapBits(MHeap *h);
void runtime·MHeap_MapSpans(MHeap *h);
-void runtime·MHeap_Scavenger(void);
-void runtime·MHeap_SplitSpan(MHeap *h, MSpan *s);
+void runtime·MHeap_Scavenge(int32 k, uint64 now, uint64 limit);
-void* runtime·mallocgc(uintptr size, uintptr typ, uint32 flag);
void* runtime·persistentalloc(uintptr size, uintptr align, uint64 *stat);
int32 runtime·mlookup(void *v, byte **base, uintptr *size, MSpan **s);
-void runtime·gc(int32 force);
uintptr runtime·sweepone(void);
-void runtime·markscan(void *v);
-void runtime·marknogc(void *v);
-void runtime·checkallocated(void *v, uintptr n);
-void runtime·markfreed(void *v);
-void runtime·checkfreed(void *v, uintptr n);
-extern int32 runtime·checking;
void runtime·markspan(void *v, uintptr size, uintptr n, bool leftover);
void runtime·unmarkspan(void *v, uintptr size);
void runtime·purgecachedstats(MCache*);
-void* runtime·cnew(Type*);
-void* runtime·cnewarray(Type*, intgo);
-void runtime·tracealloc(void*, uintptr, uintptr);
+void runtime·tracealloc(void*, uintptr, Type*);
void runtime·tracefree(void*, uintptr);
void runtime·tracegc(void);
-uintptr runtime·gettype(void*);
+int32 runtime·gcpercent;
+int32 runtime·readgogc(void);
+void runtime·clearpools(void);
enum
{
// flags to malloc
FlagNoScan = 1<<0, // GC doesn't have to scan object
- FlagNoProfiling = 1<<1, // must not profile
- FlagNoGC = 1<<2, // must not free or scan for pointers
- FlagNoZero = 1<<3, // don't zero memory
- FlagNoInvokeGC = 1<<4, // don't invoke GC
+ FlagNoZero = 1<<1, // don't zero memory
};
-void runtime·MProf_Malloc(void*, uintptr);
-void runtime·MProf_Free(Bucket*, uintptr, bool);
-void runtime·MProf_GC(void);
-void runtime·iterate_memprof(void (*callback)(Bucket*, uintptr, uintptr*, uintptr, uintptr, uintptr));
+void runtime·mProf_Malloc(void*, uintptr);
+void runtime·mProf_Free(Bucket*, uintptr, bool);
+void runtime·mProf_GC(void);
+void runtime·iterate_memprof(void (**callback)(Bucket*, uintptr, uintptr*, uintptr, uintptr, uintptr));
int32 runtime·gcprocs(void);
void runtime·helpgc(int32 nproc);
void runtime·gchelper(void);
void runtime·createfing(void);
G* runtime·wakefing(void);
+void runtime·getgcmask(byte*, Type*, byte**, uintptr*);
+
+// NOTE: Layout known to queuefinalizer.
+typedef struct Finalizer Finalizer;
+struct Finalizer
+{
+ FuncVal *fn; // function to call
+ void *arg; // ptr to object
+ uintptr nret; // bytes of return values from fn
+ Type *fint; // type of first argument of fn
+ PtrType *ot; // type of ptr to object
+};
+
+typedef struct FinBlock FinBlock;
+struct FinBlock
+{
+ FinBlock *alllink;
+ FinBlock *next;
+ int32 cnt;
+ int32 cap;
+ Finalizer fin[1];
+};
+extern Mutex runtime·finlock; // protects the following variables
+extern G* runtime·fing;
extern bool runtime·fingwait;
extern bool runtime·fingwake;
+extern FinBlock *runtime·finq; // list of finalizers that are to be executed
+extern FinBlock *runtime·finc; // cache of free blocks
-void runtime·setprofilebucket(void *p, Bucket *b);
+void runtime·setprofilebucket_m(void);
bool runtime·addfinalizer(void*, FuncVal *fn, uintptr, Type*, PtrType*);
void runtime·removefinalizer(void*);
void runtime·queuefinalizer(byte *p, FuncVal *fn, uintptr nret, Type *fint, PtrType *ot);
-
-void runtime·freeallspecials(MSpan *span, void *p, uintptr size);
bool runtime·freespecial(Special *s, void *p, uintptr size, bool freed);
-enum
-{
- TypeInfo_SingleObject = 0,
- TypeInfo_Array = 1,
- TypeInfo_Chan = 2,
-
- // Enables type information at the end of blocks allocated from heap
- DebugTypeAtBlockEnd = 0,
-};
-
// Information from the compiler about the layout of stack frames.
-typedef struct BitVector BitVector;
struct BitVector
{
int32 n; // # of bits
- uint32 *data;
+ uint8 *bytedata;
};
typedef struct StackMap StackMap;
struct StackMap
{
int32 n; // number of bitmaps
int32 nbit; // number of bits in each bitmap
- uint32 data[];
-};
-enum {
- // Pointer map
- BitsPerPointer = 2,
- BitsDead = 0,
- BitsScalar = 1,
- BitsPointer = 2,
- BitsMultiWord = 3,
- // BitsMultiWord will be set for the first word of a multi-word item.
- // When it is set, one of the following will be set for the second word.
- BitsString = 0,
- BitsSlice = 1,
- BitsIface = 2,
- BitsEface = 3,
+ uint8 bytedata[]; // bitmaps, each starting on a 32-bit boundary
};
// Returns pointer map data for the given stackmap index
// (the index is encoded in PCDATA_StackMapIndex).
BitVector runtime·stackmapdata(StackMap *stackmap, int32 n);
+extern BitVector runtime·gcdatamask;
+extern BitVector runtime·gcbssmask;
+
// defined in mgc0.go
void runtime·gc_m_ptr(Eface*);
void runtime·gc_g_ptr(Eface*);
void runtime·gc_itab_ptr(Eface*);
-void runtime·memorydump(void);
-int32 runtime·setgcpercent(int32);
+void runtime·setgcpercent_m(void);
// Value we use to mark dead pointers when GODEBUG=gcdead=1.
#define PoisonGC ((uintptr)0xf969696969696969ULL)
diff --git a/src/pkg/runtime/malloc_test.go b/src/runtime/malloc_test.go
index 128ec098c..b7795aa1d 100644
--- a/src/pkg/runtime/malloc_test.go
+++ b/src/runtime/malloc_test.go
@@ -16,14 +16,34 @@ func TestMemStats(t *testing.T) {
// Test that MemStats has sane values.
st := new(MemStats)
ReadMemStats(st)
- if st.HeapSys == 0 || st.StackSys == 0 || st.MSpanSys == 0 || st.MCacheSys == 0 ||
- st.BuckHashSys == 0 || st.GCSys == 0 || st.OtherSys == 0 {
- t.Fatalf("Zero sys value: %+v", *st)
+
+ // Everything except HeapReleased and HeapIdle, 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 {
+ t.Fatalf("Zero value: %+v", *st)
+ }
+
+ if st.Alloc > 1e10 || st.TotalAlloc > 1e11 || st.Sys > 1e10 || st.Lookups > 1e10 ||
+ st.Mallocs > 1e10 || st.Frees > 1e10 || st.HeapAlloc > 1e10 || st.HeapSys > 1e10 ||
+ st.HeapIdle > 1e10 || st.HeapInuse > 1e10 || st.HeapObjects > 1e10 || st.StackInuse > 1e10 ||
+ st.StackSys > 1e10 || st.MSpanInuse > 1e10 || st.MSpanSys > 1e10 || st.MCacheInuse > 1e10 ||
+ st.MCacheSys > 1e10 || st.BuckHashSys > 1e10 || st.GCSys > 1e10 || st.OtherSys > 1e10 ||
+ st.NextGC > 1e10 || st.NumGC > 1e9 {
+ t.Fatalf("Insanely high value (overflow?): %+v", *st)
}
+
if st.Sys != st.HeapSys+st.StackSys+st.MSpanSys+st.MCacheSys+
st.BuckHashSys+st.GCSys+st.OtherSys {
t.Fatalf("Bad sys value: %+v", *st)
}
+
+ if st.HeapIdle+st.HeapInuse != st.HeapSys {
+ t.Fatalf("HeapIdle(%d) + HeapInuse(%d) should be equal to HeapSys(%d), but isn't.", st.HeapIdle, st.HeapInuse, st.HeapSys)
+ }
}
var mallocSink uintptr
@@ -68,6 +88,19 @@ func BenchmarkMallocTypeInfo16(b *testing.B) {
mallocSink = x
}
+type LargeStruct struct {
+ x [16][]byte
+}
+
+func BenchmarkMallocLargeStruct(b *testing.B) {
+ var x uintptr
+ for i := 0; i < b.N; i++ {
+ p := make([]LargeStruct, 2)
+ x ^= uintptr(unsafe.Pointer(&p[0]))
+ }
+ mallocSink = x
+}
+
var n = flag.Int("n", 1000, "number of goroutines")
func BenchmarkGoroutineSelect(b *testing.B) {
@@ -100,7 +133,7 @@ func BenchmarkGoroutineBlocking(b *testing.B) {
func BenchmarkGoroutineForRange(b *testing.B) {
read := func(ch chan struct{}) {
- for _ = range ch {
+ for range ch {
}
}
benchHelper(b, *n, read)
diff --git a/src/pkg/runtime/map_test.go b/src/runtime/map_test.go
index e4e838349..92da2d820 100644
--- a/src/pkg/runtime/map_test.go
+++ b/src/runtime/map_test.go
@@ -253,7 +253,7 @@ func testConcurrentReadsAfterGrowth(t *testing.T, useReflect bool) {
for nr := 0; nr < numReader; nr++ {
go func() {
defer wg.Done()
- for _ = range m {
+ for range m {
}
}()
go func() {
@@ -412,30 +412,69 @@ func TestMapNanGrowIterator(t *testing.T) {
func TestMapIterOrder(t *testing.T) {
for _, n := range [...]int{3, 7, 9, 15} {
- // Make m be {0: true, 1: true, ..., n-1: true}.
+ for i := 0; i < 1000; i++ {
+ // Make m be {0: true, 1: true, ..., n-1: true}.
+ m := make(map[int]bool)
+ for i := 0; i < n; i++ {
+ m[i] = true
+ }
+ // Check that iterating over the map produces at least two different orderings.
+ ord := func() []int {
+ var s []int
+ for key := range m {
+ s = append(s, key)
+ }
+ return s
+ }
+ first := ord()
+ ok := false
+ for try := 0; try < 100; try++ {
+ if !reflect.DeepEqual(first, ord()) {
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ t.Errorf("Map with n=%d elements had consistent iteration order: %v", n, first)
+ break
+ }
+ }
+ }
+}
+
+// Issue 8410
+func TestMapSparseIterOrder(t *testing.T) {
+ // Run several rounds to increase the probability
+ // of failure. One is not enough.
+NextRound:
+ for round := 0; round < 10; round++ {
m := make(map[int]bool)
- for i := 0; i < n; i++ {
+ // Add 1000 items, remove 980.
+ for i := 0; i < 1000; i++ {
m[i] = true
}
- // Check that iterating over the map produces at least two different orderings.
- ord := func() []int {
- var s []int
- for key := range m {
- s = append(s, key)
- }
- return s
+ for i := 20; i < 1000; i++ {
+ delete(m, i)
}
- first := ord()
- ok := false
- for try := 0; try < 100; try++ {
- if !reflect.DeepEqual(first, ord()) {
- ok = true
- break
- }
+
+ var first []int
+ for i := range m {
+ first = append(first, i)
}
- if !ok {
- t.Errorf("Map with n=%d elements had consistent iteration order: %v", n, first)
+
+ // 800 chances to get a different iteration order.
+ // See bug 8736 for why we need so many tries.
+ for n := 0; n < 800; n++ {
+ idx := 0
+ for i := range m {
+ if i != first[idx] {
+ // iteration order changed.
+ continue NextRound
+ }
+ idx++
+ }
}
+ t.Fatalf("constant iteration order on round %d: %v", round, first)
}
}
@@ -475,3 +514,24 @@ func TestMapStringBytesLookup(t *testing.T) {
t.Errorf("AllocsPerRun for x,ok = m[string(buf)] = %v, want 0", n)
}
}
+
+func benchmarkMapPop(b *testing.B, n int) {
+ m := map[int]int{}
+ for i := 0; i < b.N; i++ {
+ for j := 0; j < n; j++ {
+ m[j] = j
+ }
+ for j := 0; j < n; j++ {
+ // Use iterator to pop an element.
+ // We want this to be fast, see issue 8412.
+ for k := range m {
+ delete(m, k)
+ break
+ }
+ }
+ }
+}
+
+func BenchmarkMapPop100(b *testing.B) { benchmarkMapPop(b, 100) }
+func BenchmarkMapPop1000(b *testing.B) { benchmarkMapPop(b, 1000) }
+func BenchmarkMapPop10000(b *testing.B) { benchmarkMapPop(b, 10000) }
diff --git a/src/pkg/runtime/mapspeed_test.go b/src/runtime/mapspeed_test.go
index da45ea11e..119eb3f39 100644
--- a/src/pkg/runtime/mapspeed_test.go
+++ b/src/runtime/mapspeed_test.go
@@ -241,7 +241,7 @@ func BenchmarkMapIter(b *testing.B) {
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
- for _, _ = range m {
+ for range m {
}
}
}
@@ -250,7 +250,7 @@ func BenchmarkMapIterEmpty(b *testing.B) {
m := make(map[int]bool)
b.ResetTimer()
for i := 0; i < b.N; i++ {
- for _, _ = range m {
+ for range m {
}
}
}
diff --git a/src/pkg/runtime/mcache.c b/src/runtime/mcache.c
index 26e3db2dc..5fdbe3266 100644
--- a/src/pkg/runtime/mcache.c
+++ b/src/runtime/mcache.c
@@ -13,7 +13,7 @@
extern volatile intgo runtime·MemProfileRate;
// dummy MSpan that contains no free objects.
-static MSpan emptymspan;
+MSpan runtime·emptymspan;
MCache*
runtime·allocmcache(void)
@@ -22,12 +22,12 @@ runtime·allocmcache(void)
MCache *c;
int32 i;
- runtime·lock(&runtime·mheap);
+ runtime·lock(&runtime·mheap.lock);
c = runtime·FixAlloc_Alloc(&runtime·mheap.cachealloc);
- runtime·unlock(&runtime·mheap);
+ runtime·unlock(&runtime·mheap.lock);
runtime·memclr((byte*)c, sizeof(*c));
for(i = 0; i < NumSizeClasses; i++)
- c->alloc[i] = &emptymspan;
+ c->alloc[i] = &runtime·emptymspan;
// Set first allocation sample size.
rate = runtime·MemProfileRate;
@@ -39,14 +39,36 @@ runtime·allocmcache(void)
return c;
}
-void
-runtime·freemcache(MCache *c)
+static void
+freemcache(MCache *c)
{
runtime·MCache_ReleaseAll(c);
- runtime·lock(&runtime·mheap);
+ runtime·stackcache_clear(c);
+ runtime·gcworkbuffree(c->gcworkbuf);
+ runtime·lock(&runtime·mheap.lock);
runtime·purgecachedstats(c);
runtime·FixAlloc_Free(&runtime·mheap.cachealloc, c);
- runtime·unlock(&runtime·mheap);
+ runtime·unlock(&runtime·mheap.lock);
+}
+
+static void
+freemcache_m(void)
+{
+ MCache *c;
+
+ c = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ freemcache(c);
+}
+
+void
+runtime·freemcache(MCache *c)
+{
+ void (*fn)(void);
+
+ g->m->ptrarg[0] = c;
+ fn = freemcache_m;
+ runtime·onM(&fn);
}
// Gets a span that has a free object in it and assigns it
@@ -54,28 +76,18 @@ runtime·freemcache(MCache *c)
MSpan*
runtime·MCache_Refill(MCache *c, int32 sizeclass)
{
- MCacheList *l;
MSpan *s;
- m->locks++;
+ g->m->locks++;
// Return the current cached span to the central lists.
s = c->alloc[sizeclass];
if(s->freelist != nil)
runtime·throw("refill on a nonempty span");
- if(s != &emptymspan)
- runtime·MCentral_UncacheSpan(&runtime·mheap.central[sizeclass], s);
-
- // Push any explicitly freed objects to the central lists.
- // Not required, but it seems like a good time to do it.
- l = &c->free[sizeclass];
- if(l->nlist > 0) {
- runtime·MCentral_FreeList(&runtime·mheap.central[sizeclass], l->list);
- l->list = nil;
- l->nlist = 0;
- }
+ if(s != &runtime·emptymspan)
+ s->incache = false;
// Get a new cached span from the central lists.
- s = runtime·MCentral_CacheSpan(&runtime·mheap.central[sizeclass]);
+ s = runtime·MCentral_CacheSpan(&runtime·mheap.central[sizeclass].mcentral);
if(s == nil)
runtime·throw("out of memory");
if(s->freelist == nil) {
@@ -83,48 +95,21 @@ runtime·MCache_Refill(MCache *c, int32 sizeclass)
runtime·throw("empty span");
}
c->alloc[sizeclass] = s;
- m->locks--;
+ g->m->locks--;
return s;
}
void
-runtime·MCache_Free(MCache *c, MLink *p, int32 sizeclass, uintptr size)
-{
- MCacheList *l;
-
- // Put on free list.
- l = &c->free[sizeclass];
- p->next = l->list;
- l->list = p;
- l->nlist++;
-
- // We transfer a span at a time from MCentral to MCache,
- // so we'll do the same in the other direction.
- if(l->nlist >= (runtime·class_to_allocnpages[sizeclass]<<PageShift)/size) {
- runtime·MCentral_FreeList(&runtime·mheap.central[sizeclass], l->list);
- l->list = nil;
- l->nlist = 0;
- }
-}
-
-void
runtime·MCache_ReleaseAll(MCache *c)
{
int32 i;
MSpan *s;
- MCacheList *l;
for(i=0; i<NumSizeClasses; i++) {
s = c->alloc[i];
- if(s != &emptymspan) {
- runtime·MCentral_UncacheSpan(&runtime·mheap.central[i], s);
- c->alloc[i] = &emptymspan;
- }
- l = &c->free[i];
- if(l->nlist > 0) {
- runtime·MCentral_FreeList(&runtime·mheap.central[i], l->list);
- l->list = nil;
- l->nlist = 0;
+ if(s != &runtime·emptymspan) {
+ runtime·MCentral_UncacheSpan(&runtime·mheap.central[i].mcentral, s);
+ c->alloc[i] = &runtime·emptymspan;
}
}
}
diff --git a/src/pkg/runtime/mcentral.c b/src/runtime/mcentral.c
index 203558fca..fe6bcfeb1 100644
--- a/src/pkg/runtime/mcentral.c
+++ b/src/runtime/mcentral.c
@@ -9,18 +9,12 @@
// The MCentral doesn't actually contain the list of free objects; the MSpan does.
// Each MCentral is two lists of MSpans: those with free objects (c->nonempty)
// and those that are completely allocated (c->empty).
-//
-// TODO(rsc): tcmalloc uses a "transfer cache" to split the list
-// into sections of class_to_transfercount[sizeclass] objects
-// so that it is faster to move those lists between MCaches and MCentrals.
#include "runtime.h"
#include "arch_GOARCH.h"
#include "malloc.h"
-static bool MCentral_Grow(MCentral *c);
-static void MCentral_Free(MCentral *c, MLink *v);
-static void MCentral_ReturnToHeap(MCentral *c, MSpan *s);
+static MSpan* MCentral_Grow(MCentral *c);
// Initialize a single central free list.
void
@@ -39,22 +33,25 @@ runtime·MCentral_CacheSpan(MCentral *c)
int32 cap, n;
uint32 sg;
- runtime·lock(c);
+ runtime·lock(&c->lock);
sg = runtime·mheap.sweepgen;
retry:
for(s = c->nonempty.next; s != &c->nonempty; s = s->next) {
if(s->sweepgen == sg-2 && runtime·cas(&s->sweepgen, sg-2, sg-1)) {
- runtime·unlock(c);
- runtime·MSpan_Sweep(s);
- runtime·lock(c);
- // the span could have been moved to heap, retry
- goto retry;
+ runtime·MSpanList_Remove(s);
+ runtime·MSpanList_InsertBack(&c->empty, s);
+ runtime·unlock(&c->lock);
+ runtime·MSpan_Sweep(s, true);
+ goto havespan;
}
if(s->sweepgen == sg-1) {
// the span is being swept by background sweeper, skip
continue;
}
// we have a nonempty span that does not require sweeping, allocate from it
+ runtime·MSpanList_Remove(s);
+ runtime·MSpanList_InsertBack(&c->empty, s);
+ runtime·unlock(&c->lock);
goto havespan;
}
@@ -65,10 +62,13 @@ retry:
runtime·MSpanList_Remove(s);
// swept spans are at the end of the list
runtime·MSpanList_InsertBack(&c->empty, s);
- runtime·unlock(c);
- runtime·MSpan_Sweep(s);
- runtime·lock(c);
- // the span could be moved to nonempty or heap, retry
+ runtime·unlock(&c->lock);
+ runtime·MSpan_Sweep(s, true);
+ if(s->freelist != nil)
+ goto havespan;
+ runtime·lock(&c->lock);
+ // the span is still empty after sweep
+ // it is already in the empty list, so just retry
goto retry;
}
if(s->sweepgen == sg-1) {
@@ -79,26 +79,26 @@ retry:
// all subsequent ones must also be either swept or in process of sweeping
break;
}
+ runtime·unlock(&c->lock);
// Replenish central list if empty.
- if(!MCentral_Grow(c)) {
- runtime·unlock(c);
+ s = MCentral_Grow(c);
+ if(s == nil)
return nil;
- }
- goto retry;
+ runtime·lock(&c->lock);
+ runtime·MSpanList_InsertBack(&c->empty, s);
+ runtime·unlock(&c->lock);
havespan:
+ // At this point s is a non-empty span, queued at the end of the empty list,
+ // c is unlocked.
cap = (s->npages << PageShift) / s->elemsize;
n = cap - s->ref;
if(n == 0)
runtime·throw("empty span");
if(s->freelist == nil)
runtime·throw("freelist empty");
- c->nfree -= n;
- runtime·MSpanList_Remove(s);
- runtime·MSpanList_InsertBack(&c->empty, s);
s->incache = true;
- runtime·unlock(c);
return s;
}
@@ -106,120 +106,61 @@ havespan:
void
runtime·MCentral_UncacheSpan(MCentral *c, MSpan *s)
{
- MLink *v;
int32 cap, n;
- runtime·lock(c);
+ runtime·lock(&c->lock);
s->incache = false;
- // Move any explicitly freed items from the freebuf to the freelist.
- while((v = s->freebuf) != nil) {
- s->freebuf = v->next;
- runtime·markfreed(v);
- v->next = s->freelist;
- s->freelist = v;
- s->ref--;
- }
+ if(s->ref == 0)
+ runtime·throw("uncaching full span");
- if(s->ref == 0) {
- // Free back to heap. Unlikely, but possible.
- MCentral_ReturnToHeap(c, s); // unlocks c
- return;
- }
-
cap = (s->npages << PageShift) / s->elemsize;
n = cap - s->ref;
if(n > 0) {
- c->nfree += n;
- runtime·MSpanList_Remove(s);
- runtime·MSpanList_Insert(&c->nonempty, s);
- }
- runtime·unlock(c);
-}
-
-// Free the list of objects back into the central free list c.
-// Called from runtime·free.
-void
-runtime·MCentral_FreeList(MCentral *c, MLink *start)
-{
- MLink *next;
-
- runtime·lock(c);
- for(; start != nil; start = next) {
- next = start->next;
- MCentral_Free(c, start);
- }
- runtime·unlock(c);
-}
-
-// Helper: free one object back into the central free list.
-// Caller must hold lock on c on entry. Holds lock on exit.
-static void
-MCentral_Free(MCentral *c, MLink *v)
-{
- MSpan *s;
-
- // Find span for v.
- s = runtime·MHeap_Lookup(&runtime·mheap, v);
- if(s == nil || s->ref == 0)
- runtime·throw("invalid free");
- if(s->sweepgen != runtime·mheap.sweepgen)
- runtime·throw("free into unswept span");
-
- // If the span is currently being used unsynchronized by an MCache,
- // we can't modify the freelist. Add to the freebuf instead. The
- // items will get moved to the freelist when the span is returned
- // by the MCache.
- if(s->incache) {
- v->next = s->freebuf;
- s->freebuf = v;
- return;
- }
-
- // Move span to nonempty if necessary.
- if(s->freelist == nil) {
runtime·MSpanList_Remove(s);
runtime·MSpanList_Insert(&c->nonempty, s);
}
-
- // Add the object to span's free list.
- runtime·markfreed(v);
- v->next = s->freelist;
- s->freelist = v;
- s->ref--;
- c->nfree++;
-
- // If s is completely freed, return it to the heap.
- if(s->ref == 0) {
- MCentral_ReturnToHeap(c, s); // unlocks c
- runtime·lock(c);
- }
+ runtime·unlock(&c->lock);
}
// Free n objects from a span s back into the central free list c.
// Called during sweep.
// Returns true if the span was returned to heap. Sets sweepgen to
// the latest generation.
+// If preserve=true, don't return the span to heap nor relink in MCentral lists;
+// caller takes care of it.
bool
-runtime·MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end)
+runtime·MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end, bool preserve)
{
+ bool wasempty;
+
if(s->incache)
runtime·throw("freespan into cached span");
- runtime·lock(c);
+
+ // Add the objects back to s's free list.
+ wasempty = s->freelist == nil;
+ end->next = s->freelist;
+ s->freelist = start;
+ s->ref -= n;
+
+ if(preserve) {
+ // preserve is set only when called from MCentral_CacheSpan above,
+ // the span must be in the empty list.
+ if(s->next == nil)
+ runtime·throw("can't preserve unlinked span");
+ runtime·atomicstore(&s->sweepgen, runtime·mheap.sweepgen);
+ return false;
+ }
+
+ runtime·lock(&c->lock);
// Move to nonempty if necessary.
- if(s->freelist == nil) {
+ if(wasempty) {
runtime·MSpanList_Remove(s);
runtime·MSpanList_Insert(&c->nonempty, s);
}
- // Add the objects back to s's free list.
- end->next = s->freelist;
- s->freelist = start;
- s->ref -= n;
- c->nfree += n;
-
// 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
@@ -227,47 +168,35 @@ runtime·MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *
runtime·atomicstore(&s->sweepgen, runtime·mheap.sweepgen);
if(s->ref != 0) {
- runtime·unlock(c);
+ runtime·unlock(&c->lock);
return false;
}
// s is completely freed, return it to the heap.
- MCentral_ReturnToHeap(c, s); // unlocks c
+ runtime·MSpanList_Remove(s);
+ s->needzero = 1;
+ s->freelist = nil;
+ runtime·unlock(&c->lock);
+ runtime·unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift);
+ runtime·MHeap_Free(&runtime·mheap, s, 0);
return true;
}
-void
-runtime·MGetSizeClassInfo(int32 sizeclass, uintptr *sizep, int32 *npagesp, int32 *nobj)
-{
- int32 size;
- int32 npages;
-
- npages = runtime·class_to_allocnpages[sizeclass];
- size = runtime·class_to_size[sizeclass];
- *npagesp = npages;
- *sizep = size;
- *nobj = (npages << PageShift) / size;
-}
-
-// Fetch a new span from the heap and
-// carve into objects for the free list.
-static bool
+// Fetch a new span from the heap and carve into objects for the free list.
+static MSpan*
MCentral_Grow(MCentral *c)
{
- int32 i, n, npages;
- uintptr size;
+ uintptr size, npages, i, n;
MLink **tailp, *v;
byte *p;
MSpan *s;
- runtime·unlock(c);
- runtime·MGetSizeClassInfo(c->sizeclass, &size, &npages, &n);
+ npages = runtime·class_to_allocnpages[c->sizeclass];
+ size = runtime·class_to_size[c->sizeclass];
+ n = (npages << PageShift) / size;
s = runtime·MHeap_Alloc(&runtime·mheap, npages, c->sizeclass, 0, 1);
- if(s == nil) {
- // TODO(rsc): Log out of memory
- runtime·lock(c);
- return false;
- }
+ if(s == nil)
+ return nil;
// Carve span into sequence of blocks.
tailp = &s->freelist;
@@ -281,27 +210,5 @@ MCentral_Grow(MCentral *c)
}
*tailp = nil;
runtime·markspan((byte*)(s->start<<PageShift), size, n, size*n < (s->npages<<PageShift));
-
- runtime·lock(c);
- c->nfree += n;
- runtime·MSpanList_Insert(&c->nonempty, s);
- return true;
-}
-
-// Return s to the heap. s must be unused (s->ref == 0). Unlocks c.
-static void
-MCentral_ReturnToHeap(MCentral *c, MSpan *s)
-{
- int32 size;
-
- size = runtime·class_to_size[c->sizeclass];
- runtime·MSpanList_Remove(s);
- s->needzero = 1;
- s->freelist = nil;
- if(s->ref != 0)
- runtime·throw("ref wrong");
- c->nfree -= (s->npages << PageShift) / size;
- runtime·unlock(c);
- runtime·unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift);
- runtime·MHeap_Free(&runtime·mheap, s, 0);
+ return s;
}
diff --git a/src/pkg/runtime/mem.go b/src/runtime/mem.go
index fa308b5d9..e6f1eb0e6 100644
--- a/src/pkg/runtime/mem.go
+++ b/src/runtime/mem.go
@@ -30,7 +30,7 @@ type MemStats struct {
// Low-level fixed-size structure allocator statistics.
// Inuse is bytes used now.
// Sys is bytes obtained from system.
- StackInuse uint64 // bootstrap stacks
+ StackInuse uint64 // bytes used by stack allocator
StackSys uint64
MSpanInuse uint64 // mspan structures
MSpanSys uint64
@@ -41,10 +41,11 @@ type MemStats struct {
OtherSys uint64 // other system allocations
// Garbage collector statistics.
- NextGC uint64 // next run in HeapAlloc time (bytes)
- LastGC uint64 // last run in absolute time (ns)
+ NextGC uint64 // next collection will happen when HeapAlloc ≥ this amount
+ LastGC uint64 // end time of last collection (nanoseconds since 1970)
PauseTotalNs uint64
- PauseNs [256]uint64 // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
+ PauseNs [256]uint64 // circular buffer of recent GC pause durations, most recent at [(NumGC+255)%256]
+ PauseEnd [256]uint64 // circular buffer of recent GC pause end times
NumGC uint32
EnableGC bool
DebugGC bool
@@ -64,12 +65,44 @@ func init() {
var memStats MemStats
if sizeof_C_MStats != unsafe.Sizeof(memStats) {
println(sizeof_C_MStats, unsafe.Sizeof(memStats))
- panic("MStats vs MemStatsType size mismatch")
+ gothrow("MStats vs MemStatsType size mismatch")
}
}
// ReadMemStats populates m with memory allocator statistics.
-func ReadMemStats(m *MemStats)
+func ReadMemStats(m *MemStats) {
+ // Have to acquire worldsema to stop the world,
+ // because stoptheworld can only be used by
+ // one goroutine at a time, and there might be
+ // a pending garbage collection already calling it.
+ semacquire(&worldsema, false)
+ gp := getg()
+ gp.m.gcing = 1
+ onM(stoptheworld)
-// GC runs a garbage collection.
-func GC()
+ gp.m.ptrarg[0] = noescape(unsafe.Pointer(m))
+ onM(readmemstats_m)
+
+ gp.m.gcing = 0
+ gp.m.locks++
+ semrelease(&worldsema)
+ onM(starttheworld)
+ gp.m.locks--
+}
+
+// Implementation of runtime/debug.WriteHeapDump
+func writeHeapDump(fd uintptr) {
+ semacquire(&worldsema, false)
+ gp := getg()
+ gp.m.gcing = 1
+ onM(stoptheworld)
+
+ gp.m.scalararg[0] = fd
+ onM(writeheapdump_m)
+
+ gp.m.gcing = 0
+ gp.m.locks++
+ semrelease(&worldsema)
+ onM(starttheworld)
+ gp.m.locks--
+}
diff --git a/src/pkg/runtime/mem_darwin.c b/src/runtime/mem_darwin.c
index 878c4e1c5..bf3ede577 100644
--- a/src/pkg/runtime/mem_darwin.c
+++ b/src/runtime/mem_darwin.c
@@ -7,9 +7,11 @@
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "malloc.h"
+#include "textflag.h"
+#pragma textflag NOSPLIT
void*
-runtime·SysAlloc(uintptr n, uint64 *stat)
+runtime·sysAlloc(uintptr n, uint64 *stat)
{
void *v;
diff --git a/src/pkg/runtime/mem_dragonfly.c b/src/runtime/mem_dragonfly.c
index c270332cb..11457b2c0 100644
--- a/src/pkg/runtime/mem_dragonfly.c
+++ b/src/runtime/mem_dragonfly.c
@@ -7,14 +7,16 @@
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "malloc.h"
+#include "textflag.h"
enum
{
ENOMEM = 12,
};
+#pragma textflag NOSPLIT
void*
-runtime·SysAlloc(uintptr n, uint64 *stat)
+runtime·sysAlloc(uintptr n, uint64 *stat)
{
void *v;
diff --git a/src/pkg/runtime/mem_freebsd.c b/src/runtime/mem_freebsd.c
index 586947a2d..18a9a2f5b 100644
--- a/src/pkg/runtime/mem_freebsd.c
+++ b/src/runtime/mem_freebsd.c
@@ -7,14 +7,16 @@
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "malloc.h"
+#include "textflag.h"
enum
{
ENOMEM = 12,
};
+#pragma textflag NOSPLIT
void*
-runtime·SysAlloc(uintptr n, uint64 *stat)
+runtime·sysAlloc(uintptr n, uint64 *stat)
{
void *v;
diff --git a/src/pkg/runtime/mem_linux.c b/src/runtime/mem_linux.c
index 635594c36..bfb405607 100644
--- a/src/pkg/runtime/mem_linux.c
+++ b/src/runtime/mem_linux.c
@@ -7,6 +7,7 @@
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "malloc.h"
+#include "textflag.h"
enum
{
@@ -57,8 +58,9 @@ mmap_fixed(byte *v, uintptr n, int32 prot, int32 flags, int32 fd, uint32 offset)
return p;
}
+#pragma textflag NOSPLIT
void*
-runtime·SysAlloc(uintptr n, uint64 *stat)
+runtime·sysAlloc(uintptr n, uint64 *stat)
{
void *p;
diff --git a/src/pkg/runtime/mem_nacl.c b/src/runtime/mem_nacl.c
index e2bca40a4..6c836f18a 100644
--- a/src/pkg/runtime/mem_nacl.c
+++ b/src/runtime/mem_nacl.c
@@ -7,26 +7,28 @@
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "malloc.h"
+#include "textflag.h"
enum
{
Debug = 0,
};
+#pragma textflag NOSPLIT
void*
-runtime·SysAlloc(uintptr n, uint64 *stat)
+runtime·sysAlloc(uintptr n, uint64 *stat)
{
void *v;
v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
if(v < (void*)4096) {
if(Debug)
- runtime·printf("SysAlloc(%p): %p\n", n, v);
+ runtime·printf("sysAlloc(%p): %p\n", n, v);
return nil;
}
runtime·xadd64(stat, n);
if(Debug)
- runtime·printf("SysAlloc(%p) = %p\n", n, v);
+ runtime·printf("sysAlloc(%p) = %p\n", n, v);
return v;
}
diff --git a/src/pkg/runtime/mem_netbsd.c b/src/runtime/mem_netbsd.c
index 861ae90c7..31820e517 100644
--- a/src/pkg/runtime/mem_netbsd.c
+++ b/src/runtime/mem_netbsd.c
@@ -7,14 +7,16 @@
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "malloc.h"
+#include "textflag.h"
enum
{
ENOMEM = 12,
};
+#pragma textflag NOSPLIT
void*
-runtime·SysAlloc(uintptr n, uint64 *stat)
+runtime·sysAlloc(uintptr n, uint64 *stat)
{
void *v;
diff --git a/src/pkg/runtime/mem_openbsd.c b/src/runtime/mem_openbsd.c
index 861ae90c7..31820e517 100644
--- a/src/pkg/runtime/mem_openbsd.c
+++ b/src/runtime/mem_openbsd.c
@@ -7,14 +7,16 @@
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "malloc.h"
+#include "textflag.h"
enum
{
ENOMEM = 12,
};
+#pragma textflag NOSPLIT
void*
-runtime·SysAlloc(uintptr n, uint64 *stat)
+runtime·sysAlloc(uintptr n, uint64 *stat)
{
void *v;
diff --git a/src/pkg/runtime/mem_plan9.c b/src/runtime/mem_plan9.c
index bbf04c7ed..d673d6f83 100644
--- a/src/pkg/runtime/mem_plan9.c
+++ b/src/runtime/mem_plan9.c
@@ -7,18 +7,20 @@
#include "arch_GOARCH.h"
#include "malloc.h"
#include "os_GOOS.h"
+#include "textflag.h"
-extern byte end[];
-static byte *bloc = { end };
-static Lock memlock;
+extern byte runtime·end[];
+#pragma dataflag NOPTR
+static byte *bloc = { runtime·end };
+static Mutex memlock;
enum
{
Round = PAGESIZE-1
};
-void*
-runtime·SysAlloc(uintptr nbytes, uint64 *stat)
+static void*
+brk(uintptr nbytes)
{
uintptr bl;
@@ -31,8 +33,42 @@ runtime·SysAlloc(uintptr nbytes, uint64 *stat)
}
bloc = (byte*)bl + nbytes;
runtime·unlock(&memlock);
- runtime·xadd64(stat, nbytes);
- return (void*)bl;
+ return (void*)bl;
+}
+
+static void
+sysalloc(void)
+{
+ uintptr nbytes;
+ uint64 *stat;
+ void *p;
+
+ nbytes = g->m->scalararg[0];
+ stat = g->m->ptrarg[0];
+ g->m->scalararg[0] = 0;
+ g->m->ptrarg[0] = nil;
+
+ p = brk(nbytes);
+ if(p != nil)
+ runtime·xadd64(stat, nbytes);
+
+ g->m->ptrarg[0] = p;
+}
+
+#pragma textflag NOSPLIT
+void*
+runtime·sysAlloc(uintptr nbytes, uint64 *stat)
+{
+ void (*fn)(void);
+ void *p;
+
+ g->m->scalararg[0] = nbytes;
+ g->m->ptrarg[0] = stat;
+ fn = sysalloc;
+ runtime·onM(&fn);
+ p = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ return p;
}
void
@@ -42,7 +78,7 @@ runtime·SysFree(void *v, uintptr nbytes, uint64 *stat)
runtime·lock(&memlock);
// from tiny/mem.c
// Push pointer back if this is a free
- // of the most recent SysAlloc.
+ // of the most recent sysAlloc.
nbytes += (nbytes + Round) & ~Round;
if(bloc == (byte*)v+nbytes)
bloc -= nbytes;
@@ -64,7 +100,10 @@ runtime·SysUsed(void *v, uintptr nbytes)
void
runtime·SysMap(void *v, uintptr nbytes, bool reserved, uint64 *stat)
{
- USED(v, nbytes, reserved, stat);
+ // SysReserve has already allocated all heap memory,
+ // but has not adjusted stats.
+ USED(v, reserved);
+ runtime·xadd64(stat, nbytes);
}
void
@@ -78,5 +117,5 @@ runtime·SysReserve(void *v, uintptr nbytes, bool *reserved)
{
USED(v);
*reserved = true;
- return runtime·SysAlloc(nbytes, &mstats.heap_sys);
+ return brk(nbytes);
}
diff --git a/src/pkg/runtime/mem_solaris.c b/src/runtime/mem_solaris.c
index 034222887..8e90ba1d9 100644
--- a/src/pkg/runtime/mem_solaris.c
+++ b/src/runtime/mem_solaris.c
@@ -7,14 +7,16 @@
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "malloc.h"
+#include "textflag.h"
enum
{
ENOMEM = 12,
};
+#pragma textflag NOSPLIT
void*
-runtime·SysAlloc(uintptr n, uint64 *stat)
+runtime·sysAlloc(uintptr n, uint64 *stat)
{
void *v;
diff --git a/src/pkg/runtime/mem_windows.c b/src/runtime/mem_windows.c
index 77ec6e926..6ea992020 100644
--- a/src/pkg/runtime/mem_windows.c
+++ b/src/runtime/mem_windows.c
@@ -7,6 +7,7 @@
#include "os_GOOS.h"
#include "defs_GOOS_GOARCH.h"
#include "malloc.h"
+#include "textflag.h"
enum {
MEM_COMMIT = 0x1000,
@@ -25,11 +26,12 @@ extern void *runtime·VirtualAlloc;
extern void *runtime·VirtualFree;
extern void *runtime·VirtualProtect;
+#pragma textflag NOSPLIT
void*
-runtime·SysAlloc(uintptr n, uint64 *stat)
+runtime·sysAlloc(uintptr n, uint64 *stat)
{
runtime·xadd64(stat, n);
- return runtime·stdcall(runtime·VirtualAlloc, 4, nil, n, (uintptr)(MEM_COMMIT|MEM_RESERVE), (uintptr)PAGE_READWRITE);
+ return runtime·stdcall4(runtime·VirtualAlloc, 0, n, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
}
void
@@ -38,7 +40,7 @@ runtime·SysUnused(void *v, uintptr n)
void *r;
uintptr small;
- r = runtime·stdcall(runtime·VirtualFree, 3, v, n, (uintptr)MEM_DECOMMIT);
+ r = runtime·stdcall3(runtime·VirtualFree, (uintptr)v, n, MEM_DECOMMIT);
if(r != nil)
return;
@@ -53,7 +55,7 @@ runtime·SysUnused(void *v, uintptr n)
// in the worst case, but that's fast enough.
while(n > 0) {
small = n;
- while(small >= 4096 && runtime·stdcall(runtime·VirtualFree, 3, v, small, (uintptr)MEM_DECOMMIT) == nil)
+ while(small >= 4096 && runtime·stdcall3(runtime·VirtualFree, (uintptr)v, small, MEM_DECOMMIT) == nil)
small = (small / 2) & ~(4096-1);
if(small < 4096)
runtime·throw("runtime: failed to decommit pages");
@@ -66,10 +68,22 @@ void
runtime·SysUsed(void *v, uintptr n)
{
void *r;
+ uintptr small;
- r = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_COMMIT, (uintptr)PAGE_READWRITE);
+ r = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_COMMIT, PAGE_READWRITE);
if(r != v)
runtime·throw("runtime: failed to commit pages");
+
+ // Commit failed. See SysUnused.
+ while(n > 0) {
+ small = n;
+ while(small >= 4096 && runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, small, MEM_COMMIT, PAGE_READWRITE) == nil)
+ small = (small / 2) & ~(4096-1);
+ if(small < 4096)
+ runtime·throw("runtime: failed to decommit pages");
+ v = (byte*)v + small;
+ n -= small;
+ }
}
void
@@ -78,7 +92,7 @@ runtime·SysFree(void *v, uintptr n, uint64 *stat)
uintptr r;
runtime·xadd64(stat, -(uint64)n);
- r = (uintptr)runtime·stdcall(runtime·VirtualFree, 3, v, (uintptr)0, (uintptr)MEM_RELEASE);
+ r = (uintptr)runtime·stdcall3(runtime·VirtualFree, (uintptr)v, 0, MEM_RELEASE);
if(r == 0)
runtime·throw("runtime: failed to release pages");
}
@@ -96,12 +110,12 @@ runtime·SysReserve(void *v, uintptr n, bool *reserved)
*reserved = true;
// v is just a hint.
// First try at v.
- v = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_RESERVE, (uintptr)PAGE_READWRITE);
+ v = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_RESERVE, PAGE_READWRITE);
if(v != nil)
return v;
// Next let the kernel choose the address.
- return runtime·stdcall(runtime·VirtualAlloc, 4, nil, n, (uintptr)MEM_RESERVE, (uintptr)PAGE_READWRITE);
+ return runtime·stdcall4(runtime·VirtualAlloc, 0, n, MEM_RESERVE, PAGE_READWRITE);
}
void
@@ -112,7 +126,7 @@ runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
USED(reserved);
runtime·xadd64(stat, n);
- p = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_COMMIT, (uintptr)PAGE_READWRITE);
+ p = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_COMMIT, PAGE_READWRITE);
if(p != v)
runtime·throw("runtime: cannot map pages in arena address space");
}
diff --git a/src/pkg/runtime/memclr_386.s b/src/runtime/memclr_386.s
index 4b7580cb4..1520aea2e 100644
--- a/src/pkg/runtime/memclr_386.s
+++ b/src/runtime/memclr_386.s
@@ -4,7 +4,9 @@
// +build !plan9
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+
+// NOTE: Windows externalthreadhandler expects memclr to preserve DX.
// void runtime·memclr(void*, uintptr)
TEXT runtime·memclr(SB), NOSPLIT, $0-8
@@ -63,6 +65,7 @@ clr_loop:
clr_1or2:
MOVB AX, (DI)
MOVB AX, -1(DI)(BX*1)
+ RET
clr_0:
RET
clr_3or4:
diff --git a/src/pkg/runtime/memclr_amd64.s b/src/runtime/memclr_amd64.s
index 6b79363b2..94a2c7f23 100644
--- a/src/pkg/runtime/memclr_amd64.s
+++ b/src/runtime/memclr_amd64.s
@@ -4,7 +4,9 @@
// +build !plan9
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+
+// NOTE: Windows externalthreadhandler expects memclr to preserve DX.
// void runtime·memclr(void*, uintptr)
TEXT runtime·memclr(SB), NOSPLIT, $0-16
@@ -62,6 +64,7 @@ clr_loop:
clr_1or2:
MOVB AX, (DI)
MOVB AX, -1(DI)(BX*1)
+ RET
clr_0:
RET
clr_3or4:
diff --git a/src/pkg/runtime/memclr_arm.s b/src/runtime/memclr_arm.s
index b19ea72a3..1824d33b1 100644
--- a/src/pkg/runtime/memclr_arm.s
+++ b/src/runtime/memclr_arm.s
@@ -23,7 +23,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TO = 8
TOE = 11
diff --git a/src/pkg/runtime/memclr_plan9_386.s b/src/runtime/memclr_plan9_386.s
index 9b496785a..b4b671f77 100644
--- a/src/pkg/runtime/memclr_plan9_386.s
+++ b/src/runtime/memclr_plan9_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// void runtime·memclr(void*, uintptr)
TEXT runtime·memclr(SB), NOSPLIT, $0-8
@@ -32,6 +32,7 @@ clr_tail:
clr_1or2:
MOVB AX, (DI)
MOVB AX, -1(DI)(BX*1)
+ RET
clr_0:
RET
clr_3or4:
diff --git a/src/runtime/memclr_plan9_amd64.s b/src/runtime/memclr_plan9_amd64.s
new file mode 100644
index 000000000..37e61dfbc
--- /dev/null
+++ b/src/runtime/memclr_plan9_amd64.s
@@ -0,0 +1,21 @@
+// 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"
+
+// void runtime·memclr(void*, uintptr)
+TEXT runtime·memclr(SB),NOSPLIT,$0-16
+ MOVQ ptr+0(FP), DI
+ MOVQ n+8(FP), CX
+ MOVQ CX, BX
+ ANDQ $7, BX
+ SHRQ $3, CX
+ MOVQ $0, AX
+ CLD
+ REP
+ STOSQ
+ MOVQ BX, CX
+ REP
+ STOSB
+ RET
diff --git a/src/pkg/runtime/memmove_386.s b/src/runtime/memmove_386.s
index 3aed8ad07..4c0c74c1a 100644
--- a/src/pkg/runtime/memmove_386.s
+++ b/src/runtime/memmove_386.s
@@ -25,11 +25,11 @@
// +build !plan9
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT runtime·memmove(SB), NOSPLIT, $0-12
MOVL to+0(FP), DI
- MOVL fr+4(FP), SI
+ MOVL from+4(FP), SI
MOVL n+8(FP), BX
// REP instructions have a high startup cost, so we handle small sizes
@@ -115,6 +115,7 @@ move_1or2:
MOVB -1(SI)(BX*1), CX
MOVB AX, (DI)
MOVB CX, -1(DI)(BX*1)
+ RET
move_0:
RET
move_3or4:
diff --git a/src/pkg/runtime/memmove_amd64.s b/src/runtime/memmove_amd64.s
index 5895846db..f96843534 100644
--- a/src/pkg/runtime/memmove_amd64.s
+++ b/src/runtime/memmove_amd64.s
@@ -25,21 +25,24 @@
// +build !plan9
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// void runtime·memmove(void*, void*, uintptr)
TEXT runtime·memmove(SB), NOSPLIT, $0-24
MOVQ to+0(FP), DI
- MOVQ fr+8(FP), SI
+ MOVQ from+8(FP), SI
MOVQ n+16(FP), BX
// REP instructions have a high startup cost, so we handle small sizes
// with some straightline code. The REP MOVSQ instruction is really fast
- // for large sizes. The cutover is approximately 1K. We implement up to
- // 256 because that is the maximum SSE register load (loading all data
- // into registers lets us ignore copy direction).
+ // for large sizes. The cutover is approximately 2K.
tail:
+ // move_129through256 or smaller work whether or not the source and the
+ // destination memory regions overlap because they load all data into
+ // registers before writing it back. move_256through2048 on the other
+ // hand can be used only when the memory regions don't overlap or the copy
+ // direction is forward.
TESTQ BX, BX
JEQ move_0
CMPQ BX, $2
@@ -70,10 +73,12 @@ tail:
* forward copy loop
*/
forward:
+ CMPQ BX, $2048
+ JLS move_256through2048
+
MOVQ BX, CX
SHRQ $3, CX
ANDQ $7, BX
-
REP; MOVSQ
JMP tail
@@ -117,6 +122,7 @@ move_1or2:
MOVB -1(SI)(BX*1), CX
MOVB AX, (DI)
MOVB CX, -1(DI)(BX*1)
+ RET
move_0:
RET
move_3or4:
@@ -205,3 +211,42 @@ move_129through256:
MOVOU X14, -32(DI)(BX*1)
MOVOU X15, -16(DI)(BX*1)
RET
+move_256through2048:
+ SUBQ $256, BX
+ MOVOU (SI), X0
+ MOVOU 16(SI), X1
+ MOVOU 32(SI), X2
+ MOVOU 48(SI), X3
+ MOVOU 64(SI), X4
+ MOVOU 80(SI), X5
+ MOVOU 96(SI), X6
+ MOVOU 112(SI), X7
+ MOVOU 128(SI), X8
+ MOVOU 144(SI), X9
+ MOVOU 160(SI), X10
+ MOVOU 176(SI), X11
+ MOVOU 192(SI), X12
+ MOVOU 208(SI), X13
+ MOVOU 224(SI), X14
+ MOVOU 240(SI), X15
+ MOVOU X0, (DI)
+ MOVOU X1, 16(DI)
+ MOVOU X2, 32(DI)
+ MOVOU X3, 48(DI)
+ MOVOU X4, 64(DI)
+ MOVOU X5, 80(DI)
+ MOVOU X6, 96(DI)
+ MOVOU X7, 112(DI)
+ MOVOU X8, 128(DI)
+ MOVOU X9, 144(DI)
+ MOVOU X10, 160(DI)
+ MOVOU X11, 176(DI)
+ MOVOU X12, 192(DI)
+ MOVOU X13, 208(DI)
+ MOVOU X14, 224(DI)
+ MOVOU X15, 240(DI)
+ CMPQ BX, $256
+ LEAQ 256(SI), SI
+ LEAQ 256(DI), DI
+ JGE move_256through2048
+ JMP tail
diff --git a/src/pkg/runtime/memmove_arm.s b/src/runtime/memmove_arm.s
index 9701dc99f..f187d4267 100644
--- a/src/pkg/runtime/memmove_arm.s
+++ b/src/runtime/memmove_arm.s
@@ -23,7 +23,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// TE or TS are spilled to the stack during bulk register moves.
TS = 0
diff --git a/src/pkg/runtime/memmove_linux_amd64_test.go b/src/runtime/memmove_linux_amd64_test.go
index f7221f4f5..f7221f4f5 100644
--- a/src/pkg/runtime/memmove_linux_amd64_test.go
+++ b/src/runtime/memmove_linux_amd64_test.go
diff --git a/src/pkg/runtime/memmove_nacl_amd64p32.s b/src/runtime/memmove_nacl_amd64p32.s
index 1b5733112..373607afe 100644
--- a/src/pkg/runtime/memmove_nacl_amd64p32.s
+++ b/src/runtime/memmove_nacl_amd64p32.s
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT runtime·memmove(SB), NOSPLIT, $0-12
MOVL to+0(FP), DI
- MOVL fr+4(FP), SI
+ MOVL from+4(FP), SI
MOVL n+8(FP), BX
CMPL SI, DI
diff --git a/src/pkg/runtime/memmove_plan9_386.s b/src/runtime/memmove_plan9_386.s
index 187616cd0..025d4ce1b 100644
--- a/src/pkg/runtime/memmove_plan9_386.s
+++ b/src/runtime/memmove_plan9_386.s
@@ -23,11 +23,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT runtime·memmove(SB), NOSPLIT, $0-12
MOVL to+0(FP), DI
- MOVL fr+4(FP), SI
+ MOVL from+4(FP), SI
MOVL n+8(FP), BX
// REP instructions have a high startup cost, so we handle small sizes
@@ -101,6 +101,7 @@ move_1or2:
MOVB -1(SI)(BX*1), CX
MOVB AX, (DI)
MOVB CX, -1(DI)(BX*1)
+ RET
move_0:
RET
move_3or4:
diff --git a/src/pkg/runtime/memmove_plan9_amd64.s b/src/runtime/memmove_plan9_amd64.s
index 60108273c..8e96b8717 100644
--- a/src/pkg/runtime/memmove_plan9_amd64.s
+++ b/src/runtime/memmove_plan9_amd64.s
@@ -23,13 +23,13 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// void runtime·memmove(void*, void*, uintptr)
TEXT runtime·memmove(SB), NOSPLIT, $0-24
MOVQ to+0(FP), DI
- MOVQ fr+8(FP), SI
+ MOVQ from+8(FP), SI
MOVQ n+16(FP), BX
// REP instructions have a high startup cost, so we handle small sizes
@@ -104,6 +104,7 @@ move_1or2:
MOVB -1(SI)(BX*1), CX
MOVB AX, (DI)
MOVB CX, -1(DI)(BX*1)
+ RET
move_0:
RET
move_3or4:
diff --git a/src/pkg/runtime/memmove_test.go b/src/runtime/memmove_test.go
index 540f0feb5..ffda4fe6c 100644
--- a/src/pkg/runtime/memmove_test.go
+++ b/src/runtime/memmove_test.go
@@ -162,43 +162,95 @@ 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 BenchmarkClearFat8(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ var x [8 / 4]uint32
+ _ = x
+ }
+}
+func BenchmarkClearFat12(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ var x [12 / 4]uint32
+ _ = x
+ }
+}
+func BenchmarkClearFat16(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ var x [16 / 4]uint32
+ _ = x
+ }
+}
+func BenchmarkClearFat24(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ var x [24 / 4]uint32
+ _ = x
+ }
+}
func BenchmarkClearFat32(b *testing.B) {
for i := 0; i < b.N; i++ {
- var x [32]byte
+ var x [32 / 4]uint32
_ = x
}
}
func BenchmarkClearFat64(b *testing.B) {
for i := 0; i < b.N; i++ {
- var x [64]byte
+ var x [64 / 4]uint32
_ = x
}
}
func BenchmarkClearFat128(b *testing.B) {
for i := 0; i < b.N; i++ {
- var x [128]byte
+ var x [128 / 4]uint32
_ = x
}
}
func BenchmarkClearFat256(b *testing.B) {
for i := 0; i < b.N; i++ {
- var x [256]byte
+ var x [256 / 4]uint32
_ = x
}
}
func BenchmarkClearFat512(b *testing.B) {
for i := 0; i < b.N; i++ {
- var x [512]byte
+ var x [512 / 4]uint32
_ = x
}
}
func BenchmarkClearFat1024(b *testing.B) {
for i := 0; i < b.N; i++ {
- var x [1024]byte
+ var x [1024 / 4]uint32
_ = x
}
}
+func BenchmarkCopyFat8(b *testing.B) {
+ var x [8 / 4]uint32
+ for i := 0; i < b.N; i++ {
+ y := x
+ _ = y
+ }
+}
+func BenchmarkCopyFat12(b *testing.B) {
+ var x [12 / 4]uint32
+ for i := 0; i < b.N; i++ {
+ y := x
+ _ = y
+ }
+}
+func BenchmarkCopyFat16(b *testing.B) {
+ var x [16 / 4]uint32
+ for i := 0; i < b.N; i++ {
+ y := x
+ _ = y
+ }
+}
+func BenchmarkCopyFat24(b *testing.B) {
+ var x [24 / 4]uint32
+ for i := 0; i < b.N; i++ {
+ y := x
+ _ = y
+ }
+}
func BenchmarkCopyFat32(b *testing.B) {
var x [32 / 4]uint32
for i := 0; i < b.N; i++ {
diff --git a/src/pkg/runtime/mfinal_test.go b/src/runtime/mfinal_test.go
index 6b53888ab..d2cead287 100644
--- a/src/pkg/runtime/mfinal_test.go
+++ b/src/runtime/mfinal_test.go
@@ -44,10 +44,17 @@ func TestFinalizerType(t *testing.T) {
{func(x *int) interface{} { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }},
}
- for _, tt := range finalizerTests {
+ for i, tt := range finalizerTests {
done := make(chan bool, 1)
go func() {
- v := new(int)
+ // allocate struct with pointer to avoid hitting tinyalloc.
+ // Otherwise we can't be sure when the allocation will
+ // be freed.
+ type T struct {
+ v int
+ p unsafe.Pointer
+ }
+ v := &new(T).v
*v = 97531
runtime.SetFinalizer(tt.convert(v), tt.finalizer)
v = nil
@@ -58,7 +65,7 @@ func TestFinalizerType(t *testing.T) {
select {
case <-ch:
case <-time.After(time.Second * 4):
- t.Errorf("finalizer for type %T didn't run", tt.finalizer)
+ t.Errorf("#%d: finalizer for type %T didn't run", i, tt.finalizer)
}
}
}
diff --git a/src/pkg/runtime/mfixalloc.c b/src/runtime/mfixalloc.c
index d670629da..d670629da 100644
--- a/src/pkg/runtime/mfixalloc.c
+++ b/src/runtime/mfixalloc.c
diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c
new file mode 100644
index 000000000..7754bad89
--- /dev/null
+++ b/src/runtime/mgc0.c
@@ -0,0 +1,2010 @@
+// 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.
+
+// Garbage collector (GC).
+//
+// GC is:
+// - mark&sweep
+// - mostly precise (with the exception of some C-allocated objects, assembly frames/arguments, etc)
+// - parallel (up to MaxGcproc threads)
+// - partially concurrent (mark is stop-the-world, while sweep is concurrent)
+// - non-moving/non-compacting
+// - full (non-partial)
+//
+// GC rate.
+// Next GC is after we've allocated an extra amount of memory proportional to
+// the amount already in use. The proportion is controlled by GOGC environment variable
+// (100 by default). If GOGC=100 and we're using 4M, we'll GC again when we get to 8M
+// (this mark is tracked in next_gc variable). This keeps the GC cost in linear
+// proportion to the allocation cost. Adjusting GOGC just changes the linear constant
+// (and also the amount of extra memory used).
+//
+// Concurrent sweep.
+// The sweep phase proceeds concurrently with normal program execution.
+// The heap is swept span-by-span both lazily (when a goroutine needs another span)
+// and concurrently in a background goroutine (this helps programs that are not CPU bound).
+// However, at the end of the stop-the-world GC phase we don't know the size of the live heap,
+// and so next_gc calculation is tricky and happens as follows.
+// At the end of the stop-the-world phase next_gc is conservatively set based on total
+// heap size; all spans are marked as "needs sweeping".
+// Whenever a span is swept, next_gc is decremented by GOGC*newly_freed_memory.
+// The background sweeper goroutine simply sweeps spans one-by-one bringing next_gc
+// closer to the target value. However, this is not enough to avoid over-allocating memory.
+// Consider that a goroutine wants to allocate a new span for a large object and
+// there are no free swept spans, but there are small-object unswept spans.
+// If the goroutine naively allocates a new span, it can surpass the yet-unknown
+// target next_gc value. In order to prevent such cases (1) when a goroutine needs
+// to allocate a new small-object span, it sweeps small-object spans for the same
+// object size until it frees at least one object; (2) when a goroutine needs to
+// allocate large-object span from heap, it sweeps spans until it frees at least
+// that many pages into heap. Together these two measures ensure that we don't surpass
+// target next_gc value by a large margin. There is an exception: if a goroutine sweeps
+// and frees two nonadjacent one-page spans to the heap, it will allocate a new two-page span,
+// but there can still be other one-page unswept spans which could be combined into a two-page span.
+// It's critical to ensure that no operations proceed on unswept spans (that would corrupt
+// mark bits in GC bitmap). During GC all mcaches are flushed into the central cache,
+// so they are empty. When a goroutine grabs a new span into mcache, it sweeps it.
+// When a goroutine explicitly frees an object or sets a finalizer, it ensures that
+// the span is swept (either by sweeping it, or by waiting for the concurrent sweep to finish).
+// The finalizer goroutine is kicked off only when all spans are swept.
+// When the next GC starts, it sweeps all not-yet-swept spans (if any).
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
+#include "stack.h"
+#include "mgc0.h"
+#include "chan.h"
+#include "race.h"
+#include "type.h"
+#include "typekind.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+enum {
+ Debug = 0,
+ DebugPtrs = 0, // if 1, print trace of every pointer load during GC
+ ConcurrentSweep = 1,
+
+ WorkbufSize = 4*1024,
+ FinBlockSize = 4*1024,
+ RootData = 0,
+ RootBss = 1,
+ RootFinalizers = 2,
+ RootSpans = 3,
+ RootFlushCaches = 4,
+ RootCount = 5,
+};
+
+// ptrmask for an allocation containing a single pointer.
+static byte oneptr[] = {BitsPointer};
+
+// Initialized from $GOGC. GOGC=off means no gc.
+extern int32 runtime·gcpercent;
+
+// Holding worldsema grants an M the right to try to stop the world.
+// The procedure is:
+//
+// runtime·semacquire(&runtime·worldsema);
+// m->gcing = 1;
+// runtime·stoptheworld();
+//
+// ... do stuff ...
+//
+// m->gcing = 0;
+// runtime·semrelease(&runtime·worldsema);
+// runtime·starttheworld();
+//
+uint32 runtime·worldsema = 1;
+
+typedef struct Workbuf Workbuf;
+struct Workbuf
+{
+ LFNode node; // must be first
+ uintptr nobj;
+ byte* obj[(WorkbufSize-sizeof(LFNode)-sizeof(uintptr))/PtrSize];
+};
+
+extern byte runtime·data[];
+extern byte runtime·edata[];
+extern byte runtime·bss[];
+extern byte runtime·ebss[];
+
+extern byte runtime·gcdata[];
+extern byte runtime·gcbss[];
+
+Mutex runtime·finlock; // protects the following variables
+G* runtime·fing; // goroutine that runs finalizers
+FinBlock* runtime·finq; // list of finalizers that are to be executed
+FinBlock* runtime·finc; // cache of free blocks
+static byte finptrmask[FinBlockSize/PtrSize/PointersPerByte];
+bool runtime·fingwait;
+bool runtime·fingwake;
+FinBlock *runtime·allfin; // list of all blocks
+
+BitVector runtime·gcdatamask;
+BitVector runtime·gcbssmask;
+
+Mutex runtime·gclock;
+
+static uintptr badblock[1024];
+static int32 nbadblock;
+
+static Workbuf* getempty(Workbuf*);
+static Workbuf* getfull(Workbuf*);
+static void putempty(Workbuf*);
+static Workbuf* handoff(Workbuf*);
+static void gchelperstart(void);
+static void flushallmcaches(void);
+static bool scanframe(Stkframe *frame, void *unused);
+static void scanstack(G *gp);
+static BitVector unrollglobgcprog(byte *prog, uintptr size);
+
+void runtime·bgsweep(void);
+static FuncVal bgsweepv = {runtime·bgsweep};
+
+typedef struct WorkData WorkData;
+struct WorkData {
+ uint64 full; // lock-free list of full blocks
+ uint64 empty; // lock-free list of empty blocks
+ byte pad0[CacheLineSize]; // prevents false-sharing between full/empty and nproc/nwait
+ uint32 nproc;
+ int64 tstart;
+ volatile uint32 nwait;
+ volatile uint32 ndone;
+ Note alldone;
+ ParFor* markfor;
+
+ // Copy of mheap.allspans for marker or sweeper.
+ MSpan** spans;
+ uint32 nspan;
+};
+WorkData runtime·work;
+
+// Is _cgo_allocate linked into the binary?
+static bool
+have_cgo_allocate(void)
+{
+ extern byte go·weak·runtime·_cgo_allocate_internal[1];
+ return go·weak·runtime·_cgo_allocate_internal != nil;
+}
+
+// scanblock scans a block of n bytes starting at pointer b for references
+// to other objects, scanning any it finds recursively until there are no
+// unscanned objects left. Instead of using an explicit recursion, it keeps
+// a work list in the Workbuf* structures and loops in the main function
+// body. Keeping an explicit work list is easier on the stack allocator and
+// more efficient.
+static void
+scanblock(byte *b, uintptr n, byte *ptrmask)
+{
+ byte *obj, *obj0, *p, *arena_start, *arena_used, **wp, *scanbuf[8], *ptrbitp, *bitp;
+ uintptr i, j, nobj, size, idx, x, off, scanbufpos, bits, xbits, shift;
+ Workbuf *wbuf;
+ Iface *iface;
+ Eface *eface;
+ Type *typ;
+ MSpan *s;
+ pageID k;
+ bool keepworking;
+
+ // Cache memory arena parameters in local vars.
+ arena_start = runtime·mheap.arena_start;
+ arena_used = runtime·mheap.arena_used;
+
+ wbuf = getempty(nil);
+ nobj = wbuf->nobj;
+ wp = &wbuf->obj[nobj];
+ keepworking = b == nil;
+ scanbufpos = 0;
+ for(i = 0; i < nelem(scanbuf); i++)
+ scanbuf[i] = nil;
+
+ ptrbitp = nil;
+
+ // ptrmask can have 2 possible values:
+ // 1. nil - obtain pointer mask from GC bitmap.
+ // 2. pointer to a compact mask (for stacks and data).
+ if(b != nil)
+ goto scanobj;
+ for(;;) {
+ if(nobj == 0) {
+ // Out of work in workbuf.
+ // First, see is there is any work in scanbuf.
+ for(i = 0; i < nelem(scanbuf); i++) {
+ b = scanbuf[scanbufpos];
+ scanbuf[scanbufpos++] = nil;
+ scanbufpos %= nelem(scanbuf);
+ if(b != nil) {
+ n = arena_used - b; // scan until bitBoundary or BitsDead
+ ptrmask = nil; // use GC bitmap for pointer info
+ goto scanobj;
+ }
+ }
+ if(!keepworking) {
+ putempty(wbuf);
+ return;
+ }
+ // Refill workbuf from global queue.
+ wbuf = getfull(wbuf);
+ if(wbuf == nil)
+ return;
+ nobj = wbuf->nobj;
+ wp = &wbuf->obj[nobj];
+ }
+
+ // If another proc wants a pointer, give it some.
+ if(runtime·work.nwait > 0 && nobj > 4 && runtime·work.full == 0) {
+ wbuf->nobj = nobj;
+ wbuf = handoff(wbuf);
+ nobj = wbuf->nobj;
+ wp = &wbuf->obj[nobj];
+ }
+
+ wp--;
+ nobj--;
+ b = *wp;
+ n = arena_used - b; // scan until next bitBoundary or BitsDead
+ ptrmask = nil; // use GC bitmap for pointer info
+
+ scanobj:
+ if(DebugPtrs)
+ runtime·printf("scanblock %p +%p %p\n", b, n, ptrmask);
+ // Find bits of the beginning of the object.
+ if(ptrmask == nil) {
+ off = (uintptr*)b - (uintptr*)arena_start;
+ ptrbitp = arena_start - off/wordsPerBitmapByte - 1;
+ }
+ for(i = 0; i < n; i += PtrSize) {
+ obj = nil;
+ // Find bits for this word.
+ if(ptrmask == nil) {
+ // Check is we have reached end of span.
+ if((((uintptr)b+i)%PageSize) == 0 &&
+ runtime·mheap.spans[(b-arena_start)>>PageShift] != runtime·mheap.spans[(b+i-arena_start)>>PageShift])
+ break;
+ // Consult GC bitmap.
+ bits = *ptrbitp;
+
+ if(wordsPerBitmapByte != 2)
+ runtime·throw("alg doesn't work for wordsPerBitmapByte != 2");
+ j = ((uintptr)b+i)/PtrSize & 1;
+ ptrbitp -= j;
+ bits >>= gcBits*j;
+
+ if((bits&bitBoundary) != 0 && i != 0)
+ break; // reached beginning of the next object
+ bits = (bits>>2)&BitsMask;
+ if(bits == BitsDead)
+ break; // reached no-scan part of the object
+ } else // dense mask (stack or data)
+ bits = (ptrmask[(i/PtrSize)/4]>>(((i/PtrSize)%4)*BitsPerPointer))&BitsMask;
+
+ if(bits <= BitsScalar) // BitsScalar || BitsDead
+ continue;
+ if(bits == BitsPointer) {
+ obj = *(byte**)(b+i);
+ obj0 = obj;
+ goto markobj;
+ }
+
+ // With those three out of the way, must be multi-word.
+ if(Debug && bits != BitsMultiWord)
+ runtime·throw("unexpected garbage collection bits");
+ // Find the next pair of bits.
+ if(ptrmask == nil) {
+ bits = *ptrbitp;
+ j = ((uintptr)b+i+PtrSize)/PtrSize & 1;
+ ptrbitp -= j;
+ bits >>= gcBits*j;
+ bits = (bits>>2)&BitsMask;
+ } else
+ bits = (ptrmask[((i+PtrSize)/PtrSize)/4]>>((((i+PtrSize)/PtrSize)%4)*BitsPerPointer))&BitsMask;
+
+ if(Debug && bits != BitsIface && bits != BitsEface)
+ runtime·throw("unexpected garbage collection bits");
+
+ if(bits == BitsIface) {
+ iface = (Iface*)(b+i);
+ if(iface->tab != nil) {
+ typ = iface->tab->type;
+ if(!(typ->kind&KindDirectIface) || !(typ->kind&KindNoPointers))
+ obj = iface->data;
+ }
+ } else {
+ eface = (Eface*)(b+i);
+ typ = eface->type;
+ if(typ != nil) {
+ if(!(typ->kind&KindDirectIface) || !(typ->kind&KindNoPointers))
+ obj = eface->data;
+ }
+ }
+
+ i += PtrSize;
+
+ obj0 = obj;
+ markobj:
+ // At this point we have extracted the next potential pointer.
+ // Check if it points into heap.
+ if(obj == nil)
+ continue;
+ if(obj < arena_start || obj >= arena_used) {
+ if((uintptr)obj < PhysPageSize && runtime·invalidptr) {
+ s = nil;
+ goto badobj;
+ }
+ continue;
+ }
+ // Mark the object.
+ obj = (byte*)((uintptr)obj & ~(PtrSize-1));
+ off = (uintptr*)obj - (uintptr*)arena_start;
+ bitp = arena_start - off/wordsPerBitmapByte - 1;
+ shift = (off % wordsPerBitmapByte) * gcBits;
+ xbits = *bitp;
+ bits = (xbits >> shift) & bitMask;
+ if((bits&bitBoundary) == 0) {
+ // Not a beginning of a block, consult span table to find the block beginning.
+ k = (uintptr)obj>>PageShift;
+ x = k;
+ x -= (uintptr)arena_start>>PageShift;
+ s = runtime·mheap.spans[x];
+ if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse) {
+ // Stack pointers lie within the arena bounds but are not part of the GC heap.
+ // Ignore them.
+ if(s != nil && s->state == MSpanStack)
+ continue;
+
+ badobj:
+ // If cgo_allocate is linked into the binary, it can allocate
+ // memory as []unsafe.Pointer that may not contain actual
+ // pointers and must be scanned conservatively.
+ // In this case alone, allow the bad pointer.
+ if(have_cgo_allocate() && ptrmask == nil)
+ continue;
+
+ // Anything else indicates a bug somewhere.
+ // If we're in the middle of chasing down a different bad pointer,
+ // don't confuse the trace by printing about this one.
+ if(nbadblock > 0)
+ continue;
+
+ runtime·printf("runtime: garbage collector found invalid heap pointer *(%p+%p)=%p", b, i, obj);
+ if(s == nil)
+ runtime·printf(" s=nil\n");
+ else
+ runtime·printf(" span=%p-%p-%p state=%d\n", (uintptr)s->start<<PageShift, s->limit, (uintptr)(s->start+s->npages)<<PageShift, s->state);
+ if(ptrmask != nil)
+ runtime·throw("invalid heap pointer");
+ // Add to badblock list, which will cause the garbage collection
+ // to keep repeating until it has traced the chain of pointers
+ // leading to obj all the way back to a root.
+ if(nbadblock == 0)
+ badblock[nbadblock++] = (uintptr)b;
+ continue;
+ }
+ p = (byte*)((uintptr)s->start<<PageShift);
+ if(s->sizeclass != 0) {
+ size = s->elemsize;
+ idx = ((byte*)obj - p)/size;
+ p = p+idx*size;
+ }
+ if(p == obj) {
+ runtime·printf("runtime: failed to find block beginning for %p s=%p s->limit=%p\n",
+ p, s->start*PageSize, s->limit);
+ runtime·throw("failed to find block beginning");
+ }
+ obj = p;
+ goto markobj;
+ }
+ if(DebugPtrs)
+ runtime·printf("scan *%p = %p => base %p\n", b+i, obj0, obj);
+
+ if(nbadblock > 0 && (uintptr)obj == badblock[nbadblock-1]) {
+ // Running garbage collection again because
+ // we want to find the path from a root to a bad pointer.
+ // Found possible next step; extend or finish path.
+ for(j=0; j<nbadblock; j++)
+ if(badblock[j] == (uintptr)b)
+ goto AlreadyBad;
+ runtime·printf("runtime: found *(%p+%p) = %p+%p\n", b, i, obj0, (uintptr)(obj-obj0));
+ if(ptrmask != nil)
+ runtime·throw("bad pointer");
+ if(nbadblock >= nelem(badblock))
+ runtime·throw("badblock trace too long");
+ badblock[nbadblock++] = (uintptr)b;
+ AlreadyBad:;
+ }
+
+ // Now we have bits, bitp, and shift correct for
+ // obj pointing at the base of the object.
+ // Only care about not marked objects.
+ if((bits&bitMarked) != 0)
+ continue;
+ // If obj size is greater than 8, then each byte of GC bitmap
+ // contains info for at most one object. In such case we use
+ // non-atomic byte store to mark the object. This can lead
+ // to double enqueue of the object for scanning, but scanning
+ // is an idempotent operation, so it is OK. This cannot lead
+ // to bitmap corruption because the single marked bit is the
+ // only thing that can change in the byte.
+ // For 8-byte objects we use non-atomic store, if the other
+ // quadruple is already marked. Otherwise we resort to CAS
+ // loop for marking.
+ if((xbits&(bitMask|(bitMask<<gcBits))) != (bitBoundary|(bitBoundary<<gcBits)) ||
+ runtime·work.nproc == 1)
+ *bitp = xbits | (bitMarked<<shift);
+ else
+ runtime·atomicor8(bitp, bitMarked<<shift);
+
+ if(((xbits>>(shift+2))&BitsMask) == BitsDead)
+ continue; // noscan object
+
+ // Queue the obj for scanning.
+ PREFETCH(obj);
+ p = scanbuf[scanbufpos];
+ scanbuf[scanbufpos++] = obj;
+ scanbufpos %= nelem(scanbuf);
+ if(p == nil)
+ continue;
+
+ // If workbuf is full, obtain an empty one.
+ if(nobj >= nelem(wbuf->obj)) {
+ wbuf->nobj = nobj;
+ wbuf = getempty(wbuf);
+ nobj = wbuf->nobj;
+ wp = &wbuf->obj[nobj];
+ }
+ *wp = p;
+ wp++;
+ nobj++;
+ }
+ if(DebugPtrs)
+ runtime·printf("end scanblock %p +%p %p\n", b, n, ptrmask);
+
+ if(Debug && ptrmask == nil) {
+ // For heap objects ensure that we did not overscan.
+ n = 0;
+ p = nil;
+ if(!runtime·mlookup(b, &p, &n, nil) || b != p || i > n) {
+ runtime·printf("runtime: scanned (%p,%p), heap object (%p,%p)\n", b, i, p, n);
+ runtime·throw("scanblock: scanned invalid object");
+ }
+ }
+ }
+}
+
+static void
+markroot(ParFor *desc, uint32 i)
+{
+ FinBlock *fb;
+ MSpan *s;
+ uint32 spanidx, sg;
+ G *gp;
+ void *p;
+ uint32 status;
+ bool restart;
+
+ USED(&desc);
+ // Note: if you add a case here, please also update heapdump.c:dumproots.
+ switch(i) {
+ case RootData:
+ scanblock(runtime·data, runtime·edata - runtime·data, runtime·gcdatamask.bytedata);
+ break;
+
+ case RootBss:
+ scanblock(runtime·bss, runtime·ebss - runtime·bss, runtime·gcbssmask.bytedata);
+ break;
+
+ case RootFinalizers:
+ for(fb=runtime·allfin; fb; fb=fb->alllink)
+ scanblock((byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]), finptrmask);
+ break;
+
+ case RootSpans:
+ // mark MSpan.specials
+ sg = runtime·mheap.sweepgen;
+ for(spanidx=0; spanidx<runtime·work.nspan; spanidx++) {
+ Special *sp;
+ SpecialFinalizer *spf;
+
+ s = runtime·work.spans[spanidx];
+ if(s->state != MSpanInUse)
+ continue;
+ if(s->sweepgen != sg) {
+ runtime·printf("sweep %d %d\n", s->sweepgen, sg);
+ runtime·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*)sp;
+ // A finalizer can be set for an inner byte of an object, find object beginning.
+ p = (void*)((s->start << PageShift) + spf->special.offset/s->elemsize*s->elemsize);
+ scanblock(p, s->elemsize, nil);
+ scanblock((void*)&spf->fn, PtrSize, oneptr);
+ }
+ }
+ break;
+
+ case RootFlushCaches:
+ flushallmcaches();
+ break;
+
+ default:
+ // the rest is scanning goroutine stacks
+ if(i - RootCount >= runtime·allglen)
+ runtime·throw("markroot: bad index");
+ gp = runtime·allg[i - RootCount];
+ // remember when we've first observed the G blocked
+ // needed only to output in traceback
+ status = runtime·readgstatus(gp);
+ if((status == Gwaiting || status == Gsyscall) && gp->waitsince == 0)
+ gp->waitsince = runtime·work.tstart;
+ // Shrink a stack if not much of it is being used.
+ runtime·shrinkstack(gp);
+ if(runtime·readgstatus(gp) == Gdead)
+ gp->gcworkdone = true;
+ else
+ gp->gcworkdone = false;
+ restart = runtime·stopg(gp);
+ scanstack(gp);
+ if(restart)
+ runtime·restartg(gp);
+ break;
+ }
+}
+
+// Get an empty work buffer off the work.empty list,
+// allocating new buffers as needed.
+static Workbuf*
+getempty(Workbuf *b)
+{
+ MCache *c;
+
+ if(b != nil)
+ runtime·lfstackpush(&runtime·work.full, &b->node);
+ b = nil;
+ c = g->m->mcache;
+ if(c->gcworkbuf != nil) {
+ b = c->gcworkbuf;
+ c->gcworkbuf = nil;
+ }
+ if(b == nil)
+ b = (Workbuf*)runtime·lfstackpop(&runtime·work.empty);
+ if(b == nil)
+ b = runtime·persistentalloc(sizeof(*b), CacheLineSize, &mstats.gc_sys);
+ b->nobj = 0;
+ return b;
+}
+
+static void
+putempty(Workbuf *b)
+{
+ MCache *c;
+
+ c = g->m->mcache;
+ if(c->gcworkbuf == nil) {
+ c->gcworkbuf = b;
+ return;
+ }
+ runtime·lfstackpush(&runtime·work.empty, &b->node);
+}
+
+void
+runtime·gcworkbuffree(void *b)
+{
+ if(b != nil)
+ putempty(b);
+}
+
+// Get a full work buffer off the work.full list, or return nil.
+static Workbuf*
+getfull(Workbuf *b)
+{
+ int32 i;
+
+ if(b != nil)
+ runtime·lfstackpush(&runtime·work.empty, &b->node);
+ b = (Workbuf*)runtime·lfstackpop(&runtime·work.full);
+ if(b != nil || runtime·work.nproc == 1)
+ return b;
+
+ runtime·xadd(&runtime·work.nwait, +1);
+ for(i=0;; i++) {
+ if(runtime·work.full != 0) {
+ runtime·xadd(&runtime·work.nwait, -1);
+ b = (Workbuf*)runtime·lfstackpop(&runtime·work.full);
+ if(b != nil)
+ return b;
+ runtime·xadd(&runtime·work.nwait, +1);
+ }
+ if(runtime·work.nwait == runtime·work.nproc)
+ return nil;
+ if(i < 10) {
+ g->m->gcstats.nprocyield++;
+ runtime·procyield(20);
+ } else if(i < 20) {
+ g->m->gcstats.nosyield++;
+ runtime·osyield();
+ } else {
+ g->m->gcstats.nsleep++;
+ runtime·usleep(100);
+ }
+ }
+}
+
+static Workbuf*
+handoff(Workbuf *b)
+{
+ int32 n;
+ Workbuf *b1;
+
+ // Make new buffer with half of b's pointers.
+ b1 = getempty(nil);
+ n = b->nobj/2;
+ b->nobj -= n;
+ b1->nobj = n;
+ runtime·memmove(b1->obj, b->obj+b->nobj, n*sizeof b1->obj[0]);
+ g->m->gcstats.nhandoff++;
+ g->m->gcstats.nhandoffcnt += n;
+
+ // Put b on full list - let first half of b get stolen.
+ runtime·lfstackpush(&runtime·work.full, &b->node);
+ return b1;
+}
+
+BitVector
+runtime·stackmapdata(StackMap *stackmap, int32 n)
+{
+ if(n < 0 || n >= stackmap->n)
+ runtime·throw("stackmapdata: index out of range");
+ return (BitVector){stackmap->nbit, stackmap->bytedata + n*((stackmap->nbit+31)/32*4)};
+}
+
+// Scan a stack frame: local variables and function arguments/results.
+static bool
+scanframe(Stkframe *frame, void *unused)
+{
+ Func *f;
+ StackMap *stackmap;
+ BitVector bv;
+ uintptr size, minsize;
+ uintptr targetpc;
+ int32 pcdata;
+
+ USED(unused);
+ f = frame->fn;
+ targetpc = frame->continpc;
+ if(targetpc == 0) {
+ // Frame is dead.
+ return true;
+ }
+ if(Debug > 1)
+ runtime·printf("scanframe %s\n", runtime·funcname(f));
+ if(targetpc != f->entry)
+ targetpc--;
+ pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, targetpc);
+ 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
+ // at the function prologue, assume so and hope for the best.
+ pcdata = 0;
+ }
+
+ // Scan local variables if stack frame has been allocated.
+ size = frame->varp - frame->sp;
+ if(thechar != '6' && thechar != '8')
+ minsize = sizeof(uintptr);
+ else
+ minsize = 0;
+ if(size > minsize) {
+ stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
+ if(stackmap == nil || stackmap->n <= 0) {
+ runtime·printf("runtime: frame %s untyped locals %p+%p\n", runtime·funcname(f), (byte*)(frame->varp-size), size);
+ runtime·throw("missing stackmap");
+ }
+
+ // Locals bitmap information, scan just the pointers in locals.
+ if(pcdata < 0 || pcdata >= stackmap->n) {
+ // don't know where we are
+ runtime·printf("runtime: pcdata is %d and %d locals stack map entries for %s (targetpc=%p)\n",
+ pcdata, stackmap->n, runtime·funcname(f), targetpc);
+ runtime·throw("scanframe: bad symbol table");
+ }
+ bv = runtime·stackmapdata(stackmap, pcdata);
+ size = (bv.n * PtrSize) / BitsPerPointer;
+ scanblock((byte*)(frame->varp - size), bv.n/BitsPerPointer*PtrSize, bv.bytedata);
+ }
+
+ // Scan arguments.
+ if(frame->arglen > 0) {
+ if(frame->argmap != nil)
+ bv = *frame->argmap;
+ else {
+ stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
+ if(stackmap == nil || stackmap->n <= 0) {
+ runtime·printf("runtime: frame %s untyped args %p+%p\n", runtime·funcname(f), frame->argp, (uintptr)frame->arglen);
+ runtime·throw("missing stackmap");
+ }
+ if(pcdata < 0 || pcdata >= stackmap->n) {
+ // don't know where we are
+ runtime·printf("runtime: pcdata is %d and %d args stack map entries for %s (targetpc=%p)\n",
+ pcdata, stackmap->n, runtime·funcname(f), targetpc);
+ runtime·throw("scanframe: bad symbol table");
+ }
+ bv = runtime·stackmapdata(stackmap, pcdata);
+ }
+ scanblock((byte*)frame->argp, bv.n/BitsPerPointer*PtrSize, bv.bytedata);
+ }
+ return true;
+}
+
+static void
+scanstack(G *gp)
+{
+ M *mp;
+ bool (*fn)(Stkframe*, void*);
+
+ if(runtime·readgstatus(gp)&Gscan == 0) {
+ runtime·printf("runtime: gp=%p, goid=%D, gp->atomicstatus=%d\n", gp, gp->goid, runtime·readgstatus(gp));
+ runtime·throw("mark - bad status");
+ }
+
+ switch(runtime·readgstatus(gp)&~Gscan) {
+ default:
+ runtime·printf("runtime: gp=%p, goid=%D, gp->atomicstatus=%d\n", gp, gp->goid, runtime·readgstatus(gp));
+ runtime·throw("mark - bad status");
+ case Gdead:
+ return;
+ case Grunning:
+ runtime·printf("runtime: gp=%p, goid=%D, gp->atomicstatus=%d\n", gp, gp->goid, runtime·readgstatus(gp));
+ runtime·throw("mark - world not stopped");
+ case Grunnable:
+ case Gsyscall:
+ case Gwaiting:
+ break;
+ }
+
+ if(gp == g)
+ runtime·throw("can't scan our own stack");
+ if((mp = gp->m) != nil && mp->helpgc)
+ runtime·throw("can't scan gchelper stack");
+
+ fn = scanframe;
+ runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff, &fn, nil, 0);
+ runtime·tracebackdefers(gp, &fn, nil);
+}
+
+// The gp has been moved to a gc safepoint. If there is gcphase specific
+// work it is done here.
+void
+runtime·gcphasework(G *gp)
+{
+ switch(runtime·gcphase) {
+ default:
+ runtime·throw("gcphasework in bad gcphase");
+ case GCoff:
+ case GCquiesce:
+ case GCstw:
+ case GCsweep:
+ // No work for now.
+ break;
+ case GCmark:
+ // Disabled until concurrent GC is implemented
+ // but indicate the scan has been done.
+ // scanstack(gp);
+ break;
+ }
+ gp->gcworkdone = true;
+}
+
+#pragma dataflag NOPTR
+static byte finalizer1[] = {
+ // Each Finalizer is 5 words, ptr ptr uintptr ptr ptr.
+ // Each byte describes 4 words.
+ // Need 4 Finalizers described by 5 bytes before pattern repeats:
+ // ptr ptr uintptr ptr ptr
+ // ptr ptr uintptr ptr ptr
+ // ptr ptr uintptr ptr ptr
+ // ptr ptr uintptr ptr ptr
+ // aka
+ // ptr ptr uintptr ptr
+ // ptr ptr ptr uintptr
+ // ptr ptr ptr ptr
+ // uintptr ptr ptr ptr
+ // ptr uintptr ptr ptr
+ // Assumptions about Finalizer layout checked below.
+ BitsPointer | BitsPointer<<2 | BitsScalar<<4 | BitsPointer<<6,
+ BitsPointer | BitsPointer<<2 | BitsPointer<<4 | BitsScalar<<6,
+ BitsPointer | BitsPointer<<2 | BitsPointer<<4 | BitsPointer<<6,
+ BitsScalar | BitsPointer<<2 | BitsPointer<<4 | BitsPointer<<6,
+ BitsPointer | BitsScalar<<2 | BitsPointer<<4 | BitsPointer<<6,
+};
+
+void
+runtime·queuefinalizer(byte *p, FuncVal *fn, uintptr nret, Type *fint, PtrType *ot)
+{
+ FinBlock *block;
+ Finalizer *f;
+ int32 i;
+
+ runtime·lock(&runtime·finlock);
+ if(runtime·finq == nil || runtime·finq->cnt == runtime·finq->cap) {
+ if(runtime·finc == nil) {
+ runtime·finc = runtime·persistentalloc(FinBlockSize, 0, &mstats.gc_sys);
+ runtime·finc->cap = (FinBlockSize - sizeof(FinBlock)) / sizeof(Finalizer) + 1;
+ runtime·finc->alllink = runtime·allfin;
+ runtime·allfin = runtime·finc;
+ if(finptrmask[0] == 0) {
+ // Build pointer mask for Finalizer array in block.
+ // Check assumptions made in finalizer1 array above.
+ if(sizeof(Finalizer) != 5*PtrSize ||
+ offsetof(Finalizer, fn) != 0 ||
+ offsetof(Finalizer, arg) != PtrSize ||
+ offsetof(Finalizer, nret) != 2*PtrSize ||
+ offsetof(Finalizer, fint) != 3*PtrSize ||
+ offsetof(Finalizer, ot) != 4*PtrSize ||
+ BitsPerPointer != 2) {
+ runtime·throw("finalizer out of sync");
+ }
+ for(i=0; i<nelem(finptrmask); i++)
+ finptrmask[i] = finalizer1[i%nelem(finalizer1)];
+ }
+ }
+ block = runtime·finc;
+ runtime·finc = block->next;
+ block->next = runtime·finq;
+ runtime·finq = block;
+ }
+ f = &runtime·finq->fin[runtime·finq->cnt];
+ runtime·finq->cnt++;
+ f->fn = fn;
+ f->nret = nret;
+ f->fint = fint;
+ f->ot = ot;
+ f->arg = p;
+ runtime·fingwake = true;
+ runtime·unlock(&runtime·finlock);
+}
+
+void
+runtime·iterate_finq(void (*callback)(FuncVal*, byte*, uintptr, Type*, PtrType*))
+{
+ FinBlock *fb;
+ Finalizer *f;
+ uintptr i;
+
+ for(fb = runtime·allfin; fb; fb = fb->alllink) {
+ for(i = 0; i < fb->cnt; i++) {
+ f = &fb->fin[i];
+ callback(f->fn, f->arg, f->nret, f->fint, f->ot);
+ }
+ }
+}
+
+void
+runtime·MSpan_EnsureSwept(MSpan *s)
+{
+ uint32 sg;
+
+ // Caller must disable preemption.
+ // Otherwise when this function returns the span can become unswept again
+ // (if GC is triggered on another goroutine).
+ if(g->m->locks == 0 && g->m->mallocing == 0 && g != g->m->g0)
+ runtime·throw("MSpan_EnsureSwept: m is not locked");
+
+ sg = runtime·mheap.sweepgen;
+ if(runtime·atomicload(&s->sweepgen) == sg)
+ return;
+ if(runtime·cas(&s->sweepgen, sg-2, sg-1)) {
+ runtime·MSpan_Sweep(s, false);
+ return;
+ }
+ // unfortunate condition, and we don't have efficient means to wait
+ while(runtime·atomicload(&s->sweepgen) != sg)
+ runtime·osyield();
+}
+
+// Sweep frees or collects finalizers for blocks not marked in the mark phase.
+// It clears the mark bits in preparation for the next GC round.
+// Returns true if the span was returned to heap.
+// If preserve=true, don't return it to heap nor relink in MCentral lists;
+// caller takes care of it.
+bool
+runtime·MSpan_Sweep(MSpan *s, bool preserve)
+{
+ int32 cl, n, npages, nfree;
+ uintptr size, off, step;
+ uint32 sweepgen;
+ byte *p, *bitp, shift, xbits, bits;
+ MCache *c;
+ byte *arena_start;
+ MLink head, *end, *link;
+ Special *special, **specialp, *y;
+ bool res, sweepgenset;
+
+ // It's critical that we enter this function with preemption disabled,
+ // GC must not start while we are in the middle of this function.
+ if(g->m->locks == 0 && g->m->mallocing == 0 && g != g->m->g0)
+ runtime·throw("MSpan_Sweep: m is not locked");
+ sweepgen = runtime·mheap.sweepgen;
+ if(s->state != MSpanInUse || s->sweepgen != sweepgen-1) {
+ runtime·printf("MSpan_Sweep: state=%d sweepgen=%d mheap.sweepgen=%d\n",
+ s->state, s->sweepgen, sweepgen);
+ runtime·throw("MSpan_Sweep: bad span state");
+ }
+ arena_start = runtime·mheap.arena_start;
+ cl = s->sizeclass;
+ size = s->elemsize;
+ if(cl == 0) {
+ n = 1;
+ } else {
+ // Chunk full of small blocks.
+ npages = runtime·class_to_allocnpages[cl];
+ n = (npages << PageShift) / size;
+ }
+ res = false;
+ nfree = 0;
+ end = &head;
+ c = g->m->mcache;
+ sweepgenset = false;
+
+ // Mark any free objects in this span so we don't collect them.
+ for(link = s->freelist; link != nil; link = link->next) {
+ off = (uintptr*)link - (uintptr*)arena_start;
+ bitp = arena_start - off/wordsPerBitmapByte - 1;
+ shift = (off % wordsPerBitmapByte) * gcBits;
+ *bitp |= bitMarked<<shift;
+ }
+
+ // Unlink & free special records for any objects we're about to free.
+ specialp = &s->specials;
+ special = *specialp;
+ while(special != nil) {
+ // A finalizer can be set for an inner byte of an object, find object beginning.
+ p = (byte*)(s->start << PageShift) + special->offset/size*size;
+ off = (uintptr*)p - (uintptr*)arena_start;
+ bitp = arena_start - off/wordsPerBitmapByte - 1;
+ shift = (off % wordsPerBitmapByte) * gcBits;
+ bits = (*bitp>>shift) & bitMask;
+ if((bits&bitMarked) == 0) {
+ // Find the exact byte for which the special was setup
+ // (as opposed to object beginning).
+ p = (byte*)(s->start << PageShift) + special->offset;
+ // about to free object: splice out special record
+ y = special;
+ special = special->next;
+ *specialp = special;
+ if(!runtime·freespecial(y, p, size, false)) {
+ // stop freeing of object if it has a finalizer
+ *bitp |= bitMarked << shift;
+ }
+ } else {
+ // object is still live: keep special record
+ specialp = &special->next;
+ special = *specialp;
+ }
+ }
+
+ // Sweep through n objects of given size starting at p.
+ // This thread owns the span now, so it can manipulate
+ // the block bitmap without atomic operations.
+ p = (byte*)(s->start << PageShift);
+ // Find bits for the beginning of the span.
+ off = (uintptr*)p - (uintptr*)arena_start;
+ bitp = arena_start - off/wordsPerBitmapByte - 1;
+ shift = 0;
+ step = size/(PtrSize*wordsPerBitmapByte);
+ // Rewind to the previous quadruple as we move to the next
+ // in the beginning of the loop.
+ bitp += step;
+ if(step == 0) {
+ // 8-byte objects.
+ bitp++;
+ shift = gcBits;
+ }
+ for(; n > 0; n--, p += size) {
+ bitp -= step;
+ if(step == 0) {
+ if(shift != 0)
+ bitp--;
+ shift = gcBits - shift;
+ }
+
+ xbits = *bitp;
+ bits = (xbits>>shift) & bitMask;
+
+ // Allocated and marked object, reset bits to allocated.
+ if((bits&bitMarked) != 0) {
+ *bitp &= ~(bitMarked<<shift);
+ continue;
+ }
+ // At this point we know that we are looking at garbage object
+ // that needs to be collected.
+ if(runtime·debug.allocfreetrace)
+ runtime·tracefree(p, size);
+ // Reset to allocated+noscan.
+ *bitp = (xbits & ~((bitMarked|(BitsMask<<2))<<shift)) | ((uintptr)BitsDead<<(shift+2));
+ if(cl == 0) {
+ // Free large span.
+ if(preserve)
+ runtime·throw("can't preserve large span");
+ runtime·unmarkspan(p, s->npages<<PageShift);
+ s->needzero = 1;
+ // important to set sweepgen before returning it to heap
+ runtime·atomicstore(&s->sweepgen, sweepgen);
+ sweepgenset = true;
+ // NOTE(rsc,dvyukov): The original implementation of efence
+ // in CL 22060046 used SysFree instead of SysFault, so that
+ // the operating system would eventually give the memory
+ // back to us again, so that an efence program could run
+ // longer without running out of memory. Unfortunately,
+ // calling SysFree here without any kind of adjustment of the
+ // heap data structures means that when the memory does
+ // come back to us, we have the wrong metadata for it, either in
+ // the MSpan structures or in the garbage collection bitmap.
+ // Using SysFault here means that the program will run out of
+ // memory fairly quickly in efence mode, but at least it won't
+ // have mysterious crashes due to confused memory reuse.
+ // It should be possible to switch back to SysFree if we also
+ // implement and then call some kind of MHeap_DeleteSpan.
+ if(runtime·debug.efence) {
+ s->limit = nil; // prevent mlookup from finding this span
+ runtime·SysFault(p, size);
+ } else
+ runtime·MHeap_Free(&runtime·mheap, s, 1);
+ c->local_nlargefree++;
+ c->local_largefree += size;
+ runtime·xadd64(&mstats.next_gc, -(uint64)(size * (runtime·gcpercent + 100)/100));
+ res = true;
+ } else {
+ // Free small object.
+ if(size > 2*sizeof(uintptr))
+ ((uintptr*)p)[1] = (uintptr)0xdeaddeaddeaddeadll; // mark as "needs to be zeroed"
+ else if(size > sizeof(uintptr))
+ ((uintptr*)p)[1] = 0;
+
+ end->next = (MLink*)p;
+ end = (MLink*)p;
+ nfree++;
+ }
+ }
+
+ // We need to set s->sweepgen = h->sweepgen only when all blocks are swept,
+ // because of the potential for a concurrent free/SetFinalizer.
+ // 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.
+
+ if(!sweepgenset && 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) {
+ runtime·printf("MSpan_Sweep: state=%d sweepgen=%d mheap.sweepgen=%d\n",
+ s->state, s->sweepgen, sweepgen);
+ runtime·throw("MSpan_Sweep: bad span state after sweep");
+ }
+ runtime·atomicstore(&s->sweepgen, sweepgen);
+ }
+ if(nfree > 0) {
+ c->local_nsmallfree[cl] += nfree;
+ c->local_cachealloc -= nfree * size;
+ runtime·xadd64(&mstats.next_gc, -(uint64)(nfree * size * (runtime·gcpercent + 100)/100));
+ res = runtime·MCentral_FreeSpan(&runtime·mheap.central[cl].mcentral, s, nfree, head.next, end, preserve);
+ // MCentral_FreeSpan updates sweepgen
+ }
+ return res;
+}
+
+// State of background runtime·sweep.
+// Protected by runtime·gclock.
+typedef struct SweepData SweepData;
+struct SweepData
+{
+ G* g;
+ bool parked;
+
+ uint32 spanidx; // background sweeper position
+
+ uint32 nbgsweep;
+ uint32 npausesweep;
+};
+SweepData runtime·sweep;
+
+// sweeps one span
+// returns number of pages returned to heap, or -1 if there is nothing to sweep
+uintptr
+runtime·sweepone(void)
+{
+ MSpan *s;
+ uint32 idx, sg;
+ uintptr npages;
+
+ // increment locks to ensure that the goroutine is not preempted
+ // in the middle of sweep thus leaving the span in an inconsistent state for next GC
+ g->m->locks++;
+ sg = runtime·mheap.sweepgen;
+ for(;;) {
+ idx = runtime·xadd(&runtime·sweep.spanidx, 1) - 1;
+ if(idx >= runtime·work.nspan) {
+ runtime·mheap.sweepdone = true;
+ g->m->locks--;
+ return -1;
+ }
+ s = runtime·work.spans[idx];
+ if(s->state != MSpanInUse) {
+ s->sweepgen = sg;
+ continue;
+ }
+ if(s->sweepgen != sg-2 || !runtime·cas(&s->sweepgen, sg-2, sg-1))
+ continue;
+ npages = s->npages;
+ if(!runtime·MSpan_Sweep(s, false))
+ npages = 0;
+ g->m->locks--;
+ return npages;
+ }
+}
+
+static void
+sweepone_m(void)
+{
+ g->m->scalararg[0] = runtime·sweepone();
+}
+
+#pragma textflag NOSPLIT
+uintptr
+runtime·gosweepone(void)
+{
+ void (*fn)(void);
+
+ fn = sweepone_m;
+ runtime·onM(&fn);
+ return g->m->scalararg[0];
+}
+
+#pragma textflag NOSPLIT
+bool
+runtime·gosweepdone(void)
+{
+ return runtime·mheap.sweepdone;
+}
+
+void
+runtime·gchelper(void)
+{
+ uint32 nproc;
+
+ g->m->traceback = 2;
+ gchelperstart();
+
+ // parallel mark for over gc roots
+ runtime·parfordo(runtime·work.markfor);
+
+ // help other threads scan secondary blocks
+ scanblock(nil, 0, nil);
+
+ nproc = runtime·work.nproc; // runtime·work.nproc can change right after we increment runtime·work.ndone
+ if(runtime·xadd(&runtime·work.ndone, +1) == nproc-1)
+ runtime·notewakeup(&runtime·work.alldone);
+ g->m->traceback = 0;
+}
+
+static void
+cachestats(void)
+{
+ MCache *c;
+ P *p, **pp;
+
+ for(pp=runtime·allp; p=*pp; pp++) {
+ c = p->mcache;
+ if(c==nil)
+ continue;
+ runtime·purgecachedstats(c);
+ }
+}
+
+static void
+flushallmcaches(void)
+{
+ P *p, **pp;
+ MCache *c;
+
+ // Flush MCache's to MCentral.
+ for(pp=runtime·allp; p=*pp; pp++) {
+ c = p->mcache;
+ if(c==nil)
+ continue;
+ runtime·MCache_ReleaseAll(c);
+ runtime·stackcache_clear(c);
+ }
+}
+
+static void
+flushallmcaches_m(G *gp)
+{
+ flushallmcaches();
+ runtime·gogo(&gp->sched);
+}
+
+void
+runtime·updatememstats(GCStats *stats)
+{
+ M *mp;
+ MSpan *s;
+ int32 i;
+ uint64 smallfree;
+ uint64 *src, *dst;
+ void (*fn)(G*);
+
+ if(stats)
+ runtime·memclr((byte*)stats, sizeof(*stats));
+ for(mp=runtime·allm; mp; mp=mp->alllink) {
+ if(stats) {
+ src = (uint64*)&mp->gcstats;
+ dst = (uint64*)stats;
+ for(i=0; i<sizeof(*stats)/sizeof(uint64); i++)
+ dst[i] += src[i];
+ runtime·memclr((byte*)&mp->gcstats, sizeof(mp->gcstats));
+ }
+ }
+ mstats.mcache_inuse = runtime·mheap.cachealloc.inuse;
+ mstats.mspan_inuse = runtime·mheap.spanalloc.inuse;
+ mstats.sys = mstats.heap_sys + mstats.stacks_sys + mstats.mspan_sys +
+ mstats.mcache_sys + mstats.buckhash_sys + mstats.gc_sys + mstats.other_sys;
+
+ // Calculate memory allocator stats.
+ // During program execution we only count number of frees and amount of freed memory.
+ // Current number of alive object in the heap and amount of alive heap memory
+ // are calculated by scanning all spans.
+ // Total number of mallocs is calculated as number of frees plus number of alive objects.
+ // Similarly, total amount of allocated memory is calculated as amount of freed memory
+ // plus amount of alive heap memory.
+ mstats.alloc = 0;
+ mstats.total_alloc = 0;
+ mstats.nmalloc = 0;
+ mstats.nfree = 0;
+ for(i = 0; i < nelem(mstats.by_size); i++) {
+ mstats.by_size[i].nmalloc = 0;
+ mstats.by_size[i].nfree = 0;
+ }
+
+ // Flush MCache's to MCentral.
+ if(g == g->m->g0)
+ flushallmcaches();
+ else {
+ fn = flushallmcaches_m;
+ runtime·mcall(&fn);
+ }
+
+ // Aggregate local stats.
+ cachestats();
+
+ // Scan all spans and count number of alive objects.
+ runtime·lock(&runtime·mheap.lock);
+ for(i = 0; i < runtime·mheap.nspan; i++) {
+ s = runtime·mheap.allspans[i];
+ if(s->state != MSpanInUse)
+ continue;
+ if(s->sizeclass == 0) {
+ mstats.nmalloc++;
+ mstats.alloc += s->elemsize;
+ } else {
+ mstats.nmalloc += s->ref;
+ mstats.by_size[s->sizeclass].nmalloc += s->ref;
+ mstats.alloc += s->ref*s->elemsize;
+ }
+ }
+ runtime·unlock(&runtime·mheap.lock);
+
+ // Aggregate by size class.
+ smallfree = 0;
+ mstats.nfree = runtime·mheap.nlargefree;
+ for(i = 0; i < nelem(mstats.by_size); i++) {
+ mstats.nfree += runtime·mheap.nsmallfree[i];
+ mstats.by_size[i].nfree = runtime·mheap.nsmallfree[i];
+ mstats.by_size[i].nmalloc += runtime·mheap.nsmallfree[i];
+ smallfree += runtime·mheap.nsmallfree[i] * runtime·class_to_size[i];
+ }
+ mstats.nfree += mstats.tinyallocs;
+ mstats.nmalloc += mstats.nfree;
+
+ // Calculate derived stats.
+ mstats.total_alloc = mstats.alloc + runtime·mheap.largefree + smallfree;
+ mstats.heap_alloc = mstats.alloc;
+ mstats.heap_objects = mstats.nmalloc - mstats.nfree;
+}
+
+// Structure of arguments passed to function gc().
+// This allows the arguments to be passed via runtime·mcall.
+struct gc_args
+{
+ int64 start_time; // start time of GC in ns (just before stoptheworld)
+ bool eagersweep;
+};
+
+static void gc(struct gc_args *args);
+
+int32
+runtime·readgogc(void)
+{
+ byte *p;
+
+ p = runtime·getenv("GOGC");
+ if(p == nil || p[0] == '\0')
+ return 100;
+ if(runtime·strcmp(p, (byte*)"off") == 0)
+ return -1;
+ return runtime·atoi(p);
+}
+
+void
+runtime·gcinit(void)
+{
+ if(sizeof(Workbuf) != WorkbufSize)
+ runtime·throw("runtime: size of Workbuf is suboptimal");
+
+ runtime·work.markfor = runtime·parforalloc(MaxGcproc);
+ runtime·gcpercent = runtime·readgogc();
+ runtime·gcdatamask = unrollglobgcprog(runtime·gcdata, runtime·edata - runtime·data);
+ runtime·gcbssmask = unrollglobgcprog(runtime·gcbss, runtime·ebss - runtime·bss);
+}
+
+void
+runtime·gc_m(void)
+{
+ struct gc_args a;
+ G *gp;
+
+ gp = g->m->curg;
+ runtime·casgstatus(gp, Grunning, Gwaiting);
+ gp->waitreason = runtime·gostringnocopy((byte*)"garbage collection");
+
+ a.start_time = (uint64)(g->m->scalararg[0]) | ((uint64)(g->m->scalararg[1]) << 32);
+ a.eagersweep = g->m->scalararg[2];
+ gc(&a);
+
+ if(nbadblock > 0) {
+ // Work out path from root to bad block.
+ for(;;) {
+ gc(&a);
+ if(nbadblock >= nelem(badblock))
+ runtime·throw("cannot find path to bad pointer");
+ }
+ }
+
+ runtime·casgstatus(gp, Gwaiting, Grunning);
+}
+
+static void
+gc(struct gc_args *args)
+{
+ int64 t0, t1, t2, t3, t4;
+ uint64 heap0, heap1, obj;
+ GCStats stats;
+
+ if(DebugPtrs)
+ runtime·printf("GC start\n");
+
+ if(runtime·debug.allocfreetrace)
+ runtime·tracegc();
+
+ g->m->traceback = 2;
+ t0 = args->start_time;
+ runtime·work.tstart = args->start_time;
+
+ t1 = 0;
+ if(runtime·debug.gctrace)
+ t1 = runtime·nanotime();
+
+ // Sweep what is not sweeped by bgsweep.
+ while(runtime·sweepone() != -1)
+ runtime·sweep.npausesweep++;
+
+ // Cache runtime.mheap.allspans in work.spans to avoid conflicts with
+ // resizing/freeing allspans.
+ // New spans can be created while GC progresses, but they are not garbage for
+ // this round:
+ // - new stack spans can be created even while the world is stopped.
+ // - new malloc spans can be created during the concurrent sweep
+
+ // Even if this is stop-the-world, a concurrent exitsyscall can allocate a stack from heap.
+ runtime·lock(&runtime·mheap.lock);
+ // Free the old cached sweep array if necessary.
+ if(runtime·work.spans != nil && runtime·work.spans != runtime·mheap.allspans)
+ runtime·SysFree(runtime·work.spans, runtime·work.nspan*sizeof(runtime·work.spans[0]), &mstats.other_sys);
+ // Cache the current array for marking.
+ runtime·mheap.gcspans = runtime·mheap.allspans;
+ runtime·work.spans = runtime·mheap.allspans;
+ runtime·work.nspan = runtime·mheap.nspan;
+ runtime·unlock(&runtime·mheap.lock);
+
+ runtime·work.nwait = 0;
+ runtime·work.ndone = 0;
+ runtime·work.nproc = runtime·gcprocs();
+ runtime·parforsetup(runtime·work.markfor, runtime·work.nproc, RootCount + runtime·allglen, nil, false, markroot);
+ if(runtime·work.nproc > 1) {
+ runtime·noteclear(&runtime·work.alldone);
+ runtime·helpgc(runtime·work.nproc);
+ }
+
+ t2 = 0;
+ if(runtime·debug.gctrace)
+ t2 = runtime·nanotime();
+
+ gchelperstart();
+ runtime·parfordo(runtime·work.markfor);
+ scanblock(nil, 0, nil);
+
+ t3 = 0;
+ if(runtime·debug.gctrace)
+ t3 = runtime·nanotime();
+
+ if(runtime·work.nproc > 1)
+ runtime·notesleep(&runtime·work.alldone);
+
+ runtime·shrinkfinish();
+
+ cachestats();
+ // next_gc calculation is tricky with concurrent sweep since we don't know size of live heap
+ // estimate what was live heap size after previous GC (for tracing only)
+ heap0 = mstats.next_gc*100/(runtime·gcpercent+100);
+ // conservatively set next_gc to high value assuming that everything is live
+ // concurrent/lazy sweep will reduce this number while discovering new garbage
+ mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*runtime·gcpercent/100;
+
+ t4 = runtime·nanotime();
+ runtime·atomicstore64(&mstats.last_gc, runtime·unixnanotime()); // must be Unix time to make sense to user
+ mstats.pause_ns[mstats.numgc%nelem(mstats.pause_ns)] = t4 - t0;
+ mstats.pause_end[mstats.numgc%nelem(mstats.pause_end)] = t4;
+ mstats.pause_total_ns += t4 - t0;
+ mstats.numgc++;
+ if(mstats.debuggc)
+ runtime·printf("pause %D\n", t4-t0);
+
+ if(runtime·debug.gctrace) {
+ heap1 = mstats.heap_alloc;
+ runtime·updatememstats(&stats);
+ if(heap1 != mstats.heap_alloc) {
+ runtime·printf("runtime: mstats skew: heap=%D/%D\n", heap1, mstats.heap_alloc);
+ runtime·throw("mstats skew");
+ }
+ obj = mstats.nmalloc - mstats.nfree;
+
+ stats.nprocyield += runtime·work.markfor->nprocyield;
+ stats.nosyield += runtime·work.markfor->nosyield;
+ stats.nsleep += runtime·work.markfor->nsleep;
+
+ runtime·printf("gc%d(%d): %D+%D+%D+%D us, %D -> %D MB, %D (%D-%D) objects,"
+ " %d goroutines,"
+ " %d/%d/%d sweeps,"
+ " %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\n",
+ mstats.numgc, runtime·work.nproc, (t1-t0)/1000, (t2-t1)/1000, (t3-t2)/1000, (t4-t3)/1000,
+ heap0>>20, heap1>>20, obj,
+ mstats.nmalloc, mstats.nfree,
+ runtime·gcount(),
+ runtime·work.nspan, runtime·sweep.nbgsweep, runtime·sweep.npausesweep,
+ stats.nhandoff, stats.nhandoffcnt,
+ runtime·work.markfor->nsteal, runtime·work.markfor->nstealcnt,
+ stats.nprocyield, stats.nosyield, stats.nsleep);
+ runtime·sweep.nbgsweep = runtime·sweep.npausesweep = 0;
+ }
+
+ // See the comment in the beginning of this function as to why we need the following.
+ // Even if this is still stop-the-world, a concurrent exitsyscall can allocate a stack from heap.
+ runtime·lock(&runtime·mheap.lock);
+ // Free the old cached mark array if necessary.
+ if(runtime·work.spans != nil && runtime·work.spans != runtime·mheap.allspans)
+ runtime·SysFree(runtime·work.spans, runtime·work.nspan*sizeof(runtime·work.spans[0]), &mstats.other_sys);
+ // Cache the current array for sweeping.
+ runtime·mheap.gcspans = runtime·mheap.allspans;
+ runtime·mheap.sweepgen += 2;
+ runtime·mheap.sweepdone = false;
+ runtime·work.spans = runtime·mheap.allspans;
+ runtime·work.nspan = runtime·mheap.nspan;
+ runtime·sweep.spanidx = 0;
+ runtime·unlock(&runtime·mheap.lock);
+
+ if(ConcurrentSweep && !args->eagersweep) {
+ runtime·lock(&runtime·gclock);
+ if(runtime·sweep.g == nil)
+ runtime·sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, gc);
+ else if(runtime·sweep.parked) {
+ runtime·sweep.parked = false;
+ runtime·ready(runtime·sweep.g);
+ }
+ runtime·unlock(&runtime·gclock);
+ } else {
+ // Sweep all spans eagerly.
+ while(runtime·sweepone() != -1)
+ runtime·sweep.npausesweep++;
+ // Do an additional mProf_GC, because all 'free' events are now real as well.
+ runtime·mProf_GC();
+ }
+
+ runtime·mProf_GC();
+ g->m->traceback = 0;
+
+ if(DebugPtrs)
+ runtime·printf("GC end\n");
+}
+
+extern uintptr runtime·sizeof_C_MStats;
+
+static void readmemstats_m(void);
+
+void
+runtime·readmemstats_m(void)
+{
+ MStats *stats;
+
+ stats = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+
+ runtime·updatememstats(nil);
+ // Size of the trailing by_size array differs between Go and C,
+ // NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
+ runtime·memmove(stats, &mstats, runtime·sizeof_C_MStats);
+
+ // Stack numbers are part of the heap numbers, separate those out for user consumption
+ stats->stacks_sys = stats->stacks_inuse;
+ stats->heap_inuse -= stats->stacks_inuse;
+ stats->heap_sys -= stats->stacks_inuse;
+}
+
+static void readgcstats_m(void);
+
+#pragma textflag NOSPLIT
+void
+runtime∕debug·readGCStats(Slice *pauses)
+{
+ void (*fn)(void);
+
+ g->m->ptrarg[0] = pauses;
+ fn = readgcstats_m;
+ runtime·onM(&fn);
+}
+
+static void
+readgcstats_m(void)
+{
+ Slice *pauses;
+ uint64 *p;
+ uint32 i, j, n;
+
+ pauses = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+
+ // Calling code in runtime/debug should make the slice large enough.
+ if(pauses->cap < nelem(mstats.pause_ns)+3)
+ runtime·throw("runtime: short slice passed to readGCStats");
+
+ // Pass back: pauses, pause ends, last gc (absolute time), number of gc, total pause ns.
+ p = (uint64*)pauses->array;
+ runtime·lock(&runtime·mheap.lock);
+
+ n = mstats.numgc;
+ if(n > nelem(mstats.pause_ns))
+ n = nelem(mstats.pause_ns);
+
+ // The pause buffer is circular. The most recent pause is at
+ // pause_ns[(numgc-1)%nelem(pause_ns)], and then backward
+ // from there to go back farther in time. We deliver the times
+ // most recent first (in p[0]).
+ for(i=0; i<n; i++) {
+ j = (mstats.numgc-1-i)%nelem(mstats.pause_ns);
+ p[i] = mstats.pause_ns[j];
+ p[n+i] = mstats.pause_end[j];
+ }
+
+ p[n+n] = mstats.last_gc;
+ p[n+n+1] = mstats.numgc;
+ p[n+n+2] = mstats.pause_total_ns;
+ runtime·unlock(&runtime·mheap.lock);
+ pauses->len = n+n+3;
+}
+
+void
+runtime·setgcpercent_m(void)
+{
+ int32 in;
+ int32 out;
+
+ in = (int32)(intptr)g->m->scalararg[0];
+
+ runtime·lock(&runtime·mheap.lock);
+ out = runtime·gcpercent;
+ if(in < 0)
+ in = -1;
+ runtime·gcpercent = in;
+ runtime·unlock(&runtime·mheap.lock);
+
+ g->m->scalararg[0] = (uintptr)(intptr)out;
+}
+
+static void
+gchelperstart(void)
+{
+ if(g->m->helpgc < 0 || g->m->helpgc >= MaxGcproc)
+ runtime·throw("gchelperstart: bad m->helpgc");
+ if(g != g->m->g0)
+ runtime·throw("gchelper not running on g0 stack");
+}
+
+G*
+runtime·wakefing(void)
+{
+ G *res;
+
+ res = nil;
+ runtime·lock(&runtime·finlock);
+ if(runtime·fingwait && runtime·fingwake) {
+ runtime·fingwait = false;
+ runtime·fingwake = false;
+ res = runtime·fing;
+ }
+ runtime·unlock(&runtime·finlock);
+ return res;
+}
+
+// Recursively unrolls GC program in prog.
+// mask is where to store the result.
+// ppos is a pointer to position in mask, in bits.
+// sparse says to generate 4-bits per word mask for heap (2-bits for data/bss otherwise).
+static byte*
+unrollgcprog1(byte *mask, byte *prog, uintptr *ppos, bool inplace, bool sparse)
+{
+ uintptr pos, siz, i, off;
+ byte *arena_start, *prog1, v, *bitp, shift;
+
+ arena_start = runtime·mheap.arena_start;
+ pos = *ppos;
+ for(;;) {
+ switch(prog[0]) {
+ case insData:
+ prog++;
+ siz = prog[0];
+ prog++;
+ for(i = 0; i < siz; i++) {
+ v = prog[i/PointersPerByte];
+ v >>= (i%PointersPerByte)*BitsPerPointer;
+ v &= BitsMask;
+ if(inplace) {
+ // Store directly into GC bitmap.
+ off = (uintptr*)(mask+pos) - (uintptr*)arena_start;
+ bitp = arena_start - off/wordsPerBitmapByte - 1;
+ shift = (off % wordsPerBitmapByte) * gcBits;
+ if(shift==0)
+ *bitp = 0;
+ *bitp |= v<<(shift+2);
+ pos += PtrSize;
+ } else if(sparse) {
+ // 4-bits per word
+ v <<= (pos%8)+2;
+ mask[pos/8] |= v;
+ pos += gcBits;
+ } else {
+ // 2-bits per word
+ v <<= pos%8;
+ mask[pos/8] |= v;
+ pos += BitsPerPointer;
+ }
+ }
+ prog += ROUND(siz*BitsPerPointer, 8)/8;
+ break;
+ case insArray:
+ prog++;
+ siz = 0;
+ for(i = 0; i < PtrSize; i++)
+ siz = (siz<<8) + prog[PtrSize-i-1];
+ prog += PtrSize;
+ prog1 = nil;
+ for(i = 0; i < siz; i++)
+ prog1 = unrollgcprog1(mask, prog, &pos, inplace, sparse);
+ if(prog1[0] != insArrayEnd)
+ runtime·throw("unrollgcprog: array does not end with insArrayEnd");
+ prog = prog1+1;
+ break;
+ case insArrayEnd:
+ case insEnd:
+ *ppos = pos;
+ return prog;
+ default:
+ runtime·throw("unrollgcprog: unknown instruction");
+ }
+ }
+}
+
+// Unrolls GC program prog for data/bss, returns dense GC mask.
+static BitVector
+unrollglobgcprog(byte *prog, uintptr size)
+{
+ byte *mask;
+ uintptr pos, masksize;
+
+ masksize = ROUND(ROUND(size, PtrSize)/PtrSize*BitsPerPointer, 8)/8;
+ mask = runtime·persistentalloc(masksize+1, 0, &mstats.gc_sys);
+ mask[masksize] = 0xa1;
+ pos = 0;
+ prog = unrollgcprog1(mask, prog, &pos, false, false);
+ if(pos != size/PtrSize*BitsPerPointer) {
+ runtime·printf("unrollglobgcprog: bad program size, got %D, expect %D\n",
+ (uint64)pos, (uint64)size/PtrSize*BitsPerPointer);
+ runtime·throw("unrollglobgcprog: bad program size");
+ }
+ if(prog[0] != insEnd)
+ runtime·throw("unrollglobgcprog: program does not end with insEnd");
+ if(mask[masksize] != 0xa1)
+ runtime·throw("unrollglobgcprog: overflow");
+ return (BitVector){masksize*8, mask};
+}
+
+void
+runtime·unrollgcproginplace_m(void)
+{
+ uintptr size, size0, pos, off;
+ byte *arena_start, *prog, *bitp, shift;
+ Type *typ;
+ void *v;
+
+ v = g->m->ptrarg[0];
+ typ = g->m->ptrarg[1];
+ size = g->m->scalararg[0];
+ size0 = g->m->scalararg[1];
+ g->m->ptrarg[0] = nil;
+ g->m->ptrarg[1] = nil;
+
+ pos = 0;
+ prog = (byte*)typ->gc[1];
+ while(pos != size0)
+ unrollgcprog1(v, prog, &pos, true, true);
+ // Mark first word as bitAllocated.
+ arena_start = runtime·mheap.arena_start;
+ off = (uintptr*)v - (uintptr*)arena_start;
+ bitp = arena_start - off/wordsPerBitmapByte - 1;
+ shift = (off % wordsPerBitmapByte) * gcBits;
+ *bitp |= bitBoundary<<shift;
+ // Mark word after last as BitsDead.
+ if(size0 < size) {
+ off = (uintptr*)((byte*)v + size0) - (uintptr*)arena_start;
+ bitp = arena_start - off/wordsPerBitmapByte - 1;
+ shift = (off % wordsPerBitmapByte) * gcBits;
+ *bitp &= ~(bitPtrMask<<shift) | ((uintptr)BitsDead<<(shift+2));
+ }
+}
+
+// Unrolls GC program in typ->gc[1] into typ->gc[0]
+void
+runtime·unrollgcprog_m(void)
+{
+ static Mutex lock;
+ Type *typ;
+ byte *mask, *prog;
+ uintptr pos;
+ uint32 x;
+
+ typ = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+
+ runtime·lock(&lock);
+ mask = (byte*)typ->gc[0];
+ if(mask[0] == 0) {
+ pos = 8; // skip the unroll flag
+ prog = (byte*)typ->gc[1];
+ prog = unrollgcprog1(mask, prog, &pos, false, true);
+ if(prog[0] != insEnd)
+ runtime·throw("unrollgcprog: program does not end with insEnd");
+ if(((typ->size/PtrSize)%2) != 0) {
+ // repeat the program twice
+ prog = (byte*)typ->gc[1];
+ unrollgcprog1(mask, prog, &pos, false, true);
+ }
+ // atomic way to say mask[0] = 1
+ x = ((uint32*)mask)[0];
+ runtime·atomicstore((uint32*)mask, x|1);
+ }
+ runtime·unlock(&lock);
+}
+
+// mark the span of memory at v as having n blocks of the given size.
+// if leftover is true, there is left over space at the end of the span.
+void
+runtime·markspan(void *v, uintptr size, uintptr n, bool leftover)
+{
+ uintptr i, off, step;
+ byte *b;
+
+ if((byte*)v+size*n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
+ runtime·throw("markspan: bad pointer");
+
+ // Find bits of the beginning of the span.
+ off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start; // word offset
+ b = runtime·mheap.arena_start - off/wordsPerBitmapByte - 1;
+ if((off%wordsPerBitmapByte) != 0)
+ runtime·throw("markspan: unaligned length");
+
+ // Okay to use non-atomic ops here, because we control
+ // the entire span, and each bitmap byte has bits for only
+ // one span, so no other goroutines are changing these bitmap words.
+
+ if(size == PtrSize) {
+ // Possible only on 64-bits (minimal size class is 8 bytes).
+ // Poor man's memset(0x11).
+ if(0x11 != ((bitBoundary+BitsDead)<<gcBits) + (bitBoundary+BitsDead))
+ runtime·throw("markspan: bad bits");
+ if((n%(wordsPerBitmapByte*PtrSize)) != 0)
+ runtime·throw("markspan: unaligned length");
+ b = b - n/wordsPerBitmapByte + 1; // find first byte
+ if(((uintptr)b%PtrSize) != 0)
+ runtime·throw("markspan: unaligned pointer");
+ for(i = 0; i != n; i += wordsPerBitmapByte*PtrSize, b += PtrSize)
+ *(uintptr*)b = (uintptr)0x1111111111111111ULL; // bitBoundary+BitsDead
+ return;
+ }
+
+ if(leftover)
+ n++; // mark a boundary just past end of last block too
+ step = size/(PtrSize*wordsPerBitmapByte);
+ for(i = 0; i != n; i++, b -= step)
+ *b = bitBoundary|(BitsDead<<2);
+}
+
+// unmark the span of memory at v of length n bytes.
+void
+runtime·unmarkspan(void *v, uintptr n)
+{
+ uintptr off;
+ byte *b;
+
+ if((byte*)v+n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
+ runtime·throw("markspan: bad pointer");
+
+ off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start; // word offset
+ if((off % (PtrSize*wordsPerBitmapByte)) != 0)
+ runtime·throw("markspan: unaligned pointer");
+ b = runtime·mheap.arena_start - off/wordsPerBitmapByte - 1;
+ n /= PtrSize;
+ if(n%(PtrSize*wordsPerBitmapByte) != 0)
+ runtime·throw("unmarkspan: unaligned length");
+ // Okay to use non-atomic ops here, because we control
+ // the entire span, and each bitmap word has bits for only
+ // one span, so no other goroutines are changing these
+ // bitmap words.
+ n /= wordsPerBitmapByte;
+ runtime·memclr(b - n + 1, n);
+}
+
+void
+runtime·MHeap_MapBits(MHeap *h)
+{
+ // 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.
+ enum {
+ bitmapChunk = 8192
+ };
+ uintptr n;
+
+ n = (h->arena_used - h->arena_start) / (PtrSize*wordsPerBitmapByte);
+ n = ROUND(n, bitmapChunk);
+ n = ROUND(n, PhysPageSize);
+ if(h->bitmap_mapped >= n)
+ return;
+
+ runtime·SysMap(h->arena_start - n, n - h->bitmap_mapped, h->arena_reserved, &mstats.gc_sys);
+ h->bitmap_mapped = n;
+}
+
+static bool
+getgcmaskcb(Stkframe *frame, void *ctxt)
+{
+ Stkframe *frame0;
+
+ frame0 = ctxt;
+ if(frame->sp <= frame0->sp && frame0->sp < frame->varp) {
+ *frame0 = *frame;
+ return false;
+ }
+ return true;
+}
+
+// Returns GC type info for object p for testing.
+void
+runtime·getgcmask(byte *p, Type *t, byte **mask, uintptr *len)
+{
+ Stkframe frame;
+ uintptr i, n, off;
+ byte *base, bits, shift, *b;
+ bool (*cb)(Stkframe*, void*);
+
+ *mask = nil;
+ *len = 0;
+
+ // data
+ if(p >= runtime·data && p < runtime·edata) {
+ n = ((PtrType*)t)->elem->size;
+ *len = n/PtrSize;
+ *mask = runtime·mallocgc(*len, nil, FlagNoScan);
+ for(i = 0; i < n; i += PtrSize) {
+ off = (p+i-runtime·data)/PtrSize;
+ bits = (runtime·gcdatamask.bytedata[off/PointersPerByte] >> ((off%PointersPerByte)*BitsPerPointer))&BitsMask;
+ (*mask)[i/PtrSize] = bits;
+ }
+ return;
+ }
+ // bss
+ if(p >= runtime·bss && p < runtime·ebss) {
+ n = ((PtrType*)t)->elem->size;
+ *len = n/PtrSize;
+ *mask = runtime·mallocgc(*len, nil, FlagNoScan);
+ for(i = 0; i < n; i += PtrSize) {
+ off = (p+i-runtime·bss)/PtrSize;
+ bits = (runtime·gcbssmask.bytedata[off/PointersPerByte] >> ((off%PointersPerByte)*BitsPerPointer))&BitsMask;
+ (*mask)[i/PtrSize] = bits;
+ }
+ return;
+ }
+ // heap
+ if(runtime·mlookup(p, &base, &n, nil)) {
+ *len = n/PtrSize;
+ *mask = runtime·mallocgc(*len, nil, FlagNoScan);
+ for(i = 0; i < n; i += PtrSize) {
+ off = (uintptr*)(base+i) - (uintptr*)runtime·mheap.arena_start;
+ b = runtime·mheap.arena_start - off/wordsPerBitmapByte - 1;
+ shift = (off % wordsPerBitmapByte) * gcBits;
+ bits = (*b >> (shift+2))&BitsMask;
+ (*mask)[i/PtrSize] = bits;
+ }
+ return;
+ }
+ // stack
+ frame.fn = nil;
+ frame.sp = (uintptr)p;
+ cb = getgcmaskcb;
+ runtime·gentraceback(g->m->curg->sched.pc, g->m->curg->sched.sp, 0, g->m->curg, 0, nil, 1000, &cb, &frame, 0);
+ if(frame.fn != nil) {
+ Func *f;
+ StackMap *stackmap;
+ BitVector bv;
+ uintptr size;
+ uintptr targetpc;
+ int32 pcdata;
+
+ f = frame.fn;
+ targetpc = frame.continpc;
+ if(targetpc == 0)
+ return;
+ if(targetpc != f->entry)
+ targetpc--;
+ pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, targetpc);
+ if(pcdata == -1)
+ return;
+ stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
+ if(stackmap == nil || stackmap->n <= 0)
+ return;
+ bv = runtime·stackmapdata(stackmap, pcdata);
+ size = bv.n/BitsPerPointer*PtrSize;
+ n = ((PtrType*)t)->elem->size;
+ *len = n/PtrSize;
+ *mask = runtime·mallocgc(*len, nil, FlagNoScan);
+ for(i = 0; i < n; i += PtrSize) {
+ off = (p+i-(byte*)frame.varp+size)/PtrSize;
+ bits = (bv.bytedata[off*BitsPerPointer/8] >> ((off*BitsPerPointer)%8))&BitsMask;
+ (*mask)[i/PtrSize] = bits;
+ }
+ }
+}
+
+void runtime·gc_unixnanotime(int64 *now);
+
+int64
+runtime·unixnanotime(void)
+{
+ int64 now;
+
+ runtime·gc_unixnanotime(&now);
+ return now;
+}
diff --git a/src/runtime/mgc0.go b/src/runtime/mgc0.go
new file mode 100644
index 000000000..cbf5e9cfd
--- /dev/null
+++ b/src/runtime/mgc0.go
@@ -0,0 +1,152 @@
+// 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
+
+import "unsafe"
+
+// Called from C. Returns the Go type *m.
+func gc_m_ptr(ret *interface{}) {
+ *ret = (*m)(nil)
+}
+
+// Called from C. Returns the Go type *g.
+func gc_g_ptr(ret *interface{}) {
+ *ret = (*g)(nil)
+}
+
+// Called from C. Returns the Go type *itab.
+func gc_itab_ptr(ret *interface{}) {
+ *ret = (*itab)(nil)
+}
+
+func gc_unixnanotime(now *int64) {
+ sec, nsec := timenow()
+ *now = sec*1e9 + int64(nsec)
+}
+
+func freeOSMemory() {
+ gogc(2) // force GC and do eager sweep
+ onM(scavenge_m)
+}
+
+var poolcleanup func()
+
+func registerPoolCleanup(f func()) {
+ poolcleanup = f
+}
+
+func clearpools() {
+ // clear sync.Pools
+ if poolcleanup != nil {
+ poolcleanup()
+ }
+
+ for _, p := range &allp {
+ if p == nil {
+ break
+ }
+ // clear tinyalloc pool
+ if c := p.mcache; c != nil {
+ c.tiny = nil
+ c.tinysize = 0
+
+ // disconnect cached list before dropping it on the floor,
+ // so that a dangling ref to one entry does not pin all of them.
+ var sg, sgnext *sudog
+ for sg = c.sudogcache; sg != nil; sg = sgnext {
+ sgnext = sg.next
+ sg.next = nil
+ }
+ c.sudogcache = nil
+ }
+
+ // clear defer pools
+ for i := range p.deferpool {
+ // disconnect cached list before dropping it on the floor,
+ // so that a dangling ref to one entry does not pin all of them.
+ var d, dlink *_defer
+ for d = p.deferpool[i]; d != nil; d = dlink {
+ dlink = d.link
+ d.link = nil
+ }
+ p.deferpool[i] = nil
+ }
+ }
+}
+
+func gosweepone() uintptr
+func gosweepdone() bool
+
+func bgsweep() {
+ getg().issystem = true
+ for {
+ for gosweepone() != ^uintptr(0) {
+ sweep.nbgsweep++
+ Gosched()
+ }
+ lock(&gclock)
+ if !gosweepdone() {
+ // This can happen if a GC runs between
+ // gosweepone returning ^0 above
+ // and the lock being acquired.
+ unlock(&gclock)
+ continue
+ }
+ sweep.parked = true
+ goparkunlock(&gclock, "GC sweep wait")
+ }
+}
+
+// NOTE: Really dst *unsafe.Pointer, src unsafe.Pointer,
+// but if we do that, Go inserts a write barrier on *dst = src.
+//go:nosplit
+func writebarrierptr(dst *uintptr, src uintptr) {
+ *dst = src
+}
+
+//go:nosplit
+func writebarrierstring(dst *[2]uintptr, src [2]uintptr) {
+ dst[0] = src[0]
+ dst[1] = src[1]
+}
+
+//go:nosplit
+func writebarrierslice(dst *[3]uintptr, src [3]uintptr) {
+ dst[0] = src[0]
+ dst[1] = src[1]
+ dst[2] = src[2]
+}
+
+//go:nosplit
+func writebarrieriface(dst *[2]uintptr, src [2]uintptr) {
+ dst[0] = src[0]
+ dst[1] = src[1]
+}
+
+//go:nosplit
+func writebarrierfat2(dst *[2]uintptr, _ *byte, src [2]uintptr) {
+ dst[0] = src[0]
+ dst[1] = src[1]
+}
+
+//go:nosplit
+func writebarrierfat3(dst *[3]uintptr, _ *byte, src [3]uintptr) {
+ dst[0] = src[0]
+ dst[1] = src[1]
+ dst[2] = src[2]
+}
+
+//go:nosplit
+func writebarrierfat4(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ dst[0] = src[0]
+ dst[1] = src[1]
+ dst[2] = src[2]
+ dst[3] = src[3]
+}
+
+//go:nosplit
+func writebarrierfat(typ *_type, dst, src unsafe.Pointer) {
+ memmove(dst, src, typ.size)
+}
diff --git a/src/runtime/mgc0.h b/src/runtime/mgc0.h
new file mode 100644
index 000000000..64f818914
--- /dev/null
+++ b/src/runtime/mgc0.h
@@ -0,0 +1,78 @@
+// 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.
+
+// Garbage collector (GC)
+
+enum {
+ // Four bits per word (see #defines below).
+ gcBits = 4,
+ wordsPerBitmapByte = 8/gcBits,
+
+ // GC type info programs.
+ // The programs allow to store type info required for GC in a compact form.
+ // Most importantly arrays take O(1) space instead of O(n).
+ // The program grammar is:
+ //
+ // Program = {Block} "insEnd"
+ // Block = Data | Array
+ // Data = "insData" DataSize DataBlock
+ // DataSize = int // size of the DataBlock in bit pairs, 1 byte
+ // DataBlock = binary // dense GC mask (2 bits per word) of size ]DataSize/4[ bytes
+ // Array = "insArray" ArrayLen Block "insArrayEnd"
+ // ArrayLen = int // length of the array, 8 bytes (4 bytes for 32-bit arch)
+ //
+ // Each instruction (insData, insArray, etc) is 1 byte.
+ // For example, for type struct { x []byte; y [20]struct{ z int; w *byte }; }
+ // the program looks as:
+ //
+ // insData 3 (BitsMultiWord BitsSlice BitsScalar)
+ // insArray 20 insData 2 (BitsScalar BitsPointer) insArrayEnd insEnd
+ //
+ // Total size of the program is 17 bytes (13 bytes on 32-bits).
+ // The corresponding GC mask would take 43 bytes (it would be repeated
+ // because the type has odd number of words).
+ insData = 1,
+ insArray,
+ insArrayEnd,
+ insEnd,
+
+ // Pointer map
+ BitsPerPointer = 2,
+ BitsMask = (1<<BitsPerPointer)-1,
+ PointersPerByte = 8/BitsPerPointer,
+
+ // If you change these, also change scanblock.
+ // scanblock does "if(bits == BitsScalar || bits == BitsDead)" as "if(bits <= BitsScalar)".
+ BitsDead = 0,
+ BitsScalar = 1,
+ BitsPointer = 2,
+ BitsMultiWord = 3,
+ // BitsMultiWord will be set for the first word of a multi-word item.
+ // When it is set, one of the following will be set for the second word.
+ // NOT USED ANYMORE: BitsString = 0,
+ // NOT USED ANYMORE: BitsSlice = 1,
+ BitsIface = 2,
+ BitsEface = 3,
+
+ // 64 bytes cover objects of size 1024/512 on 64/32 bits, respectively.
+ MaxGCMask = 64,
+};
+
+// Bits in per-word bitmap.
+// #defines because we shift the values beyond 32 bits.
+//
+// Each word in the bitmap describes wordsPerBitmapWord words
+// of heap memory. There are 4 bitmap bits dedicated to each heap word,
+// so on a 64-bit system there is one bitmap word per 16 heap words.
+//
+// The bitmap starts at mheap.arena_start and extends *backward* from
+// there. On a 64-bit system the off'th word in the arena is tracked by
+// the off/16+1'th word before mheap.arena_start. (On a 32-bit system,
+// the only difference is that the divisor is 8.)
+enum {
+ bitBoundary = 1, // boundary of an object
+ bitMarked = 2, // marked object
+ bitMask = bitBoundary | bitMarked,
+ bitPtrMask = BitsMask<<2,
+};
diff --git a/src/pkg/runtime/mheap.c b/src/runtime/mheap.c
index 7e83eb283..bb203d5ce 100644
--- a/src/pkg/runtime/mheap.c
+++ b/src/runtime/mheap.c
@@ -9,16 +9,16 @@
// When a MSpan is in the heap free list, state == MSpanFree
// and heapmap(s->start) == span, heapmap(s->start+s->npages-1) == span.
//
-// When a MSpan is allocated, state == MSpanInUse
+// When a MSpan is allocated, state == MSpanInUse or MSpanStack
// and heapmap(i) == span for all s->start <= i < s->start+s->npages.
#include "runtime.h"
#include "arch_GOARCH.h"
#include "malloc.h"
-static MSpan *MHeap_AllocLocked(MHeap*, uintptr, int32);
+static MSpan *MHeap_AllocSpanLocked(MHeap*, uintptr);
+static void MHeap_FreeSpanLocked(MHeap*, MSpan*, bool, bool);
static bool MHeap_Grow(MHeap*, uintptr);
-static void MHeap_FreeLocked(MHeap*, MSpan*);
static MSpan *MHeap_AllocLarge(MHeap*, uintptr);
static MSpan *BestFit(MSpan*, uintptr, MSpan*);
@@ -36,14 +36,14 @@ RecordSpan(void *vh, byte *p)
cap = 64*1024/sizeof(all[0]);
if(cap < h->nspancap*3/2)
cap = h->nspancap*3/2;
- all = (MSpan**)runtime·SysAlloc(cap*sizeof(all[0]), &mstats.other_sys);
+ all = (MSpan**)runtime·sysAlloc(cap*sizeof(all[0]), &mstats.other_sys);
if(all == nil)
runtime·throw("runtime: cannot allocate memory");
if(h->allspans) {
runtime·memmove(all, h->allspans, h->nspancap*sizeof(all[0]));
// Don't free the old array if it's referenced by sweep.
// See the comment in mgc0.c.
- if(h->allspans != runtime·mheap.sweepspans)
+ if(h->allspans != runtime·mheap.gcspans)
runtime·SysFree(h->allspans, h->nspancap*sizeof(all[0]), &mstats.other_sys);
}
h->allspans = all;
@@ -70,7 +70,7 @@ runtime·MHeap_Init(MHeap *h)
runtime·MSpanList_Init(&h->freelarge);
runtime·MSpanList_Init(&h->busylarge);
for(i=0; i<nelem(h->central); i++)
- runtime·MCentral_Init(&h->central[i], i);
+ runtime·MCentral_Init(&h->central[i].mcentral, i);
}
void
@@ -106,9 +106,9 @@ retry:
runtime·MSpanList_Remove(s);
// swept spans are at the end of the list
runtime·MSpanList_InsertBack(list, s);
- runtime·unlock(h);
- n += runtime·MSpan_Sweep(s);
- runtime·lock(h);
+ runtime·unlock(&h->lock);
+ n += runtime·MSpan_Sweep(s, false);
+ runtime·lock(&h->lock);
if(n >= npages)
return n;
// the span could have been moved elsewhere
@@ -153,7 +153,7 @@ MHeap_Reclaim(MHeap *h, uintptr npage)
}
// Now sweep everything that is not yet swept.
- runtime·unlock(h);
+ runtime·unlock(&h->lock);
for(;;) {
n = runtime·sweepone();
if(n == -1) // all spans are swept
@@ -162,22 +162,43 @@ MHeap_Reclaim(MHeap *h, uintptr npage)
if(reclaimed >= npage)
break;
}
- runtime·lock(h);
+ runtime·lock(&h->lock);
}
-// Allocate a new span of npage pages from the heap
+// Allocate a new span of npage pages from the heap for GC'd memory
// and record its size class in the HeapMap and HeapMapCache.
-MSpan*
-runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large, bool needzero)
+static MSpan*
+mheap_alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large)
{
MSpan *s;
- runtime·lock(h);
- mstats.heap_alloc += m->mcache->local_cachealloc;
- m->mcache->local_cachealloc = 0;
- s = MHeap_AllocLocked(h, npage, sizeclass);
+ if(g != g->m->g0)
+ runtime·throw("mheap_alloc not on M stack");
+ runtime·lock(&h->lock);
+
+ // To prevent excessive heap growth, before allocating n pages
+ // we need to sweep and reclaim at least n pages.
+ if(!h->sweepdone)
+ MHeap_Reclaim(h, npage);
+
+ // transfer stats from cache to global
+ mstats.heap_alloc += g->m->mcache->local_cachealloc;
+ g->m->mcache->local_cachealloc = 0;
+ mstats.tinyallocs += g->m->mcache->local_tinyallocs;
+ g->m->mcache->local_tinyallocs = 0;
+
+ s = MHeap_AllocSpanLocked(h, npage);
if(s != nil) {
- mstats.heap_inuse += npage<<PageShift;
+ // Record span info, because gc needs to be
+ // able to map interior pointer to containing span.
+ runtime·atomicstore(&s->sweepgen, h->sweepgen);
+ s->state = MSpanInUse;
+ s->freelist = nil;
+ s->ref = 0;
+ s->sizeclass = sizeclass;
+ s->elemsize = (sizeclass==0 ? s->npages<<PageShift : runtime·class_to_size[sizeclass]);
+
+ // update stats, sweep lists
if(large) {
mstats.heap_objects++;
mstats.heap_alloc += npage<<PageShift;
@@ -188,7 +209,45 @@ runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large, bool
runtime·MSpanList_InsertBack(&h->busylarge, s);
}
}
- runtime·unlock(h);
+ runtime·unlock(&h->lock);
+ return s;
+}
+
+static void
+mheap_alloc_m(G *gp)
+{
+ MHeap *h;
+ MSpan *s;
+
+ h = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ s = mheap_alloc(h, g->m->scalararg[0], g->m->scalararg[1], g->m->scalararg[2]);
+ g->m->ptrarg[0] = s;
+
+ runtime·gogo(&gp->sched);
+}
+
+MSpan*
+runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large, bool needzero)
+{
+ MSpan *s;
+ void (*fn)(G*);
+
+ // 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.
+ if(g == g->m->g0) {
+ s = mheap_alloc(h, npage, sizeclass, large);
+ } else {
+ g->m->ptrarg[0] = h;
+ g->m->scalararg[0] = npage;
+ g->m->scalararg[1] = sizeclass;
+ g->m->scalararg[2] = large;
+ fn = mheap_alloc_m;
+ runtime·mcall(&fn);
+ s = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ }
if(s != nil) {
if(needzero && s->needzero)
runtime·memclr((byte*)(s->start<<PageShift), s->npages<<PageShift);
@@ -197,17 +256,34 @@ runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large, bool
return s;
}
+MSpan*
+runtime·MHeap_AllocStack(MHeap *h, uintptr npage)
+{
+ MSpan *s;
+
+ if(g != g->m->g0)
+ runtime·throw("mheap_allocstack not on M stack");
+ runtime·lock(&h->lock);
+ s = MHeap_AllocSpanLocked(h, npage);
+ if(s != nil) {
+ s->state = MSpanStack;
+ s->freelist = nil;
+ s->ref = 0;
+ mstats.stacks_inuse += s->npages<<PageShift;
+ }
+ runtime·unlock(&h->lock);
+ return s;
+}
+
+// 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.
static MSpan*
-MHeap_AllocLocked(MHeap *h, uintptr npage, int32 sizeclass)
+MHeap_AllocSpanLocked(MHeap *h, uintptr npage)
{
uintptr n;
MSpan *s, *t;
- PageID p;
-
- // To prevent excessive heap growth, before allocating n pages
- // we need to sweep and reclaim at least n pages.
- if(!h->sweepdone)
- MHeap_Reclaim(h, npage);
+ pageID p;
// Try in fixed-size lists up to max.
for(n=npage; n < nelem(h->free); n++) {
@@ -232,13 +308,13 @@ HaveSpan:
if(s->npages < npage)
runtime·throw("MHeap_AllocLocked - bad npages");
runtime·MSpanList_Remove(s);
- runtime·atomicstore(&s->sweepgen, h->sweepgen);
- s->state = MSpanInUse;
- mstats.heap_idle -= s->npages<<PageShift;
- mstats.heap_released -= s->npreleased<<PageShift;
- if(s->npreleased > 0)
+ if(s->next != nil || s->prev != nil)
+ runtime·throw("still in list");
+ if(s->npreleased > 0) {
runtime·SysUsed((void*)(s->start<<PageShift), s->npages<<PageShift);
- s->npreleased = 0;
+ mstats.heap_released -= s->npreleased<<PageShift;
+ s->npreleased = 0;
+ }
if(s->npages > npage) {
// Trim extra and put it back in the heap.
@@ -252,22 +328,25 @@ HaveSpan:
h->spans[p] = t;
h->spans[p+t->npages-1] = t;
t->needzero = s->needzero;
- runtime·atomicstore(&t->sweepgen, h->sweepgen);
- t->state = MSpanInUse;
- MHeap_FreeLocked(h, t);
- t->unusedsince = s->unusedsince; // preserve age
+ s->state = MSpanStack; // prevent coalescing with s
+ t->state = MSpanStack;
+ MHeap_FreeSpanLocked(h, t, false, false);
+ t->unusedsince = s->unusedsince; // preserve age (TODO: wrong: t is possibly merged and/or deallocated at this point)
+ s->state = MSpanFree;
}
s->unusedsince = 0;
- // Record span info, because gc needs to be
- // able to map interior pointer to containing span.
- s->sizeclass = sizeclass;
- s->elemsize = (sizeclass==0 ? s->npages<<PageShift : runtime·class_to_size[sizeclass]);
- s->types.compression = MTypes_Empty;
p = s->start;
p -= ((uintptr)h->arena_start>>PageShift);
for(n=0; n<npage; n++)
h->spans[p+n] = s;
+
+ mstats.heap_inuse += npage<<PageShift;
+ mstats.heap_idle -= npage<<PageShift;
+
+ //runtime·printf("spanalloc %p\n", s->start << PageShift);
+ if(s->next != nil || s->prev != nil)
+ runtime·throw("still in list");
return s;
}
@@ -305,13 +384,13 @@ MHeap_Grow(MHeap *h, uintptr npage)
uintptr ask;
void *v;
MSpan *s;
- PageID p;
+ pageID p;
// 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.
- // Allocate a multiple of 64kB (16 pages).
- npage = (npage+15)&~15;
+ // Allocate a multiple of 64kB.
+ npage = ROUND(npage, (64<<10)/PageSize);
ask = npage<<PageShift;
if(ask < HeapAllocChunk)
ask = HeapAllocChunk;
@@ -338,7 +417,7 @@ MHeap_Grow(MHeap *h, uintptr npage)
h->spans[p + s->npages - 1] = s;
runtime·atomicstore(&s->sweepgen, h->sweepgen);
s->state = MSpanInUse;
- MHeap_FreeLocked(h, s);
+ MHeap_FreeSpanLocked(h, s, false, true);
return true;
}
@@ -366,7 +445,7 @@ MSpan*
runtime·MHeap_LookupMaybe(MHeap *h, void *v)
{
MSpan *s;
- PageID p, q;
+ pageID p, q;
if((byte*)v < h->arena_start || (byte*)v >= h->arena_used)
return nil;
@@ -380,35 +459,92 @@ runtime·MHeap_LookupMaybe(MHeap *h, void *v)
}
// Free the span back into the heap.
-void
-runtime·MHeap_Free(MHeap *h, MSpan *s, int32 acct)
-{
- runtime·lock(h);
- mstats.heap_alloc += m->mcache->local_cachealloc;
- m->mcache->local_cachealloc = 0;
- mstats.heap_inuse -= s->npages<<PageShift;
+static void
+mheap_free(MHeap *h, MSpan *s, int32 acct)
+{
+ if(g != g->m->g0)
+ runtime·throw("mheap_free not on M stack");
+ runtime·lock(&h->lock);
+ mstats.heap_alloc += g->m->mcache->local_cachealloc;
+ g->m->mcache->local_cachealloc = 0;
+ mstats.tinyallocs += g->m->mcache->local_tinyallocs;
+ g->m->mcache->local_tinyallocs = 0;
if(acct) {
mstats.heap_alloc -= s->npages<<PageShift;
mstats.heap_objects--;
}
- MHeap_FreeLocked(h, s);
- runtime·unlock(h);
+ MHeap_FreeSpanLocked(h, s, true, true);
+ runtime·unlock(&h->lock);
}
static void
-MHeap_FreeLocked(MHeap *h, MSpan *s)
+mheap_free_m(G *gp)
{
- MSpan *t;
- PageID p;
+ MHeap *h;
+ MSpan *s;
+
+ h = g->m->ptrarg[0];
+ s = g->m->ptrarg[1];
+ g->m->ptrarg[0] = nil;
+ g->m->ptrarg[1] = nil;
+ mheap_free(h, s, g->m->scalararg[0]);
+ runtime·gogo(&gp->sched);
+}
+
+void
+runtime·MHeap_Free(MHeap *h, MSpan *s, int32 acct)
+{
+ void (*fn)(G*);
+
+ if(g == g->m->g0) {
+ mheap_free(h, s, acct);
+ } else {
+ g->m->ptrarg[0] = h;
+ g->m->ptrarg[1] = s;
+ g->m->scalararg[0] = acct;
+ fn = mheap_free_m;
+ runtime·mcall(&fn);
+ }
+}
+
+void
+runtime·MHeap_FreeStack(MHeap *h, MSpan *s)
+{
+ if(g != g->m->g0)
+ runtime·throw("mheap_freestack not on M stack");
+ s->needzero = 1;
+ runtime·lock(&h->lock);
+ mstats.stacks_inuse -= s->npages<<PageShift;
+ MHeap_FreeSpanLocked(h, s, true, true);
+ runtime·unlock(&h->lock);
+}
- s->types.compression = MTypes_Empty;
+static void
+MHeap_FreeSpanLocked(MHeap *h, MSpan *s, bool acctinuse, bool acctidle)
+{
+ MSpan *t;
+ pageID p;
- if(s->state != MSpanInUse || s->ref != 0 || s->sweepgen != h->sweepgen) {
- runtime·printf("MHeap_FreeLocked - span %p ptr %p state %d ref %d sweepgen %d/%d\n",
- s, s->start<<PageShift, s->state, s->ref, s->sweepgen, h->sweepgen);
- runtime·throw("MHeap_FreeLocked - invalid free");
+ switch(s->state) {
+ case MSpanStack:
+ if(s->ref != 0)
+ runtime·throw("MHeap_FreeSpanLocked - invalid stack free");
+ break;
+ case MSpanInUse:
+ if(s->ref != 0 || s->sweepgen != h->sweepgen) {
+ runtime·printf("MHeap_FreeSpanLocked - span %p ptr %p ref %d sweepgen %d/%d\n",
+ s, s->start<<PageShift, s->ref, s->sweepgen, h->sweepgen);
+ runtime·throw("MHeap_FreeSpanLocked - invalid free");
+ }
+ break;
+ default:
+ runtime·throw("MHeap_FreeSpanLocked - invalid span state");
+ break;
}
- mstats.heap_idle += s->npages<<PageShift;
+ if(acctinuse)
+ mstats.heap_inuse -= s->npages<<PageShift;
+ if(acctidle)
+ mstats.heap_idle += s->npages<<PageShift;
s->state = MSpanFree;
runtime·MSpanList_Remove(s);
// Stamp newly unused spans. The scavenger will use that
@@ -419,7 +555,7 @@ MHeap_FreeLocked(MHeap *h, MSpan *s)
// Coalesce with earlier, later spans.
p = s->start;
p -= (uintptr)h->arena_start >> PageShift;
- if(p > 0 && (t = h->spans[p-1]) != nil && t->state != MSpanInUse) {
+ if(p > 0 && (t = h->spans[p-1]) != nil && t->state != MSpanInUse && t->state != MSpanStack) {
s->start = t->start;
s->npages += t->npages;
s->npreleased = t->npreleased; // absorb released pages
@@ -430,7 +566,7 @@ MHeap_FreeLocked(MHeap *h, MSpan *s)
t->state = MSpanDead;
runtime·FixAlloc_Free(&h->spanalloc, t);
}
- if((p+s->npages)*sizeof(h->spans[0]) < h->spans_mapped && (t = h->spans[p+s->npages]) != nil && t->state != MSpanInUse) {
+ if((p+s->npages)*sizeof(h->spans[0]) < h->spans_mapped && (t = h->spans[p+s->npages]) != nil && t->state != MSpanInUse && t->state != MSpanStack) {
s->npages += t->npages;
s->npreleased += t->npreleased;
s->needzero |= t->needzero;
@@ -447,13 +583,6 @@ MHeap_FreeLocked(MHeap *h, MSpan *s)
runtime·MSpanList_Insert(&h->freelarge, s);
}
-static void
-forcegchelper(Note *note)
-{
- runtime·gc(1);
- runtime·notewakeup(note);
-}
-
static uintptr
scavengelist(MSpan *list, uint64 now, uint64 limit)
{
@@ -476,94 +605,41 @@ scavengelist(MSpan *list, uint64 now, uint64 limit)
return sumreleased;
}
-static void
-scavenge(int32 k, uint64 now, uint64 limit)
+void
+runtime·MHeap_Scavenge(int32 k, uint64 now, uint64 limit)
{
uint32 i;
uintptr sumreleased;
MHeap *h;
h = &runtime·mheap;
+ runtime·lock(&h->lock);
sumreleased = 0;
for(i=0; i < nelem(h->free); i++)
sumreleased += scavengelist(&h->free[i], now, limit);
sumreleased += scavengelist(&h->freelarge, now, limit);
+ runtime·unlock(&h->lock);
if(runtime·debug.gctrace > 0) {
if(sumreleased > 0)
runtime·printf("scvg%d: %D MB released\n", k, (uint64)sumreleased>>20);
+ // TODO(dvyukov): these stats are incorrect as we don't subtract stack usage from heap.
+ // But we can't call ReadMemStats on g0 holding locks.
runtime·printf("scvg%d: inuse: %D, idle: %D, sys: %D, released: %D, consumed: %D (MB)\n",
k, mstats.heap_inuse>>20, mstats.heap_idle>>20, mstats.heap_sys>>20,
mstats.heap_released>>20, (mstats.heap_sys - mstats.heap_released)>>20);
}
}
-static FuncVal forcegchelperv = {(void(*)(void))forcegchelper};
-
-// Release (part of) unused memory to OS.
-// Goroutine created at startup.
-// Loop forever.
-void
-runtime·MHeap_Scavenger(void)
-{
- MHeap *h;
- uint64 tick, now, forcegc, limit;
- int64 unixnow;
- int32 k;
- Note note, *notep;
-
- g->issystem = true;
- g->isbackground = true;
-
- // If we go two minutes without a garbage collection, force one to run.
- forcegc = 2*60*1e9;
- // If a span goes unused for 5 minutes after a garbage collection,
- // we hand it back to the operating system.
- limit = 5*60*1e9;
- // Make wake-up period small enough for the sampling to be correct.
- if(forcegc < limit)
- tick = forcegc/2;
- else
- tick = limit/2;
-
- h = &runtime·mheap;
- for(k=0;; k++) {
- runtime·noteclear(&note);
- runtime·notetsleepg(&note, tick);
-
- runtime·lock(h);
- unixnow = runtime·unixnanotime();
- if(unixnow - mstats.last_gc > forcegc) {
- runtime·unlock(h);
- // The scavenger can not block other goroutines,
- // otherwise deadlock detector can fire spuriously.
- // GC blocks other goroutines via the runtime·worldsema.
- runtime·noteclear(&note);
- notep = &note;
- runtime·newproc1(&forcegchelperv, (byte*)&notep, sizeof(notep), 0, runtime·MHeap_Scavenger);
- runtime·notetsleepg(&note, -1);
- if(runtime·debug.gctrace > 0)
- runtime·printf("scvg%d: GC forced\n", k);
- runtime·lock(h);
- }
- now = runtime·nanotime();
- scavenge(k, now, limit);
- runtime·unlock(h);
- }
-}
-
void
-runtime∕debug·freeOSMemory(void)
+runtime·scavenge_m(void)
{
- runtime·gc(2); // force GC and do eager sweep
- runtime·lock(&runtime·mheap);
- scavenge(-1, ~(uintptr)0, 0);
- runtime·unlock(&runtime·mheap);
+ runtime·MHeap_Scavenge(-1, ~(uintptr)0, 0);
}
// Initialize a new span with the given start and npages.
void
-runtime·MSpan_Init(MSpan *span, PageID start, uintptr npages)
+runtime·MSpan_Init(MSpan *span, pageID start, uintptr npages)
{
span->next = nil;
span->prev = nil;
@@ -577,11 +653,9 @@ runtime·MSpan_Init(MSpan *span, PageID start, uintptr npages)
span->state = MSpanDead;
span->unusedsince = 0;
span->npreleased = 0;
- span->types.compression = MTypes_Empty;
span->specialLock.key = 0;
span->specials = nil;
span->needzero = 0;
- span->freebuf = nil;
}
// Initialize an empty doubly-linked list.
@@ -656,7 +730,7 @@ addspecial(void *p, Special *s)
// Ensure that the span is swept.
// GC accesses specials list w/o locks. And it's just much safer.
- m->locks++;
+ g->m->locks++;
runtime·MSpan_EnsureSwept(span);
offset = (uintptr)p - (span->start << PageShift);
@@ -669,7 +743,7 @@ addspecial(void *p, Special *s)
while((x = *t) != nil) {
if(offset == x->offset && kind == x->kind) {
runtime·unlock(&span->specialLock);
- m->locks--;
+ g->m->locks--;
return false; // already exists
}
if(offset < x->offset || (offset == x->offset && kind < x->kind))
@@ -681,7 +755,7 @@ addspecial(void *p, Special *s)
s->next = x;
*t = s;
runtime·unlock(&span->specialLock);
- m->locks--;
+ g->m->locks--;
return true;
}
@@ -701,7 +775,7 @@ removespecial(void *p, byte kind)
// Ensure that the span is swept.
// GC accesses specials list w/o locks. And it's just much safer.
- m->locks++;
+ g->m->locks++;
runtime·MSpan_EnsureSwept(span);
offset = (uintptr)p - (span->start << PageShift);
@@ -714,13 +788,13 @@ removespecial(void *p, byte kind)
if(offset == s->offset && kind == s->kind) {
*t = s->next;
runtime·unlock(&span->specialLock);
- m->locks--;
+ g->m->locks--;
return s;
}
t = &s->next;
}
runtime·unlock(&span->specialLock);
- m->locks--;
+ g->m->locks--;
return nil;
}
@@ -733,12 +807,12 @@ runtime·addfinalizer(void *p, FuncVal *f, uintptr nret, Type *fint, PtrType *ot
runtime·lock(&runtime·mheap.speciallock);
s = runtime·FixAlloc_Alloc(&runtime·mheap.specialfinalizeralloc);
runtime·unlock(&runtime·mheap.speciallock);
- s->kind = KindSpecialFinalizer;
+ s->special.kind = KindSpecialFinalizer;
s->fn = f;
s->nret = nret;
s->fint = fint;
s->ot = ot;
- if(addspecial(p, s))
+ if(addspecial(p, &s->special))
return true;
// There was an old finalizer
@@ -764,16 +838,23 @@ runtime·removefinalizer(void *p)
// Set the heap profile bucket associated with addr to b.
void
-runtime·setprofilebucket(void *p, Bucket *b)
-{
+runtime·setprofilebucket_m(void)
+{
+ void *p;
+ Bucket *b;
SpecialProfile *s;
+
+ p = g->m->ptrarg[0];
+ b = g->m->ptrarg[1];
+ g->m->ptrarg[0] = nil;
+ g->m->ptrarg[1] = nil;
runtime·lock(&runtime·mheap.speciallock);
s = runtime·FixAlloc_Alloc(&runtime·mheap.specialprofilealloc);
runtime·unlock(&runtime·mheap.speciallock);
- s->kind = KindSpecialProfile;
+ s->special.kind = KindSpecialProfile;
s->b = b;
- if(!addspecial(p, s))
+ if(!addspecial(p, &s->special))
runtime·throw("setprofilebucket: profile already set");
}
@@ -796,7 +877,7 @@ runtime·freespecial(Special *s, void *p, uintptr size, bool freed)
return false; // don't free p until finalizer is done
case KindSpecialProfile:
sp = (SpecialProfile*)s;
- runtime·MProf_Free(sp->b, size, freed);
+ runtime·mProf_Free(sp->b, size, freed);
runtime·lock(&runtime·mheap.speciallock);
runtime·FixAlloc_Free(&runtime·mheap.specialprofilealloc, sp);
runtime·unlock(&runtime·mheap.speciallock);
@@ -806,127 +887,3 @@ runtime·freespecial(Special *s, void *p, uintptr size, bool freed)
return true;
}
}
-
-// Free all special records for p.
-void
-runtime·freeallspecials(MSpan *span, void *p, uintptr size)
-{
- Special *s, **t, *list;
- uintptr offset;
-
- if(span->sweepgen != runtime·mheap.sweepgen)
- runtime·throw("runtime: freeallspecials: unswept span");
- // first, collect all specials into the list; then, free them
- // this is required to not cause deadlock between span->specialLock and proflock
- list = nil;
- offset = (uintptr)p - (span->start << PageShift);
- runtime·lock(&span->specialLock);
- t = &span->specials;
- while((s = *t) != nil) {
- if(offset + size <= s->offset)
- break;
- if(offset <= s->offset) {
- *t = s->next;
- s->next = list;
- list = s;
- } else
- t = &s->next;
- }
- runtime·unlock(&span->specialLock);
-
- while(list != nil) {
- s = list;
- list = s->next;
- if(!runtime·freespecial(s, p, size, true))
- runtime·throw("can't explicitly free an object with a finalizer");
- }
-}
-
-// Split an allocated span into two equal parts.
-void
-runtime·MHeap_SplitSpan(MHeap *h, MSpan *s)
-{
- MSpan *t;
- MCentral *c;
- uintptr i;
- uintptr npages;
- PageID p;
-
- if(s->state != MSpanInUse)
- runtime·throw("MHeap_SplitSpan on a free span");
- if(s->sizeclass != 0 && s->ref != 1)
- runtime·throw("MHeap_SplitSpan doesn't have an allocated object");
- npages = s->npages;
-
- // remove the span from whatever list it is in now
- if(s->sizeclass > 0) {
- // must be in h->central[x].empty
- c = &h->central[s->sizeclass];
- runtime·lock(c);
- runtime·MSpanList_Remove(s);
- runtime·unlock(c);
- runtime·lock(h);
- } else {
- // must be in h->busy/busylarge
- runtime·lock(h);
- runtime·MSpanList_Remove(s);
- }
- // heap is locked now
-
- if(npages == 1) {
- // convert span of 1 PageSize object to a span of 2 PageSize/2 objects.
- s->ref = 2;
- s->sizeclass = runtime·SizeToClass(PageSize/2);
- s->elemsize = PageSize/2;
- } else {
- // convert span of n>1 pages into two spans of n/2 pages each.
- if((s->npages & 1) != 0)
- runtime·throw("MHeap_SplitSpan on an odd size span");
-
- // compute position in h->spans
- p = s->start;
- p -= (uintptr)h->arena_start >> PageShift;
-
- // Allocate a new span for the first half.
- t = runtime·FixAlloc_Alloc(&h->spanalloc);
- runtime·MSpan_Init(t, s->start, npages/2);
- t->limit = (byte*)((t->start + npages/2) << PageShift);
- t->state = MSpanInUse;
- t->elemsize = npages << (PageShift - 1);
- t->sweepgen = s->sweepgen;
- if(t->elemsize <= MaxSmallSize) {
- t->sizeclass = runtime·SizeToClass(t->elemsize);
- t->ref = 1;
- }
-
- // the old span holds the second half.
- s->start += npages/2;
- s->npages = npages/2;
- s->elemsize = npages << (PageShift - 1);
- if(s->elemsize <= MaxSmallSize) {
- s->sizeclass = runtime·SizeToClass(s->elemsize);
- s->ref = 1;
- }
-
- // update span lookup table
- for(i = p; i < p + npages/2; i++)
- h->spans[i] = t;
- }
-
- // place the span into a new list
- if(s->sizeclass > 0) {
- runtime·unlock(h);
- c = &h->central[s->sizeclass];
- runtime·lock(c);
- // swept spans are at the end of the list
- runtime·MSpanList_InsertBack(&c->empty, s);
- runtime·unlock(c);
- } else {
- // Swept spans are at the end of lists.
- if(s->npages < nelem(h->free))
- runtime·MSpanList_InsertBack(&h->busy[s->npages], s);
- else
- runtime·MSpanList_InsertBack(&h->busylarge, s);
- runtime·unlock(h);
- }
-}
diff --git a/src/pkg/runtime/mknacl.sh b/src/runtime/mknacl.sh
index 47fb7bd88..47fb7bd88 100644
--- a/src/pkg/runtime/mknacl.sh
+++ b/src/runtime/mknacl.sh
diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go
new file mode 100644
index 000000000..d409c6c30
--- /dev/null
+++ b/src/runtime/mprof.go
@@ -0,0 +1,672 @@
+// 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.
+
+// Malloc profiling.
+// Patterned after tcmalloc's algorithms; shorter code.
+
+package runtime
+
+import (
+ "unsafe"
+)
+
+// NOTE(rsc): Everything here could use cas if contention became an issue.
+var proflock mutex
+
+// All memory allocations are local and do not escape outside of the profiler.
+// The profiler is forbidden from referring to garbage-collected memory.
+
+const (
+ // profile types
+ memProfile bucketType = 1 + iota
+ blockProfile
+
+ // size of bucket hash table
+ buckHashSize = 179999
+
+ // max depth of stack to record in bucket
+ maxStack = 32
+)
+
+type bucketType int
+
+// A bucket holds per-call-stack profiling information.
+// The representation is a bit sleazy, inherited from C.
+// This struct defines the bucket header. It is followed in
+// memory by the stack words and then the actual record
+// data, either a memRecord or a blockRecord.
+//
+// Per-call-stack profiling information.
+// Lookup by hashing call stack into a linked-list hash table.
+type bucket struct {
+ next *bucket
+ allnext *bucket
+ typ bucketType // memBucket or blockBucket
+ hash uintptr
+ size uintptr
+ nstk uintptr
+}
+
+// A memRecord is the bucket data for a bucket of type memProfile,
+// part of the memory profile.
+type memRecord struct {
+ // The following complex 3-stage scheme of stats accumulation
+ // is required to obtain a consistent picture of mallocs and frees
+ // for some point in time.
+ // The problem is that mallocs come in real time, while frees
+ // come only after a GC during concurrent sweeping. So if we would
+ // naively count them, we would get a skew toward mallocs.
+ //
+ // Mallocs are accounted in recent stats.
+ // Explicit frees are accounted in recent stats.
+ // GC frees are accounted in prev stats.
+ // After GC prev stats are added to final stats and
+ // recent stats are moved into prev stats.
+ allocs uintptr
+ frees uintptr
+ alloc_bytes uintptr
+ free_bytes uintptr
+
+ // changes between next-to-last GC and last GC
+ prev_allocs uintptr
+ prev_frees uintptr
+ prev_alloc_bytes uintptr
+ prev_free_bytes uintptr
+
+ // changes since last GC
+ recent_allocs uintptr
+ recent_frees uintptr
+ recent_alloc_bytes uintptr
+ recent_free_bytes uintptr
+}
+
+// A blockRecord is the bucket data for a bucket of type blockProfile,
+// part of the blocking profile.
+type blockRecord struct {
+ count int64
+ cycles int64
+}
+
+var (
+ mbuckets *bucket // memory profile buckets
+ bbuckets *bucket // blocking profile buckets
+ buckhash *[179999]*bucket
+ bucketmem uintptr
+)
+
+// newBucket allocates a bucket with the given type and number of stack entries.
+func newBucket(typ bucketType, nstk int) *bucket {
+ size := unsafe.Sizeof(bucket{}) + uintptr(nstk)*unsafe.Sizeof(uintptr(0))
+ switch typ {
+ default:
+ gothrow("invalid profile bucket type")
+ case memProfile:
+ size += unsafe.Sizeof(memRecord{})
+ case blockProfile:
+ size += unsafe.Sizeof(blockRecord{})
+ }
+
+ b := (*bucket)(persistentalloc(size, 0, &memstats.buckhash_sys))
+ bucketmem += size
+ b.typ = typ
+ b.nstk = uintptr(nstk)
+ return b
+}
+
+// stk returns the slice in b holding the stack.
+func (b *bucket) stk() []uintptr {
+ stk := (*[maxStack]uintptr)(add(unsafe.Pointer(b), unsafe.Sizeof(*b)))
+ return stk[:b.nstk:b.nstk]
+}
+
+// mp returns the memRecord associated with the memProfile bucket b.
+func (b *bucket) mp() *memRecord {
+ if b.typ != memProfile {
+ gothrow("bad use of bucket.mp")
+ }
+ data := add(unsafe.Pointer(b), unsafe.Sizeof(*b)+b.nstk*unsafe.Sizeof(uintptr(0)))
+ return (*memRecord)(data)
+}
+
+// bp returns the blockRecord associated with the blockProfile bucket b.
+func (b *bucket) bp() *blockRecord {
+ if b.typ != blockProfile {
+ gothrow("bad use of bucket.bp")
+ }
+ data := add(unsafe.Pointer(b), unsafe.Sizeof(*b)+b.nstk*unsafe.Sizeof(uintptr(0)))
+ return (*blockRecord)(data)
+}
+
+// Return the bucket for stk[0:nstk], allocating new bucket if needed.
+func stkbucket(typ bucketType, size uintptr, stk []uintptr, alloc bool) *bucket {
+ if buckhash == nil {
+ buckhash = (*[buckHashSize]*bucket)(sysAlloc(unsafe.Sizeof(*buckhash), &memstats.buckhash_sys))
+ if buckhash == nil {
+ gothrow("runtime: cannot allocate memory")
+ }
+ }
+
+ // Hash stack.
+ var h uintptr
+ for _, pc := range stk {
+ h += pc
+ h += h << 10
+ h ^= h >> 6
+ }
+ // hash in size
+ h += size
+ h += h << 10
+ h ^= h >> 6
+ // finalize
+ h += h << 3
+ h ^= h >> 11
+
+ i := int(h % buckHashSize)
+ for b := buckhash[i]; b != nil; b = b.next {
+ if b.typ == typ && b.hash == h && b.size == size && eqslice(b.stk(), stk) {
+ return b
+ }
+ }
+
+ if !alloc {
+ return nil
+ }
+
+ // Create new bucket.
+ b := newBucket(typ, len(stk))
+ copy(b.stk(), stk)
+ b.hash = h
+ b.size = size
+ b.next = buckhash[i]
+ buckhash[i] = b
+ if typ == memProfile {
+ b.allnext = mbuckets
+ mbuckets = b
+ } else {
+ b.allnext = bbuckets
+ bbuckets = b
+ }
+ return b
+}
+
+func sysAlloc(n uintptr, stat *uint64) unsafe.Pointer
+
+func eqslice(x, y []uintptr) bool {
+ if len(x) != len(y) {
+ return false
+ }
+ for i, xi := range x {
+ if xi != y[i] {
+ return false
+ }
+ }
+ return true
+}
+
+func mprof_GC() {
+ for b := mbuckets; b != nil; b = b.allnext {
+ mp := b.mp()
+ mp.allocs += mp.prev_allocs
+ mp.frees += mp.prev_frees
+ mp.alloc_bytes += mp.prev_alloc_bytes
+ mp.free_bytes += mp.prev_free_bytes
+
+ mp.prev_allocs = mp.recent_allocs
+ mp.prev_frees = mp.recent_frees
+ mp.prev_alloc_bytes = mp.recent_alloc_bytes
+ mp.prev_free_bytes = mp.recent_free_bytes
+
+ mp.recent_allocs = 0
+ mp.recent_frees = 0
+ mp.recent_alloc_bytes = 0
+ mp.recent_free_bytes = 0
+ }
+}
+
+// Record that a gc just happened: all the 'recent' statistics are now real.
+func mProf_GC() {
+ lock(&proflock)
+ mprof_GC()
+ unlock(&proflock)
+}
+
+// Called by malloc to record a profiled block.
+func mProf_Malloc(p unsafe.Pointer, size uintptr) {
+ var stk [maxStack]uintptr
+ nstk := callers(4, &stk[0], len(stk))
+ lock(&proflock)
+ b := stkbucket(memProfile, size, stk[:nstk], true)
+ mp := b.mp()
+ mp.recent_allocs++
+ mp.recent_alloc_bytes += size
+ unlock(&proflock)
+
+ // Setprofilebucket locks a bunch of other mutexes, so we call it outside of proflock.
+ // This reduces potential contention and chances of deadlocks.
+ // Since the object must be alive during call to mProf_Malloc,
+ // it's fine to do this non-atomically.
+ setprofilebucket(p, b)
+}
+
+func setprofilebucket_m() // mheap.c
+
+func setprofilebucket(p unsafe.Pointer, b *bucket) {
+ g := getg()
+ g.m.ptrarg[0] = p
+ g.m.ptrarg[1] = unsafe.Pointer(b)
+ onM(setprofilebucket_m)
+}
+
+// Called when freeing a profiled block.
+func mProf_Free(b *bucket, size uintptr, freed bool) {
+ lock(&proflock)
+ mp := b.mp()
+ if freed {
+ mp.recent_frees++
+ mp.recent_free_bytes += size
+ } else {
+ mp.prev_frees++
+ mp.prev_free_bytes += size
+ }
+ unlock(&proflock)
+}
+
+var blockprofilerate uint64 // in CPU ticks
+
+// SetBlockProfileRate controls the fraction of goroutine blocking events
+// that are reported in the blocking profile. The profiler aims to sample
+// an average of one blocking event per rate nanoseconds spent blocked.
+//
+// To include every blocking event in the profile, pass rate = 1.
+// To turn off profiling entirely, pass rate <= 0.
+func SetBlockProfileRate(rate int) {
+ var r int64
+ if rate <= 0 {
+ r = 0 // disable profiling
+ } else if rate == 1 {
+ r = 1 // profile everything
+ } else {
+ // convert ns to cycles, use float64 to prevent overflow during multiplication
+ r = int64(float64(rate) * float64(tickspersecond()) / (1000 * 1000 * 1000))
+ if r == 0 {
+ r = 1
+ }
+ }
+
+ atomicstore64(&blockprofilerate, uint64(r))
+}
+
+func blockevent(cycles int64, skip int) {
+ if cycles <= 0 {
+ cycles = 1
+ }
+ rate := int64(atomicload64(&blockprofilerate))
+ if rate <= 0 || (rate > cycles && int64(fastrand1())%rate > cycles) {
+ return
+ }
+ gp := getg()
+ var nstk int
+ var stk [maxStack]uintptr
+ if gp.m.curg == nil || gp.m.curg == gp {
+ nstk = callers(skip, &stk[0], len(stk))
+ } else {
+ nstk = gcallers(gp.m.curg, skip, &stk[0], len(stk))
+ }
+ lock(&proflock)
+ b := stkbucket(blockProfile, 0, stk[:nstk], true)
+ b.bp().count++
+ b.bp().cycles += cycles
+ unlock(&proflock)
+}
+
+// Go interface to profile data.
+
+// A StackRecord describes a single execution stack.
+type StackRecord struct {
+ Stack0 [32]uintptr // stack trace for this record; ends at first 0 entry
+}
+
+// Stack returns the stack trace associated with the record,
+// a prefix of r.Stack0.
+func (r *StackRecord) Stack() []uintptr {
+ for i, v := range r.Stack0 {
+ if v == 0 {
+ return r.Stack0[0:i]
+ }
+ }
+ return r.Stack0[0:]
+}
+
+// MemProfileRate controls the fraction of memory allocations
+// that are recorded and reported in the memory profile.
+// The profiler aims to sample an average of
+// one allocation per MemProfileRate bytes allocated.
+//
+// To include every allocated block in the profile, set MemProfileRate to 1.
+// To turn off profiling entirely, set MemProfileRate to 0.
+//
+// The tools that process the memory profiles assume that the
+// profile rate is constant across the lifetime of the program
+// and equal to the current value. Programs that change the
+// memory profiling rate should do so just once, as early as
+// possible in the execution of the program (for example,
+// at the beginning of main).
+var MemProfileRate int = 512 * 1024
+
+// A MemProfileRecord describes the live objects allocated
+// by a particular call sequence (stack trace).
+type MemProfileRecord struct {
+ AllocBytes, FreeBytes int64 // number of bytes allocated, freed
+ AllocObjects, FreeObjects int64 // number of objects allocated, freed
+ Stack0 [32]uintptr // stack trace for this record; ends at first 0 entry
+}
+
+// InUseBytes returns the number of bytes in use (AllocBytes - FreeBytes).
+func (r *MemProfileRecord) InUseBytes() int64 { return r.AllocBytes - r.FreeBytes }
+
+// InUseObjects returns the number of objects in use (AllocObjects - FreeObjects).
+func (r *MemProfileRecord) InUseObjects() int64 {
+ return r.AllocObjects - r.FreeObjects
+}
+
+// Stack returns the stack trace associated with the record,
+// a prefix of r.Stack0.
+func (r *MemProfileRecord) Stack() []uintptr {
+ for i, v := range r.Stack0 {
+ if v == 0 {
+ return r.Stack0[0:i]
+ }
+ }
+ return r.Stack0[0:]
+}
+
+// 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.
+//
+// If inuseZero is true, the profile includes allocation records
+// where r.AllocBytes > 0 but r.AllocBytes == r.FreeBytes.
+// These are sites where memory was allocated, but it has all
+// been released back to the runtime.
+//
+// Most clients should use the runtime/pprof package or
+// the testing package's -test.memprofile flag instead
+// of calling MemProfile directly.
+func MemProfile(p []MemProfileRecord, inuseZero bool) (n int, ok bool) {
+ lock(&proflock)
+ clear := true
+ for b := mbuckets; b != nil; b = b.allnext {
+ mp := b.mp()
+ if inuseZero || mp.alloc_bytes != mp.free_bytes {
+ n++
+ }
+ if mp.allocs != 0 || mp.frees != 0 {
+ clear = false
+ }
+ }
+ if clear {
+ // Absolutely no data, suggesting that a garbage collection
+ // has not yet happened. In order to allow profiling when
+ // garbage collection is disabled from the beginning of execution,
+ // accumulate stats as if a GC just happened, and recount buckets.
+ mprof_GC()
+ mprof_GC()
+ n = 0
+ for b := mbuckets; b != nil; b = b.allnext {
+ mp := b.mp()
+ if inuseZero || mp.alloc_bytes != mp.free_bytes {
+ n++
+ }
+ }
+ }
+ if n <= len(p) {
+ ok = true
+ idx := 0
+ for b := mbuckets; b != nil; b = b.allnext {
+ mp := b.mp()
+ if inuseZero || mp.alloc_bytes != mp.free_bytes {
+ record(&p[idx], b)
+ idx++
+ }
+ }
+ }
+ unlock(&proflock)
+ return
+}
+
+// Write b's data to r.
+func record(r *MemProfileRecord, b *bucket) {
+ mp := b.mp()
+ r.AllocBytes = int64(mp.alloc_bytes)
+ r.FreeBytes = int64(mp.free_bytes)
+ r.AllocObjects = int64(mp.allocs)
+ r.FreeObjects = int64(mp.frees)
+ copy(r.Stack0[:], b.stk())
+ for i := int(b.nstk); i < len(r.Stack0); i++ {
+ r.Stack0[i] = 0
+ }
+}
+
+func iterate_memprof(fn func(*bucket, uintptr, *uintptr, uintptr, uintptr, uintptr)) {
+ lock(&proflock)
+ for b := mbuckets; b != nil; b = b.allnext {
+ mp := b.mp()
+ fn(b, uintptr(b.nstk), &b.stk()[0], b.size, mp.allocs, mp.frees)
+ }
+ unlock(&proflock)
+}
+
+// BlockProfileRecord describes blocking events originated
+// at a particular call sequence (stack trace).
+type BlockProfileRecord struct {
+ Count int64
+ Cycles int64
+ StackRecord
+}
+
+// BlockProfile returns n, the number of records in the current blocking profile.
+// If len(p) >= n, BlockProfile copies the profile into p and returns n, true.
+// If len(p) < n, BlockProfile does not change p and returns n, false.
+//
+// Most clients should use the runtime/pprof package or
+// the testing package's -test.blockprofile flag instead
+// of calling BlockProfile directly.
+func BlockProfile(p []BlockProfileRecord) (n int, ok bool) {
+ lock(&proflock)
+ for b := bbuckets; b != nil; b = b.allnext {
+ n++
+ }
+ if n <= len(p) {
+ ok = true
+ for b := bbuckets; b != nil; b = b.allnext {
+ bp := b.bp()
+ r := &p[0]
+ r.Count = int64(bp.count)
+ r.Cycles = int64(bp.cycles)
+ i := copy(r.Stack0[:], b.stk())
+ for ; i < len(r.Stack0); i++ {
+ r.Stack0[i] = 0
+ }
+ p = p[1:]
+ }
+ }
+ unlock(&proflock)
+ return
+}
+
+// ThreadCreateProfile returns n, the number of records in the thread creation profile.
+// If len(p) >= n, ThreadCreateProfile copies the profile into p and returns n, true.
+// If len(p) < n, ThreadCreateProfile does not change p and returns n, false.
+//
+// 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)))
+ for mp := first; mp != nil; mp = mp.alllink {
+ n++
+ }
+ if n <= len(p) {
+ ok = true
+ i := 0
+ for mp := first; mp != nil; mp = mp.alllink {
+ for s := range mp.createstack {
+ p[i].Stack0[s] = uintptr(mp.createstack[s])
+ }
+ i++
+ }
+ }
+ return
+}
+
+var allgs []*g // proc.c
+
+// GoroutineProfile returns n, the number of records in the active goroutine stack profile.
+// If len(p) >= n, GoroutineProfile copies the profile into p and returns n, true.
+// If len(p) < n, GoroutineProfile does not change p and returns n, false.
+//
+// Most clients should use the runtime/pprof package instead
+// of calling GoroutineProfile directly.
+func GoroutineProfile(p []StackRecord) (n int, ok bool) {
+
+ n = NumGoroutine()
+ if n <= len(p) {
+ gp := getg()
+ semacquire(&worldsema, false)
+ gp.m.gcing = 1
+ onM(stoptheworld)
+
+ n = NumGoroutine()
+ if n <= len(p) {
+ ok = true
+ r := p
+ sp := getcallersp(unsafe.Pointer(&p))
+ pc := getcallerpc(unsafe.Pointer(&p))
+ onM(func() {
+ saveg(pc, sp, gp, &r[0])
+ })
+ r = r[1:]
+ for _, gp1 := range allgs {
+ if gp1 == gp || readgstatus(gp1) == _Gdead {
+ continue
+ }
+ saveg(^uintptr(0), ^uintptr(0), gp1, &r[0])
+ r = r[1:]
+ }
+ }
+
+ gp.m.gcing = 0
+ semrelease(&worldsema)
+ onM(starttheworld)
+ }
+
+ return n, ok
+}
+
+func saveg(pc, sp uintptr, gp *g, r *StackRecord) {
+ n := gentraceback(pc, sp, 0, gp, 0, &r.Stack0[0], len(r.Stack0), nil, nil, 0)
+ if n < len(r.Stack0) {
+ r.Stack0[n] = 0
+ }
+}
+
+// Stack formats a stack trace of the calling goroutine into buf
+// and returns the number of bytes written to buf.
+// If all is true, Stack formats stack traces of all other goroutines
+// into buf after the trace for the current goroutine.
+func Stack(buf []byte, all bool) int {
+ mp := acquirem()
+ gp := mp.curg
+ if all {
+ semacquire(&worldsema, false)
+ mp.gcing = 1
+ releasem(mp)
+ onM(stoptheworld)
+ if mp != acquirem() {
+ gothrow("Stack: rescheduled")
+ }
+ }
+
+ n := 0
+ if len(buf) > 0 {
+ sp := getcallersp(unsafe.Pointer(&buf))
+ pc := getcallerpc(unsafe.Pointer(&buf))
+ onM(func() {
+ g0 := getg()
+ g0.writebuf = buf[0:0:len(buf)]
+ goroutineheader(gp)
+ traceback(pc, sp, 0, gp)
+ if all {
+ tracebackothers(gp)
+ }
+ n = len(g0.writebuf)
+ g0.writebuf = nil
+ })
+ }
+
+ if all {
+ mp.gcing = 0
+ semrelease(&worldsema)
+ onM(starttheworld)
+ }
+ releasem(mp)
+ return n
+}
+
+// Tracing of alloc/free/gc.
+
+var tracelock mutex
+
+func tracealloc(p unsafe.Pointer, size uintptr, typ *_type) {
+ lock(&tracelock)
+ gp := getg()
+ gp.m.traceback = 2
+ if typ == nil {
+ print("tracealloc(", p, ", ", hex(size), ")\n")
+ } else {
+ print("tracealloc(", p, ", ", hex(size), ", ", *typ._string, ")\n")
+ }
+ if gp.m.curg == nil || gp == gp.m.curg {
+ goroutineheader(gp)
+ pc := getcallerpc(unsafe.Pointer(&p))
+ sp := getcallersp(unsafe.Pointer(&p))
+ onM(func() {
+ traceback(pc, sp, 0, gp)
+ })
+ } else {
+ goroutineheader(gp.m.curg)
+ traceback(^uintptr(0), ^uintptr(0), 0, gp.m.curg)
+ }
+ print("\n")
+ gp.m.traceback = 0
+ unlock(&tracelock)
+}
+
+func tracefree(p unsafe.Pointer, size uintptr) {
+ lock(&tracelock)
+ gp := getg()
+ gp.m.traceback = 2
+ print("tracefree(", p, ", ", hex(size), ")\n")
+ goroutineheader(gp)
+ pc := getcallerpc(unsafe.Pointer(&p))
+ sp := getcallersp(unsafe.Pointer(&p))
+ onM(func() {
+ traceback(pc, sp, 0, gp)
+ })
+ print("\n")
+ gp.m.traceback = 0
+ unlock(&tracelock)
+}
+
+func tracegc() {
+ lock(&tracelock)
+ gp := getg()
+ gp.m.traceback = 2
+ print("tracegc()\n")
+ // running on m->g0 stack; show all non-g0 goroutines
+ tracebackothers(gp)
+ print("end tracegc\n")
+ print("\n")
+ gp.m.traceback = 0
+ unlock(&tracelock)
+}
diff --git a/src/pkg/runtime/msize.c b/src/runtime/msize.c
index 2fbd5e104..7cb65dad0 100644
--- a/src/pkg/runtime/msize.c
+++ b/src/runtime/msize.c
@@ -28,7 +28,7 @@
#include "runtime.h"
#include "arch_GOARCH.h"
#include "malloc.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#pragma dataflag NOPTR
int32 runtime·class_to_size[NumSizeClasses];
diff --git a/src/runtime/netpoll.go b/src/runtime/netpoll.go
new file mode 100644
index 000000000..3456e0208
--- /dev/null
+++ b/src/runtime/netpoll.go
@@ -0,0 +1,455 @@
+// 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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package runtime
+
+import "unsafe"
+
+// Integrated network poller (platform-independent part).
+// A particular implementation (epoll/kqueue) must define the following functions:
+// func netpollinit() // to initialize the poller
+// func netpollopen(fd uintptr, pd *pollDesc) int32 // to arm edge-triggered notifications
+// and associate fd with pd.
+// An implementation must call the following function to denote that the pd is ready.
+// func netpollready(gpp **g, pd *pollDesc, mode int32)
+
+// pollDesc contains 2 binary semaphores, rg and wg, to park reader and writer
+// goroutines respectively. The semaphore can be in the following states:
+// pdReady - io readiness notification is pending;
+// a goroutine consumes the notification by changing the state to nil.
+// pdWait - a goroutine prepares to park on the semaphore, but not yet parked;
+// the goroutine commits to park by changing the state to G pointer,
+// or, alternatively, concurrent io notification changes the state to READY,
+// or, alternatively, concurrent timeout/close changes the state to nil.
+// G pointer - the goroutine is blocked on the semaphore;
+// io notification or timeout/close changes the state to READY or nil respectively
+// and unparks the goroutine.
+// nil - nothing of the above.
+const (
+ pdReady uintptr = 1
+ pdWait uintptr = 2
+)
+
+const pollBlockSize = 4 * 1024
+
+// Network poller descriptor.
+type pollDesc struct {
+ link *pollDesc // in pollcache, protected by pollcache.lock
+
+ // The lock protects pollOpen, pollSetDeadline, pollUnblock and deadlineimpl operations.
+ // This fully covers seq, rt and wt variables. fd is constant throughout the PollDesc lifetime.
+ // pollReset, pollWait, pollWaitCanceled and runtime·netpollready (IO readiness notification)
+ // proceed w/o taking the lock. So closing, rg, rd, wg and wd are manipulated
+ // in a lock-free way by all operations.
+ // NOTE(dvyukov): the following code uses uintptr to store *g (rg/wg),
+ // that will blow up when GC starts moving objects.
+ lock mutex // protectes the following fields
+ fd uintptr
+ closing bool
+ seq uintptr // protects from stale timers and ready notifications
+ rg uintptr // pdReady, pdWait, G waiting for read or nil
+ rt timer // read deadline timer (set if rt.f != nil)
+ rd int64 // read deadline
+ wg uintptr // pdReady, pdWait, G waiting for write or nil
+ wt timer // write deadline timer
+ wd int64 // write deadline
+ user unsafe.Pointer // user settable cookie
+}
+
+type pollCache struct {
+ lock mutex
+ first *pollDesc
+ // PollDesc objects must be type-stable,
+ // because we can get ready notification from epoll/kqueue
+ // after the descriptor is closed/reused.
+ // Stale notifications are detected using seq variable,
+ // seq is incremented when deadlines are changed or descriptor is reused.
+}
+
+var pollcache pollCache
+
+func netpollServerInit() {
+ onM(netpollinit)
+}
+
+func netpollOpen(fd uintptr) (*pollDesc, int) {
+ pd := pollcache.alloc()
+ lock(&pd.lock)
+ if pd.wg != 0 && pd.wg != pdReady {
+ gothrow("netpollOpen: blocked write on free descriptor")
+ }
+ if pd.rg != 0 && pd.rg != pdReady {
+ gothrow("netpollOpen: blocked read on free descriptor")
+ }
+ pd.fd = fd
+ pd.closing = false
+ pd.seq++
+ pd.rg = 0
+ pd.rd = 0
+ pd.wg = 0
+ pd.wd = 0
+ unlock(&pd.lock)
+
+ var errno int32
+ onM(func() {
+ errno = netpollopen(fd, pd)
+ })
+ return pd, int(errno)
+}
+
+func netpollClose(pd *pollDesc) {
+ if !pd.closing {
+ gothrow("netpollClose: close w/o unblock")
+ }
+ if pd.wg != 0 && pd.wg != pdReady {
+ gothrow("netpollClose: blocked write on closing descriptor")
+ }
+ if pd.rg != 0 && pd.rg != pdReady {
+ gothrow("netpollClose: blocked read on closing descriptor")
+ }
+ onM(func() {
+ netpollclose(uintptr(pd.fd))
+ })
+ pollcache.free(pd)
+}
+
+func (c *pollCache) free(pd *pollDesc) {
+ lock(&c.lock)
+ pd.link = c.first
+ c.first = pd
+ unlock(&c.lock)
+}
+
+func netpollReset(pd *pollDesc, mode int) int {
+ err := netpollcheckerr(pd, int32(mode))
+ if err != 0 {
+ return err
+ }
+ if mode == 'r' {
+ pd.rg = 0
+ } else if mode == 'w' {
+ pd.wg = 0
+ }
+ return 0
+}
+
+func netpollWait(pd *pollDesc, mode int) int {
+ err := netpollcheckerr(pd, int32(mode))
+ if err != 0 {
+ return err
+ }
+ // As for now only Solaris uses level-triggered IO.
+ if GOOS == "solaris" {
+ onM(func() {
+ netpollarm(pd, mode)
+ })
+ }
+ for !netpollblock(pd, int32(mode), false) {
+ err = netpollcheckerr(pd, int32(mode))
+ if err != 0 {
+ return err
+ }
+ // Can happen if timeout has fired and unblocked us,
+ // but before we had a chance to run, timeout has been reset.
+ // Pretend it has not happened and retry.
+ }
+ return 0
+}
+
+func netpollWaitCanceled(pd *pollDesc, mode int) {
+ // This function is used only on windows after a failed attempt to cancel
+ // a pending async IO operation. Wait for ioready, ignore closing or timeouts.
+ for !netpollblock(pd, int32(mode), true) {
+ }
+}
+
+func netpollSetDeadline(pd *pollDesc, d int64, mode int) {
+ lock(&pd.lock)
+ if pd.closing {
+ unlock(&pd.lock)
+ return
+ }
+ pd.seq++ // invalidate current timers
+ // Reset current timers.
+ if pd.rt.f != nil {
+ deltimer(&pd.rt)
+ pd.rt.f = nil
+ }
+ if pd.wt.f != nil {
+ deltimer(&pd.wt)
+ pd.wt.f = nil
+ }
+ // Setup new timers.
+ if d != 0 && d <= nanotime() {
+ d = -1
+ }
+ if mode == 'r' || mode == 'r'+'w' {
+ pd.rd = d
+ }
+ if mode == 'w' || mode == 'r'+'w' {
+ pd.wd = d
+ }
+ if pd.rd > 0 && pd.rd == pd.wd {
+ pd.rt.f = netpollDeadline
+ pd.rt.when = pd.rd
+ // Copy current seq into the timer arg.
+ // Timer func will check the seq against current descriptor seq,
+ // if they differ the descriptor was reused or timers were reset.
+ pd.rt.arg = pd
+ pd.rt.seq = pd.seq
+ addtimer(&pd.rt)
+ } else {
+ if pd.rd > 0 {
+ pd.rt.f = netpollReadDeadline
+ pd.rt.when = pd.rd
+ pd.rt.arg = pd
+ pd.rt.seq = pd.seq
+ addtimer(&pd.rt)
+ }
+ if pd.wd > 0 {
+ pd.wt.f = netpollWriteDeadline
+ pd.wt.when = pd.wd
+ pd.wt.arg = pd
+ pd.wt.seq = pd.seq
+ addtimer(&pd.wt)
+ }
+ }
+ // If we set the new deadline in the past, unblock currently pending IO if any.
+ var rg, wg *g
+ atomicstorep(unsafe.Pointer(&wg), nil) // full memory barrier between stores to rd/wd and load of rg/wg in netpollunblock
+ if pd.rd < 0 {
+ rg = netpollunblock(pd, 'r', false)
+ }
+ if pd.wd < 0 {
+ wg = netpollunblock(pd, 'w', false)
+ }
+ unlock(&pd.lock)
+ if rg != nil {
+ goready(rg)
+ }
+ if wg != nil {
+ goready(wg)
+ }
+}
+
+func netpollUnblock(pd *pollDesc) {
+ lock(&pd.lock)
+ if pd.closing {
+ gothrow("netpollUnblock: already closing")
+ }
+ pd.closing = true
+ pd.seq++
+ var rg, wg *g
+ atomicstorep(unsafe.Pointer(&rg), nil) // full memory barrier between store to closing and read of rg/wg in netpollunblock
+ rg = netpollunblock(pd, 'r', false)
+ wg = netpollunblock(pd, 'w', false)
+ if pd.rt.f != nil {
+ deltimer(&pd.rt)
+ pd.rt.f = nil
+ }
+ if pd.wt.f != nil {
+ deltimer(&pd.wt)
+ pd.wt.f = nil
+ }
+ unlock(&pd.lock)
+ if rg != nil {
+ goready(rg)
+ }
+ if wg != nil {
+ goready(wg)
+ }
+}
+
+func netpollfd(pd *pollDesc) uintptr {
+ return pd.fd
+}
+
+func netpolluser(pd *pollDesc) *unsafe.Pointer {
+ return &pd.user
+}
+
+func netpollclosing(pd *pollDesc) bool {
+ return pd.closing
+}
+
+func netpolllock(pd *pollDesc) {
+ lock(&pd.lock)
+}
+
+func netpollunlock(pd *pollDesc) {
+ unlock(&pd.lock)
+}
+
+// make pd ready, newly runnable goroutines (if any) are returned in rg/wg
+func netpollready(gpp **g, pd *pollDesc, mode int32) {
+ var rg, wg *g
+ if mode == 'r' || mode == 'r'+'w' {
+ rg = netpollunblock(pd, 'r', true)
+ }
+ if mode == 'w' || mode == 'r'+'w' {
+ wg = netpollunblock(pd, 'w', true)
+ }
+ if rg != nil {
+ rg.schedlink = *gpp
+ *gpp = rg
+ }
+ if wg != nil {
+ wg.schedlink = *gpp
+ *gpp = wg
+ }
+}
+
+func netpollcheckerr(pd *pollDesc, mode int32) int {
+ if pd.closing {
+ return 1 // errClosing
+ }
+ if (mode == 'r' && pd.rd < 0) || (mode == 'w' && pd.wd < 0) {
+ return 2 // errTimeout
+ }
+ return 0
+}
+
+func netpollblockcommit(gp *g, gpp unsafe.Pointer) bool {
+ return casuintptr((*uintptr)(gpp), pdWait, uintptr(unsafe.Pointer(gp)))
+}
+
+// returns true if IO is ready, or false if timedout or closed
+// waitio - wait only for completed IO, ignore errors
+func netpollblock(pd *pollDesc, mode int32, waitio bool) bool {
+ gpp := &pd.rg
+ if mode == 'w' {
+ gpp = &pd.wg
+ }
+
+ // set the gpp semaphore to WAIT
+ for {
+ old := *gpp
+ if old == pdReady {
+ *gpp = 0
+ return true
+ }
+ if old != 0 {
+ gothrow("netpollblock: double wait")
+ }
+ if casuintptr(gpp, 0, pdWait) {
+ break
+ }
+ }
+
+ // need to recheck error states after setting gpp to WAIT
+ // this is necessary because runtime_pollUnblock/runtime_pollSetDeadline/deadlineimpl
+ // do the opposite: store to closing/rd/wd, membarrier, load of rg/wg
+ if waitio || netpollcheckerr(pd, mode) == 0 {
+ f := netpollblockcommit
+ gopark(**(**unsafe.Pointer)(unsafe.Pointer(&f)), unsafe.Pointer(gpp), "IO wait")
+ }
+ // be careful to not lose concurrent READY notification
+ old := xchguintptr(gpp, 0)
+ if old > pdWait {
+ gothrow("netpollblock: corrupted state")
+ }
+ return old == pdReady
+}
+
+func netpollunblock(pd *pollDesc, mode int32, ioready bool) *g {
+ gpp := &pd.rg
+ if mode == 'w' {
+ gpp = &pd.wg
+ }
+
+ for {
+ old := *gpp
+ if old == pdReady {
+ return nil
+ }
+ if old == 0 && !ioready {
+ // Only set READY for ioready. runtime_pollWait
+ // will check for timeout/cancel before waiting.
+ return nil
+ }
+ var new uintptr
+ if ioready {
+ new = pdReady
+ }
+ if casuintptr(gpp, old, new) {
+ if old == pdReady || old == pdWait {
+ old = 0
+ }
+ return (*g)(unsafe.Pointer(old))
+ }
+ }
+}
+
+func netpolldeadlineimpl(pd *pollDesc, seq uintptr, read, write bool) {
+ lock(&pd.lock)
+ // Seq arg is seq when the timer was set.
+ // If it's stale, ignore the timer event.
+ if seq != pd.seq {
+ // The descriptor was reused or timers were reset.
+ unlock(&pd.lock)
+ return
+ }
+ var rg *g
+ if read {
+ if pd.rd <= 0 || pd.rt.f == nil {
+ gothrow("netpolldeadlineimpl: inconsistent read deadline")
+ }
+ pd.rd = -1
+ atomicstorep(unsafe.Pointer(&pd.rt.f), nil) // full memory barrier between store to rd and load of rg in netpollunblock
+ rg = netpollunblock(pd, 'r', false)
+ }
+ var wg *g
+ if write {
+ if pd.wd <= 0 || pd.wt.f == nil && !read {
+ gothrow("netpolldeadlineimpl: inconsistent write deadline")
+ }
+ pd.wd = -1
+ atomicstorep(unsafe.Pointer(&pd.wt.f), nil) // full memory barrier between store to wd and load of wg in netpollunblock
+ wg = netpollunblock(pd, 'w', false)
+ }
+ unlock(&pd.lock)
+ if rg != nil {
+ goready(rg)
+ }
+ if wg != nil {
+ goready(wg)
+ }
+}
+
+func netpollDeadline(arg interface{}, seq uintptr) {
+ netpolldeadlineimpl(arg.(*pollDesc), seq, true, true)
+}
+
+func netpollReadDeadline(arg interface{}, seq uintptr) {
+ netpolldeadlineimpl(arg.(*pollDesc), seq, true, false)
+}
+
+func netpollWriteDeadline(arg interface{}, seq uintptr) {
+ netpolldeadlineimpl(arg.(*pollDesc), seq, false, true)
+}
+
+func (c *pollCache) alloc() *pollDesc {
+ lock(&c.lock)
+ if c.first == nil {
+ const pdSize = unsafe.Sizeof(pollDesc{})
+ n := pollBlockSize / pdSize
+ if n == 0 {
+ n = 1
+ }
+ // Must be in non-GC memory because can be referenced
+ // only from epoll/kqueue internals.
+ mem := persistentalloc(n*pdSize, 0, &memstats.other_sys)
+ for i := uintptr(0); i < n; i++ {
+ pd := (*pollDesc)(add(mem, i*pdSize))
+ pd.link = c.first
+ c.first = pd
+ }
+ }
+ pd := c.first
+ c.first = pd.link
+ unlock(&c.lock)
+ return pd
+}
diff --git a/src/runtime/netpoll_epoll.go b/src/runtime/netpoll_epoll.go
new file mode 100644
index 000000000..ecfc9cdde
--- /dev/null
+++ b/src/runtime/netpoll_epoll.go
@@ -0,0 +1,97 @@
+// 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 linux
+
+package runtime
+
+import "unsafe"
+
+func epollcreate(size int32) int32
+func epollcreate1(flags int32) int32
+
+//go:noescape
+func epollctl(epfd, op, fd int32, ev *epollevent) int32
+
+//go:noescape
+func epollwait(epfd int32, ev *epollevent, nev, timeout int32) int32
+func closeonexec(fd int32)
+
+var (
+ epfd int32 = -1 // epoll descriptor
+ netpolllasterr int32
+)
+
+func netpollinit() {
+ epfd = epollcreate1(_EPOLL_CLOEXEC)
+ if epfd >= 0 {
+ return
+ }
+ epfd = epollcreate(1024)
+ if epfd >= 0 {
+ closeonexec(epfd)
+ return
+ }
+ println("netpollinit: failed to create epoll descriptor", -epfd)
+ gothrow("netpollinit: failed to create descriptor")
+}
+
+func netpollopen(fd uintptr, pd *pollDesc) int32 {
+ var ev epollevent
+ ev.events = _EPOLLIN | _EPOLLOUT | _EPOLLRDHUP | _EPOLLET
+ *(**pollDesc)(unsafe.Pointer(&ev.data)) = pd
+ return -epollctl(epfd, _EPOLL_CTL_ADD, int32(fd), &ev)
+}
+
+func netpollclose(fd uintptr) int32 {
+ var ev epollevent
+ return -epollctl(epfd, _EPOLL_CTL_DEL, int32(fd), &ev)
+}
+
+func netpollarm(pd *pollDesc, mode int) {
+ gothrow("unused")
+}
+
+// polls for ready network connections
+// returns list of goroutines that become runnable
+func netpoll(block bool) (gp *g) {
+ if epfd == -1 {
+ return
+ }
+ waitms := int32(-1)
+ if !block {
+ waitms = 0
+ }
+ var events [128]epollevent
+retry:
+ n := epollwait(epfd, &events[0], int32(len(events)), waitms)
+ if n < 0 {
+ if n != -_EINTR && n != netpolllasterr {
+ netpolllasterr = n
+ println("runtime: epollwait on fd", epfd, "failed with", -n)
+ }
+ goto retry
+ }
+ for i := int32(0); i < n; i++ {
+ ev := &events[i]
+ if ev.events == 0 {
+ continue
+ }
+ var mode int32
+ if ev.events&(_EPOLLIN|_EPOLLRDHUP|_EPOLLHUP|_EPOLLERR) != 0 {
+ mode += 'r'
+ }
+ if ev.events&(_EPOLLOUT|_EPOLLHUP|_EPOLLERR) != 0 {
+ mode += 'w'
+ }
+ if mode != 0 {
+ pd := *(**pollDesc)(unsafe.Pointer(&ev.data))
+ netpollready((**g)(noescape(unsafe.Pointer(&gp))), pd, mode)
+ }
+ }
+ if block && gp == nil {
+ goto retry
+ }
+ return gp
+}
diff --git a/src/runtime/netpoll_kqueue.go b/src/runtime/netpoll_kqueue.go
new file mode 100644
index 000000000..d6d55b97b
--- /dev/null
+++ b/src/runtime/netpoll_kqueue.go
@@ -0,0 +1,101 @@
+// 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 darwin dragonfly freebsd netbsd openbsd
+
+package runtime
+
+// Integrated network poller (kqueue-based implementation).
+
+import "unsafe"
+
+func kqueue() int32
+
+//go:noescape
+func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
+func closeonexec(fd int32)
+
+var (
+ kq int32 = -1
+ netpolllasterr int32
+)
+
+func netpollinit() {
+ kq = kqueue()
+ if kq < 0 {
+ println("netpollinit: kqueue failed with", -kq)
+ gothrow("netpollinit: kqueue failed")
+ }
+ closeonexec(kq)
+}
+
+func netpollopen(fd uintptr, pd *pollDesc) int32 {
+ // Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
+ // for the whole fd lifetime. The notifications are automatically unregistered
+ // when fd is closed.
+ var ev [2]keventt
+ *(*uintptr)(unsafe.Pointer(&ev[0].ident)) = fd
+ ev[0].filter = _EVFILT_READ
+ ev[0].flags = _EV_ADD | _EV_CLEAR
+ ev[0].fflags = 0
+ ev[0].data = 0
+ ev[0].udata = (*byte)(unsafe.Pointer(pd))
+ ev[1] = ev[0]
+ ev[1].filter = _EVFILT_WRITE
+ n := kevent(kq, &ev[0], 2, nil, 0, nil)
+ if n < 0 {
+ return -n
+ }
+ return 0
+}
+
+func netpollclose(fd uintptr) int32 {
+ // Don't need to unregister because calling close()
+ // on fd will remove any kevents that reference the descriptor.
+ return 0
+}
+
+func netpollarm(pd *pollDesc, mode int) {
+ gothrow("unused")
+}
+
+// Polls for ready network connections.
+// Returns list of goroutines that become runnable.
+func netpoll(block bool) (gp *g) {
+ if kq == -1 {
+ return
+ }
+ var tp *timespec
+ var ts timespec
+ if !block {
+ tp = &ts
+ }
+ var events [64]keventt
+retry:
+ n := kevent(kq, nil, 0, &events[0], int32(len(events)), tp)
+ if n < 0 {
+ if n != -_EINTR && n != netpolllasterr {
+ netpolllasterr = n
+ println("runtime: kevent on fd", kq, "failed with", -n)
+ }
+ goto retry
+ }
+ for i := 0; i < int(n); i++ {
+ ev := &events[i]
+ var mode int32
+ if ev.filter == _EVFILT_READ {
+ mode += 'r'
+ }
+ if ev.filter == _EVFILT_WRITE {
+ mode += 'w'
+ }
+ if mode != 0 {
+ netpollready((**g)(noescape(unsafe.Pointer(&gp))), (*pollDesc)(unsafe.Pointer(ev.udata)), mode)
+ }
+ }
+ if block && gp == nil {
+ goto retry
+ }
+ return gp
+}
diff --git a/src/runtime/netpoll_nacl.go b/src/runtime/netpoll_nacl.go
new file mode 100644
index 000000000..5cbc30032
--- /dev/null
+++ b/src/runtime/netpoll_nacl.go
@@ -0,0 +1,26 @@
+// 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.
+
+// Fake network poller for NaCl.
+// Should never be used, because NaCl network connections do not honor "SetNonblock".
+
+package runtime
+
+func netpollinit() {
+}
+
+func netpollopen(fd uintptr, pd *pollDesc) int32 {
+ return 0
+}
+
+func netpollclose(fd uintptr) int32 {
+ return 0
+}
+
+func netpollarm(pd *pollDesc, mode int) {
+}
+
+func netpoll(block bool) *g {
+ return nil
+}
diff --git a/src/pkg/runtime/netpoll_solaris.c b/src/runtime/netpoll_solaris.c
index a2631a8ab..d422719cf 100644
--- a/src/pkg/runtime/netpoll_solaris.c
+++ b/src/runtime/netpoll_solaris.c
@@ -79,40 +79,36 @@ extern uintptr libc·port_associate;
extern uintptr libc·port_dissociate;
extern uintptr libc·port_getn;
-#define errno (*m->perrno)
+#define errno (*g->m->perrno)
int32
runtime·fcntl(int32 fd, int32 cmd, uintptr arg)
{
- return runtime·sysvicall6(libc·fcntl, 3,
- (uintptr)fd, (uintptr)cmd, (uintptr)arg);
+ return runtime·sysvicall3(libc·fcntl, (uintptr)fd, (uintptr)cmd, (uintptr)arg);
}
int32
runtime·port_create(void)
{
- return runtime·sysvicall6(libc·port_create, 0);
+ return runtime·sysvicall0(libc·port_create);
}
int32
runtime·port_associate(int32 port, int32 source, uintptr object, int32 events, uintptr user)
{
- return runtime·sysvicall6(libc·port_associate,
- 5, (uintptr)port, (uintptr)source, object, (uintptr)events, user);
+ return runtime·sysvicall5(libc·port_associate, (uintptr)port, (uintptr)source, object, (uintptr)events, user);
}
int32
runtime·port_dissociate(int32 port, int32 source, uintptr object)
{
- return runtime·sysvicall6(libc·port_dissociate,
- 3, (uintptr)port, (uintptr)source, object);
+ return runtime·sysvicall3(libc·port_dissociate, (uintptr)port, (uintptr)source, object);
}
int32
runtime·port_getn(int32 port, PortEvent *evs, uint32 max, uint32 *nget, Timespec *timeout)
{
- return runtime·sysvicall6(libc·port_getn, 5, (uintptr)port,
- (uintptr)evs, (uintptr)max, (uintptr)nget, (uintptr)timeout);
+ return runtime·sysvicall5(libc·port_getn, (uintptr)port, (uintptr)evs, (uintptr)max, (uintptr)nget, (uintptr)timeout);
}
static int32 portfd = -1;
diff --git a/src/pkg/runtime/netpoll_stub.c b/src/runtime/netpoll_stub.c
index b7a8f2944..b7a8f2944 100644
--- a/src/pkg/runtime/netpoll_stub.c
+++ b/src/runtime/netpoll_stub.c
diff --git a/src/pkg/runtime/netpoll_windows.c b/src/runtime/netpoll_windows.c
index f3cd15c7a..64da41ad9 100644
--- a/src/pkg/runtime/netpoll_windows.c
+++ b/src/runtime/netpoll_windows.c
@@ -47,7 +47,7 @@ static uintptr iocphandle = INVALID_HANDLE_VALUE; // completion port io handle
void
runtime·netpollinit(void)
{
- iocphandle = (uintptr)runtime·stdcall(runtime·CreateIoCompletionPort, 4, INVALID_HANDLE_VALUE, (uintptr)0, (uintptr)0, (uintptr)DWORD_MAX);
+ iocphandle = (uintptr)runtime·stdcall4(runtime·CreateIoCompletionPort, INVALID_HANDLE_VALUE, 0, 0, DWORD_MAX);
if(iocphandle == 0) {
runtime·printf("netpoll: failed to create iocp handle (errno=%d)\n", runtime·getlasterror());
runtime·throw("netpoll: failed to create iocp handle");
@@ -59,7 +59,7 @@ int32
runtime·netpollopen(uintptr fd, PollDesc *pd)
{
USED(pd);
- if(runtime·stdcall(runtime·CreateIoCompletionPort, 4, fd, iocphandle, (uintptr)0, (uintptr)0) == 0)
+ if(runtime·stdcall4(runtime·CreateIoCompletionPort, fd, iocphandle, 0, 0) == 0)
return -runtime·getlasterror();
return 0;
}
@@ -102,21 +102,21 @@ retry:
if(n < 8)
n = 8;
if(block)
- m->blocked = true;
- if(runtime·stdcall(runtime·GetQueuedCompletionStatusEx, 6, iocphandle, entries, (uintptr)n, &n, (uintptr)wait, (uintptr)0) == 0) {
- m->blocked = false;
+ g->m->blocked = true;
+ if(runtime·stdcall6(runtime·GetQueuedCompletionStatusEx, iocphandle, (uintptr)entries, n, (uintptr)&n, wait, 0) == 0) {
+ g->m->blocked = false;
errno = runtime·getlasterror();
if(!block && errno == WAIT_TIMEOUT)
return nil;
runtime·printf("netpoll: GetQueuedCompletionStatusEx failed (errno=%d)\n", errno);
runtime·throw("netpoll: GetQueuedCompletionStatusEx failed");
}
- m->blocked = false;
+ g->m->blocked = false;
for(i = 0; i < n; i++) {
op = entries[i].op;
errno = 0;
qty = 0;
- if(runtime·stdcall(runtime·WSAGetOverlappedResult, 5, runtime·netpollfd(op->pd), op, &qty, (uintptr)0, (uintptr)&flags) == 0)
+ if(runtime·stdcall5(runtime·WSAGetOverlappedResult, runtime·netpollfd(op->pd), (uintptr)op, (uintptr)&qty, 0, (uintptr)&flags) == 0)
errno = runtime·getlasterror();
handlecompletion(&gp, op, errno, qty);
}
@@ -125,9 +125,9 @@ retry:
errno = 0;
qty = 0;
if(block)
- m->blocked = true;
- if(runtime·stdcall(runtime·GetQueuedCompletionStatus, 5, iocphandle, &qty, &key, &op, (uintptr)wait) == 0) {
- m->blocked = false;
+ g->m->blocked = true;
+ if(runtime·stdcall5(runtime·GetQueuedCompletionStatus, iocphandle, (uintptr)&qty, (uintptr)&key, (uintptr)&op, wait) == 0) {
+ g->m->blocked = false;
errno = runtime·getlasterror();
if(!block && errno == WAIT_TIMEOUT)
return nil;
@@ -137,7 +137,7 @@ retry:
}
// dequeued failed IO packet, so report that
}
- m->blocked = false;
+ g->m->blocked = false;
handlecompletion(&gp, op, errno, qty);
}
if(block && gp == nil)
diff --git a/src/runtime/noasm_arm.go b/src/runtime/noasm_arm.go
new file mode 100644
index 000000000..dd3ef8267
--- /dev/null
+++ b/src/runtime/noasm_arm.go
@@ -0,0 +1,54 @@
+// 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.
+
+// Routines that are implemented in assembly in asm_{amd64,386}.s
+// but are implemented in Go for arm.
+
+package runtime
+
+func cmpstring(s1, s2 string) int {
+ l := len(s1)
+ if len(s2) < l {
+ l = len(s2)
+ }
+ for i := 0; i < l; i++ {
+ c1, c2 := s1[i], s2[i]
+ if c1 < c2 {
+ return -1
+ }
+ if c1 > c2 {
+ return +1
+ }
+ }
+ if len(s1) < len(s2) {
+ return -1
+ }
+ if len(s1) > len(s2) {
+ return +1
+ }
+ return 0
+}
+
+func cmpbytes(s1, s2 []byte) int {
+ l := len(s1)
+ if len(s2) < l {
+ l = len(s2)
+ }
+ for i := 0; i < l; i++ {
+ c1, c2 := s1[i], s2[i]
+ if c1 < c2 {
+ return -1
+ }
+ if c1 > c2 {
+ return +1
+ }
+ }
+ if len(s1) < len(s2) {
+ return -1
+ }
+ if len(s1) > len(s2) {
+ return +1
+ }
+ return 0
+}
diff --git a/src/pkg/runtime/norace_test.go b/src/runtime/norace_test.go
index 3b171877a..3b171877a 100644
--- a/src/pkg/runtime/norace_test.go
+++ b/src/runtime/norace_test.go
diff --git a/src/runtime/os_android.c b/src/runtime/os_android.c
new file mode 100644
index 000000000..5805f6871
--- /dev/null
+++ b/src/runtime/os_android.c
@@ -0,0 +1,16 @@
+// 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 "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+// Export the runtime entry point symbol.
+//
+// Used by the app package to start the Go runtime after loading
+// a shared library via JNI. See golang.org/x/mobile/app.
+
+void _rt0_arm_linux1();
+#pragma cgo_export_static _rt0_arm_linux1
+#pragma cgo_export_dynamic _rt0_arm_linux1
diff --git a/src/runtime/os_android.h b/src/runtime/os_android.h
new file mode 100644
index 000000000..c7c1098e8
--- /dev/null
+++ b/src/runtime/os_android.h
@@ -0,0 +1 @@
+#include "os_linux.h"
diff --git a/src/pkg/runtime/os_darwin.c b/src/runtime/os_darwin.c
index 33a2df958..bbd29282b 100644
--- a/src/pkg/runtime/os_darwin.c
+++ b/src/runtime/os_darwin.c
@@ -7,7 +7,7 @@
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
extern SigTab runtime·sigtab[];
@@ -22,16 +22,31 @@ unimplemented(int8 *name)
*(int32*)1231 = 1231;
}
+#pragma textflag NOSPLIT
void
runtime·semawakeup(M *mp)
{
runtime·mach_semrelease(mp->waitsema);
}
+static void
+semacreate(void)
+{
+ g->m->scalararg[0] = runtime·mach_semcreate();
+}
+
+#pragma textflag NOSPLIT
uintptr
runtime·semacreate(void)
{
- return runtime·mach_semcreate();
+ uintptr x;
+ void (*fn)(void);
+
+ fn = semacreate;
+ runtime·onM(&fn);
+ x = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+ return x;
}
// BSD interface for threading.
@@ -56,6 +71,7 @@ runtime·osinit(void)
runtime·ncpu = out;
}
+#pragma textflag NOSPLIT
void
runtime·get_random_data(byte **rnd, int32 *rnd_len)
{
@@ -119,6 +135,7 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K
+ mp->gsignal->m = mp;
}
// Called to initialize a new m (including the bootstrap m).
@@ -127,7 +144,7 @@ void
runtime·minit(void)
{
// Initialize signal handling.
- runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
+ runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024);
runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
}
@@ -142,7 +159,6 @@ runtime·unminit(void)
// Mach IPC, to get at semaphores
// Definitions are in /usr/include/mach on a Mac.
-#pragma textflag NOSPLIT
static void
macherror(int32 r, int8 *fn)
{
@@ -202,9 +218,9 @@ machcall(MachHeader *h, int32 maxsize, int32 rxsize)
uint32 port;
CodeMsg *c;
- if((port = m->machport) == 0){
+ if((port = g->m->machport) == 0){
port = runtime·mach_reply_port();
- m->machport = port;
+ g->m->machport = port;
}
h->msgh_bits |= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
@@ -397,74 +413,89 @@ int32 runtime·mach_semaphore_timedwait(uint32 sema, uint32 sec, uint32 nsec);
int32 runtime·mach_semaphore_signal(uint32 sema);
int32 runtime·mach_semaphore_signal_all(uint32 sema);
-#pragma textflag NOSPLIT
-int32
-runtime·semasleep(int64 ns)
+static void
+semasleep(void)
{
int32 r, secs, nsecs;
+ int64 ns;
+
+ ns = (int64)(uint32)g->m->scalararg[0] | (int64)(uint32)g->m->scalararg[1]<<32;
+ g->m->scalararg[0] = 0;
+ g->m->scalararg[1] = 0;
if(ns >= 0) {
secs = runtime·timediv(ns, 1000000000, &nsecs);
- r = runtime·mach_semaphore_timedwait(m->waitsema, secs, nsecs);
- if(r == KERN_ABORTED || r == KERN_OPERATION_TIMED_OUT)
- return -1;
+ r = runtime·mach_semaphore_timedwait(g->m->waitsema, secs, nsecs);
+ if(r == KERN_ABORTED || r == KERN_OPERATION_TIMED_OUT) {
+ g->m->scalararg[0] = -1;
+ return;
+ }
if(r != 0)
macherror(r, "semaphore_wait");
- return 0;
+ g->m->scalararg[0] = 0;
+ return;
}
- while((r = runtime·mach_semaphore_wait(m->waitsema)) != 0) {
+ while((r = runtime·mach_semaphore_wait(g->m->waitsema)) != 0) {
if(r == KERN_ABORTED) // interrupted
continue;
macherror(r, "semaphore_wait");
}
- return 0;
+ g->m->scalararg[0] = 0;
+ return;
}
-void
-runtime·mach_semrelease(uint32 sem)
+#pragma textflag NOSPLIT
+int32
+runtime·semasleep(int64 ns)
{
int32 r;
+ void (*fn)(void);
+
+ g->m->scalararg[0] = (uint32)ns;
+ g->m->scalararg[1] = (uint32)(ns>>32);
+ fn = semasleep;
+ runtime·onM(&fn);
+ r = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+ return r;
+}
- while((r = runtime·mach_semaphore_signal(sem)) != 0) {
- if(r == KERN_ABORTED) // interrupted
- continue;
- macherror(r, "semaphore_signal");
- }
+static int32 mach_semrelease_errno;
+
+static void
+mach_semrelease_fail(void)
+{
+ macherror(mach_semrelease_errno, "semaphore_signal");
}
+#pragma textflag NOSPLIT
void
-runtime·sigpanic(void)
+runtime·mach_semrelease(uint32 sem)
{
- if(!runtime·canpanic(g))
- runtime·throw("unexpected signal during runtime execution");
+ int32 r;
+ void (*fn)(void);
- switch(g->sig) {
- case SIGBUS:
- if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGSEGV:
- if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGFPE:
- switch(g->sigcode0) {
- case FPE_INTDIV:
- runtime·panicstring("integer divide by zero");
- case FPE_INTOVF:
- runtime·panicstring("integer overflow");
- }
- runtime·panicstring("floating point error");
+ while((r = runtime·mach_semaphore_signal(sem)) != 0) {
+ if(r == KERN_ABORTED) // interrupted
+ continue;
+
+ // mach_semrelease must be completely nosplit,
+ // because it is called from Go code.
+ // If we're going to die, start that process on the m stack
+ // to avoid a Go stack split.
+ // Only do that if we're actually running on the g stack.
+ // We might be on the gsignal stack, and if so, onM will abort.
+ // We use the global variable instead of scalararg because
+ // we might be on the gsignal stack, having interrupted a
+ // normal call to onM. It doesn't quite matter, since the
+ // program is about to die, but better to be clean.
+ mach_semrelease_errno = r;
+ fn = mach_semrelease_fail;
+ if(g == g->m->curg)
+ runtime·onM(&fn);
+ else
+ fn();
}
- runtime·panicstring(runtime·sigtab[g->sig].name);
}
#pragma textflag NOSPLIT
@@ -487,7 +518,7 @@ runtime·memlimit(void)
void
runtime·setsig(int32 i, GoSighandler *fn, bool restart)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
@@ -502,7 +533,7 @@ runtime·setsig(int32 i, GoSighandler *fn, bool restart)
GoSighandler*
runtime·getsig(int32 i)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
@@ -527,3 +558,10 @@ runtime·unblocksignals(void)
{
runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
}
+
+#pragma textflag NOSPLIT
+int8*
+runtime·signame(int32 sig)
+{
+ return runtime·sigtab[sig].name;
+}
diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go
new file mode 100644
index 000000000..4327ced91
--- /dev/null
+++ b/src/runtime/os_darwin.go
@@ -0,0 +1,24 @@
+// 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"
+
+func bsdthread_create(stk, mm, gg, fn unsafe.Pointer) int32
+func bsdthread_register() int32
+func mach_msg_trap(h unsafe.Pointer, op int32, send_size, rcv_size, rcv_name, timeout, notify uint32) int32
+func mach_reply_port() uint32
+func mach_task_self() uint32
+func mach_thread_self() uint32
+func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+func sigprocmask(sig int32, new, old unsafe.Pointer)
+func sigaction(mode uint32, new, old unsafe.Pointer)
+func sigaltstack(new, old unsafe.Pointer)
+func sigtramp()
+func setitimer(mode int32, new, old unsafe.Pointer)
+func mach_semaphore_wait(sema uint32) int32
+func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
+func mach_semaphore_signal(sema uint32) int32
+func mach_semaphore_signal_all(sema uint32) int32
diff --git a/src/pkg/runtime/os_darwin.h b/src/runtime/os_darwin.h
index 91a405f21..e8bb45daf 100644
--- a/src/pkg/runtime/os_darwin.h
+++ b/src/runtime/os_darwin.h
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define SS_DISABLE 4
-
typedef byte* kevent_udata;
int32 runtime·bsdthread_create(void*, M*, G*, void(*)(void));
@@ -25,8 +23,8 @@ typedef uint32 Sigset;
void runtime·sigprocmask(int32, Sigset*, Sigset*);
void runtime·unblocksignals(void);
-struct Sigaction;
-void runtime·sigaction(uintptr, struct Sigaction*, struct Sigaction*);
+struct SigactionT;
+void runtime·sigaction(uintptr, struct SigactionT*, struct SigactionT*);
struct StackT;
void runtime·sigaltstack(struct StackT*, struct StackT*);
@@ -35,8 +33,11 @@ void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
-#define NSIG 32
-#define SI_USER 0 /* empirically true, but not what headers say */
-#define SIG_BLOCK 1
-#define SIG_UNBLOCK 2
-#define SIG_SETMASK 3
+enum {
+ NSIG = 32,
+ SI_USER = 0, /* empirically true, but not what headers say */
+ SIG_BLOCK = 1,
+ SIG_UNBLOCK = 2,
+ SIG_SETMASK = 3,
+ SS_DISABLE = 4,
+};
diff --git a/src/pkg/runtime/os_dragonfly.c b/src/runtime/os_dragonfly.c
index e7fd2cc06..e372205ec 100644
--- a/src/pkg/runtime/os_dragonfly.c
+++ b/src/runtime/os_dragonfly.c
@@ -7,7 +7,7 @@
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
extern SigTab runtime·sigtab[];
extern int32 runtime·sys_umtx_sleep(uint32*, int32, int32);
@@ -40,13 +40,38 @@ getncpu(void)
return 1;
}
+static void futexsleep(void);
+
#pragma textflag NOSPLIT
void
runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
{
+ void (*fn)(void);
+
+ g->m->ptrarg[0] = addr;
+ g->m->scalararg[0] = val;
+ g->m->ptrarg[1] = &ns;
+
+ fn = futexsleep;
+ runtime·onM(&fn);
+}
+
+static void
+futexsleep(void)
+{
+ uint32 *addr;
+ uint32 val;
+ int64 ns;
int32 timeout = 0;
int32 ret;
+ addr = g->m->ptrarg[0];
+ val = g->m->scalararg[0];
+ ns = *(int64*)g->m->ptrarg[1];
+ g->m->ptrarg[0] = nil;
+ g->m->scalararg[0] = 0;
+ g->m->ptrarg[1] = nil;
+
if(ns >= 0) {
// The timeout is specified in microseconds - ensure that we
// do not end up dividing to zero, which would put us to sleep
@@ -72,19 +97,40 @@ runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
*(int32*)0x1005 = 0x1005;
}
+static void badfutexwakeup(void);
+
+#pragma textflag NOSPLIT
void
runtime·futexwakeup(uint32 *addr, uint32 cnt)
{
int32 ret;
+ void (*fn)(void);
ret = runtime·sys_umtx_wakeup(addr, cnt);
if(ret >= 0)
return;
- runtime·printf("umtx_wake addr=%p ret=%d\n", addr, ret);
+ g->m->ptrarg[0] = addr;
+ g->m->scalararg[0] = ret;
+ fn = badfutexwakeup;
+ if(g == g->m->gsignal)
+ fn();
+ else
+ runtime·onM(&fn);
*(int32*)0x1006 = 0x1006;
}
+static void
+badfutexwakeup(void)
+{
+ void *addr;
+ int32 ret;
+
+ addr = g->m->ptrarg[0];
+ ret = g->m->scalararg[0];
+ runtime·printf("umtx_wake addr=%p ret=%d\n", addr, ret);
+}
+
void runtime·lwp_start(void*);
void
@@ -119,6 +165,7 @@ runtime·osinit(void)
runtime·ncpu = getncpu();
}
+#pragma textflag NOSPLIT
void
runtime·get_random_data(byte **rnd, int32 *rnd_len)
{
@@ -148,6 +195,7 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024);
+ mp->gsignal->m = mp;
}
// Called to initialize a new m (including the bootstrap m).
@@ -156,7 +204,7 @@ void
runtime·minit(void)
{
// Initialize signal handling
- runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
+ runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024);
runtime·sigprocmask(&sigset_none, nil);
}
@@ -167,46 +215,11 @@ runtime·unminit(void)
runtime·signalstack(nil, 0);
}
-void
-runtime·sigpanic(void)
-{
- if(!runtime·canpanic(g))
- runtime·throw("unexpected signal during runtime execution");
-
- switch(g->sig) {
- case SIGBUS:
- if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGSEGV:
- if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGFPE:
- switch(g->sigcode0) {
- case FPE_INTDIV:
- runtime·panicstring("integer divide by zero");
- case FPE_INTOVF:
- runtime·panicstring("integer overflow");
- }
- runtime·panicstring("floating point error");
- }
- runtime·panicstring(runtime·sigtab[g->sig].name);
-}
-
uintptr
runtime·memlimit(void)
{
Rlimit rl;
- extern byte text[], end[];
+ extern byte runtime·text[], runtime·end[];
uintptr used;
if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
@@ -217,7 +230,7 @@ runtime·memlimit(void)
// Estimate our VM footprint excluding the heap.
// Not an exact science: use size of binary plus
// some room for thread stacks.
- used = end - text + (64<<20);
+ used = runtime·end - runtime·text + (64<<20);
if(used >= rl.rlim_cur)
return 0;
@@ -239,12 +252,12 @@ typedef struct sigaction {
} __sigaction_u; /* signal handler */
int32 sa_flags; /* see signal options below */
Sigset sa_mask; /* signal mask to apply */
-} Sigaction;
+} SigactionT;
void
runtime·setsig(int32 i, GoSighandler *fn, bool restart)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
@@ -263,7 +276,7 @@ runtime·setsig(int32 i, GoSighandler *fn, bool restart)
GoSighandler*
runtime·getsig(int32 i)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
@@ -290,3 +303,10 @@ runtime·unblocksignals(void)
{
runtime·sigprocmask(&sigset_none, nil);
}
+
+#pragma textflag NOSPLIT
+int8*
+runtime·signame(int32 sig)
+{
+ return runtime·sigtab[sig].name;
+}
diff --git a/src/runtime/os_dragonfly.go b/src/runtime/os_dragonfly.go
new file mode 100644
index 000000000..cdaa06986
--- /dev/null
+++ b/src/runtime/os_dragonfly.go
@@ -0,0 +1,20 @@
+// 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"
+
+func lwp_create(param unsafe.Pointer) int32
+func sigaltstack(new, old unsafe.Pointer)
+func sigaction(sig int32, new, old unsafe.Pointer)
+func sigprocmask(new, old unsafe.Pointer)
+func setitimer(mode int32, new, old unsafe.Pointer)
+func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+func getrlimit(kind int32, limit unsafe.Pointer) int32
+func raise(sig int32)
+func sys_umtx_sleep(addr unsafe.Pointer, val, timeout int32) int32
+func sys_umtx_wakeup(addr unsafe.Pointer, val int32) int32
+
+const stackSystem = 0
diff --git a/src/pkg/runtime/os_dragonfly.h b/src/runtime/os_dragonfly.h
index fddeede85..389736a32 100644
--- a/src/pkg/runtime/os_dragonfly.h
+++ b/src/runtime/os_dragonfly.h
@@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define SS_DISABLE 4
typedef byte* kevent_udata;
int32 runtime·lwp_create(Lwpparams*);
void runtime·sigpanic(void);
-void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
+void runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
struct sigaction;
void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
void runtime·sigprocmask(Sigset *, Sigset *);
@@ -16,11 +15,13 @@ void runtime·unblocksignals(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
+enum {
+ NSIG = 33,
+ SI_USER = 0x10001,
+ SS_DISABLE = 4,
+ RLIMIT_AS = 10,
+};
-#define NSIG 33
-#define SI_USER 0x10001
-
-#define RLIMIT_AS 10
typedef struct Rlimit Rlimit;
struct Rlimit {
int64 rlim_cur;
diff --git a/src/pkg/runtime/os_freebsd.c b/src/runtime/os_freebsd.c
index 02b13472c..a513cb604 100644
--- a/src/pkg/runtime/os_freebsd.c
+++ b/src/runtime/os_freebsd.c
@@ -7,7 +7,7 @@
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
extern SigTab runtime·sigtab[];
extern int32 runtime·sys_umtx_op(uint32*, int32, uint32, void*, void*);
@@ -42,12 +42,37 @@ getncpu(void)
// FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
// thus the code is largely similar. See linux/thread.c and lock_futex.c for comments.
+static void futexsleep(void);
+
#pragma textflag NOSPLIT
void
runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
{
+ void (*fn)(void);
+
+ g->m->ptrarg[0] = addr;
+ g->m->scalararg[0] = val;
+ g->m->ptrarg[1] = &ns;
+
+ fn = futexsleep;
+ runtime·onM(&fn);
+}
+
+static void
+futexsleep(void)
+{
+ uint32 *addr;
+ uint32 val;
+ int64 ns;
int32 ret;
Timespec ts;
+
+ addr = g->m->ptrarg[0];
+ val = g->m->scalararg[0];
+ ns = *(int64*)g->m->ptrarg[1];
+ g->m->ptrarg[0] = nil;
+ g->m->scalararg[0] = 0;
+ g->m->ptrarg[1] = nil;
if(ns < 0) {
ret = runtime·sys_umtx_op(addr, UMTX_OP_WAIT_UINT_PRIVATE, val, nil, nil);
@@ -73,19 +98,40 @@ fail:
*(int32*)0x1005 = 0x1005;
}
+static void badfutexwakeup(void);
+
+#pragma textflag NOSPLIT
void
runtime·futexwakeup(uint32 *addr, uint32 cnt)
{
int32 ret;
+ void (*fn)(void);
ret = runtime·sys_umtx_op(addr, UMTX_OP_WAKE_PRIVATE, cnt, nil, nil);
if(ret >= 0)
return;
- runtime·printf("umtx_wake addr=%p ret=%d\n", addr, ret);
+ g->m->ptrarg[0] = addr;
+ g->m->scalararg[0] = ret;
+ fn = badfutexwakeup;
+ if(g == g->m->gsignal)
+ fn();
+ else
+ runtime·onM(&fn);
*(int32*)0x1006 = 0x1006;
}
+static void
+badfutexwakeup(void)
+{
+ void *addr;
+ int32 ret;
+
+ addr = g->m->ptrarg[0];
+ ret = g->m->scalararg[0];
+ runtime·printf("umtx_wake addr=%p ret=%d\n", addr, ret);
+}
+
void runtime·thr_start(void*);
void
@@ -107,10 +153,10 @@ runtime·newosproc(M *mp, void *stk)
// NOTE(rsc): This code is confused. stackbase is the top of the stack
// and is equal to stk. However, it's working, so I'm not changing it.
- param.stack_base = (void*)mp->g0->stackbase;
- param.stack_size = (byte*)stk - (byte*)mp->g0->stackbase;
+ param.stack_base = (void*)mp->g0->stack.hi;
+ param.stack_size = (byte*)stk - (byte*)mp->g0->stack.hi;
- param.child_tid = (intptr*)&mp->procid;
+ param.child_tid = (void*)&mp->procid;
param.parent_tid = nil;
param.tls_base = (void*)&mp->tls[0];
param.tls_size = sizeof mp->tls;
@@ -127,6 +173,7 @@ runtime·osinit(void)
runtime·ncpu = getncpu();
}
+#pragma textflag NOSPLIT
void
runtime·get_random_data(byte **rnd, int32 *rnd_len)
{
@@ -156,6 +203,7 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024);
+ mp->gsignal->m = mp;
}
// Called to initialize a new m (including the bootstrap m).
@@ -164,7 +212,7 @@ void
runtime·minit(void)
{
// Initialize signal handling
- runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
+ runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024);
runtime·sigprocmask(&sigset_none, nil);
}
@@ -175,46 +223,11 @@ runtime·unminit(void)
runtime·signalstack(nil, 0);
}
-void
-runtime·sigpanic(void)
-{
- if(!runtime·canpanic(g))
- runtime·throw("unexpected signal during runtime execution");
-
- switch(g->sig) {
- case SIGBUS:
- if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGSEGV:
- if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGFPE:
- switch(g->sigcode0) {
- case FPE_INTDIV:
- runtime·panicstring("integer divide by zero");
- case FPE_INTOVF:
- runtime·panicstring("integer overflow");
- }
- runtime·panicstring("floating point error");
- }
- runtime·panicstring(runtime·sigtab[g->sig].name);
-}
-
uintptr
runtime·memlimit(void)
{
Rlimit rl;
- extern byte text[], end[];
+ extern byte runtime·text[], runtime·end[];
uintptr used;
if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
@@ -225,7 +238,7 @@ runtime·memlimit(void)
// Estimate our VM footprint excluding the heap.
// Not an exact science: use size of binary plus
// some room for thread stacks.
- used = end - text + (64<<20);
+ used = runtime·end - runtime·text + (64<<20);
if(used >= rl.rlim_cur)
return 0;
@@ -247,12 +260,12 @@ typedef struct sigaction {
} __sigaction_u; /* signal handler */
int32 sa_flags; /* see signal options below */
Sigset sa_mask; /* signal mask to apply */
-} Sigaction;
+} SigactionT;
void
runtime·setsig(int32 i, GoSighandler *fn, bool restart)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
@@ -271,7 +284,7 @@ runtime·setsig(int32 i, GoSighandler *fn, bool restart)
GoSighandler*
runtime·getsig(int32 i)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
@@ -298,3 +311,10 @@ runtime·unblocksignals(void)
{
runtime·sigprocmask(&sigset_none, nil);
}
+
+#pragma textflag NOSPLIT
+int8*
+runtime·signame(int32 sig)
+{
+ return runtime·sigtab[sig].name;
+}
diff --git a/src/runtime/os_freebsd.go b/src/runtime/os_freebsd.go
new file mode 100644
index 000000000..59708049c
--- /dev/null
+++ b/src/runtime/os_freebsd.go
@@ -0,0 +1,17 @@
+// 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"
+
+func thr_new(param unsafe.Pointer, size int32)
+func sigaltstack(new, old unsafe.Pointer)
+func sigaction(sig int32, new, old unsafe.Pointer)
+func sigprocmask(new, old unsafe.Pointer)
+func setitimer(mode int32, new, old unsafe.Pointer)
+func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+func getrlimit(kind int32, limit unsafe.Pointer) int32
+func raise(sig int32)
+func sys_umtx_op(addr unsafe.Pointer, mode int32, val uint32, ptr2, ts unsafe.Pointer) int32
diff --git a/src/pkg/runtime/os_freebsd.h b/src/runtime/os_freebsd.h
index 4b2c25330..b86bb393c 100644
--- a/src/pkg/runtime/os_freebsd.h
+++ b/src/runtime/os_freebsd.h
@@ -2,13 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define SS_DISABLE 4
-
typedef byte* kevent_udata;
int32 runtime·thr_new(ThrParam*, int32);
void runtime·sigpanic(void);
-void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
+void runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
struct sigaction;
void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
void runtime·sigprocmask(Sigset *, Sigset *);
@@ -16,11 +14,13 @@ void runtime·unblocksignals(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
+enum {
+ SS_DISABLE = 4,
+ NSIG = 33,
+ SI_USER = 0x10001,
+ RLIMIT_AS = 10,
+};
-#define NSIG 33
-#define SI_USER 0x10001
-
-#define RLIMIT_AS 10
typedef struct Rlimit Rlimit;
struct Rlimit {
int64 rlim_cur;
diff --git a/src/pkg/runtime/os_freebsd_arm.c b/src/runtime/os_freebsd_arm.c
index 1fa235b01..2f2d7767f 100644
--- a/src/pkg/runtime/os_freebsd_arm.c
+++ b/src/runtime/os_freebsd_arm.c
@@ -5,7 +5,7 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
void
runtime·checkgoarm(void)
diff --git a/src/pkg/runtime/os_linux.c b/src/runtime/os_linux.c
index 8a945242b..0d8ffc995 100644
--- a/src/pkg/runtime/os_linux.c
+++ b/src/runtime/os_linux.c
@@ -7,7 +7,7 @@
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
extern SigTab runtime·sigtab[];
@@ -55,24 +55,44 @@ runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
runtime·futex(addr, FUTEX_WAIT, val, &ts, nil, 0);
}
+static void badfutexwakeup(void);
+
// If any procs are sleeping on addr, wake up at most cnt.
+#pragma textflag NOSPLIT
void
runtime·futexwakeup(uint32 *addr, uint32 cnt)
{
int64 ret;
+ void (*fn)(void);
ret = runtime·futex(addr, FUTEX_WAKE, cnt, nil, nil, 0);
-
if(ret >= 0)
return;
// I don't know that futex wakeup can return
// EAGAIN or EINTR, but if it does, it would be
// safe to loop and call futex again.
- runtime·printf("futexwakeup addr=%p returned %D\n", addr, ret);
+ g->m->ptrarg[0] = addr;
+ g->m->scalararg[0] = (int32)ret; // truncated but fine
+ fn = badfutexwakeup;
+ if(g == g->m->gsignal)
+ fn();
+ else
+ runtime·onM(&fn);
*(int32*)0x1006 = 0x1006;
}
+static void
+badfutexwakeup(void)
+{
+ void *addr;
+ int64 ret;
+
+ addr = g->m->ptrarg[0];
+ ret = (int32)g->m->scalararg[0];
+ runtime·printf("futexwakeup addr=%p returned %D\n", addr, ret);
+}
+
extern runtime·sched_getaffinity(uintptr pid, uintptr len, uintptr *buf);
static int32
getproccount(void)
@@ -162,6 +182,7 @@ runtime·osinit(void)
byte* runtime·startup_random_data;
uint32 runtime·startup_random_data_len;
+#pragma textflag NOSPLIT
void
runtime·get_random_data(byte **rnd, int32 *rnd_len)
{
@@ -196,6 +217,7 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K
+ mp->gsignal->m = mp;
}
// Called to initialize a new m (including the bootstrap m).
@@ -204,7 +226,7 @@ void
runtime·minit(void)
{
// Initialize signal handling.
- runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
+ runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024);
runtime·rtsigprocmask(SIG_SETMASK, &sigset_none, nil, sizeof(Sigset));
}
@@ -215,46 +237,11 @@ runtime·unminit(void)
runtime·signalstack(nil, 0);
}
-void
-runtime·sigpanic(void)
-{
- if(!runtime·canpanic(g))
- runtime·throw("unexpected signal during runtime execution");
-
- switch(g->sig) {
- case SIGBUS:
- if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGSEGV:
- if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGFPE:
- switch(g->sigcode0) {
- case FPE_INTDIV:
- runtime·panicstring("integer divide by zero");
- case FPE_INTOVF:
- runtime·panicstring("integer overflow");
- }
- runtime·panicstring("floating point error");
- }
- runtime·panicstring(runtime·sigtab[g->sig].name);
-}
-
uintptr
runtime·memlimit(void)
{
Rlimit rl;
- extern byte text[], end[];
+ extern byte runtime·text[], runtime·end[];
uintptr used;
if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
@@ -265,7 +252,7 @@ runtime·memlimit(void)
// Estimate our VM footprint excluding the heap.
// Not an exact science: use size of binary plus
// some room for thread stacks.
- used = end - text + (64<<20);
+ used = runtime·end - runtime·text + (64<<20);
if(used >= rl.rlim_cur)
return 0;
@@ -287,21 +274,27 @@ runtime·memlimit(void)
* and calls sighandler().
*/
extern void runtime·sigtramp(void);
-extern void runtime·sigreturn(void); // calls runtime·sigreturn
+extern void runtime·sigreturn(void); // calls rt_sigreturn, only used with SA_RESTORER
void
runtime·setsig(int32 i, GoSighandler *fn, bool restart)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask = ~0ULL;
- // TODO(adonovan): Linux manpage says "sa_restorer element is
- // obsolete and should not be used". Avoid it here, and test.
+ // Although Linux manpage says "sa_restorer element is obsolete and
+ // should not be used". x86_64 kernel requires it. Only use it on
+ // x86.
+#ifdef GOARCH_386
sa.sa_restorer = (void*)runtime·sigreturn;
+#endif
+#ifdef GOARCH_amd64
+ sa.sa_restorer = (void*)runtime·sigreturn;
+#endif
if(fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.sa_handler = fn;
@@ -312,7 +305,7 @@ runtime·setsig(int32 i, GoSighandler *fn, bool restart)
GoSighandler*
runtime·getsig(int32 i)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
@@ -325,7 +318,7 @@ runtime·getsig(int32 i)
void
runtime·signalstack(byte *p, int32 n)
{
- Sigaltstack st;
+ SigaltstackT st;
st.ss_sp = p;
st.ss_size = n;
@@ -340,3 +333,10 @@ runtime·unblocksignals(void)
{
runtime·rtsigprocmask(SIG_SETMASK, &sigset_none, nil, sizeof sigset_none);
}
+
+#pragma textflag NOSPLIT
+int8*
+runtime·signame(int32 sig)
+{
+ return runtime·sigtab[sig].name;
+}
diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go
new file mode 100644
index 000000000..41123ad57
--- /dev/null
+++ b/src/runtime/os_linux.go
@@ -0,0 +1,17 @@
+// 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"
+
+func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32
+func clone(flags int32, stk, mm, gg, fn unsafe.Pointer) int32
+func rt_sigaction(sig uintptr, new, old unsafe.Pointer, size uintptr) int32
+func sigaltstack(new, old unsafe.Pointer)
+func setitimer(mode int32, new, old unsafe.Pointer)
+func rtsigprocmask(sig int32, new, old unsafe.Pointer, size int32)
+func getrlimit(kind int32, limit unsafe.Pointer) int32
+func raise(sig int32)
+func sched_getaffinity(pid, len uintptr, buf *uintptr) int32
diff --git a/src/pkg/runtime/os_linux.h b/src/runtime/os_linux.h
index d4b1902c3..75606d615 100644
--- a/src/pkg/runtime/os_linux.h
+++ b/src/runtime/os_linux.h
@@ -2,22 +2,25 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define SS_DISABLE 2
// Linux-specific system calls
int32 runtime·futex(uint32*, int32, uint32, Timespec*, uint32*, uint32);
int32 runtime·clone(int32, void*, M*, G*, void(*)(void));
-struct Sigaction;
-int32 runtime·rt_sigaction(uintptr, struct Sigaction*, void*, uintptr);
+struct SigactionT;
+int32 runtime·rt_sigaction(uintptr, struct SigactionT*, void*, uintptr);
-void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
+void runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
-
-#define NSIG 65
-#define SI_USER 0
+enum {
+ SS_DISABLE = 2,
+ NSIG = 65,
+ SI_USER = 0,
+ 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
@@ -29,9 +32,7 @@ struct Sigset
};
void runtime·rtsigprocmask(int32, Sigset*, Sigset*, int32);
void runtime·unblocksignals(void);
-#define SIG_SETMASK 2
-#define RLIMIT_AS 9
typedef struct Rlimit Rlimit;
struct Rlimit {
uintptr rlim_cur;
diff --git a/src/pkg/runtime/os_linux_386.c b/src/runtime/os_linux_386.c
index ad7281464..dc89d04e2 100644
--- a/src/pkg/runtime/os_linux_386.c
+++ b/src/runtime/os_linux_386.c
@@ -5,7 +5,7 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#define AT_NULL 0
#define AT_RANDOM 25
diff --git a/src/pkg/runtime/os_linux_arm.c b/src/runtime/os_linux_arm.c
index aad08b989..e3eda7c2d 100644
--- a/src/pkg/runtime/os_linux_arm.c
+++ b/src/runtime/os_linux_arm.c
@@ -5,7 +5,7 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#define AT_NULL 0
#define AT_PLATFORM 15 // introduced in at least 2.6.11
diff --git a/src/pkg/runtime/os_nacl.c b/src/runtime/os_nacl.c
index 3196e2ce3..14b558303 100644
--- a/src/pkg/runtime/os_nacl.c
+++ b/src/runtime/os_nacl.c
@@ -6,7 +6,7 @@
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "arch_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#include "stack.h"
int8 *goos = "nacl";
@@ -20,6 +20,7 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K
+ mp->gsignal->m = mp;
}
// Called to initialize a new m (including the bootstrap m).
@@ -30,7 +31,7 @@ runtime·minit(void)
int32 ret;
// Initialize signal handling
- ret = runtime·nacl_exception_stack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
+ ret = runtime·nacl_exception_stack((byte*)g->m->gsignal->stack.lo, 32*1024);
if(ret < 0)
runtime·printf("runtime: nacl_exception_stack: error %d\n", -ret);
@@ -54,7 +55,7 @@ void
runtime·osinit(void)
{
runtime·ncpu = 1;
- m->procid = 2;
+ g->m->procid = 2;
//runtime·nacl_exception_handler(runtime·sigtramp, nil);
}
@@ -64,6 +65,7 @@ runtime·crash(void)
*(int32*)0 = 0;
}
+#pragma textflag NOSPLIT
void
runtime·get_random_data(byte **rnd, int32 *rnd_len)
{
@@ -111,8 +113,8 @@ runtime·newosproc(M *mp, void *stk)
}
}
-uintptr
-runtime·semacreate(void)
+static void
+semacreate(void)
{
int32 mu, cond;
@@ -126,30 +128,49 @@ runtime·semacreate(void)
runtime·printf("nacl_cond_create: error %d\n", -cond);
runtime·throw("semacreate");
}
- m->waitsemalock = mu;
- return cond; // assigned to m->waitsema
+ g->m->waitsemalock = mu;
+ g->m->scalararg[0] = cond; // assigned to m->waitsema
}
#pragma textflag NOSPLIT
-int32
-runtime·semasleep(int64 ns)
+uint32
+runtime·semacreate(void)
+{
+ void (*fn)(void);
+ uint32 x;
+
+ fn = semacreate;
+ runtime·onM(&fn);
+ x = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+ return x;
+}
+
+static void
+semasleep(void)
{
int32 ret;
+ int64 ns;
+
+ ns = (int64)(uint32)g->m->scalararg[0] | (int64)(uint32)g->m->scalararg[1]<<32;
+ g->m->scalararg[0] = 0;
+ g->m->scalararg[1] = 0;
- ret = runtime·nacl_mutex_lock(m->waitsemalock);
+ ret = runtime·nacl_mutex_lock(g->m->waitsemalock);
if(ret < 0) {
//runtime·printf("nacl_mutex_lock: error %d\n", -ret);
runtime·throw("semasleep");
}
- if(m->waitsemacount > 0) {
- m->waitsemacount = 0;
- runtime·nacl_mutex_unlock(m->waitsemalock);
- return 0;
+ if(g->m->waitsemacount > 0) {
+ g->m->waitsemacount = 0;
+ runtime·nacl_mutex_unlock(g->m->waitsemalock);
+ g->m->scalararg[0] = 0;
+ return;
}
- while(m->waitsemacount == 0) {
+ while(g->m->waitsemacount == 0) {
if(ns < 0) {
- ret = runtime·nacl_cond_wait(m->waitsema, m->waitsemalock);
+ ret = runtime·nacl_cond_wait(g->m->waitsema, g->m->waitsemalock);
if(ret < 0) {
//runtime·printf("nacl_cond_wait: error %d\n", -ret);
runtime·throw("semasleep");
@@ -159,10 +180,11 @@ runtime·semasleep(int64 ns)
ns += runtime·nanotime();
ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
- ret = runtime·nacl_cond_timed_wait_abs(m->waitsema, m->waitsemalock, &ts);
+ ret = runtime·nacl_cond_timed_wait_abs(g->m->waitsema, g->m->waitsemalock, &ts);
if(ret == -ETIMEDOUT) {
- runtime·nacl_mutex_unlock(m->waitsemalock);
- return -1;
+ runtime·nacl_mutex_unlock(g->m->waitsemalock);
+ g->m->scalararg[0] = -1;
+ return;
}
if(ret < 0) {
//runtime·printf("nacl_cond_timed_wait_abs: error %d\n", -ret);
@@ -171,16 +193,36 @@ runtime·semasleep(int64 ns)
}
}
- m->waitsemacount = 0;
- runtime·nacl_mutex_unlock(m->waitsemalock);
- return 0;
+ g->m->waitsemacount = 0;
+ runtime·nacl_mutex_unlock(g->m->waitsemalock);
+ g->m->scalararg[0] = 0;
}
-void
-runtime·semawakeup(M *mp)
+#pragma textflag NOSPLIT
+int32
+runtime·semasleep(int64 ns)
+{
+ int32 r;
+ void (*fn)(void);
+
+ g->m->scalararg[0] = (uint32)ns;
+ g->m->scalararg[1] = (uint32)(ns>>32);
+ fn = semasleep;
+ runtime·onM(&fn);
+ r = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+ return r;
+}
+
+static void
+semawakeup(void)
{
int32 ret;
+ M *mp;
+ mp = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+
ret = runtime·nacl_mutex_lock(mp->waitsemalock);
if(ret < 0) {
//runtime·printf("nacl_mutex_lock: error %d\n", -ret);
@@ -195,10 +237,15 @@ runtime·semawakeup(M *mp)
runtime·nacl_mutex_unlock(mp->waitsemalock);
}
+#pragma textflag NOSPLIT
void
-os·sigpipe(void)
+runtime·semawakeup(M *mp)
{
- runtime·throw("too many writes on closed pipe");
+ void (*fn)(void);
+
+ g->m->ptrarg[0] = mp;
+ fn = semawakeup;
+ runtime·onM(&fn);
}
uintptr
@@ -244,19 +291,6 @@ runtime·closeonexec(int32)
{
}
-void
-runtime·sigpanic(void)
-{
- if(!runtime·canpanic(g))
- runtime·throw("unexpected signal during runtime execution");
-
- // Native Client only invokes the exception handler for memory faults.
- g->sig = SIGSEGV;
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
-}
-
uint32 runtime·writelock; // test-and-set spin lock for runtime.write
/*
@@ -275,4 +309,4 @@ int32 runtime·nacl_irt_memory_v0_3_size = sizeof(runtime·nacl_irt_memory_v0_3)
int8 runtime·nacl_irt_thread_v0_1_str[] = "nacl-irt-thread-0.1";
void *runtime·nacl_irt_thread_v0_1[3]; // thread_create, thread_exit, thread_nice
int32 runtime·nacl_irt_thread_v0_1_size = sizeof(runtime·nacl_irt_thread_v0_1);
-*/ \ No newline at end of file
+*/
diff --git a/src/runtime/os_nacl.go b/src/runtime/os_nacl.go
new file mode 100644
index 000000000..8dd43ff06
--- /dev/null
+++ b/src/runtime/os_nacl.go
@@ -0,0 +1,39 @@
+// 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"
+
+func nacl_exception_stack(p unsafe.Pointer, size int32) int32
+func nacl_exception_handler(fn, arg unsafe.Pointer) int32
+func nacl_sem_create(flag int32) int32
+func nacl_sem_wait(sem int32) int32
+func nacl_sem_post(sem int32) int32
+func nacl_mutex_create(flag int32) int32
+func nacl_mutex_lock(mutex int32) int32
+func nacl_mutex_trylock(mutex int32) int32
+func nacl_mutex_unlock(mutex int32) int32
+func nacl_cond_create(flag int32) int32
+func nacl_cond_wait(cond, n int32) int32
+func nacl_cond_signal(cond int32) int32
+func nacl_cond_broadcast(cond int32) int32
+func nacl_cond_timed_wait_abs(cond, lock int32, ts unsafe.Pointer) int32
+func nacl_thread_create(fn, stk, tls, xx unsafe.Pointer) int32
+func nacl_nanosleep(ts, extra unsafe.Pointer) int32
+
+func os_sigpipe() {
+ gothrow("too many writes on closed pipe")
+}
+
+func sigpanic() {
+ g := getg()
+ if !canpanic(g) {
+ gothrow("unexpected signal during runtime execution")
+ }
+
+ // Native Client only invokes the exception handler for memory faults.
+ g.sig = _SIGSEGV
+ panicmem()
+}
diff --git a/src/pkg/runtime/os_nacl.h b/src/runtime/os_nacl.h
index 7c9d9c242..7c9d9c242 100644
--- a/src/pkg/runtime/os_nacl.h
+++ b/src/runtime/os_nacl.h
diff --git a/src/runtime/os_nacl_arm.c b/src/runtime/os_nacl_arm.c
new file mode 100644
index 000000000..1248ea644
--- /dev/null
+++ b/src/runtime/os_nacl_arm.c
@@ -0,0 +1,24 @@
+// 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 "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "textflag.h"
+
+void
+runtime·checkgoarm(void)
+{
+ return; // NaCl/ARM only supports ARMv7
+}
+
+#pragma textflag NOSPLIT
+int64
+runtime·cputicks(void)
+{
+ // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
+ // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+ // TODO: need more entropy to better seed fastrand1.
+ return runtime·nanotime();
+}
diff --git a/src/pkg/runtime/os_netbsd.c b/src/runtime/os_netbsd.c
index 93229bffe..58e5bedf2 100644
--- a/src/pkg/runtime/os_netbsd.c
+++ b/src/runtime/os_netbsd.c
@@ -7,7 +7,7 @@
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
enum
{
@@ -57,25 +57,30 @@ getncpu(void)
return 1;
}
+#pragma textflag NOSPLIT
uintptr
runtime·semacreate(void)
{
return 1;
}
-#pragma textflag NOSPLIT
-int32
-runtime·semasleep(int64 ns)
+static void
+semasleep(void)
{
+ int64 ns;
Timespec ts;
+ ns = (int64)(uint32)g->m->scalararg[0] | (int64)(uint32)g->m->scalararg[1]<<32;
+ g->m->scalararg[0] = 0;
+ g->m->scalararg[1] = 0;
+
// spin-mutex lock
- while(runtime·xchg(&m->waitsemalock, 1))
+ while(runtime·xchg(&g->m->waitsemalock, 1))
runtime·osyield();
for(;;) {
// lock held
- if(m->waitsemacount == 0) {
+ if(g->m->waitsemacount == 0) {
// sleep until semaphore != 0 or timeout.
// thrsleep unlocks m->waitsemalock.
if(ns < 0) {
@@ -92,8 +97,8 @@ runtime·semasleep(int64 ns)
// the NetBSD kernel does not appear to provide
// a mechanism for unlocking the userspace
// mutex once the thread is actually parked.
- runtime·atomicstore(&m->waitsemalock, 0);
- runtime·lwp_park(nil, 0, &m->waitsemacount, nil);
+ runtime·atomicstore(&g->m->waitsemalock, 0);
+ runtime·lwp_park(nil, 0, &g->m->waitsemacount, nil);
} else {
ns = ns + runtime·nanotime();
// NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
@@ -101,21 +106,22 @@ runtime·semasleep(int64 ns)
ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
// TODO(jsing) - potential deadlock!
// See above for details.
- runtime·atomicstore(&m->waitsemalock, 0);
- runtime·lwp_park(&ts, 0, &m->waitsemacount, nil);
+ runtime·atomicstore(&g->m->waitsemalock, 0);
+ runtime·lwp_park(&ts, 0, &g->m->waitsemacount, nil);
}
// reacquire lock
- while(runtime·xchg(&m->waitsemalock, 1))
+ while(runtime·xchg(&g->m->waitsemalock, 1))
runtime·osyield();
}
// lock held (again)
- if(m->waitsemacount != 0) {
+ if(g->m->waitsemacount != 0) {
// semaphore is available.
- m->waitsemacount--;
+ g->m->waitsemacount--;
// spin-mutex unlock
- runtime·atomicstore(&m->waitsemalock, 0);
- return 0; // semaphore acquired
+ runtime·atomicstore(&g->m->waitsemalock, 0);
+ g->m->scalararg[0] = 0; // semaphore acquired
+ return;
}
// semaphore not available.
@@ -127,14 +133,37 @@ runtime·semasleep(int64 ns)
// lock held but giving up
// spin-mutex unlock
- runtime·atomicstore(&m->waitsemalock, 0);
- return -1;
+ runtime·atomicstore(&g->m->waitsemalock, 0);
+ g->m->scalararg[0] = -1;
+ return;
}
+#pragma textflag NOSPLIT
+int32
+runtime·semasleep(int64 ns)
+{
+ int32 r;
+ void (*fn)(void);
+
+ g->m->scalararg[0] = (uint32)ns;
+ g->m->scalararg[1] = (uint32)(ns>>32);
+ fn = semasleep;
+ runtime·onM(&fn);
+ r = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+ return r;
+}
+
+static void badsemawakeup(void);
+
+#pragma textflag NOSPLIT
void
runtime·semawakeup(M *mp)
{
uint32 ret;
+ void (*fn)(void);
+ void *oldptr;
+ uintptr oldscalar;
// spin-mutex lock
while(runtime·xchg(&mp->waitsemalock, 1))
@@ -143,12 +172,39 @@ runtime·semawakeup(M *mp)
// TODO(jsing) - potential deadlock, see semasleep() for details.
// Confirm that LWP is parked before unparking...
ret = runtime·lwp_unpark(mp->procid, &mp->waitsemacount);
- if(ret != 0 && ret != ESRCH)
- runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
+ if(ret != 0 && ret != ESRCH) {
+ // semawakeup can be called on signal stack.
+ // Save old ptrarg/scalararg so we can restore them.
+ oldptr = g->m->ptrarg[0];
+ oldscalar = g->m->scalararg[0];
+ g->m->ptrarg[0] = mp;
+ g->m->scalararg[0] = ret;
+ fn = badsemawakeup;
+ if(g == g->m->gsignal)
+ fn();
+ else
+ runtime·onM(&fn);
+ g->m->ptrarg[0] = oldptr;
+ g->m->scalararg[0] = oldscalar;
+ }
// spin-mutex unlock
runtime·atomicstore(&mp->waitsemalock, 0);
}
+static void
+badsemawakeup(void)
+{
+ M *mp;
+ int32 ret;
+
+ mp = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ ret = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+
+ runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
+}
+
void
runtime·newosproc(M *mp, void *stk)
{
@@ -185,6 +241,7 @@ runtime·osinit(void)
runtime·ncpu = getncpu();
}
+#pragma textflag NOSPLIT
void
runtime·get_random_data(byte **rnd, int32 *rnd_len)
{
@@ -214,6 +271,7 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024);
+ mp->gsignal->m = mp;
}
// Called to initialize a new m (including the bootstrap m).
@@ -221,10 +279,10 @@ runtime·mpreinit(M *mp)
void
runtime·minit(void)
{
- m->procid = runtime·lwp_self();
+ g->m->procid = runtime·lwp_self();
// Initialize signal handling
- runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
+ runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024);
runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
}
@@ -235,41 +293,6 @@ runtime·unminit(void)
runtime·signalstack(nil, 0);
}
-void
-runtime·sigpanic(void)
-{
- if(!runtime·canpanic(g))
- runtime·throw("unexpected signal during runtime execution");
-
- switch(g->sig) {
- case SIGBUS:
- if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGSEGV:
- if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGFPE:
- switch(g->sigcode0) {
- case FPE_INTDIV:
- runtime·panicstring("integer divide by zero");
- case FPE_INTOVF:
- runtime·panicstring("integer overflow");
- }
- runtime·panicstring("floating point error");
- }
- runtime·panicstring(runtime·sigtab[g->sig].name);
-}
-
uintptr
runtime·memlimit(void)
{
@@ -285,12 +308,12 @@ typedef struct sigaction {
} _sa_u; /* signal handler */
uint32 sa_mask[4]; /* signal mask to apply */
int32 sa_flags; /* see signal options below */
-} Sigaction;
+} SigactionT;
void
runtime·setsig(int32 i, GoSighandler *fn, bool restart)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
@@ -309,7 +332,7 @@ runtime·setsig(int32 i, GoSighandler *fn, bool restart)
GoSighandler*
runtime·getsig(int32 i)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
@@ -336,3 +359,10 @@ runtime·unblocksignals(void)
{
runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
}
+
+#pragma textflag NOSPLIT
+int8*
+runtime·signame(int32 sig)
+{
+ return runtime·sigtab[sig].name;
+}
diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go
new file mode 100644
index 000000000..f000c5e9f
--- /dev/null
+++ b/src/runtime/os_netbsd.go
@@ -0,0 +1,20 @@
+// 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"
+
+func setitimer(mode int32, new, old unsafe.Pointer)
+func sigaction(sig int32, new, old unsafe.Pointer)
+func sigaltstack(new, old unsafe.Pointer)
+func sigprocmask(mode int32, new, old unsafe.Pointer)
+func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+func lwp_tramp()
+func raise(sig int32)
+func getcontext(ctxt unsafe.Pointer)
+func lwp_create(ctxt unsafe.Pointer, flags uintptr, lwpid unsafe.Pointer) int32
+func lwp_park(abstime unsafe.Pointer, unpark int32, hint, unparkhint unsafe.Pointer) int32
+func lwp_unpark(lwp int32, hint unsafe.Pointer) int32
+func lwp_self() int32
diff --git a/src/pkg/runtime/os_netbsd.h b/src/runtime/os_netbsd.h
index 16e9833af..f95db325f 100644
--- a/src/pkg/runtime/os_netbsd.h
+++ b/src/runtime/os_netbsd.h
@@ -2,11 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define SS_DISABLE 4
-
-#define SIG_BLOCK 1
-#define SIG_UNBLOCK 2
-#define SIG_SETMASK 3
typedef uintptr kevent_udata;
@@ -16,15 +11,21 @@ void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
-void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
+void runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
void runtime·sigprocmask(int32, Sigset*, Sigset*);
void runtime·unblocksignals(void);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
extern void runtime·lwp_tramp(void);
-#define NSIG 33
-#define SI_USER 0
-
-// From NetBSD's <sys/ucontext.h>
-#define _UC_SIGMASK 0x01
-#define _UC_CPU 0x04
+enum {
+ SS_DISABLE = 4,
+ SIG_BLOCK = 1,
+ SIG_UNBLOCK = 2,
+ SIG_SETMASK = 3,
+ NSIG = 33,
+ SI_USER = 0,
+
+ // From NetBSD's <sys/ucontext.h>
+ _UC_SIGMASK = 0x01,
+ _UC_CPU = 0x04,
+};
diff --git a/src/pkg/runtime/os_netbsd_386.c b/src/runtime/os_netbsd_386.c
index 23e9db3c1..23e9db3c1 100644
--- a/src/pkg/runtime/os_netbsd_386.c
+++ b/src/runtime/os_netbsd_386.c
diff --git a/src/pkg/runtime/os_netbsd_amd64.c b/src/runtime/os_netbsd_amd64.c
index 226846cbb..226846cbb 100644
--- a/src/pkg/runtime/os_netbsd_amd64.c
+++ b/src/runtime/os_netbsd_amd64.c
diff --git a/src/pkg/runtime/os_netbsd_arm.c b/src/runtime/os_netbsd_arm.c
index e440e7def..9dd4bcdc9 100644
--- a/src/pkg/runtime/os_netbsd_arm.c
+++ b/src/runtime/os_netbsd_arm.c
@@ -6,7 +6,7 @@
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
void
runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
diff --git a/src/pkg/runtime/os_openbsd.c b/src/runtime/os_openbsd.c
index 08a290a05..eebaa13ee 100644
--- a/src/pkg/runtime/os_openbsd.c
+++ b/src/runtime/os_openbsd.c
@@ -7,11 +7,13 @@
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
enum
{
ESRCH = 3,
+ EAGAIN = 35,
+ EWOULDBLOCK = EAGAIN,
ENOTSUP = 91,
// From OpenBSD's sys/time.h
@@ -26,7 +28,7 @@ extern SigTab runtime·sigtab[];
static Sigset sigset_none;
static Sigset sigset_all = ~(Sigset)0;
-extern int64 runtime·tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
+extern int32 runtime·tfork(TforkT *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
extern int32 runtime·thrsleep(void *ident, int32 clock_id, void *tsp, void *lock, const int32 *abort);
extern int32 runtime·thrwakeup(void *ident, int32 n);
@@ -54,6 +56,7 @@ getncpu(void)
return 1;
}
+#pragma textflag NOSPLIT
uintptr
runtime·semacreate(void)
{
@@ -64,73 +67,93 @@ runtime·semacreate(void)
int32
runtime·semasleep(int64 ns)
{
- Timespec ts;
-
- // spin-mutex lock
- while(runtime·xchg(&m->waitsemalock, 1))
- runtime·osyield();
+ Timespec ts, *tsp = nil;
+
+ // Compute sleep deadline.
+ if(ns >= 0) {
+ int32 nsec;
+ ns += runtime·nanotime();
+ ts.tv_sec = runtime·timediv(ns, 1000000000, &nsec);
+ ts.tv_nsec = nsec; // tv_nsec is int64 on amd64
+ tsp = &ts;
+ }
for(;;) {
- // lock held
- if(m->waitsemacount == 0) {
- // sleep until semaphore != 0 or timeout.
- // thrsleep unlocks m->waitsemalock.
- if(ns < 0)
- runtime·thrsleep(&m->waitsemacount, 0, nil, &m->waitsemalock, nil);
- else {
- ns += runtime·nanotime();
- // NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
- ts.tv_nsec = 0;
- ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
- runtime·thrsleep(&m->waitsemacount, CLOCK_MONOTONIC, &ts, &m->waitsemalock, nil);
- }
- // reacquire lock
- while(runtime·xchg(&m->waitsemalock, 1))
- runtime·osyield();
- }
+ int32 ret;
- // lock held (again)
- if(m->waitsemacount != 0) {
+ // spin-mutex lock
+ while(runtime·xchg(&g->m->waitsemalock, 1))
+ runtime·osyield();
+
+ if(g->m->waitsemacount != 0) {
// semaphore is available.
- m->waitsemacount--;
+ g->m->waitsemacount--;
// spin-mutex unlock
- runtime·atomicstore(&m->waitsemalock, 0);
+ runtime·atomicstore(&g->m->waitsemalock, 0);
return 0; // semaphore acquired
}
- // semaphore not available.
- // if there is a timeout, stop now.
- // otherwise keep trying.
- if(ns >= 0)
- break;
+ // sleep until semaphore != 0 or timeout.
+ // thrsleep unlocks m->waitsemalock.
+ ret = runtime·thrsleep(&g->m->waitsemacount, CLOCK_MONOTONIC, tsp, &g->m->waitsemalock, (int32 *)&g->m->waitsemacount);
+ if(ret == EWOULDBLOCK)
+ return -1;
}
-
- // lock held but giving up
- // spin-mutex unlock
- runtime·atomicstore(&m->waitsemalock, 0);
- return -1;
}
+static void badsemawakeup(void);
+
+#pragma textflag NOSPLIT
void
runtime·semawakeup(M *mp)
{
uint32 ret;
+ void *oldptr;
+ uint32 oldscalar;
+ void (*fn)(void);
// spin-mutex lock
while(runtime·xchg(&mp->waitsemalock, 1))
runtime·osyield();
mp->waitsemacount++;
ret = runtime·thrwakeup(&mp->waitsemacount, 1);
- if(ret != 0 && ret != ESRCH)
- runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
+ if(ret != 0 && ret != ESRCH) {
+ // semawakeup can be called on signal stack.
+ // Save old ptrarg/scalararg so we can restore them.
+ oldptr = g->m->ptrarg[0];
+ oldscalar = g->m->scalararg[0];
+ g->m->ptrarg[0] = mp;
+ g->m->scalararg[0] = ret;
+ fn = badsemawakeup;
+ if(g == g->m->gsignal)
+ fn();
+ else
+ runtime·onM(&fn);
+ g->m->ptrarg[0] = oldptr;
+ g->m->scalararg[0] = oldscalar;
+ }
// spin-mutex unlock
runtime·atomicstore(&mp->waitsemalock, 0);
}
+static void
+badsemawakeup(void)
+{
+ M *mp;
+ int32 ret;
+
+ mp = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ ret = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+
+ runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
+}
+
void
runtime·newosproc(M *mp, void *stk)
{
- Tfork param;
+ TforkT param;
Sigset oset;
int32 ret;
@@ -147,7 +170,7 @@ runtime·newosproc(M *mp, void *stk)
param.tf_stack = stk;
oset = runtime·sigprocmask(SIG_SETMASK, sigset_all);
- ret = runtime·tfork((byte*)&param, sizeof(param), mp, mp->g0, runtime·mstart);
+ ret = runtime·tfork(&param, sizeof(param), mp, mp->g0, runtime·mstart);
runtime·sigprocmask(SIG_SETMASK, oset);
if(ret < 0) {
@@ -164,6 +187,7 @@ runtime·osinit(void)
runtime·ncpu = getncpu();
}
+#pragma textflag NOSPLIT
void
runtime·get_random_data(byte **rnd, int32 *rnd_len)
{
@@ -193,6 +217,7 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024);
+ mp->gsignal->m = mp;
}
// Called to initialize a new m (including the bootstrap m).
@@ -201,7 +226,7 @@ void
runtime·minit(void)
{
// Initialize signal handling
- runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
+ runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024);
runtime·sigprocmask(SIG_SETMASK, sigset_none);
}
@@ -212,41 +237,6 @@ runtime·unminit(void)
runtime·signalstack(nil, 0);
}
-void
-runtime·sigpanic(void)
-{
- if(!runtime·canpanic(g))
- runtime·throw("unexpected signal during runtime execution");
-
- switch(g->sig) {
- case SIGBUS:
- if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGSEGV:
- if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGFPE:
- switch(g->sigcode0) {
- case FPE_INTDIV:
- runtime·panicstring("integer divide by zero");
- case FPE_INTOVF:
- runtime·panicstring("integer overflow");
- }
- runtime·panicstring("floating point error");
- }
- runtime·panicstring(runtime·sigtab[g->sig].name);
-}
-
uintptr
runtime·memlimit(void)
{
@@ -262,12 +252,12 @@ typedef struct sigaction {
} __sigaction_u; /* signal handler */
uint32 sa_mask; /* signal mask to apply */
int32 sa_flags; /* see signal options below */
-} Sigaction;
+} SigactionT;
void
runtime·setsig(int32 i, GoSighandler *fn, bool restart)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
@@ -283,7 +273,7 @@ runtime·setsig(int32 i, GoSighandler *fn, bool restart)
GoSighandler*
runtime·getsig(int32 i)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
@@ -310,3 +300,10 @@ runtime·unblocksignals(void)
{
runtime·sigprocmask(SIG_SETMASK, sigset_none);
}
+
+#pragma textflag NOSPLIT
+int8*
+runtime·signame(int32 sig)
+{
+ return runtime·sigtab[sig].name;
+}
diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go
new file mode 100644
index 000000000..a000f963e
--- /dev/null
+++ b/src/runtime/os_openbsd.go
@@ -0,0 +1,17 @@
+// 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"
+
+func setitimer(mode int32, new, old unsafe.Pointer)
+func sigaction(sig int32, new, old unsafe.Pointer)
+func sigaltstack(new, old unsafe.Pointer)
+func sigprocmask(mode int32, new uint32) uint32
+func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+func raise(sig int32)
+func tfork(param unsafe.Pointer, psize uintptr, mm, gg, fn unsafe.Pointer) int32
+func thrsleep(ident unsafe.Pointer, clock_id int32, tsp, lock, abort unsafe.Pointer) int32
+func thrwakeup(ident unsafe.Pointer, n int32) int32
diff --git a/src/pkg/runtime/os_openbsd.h b/src/runtime/os_openbsd.h
index bbfde39e2..6ad98109e 100644
--- a/src/pkg/runtime/os_openbsd.h
+++ b/src/runtime/os_openbsd.h
@@ -2,11 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define SS_DISABLE 4
-
-#define SIG_BLOCK 1
-#define SIG_UNBLOCK 2
-#define SIG_SETMASK 3
typedef byte* kevent_udata;
@@ -16,10 +11,16 @@ void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
-void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
+void runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
Sigset runtime·sigprocmask(int32, Sigset);
void runtime·unblocksignals(void);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
-#define NSIG 33
-#define SI_USER 0
+enum {
+ SS_DISABLE = 4,
+ SIG_BLOCK = 1,
+ SIG_UNBLOCK = 2,
+ SIG_SETMASK = 3,
+ NSIG = 33,
+ SI_USER = 0,
+};
diff --git a/src/pkg/runtime/os_plan9.c b/src/runtime/os_plan9.c
index 14d4fae48..f8c543f6f 100644
--- a/src/pkg/runtime/os_plan9.c
+++ b/src/runtime/os_plan9.c
@@ -5,7 +5,8 @@
#include "runtime.h"
#include "os_GOOS.h"
#include "arch_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "malloc.h"
int8 *goos = "plan9";
extern SigTab runtime·sigtab[];
@@ -19,11 +20,12 @@ runtime·mpreinit(M *mp)
{
// Initialize stack and goroutine for note handling.
mp->gsignal = runtime·malg(32*1024);
- mp->notesig = (int8*)runtime·malloc(ERRMAX*sizeof(int8));
+ mp->gsignal->m = mp;
+ mp->notesig = (int8*)runtime·mallocgc(ERRMAX*sizeof(int8), nil, FlagNoScan);
// Initialize stack for handling strings from the
// errstr system call, as used in package syscall.
- mp->errstr = (byte*)runtime·malloc(ERRMAX*sizeof(byte));
+ mp->errstr = (byte*)runtime·mallocgc(ERRMAX*sizeof(byte), nil, FlagNoScan);
}
// Called to initialize a new m (including the bootstrap m).
@@ -88,7 +90,7 @@ void
runtime·osinit(void)
{
runtime·ncpu = getproccount();
- m->procid = getpid();
+ g->m->procid = getpid();
runtime·notify(runtime·sigtramp);
}
@@ -99,6 +101,7 @@ runtime·crash(void)
*(int32*)0 = 0;
}
+#pragma textflag NOSPLIT
void
runtime·get_random_data(byte **rnd, int32 *rnd_len)
{
@@ -145,18 +148,20 @@ runtime·usleep(uint32 µs)
runtime·sleep(ms);
}
-void
-time·now(int64 sec, int32 nsec)
+#pragma textflag NOSPLIT
+int64
+runtime·nanotime(void)
{
- int64 ns;
+ int64 ns, scratch;
- ns = runtime·nanotime();
- sec = ns / 1000000000LL;
- nsec = ns - sec * 1000000000LL;
- FLUSH(&sec);
- FLUSH(&nsec);
+ ns = runtime·nsec(&scratch);
+ // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
+ if(ns == 0)
+ return scratch;
+ return ns;
}
+#pragma textflag NOSPLIT
void
runtime·itoa(int32 n, byte *p, uint32 len)
{
@@ -237,12 +242,29 @@ runtime·postnote(int32 pid, int8* msg)
return 0;
}
+static void exit(void);
+
+#pragma textflag NOSPLIT
void
runtime·exit(int32 e)
{
+ void (*fn)(void);
+
+ g->m->scalararg[0] = e;
+ fn = exit;
+ runtime·onM(&fn);
+}
+
+static void
+exit(void)
+{
+ int32 e;
byte tmp[16];
int8 *status;
+ e = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+
if(e == 0)
status = "";
else {
@@ -258,16 +280,19 @@ runtime·exit(int32 e)
void
runtime·newosproc(M *mp, void *stk)
{
- mp->tls[0] = mp->id; // so 386 asm can find it
- if(0){
- runtime·printf("newosproc stk=%p m=%p g=%p rfork=%p id=%d/%d ostk=%p\n",
- stk, mp, mp->g0, runtime·rfork, mp->id, (int32)mp->tls[0], &mp);
- }
+ int32 pid;
+
+ if(0)
+ runtime·printf("newosproc mp=%p ostk=%p\n", mp, &mp);
- if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, mp, mp->g0, runtime·mstart) < 0)
- runtime·throw("newosproc: rfork failed");
+ USED(stk);
+ if((pid = runtime·rfork(RFPROC|RFMEM|RFNOWAIT)) < 0)
+ runtime·throw("newosproc: rfork failed\n");
+ if(pid == 0)
+ runtime·tstart_plan9(mp);
}
+#pragma textflag NOSPLIT
uintptr
runtime·semacreate(void)
{
@@ -285,114 +310,33 @@ runtime·semasleep(int64 ns)
ms = runtime·timediv(ns, 1000000, nil);
if(ms == 0)
ms = 1;
- ret = runtime·plan9_tsemacquire(&m->waitsemacount, ms);
+ ret = runtime·plan9_tsemacquire(&g->m->waitsemacount, ms);
if(ret == 1)
return 0; // success
return -1; // timeout or interrupted
}
- while(runtime·plan9_semacquire(&m->waitsemacount, 1) < 0) {
+ while(runtime·plan9_semacquire(&g->m->waitsemacount, 1) < 0) {
/* interrupted; try again (c.f. lock_sema.c) */
}
return 0; // success
}
+#pragma textflag NOSPLIT
void
runtime·semawakeup(M *mp)
{
runtime·plan9_semrelease(&mp->waitsemacount, 1);
}
-void
-os·sigpipe(void)
-{
- runtime·throw("too many writes on closed pipe");
-}
-
-static int64
-atolwhex(byte *p)
-{
- int64 n;
- int32 f;
-
- n = 0;
- f = 0;
- while(*p == ' ' || *p == '\t')
- p++;
- if(*p == '-' || *p == '+') {
- if(*p++ == '-')
- f = 1;
- while(*p == ' ' || *p == '\t')
- p++;
- }
- if(p[0] == '0' && p[1]) {
- if(p[1] == 'x' || p[1] == 'X') {
- p += 2;
- for(;;) {
- if('0' <= *p && *p <= '9')
- n = n*16 + *p++ - '0';
- else if('a' <= *p && *p <= 'f')
- n = n*16 + *p++ - 'a' + 10;
- else if('A' <= *p && *p <= 'F')
- n = n*16 + *p++ - 'A' + 10;
- else
- break;
- }
- } else
- while('0' <= *p && *p <= '7')
- n = n*8 + *p++ - '0';
- } else
- while('0' <= *p && *p <= '9')
- n = n*10 + *p++ - '0';
- if(f)
- n = -n;
- return n;
-}
-
-void
-runtime·sigpanic(void)
-{
- byte *p;
-
- if(!runtime·canpanic(g))
- runtime·throw("unexpected signal during runtime execution");
-
- switch(g->sig) {
- case SIGRFAULT:
- case SIGWFAULT:
- p = runtime·strstr((byte*)m->notesig, (byte*)"addr=")+5;
- g->sigcode1 = atolwhex(p);
- if(g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- break;
- case SIGTRAP:
- if(g->paniconfault)
- runtime·panicstring("invalid memory address or nil pointer dereference");
- runtime·throw(m->notesig);
- break;
- case SIGINTDIV:
- runtime·panicstring("integer divide by zero");
- break;
- case SIGFLOAT:
- runtime·panicstring("floating point error");
- break;
- default:
- runtime·panicstring(m->notesig);
- break;
- }
-}
-
+#pragma textflag NOSPLIT
int32
runtime·read(int32 fd, void *buf, int32 nbytes)
{
return runtime·pread(fd, buf, nbytes, -1LL);
}
+#pragma textflag NOSPLIT
int32
runtime·write(uintptr fd, void *buf, int32 nbytes)
{
diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go
new file mode 100644
index 000000000..20e47bf42
--- /dev/null
+++ b/src/runtime/os_plan9.go
@@ -0,0 +1,103 @@
+// 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"
+
+func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
+func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
+func seek(fd int32, offset int64, whence int32) int64
+func exits(msg *byte)
+func brk_(addr unsafe.Pointer) uintptr
+func sleep(ms int32) int32
+func rfork(flags int32) int32
+func plan9_semacquire(addr *uint32, block int32) int32
+func plan9_tsemacquire(addr *uint32, ms int32) int32
+func plan9_semrelease(addr *uint32, count int32) int32
+func notify(fn unsafe.Pointer) int32
+func noted(mode int32) int32
+func nsec(*int64) int64
+func sigtramp(ureg, msg unsafe.Pointer)
+func setfpmasks()
+func tstart_plan9(newm *m)
+func errstr() string
+
+type _Plink uintptr
+
+func os_sigpipe() {
+ gothrow("too many writes on closed pipe")
+}
+
+func sigpanic() {
+ g := getg()
+ if !canpanic(g) {
+ gothrow("unexpected signal during runtime execution")
+ }
+
+ note := gostringnocopy((*byte)(unsafe.Pointer(g.m.notesig)))
+ switch g.sig {
+ case _SIGRFAULT, _SIGWFAULT:
+ addr := note[index(note, "addr=")+5:]
+ g.sigcode1 = uintptr(atolwhex(addr))
+ if g.sigcode1 < 0x1000 || g.paniconfault {
+ panicmem()
+ }
+ print("unexpected fault address ", hex(g.sigcode1), "\n")
+ gothrow("fault")
+ case _SIGTRAP:
+ if g.paniconfault {
+ panicmem()
+ }
+ gothrow(note)
+ case _SIGINTDIV:
+ panicdivide()
+ case _SIGFLOAT:
+ panicfloat()
+ default:
+ panic(errorString(note))
+ }
+}
+
+func atolwhex(p string) int64 {
+ for hasprefix(p, " ") || hasprefix(p, "\t") {
+ p = p[1:]
+ }
+ neg := false
+ if hasprefix(p, "-") || hasprefix(p, "+") {
+ neg = p[0] == '-'
+ p = p[1:]
+ for hasprefix(p, " ") || hasprefix(p, "\t") {
+ p = p[1:]
+ }
+ }
+ var n int64
+ switch {
+ case hasprefix(p, "0x"), hasprefix(p, "0X"):
+ p = p[2:]
+ for ; len(p) > 0; p = p[1:] {
+ if '0' <= p[0] && p[0] <= '9' {
+ n = n*16 + int64(p[0]-'0')
+ } else if 'a' <= p[0] && p[0] <= 'f' {
+ n = n*16 + int64(p[0]-'a'+10)
+ } else if 'A' <= p[0] && p[0] <= 'F' {
+ n = n*16 + int64(p[0]-'A'+10)
+ } else {
+ break
+ }
+ }
+ case hasprefix(p, "0"):
+ for ; len(p) > 0 && '0' <= p[0] && p[0] <= '7'; p = p[1:] {
+ n = n*8 + int64(p[0]-'0')
+ }
+ default:
+ for ; len(p) > 0 && '0' <= p[0] && p[0] <= '9'; p = p[1:] {
+ n = n*10 + int64(p[0]-'0')
+ }
+ }
+ if neg {
+ n = -n
+ }
+ return n
+}
diff --git a/src/pkg/runtime/os_plan9.h b/src/runtime/os_plan9.h
index 00ea8366d..6d1802483 100644
--- a/src/pkg/runtime/os_plan9.h
+++ b/src/runtime/os_plan9.h
@@ -9,16 +9,18 @@ int64 runtime·seek(int32 fd, int64 offset, int32 whence);
void runtime·exits(int8* msg);
intptr runtime·brk_(void*);
int32 runtime·sleep(int32 ms);
-int32 runtime·rfork(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
+int32 runtime·rfork(int32 flags);
int32 runtime·plan9_semacquire(uint32 *addr, int32 block);
int32 runtime·plan9_tsemacquire(uint32 *addr, int32 ms);
int32 runtime·plan9_semrelease(uint32 *addr, int32 count);
int32 runtime·notify(void (*fn)(void*, int8*));
int32 runtime·noted(int32);
+int64 runtime·nsec(int64*);
void runtime·sigtramp(void*, int8*);
void runtime·sigpanic(void);
void runtime·goexitsall(int8*);
void runtime·setfpmasks(void);
+void runtime·tstart_plan9(M *newm);
/* open */
enum
@@ -58,15 +60,15 @@ enum
};
typedef struct Tos Tos;
-typedef intptr Plink;
+typedef intptr _Plink;
struct Tos {
- struct /* Per process profiling */
+ struct TosProf /* Per process profiling */
{
- Plink *pp; /* known to be 0(ptr) */
- Plink *next; /* known to be 4(ptr) */
- Plink *last;
- Plink *first;
+ _Plink *pp; /* known to be 0(ptr) */
+ _Plink *next; /* known to be 4(ptr) */
+ _Plink *last;
+ _Plink *first;
uint32 pid;
uint32 what;
} prof;
@@ -78,12 +80,14 @@ struct Tos {
/* top of stack is here */
};
-#define NSIG 14 /* number of signals in runtime·SigTab array */
-#define ERRMAX 128 /* max length of note string */
+enum {
+ NSIG = 14, /* number of signals in runtime·SigTab array */
+ ERRMAX = 128, /* max length of note string */
-/* Notes in runtime·sigtab that are handled by runtime·sigpanic. */
-#define SIGRFAULT 2
-#define SIGWFAULT 3
-#define SIGINTDIV 4
-#define SIGFLOAT 5
-#define SIGTRAP 6
+ /* Notes in runtime·sigtab that are handled by runtime·sigpanic. */
+ SIGRFAULT = 2,
+ SIGWFAULT = 3,
+ SIGINTDIV = 4,
+ SIGFLOAT = 5,
+ SIGTRAP = 6,
+};
diff --git a/src/pkg/runtime/os_plan9_386.c b/src/runtime/os_plan9_386.c
index 80d711f33..42c6d161c 100644
--- a/src/pkg/runtime/os_plan9_386.c
+++ b/src/runtime/os_plan9_386.c
@@ -73,7 +73,7 @@ runtime·sighandler(void *v, int8 *note, G *gp)
if(flags & SigPanic) {
// Copy the error string from sigtramp's stack into m->notesig so
// we can reliably access it from the panic routines.
- runtime·memmove(m->notesig, note, len+1);
+ runtime·memmove(g->m->notesig, note, len+1);
gp->sig = sig;
gp->sigpc = ureg->pc;
@@ -104,8 +104,8 @@ runtime·sighandler(void *v, int8 *note, G *gp)
return NCONT;
Throw:
- m->throwing = 1;
- m->caughtsig = gp;
+ g->m->throwing = 1;
+ g->m->caughtsig = gp;
runtime·startpanic();
runtime·printf("%s\n", note);
@@ -114,7 +114,7 @@ Throw:
if(runtime·gotraceback(&crash)) {
runtime·goroutineheader(gp);
- runtime·traceback(ureg->pc, ureg->sp, 0, gp);
+ runtime·tracebacktrap(ureg->pc, ureg->sp, 0, gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
runtime·dumpregs(ureg);
@@ -146,5 +146,5 @@ runtime·resetcpuprofiler(int32 hz)
{
// TODO: Enable profiling interrupts.
- m->profilehz = hz;
+ g->m->profilehz = hz;
}
diff --git a/src/pkg/runtime/os_plan9_amd64.c b/src/runtime/os_plan9_amd64.c
index a4e5ba819..a9dc0eb96 100644
--- a/src/pkg/runtime/os_plan9_amd64.c
+++ b/src/runtime/os_plan9_amd64.c
@@ -81,7 +81,7 @@ runtime·sighandler(void *v, int8 *note, G *gp)
if(flags & SigPanic) {
// Copy the error string from sigtramp's stack into m->notesig so
// we can reliably access it from the panic routines.
- runtime·memmove(m->notesig, note, len+1);
+ runtime·memmove(g->m->notesig, note, len+1);
gp->sig = sig;
gp->sigpc = ureg->ip;
@@ -112,8 +112,8 @@ runtime·sighandler(void *v, int8 *note, G *gp)
return NCONT;
Throw:
- m->throwing = 1;
- m->caughtsig = gp;
+ g->m->throwing = 1;
+ g->m->caughtsig = gp;
runtime·startpanic();
runtime·printf("%s\n", note);
@@ -122,7 +122,7 @@ Throw:
if(runtime·gotraceback(&crash)) {
runtime·goroutineheader(gp);
- runtime·traceback(ureg->ip, ureg->sp, 0, gp);
+ runtime·tracebacktrap(ureg->ip, ureg->sp, 0, gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
runtime·dumpregs(ureg);
@@ -154,5 +154,5 @@ runtime·resetcpuprofiler(int32 hz)
{
// TODO: Enable profiling interrupts.
- m->profilehz = hz;
+ g->m->profilehz = hz;
}
diff --git a/src/pkg/runtime/os_solaris.c b/src/runtime/os_solaris.c
index c6bbea311..e16b8e637 100644
--- a/src/pkg/runtime/os_solaris.c
+++ b/src/runtime/os_solaris.c
@@ -7,11 +7,11 @@
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
-#pragma dynexport end _end
-#pragma dynexport etext _etext
-#pragma dynexport edata _edata
+#pragma dynexport runtime·end _end
+#pragma dynexport runtime·etext _etext
+#pragma dynexport runtime·edata _edata
#pragma dynimport libc·___errno ___errno "libc.so"
#pragma dynimport libc·clock_gettime clock_gettime "libc.so"
@@ -97,21 +97,6 @@ extern SigTab runtime·sigtab[];
static Sigset sigset_none;
static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, };
-// Calling sysvcall on os stack.
-#pragma textflag NOSPLIT
-uintptr
-runtime·sysvicall6(uintptr fn, int32 count, ...)
-{
- runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
- m->libcall.fn = (void*)fn;
- m->libcall.n = (uintptr)count;
- for(;count; count--)
- m->scratch.v[count - 1] = *((uintptr*)&count + count);
- m->libcall.args = (uintptr*)&m->scratch.v[0];
- runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
- return m->libcall.r1;
-}
-
static int32
getncpu(void)
{
@@ -136,14 +121,17 @@ runtime·newosproc(M *mp, void *stk)
Sigset oset;
Pthread tid;
int32 ret;
+ uint64 size;
USED(stk);
if(runtime·pthread_attr_init(&attr) != 0)
runtime·throw("pthread_attr_init");
if(runtime·pthread_attr_setstack(&attr, 0, 0x200000) != 0)
runtime·throw("pthread_attr_setstack");
- if(runtime·pthread_attr_getstack(&attr, (void**)&mp->g0->stackbase, &mp->g0->stacksize) != 0)
+ size = 0;
+ if(runtime·pthread_attr_getstack(&attr, (void**)&mp->g0->stack.hi, &size) != 0)
runtime·throw("pthread_attr_getstack");
+ mp->g0->stack.lo = mp->g0->stack.hi - size;
if(runtime·pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
runtime·throw("pthread_attr_setdetachstate");
@@ -158,6 +146,7 @@ runtime·newosproc(M *mp, void *stk)
}
}
+#pragma textflag NOSPLIT
void
runtime·get_random_data(byte **rnd, int32 *rnd_len)
{
@@ -187,6 +176,7 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024);
+ mp->gsignal->m = mp;
}
// Called to initialize a new m (including the bootstrap m).
@@ -196,7 +186,7 @@ runtime·minit(void)
{
runtime·asmcgocall(runtime·miniterrno, (void *)libc·___errno);
// Initialize signal handling
- runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
+ runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024);
runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
}
@@ -207,46 +197,11 @@ runtime·unminit(void)
runtime·signalstack(nil, 0);
}
-void
-runtime·sigpanic(void)
-{
- if(!runtime·canpanic(g))
- runtime·throw("unexpected signal during runtime execution");
-
- switch(g->sig) {
- case SIGBUS:
- if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGSEGV:
- if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case SIGFPE:
- switch(g->sigcode0) {
- case FPE_INTDIV:
- runtime·panicstring("integer divide by zero");
- case FPE_INTOVF:
- runtime·panicstring("integer overflow");
- }
- runtime·panicstring("floating point error");
- }
- runtime·panicstring(runtime·sigtab[g->sig].name);
-}
-
uintptr
runtime·memlimit(void)
{
Rlimit rl;
- extern byte text[], end[];
+ extern byte runtime·text[], runtime·end[];
uintptr used;
if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
@@ -257,7 +212,7 @@ runtime·memlimit(void)
// Estimate our VM footprint excluding the heap.
// Not an exact science: use size of binary plus
// some room for thread stacks.
- used = end - text + (64<<20);
+ used = runtime·end - runtime·text + (64<<20);
if(used >= rl.rlim_cur)
return 0;
@@ -281,7 +236,7 @@ extern void runtime·sigtramp(void);
void
runtime·setsig(int32 i, GoSighandler *fn, bool restart)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
@@ -300,7 +255,7 @@ runtime·setsig(int32 i, GoSighandler *fn, bool restart)
GoSighandler*
runtime·getsig(int32 i)
{
- Sigaction sa;
+ SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
@@ -337,13 +292,13 @@ runtime·semacreate(void)
// Call libc's malloc rather than runtime·malloc. This will
// allocate space on the C heap. We can't call runtime·malloc
// here because it could cause a deadlock.
- m->libcall.fn = (void*)libc·malloc;
- m->libcall.n = 1;
- runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
- m->scratch.v[0] = (uintptr)sizeof(*sem);
- m->libcall.args = (uintptr*)&m->scratch;
- runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
- sem = (void*)m->libcall.r1;
+ g->m->libcall.fn = (uintptr)(void*)libc·malloc;
+ g->m->libcall.n = 1;
+ runtime·memclr((byte*)&g->m->scratch, sizeof(g->m->scratch));
+ g->m->scratch.v[0] = (uintptr)sizeof(*sem);
+ g->m->libcall.args = (uintptr)(uintptr*)&g->m->scratch;
+ runtime·asmcgocall(runtime·asmsysvicall6, &g->m->libcall);
+ sem = (void*)g->m->libcall.r1;
if(runtime·sem_init(sem, 0, 0) != 0)
runtime·throw("sem_init");
return (uintptr)sem;
@@ -353,16 +308,19 @@ runtime·semacreate(void)
int32
runtime·semasleep(int64 ns)
{
+ M *m;
+
+ m = g->m;
if(ns >= 0) {
m->ts.tv_sec = ns / 1000000000LL;
m->ts.tv_nsec = ns % 1000000000LL;
- m->libcall.fn = (void*)libc·sem_reltimedwait_np;
+ m->libcall.fn = (uintptr)(void*)libc·sem_reltimedwait_np;
m->libcall.n = 2;
runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
m->scratch.v[0] = m->waitsema;
m->scratch.v[1] = (uintptr)&m->ts;
- m->libcall.args = (uintptr*)&m->scratch;
+ m->libcall.args = (uintptr)(uintptr*)&m->scratch;
runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
if(*m->perrno != 0) {
if(*m->perrno == ETIMEDOUT || *m->perrno == EAGAIN || *m->perrno == EINTR)
@@ -372,11 +330,11 @@ runtime·semasleep(int64 ns)
return 0;
}
for(;;) {
- m->libcall.fn = (void*)libc·sem_wait;
+ m->libcall.fn = (uintptr)(void*)libc·sem_wait;
m->libcall.n = 1;
runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
m->scratch.v[0] = m->waitsema;
- m->libcall.args = (uintptr*)&m->scratch;
+ m->libcall.args = (uintptr)(uintptr*)&m->scratch;
runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
if(m->libcall.r1 == 0)
break;
@@ -396,40 +354,46 @@ runtime·semawakeup(M *mp)
runtime·throw("sem_post");
}
+#pragma textflag NOSPLIT
int32
runtime·close(int32 fd)
{
- return runtime·sysvicall6(libc·close, 1, (uintptr)fd);
+ return runtime·sysvicall1(libc·close, (uintptr)fd);
}
+#pragma textflag NOSPLIT
void
runtime·exit(int32 r)
{
- runtime·sysvicall6(libc·exit, 1, (uintptr)r);
+ runtime·sysvicall1(libc·exit, (uintptr)r);
}
+#pragma textflag NOSPLIT
/* int32 */ void
runtime·getcontext(Ucontext* context)
{
- runtime·sysvicall6(libc·getcontext, 1, (uintptr)context);
+ runtime·sysvicall1(libc·getcontext, (uintptr)context);
}
+#pragma textflag NOSPLIT
int32
runtime·getrlimit(int32 res, Rlimit* rlp)
{
- return runtime·sysvicall6(libc·getrlimit, 2, (uintptr)res, (uintptr)rlp);
+ return runtime·sysvicall2(libc·getrlimit, (uintptr)res, (uintptr)rlp);
}
+#pragma textflag NOSPLIT
uint8*
runtime·mmap(byte* addr, uintptr len, int32 prot, int32 flags, int32 fildes, uint32 off)
{
- return (uint8*)runtime·sysvicall6(libc·mmap, 6, (uintptr)addr, (uintptr)len, (uintptr)prot, (uintptr)flags, (uintptr)fildes, (uintptr)off);
+ return (uint8*)runtime·sysvicall6(libc·mmap, (uintptr)addr, (uintptr)len, (uintptr)prot, (uintptr)flags, (uintptr)fildes, (uintptr)off);
}
+#pragma textflag NOSPLIT
void
runtime·munmap(byte* addr, uintptr len)
{
- runtime·sysvicall6(libc·munmap, 2, (uintptr)addr, (uintptr)len);
+ runtime·sysvicall2(libc·munmap, (uintptr)addr, (uintptr)len);
}
extern int64 runtime·nanotime1(void);
@@ -437,147 +401,157 @@ extern int64 runtime·nanotime1(void);
int64
runtime·nanotime(void)
{
- return runtime·sysvicall6((uintptr)runtime·nanotime1, 0);
-}
-
-void
-time·now(int64 sec, int32 usec)
-{
- int64 ns;
-
- ns = runtime·nanotime();
- sec = ns / 1000000000LL;
- usec = ns - sec * 1000000000LL;
- FLUSH(&sec);
- FLUSH(&usec);
+ return runtime·sysvicall0((uintptr)runtime·nanotime1);
}
+#pragma textflag NOSPLIT
int32
runtime·open(int8* path, int32 oflag, int32 mode)
{
- return runtime·sysvicall6(libc·open, 3, (uintptr)path, (uintptr)oflag, (uintptr)mode);
+ return runtime·sysvicall3(libc·open, (uintptr)path, (uintptr)oflag, (uintptr)mode);
}
int32
runtime·pthread_attr_destroy(PthreadAttr* attr)
{
- return runtime·sysvicall6(libc·pthread_attr_destroy, 1, (uintptr)attr);
+ return runtime·sysvicall1(libc·pthread_attr_destroy, (uintptr)attr);
}
int32
runtime·pthread_attr_getstack(PthreadAttr* attr, void** addr, uint64* size)
{
- return runtime·sysvicall6(libc·pthread_attr_getstack, 3, (uintptr)attr, (uintptr)addr, (uintptr)size);
+ return runtime·sysvicall3(libc·pthread_attr_getstack, (uintptr)attr, (uintptr)addr, (uintptr)size);
}
int32
runtime·pthread_attr_init(PthreadAttr* attr)
{
- return runtime·sysvicall6(libc·pthread_attr_init, 1, (uintptr)attr);
+ return runtime·sysvicall1(libc·pthread_attr_init, (uintptr)attr);
}
int32
runtime·pthread_attr_setdetachstate(PthreadAttr* attr, int32 state)
{
- return runtime·sysvicall6(libc·pthread_attr_setdetachstate, 2, (uintptr)attr, (uintptr)state);
+ return runtime·sysvicall2(libc·pthread_attr_setdetachstate, (uintptr)attr, (uintptr)state);
}
int32
runtime·pthread_attr_setstack(PthreadAttr* attr, void* addr, uint64 size)
{
- return runtime·sysvicall6(libc·pthread_attr_setstack, 3, (uintptr)attr, (uintptr)addr, (uintptr)size);
+ return runtime·sysvicall3(libc·pthread_attr_setstack, (uintptr)attr, (uintptr)addr, (uintptr)size);
}
int32
runtime·pthread_create(Pthread* thread, PthreadAttr* attr, void(*fn)(void), void *arg)
{
- return runtime·sysvicall6(libc·pthread_create, 4, (uintptr)thread, (uintptr)attr, (uintptr)fn, (uintptr)arg);
+ return runtime·sysvicall4(libc·pthread_create, (uintptr)thread, (uintptr)attr, (uintptr)fn, (uintptr)arg);
}
/* int32 */ void
runtime·raise(int32 sig)
{
- runtime·sysvicall6(libc·raise, 1, (uintptr)sig);
+ runtime·sysvicall1(libc·raise, (uintptr)sig);
}
+#pragma textflag NOSPLIT
int32
runtime·read(int32 fd, void* buf, int32 nbyte)
{
- return runtime·sysvicall6(libc·read, 3, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
+ return runtime·sysvicall3(libc·read, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
}
#pragma textflag NOSPLIT
int32
runtime·sem_init(SemT* sem, int32 pshared, uint32 value)
{
- return runtime·sysvicall6(libc·sem_init, 3, (uintptr)sem, (uintptr)pshared, (uintptr)value);
+ return runtime·sysvicall3(libc·sem_init, (uintptr)sem, (uintptr)pshared, (uintptr)value);
}
#pragma textflag NOSPLIT
int32
runtime·sem_post(SemT* sem)
{
- return runtime·sysvicall6(libc·sem_post, 1, (uintptr)sem);
+ return runtime·sysvicall1(libc·sem_post, (uintptr)sem);
}
#pragma textflag NOSPLIT
int32
runtime·sem_reltimedwait_np(SemT* sem, Timespec* timeout)
{
- return runtime·sysvicall6(libc·sem_reltimedwait_np, 2, (uintptr)sem, (uintptr)timeout);
+ return runtime·sysvicall2(libc·sem_reltimedwait_np, (uintptr)sem, (uintptr)timeout);
}
#pragma textflag NOSPLIT
int32
runtime·sem_wait(SemT* sem)
{
- return runtime·sysvicall6(libc·sem_wait, 1, (uintptr)sem);
+ return runtime·sysvicall1(libc·sem_wait, (uintptr)sem);
}
/* int32 */ void
runtime·setitimer(int32 which, Itimerval* value, Itimerval* ovalue)
{
- runtime·sysvicall6(libc·setitimer, 3, (uintptr)which, (uintptr)value, (uintptr)ovalue);
+ runtime·sysvicall3(libc·setitimer, (uintptr)which, (uintptr)value, (uintptr)ovalue);
}
/* int32 */ void
-runtime·sigaction(int32 sig, struct Sigaction* act, struct Sigaction* oact)
+runtime·sigaction(int32 sig, struct SigactionT* act, struct SigactionT* oact)
{
- runtime·sysvicall6(libc·sigaction, 3, (uintptr)sig, (uintptr)act, (uintptr)oact);
+ runtime·sysvicall3(libc·sigaction, (uintptr)sig, (uintptr)act, (uintptr)oact);
}
/* int32 */ void
-runtime·sigaltstack(Sigaltstack* ss, Sigaltstack* oss)
+runtime·sigaltstack(SigaltstackT* ss, SigaltstackT* oss)
{
- runtime·sysvicall6(libc·sigaltstack, 2, (uintptr)ss, (uintptr)oss);
+ runtime·sysvicall2(libc·sigaltstack, (uintptr)ss, (uintptr)oss);
}
/* int32 */ void
runtime·sigprocmask(int32 how, Sigset* set, Sigset* oset)
{
- runtime·sysvicall6(libc·sigprocmask, 3, (uintptr)how, (uintptr)set, (uintptr)oset);
+ runtime·sysvicall3(libc·sigprocmask, (uintptr)how, (uintptr)set, (uintptr)oset);
}
int64
runtime·sysconf(int32 name)
{
- return runtime·sysvicall6(libc·sysconf, 1, (uintptr)name);
+ return runtime·sysvicall1(libc·sysconf, (uintptr)name);
}
+extern void runtime·usleep1(uint32);
+
+#pragma textflag NOSPLIT
void
-runtime·usleep(uint32 us)
+runtime·usleep(uint32 µs)
{
- runtime·sysvicall6(libc·usleep, 1, (uintptr)us);
+ runtime·usleep1(µs);
}
+#pragma textflag NOSPLIT
int32
runtime·write(uintptr fd, void* buf, int32 nbyte)
{
- return runtime·sysvicall6(libc·write, 3, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
+ return runtime·sysvicall3(libc·write, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
}
+extern void runtime·osyield1(void);
+
+#pragma textflag NOSPLIT
void
runtime·osyield(void)
{
- runtime·sysvicall6(libc·sched_yield, 0);
+ // Check the validity of m because we might be called in cgo callback
+ // path early enough where there isn't a m available yet.
+ if(g && g->m != nil) {
+ runtime·sysvicall0(libc·sched_yield);
+ return;
+ }
+ runtime·osyield1();
+}
+
+#pragma textflag NOSPLIT
+int8*
+runtime·signame(int32 sig)
+{
+ return runtime·sigtab[sig].name;
}
diff --git a/src/runtime/os_solaris.go b/src/runtime/os_solaris.go
new file mode 100644
index 000000000..ca1315120
--- /dev/null
+++ b/src/runtime/os_solaris.go
@@ -0,0 +1,100 @@
+// 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"
+
+func setitimer(mode int32, new, old unsafe.Pointer)
+func sigaction(sig int32, new, old unsafe.Pointer)
+func sigaltstack(new, old unsafe.Pointer)
+func sigprocmask(mode int32, new, old unsafe.Pointer)
+func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+func getrlimit(kind int32, limit unsafe.Pointer)
+func miniterrno(fn unsafe.Pointer)
+func raise(sig int32)
+func getcontext(ctxt unsafe.Pointer)
+func tstart_sysvicall(mm unsafe.Pointer) uint32
+func nanotime1() int64
+func usleep1(usec uint32)
+func osyield1()
+func netpollinit()
+func netpollopen(fd uintptr, pd *pollDesc) int32
+func netpollclose(fd uintptr) int32
+func netpollarm(pd *pollDesc, mode int)
+
+type libcFunc byte
+
+var asmsysvicall6 libcFunc
+
+//go:nosplit
+func sysvicall0(fn *libcFunc) uintptr {
+ libcall := &getg().m.libcall
+ libcall.fn = uintptr(unsafe.Pointer(fn))
+ libcall.n = 0
+ // TODO(rsc): Why is noescape necessary here and below?
+ libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+ return libcall.r1
+}
+
+//go:nosplit
+func sysvicall1(fn *libcFunc, a1 uintptr) uintptr {
+ libcall := &getg().m.libcall
+ libcall.fn = uintptr(unsafe.Pointer(fn))
+ libcall.n = 1
+ libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+ return libcall.r1
+}
+
+//go:nosplit
+func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr {
+ libcall := &getg().m.libcall
+ libcall.fn = uintptr(unsafe.Pointer(fn))
+ libcall.n = 2
+ libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+ return libcall.r1
+}
+
+//go:nosplit
+func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr {
+ libcall := &getg().m.libcall
+ libcall.fn = uintptr(unsafe.Pointer(fn))
+ libcall.n = 3
+ libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+ return libcall.r1
+}
+
+//go:nosplit
+func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr {
+ libcall := &getg().m.libcall
+ libcall.fn = uintptr(unsafe.Pointer(fn))
+ libcall.n = 4
+ libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+ return libcall.r1
+}
+
+//go:nosplit
+func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
+ libcall := &getg().m.libcall
+ libcall.fn = uintptr(unsafe.Pointer(fn))
+ libcall.n = 5
+ libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+ return libcall.r1
+}
+
+//go:nosplit
+func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
+ libcall := &getg().m.libcall
+ libcall.fn = uintptr(unsafe.Pointer(fn))
+ libcall.n = 6
+ libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+ return libcall.r1
+}
diff --git a/src/runtime/os_solaris.h b/src/runtime/os_solaris.h
new file mode 100644
index 000000000..3d9e1a240
--- /dev/null
+++ b/src/runtime/os_solaris.h
@@ -0,0 +1,55 @@
+// 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.
+
+
+typedef uintptr kevent_udata;
+
+struct sigaction;
+
+void runtime·sigpanic(void);
+
+void runtime·setitimer(int32, Itimerval*, Itimerval*);
+void runtime·sigaction(int32, struct SigactionT*, struct SigactionT*);
+void runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
+void runtime·sigprocmask(int32, Sigset*, Sigset*);
+void runtime·unblocksignals(void);
+int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
+
+
+void runtime·raisesigpipe(void);
+void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
+void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
+void runtime·sigpanic(void);
+
+enum {
+ SS_DISABLE = 2,
+ SIG_BLOCK = 1,
+ SIG_UNBLOCK = 2,
+ SIG_SETMASK = 3,
+ NSIG = 73, /* number of signals in runtime·SigTab array */
+ SI_USER = 0,
+ _UC_SIGMASK = 0x01,
+ _UC_CPU = 0x04,
+ RLIMIT_AS = 10,
+};
+
+typedef struct Rlimit Rlimit;
+struct Rlimit {
+ int64 rlim_cur;
+ int64 rlim_max;
+};
+int32 runtime·getrlimit(int32, Rlimit*);
+
+// Call an external library function described by {fn, a0, ..., an}, with
+// SysV conventions, switching to os stack during the call, if necessary.
+uintptr runtime·sysvicall0(uintptr fn);
+uintptr runtime·sysvicall1(uintptr fn, uintptr a1);
+uintptr runtime·sysvicall2(uintptr fn, uintptr a1, uintptr a2);
+uintptr runtime·sysvicall3(uintptr fn, uintptr a1, uintptr a2, uintptr a3);
+uintptr runtime·sysvicall4(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4);
+uintptr runtime·sysvicall5(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5);
+uintptr runtime·sysvicall6(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6);
+void runtime·asmsysvicall6(void *c);
+
+void runtime·miniterrno(void *fn);
diff --git a/src/pkg/runtime/os_windows.c b/src/runtime/os_windows.c
index 0dd44ed1b..b8b8eda5f 100644
--- a/src/pkg/runtime/os_windows.c
+++ b/src/runtime/os_windows.c
@@ -6,7 +6,9 @@
#include "type.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
#pragma dynimport runtime·AddVectoredExceptionHandler AddVectoredExceptionHandler "kernel32.dll"
#pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll"
@@ -23,7 +25,6 @@
#pragma dynimport runtime·GetProcAddress GetProcAddress "kernel32.dll"
#pragma dynimport runtime·GetStdHandle GetStdHandle "kernel32.dll"
#pragma dynimport runtime·GetSystemInfo GetSystemInfo "kernel32.dll"
-#pragma dynimport runtime·GetSystemTimeAsFileTime GetSystemTimeAsFileTime "kernel32.dll"
#pragma dynimport runtime·GetThreadContext GetThreadContext "kernel32.dll"
#pragma dynimport runtime·LoadLibrary LoadLibraryW "kernel32.dll"
#pragma dynimport runtime·LoadLibraryA LoadLibraryA "kernel32.dll"
@@ -33,6 +34,7 @@
#pragma dynimport runtime·SetEvent SetEvent "kernel32.dll"
#pragma dynimport runtime·SetProcessPriorityBoost SetProcessPriorityBoost "kernel32.dll"
#pragma dynimport runtime·SetThreadPriority SetThreadPriority "kernel32.dll"
+#pragma dynimport runtime·SetUnhandledExceptionFilter SetUnhandledExceptionFilter "kernel32.dll"
#pragma dynimport runtime·SetWaitableTimer SetWaitableTimer "kernel32.dll"
#pragma dynimport runtime·Sleep Sleep "kernel32.dll"
#pragma dynimport runtime·SuspendThread SuspendThread "kernel32.dll"
@@ -55,7 +57,6 @@ extern void *runtime·GetEnvironmentStringsW;
extern void *runtime·GetProcAddress;
extern void *runtime·GetStdHandle;
extern void *runtime·GetSystemInfo;
-extern void *runtime·GetSystemTimeAsFileTime;
extern void *runtime·GetThreadContext;
extern void *runtime·LoadLibrary;
extern void *runtime·LoadLibraryA;
@@ -65,6 +66,7 @@ extern void *runtime·SetConsoleCtrlHandler;
extern void *runtime·SetEvent;
extern void *runtime·SetProcessPriorityBoost;
extern void *runtime·SetThreadPriority;
+extern void *runtime·SetUnhandledExceptionFilter;
extern void *runtime·SetWaitableTimer;
extern void *runtime·Sleep;
extern void *runtime·SuspendThread;
@@ -72,18 +74,35 @@ extern void *runtime·WaitForSingleObject;
extern void *runtime·WriteFile;
extern void *runtime·timeBeginPeriod;
+#pragma dataflag NOPTR
void *runtime·GetQueuedCompletionStatusEx;
extern uintptr runtime·externalthreadhandlerp;
void runtime·externalthreadhandler(void);
-void runtime·sigtramp(void);
+void runtime·exceptiontramp(void);
+void runtime·firstcontinuetramp(void);
+void runtime·lastcontinuetramp(void);
+
+#pragma textflag NOSPLIT
+uintptr
+runtime·getLoadLibrary(void)
+{
+ return (uintptr)runtime·LoadLibrary;
+}
+
+#pragma textflag NOSPLIT
+uintptr
+runtime·getGetProcAddress(void)
+{
+ return (uintptr)runtime·GetProcAddress;
+}
static int32
getproccount(void)
{
SystemInfo info;
- runtime·stdcall(runtime·GetSystemInfo, 1, &info);
+ runtime·stdcall1(runtime·GetSystemInfo, (uintptr)&info);
return info.dwNumberOfProcessors;
}
@@ -91,80 +110,98 @@ void
runtime·osinit(void)
{
void *kernel32;
+ void *addVectoredContinueHandler;
+
+ kernel32 = runtime·stdcall1(runtime·LoadLibraryA, (uintptr)"kernel32.dll");
runtime·externalthreadhandlerp = (uintptr)runtime·externalthreadhandler;
- runtime·stdcall(runtime·AddVectoredExceptionHandler, 2, (uintptr)1, (uintptr)runtime·sigtramp);
- runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1);
- runtime·stdcall(runtime·timeBeginPeriod, 1, (uintptr)1);
+ runtime·stdcall2(runtime·AddVectoredExceptionHandler, 1, (uintptr)runtime·exceptiontramp);
+ addVectoredContinueHandler = nil;
+ if(kernel32 != nil)
+ addVectoredContinueHandler = runtime·stdcall2(runtime·GetProcAddress, (uintptr)kernel32, (uintptr)"AddVectoredContinueHandler");
+ if(addVectoredContinueHandler == nil || sizeof(void*) == 4) {
+ // use SetUnhandledExceptionFilter for windows-386 or
+ // if VectoredContinueHandler is unavailable.
+ // note: SetUnhandledExceptionFilter handler won't be called, if debugging.
+ runtime·stdcall1(runtime·SetUnhandledExceptionFilter, (uintptr)runtime·lastcontinuetramp);
+ } else {
+ runtime·stdcall2(addVectoredContinueHandler, 1, (uintptr)runtime·firstcontinuetramp);
+ runtime·stdcall2(addVectoredContinueHandler, 0, (uintptr)runtime·lastcontinuetramp);
+ }
+
+ runtime·stdcall2(runtime·SetConsoleCtrlHandler, (uintptr)runtime·ctrlhandler, 1);
+
+ runtime·stdcall1(runtime·timeBeginPeriod, 1);
+
runtime·ncpu = getproccount();
// Windows dynamic priority boosting assumes that a process has different types
// of dedicated threads -- GUI, IO, computational, etc. Go processes use
// equivalent threads that all do a mix of GUI, IO, computations, etc.
// In such context dynamic priority boosting does nothing but harm, so we turn it off.
- runtime·stdcall(runtime·SetProcessPriorityBoost, 2, (uintptr)-1, (uintptr)1);
+ runtime·stdcall2(runtime·SetProcessPriorityBoost, -1, 1);
- kernel32 = runtime·stdcall(runtime·LoadLibraryA, 1, "kernel32.dll");
if(kernel32 != nil) {
- runtime·GetQueuedCompletionStatusEx = runtime·stdcall(runtime·GetProcAddress, 2, kernel32, "GetQueuedCompletionStatusEx");
+ runtime·GetQueuedCompletionStatusEx = runtime·stdcall2(runtime·GetProcAddress, (uintptr)kernel32, (uintptr)"GetQueuedCompletionStatusEx");
}
}
+#pragma textflag NOSPLIT
void
runtime·get_random_data(byte **rnd, int32 *rnd_len)
{
uintptr handle;
*rnd = nil;
*rnd_len = 0;
- if(runtime·stdcall(runtime·CryptAcquireContextW, 5, &handle, nil, nil,
- (uintptr)1 /* PROV_RSA_FULL */,
- (uintptr)0xf0000000U /* CRYPT_VERIFYCONTEXT */) != 0) {
+ if(runtime·stdcall5(runtime·CryptAcquireContextW, (uintptr)&handle, (uintptr)nil, (uintptr)nil,
+ 1 /* PROV_RSA_FULL */,
+ 0xf0000000U /* CRYPT_VERIFYCONTEXT */) != 0) {
static byte random_data[HashRandomBytes];
- if(runtime·stdcall(runtime·CryptGenRandom, 3, handle, (uintptr)HashRandomBytes, random_data)) {
+ if(runtime·stdcall3(runtime·CryptGenRandom, handle, HashRandomBytes, (uintptr)&random_data[0])) {
*rnd = random_data;
*rnd_len = HashRandomBytes;
}
- runtime·stdcall(runtime·CryptReleaseContext, 2, handle, (uintptr)0);
+ runtime·stdcall2(runtime·CryptReleaseContext, handle, 0);
}
}
void
runtime·goenvs(void)
{
- extern Slice syscall·envs;
+ extern Slice runtime·envs;
uint16 *env;
String *s;
int32 i, n;
uint16 *p;
- env = runtime·stdcall(runtime·GetEnvironmentStringsW, 0);
+ env = runtime·stdcall0(runtime·GetEnvironmentStringsW);
n = 0;
for(p=env; *p; n++)
p += runtime·findnullw(p)+1;
- s = runtime·malloc(n*sizeof s[0]);
+ runtime·envs = runtime·makeStringSlice(n);
+ s = (String*)runtime·envs.array;
p = env;
for(i=0; i<n; i++) {
s[i] = runtime·gostringw(p);
p += runtime·findnullw(p)+1;
}
- syscall·envs.array = (byte*)s;
- syscall·envs.len = n;
- syscall·envs.cap = n;
- runtime·stdcall(runtime·FreeEnvironmentStringsW, 1, env);
+ runtime·stdcall1(runtime·FreeEnvironmentStringsW, (uintptr)env);
}
+#pragma textflag NOSPLIT
void
runtime·exit(int32 code)
{
- runtime·stdcall(runtime·ExitProcess, 1, (uintptr)code);
+ runtime·stdcall1(runtime·ExitProcess, code);
}
+#pragma textflag NOSPLIT
int32
runtime·write(uintptr fd, void *buf, int32 n)
{
@@ -174,17 +211,17 @@ runtime·write(uintptr fd, void *buf, int32 n)
written = 0;
switch(fd) {
case 1:
- handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-11);
+ handle = runtime·stdcall1(runtime·GetStdHandle, -11);
break;
case 2:
- handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-12);
+ handle = runtime·stdcall1(runtime·GetStdHandle, -12);
break;
default:
// assume fd is real windows handle.
handle = (void*)fd;
break;
}
- runtime·stdcall(runtime·WriteFile, 5, handle, buf, (uintptr)n, &written, (uintptr)0);
+ runtime·stdcall5(runtime·WriteFile, (uintptr)handle, (uintptr)buf, n, (uintptr)&written, 0);
return written;
}
@@ -202,21 +239,23 @@ runtime·semasleep(int64 ns)
if(ns == 0)
ns = 1;
}
- if(runtime·stdcall(runtime·WaitForSingleObject, 2, m->waitsema, (uintptr)ns) != 0)
+ if(runtime·stdcall2(runtime·WaitForSingleObject, (uintptr)g->m->waitsema, ns) != 0)
return -1; // timeout
return 0;
}
+#pragma textflag NOSPLIT
void
runtime·semawakeup(M *mp)
{
- runtime·stdcall(runtime·SetEvent, 1, mp->waitsema);
+ runtime·stdcall1(runtime·SetEvent, mp->waitsema);
}
+#pragma textflag NOSPLIT
uintptr
runtime·semacreate(void)
{
- return (uintptr)runtime·stdcall(runtime·CreateEvent, 4, (uintptr)0, (uintptr)0, (uintptr)0, (uintptr)0);
+ return (uintptr)runtime·stdcall4(runtime·CreateEvent, 0, 0, 0, 0);
}
#define STACK_SIZE_PARAM_IS_A_RESERVATION ((uintptr)0x00010000)
@@ -228,9 +267,9 @@ runtime·newosproc(M *mp, void *stk)
USED(stk);
- thandle = runtime·stdcall(runtime·CreateThread, 6,
- nil, (uintptr)0x20000, runtime·tstart_stdcall, mp,
- STACK_SIZE_PARAM_IS_A_RESERVATION, nil);
+ thandle = runtime·stdcall6(runtime·CreateThread,
+ (uintptr)nil, 0x20000, (uintptr)runtime·tstart_stdcall, (uintptr)mp,
+ STACK_SIZE_PARAM_IS_A_RESERVATION, (uintptr)nil);
if(thandle == nil) {
runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), runtime·getlasterror());
runtime·throw("runtime.newosproc");
@@ -250,65 +289,174 @@ runtime·mpreinit(M *mp)
void
runtime·minit(void)
{
- void *thandle;
+ uintptr thandle;
// -1 = current process, -2 = current thread
- runtime·stdcall(runtime·DuplicateHandle, 7,
- (uintptr)-1, (uintptr)-2, (uintptr)-1, &thandle,
- (uintptr)0, (uintptr)0, (uintptr)DUPLICATE_SAME_ACCESS);
- runtime·atomicstorep(&m->thread, thandle);
+ runtime·stdcall7(runtime·DuplicateHandle, -1, -2, -1, (uintptr)&thandle, 0, 0, DUPLICATE_SAME_ACCESS);
+ runtime·atomicstoreuintptr(&g->m->thread, thandle);
}
// Called from dropm to undo the effect of an minit.
void
runtime·unminit(void)
{
+ runtime·stdcall1(runtime·CloseHandle, g->m->thread);
+ g->m->thread = 0;
}
+// Described in http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/
+typedef struct KSYSTEM_TIME {
+ uint32 LowPart;
+ int32 High1Time;
+ int32 High2Time;
+} KSYSTEM_TIME;
+
+#pragma dataflag NOPTR
+const KSYSTEM_TIME* INTERRUPT_TIME = (KSYSTEM_TIME*)0x7ffe0008;
+#pragma dataflag NOPTR
+const KSYSTEM_TIME* SYSTEM_TIME = (KSYSTEM_TIME*)0x7ffe0014;
+
+static void badsystime(void);
+
#pragma textflag NOSPLIT
int64
-runtime·nanotime(void)
+runtime·systime(KSYSTEM_TIME *timeaddr)
{
- int64 filetime;
-
- runtime·stdcall(runtime·GetSystemTimeAsFileTime, 1, &filetime);
+ KSYSTEM_TIME t;
+ int32 i;
+ void (*fn)(void);
+
+ for(i = 1; i < 10000; i++) {
+ // these fields must be read in that order (see URL above)
+ t.High1Time = timeaddr->High1Time;
+ t.LowPart = timeaddr->LowPart;
+ t.High2Time = timeaddr->High2Time;
+ if(t.High1Time == t.High2Time)
+ return (int64)t.High1Time<<32 | t.LowPart;
+ if((i%100) == 0)
+ runtime·osyield();
+ }
+ fn = badsystime;
+ runtime·onM(&fn);
+ return 0;
+}
- // Filetime is 100s of nanoseconds since January 1, 1601.
- // Convert to nanoseconds since January 1, 1970.
- return (filetime - 116444736000000000LL) * 100LL;
+#pragma textflag NOSPLIT
+int64
+runtime·unixnano(void)
+{
+ return (runtime·systime(SYSTEM_TIME) - 116444736000000000LL) * 100LL;
}
-void
-time·now(int64 sec, int32 usec)
+static void
+badsystime(void)
{
- int64 ns;
+ runtime·throw("interrupt/system time is changing too fast");
+}
- ns = runtime·nanotime();
- sec = ns / 1000000000LL;
- usec = ns - sec * 1000000000LL;
- FLUSH(&sec);
- FLUSH(&usec);
+#pragma textflag NOSPLIT
+int64
+runtime·nanotime(void)
+{
+ return runtime·systime(INTERRUPT_TIME) * 100LL;
}
// Calling stdcall on os stack.
#pragma textflag NOSPLIT
-void *
-runtime·stdcall(void *fn, int32 count, ...)
+static void*
+stdcall(void *fn)
{
- m->libcall.fn = fn;
- m->libcall.n = count;
- m->libcall.args = (uintptr*)&count + 1;
- if(m->profilehz != 0) {
+ g->m->libcall.fn = (uintptr)fn;
+ if(g->m->profilehz != 0) {
// leave pc/sp for cpu profiler
- m->libcallg = g;
- m->libcallpc = (uintptr)runtime·getcallerpc(&fn);
+ g->m->libcallg = g;
+ g->m->libcallpc = (uintptr)runtime·getcallerpc(&fn);
// sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them
- m->libcallsp = (uintptr)runtime·getcallersp(&fn);
+ g->m->libcallsp = (uintptr)runtime·getcallersp(&fn);
}
- runtime·asmcgocall(runtime·asmstdcall, &m->libcall);
- m->libcallsp = 0;
- return (void*)m->libcall.r1;
+ runtime·asmcgocall(runtime·asmstdcall, &g->m->libcall);
+ g->m->libcallsp = 0;
+ return (void*)g->m->libcall.r1;
+}
+
+#pragma textflag NOSPLIT
+void*
+runtime·stdcall0(void *fn)
+{
+ g->m->libcall.n = 0;
+ g->m->libcall.args = (uintptr)&fn; // it's unused but must be non-nil, otherwise crashes
+ return stdcall(fn);
+}
+
+#pragma textflag NOSPLIT
+void*
+runtime·stdcall1(void *fn, uintptr a0)
+{
+ USED(a0);
+ g->m->libcall.n = 1;
+ g->m->libcall.args = (uintptr)&a0;
+ return stdcall(fn);
+}
+
+#pragma textflag NOSPLIT
+void*
+runtime·stdcall2(void *fn, uintptr a0, uintptr a1)
+{
+ USED(a0, a1);
+ g->m->libcall.n = 2;
+ g->m->libcall.args = (uintptr)&a0;
+ return stdcall(fn);
+}
+
+#pragma textflag NOSPLIT
+void*
+runtime·stdcall3(void *fn, uintptr a0, uintptr a1, uintptr a2)
+{
+ USED(a0, a1, a2);
+ g->m->libcall.n = 3;
+ g->m->libcall.args = (uintptr)&a0;
+ return stdcall(fn);
+}
+
+#pragma textflag NOSPLIT
+void*
+runtime·stdcall4(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3)
+{
+ USED(a0, a1, a2, a3);
+ g->m->libcall.n = 4;
+ g->m->libcall.args = (uintptr)&a0;
+ return stdcall(fn);
+}
+
+#pragma textflag NOSPLIT
+void*
+runtime·stdcall5(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4)
+{
+ USED(a0, a1, a2, a3, a4);
+ g->m->libcall.n = 5;
+ g->m->libcall.args = (uintptr)&a0;
+ return stdcall(fn);
+}
+
+#pragma textflag NOSPLIT
+void*
+runtime·stdcall6(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5)
+{
+ USED(a0, a1, a2, a3, a4, a5);
+ g->m->libcall.n = 6;
+ g->m->libcall.args = (uintptr)&a0;
+ return stdcall(fn);
+}
+
+#pragma textflag NOSPLIT
+void*
+runtime·stdcall7(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6)
+{
+ USED(a0, a1, a2, a3, a4, a5, a6);
+ g->m->libcall.n = 7;
+ g->m->libcall.args = (uintptr)&a0;
+ return stdcall(fn);
}
extern void runtime·usleep1(uint32);
@@ -340,47 +488,23 @@ runtime·issigpanic(uint32 code)
case EXCEPTION_FLT_INEXACT_RESULT:
case EXCEPTION_FLT_OVERFLOW:
case EXCEPTION_FLT_UNDERFLOW:
+ case EXCEPTION_BREAKPOINT:
return 1;
}
return 0;
}
void
-runtime·sigpanic(void)
-{
- if(!runtime·canpanic(g))
- runtime·throw("unexpected signal during runtime execution");
-
- switch(g->sig) {
- case EXCEPTION_ACCESS_VIOLATION:
- if(g->sigcode1 < 0x1000 || g->paniconfault) {
- if(g->sigpc == 0)
- runtime·panicstring("call of nil func value");
- runtime·panicstring("invalid memory address or nil pointer dereference");
- }
- runtime·printf("unexpected fault address %p\n", g->sigcode1);
- runtime·throw("fault");
- case EXCEPTION_INT_DIVIDE_BY_ZERO:
- runtime·panicstring("integer divide by zero");
- case EXCEPTION_INT_OVERFLOW:
- runtime·panicstring("integer overflow");
- case EXCEPTION_FLT_DENORMAL_OPERAND:
- case EXCEPTION_FLT_DIVIDE_BY_ZERO:
- case EXCEPTION_FLT_INEXACT_RESULT:
- case EXCEPTION_FLT_OVERFLOW:
- case EXCEPTION_FLT_UNDERFLOW:
- runtime·panicstring("floating point error");
- }
- runtime·throw("fault");
-}
-
-void
runtime·initsig(void)
{
- // following line keeps sigtramp alive at link stage
+ // following line keeps these functions alive at link stage
// if there's a better way please write it here
- void *p = runtime·sigtramp;
- USED(p);
+ void *e = runtime·exceptiontramp;
+ void *f = runtime·firstcontinuetramp;
+ void *l = runtime·lastcontinuetramp;
+ USED(e);
+ USED(f);
+ USED(l);
}
uint32
@@ -405,6 +529,7 @@ runtime·ctrlhandler1(uint32 type)
extern void runtime·dosigprof(Context *r, G *gp, M *mp);
extern void runtime·profileloop(void);
+#pragma dataflag NOPTR
static void *profiletimer;
static void
@@ -425,7 +550,7 @@ profilem(M *mp)
// align Context to 16 bytes
r = (Context*)((uintptr)(&rbuf[15]) & ~15);
r->ContextFlags = CONTEXT_CONTROL;
- runtime·stdcall(runtime·GetThreadContext, 2, mp->thread, r);
+ runtime·stdcall2(runtime·GetThreadContext, (uintptr)mp->thread, (uintptr)r);
runtime·dosigprof(r, gp, mp);
}
@@ -433,25 +558,24 @@ void
runtime·profileloop1(void)
{
M *mp, *allm;
- void *thread;
+ uintptr thread;
- runtime·stdcall(runtime·SetThreadPriority, 2,
- (uintptr)-2, (uintptr)THREAD_PRIORITY_HIGHEST);
+ runtime·stdcall2(runtime·SetThreadPriority, -2, THREAD_PRIORITY_HIGHEST);
for(;;) {
- runtime·stdcall(runtime·WaitForSingleObject, 2, profiletimer, (uintptr)-1);
+ runtime·stdcall2(runtime·WaitForSingleObject, (uintptr)profiletimer, -1);
allm = runtime·atomicloadp(&runtime·allm);
for(mp = allm; mp != nil; mp = mp->alllink) {
- thread = runtime·atomicloadp(&mp->thread);
+ thread = runtime·atomicloaduintptr(&mp->thread);
// Do not profile threads blocked on Notes,
// this includes idle worker threads,
// idle timer thread, idle heap scavenger, etc.
- if(thread == nil || mp->profilehz == 0 || mp->blocked)
+ if(thread == 0 || mp->profilehz == 0 || mp->blocked)
continue;
- runtime·stdcall(runtime·SuspendThread, 1, thread);
+ runtime·stdcall1(runtime·SuspendThread, (uintptr)thread);
if(mp->profilehz != 0 && !mp->blocked)
profilem(mp);
- runtime·stdcall(runtime·ResumeThread, 1, thread);
+ runtime·stdcall1(runtime·ResumeThread, (uintptr)thread);
}
}
}
@@ -459,18 +583,19 @@ runtime·profileloop1(void)
void
runtime·resetcpuprofiler(int32 hz)
{
- static Lock lock;
+ static Mutex lock;
void *timer, *thread;
int32 ms;
int64 due;
runtime·lock(&lock);
if(profiletimer == nil) {
- timer = runtime·stdcall(runtime·CreateWaitableTimer, 3, nil, nil, nil);
+ timer = runtime·stdcall3(runtime·CreateWaitableTimer, (uintptr)nil, (uintptr)nil, (uintptr)nil);
runtime·atomicstorep(&profiletimer, timer);
- thread = runtime·stdcall(runtime·CreateThread, 6,
- nil, nil, runtime·profileloop, nil, nil, nil);
- runtime·stdcall(runtime·CloseHandle, 1, thread);
+ thread = runtime·stdcall6(runtime·CreateThread,
+ (uintptr)nil, (uintptr)nil, (uintptr)runtime·profileloop, (uintptr)nil, (uintptr)nil, (uintptr)nil);
+ runtime·stdcall2(runtime·SetThreadPriority, (uintptr)thread, THREAD_PRIORITY_HIGHEST);
+ runtime·stdcall1(runtime·CloseHandle, (uintptr)thread);
}
runtime·unlock(&lock);
@@ -482,15 +607,9 @@ runtime·resetcpuprofiler(int32 hz)
ms = 1;
due = ms * -10000;
}
- runtime·stdcall(runtime·SetWaitableTimer, 6,
- profiletimer, &due, (uintptr)ms, nil, nil, nil);
- runtime·atomicstore((uint32*)&m->profilehz, hz);
-}
-
-void
-os·sigpipe(void)
-{
- runtime·throw("too many writes on closed pipe");
+ runtime·stdcall6(runtime·SetWaitableTimer,
+ (uintptr)profiletimer, (uintptr)&due, ms, (uintptr)nil, (uintptr)nil, (uintptr)nil);
+ runtime·atomicstore((uint32*)&g->m->profilehz, hz);
}
uintptr
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
new file mode 100644
index 000000000..1528d2fd1
--- /dev/null
+++ b/src/runtime/os_windows.go
@@ -0,0 +1,58 @@
+// 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"
+
+type stdFunction *byte
+
+func stdcall0(fn stdFunction) uintptr
+func stdcall1(fn stdFunction, a0 uintptr) uintptr
+func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr
+func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr
+func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr
+func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr
+func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr
+func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr
+
+func asmstdcall(fn unsafe.Pointer)
+func getlasterror() uint32
+func setlasterror(err uint32)
+func usleep1(usec uint32)
+func netpollinit()
+func netpollopen(fd uintptr, pd *pollDesc) int32
+func netpollclose(fd uintptr) int32
+func netpollarm(pd *pollDesc, mode int)
+
+func os_sigpipe() {
+ gothrow("too many writes on closed pipe")
+}
+
+func sigpanic() {
+ g := getg()
+ if !canpanic(g) {
+ gothrow("unexpected signal during runtime execution")
+ }
+
+ switch uint32(g.sig) {
+ case _EXCEPTION_ACCESS_VIOLATION:
+ if g.sigcode1 < 0x1000 || g.paniconfault {
+ panicmem()
+ }
+ print("unexpected fault address ", hex(g.sigcode1), "\n")
+ gothrow("fault")
+ case _EXCEPTION_INT_DIVIDE_BY_ZERO:
+ panicdivide()
+ case _EXCEPTION_INT_OVERFLOW:
+ panicoverflow()
+ case _EXCEPTION_FLT_DENORMAL_OPERAND,
+ _EXCEPTION_FLT_DIVIDE_BY_ZERO,
+ _EXCEPTION_FLT_INEXACT_RESULT,
+ _EXCEPTION_FLT_OVERFLOW,
+ _EXCEPTION_FLT_UNDERFLOW:
+ panicfloat()
+ }
+ gothrow("fault")
+}
diff --git a/src/pkg/runtime/os_windows.h b/src/runtime/os_windows.h
index b64fa8873..d5d168d77 100644
--- a/src/pkg/runtime/os_windows.h
+++ b/src/runtime/os_windows.h
@@ -8,11 +8,15 @@ extern void *runtime·GetQueuedCompletionStatusEx;
// Call a Windows function with stdcall conventions,
// and switch to os stack during the call.
-#pragma varargck countpos runtime·stdcall 2
-#pragma varargck type runtime·stdcall void*
-#pragma varargck type runtime·stdcall uintptr
void runtime·asmstdcall(void *c);
-void *runtime·stdcall(void *fn, int32 count, ...);
+void *runtime·stdcall0(void *fn);
+void *runtime·stdcall1(void *fn, uintptr a0);
+void *runtime·stdcall2(void *fn, uintptr a0, uintptr a1);
+void *runtime·stdcall3(void *fn, uintptr a0, uintptr a1, uintptr a2);
+void *runtime·stdcall4(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3);
+void *runtime·stdcall5(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4);
+void *runtime·stdcall6(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5);
+void *runtime·stdcall7(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6);
uint32 runtime·getlasterror(void);
void runtime·setlasterror(uint32 err);
@@ -33,4 +37,6 @@ void runtime·install_exception_handler(void);
void runtime·remove_exception_handler(void);
// TODO(brainman): should not need those
-#define NSIG 65
+enum {
+ NSIG = 65,
+};
diff --git a/src/runtime/os_windows_386.c b/src/runtime/os_windows_386.c
new file mode 100644
index 000000000..9962f0dc2
--- /dev/null
+++ b/src/runtime/os_windows_386.c
@@ -0,0 +1,128 @@
+// 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.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+void
+runtime·dumpregs(Context *r)
+{
+ runtime·printf("eax %x\n", r->Eax);
+ runtime·printf("ebx %x\n", r->Ebx);
+ runtime·printf("ecx %x\n", r->Ecx);
+ runtime·printf("edx %x\n", r->Edx);
+ runtime·printf("edi %x\n", r->Edi);
+ runtime·printf("esi %x\n", r->Esi);
+ runtime·printf("ebp %x\n", r->Ebp);
+ runtime·printf("esp %x\n", r->Esp);
+ runtime·printf("eip %x\n", r->Eip);
+ runtime·printf("eflags %x\n", r->EFlags);
+ runtime·printf("cs %x\n", r->SegCs);
+ runtime·printf("fs %x\n", r->SegFs);
+ runtime·printf("gs %x\n", r->SegGs);
+}
+
+bool
+runtime·isgoexception(ExceptionRecord *info, Context *r)
+{
+ extern byte runtime·text[], runtime·etext[];
+
+ // Only handle exception if executing instructions in Go binary
+ // (not Windows library code).
+ if(r->Eip < (uint32)runtime·text || (uint32)runtime·etext < r->Eip)
+ return false;
+
+ if(!runtime·issigpanic(info->ExceptionCode))
+ return false;
+
+ return true;
+}
+
+// Called by sigtramp from Windows VEH handler.
+// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
+// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
+uint32
+runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp)
+{
+ uintptr *sp;
+
+ if(!runtime·isgoexception(info, r))
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ // 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 = info->ExceptionCode;
+ gp->sigcode0 = info->ExceptionInformation[0];
+ gp->sigcode1 = info->ExceptionInformation[1];
+ gp->sigpc = r->Eip;
+
+ // Only push runtime·sigpanic if r->eip != 0.
+ // If r->eip == 0, probably panicked because of a
+ // call to a nil func. Not pushing that onto sp will
+ // make the trace look like a call to runtime·sigpanic instead.
+ // (Otherwise the trace will end at runtime·sigpanic and we
+ // won't get to see who faulted.)
+ if(r->Eip != 0) {
+ sp = (uintptr*)r->Esp;
+ *--sp = r->Eip;
+ r->Esp = (uintptr)sp;
+ }
+ r->Eip = (uintptr)runtime·sigpanic;
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+
+// lastcontinuehandler is reached, because runtime cannot handle
+// current exception. lastcontinuehandler will print crash info and exit.
+uint32
+runtime·lastcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
+{
+ bool crash;
+
+ if(runtime·panicking) // traceback already printed
+ runtime·exit(2);
+ runtime·panicking = 1;
+
+ runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode,
+ (uintptr)info->ExceptionInformation[0], (uintptr)info->ExceptionInformation[1], (uintptr)r->Eip);
+
+ runtime·printf("PC=%x\n", r->Eip);
+ if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
+ runtime·printf("signal arrived during cgo execution\n");
+ gp = g->m->lockedg;
+ }
+ runtime·printf("\n");
+
+ if(runtime·gotraceback(&crash)){
+ runtime·tracebacktrap(r->Eip, r->Esp, 0, gp);
+ runtime·tracebackothers(gp);
+ runtime·dumpregs(r);
+ }
+
+ if(crash)
+ runtime·crash();
+
+ runtime·exit(2);
+ return 0; // not reached
+}
+
+void
+runtime·sigenable(uint32 sig)
+{
+ USED(sig);
+}
+
+void
+runtime·sigdisable(uint32 sig)
+{
+ USED(sig);
+}
+
+void
+runtime·dosigprof(Context *r, G *gp, M *mp)
+{
+ runtime·sigprof((uint8*)r->Eip, (uint8*)r->Esp, nil, gp, mp);
+}
diff --git a/src/runtime/os_windows_386.go b/src/runtime/os_windows_386.go
new file mode 100644
index 000000000..86a1906c0
--- /dev/null
+++ b/src/runtime/os_windows_386.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 runtime
+
+// contextPC returns the EIP (program counter) register from the context.
+func contextPC(r *context) uintptr { return uintptr(r.eip) }
+
+// contextSP returns the ESP (stack pointer) register from the context.
+func contextSP(r *context) uintptr { return uintptr(r.esp) }
diff --git a/src/runtime/os_windows_amd64.c b/src/runtime/os_windows_amd64.c
new file mode 100644
index 000000000..e4617e4ce
--- /dev/null
+++ b/src/runtime/os_windows_amd64.c
@@ -0,0 +1,150 @@
+// 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 "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+void
+runtime·dumpregs(Context *r)
+{
+ runtime·printf("rax %X\n", r->Rax);
+ runtime·printf("rbx %X\n", r->Rbx);
+ runtime·printf("rcx %X\n", r->Rcx);
+ runtime·printf("rdx %X\n", r->Rdx);
+ runtime·printf("rdi %X\n", r->Rdi);
+ runtime·printf("rsi %X\n", r->Rsi);
+ runtime·printf("rbp %X\n", r->Rbp);
+ runtime·printf("rsp %X\n", r->Rsp);
+ runtime·printf("r8 %X\n", r->R8 );
+ runtime·printf("r9 %X\n", r->R9 );
+ runtime·printf("r10 %X\n", r->R10);
+ runtime·printf("r11 %X\n", r->R11);
+ runtime·printf("r12 %X\n", r->R12);
+ runtime·printf("r13 %X\n", r->R13);
+ runtime·printf("r14 %X\n", r->R14);
+ runtime·printf("r15 %X\n", r->R15);
+ runtime·printf("rip %X\n", r->Rip);
+ runtime·printf("rflags %X\n", r->EFlags);
+ runtime·printf("cs %X\n", (uint64)r->SegCs);
+ runtime·printf("fs %X\n", (uint64)r->SegFs);
+ runtime·printf("gs %X\n", (uint64)r->SegGs);
+}
+
+bool
+runtime·isgoexception(ExceptionRecord *info, Context *r)
+{
+ extern byte runtime·text[], runtime·etext[];
+
+ // Only handle exception if executing instructions in Go binary
+ // (not Windows library code).
+ if(r->Rip < (uint64)runtime·text || (uint64)runtime·etext < r->Rip)
+ return false;
+
+ if(!runtime·issigpanic(info->ExceptionCode))
+ return false;
+
+ return true;
+}
+
+// Called by sigtramp from Windows VEH handler.
+// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
+// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
+uint32
+runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp)
+{
+ uintptr *sp;
+
+ if(!runtime·isgoexception(info, r))
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ // 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 = info->ExceptionCode;
+ gp->sigcode0 = info->ExceptionInformation[0];
+ gp->sigcode1 = info->ExceptionInformation[1];
+ gp->sigpc = r->Rip;
+
+ // Only push runtime·sigpanic if r->rip != 0.
+ // If r->rip == 0, probably panicked because of a
+ // call to a nil func. Not pushing that onto sp will
+ // make the trace look like a call to runtime·sigpanic instead.
+ // (Otherwise the trace will end at runtime·sigpanic and we
+ // won't get to see who faulted.)
+ if(r->Rip != 0) {
+ sp = (uintptr*)r->Rsp;
+ *--sp = r->Rip;
+ r->Rsp = (uintptr)sp;
+ }
+ r->Rip = (uintptr)runtime·sigpanic;
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+
+// It seems Windows searches ContinueHandler's list even
+// if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION.
+// firstcontinuehandler will stop that search,
+// if exceptionhandler did the same earlier.
+uint32
+runtime·firstcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
+{
+ USED(gp);
+ if(!runtime·isgoexception(info, r))
+ return EXCEPTION_CONTINUE_SEARCH;
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+
+// lastcontinuehandler is reached, because runtime cannot handle
+// current exception. lastcontinuehandler will print crash info and exit.
+uint32
+runtime·lastcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
+{
+ bool crash;
+
+ if(runtime·panicking) // traceback already printed
+ runtime·exit(2);
+ runtime·panicking = 1;
+
+ runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode,
+ info->ExceptionInformation[0], info->ExceptionInformation[1], r->Rip);
+
+
+ runtime·printf("PC=%X\n", r->Rip);
+ if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
+ runtime·printf("signal arrived during cgo execution\n");
+ gp = g->m->lockedg;
+ }
+ runtime·printf("\n");
+
+ if(runtime·gotraceback(&crash)){
+ runtime·tracebacktrap(r->Rip, r->Rsp, 0, gp);
+ runtime·tracebackothers(gp);
+ runtime·dumpregs(r);
+ }
+
+ if(crash)
+ runtime·crash();
+
+ runtime·exit(2);
+ return 0; // not reached
+}
+
+void
+runtime·sigenable(uint32 sig)
+{
+ USED(sig);
+}
+
+void
+runtime·sigdisable(uint32 sig)
+{
+ USED(sig);
+}
+
+void
+runtime·dosigprof(Context *r, G *gp, M *mp)
+{
+ runtime·sigprof((uint8*)r->Rip, (uint8*)r->Rsp, nil, gp, mp);
+}
diff --git a/src/runtime/os_windows_amd64.go b/src/runtime/os_windows_amd64.go
new file mode 100644
index 000000000..3f4d4d07c
--- /dev/null
+++ b/src/runtime/os_windows_amd64.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 runtime
+
+// contextPC returns the RIP (program counter) register from the context.
+func contextPC(r *context) uintptr { return uintptr(r.rip) }
+
+// contextSP returns the RSP (stack pointer) register from the context.
+func contextSP(r *context) uintptr { return uintptr(r.rsp) }
diff --git a/src/runtime/panic.c b/src/runtime/panic.c
new file mode 100644
index 000000000..24eb6dbfe
--- /dev/null
+++ b/src/runtime/panic.c
@@ -0,0 +1,200 @@
+// 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.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "stack.h"
+#include "malloc.h"
+#include "textflag.h"
+
+// Code related to defer, panic and recover.
+
+// TODO: remove once code is moved to Go
+extern Defer* runtime·newdefer(int32 siz);
+extern runtime·freedefer(Defer *d);
+
+uint32 runtime·panicking;
+static Mutex paniclk;
+
+void
+runtime·deferproc_m(void)
+{
+ int32 siz;
+ FuncVal *fn;
+ uintptr argp;
+ uintptr callerpc;
+ Defer *d;
+
+ siz = g->m->scalararg[0];
+ fn = g->m->ptrarg[0];
+ argp = g->m->scalararg[1];
+ callerpc = g->m->scalararg[2];
+ g->m->ptrarg[0] = nil;
+ g->m->scalararg[1] = 0;
+
+ d = runtime·newdefer(siz);
+ if(d->panic != nil)
+ runtime·throw("deferproc: d->panic != nil after newdefer");
+ d->fn = fn;
+ d->pc = callerpc;
+ d->argp = argp;
+ runtime·memmove(d+1, (void*)argp, siz);
+}
+
+// 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.
+void
+runtime·recovery_m(G *gp)
+{
+ void *argp;
+ uintptr pc;
+
+ // Info about defer passed in G struct.
+ argp = (void*)gp->sigcode0;
+ pc = (uintptr)gp->sigcode1;
+
+ // d's arguments need to be in the stack.
+ if(argp != nil && ((uintptr)argp < gp->stack.lo || gp->stack.hi < (uintptr)argp)) {
+ runtime·printf("recover: %p not in [%p, %p]\n", argp, gp->stack.lo, gp->stack.hi);
+ runtime·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.
+ // The -2*sizeof(uintptr) makes up for the
+ // two extra words that are on the stack at
+ // each call to deferproc.
+ // (The pc we're returning to does pop pop
+ // before it tests the return value.)
+ // On the arm there are 2 saved LRs mixed in too.
+ if(thechar == '5')
+ gp->sched.sp = (uintptr)argp - 4*sizeof(uintptr);
+ else
+ gp->sched.sp = (uintptr)argp - 2*sizeof(uintptr);
+ gp->sched.pc = pc;
+ gp->sched.lr = 0;
+ gp->sched.ret = 1;
+ runtime·gogo(&gp->sched);
+}
+
+void
+runtime·startpanic_m(void)
+{
+ if(runtime·mheap.cachealloc.size == 0) { // very early
+ runtime·printf("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 = runtime·allocmcache();
+ switch(g->m->dying) {
+ case 0:
+ g->m->dying = 1;
+ if(g != nil) {
+ g->writebuf.array = nil;
+ g->writebuf.len = 0;
+ g->writebuf.cap = 0;
+ }
+ runtime·xadd(&runtime·panicking, 1);
+ runtime·lock(&paniclk);
+ if(runtime·debug.schedtrace > 0 || runtime·debug.scheddetail > 0)
+ runtime·schedtrace(true);
+ runtime·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;
+ runtime·printf("panic during panic\n");
+ runtime·dopanic(0);
+ runtime·exit(3);
+ case 2:
+ // This is a genuine bug in the runtime, we couldn't even
+ // print the stack trace successfully.
+ g->m->dying = 3;
+ runtime·printf("stack trace unavailable\n");
+ runtime·exit(4);
+ default:
+ // Can't even print! Just exit.
+ runtime·exit(5);
+ }
+}
+
+void
+runtime·dopanic_m(void)
+{
+ G *gp;
+ uintptr sp, pc;
+ static bool didothers;
+ bool crash;
+ int32 t;
+
+ gp = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ pc = g->m->scalararg[0];
+ sp = g->m->scalararg[1];
+ g->m->scalararg[1] = 0;
+ if(gp->sig != 0)
+ runtime·printf("[signal %x code=%p addr=%p pc=%p]\n",
+ gp->sig, gp->sigcode0, gp->sigcode1, gp->sigpc);
+
+ if((t = runtime·gotraceback(&crash)) > 0){
+ if(gp != gp->m->g0) {
+ runtime·printf("\n");
+ runtime·goroutineheader(gp);
+ runtime·traceback(pc, sp, 0, gp);
+ } else if(t >= 2 || g->m->throwing > 0) {
+ runtime·printf("\nruntime stack:\n");
+ runtime·traceback(pc, sp, 0, gp);
+ }
+ if(!didothers) {
+ didothers = true;
+ runtime·tracebackothers(gp);
+ }
+ }
+ runtime·unlock(&paniclk);
+ if(runtime·xadd(&runtime·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.
+ static Mutex deadlock;
+ runtime·lock(&deadlock);
+ runtime·lock(&deadlock);
+ }
+
+ if(crash)
+ runtime·crash();
+
+ runtime·exit(2);
+}
+
+#pragma textflag NOSPLIT
+bool
+runtime·canpanic(G *gp)
+{
+ M *m;
+ uint32 status;
+
+ // 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.
+ 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->gcing != 0 || m->dying != 0)
+ return false;
+ status = runtime·readgstatus(gp);
+ if((status&~Gscan) != Grunning || gp->syscallsp != 0)
+ return false;
+#ifdef GOOS_windows
+ if(m->libcallsp != 0)
+ return false;
+#endif
+ return true;
+}
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
new file mode 100644
index 000000000..685ff5ca0
--- /dev/null
+++ b/src/runtime/panic.go
@@ -0,0 +1,505 @@
+// 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 indexError = error(errorString("index out of range"))
+
+func panicindex() {
+ panic(indexError)
+}
+
+var sliceError = error(errorString("slice bounds out of range"))
+
+func panicslice() {
+ panic(sliceError)
+}
+
+var divideError = error(errorString("integer divide by zero"))
+
+func panicdivide() {
+ panic(divideError)
+}
+
+var overflowError = error(errorString("integer overflow"))
+
+func panicoverflow() {
+ panic(overflowError)
+}
+
+var floatError = error(errorString("floating point error"))
+
+func panicfloat() {
+ panic(floatError)
+}
+
+var memoryError = error(errorString("invalid memory address or nil pointer dereference"))
+
+func panicmem() {
+ panic(memoryError)
+}
+
+func throwreturn() {
+ gothrow("no return at end of a typed function - compiler is broken")
+}
+
+func throwinit() {
+ gothrow("recursive call during initialization - linker skew")
+}
+
+// Create a new deferred function fn with siz bytes of arguments.
+// The compiler turns a defer statement into a call to this.
+//go:nosplit
+func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn
+ // the arguments of fn are in a perilous state. The stack map
+ // for deferproc does not describe them. So we can't let garbage
+ // collection or stack copying trigger until we've copied them out
+ // to somewhere safe. deferproc_m does that. Until deferproc_m,
+ // we can only call nosplit routines.
+ argp := uintptr(unsafe.Pointer(&fn))
+ argp += unsafe.Sizeof(fn)
+ if GOARCH == "arm" {
+ argp += ptrSize // skip caller's saved link register
+ }
+ mp := acquirem()
+ mp.scalararg[0] = uintptr(siz)
+ mp.ptrarg[0] = unsafe.Pointer(fn)
+ mp.scalararg[1] = argp
+ mp.scalararg[2] = getcallerpc(unsafe.Pointer(&siz))
+
+ if mp.curg != getg() {
+ // go code on the m stack can't defer
+ gothrow("defer on m")
+ }
+
+ onM(deferproc_m)
+
+ releasem(mp)
+
+ // deferproc returns 0 normally.
+ // a deferred func that stops a panic
+ // makes the deferproc return 1.
+ // the code the compiler generates always
+ // checks the return value and jumps to the
+ // end of the function if deferproc returns != 0.
+ return0()
+ // No code can go here - the C return register has
+ // been set and must not be clobbered.
+}
+
+// Small malloc size classes >= 16 are the multiples of 16: 16, 32, 48, 64, 80, 96, 112, 128, 144, ...
+// Each P holds a pool for defers with small arg sizes.
+// Assign defer allocations to pools by rounding to 16, to match malloc size classes.
+
+const (
+ deferHeaderSize = unsafe.Sizeof(_defer{})
+ minDeferAlloc = (deferHeaderSize + 15) &^ 15
+ minDeferArgs = minDeferAlloc - deferHeaderSize
+)
+
+// defer size class for arg size sz
+//go:nosplit
+func deferclass(siz uintptr) uintptr {
+ if siz <= minDeferArgs {
+ return 0
+ }
+ return (siz - minDeferArgs + 15) / 16
+}
+
+// total size of memory block for defer with arg size sz
+func totaldefersize(siz uintptr) uintptr {
+ if siz <= minDeferArgs {
+ return minDeferAlloc
+ }
+ return deferHeaderSize + siz
+}
+
+// Ensure that defer arg sizes that map to the same defer size class
+// also map to the same malloc size class.
+func testdefersizes() {
+ var m [len(p{}.deferpool)]int32
+
+ for i := range m {
+ m[i] = -1
+ }
+ for i := uintptr(0); ; i++ {
+ defersc := deferclass(i)
+ if defersc >= uintptr(len(m)) {
+ break
+ }
+ siz := goroundupsize(totaldefersize(i))
+ if m[defersc] < 0 {
+ m[defersc] = int32(siz)
+ continue
+ }
+ if m[defersc] != int32(siz) {
+ print("bad defer size class: i=", i, " siz=", siz, " defersc=", defersc, "\n")
+ gothrow("bad defer size class")
+ }
+ }
+}
+
+// The arguments associated with a deferred call are stored
+// immediately after the _defer header in memory.
+//go:nosplit
+func deferArgs(d *_defer) unsafe.Pointer {
+ return add(unsafe.Pointer(d), unsafe.Sizeof(*d))
+}
+
+var deferType *_type // type of _defer struct
+
+func init() {
+ var x interface{}
+ x = (*_defer)(nil)
+ deferType = (*(**ptrtype)(unsafe.Pointer(&x))).elem
+}
+
+// Allocate a Defer, usually using per-P pool.
+// Each defer must be released with freedefer.
+// Note: runs on M stack
+func newdefer(siz int32) *_defer {
+ var d *_defer
+ sc := deferclass(uintptr(siz))
+ mp := acquirem()
+ if sc < uintptr(len(p{}.deferpool)) {
+ pp := mp.p
+ d = pp.deferpool[sc]
+ if d != nil {
+ pp.deferpool[sc] = d.link
+ }
+ }
+ if d == nil {
+ // Allocate new defer+args.
+ total := goroundupsize(totaldefersize(uintptr(siz)))
+ d = (*_defer)(mallocgc(total, deferType, 0))
+ }
+ d.siz = siz
+ gp := mp.curg
+ d.link = gp._defer
+ gp._defer = d
+ releasem(mp)
+ return d
+}
+
+// Free the given defer.
+// The defer cannot be used after this call.
+//go:nosplit
+func freedefer(d *_defer) {
+ if d._panic != nil {
+ freedeferpanic()
+ }
+ if d.fn != nil {
+ freedeferfn()
+ }
+ sc := deferclass(uintptr(d.siz))
+ if sc < uintptr(len(p{}.deferpool)) {
+ mp := acquirem()
+ pp := mp.p
+ *d = _defer{}
+ d.link = pp.deferpool[sc]
+ pp.deferpool[sc] = d
+ releasem(mp)
+ }
+}
+
+// Separate function so that it can split stack.
+// Windows otherwise runs out of stack space.
+func freedeferpanic() {
+ // _panic must be cleared before d is unlinked from gp.
+ gothrow("freedefer with d._panic != nil")
+}
+
+func freedeferfn() {
+ // fn must be cleared before d is unlinked from gp.
+ gothrow("freedefer with d.fn != nil")
+}
+
+// Run a deferred function if there is one.
+// The compiler inserts a call to this at the end of any
+// function which calls defer.
+// If there is a deferred function, this will call runtime·jmpdefer,
+// which will jump to the deferred function such that it appears
+// to have been called by the caller of deferreturn at the point
+// just before deferreturn was called. The effect is that deferreturn
+// is called again and again until there are no more deferred functions.
+// Cannot split the stack because we reuse the caller's frame to
+// call the deferred function.
+
+// The single argument isn't actually used - it just has its address
+// taken so it can be matched against pending defers.
+//go:nosplit
+func deferreturn(arg0 uintptr) {
+ gp := getg()
+ d := gp._defer
+ if d == nil {
+ return
+ }
+ argp := uintptr(unsafe.Pointer(&arg0))
+ if d.argp != argp {
+ return
+ }
+
+ // Moving arguments around.
+ // Do not allow preemption here, because the garbage collector
+ // won't know the form of the arguments until the jmpdefer can
+ // flip the PC over to fn.
+ mp := acquirem()
+ memmove(unsafe.Pointer(argp), deferArgs(d), uintptr(d.siz))
+ fn := d.fn
+ d.fn = nil
+ gp._defer = d.link
+ freedefer(d)
+ releasem(mp)
+ jmpdefer(fn, argp)
+}
+
+// Goexit terminates the goroutine that calls it. No other goroutine is affected.
+// Goexit runs all deferred calls before terminating the goroutine. Because Goexit
+// is not panic, however, any recover calls in those deferred functions will return nil.
+//
+// Calling Goexit from the main goroutine terminates that goroutine
+// without func main returning. Since func main has not returned,
+// the program continues execution of other goroutines.
+// If all other goroutines exit, the program crashes.
+func Goexit() {
+ // Run all deferred functions for the current goroutine.
+ // This code is similar to gopanic, see that implementation
+ // for detailed comments.
+ gp := getg()
+ for {
+ d := gp._defer
+ if d == nil {
+ break
+ }
+ if d.started {
+ if d._panic != nil {
+ d._panic.aborted = true
+ d._panic = nil
+ }
+ d.fn = nil
+ gp._defer = d.link
+ freedefer(d)
+ continue
+ }
+ d.started = true
+ reflectcall(unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
+ if gp._defer != d {
+ gothrow("bad defer entry in Goexit")
+ }
+ d._panic = nil
+ d.fn = nil
+ gp._defer = d.link
+ freedefer(d)
+ // Note: we ignore recovers here because Goexit isn't a panic
+ }
+ goexit()
+}
+
+func canpanic(*g) bool
+
+// Print all currently active panics. Used when crashing.
+func printpanics(p *_panic) {
+ if p.link != nil {
+ printpanics(p.link)
+ print("\t")
+ }
+ print("panic: ")
+ printany(p.arg)
+ if p.recovered {
+ print(" [recovered]")
+ }
+ print("\n")
+}
+
+// The implementation of the predeclared function panic.
+func gopanic(e interface{}) {
+ gp := getg()
+ if gp.m.curg != gp {
+ gothrow("panic on m stack")
+ }
+
+ // m.softfloat is set during software floating point.
+ // It increments m.locks to avoid preemption.
+ // We moved the memory loads out, so there shouldn't be
+ // any reason for it to panic anymore.
+ if gp.m.softfloat != 0 {
+ gp.m.locks--
+ gp.m.softfloat = 0
+ gothrow("panic during softfloat")
+ }
+ if gp.m.mallocing != 0 {
+ print("panic: ")
+ printany(e)
+ print("\n")
+ gothrow("panic during malloc")
+ }
+ if gp.m.gcing != 0 {
+ print("panic: ")
+ printany(e)
+ print("\n")
+ gothrow("panic during gc")
+ }
+ if gp.m.locks != 0 {
+ print("panic: ")
+ printany(e)
+ print("\n")
+ gothrow("panic holding locks")
+ }
+
+ var p _panic
+ p.arg = e
+ p.link = gp._panic
+ gp._panic = (*_panic)(noescape(unsafe.Pointer(&p)))
+
+ for {
+ d := gp._defer
+ if d == nil {
+ break
+ }
+
+ // If defer was started by earlier panic or Goexit (and, since we're back here, that triggered a new panic),
+ // take defer off list. The earlier panic or Goexit will not continue running.
+ if d.started {
+ if d._panic != nil {
+ d._panic.aborted = true
+ }
+ d._panic = nil
+ d.fn = nil
+ gp._defer = d.link
+ freedefer(d)
+ continue
+ }
+
+ // Mark defer as started, but keep on list, so that traceback
+ // can find and update the defer's argument frame if stack growth
+ // or a garbage collection hapens before reflectcall starts executing d.fn.
+ d.started = true
+
+ // 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)))
+
+ p.argp = unsafe.Pointer(getargp(0))
+ reflectcall(unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
+ p.argp = nil
+
+ // reflectcall did not panic. Remove d.
+ if gp._defer != d {
+ gothrow("bad defer entry in panic")
+ }
+ d._panic = nil
+ d.fn = nil
+ gp._defer = d.link
+
+ // trigger shrinkage to test stack copy. See stack_test.go:TestStackPanic
+ //GC()
+
+ pc := d.pc
+ argp := unsafe.Pointer(d.argp) // must be pointer so it gets adjusted during stack copy
+ freedefer(d)
+ if p.recovered {
+ gp._panic = p.link
+ // Aborted panics are marked but remain on the g.panic list.
+ // Remove them from the list.
+ for gp._panic != nil && gp._panic.aborted {
+ gp._panic = gp._panic.link
+ }
+ if gp._panic == nil { // must be done with signal
+ gp.sig = 0
+ }
+ // Pass information about recovering frame to recovery.
+ gp.sigcode0 = uintptr(argp)
+ gp.sigcode1 = pc
+ mcall(recovery_m)
+ gothrow("recovery failed") // mcall should not return
+ }
+ }
+
+ // ran out of deferred calls - old-school panic now
+ startpanic()
+ printpanics(gp._panic)
+ dopanic(0) // should not return
+ *(*int)(nil) = 0 // not reached
+}
+
+// getargp returns the location where the caller
+// writes outgoing function call arguments.
+//go:nosplit
+func getargp(x int) uintptr {
+ // x is an argument mainly so that we can return its address.
+ // However, we need to make the function complex enough
+ // that it won't be inlined. We always pass x = 0, so this code
+ // does nothing other than keep the compiler from thinking
+ // the function is simple enough to inline.
+ if x > 0 {
+ return getcallersp(unsafe.Pointer(&x)) * 0
+ }
+ return uintptr(noescape(unsafe.Pointer(&x)))
+}
+
+// The implementation of the predeclared function recover.
+// Cannot split the stack because it needs to reliably
+// find the stack segment of its caller.
+//
+// TODO(rsc): Once we commit to CopyStackAlways,
+// this doesn't need to be nosplit.
+//go:nosplit
+func gorecover(argp uintptr) interface{} {
+ // Must be in a function running as part of a deferred call during the panic.
+ // Must be called from the topmost function of the call
+ // (the function used in the defer statement).
+ // p.argp is the argument pointer of that topmost deferred function call.
+ // Compare against argp reported by caller.
+ // If they match, the caller is the one who can recover.
+ gp := getg()
+ p := gp._panic
+ if p != nil && !p.recovered && argp == uintptr(p.argp) {
+ p.recovered = true
+ return p.arg
+ }
+ return nil
+}
+
+//go:nosplit
+func startpanic() {
+ onM_signalok(startpanic_m)
+}
+
+//go:nosplit
+func dopanic(unused int) {
+ gp := getg()
+ mp := acquirem()
+ mp.ptrarg[0] = unsafe.Pointer(gp)
+ mp.scalararg[0] = getcallerpc((unsafe.Pointer)(&unused))
+ mp.scalararg[1] = getcallersp((unsafe.Pointer)(&unused))
+ onM_signalok(dopanic_m) // should never return
+ *(*int)(nil) = 0
+}
+
+//go:nosplit
+func throw(s *byte) {
+ gp := getg()
+ if gp.m.throwing == 0 {
+ gp.m.throwing = 1
+ }
+ startpanic()
+ print("fatal error: ", gostringnocopy(s), "\n")
+ dopanic(0)
+ *(*int)(nil) = 0 // not reached
+}
+
+//go:nosplit
+func gothrow(s string) {
+ gp := getg()
+ if gp.m.throwing == 0 {
+ gp.m.throwing = 1
+ }
+ startpanic()
+ print("fatal error: ", s, "\n")
+ dopanic(0)
+ *(*int)(nil) = 0 // not reached
+}
diff --git a/src/pkg/runtime/parfor.c b/src/runtime/parfor.c
index 4706e0a43..e44956840 100644
--- a/src/pkg/runtime/parfor.c
+++ b/src/runtime/parfor.c
@@ -6,6 +6,7 @@
#include "runtime.h"
#include "arch_GOARCH.h"
+#include "malloc.h"
struct ParForThread
{
@@ -20,19 +21,6 @@ struct ParForThread
byte pad[CacheLineSize];
};
-ParFor*
-runtime·parforalloc(uint32 nthrmax)
-{
- ParFor *desc;
-
- // The ParFor object is followed by CacheLineSize padding
- // and then nthrmax ParForThread.
- desc = (ParFor*)runtime·malloc(sizeof(ParFor) + CacheLineSize + nthrmax * sizeof(ParForThread));
- desc->thr = (ParForThread*)((byte*)(desc+1) + CacheLineSize);
- desc->nthrmax = nthrmax;
- return desc;
-}
-
void
runtime·parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32))
{
@@ -192,8 +180,47 @@ exit:
// For testing from Go.
void
-runtime·parforiters(ParFor *desc, uintptr tid, uintptr *start, uintptr *end)
+runtime·newparfor_m(void)
{
- *start = (uint32)desc->thr[tid].pos;
- *end = (uint32)(desc->thr[tid].pos>>32);
+ g->m->ptrarg[0] = runtime·parforalloc(g->m->scalararg[0]);
+}
+
+void
+runtime·parforsetup_m(void)
+{
+ ParFor *desc;
+ void *ctx;
+ void (*body)(ParFor*, uint32);
+
+ desc = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ ctx = g->m->ptrarg[1];
+ g->m->ptrarg[1] = nil;
+ body = g->m->ptrarg[2];
+ g->m->ptrarg[2] = nil;
+
+ runtime·parforsetup(desc, g->m->scalararg[0], g->m->scalararg[1], ctx, g->m->scalararg[2], body);
+}
+
+void
+runtime·parfordo_m(void)
+{
+ ParFor *desc;
+
+ desc = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ runtime·parfordo(desc);
+}
+
+void
+runtime·parforiters_m(void)
+{
+ ParFor *desc;
+ uintptr tid;
+
+ desc = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ tid = g->m->scalararg[0];
+ g->m->scalararg[0] = desc->thr[tid].pos;
+ g->m->scalararg[1] = desc->thr[tid].pos>>32;
}
diff --git a/src/pkg/runtime/parfor_test.go b/src/runtime/parfor_test.go
index de64285b8..de64285b8 100644
--- a/src/pkg/runtime/parfor_test.go
+++ b/src/runtime/parfor_test.go
diff --git a/src/runtime/pprof/mprof_test.go b/src/runtime/pprof/mprof_test.go
new file mode 100644
index 000000000..ebf53dd66
--- /dev/null
+++ b/src/runtime/pprof/mprof_test.go
@@ -0,0 +1,99 @@
+// 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 pprof_test
+
+import (
+ "bytes"
+ "fmt"
+ "regexp"
+ "runtime"
+ . "runtime/pprof"
+ "testing"
+ "unsafe"
+)
+
+var memSink interface{}
+
+func allocateTransient1M() {
+ for i := 0; i < 1024; i++ {
+ memSink = &struct{ x [1024]byte }{}
+ }
+}
+
+func allocateTransient2M() {
+ // prevent inlining
+ if memSink == nil {
+ panic("bad")
+ }
+ memSink = make([]byte, 2<<20)
+}
+
+type Obj32 struct {
+ link *Obj32
+ pad [32 - unsafe.Sizeof(uintptr(0))]byte
+}
+
+var persistentMemSink *Obj32
+
+func allocatePersistent1K() {
+ for i := 0; i < 32; i++ {
+ // Can't use slice because that will introduce implicit allocations.
+ obj := &Obj32{link: persistentMemSink}
+ persistentMemSink = obj
+ }
+}
+
+var memoryProfilerRun = 0
+
+func TestMemoryProfiler(t *testing.T) {
+ // Disable sampling, otherwise it's difficult to assert anything.
+ oldRate := runtime.MemProfileRate
+ runtime.MemProfileRate = 1
+ defer func() {
+ runtime.MemProfileRate = oldRate
+ }()
+
+ // Allocate a meg to ensure that mcache.next_sample is updated to 1.
+ for i := 0; i < 1024; i++ {
+ memSink = make([]byte, 1024)
+ }
+
+ // Do the interesting allocations.
+ allocateTransient1M()
+ allocateTransient2M()
+ allocatePersistent1K()
+ memSink = nil
+
+ runtime.GC() // materialize stats
+ var buf bytes.Buffer
+ if err := Lookup("heap").WriteTo(&buf, 1); err != nil {
+ t.Fatalf("failed to write heap profile: %v", err)
+ }
+
+ memoryProfilerRun++
+
+ 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
+`, 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
+`, (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
+`, memoryProfilerRun, (2<<20)*memoryProfilerRun),
+ }
+
+ for _, test := range tests {
+ if !regexp.MustCompile(test).Match(buf.Bytes()) {
+ t.Fatalf("The entry did not match:\n%v\n\nProfile:\n%v\n", test, buf.String())
+ }
+ }
+}
diff --git a/src/pkg/runtime/pprof/pprof.go b/src/runtime/pprof/pprof.go
index 26aa0b8be..236de54f3 100644
--- a/src/pkg/runtime/pprof/pprof.go
+++ b/src/runtime/pprof/pprof.go
@@ -574,12 +574,6 @@ func StartCPUProfile(w io.Writer) error {
// each client to specify the frequency, we hard code it.
const hz = 100
- // Avoid queueing behind StopCPUProfile.
- // Could use TryLock instead if we had it.
- if cpu.profiling {
- return fmt.Errorf("cpu profiling already in use")
- }
-
cpu.Lock()
defer cpu.Unlock()
if cpu.done == nil {
diff --git a/src/pkg/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index aba538e75..8677cb30c 100644
--- a/src/pkg/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -9,7 +9,6 @@ package pprof_test
import (
"bytes"
"fmt"
- "hash/crc32"
"math/big"
"os/exec"
"regexp"
@@ -22,35 +21,65 @@ import (
"unsafe"
)
-func TestCPUProfile(t *testing.T) {
- buf := make([]byte, 100000)
- testCPUProfile(t, []string{"crc32.ChecksumIEEE"}, func() {
- // This loop takes about a quarter second on a 2 GHz laptop.
- // We only need to get one 100 Hz clock tick, so we've got
- // a 25x safety buffer.
- for i := 0; i < 1000; i++ {
- crc32.ChecksumIEEE(buf)
+func cpuHogger(f func()) {
+ // We only need to get one 100 Hz clock tick, so we've got
+ // a 25x 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.
+ t0 := time.Now()
+ for i := 0; i < 500 || time.Since(t0) < 250*time.Millisecond; i++ {
+ f()
+ }
+}
+
+var (
+ salt1 = 0
+ salt2 = 0
+)
+
+// The actual CPU hogging function.
+// Must not call other functions nor access heap/globals in the loop,
+// otherwise under race detector the samples will be in the race runtime.
+func cpuHog1() {
+ foo := salt1
+ for i := 0; i < 1e5; i++ {
+ if foo > 0 {
+ foo *= foo
+ } else {
+ foo *= foo + 1
}
+ }
+ salt1 = foo
+}
+
+func cpuHog2() {
+ foo := salt2
+ for i := 0; i < 1e5; i++ {
+ if foo > 0 {
+ foo *= foo
+ } else {
+ foo *= foo + 2
+ }
+ }
+ salt2 = foo
+}
+
+func TestCPUProfile(t *testing.T) {
+ testCPUProfile(t, []string{"runtime/pprof_test.cpuHog1"}, func() {
+ cpuHogger(cpuHog1)
})
}
func TestCPUProfileMultithreaded(t *testing.T) {
- buf := make([]byte, 100000)
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
- testCPUProfile(t, []string{"crc32.ChecksumIEEE", "crc32.Update"}, func() {
+ testCPUProfile(t, []string{"runtime/pprof_test.cpuHog1", "runtime/pprof_test.cpuHog2"}, func() {
c := make(chan int)
go func() {
- for i := 0; i < 2000; i++ {
- crc32.Update(0, crc32.IEEETable, buf)
- }
+ cpuHogger(cpuHog1)
c <- 1
}()
- // This loop takes about a quarter second on a 2 GHz laptop.
- // We only need to get one 100 Hz clock tick, so we've got
- // a 25x safety buffer.
- for i := 0; i < 2000; i++ {
- crc32.ChecksumIEEE(buf)
- }
+ cpuHogger(cpuHog2)
<-c
})
}
@@ -110,7 +139,7 @@ func testCPUProfile(t *testing.T, need []string, f func()) {
f()
StopCPUProfile()
- // Check that profile is well formed and contains ChecksumIEEE.
+ // Check that profile is well formed and contains need.
have := make([]uintptr, len(need))
parseProfile(t, prof.Bytes(), func(count uintptr, stk []uintptr) {
for _, pc := range stk {
@@ -220,7 +249,7 @@ func TestGoroutineSwitch(t *testing.T) {
// exists to record a PC without a traceback. Those are okay.
if len(stk) == 2 {
f := runtime.FuncForPC(stk[1])
- if f != nil && (f.Name() == "System" || f.Name() == "ExternalCode") {
+ if f != nil && (f.Name() == "System" || f.Name() == "ExternalCode" || f.Name() == "GC") {
return
}
}
@@ -281,39 +310,45 @@ func TestBlockProfile(t *testing.T) {
tests := [...]TestCase{
{"chan recv", blockChanRecv, `
[0-9]+ [0-9]+ @ 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\.chanrecv1\+0x[0-9,a-f]+ .*/src/pkg/runtime/chan.goc:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.blockChanRecv\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime\.chanrecv1\+0x[0-9,a-f]+ .*/src/runtime/chan.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockChanRecv\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
`},
{"chan send", blockChanSend, `
[0-9]+ [0-9]+ @ 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\.chansend1\+0x[0-9,a-f]+ .*/src/pkg/runtime/chan.goc:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.blockChanSend\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime\.chansend1\+0x[0-9,a-f]+ .*/src/runtime/chan.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockChanSend\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
`},
{"chan close", blockChanClose, `
[0-9]+ [0-9]+ @ 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\.chanrecv1\+0x[0-9,a-f]+ .*/src/pkg/runtime/chan.goc:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.blockChanClose\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime\.chanrecv1\+0x[0-9,a-f]+ .*/src/runtime/chan.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockChanClose\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
`},
{"select recv async", blockSelectRecvAsync, `
[0-9]+ [0-9]+ @ 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\.selectgo\+0x[0-9,a-f]+ .*/src/pkg/runtime/chan.goc:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.blockSelectRecvAsync\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime\.selectgo\+0x[0-9,a-f]+ .*/src/runtime/select.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockSelectRecvAsync\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
`},
{"select send sync", blockSelectSendSync, `
[0-9]+ [0-9]+ @ 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\.selectgo\+0x[0-9,a-f]+ .*/src/pkg/runtime/chan.goc:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.blockSelectSendSync\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime\.selectgo\+0x[0-9,a-f]+ .*/src/runtime/select.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockSelectSendSync\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
`},
{"mutex", blockMutex, `
[0-9]+ [0-9]+ @ 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]+ sync\.\(\*Mutex\)\.Lock\+0x[0-9,a-f]+ .*/src/pkg/sync/mutex\.go:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.blockMutex\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ sync\.\(\*Mutex\)\.Lock\+0x[0-9,a-f]+ .*/src/sync/mutex\.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockMutex\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+`},
+ {"cond", blockCond, `
+[0-9]+ [0-9]+ @ 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]+ sync\.\(\*Cond\)\.Wait\+0x[0-9,a-f]+ .*/src/sync/cond\.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockCond\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
`},
}
@@ -401,3 +436,17 @@ func blockMutex() {
}()
mu.Lock()
}
+
+func blockCond() {
+ var mu sync.Mutex
+ c := sync.NewCond(&mu)
+ mu.Lock()
+ go func() {
+ time.Sleep(blockDelay)
+ mu.Lock()
+ c.Signal()
+ mu.Unlock()
+ }()
+ c.Wait()
+ mu.Unlock()
+}
diff --git a/src/runtime/print1.go b/src/runtime/print1.go
new file mode 100644
index 000000000..8f8268873
--- /dev/null
+++ b/src/runtime/print1.go
@@ -0,0 +1,323 @@
+// 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 = sp.str
+ rp.len = uint(sp.len)
+ rp.cap = uint(sp.len)
+ return
+}
+
+// printf is only called from C code. It has no type information for the args,
+// but C stacks are ignored by the garbage collector anyway, so having
+// type information would not add anything.
+//go:nosplit
+func printf(s *byte) {
+ vprintf(gostringnocopy(s), add(unsafe.Pointer(&s), unsafe.Sizeof(s)))
+}
+
+// sprintf is only called from C code. It has no type information for the args,
+// but C stacks are ignored by the garbage collector anyway, so having
+// type information would not add anything.
+//go:nosplit
+func snprintf(dst *byte, n int32, s *byte) {
+ buf := (*[1 << 30]byte)(unsafe.Pointer(dst))[0:n:n]
+
+ gp := getg()
+ gp.writebuf = buf[0:0 : n-1] // leave room for NUL, this is called from C
+ vprintf(gostringnocopy(s), add(unsafe.Pointer(&s), unsafe.Sizeof(s)))
+ buf[len(gp.writebuf)] = '\x00'
+ gp.writebuf = nil
+}
+
+//var debuglock mutex
+
+// 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 {
+ write(2, unsafe.Pointer(&b[0]), int32(len(b)))
+ return
+ }
+
+ n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
+ gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
+}
+
+func prints(s *byte) {
+ b := (*[1 << 30]byte)(unsafe.Pointer(s))
+ for i := 0; ; i++ {
+ if b[i] == 0 {
+ gwrite(b[:i])
+ return
+ }
+ }
+}
+
+func printsp() {
+ print(" ")
+}
+
+func printnl() {
+ print("\n")
+}
+
+// Very simple printf. Only for debugging prints.
+// Do not add to this without checking with Rob.
+func vprintf(str string, arg unsafe.Pointer) {
+ //lock(&debuglock);
+
+ s := bytes(str)
+ start := 0
+ i := 0
+ for ; i < len(s); i++ {
+ if s[i] != '%' {
+ continue
+ }
+ if i > start {
+ gwrite(s[start:i])
+ }
+ if i++; i >= len(s) {
+ break
+ }
+ var siz uintptr
+ switch s[i] {
+ case 't', 'c':
+ siz = 1
+ case 'd', 'x': // 32-bit
+ arg = roundup(arg, 4)
+ siz = 4
+ case 'D', 'U', 'X', 'f': // 64-bit
+ arg = roundup(arg, unsafe.Sizeof(uintreg(0)))
+ siz = 8
+ case 'C':
+ arg = roundup(arg, unsafe.Sizeof(uintreg(0)))
+ siz = 16
+ case 'p', 's': // pointer-sized
+ arg = roundup(arg, unsafe.Sizeof(uintptr(0)))
+ siz = unsafe.Sizeof(uintptr(0))
+ case 'S': // pointer-aligned but bigger
+ arg = roundup(arg, unsafe.Sizeof(uintptr(0)))
+ siz = unsafe.Sizeof(string(""))
+ case 'a': // pointer-aligned but bigger
+ arg = roundup(arg, unsafe.Sizeof(uintptr(0)))
+ siz = unsafe.Sizeof([]byte{})
+ case 'i', 'e': // pointer-aligned but bigger
+ arg = roundup(arg, unsafe.Sizeof(uintptr(0)))
+ siz = unsafe.Sizeof(interface{}(nil))
+ }
+ switch s[i] {
+ case 'a':
+ printslice(*(*[]byte)(arg))
+ case 'c':
+ printbyte(*(*byte)(arg))
+ case 'd':
+ printint(int64(*(*int32)(arg)))
+ case 'D':
+ printint(int64(*(*int64)(arg)))
+ case 'e':
+ printeface(*(*interface{})(arg))
+ case 'f':
+ printfloat(*(*float64)(arg))
+ case 'C':
+ printcomplex(*(*complex128)(arg))
+ case 'i':
+ printiface(*(*fInterface)(arg))
+ case 'p':
+ printpointer(*(*unsafe.Pointer)(arg))
+ case 's':
+ prints(*(**byte)(arg))
+ case 'S':
+ printstring(*(*string)(arg))
+ case 't':
+ printbool(*(*bool)(arg))
+ case 'U':
+ printuint(*(*uint64)(arg))
+ case 'x':
+ printhex(uint64(*(*uint32)(arg)))
+ case 'X':
+ printhex(*(*uint64)(arg))
+ }
+ arg = add(arg, siz)
+ start = i + 1
+ }
+ if start < i {
+ gwrite(s[start:i])
+ }
+
+ //unlock(&debuglock);
+}
+
+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/pkg/runtime/proc.c b/src/runtime/proc.c
index de4f70153..8462c4b1d 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/runtime/proc.c
@@ -9,7 +9,8 @@
#include "stack.h"
#include "race.h"
#include "type.h"
-#include "../../cmd/ld/textflag.h"
+#include "mgc0.h"
+#include "textflag.h"
// Goroutine scheduler
// The scheduler's job is to distribute ready-to-run goroutines over worker threads.
@@ -23,53 +24,14 @@
//
// Design doc at http://golang.org/s/go11sched.
-typedef struct Sched Sched;
-struct Sched {
- Lock;
-
- uint64 goidgen;
-
- M* midle; // idle m's waiting for work
- int32 nmidle; // number of idle m's waiting for work
- int32 nmidlelocked; // number of locked m's waiting for work
- int32 mcount; // number of m's that have been created
- int32 maxmcount; // maximum number of m's allowed (or die)
-
- P* pidle; // idle P's
- uint32 npidle;
- uint32 nmspinning;
-
- // Global runnable queue.
- G* runqhead;
- G* runqtail;
- int32 runqsize;
-
- // Global cache of dead G's.
- Lock gflock;
- G* gfree;
-
- uint32 gcwaiting; // gc is waiting to run
- int32 stopwait;
- Note stopnote;
- uint32 sysmonwait;
- Note sysmonnote;
- uint64 lastpoll;
-
- int32 profilehz; // cpu profiling rate
-};
-
enum
{
- // The max value of GOMAXPROCS.
- // There are no fundamental restrictions on the value.
- MaxGomaxprocs = 1<<8,
-
// Number of goroutine ids to grab from runtime·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,
};
-Sched runtime·sched;
+SchedT runtime·sched;
int32 runtime·gomaxprocs;
uint32 runtime·needextram;
bool runtime·iscgo;
@@ -78,14 +40,16 @@ G runtime·g0; // idle goroutine for m0
G* runtime·lastg;
M* runtime·allm;
M* runtime·extram;
+P* runtime·allp[MaxGomaxprocs+1];
int8* runtime·goos;
int32 runtime·ncpu;
-static int32 newprocs;
+int32 runtime·newprocs;
-static Lock allglock; // the following vars are protected by this lock or by stoptheworld
+Mutex runtime·allglock; // the following vars are protected by this lock or by stoptheworld
G** runtime·allg;
+Slice runtime·allgs;
uintptr runtime·allglen;
-static uintptr allgcap;
+ForceGCState runtime·forcegc;
void runtime·mstart(void);
static void runqput(P*, G*);
@@ -111,7 +75,7 @@ static uint32 retake(int64);
static void incidlelocked(int32);
static void checkdead(void);
static void exitsyscall0(G*);
-static void park0(G*);
+void runtime·park_m(G*);
static void goexit0(G*);
static void gfput(P*, G*);
static G* gfget(P*);
@@ -126,7 +90,25 @@ static bool preemptall(void);
static bool preemptone(P*);
static bool exitsyscallfast(void);
static bool haveexperiment(int8*);
-static void allgadd(G*);
+void runtime·allgadd(G*);
+static void dropg(void);
+
+extern String runtime·buildVersion;
+
+// For cgo-using programs with external linking,
+// export "main" (defined in assembly) so that libc can handle basic
+// C runtime startup and call the Go program as if it were
+// the C main function.
+#pragma cgo_export_static main
+
+// Filled in by dynamic linker when Cgo is available.
+void (*_cgo_init)(void);
+void (*_cgo_malloc)(void);
+void (*_cgo_free)(void);
+
+// Copy for Go code.
+void* runtime·cgoMalloc;
+void* runtime·cgoFree;
// The bootstrap sequence is:
//
@@ -141,28 +123,24 @@ runtime·schedinit(void)
{
int32 n, procs;
byte *p;
- Eface i;
+
+ // raceinit must be the first call to race detector.
+ // In particular, it must be done before mallocinit below calls racemapshadow.
+ if(raceenabled)
+ g->racectx = runtime·raceinit();
runtime·sched.maxmcount = 10000;
- runtime·precisestack = true; // haveexperiment("precisestack");
+ runtime·tracebackinit();
runtime·symtabinit();
+ runtime·stackinit();
runtime·mallocinit();
- mcommoninit(m);
+ mcommoninit(g->m);
- // Initialize the itable value for newErrorCString,
- // so that the next time it gets called, possibly
- // in a fault during a garbage collection, it will not
- // need to allocated memory.
- runtime·newErrorCString(0, &i);
-
- // Initialize the cached gotraceback value, since
- // gotraceback calls getenv, which mallocs on Plan 9.
- runtime·gotraceback(nil);
-
runtime·goargs();
runtime·goenvs();
runtime·parsedebugvars();
+ runtime·gcinit();
runtime·sched.lastpoll = runtime·nanotime();
procs = 1;
@@ -172,174 +150,37 @@ runtime·schedinit(void)
n = MaxGomaxprocs;
procs = n;
}
- runtime·allp = runtime·malloc((MaxGomaxprocs+1)*sizeof(runtime·allp[0]));
procresize(procs);
- runtime·copystack = runtime·precisestack;
- p = runtime·getenv("GOCOPYSTACK");
- if(p != nil && !runtime·strcmp(p, (byte*)"0"))
- runtime·copystack = false;
-
- mstats.enablegc = 1;
+ if(runtime·buildVersion.str == nil) {
+ // Condition should never trigger. This code just serves
+ // to ensure runtime·buildVersion is kept in the resulting binary.
+ runtime·buildVersion.str = (uint8*)"unknown";
+ runtime·buildVersion.len = 7;
+ }
- if(raceenabled)
- g->racectx = runtime·raceinit();
+ runtime·cgoMalloc = _cgo_malloc;
+ runtime·cgoFree = _cgo_free;
}
-extern void main·init(void);
-extern void main·main(void);
-
-static FuncVal scavenger = {runtime·MHeap_Scavenger};
-
-static FuncVal initDone = { runtime·unlockOSThread };
-
-// The main goroutine.
-// Note: C frames in general are not copyable during stack growth, for two reasons:
-// 1) We don't know where in a frame to find pointers to other stack locations.
-// 2) There's no guarantee that globals or heap values do not point into the frame.
-//
-// The C frame for runtime.main is copyable, because:
-// 1) There are no pointers to other stack locations in the frame
-// (d.fn points at a global, d.link is nil, d.argp is -1).
-// 2) The only pointer into this frame is from the defer chain,
-// which is explicitly handled during stack copying.
void
-runtime·main(void)
+runtime·newsysmon(void)
{
- Defer d;
-
- // 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(sizeof(void*) == 8)
- runtime·maxstacksize = 1000000000;
- else
- runtime·maxstacksize = 250000000;
-
newm(sysmon, nil);
-
- // Lock the main goroutine onto this, the main OS thread,
- // during initialization. Most programs won't care, but a few
- // do require certain calls to be made by the main thread.
- // Those can arrange for main.main to run in the main thread
- // by calling runtime.LockOSThread during initialization
- // to preserve the lock.
- runtime·lockOSThread();
-
- // Defer unlock so that runtime.Goexit during init does the unlock too.
- d.fn = &initDone;
- d.siz = 0;
- d.link = g->defer;
- d.argp = NoArgs;
- d.special = true;
- g->defer = &d;
-
- if(m != &runtime·m0)
- runtime·throw("runtime·main not on m0");
- runtime·newproc1(&scavenger, nil, 0, 0, runtime·main);
- main·init();
-
- if(g->defer != &d || d.fn != &initDone)
- runtime·throw("runtime: bad defer entry after init");
- g->defer = d.link;
- runtime·unlockOSThread();
-
- main·main();
- if(raceenabled)
- runtime·racefini();
-
- // Make racy client program work: if panicking on
- // another goroutine at the same time as main returns,
- // let the other goroutine finish printing the panic trace.
- // Once it does, it will exit. See issue 3934.
- if(runtime·panicking)
- runtime·park(nil, nil, "panicwait");
-
- runtime·exit(0);
- for(;;)
- *(int32*)runtime·main = 0;
}
-void
-runtime·goroutineheader(G *gp)
+static void
+dumpgstatus(G* gp)
{
- int8 *status;
- int64 waitfor;
-
- switch(gp->status) {
- case Gidle:
- status = "idle";
- break;
- case Grunnable:
- status = "runnable";
- break;
- case Grunning:
- status = "running";
- break;
- case Gsyscall:
- status = "syscall";
- break;
- case Gwaiting:
- if(gp->waitreason)
- status = gp->waitreason;
- else
- status = "waiting";
- break;
- default:
- status = "???";
- break;
- }
-
- // approx time the G is blocked, in minutes
- waitfor = 0;
- if((gp->status == Gwaiting || gp->status == Gsyscall) && gp->waitsince != 0)
- waitfor = (runtime·nanotime() - gp->waitsince) / (60LL*1000*1000*1000);
-
- if(waitfor < 1)
- runtime·printf("goroutine %D [%s]:\n", gp->goid, status);
- else
- runtime·printf("goroutine %D [%s, %D minutes]:\n", gp->goid, status, waitfor);
-}
-
-void
-runtime·tracebackothers(G *me)
-{
- G *gp;
- int32 traceback;
- uintptr i;
-
- traceback = runtime·gotraceback(nil);
-
- // Show the current goroutine first, if we haven't already.
- if((gp = m->curg) != nil && gp != me) {
- runtime·printf("\n");
- runtime·goroutineheader(gp);
- runtime·traceback(~(uintptr)0, ~(uintptr)0, 0, gp);
- }
-
- runtime·lock(&allglock);
- for(i = 0; i < runtime·allglen; i++) {
- gp = runtime·allg[i];
- if(gp == me || gp == m->curg || gp->status == Gdead)
- continue;
- if(gp->issystem && traceback < 2)
- continue;
- runtime·printf("\n");
- runtime·goroutineheader(gp);
- if(gp->status == Grunning) {
- runtime·printf("\tgoroutine running on other thread; stack unavailable\n");
- runtime·printcreatedby(gp);
- } else
- runtime·traceback(~(uintptr)0, ~(uintptr)0, 0, gp);
- }
- runtime·unlock(&allglock);
+ runtime·printf("runtime: gp: gp=%p, goid=%D, gp->atomicstatus=%x\n", gp, gp->goid, runtime·readgstatus(gp));
+ runtime·printf("runtime: g: g=%p, goid=%D, g->atomicstatus=%x\n", g, g->goid, runtime·readgstatus(g));
}
static void
checkmcount(void)
{
// sched lock is held
- if(runtime·sched.mcount > runtime·sched.maxmcount) {
+ if(runtime·sched.mcount > runtime·sched.maxmcount){
runtime·printf("runtime: program exceeds %d-thread limit\n", runtime·sched.maxmcount);
runtime·throw("thread exhaustion");
}
@@ -348,46 +189,61 @@ checkmcount(void)
static void
mcommoninit(M *mp)
{
- // If there is no mcache runtime·callers() will crash,
- // and we are most likely in sysmon thread so the stack is senseless anyway.
- if(m->mcache)
+ // g0 stack won't make sense for user (and is not necessary unwindable).
+ if(g != g->m->g0)
runtime·callers(1, mp->createstack, nelem(mp->createstack));
mp->fastrand = 0x49f6428aUL + mp->id + runtime·cputicks();
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
mp->id = runtime·sched.mcount++;
checkmcount();
runtime·mpreinit(mp);
+ if(mp->gsignal)
+ mp->gsignal->stackguard1 = mp->gsignal->stack.lo + StackGuard;
- // Add to runtime·allm so garbage collector doesn't free m
+ // Add to runtime·allm so garbage collector doesn't free g->m
// when it is just in a register or thread-local storage.
mp->alllink = runtime·allm;
// runtime·NumCgoCall() iterates over allm w/o schedlock,
// so we need to publish it safely.
runtime·atomicstorep(&runtime·allm, mp);
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
}
// Mark gp ready to run.
void
runtime·ready(G *gp)
{
+ uint32 status;
+
+ status = runtime·readgstatus(gp);
// Mark runnable.
- m->locks++; // disable preemption because it can be holding p in a local var
- if(gp->status != Gwaiting) {
- runtime·printf("goroutine %D has status %d\n", gp->goid, gp->status);
+ g->m->locks++; // disable preemption because it can be holding p in a local var
+ if((status&~Gscan) != Gwaiting){
+ dumpgstatus(gp);
runtime·throw("bad g->status in ready");
}
- gp->status = Grunnable;
- runqput(m->p, gp);
+ // status is Gwaiting or Gscanwaiting, make Grunnable and put on runq
+ runtime·casgstatus(gp, Gwaiting, Grunnable);
+ runqput(g->m->p, gp);
if(runtime·atomicload(&runtime·sched.npidle) != 0 && runtime·atomicload(&runtime·sched.nmspinning) == 0) // TODO: fast atomic
wakep();
- m->locks--;
- if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
+ 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;
}
+void
+runtime·ready_m(void)
+{
+ G *gp;
+
+ gp = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ runtime·ready(gp);
+}
+
int32
runtime·gcprocs(void)
{
@@ -395,7 +251,7 @@ runtime·gcprocs(void)
// Figure out how many CPUs to use during GC.
// Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
n = runtime·gomaxprocs;
if(n > runtime·ncpu)
n = runtime·ncpu;
@@ -403,7 +259,7 @@ runtime·gcprocs(void)
n = MaxGcproc;
if(n > runtime·sched.nmidle+1) // one M is currently running
n = runtime·sched.nmidle+1;
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
return n;
}
@@ -412,14 +268,14 @@ needaddgcproc(void)
{
int32 n;
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
n = runtime·gomaxprocs;
if(n > runtime·ncpu)
n = runtime·ncpu;
if(n > MaxGcproc)
n = MaxGcproc;
n -= runtime·sched.nmidle+1; // one M is currently running
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
return n > 0;
}
@@ -429,10 +285,10 @@ runtime·helpgc(int32 nproc)
M *mp;
int32 n, pos;
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
pos = 0;
for(n = 1; n < nproc; n++) { // one M is currently running
- if(runtime·allp[pos]->mcache == m->mcache)
+ if(runtime·allp[pos]->mcache == g->m->mcache)
pos++;
mp = mget();
if(mp == nil)
@@ -442,7 +298,7 @@ runtime·helpgc(int32 nproc)
pos++;
runtime·notewakeup(&mp->park);
}
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
}
// Similar to stoptheworld but best-effort and can be called several times.
@@ -473,6 +329,356 @@ runtime·freezetheworld(void)
runtime·usleep(1000);
}
+static bool
+isscanstatus(uint32 status)
+{
+ if(status == Gscan)
+ runtime·throw("isscanstatus: Bad status Gscan");
+ return (status&Gscan) == Gscan;
+}
+
+// All reads and writes of g's status go through readgstatus, casgstatus
+// castogscanstatus, casfromgscanstatus.
+#pragma textflag NOSPLIT
+uint32
+runtime·readgstatus(G *gp)
+{
+ return runtime·atomicload(&gp->atomicstatus);
+}
+
+// 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.
+void
+runtime·casfromgscanstatus(G *gp, uint32 oldval, uint32 newval)
+{
+ bool success = false;
+
+ // Check that transition is valid.
+ switch(oldval) {
+ case Gscanrunnable:
+ case Gscanwaiting:
+ case Gscanrunning:
+ case Gscansyscall:
+ if(newval == (oldval&~Gscan))
+ success = runtime·cas(&gp->atomicstatus, oldval, newval);
+ break;
+ case Gscanenqueue:
+ if(newval == Gwaiting)
+ success = runtime·cas(&gp->atomicstatus, oldval, newval);
+ break;
+ }
+ if(!success){
+ runtime·printf("runtime: casfromgscanstatus failed gp=%p, oldval=%d, newval=%d\n",
+ gp, oldval, newval);
+ dumpgstatus(gp);
+ runtime·throw("casfromgscanstatus: gp->status is not in scan state");
+ }
+}
+
+// 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.
+bool
+runtime·castogscanstatus(G *gp, uint32 oldval, uint32 newval)
+{
+ switch(oldval) {
+ case Grunnable:
+ case Gwaiting:
+ case Gsyscall:
+ if(newval == (oldval|Gscan))
+ return runtime·cas(&gp->atomicstatus, oldval, newval);
+ break;
+ case Grunning:
+ if(newval == Gscanrunning || newval == Gscanenqueue)
+ return runtime·cas(&gp->atomicstatus, oldval, newval);
+ break;
+ }
+
+ runtime·printf("runtime: castogscanstatus oldval=%d newval=%d\n", oldval, newval);
+ runtime·throw("castogscanstatus");
+ return false; // not reached
+}
+
+static void badcasgstatus(void);
+static void helpcasgstatus(void);
+static void badgstatusrunnable(void);
+
+// If asked to move to or from a Gscanstatus this will throw. Use the castogscanstatus
+// and casfromgscanstatus 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.
+#pragma textflag NOSPLIT
+void
+runtime·casgstatus(G *gp, uint32 oldval, uint32 newval)
+{
+ void (*fn)(void);
+
+ if((oldval&Gscan) || (newval&Gscan) || oldval == newval) {
+ g->m->scalararg[0] = oldval;
+ g->m->scalararg[1] = newval;
+ fn = badcasgstatus;
+ runtime·onM(&fn);
+ }
+
+ // loop if gp->atomicstatus is in a scan state giving
+ // GC time to finish and change the state to oldval.
+ while(!runtime·cas(&gp->atomicstatus, oldval, newval)) {
+ if(oldval == Gwaiting && gp->atomicstatus == Grunnable) {
+ fn = badgstatusrunnable;
+ runtime·onM(&fn);
+ }
+ // Help GC if needed.
+ if(gp->preemptscan && !gp->gcworkdone && (oldval == Grunning || oldval == Gsyscall)) {
+ gp->preemptscan = false;
+ g->m->ptrarg[0] = gp;
+ fn = helpcasgstatus;
+ runtime·onM(&fn);
+ }
+ }
+}
+
+static void
+badgstatusrunnable(void)
+{
+ runtime·throw("casgstatus: waiting for Gwaiting but is Grunnable");
+}
+
+// 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.
+#pragma textflag NOSPLIT
+uint32
+runtime·casgcopystack(G *gp)
+{
+ uint32 oldstatus;
+
+ for(;;) {
+ oldstatus = runtime·readgstatus(gp) & ~Gscan;
+ if(oldstatus != Gwaiting && oldstatus != Grunnable)
+ runtime·throw("copystack: bad status, not Gwaiting or Grunnable");
+ if(runtime·cas(&gp->atomicstatus, oldstatus, Gcopystack))
+ break;
+ }
+ return oldstatus;
+}
+
+static void
+badcasgstatus(void)
+{
+ uint32 oldval, newval;
+
+ oldval = g->m->scalararg[0];
+ newval = g->m->scalararg[1];
+ g->m->scalararg[0] = 0;
+ g->m->scalararg[1] = 0;
+
+ runtime·printf("casgstatus: oldval=%d, newval=%d\n", oldval, newval);
+ runtime·throw("casgstatus: bad incoming values");
+}
+
+static void
+helpcasgstatus(void)
+{
+ G *gp;
+
+ gp = g->m->ptrarg[0];
+ g->m->ptrarg[0] = 0;
+ runtime·gcphasework(gp);
+}
+
+// stopg ensures that gp is stopped at a GC safe point where its stack can be scanned
+// or in the context of a moving collector the pointers can be flipped from pointing
+// to old object to pointing to new objects.
+// If stopg returns true, the caller knows gp is at a GC safe point and will remain there until
+// the caller calls restartg.
+// If stopg returns false, the caller is not responsible for calling restartg. This can happen
+// if another thread, either the gp itself or another GC thread is taking the responsibility
+// to do the GC work related to this thread.
+bool
+runtime·stopg(G *gp)
+{
+ uint32 s;
+
+ for(;;) {
+ if(gp->gcworkdone)
+ return false;
+
+ s = runtime·readgstatus(gp);
+ switch(s) {
+ default:
+ dumpgstatus(gp);
+ runtime·throw("stopg: gp->atomicstatus is not valid");
+
+ case Gdead:
+ return false;
+
+ case Gcopystack:
+ // Loop until a new stack is in place.
+ break;
+
+ case Grunnable:
+ case Gsyscall:
+ case Gwaiting:
+ // Claim goroutine by setting scan bit.
+ if(!runtime·castogscanstatus(gp, s, s|Gscan))
+ break;
+ // In scan state, do work.
+ runtime·gcphasework(gp);
+ return true;
+
+ case Gscanrunnable:
+ case Gscanwaiting:
+ case Gscansyscall:
+ // Goroutine already claimed by another GC helper.
+ return false;
+
+ case Grunning:
+ // Claim goroutine, so we aren't racing with a status
+ // transition away from Grunning.
+ if(!runtime·castogscanstatus(gp, Grunning, Gscanrunning))
+ break;
+
+ // Mark gp for preemption.
+ if(!gp->gcworkdone) {
+ gp->preemptscan = true;
+ gp->preempt = true;
+ gp->stackguard0 = StackPreempt;
+ }
+
+ // Unclaim.
+ runtime·casfromgscanstatus(gp, Gscanrunning, Grunning);
+ return false;
+ }
+ }
+ // Should not be here....
+}
+
+// The GC requests that this routine be moved from a scanmumble state to a mumble state.
+void
+runtime·restartg (G *gp)
+{
+ uint32 s;
+
+ s = runtime·readgstatus(gp);
+ switch(s) {
+ default:
+ dumpgstatus(gp);
+ runtime·throw("restartg: unexpected status");
+
+ case Gdead:
+ break;
+
+ case Gscanrunnable:
+ case Gscanwaiting:
+ case Gscansyscall:
+ runtime·casfromgscanstatus(gp, s, s&~Gscan);
+ break;
+
+ case Gscanenqueue:
+ // 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.
+ runtime·casfromgscanstatus(gp, Gscanenqueue, Gwaiting);
+ if(gp != g->m->curg)
+ runtime·throw("processing Gscanenqueue on wrong m");
+ dropg();
+ runtime·ready(gp);
+ break;
+ }
+}
+
+static void
+stopscanstart(G* gp)
+{
+ if(g == gp)
+ runtime·throw("GC not moved to G0");
+ if(runtime·stopg(gp)) {
+ if(!isscanstatus(runtime·readgstatus(gp))) {
+ dumpgstatus(gp);
+ runtime·throw("GC not in scan state");
+ }
+ runtime·restartg(gp);
+ }
+}
+
+// Runs on g0 and does the actual work after putting the g back on the run queue.
+static void
+mquiesce(G *gpmaster)
+{
+ G* gp;
+ uint32 i;
+ uint32 status;
+ uint32 activeglen;
+
+ activeglen = runtime·allglen;
+ // enqueue the calling goroutine.
+ runtime·restartg(gpmaster);
+ for(i = 0; i < activeglen; i++) {
+ gp = runtime·allg[i];
+ if(runtime·readgstatus(gp) == Gdead)
+ gp->gcworkdone = true; // noop scan.
+ else
+ gp->gcworkdone = false;
+ stopscanstart(gp);
+ }
+
+ // Check that the G's gcwork (such as scanning) has been done. If not do it now.
+ // You can end up doing work here if the page trap on a Grunning Goroutine has
+ // not been sprung or in some race situations. For example a runnable goes dead
+ // and is started up again with a gp->gcworkdone set to false.
+ for(i = 0; i < activeglen; i++) {
+ gp = runtime·allg[i];
+ while (!gp->gcworkdone) {
+ status = runtime·readgstatus(gp);
+ if(status == Gdead) {
+ gp->gcworkdone = true; // scan is a noop
+ break;
+ //do nothing, scan not needed.
+ }
+ if(status == Grunning && gp->stackguard0 == (uintptr)StackPreempt && runtime·notetsleep(&runtime·sched.stopnote, 100*1000)) // nanosecond arg
+ runtime·noteclear(&runtime·sched.stopnote);
+ else
+ stopscanstart(gp);
+ }
+ }
+
+ for(i = 0; i < activeglen; i++) {
+ gp = runtime·allg[i];
+ status = runtime·readgstatus(gp);
+ if(isscanstatus(status)) {
+ runtime·printf("mstopandscang:bottom: post scan bad status gp=%p has status %x\n", gp, status);
+ dumpgstatus(gp);
+ }
+ if(!gp->gcworkdone && status != Gdead) {
+ runtime·printf("mstopandscang:bottom: post scan gp=%p->gcworkdone still false\n", gp);
+ dumpgstatus(gp);
+ }
+ }
+
+ schedule(); // Never returns.
+}
+
+// quiesce moves all the goroutines to a GC safepoint which for now is a at preemption point.
+// If the global runtime·gcphase is GCmark quiesce will ensure that all of the goroutine's stacks
+// have been scanned before it returns.
+void
+runtime·quiesce(G* mastergp)
+{
+ void (*fn)(G*);
+
+ runtime·castogscanstatus(mastergp, Grunning, Gscanenqueue);
+ // Now move this to the g0 (aka m) stack.
+ // g0 will potentially scan this thread and put mastergp on the runqueue
+ fn = mquiesce;
+ runtime·mcall(&fn);
+}
+
+// This is used by the GC as well as the routines that do stack dumps. In the case
+// of GC all the routines can be reliably stopped. This is not always the case
+// when the system is in panic or being exited.
void
runtime·stoptheworld(void)
{
@@ -481,12 +687,17 @@ runtime·stoptheworld(void)
P *p;
bool wait;
- runtime·lock(&runtime·sched);
+ // 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)
+ runtime·throw("stoptheworld: holding locks");
+
+ runtime·lock(&runtime·sched.lock);
runtime·sched.stopwait = runtime·gomaxprocs;
runtime·atomicstore((uint32*)&runtime·sched.gcwaiting, 1);
preemptall();
// stop current P
- m->p->status = Pgcstop;
+ g->m->p->status = Pgcstop; // Pgcstop is only diagnostic.
runtime·sched.stopwait--;
// try to retake all P's in Psyscall status
for(i = 0; i < runtime·gomaxprocs; i++) {
@@ -501,7 +712,7 @@ runtime·stoptheworld(void)
runtime·sched.stopwait--;
}
wait = runtime·sched.stopwait > 0;
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
// wait for remaining P's to stop voluntarily
if(wait) {
@@ -526,7 +737,7 @@ runtime·stoptheworld(void)
static void
mhelpgc(void)
{
- m->helpgc = -1;
+ g->m->helpgc = -1;
}
void
@@ -537,14 +748,14 @@ runtime·starttheworld(void)
G *gp;
bool add;
- m->locks++; // disable preemption because it can be holding p in a local var
+ g->m->locks++; // disable preemption because it can be holding p in a local var
gp = runtime·netpoll(false); // non-blocking
injectglist(gp);
add = needaddgcproc();
- runtime·lock(&runtime·sched);
- if(newprocs) {
- procresize(newprocs);
- newprocs = 0;
+ runtime·lock(&runtime·sched.lock);
+ if(runtime·newprocs) {
+ procresize(runtime·newprocs);
+ runtime·newprocs = 0;
} else
procresize(runtime·gomaxprocs);
runtime·sched.gcwaiting = 0;
@@ -565,7 +776,7 @@ runtime·starttheworld(void)
runtime·sched.sysmonwait = false;
runtime·notewakeup(&runtime·sched.sysmonnote);
}
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
while(p1) {
p = p1;
@@ -594,41 +805,65 @@ runtime·starttheworld(void)
// the maximum number of procs.
newm(mhelpgc, nil);
}
- m->locks--;
- if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
+ 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;
}
+static void mstart(void);
+
// Called to start an M.
+#pragma textflag NOSPLIT
void
runtime·mstart(void)
{
- if(g != m->g0)
+ uintptr x, size;
+
+ 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;
+ g->stack.hi = (uintptr)&x;
+ 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;
+ mstart();
+}
+
+static void
+mstart(void)
+{
+ if(g != g->m->g0)
runtime·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.
- runtime·gosave(&m->g0->sched);
- m->g0->sched.pc = (uintptr)-1; // make sure it is never used
- m->g0->stackguard = m->g0->stackguard0; // cgo sets only stackguard0, copy it to stackguard
+ runtime·gosave(&g->m->g0->sched);
+ g->m->g0->sched.pc = (uintptr)-1; // make sure it is never used
runtime·asminit();
runtime·minit();
// Install signal handlers; after minit so that minit can
// prepare the thread to be able to handle the signals.
- if(m == &runtime·m0)
+ if(g->m == &runtime·m0)
runtime·initsig();
- if(m->mstartfn)
- m->mstartfn();
+ if(g->m->mstartfn)
+ g->m->mstartfn();
- if(m->helpgc) {
- m->helpgc = 0;
+ if(g->m->helpgc) {
+ g->m->helpgc = 0;
stopm();
- } else if(m != &runtime·m0) {
- acquirep(m->nextp);
- m->nextp = nil;
+ } else if(g->m != &runtime·m0) {
+ acquirep(g->m->nextp);
+ g->m->nextp = nil;
}
schedule();
@@ -645,61 +880,49 @@ void (*_cgo_thread_start)(void*);
typedef struct CgoThreadStart CgoThreadStart;
struct CgoThreadStart
{
- M *m;
G *g;
uintptr *tls;
void (*fn)(void);
};
+M *runtime·newM(void); // in proc.go
+
// Allocate a new m unassociated with any thread.
// Can use p for allocation context if needed.
M*
runtime·allocm(P *p)
{
M *mp;
- static Type *mtype; // The Go type M
- m->locks++; // disable GC because it can be called from sysmon
- if(m->p == nil)
+ g->m->locks++; // disable GC because it can be called from sysmon
+ if(g->m->p == nil)
acquirep(p); // temporarily borrow p for mallocs in this function
- if(mtype == nil) {
- Eface e;
- runtime·gc_m_ptr(&e);
- mtype = ((PtrType*)e.type)->elem;
- }
-
- mp = runtime·cnew(mtype);
+ mp = runtime·newM();
mcommoninit(mp);
// In case of cgo or Solaris, pthread_create will make us a stack.
- // Windows will layout sched stack on OS stack.
- if(runtime·iscgo || Solaris || Windows)
+ // Windows and Plan 9 will layout sched stack on OS stack.
+ if(runtime·iscgo || Solaris || Windows || Plan9)
mp->g0 = runtime·malg(-1);
else
mp->g0 = runtime·malg(8192);
+ mp->g0->m = mp;
- if(p == m->p)
+ if(p == g->m->p)
releasep();
- m->locks--;
- if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
+ 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;
}
+G *runtime·newG(void); // in proc.go
+
static G*
allocg(void)
{
- G *gp;
- static Type *gtype;
-
- if(gtype == nil) {
- Eface e;
- runtime·gc_g_ptr(&e);
- gtype = ((PtrType*)e.type)->elem;
- }
- gp = runtime·cnew(gtype);
- return gp;
+ return runtime·newG();
}
static M* lockextra(bool nilokay);
@@ -768,15 +991,15 @@ runtime·needm(byte x)
mp->needextram = mp->schedlink == nil;
unlockextra(mp->schedlink);
- // Install m and g (= m->g0) and set the stack bounds
+ // 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.
- runtime·setmg(mp, mp->g0);
- g->stackbase = (uintptr)(&x + 1024);
- g->stackguard = (uintptr)(&x - 32*1024);
- g->stackguard0 = g->stackguard;
+ runtime·setg(mp->g0);
+ g->stack.hi = (uintptr)(&x + 1024);
+ g->stack.lo = (uintptr)(&x - 32*1024);
+ g->stackguard0 = g->stack.lo + StackGuard;
// Initialize this thread to use the m.
runtime·asminit();
@@ -799,15 +1022,17 @@ runtime·newextram(void)
// the goroutine stack ends.
mp = runtime·allocm(nil);
gp = runtime·malg(4096);
- gp->sched.pc = (uintptr)runtime·goexit;
- gp->sched.sp = gp->stackbase;
+ gp->sched.pc = (uintptr)runtime·goexit + PCQuantum;
+ gp->sched.sp = gp->stack.hi;
+ gp->sched.sp -= 4*sizeof(uintreg); // extra space in case of reads slightly beyond frame
gp->sched.lr = 0;
gp->sched.g = gp;
gp->syscallpc = gp->sched.pc;
gp->syscallsp = gp->sched.sp;
- gp->syscallstack = gp->stackbase;
- gp->syscallguard = gp->stackguard;
- gp->status = Gsyscall;
+ // malg returns status as Gidle, change to Gsyscall before adding to allg
+ // where GC will see it.
+ runtime·casgstatus(gp, Gidle, Gsyscall);
+ gp->m = mp;
mp->curg = gp;
mp->locked = LockInternal;
mp->lockedg = gp;
@@ -816,7 +1041,7 @@ runtime·newextram(void)
if(raceenabled)
gp->racectx = runtime·racegostart(runtime·newextram);
// put on allg for garbage collector
- allgadd(gp);
+ runtime·allgadd(gp);
// Add m to the extra list.
mnext = lockextra(true);
@@ -857,8 +1082,8 @@ runtime·dropm(void)
// Clear m and g, and return m to the extra list.
// After the call to setmg we can only call nosplit functions.
- mp = m;
- runtime·setmg(nil, nil);
+ mp = g->m;
+ runtime·setg(nil);
mnext = lockextra(true);
mp->schedlink = mnext;
@@ -923,14 +1148,13 @@ newm(void(*fn)(void), P *p)
if(_cgo_thread_start == nil)
runtime·throw("_cgo_thread_start missing");
- ts.m = mp;
ts.g = mp->g0;
ts.tls = mp->tls;
ts.fn = runtime·mstart;
runtime·asmcgocall(_cgo_thread_start, &ts);
return;
}
- runtime·newosproc(mp, (byte*)mp->g0->stackbase);
+ runtime·newosproc(mp, (byte*)mp->g0->stack.hi);
}
// Stops execution of the current m until new work is available.
@@ -938,35 +1162,35 @@ newm(void(*fn)(void), P *p)
static void
stopm(void)
{
- if(m->locks)
+ if(g->m->locks)
runtime·throw("stopm holding locks");
- if(m->p)
+ if(g->m->p)
runtime·throw("stopm holding p");
- if(m->spinning) {
- m->spinning = false;
+ if(g->m->spinning) {
+ g->m->spinning = false;
runtime·xadd(&runtime·sched.nmspinning, -1);
}
retry:
- runtime·lock(&runtime·sched);
- mput(m);
- runtime·unlock(&runtime·sched);
- runtime·notesleep(&m->park);
- runtime·noteclear(&m->park);
- if(m->helpgc) {
+ runtime·lock(&runtime·sched.lock);
+ mput(g->m);
+ runtime·unlock(&runtime·sched.lock);
+ runtime·notesleep(&g->m->park);
+ runtime·noteclear(&g->m->park);
+ if(g->m->helpgc) {
runtime·gchelper();
- m->helpgc = 0;
- m->mcache = nil;
+ g->m->helpgc = 0;
+ g->m->mcache = nil;
goto retry;
}
- acquirep(m->nextp);
- m->nextp = nil;
+ acquirep(g->m->nextp);
+ g->m->nextp = nil;
}
static void
mspinning(void)
{
- m->spinning = true;
+ g->m->spinning = true;
}
// Schedules some M to run the p (creates an M if necessary).
@@ -977,18 +1201,18 @@ startm(P *p, bool spinning)
M *mp;
void (*fn)(void);
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
if(p == nil) {
p = pidleget();
if(p == nil) {
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
if(spinning)
runtime·xadd(&runtime·sched.nmspinning, -1);
return;
}
}
mp = mget();
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
if(mp == nil) {
fn = nil;
if(spinning)
@@ -1017,32 +1241,32 @@ handoffp(P *p)
// no local work, check that there are no spinning/idle M's,
// otherwise our help is not required
if(runtime·atomicload(&runtime·sched.nmspinning) + runtime·atomicload(&runtime·sched.npidle) == 0 && // TODO: fast atomic
- runtime·cas(&runtime·sched.nmspinning, 0, 1)) {
+ runtime·cas(&runtime·sched.nmspinning, 0, 1)){
startm(p, true);
return;
}
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
if(runtime·sched.gcwaiting) {
p->status = Pgcstop;
if(--runtime·sched.stopwait == 0)
runtime·notewakeup(&runtime·sched.stopnote);
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
return;
}
if(runtime·sched.runqsize) {
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·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(runtime·sched.npidle == runtime·gomaxprocs-1 && runtime·atomicload64(&runtime·sched.lastpoll) != 0) {
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
startm(p, false);
return;
}
pidleput(p);
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
}
// Tries to add one more P to execute G's.
@@ -1062,22 +1286,27 @@ static void
stoplockedm(void)
{
P *p;
+ uint32 status;
- if(m->lockedg == nil || m->lockedg->lockedm != m)
+ if(g->m->lockedg == nil || g->m->lockedg->lockedm != g->m)
runtime·throw("stoplockedm: inconsistent locking");
- if(m->p) {
+ if(g->m->p) {
// Schedule another M to run this p.
p = releasep();
handoffp(p);
}
incidlelocked(1);
// Wait until another thread schedules lockedg again.
- runtime·notesleep(&m->park);
- runtime·noteclear(&m->park);
- if(m->lockedg->status != Grunnable)
+ runtime·notesleep(&g->m->park);
+ runtime·noteclear(&g->m->park);
+ status = runtime·readgstatus(g->m->lockedg);
+ if((status&~Gscan) != Grunnable){
+ runtime·printf("runtime:stoplockedm: g is not Grunnable or Gscanrunnable");
+ dumpgstatus(g);
runtime·throw("stoplockedm: not runnable");
- acquirep(m->nextp);
- m->nextp = nil;
+ }
+ acquirep(g->m->nextp);
+ g->m->nextp = nil;
}
// Schedules the locked m to run the locked gp.
@@ -1088,7 +1317,7 @@ startlockedm(G *gp)
P *p;
mp = gp->lockedm;
- if(mp == m)
+ if(mp == g->m)
runtime·throw("startlockedm: locked to me");
if(mp->nextp)
runtime·throw("startlockedm: m has p");
@@ -1109,16 +1338,16 @@ gcstopm(void)
if(!runtime·sched.gcwaiting)
runtime·throw("gcstopm: not waiting for gc");
- if(m->spinning) {
- m->spinning = false;
+ if(g->m->spinning) {
+ g->m->spinning = false;
runtime·xadd(&runtime·sched.nmspinning, -1);
}
p = releasep();
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
p->status = Pgcstop;
if(--runtime·sched.stopwait == 0)
runtime·notewakeup(&runtime·sched.stopnote);
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
stopm();
}
@@ -1128,22 +1357,18 @@ static void
execute(G *gp)
{
int32 hz;
-
- if(gp->status != Grunnable) {
- runtime·printf("execute: bad g status %d\n", gp->status);
- runtime·throw("execute: bad g status");
- }
- gp->status = Grunning;
+
+ runtime·casgstatus(gp, Grunnable, Grunning);
gp->waitsince = 0;
gp->preempt = false;
- gp->stackguard0 = gp->stackguard;
- m->p->schedtick++;
- m->curg = gp;
- gp->m = m;
+ gp->stackguard0 = gp->stack.lo + StackGuard;
+ g->m->p->schedtick++;
+ g->m->curg = gp;
+ gp->m = g->m;
// Check whether the profiler needs to be turned on or off.
hz = runtime·sched.profilehz;
- if(m->profilehz != hz)
+ if(g->m->profilehz != hz)
runtime·resetcpuprofiler(hz);
runtime·gogo(&gp->sched);
@@ -1166,14 +1391,14 @@ top:
if(runtime·fingwait && runtime·fingwake && (gp = runtime·wakefing()) != nil)
runtime·ready(gp);
// local runq
- gp = runqget(m->p);
+ gp = runqget(g->m->p);
if(gp)
return gp;
// global runq
if(runtime·sched.runqsize) {
- runtime·lock(&runtime·sched);
- gp = globrunqget(m->p, 0);
- runtime·unlock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
+ gp = globrunqget(g->m->p, 0);
+ runtime·unlock(&runtime·sched.lock);
if(gp)
return gp;
}
@@ -1181,16 +1406,16 @@ top:
gp = runtime·netpoll(false); // non-blocking
if(gp) {
injectglist(gp->schedlink);
- gp->status = Grunnable;
+ runtime·casgstatus(gp, Gwaiting, Grunnable);
return gp;
}
// 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(!m->spinning && 2 * runtime·atomicload(&runtime·sched.nmspinning) >= runtime·gomaxprocs - runtime·atomicload(&runtime·sched.npidle)) // TODO: fast atomic
+ if(!g->m->spinning && 2 * runtime·atomicload(&runtime·sched.nmspinning) >= runtime·gomaxprocs - runtime·atomicload(&runtime·sched.npidle)) // TODO: fast atomic
goto stop;
- if(!m->spinning) {
- m->spinning = true;
+ if(!g->m->spinning) {
+ g->m->spinning = true;
runtime·xadd(&runtime·sched.nmspinning, 1);
}
// random steal from other P's
@@ -1198,39 +1423,39 @@ top:
if(runtime·sched.gcwaiting)
goto top;
p = runtime·allp[runtime·fastrand1()%runtime·gomaxprocs];
- if(p == m->p)
+ if(p == g->m->p)
gp = runqget(p);
else
- gp = runqsteal(m->p, p);
+ gp = runqsteal(g->m->p, p);
if(gp)
return gp;
}
stop:
// return P and block
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
if(runtime·sched.gcwaiting) {
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
goto top;
}
if(runtime·sched.runqsize) {
- gp = globrunqget(m->p, 0);
- runtime·unlock(&runtime·sched);
+ gp = globrunqget(g->m->p, 0);
+ runtime·unlock(&runtime·sched.lock);
return gp;
}
p = releasep();
pidleput(p);
- runtime·unlock(&runtime·sched);
- if(m->spinning) {
- m->spinning = false;
+ runtime·unlock(&runtime·sched.lock);
+ if(g->m->spinning) {
+ g->m->spinning = false;
runtime·xadd(&runtime·sched.nmspinning, -1);
}
// check all runqueues once again
for(i = 0; i < runtime·gomaxprocs; i++) {
p = runtime·allp[i];
if(p && p->runqhead != p->runqtail) {
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
p = pidleget();
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
if(p) {
acquirep(p);
goto top;
@@ -1240,20 +1465,20 @@ stop:
}
// poll network
if(runtime·xchg64(&runtime·sched.lastpoll, 0) != 0) {
- if(m->p)
+ if(g->m->p)
runtime·throw("findrunnable: netpoll with p");
- if(m->spinning)
+ if(g->m->spinning)
runtime·throw("findrunnable: netpoll with spinning");
gp = runtime·netpoll(true); // block until new work is available
runtime·atomicstore64(&runtime·sched.lastpoll, runtime·nanotime());
if(gp) {
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
p = pidleget();
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
if(p) {
acquirep(p);
injectglist(gp->schedlink);
- gp->status = Grunnable;
+ runtime·casgstatus(gp, Gwaiting, Grunnable);
return gp;
}
injectglist(gp);
@@ -1268,8 +1493,8 @@ resetspinning(void)
{
int32 nmspinning;
- if(m->spinning) {
- m->spinning = false;
+ if(g->m->spinning) {
+ g->m->spinning = false;
nmspinning = runtime·xadd(&runtime·sched.nmspinning, -1);
if(nmspinning < 0)
runtime·throw("findrunnable: negative nmspinning");
@@ -1292,14 +1517,14 @@ injectglist(G *glist)
if(glist == nil)
return;
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
for(n = 0; glist; n++) {
gp = glist;
glist = gp->schedlink;
- gp->status = Grunnable;
+ runtime·casgstatus(gp, Gwaiting, Grunnable);
globrunqput(gp);
}
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
for(; n && runtime·sched.npidle; n--)
startm(nil, false);
@@ -1313,9 +1538,14 @@ schedule(void)
G *gp;
uint32 tick;
- if(m->locks)
+ if(g->m->locks)
runtime·throw("schedule: holding locks");
+ if(g->m->lockedg) {
+ stoplockedm();
+ execute(g->m->lockedg); // Never returns.
+ }
+
top:
if(runtime·sched.gcwaiting) {
gcstopm();
@@ -1326,19 +1556,19 @@ top:
// 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.
- tick = m->p->schedtick;
+ tick = g->m->p->schedtick;
// This is a fancy way to say tick%61==0,
// it uses 2 MUL instructions instead of a single DIV and so is faster on modern processors.
if(tick - (((uint64)tick*0x4325c53fu)>>36)*61 == 0 && runtime·sched.runqsize > 0) {
- runtime·lock(&runtime·sched);
- gp = globrunqget(m->p, 1);
- runtime·unlock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
+ gp = globrunqget(g->m->p, 1);
+ runtime·unlock(&runtime·sched.lock);
if(gp)
resetspinning();
}
if(gp == nil) {
- gp = runqget(m->p);
- if(gp && m->spinning)
+ gp = runqget(g->m->p);
+ if(gp && g->m->spinning)
runtime·throw("schedule: spinning with local work");
}
if(gp == nil) {
@@ -1356,21 +1586,38 @@ top:
execute(gp);
}
+// 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 runtime·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.
+static void
+dropg(void)
+{
+ if(g->m->lockedg == nil) {
+ g->m->curg->m = nil;
+ g->m->curg = nil;
+ }
+}
+
// Puts the current goroutine into a waiting state and calls unlockf.
// If unlockf returns false, the goroutine is resumed.
void
-runtime·park(bool(*unlockf)(G*, void*), void *lock, int8 *reason)
+runtime·park(bool(*unlockf)(G*, void*), void *lock, String reason)
{
- if(g->status != Grunning)
- runtime·throw("bad g status");
- m->waitlock = lock;
- m->waitunlockf = unlockf;
+ void (*fn)(G*);
+
+ g->m->waitlock = lock;
+ g->m->waitunlockf = unlockf;
g->waitreason = reason;
- runtime·mcall(park0);
+ fn = runtime·park_m;
+ runtime·mcall(&fn);
}
-static bool
-parkunlock(G *gp, void *lock)
+bool
+runtime·parkunlock_c(G *gp, void *lock)
{
USED(gp);
runtime·unlock(lock);
@@ -1380,108 +1627,101 @@ parkunlock(G *gp, void *lock)
// Puts the current goroutine into a waiting state and unlocks the lock.
// The goroutine can be made runnable again by calling runtime·ready(gp).
void
-runtime·parkunlock(Lock *lock, int8 *reason)
+runtime·parkunlock(Mutex *lock, String reason)
{
- runtime·park(parkunlock, lock, reason);
+ runtime·park(runtime·parkunlock_c, lock, reason);
}
// runtime·park continuation on g0.
-static void
-park0(G *gp)
+void
+runtime·park_m(G *gp)
{
bool ok;
- gp->status = Gwaiting;
- gp->m = nil;
- m->curg = nil;
- if(m->waitunlockf) {
- ok = m->waitunlockf(gp, m->waitlock);
- m->waitunlockf = nil;
- m->waitlock = nil;
+ runtime·casgstatus(gp, Grunning, Gwaiting);
+ dropg();
+
+ if(g->m->waitunlockf) {
+ ok = g->m->waitunlockf(gp, g->m->waitlock);
+ g->m->waitunlockf = nil;
+ g->m->waitlock = nil;
if(!ok) {
- gp->status = Grunnable;
+ runtime·casgstatus(gp, Gwaiting, Grunnable);
execute(gp); // Schedule it back, never returns.
}
}
- if(m->lockedg) {
- stoplockedm();
- execute(gp); // Never returns.
- }
+
schedule();
}
-// Scheduler yield.
+// Gosched continuation on g0.
void
-runtime·gosched(void)
+runtime·gosched_m(G *gp)
{
- if(g->status != Grunning)
- runtime·throw("bad g status");
- runtime·mcall(runtime·gosched0);
-}
+ uint32 status;
-// runtime·gosched continuation on g0.
-void
-runtime·gosched0(G *gp)
-{
- gp->status = Grunnable;
- gp->m = nil;
- m->curg = nil;
- runtime·lock(&runtime·sched);
- globrunqput(gp);
- runtime·unlock(&runtime·sched);
- if(m->lockedg) {
- stoplockedm();
- execute(gp); // Never returns.
+ status = runtime·readgstatus(gp);
+ if((status&~Gscan) != Grunning){
+ dumpgstatus(gp);
+ runtime·throw("bad g status");
}
+ runtime·casgstatus(gp, Grunning, Grunnable);
+ dropg();
+ runtime·lock(&runtime·sched.lock);
+ globrunqput(gp);
+ runtime·unlock(&runtime·sched.lock);
+
schedule();
}
// Finishes execution of the current goroutine.
-// Need to mark it as nosplit, because it runs with sp > stackbase (as runtime·lessstack).
-// Since it does not return it does not matter. But if it is preempted
-// at the split stack check, GC will complain about inconsistent sp.
+// Must be NOSPLIT because it is called from Go.
#pragma textflag NOSPLIT
void
-runtime·goexit(void)
+runtime·goexit1(void)
{
- if(g->status != Grunning)
- runtime·throw("bad g status");
+ void (*fn)(G*);
+
if(raceenabled)
runtime·racegoend();
- runtime·mcall(goexit0);
+ fn = goexit0;
+ runtime·mcall(&fn);
}
// runtime·goexit continuation on g0.
static void
goexit0(G *gp)
{
- gp->status = Gdead;
+ runtime·casgstatus(gp, Grunning, Gdead);
gp->m = nil;
gp->lockedm = nil;
+ g->m->lockedg = nil;
gp->paniconfault = 0;
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->writenbuf = 0;
- gp->writebuf = nil;
- gp->waitreason = nil;
+ gp->writebuf.array = nil;
+ gp->writebuf.len = 0;
+ gp->writebuf.cap = 0;
+ gp->waitreason.str = nil;
+ gp->waitreason.len = 0;
gp->param = nil;
- m->curg = nil;
- m->lockedg = nil;
- if(m->locked & ~LockExternal) {
- runtime·printf("invalid m->locked = %d\n", m->locked);
+
+ dropg();
+
+ if(g->m->locked & ~LockExternal) {
+ runtime·printf("invalid m->locked = %d\n", g->m->locked);
runtime·throw("internal lockOSThread error");
}
- m->locked = 0;
- runtime·unwindstack(gp, nil);
- gfput(m->p, gp);
+ g->m->locked = 0;
+ gfput(g->m->p, gp);
schedule();
}
#pragma textflag NOSPLIT
static void
-save(void *pc, uintptr sp)
+save(uintptr pc, uintptr sp)
{
- g->sched.pc = (uintptr)pc;
+ g->sched.pc = pc;
g->sched.sp = sp;
g->sched.lr = 0;
g->sched.ret = 0;
@@ -1489,6 +1729,10 @@ save(void *pc, uintptr sp)
g->sched.g = g;
}
+static void entersyscall_bad(void);
+static void entersyscall_sysmon(void);
+static void entersyscall_gcwait(void);
+
// 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,
@@ -1497,47 +1741,59 @@ save(void *pc, uintptr sp)
// Entersyscall cannot split the stack: the runtime·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 onM
+// to run bigger things on the m 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.
#pragma textflag NOSPLIT
void
-runtime·reentersyscall(void *pc, uintptr sp)
+runtime·reentersyscall(uintptr pc, uintptr sp)
{
+ void (*fn)(void);
+
// Disable preemption because during this function g is in Gsyscall status,
// but can have inconsistent g->sched, do not let GC observe it.
- m->locks++;
+ 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 = 1;
// Leave SP around for GC and traceback.
save(pc, sp);
- g->syscallsp = g->sched.sp;
- g->syscallpc = g->sched.pc;
- g->syscallstack = g->stackbase;
- g->syscallguard = g->stackguard;
- g->status = Gsyscall;
- if(g->syscallsp < g->syscallguard-StackGuard || g->syscallstack < g->syscallsp) {
- // runtime·printf("entersyscall inconsistent %p [%p,%p]\n",
- // g->syscallsp, g->syscallguard-StackGuard, g->syscallstack);
- runtime·throw("entersyscall");
+ g->syscallsp = sp;
+ g->syscallpc = pc;
+ runtime·casgstatus(g, Grunning, Gsyscall);
+ if(g->syscallsp < g->stack.lo || g->stack.hi < g->syscallsp) {
+ fn = entersyscall_bad;
+ runtime·onM(&fn);
}
if(runtime·atomicload(&runtime·sched.sysmonwait)) { // TODO: fast atomic
- runtime·lock(&runtime·sched);
- if(runtime·atomicload(&runtime·sched.sysmonwait)) {
- runtime·atomicstore(&runtime·sched.sysmonwait, 0);
- runtime·notewakeup(&runtime·sched.sysmonnote);
- }
- runtime·unlock(&runtime·sched);
+ fn = entersyscall_sysmon;
+ runtime·onM(&fn);
save(pc, sp);
}
- m->mcache = nil;
- m->p->m = nil;
- runtime·atomicstore(&m->p->status, Psyscall);
+ g->m->mcache = nil;
+ g->m->p->m = nil;
+ runtime·atomicstore(&g->m->p->status, Psyscall);
if(runtime·sched.gcwaiting) {
- runtime·lock(&runtime·sched);
- if (runtime·sched.stopwait > 0 && runtime·cas(&m->p->status, Psyscall, Pgcstop)) {
- if(--runtime·sched.stopwait == 0)
- runtime·notewakeup(&runtime·sched.stopnote);
- }
- runtime·unlock(&runtime·sched);
+ fn = entersyscall_gcwait;
+ runtime·onM(&fn);
save(pc, sp);
}
@@ -1545,48 +1801,86 @@ runtime·reentersyscall(void *pc, uintptr sp)
// We set stackguard to StackPreempt so that first split stack check calls morestack.
// Morestack detects this case and throws.
g->stackguard0 = StackPreempt;
- m->locks--;
+ g->m->locks--;
}
+// Standard syscall entry used by the go syscall library and normal cgo calls.
#pragma textflag NOSPLIT
void
·entersyscall(int32 dummy)
{
- runtime·reentersyscall(runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
+ runtime·reentersyscall((uintptr)runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
}
+static void
+entersyscall_bad(void)
+{
+ G *gp;
+
+ gp = g->m->curg;
+ runtime·printf("entersyscall inconsistent %p [%p,%p]\n",
+ gp->syscallsp, gp->stack.lo, gp->stack.hi);
+ runtime·throw("entersyscall");
+}
+
+static void
+entersyscall_sysmon(void)
+{
+ runtime·lock(&runtime·sched.lock);
+ if(runtime·atomicload(&runtime·sched.sysmonwait)) {
+ runtime·atomicstore(&runtime·sched.sysmonwait, 0);
+ runtime·notewakeup(&runtime·sched.sysmonnote);
+ }
+ runtime·unlock(&runtime·sched.lock);
+}
+
+static void
+entersyscall_gcwait(void)
+{
+ runtime·lock(&runtime·sched.lock);
+ if (runtime·sched.stopwait > 0 && runtime·cas(&g->m->p->status, Psyscall, Pgcstop)) {
+ if(--runtime·sched.stopwait == 0)
+ runtime·notewakeup(&runtime·sched.stopnote);
+ }
+ runtime·unlock(&runtime·sched.lock);
+}
+
+static void entersyscallblock_handoff(void);
+
// The same as runtime·entersyscall(), but with a hint that the syscall is blocking.
#pragma textflag NOSPLIT
void
·entersyscallblock(int32 dummy)
{
- P *p;
+ void (*fn)(void);
- m->locks++; // see comment in entersyscall
+ g->m->locks++; // see comment in entersyscall
+ g->throwsplit = 1;
+ g->stackguard0 = StackPreempt; // see comment in entersyscall
// Leave SP around for GC and traceback.
- save(runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
+ save((uintptr)runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
g->syscallsp = g->sched.sp;
g->syscallpc = g->sched.pc;
- g->syscallstack = g->stackbase;
- g->syscallguard = g->stackguard;
- g->status = Gsyscall;
- if(g->syscallsp < g->syscallguard-StackGuard || g->syscallstack < g->syscallsp) {
- // runtime·printf("entersyscall inconsistent %p [%p,%p]\n",
- // g->syscallsp, g->syscallguard-StackGuard, g->syscallstack);
- runtime·throw("entersyscallblock");
+ runtime·casgstatus(g, Grunning, Gsyscall);
+ if(g->syscallsp < g->stack.lo || g->stack.hi < g->syscallsp) {
+ fn = entersyscall_bad;
+ runtime·onM(&fn);
}
-
- p = releasep();
- handoffp(p);
- if(g->isbackground) // do not consider blocked scavenger for deadlock detection
- incidlelocked(1);
+
+ fn = entersyscallblock_handoff;
+ runtime·onM(&fn);
// Resave for traceback during blocked call.
- save(runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
+ save((uintptr)runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
- g->stackguard0 = StackPreempt; // see comment in entersyscall
- m->locks--;
+ g->m->locks--;
+}
+
+static void
+entersyscallblock_handoff(void)
+{
+ handoffp(releasep());
}
// The goroutine g exited its system call.
@@ -1597,87 +1891,105 @@ void
void
·exitsyscall(int32 dummy)
{
- m->locks++; // see comment in entersyscall
+ void (*fn)(G*);
+
+ g->m->locks++; // see comment in entersyscall
if(runtime·getcallersp(&dummy) > g->syscallsp)
runtime·throw("exitsyscall: syscall frame is no longer valid");
- if(g->isbackground) // do not consider blocked scavenger for deadlock detection
- incidlelocked(-1);
-
g->waitsince = 0;
if(exitsyscallfast()) {
// There's a cpu for us, so we can run.
- m->p->syscalltick++;
- g->status = Grunning;
+ g->m->p->syscalltick++;
+ // We need to cas the status and scan before resuming...
+ runtime·casgstatus(g, Gsyscall, Grunning);
+
// Garbage collector isn't running (since we are),
- // so okay to clear gcstack and gcsp.
- g->syscallstack = (uintptr)nil;
+ // so okay to clear syscallsp.
g->syscallsp = (uintptr)nil;
- m->locks--;
+ 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->stackguard;
+ g->stackguard0 = g->stack.lo + StackGuard;
}
+ g->throwsplit = 0;
return;
}
- m->locks--;
+ g->m->locks--;
// Call the scheduler.
- runtime·mcall(exitsyscall0);
+ fn = exitsyscall0;
+ runtime·mcall(&fn);
// Scheduler returned, so we're allowed to run now.
- // Delete the gcstack information that we left for
+ // 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->syscallstack = (uintptr)nil;
g->syscallsp = (uintptr)nil;
- m->p->syscalltick++;
+ g->m->p->syscalltick++;
+ g->throwsplit = 0;
}
+static void exitsyscallfast_pidle(void);
+
#pragma textflag NOSPLIT
static bool
exitsyscallfast(void)
{
- P *p;
+ void (*fn)(void);
// Freezetheworld sets stopwait but does not retake P's.
if(runtime·sched.stopwait) {
- m->p = nil;
+ g->m->p = nil;
return false;
}
// Try to re-acquire the last P.
- if(m->p && m->p->status == Psyscall && runtime·cas(&m->p->status, Psyscall, Prunning)) {
+ if(g->m->p && g->m->p->status == Psyscall && runtime·cas(&g->m->p->status, Psyscall, Prunning)) {
// There's a cpu for us, so we can run.
- m->mcache = m->p->mcache;
- m->p->m = m;
+ g->m->mcache = g->m->p->mcache;
+ g->m->p->m = g->m;
return true;
}
// Try to get any other idle P.
- m->p = nil;
+ g->m->p = nil;
if(runtime·sched.pidle) {
- runtime·lock(&runtime·sched);
- p = pidleget();
- if(p && runtime·atomicload(&runtime·sched.sysmonwait)) {
- runtime·atomicstore(&runtime·sched.sysmonwait, 0);
- runtime·notewakeup(&runtime·sched.sysmonnote);
- }
- runtime·unlock(&runtime·sched);
- if(p) {
- acquirep(p);
+ fn = exitsyscallfast_pidle;
+ runtime·onM(&fn);
+ if(g->m->scalararg[0]) {
+ g->m->scalararg[0] = 0;
return true;
}
}
return false;
}
+static void
+exitsyscallfast_pidle(void)
+{
+ P *p;
+
+ runtime·lock(&runtime·sched.lock);
+ p = pidleget();
+ if(p && runtime·atomicload(&runtime·sched.sysmonwait)) {
+ runtime·atomicstore(&runtime·sched.sysmonwait, 0);
+ runtime·notewakeup(&runtime·sched.sysmonnote);
+ }
+ runtime·unlock(&runtime·sched.lock);
+ if(p) {
+ acquirep(p);
+ g->m->scalararg[0] = 1;
+ } else
+ g->m->scalararg[0] = 0;
+}
+
// runtime·exitsyscall slow path on g0.
// Failed to acquire P, enqueue gp as runnable.
static void
@@ -1685,10 +1997,9 @@ exitsyscall0(G *gp)
{
P *p;
- gp->status = Grunnable;
- gp->m = nil;
- m->curg = nil;
- runtime·lock(&runtime·sched);
+ runtime·casgstatus(gp, Gsyscall, Grunnable);
+ dropg();
+ runtime·lock(&runtime·sched.lock);
p = pidleget();
if(p == nil)
globrunqput(gp);
@@ -1696,12 +2007,12 @@ exitsyscall0(G *gp)
runtime·atomicstore(&runtime·sched.sysmonwait, 0);
runtime·notewakeup(&runtime·sched.sysmonnote);
}
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
if(p) {
acquirep(p);
execute(gp); // Never returns.
}
- if(m->lockedg) {
+ if(g->m->lockedg) {
// Wait until another thread schedules gp and so m again.
stoplockedm();
execute(gp); // Never returns.
@@ -1710,42 +2021,61 @@ exitsyscall0(G *gp)
schedule(); // Never returns.
}
-// Called from syscall package before fork.
-#pragma textflag NOSPLIT
-void
-syscall·runtime_BeforeFork(void)
+static void
+beforefork(void)
{
+ G *gp;
+
+ gp = g->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.
- m->locks++;
- if(m->profilehz != 0)
+ gp->m->locks++;
+ if(gp->m->profilehz != 0)
runtime·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.
- m->forkstackguard = g->stackguard;
- g->stackguard0 = StackPreempt-1;
- g->stackguard = StackPreempt-1;
+ gp->stackguard0 = StackFork;
}
-// Called from syscall package after fork in parent.
+// Called from syscall package before fork.
#pragma textflag NOSPLIT
void
-syscall·runtime_AfterFork(void)
+syscall·runtime_BeforeFork(void)
{
- int32 hz;
+ void (*fn)(void);
+
+ fn = beforefork;
+ runtime·onM(&fn);
+}
+static void
+afterfork(void)
+{
+ int32 hz;
+ G *gp;
+
+ gp = g->m->curg;
// See the comment in runtime_BeforeFork.
- g->stackguard0 = m->forkstackguard;
- g->stackguard = m->forkstackguard;
- m->forkstackguard = 0;
+ gp->stackguard0 = gp->stack.lo + StackGuard;
hz = runtime·sched.profilehz;
if(hz != 0)
runtime·resetcpuprofiler(hz);
- m->locks--;
+ gp->m->locks--;
+}
+
+// Called from syscall package after fork in parent.
+#pragma textflag NOSPLIT
+void
+syscall·runtime_AfterFork(void)
+{
+ void (*fn)(void);
+
+ fn = afterfork;
+ runtime·onM(&fn);
}
// Hook used by runtime·malg to call runtime·stackalloc on the
@@ -1758,10 +2088,11 @@ mstackalloc(G *gp)
G *newg;
uintptr size;
- newg = (G*)gp->param;
- size = newg->stacksize;
- newg->stacksize = 0;
- gp->param = runtime·stackalloc(newg, size);
+ newg = g->m->ptrarg[0];
+ size = g->m->scalararg[0];
+
+ newg->stack = runtime·stackalloc(size);
+
runtime·gogo(&gp->sched);
}
@@ -1770,55 +2101,76 @@ G*
runtime·malg(int32 stacksize)
{
G *newg;
- byte *stk;
-
- if(StackTop < sizeof(Stktop)) {
- runtime·printf("runtime: SizeofStktop=%d, should be >=%d\n", (int32)StackTop, (int32)sizeof(Stktop));
- runtime·throw("runtime: bad stack.h");
- }
+ void (*fn)(G*);
newg = allocg();
if(stacksize >= 0) {
stacksize = runtime·round2(StackSystem + stacksize);
- if(g == m->g0) {
+ if(g == g->m->g0) {
// running on scheduler stack already.
- stk = runtime·stackalloc(newg, stacksize);
+ newg->stack = runtime·stackalloc(stacksize);
} else {
// have to call stackalloc on scheduler stack.
- newg->stacksize = stacksize;
- g->param = newg;
- runtime·mcall(mstackalloc);
- stk = g->param;
- g->param = nil;
+ g->m->scalararg[0] = stacksize;
+ g->m->ptrarg[0] = newg;
+ fn = mstackalloc;
+ runtime·mcall(&fn);
+ g->m->ptrarg[0] = nil;
}
- newg->stack0 = (uintptr)stk;
- newg->stackguard = (uintptr)stk + StackGuard;
- newg->stackguard0 = newg->stackguard;
- newg->stackbase = (uintptr)stk + stacksize - sizeof(Stktop);
+ newg->stackguard0 = newg->stack.lo + StackGuard;
+ newg->stackguard1 = ~(uintptr)0;
}
return newg;
}
+static void
+newproc_m(void)
+{
+ byte *argp;
+ void *callerpc;
+ FuncVal *fn;
+ int32 siz;
+
+ siz = g->m->scalararg[0];
+ callerpc = (void*)g->m->scalararg[1];
+ argp = g->m->ptrarg[0];
+ fn = (FuncVal*)g->m->ptrarg[1];
+
+ runtime·newproc1(fn, argp, siz, 0, callerpc);
+ g->m->ptrarg[0] = nil;
+ g->m->ptrarg[1] = nil;
+}
+
// 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. It's OK for this to call
-// functions that split the stack.
+// copied if a stack split occurred.
#pragma textflag NOSPLIT
void
runtime·newproc(int32 siz, FuncVal* fn, ...)
{
byte *argp;
+ void (*mfn)(void);
if(thechar == '5')
argp = (byte*)(&fn+2); // skip caller's saved LR
else
argp = (byte*)(&fn+1);
- runtime·newproc1(fn, argp, siz, 0, runtime·getcallerpc(&siz));
+
+ g->m->locks++;
+ g->m->scalararg[0] = siz;
+ g->m->scalararg[1] = (uintptr)runtime·getcallerpc(&siz);
+ g->m->ptrarg[0] = argp;
+ g->m->ptrarg[1] = fn;
+ mfn = newproc_m;
+ runtime·onM(&mfn);
+ g->m->locks--;
}
+void runtime·main(void);
+
// 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
@@ -1831,32 +2183,35 @@ runtime·newproc1(FuncVal *fn, byte *argp, int32 narg, int32 nret, void *callerp
P *p;
int32 siz;
-//runtime·printf("newproc1 %p %p narg=%d nret=%d\n", fn->fn, argp, narg, nret);
if(fn == nil) {
- m->throwing = -1; // do not dump full stacks
+ g->m->throwing = -1; // do not dump full stacks
runtime·throw("go of nil func value");
}
- m->locks++; // disable preemption because it can be holding p in a local var
+ g->m->locks++; // disable preemption because it can be holding p in a local var
siz = narg + nret;
siz = (siz+7) & ~7;
- // We could instead create a secondary stack frame
- // and make it look like goexit was on the original but
- // the call to the actual goroutine function was split.
+ // We could allocate a larger initial stack if necessary.
// Not worth it: this is almost always an error.
- if(siz > StackMin - 1024)
+ // 4*sizeof(uintreg): extra space added below
+ // sizeof(uintreg): caller's LR (arm) or return address (x86, in gostartcall).
+ if(siz >= StackMin - 4*sizeof(uintreg) - sizeof(uintreg))
runtime·throw("runtime.newproc: function arguments too large for new goroutine");
- p = m->p;
- if((newg = gfget(p)) != nil) {
- if(newg->stackguard - StackGuard != newg->stack0)
- runtime·throw("invalid stack in newg");
- } else {
+ p = g->m->p;
+ if((newg = gfget(p)) == nil) {
newg = runtime·malg(StackMin);
- allgadd(newg);
+ runtime·casgstatus(newg, Gidle, Gdead);
+ runtime·allgadd(newg); // publishes with a g->status of Gdead so GC scanner doesn't look at uninitialized stack.
}
+ if(newg->stack.hi == 0)
+ runtime·throw("newproc1: newg missing stack");
+
+ if(runtime·readgstatus(newg) != Gdead)
+ runtime·throw("newproc1: new g is not Gdead");
- sp = (byte*)newg->stackbase;
+ sp = (byte*)newg->stack.hi;
+ sp -= 4*sizeof(uintreg); // extra space in case of reads slightly beyond frame
sp -= siz;
runtime·memmove(sp, argp, narg);
if(thechar == '5') {
@@ -1867,78 +2222,51 @@ runtime·newproc1(FuncVal *fn, byte *argp, int32 narg, int32 nret, void *callerp
runtime·memclr((byte*)&newg->sched, sizeof newg->sched);
newg->sched.sp = (uintptr)sp;
- newg->sched.pc = (uintptr)runtime·goexit;
+ newg->sched.pc = (uintptr)runtime·goexit + PCQuantum; // +PCQuantum so that previous instruction is in same function
newg->sched.g = newg;
runtime·gostartcallfn(&newg->sched, fn);
newg->gopc = (uintptr)callerpc;
- newg->status = Grunnable;
+ runtime·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 = runtime·xadd64(&runtime·sched.goidgen, GoidCacheBatch);
+ p->goidcache -= GoidCacheBatch - 1;
p->goidcacheend = p->goidcache + GoidCacheBatch;
}
newg->goid = p->goidcache++;
- newg->panicwrap = 0;
if(raceenabled)
newg->racectx = runtime·racegostart((void*)callerpc);
runqput(p, newg);
if(runtime·atomicload(&runtime·sched.npidle) != 0 && runtime·atomicload(&runtime·sched.nmspinning) == 0 && fn->fn != runtime·main) // TODO: fast atomic
wakep();
- m->locks--;
- if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
+ 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;
}
-static void
-allgadd(G *gp)
-{
- G **new;
- uintptr cap;
-
- runtime·lock(&allglock);
- if(runtime·allglen >= allgcap) {
- cap = 4096/sizeof(new[0]);
- if(cap < 2*allgcap)
- cap = 2*allgcap;
- new = runtime·malloc(cap*sizeof(new[0]));
- if(new == nil)
- runtime·throw("runtime: cannot allocate memory");
- if(runtime·allg != nil) {
- runtime·memmove(new, runtime·allg, runtime·allglen*sizeof(new[0]));
- runtime·free(runtime·allg);
- }
- runtime·allg = new;
- allgcap = cap;
- }
- runtime·allg[runtime·allglen++] = gp;
- runtime·unlock(&allglock);
-}
-
// Put on gfree list.
// If local list is too long, transfer a batch to the global list.
static void
gfput(P *p, G *gp)
{
uintptr stksize;
- Stktop *top;
-
- if(gp->stackguard - StackGuard != gp->stack0)
- runtime·throw("invalid stack in gfput");
- stksize = gp->stackbase + sizeof(Stktop) - gp->stack0;
- if(stksize != gp->stacksize) {
- runtime·printf("runtime: bad stacksize, goroutine %D, remain=%d, last=%d\n",
- gp->goid, (int32)gp->stacksize, (int32)stksize);
- runtime·throw("gfput: bad stacksize");
- }
- top = (Stktop*)gp->stackbase;
- if(top->malloced) {
+
+ if(runtime·readgstatus(gp) != Gdead)
+ runtime·throw("gfput: bad status (not Gdead)");
+
+ stksize = gp->stack.hi - gp->stack.lo;
+
+ if(stksize != FixedStack) {
// non-standard stack size - free it.
- runtime·stackfree(gp, (void*)gp->stack0, top);
- gp->stack0 = 0;
- gp->stackguard = 0;
+ runtime·stackfree(gp->stack);
+ gp->stack.lo = 0;
+ gp->stack.hi = 0;
gp->stackguard0 = 0;
- gp->stackbase = 0;
}
gp->schedlink = p->gfree;
p->gfree = gp;
@@ -1951,6 +2279,7 @@ gfput(P *p, G *gp)
p->gfree = gp->schedlink;
gp->schedlink = runtime·sched.gfree;
runtime·sched.gfree = gp;
+ runtime·sched.ngfree++;
}
runtime·unlock(&runtime·sched.gflock);
}
@@ -1962,16 +2291,17 @@ static G*
gfget(P *p)
{
G *gp;
- byte *stk;
+ void (*fn)(G*);
retry:
gp = p->gfree;
if(gp == nil && runtime·sched.gfree) {
runtime·lock(&runtime·sched.gflock);
- while(p->gfreecnt < 32 && runtime·sched.gfree) {
+ while(p->gfreecnt < 32 && runtime·sched.gfree != nil) {
p->gfreecnt++;
gp = runtime·sched.gfree;
runtime·sched.gfree = gp->schedlink;
+ runtime·sched.ngfree--;
gp->schedlink = p->gfree;
p->gfree = gp;
}
@@ -1982,21 +2312,21 @@ retry:
p->gfree = gp->schedlink;
p->gfreecnt--;
- if(gp->stack0 == 0) {
+ if(gp->stack.lo == 0) {
// Stack was deallocated in gfput. Allocate a new one.
- if(g == m->g0) {
- stk = runtime·stackalloc(gp, FixedStack);
+ if(g == g->m->g0) {
+ gp->stack = runtime·stackalloc(FixedStack);
} else {
- gp->stacksize = FixedStack;
- g->param = gp;
- runtime·mcall(mstackalloc);
- stk = g->param;
- g->param = nil;
+ g->m->scalararg[0] = FixedStack;
+ g->m->ptrarg[0] = gp;
+ fn = mstackalloc;
+ runtime·mcall(&fn);
+ g->m->ptrarg[0] = nil;
}
- gp->stack0 = (uintptr)stk;
- gp->stackbase = (uintptr)stk + FixedStack - sizeof(Stktop);
- gp->stackguard = (uintptr)stk + StackGuard;
- gp->stackguard0 = gp->stackguard;
+ gp->stackguard0 = gp->stack.lo + StackGuard;
+ } else {
+ if(raceenabled)
+ runtime·racemalloc((void*)gp->stack.lo, gp->stack.hi - gp->stack.lo);
}
}
return gp;
@@ -2009,56 +2339,24 @@ gfpurge(P *p)
G *gp;
runtime·lock(&runtime·sched.gflock);
- while(p->gfreecnt) {
+ while(p->gfreecnt != 0) {
p->gfreecnt--;
gp = p->gfree;
p->gfree = gp->schedlink;
gp->schedlink = runtime·sched.gfree;
runtime·sched.gfree = gp;
+ runtime·sched.ngfree++;
}
runtime·unlock(&runtime·sched.gflock);
}
+#pragma textflag NOSPLIT
void
runtime·Breakpoint(void)
{
runtime·breakpoint();
}
-void
-runtime·Gosched(void)
-{
- runtime·gosched();
-}
-
-// Implementation of runtime.GOMAXPROCS.
-// delete when scheduler is even stronger
-int32
-runtime·gomaxprocsfunc(int32 n)
-{
- int32 ret;
-
- if(n > MaxGomaxprocs)
- n = MaxGomaxprocs;
- runtime·lock(&runtime·sched);
- ret = runtime·gomaxprocs;
- if(n <= 0 || n == ret) {
- runtime·unlock(&runtime·sched);
- return ret;
- }
- runtime·unlock(&runtime·sched);
-
- runtime·semacquire(&runtime·worldsema, false);
- m->gcing = 1;
- runtime·stoptheworld();
- newprocs = n;
- m->gcing = 0;
- runtime·semrelease(&runtime·worldsema);
- runtime·starttheworld();
-
- return ret;
-}
-
// lockOSThread is called by runtime.LockOSThread and runtime.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.
@@ -2066,21 +2364,23 @@ runtime·gomaxprocsfunc(int32 n)
static void
lockOSThread(void)
{
- m->lockedg = g;
- g->lockedm = m;
+ g->m->lockedg = g;
+ g->lockedm = g->m;
}
+#pragma textflag NOSPLIT
void
runtime·LockOSThread(void)
{
- m->locked |= LockExternal;
+ g->m->locked |= LockExternal;
lockOSThread();
}
+#pragma textflag NOSPLIT
void
runtime·lockOSThread(void)
{
- m->locked += LockInternal;
+ g->m->locked += LockInternal;
lockOSThread();
}
@@ -2092,54 +2392,56 @@ runtime·lockOSThread(void)
static void
unlockOSThread(void)
{
- if(m->locked != 0)
+ if(g->m->locked != 0)
return;
- m->lockedg = nil;
+ g->m->lockedg = nil;
g->lockedm = nil;
}
+#pragma textflag NOSPLIT
void
runtime·UnlockOSThread(void)
{
- m->locked &= ~LockExternal;
+ g->m->locked &= ~LockExternal;
unlockOSThread();
}
+static void badunlockOSThread(void);
+
+#pragma textflag NOSPLIT
void
runtime·unlockOSThread(void)
{
- if(m->locked < LockInternal)
- runtime·throw("runtime: internal error: misuse of lockOSThread/unlockOSThread");
- m->locked -= LockInternal;
+ void (*fn)(void);
+
+ if(g->m->locked < LockInternal) {
+ fn = badunlockOSThread;
+ runtime·onM(&fn);
+ }
+ g->m->locked -= LockInternal;
unlockOSThread();
}
-bool
-runtime·lockedOSThread(void)
+static void
+badunlockOSThread(void)
{
- return g->lockedm != nil && m->lockedg != nil;
+ runtime·throw("runtime: internal error: misuse of lockOSThread/unlockOSThread");
}
+#pragma textflag NOSPLIT
int32
runtime·gcount(void)
{
- G *gp;
- int32 n, s;
- uintptr i;
+ P *p, **pp;
+ int32 n;
- n = 0;
- runtime·lock(&allglock);
- // TODO(dvyukov): runtime.NumGoroutine() is O(N).
- // We do not want to increment/decrement centralized counter in newproc/goexit,
- // just to make runtime.NumGoroutine() faster.
- // Compromise solution is to introduce per-P counters of active goroutines.
- for(i = 0; i < runtime·allglen; i++) {
- gp = runtime·allg[i];
- s = gp->status;
- if(s == Grunnable || s == Grunning || s == Gsyscall || s == Gwaiting)
- n++;
- }
- runtime·unlock(&allglock);
+ n = runtime·allglen - runtime·sched.ngfree;
+ for(pp=runtime·allp; p=*pp; pp++)
+ 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;
}
@@ -2149,37 +2451,17 @@ runtime·mcount(void)
return runtime·sched.mcount;
}
-void
-runtime·badmcall(void (*fn)(G*)) // called from assembly
-{
- USED(fn); // TODO: print fn?
- runtime·throw("runtime: mcall called on m->g0 stack");
-}
-
-void
-runtime·badmcall2(void (*fn)(G*)) // called from assembly
-{
- USED(fn);
- runtime·throw("runtime: mcall function returned");
-}
-
-void
-runtime·badreflectcall(void) // called from assembly
-{
- runtime·panicstring("runtime: arg size to reflect.call more than 1GB");
-}
-
-static struct {
- Lock;
- void (*fn)(uintptr*, int32);
+static struct ProfState {
+ uint32 lock;
int32 hz;
- uintptr pcbuf[100];
} prof;
-static void System(void) {}
-static void ExternalCode(void) {}
-static void GC(void) {}
-extern byte etext[];
+static void System(void) { System(); }
+static void ExternalCode(void) { ExternalCode(); }
+static void GC(void) { GC(); }
+
+extern void runtime·cpuproftick(uintptr*, int32);
+extern byte runtime·etext[];
// Called if we receive a SIGPROF signal.
void
@@ -2190,11 +2472,12 @@ runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp, M *mp)
// Do not use global m in this function, use mp instead.
// On windows one m is sending reports about all the g's, so m means a wrong thing.
byte m;
+ uintptr stk[100];
m = 0;
USED(m);
- if(prof.fn == nil || prof.hz == 0)
+ if(prof.hz == 0)
return;
// Profiling runs concurrently with GC, so it must not allocate.
@@ -2274,19 +2557,13 @@ runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp, M *mp)
// in runtime.gogo.
traceback = true;
if(gp == nil || gp != mp->curg ||
- (uintptr)sp < gp->stackguard - StackGuard || gp->stackbase < (uintptr)sp ||
+ (uintptr)sp < gp->stack.lo || gp->stack.hi < (uintptr)sp ||
((uint8*)runtime·gogo <= pc && pc < (uint8*)runtime·gogo + RuntimeGogoBytes))
traceback = false;
- runtime·lock(&prof);
- if(prof.fn == nil) {
- runtime·unlock(&prof);
- mp->mallocing--;
- return;
- }
n = 0;
if(traceback)
- n = runtime·gentraceback((uintptr)pc, (uintptr)sp, (uintptr)lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf), nil, nil, false);
+ n = runtime·gentraceback((uintptr)pc, (uintptr)sp, (uintptr)lr, gp, 0, stk, nelem(stk), nil, nil, TraceTrap);
if(!traceback || n <= 0) {
// Normal traceback is impossible or has failed.
// See if it falls into several common cases.
@@ -2296,68 +2573,79 @@ runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp, M *mp)
// 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 = runtime·gentraceback(mp->curg->syscallpc, mp->curg->syscallsp, 0, mp->curg, 0, prof.pcbuf, nelem(prof.pcbuf), nil, nil, false);
+ n = runtime·gentraceback(mp->curg->syscallpc, mp->curg->syscallsp, 0, mp->curg, 0, stk, nelem(stk), nil, nil, 0);
}
#ifdef GOOS_windows
if(n == 0 && mp->libcallg != nil && mp->libcallpc != 0 && mp->libcallsp != 0) {
// Libcall, i.e. runtime syscall on windows.
// Collect Go stack that leads to the call.
- n = runtime·gentraceback(mp->libcallpc, mp->libcallsp, 0, mp->libcallg, 0, prof.pcbuf, nelem(prof.pcbuf), nil, nil, false);
+ n = runtime·gentraceback(mp->libcallpc, mp->libcallsp, 0, mp->libcallg, 0, stk, nelem(stk), nil, nil, 0);
}
#endif
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((uintptr)pc > (uintptr)etext)
+ if((uintptr)pc > (uintptr)runtime·etext)
pc = (byte*)ExternalCode + PCQuantum;
- prof.pcbuf[0] = (uintptr)pc;
+ stk[0] = (uintptr)pc;
if(mp->gcing || mp->helpgc)
- prof.pcbuf[1] = (uintptr)GC + PCQuantum;
+ stk[1] = (uintptr)GC + PCQuantum;
else
- prof.pcbuf[1] = (uintptr)System + PCQuantum;
+ stk[1] = (uintptr)System + PCQuantum;
}
}
- prof.fn(prof.pcbuf, n);
- runtime·unlock(&prof);
+
+ if(prof.hz != 0) {
+ // Simple cas-lock to coordinate with setcpuprofilerate.
+ while(!runtime·cas(&prof.lock, 0, 1))
+ runtime·osyield();
+ if(prof.hz != 0)
+ runtime·cpuproftick(stk, n);
+ runtime·atomicstore(&prof.lock, 0);
+ }
mp->mallocing--;
}
// Arrange to call fn with a traceback hz times a second.
void
-runtime·setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
+runtime·setcpuprofilerate_m(void)
{
+ int32 hz;
+
+ hz = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+
// Force sane arguments.
if(hz < 0)
hz = 0;
- if(hz == 0)
- fn = nil;
- if(fn == nil)
- hz = 0;
// Disable preemption, otherwise we can be rescheduled to another thread
// that has profiling enabled.
- m->locks++;
+ 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.
runtime·resetcpuprofiler(0);
- runtime·lock(&prof);
- prof.fn = fn;
+ while(!runtime·cas(&prof.lock, 0, 1))
+ runtime·osyield();
prof.hz = hz;
- runtime·unlock(&prof);
- runtime·lock(&runtime·sched);
+ runtime·atomicstore(&prof.lock, 0);
+
+ runtime·lock(&runtime·sched.lock);
runtime·sched.profilehz = hz;
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
if(hz != 0)
runtime·resetcpuprofiler(hz);
- m->locks--;
+ g->m->locks--;
}
+P *runtime·newP(void);
+
// Change number of processors. The world is stopped, sched is locked.
static void
procresize(int32 new)
@@ -2374,14 +2662,14 @@ procresize(int32 new)
for(i = 0; i < new; i++) {
p = runtime·allp[i];
if(p == nil) {
- p = (P*)runtime·mallocgc(sizeof(*p), 0, FlagNoInvokeGC);
+ p = runtime·newP();
p->id = i;
p->status = Pgcstop;
runtime·atomicstorep(&runtime·allp[i], p);
}
if(p->mcache == nil) {
if(old==0 && i==0)
- p->mcache = m->mcache; // bootstrap
+ p->mcache = g->m->mcache; // bootstrap
else
p->mcache = runtime·allocmcache();
}
@@ -2432,10 +2720,10 @@ procresize(int32 new)
// can't free P itself because it can be referenced by an M in syscall
}
- if(m->p)
- m->p->m = nil;
- m->p = nil;
- m->mcache = nil;
+ if(g->m->p)
+ g->m->p->m = nil;
+ g->m->p = nil;
+ g->m->mcache = nil;
p = runtime·allp[0];
p->m = nil;
p->status = Pidle;
@@ -2452,15 +2740,15 @@ procresize(int32 new)
static void
acquirep(P *p)
{
- if(m->p || m->mcache)
+ if(g->m->p || g->m->mcache)
runtime·throw("acquirep: already in go");
if(p->m || p->status != Pidle) {
runtime·printf("acquirep: p->m=%p(%d) p->status=%d\n", p->m, p->m ? p->m->id : 0, p->status);
runtime·throw("acquirep: invalid p state");
}
- m->mcache = p->mcache;
- m->p = p;
- p->m = m;
+ g->m->mcache = p->mcache;
+ g->m->p = p;
+ p->m = g->m;
p->status = Prunning;
}
@@ -2470,16 +2758,16 @@ releasep(void)
{
P *p;
- if(m->p == nil || m->mcache == nil)
+ if(g->m->p == nil || g->m->mcache == nil)
runtime·throw("releasep: invalid arg");
- p = m->p;
- if(p->m != m || p->mcache != m->mcache || p->status != Prunning) {
+ p = g->m->p;
+ if(p->m != g->m || p->mcache != g->m->mcache || p->status != Prunning) {
runtime·printf("releasep: m=%p m->p=%p p->m=%p m->mcache=%p p->mcache=%p p->status=%d\n",
- m, m->p, p->m, m->mcache, p->mcache, p->status);
+ g->m, g->m->p, p->m, g->m->mcache, p->mcache, p->status);
runtime·throw("releasep: invalid p state");
}
- m->p = nil;
- m->mcache = nil;
+ g->m->p = nil;
+ g->m->mcache = nil;
p->m = nil;
p->status = Pidle;
return p;
@@ -2488,11 +2776,11 @@ releasep(void)
static void
incidlelocked(int32 v)
{
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
runtime·sched.nmidlelocked += v;
if(v > 0)
checkdead();
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
}
// Check for deadlock situation.
@@ -2501,6 +2789,8 @@ static void
checkdead(void)
{
G *gp;
+ P *p;
+ M *mp;
int32 run, grunning, s;
uintptr i;
@@ -2520,34 +2810,75 @@ checkdead(void)
runtime·throw("checkdead: inconsistent counts");
}
grunning = 0;
- runtime·lock(&allglock);
+ runtime·lock(&runtime·allglock);
for(i = 0; i < runtime·allglen; i++) {
gp = runtime·allg[i];
- if(gp->isbackground)
+ if(gp->issystem)
continue;
- s = gp->status;
- if(s == Gwaiting)
+ s = runtime·readgstatus(gp);
+ switch(s&~Gscan) {
+ case Gwaiting:
grunning++;
- else if(s == Grunnable || s == Grunning || s == Gsyscall) {
- runtime·unlock(&allglock);
+ break;
+ case Grunnable:
+ case Grunning:
+ case Gsyscall:
+ runtime·unlock(&runtime·allglock);
runtime·printf("runtime: checkdead: find g %D in status %d\n", gp->goid, s);
runtime·throw("checkdead: runnable g");
+ break;
}
}
- runtime·unlock(&allglock);
+ runtime·unlock(&runtime·allglock);
if(grunning == 0) // possible if main goroutine calls runtime·Goexit()
runtime·throw("no goroutines (main called runtime.Goexit) - deadlock!");
- m->throwing = -1; // do not dump full stacks
+
+ // Maybe jump time forward for playground.
+ if((gp = runtime·timejump()) != nil) {
+ runtime·casgstatus(gp, Gwaiting, Grunnable);
+ globrunqput(gp);
+ p = pidleget();
+ if(p == nil)
+ runtime·throw("checkdead: no p for timer");
+ mp = mget();
+ if(mp == nil)
+ newm(nil, p);
+ else {
+ mp->nextp = p;
+ runtime·notewakeup(&mp->park);
+ }
+ return;
+ }
+
+ g->m->throwing = -1; // do not dump full stacks
runtime·throw("all goroutines are asleep - deadlock!");
}
static void
sysmon(void)
{
- uint32 idle, delay;
- int64 now, lastpoll, lasttrace;
+ uint32 idle, delay, nscavenge;
+ int64 now, unixnow, lastpoll, lasttrace, lastgc;
+ int64 forcegcperiod, scavengelimit, lastscavenge, maxsleep;
G *gp;
+ // If we go two minutes without a garbage collection, force one to run.
+ forcegcperiod = 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 = 5*60*1e9;
+ if(runtime·debug.scavenge > 0) {
+ // Scavenge-a-lot for testing.
+ forcegcperiod = 10*1e6;
+ scavengelimit = 20*1e6;
+ }
+ lastscavenge = runtime·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 = 0;
idle = 0; // how many cycles in succession we had not wokeup somebody
delay = 0;
@@ -2561,20 +2892,23 @@ sysmon(void)
runtime·usleep(delay);
if(runtime·debug.schedtrace <= 0 &&
(runtime·sched.gcwaiting || runtime·atomicload(&runtime·sched.npidle) == runtime·gomaxprocs)) { // TODO: fast atomic
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
if(runtime·atomicload(&runtime·sched.gcwaiting) || runtime·atomicload(&runtime·sched.npidle) == runtime·gomaxprocs) {
runtime·atomicstore(&runtime·sched.sysmonwait, 1);
- runtime·unlock(&runtime·sched);
- runtime·notesleep(&runtime·sched.sysmonnote);
+ runtime·unlock(&runtime·sched.lock);
+ runtime·notetsleep(&runtime·sched.sysmonnote, maxsleep);
+ runtime·lock(&runtime·sched.lock);
+ runtime·atomicstore(&runtime·sched.sysmonwait, 0);
runtime·noteclear(&runtime·sched.sysmonnote);
idle = 0;
delay = 20;
- } else
- runtime·unlock(&runtime·sched);
+ }
+ runtime·unlock(&runtime·sched.lock);
}
// poll network if not polled for more than 10ms
lastpoll = runtime·atomicload64(&runtime·sched.lastpoll);
now = runtime·nanotime();
+ unixnow = runtime·unixnanotime();
if(lastpoll != 0 && lastpoll + 10*1000*1000 < now) {
runtime·cas64(&runtime·sched.lastpoll, lastpoll, now);
gp = runtime·netpoll(false); // non-blocking
@@ -2598,6 +2932,23 @@ sysmon(void)
else
idle++;
+ // check if we need to force a GC
+ lastgc = runtime·atomicload64(&mstats.last_gc);
+ if(lastgc != 0 && unixnow - lastgc > forcegcperiod && runtime·atomicload(&runtime·forcegc.idle)) {
+ runtime·lock(&runtime·forcegc.lock);
+ runtime·forcegc.idle = 0;
+ runtime·forcegc.g->schedlink = nil;
+ injectglist(runtime·forcegc.g);
+ runtime·unlock(&runtime·forcegc.lock);
+ }
+
+ // scavenge heap once in a while
+ if(lastscavenge + scavengelimit/2 < now) {
+ runtime·MHeap_Scavenge(nscavenge, now, scavengelimit);
+ lastscavenge = now;
+ nscavenge++;
+ }
+
if(runtime·debug.schedtrace > 0 && lasttrace + runtime·debug.schedtrace*1000000ll <= now) {
lasttrace = now;
runtime·schedtrace(runtime·debug.scheddetail);
@@ -2701,6 +3052,9 @@ preemptall(void)
// simultaneously executing runtime·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
static bool
preemptone(P *p)
{
@@ -2708,12 +3062,16 @@ preemptone(P *p)
G *gp;
mp = p->m;
- if(mp == nil || mp == m)
+ if(mp == nil || mp == g->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;
}
@@ -2735,13 +3093,13 @@ runtime·schedtrace(bool detailed)
if(starttime == 0)
starttime = now;
- runtime·lock(&runtime·sched);
- runtime·printf("SCHED %Dms: gomaxprocs=%d idleprocs=%d threads=%d idlethreads=%d runqueue=%d",
+ runtime·lock(&runtime·sched.lock);
+ runtime·printf("SCHED %Dms: gomaxprocs=%d idleprocs=%d threads=%d spinningthreads=%d idlethreads=%d runqueue=%d",
(now-starttime)/1000000, runtime·gomaxprocs, runtime·sched.npidle, runtime·sched.mcount,
- runtime·sched.nmidle, runtime·sched.runqsize);
+ runtime·sched.nmspinning, runtime·sched.nmidle, runtime·sched.runqsize);
if(detailed) {
- runtime·printf(" gcwaiting=%d nmidlelocked=%d nmspinning=%d stopwait=%d sysmonwait=%d\n",
- runtime·sched.gcwaiting, runtime·sched.nmidlelocked, runtime·sched.nmspinning,
+ runtime·printf(" gcwaiting=%d nmidlelocked=%d stopwait=%d sysmonwait=%d\n",
+ runtime·sched.gcwaiting, runtime·sched.nmidlelocked,
runtime·sched.stopwait, runtime·sched.sysmonwait);
}
// We must be careful while reading data from P's, M's and G's.
@@ -2771,7 +3129,7 @@ runtime·schedtrace(bool detailed)
}
}
if(!detailed) {
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
return;
}
for(mp = runtime·allm; mp; mp = mp->alllink) {
@@ -2791,19 +3149,19 @@ runtime·schedtrace(bool detailed)
" locks=%d dying=%d helpgc=%d spinning=%d blocked=%d lockedg=%D\n",
mp->id, id1, id2,
mp->mallocing, mp->throwing, mp->gcing, mp->locks, mp->dying, mp->helpgc,
- mp->spinning, m->blocked, id3);
+ mp->spinning, g->m->blocked, id3);
}
- runtime·lock(&allglock);
+ runtime·lock(&runtime·allglock);
for(gi = 0; gi < runtime·allglen; gi++) {
gp = runtime·allg[gi];
mp = gp->m;
lockedm = gp->lockedm;
- runtime·printf(" G%D: status=%d(%s) m=%d lockedm=%d\n",
- gp->goid, gp->status, gp->waitreason, mp ? mp->id : -1,
+ runtime·printf(" G%D: status=%d(%S) m=%d lockedm=%d\n",
+ gp->goid, runtime·readgstatus(gp), gp->waitreason, mp ? mp->id : -1,
lockedm ? lockedm->id : -1);
}
- runtime·unlock(&allglock);
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·allglock);
+ runtime·unlock(&runtime·sched.lock);
}
// Put mp on midle list.
@@ -2959,9 +3317,9 @@ runqputslow(P *p, G *gp, uint32 h, uint32 t)
for(i=0; i<n; i++)
batch[i]->schedlink = batch[i+1];
// Now put the batch on global queue.
- runtime·lock(&runtime·sched);
+ runtime·lock(&runtime·sched.lock);
globrunqputbatch(batch[0], batch[n], n+1);
- runtime·unlock(&runtime·sched);
+ runtime·unlock(&runtime·sched.lock);
return true;
}
@@ -3039,24 +3397,25 @@ runqsteal(P *p, P *p2)
void
runtime·testSchedLocalQueue(void)
{
- P p;
- G gs[nelem(p.runq)];
+ P *p;
+ G *gs;
int32 i, j;
- runtime·memclr((byte*)&p, sizeof(p));
+ p = (P*)runtime·mallocgc(sizeof(*p), nil, FlagNoScan);
+ gs = (G*)runtime·mallocgc(nelem(p->runq)*sizeof(*gs), nil, FlagNoScan);
- for(i = 0; i < nelem(gs); i++) {
- if(runqget(&p) != nil)
+ for(i = 0; i < nelem(p->runq); i++) {
+ if(runqget(p) != nil)
runtime·throw("runq is not empty initially");
for(j = 0; j < i; j++)
- runqput(&p, &gs[i]);
+ runqput(p, &gs[i]);
for(j = 0; j < i; j++) {
- if(runqget(&p) != &gs[i]) {
+ if(runqget(p) != &gs[i]) {
runtime·printf("bad element at iter %d/%d\n", i, j);
runtime·throw("bad element");
}
}
- if(runqget(&p) != nil)
+ if(runqget(p) != nil)
runtime·throw("runq is not empty afterwards");
}
}
@@ -3064,29 +3423,30 @@ runtime·testSchedLocalQueue(void)
void
runtime·testSchedLocalQueueSteal(void)
{
- P p1, p2;
- G gs[nelem(p1.runq)], *gp;
+ P *p1, *p2;
+ G *gs, *gp;
int32 i, j, s;
- runtime·memclr((byte*)&p1, sizeof(p1));
- runtime·memclr((byte*)&p2, sizeof(p2));
+ p1 = (P*)runtime·mallocgc(sizeof(*p1), nil, FlagNoScan);
+ p2 = (P*)runtime·mallocgc(sizeof(*p2), nil, FlagNoScan);
+ gs = (G*)runtime·mallocgc(nelem(p1->runq)*sizeof(*gs), nil, FlagNoScan);
- for(i = 0; i < nelem(gs); i++) {
+ for(i = 0; i < nelem(p1->runq); i++) {
for(j = 0; j < i; j++) {
gs[j].sig = 0;
- runqput(&p1, &gs[j]);
+ runqput(p1, &gs[j]);
}
- gp = runqsteal(&p2, &p1);
+ gp = runqsteal(p2, p1);
s = 0;
if(gp) {
s++;
gp->sig++;
}
- while(gp = runqget(&p2)) {
+ while(gp = runqget(p2)) {
s++;
gp->sig++;
}
- while(gp = runqget(&p1))
+ while(gp = runqget(p1))
gp->sig++;
for(j = 0; j < i; j++) {
if(gs[j].sig != 1) {
@@ -3102,33 +3462,21 @@ runtime·testSchedLocalQueueSteal(void)
}
}
-extern void runtime·morestack(void);
-uintptr runtime·externalthreadhandlerp;
-
-// Does f mark the top of a goroutine stack?
-bool
-runtime·topofstack(Func *f)
-{
- return f->entry == (uintptr)runtime·goexit ||
- f->entry == (uintptr)runtime·mstart ||
- f->entry == (uintptr)runtime·mcall ||
- f->entry == (uintptr)runtime·morestack ||
- f->entry == (uintptr)runtime·lessstack ||
- f->entry == (uintptr)_rt0_go ||
- (runtime·externalthreadhandlerp != 0 && f->entry == runtime·externalthreadhandlerp);
-}
-
-int32
-runtime·setmaxthreads(int32 in)
+void
+runtime·setmaxthreads_m(void)
{
+ int32 in;
int32 out;
- runtime·lock(&runtime·sched);
+ in = g->m->scalararg[0];
+
+ runtime·lock(&runtime·sched.lock);
out = runtime·sched.maxmcount;
runtime·sched.maxmcount = in;
checkmcount();
- runtime·unlock(&runtime·sched);
- return out;
+ runtime·unlock(&runtime·sched.lock);
+
+ g->m->scalararg[0] = out;
}
static int8 experiment[] = GOEXPERIMENT; // defined in zaexperiment.h
@@ -3151,3 +3499,23 @@ haveexperiment(int8 *name)
}
return 0;
}
+
+#pragma textflag NOSPLIT
+void
+sync·runtime_procPin(intptr p)
+{
+ M *mp;
+
+ mp = g->m;
+ // Disable preemption.
+ mp->locks++;
+ p = mp->p->id;
+ FLUSH(&p);
+}
+
+#pragma textflag NOSPLIT
+void
+sync·runtime_procUnpin()
+{
+ g->m->locks--;
+}
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
new file mode 100644
index 000000000..517ca03df
--- /dev/null
+++ b/src/runtime/proc.go
@@ -0,0 +1,246 @@
+// 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"
+
+func newsysmon()
+
+func runtime_init()
+func main_init()
+func main_main()
+
+// The main goroutine.
+func main() {
+ g := getg()
+
+ // Racectx of m0->g0 is used only as the parent of the main goroutine.
+ // It must not be used for anything else.
+ g.m.g0.racectx = 0
+
+ // 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 {
+ maxstacksize = 1000000000
+ } else {
+ maxstacksize = 250000000
+ }
+
+ onM(newsysmon)
+
+ // Lock the main goroutine onto this, the main OS thread,
+ // during initialization. Most programs won't care, but a few
+ // do require certain calls to be made by the main thread.
+ // Those can arrange for main.main to run in the main thread
+ // by calling runtime.LockOSThread during initialization
+ // to preserve the lock.
+ lockOSThread()
+
+ if g.m != &m0 {
+ gothrow("runtime.main not on m0")
+ }
+
+ runtime_init() // must be before defer
+
+ // Defer unlock so that runtime.Goexit during init does the unlock too.
+ needUnlock := true
+ defer func() {
+ if needUnlock {
+ unlockOSThread()
+ }
+ }()
+
+ memstats.enablegc = true // now that runtime is initialized, GC is okay
+
+ main_init()
+
+ needUnlock = false
+ unlockOSThread()
+
+ main_main()
+ if raceenabled {
+ racefini()
+ }
+
+ // Make racy client program work: if panicking on
+ // another goroutine at the same time as main returns,
+ // let the other goroutine finish printing the panic trace.
+ // Once it does, it will exit. See issue 3934.
+ if panicking != 0 {
+ gopark(nil, nil, "panicwait")
+ }
+
+ exit(0)
+ for {
+ var x *int32
+ *x = 0
+ }
+}
+
+var parkunlock_c byte
+
+// start forcegc helper goroutine
+func init() {
+ go forcegchelper()
+}
+
+func forcegchelper() {
+ forcegc.g = getg()
+ forcegc.g.issystem = true
+ for {
+ lock(&forcegc.lock)
+ if forcegc.idle != 0 {
+ gothrow("forcegc: phase error")
+ }
+ atomicstore(&forcegc.idle, 1)
+ goparkunlock(&forcegc.lock, "force gc (idle)")
+ // this goroutine is explicitly resumed by sysmon
+ if debug.gctrace > 0 {
+ println("GC forced")
+ }
+ gogc(1)
+ }
+}
+
+//go:nosplit
+
+// Gosched yields the processor, allowing other goroutines to run. It does not
+// suspend the current goroutine, so execution resumes automatically.
+func Gosched() {
+ mcall(gosched_m)
+}
+
+// Puts the current goroutine into a waiting state and calls unlockf.
+// If unlockf returns false, the goroutine is resumed.
+func gopark(unlockf unsafe.Pointer, lock unsafe.Pointer, reason string) {
+ mp := acquirem()
+ gp := mp.curg
+ status := readgstatus(gp)
+ if status != _Grunning && status != _Gscanrunning {
+ gothrow("gopark: bad g status")
+ }
+ mp.waitlock = lock
+ mp.waitunlockf = unlockf
+ gp.waitreason = reason
+ releasem(mp)
+ // can't do anything that might move the G between Ms here.
+ mcall(park_m)
+}
+
+// Puts the current goroutine into a waiting state and unlocks the lock.
+// The goroutine can be made runnable again by calling goready(gp).
+func goparkunlock(lock *mutex, reason string) {
+ gopark(unsafe.Pointer(&parkunlock_c), unsafe.Pointer(lock), reason)
+}
+
+func goready(gp *g) {
+ mp := acquirem()
+ mp.ptrarg[0] = unsafe.Pointer(gp)
+ onM(ready_m)
+ releasem(mp)
+}
+
+//go:nosplit
+func acquireSudog() *sudog {
+ c := gomcache()
+ s := c.sudogcache
+ if s != nil {
+ if s.elem != nil {
+ gothrow("acquireSudog: found s.elem != nil in cache")
+ }
+ c.sudogcache = s.next
+ s.next = nil
+ return s
+ }
+
+ // Delicate dance: the semaphore implementation calls
+ // acquireSudog, acquireSudog calls new(sudog),
+ // new calls malloc, malloc can call the garbage collector,
+ // and the garbage collector calls the semaphore implementation
+ // in stoptheworld.
+ // Break the cycle by doing acquirem/releasem around new(sudog).
+ // The acquirem/releasem increments m.locks during new(sudog),
+ // which keeps the garbage collector from being invoked.
+ mp := acquirem()
+ p := new(sudog)
+ releasem(mp)
+ return p
+}
+
+//go:nosplit
+func releaseSudog(s *sudog) {
+ if s.elem != nil {
+ gothrow("runtime: sudog with non-nil elem")
+ }
+ if s.selectdone != nil {
+ gothrow("runtime: sudog with non-nil selectdone")
+ }
+ if s.next != nil {
+ gothrow("runtime: sudog with non-nil next")
+ }
+ if s.prev != nil {
+ gothrow("runtime: sudog with non-nil prev")
+ }
+ if s.waitlink != nil {
+ gothrow("runtime: sudog with non-nil waitlink")
+ }
+ gp := getg()
+ if gp.param != nil {
+ gothrow("runtime: releaseSudog with non-nil gp.param")
+ }
+ c := gomcache()
+ s.next = c.sudogcache
+ c.sudogcache = s
+}
+
+// funcPC returns the entry PC of the function f.
+// 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))
+}
+
+// called from assembly
+func badmcall(fn func(*g)) {
+ gothrow("runtime: mcall called on m->g0 stack")
+}
+
+func badmcall2(fn func(*g)) {
+ gothrow("runtime: mcall function returned")
+}
+
+func badreflectcall() {
+ panic("runtime: arg size to reflect.call more than 1GB")
+}
+
+func lockedOSThread() bool {
+ gp := getg()
+ return gp.lockedm != nil && gp.m.lockedg != nil
+}
+
+func newP() *p {
+ return new(p)
+}
+
+func newM() *m {
+ return new(m)
+}
+
+func newG() *g {
+ return new(g)
+}
+
+func allgadd(gp *g) {
+ if readgstatus(gp) == _Gidle {
+ gothrow("allgadd: bad status Gidle")
+ }
+
+ lock(&allglock)
+ allgs = append(allgs, gp)
+ allg = &allgs[0]
+ allglen = uintptr(len(allgs))
+ unlock(&allglock)
+}
diff --git a/src/pkg/runtime/proc_test.go b/src/runtime/proc_test.go
index 5be355195..aa9bc81ac 100644
--- a/src/pkg/runtime/proc_test.go
+++ b/src/runtime/proc_test.go
@@ -101,6 +101,10 @@ func TestGoroutineParallelism(t *testing.T) {
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.
+ // So give this test as much time as possible.
+ runtime.GC()
for try := 0; try < N; try++ {
done := make(chan bool)
x := uint32(0)
@@ -362,11 +366,11 @@ func nonleaf(stop chan int) bool {
}
func TestSchedLocalQueue(t *testing.T) {
- runtime.TestSchedLocalQueue1()
+ runtime.RunSchedLocalQueueTest()
}
func TestSchedLocalQueueSteal(t *testing.T) {
- runtime.TestSchedLocalQueueSteal1()
+ runtime.RunSchedLocalQueueStealTest()
}
func benchmarkStackGrowth(b *testing.B, rec int) {
diff --git a/src/pkg/runtime/race.c b/src/runtime/race.c
index eb0be7fa6..5b0d11664 100644
--- a/src/pkg/runtime/race.c
+++ b/src/runtime/race.c
@@ -11,6 +11,7 @@
#include "race.h"
#include "type.h"
#include "typekind.h"
+#include "textflag.h"
// Race runtime functions called via runtime·racecall.
void __tsan_init(void);
@@ -23,6 +24,8 @@ void __tsan_malloc(void);
void __tsan_acquire(void);
void __tsan_release(void);
void __tsan_release_merge(void);
+void __tsan_go_ignore_sync_begin(void);
+void __tsan_go_ignore_sync_end(void);
// Mimic what cmd/cgo would do.
#pragma cgo_import_static __tsan_init
@@ -35,6 +38,8 @@ void __tsan_release_merge(void);
#pragma cgo_import_static __tsan_acquire
#pragma cgo_import_static __tsan_release
#pragma cgo_import_static __tsan_release_merge
+#pragma cgo_import_static __tsan_go_ignore_sync_begin
+#pragma cgo_import_static __tsan_go_ignore_sync_end
// These are called from race_amd64.s.
#pragma cgo_import_static __tsan_read
@@ -46,9 +51,29 @@ void __tsan_release_merge(void);
#pragma cgo_import_static __tsan_func_enter
#pragma cgo_import_static __tsan_func_exit
-extern byte noptrdata[];
-extern byte enoptrbss[];
-
+#pragma cgo_import_static __tsan_go_atomic32_load
+#pragma cgo_import_static __tsan_go_atomic64_load
+#pragma cgo_import_static __tsan_go_atomic32_store
+#pragma cgo_import_static __tsan_go_atomic64_store
+#pragma cgo_import_static __tsan_go_atomic32_exchange
+#pragma cgo_import_static __tsan_go_atomic64_exchange
+#pragma cgo_import_static __tsan_go_atomic32_fetch_add
+#pragma cgo_import_static __tsan_go_atomic64_fetch_add
+#pragma cgo_import_static __tsan_go_atomic32_compare_exchange
+#pragma cgo_import_static __tsan_go_atomic64_compare_exchange
+
+extern byte runtime·noptrdata[];
+extern byte runtime·enoptrdata[];
+extern byte runtime·data[];
+extern byte runtime·edata[];
+extern byte runtime·bss[];
+extern byte runtime·ebss[];
+extern byte runtime·noptrbss[];
+extern byte runtime·enoptrbss[];
+
+// start/end of global data (data+bss).
+uintptr runtime·racedatastart;
+uintptr runtime·racedataend;
// start/end of heap for race_amd64.s
uintptr runtime·racearenastart;
uintptr runtime·racearenaend;
@@ -63,28 +88,67 @@ void runtime·racesymbolizethunk(void*);
// with up to 4 uintptr arguments.
void runtime·racecall(void(*f)(void), ...);
+// checks if the address has shadow (i.e. heap or data/bss)
+#pragma textflag NOSPLIT
+static bool
+isvalidaddr(uintptr addr)
+{
+ if(addr >= runtime·racearenastart && addr < runtime·racearenaend)
+ return true;
+ if(addr >= runtime·racedatastart && addr < runtime·racedataend)
+ return true;
+ return false;
+}
+
+#pragma textflag NOSPLIT
uintptr
runtime·raceinit(void)
{
- uintptr racectx, start, size;
+ uintptr racectx, start, end, size;
// cgo is required to initialize libc, which is used by race runtime
if(!runtime·iscgo)
runtime·throw("raceinit: race build must use cgo");
runtime·racecall(__tsan_init, &racectx, runtime·racesymbolizethunk);
// Round data segment to page boundaries, because it's used in mmap().
- start = (uintptr)noptrdata & ~(PageSize-1);
- size = ROUND((uintptr)enoptrbss - start, PageSize);
+ // The relevant sections are noptrdata, data, bss, noptrbss.
+ // In external linking mode, there may be other non-Go data mixed in,
+ // and the sections may even occur out of order.
+ // Work out a conservative range of addresses.
+ start = ~(uintptr)0;
+ end = 0;
+ if(start > (uintptr)runtime·noptrdata)
+ start = (uintptr)runtime·noptrdata;
+ if(start > (uintptr)runtime·data)
+ start = (uintptr)runtime·data;
+ if(start > (uintptr)runtime·noptrbss)
+ start = (uintptr)runtime·noptrbss;
+ if(start > (uintptr)runtime·bss)
+ start = (uintptr)runtime·bss;
+ if(end < (uintptr)runtime·enoptrdata)
+ end = (uintptr)runtime·enoptrdata;
+ if(end < (uintptr)runtime·edata)
+ end = (uintptr)runtime·edata;
+ if(end < (uintptr)runtime·enoptrbss)
+ end = (uintptr)runtime·enoptrbss;
+ if(end < (uintptr)runtime·ebss)
+ end = (uintptr)runtime·ebss;
+ start = start & ~(PageSize-1);
+ size = ROUND(end - start, PageSize);
runtime·racecall(__tsan_map_shadow, start, size);
+ runtime·racedatastart = start;
+ runtime·racedataend = start + size;
return racectx;
}
+#pragma textflag NOSPLIT
void
runtime·racefini(void)
{
runtime·racecall(__tsan_fini);
}
+#pragma textflag NOSPLIT
void
runtime·racemapshadow(void *addr, uintptr size)
{
@@ -95,30 +159,45 @@ runtime·racemapshadow(void *addr, uintptr size)
runtime·racecall(__tsan_map_shadow, addr, size);
}
+#pragma textflag NOSPLIT
void
runtime·racemalloc(void *p, uintptr sz)
{
runtime·racecall(__tsan_malloc, p, sz);
}
+#pragma textflag NOSPLIT
uintptr
runtime·racegostart(void *pc)
{
uintptr racectx;
+ G *spawng;
- runtime·racecall(__tsan_go_start, g->racectx, &racectx, pc);
+ if(g->m->curg != nil)
+ spawng = g->m->curg;
+ else
+ spawng = g;
+
+ runtime·racecall(__tsan_go_start, spawng->racectx, &racectx, pc);
return racectx;
}
+#pragma textflag NOSPLIT
void
runtime·racegoend(void)
{
runtime·racecall(__tsan_go_end, g->racectx);
}
+#pragma textflag NOSPLIT
void
runtime·racewriterangepc(void *addr, uintptr sz, void *callpc, void *pc)
{
+ if(g != g->m->curg) {
+ // The call is coming from manual instrumentation of Go code running on g0/gsignal.
+ // Not interesting.
+ return;
+ }
if(callpc != nil)
runtime·racefuncenter(callpc);
runtime·racewriterangepc1(addr, sz, pc);
@@ -126,9 +205,15 @@ runtime·racewriterangepc(void *addr, uintptr sz, void *callpc, void *pc)
runtime·racefuncexit();
}
+#pragma textflag NOSPLIT
void
runtime·racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc)
{
+ if(g != g->m->curg) {
+ // The call is coming from manual instrumentation of Go code running on g0/gsignal.
+ // Not interesting.
+ return;
+ }
if(callpc != nil)
runtime·racefuncenter(callpc);
runtime·racereadrangepc1(addr, sz, pc);
@@ -136,72 +221,83 @@ runtime·racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc)
runtime·racefuncexit();
}
+#pragma textflag NOSPLIT
void
runtime·racewriteobjectpc(void *addr, Type *t, void *callpc, void *pc)
{
uint8 kind;
- kind = t->kind & ~KindNoPointers;
+ kind = t->kind & KindMask;
if(kind == KindArray || kind == KindStruct)
runtime·racewriterangepc(addr, t->size, callpc, pc);
else
runtime·racewritepc(addr, callpc, pc);
}
+#pragma textflag NOSPLIT
void
runtime·racereadobjectpc(void *addr, Type *t, void *callpc, void *pc)
{
uint8 kind;
- kind = t->kind & ~KindNoPointers;
+ kind = t->kind & KindMask;
if(kind == KindArray || kind == KindStruct)
runtime·racereadrangepc(addr, t->size, callpc, pc);
else
runtime·racereadpc(addr, callpc, pc);
}
+#pragma textflag NOSPLIT
void
runtime·raceacquire(void *addr)
{
runtime·raceacquireg(g, addr);
}
+#pragma textflag NOSPLIT
void
runtime·raceacquireg(G *gp, void *addr)
{
- if(g->raceignore)
+ if(g->raceignore || !isvalidaddr((uintptr)addr))
return;
runtime·racecall(__tsan_acquire, gp->racectx, addr);
}
+#pragma textflag NOSPLIT
void
runtime·racerelease(void *addr)
{
+ if(g->raceignore || !isvalidaddr((uintptr)addr))
+ return;
runtime·racereleaseg(g, addr);
}
+#pragma textflag NOSPLIT
void
runtime·racereleaseg(G *gp, void *addr)
{
- if(g->raceignore)
+ if(g->raceignore || !isvalidaddr((uintptr)addr))
return;
runtime·racecall(__tsan_release, gp->racectx, addr);
}
+#pragma textflag NOSPLIT
void
runtime·racereleasemerge(void *addr)
{
runtime·racereleasemergeg(g, addr);
}
+#pragma textflag NOSPLIT
void
runtime·racereleasemergeg(G *gp, void *addr)
{
- if(g->raceignore)
+ if(g->raceignore || !isvalidaddr((uintptr)addr))
return;
runtime·racecall(__tsan_release_merge, gp->racectx, addr);
}
+#pragma textflag NOSPLIT
void
runtime·racefingo(void)
{
@@ -209,6 +305,7 @@ runtime·racefingo(void)
}
// func RaceAcquire(addr unsafe.Pointer)
+#pragma textflag NOSPLIT
void
runtime·RaceAcquire(void *addr)
{
@@ -216,6 +313,7 @@ runtime·RaceAcquire(void *addr)
}
// func RaceRelease(addr unsafe.Pointer)
+#pragma textflag NOSPLIT
void
runtime·RaceRelease(void *addr)
{
@@ -223,70 +321,27 @@ runtime·RaceRelease(void *addr)
}
// func RaceReleaseMerge(addr unsafe.Pointer)
+#pragma textflag NOSPLIT
void
runtime·RaceReleaseMerge(void *addr)
{
runtime·racereleasemerge(addr);
}
-// func RaceSemacquire(s *uint32)
-void
-runtime·RaceSemacquire(uint32 *s)
-{
- runtime·semacquire(s, false);
-}
-
-// func RaceSemrelease(s *uint32)
-void
-runtime·RaceSemrelease(uint32 *s)
-{
- runtime·semrelease(s);
-}
-
// func RaceDisable()
+#pragma textflag NOSPLIT
void
runtime·RaceDisable(void)
{
- g->raceignore++;
+ if(g->raceignore++ == 0)
+ runtime·racecall(__tsan_go_ignore_sync_begin, g->racectx);
}
// func RaceEnable()
+#pragma textflag NOSPLIT
void
runtime·RaceEnable(void)
{
- g->raceignore--;
-}
-
-typedef struct SymbolizeContext SymbolizeContext;
-struct SymbolizeContext
-{
- uintptr pc;
- int8* func;
- int8* file;
- uintptr line;
- uintptr off;
- uintptr res;
-};
-
-// Callback from C into Go, runs on g0.
-void
-runtime·racesymbolize(SymbolizeContext *ctx)
-{
- Func *f;
- String file;
-
- f = runtime·findfunc(ctx->pc);
- if(f == nil) {
- ctx->func = "??";
- ctx->file = "-";
- ctx->line = 0;
- ctx->off = ctx->pc;
- ctx->res = 1;
- return;
- }
- ctx->func = runtime·funcname(f);
- ctx->line = runtime·funcline(f, ctx->pc, &file);
- ctx->file = (int8*)file.str; // assume zero-terminated
- ctx->off = ctx->pc - f->entry;
- ctx->res = 1;
+ if(--g->raceignore == 0)
+ runtime·racecall(__tsan_go_ignore_sync_end, g->racectx);
}
diff --git a/src/runtime/race.go b/src/runtime/race.go
new file mode 100644
index 000000000..bb0ee6df6
--- /dev/null
+++ b/src/runtime/race.go
@@ -0,0 +1,127 @@
+// 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
+
+// Public race detection API, present iff build with -race.
+
+package runtime
+
+import (
+ "unsafe"
+)
+
+func racefini()
+
+// RaceDisable disables handling of race events in the current goroutine.
+func RaceDisable()
+
+// RaceEnable re-enables handling of race events in the current goroutine.
+func RaceEnable()
+
+func RaceAcquire(addr unsafe.Pointer)
+func RaceRelease(addr unsafe.Pointer)
+func RaceReleaseMerge(addr unsafe.Pointer)
+
+func RaceRead(addr unsafe.Pointer)
+func RaceWrite(addr unsafe.Pointer)
+func RaceReadRange(addr unsafe.Pointer, len int)
+func RaceWriteRange(addr unsafe.Pointer, len int)
+
+func RaceSemacquire(s *uint32)
+func RaceSemrelease(s *uint32)
+
+// private interface for the runtime
+const raceenabled = true
+
+func raceReadObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) {
+ kind := t.kind & kindMask
+ if kind == kindArray || kind == kindStruct {
+ // for composite objects we have to read every address
+ // because a write might happen to any subobject.
+ racereadrangepc(addr, t.size, callerpc, pc)
+ } else {
+ // for non-composite objects we can read just the start
+ // address, as any write must write the first byte.
+ racereadpc(addr, callerpc, pc)
+ }
+}
+
+func raceWriteObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) {
+ kind := t.kind & kindMask
+ if kind == kindArray || kind == kindStruct {
+ // for composite objects we have to write every address
+ // because a write might happen to any subobject.
+ racewriterangepc(addr, t.size, callerpc, pc)
+ } else {
+ // for non-composite objects we can write just the start
+ // address, as any write must write the first byte.
+ racewritepc(addr, callerpc, pc)
+ }
+}
+
+//go:noescape
+func racereadpc(addr unsafe.Pointer, callpc, pc uintptr)
+
+//go:noescape
+func racewritepc(addr unsafe.Pointer, callpc, pc uintptr)
+
+//go:noescape
+func racereadrangepc(addr unsafe.Pointer, len uintptr, callpc, pc uintptr)
+
+//go:noescape
+func racewriterangepc(addr unsafe.Pointer, len uintptr, callpc, pc uintptr)
+
+//go:noescape
+func raceacquire(addr unsafe.Pointer)
+
+//go:noescape
+func racerelease(addr unsafe.Pointer)
+
+//go:noescape
+func raceacquireg(gp *g, addr unsafe.Pointer)
+
+//go:noescape
+func racereleaseg(gp *g, addr unsafe.Pointer)
+
+func racefingo()
+
+//go:noescape
+func racemalloc(p unsafe.Pointer, size uintptr)
+
+//go:noescape
+func racereleasemerge(addr unsafe.Pointer)
+
+type symbolizeContext struct {
+ pc uintptr
+ fn *byte
+ file *byte
+ line uintptr
+ off uintptr
+ res uintptr
+}
+
+var qq = [...]byte{'?', '?', 0}
+var dash = [...]byte{'-', 0}
+
+// Callback from C into Go, runs on g0.
+func racesymbolize(ctx *symbolizeContext) {
+ f := findfunc(ctx.pc)
+ if f == nil {
+ ctx.fn = &qq[0]
+ ctx.file = &dash[0]
+ ctx.line = 0
+ ctx.off = ctx.pc
+ ctx.res = 1
+ return
+ }
+
+ ctx.fn = funcname(f)
+ var file string
+ ctx.line = uintptr(funcline(f, ctx.pc, &file))
+ ctx.file = &bytes(file)[0] // assume NUL-terminated
+ ctx.off = ctx.pc - f.entry
+ ctx.res = 1
+ return
+}
diff --git a/src/pkg/runtime/race.h b/src/runtime/race.h
index fee31e09f..fee31e09f 100644
--- a/src/pkg/runtime/race.h
+++ b/src/runtime/race.h
diff --git a/src/pkg/runtime/race/README b/src/runtime/race/README
index 785640607..7f185359f 100644
--- a/src/pkg/runtime/race/README
+++ b/src/runtime/race/README
@@ -9,4 +9,4 @@ $ ./buildgo.sh
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 203116.
+Current runtime is built on rev 215000.
diff --git a/src/pkg/runtime/race/doc.go b/src/runtime/race/doc.go
index aef805dad..aef805dad 100644
--- a/src/pkg/runtime/race/doc.go
+++ b/src/runtime/race/doc.go
diff --git a/src/pkg/runtime/race/output_test.go b/src/runtime/race/output_test.go
index d2303f7af..d2303f7af 100644
--- a/src/pkg/runtime/race/output_test.go
+++ b/src/runtime/race/output_test.go
diff --git a/src/pkg/runtime/race/race.go b/src/runtime/race/race.go
index e53cacf4a..31deedd73 100644
--- a/src/pkg/runtime/race/race.go
+++ b/src/runtime/race/race.go
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build race,linux,amd64 race,darwin,amd64 race,windows,amd64
+// +build race,linux,amd64 race,freebsd,amd64 race,darwin,amd64 race,windows,amd64
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/pkg/runtime/race.c.
+// Calls to the runtime are done directly from src/runtime/race.c.
// 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
new file mode 100644
index 000000000..81b48c6c9
--- /dev/null
+++ b/src/runtime/race/race_darwin_amd64.syso
Binary files differ
diff --git a/src/runtime/race/race_freebsd_amd64.syso b/src/runtime/race/race_freebsd_amd64.syso
new file mode 100644
index 000000000..5bbe32229
--- /dev/null
+++ b/src/runtime/race/race_freebsd_amd64.syso
Binary files differ
diff --git a/src/runtime/race/race_linux_amd64.syso b/src/runtime/race/race_linux_amd64.syso
new file mode 100644
index 000000000..49bf08ef3
--- /dev/null
+++ b/src/runtime/race/race_linux_amd64.syso
Binary files differ
diff --git a/src/pkg/runtime/race/race_test.go b/src/runtime/race/race_test.go
index 7e0ee866a..7e0ee866a 100644
--- a/src/pkg/runtime/race/race_test.go
+++ b/src/runtime/race/race_test.go
diff --git a/src/runtime/race/race_unix_test.go b/src/runtime/race/race_unix_test.go
new file mode 100644
index 000000000..84f0acece
--- /dev/null
+++ b/src/runtime/race/race_unix_test.go
@@ -0,0 +1,30 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build race
+// +build darwin freebsd linux
+
+package race_test
+
+import (
+ "sync/atomic"
+ "syscall"
+ "testing"
+ "unsafe"
+)
+
+// Test that race detector does not crash when accessing non-Go allocated memory (issue 9136).
+func TestNonGoMemory(t *testing.T) {
+ data, err := syscall.Mmap(-1, 0, 4096, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
+ if err != nil {
+ t.Fatalf("failed to mmap memory: %v", err)
+ }
+ p := (*uint32)(unsafe.Pointer(&data[0]))
+ atomic.AddUint32(p, 1)
+ (*p)++
+ if *p != 2 {
+ t.Fatalf("data[0] = %v, expect 2", *p)
+ }
+ syscall.Munmap(data)
+}
diff --git a/src/runtime/race/race_windows_amd64.syso b/src/runtime/race/race_windows_amd64.syso
new file mode 100644
index 000000000..a4eae9bdd
--- /dev/null
+++ b/src/runtime/race/race_windows_amd64.syso
Binary files differ
diff --git a/src/pkg/runtime/race/testdata/atomic_test.go b/src/runtime/race/testdata/atomic_test.go
index fc569b96c..232744b3d 100644
--- a/src/pkg/runtime/race/testdata/atomic_test.go
+++ b/src/runtime/race/testdata/atomic_test.go
@@ -225,8 +225,7 @@ func TestNoRaceAtomicStoreCASUint64(t *testing.T) {
x = 1
}
-// Races with non-atomic loads are not detected.
-func TestRaceFailingAtomicStoreLoad(t *testing.T) {
+func TestRaceAtomicStoreLoad(t *testing.T) {
c := make(chan bool)
var a uint64
go func() {
@@ -248,8 +247,7 @@ func TestRaceAtomicLoadStore(t *testing.T) {
<-c
}
-// Races with non-atomic loads are not detected.
-func TestRaceFailingAtomicAddLoad(t *testing.T) {
+func TestRaceAtomicAddLoad(t *testing.T) {
c := make(chan bool)
var a uint64
go func() {
diff --git a/src/pkg/runtime/race/testdata/cgo_test.go b/src/runtime/race/testdata/cgo_test.go
index ba7e7b562..ba7e7b562 100644
--- a/src/pkg/runtime/race/testdata/cgo_test.go
+++ b/src/runtime/race/testdata/cgo_test.go
diff --git a/src/pkg/runtime/race/testdata/cgo_test_main.go b/src/runtime/race/testdata/cgo_test_main.go
index 620cea18b..620cea18b 100644
--- a/src/pkg/runtime/race/testdata/cgo_test_main.go
+++ b/src/runtime/race/testdata/cgo_test_main.go
diff --git a/src/pkg/runtime/race/testdata/chan_test.go b/src/runtime/race/testdata/chan_test.go
index 4a3d5290f..eabd81f40 100644
--- a/src/pkg/runtime/race/testdata/chan_test.go
+++ b/src/runtime/race/testdata/chan_test.go
@@ -88,7 +88,7 @@ func TestNoRaceChanAsyncCloseRecv3(t *testing.T) {
v = 1
close(c)
}()
- for _ = range c {
+ for range c {
}
v = 2
}
@@ -127,7 +127,7 @@ func TestNoRaceChanSyncCloseRecv3(t *testing.T) {
v = 1
close(c)
}()
- for _ = range c {
+ for range c {
}
v = 2
}
diff --git a/src/pkg/runtime/race/testdata/comp_test.go b/src/runtime/race/testdata/comp_test.go
index 27b2d0081..27b2d0081 100644
--- a/src/pkg/runtime/race/testdata/comp_test.go
+++ b/src/runtime/race/testdata/comp_test.go
diff --git a/src/pkg/runtime/race/testdata/finalizer_test.go b/src/runtime/race/testdata/finalizer_test.go
index 222cbf67a..222cbf67a 100644
--- a/src/pkg/runtime/race/testdata/finalizer_test.go
+++ b/src/runtime/race/testdata/finalizer_test.go
diff --git a/src/pkg/runtime/race/testdata/io_test.go b/src/runtime/race/testdata/io_test.go
index 9eb3552dc..9eb3552dc 100644
--- a/src/pkg/runtime/race/testdata/io_test.go
+++ b/src/runtime/race/testdata/io_test.go
diff --git a/src/pkg/runtime/race/testdata/map_test.go b/src/runtime/race/testdata/map_test.go
index 98e2a5f10..a8d8148d0 100644
--- a/src/pkg/runtime/race/testdata/map_test.go
+++ b/src/runtime/race/testdata/map_test.go
@@ -57,7 +57,7 @@ func TestRaceMapRange(t *testing.T) {
m := make(map[int]int)
ch := make(chan bool, 1)
go func() {
- for _ = range m {
+ for range m {
}
ch <- true
}()
@@ -69,7 +69,7 @@ func TestRaceMapRange2(t *testing.T) {
m := make(map[int]int)
ch := make(chan bool, 1)
go func() {
- for _ = range m {
+ for range m {
}
ch <- true
}()
@@ -85,11 +85,11 @@ func TestNoRaceMapRangeRange(t *testing.T) {
m[0] = 0
ch := make(chan bool, 1)
go func() {
- for _ = range m {
+ for range m {
}
ch <- true
}()
- for _ = range m {
+ for range m {
}
<-ch
}
@@ -238,3 +238,96 @@ func TestRaceMapAssignMultipleReturn(t *testing.T) {
_ = x
<-ch
}
+
+// BigKey and BigVal must be larger than 256 bytes,
+// so that compiler sets KindGCProg for them.
+type BigKey [1000]*int
+
+type BigVal struct {
+ x int
+ y [1000]*int
+}
+
+func TestRaceMapBigKeyAccess1(t *testing.T) {
+ m := make(map[BigKey]int)
+ var k BigKey
+ ch := make(chan bool, 1)
+ go func() {
+ _ = m[k]
+ ch <- true
+ }()
+ k[30] = new(int)
+ <-ch
+}
+
+func TestRaceMapBigKeyAccess2(t *testing.T) {
+ m := make(map[BigKey]int)
+ var k BigKey
+ ch := make(chan bool, 1)
+ go func() {
+ _, _ = m[k]
+ ch <- true
+ }()
+ k[30] = new(int)
+ <-ch
+}
+
+func TestRaceMapBigKeyInsert(t *testing.T) {
+ m := make(map[BigKey]int)
+ var k BigKey
+ ch := make(chan bool, 1)
+ go func() {
+ m[k] = 1
+ ch <- true
+ }()
+ k[30] = new(int)
+ <-ch
+}
+
+func TestRaceMapBigKeyDelete(t *testing.T) {
+ m := make(map[BigKey]int)
+ var k BigKey
+ ch := make(chan bool, 1)
+ go func() {
+ delete(m, k)
+ ch <- true
+ }()
+ k[30] = new(int)
+ <-ch
+}
+
+func TestRaceMapBigValInsert(t *testing.T) {
+ m := make(map[int]BigVal)
+ var v BigVal
+ ch := make(chan bool, 1)
+ go func() {
+ m[1] = v
+ ch <- true
+ }()
+ v.y[30] = new(int)
+ <-ch
+}
+
+func TestRaceMapBigValAccess1(t *testing.T) {
+ m := make(map[int]BigVal)
+ var v BigVal
+ ch := make(chan bool, 1)
+ go func() {
+ v = m[1]
+ ch <- true
+ }()
+ v.y[30] = new(int)
+ <-ch
+}
+
+func TestRaceMapBigValAccess2(t *testing.T) {
+ m := make(map[int]BigVal)
+ var v BigVal
+ ch := make(chan bool, 1)
+ go func() {
+ v, _ = m[1]
+ ch <- true
+ }()
+ v.y[30] = new(int)
+ <-ch
+}
diff --git a/src/pkg/runtime/race/testdata/mop_test.go b/src/runtime/race/testdata/mop_test.go
index 14591b184..cb17a27d3 100644
--- a/src/pkg/runtime/race/testdata/mop_test.go
+++ b/src/runtime/race/testdata/mop_test.go
@@ -233,7 +233,7 @@ func TestRaceCaseFallthrough(t *testing.T) {
func TestRaceCaseIssue6418(t *testing.T) {
m := map[string]map[string]string{
- "a": map[string]string{
+ "a": {
"b": "c",
},
}
diff --git a/src/pkg/runtime/race/testdata/mutex_test.go b/src/runtime/race/testdata/mutex_test.go
index 3cf03ae6b..3cf03ae6b 100644
--- a/src/pkg/runtime/race/testdata/mutex_test.go
+++ b/src/runtime/race/testdata/mutex_test.go
diff --git a/src/pkg/runtime/race/testdata/regression_test.go b/src/runtime/race/testdata/regression_test.go
index d461269d9..d461269d9 100644
--- a/src/pkg/runtime/race/testdata/regression_test.go
+++ b/src/runtime/race/testdata/regression_test.go
diff --git a/src/pkg/runtime/race/testdata/rwmutex_test.go b/src/runtime/race/testdata/rwmutex_test.go
index 85cb5df3c..85cb5df3c 100644
--- a/src/pkg/runtime/race/testdata/rwmutex_test.go
+++ b/src/runtime/race/testdata/rwmutex_test.go
diff --git a/src/pkg/runtime/race/testdata/select_test.go b/src/runtime/race/testdata/select_test.go
index 4a3a23647..4a3a23647 100644
--- a/src/pkg/runtime/race/testdata/select_test.go
+++ b/src/runtime/race/testdata/select_test.go
diff --git a/src/pkg/runtime/race/testdata/slice_test.go b/src/runtime/race/testdata/slice_test.go
index c85df5e3d..5702d1ac8 100644
--- a/src/pkg/runtime/race/testdata/slice_test.go
+++ b/src/runtime/race/testdata/slice_test.go
@@ -198,7 +198,7 @@ func TestNoRaceStructSlicesRangeWrite(t *testing.T) {
s.a = make([]int, 10)
s.b = make([]int, 10)
go func() {
- for _ = range s.a {
+ for range s.a {
}
ch <- true
}()
@@ -240,7 +240,7 @@ func TestNoRaceSliceRangeWrite(t *testing.T) {
s[3] = 3
c <- true
}()
- for _ = range s {
+ for range s {
}
<-c
}
@@ -252,7 +252,7 @@ func TestRaceSliceRangeAppend(t *testing.T) {
s = append(s, 3)
c <- true
}()
- for _ = range s {
+ for range s {
}
<-c
}
@@ -264,7 +264,7 @@ func TestNoRaceSliceRangeAppend(t *testing.T) {
_ = append(s, 3)
c <- true
}()
- for _ = range s {
+ for range s {
}
<-c
}
@@ -295,7 +295,7 @@ func TestRaceSliceVarRange(t *testing.T) {
c := make(chan bool, 1)
s := make([]int, 10)
go func() {
- for _ = range s {
+ for range s {
}
c <- true
}()
diff --git a/src/pkg/runtime/race/testdata/sync_test.go b/src/runtime/race/testdata/sync_test.go
index 93af0b1e6..93af0b1e6 100644
--- a/src/pkg/runtime/race/testdata/sync_test.go
+++ b/src/runtime/race/testdata/sync_test.go
diff --git a/src/pkg/runtime/race/testdata/waitgroup_test.go b/src/runtime/race/testdata/waitgroup_test.go
index ff152b0ab..ff152b0ab 100644
--- a/src/pkg/runtime/race/testdata/waitgroup_test.go
+++ b/src/runtime/race/testdata/waitgroup_test.go
diff --git a/src/runtime/race0.go b/src/runtime/race0.go
new file mode 100644
index 000000000..5d90cc859
--- /dev/null
+++ b/src/runtime/race0.go
@@ -0,0 +1,37 @@
+// 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 !race
+
+// Dummy race detection API, used when not built with -race.
+
+package runtime
+
+import (
+ "unsafe"
+)
+
+const raceenabled = false
+
+// Because raceenabled is false, none of these functions should be called.
+
+func raceReadObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) { gothrow("race") }
+func raceWriteObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) { gothrow("race") }
+func raceinit() { gothrow("race") }
+func racefini() { gothrow("race") }
+func racemapshadow(addr unsafe.Pointer, size uintptr) { gothrow("race") }
+func racewritepc(addr unsafe.Pointer, callerpc, pc uintptr) { gothrow("race") }
+func racereadpc(addr unsafe.Pointer, callerpc, pc uintptr) { gothrow("race") }
+func racereadrangepc(addr unsafe.Pointer, sz, callerpc, pc uintptr) { gothrow("race") }
+func racewriterangepc(addr unsafe.Pointer, sz, callerpc, pc uintptr) { gothrow("race") }
+func raceacquire(addr unsafe.Pointer) { gothrow("race") }
+func raceacquireg(gp *g, addr unsafe.Pointer) { gothrow("race") }
+func racerelease(addr unsafe.Pointer) { gothrow("race") }
+func racereleaseg(gp *g, addr unsafe.Pointer) { gothrow("race") }
+func racereleasemerge(addr unsafe.Pointer) { gothrow("race") }
+func racereleasemergeg(gp *g, addr unsafe.Pointer) { gothrow("race") }
+func racefingo() { gothrow("race") }
+func racemalloc(p unsafe.Pointer, sz uintptr) { gothrow("race") }
+func racegostart(pc uintptr) uintptr { gothrow("race"); return 0 }
+func racegoend() { gothrow("race") }
diff --git a/src/pkg/runtime/race_amd64.s b/src/runtime/race_amd64.s
index d60cf899b..a96d9de12 100644
--- a/src/pkg/runtime/race_amd64.s
+++ b/src/runtime/race_amd64.s
@@ -6,7 +6,7 @@
#include "zasm_GOOS_GOARCH.h"
#include "funcdata.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// The following thunks allow calling the gcc-compiled race runtime directly
// from Go code without going all the way through cgo.
@@ -79,7 +79,7 @@ TEXT runtime·RaceWrite(SB), NOSPLIT, $0-8
TEXT runtime·racewritepc(SB), NOSPLIT, $0-24
MOVQ addr+0(FP), RARG1
MOVQ callpc+8(FP), RARG2
- MOVQ cp+16(FP), RARG3
+ MOVQ pc+16(FP), RARG3
// void __tsan_write_pc(ThreadState *thr, void *addr, void *callpc, void *pc);
MOVQ $__tsan_write_pc(SB), AX
JMP racecalladdr<>(SB)
@@ -138,15 +138,15 @@ TEXT racecalladdr<>(SB), NOSPLIT, $0-0
get_tls(R12)
MOVQ g(R12), R14
MOVQ g_racectx(R14), RARG0 // goroutine context
- // Check that addr is within [arenastart, arenaend) or within [noptrdata, enoptrbss).
+ // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
CMPQ RARG1, runtime·racearenastart(SB)
JB racecalladdr_data
CMPQ RARG1, runtime·racearenaend(SB)
JB racecalladdr_call
racecalladdr_data:
- CMPQ RARG1, $noptrdata(SB)
+ CMPQ RARG1, runtime·racedatastart(SB)
JB racecalladdr_ret
- CMPQ RARG1, $enoptrbss(SB)
+ CMPQ RARG1, runtime·racedataend(SB)
JAE racecalladdr_ret
racecalladdr_call:
MOVQ AX, AX // w/o this 6a miscompiles this function
@@ -164,6 +164,7 @@ TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8
MOVQ callpc+0(FP), RARG1
// void __tsan_func_enter(ThreadState *thr, void *pc);
MOVQ $__tsan_func_enter(SB), AX
+ // racecall<> preserves R15
CALL racecall<>(SB)
MOVQ R15, DX // restore function entry context
RET
@@ -178,6 +179,173 @@ TEXT runtime·racefuncexit(SB), NOSPLIT, $0-0
MOVQ $__tsan_func_exit(SB), AX
JMP racecall<>(SB)
+// Atomic operations for sync/atomic package.
+
+// Load
+TEXT sync∕atomic·LoadInt32(SB), NOSPLIT, $0-0
+ MOVQ $__tsan_go_atomic32_load(SB), AX
+ CALL racecallatomic<>(SB)
+ RET
+
+TEXT sync∕atomic·LoadInt64(SB), NOSPLIT, $0-0
+ MOVQ $__tsan_go_atomic64_load(SB), AX
+ CALL racecallatomic<>(SB)
+ RET
+
+TEXT sync∕atomic·LoadUint32(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·LoadInt32(SB)
+
+TEXT sync∕atomic·LoadUint64(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·LoadInt64(SB)
+
+TEXT sync∕atomic·LoadUintptr(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·LoadInt64(SB)
+
+TEXT sync∕atomic·LoadPointer(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·LoadInt64(SB)
+
+// Store
+TEXT sync∕atomic·StoreInt32(SB), NOSPLIT, $0-0
+ MOVQ $__tsan_go_atomic32_store(SB), AX
+ CALL racecallatomic<>(SB)
+ RET
+
+TEXT sync∕atomic·StoreInt64(SB), NOSPLIT, $0-0
+ MOVQ $__tsan_go_atomic64_store(SB), AX
+ CALL racecallatomic<>(SB)
+ RET
+
+TEXT sync∕atomic·StoreUint32(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·StoreInt32(SB)
+
+TEXT sync∕atomic·StoreUint64(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·StoreInt64(SB)
+
+TEXT sync∕atomic·StoreUintptr(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·StoreInt64(SB)
+
+TEXT sync∕atomic·StorePointer(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·StoreInt64(SB)
+
+// Swap
+TEXT sync∕atomic·SwapInt32(SB), NOSPLIT, $0-0
+ MOVQ $__tsan_go_atomic32_exchange(SB), AX
+ CALL racecallatomic<>(SB)
+ RET
+
+TEXT sync∕atomic·SwapInt64(SB), NOSPLIT, $0-0
+ MOVQ $__tsan_go_atomic64_exchange(SB), AX
+ CALL racecallatomic<>(SB)
+ RET
+
+TEXT sync∕atomic·SwapUint32(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·SwapInt32(SB)
+
+TEXT sync∕atomic·SwapUint64(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·SwapInt64(SB)
+
+TEXT sync∕atomic·SwapUintptr(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·SwapInt64(SB)
+
+TEXT sync∕atomic·SwapPointer(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·SwapInt64(SB)
+
+// Add
+TEXT sync∕atomic·AddInt32(SB), NOSPLIT, $0-0
+ MOVQ $__tsan_go_atomic32_fetch_add(SB), AX
+ CALL racecallatomic<>(SB)
+ MOVL add+8(FP), AX // convert fetch_add to add_fetch
+ ADDL AX, ret+16(FP)
+ RET
+
+TEXT sync∕atomic·AddInt64(SB), NOSPLIT, $0-0
+ MOVQ $__tsan_go_atomic64_fetch_add(SB), AX
+ CALL racecallatomic<>(SB)
+ MOVQ add+8(FP), AX // convert fetch_add to add_fetch
+ ADDQ AX, ret+16(FP)
+ RET
+
+TEXT sync∕atomic·AddUint32(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·AddInt32(SB)
+
+TEXT sync∕atomic·AddUint64(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·AddInt64(SB)
+
+TEXT sync∕atomic·AddUintptr(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·AddInt64(SB)
+
+TEXT sync∕atomic·AddPointer(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·AddInt64(SB)
+
+// CompareAndSwap
+TEXT sync∕atomic·CompareAndSwapInt32(SB), NOSPLIT, $0-0
+ MOVQ $__tsan_go_atomic32_compare_exchange(SB), AX
+ CALL racecallatomic<>(SB)
+ RET
+
+TEXT sync∕atomic·CompareAndSwapInt64(SB), NOSPLIT, $0-0
+ MOVQ $__tsan_go_atomic64_compare_exchange(SB), AX
+ CALL racecallatomic<>(SB)
+ RET
+
+TEXT sync∕atomic·CompareAndSwapUint32(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·CompareAndSwapInt32(SB)
+
+TEXT sync∕atomic·CompareAndSwapUint64(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·CompareAndSwapInt64(SB)
+
+TEXT sync∕atomic·CompareAndSwapUintptr(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·CompareAndSwapInt64(SB)
+
+TEXT sync∕atomic·CompareAndSwapPointer(SB), NOSPLIT, $0-0
+ JMP sync∕atomic·CompareAndSwapInt64(SB)
+
+// Generic atomic operation implementation.
+// AX already contains target function.
+TEXT racecallatomic<>(SB), NOSPLIT, $0-0
+ // Trigger SIGSEGV early.
+ MOVQ 16(SP), R12
+ MOVL (R12), R13
+ // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
+ CMPQ R12, runtime·racearenastart(SB)
+ JB racecallatomic_data
+ CMPQ R12, runtime·racearenaend(SB)
+ JB racecallatomic_ok
+racecallatomic_data:
+ CMPQ R12, runtime·racedatastart(SB)
+ JB racecallatomic_ignore
+ CMPQ R12, runtime·racedataend(SB)
+ JAE racecallatomic_ignore
+racecallatomic_ok:
+ // Addr is within the good range, call the atomic function.
+ get_tls(R12)
+ MOVQ g(R12), R14
+ MOVQ g_racectx(R14), RARG0 // goroutine context
+ MOVQ 8(SP), RARG1 // caller pc
+ MOVQ (SP), RARG2 // pc
+ LEAQ 16(SP), RARG3 // arguments
+ JMP racecall<>(SB) // does not return
+racecallatomic_ignore:
+ // Addr is outside the good range.
+ // Call __tsan_go_ignore_sync_begin to ignore synchronization during the atomic op.
+ // An attempt to synchronize on the address would cause crash.
+ MOVQ AX, R15 // remember the original function
+ MOVQ $__tsan_go_ignore_sync_begin(SB), AX
+ MOVQ g(R12), R14
+ MOVQ g_racectx(R14), RARG0 // goroutine context
+ CALL racecall<>(SB)
+ MOVQ R15, AX // restore the original function
+ // Call the atomic function.
+ MOVQ g_racectx(R14), RARG0 // goroutine context
+ MOVQ 8(SP), RARG1 // caller pc
+ MOVQ (SP), RARG2 // pc
+ LEAQ 16(SP), RARG3 // arguments
+ CALL racecall<>(SB)
+ // Call __tsan_go_ignore_sync_end.
+ MOVQ $__tsan_go_ignore_sync_end(SB), AX
+ MOVQ g_racectx(R14), RARG0 // goroutine context
+ JMP racecall<>(SB)
+
// void runtime·racecall(void(*f)(...), ...)
// Calls C function f from race runtime and passes up to 4 arguments to it.
// The arguments are never heap-object-preserving pointers, so we pretend there are no arguments.
@@ -192,8 +360,8 @@ TEXT runtime·racecall(SB), NOSPLIT, $0-0
// Switches SP to g0 stack and calls (AX). Arguments already set.
TEXT racecall<>(SB), NOSPLIT, $0-0
get_tls(R12)
- MOVQ m(R12), R13
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
@@ -222,14 +390,16 @@ TEXT runtime·racesymbolizethunk(SB), NOSPLIT, $56-8
PUSHQ R15
// Set g = g0.
get_tls(R12)
- MOVQ m(R12), R13
+ MOVQ g(R12), R13
+ MOVQ g_m(R13), R13
MOVQ m_g0(R13), R14
MOVQ R14, g(R12) // g = m->g0
MOVQ RARG0, 0(SP) // func arg
CALL runtime·racesymbolize(SB)
// All registers are smashed after Go code, reload.
get_tls(R12)
- MOVQ m(R12), R13
+ MOVQ g(R12), R13
+ MOVQ g_m(R13), R13
MOVQ m_curg(R13), R14
MOVQ R14, g(R12) // g = m->curg
// Restore callee-saved registers.
diff --git a/src/runtime/rdebug.go b/src/runtime/rdebug.go
new file mode 100644
index 000000000..e5e691122
--- /dev/null
+++ b/src/runtime/rdebug.go
@@ -0,0 +1,37 @@
+// 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
+
+func setMaxStack(in int) (out int) {
+ out = int(maxstacksize)
+ maxstacksize = uintptr(in)
+ return out
+}
+
+func setGCPercent(in int32) (out int32) {
+ mp := acquirem()
+ mp.scalararg[0] = uintptr(int(in))
+ onM(setgcpercent_m)
+ out = int32(int(mp.scalararg[0]))
+ releasem(mp)
+ return out
+}
+
+func setPanicOnFault(new bool) (old bool) {
+ mp := acquirem()
+ old = mp.curg.paniconfault
+ mp.curg.paniconfault = new
+ releasem(mp)
+ return old
+}
+
+func setMaxThreads(in int) (out int) {
+ mp := acquirem()
+ mp.scalararg[0] = uintptr(in)
+ onM(setmaxthreads_m)
+ out = int(mp.scalararg[0])
+ releasem(mp)
+ return out
+}
diff --git a/src/runtime/rt0_android_arm.s b/src/runtime/rt0_android_arm.s
new file mode 100644
index 000000000..6b65fb47b
--- /dev/null
+++ b/src/runtime/rt0_android_arm.s
@@ -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.
+
+#include "textflag.h"
+
+TEXT _rt0_arm_android(SB),NOSPLIT,$-4
+ MOVW (R13), R0 // argc
+ MOVW $4(R13), R1 // argv
+ MOVW $_rt0_arm_linux1(SB), R4
+ B (R4)
diff --git a/src/pkg/runtime/rt0_darwin_386.s b/src/runtime/rt0_darwin_386.s
index 4f85250c2..4c8c92dda 100644
--- a/src/pkg/runtime/rt0_darwin_386.s
+++ b/src/runtime/rt0_darwin_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_386_darwin(SB),NOSPLIT,$8
MOVL 8(SP), AX
@@ -13,4 +13,4 @@ TEXT _rt0_386_darwin(SB),NOSPLIT,$8
INT $3
TEXT main(SB),NOSPLIT,$0
- JMP _rt0_go(SB)
+ JMP runtime·rt0_go(SB)
diff --git a/src/pkg/runtime/rt0_darwin_amd64.s b/src/runtime/rt0_darwin_amd64.s
index 8d2962b03..452d85455 100644
--- a/src/pkg/runtime/rt0_darwin_amd64.s
+++ b/src/runtime/rt0_darwin_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_amd64_darwin(SB),NOSPLIT,$-8
LEAQ 8(SP), SI // argv
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_darwin(SB),NOSPLIT,$-8
JMP AX
TEXT main(SB),NOSPLIT,$-8
- MOVQ $_rt0_go(SB), AX
+ MOVQ $runtime·rt0_go(SB), AX
JMP AX
diff --git a/src/pkg/runtime/rt0_dragonfly_386.s b/src/runtime/rt0_dragonfly_386.s
index b857f6039..548ba796a 100644
--- a/src/pkg/runtime/rt0_dragonfly_386.s
+++ b/src/runtime/rt0_dragonfly_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_386_dragonfly(SB),NOSPLIT,$8
MOVL 8(SP), AX
@@ -13,4 +13,4 @@ TEXT _rt0_386_dragonfly(SB),NOSPLIT,$8
INT $3
TEXT main(SB),NOSPLIT,$0
- JMP _rt0_go(SB)
+ JMP runtime·rt0_go(SB)
diff --git a/src/pkg/runtime/rt0_dragonfly_amd64.s b/src/runtime/rt0_dragonfly_amd64.s
index fc7e74598..fb56618d8 100644
--- a/src/pkg/runtime/rt0_dragonfly_amd64.s
+++ b/src/runtime/rt0_dragonfly_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_amd64_dragonfly(SB),NOSPLIT,$-8
LEAQ 8(DI), SI // argv
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_dragonfly(SB),NOSPLIT,$-8
JMP AX
TEXT main(SB),NOSPLIT,$-8
- MOVQ $_rt0_go(SB), AX
+ MOVQ $runtime·rt0_go(SB), AX
JMP AX
diff --git a/src/pkg/runtime/rt0_freebsd_386.s b/src/runtime/rt0_freebsd_386.s
index 758f7d268..cd7a915f8 100644
--- a/src/pkg/runtime/rt0_freebsd_386.s
+++ b/src/runtime/rt0_freebsd_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_386_freebsd(SB),NOSPLIT,$8
MOVL 8(SP), AX
@@ -13,4 +13,4 @@ TEXT _rt0_386_freebsd(SB),NOSPLIT,$8
INT $3
TEXT main(SB),NOSPLIT,$0
- JMP _rt0_go(SB)
+ JMP runtime·rt0_go(SB)
diff --git a/src/pkg/runtime/rt0_freebsd_amd64.s b/src/runtime/rt0_freebsd_amd64.s
index 3cf7163b5..7989f7c3e 100644
--- a/src/pkg/runtime/rt0_freebsd_amd64.s
+++ b/src/runtime/rt0_freebsd_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_amd64_freebsd(SB),NOSPLIT,$-8
LEAQ 8(DI), SI // argv
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_freebsd(SB),NOSPLIT,$-8
JMP AX
TEXT main(SB),NOSPLIT,$-8
- MOVQ $_rt0_go(SB), AX
+ MOVQ $runtime·rt0_go(SB), AX
JMP AX
diff --git a/src/pkg/runtime/rt0_freebsd_arm.s b/src/runtime/rt0_freebsd_arm.s
index 56219f899..f31252698 100644
--- a/src/pkg/runtime/rt0_freebsd_arm.s
+++ b/src/runtime/rt0_freebsd_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// FreeBSD and Linux use the same linkage to main
@@ -10,9 +10,9 @@ TEXT _rt0_arm_freebsd(SB),NOSPLIT,$-4
MOVW (R13), R0 // argc
MOVW $4(R13), R1 // argv
MOVM.DB.W [R0-R1], (R13)
- B _rt0_go(SB)
+ B runtime·rt0_go(SB)
TEXT main(SB),NOSPLIT,$-4
MOVM.DB.W [R0-R1], (R13)
- MOVW $_rt0_go(SB), R4
+ MOVW $runtime·rt0_go(SB), R4
B (R4)
diff --git a/src/pkg/runtime/rt0_linux_386.s b/src/runtime/rt0_linux_386.s
index c6f4159ce..352e594d5 100644
--- a/src/pkg/runtime/rt0_linux_386.s
+++ b/src/runtime/rt0_linux_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_386_linux(SB),NOSPLIT,$8
MOVL 8(SP), AX
@@ -14,12 +14,12 @@ TEXT _rt0_386_linux(SB),NOSPLIT,$8
INT $3
TEXT main(SB),NOSPLIT,$0
- JMP _rt0_go(SB)
+ JMP runtime·rt0_go(SB)
TEXT _fallback_vdso(SB),NOSPLIT,$0
INT $0x80
RET
DATA runtime·_vdso(SB)/4, $_fallback_vdso(SB)
-GLOBL runtime·_vdso(SB), $4
+GLOBL runtime·_vdso(SB), NOPTR, $4
diff --git a/src/pkg/runtime/rt0_linux_amd64.s b/src/runtime/rt0_linux_amd64.s
index a887ced8f..985426acc 100644
--- a/src/pkg/runtime/rt0_linux_amd64.s
+++ b/src/runtime/rt0_linux_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
LEAQ 8(SP), SI // argv
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
JMP AX
TEXT main(SB),NOSPLIT,$-8
- MOVQ $_rt0_go(SB), AX
+ MOVQ $runtime·rt0_go(SB), AX
JMP AX
diff --git a/src/pkg/runtime/rt0_linux_arm.s b/src/runtime/rt0_linux_arm.s
index 309fa2f79..5f521d24b 100644
--- a/src/pkg/runtime/rt0_linux_arm.s
+++ b/src/runtime/rt0_linux_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_arm_linux(SB),NOSPLIT,$-4
MOVW (R13), R0 // argc
@@ -56,7 +56,7 @@ TEXT _rt0_arm_linux1(SB),NOSPLIT,$-4
SUB $4, R13 // fake a stack frame for runtime·setup_auxv
BL runtime·setup_auxv(SB)
ADD $4, R13
- B _rt0_go(SB)
+ B runtime·rt0_go(SB)
TEXT bad_abi<>(SB),NOSPLIT,$-4
// give diagnosis and exit
@@ -77,7 +77,7 @@ DATA bad_abi_msg+0x18(SB)/8, $" run on "
DATA bad_abi_msg+0x20(SB)/8, $"EABI ker"
DATA bad_abi_msg+0x28(SB)/4, $"nels"
DATA bad_abi_msg+0x2c(SB)/1, $0xa
-GLOBL bad_abi_msg(SB), $45
+GLOBL bad_abi_msg(SB), RODATA, $45
TEXT oabi_syscall<>(SB),NOSPLIT,$-4
ADD $1, PC, R4
diff --git a/src/pkg/runtime/rt0_nacl_386.s b/src/runtime/rt0_nacl_386.s
index 8b713548f..d4ba06306 100644
--- a/src/pkg/runtime/rt0_nacl_386.s
+++ b/src/runtime/rt0_nacl_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// NaCl entry has:
// 0(FP) - arg block == SP+8
@@ -19,4 +19,4 @@ TEXT _rt0_386_nacl(SB),NOSPLIT,$8
INT $3
TEXT main(SB),NOSPLIT,$0
- JMP _rt0_go(SB)
+ JMP runtime·rt0_go(SB)
diff --git a/src/pkg/runtime/rt0_nacl_amd64p32.s b/src/runtime/rt0_nacl_amd64p32.s
index 502d2e2bf..54e4b1de8 100644
--- a/src/pkg/runtime/rt0_nacl_amd64p32.s
+++ b/src/runtime/rt0_nacl_amd64p32.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// NaCl entry on 32-bit x86 has DI pointing at the arg block, which contains:
//
@@ -26,5 +26,5 @@ TEXT _rt0_amd64p32_nacl(SB),NOSPLIT,$16
TEXT main(SB),NOSPLIT,$0
// Uncomment for fake time like on Go Playground.
//MOVQ $1257894000000000000, AX
- //MOVQ AX, runtime·timens(SB)
- JMP _rt0_go(SB)
+ //MOVQ AX, runtime·faketime(SB)
+ JMP runtime·rt0_go(SB)
diff --git a/src/runtime/rt0_nacl_arm.s b/src/runtime/rt0_nacl_arm.s
new file mode 100644
index 000000000..eadb4782d
--- /dev/null
+++ b/src/runtime/rt0_nacl_arm.s
@@ -0,0 +1,20 @@
+// 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"
+
+// NaCl entry has:
+// 0(FP) - 0
+// 4(FP) - cleanup function pointer, always 0
+// 8(FP) - envc
+// 12(FP) - argc
+// 16(FP) - argv, then 0, then envv, then 0, then auxv
+TEXT _rt0_arm_nacl(SB),NOSPLIT,$-4
+ MOVW 8(R13), R0
+ MOVW $12(R13), R1
+ MOVM.DB.W [R0-R1], (R13)
+ B main(SB)
+
+TEXT main(SB),NOSPLIT,$0
+ B runtime·rt0_go(SB)
diff --git a/src/pkg/runtime/rt0_netbsd_386.s b/src/runtime/rt0_netbsd_386.s
index eb348fcee..70b853253 100644
--- a/src/pkg/runtime/rt0_netbsd_386.s
+++ b/src/runtime/rt0_netbsd_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_386_netbsd(SB),NOSPLIT,$8
MOVL 8(SP), AX
@@ -13,4 +13,4 @@ TEXT _rt0_386_netbsd(SB),NOSPLIT,$8
INT $3
TEXT main(SB),NOSPLIT,$0
- JMP _rt0_go(SB)
+ JMP runtime·rt0_go(SB)
diff --git a/src/pkg/runtime/rt0_netbsd_amd64.s b/src/runtime/rt0_netbsd_amd64.s
index c8e3fb18c..fad56614e 100644
--- a/src/pkg/runtime/rt0_netbsd_amd64.s
+++ b/src/runtime/rt0_netbsd_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_amd64_netbsd(SB),NOSPLIT,$-8
LEAQ 8(SP), SI // argv
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_netbsd(SB),NOSPLIT,$-8
JMP AX
TEXT main(SB),NOSPLIT,$-8
- MOVQ $_rt0_go(SB), AX
+ MOVQ $runtime·rt0_go(SB), AX
JMP AX
diff --git a/src/pkg/runtime/rt0_netbsd_arm.s b/src/runtime/rt0_netbsd_arm.s
index 36effc3c5..bad66e06c 100644
--- a/src/pkg/runtime/rt0_netbsd_arm.s
+++ b/src/runtime/rt0_netbsd_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// FreeBSD/NetBSD and Linux use the same linkage to main
@@ -10,4 +10,4 @@ TEXT _rt0_arm_netbsd(SB),NOSPLIT,$-4
MOVW (R13), R0 // argc
MOVW $4(R13), R1 // argv
MOVM.DB.W [R0-R1], (R13)
- B _rt0_go(SB)
+ B runtime·rt0_go(SB)
diff --git a/src/pkg/runtime/rt0_openbsd_386.s b/src/runtime/rt0_openbsd_386.s
index 9e80f69be..f25d2e1cf 100644
--- a/src/pkg/runtime/rt0_openbsd_386.s
+++ b/src/runtime/rt0_openbsd_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_386_openbsd(SB),NOSPLIT,$8
MOVL 8(SP), AX
@@ -13,4 +13,4 @@ TEXT _rt0_386_openbsd(SB),NOSPLIT,$8
INT $3
TEXT main(SB),NOSPLIT,$0
- JMP _rt0_go(SB)
+ JMP runtime·rt0_go(SB)
diff --git a/src/pkg/runtime/rt0_openbsd_amd64.s b/src/runtime/rt0_openbsd_amd64.s
index b1ad403b7..58fe66639 100644
--- a/src/pkg/runtime/rt0_openbsd_amd64.s
+++ b/src/runtime/rt0_openbsd_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_amd64_openbsd(SB),NOSPLIT,$-8
LEAQ 8(SP), SI // argv
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_openbsd(SB),NOSPLIT,$-8
JMP AX
TEXT main(SB),NOSPLIT,$-8
- MOVQ $_rt0_go(SB), AX
+ MOVQ $runtime·rt0_go(SB), AX
JMP AX
diff --git a/src/runtime/rt0_plan9_386.s b/src/runtime/rt0_plan9_386.s
new file mode 100644
index 000000000..c451299ee
--- /dev/null
+++ b/src/runtime/rt0_plan9_386.s
@@ -0,0 +1,23 @@
+// 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"
+
+TEXT _rt0_386_plan9(SB),NOSPLIT,$12
+ MOVL AX, _tos(SB)
+ LEAL 8(SP), AX
+ MOVL AX, _privates(SB)
+ MOVL $1, _nprivates(SB)
+ CALL runtime·asminit(SB)
+ MOVL inargc-4(FP), AX
+ MOVL AX, 0(SP)
+ LEAL inargv+0(FP), AX
+ 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
new file mode 100644
index 000000000..ec2d9ec82
--- /dev/null
+++ b/src/runtime/rt0_plan9_amd64.s
@@ -0,0 +1,21 @@
+// 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"
+
+TEXT _rt0_amd64_plan9(SB),NOSPLIT,$24
+ MOVQ AX, _tos(SB)
+ LEAQ 16(SP), AX
+ MOVQ AX, _privates(SB)
+ MOVL $1, _nprivates(SB)
+ MOVL inargc-8(FP), DI
+ LEAQ inargv+0(FP), SI
+ 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/pkg/runtime/rt0_solaris_amd64.s b/src/runtime/rt0_solaris_amd64.s
index 4aca991f0..5997cbf8e 100644
--- a/src/pkg/runtime/rt0_solaris_amd64.s
+++ b/src/runtime/rt0_solaris_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_amd64_solaris(SB),NOSPLIT,$-8
LEAQ 8(SP), SI // argv
@@ -11,8 +11,8 @@ TEXT _rt0_amd64_solaris(SB),NOSPLIT,$-8
JMP AX
TEXT main(SB),NOSPLIT,$-8
- MOVQ $_rt0_go(SB), AX
+ MOVQ $runtime·rt0_go(SB), AX
JMP AX
DATA runtime·issolaris(SB)/4, $1
-GLOBL runtime·issolaris(SB), $4
+GLOBL runtime·issolaris(SB), NOPTR, $4
diff --git a/src/pkg/runtime/rt0_windows_386.s b/src/runtime/rt0_windows_386.s
index 594e2cd34..3c2deda90 100644
--- a/src/pkg/runtime/rt0_windows_386.s
+++ b/src/runtime/rt0_windows_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_386_windows(SB),NOSPLIT,$12
MOVL 12(SP), AX
@@ -13,8 +13,8 @@ TEXT _rt0_386_windows(SB),NOSPLIT,$12
JMP main(SB)
TEXT main(SB),NOSPLIT,$0
- JMP _rt0_go(SB)
+ JMP runtime·rt0_go(SB)
DATA runtime·iswindows(SB)/4, $1
-GLOBL runtime·iswindows(SB), $4
+GLOBL runtime·iswindows(SB), NOPTR, $4
diff --git a/src/pkg/runtime/rt0_windows_amd64.s b/src/runtime/rt0_windows_amd64.s
index 32e18b02b..197f52e11 100644
--- a/src/pkg/runtime/rt0_windows_amd64.s
+++ b/src/runtime/rt0_windows_amd64.s
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT _rt0_amd64_windows(SB),NOSPLIT,$-8
LEAQ 8(SP), SI // argv
@@ -12,8 +12,8 @@ TEXT _rt0_amd64_windows(SB),NOSPLIT,$-8
JMP AX
TEXT main(SB),NOSPLIT,$-8
- MOVQ $_rt0_go(SB), AX
+ MOVQ $runtime·rt0_go(SB), AX
JMP AX
DATA runtime·iswindows(SB)/4, $1
-GLOBL runtime·iswindows(SB), $4
+GLOBL runtime·iswindows(SB), NOPTR, $4
diff --git a/src/runtime/rune.go b/src/runtime/rune.go
new file mode 100644
index 000000000..a9f683581
--- /dev/null
+++ b/src/runtime/rune.go
@@ -0,0 +1,219 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ * Copyright (c) 2002 by Lucent Technologies.
+ * Portions Copyright 2009 The Go Authors. All rights reserved.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+/*
+ * This code is copied, with slight editing due to type differences,
+ * from a subset of ../lib9/utf/rune.c
+ */
+
+package runtime
+
+const (
+ bit1 = 7
+ bitx = 6
+ bit2 = 5
+ bit3 = 4
+ bit4 = 3
+ bit5 = 2
+
+ t1 = ((1 << (bit1 + 1)) - 1) ^ 0xFF /* 0000 0000 */
+ tx = ((1 << (bitx + 1)) - 1) ^ 0xFF /* 1000 0000 */
+ t2 = ((1 << (bit2 + 1)) - 1) ^ 0xFF /* 1100 0000 */
+ t3 = ((1 << (bit3 + 1)) - 1) ^ 0xFF /* 1110 0000 */
+ t4 = ((1 << (bit4 + 1)) - 1) ^ 0xFF /* 1111 0000 */
+ t5 = ((1 << (bit5 + 1)) - 1) ^ 0xFF /* 1111 1000 */
+
+ rune1 = (1 << (bit1 + 0*bitx)) - 1 /* 0000 0000 0111 1111 */
+ rune2 = (1 << (bit2 + 1*bitx)) - 1 /* 0000 0111 1111 1111 */
+ rune3 = (1 << (bit3 + 2*bitx)) - 1 /* 1111 1111 1111 1111 */
+ rune4 = (1 << (bit4 + 3*bitx)) - 1 /* 0001 1111 1111 1111 1111 1111 */
+
+ maskx = (1 << bitx) - 1 /* 0011 1111 */
+ testx = maskx ^ 0xFF /* 1100 0000 */
+
+ runeerror = 0xFFFD
+ runeself = 0x80
+
+ surrogateMin = 0xD800
+ surrogateMax = 0xDFFF
+
+ bad = runeerror
+
+ runemax = 0x10FFFF /* maximum rune value */
+)
+
+/*
+ * Modified by Wei-Hwa Huang, Google Inc., on 2004-09-24
+ * This is a slower but "safe" version of the old chartorune
+ * that works on strings that are not necessarily null-terminated.
+ *
+ * If you know for sure that your string is null-terminated,
+ * chartorune will be a bit faster.
+ *
+ * It is guaranteed not to attempt to access "length"
+ * past the incoming pointer. This is to avoid
+ * possible access violations. If the string appears to be
+ * well-formed but incomplete (i.e., to get the whole Rune
+ * we'd need to read past str+length) then we'll set the Rune
+ * to Bad and return 0.
+ *
+ * Note that if we have decoding problems for other
+ * reasons, we return 1 instead of 0.
+ */
+func charntorune(s string) (rune, int) {
+ /* When we're not allowed to read anything */
+ if len(s) <= 0 {
+ return bad, 1
+ }
+
+ /*
+ * one character sequence (7-bit value)
+ * 00000-0007F => T1
+ */
+ c := s[0]
+ if c < tx {
+ return rune(c), 1
+ }
+
+ // If we can't read more than one character we must stop
+ if len(s) <= 1 {
+ return bad, 1
+ }
+
+ /*
+ * two character sequence (11-bit value)
+ * 0080-07FF => t2 tx
+ */
+ c1 := s[1] ^ tx
+ if (c1 & testx) != 0 {
+ return bad, 1
+ }
+ if c < t3 {
+ if c < t2 {
+ return bad, 1
+ }
+ l := ((rune(c) << bitx) | rune(c1)) & rune2
+ if l <= rune1 {
+ return bad, 1
+ }
+ return l, 2
+ }
+
+ // If we can't read more than two characters we must stop
+ if len(s) <= 2 {
+ return bad, 1
+ }
+
+ /*
+ * three character sequence (16-bit value)
+ * 0800-FFFF => t3 tx tx
+ */
+ c2 := s[2] ^ tx
+ if (c2 & testx) != 0 {
+ return bad, 1
+ }
+ if c < t4 {
+ l := ((((rune(c) << bitx) | rune(c1)) << bitx) | rune(c2)) & rune3
+ if l <= rune2 {
+ return bad, 1
+ }
+ if surrogateMin <= l && l <= surrogateMax {
+ return bad, 1
+ }
+ return l, 3
+ }
+
+ if len(s) <= 3 {
+ return bad, 1
+ }
+
+ /*
+ * four character sequence (21-bit value)
+ * 10000-1FFFFF => t4 tx tx tx
+ */
+ c3 := s[3] ^ tx
+ if (c3 & testx) != 0 {
+ return bad, 1
+ }
+ if c < t5 {
+ l := ((((((rune(c) << bitx) | rune(c1)) << bitx) | rune(c2)) << bitx) | rune(c3)) & rune4
+ if l <= rune3 || l > runemax {
+ return bad, 1
+ }
+ return l, 4
+ }
+
+ // Support for 5-byte or longer UTF-8 would go here, but
+ // since we don't have that, we'll just return bad.
+ return bad, 1
+}
+
+// runetochar converts r to bytes and writes the result to str.
+// returns the number of bytes generated.
+func runetochar(str []byte, r rune) int {
+ /* runes are signed, so convert to unsigned for range check. */
+ c := uint32(r)
+ /*
+ * one character sequence
+ * 00000-0007F => 00-7F
+ */
+ if c <= rune1 {
+ str[0] = byte(c)
+ return 1
+ }
+ /*
+ * two character sequence
+ * 0080-07FF => t2 tx
+ */
+ if c <= rune2 {
+ str[0] = byte(t2 | (c >> (1 * bitx)))
+ str[1] = byte(tx | (c & maskx))
+ return 2
+ }
+
+ /*
+ * If the rune is out of range or a surrogate half, convert it to the error rune.
+ * Do this test here because the error rune encodes to three bytes.
+ * Doing it earlier would duplicate work, since an out of range
+ * rune wouldn't have fit in one or two bytes.
+ */
+ if c > runemax {
+ c = runeerror
+ }
+ if surrogateMin <= c && c <= surrogateMax {
+ c = runeerror
+ }
+
+ /*
+ * three character sequence
+ * 0800-FFFF => t3 tx tx
+ */
+ if c <= rune3 {
+ str[0] = byte(t3 | (c >> (2 * bitx)))
+ str[1] = byte(tx | ((c >> (1 * bitx)) & maskx))
+ str[2] = byte(tx | (c & maskx))
+ return 3
+ }
+
+ /*
+ * four character sequence (21-bit value)
+ * 10000-1FFFFF => t4 tx tx tx
+ */
+ str[0] = byte(t4 | (c >> (3 * bitx)))
+ str[1] = byte(tx | ((c >> (2 * bitx)) & maskx))
+ str[2] = byte(tx | ((c >> (1 * bitx)) & maskx))
+ str[3] = byte(tx | (c & maskx))
+ return 4
+}
diff --git a/src/pkg/runtime/runtime-gdb.py b/src/runtime/runtime-gdb.py
index eedac7cf4..eedac7cf4 100644
--- a/src/pkg/runtime/runtime-gdb.py
+++ b/src/runtime/runtime-gdb.py
diff --git a/src/pkg/runtime/runtime.c b/src/runtime/runtime.c
index 3b322e0de..c823691ec 100644
--- a/src/pkg/runtime/runtime.c
+++ b/src/runtime/runtime.c
@@ -5,18 +5,15 @@
#include "runtime.h"
#include "stack.h"
#include "arch_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
-
-enum {
- maxround = sizeof(uintptr),
-};
+#include "textflag.h"
+#include "malloc.h"
// 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.
-static uint32 traceback_cache = ~(uint32)0;
+static uint32 traceback_cache = 2<<1;
// The GOTRACEBACK environment variable controls the
// behavior of a Go program that is crashing and exiting.
@@ -24,32 +21,17 @@ static uint32 traceback_cache = ~(uint32)0;
// 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)
+#pragma textflag NOSPLIT
int32
runtime·gotraceback(bool *crash)
{
- byte *p;
- uint32 x;
-
if(crash != nil)
*crash = false;
- if(m->traceback != 0)
- return m->traceback;
- x = runtime·atomicload(&traceback_cache);
- if(x == ~(uint32)0) {
- p = runtime·getenv("GOTRACEBACK");
- if(p == nil)
- p = (byte*)"";
- if(p[0] == '\0')
- x = 1<<1;
- else if(runtime·strcmp(p, (byte*)"crash") == 0)
- x = (2<<1) | 1;
- else
- x = runtime·atoi(p)<<1;
- runtime·atomicstore(&traceback_cache, x);
- }
+ if(g->m->traceback != 0)
+ return g->m->traceback;
if(crash != nil)
- *crash = x&1;
- return x>>1;
+ *crash = traceback_cache&1;
+ return traceback_cache>>1;
}
int32
@@ -80,10 +62,12 @@ runtime·mchr(byte *p, byte c, byte *ep)
}
static int32 argc;
+
+#pragma dataflag NOPTR /* argv not a heap pointer */
static uint8** argv;
-Slice os·Args;
-Slice syscall·envs;
+extern Slice runtime·argslice;
+extern Slice runtime·envs;
void (*runtime·sysargs)(int32, uint8**);
@@ -115,12 +99,10 @@ runtime·goargs(void)
if(Windows)
return;
- s = runtime·malloc(argc*sizeof s[0]);
+ runtime·argslice = runtime·makeStringSlice(argc);
+ s = (String*)runtime·argslice.array;
for(i=0; i<argc; i++)
s[i] = runtime·gostringnocopy(argv[i]);
- os·Args.array = (byte*)s;
- os·Args.len = argc;
- os·Args.cap = argc;
}
void
@@ -132,12 +114,17 @@ runtime·goenvs_unix(void)
for(n=0; argv[argc+1+n] != 0; n++)
;
- s = runtime·malloc(n*sizeof s[0]);
+ runtime·envs = runtime·makeStringSlice(n);
+ s = (String*)runtime·envs.array;
for(i=0; i<n; i++)
s[i] = runtime·gostringnocopy(argv[argc+1+i]);
- syscall·envs.array = (byte*)s;
- syscall·envs.len = n;
- syscall·envs.cap = n;
+}
+
+#pragma textflag NOSPLIT
+Slice
+runtime·environ()
+{
+ return runtime·envs;
}
int32
@@ -279,61 +266,29 @@ runtime·check(void)
runtime·throw("FixedStack is not power-of-2");
}
-uint32
-runtime·fastrand1(void)
-{
- uint32 x;
-
- x = m->fastrand;
- x += x;
- if(x & 0x80000000L)
- x ^= 0x88888eefUL;
- m->fastrand = x;
- return x;
-}
-
-static Lock ticksLock;
-static int64 ticks;
-
-int64
-runtime·tickspersecond(void)
-{
- int64 res, t0, t1, c0, c1;
-
- res = (int64)runtime·atomicload64((uint64*)&ticks);
- if(res != 0)
- return ticks;
- runtime·lock(&ticksLock);
- res = ticks;
- if(res == 0) {
- t0 = runtime·nanotime();
- c0 = runtime·cputicks();
- runtime·usleep(100*1000);
- t1 = runtime·nanotime();
- c1 = runtime·cputicks();
- if(t1 == t0)
- t1++;
- res = (c1-c0)*1000*1000*1000/(t1-t0);
- if(res == 0)
- res++;
- runtime·atomicstore64((uint64*)&ticks, res);
- }
- runtime·unlock(&ticksLock);
- return res;
-}
-
+#pragma dataflag NOPTR
DebugVars runtime·debug;
-static struct {
+typedef struct DbgVar DbgVar;
+struct DbgVar
+{
int8* name;
int32* value;
-} dbgvar[] = {
+};
+
+// Do we report invalid pointers found during stack or heap scans?
+int32 runtime·invalidptr = 1;
+
+#pragma dataflag NOPTR /* dbgvar has no heap pointers */
+static DbgVar dbgvar[] = {
{"allocfreetrace", &runtime·debug.allocfreetrace},
+ {"invalidptr", &runtime·invalidptr},
{"efence", &runtime·debug.efence},
{"gctrace", &runtime·debug.gctrace},
{"gcdead", &runtime·debug.gcdead},
{"scheddetail", &runtime·debug.scheddetail},
{"schedtrace", &runtime·debug.schedtrace},
+ {"scavenge", &runtime·debug.scavenge},
};
void
@@ -341,31 +296,31 @@ runtime·parsedebugvars(void)
{
byte *p;
intgo i, n;
- bool tmp;
-
- // gotraceback caches the GOTRACEBACK setting in traceback_cache.
- // gotraceback can be called before the environment is available.
- // traceback_cache must be reset after the environment is made
- // available, in order for the environment variable to take effect.
- // The code is fixed differently in Go 1.4.
- // This is a limited fix for Go 1.3.3.
- traceback_cache = ~(uint32)0;
- runtime·gotraceback(&tmp);
p = runtime·getenv("GODEBUG");
- if(p == nil)
- return;
- for(;;) {
- for(i=0; i<nelem(dbgvar); i++) {
- n = runtime·findnull((byte*)dbgvar[i].name);
- if(runtime·mcmp(p, (byte*)dbgvar[i].name, n) == 0 && p[n] == '=')
- *dbgvar[i].value = runtime·atoi(p+n+1);
+ if(p != nil){
+ for(;;) {
+ for(i=0; i<nelem(dbgvar); i++) {
+ n = runtime·findnull((byte*)dbgvar[i].name);
+ if(runtime·mcmp(p, (byte*)dbgvar[i].name, n) == 0 && p[n] == '=')
+ *dbgvar[i].value = runtime·atoi(p+n+1);
+ }
+ p = runtime·strstr(p, (byte*)",");
+ if(p == nil)
+ break;
+ p++;
}
- p = runtime·strstr(p, (byte*)",");
- if(p == nil)
- break;
- p++;
}
+
+ p = runtime·getenv("GOTRACEBACK");
+ if(p == nil)
+ p = (byte*)"";
+ if(p[0] == '\0')
+ traceback_cache = 1<<1;
+ else if(runtime·strcmp(p, (byte*)"crash") == 0)
+ traceback_cache = (2<<1) | 1;
+ else
+ traceback_cache = runtime·atoi(p)<<1;
}
// Poor mans 64-bit division.
@@ -378,11 +333,6 @@ runtime·timediv(int64 v, int32 div, int32 *rem)
{
int32 res, bit;
- if(v >= (int64)div*0x7fffffffLL) {
- if(rem != nil)
- *rem = 0;
- return 0x7fffffff;
- }
res = 0;
for(bit = 30; bit >= 0; bit--) {
if(v >= ((int64)div<<bit)) {
@@ -390,7 +340,60 @@ runtime·timediv(int64 v, int32 div, int32 *rem)
res += 1<<bit;
}
}
+ if(v >= (int64)div) {
+ if(rem != nil)
+ *rem = 0;
+ return 0x7fffffff;
+ }
if(rem != nil)
*rem = v;
return res;
}
+
+// Helpers for Go. Must be NOSPLIT, must only call NOSPLIT functions, and must not block.
+
+#pragma textflag NOSPLIT
+G*
+runtime·getg(void)
+{
+ return g;
+}
+
+#pragma textflag NOSPLIT
+M*
+runtime·acquirem(void)
+{
+ g->m->locks++;
+ return g->m;
+}
+
+#pragma textflag NOSPLIT
+void
+runtime·releasem(M *mp)
+{
+ mp->locks--;
+ if(mp->locks == 0 && g->preempt) {
+ // restore the preemption request in case we've cleared it in newstack
+ g->stackguard0 = StackPreempt;
+ }
+}
+
+#pragma textflag NOSPLIT
+MCache*
+runtime·gomcache(void)
+{
+ return g->m->mcache;
+}
+
+#pragma textflag NOSPLIT
+Slice
+reflect·typelinks(void)
+{
+ extern Type *runtime·typelink[], *runtime·etypelink[];
+ Slice ret;
+
+ ret.array = (byte*)runtime·typelink;
+ ret.len = runtime·etypelink - runtime·typelink;
+ ret.cap = ret.len;
+ return ret;
+}
diff --git a/src/runtime/runtime.go b/src/runtime/runtime.go
new file mode 100644
index 000000000..4e4e1d17a
--- /dev/null
+++ b/src/runtime/runtime.go
@@ -0,0 +1,60 @@
+// 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
+
+var ticks struct {
+ lock mutex
+ 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))
+ if r != 0 {
+ return r
+ }
+ lock(&ticks.lock)
+ r = int64(ticks.val)
+ if r == 0 {
+ t0 := nanotime()
+ c0 := cputicks()
+ usleep(100 * 1000)
+ t1 := nanotime()
+ c1 := cputicks()
+ if t1 == t0 {
+ t1++
+ }
+ r = (c1 - c0) * 1000 * 1000 * 1000 / (t1 - t0)
+ if r == 0 {
+ r++
+ }
+ atomicstore64(&ticks.val, uint64(r))
+ }
+ unlock(&ticks.lock)
+ return r
+}
+
+func makeStringSlice(n int) []string {
+ return make([]string, n)
+}
+
+// TODO: Move to parfor.go when parfor.c becomes parfor.go.
+func parforalloc(nthrmax uint32) *parfor {
+ return &parfor{
+ thr: &make([]parforthread, nthrmax)[0],
+ nthrmax: nthrmax,
+ }
+}
+
+var envs []string
+var argslice []string
+
+// called from syscall
+func runtime_envs() []string { return envs }
+
+// called from os
+func runtime_args() []string { return argslice }
diff --git a/src/pkg/runtime/runtime.h b/src/runtime/runtime.h
index 42fb3a47d..177a1287e 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -56,12 +56,13 @@ typedef uint8 byte;
typedef struct Func Func;
typedef struct G G;
typedef struct Gobuf Gobuf;
-typedef struct Lock Lock;
+typedef struct SudoG SudoG;
+typedef struct Mutex Mutex;
typedef struct M M;
typedef struct P P;
+typedef struct SchedT SchedT;
typedef struct Note Note;
typedef struct Slice Slice;
-typedef struct Stktop Stktop;
typedef struct String String;
typedef struct FuncVal FuncVal;
typedef struct SigTab SigTab;
@@ -73,19 +74,17 @@ typedef struct InterfaceType InterfaceType;
typedef struct Eface Eface;
typedef struct Type Type;
typedef struct PtrType PtrType;
-typedef struct ChanType ChanType;
+typedef struct ChanType ChanType;
typedef struct MapType MapType;
typedef struct Defer Defer;
typedef struct Panic Panic;
typedef struct Hmap Hmap;
-typedef struct Hiter Hiter;
+typedef struct Hiter Hiter;
typedef struct Hchan Hchan;
typedef struct Complex64 Complex64;
typedef struct Complex128 Complex128;
typedef struct LibCall LibCall;
typedef struct WinCallbackContext WinCallbackContext;
-typedef struct Timers Timers;
-typedef struct Timer Timer;
typedef struct GCStats GCStats;
typedef struct LFNode LFNode;
typedef struct ParFor ParFor;
@@ -93,6 +92,8 @@ typedef struct ParForThread ParForThread;
typedef struct CgoMal CgoMal;
typedef struct PollDesc PollDesc;
typedef struct DebugVars DebugVars;
+typedef struct ForceGCState ForceGCState;
+typedef struct Stack Stack;
/*
* Per-CPU declaration.
@@ -102,14 +103,13 @@ typedef struct DebugVars DebugVars;
* local storage indexed by a pseudo-register TLS. See zasmhdr in
* src/cmd/dist/buildruntime.c for details, and be aware that the linker may
* make further OS-specific changes to the compiler's output. For example,
- * 6l/linux rewrites 0(TLS) as -16(FS).
+ * 6l/linux rewrites 0(TLS) as -8(FS).
*
* Every C file linked into a Go program must include runtime.h so that the
* C compiler (6c, 8c, etc.) knows to avoid other uses of these dedicated
* registers. The Go compiler (6g, 8g, etc.) knows to avoid them.
*/
extern register G* g;
-extern register M* m;
/*
* defined constants
@@ -121,13 +121,25 @@ enum
// If you add to this list, add to the list
// of "okay during garbage collection" status
// in mgc0.c too.
- Gidle,
- Grunnable,
- Grunning,
- Gsyscall,
- Gwaiting,
- Gmoribund_unused, // currently unused, but hardcoded in gdb scripts
- Gdead,
+ Gidle, // 0
+ Grunnable, // 1 runnable and on a run queue
+ Grunning, // 2
+ Gsyscall, // 3
+ Gwaiting, // 4
+ Gmoribund_unused, // 5 currently unused, but hardcoded in gdb scripts
+ Gdead, // 6
+ Genqueue, // 7 Only the Gscanenqueue is used.
+ Gcopystack, // 8 in this state when newstack is moving the stack
+ // the following encode that the GC is scanning the stack and what to do when it is done
+ Gscan = 0x1000, // atomicstatus&~Gscan = the non-scan state,
+ // Gscanidle = Gscan + Gidle, // Not used. Gidle only used with newly malloced gs
+ Gscanrunnable = Gscan + Grunnable, // 0x1001 When scanning complets make Grunnable (it is already on run queue)
+ Gscanrunning = Gscan + Grunning, // 0x1002 Used to tell preemption newstack routine to scan preempted stack.
+ Gscansyscall = Gscan + Gsyscall, // 0x1003 When scanning completes make is Gsyscall
+ Gscanwaiting = Gscan + Gwaiting, // 0x1004 When scanning completes make it Gwaiting
+ // Gscanmoribund_unused, // not possible
+ // Gscandead, // not possible
+ Gscanenqueue = Gscan + Genqueue, // When scanning completes make it Grunnable and put on runqueue
};
enum
{
@@ -147,17 +159,10 @@ enum
{
PtrSize = sizeof(void*),
};
-enum
-{
- // Per-M stack segment cache size.
- StackCacheSize = 32,
- // Global <-> per-M stack segment cache transfer batch size.
- StackCacheBatch = 16,
-};
/*
* structures
*/
-struct Lock
+struct Mutex
{
// Futex-based impl treats it as uint32 key,
// while sema-based impl as M* waitm.
@@ -214,10 +219,23 @@ struct Gobuf
uintptr sp;
uintptr pc;
G* g;
- void* ctxt;
+ void* ctxt; // this has to be a pointer so that GC scans it
uintreg ret;
uintptr lr;
};
+// Known to compiler.
+// Changes here must also be made in src/cmd/gc/select.c's selecttype.
+struct SudoG
+{
+ G* g;
+ uint32* selectdone;
+ SudoG* next;
+ SudoG* prev;
+ void* elem; // data element
+ int64 releasetime;
+ int32 nrelease; // -1 for acquire
+ SudoG* waitlink; // G.waiting list
+};
struct GCStats
{
// the struct must consist of only uint64's,
@@ -231,9 +249,9 @@ struct GCStats
struct LibCall
{
- void (*fn)(void*);
+ uintptr fn;
uintptr n; // number of parameters
- void* args; // parameters
+ uintptr args; // parameters
uintptr r1; // return values
uintptr r2;
uintptr err; // error number
@@ -248,57 +266,65 @@ struct WinCallbackContext
bool cleanstack;
};
+// Stack describes a Go execution stack.
+// The bounds of the stack are exactly [lo, hi),
+// with no implicit data structures on either side.
+struct Stack
+{
+ uintptr lo;
+ uintptr hi;
+};
+
struct G
{
- // stackguard0 can be set to StackPreempt as opposed to stackguard
- uintptr stackguard0; // cannot move - also known to linker, libmach, runtime/cgo
- uintptr stackbase; // cannot move - also known to libmach, runtime/cgo
- uint32 panicwrap; // cannot move - also known to linker
- Defer* defer;
- Panic* panic;
+ // Stack parameters.
+ // stack describes the actual stack memory: [stack.lo, stack.hi).
+ // stackguard0 is the stack pointer compared in the Go stack growth prologue.
+ // It is stack.lo+StackGuard normally, but can be StackPreempt to trigger a preemption.
+ // stackguard1 is the stack pointer compared in the C stack growth prologue.
+ // It is stack.lo+StackGuard on g0 and gsignal stacks.
+ // It is ~0 on other goroutine stacks, to trigger a call to morestackc (and crash).
+ Stack stack; // offset known to runtime/cgo
+ uintptr stackguard0; // offset known to liblink
+ uintptr stackguard1; // offset known to liblink
+
+ Panic* panic; // innermost panic - offset known to liblink
+ Defer* defer; // innermost defer
Gobuf sched;
- uintptr syscallstack; // if status==Gsyscall, syscallstack = stackbase to use during gc
uintptr syscallsp; // if status==Gsyscall, syscallsp = sched.sp to use during gc
uintptr syscallpc; // if status==Gsyscall, syscallpc = sched.pc to use during gc
- uintptr syscallguard; // if status==Gsyscall, syscallguard = stackguard to use during gc
- uintptr stackguard; // same as stackguard0, but not set to StackPreempt
- uintptr stack0;
- uintptr stacksize;
void* param; // passed parameter on wakeup
- int16 status;
+ uint32 atomicstatus;
int64 goid;
int64 waitsince; // approx time when the G become blocked
- int8* waitreason; // if status==Gwaiting
+ String waitreason; // if status==Gwaiting
G* schedlink;
- bool ispanic;
- bool issystem; // do not output in stack dump
- bool isbackground; // ignore in deadlock detector
+ bool issystem; // do not output in stack dump, ignore in deadlock detector
bool preempt; // preemption signal, duplicates stackguard0 = StackPreempt
bool paniconfault; // panic (instead of crash) on unexpected fault address
+ bool preemptscan; // preempted g does scan for GC
+ bool gcworkdone; // debug: cleared at begining of gc work phase cycle, set by gcphasework, tested at end of cycle
+ bool throwsplit; // must not split stack
int8 raceignore; // ignore race detection events
M* m; // for debuggers, but offset not hard-coded
M* lockedm;
int32 sig;
- int32 writenbuf;
- byte* writebuf;
+ Slice writebuf;
uintptr sigcode0;
uintptr sigcode1;
uintptr sigpc;
uintptr gopc; // pc of go statement that created this goroutine
uintptr racectx;
+ SudoG* waiting; // sudog structures this G is waiting on (that have a valid elem ptr)
uintptr end[];
};
struct M
{
G* g0; // goroutine with scheduling stack
- void* moreargp; // argument pointer for more stack
Gobuf morebuf; // gobuf arg to morestack
// Fields not known to debuggers.
- uint32 moreframesize; // size arguments to morestack
- uint32 moreargsize; // known by amd64 asm to follow moreframesize
- uintreg cret; // return value from C
uint64 procid; // for debuggers, but offset not hard-coded
G* gsignal; // signal-handling G
uintptr tls[4]; // thread-local storage (for x86 extern register)
@@ -327,10 +353,6 @@ struct M
M* schedlink;
uint32 machport; // Return address for Mach IPC (OS X)
MCache* mcache;
- int32 stackinuse;
- uint32 stackcachepos;
- uint32 stackcachecnt;
- void* stackcache[StackCacheSize];
G* lockedg;
uintptr createstack[32];// Stack that created this thread.
uint32 freglo[16]; // D[i] lsb and F[i]
@@ -346,9 +368,10 @@ struct M
uint8 traceback;
bool (*waitunlockf)(G*, void*);
void* waitlock;
- uintptr forkstackguard;
+ uintptr scalararg[4]; // scalar argument/return for mcall
+ void* ptrarg[4]; // pointer argument/return for mcall
#ifdef GOOS_windows
- void* thread; // thread handle
+ uintptr thread; // thread handle
// these are here because they are too large to be on the stack
// of low-level NOSPLIT functions.
LibCall libcall;
@@ -361,11 +384,11 @@ struct M
// these are here because they are too large to be on the stack
// of low-level NOSPLIT functions.
LibCall libcall;
- struct {
+ struct MTs {
int64 tv_sec;
int64 tv_nsec;
} ts;
- struct {
+ struct MScratch {
uintptr v[6];
} scratch;
#endif
@@ -378,7 +401,7 @@ struct M
struct P
{
- Lock;
+ Mutex lock;
int32 id;
uint32 status; // one of Pidle/Prunning/...
@@ -405,6 +428,48 @@ struct P
byte pad[64];
};
+enum {
+ // The max value of GOMAXPROCS.
+ // There are no fundamental restrictions on the value.
+ MaxGomaxprocs = 1<<8,
+};
+
+struct SchedT
+{
+ Mutex lock;
+
+ uint64 goidgen;
+
+ M* midle; // idle m's waiting for work
+ int32 nmidle; // number of idle m's waiting for work
+ int32 nmidlelocked; // number of locked m's waiting for work
+ int32 mcount; // number of m's that have been created
+ int32 maxmcount; // maximum number of m's allowed (or die)
+
+ P* pidle; // idle P's
+ uint32 npidle;
+ uint32 nmspinning;
+
+ // Global runnable queue.
+ G* runqhead;
+ G* runqtail;
+ int32 runqsize;
+
+ // Global cache of dead G's.
+ Mutex gflock;
+ G* gfree;
+ int32 ngfree;
+
+ uint32 gcwaiting; // gc is waiting to run
+ int32 stopwait;
+ Note stopnote;
+ uint32 sysmonwait;
+ Note sysmonnote;
+ uint64 lastpoll;
+
+ int32 profilehz; // cpu profiling rate
+};
+
// The m->locked word holds two pieces of state counting active calls to LockOSThread/lockOSThread.
// The low bit (LockExternal) is a boolean reporting whether any LockOSThread call is active.
// External locks are not recursive; a second lock is silently ignored.
@@ -418,19 +483,6 @@ enum
LockInternal = 2,
};
-struct Stktop
-{
- // The offsets of these fields are known to (hard-coded in) libmach.
- uintptr stackguard;
- uintptr stackbase;
- Gobuf gobuf;
- uint32 argsize;
- uint32 panicwrap;
-
- uint8* argp; // pointer to arguments in old frame
- bool panic; // is this frame the top of a panic?
- bool malloced;
-};
struct SigTab
{
int32 flags;
@@ -451,7 +503,7 @@ enum
// Layout of in-memory per-function information prepared by linker
// See http://golang.org/s/go12symtab.
// Keep in sync with linker and with ../../libmach/sym.c
-// and with package debug/gosym.
+// and with package debug/gosym and with symtab.go in package runtime.
struct Func
{
uintptr entry; // start pc
@@ -507,35 +559,15 @@ enum {
Solaris = 0
};
#endif
-
-struct Timers
-{
- Lock;
- G *timerproc;
- bool sleeping;
- bool rescheduling;
- Note waitnote;
- Timer **t;
- int32 len;
- int32 cap;
+#ifdef GOOS_plan9
+enum {
+ Plan9 = 1
};
-
-// Package time knows the layout of this structure.
-// If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
-// For GOOS=nacl, package syscall knows the layout of this structure.
-// If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
-struct Timer
-{
- int32 i; // 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
- // a well-behaved function and not block.
- int64 when;
- int64 period;
- FuncVal *fv;
- Eface arg;
+#else
+enum {
+ Plan9 = 0
};
+#endif
// Lock-free stack node.
struct LFNode
@@ -583,10 +615,27 @@ struct DebugVars
int32 gcdead;
int32 scheddetail;
int32 schedtrace;
+ int32 scavenge;
+};
+
+// Indicates to write barrier and sychronization task to preform.
+enum
+{ // Synchronization Write barrier
+ GCoff, // stop and start nop
+ GCquiesce, // stop and start nop
+ GCstw, // stop the ps nop
+ GCmark, // scan the stacks and start no white to black
+ GCsweep, // stop and start nop
+};
+
+struct ForceGCState
+{
+ Mutex lock;
+ G* g;
+ uint32 idle;
};
-extern bool runtime·precisestack;
-extern bool runtime·copystack;
+extern uint32 runtime·gcphase;
/*
* defined macros
@@ -605,89 +654,24 @@ enum {
Structrnd = sizeof(uintreg),
};
-/*
- * type algorithms - known to compiler
- */
-enum
-{
- AMEM,
- AMEM0,
- AMEM8,
- AMEM16,
- AMEM32,
- AMEM64,
- AMEM128,
- ANOEQ,
- ANOEQ0,
- ANOEQ8,
- ANOEQ16,
- ANOEQ32,
- ANOEQ64,
- ANOEQ128,
- ASTRING,
- AINTER,
- ANILINTER,
- ASLICE,
- AFLOAT32,
- AFLOAT64,
- ACPLX64,
- ACPLX128,
- Amax
-};
-typedef struct Alg Alg;
-struct Alg
-{
- void (*hash)(uintptr*, uintptr, void*);
- void (*equal)(bool*, uintptr, void*, void*);
- void (*print)(uintptr, void*);
- void (*copy)(uintptr, void*, void*);
-};
-
-extern Alg runtime·algarray[Amax];
-
byte* runtime·startup_random_data;
uint32 runtime·startup_random_data_len;
-void runtime·get_random_data(byte**, int32*);
+
+int32 runtime·invalidptr;
enum {
// hashinit wants this many random bytes
HashRandomBytes = 32
};
-void runtime·hashinit(void);
-
-void runtime·memhash(uintptr*, uintptr, void*);
-void runtime·nohash(uintptr*, uintptr, void*);
-void runtime·strhash(uintptr*, uintptr, void*);
-void runtime·interhash(uintptr*, uintptr, void*);
-void runtime·nilinterhash(uintptr*, uintptr, void*);
-void runtime·aeshash(uintptr*, uintptr, void*);
-void runtime·aeshash32(uintptr*, uintptr, void*);
-void runtime·aeshash64(uintptr*, uintptr, void*);
-void runtime·aeshashstr(uintptr*, uintptr, void*);
-
-void runtime·memequal(bool*, uintptr, void*, void*);
-void runtime·noequal(bool*, uintptr, void*, void*);
-void runtime·strequal(bool*, uintptr, void*, void*);
-void runtime·interequal(bool*, uintptr, void*, void*);
-void runtime·nilinterequal(bool*, uintptr, void*, void*);
-
-bool runtime·memeq(void*, void*, uintptr);
-
-void runtime·memprint(uintptr, void*);
-void runtime·strprint(uintptr, void*);
-void runtime·interprint(uintptr, void*);
-void runtime·nilinterprint(uintptr, void*);
-
-void runtime·memcopy(uintptr, void*, void*);
-void runtime·memcopy8(uintptr, void*, void*);
-void runtime·memcopy16(uintptr, void*, void*);
-void runtime·memcopy32(uintptr, void*, void*);
-void runtime·memcopy64(uintptr, void*, void*);
-void runtime·memcopy128(uintptr, void*, void*);
-void runtime·strcopy(uintptr, void*, void*);
-void runtime·algslicecopy(uintptr, void*, void*);
-void runtime·intercopy(uintptr, void*, void*);
-void runtime·nilintercopy(uintptr, void*, void*);
+
+uint32 runtime·readgstatus(G*);
+void runtime·casgstatus(G*, uint32, uint32);
+void runtime·casgstatus(G*, uint32, uint32);
+uint32 runtime·casgcopystack(G*);
+void runtime·quiesce(G*);
+bool runtime·stopg(G*);
+void runtime·restartg(G*);
+void runtime·gcphasework(G*);
/*
* deferred subroutine calls
@@ -695,28 +679,25 @@ void runtime·nilintercopy(uintptr, void*, void*);
struct Defer
{
int32 siz;
- bool special; // not part of defer frame
- byte* argp; // where args were copied from
- byte* pc;
+ bool started;
+ uintptr argp; // where args were copied from
+ uintptr pc;
FuncVal* fn;
+ Panic* panic; // panic that is running defer
Defer* link;
- void* args[1]; // padded to actual size
};
// argp used in Defer structs when there is no argp.
-// TODO(rsc): Maybe we could use nil instead, but we've always used -1
-// and I don't want to change this days before the Go 1.3 release.
-#define NoArgs ((byte*)-1)
+#define NoArgs ((uintptr)-1)
/*
* panics
*/
struct Panic
{
+ void* argp; // pointer to arguments of deferred call run during panic; cannot move - known to liblink
Eface arg; // argument to panic
- uintptr stackbase; // g->stackbase in panic
Panic* link; // link to earlier panic
- Defer* defer; // current executing defer
bool recovered; // whether this panic is over
bool aborted; // the panic was aborted
};
@@ -725,6 +706,7 @@ struct Panic
* stack traces
*/
typedef struct Stkframe Stkframe;
+typedef struct BitVector BitVector;
struct Stkframe
{
Func* fn; // function being run
@@ -733,13 +715,21 @@ struct Stkframe
uintptr lr; // program counter at caller aka link register
uintptr sp; // stack pointer at pc
uintptr fp; // stack pointer at caller aka frame pointer
- byte* varp; // top of local variables
- byte* argp; // pointer to function arguments
+ uintptr varp; // top of local variables
+ uintptr argp; // pointer to function arguments
uintptr arglen; // number of bytes at argp
+ BitVector* argmap; // force use of this argmap
};
-int32 runtime·gentraceback(uintptr, uintptr, uintptr, G*, int32, uintptr*, int32, bool(*)(Stkframe*, void*), void*, bool);
+enum
+{
+ TraceRuntimeFrames = 1<<0, // include frames for internal runtime functions.
+ TraceTrap = 1<<1, // the initial PC, SP are from a trap, not a return PC from a call
+};
+intgo runtime·gentraceback(uintptr, uintptr, uintptr, G*, intgo, uintptr*, intgo, bool(**)(Stkframe*, void*), void*, uintgo);
+void runtime·tracebackdefers(G*, bool(**)(Stkframe*, void*), void*);
void runtime·traceback(uintptr pc, uintptr sp, uintptr lr, G* gp);
+void runtime·tracebacktrap(uintptr pc, uintptr sp, uintptr lr, G* gp);
void runtime·tracebackothers(G*);
bool runtime·haszeroargs(uintptr pc);
bool runtime·topofstack(Func*);
@@ -753,12 +743,12 @@ enum
* external data
*/
extern String runtime·emptystring;
-extern uintptr runtime·zerobase;
extern G** runtime·allg;
+extern Slice runtime·allgs; // []*G
extern uintptr runtime·allglen;
extern G* runtime·lastg;
extern M* runtime·allm;
-extern P** runtime·allp;
+extern P* runtime·allp[MaxGomaxprocs+1];
extern int32 runtime·gomaxprocs;
extern uint32 runtime·needextram;
extern uint32 runtime·panicking;
@@ -767,11 +757,14 @@ extern int32 runtime·ncpu;
extern bool runtime·iscgo;
extern void (*runtime·sysargs)(int32, uint8**);
extern uintptr runtime·maxstring;
-extern uint32 runtime·Hchansize;
extern uint32 runtime·cpuid_ecx;
extern uint32 runtime·cpuid_edx;
extern DebugVars runtime·debug;
extern uintptr runtime·maxstacksize;
+extern Note runtime·signote;
+extern ForceGCState runtime·forcegc;
+extern SchedT runtime·sched;
+extern int32 runtime·newprocs;
/*
* common functions and data
@@ -816,23 +809,21 @@ void runtime·gogo(Gobuf*);
void runtime·gostartcall(Gobuf*, void(*)(void), void*);
void runtime·gostartcallfn(Gobuf*, FuncVal*);
void runtime·gosave(Gobuf*);
-void runtime·lessstack(void);
void runtime·goargs(void);
void runtime·goenvs(void);
void runtime·goenvs_unix(void);
void* runtime·getu(void);
void runtime·throw(int8*);
-void runtime·panicstring(int8*);
bool runtime·canpanic(G*);
void runtime·prints(int8*);
void runtime·printf(int8*, ...);
-int32 runtime·snprintf(byte*, int32, int8*, ...);
+void runtime·snprintf(byte*, int32, int8*, ...);
byte* runtime·mchr(byte*, byte, byte*);
int32 runtime·mcmp(byte*, byte*, uintptr);
void runtime·memmove(void*, void*, uintptr);
-void* runtime·mal(uintptr);
String runtime·catstring(String, String);
String runtime·gostring(byte*);
+Slice runtime·makeStringSlice(intgo);
String runtime·gostringn(byte*, intgo);
Slice runtime·gobytes(byte*, intgo);
String runtime·gostringnocopy(byte*);
@@ -847,7 +838,7 @@ int32 runtime·read(int32, void*, int32);
int32 runtime·write(uintptr, void*, int32); // use uintptr to accommodate windows.
int32 runtime·close(int32);
int32 runtime·mincore(void*, uintptr, byte*);
-void runtime·jmpdefer(FuncVal*, void*);
+void runtime·jmpdefer(FuncVal*, uintptr);
void runtime·exit1(int32);
void runtime·ready(G*);
byte* runtime·getenv(int8*);
@@ -860,30 +851,30 @@ void runtime·mpreinit(M*);
void runtime·minit(void);
void runtime·unminit(void);
void runtime·signalstack(byte*, int32);
+void runtime·tracebackinit(void);
void runtime·symtabinit(void);
Func* runtime·findfunc(uintptr);
int32 runtime·funcline(Func*, uintptr, String*);
-int32 runtime·funcarglen(Func*, uintptr);
int32 runtime·funcspdelta(Func*, uintptr);
int8* runtime·funcname(Func*);
int32 runtime·pcdatavalue(Func*, int32, uintptr);
-void* runtime·stackalloc(G*, uint32);
-void runtime·stackfree(G*, void*, Stktop*);
+void runtime·stackinit(void);
+Stack runtime·stackalloc(uint32);
+void runtime·stackfree(Stack);
void runtime·shrinkstack(G*);
+void runtime·shrinkfinish(void);
MCache* runtime·allocmcache(void);
void runtime·freemcache(MCache*);
void runtime·mallocinit(void);
-bool runtime·ifaceeq_c(Iface, Iface);
-bool runtime·efaceeq_c(Eface, Eface);
-uintptr runtime·ifacehash(Iface, uintptr);
-uintptr runtime·efacehash(Eface, uintptr);
-void* runtime·malloc(uintptr size);
-void runtime·free(void *v);
+void runtime·gcinit(void);
+void* runtime·mallocgc(uintptr size, Type* typ, uint32 flag);
void runtime·runpanic(Panic*);
uintptr runtime·getcallersp(void*);
int32 runtime·mcount(void);
int32 runtime·gcount(void);
-void runtime·mcall(void(*)(G*));
+void runtime·mcall(void(**)(G*));
+void runtime·onM(void(**)(void));
+void runtime·onMsignal(void(**)(void));
uint32 runtime·fastrand1(void);
void runtime·rewindmorestack(Gobuf*);
int32 runtime·timediv(int64, int32, int32*);
@@ -905,62 +896,57 @@ void runtime·atomicstore(uint32 volatile*, uint32);
void runtime·atomicstore64(uint64 volatile*, uint64);
uint64 runtime·atomicload64(uint64 volatile*);
void* runtime·atomicloadp(void* volatile*);
+uintptr runtime·atomicloaduintptr(uintptr volatile*);
void runtime·atomicstorep(void* volatile*, void*);
+void runtime·atomicstoreuintptr(uintptr volatile*, uintptr);
+void runtime·atomicor8(byte volatile*, byte);
-void runtime·setmg(M*, G*);
+void runtime·setg(G*);
void runtime·newextram(void);
void runtime·exit(int32);
void runtime·breakpoint(void);
-void runtime·gosched(void);
-void runtime·gosched0(G*);
+void runtime·gosched_m(G*);
void runtime·schedtrace(bool);
-void runtime·park(bool(*)(G*, void*), void*, int8*);
-void runtime·parkunlock(Lock*, int8*);
-void runtime·tsleep(int64, int8*);
+void runtime·park(bool(*)(G*, void*), void*, String);
+void runtime·parkunlock(Mutex*, String);
+void runtime·tsleep(int64, String);
M* runtime·newm(void);
void runtime·goexit(void);
void runtime·asmcgocall(void (*fn)(void*), void*);
+int32 runtime·asmcgocall_errno(void (*fn)(void*), void*);
void runtime·entersyscall(void);
-void runtime·reentersyscall(void*, uintptr);
+void runtime·reentersyscall(uintptr, uintptr);
void runtime·entersyscallblock(void);
void runtime·exitsyscall(void);
G* runtime·newproc1(FuncVal*, byte*, int32, int32, void*);
bool runtime·sigsend(int32 sig);
-int32 runtime·callers(int32, uintptr*, int32);
+intgo runtime·callers(intgo, uintptr*, intgo);
+intgo runtime·gcallers(G*, intgo, uintptr*, intgo);
int64 runtime·nanotime(void); // monotonic time
int64 runtime·unixnanotime(void); // real time, can skip
void runtime·dopanic(int32);
void runtime·startpanic(void);
void runtime·freezetheworld(void);
-void runtime·unwindstack(G*, byte*);
void runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp, M *mp);
void runtime·resetcpuprofiler(int32);
-void runtime·setcpuprofilerate(void(*)(uintptr*, int32), int32);
+void runtime·setcpuprofilerate(int32);
void runtime·usleep(uint32);
int64 runtime·cputicks(void);
int64 runtime·tickspersecond(void);
-void runtime·blockevent(int64, int32);
-extern int64 runtime·blockprofilerate;
-void runtime·addtimer(Timer*);
-bool runtime·deltimer(Timer*);
+void runtime·blockevent(int64, intgo);
G* runtime·netpoll(bool);
-void runtime·netpollinit(void);
-int32 runtime·netpollopen(uintptr, PollDesc*);
-int32 runtime·netpollclose(uintptr);
void runtime·netpollready(G**, PollDesc*, int32);
uintptr runtime·netpollfd(PollDesc*);
-void runtime·netpollarm(PollDesc*, int32);
void** runtime·netpolluser(PollDesc*);
bool runtime·netpollclosing(PollDesc*);
void runtime·netpolllock(PollDesc*);
void runtime·netpollunlock(PollDesc*);
void runtime·crash(void);
void runtime·parsedebugvars(void);
-void _rt0_go(void);
void* runtime·funcdata(Func*, int32);
-int32 runtime·setmaxthreads(int32);
+void runtime·setmaxthreads_m(void);
G* runtime·timejump(void);
-void runtime·iterate_itabs(void (*callback)(Itab*));
+void runtime·iterate_itabs(void (**callback)(Itab*));
void runtime·iterate_finq(void (*callback)(FuncVal*, byte*, uintptr, Type*, PtrType*));
#pragma varargck argpos runtime·printf 1
@@ -987,10 +973,10 @@ extern uint32 runtime·worldsema;
* mutual exclusion locks. in the uncontended case,
* as fast as spin locks (just a few user-level instructions),
* but on the contention path they sleep in the kernel.
- * a zeroed Lock is unlocked (no need to initialize each lock).
+ * a zeroed Mutex is unlocked (no need to initialize each lock).
*/
-void runtime·lock(Lock*);
-void runtime·unlock(Lock*);
+void runtime·lock(Mutex*);
+void runtime·unlock(Mutex*);
/*
* sleep and wakeup on one-time events.
@@ -1031,7 +1017,7 @@ void runtime·futexsleep(uint32*, uint32, int64);
void runtime·futexwakeup(uint32*, uint32);
/*
- * Lock-free stack.
+ * Mutex-free stack.
* Initialize uint64 head to 0, compare with 0 to test for emptiness.
* The stack does not keep pointers to nodes,
* so they can be garbage collected if there are no other pointers to nodes.
@@ -1064,10 +1050,6 @@ void runtime·madvise(byte*, uintptr, int32);
void runtime·memclr(byte*, uintptr);
void runtime·setcallerpc(void*, void*);
void* runtime·getcallerpc(void*);
-
-/*
- * runtime go-called
- */
void runtime·printbool(bool);
void runtime·printbyte(int8);
void runtime·printfloat(float64);
@@ -1081,9 +1063,11 @@ void runtime·printuint(uint64);
void runtime·printhex(uint64);
void runtime·printslice(Slice);
void runtime·printcomplex(Complex128);
-void runtime·newstackcall(FuncVal*, byte*, uint32);
-void reflect·call(FuncVal*, byte*, uint32, uint32);
-void runtime·panic(Eface);
+
+/*
+ * runtime go-called
+ */
+void runtime·gopanic(Eface);
void runtime·panicindex(void);
void runtime·panicslice(void);
void runtime·panicdivide(void);
@@ -1093,8 +1077,6 @@ void runtime·panicdivide(void);
*/
void runtime·printany(Eface);
void runtime·newTypeAssertionError(String*, String*, String*, String*, Eface*);
-void runtime·newErrorString(String, Eface*);
-void runtime·newErrorCString(int8*, Eface*);
void runtime·fadd64c(uint64, uint64, uint64*);
void runtime·fsub64c(uint64, uint64, uint64*);
void runtime·fmul64c(uint64, uint64, uint64*);
@@ -1127,7 +1109,6 @@ void runtime·procyield(uint32);
void runtime·osyield(void);
void runtime·lockOSThread(void);
void runtime·unlockOSThread(void);
-bool runtime·lockedOSThread(void);
bool runtime·showframe(Func*, G*);
void runtime·printcreatedby(G*);
diff --git a/src/pkg/runtime/runtime_linux_test.go b/src/runtime/runtime_linux_test.go
index 5344ed205..5344ed205 100644
--- a/src/pkg/runtime/runtime_linux_test.go
+++ b/src/runtime/runtime_linux_test.go
diff --git a/src/pkg/runtime/runtime_test.go b/src/runtime/runtime_test.go
index 5a9f52fe0..1688364a8 100644
--- a/src/pkg/runtime/runtime_test.go
+++ b/src/runtime/runtime_test.go
@@ -95,8 +95,9 @@ func BenchmarkDeferMany(b *testing.B) {
// The value reported will include the padding between runtime.gogo and the
// next function in memory. That's fine.
func TestRuntimeGogoBytes(t *testing.T) {
- if GOOS == "nacl" {
- t.Skip("skipping on nacl")
+ switch GOOS {
+ case "android", "nacl":
+ t.Skipf("skipping on %s", GOOS)
}
dir, err := ioutil.TempDir("", "go-build")
@@ -105,7 +106,7 @@ func TestRuntimeGogoBytes(t *testing.T) {
}
defer os.RemoveAll(dir)
- out, err := exec.Command("go", "build", "-o", dir+"/hello", "../../../test/helloworld.go").CombinedOutput()
+ out, err := exec.Command("go", "build", "-o", dir+"/hello", "../../test/helloworld.go").CombinedOutput()
if err != nil {
t.Fatalf("building hello world: %v\n%s", err, out)
}
@@ -156,8 +157,8 @@ var faultAddrs = []uint64{
// or else malformed.
0xffffffffffffffff,
0xfffffffffffff001,
- // no 0xffffffffffff0001; 0xffff0001 is mapped for 32-bit user space on OS X
- // no 0xfffffffffff00001; 0xfff00001 is mapped for 32-bit user space sometimes on Linux
+ 0xffffffffffff0001,
+ 0xfffffffffff00001,
0xffffffffff000001,
0xfffffffff0000001,
0xffffffff00000001,
@@ -181,24 +182,68 @@ func TestSetPanicOnFault(t *testing.T) {
old := debug.SetPanicOnFault(true)
defer debug.SetPanicOnFault(old)
+ nfault := 0
for _, addr := range faultAddrs {
- testSetPanicOnFault(t, uintptr(addr))
+ testSetPanicOnFault(t, uintptr(addr), &nfault)
+ }
+ if nfault == 0 {
+ t.Fatalf("none of the addresses faulted")
}
}
-func testSetPanicOnFault(t *testing.T, addr uintptr) {
+func testSetPanicOnFault(t *testing.T, addr uintptr, nfault *int) {
if GOOS == "nacl" {
t.Skip("nacl doesn't seem to fault on high addresses")
}
defer func() {
- if err := recover(); err == nil {
- t.Fatalf("did not find error in recover")
+ if err := recover(); err != nil {
+ *nfault++
}
}()
- var p *int
- p = (*int)(unsafe.Pointer(addr))
- println(*p)
- t.Fatalf("still here - should have faulted on address %#x", addr)
+ // The read should fault, except that sometimes we hit
+ // addresses that have had C or kernel pages mapped there
+ // readable by user code. So just log the content.
+ // If no addresses fault, we'll fail the test.
+ v := *(*byte)(unsafe.Pointer(addr))
+ t.Logf("addr %#x: %#x\n", addr, v)
+}
+
+func eqstring_generic(s1, s2 string) bool {
+ if len(s1) != len(s2) {
+ return false
+ }
+ // optimization in assembly versions:
+ // if s1.str == s2.str { return true }
+ for i := 0; i < len(s1); i++ {
+ if s1[i] != s2[i] {
+ return false
+ }
+ }
+ return true
+}
+
+func TestEqString(t *testing.T) {
+ // This isn't really an exhaustive test of eqstring, it's
+ // just a convenient way of documenting (via eqstring_generic)
+ // what eqstring does.
+ s := []string{
+ "",
+ "a",
+ "c",
+ "aaa",
+ "ccc",
+ "cccc"[:3], // same contents, different string
+ "1234567890",
+ }
+ for _, s1 := range s {
+ for _, s2 := range s {
+ x := s1 == s2
+ y := eqstring_generic(s1, s2)
+ if x != y {
+ t.Errorf(`eqstring("%s","%s") = %t, want %t`, s1, s2, x, y)
+ }
+ }
+ }
}
diff --git a/src/pkg/runtime/runtime_unix_test.go b/src/runtime/runtime_unix_test.go
index 963de8cdb..963de8cdb 100644
--- a/src/pkg/runtime/runtime_unix_test.go
+++ b/src/runtime/runtime_unix_test.go
diff --git a/src/runtime/select.go b/src/runtime/select.go
new file mode 100644
index 000000000..f735a71e2
--- /dev/null
+++ b/src/runtime/select.go
@@ -0,0 +1,651 @@
+// 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
+
+// This file contains the implementation of Go select statements.
+
+import "unsafe"
+
+const (
+ debugSelect = false
+)
+
+var (
+ chansendpc = funcPC(chansend)
+ chanrecvpc = funcPC(chanrecv)
+)
+
+func selectsize(size uintptr) uintptr {
+ selsize := unsafe.Sizeof(_select{}) +
+ (size-1)*unsafe.Sizeof(_select{}.scase[0]) +
+ size*unsafe.Sizeof(*_select{}.lockorder) +
+ size*unsafe.Sizeof(*_select{}.pollorder)
+ return round(selsize, _Int64Align)
+}
+
+func newselect(sel *_select, selsize int64, size int32) {
+ if selsize != int64(selectsize(uintptr(size))) {
+ print("runtime: bad select size ", selsize, ", want ", selectsize(uintptr(size)), "\n")
+ gothrow("bad select size")
+ }
+ sel.tcase = uint16(size)
+ sel.ncase = 0
+ sel.lockorder = (**hchan)(add(unsafe.Pointer(&sel.scase), uintptr(size)*unsafe.Sizeof(_select{}.scase[0])))
+ sel.pollorder = (*uint16)(add(unsafe.Pointer(sel.lockorder), uintptr(size)*unsafe.Sizeof(*_select{}.lockorder)))
+
+ if debugSelect {
+ print("newselect s=", sel, " size=", size, "\n")
+ }
+}
+
+//go:nosplit
+func selectsend(sel *_select, c *hchan, elem unsafe.Pointer) (selected bool) {
+ // nil cases do not compete
+ if c != nil {
+ selectsendImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
+ }
+ return
+}
+
+// cut in half to give stack a chance to split
+func selectsendImpl(sel *_select, c *hchan, pc uintptr, elem unsafe.Pointer, so uintptr) {
+ i := sel.ncase
+ if i >= sel.tcase {
+ gothrow("selectsend: too many cases")
+ }
+ sel.ncase = i + 1
+ cas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))
+
+ cas.pc = pc
+ cas._chan = c
+ cas.so = uint16(so)
+ cas.kind = _CaseSend
+ cas.elem = elem
+
+ if debugSelect {
+ print("selectsend s=", sel, " pc=", hex(cas.pc), " chan=", cas._chan, " so=", cas.so, "\n")
+ }
+}
+
+//go:nosplit
+func selectrecv(sel *_select, c *hchan, elem unsafe.Pointer) (selected bool) {
+ // nil cases do not compete
+ if c != nil {
+ selectrecvImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, nil, uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
+ }
+ return
+}
+
+//go:nosplit
+func selectrecv2(sel *_select, c *hchan, elem unsafe.Pointer, received *bool) (selected bool) {
+ // nil cases do not compete
+ if c != nil {
+ selectrecvImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, received, uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
+ }
+ return
+}
+
+func selectrecvImpl(sel *_select, c *hchan, pc uintptr, elem unsafe.Pointer, received *bool, so uintptr) {
+ i := sel.ncase
+ if i >= sel.tcase {
+ gothrow("selectrecv: too many cases")
+ }
+ sel.ncase = i + 1
+ cas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))
+ cas.pc = pc
+ cas._chan = c
+ cas.so = uint16(so)
+ cas.kind = _CaseRecv
+ cas.elem = elem
+ cas.receivedp = received
+
+ if debugSelect {
+ print("selectrecv s=", sel, " pc=", hex(cas.pc), " chan=", cas._chan, " so=", cas.so, "\n")
+ }
+}
+
+//go:nosplit
+func selectdefault(sel *_select) (selected bool) {
+ selectdefaultImpl(sel, getcallerpc(unsafe.Pointer(&sel)), uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
+ return
+}
+
+func selectdefaultImpl(sel *_select, callerpc uintptr, so uintptr) {
+ i := sel.ncase
+ if i >= sel.tcase {
+ gothrow("selectdefault: too many cases")
+ }
+ sel.ncase = i + 1
+ cas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))
+ cas.pc = callerpc
+ cas._chan = nil
+ cas.so = uint16(so)
+ cas.kind = _CaseDefault
+
+ if debugSelect {
+ print("selectdefault s=", sel, " pc=", hex(cas.pc), " so=", cas.so, "\n")
+ }
+}
+
+func sellock(sel *_select) {
+ lockslice := sliceStruct{unsafe.Pointer(sel.lockorder), int(sel.ncase), int(sel.ncase)}
+ lockorder := *(*[]*hchan)(unsafe.Pointer(&lockslice))
+ var c *hchan
+ for _, c0 := range lockorder {
+ if c0 != nil && c0 != c {
+ c = c0
+ lock(&c.lock)
+ }
+ }
+}
+
+func selunlock(sel *_select) {
+ // We must be very careful here to not touch sel after we have unlocked
+ // the last lock, because sel can be freed right after the last unlock.
+ // Consider the following situation.
+ // First M calls runtime·park() in runtime·selectgo() passing the sel.
+ // Once runtime·park() has unlocked the last lock, another M makes
+ // the G that calls select runnable again and schedules it for execution.
+ // When the G runs on another M, it locks all the locks and frees sel.
+ // Now if the first M touches sel, it will access freed memory.
+ n := int(sel.ncase)
+ r := 0
+ lockslice := sliceStruct{unsafe.Pointer(sel.lockorder), n, n}
+ lockorder := *(*[]*hchan)(unsafe.Pointer(&lockslice))
+ // skip the default case
+ if n > 0 && lockorder[0] == nil {
+ r = 1
+ }
+ for i := n - 1; i >= r; i-- {
+ c := lockorder[i]
+ if i > 0 && c == lockorder[i-1] {
+ continue // will unlock it on the next iteration
+ }
+ unlock(&c.lock)
+ }
+}
+
+func selparkcommit(gp *g, sel *_select) bool {
+ selunlock(sel)
+ return true
+}
+
+func block() {
+ gopark(nil, nil, "select (no cases)") // forever
+}
+
+// overwrites return pc on stack to signal which case of the select
+// to run, so cannot appear at the top of a split stack.
+//go:nosplit
+func selectgo(sel *_select) {
+ pc, offset := selectgoImpl(sel)
+ *(*bool)(add(unsafe.Pointer(&sel), uintptr(offset))) = true
+ setcallerpc(unsafe.Pointer(&sel), pc)
+}
+
+// selectgoImpl returns scase.pc and scase.so for the select
+// case which fired.
+func selectgoImpl(sel *_select) (uintptr, uint16) {
+ if debugSelect {
+ print("select: sel=", sel, "\n")
+ }
+
+ scaseslice := sliceStruct{unsafe.Pointer(&sel.scase), int(sel.ncase), int(sel.ncase)}
+ scases := *(*[]scase)(unsafe.Pointer(&scaseslice))
+
+ var t0 int64
+ if blockprofilerate > 0 {
+ t0 = cputicks()
+ for i := 0; i < int(sel.ncase); i++ {
+ scases[i].releasetime = -1
+ }
+ }
+
+ // The compiler rewrites selects that statically have
+ // only 0 or 1 cases plus default into simpler constructs.
+ // The only way we can end up with such small sel.ncase
+ // values here is for a larger select in which most channels
+ // have been nilled out. The general code handles those
+ // cases correctly, and they are rare enough not to bother
+ // optimizing (and needing to test).
+
+ // generate permuted order
+ pollslice := sliceStruct{unsafe.Pointer(sel.pollorder), int(sel.ncase), int(sel.ncase)}
+ pollorder := *(*[]uint16)(unsafe.Pointer(&pollslice))
+ for i := 0; i < int(sel.ncase); i++ {
+ pollorder[i] = uint16(i)
+ }
+ for i := 1; i < int(sel.ncase); i++ {
+ o := pollorder[i]
+ j := int(fastrand1()) % (i + 1)
+ pollorder[i] = pollorder[j]
+ pollorder[j] = o
+ }
+
+ // sort the cases by Hchan address to get the locking order.
+ // simple heap sort, to guarantee n log n time and constant stack footprint.
+ lockslice := sliceStruct{unsafe.Pointer(sel.lockorder), int(sel.ncase), int(sel.ncase)}
+ lockorder := *(*[]*hchan)(unsafe.Pointer(&lockslice))
+ for i := 0; i < int(sel.ncase); i++ {
+ j := i
+ c := scases[j]._chan
+ for j > 0 && lockorder[(j-1)/2].sortkey() < c.sortkey() {
+ k := (j - 1) / 2
+ lockorder[j] = lockorder[k]
+ j = k
+ }
+ lockorder[j] = c
+ }
+ for i := int(sel.ncase) - 1; i >= 0; i-- {
+ c := lockorder[i]
+ lockorder[i] = lockorder[0]
+ j := 0
+ for {
+ k := j*2 + 1
+ if k >= i {
+ break
+ }
+ if k+1 < i && lockorder[k].sortkey() < lockorder[k+1].sortkey() {
+ k++
+ }
+ if c.sortkey() < lockorder[k].sortkey() {
+ lockorder[j] = lockorder[k]
+ j = k
+ continue
+ }
+ break
+ }
+ lockorder[j] = c
+ }
+ /*
+ for i := 0; i+1 < int(sel.ncase); i++ {
+ if lockorder[i].sortkey() > lockorder[i+1].sortkey() {
+ print("i=", i, " x=", lockorder[i], " y=", lockorder[i+1], "\n")
+ gothrow("select: broken sort")
+ }
+ }
+ */
+
+ // lock all the channels involved in the select
+ sellock(sel)
+
+ var (
+ gp *g
+ done uint32
+ sg *sudog
+ c *hchan
+ k *scase
+ sglist *sudog
+ sgnext *sudog
+ )
+
+loop:
+ // pass 1 - look for something already waiting
+ var dfl *scase
+ var cas *scase
+ for i := 0; i < int(sel.ncase); i++ {
+ cas = &scases[pollorder[i]]
+ c = cas._chan
+
+ 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
+ }
+ }
+ if c.closed != 0 {
+ goto rclose
+ }
+
+ case _CaseSend:
+ if raceenabled {
+ racereadpc(unsafe.Pointer(c), cas.pc, chansendpc)
+ }
+ 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
+ }
+ }
+
+ case _CaseDefault:
+ dfl = cas
+ }
+ }
+
+ if dfl != nil {
+ selunlock(sel)
+ cas = dfl
+ goto retc
+ }
+
+ // pass 2 - enqueue on all chans
+ gp = getg()
+ done = 0
+ for i := 0; i < int(sel.ncase); i++ {
+ cas = &scases[pollorder[i]]
+ c = cas._chan
+ sg := acquireSudog()
+ sg.g = gp
+ // Note: selectdone is adjusted for stack copies in stack.c:adjustsudogs
+ sg.selectdone = (*uint32)(noescape(unsafe.Pointer(&done)))
+ sg.elem = cas.elem
+ sg.releasetime = 0
+ if t0 != 0 {
+ sg.releasetime = -1
+ }
+ sg.waitlink = gp.waiting
+ gp.waiting = sg
+
+ switch cas.kind {
+ case _CaseRecv:
+ c.recvq.enqueue(sg)
+
+ case _CaseSend:
+ c.sendq.enqueue(sg)
+ }
+ }
+
+ // wait for someone to wake us up
+ gp.param = nil
+ gopark(unsafe.Pointer(funcPC(selparkcommit)), unsafe.Pointer(sel), "select")
+
+ // someone woke us up
+ sellock(sel)
+ sg = (*sudog)(gp.param)
+ gp.param = nil
+
+ // pass 3 - dequeue from unsuccessful chans
+ // otherwise they stack up on quiet channels
+ // record the successful case, if any.
+ // We singly-linked up the SudoGs in case order, so when
+ // iterating through the linked list they are in reverse order.
+ cas = nil
+ sglist = gp.waiting
+ // Clear all selectdone and elem before unlinking from gp.waiting.
+ // They must be cleared before being put back into the sudog cache.
+ // Clear before unlinking, because if a stack copy happens after the unlink,
+ // they will not be updated, they will be left pointing to the old stack,
+ // which creates dangling pointers, which may be detected by the
+ // garbage collector.
+ for sg1 := gp.waiting; sg1 != nil; sg1 = sg1.waitlink {
+ sg1.selectdone = nil
+ sg1.elem = nil
+ }
+ gp.waiting = nil
+ for i := int(sel.ncase) - 1; i >= 0; i-- {
+ k = &scases[pollorder[i]]
+ if sglist.releasetime > 0 {
+ k.releasetime = sglist.releasetime
+ }
+ if sg == sglist {
+ cas = k
+ } else {
+ c = k._chan
+ if k.kind == _CaseSend {
+ c.sendq.dequeueSudoG(sglist)
+ } else {
+ c.recvq.dequeueSudoG(sglist)
+ }
+ }
+ sgnext = sglist.waitlink
+ sglist.waitlink = nil
+ releaseSudog(sglist)
+ sglist = sgnext
+ }
+
+ if cas == nil {
+ goto loop
+ }
+
+ c = cas._chan
+
+ if c.dataqsiz > 0 {
+ gothrow("selectgo: shouldn't happen")
+ }
+
+ if debugSelect {
+ print("wait-return: sel=", sel, " c=", c, " cas=", cas, " kind=", cas.kind, "\n")
+ }
+
+ if cas.kind == _CaseRecv {
+ if cas.receivedp != nil {
+ *cas.receivedp = true
+ }
+ }
+
+ if raceenabled {
+ if cas.kind == _CaseRecv && cas.elem != nil {
+ raceWriteObjectPC(c.elemtype, cas.elem, cas.pc, chanrecvpc)
+ } else if cas.kind == _CaseSend {
+ raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
+ }
+ }
+
+ selunlock(sel)
+ goto retc
+
+asyncrecv:
+ // can receive from buffer
+ if raceenabled {
+ if cas.elem != nil {
+ raceWriteObjectPC(c.elemtype, cas.elem, cas.pc, chanrecvpc)
+ }
+ raceacquire(chanbuf(c, c.recvx))
+ racerelease(chanbuf(c, c.recvx))
+ }
+ if cas.receivedp != nil {
+ *cas.receivedp = true
+ }
+ if cas.elem != nil {
+ memmove(cas.elem, chanbuf(c, c.recvx), uintptr(c.elemsize))
+ }
+ memclr(chanbuf(c, c.recvx), 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)
+ } else {
+ selunlock(sel)
+ }
+ goto retc
+
+asyncsend:
+ // can send to buffer
+ if raceenabled {
+ raceacquire(chanbuf(c, c.sendx))
+ racerelease(chanbuf(c, c.sendx))
+ raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
+ }
+ memmove(chanbuf(c, c.sendx), cas.elem, uintptr(c.elemsize))
+ 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)
+ } else {
+ selunlock(sel)
+ }
+ goto retc
+
+syncrecv:
+ // 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)
+ if debugSelect {
+ print("syncrecv: sel=", sel, " c=", c, "\n")
+ }
+ if cas.receivedp != nil {
+ *cas.receivedp = true
+ }
+ if cas.elem != nil {
+ memmove(cas.elem, sg.elem, uintptr(c.elemsize))
+ }
+ sg.elem = nil
+ gp = sg.g
+ gp.param = unsafe.Pointer(sg)
+ if sg.releasetime != 0 {
+ sg.releasetime = cputicks()
+ }
+ goready(gp)
+ goto retc
+
+rclose:
+ // read at end of closed channel
+ selunlock(sel)
+ if cas.receivedp != nil {
+ *cas.receivedp = false
+ }
+ if cas.elem != nil {
+ memclr(cas.elem, uintptr(c.elemsize))
+ }
+ if raceenabled {
+ raceacquire(unsafe.Pointer(c))
+ }
+ goto retc
+
+syncsend:
+ // can send to sleeping receiver (sg)
+ if raceenabled {
+ raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
+ racesync(c, sg)
+ }
+ selunlock(sel)
+ if debugSelect {
+ print("syncsend: sel=", sel, " c=", c, "\n")
+ }
+ if sg.elem != nil {
+ memmove(sg.elem, cas.elem, uintptr(c.elemsize))
+ }
+ sg.elem = nil
+ gp = sg.g
+ gp.param = unsafe.Pointer(sg)
+ if sg.releasetime != 0 {
+ sg.releasetime = cputicks()
+ }
+ goready(gp)
+
+retc:
+ if cas.releasetime > 0 {
+ blockevent(cas.releasetime-t0, 2)
+ }
+ return cas.pc, cas.so
+
+sclose:
+ // send on closed channel
+ selunlock(sel)
+ panic("send on closed channel")
+}
+
+func (c *hchan) sortkey() uintptr {
+ // TODO(khr): if we have a moving garbage collector, we'll need to
+ // change this function.
+ return uintptr(unsafe.Pointer(c))
+}
+
+// A runtimeSelect is a single case passed to rselect.
+// This must match ../reflect/value.go:/runtimeSelect
+type runtimeSelect struct {
+ dir selectDir
+ typ unsafe.Pointer // channel type (not used here)
+ ch *hchan // channel
+ val unsafe.Pointer // ptr to data (SendDir) or ptr to receive buffer (RecvDir)
+}
+
+// These values must match ../reflect/value.go:/SelectDir.
+type selectDir int
+
+const (
+ _ selectDir = iota
+ selectSend // case Chan <- Send
+ selectRecv // case <-Chan:
+ selectDefault // default
+)
+
+func reflect_rselect(cases []runtimeSelect) (chosen int, recvOK bool) {
+ // flagNoScan is safe here, because all objects are also referenced from cases.
+ size := selectsize(uintptr(len(cases)))
+ sel := (*_select)(mallocgc(size, nil, flagNoScan))
+ newselect(sel, int64(size), int32(len(cases)))
+ r := new(bool)
+ for i := range cases {
+ rc := &cases[i]
+ switch rc.dir {
+ case selectDefault:
+ selectdefaultImpl(sel, uintptr(i), 0)
+ case selectSend:
+ if rc.ch == nil {
+ break
+ }
+ selectsendImpl(sel, rc.ch, uintptr(i), rc.val, 0)
+ case selectRecv:
+ if rc.ch == nil {
+ break
+ }
+ selectrecvImpl(sel, rc.ch, uintptr(i), rc.val, r, 0)
+ }
+ }
+
+ pc, _ := selectgoImpl(sel)
+ chosen = int(pc)
+ recvOK = *r
+ return
+}
+
+func (q *waitq) dequeueSudoG(s *sudog) {
+ var prevsgp *sudog
+ l := &q.first
+ for {
+ sgp := *l
+ if sgp == nil {
+ return
+ }
+ if sgp == s {
+ *l = sgp.next
+ if q.last == sgp {
+ q.last = prevsgp
+ }
+ s.next = nil
+ return
+ }
+ l = &sgp.next
+ prevsgp = sgp
+ }
+}
diff --git a/src/runtime/sema.go b/src/runtime/sema.go
new file mode 100644
index 000000000..26dbd30ea
--- /dev/null
+++ b/src/runtime/sema.go
@@ -0,0 +1,275 @@
+// 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.
+
+// Semaphore implementation exposed to Go.
+// Intended use is provide a sleep and wakeup
+// primitive that can be used in the contended case
+// of other synchronization primitives.
+// Thus it targets the same goal as Linux's futex,
+// but it has much simpler semantics.
+//
+// That is, don't think of these as semaphores.
+// Think of them as a way to implement sleep and wakeup
+// such that every sleep is paired with a single wakeup,
+// even if, due to races, the wakeup happens before the sleep.
+//
+// See Mullender and Cox, ``Semaphores in Plan 9,''
+// http://swtch.com/semaphore.pdf
+
+package runtime
+
+import "unsafe"
+
+// Asynchronous semaphore for sync.Mutex.
+
+type semaRoot struct {
+ lock mutex
+ head *sudog
+ tail *sudog
+ nwait uint32 // Number of waiters. Read w/o the lock.
+}
+
+// Prime to not correlate with any user patterns.
+const semTabSize = 251
+
+var semtable [semTabSize]struct {
+ root semaRoot
+ pad [_CacheLineSize - unsafe.Sizeof(semaRoot{})]byte
+}
+
+// Called from sync/net packages.
+func asyncsemacquire(addr *uint32) {
+ semacquire(addr, true)
+}
+
+func asyncsemrelease(addr *uint32) {
+ semrelease(addr)
+}
+
+// Called from runtime.
+func semacquire(addr *uint32, profile bool) {
+ gp := getg()
+ if gp != gp.m.curg {
+ gothrow("semacquire not on the G stack")
+ }
+
+ // Easy case.
+ if cansemacquire(addr) {
+ return
+ }
+
+ // Harder case:
+ // increment waiter count
+ // try cansemacquire one more time, return if succeeded
+ // enqueue itself as a waiter
+ // sleep
+ // (waiter descriptor is dequeued by signaler)
+ s := acquireSudog()
+ root := semroot(addr)
+ t0 := int64(0)
+ s.releasetime = 0
+ if profile && blockprofilerate > 0 {
+ t0 = cputicks()
+ s.releasetime = -1
+ }
+ for {
+ lock(&root.lock)
+ // Add ourselves to nwait to disable "easy case" in semrelease.
+ xadd(&root.nwait, 1)
+ // Check cansemacquire to avoid missed wakeup.
+ if cansemacquire(addr) {
+ xadd(&root.nwait, -1)
+ unlock(&root.lock)
+ break
+ }
+ // Any semrelease after the cansemacquire knows we're waiting
+ // (we set nwait above), so go to sleep.
+ root.queue(addr, s)
+ goparkunlock(&root.lock, "semacquire")
+ if cansemacquire(addr) {
+ break
+ }
+ }
+ if s.releasetime > 0 {
+ blockevent(int64(s.releasetime)-t0, 3)
+ }
+ releaseSudog(s)
+}
+
+func semrelease(addr *uint32) {
+ root := semroot(addr)
+ 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 {
+ return
+ }
+
+ // Harder case: search for a waiter and wake it.
+ lock(&root.lock)
+ if atomicload(&root.nwait) == 0 {
+ // The count is already consumed by another goroutine,
+ // so no need to wake up another goroutine.
+ unlock(&root.lock)
+ return
+ }
+ s := root.head
+ for ; s != nil; s = s.next {
+ if s.elem == unsafe.Pointer(addr) {
+ xadd(&root.nwait, -1)
+ root.dequeue(s)
+ break
+ }
+ }
+ unlock(&root.lock)
+ if s != nil {
+ if s.releasetime != 0 {
+ s.releasetime = cputicks()
+ }
+ goready(s.g)
+ }
+}
+
+func semroot(addr *uint32) *semaRoot {
+ return &semtable[(uintptr(unsafe.Pointer(addr))>>3)%semTabSize].root
+}
+
+func cansemacquire(addr *uint32) bool {
+ for {
+ v := atomicload(addr)
+ if v == 0 {
+ return false
+ }
+ if cas(addr, v, v-1) {
+ return true
+ }
+ }
+}
+
+func (root *semaRoot) queue(addr *uint32, s *sudog) {
+ s.g = getg()
+ s.elem = unsafe.Pointer(addr)
+ s.next = nil
+ s.prev = root.tail
+ if root.tail != nil {
+ root.tail.next = s
+ } else {
+ root.head = s
+ }
+ root.tail = s
+}
+
+func (root *semaRoot) dequeue(s *sudog) {
+ if s.next != nil {
+ s.next.prev = s.prev
+ } else {
+ root.tail = s.prev
+ }
+ if s.prev != nil {
+ s.prev.next = s.next
+ } else {
+ root.head = s.next
+ }
+ s.elem = nil
+ s.next = nil
+ s.prev = nil
+}
+
+// Synchronous semaphore for sync.Cond.
+type syncSema struct {
+ lock mutex
+ head *sudog
+ tail *sudog
+}
+
+// Syncsemacquire waits for a pairing syncsemrelease on the same semaphore s.
+func syncsemacquire(s *syncSema) {
+ lock(&s.lock)
+ if s.head != nil && s.head.nrelease > 0 {
+ // Have pending release, consume it.
+ var wake *sudog
+ s.head.nrelease--
+ if s.head.nrelease == 0 {
+ wake = s.head
+ s.head = wake.next
+ if s.head == nil {
+ s.tail = nil
+ }
+ }
+ unlock(&s.lock)
+ if wake != nil {
+ wake.next = nil
+ goready(wake.g)
+ }
+ } else {
+ // Enqueue itself.
+ w := acquireSudog()
+ w.g = getg()
+ w.nrelease = -1
+ w.next = nil
+ w.releasetime = 0
+ t0 := int64(0)
+ if blockprofilerate > 0 {
+ t0 = cputicks()
+ w.releasetime = -1
+ }
+ if s.tail == nil {
+ s.head = w
+ } else {
+ s.tail.next = w
+ }
+ s.tail = w
+ goparkunlock(&s.lock, "semacquire")
+ if t0 != 0 {
+ blockevent(int64(w.releasetime)-t0, 2)
+ }
+ releaseSudog(w)
+ }
+}
+
+// Syncsemrelease waits for n pairing syncsemacquire on the same semaphore s.
+func syncsemrelease(s *syncSema, n uint32) {
+ lock(&s.lock)
+ for n > 0 && s.head != nil && s.head.nrelease < 0 {
+ // Have pending acquire, satisfy it.
+ wake := s.head
+ s.head = wake.next
+ if s.head == nil {
+ s.tail = nil
+ }
+ if wake.releasetime != 0 {
+ wake.releasetime = cputicks()
+ }
+ wake.next = nil
+ goready(wake.g)
+ n--
+ }
+ if n > 0 {
+ // enqueue itself
+ w := acquireSudog()
+ w.g = getg()
+ w.nrelease = int32(n)
+ w.next = nil
+ w.releasetime = 0
+ if s.tail == nil {
+ s.head = w
+ } else {
+ s.tail.next = w
+ }
+ s.tail = w
+ goparkunlock(&s.lock, "semarelease")
+ releaseSudog(w)
+ } else {
+ unlock(&s.lock)
+ }
+}
+
+func syncsemcheck(sz uintptr) {
+ if sz != unsafe.Sizeof(syncSema{}) {
+ print("runtime: bad syncSema size - sync=", sz, " runtime=", unsafe.Sizeof(syncSema{}), "\n")
+ gothrow("bad syncSema size")
+ }
+}
diff --git a/src/runtime/signal.c b/src/runtime/signal.c
new file mode 100644
index 000000000..0674bfb22
--- /dev/null
+++ b/src/runtime/signal.c
@@ -0,0 +1,25 @@
+// 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 "runtime.h"
+
+void
+runtime·sigenable_m(void)
+{
+ uint32 s;
+
+ s = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+ runtime·sigenable(s);
+}
+
+void
+runtime·sigdisable_m(void)
+{
+ uint32 s;
+
+ s = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+ runtime·sigdisable(s);
+}
diff --git a/src/pkg/runtime/signal_386.c b/src/runtime/signal_386.c
index 70fcc6a63..30a7488bd 100644
--- a/src/pkg/runtime/signal_386.c
+++ b/src/runtime/signal_386.c
@@ -39,7 +39,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
bool crash;
if(sig == SIGPROF) {
- runtime·sigprof((byte*)SIG_EIP(info, ctxt), (byte*)SIG_ESP(info, ctxt), nil, gp, m);
+ runtime·sigprof((byte*)SIG_EIP(info, ctxt), (byte*)SIG_ESP(info, ctxt), nil, gp, g->m);
return;
}
@@ -91,8 +91,8 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
if(!(t->flags & SigThrow))
return;
- m->throwing = 1;
- m->caughtsig = gp;
+ g->m->throwing = 1;
+ g->m->caughtsig = gp;
runtime·startpanic();
if(sig < 0 || sig >= NSIG)
@@ -101,15 +101,15 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%x\n", SIG_EIP(info, ctxt));
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
+ if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
+ gp = g->m->lockedg;
+ }
runtime·printf("\n");
if(runtime·gotraceback(&crash)){
runtime·goroutineheader(gp);
- runtime·traceback(SIG_EIP(info, ctxt), SIG_ESP(info, ctxt), 0, gp);
+ runtime·tracebacktrap(SIG_EIP(info, ctxt), SIG_ESP(info, ctxt), 0, gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
runtime·dumpregs(info, ctxt);
diff --git a/src/pkg/runtime/signal_amd64x.c b/src/runtime/signal_amd64x.c
index 04026f32f..feb4afcce 100644
--- a/src/pkg/runtime/signal_amd64x.c
+++ b/src/runtime/signal_amd64x.c
@@ -48,7 +48,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
bool crash;
if(sig == SIGPROF) {
- runtime·sigprof((byte*)SIG_RIP(info, ctxt), (byte*)SIG_RSP(info, ctxt), nil, gp, m);
+ runtime·sigprof((byte*)SIG_RIP(info, ctxt), (byte*)SIG_RSP(info, ctxt), nil, gp, g->m);
return;
}
@@ -125,8 +125,8 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
if(!(t->flags & SigThrow))
return;
- m->throwing = 1;
- m->caughtsig = gp;
+ g->m->throwing = 1;
+ g->m->caughtsig = gp;
runtime·startpanic();
if(sig < 0 || sig >= NSIG)
@@ -135,15 +135,15 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%X\n", SIG_RIP(info, ctxt));
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
+ if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
+ gp = g->m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback(&crash)){
runtime·goroutineheader(gp);
- runtime·traceback(SIG_RIP(info, ctxt), SIG_RSP(info, ctxt), 0, gp);
+ runtime·tracebacktrap(SIG_RIP(info, ctxt), SIG_RSP(info, ctxt), 0, gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
runtime·dumpregs(info, ctxt);
diff --git a/src/runtime/signal_android_386.h b/src/runtime/signal_android_386.h
new file mode 100644
index 000000000..2a1bb4b3e
--- /dev/null
+++ b/src/runtime/signal_android_386.h
@@ -0,0 +1 @@
+#include "signal_linux_386.h"
diff --git a/src/runtime/signal_android_arm.h b/src/runtime/signal_android_arm.h
new file mode 100644
index 000000000..8a05e21e5
--- /dev/null
+++ b/src/runtime/signal_android_arm.h
@@ -0,0 +1 @@
+#include "signal_linux_arm.h"
diff --git a/src/pkg/runtime/signal_arm.c b/src/runtime/signal_arm.c
index 9b2a43d9b..afad5e7d1 100644
--- a/src/pkg/runtime/signal_arm.c
+++ b/src/runtime/signal_arm.c
@@ -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 darwin dragonfly freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
@@ -46,7 +46,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
bool crash;
if(sig == SIGPROF) {
- runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LR(info, ctxt), gp, m);
+ runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LR(info, ctxt), gp, g->m);
return;
}
@@ -76,7 +76,6 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
SIG_LR(info, ctxt) = gp->sigpc;
// In case we are panicking from external C code
SIG_R10(info, ctxt) = (uintptr)gp;
- SIG_R9(info, ctxt) = (uintptr)m;
SIG_PC(info, ctxt) = (uintptr)runtime·sigpanic;
return;
}
@@ -89,8 +88,8 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
if(!(t->flags & SigThrow))
return;
- m->throwing = 1;
- m->caughtsig = gp;
+ g->m->throwing = 1;
+ g->m->caughtsig = gp;
if(runtime·panicking) // traceback already printed
runtime·exit(2);
runtime·panicking = 1;
@@ -101,15 +100,15 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%x\n", SIG_PC(info, ctxt));
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
+ if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
+ gp = g->m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback(&crash)){
runtime·goroutineheader(gp);
- runtime·traceback(SIG_PC(info, ctxt), SIG_SP(info, ctxt), SIG_LR(info, ctxt), gp);
+ runtime·tracebacktrap(SIG_PC(info, ctxt), SIG_SP(info, ctxt), SIG_LR(info, ctxt), gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
runtime·dumpregs(info, ctxt);
diff --git a/src/pkg/runtime/signal_darwin_386.h b/src/runtime/signal_darwin_386.h
index 5459e10a1..5459e10a1 100644
--- a/src/pkg/runtime/signal_darwin_386.h
+++ b/src/runtime/signal_darwin_386.h
diff --git a/src/pkg/runtime/signal_darwin_amd64.h b/src/runtime/signal_darwin_amd64.h
index e3da6de3a..e3da6de3a 100644
--- a/src/pkg/runtime/signal_darwin_amd64.h
+++ b/src/runtime/signal_darwin_amd64.h
diff --git a/src/pkg/runtime/signal_dragonfly_386.h b/src/runtime/signal_dragonfly_386.h
index a24f1ee96..a24f1ee96 100644
--- a/src/pkg/runtime/signal_dragonfly_386.h
+++ b/src/runtime/signal_dragonfly_386.h
diff --git a/src/pkg/runtime/signal_dragonfly_amd64.h b/src/runtime/signal_dragonfly_amd64.h
index 5b4f97782..5b4f97782 100644
--- a/src/pkg/runtime/signal_dragonfly_amd64.h
+++ b/src/runtime/signal_dragonfly_amd64.h
diff --git a/src/pkg/runtime/signal_freebsd_386.h b/src/runtime/signal_freebsd_386.h
index a24f1ee96..a24f1ee96 100644
--- a/src/pkg/runtime/signal_freebsd_386.h
+++ b/src/runtime/signal_freebsd_386.h
diff --git a/src/pkg/runtime/signal_freebsd_amd64.h b/src/runtime/signal_freebsd_amd64.h
index 7d35b7f85..7d35b7f85 100644
--- a/src/pkg/runtime/signal_freebsd_amd64.h
+++ b/src/runtime/signal_freebsd_amd64.h
diff --git a/src/pkg/runtime/signal_freebsd_arm.h b/src/runtime/signal_freebsd_arm.h
index 87a45aa27..87a45aa27 100644
--- a/src/pkg/runtime/signal_freebsd_arm.h
+++ b/src/runtime/signal_freebsd_arm.h
diff --git a/src/pkg/runtime/signal_linux_386.h b/src/runtime/signal_linux_386.h
index f77f1c9d5..f77f1c9d5 100644
--- a/src/pkg/runtime/signal_linux_386.h
+++ b/src/runtime/signal_linux_386.h
diff --git a/src/pkg/runtime/signal_linux_amd64.h b/src/runtime/signal_linux_amd64.h
index 5a9a3e5da..5a9a3e5da 100644
--- a/src/pkg/runtime/signal_linux_amd64.h
+++ b/src/runtime/signal_linux_amd64.h
diff --git a/src/pkg/runtime/signal_linux_arm.h b/src/runtime/signal_linux_arm.h
index a674c0d57..a674c0d57 100644
--- a/src/pkg/runtime/signal_linux_arm.h
+++ b/src/runtime/signal_linux_arm.h
diff --git a/src/pkg/runtime/signal_nacl_386.h b/src/runtime/signal_nacl_386.h
index c9481b5f4..c9481b5f4 100644
--- a/src/pkg/runtime/signal_nacl_386.h
+++ b/src/runtime/signal_nacl_386.h
diff --git a/src/pkg/runtime/signal_nacl_amd64p32.h b/src/runtime/signal_nacl_amd64p32.h
index c58593a29..f62305cb5 100644
--- a/src/pkg/runtime/signal_nacl_amd64p32.h
+++ b/src/runtime/signal_nacl_amd64p32.h
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define SIG_REGS(ctxt) (((ExcContext*)(ctxt))->regs64)
+#define SIG_REGS(ctxt) (((ExcContext*)(ctxt))->regs.regs64)
#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).rax)
#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).rbx)
diff --git a/src/runtime/signal_nacl_arm.h b/src/runtime/signal_nacl_arm.h
new file mode 100644
index 000000000..e5bbb211d
--- /dev/null
+++ b/src/runtime/signal_nacl_arm.h
@@ -0,0 +1,28 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (((ExcContext*)(ctxt))->regs)
+
+#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).r0)
+#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).r1)
+#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).r2)
+#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).r3)
+#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).r4)
+#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).r5)
+#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).r6)
+#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).r7)
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8)
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9)
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10)
+#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).r11)
+#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).r12)
+#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).sp)
+#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).lr)
+#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).pc)
+#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).cpsr)
+#define SIG_FAULT(info, ctxt) (~0)
+#define SIG_TRAP(info, ctxt) (~0)
+#define SIG_ERROR(info, ctxt) (~0)
+#define SIG_OLDMASK(info, ctxt) (~0)
+#define SIG_CODE0(info, ctxt) (~0)
diff --git a/src/pkg/runtime/signal_netbsd_386.h b/src/runtime/signal_netbsd_386.h
index d5a8a0c4b..d5a8a0c4b 100644
--- a/src/pkg/runtime/signal_netbsd_386.h
+++ b/src/runtime/signal_netbsd_386.h
diff --git a/src/pkg/runtime/signal_netbsd_amd64.h b/src/runtime/signal_netbsd_amd64.h
index 7ec4cd98c..7ec4cd98c 100644
--- a/src/pkg/runtime/signal_netbsd_amd64.h
+++ b/src/runtime/signal_netbsd_amd64.h
diff --git a/src/pkg/runtime/signal_netbsd_arm.h b/src/runtime/signal_netbsd_arm.h
index 12f5827a6..12f5827a6 100644
--- a/src/pkg/runtime/signal_netbsd_arm.h
+++ b/src/runtime/signal_netbsd_arm.h
diff --git a/src/pkg/runtime/signal_openbsd_386.h b/src/runtime/signal_openbsd_386.h
index 6742db8d4..6742db8d4 100644
--- a/src/pkg/runtime/signal_openbsd_386.h
+++ b/src/runtime/signal_openbsd_386.h
diff --git a/src/pkg/runtime/signal_openbsd_amd64.h b/src/runtime/signal_openbsd_amd64.h
index b46a5dfa6..b46a5dfa6 100644
--- a/src/pkg/runtime/signal_openbsd_amd64.h
+++ b/src/runtime/signal_openbsd_amd64.h
diff --git a/src/pkg/runtime/signal_solaris_amd64.h b/src/runtime/signal_solaris_amd64.h
index c2e0a1549..c2e0a1549 100644
--- a/src/pkg/runtime/signal_solaris_amd64.h
+++ b/src/runtime/signal_solaris_amd64.h
diff --git a/src/pkg/runtime/signal_unix.c b/src/runtime/signal_unix.c
index 246a1eb25..0e33ece49 100644
--- a/src/pkg/runtime/signal_unix.c
+++ b/src/runtime/signal_unix.c
@@ -89,11 +89,11 @@ runtime·resetcpuprofiler(int32 hz)
it.it_value = it.it_interval;
runtime·setitimer(ITIMER_PROF, &it, nil);
}
- m->profilehz = hz;
+ g->m->profilehz = hz;
}
void
-os·sigpipe(void)
+runtime·sigpipe(void)
{
runtime·setsig(SIGPIPE, SIG_DFL, false);
runtime·raise(SIGPIPE);
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
new file mode 100644
index 000000000..ba77b6e7b
--- /dev/null
+++ b/src/runtime/signal_unix.go
@@ -0,0 +1,13 @@
+// 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 solaris
+
+package runtime
+
+func sigpipe()
+
+func os_sigpipe() {
+ onM(sigpipe)
+}
diff --git a/src/pkg/runtime/signal_unix.h b/src/runtime/signal_unix.h
index 2d84a0186..2d84a0186 100644
--- a/src/pkg/runtime/signal_unix.h
+++ b/src/runtime/signal_unix.h
diff --git a/src/runtime/signals_android.h b/src/runtime/signals_android.h
new file mode 100644
index 000000000..5140d8a18
--- /dev/null
+++ b/src/runtime/signals_android.h
@@ -0,0 +1 @@
+#include "signals_linux.h"
diff --git a/src/pkg/runtime/signals_darwin.h b/src/runtime/signals_darwin.h
index 229b58590..8761e1bd9 100644
--- a/src/pkg/runtime/signals_darwin.h
+++ b/src/runtime/signals_darwin.h
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include "textflag.h"
+
#define N SigNotify
#define K SigKill
#define T SigThrow
#define P SigPanic
#define D SigDefault
+#pragma dataflag NOPTR
SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup",
diff --git a/src/pkg/runtime/signals_dragonfly.h b/src/runtime/signals_dragonfly.h
index 4d27e050d..07343a766 100644
--- a/src/pkg/runtime/signals_dragonfly.h
+++ b/src/runtime/signals_dragonfly.h
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include "textflag.h"
+
#define N SigNotify
#define K SigKill
#define T SigThrow
#define P SigPanic
#define D SigDefault
+#pragma dataflag NOPTR
SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup",
diff --git a/src/pkg/runtime/signals_freebsd.h b/src/runtime/signals_freebsd.h
index 8d45c50c3..39e0a947e 100644
--- a/src/pkg/runtime/signals_freebsd.h
+++ b/src/runtime/signals_freebsd.h
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include "textflag.h"
+
#define N SigNotify
#define K SigKill
#define T SigThrow
#define P SigPanic
#define D SigDefault
+#pragma dataflag NOPTR
SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup",
diff --git a/src/pkg/runtime/signals_linux.h b/src/runtime/signals_linux.h
index 368afc1c8..374107609 100644
--- a/src/pkg/runtime/signals_linux.h
+++ b/src/runtime/signals_linux.h
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include "textflag.h"
+
#define N SigNotify
#define K SigKill
#define T SigThrow
#define P SigPanic
#define D SigDefault
+#pragma dataflag NOPTR
SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup",
diff --git a/src/pkg/runtime/signals_nacl.h b/src/runtime/signals_nacl.h
index 229b58590..8761e1bd9 100644
--- a/src/pkg/runtime/signals_nacl.h
+++ b/src/runtime/signals_nacl.h
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include "textflag.h"
+
#define N SigNotify
#define K SigKill
#define T SigThrow
#define P SigPanic
#define D SigDefault
+#pragma dataflag NOPTR
SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup",
diff --git a/src/pkg/runtime/signals_netbsd.h b/src/runtime/signals_netbsd.h
index 7140de86f..950a2fe62 100644
--- a/src/pkg/runtime/signals_netbsd.h
+++ b/src/runtime/signals_netbsd.h
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include "textflag.h"
+
#define N SigNotify
#define K SigKill
#define T SigThrow
#define P SigPanic
#define D SigDefault
+#pragma dataflag NOPTR
SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup",
diff --git a/src/pkg/runtime/signals_openbsd.h b/src/runtime/signals_openbsd.h
index 7140de86f..950a2fe62 100644
--- a/src/pkg/runtime/signals_openbsd.h
+++ b/src/runtime/signals_openbsd.h
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include "textflag.h"
+
#define N SigNotify
#define K SigKill
#define T SigThrow
#define P SigPanic
#define D SigDefault
+#pragma dataflag NOPTR
SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup",
diff --git a/src/pkg/runtime/signals_plan9.h b/src/runtime/signals_plan9.h
index 818f508cf..4ee8e542c 100644
--- a/src/pkg/runtime/signals_plan9.h
+++ b/src/runtime/signals_plan9.h
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include "textflag.h"
+
#define N SigNotify
#define K SigKill
#define T SigThrow
@@ -16,6 +18,7 @@
// If you add entries to this table, you must respect the prefix ordering
// and also update the constant values is os_plan9.h.
+#pragma dataflag NOPTR
SigTab runtime·sigtab[] = {
// Traps that we cannot be recovered.
T, "sys: trap: debug exception",
diff --git a/src/pkg/runtime/signals_solaris.h b/src/runtime/signals_solaris.h
index c272cad29..1f0a65ea6 100644
--- a/src/pkg/runtime/signals_solaris.h
+++ b/src/runtime/signals_solaris.h
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include "textflag.h"
+
#define N SigNotify
#define K SigKill
#define T SigThrow
#define P SigPanic
#define D SigDefault
+#pragma dataflag NOPTR
SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: hangup",
diff --git a/src/pkg/runtime/signals_windows.h b/src/runtime/signals_windows.h
index 6943714b0..6943714b0 100644
--- a/src/pkg/runtime/signals_windows.h
+++ b/src/runtime/signals_windows.h
diff --git a/src/runtime/sigpanic_unix.go b/src/runtime/sigpanic_unix.go
new file mode 100644
index 000000000..68079859b
--- /dev/null
+++ b/src/runtime/sigpanic_unix.go
@@ -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 darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package runtime
+
+func signame(int32) *byte
+
+func sigpanic() {
+ g := getg()
+ if !canpanic(g) {
+ gothrow("unexpected signal during runtime execution")
+ }
+
+ switch g.sig {
+ case _SIGBUS:
+ if g.sigcode0 == _BUS_ADRERR && g.sigcode1 < 0x1000 || g.paniconfault {
+ panicmem()
+ }
+ print("unexpected fault address ", hex(g.sigcode1), "\n")
+ gothrow("fault")
+ case _SIGSEGV:
+ if (g.sigcode0 == 0 || g.sigcode0 == _SEGV_MAPERR || g.sigcode0 == _SEGV_ACCERR) && g.sigcode1 < 0x1000 || g.paniconfault {
+ panicmem()
+ }
+ print("unexpected fault address ", hex(g.sigcode1), "\n")
+ gothrow("fault")
+ case _SIGFPE:
+ switch g.sigcode0 {
+ case _FPE_INTDIV:
+ panicdivide()
+ case _FPE_INTOVF:
+ panicoverflow()
+ }
+ panicfloat()
+ }
+ panic(errorString(gostringnocopy(signame(g.sig))))
+}
diff --git a/src/runtime/sigqueue.go b/src/runtime/sigqueue.go
new file mode 100644
index 000000000..2d9c24d2d
--- /dev/null
+++ b/src/runtime/sigqueue.go
@@ -0,0 +1,173 @@
+// 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.
+
+// This file implements runtime support for signal handling.
+//
+// Most synchronization primitives are not available from
+// the signal handler (it cannot block, allocate memory, or use locks)
+// so the handler communicates with a processing goroutine
+// via struct sig, below.
+//
+// sigsend is called by the signal handler to queue a new signal.
+// signal_recv is called by the Go program to receive a newly queued signal.
+// Synchronization between sigsend and signal_recv is based on the sig.state
+// variable. It can be in 3 states: sigIdle, sigReceiving and sigSending.
+// sigReceiving means that signal_recv is blocked on sig.Note and there are no
+// new pending signals.
+// sigSending means that sig.mask *may* contain new pending signals,
+// signal_recv can't be blocked in this state.
+// sigIdle means that there are no new pending signals and signal_recv is not blocked.
+// Transitions between states are done atomically with CAS.
+// When signal_recv is unblocked, it resets sig.Note and rechecks sig.mask.
+// If several sigsends and signal_recv execute concurrently, it can lead to
+// unnecessary rechecks of sig.mask, but it cannot lead to missed signals
+// nor deadlocks.
+
+package runtime
+
+import "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
+}
+
+const (
+ sigIdle = iota
+ sigReceiving
+ sigSending
+)
+
+// Called from sighandler to send a signal back out of the signal handling thread.
+// Reports whether the signal was sent. If not, the caller typically crashes the program.
+func sigsend(s int32) bool {
+ bit := uint32(1) << uint(s&31)
+ if !sig.inuse || s < 0 || int(s) >= 32*len(sig.wanted) || sig.wanted[s/32]&bit == 0 {
+ return false
+ }
+
+ // Add signal to outgoing queue.
+ for {
+ mask := sig.mask[s/32]
+ if mask&bit != 0 {
+ return true // signal already in queue
+ }
+ if cas(&sig.mask[s/32], mask, mask|bit) {
+ break
+ }
+ }
+
+ // Notify receiver that queue has new bit.
+Send:
+ for {
+ switch atomicload(&sig.state) {
+ default:
+ gothrow("sigsend: inconsistent state")
+ case sigIdle:
+ if cas(&sig.state, sigIdle, sigSending) {
+ break Send
+ }
+ case sigSending:
+ // notification already pending
+ break Send
+ case sigReceiving:
+ if cas(&sig.state, sigReceiving, sigIdle) {
+ notewakeup(&sig.note)
+ break Send
+ }
+ }
+ }
+
+ return true
+}
+
+// Called to receive the next queued signal.
+// Must only be called from a single goroutine at a time.
+func signal_recv() uint32 {
+ for {
+ // Serve any signals from local copy.
+ for i := uint32(0); i < _NSIG; i++ {
+ if sig.recv[i/32]&(1<<(i&31)) != 0 {
+ sig.recv[i/32] &^= 1 << (i & 31)
+ return i
+ }
+ }
+
+ // Wait for updates to be available from signal sender.
+ Receive:
+ for {
+ switch atomicload(&sig.state) {
+ default:
+ gothrow("signal_recv: inconsistent state")
+ case sigIdle:
+ if cas(&sig.state, sigIdle, sigReceiving) {
+ notetsleepg(&sig.note, -1)
+ noteclear(&sig.note)
+ break Receive
+ }
+ case sigSending:
+ if cas(&sig.state, sigSending, sigIdle) {
+ break Receive
+ }
+ }
+ }
+
+ // Incorporate updates from sender into local copy.
+ for i := range sig.mask {
+ sig.recv[i] = xchg(&sig.mask[i], 0)
+ }
+ }
+}
+
+// Must only be called from a single goroutine at a time.
+func signal_enable(s uint32) {
+ if !sig.inuse {
+ // The first call to signal_enable is for us
+ // to use for initialization. It does not pass
+ // signal information in m.
+ sig.inuse = true // enable reception of signals; cannot disable
+ noteclear(&sig.note)
+ return
+ }
+
+ if int(s) >= len(sig.wanted)*32 {
+ return
+ }
+ sig.wanted[s/32] |= 1 << (s & 31)
+ sigenable_go(s)
+}
+
+// Must only be called from a single goroutine at a time.
+func signal_disable(s uint32) {
+ if int(s) >= len(sig.wanted)*32 {
+ return
+ }
+ sig.wanted[s/32] &^= 1 << (s & 31)
+ sigdisable_go(s)
+}
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+//go:nosplit
+func badsignal(sig uintptr) {
+ cgocallback(unsafe.Pointer(funcPC(sigsend)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
+}
+
+func sigenable_m()
+func sigdisable_m()
+
+func sigenable_go(s uint32) {
+ g := getg()
+ g.m.scalararg[0] = uintptr(s)
+ onM(sigenable_m)
+}
+
+func sigdisable_go(s uint32) {
+ g := getg()
+ g.m.scalararg[0] = uintptr(s)
+ onM(sigdisable_m)
+}
diff --git a/src/runtime/slice.go b/src/runtime/slice.go
new file mode 100644
index 000000000..171087d7f
--- /dev/null
+++ b/src/runtime/slice.go
@@ -0,0 +1,139 @@
+// 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 sliceStruct struct {
+ array unsafe.Pointer
+ len int
+ cap int
+}
+
+// TODO: take uintptrs instead of int64s?
+func makeslice(t *slicetype, len64 int64, cap64 int64) sliceStruct {
+ // NOTE: The len > MaxMem/elemsize check here is not strictly necessary,
+ // but it produces a 'len out of range' error instead of a 'cap out of range' error
+ // when someone does make([]T, bignumber). 'cap out of range' is true too,
+ // but since the cap is only being supplied implicitly, saying len is clearer.
+ // See issue 4085.
+ len := int(len64)
+ if len64 < 0 || int64(len) != len64 || t.elem.size > 0 && uintptr(len) > maxmem/uintptr(t.elem.size) {
+ panic(errorString("makeslice: len out of range"))
+ }
+ cap := int(cap64)
+ if cap < len || int64(cap) != cap64 || t.elem.size > 0 && uintptr(cap) > maxmem/uintptr(t.elem.size) {
+ panic(errorString("makeslice: cap out of range"))
+ }
+ p := newarray(t.elem, uintptr(cap))
+ return sliceStruct{p, len, cap}
+}
+
+// TODO: take uintptr instead of int64?
+func growslice(t *slicetype, old sliceStruct, n int64) sliceStruct {
+ if n < 1 {
+ panic(errorString("growslice: invalid n"))
+ }
+
+ cap64 := int64(old.cap) + n
+ cap := int(cap64)
+
+ if int64(cap) != cap64 || cap < old.cap || t.elem.size > 0 && uintptr(cap) > maxmem/uintptr(t.elem.size) {
+ panic(errorString("growslice: cap out of range"))
+ }
+
+ if raceenabled {
+ callerpc := getcallerpc(unsafe.Pointer(&t))
+ racereadrangepc(old.array, uintptr(old.len*int(t.elem.size)), callerpc, funcPC(growslice))
+ }
+
+ et := t.elem
+ if et.size == 0 {
+ return sliceStruct{old.array, old.len, cap}
+ }
+
+ newcap := old.cap
+ if newcap+newcap < cap {
+ newcap = cap
+ } else {
+ for {
+ if old.len < 1024 {
+ newcap += newcap
+ } else {
+ newcap += newcap / 4
+ }
+ if newcap >= cap {
+ break
+ }
+ }
+ }
+
+ if uintptr(newcap) >= maxmem/uintptr(et.size) {
+ panic(errorString("growslice: cap out of range"))
+ }
+ lenmem := uintptr(old.len) * uintptr(et.size)
+ capmem := goroundupsize(uintptr(newcap) * uintptr(et.size))
+ newcap = int(capmem / uintptr(et.size))
+ var p unsafe.Pointer
+ if et.kind&kindNoPointers != 0 {
+ p = rawmem(capmem)
+ memclr(add(p, lenmem), capmem-lenmem)
+ } else {
+ // Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan unitialized memory
+ p = newarray(et, uintptr(newcap))
+ }
+ memmove(p, old.array, lenmem)
+
+ return sliceStruct{p, old.len, newcap}
+}
+
+func slicecopy(to sliceStruct, fm sliceStruct, width uintptr) int {
+ if fm.len == 0 || to.len == 0 || width == 0 {
+ return 0
+ }
+
+ n := fm.len
+ if to.len < n {
+ n = to.len
+ }
+
+ if raceenabled {
+ callerpc := getcallerpc(unsafe.Pointer(&to))
+ pc := funcPC(slicecopy)
+ racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc)
+ racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc)
+ }
+
+ size := uintptr(n) * width
+ if size == 1 { // common case worth about 2x to do here
+ // TODO: is this still worth it with new memmove impl?
+ *(*byte)(to.array) = *(*byte)(fm.array) // known to be a byte pointer
+ } else {
+ memmove(to.array, fm.array, size)
+ }
+ return int(n)
+}
+
+func slicestringcopy(to []byte, fm string) int {
+ if len(fm) == 0 || len(to) == 0 {
+ return 0
+ }
+
+ n := len(fm)
+ if len(to) < n {
+ n = len(to)
+ }
+
+ if raceenabled {
+ callerpc := getcallerpc(unsafe.Pointer(&to))
+ pc := funcPC(slicestringcopy)
+ racewriterangepc(unsafe.Pointer(&to[0]), uintptr(n), callerpc, pc)
+ }
+
+ memmove(unsafe.Pointer(&to[0]), unsafe.Pointer((*stringStruct)(unsafe.Pointer(&fm)).str), uintptr(n))
+ return n
+}
diff --git a/src/pkg/runtime/softfloat64.go b/src/runtime/softfloat64.go
index 4fcf8f269..4fcf8f269 100644
--- a/src/pkg/runtime/softfloat64.go
+++ b/src/runtime/softfloat64.go
diff --git a/src/pkg/runtime/softfloat64_test.go b/src/runtime/softfloat64_test.go
index df63010fb..df63010fb 100644
--- a/src/pkg/runtime/softfloat64_test.go
+++ b/src/runtime/softfloat64_test.go
diff --git a/src/pkg/runtime/softfloat_arm.c b/src/runtime/softfloat_arm.c
index 29a52bd0e..3f3f33a19 100644
--- a/src/pkg/runtime/softfloat_arm.c
+++ b/src/runtime/softfloat_arm.c
@@ -7,7 +7,7 @@
// It uses true little-endian doubles, while the 7500 used mixed-endian.
#include "runtime.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#define CPSR 14
#define FLAGS_N (1U << 31)
@@ -32,20 +32,20 @@ fabort(void)
static void
putf(uint32 reg, uint32 val)
{
- m->freglo[reg] = val;
+ g->m->freglo[reg] = val;
}
static void
putd(uint32 reg, uint64 val)
{
- m->freglo[reg] = (uint32)val;
- m->freghi[reg] = (uint32)(val>>32);
+ g->m->freglo[reg] = (uint32)val;
+ g->m->freghi[reg] = (uint32)(val>>32);
}
static uint64
getd(uint32 reg)
{
- return (uint64)m->freglo[reg] | ((uint64)m->freghi[reg]<<32);
+ return (uint64)g->m->freglo[reg] | ((uint64)g->m->freghi[reg]<<32);
}
static void
@@ -53,7 +53,7 @@ fprint(void)
{
uint32 i;
for (i = 0; i < 16; i++) {
- runtime·printf("\tf%d:\t%X %X\n", i, m->freghi[i], m->freglo[i]);
+ runtime·printf("\tf%d:\t%X %X\n", i, g->m->freghi[i], g->m->freglo[i]);
}
}
@@ -90,6 +90,7 @@ fstatus(bool nan, int32 cmp)
// conditions array record the required CPSR cond field for the
// first 5 pairs of conditional execution opcodes
// higher 4 bits are must set, lower 4 bits are must clear
+#pragma dataflag NOPTR
static const uint8 conditions[10/2] = {
[0/2] = (FLAGS_Z >> 24) | 0, // 0: EQ (Z set), 1: NE (Z clear)
[2/2] = (FLAGS_C >> 24) | 0, // 2: CS/HS (C set), 3: CC/LO (C clear)
@@ -99,6 +100,8 @@ static const uint8 conditions[10/2] = {
(FLAGS_Z >> 28), // 8: HI (C set and Z clear), 9: LS (C clear and Z set)
};
+#define FAULT (0x80000000U) // impossible PC offset
+
// returns number of words that the fp instruction
// is occupying, 0 if next instruction isn't float.
static uint32
@@ -111,7 +114,11 @@ stepflt(uint32 *pc, uint32 *regs)
int64 sval;
bool nan, ok;
int32 cmp;
+ M *m;
+ // m is locked in vlop_arm.s, so g->m cannot change during this function call,
+ // so caching it in a local variable is safe.
+ m = g->m;
i = *pc;
if(trace)
@@ -216,6 +223,11 @@ stage1: // load/store regn is cpureg, regm is 8bit offset
case 0xed900a00: // single load
addr = (uint32*)(regs[regn] + regm);
+ if((uintptr)addr < 4096) {
+ if(trace)
+ runtime·printf("*** load @%p => fault\n", addr);
+ return FAULT;
+ }
m->freglo[regd] = addr[0];
if(trace)
@@ -225,6 +237,11 @@ stage1: // load/store regn is cpureg, regm is 8bit offset
case 0xed900b00: // double load
addr = (uint32*)(regs[regn] + regm);
+ if((uintptr)addr < 4096) {
+ if(trace)
+ runtime·printf("*** double load @%p => fault\n", addr);
+ return FAULT;
+ }
m->freglo[regd] = addr[0];
m->freghi[regd] = addr[1];
@@ -235,6 +252,11 @@ stage1: // load/store regn is cpureg, regm is 8bit offset
case 0xed800a00: // single store
addr = (uint32*)(regs[regn] + regm);
+ if((uintptr)addr < 4096) {
+ if(trace)
+ runtime·printf("*** store @%p => fault\n", addr);
+ return FAULT;
+ }
addr[0] = m->freglo[regd];
if(trace)
@@ -244,6 +266,11 @@ stage1: // load/store regn is cpureg, regm is 8bit offset
case 0xed800b00: // double store
addr = (uint32*)(regs[regn] + regm);
+ if((uintptr)addr < 4096) {
+ if(trace)
+ runtime·printf("*** double store @%p => fault\n", addr);
+ return FAULT;
+ }
addr[0] = m->freglo[regd];
addr[1] = m->freghi[regd];
@@ -601,20 +628,60 @@ struct Sfregs
uint32 cspr;
};
+static void sfloat2(void);
+void _sfloatpanic(void);
+
#pragma textflag NOSPLIT
uint32*
-runtime·_sfloat2(uint32 *lr, Sfregs regs)
+runtime·_sfloat2(uint32 *pc, Sfregs regs)
{
- uint32 skip;
+ void (*fn)(void);
+
+ g->m->ptrarg[0] = pc;
+ g->m->ptrarg[1] = &regs;
+ fn = sfloat2;
+ runtime·onM(&fn);
+ pc = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ return pc;
+}
- skip = stepflt(lr, (uint32*)&regs.r0);
- if(skip == 0) {
- runtime·printf("sfloat2 %p %x\n", lr, *lr);
+static void
+sfloat2(void)
+{
+ uint32 *pc;
+ G *curg;
+ Sfregs *regs;
+ int32 skip;
+ bool first;
+
+ pc = g->m->ptrarg[0];
+ regs = g->m->ptrarg[1];
+ g->m->ptrarg[0] = nil;
+ g->m->ptrarg[1] = nil;
+
+ first = true;
+ while(skip = stepflt(pc, (uint32*)&regs->r0)) {
+ first = false;
+ if(skip == FAULT) {
+ // Encountered bad address in store/load.
+ // Record signal information and return to assembly
+ // trampoline that fakes the call.
+ enum { SIGSEGV = 11 };
+ curg = g->m->curg;
+ curg->sig = SIGSEGV;
+ curg->sigcode0 = 0;
+ curg->sigcode1 = 0;
+ curg->sigpc = (uint32)pc;
+ pc = (uint32*)_sfloatpanic;
+ break;
+ }
+ pc += skip;
+ }
+ if(first) {
+ runtime·printf("sfloat2 %p %x\n", pc, *pc);
fabort(); // not ok to fail first instruction
}
-
- lr += skip;
- while(skip = stepflt(lr, (uint32*)&regs.r0))
- lr += skip;
- return lr;
+
+ g->m->ptrarg[0] = pc;
}
diff --git a/src/pkg/runtime/sqrt.go b/src/runtime/sqrt.go
index 34a8c3806..34a8c3806 100644
--- a/src/pkg/runtime/sqrt.go
+++ b/src/runtime/sqrt.go
diff --git a/src/runtime/stack.c b/src/runtime/stack.c
new file mode 100644
index 000000000..cb9557243
--- /dev/null
+++ b/src/runtime/stack.c
@@ -0,0 +1,892 @@
+// 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 "runtime.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
+#include "stack.h"
+#include "funcdata.h"
+#include "typekind.h"
+#include "type.h"
+#include "race.h"
+#include "mgc0.h"
+#include "textflag.h"
+
+enum
+{
+ // 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,
+};
+
+// 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.
+MSpan runtime·stackpool[NumStackOrders];
+Mutex runtime·stackpoolmu;
+// TODO: one lock per order?
+
+static Stack stackfreequeue;
+
+void
+runtime·stackinit(void)
+{
+ int32 i;
+
+ if((StackCacheSize & PageMask) != 0)
+ runtime·throw("cache size must be a multiple of page size");
+
+ for(i = 0; i < NumStackOrders; i++)
+ runtime·MSpanList_Init(&runtime·stackpool[i]);
+}
+
+// Allocates a stack from the free pool. Must be called with
+// stackpoolmu held.
+static MLink*
+poolalloc(uint8 order)
+{
+ MSpan *list;
+ MSpan *s;
+ MLink *x;
+ uintptr i;
+
+ list = &runtime·stackpool[order];
+ s = list->next;
+ if(s == list) {
+ // no free stacks. Allocate another span worth.
+ s = runtime·MHeap_AllocStack(&runtime·mheap, StackCacheSize >> PageShift);
+ if(s == nil)
+ runtime·throw("out of memory");
+ if(s->ref != 0)
+ runtime·throw("bad ref");
+ if(s->freelist != nil)
+ runtime·throw("bad freelist");
+ for(i = 0; i < StackCacheSize; i += FixedStack << order) {
+ x = (MLink*)((s->start << PageShift) + i);
+ x->next = s->freelist;
+ s->freelist = x;
+ }
+ runtime·MSpanList_Insert(list, s);
+ }
+ x = s->freelist;
+ if(x == nil)
+ runtime·throw("span has no free stacks");
+ s->freelist = x->next;
+ s->ref++;
+ if(s->freelist == nil) {
+ // all stacks in s are allocated.
+ runtime·MSpanList_Remove(s);
+ }
+ return x;
+}
+
+// Adds stack x to the free pool. Must be called with stackpoolmu held.
+static void
+poolfree(MLink *x, uint8 order)
+{
+ MSpan *s;
+
+ s = runtime·MHeap_Lookup(&runtime·mheap, x);
+ if(s->state != MSpanStack)
+ runtime·throw("freeing stack not in a stack span");
+ if(s->freelist == nil) {
+ // s will now have a free stack
+ runtime·MSpanList_Insert(&runtime·stackpool[order], s);
+ }
+ x->next = s->freelist;
+ s->freelist = x;
+ s->ref--;
+ if(s->ref == 0) {
+ // span is completely free - return to heap
+ runtime·MSpanList_Remove(s);
+ s->freelist = nil;
+ runtime·MHeap_FreeStack(&runtime·mheap, s);
+ }
+}
+
+// stackcacherefill/stackcacherelease implement a global pool of stack segments.
+// The pool is required to prevent unlimited growth of per-thread caches.
+static void
+stackcacherefill(MCache *c, uint8 order)
+{
+ MLink *x, *list;
+ uintptr size;
+
+ if(StackDebug >= 1)
+ runtime·printf("stackcacherefill order=%d\n", order);
+
+ // Grab some stacks from the global cache.
+ // Grab half of the allowed capacity (to prevent thrashing).
+ list = nil;
+ size = 0;
+ runtime·lock(&runtime·stackpoolmu);
+ while(size < StackCacheSize/2) {
+ x = poolalloc(order);
+ x->next = list;
+ list = x;
+ size += FixedStack << order;
+ }
+ runtime·unlock(&runtime·stackpoolmu);
+
+ c->stackcache[order].list = list;
+ c->stackcache[order].size = size;
+}
+
+static void
+stackcacherelease(MCache *c, uint8 order)
+{
+ MLink *x, *y;
+ uintptr size;
+
+ if(StackDebug >= 1)
+ runtime·printf("stackcacherelease order=%d\n", order);
+ x = c->stackcache[order].list;
+ size = c->stackcache[order].size;
+ runtime·lock(&runtime·stackpoolmu);
+ while(size > StackCacheSize/2) {
+ y = x->next;
+ poolfree(x, order);
+ x = y;
+ size -= FixedStack << order;
+ }
+ runtime·unlock(&runtime·stackpoolmu);
+ c->stackcache[order].list = x;
+ c->stackcache[order].size = size;
+}
+
+void
+runtime·stackcache_clear(MCache *c)
+{
+ uint8 order;
+ MLink *x, *y;
+
+ if(StackDebug >= 1)
+ runtime·printf("stackcache clear\n");
+ runtime·lock(&runtime·stackpoolmu);
+ for(order = 0; order < NumStackOrders; order++) {
+ x = c->stackcache[order].list;
+ while(x != nil) {
+ y = x->next;
+ poolfree(x, order);
+ x = y;
+ }
+ c->stackcache[order].list = nil;
+ c->stackcache[order].size = 0;
+ }
+ runtime·unlock(&runtime·stackpoolmu);
+}
+
+Stack
+runtime·stackalloc(uint32 n)
+{
+ uint8 order;
+ uint32 n2;
+ void *v;
+ MLink *x;
+ MSpan *s;
+ MCache *c;
+
+ // 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).
+ if(g != g->m->g0)
+ runtime·throw("stackalloc not on scheduler stack");
+ if((n & (n-1)) != 0)
+ runtime·throw("stack size not a power of 2");
+ if(StackDebug >= 1)
+ runtime·printf("stackalloc %d\n", n);
+
+ if(runtime·debug.efence || StackFromSystem) {
+ v = runtime·sysAlloc(ROUND(n, PageSize), &mstats.stacks_sys);
+ if(v == nil)
+ runtime·throw("out of memory (stackalloc)");
+ return (Stack){(uintptr)v, (uintptr)v+n};
+ }
+
+ // 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.
+ if(StackCache && n < FixedStack << NumStackOrders && n < StackCacheSize) {
+ order = 0;
+ n2 = n;
+ while(n2 > FixedStack) {
+ order++;
+ n2 >>= 1;
+ }
+ c = g->m->mcache;
+ if(c == nil || g->m->gcing || g->m->helpgc) {
+ // 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.
+ runtime·lock(&runtime·stackpoolmu);
+ x = poolalloc(order);
+ runtime·unlock(&runtime·stackpoolmu);
+ } else {
+ x = c->stackcache[order].list;
+ if(x == nil) {
+ stackcacherefill(c, order);
+ x = c->stackcache[order].list;
+ }
+ c->stackcache[order].list = x->next;
+ c->stackcache[order].size -= n;
+ }
+ v = (byte*)x;
+ } else {
+ s = runtime·MHeap_AllocStack(&runtime·mheap, ROUND(n, PageSize) >> PageShift);
+ if(s == nil)
+ runtime·throw("out of memory");
+ v = (byte*)(s->start<<PageShift);
+ }
+
+ if(raceenabled)
+ runtime·racemalloc(v, n);
+ if(StackDebug >= 1)
+ runtime·printf(" allocated %p\n", v);
+ return (Stack){(uintptr)v, (uintptr)v+n};
+}
+
+void
+runtime·stackfree(Stack stk)
+{
+ uint8 order;
+ uintptr n, n2;
+ MSpan *s;
+ MLink *x;
+ MCache *c;
+ void *v;
+
+ n = stk.hi - stk.lo;
+ v = (void*)stk.lo;
+ if(n & (n-1))
+ runtime·throw("stack not a power of 2");
+ if(StackDebug >= 1) {
+ runtime·printf("stackfree %p %d\n", v, (int32)n);
+ runtime·memclr(v, n); // for testing, clobber stack data
+ }
+ if(runtime·debug.efence || StackFromSystem) {
+ if(runtime·debug.efence || StackFaultOnFree)
+ runtime·SysFault(v, n);
+ else
+ runtime·SysFree(v, n, &mstats.stacks_sys);
+ return;
+ }
+ if(StackCache && n < FixedStack << NumStackOrders && n < StackCacheSize) {
+ order = 0;
+ n2 = n;
+ while(n2 > FixedStack) {
+ order++;
+ n2 >>= 1;
+ }
+ x = (MLink*)v;
+ c = g->m->mcache;
+ if(c == nil || g->m->gcing || g->m->helpgc) {
+ runtime·lock(&runtime·stackpoolmu);
+ poolfree(x, order);
+ runtime·unlock(&runtime·stackpoolmu);
+ } else {
+ if(c->stackcache[order].size >= StackCacheSize)
+ stackcacherelease(c, order);
+ x->next = c->stackcache[order].list;
+ c->stackcache[order].list = x;
+ c->stackcache[order].size += n;
+ }
+ } else {
+ s = runtime·MHeap_Lookup(&runtime·mheap, v);
+ if(s->state != MSpanStack) {
+ runtime·printf("%p %p\n", s->start<<PageShift, v);
+ runtime·throw("bad span state");
+ }
+ runtime·MHeap_FreeStack(&runtime·mheap, s);
+ }
+}
+
+uintptr runtime·maxstacksize = 1<<20; // enough until runtime.main sets it for real
+
+static uint8*
+mapnames[] = {
+ (uint8*)"---",
+ (uint8*)"scalar",
+ (uint8*)"ptr",
+ (uint8*)"multi",
+};
+
+// Stack frame layout
+//
+// (x86)
+// +------------------+
+// | args from caller |
+// +------------------+ <- frame->argp
+// | return address |
+// +------------------+ <- 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
+
+void runtime·main(void);
+void runtime·switchtoM(void(*)(void));
+
+typedef struct AdjustInfo AdjustInfo;
+struct AdjustInfo {
+ Stack old;
+ uintptr delta; // 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.
+static void
+adjustpointer(AdjustInfo *adjinfo, void *vpp)
+{
+ byte **pp, *p;
+
+ pp = vpp;
+ p = *pp;
+ if(StackDebug >= 4)
+ runtime·printf(" %p:%p\n", pp, p);
+ if(adjinfo->old.lo <= (uintptr)p && (uintptr)p < adjinfo->old.hi) {
+ *pp = p + adjinfo->delta;
+ if(StackDebug >= 3)
+ runtime·printf(" adjust ptr %p: %p -> %p\n", pp, p, *pp);
+ }
+}
+
+// bv describes the memory starting at address scanp.
+// Adjust any pointers contained therein.
+static void
+adjustpointers(byte **scanp, BitVector *bv, AdjustInfo *adjinfo, Func *f)
+{
+ uintptr delta;
+ int32 num, i;
+ byte *p, *minp, *maxp;
+ Type *t;
+ Itab *tab;
+
+ minp = (byte*)adjinfo->old.lo;
+ maxp = (byte*)adjinfo->old.hi;
+ delta = adjinfo->delta;
+ num = bv->n / BitsPerPointer;
+ for(i = 0; i < num; i++) {
+ if(StackDebug >= 4)
+ runtime·printf(" %p:%s:%p\n", &scanp[i], mapnames[bv->bytedata[i / (8 / BitsPerPointer)] >> (i * BitsPerPointer & 7) & 3], scanp[i]);
+ switch(bv->bytedata[i / (8 / BitsPerPointer)] >> (i * BitsPerPointer & 7) & 3) {
+ case BitsDead:
+ if(runtime·debug.gcdead)
+ scanp[i] = (byte*)PoisonStack;
+ break;
+ case BitsScalar:
+ break;
+ case BitsPointer:
+ p = scanp[i];
+ if(f != nil && (byte*)0 < p && (p < (byte*)PageSize && runtime·invalidptr || (uintptr)p == PoisonGC || (uintptr)p == PoisonStack)) {
+ // Looks like a junk value in a pointer slot.
+ // Live analysis wrong?
+ g->m->traceback = 2;
+ runtime·printf("runtime: bad pointer in frame %s at %p: %p\n", runtime·funcname(f), &scanp[i], p);
+ runtime·throw("invalid stack pointer");
+ }
+ if(minp <= p && p < maxp) {
+ if(StackDebug >= 3)
+ runtime·printf("adjust ptr %p %s\n", p, runtime·funcname(f));
+ scanp[i] = p + delta;
+ }
+ break;
+ case BitsMultiWord:
+ switch(bv->bytedata[(i+1) / (8 / BitsPerPointer)] >> ((i+1) * BitsPerPointer & 7) & 3) {
+ default:
+ runtime·throw("unexpected garbage collection bits");
+ case BitsEface:
+ t = (Type*)scanp[i];
+ if(t != nil && ((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0)) {
+ p = scanp[i+1];
+ if(minp <= p && p < maxp) {
+ if(StackDebug >= 3)
+ runtime·printf("adjust eface %p\n", p);
+ if(t->size > PtrSize) // currently we always allocate such objects on the heap
+ runtime·throw("large interface value found on stack");
+ scanp[i+1] = p + delta;
+ }
+ }
+ i++;
+ break;
+ case BitsIface:
+ tab = (Itab*)scanp[i];
+ if(tab != nil) {
+ t = tab->type;
+ //runtime·printf(" type=%p\n", t);
+ if((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0) {
+ p = scanp[i+1];
+ if(minp <= p && p < maxp) {
+ if(StackDebug >= 3)
+ runtime·printf("adjust iface %p\n", p);
+ if(t->size > PtrSize) // currently we always allocate such objects on the heap
+ runtime·throw("large interface value found on stack");
+ scanp[i+1] = p + delta;
+ }
+ }
+ }
+ i++;
+ break;
+ }
+ break;
+ }
+ }
+}
+
+// Note: the argument/return area is adjusted by the callee.
+static bool
+adjustframe(Stkframe *frame, void *arg)
+{
+ AdjustInfo *adjinfo;
+ Func *f;
+ StackMap *stackmap;
+ int32 pcdata;
+ BitVector bv;
+ uintptr targetpc, size, minsize;
+
+ adjinfo = arg;
+ targetpc = frame->continpc;
+ if(targetpc == 0) {
+ // Frame is dead.
+ return true;
+ }
+ f = frame->fn;
+ if(StackDebug >= 2)
+ runtime·printf(" adjusting %s frame=[%p,%p] pc=%p continpc=%p\n", runtime·funcname(f), frame->sp, frame->fp, frame->pc, frame->continpc);
+ if(f->entry == (uintptr)runtime·switchtoM) {
+ // A special routine at the bottom of stack of a goroutine that does an onM 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 = runtime·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;
+ if(thechar != '6' && thechar != '8')
+ minsize = sizeof(uintptr);
+ else
+ minsize = 0;
+ if(size > minsize) {
+ stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
+ if(stackmap == nil || stackmap->n <= 0) {
+ runtime·printf("runtime: frame %s untyped locals %p+%p\n", runtime·funcname(f), (byte*)(frame->varp-size), size);
+ runtime·throw("missing stackmap");
+ }
+ // Locals bitmap information, scan just the pointers in locals.
+ if(pcdata < 0 || pcdata >= stackmap->n) {
+ // don't know where we are
+ runtime·printf("runtime: pcdata is %d and %d locals stack map entries for %s (targetpc=%p)\n",
+ pcdata, stackmap->n, runtime·funcname(f), targetpc);
+ runtime·throw("bad symbol table");
+ }
+ bv = runtime·stackmapdata(stackmap, pcdata);
+ size = (bv.n * PtrSize) / BitsPerPointer;
+ if(StackDebug >= 3)
+ runtime·printf(" locals\n");
+ adjustpointers((byte**)(frame->varp - size), &bv, adjinfo, f);
+ }
+
+ // Adjust arguments.
+ if(frame->arglen > 0) {
+ if(frame->argmap != nil) {
+ bv = *frame->argmap;
+ } else {
+ stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
+ if(stackmap == nil || stackmap->n <= 0) {
+ runtime·printf("runtime: frame %s untyped args %p+%p\n", runtime·funcname(f), frame->argp, (uintptr)frame->arglen);
+ runtime·throw("missing stackmap");
+ }
+ if(pcdata < 0 || pcdata >= stackmap->n) {
+ // don't know where we are
+ runtime·printf("runtime: pcdata is %d and %d args stack map entries for %s (targetpc=%p)\n",
+ pcdata, stackmap->n, runtime·funcname(f), targetpc);
+ runtime·throw("bad symbol table");
+ }
+ bv = runtime·stackmapdata(stackmap, pcdata);
+ }
+ if(StackDebug >= 3)
+ runtime·printf(" args\n");
+ adjustpointers((byte**)frame->argp, &bv, adjinfo, nil);
+ }
+
+ return true;
+}
+
+static void
+adjustctxt(G *gp, AdjustInfo *adjinfo)
+{
+ adjustpointer(adjinfo, &gp->sched.ctxt);
+}
+
+static void
+adjustdefers(G *gp, AdjustInfo *adjinfo)
+{
+ Defer *d;
+ bool (*cb)(Stkframe*, void*);
+
+ // Adjust defer argument blocks the same way we adjust active stack frames.
+ cb = adjustframe;
+ runtime·tracebackdefers(gp, &cb, 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, &d->fn);
+ adjustpointer(adjinfo, &d->argp);
+ adjustpointer(adjinfo, &d->panic);
+ }
+}
+
+static void
+adjustpanics(G *gp, AdjustInfo *adjinfo)
+{
+ // Panics are on stack and already adjusted.
+ // Update pointer to head of list in G.
+ adjustpointer(adjinfo, &gp->panic);
+}
+
+static void
+adjustsudogs(G *gp, AdjustInfo *adjinfo)
+{
+ SudoG *s;
+
+ // 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, &s->elem);
+ adjustpointer(adjinfo, &s->selectdone);
+ }
+}
+
+// Copies gp's stack to a new stack of a different size.
+static void
+copystack(G *gp, uintptr newsize)
+{
+ Stack old, new;
+ uintptr used;
+ AdjustInfo adjinfo;
+ uint32 oldstatus;
+ bool (*cb)(Stkframe*, void*);
+ byte *p, *ep;
+
+ if(gp->syscallsp != 0)
+ runtime·throw("stack growth not allowed in system call");
+ old = gp->stack;
+ if(old.lo == 0)
+ runtime·throw("nil stackbase");
+ used = old.hi - gp->sched.sp;
+
+ // allocate new stack
+ new = runtime·stackalloc(newsize);
+ if(StackPoisonCopy) {
+ p = (byte*)new.lo;
+ ep = (byte*)new.hi;
+ while(p < ep)
+ *p++ = 0xfd;
+ }
+
+ if(StackDebug >= 1)
+ runtime·printf("copystack gp=%p [%p %p %p]/%d -> [%p %p %p]/%d\n", gp, old.lo, old.hi-used, old.hi, (int32)(old.hi-old.lo), new.lo, new.hi-used, new.hi, (int32)newsize);
+
+ // adjust pointers in the to-be-copied frames
+ adjinfo.old = old;
+ adjinfo.delta = new.hi - old.hi;
+ cb = adjustframe;
+ runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff, &cb, &adjinfo, 0);
+
+ // adjust other miscellaneous things that have pointers into stacks.
+ adjustctxt(gp, &adjinfo);
+ adjustdefers(gp, &adjinfo);
+ adjustpanics(gp, &adjinfo);
+ adjustsudogs(gp, &adjinfo);
+
+ // copy the stack to the new location
+ if(StackPoisonCopy) {
+ p = (byte*)new.lo;
+ ep = (byte*)new.hi;
+ while(p < ep)
+ *p++ = 0xfb;
+ }
+ runtime·memmove((byte*)new.hi - used, (byte*)old.hi - used, used);
+
+ oldstatus = runtime·casgcopystack(gp); // cas from Gwaiting or Grunnable to Gcopystack, return old status
+
+ // 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;
+
+ runtime·casgstatus(gp, Gcopystack, oldstatus); // oldstatus is Gwaiting or Grunnable
+
+ // free old stack
+ if(StackPoisonCopy) {
+ p = (byte*)old.lo;
+ ep = (byte*)old.hi;
+ while(p < ep)
+ *p++ = 0xfc;
+ }
+ if(newsize > old.hi-old.lo) {
+ // growing, free stack immediately
+ runtime·stackfree(old);
+ } else {
+ // shrinking, queue up free operation. We can't actually free the stack
+ // just yet because we might run into the following situation:
+ // 1) GC starts, scans a SudoG but does not yet mark the SudoG.elem pointer
+ // 2) The stack that pointer points to is shrunk
+ // 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.
+ runtime·lock(&runtime·stackpoolmu);
+ *(Stack*)old.lo = stackfreequeue;
+ stackfreequeue = old;
+ runtime·unlock(&runtime·stackpoolmu);
+ }
+}
+
+// round x up to a power of 2.
+int32
+runtime·round2(int32 x)
+{
+ int32 s;
+
+ s = 0;
+ while((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.
+void
+runtime·newstack(void)
+{
+ int32 oldsize, newsize;
+ uintptr sp;
+ G *gp;
+ Gobuf morebuf;
+
+ if(g->m->morebuf.g->stackguard0 == (uintptr)StackFork)
+ runtime·throw("stack growth after fork");
+ if(g->m->morebuf.g != g->m->curg) {
+ runtime·printf("runtime: newstack called from g=%p\n"
+ "\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n",
+ g->m->morebuf.g, g->m, g->m->curg, g->m->g0, g->m->gsignal);
+ morebuf = g->m->morebuf;
+ runtime·traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g);
+ runtime·throw("runtime: wrong goroutine in newstack");
+ }
+ if(g->m->curg->throwsplit)
+ runtime·throw("runtime: stack split at bad time");
+
+ // The goroutine must be executing in order to call newstack,
+ // so it must be Grunning or Gscanrunning.
+
+ gp = g->m->curg;
+ morebuf = g->m->morebuf;
+ g->m->morebuf.pc = (uintptr)nil;
+ g->m->morebuf.lr = (uintptr)nil;
+ g->m->morebuf.sp = (uintptr)nil;
+ g->m->morebuf.g = (G*)nil;
+
+ runtime·casgstatus(gp, Grunning, Gwaiting);
+ gp->waitreason = runtime·gostringnocopy((byte*)"stack growth");
+
+ runtime·rewindmorestack(&gp->sched);
+
+ if(gp->stack.lo == 0)
+ runtime·throw("missing stack in newstack");
+ sp = gp->sched.sp;
+ if(thechar == '6' || thechar == '8') {
+ // The call to morestack cost a word.
+ sp -= sizeof(uintreg);
+ }
+ if(StackDebug >= 1 || sp < gp->stack.lo) {
+ runtime·printf("runtime: newstack sp=%p stack=[%p, %p]\n"
+ "\tmorebuf={pc:%p sp:%p lr:%p}\n"
+ "\tsched={pc:%p sp:%p lr:%p ctxt:%p}\n",
+ sp, gp->stack.lo, gp->stack.hi,
+ g->m->morebuf.pc, g->m->morebuf.sp, g->m->morebuf.lr,
+ gp->sched.pc, gp->sched.sp, gp->sched.lr, gp->sched.ctxt);
+ }
+ if(sp < gp->stack.lo) {
+ runtime·printf("runtime: gp=%p, gp->status=%d\n ", (void*)gp, runtime·readgstatus(gp));
+ runtime·printf("runtime: split stack overflow: %p < %p\n", sp, gp->stack.lo);
+ runtime·throw("runtime: split stack overflow");
+ }
+
+ if(gp->stackguard0 == (uintptr)StackPreempt) {
+ if(gp == g->m->g0)
+ runtime·throw("runtime: preempt g0");
+ if(g->m->p == nil && g->m->locks == 0)
+ runtime·throw("runtime: g is running but p is not");
+ if(gp->preemptscan) {
+ runtime·gcphasework(gp);
+ runtime·casgstatus(gp, Gwaiting, Grunning);
+ gp->stackguard0 = gp->stack.lo + StackGuard;
+ gp->preempt = false;
+ gp->preemptscan = false; // Tells the GC premption was successful.
+ runtime·gogo(&gp->sched); // never return
+ }
+
+ // Be conservative about where we preempt.
+ // We are interested in preempting user Go code, not runtime code.
+ if(g->m->locks || g->m->mallocing || g->m->gcing || g->m->p->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;
+ runtime·casgstatus(gp, Gwaiting, Grunning);
+ runtime·gogo(&gp->sched); // never return
+ }
+ // Act like goroutine called runtime.Gosched.
+ runtime·casgstatus(gp, Gwaiting, Grunning);
+ runtime·gosched_m(gp); // never return
+ }
+
+ // Allocate a bigger segment and move the stack.
+ oldsize = gp->stack.hi - gp->stack.lo;
+ newsize = oldsize * 2;
+ if(newsize > runtime·maxstacksize) {
+ runtime·printf("runtime: goroutine stack exceeds %D-byte limit\n", (uint64)runtime·maxstacksize);
+ runtime·throw("stack overflow");
+ }
+
+ // Note that the concurrent GC might be scanning the stack as we try to replace it.
+ // copystack takes care of the appropriate coordination with the stack scanner.
+ copystack(gp, newsize);
+ if(StackDebug >= 1)
+ runtime·printf("stack grow done\n");
+ runtime·casgstatus(gp, Gwaiting, Grunning);
+ runtime·gogo(&gp->sched);
+}
+
+#pragma textflag NOSPLIT
+void
+runtime·nilfunc(void)
+{
+ *(byte*)0 = 0;
+}
+
+// adjust Gobuf as if it executed a call to fn
+// and then did an immediate gosave.
+void
+runtime·gostartcallfn(Gobuf *gobuf, FuncVal *fv)
+{
+ void *fn;
+
+ if(fv != nil)
+ fn = fv->fn;
+ else
+ fn = runtime·nilfunc;
+ runtime·gostartcall(gobuf, fn, fv);
+}
+
+// Maybe shrink the stack being used by gp.
+// Called at garbage collection time.
+void
+runtime·shrinkstack(G *gp)
+{
+ uintptr used, oldsize, newsize;
+
+ if(runtime·readgstatus(gp) == Gdead) {
+ if(gp->stack.lo != 0) {
+ // Free whole stack - it will get reallocated
+ // if G is used again.
+ runtime·stackfree(gp->stack);
+ gp->stack.lo = 0;
+ gp->stack.hi = 0;
+ }
+ return;
+ }
+ if(gp->stack.lo == 0)
+ runtime·throw("missing stack in shrinkstack");
+
+ oldsize = gp->stack.hi - gp->stack.lo;
+ newsize = oldsize / 2;
+ if(newsize < FixedStack)
+ return; // don't shrink below the minimum-sized stack
+ used = gp->stack.hi - gp->sched.sp;
+ if(used >= oldsize / 4)
+ return; // still using at least 1/4 of the segment.
+
+ // 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;
+
+#ifdef GOOS_windows
+ if(gp->m != nil && gp->m->libcallsp != 0)
+ return;
+#endif
+ if(StackDebug > 0)
+ runtime·printf("shrinking stack %D->%D\n", (uint64)oldsize, (uint64)newsize);
+ copystack(gp, newsize);
+}
+
+// Do any delayed stack freeing that was queued up during GC.
+void
+runtime·shrinkfinish(void)
+{
+ Stack s, t;
+
+ runtime·lock(&runtime·stackpoolmu);
+ s = stackfreequeue;
+ stackfreequeue = (Stack){0,0};
+ runtime·unlock(&runtime·stackpoolmu);
+ while(s.lo != 0) {
+ t = *(Stack*)s.lo;
+ runtime·stackfree(s);
+ s = t;
+ }
+}
+
+static void badc(void);
+
+#pragma textflag NOSPLIT
+void
+runtime·morestackc(void)
+{
+ void (*fn)(void);
+
+ fn = badc;
+ runtime·onM(&fn);
+}
+
+static void
+badc(void)
+{
+ runtime·throw("attempt to execute C code on Go stack");
+}
diff --git a/src/runtime/stack.go b/src/runtime/stack.go
new file mode 100644
index 000000000..f1b7d32d2
--- /dev/null
+++ b/src/runtime/stack.go
@@ -0,0 +1,13 @@
+// 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 (
+ // Goroutine preemption request.
+ // Stored into g->stackguard0 to cause split stack check failure.
+ // Must be greater than any real sp.
+ // 0xfffffade in hex.
+ stackPreempt = ^uintptr(1313)
+)
diff --git a/src/pkg/runtime/stack.h b/src/runtime/stack.h
index 18ab30b69..f97dc4ed8 100644
--- a/src/pkg/runtime/stack.h
+++ b/src/runtime/stack.h
@@ -47,7 +47,7 @@ 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 = 128 bytes at the bottom.
+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.
*/
@@ -69,16 +69,19 @@ enum {
#endif // Plan 9
#endif // Windows
- // The amount of extra stack to allocate beyond the size
- // needed for the single frame that triggered the split.
- StackExtra = 2048,
+ // The minimum size of stack used by Go code
+ StackMin = 2048,
- // The minimum stack segment size to allocate.
- // If the amount needed for the splitting frame + StackExtra
- // is less than this number, the stack will have this size instead.
- StackMin = 8192,
- StackSystemRounded = StackSystem + (-StackSystem & (StackMin-1)),
- FixedStack = StackMin + StackSystemRounded,
+ // 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
@@ -89,7 +92,7 @@ enum {
// The stack guard is a pointer this many bytes above the
// bottom of the stack.
- StackGuard = 256 + StackSystem,
+ StackGuard = 512 + StackSystem,
// After a stack split check the SP is allowed to be this
// many bytes below the stack guard. This saves an instruction
@@ -99,11 +102,6 @@ enum {
// The maximum number of bytes that a chain of NOSPLIT
// functions can use.
StackLimit = StackGuard - StackSystem - StackSmall,
-
- // The assumed size of the top-of-stack data block.
- // The actual size can be smaller than this but cannot be larger.
- // Checked in proc.c's runtime.malg.
- StackTop = 88,
};
// Goroutine preemption request.
@@ -111,3 +109,10 @@ enum {
// Must be greater than any real sp.
// 0xfffffade in hex.
#define StackPreempt ((uint64)-1314)
+/*c2go
+enum
+{
+ StackPreempt = -1314,
+};
+*/
+#define StackFork ((uint64)-1234)
diff --git a/src/runtime/stack_test.go b/src/runtime/stack_test.go
new file mode 100644
index 000000000..652c72eee
--- /dev/null
+++ b/src/runtime/stack_test.go
@@ -0,0 +1,397 @@
+// 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_test
+
+import (
+ . "runtime"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+)
+
+// TestStackMem measures per-thread stack segment cache behavior.
+// The test consumed up to 500MB in the past.
+func TestStackMem(t *testing.T) {
+ const (
+ BatchSize = 32
+ BatchCount = 256
+ ArraySize = 1024
+ RecursionDepth = 128
+ )
+ if testing.Short() {
+ return
+ }
+ defer GOMAXPROCS(GOMAXPROCS(BatchSize))
+ s0 := new(MemStats)
+ ReadMemStats(s0)
+ for b := 0; b < BatchCount; b++ {
+ c := make(chan bool, BatchSize)
+ for i := 0; i < BatchSize; i++ {
+ go func() {
+ var f func(k int, a [ArraySize]byte)
+ f = func(k int, a [ArraySize]byte) {
+ if k == 0 {
+ time.Sleep(time.Millisecond)
+ return
+ }
+ f(k-1, a)
+ }
+ f(RecursionDepth, [ArraySize]byte{})
+ c <- true
+ }()
+ }
+ for i := 0; i < BatchSize; i++ {
+ <-c
+ }
+
+ // The goroutines have signaled via c that they are ready to exit.
+ // Give them a chance to exit by sleeping. If we don't wait, we
+ // might not reuse them on the next batch.
+ time.Sleep(10 * time.Millisecond)
+ }
+ s1 := new(MemStats)
+ ReadMemStats(s1)
+ consumed := int64(s1.StackSys - s0.StackSys)
+ t.Logf("Consumed %vMB for stack mem", consumed>>20)
+ estimate := int64(8 * BatchSize * ArraySize * RecursionDepth) // 8 is to reduce flakiness.
+ if consumed > estimate {
+ t.Fatalf("Stack mem: want %v, got %v", estimate, consumed)
+ }
+ // Due to broken stack memory accounting (http://golang.org/issue/7468),
+ // StackInuse can decrease during function execution, so we cast the values to int64.
+ inuse := int64(s1.StackInuse) - int64(s0.StackInuse)
+ t.Logf("Inuse %vMB for stack mem", inuse>>20)
+ if inuse > 4<<20 {
+ t.Fatalf("Stack inuse: want %v, got %v", 4<<20, inuse)
+ }
+}
+
+// Test stack growing in different contexts.
+func TestStackGrowth(t *testing.T) {
+ t.Parallel()
+ var wg sync.WaitGroup
+
+ // in a normal goroutine
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ growStack()
+ }()
+ wg.Wait()
+
+ // in locked goroutine
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ LockOSThread()
+ growStack()
+ UnlockOSThread()
+ }()
+ wg.Wait()
+
+ // in finalizer
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ done := make(chan bool)
+ go func() {
+ s := new(string)
+ SetFinalizer(s, func(ss *string) {
+ growStack()
+ done <- true
+ })
+ s = nil
+ done <- true
+ }()
+ <-done
+ GC()
+ select {
+ case <-done:
+ case <-time.After(20 * time.Second):
+ t.Fatal("finalizer did not run")
+ }
+ }()
+ wg.Wait()
+}
+
+// ... and in init
+//func init() {
+// growStack()
+//}
+
+func growStack() {
+ n := 1 << 10
+ if testing.Short() {
+ n = 1 << 8
+ }
+ for i := 0; i < n; i++ {
+ x := 0
+ growStackIter(&x, i)
+ if x != i+1 {
+ panic("stack is corrupted")
+ }
+ }
+ GC()
+}
+
+// This function is not an anonymous func, so that the compiler can do escape
+// analysis and place x on stack (and subsequently stack growth update the pointer).
+func growStackIter(p *int, n int) {
+ if n == 0 {
+ *p = n + 1
+ GC()
+ return
+ }
+ *p = n + 1
+ x := 0
+ growStackIter(&x, n-1)
+ if x != n {
+ panic("stack is corrupted")
+ }
+}
+
+func TestStackGrowthCallback(t *testing.T) {
+ t.Parallel()
+ var wg sync.WaitGroup
+
+ // test stack growth at chan op
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ c := make(chan int, 1)
+ growStackWithCallback(func() {
+ c <- 1
+ <-c
+ })
+ }()
+
+ // test stack growth at map op
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ m := make(map[int]int)
+ growStackWithCallback(func() {
+ _, _ = m[1]
+ m[1] = 1
+ })
+ }()
+
+ // test stack growth at goroutine creation
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ growStackWithCallback(func() {
+ done := make(chan bool)
+ go func() {
+ done <- true
+ }()
+ <-done
+ })
+ }()
+
+ wg.Wait()
+}
+
+func growStackWithCallback(cb func()) {
+ var f func(n int)
+ f = func(n int) {
+ if n == 0 {
+ cb()
+ return
+ }
+ f(n - 1)
+ }
+ for i := 0; i < 1<<10; i++ {
+ f(i)
+ }
+}
+
+// TestDeferPtrs tests the adjustment of Defer's argument pointers (p aka &y)
+// during a stack copy.
+func set(p *int, x int) {
+ *p = x
+}
+func TestDeferPtrs(t *testing.T) {
+ var y int
+
+ defer func() {
+ if y != 42 {
+ t.Errorf("defer's stack references were not adjusted appropriately")
+ }
+ }()
+ defer set(&y, 42)
+ growStack()
+}
+
+type bigBuf [4 * 1024]byte
+
+// TestDeferPtrsGoexit is like TestDeferPtrs but exercises the possibility that the
+// stack grows as part of starting the deferred function. It calls Goexit at various
+// stack depths, forcing the deferred function (with >4kB of args) to be run at
+// the bottom of the stack. The goal is to find a stack depth less than 4kB from
+// the end of the stack. Each trial runs in a different goroutine so that an earlier
+// stack growth does not invalidate a later attempt.
+func TestDeferPtrsGoexit(t *testing.T) {
+ for i := 0; i < 100; i++ {
+ c := make(chan int, 1)
+ go testDeferPtrsGoexit(c, i)
+ if n := <-c; n != 42 {
+ t.Fatalf("defer's stack references were not adjusted appropriately (i=%d n=%d)", i, n)
+ }
+ }
+}
+
+func testDeferPtrsGoexit(c chan int, i int) {
+ var y int
+ defer func() {
+ c <- y
+ }()
+ defer setBig(&y, 42, bigBuf{})
+ useStackAndCall(i, Goexit)
+}
+
+func setBig(p *int, x int, b bigBuf) {
+ *p = x
+}
+
+// TestDeferPtrsPanic is like TestDeferPtrsGoexit, but it's using panic instead
+// of Goexit to run the Defers. Those two are different execution paths
+// in the runtime.
+func TestDeferPtrsPanic(t *testing.T) {
+ for i := 0; i < 100; i++ {
+ c := make(chan int, 1)
+ go testDeferPtrsGoexit(c, i)
+ if n := <-c; n != 42 {
+ t.Fatalf("defer's stack references were not adjusted appropriately (i=%d n=%d)", i, n)
+ }
+ }
+}
+
+func testDeferPtrsPanic(c chan int, i int) {
+ var y int
+ defer func() {
+ if recover() == nil {
+ c <- -1
+ return
+ }
+ c <- y
+ }()
+ defer setBig(&y, 42, bigBuf{})
+ useStackAndCall(i, func() { panic(1) })
+}
+
+// TestPanicUseStack checks that a chain of Panic structs on the stack are
+// updated correctly if the stack grows during the deferred execution that
+// happens as a result of the panic.
+func TestPanicUseStack(t *testing.T) {
+ pc := make([]uintptr, 10000)
+ defer func() {
+ recover()
+ Callers(0, pc) // force stack walk
+ useStackAndCall(100, func() {
+ defer func() {
+ recover()
+ Callers(0, pc) // force stack walk
+ useStackAndCall(200, func() {
+ defer func() {
+ recover()
+ Callers(0, pc) // force stack walk
+ }()
+ panic(3)
+ })
+ }()
+ panic(2)
+ })
+ }()
+ panic(1)
+}
+
+// use about n KB of stack and call f
+func useStackAndCall(n int, f func()) {
+ if n == 0 {
+ f()
+ return
+ }
+ var b [1024]byte // makes frame about 1KB
+ useStackAndCall(n-1+int(b[99]), f)
+}
+
+func useStack(n int) {
+ useStackAndCall(n, func() {})
+}
+
+func growing(c chan int, done chan struct{}) {
+ for n := range c {
+ useStack(n)
+ done <- struct{}{}
+ }
+ done <- struct{}{}
+}
+
+func TestStackCache(t *testing.T) {
+ // Allocate a bunch of goroutines and grow their stacks.
+ // Repeat a few times to test the stack cache.
+ const (
+ R = 4
+ G = 200
+ S = 5
+ )
+ for i := 0; i < R; i++ {
+ var reqchans [G]chan int
+ done := make(chan struct{})
+ for j := 0; j < G; j++ {
+ reqchans[j] = make(chan int)
+ go growing(reqchans[j], done)
+ }
+ for s := 0; s < S; s++ {
+ for j := 0; j < G; j++ {
+ reqchans[j] <- 1 << uint(s)
+ }
+ for j := 0; j < G; j++ {
+ <-done
+ }
+ }
+ for j := 0; j < G; j++ {
+ close(reqchans[j])
+ }
+ for j := 0; j < G; j++ {
+ <-done
+ }
+ }
+}
+
+func TestStackOutput(t *testing.T) {
+ b := make([]byte, 1024)
+ stk := string(b[:Stack(b, false)])
+ if !strings.HasPrefix(stk, "goroutine ") {
+ t.Errorf("Stack (len %d):\n%s", len(stk), stk)
+ t.Errorf("Stack output should begin with \"goroutine \"")
+ }
+}
+
+func TestStackAllOutput(t *testing.T) {
+ b := make([]byte, 1024)
+ stk := string(b[:Stack(b, true)])
+ if !strings.HasPrefix(stk, "goroutine ") {
+ t.Errorf("Stack (len %d):\n%s", len(stk), stk)
+ t.Errorf("Stack output should begin with \"goroutine \"")
+ }
+}
+
+func TestStackPanic(t *testing.T) {
+ // Test that stack copying copies panics correctly. This is difficult
+ // to test because it is very unlikely that the stack will be copied
+ // in the middle of gopanic. But it can happen.
+ // To make this test effective, edit panic.go:gopanic and uncomment
+ // the GC() call just before freedefer(d).
+ defer func() {
+ if x := recover(); x == nil {
+ t.Errorf("recover failed")
+ }
+ }()
+ useStack(32)
+ panic("test panic")
+}
diff --git a/src/runtime/string.c b/src/runtime/string.c
new file mode 100644
index 000000000..ed5debc33
--- /dev/null
+++ b/src/runtime/string.c
@@ -0,0 +1,226 @@
+// 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.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
+#include "race.h"
+#include "textflag.h"
+
+String runtime·emptystring;
+
+#pragma textflag NOSPLIT
+intgo
+runtime·findnull(byte *s)
+{
+ intgo l;
+
+ if(s == nil)
+ return 0;
+ for(l=0; s[l]!=0; l++)
+ ;
+ return l;
+}
+
+intgo
+runtime·findnullw(uint16 *s)
+{
+ intgo l;
+
+ if(s == nil)
+ return 0;
+ for(l=0; s[l]!=0; l++)
+ ;
+ return l;
+}
+
+uintptr runtime·maxstring = 256; // a hint for print
+
+#pragma textflag NOSPLIT
+String
+runtime·gostringnocopy(byte *str)
+{
+ String s;
+ uintptr ms;
+
+ s.str = str;
+ s.len = runtime·findnull(str);
+ while(true) {
+ ms = runtime·maxstring;
+ if(s.len <= ms || runtime·casp((void**)&runtime·maxstring, (void*)ms, (void*)s.len))
+ return s;
+ }
+}
+
+// TODO: move this elsewhere
+enum
+{
+ Bit1 = 7,
+ Bitx = 6,
+ Bit2 = 5,
+ Bit3 = 4,
+ Bit4 = 3,
+ Bit5 = 2,
+
+ Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */
+ T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */
+ T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */
+ T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */
+
+ Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */
+ Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */
+ Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */
+
+ Maskx = (1<<Bitx)-1, /* 0011 1111 */
+
+ Runeerror = 0xFFFD,
+
+ SurrogateMin = 0xD800,
+ SurrogateMax = 0xDFFF,
+
+ Runemax = 0x10FFFF, /* maximum rune value */
+};
+
+static int32
+runetochar(byte *str, int32 rune) /* note: in original, arg2 was pointer */
+{
+ /* Runes are signed, so convert to unsigned for range check. */
+ uint32 c;
+
+ /*
+ * one character sequence
+ * 00000-0007F => 00-7F
+ */
+ c = rune;
+ if(c <= Rune1) {
+ str[0] = c;
+ return 1;
+ }
+
+ /*
+ * two character sequence
+ * 0080-07FF => T2 Tx
+ */
+ if(c <= Rune2) {
+ str[0] = T2 | (c >> 1*Bitx);
+ str[1] = Tx | (c & Maskx);
+ return 2;
+ }
+
+ /*
+ * If the Rune is out of range or a surrogate half, convert it to the error rune.
+ * Do this test here because the error rune encodes to three bytes.
+ * Doing it earlier would duplicate work, since an out of range
+ * Rune wouldn't have fit in one or two bytes.
+ */
+ if (c > Runemax)
+ c = Runeerror;
+ if (SurrogateMin <= c && c <= SurrogateMax)
+ c = Runeerror;
+
+ /*
+ * three character sequence
+ * 0800-FFFF => T3 Tx Tx
+ */
+ if (c <= Rune3) {
+ str[0] = T3 | (c >> 2*Bitx);
+ str[1] = Tx | ((c >> 1*Bitx) & Maskx);
+ str[2] = Tx | (c & Maskx);
+ return 3;
+ }
+
+ /*
+ * four character sequence (21-bit value)
+ * 10000-1FFFFF => T4 Tx Tx Tx
+ */
+ str[0] = T4 | (c >> 3*Bitx);
+ str[1] = Tx | ((c >> 2*Bitx) & Maskx);
+ str[2] = Tx | ((c >> 1*Bitx) & Maskx);
+ str[3] = Tx | (c & Maskx);
+ return 4;
+}
+
+String runtime·gostringsize(intgo);
+
+String
+runtime·gostringw(uint16 *str)
+{
+ intgo n1, n2, i;
+ byte buf[8];
+ String s;
+
+ n1 = 0;
+ for(i=0; str[i]; i++)
+ n1 += runetochar(buf, str[i]);
+ s = runtime·gostringsize(n1+4);
+ n2 = 0;
+ for(i=0; str[i]; i++) {
+ // check for race
+ if(n2 >= n1)
+ break;
+ n2 += runetochar(s.str+n2, str[i]);
+ }
+ s.len = n2;
+ s.str[s.len] = 0;
+ return s;
+}
+
+int32
+runtime·strcmp(byte *s1, byte *s2)
+{
+ uintptr i;
+ byte c1, c2;
+
+ for(i=0;; i++) {
+ c1 = s1[i];
+ c2 = s2[i];
+ if(c1 < c2)
+ return -1;
+ if(c1 > c2)
+ return +1;
+ if(c1 == 0)
+ return 0;
+ }
+}
+
+int32
+runtime·strncmp(byte *s1, byte *s2, uintptr n)
+{
+ uintptr i;
+ byte c1, c2;
+
+ for(i=0; i<n; i++) {
+ c1 = s1[i];
+ c2 = s2[i];
+ if(c1 < c2)
+ return -1;
+ if(c1 > c2)
+ return +1;
+ if(c1 == 0)
+ break;
+ }
+ return 0;
+}
+
+byte*
+runtime·strstr(byte *s1, byte *s2)
+{
+ byte *sp1, *sp2;
+
+ if(*s2 == 0)
+ return s1;
+ for(; *s1; s1++) {
+ if(*s1 != *s2)
+ continue;
+ sp1 = s1;
+ sp2 = s2;
+ for(;;) {
+ if(*sp2 == 0)
+ return s1;
+ if(*sp1++ != *sp2++)
+ break;
+ }
+ }
+ return nil;
+}
diff --git a/src/runtime/string.go b/src/runtime/string.go
new file mode 100644
index 000000000..0809f89bc
--- /dev/null
+++ b/src/runtime/string.go
@@ -0,0 +1,298 @@
+// 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"
+)
+
+func concatstrings(a []string) string {
+ idx := 0
+ l := 0
+ count := 0
+ for i, x := range a {
+ n := len(x)
+ if n == 0 {
+ continue
+ }
+ if l+n < l {
+ gothrow("string concatenation too long")
+ }
+ l += n
+ count++
+ idx = i
+ }
+ if count == 0 {
+ return ""
+ }
+ if count == 1 {
+ return a[idx]
+ }
+ s, b := rawstring(l)
+ l = 0
+ for _, x := range a {
+ copy(b[l:], x)
+ l += len(x)
+ }
+ return s
+}
+
+//go:nosplit
+func concatstring2(a [2]string) string {
+ return concatstrings(a[:])
+}
+
+//go:nosplit
+func concatstring3(a [3]string) string {
+ return concatstrings(a[:])
+}
+
+//go:nosplit
+func concatstring4(a [4]string) string {
+ return concatstrings(a[:])
+}
+
+//go:nosplit
+func concatstring5(a [5]string) string {
+ return concatstrings(a[:])
+}
+
+func slicebytetostring(b []byte) string {
+ if raceenabled && len(b) > 0 {
+ racereadrangepc(unsafe.Pointer(&b[0]),
+ uintptr(len(b)),
+ getcallerpc(unsafe.Pointer(&b)),
+ funcPC(slicebytetostring))
+ }
+ s, c := rawstring(len(b))
+ copy(c, b)
+ return s
+}
+
+func slicebytetostringtmp(b []byte) string {
+ // Return a "string" referring to the actual []byte bytes.
+ // This is only for use by internal compiler optimizations
+ // that know that the string form will be discarded before
+ // the calling goroutine could possibly modify the original
+ // slice or synchronize with another goroutine.
+ // Today, the only such case is a m[string(k)] lookup where
+ // m is a string-keyed map and k is a []byte.
+
+ if raceenabled && len(b) > 0 {
+ racereadrangepc(unsafe.Pointer(&b[0]),
+ uintptr(len(b)),
+ getcallerpc(unsafe.Pointer(&b)),
+ funcPC(slicebytetostringtmp))
+ }
+ return *(*string)(unsafe.Pointer(&b))
+}
+
+func stringtoslicebyte(s string) []byte {
+ b := rawbyteslice(len(s))
+ copy(b, s)
+ return b
+}
+
+func stringtoslicerune(s string) []rune {
+ // two passes.
+ // unlike slicerunetostring, no race because strings are immutable.
+ n := 0
+ t := s
+ for len(s) > 0 {
+ _, k := charntorune(s)
+ s = s[k:]
+ n++
+ }
+ a := rawruneslice(n)
+ n = 0
+ for len(t) > 0 {
+ r, k := charntorune(t)
+ t = t[k:]
+ a[n] = r
+ n++
+ }
+ return a
+}
+
+func slicerunetostring(a []rune) string {
+ if raceenabled && len(a) > 0 {
+ racereadrangepc(unsafe.Pointer(&a[0]),
+ uintptr(len(a))*unsafe.Sizeof(a[0]),
+ getcallerpc(unsafe.Pointer(&a)),
+ funcPC(slicerunetostring))
+ }
+ var dum [4]byte
+ size1 := 0
+ for _, r := range a {
+ size1 += runetochar(dum[:], r)
+ }
+ s, b := rawstring(size1 + 3)
+ size2 := 0
+ for _, r := range a {
+ // check for race
+ if size2 >= size1 {
+ break
+ }
+ size2 += runetochar(b[size2:], r)
+ }
+ return s[:size2]
+}
+
+type stringStruct struct {
+ str unsafe.Pointer
+ len int
+}
+
+func intstring(v int64) string {
+ s, b := rawstring(4)
+ n := runetochar(b, rune(v))
+ return s[:n]
+}
+
+// stringiter returns the index of the next
+// rune after the rune that starts at s[k].
+func stringiter(s string, k int) int {
+ if k >= len(s) {
+ // 0 is end of iteration
+ return 0
+ }
+
+ c := s[k]
+ if c < runeself {
+ return k + 1
+ }
+
+ // multi-char rune
+ _, n := charntorune(s[k:])
+ return k + n
+}
+
+// stringiter2 returns the rune that starts at s[k]
+// and the index where the next rune starts.
+func stringiter2(s string, k int) (int, rune) {
+ if k >= len(s) {
+ // 0 is end of iteration
+ return 0, 0
+ }
+
+ c := s[k]
+ if c < runeself {
+ return k + 1, rune(c)
+ }
+
+ // multi-char rune
+ r, n := charntorune(s[k:])
+ return k + n, r
+}
+
+// rawstring allocates storage for a new string. The returned
+// string and byte slice both refer to the same storage.
+// The storage is not zeroed. Callers should use
+// b to set the string contents and then drop b.
+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
+
+ (*slice)(unsafe.Pointer(&b)).array = (*uint8)(p)
+ (*slice)(unsafe.Pointer(&b)).len = uint(size)
+ (*slice)(unsafe.Pointer(&b)).cap = uint(size)
+
+ for {
+ ms := maxstring
+ if uintptr(size) <= uintptr(ms) || casuintptr((*uintptr)(unsafe.Pointer(&maxstring)), uintptr(ms), uintptr(size)) {
+ return
+ }
+ }
+}
+
+// rawbyteslice allocates a new byte slice. The byte slice is not zeroed.
+func rawbyteslice(size int) (b []byte) {
+ cap := goroundupsize(uintptr(size))
+ p := mallocgc(cap, nil, flagNoScan|flagNoZero)
+ if cap != uintptr(size) {
+ memclr(add(p, uintptr(size)), cap-uintptr(size))
+ }
+
+ (*slice)(unsafe.Pointer(&b)).array = (*uint8)(p)
+ (*slice)(unsafe.Pointer(&b)).len = uint(size)
+ (*slice)(unsafe.Pointer(&b)).cap = uint(cap)
+ return
+}
+
+// rawruneslice allocates a new rune slice. The rune slice is not zeroed.
+func rawruneslice(size int) (b []rune) {
+ if uintptr(size) > maxmem/4 {
+ gothrow("out of memory")
+ }
+ mem := goroundupsize(uintptr(size) * 4)
+ p := mallocgc(mem, nil, flagNoScan|flagNoZero)
+ if mem != uintptr(size)*4 {
+ memclr(add(p, uintptr(size)*4), mem-uintptr(size)*4)
+ }
+
+ (*slice)(unsafe.Pointer(&b)).array = (*uint8)(p)
+ (*slice)(unsafe.Pointer(&b)).len = uint(size)
+ (*slice)(unsafe.Pointer(&b)).cap = uint(mem / 4)
+ return
+}
+
+// used by cmd/cgo
+func gobytes(p *byte, n int) []byte {
+ if n == 0 {
+ return make([]byte, 0)
+ }
+ x := make([]byte, n)
+ memmove(unsafe.Pointer(&x[0]), unsafe.Pointer(p), uintptr(n))
+ return x
+}
+
+func gostringsize(n int) string {
+ s, _ := rawstring(n)
+ return s
+}
+
+//go:noescape
+func findnull(*byte) int
+
+func gostring(p *byte) string {
+ l := findnull(p)
+ if l == 0 {
+ return ""
+ }
+ s, b := rawstring(l)
+ memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l))
+ return s
+}
+
+func gostringn(p *byte, l int) string {
+ if l == 0 {
+ return ""
+ }
+ s, b := rawstring(l)
+ memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l))
+ return s
+}
+
+func index(s, t string) int {
+ if len(t) == 0 {
+ return 0
+ }
+ for i := 0; i < len(s); i++ {
+ if s[i] == t[0] && hasprefix(s[i:], t) {
+ return i
+ }
+ }
+ return -1
+}
+
+func contains(s, t string) bool {
+ return index(s, t) >= 0
+}
+
+func hasprefix(s, t string) bool {
+ return len(s) >= len(t) && s[:len(t)] == t
+}
diff --git a/src/runtime/string_test.go b/src/runtime/string_test.go
new file mode 100644
index 000000000..1551ecc82
--- /dev/null
+++ b/src/runtime/string_test.go
@@ -0,0 +1,160 @@
+// 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_test
+
+import (
+ "runtime"
+ "strings"
+ "testing"
+)
+
+func BenchmarkCompareStringEqual(b *testing.B) {
+ bytes := []byte("Hello Gophers!")
+ s1, s2 := string(bytes), string(bytes)
+ for i := 0; i < b.N; i++ {
+ if s1 != s2 {
+ b.Fatal("s1 != s2")
+ }
+ }
+}
+
+func BenchmarkCompareStringIdentical(b *testing.B) {
+ s1 := "Hello Gophers!"
+ s2 := s1
+ for i := 0; i < b.N; i++ {
+ if s1 != s2 {
+ b.Fatal("s1 != s2")
+ }
+ }
+}
+
+func BenchmarkCompareStringSameLength(b *testing.B) {
+ s1 := "Hello Gophers!"
+ s2 := "Hello, Gophers"
+ for i := 0; i < b.N; i++ {
+ if s1 == s2 {
+ b.Fatal("s1 == s2")
+ }
+ }
+}
+
+func BenchmarkCompareStringDifferentLength(b *testing.B) {
+ s1 := "Hello Gophers!"
+ s2 := "Hello, Gophers!"
+ for i := 0; i < b.N; i++ {
+ if s1 == s2 {
+ b.Fatal("s1 == s2")
+ }
+ }
+}
+
+func BenchmarkCompareStringBigUnaligned(b *testing.B) {
+ bytes := make([]byte, 0, 1<<20)
+ for len(bytes) < 1<<20 {
+ bytes = append(bytes, "Hello Gophers!"...)
+ }
+ s1, s2 := string(bytes), "hello"+string(bytes)
+ for i := 0; i < b.N; i++ {
+ if s1 != s2[len("hello"):] {
+ b.Fatal("s1 != s2")
+ }
+ }
+ b.SetBytes(int64(len(s1)))
+}
+
+func BenchmarkCompareStringBig(b *testing.B) {
+ bytes := make([]byte, 0, 1<<20)
+ for len(bytes) < 1<<20 {
+ bytes = append(bytes, "Hello Gophers!"...)
+ }
+ s1, s2 := string(bytes), string(bytes)
+ for i := 0; i < b.N; i++ {
+ if s1 != s2 {
+ b.Fatal("s1 != s2")
+ }
+ }
+ b.SetBytes(int64(len(s1)))
+}
+
+func BenchmarkRuneIterate(b *testing.B) {
+ bytes := make([]byte, 100)
+ for i := range bytes {
+ bytes[i] = byte('A')
+ }
+ s := string(bytes)
+ for i := 0; i < b.N; i++ {
+ for range s {
+ }
+ }
+}
+
+func BenchmarkRuneIterate2(b *testing.B) {
+ bytes := make([]byte, 100)
+ for i := range bytes {
+ bytes[i] = byte('A')
+ }
+ s := string(bytes)
+ for i := 0; i < b.N; i++ {
+ for range s {
+ }
+ }
+}
+
+func TestStringW(t *testing.T) {
+ strings := []string{
+ "hello",
+ "a\u5566\u7788b",
+ }
+
+ for _, s := range strings {
+ var b []uint16
+ for _, c := range s {
+ b = append(b, uint16(c))
+ if c != rune(uint16(c)) {
+ t.Errorf("bad test: stringW can't handle >16 bit runes")
+ }
+ }
+ b = append(b, 0)
+ r := runtime.GostringW(b)
+ if r != s {
+ t.Errorf("gostringW(%v) = %s, want %s", b, r, s)
+ }
+ }
+}
+
+func TestLargeStringConcat(t *testing.T) {
+ output := executeTest(t, largeStringConcatSource, nil)
+ 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) {
+ t.Fatalf("output does not start with %q:\n%s", want, output)
+ }
+}
+
+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)
+ for i := uintptr(0); i < max+9; i++ {
+ b[i] = 'a'
+ }
+ _ = runtime.Gostringnocopy(&b[0])
+ newmax := *runtime.Maxstring
+ if newmax != max+9 {
+ t.Errorf("want %d, got %d", max+9, newmax)
+ }
+}
diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go
new file mode 100644
index 000000000..fe8f9c922
--- /dev/null
+++ b/src/runtime/stubs.go
@@ -0,0 +1,316 @@
+// 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"
+
+// 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
+
+// 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)
+}
+
+// n must be a power of 2
+func roundup(p unsafe.Pointer, n uintptr) unsafe.Pointer {
+ delta := -uintptr(p) & (n - 1)
+ return unsafe.Pointer(uintptr(p) + delta)
+}
+
+// in runtime.c
+func getg() *g
+func acquirem() *m
+func releasem(mp *m)
+func gomcache() *mcache
+func readgstatus(*g) uint32 // proc.c
+
+// mcall switches from the g to the g0 stack and invokes fn(g),
+// where g is the goroutine that made the call.
+// mcall saves g's current PC/SP in g->sched so that it can be restored later.
+// It is up to fn to arrange for that later execution, typically by recording
+// g in a data structure, causing something to call ready(g) later.
+// mcall returns to the original goroutine g later, when g has been rescheduled.
+// fn must not return at all; typically it ends by calling schedule, to let the m
+// run other goroutines.
+//
+// mcall can only be called from g stacks (not g0, not gsignal).
+//go:noescape
+func mcall(fn func(*g))
+
+// onM switches from the g to the g0 stack and invokes fn().
+// When fn returns, onM switches back to the g and returns,
+// continuing execution on the g stack.
+// If arguments must be passed to fn, they can be written to
+// g->m->ptrarg (pointers) and g->m->scalararg (non-pointers)
+// before the call and then consulted during fn.
+// Similarly, fn can pass return values back in those locations.
+// If fn is written in Go, it can be a closure, which avoids the need for
+// ptrarg and scalararg entirely.
+// After reading values out of ptrarg and scalararg it is conventional
+// to zero them to avoid (memory or information) leaks.
+//
+// If onM is called from a g0 stack, it invokes fn and returns,
+// without any stack switches.
+//
+// If onM is called from a gsignal stack, it crashes the program.
+// The implication is that functions used in signal handlers must
+// not use onM.
+//
+// NOTE(rsc): We could introduce a separate onMsignal that is
+// like onM but if called from a gsignal stack would just run fn on
+// that stack. The caller of onMsignal would be required to save the
+// old values of ptrarg/scalararg and restore them when the call
+// was finished, in case the signal interrupted an onM sequence
+// in progress on the g or g0 stacks. Until there is a clear need for this,
+// we just reject onM in signal handling contexts entirely.
+//
+//go:noescape
+func onM(fn func())
+
+// onMsignal is like onM but is allowed to be used in code that
+// might run on the gsignal stack. Code running on a signal stack
+// may be interrupting an onM sequence on the main stack, so
+// if the onMsignal calling sequence writes to ptrarg/scalararg,
+// it must first save the old values and then restore them when
+// finished. As an exception to the rule, it is fine not to save and
+// restore the values if the program is trying to crash rather than
+// return from the signal handler.
+// Once all the runtime is written in Go, there will be no ptrarg/scalararg
+// and the distinction between onM and onMsignal (and perhaps mcall)
+// can go away.
+//
+// If onMsignal is called from a gsignal stack, it invokes fn directly,
+// without a stack switch. Otherwise onMsignal behaves like onM.
+//
+//go:noescape
+func onM_signalok(fn func())
+
+func badonm() {
+ gothrow("onM called from signal goroutine")
+}
+
+// C functions that run on the M stack.
+// Call using mcall.
+func gosched_m(*g)
+func park_m(*g)
+func recovery_m(*g)
+
+// More C functions that run on the M stack.
+// Call using onM.
+func mcacheRefill_m()
+func largeAlloc_m()
+func gc_m()
+func scavenge_m()
+func setFinalizer_m()
+func removeFinalizer_m()
+func markallocated_m()
+func unrollgcprog_m()
+func unrollgcproginplace_m()
+func setgcpercent_m()
+func setmaxthreads_m()
+func ready_m()
+func deferproc_m()
+func goexit_m()
+func startpanic_m()
+func dopanic_m()
+func readmemstats_m()
+func writeheapdump_m()
+
+// memclr clears n bytes starting at ptr.
+// in memclr_*.s
+//go:noescape
+func memclr(ptr unsafe.Pointer, n uintptr)
+
+// memmove copies n bytes from "from" to "to".
+// in memmove_*.s
+//go:noescape
+func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
+
+func starttheworld()
+func stoptheworld()
+func newextram()
+func lockOSThread()
+func unlockOSThread()
+
+// exported value for testing
+var hashLoad = loadFactor
+
+// in asm_*.s
+func fastrand1() uint32
+
+// in asm_*.s
+//go:noescape
+func memeq(a, b unsafe.Pointer, size uintptr) bool
+
+// noescape hides a pointer from escape analysis. noescape is
+// the identity function but escape analysis doesn't think the
+// output depends on the input. noescape is inlined and currently
+// compiles down to a single xor instruction.
+// USE CAREFULLY!
+//go:nosplit
+func noescape(p unsafe.Pointer) unsafe.Pointer {
+ x := uintptr(p)
+ return unsafe.Pointer(x ^ 0)
+}
+
+func entersyscall()
+func reentersyscall(pc uintptr, sp unsafe.Pointer)
+func entersyscallblock()
+func exitsyscall()
+
+func cgocallback(fn, frame unsafe.Pointer, framesize uintptr)
+func gogo(buf *gobuf)
+func gosave(buf *gobuf)
+func read(fd int32, p unsafe.Pointer, n int32) int32
+func close(fd int32) int32
+func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32
+
+//go:noescape
+func jmpdefer(fv *funcval, argp uintptr)
+func exit1(code int32)
+func asminit()
+func setg(gg *g)
+func exit(code int32)
+func breakpoint()
+func nanotime() int64
+func usleep(usec uint32)
+
+// careful: cputicks is not guaranteed to be monotonic! In particular, we have
+// noticed drift between cpus on certain os/arch combinations. See issue 8976.
+func cputicks() int64
+
+func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
+func munmap(addr unsafe.Pointer, n uintptr)
+func madvise(addr unsafe.Pointer, n uintptr, flags int32)
+func reflectcall(fn, arg unsafe.Pointer, n uint32, retoffset uint32)
+func osyield()
+func procyield(cycles uint32)
+func cgocallback_gofunc(fv *funcval, frame unsafe.Pointer, framesize uintptr)
+func readgogc() int32
+func purgecachedstats(c *mcache)
+func gostringnocopy(b *byte) string
+func goexit()
+
+//go:noescape
+func write(fd uintptr, p unsafe.Pointer, n int32) int32
+
+//go:noescape
+func cas(ptr *uint32, old, new uint32) bool
+
+//go:noescape
+func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool
+
+//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
+
+//go:noescape
+func setcallerpc(argp unsafe.Pointer, pc uintptr)
+
+// getcallerpc returns the program counter (PC) of its caller's caller.
+// getcallersp returns the stack pointer (SP) of its caller's caller.
+// For both, the argp must be a pointer to the caller's first function argument.
+// The implementation may or may not use argp, depending on
+// the architecture.
+//
+// For example:
+//
+// func f(arg1, arg2, arg3 int) {
+// pc := getcallerpc(unsafe.Pointer(&arg1))
+// sp := getcallerpc(unsafe.Pointer(&arg2))
+// }
+//
+// These two lines find the PC and SP immediately following
+// the call to f (where f will return).
+//
+// The call to getcallerpc and getcallersp must be done in the
+// frame being asked about. It would not be correct for f to pass &arg1
+// to another function g and let g call getcallerpc/getcallersp.
+// The call inside g might return information about g's caller or
+// information about f's caller or complete garbage.
+//
+// The result of getcallersp is correct at the time of the return,
+// but it may be invalidated by any subsequent call to a function
+// that might relocate the stack in order to grow or shrink it.
+// A general rule is that the result of getcallersp should be used
+// immediately and can only be passed to nosplit functions.
+
+//go:noescape
+func getcallerpc(argp unsafe.Pointer) uintptr
+
+//go:noescape
+func getcallersp(argp unsafe.Pointer) uintptr
+
+//go:noescape
+func asmcgocall(fn, arg unsafe.Pointer)
+
+//go:noescape
+func asmcgocall_errno(fn, arg unsafe.Pointer) int32
+
+//go:noescape
+func open(name *byte, mode, perm int32) int32
+
+//go:noescape
+func gotraceback(*bool) int32
+
+const _NoArgs = ^uintptr(0)
+
+func newstack()
+func newproc()
+func morestack()
+func mstart()
+func rt0_go()
+
+// return0 is a stub used to return 0 from deferproc.
+// It is called at the very end of deferproc to signal
+// the calling Go function that it should not jump
+// to deferreturn.
+// in asm_*.s
+func return0()
+
+// thunk to call time.now.
+func timenow() (sec int64, nsec int32)
+
+// in asm_*.s
+// not called directly; definitions here supply type information for traceback.
+func call16(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call32(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call64(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call128(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call256(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call512(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call1024(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call2048(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call4096(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call8192(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call16384(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call32768(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call65536(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call131072(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call262144(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call524288(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call1048576(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call2097152(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call4194304(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call8388608(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call16777216(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call33554432(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call67108864(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call134217728(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call268435456(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call536870912(fn, arg unsafe.Pointer, n, retoffset uint32)
+func call1073741824(fn, arg unsafe.Pointer, n, retoffset uint32)
diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go
new file mode 100644
index 000000000..45d107b77
--- /dev/null
+++ b/src/runtime/symtab.go
@@ -0,0 +1,288 @@
+// 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"
+
+// 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
+// with (say) *f = Func{}.
+// All code operating on a *Func must call raw to get the *_func instead.
+
+// A Func represents a Go function in the running binary.
+type Func struct {
+ opaque struct{} // unexported field to disallow conversions
+}
+
+func (f *Func) raw() *_func {
+ return (*_func)(unsafe.Pointer(f))
+}
+
+// funcdata.h
+const (
+ _PCDATA_ArgSize = 0
+ _PCDATA_StackMapIndex = 1
+ _FUNCDATA_ArgsPointerMaps = 0
+ _FUNCDATA_LocalsPointerMaps = 1
+ _FUNCDATA_DeadValueMaps = 2
+ _ArgsSizeUnknown = -0x80000000
+)
+
+var (
+ pclntable []byte
+ ftab []functab
+ filetab []uint32
+
+ pclntab, epclntab struct{} // linker symbols
+)
+
+type functab struct {
+ entry uintptr
+ funcoff uintptr
+}
+
+func symtabinit() {
+ // See golang.org/s/go12symtab for header: 0xfffffffb,
+ // two zero bytes, a byte giving the PC quantum,
+ // and a byte giving the pointer width in bytes.
+ pcln := (*[8]byte)(unsafe.Pointer(&pclntab))
+ pcln32 := (*[2]uint32)(unsafe.Pointer(&pclntab))
+ if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != _PCQuantum || pcln[7] != ptrSize {
+ println("runtime: function symbol table header:", hex(pcln32[0]), hex(pcln[4]), hex(pcln[5]), hex(pcln[6]), hex(pcln[7]))
+ gothrow("invalid function symbol table\n")
+ }
+
+ // pclntable is all bytes of pclntab symbol.
+ sp := (*sliceStruct)(unsafe.Pointer(&pclntable))
+ sp.array = unsafe.Pointer(&pclntab)
+ sp.len = int(uintptr(unsafe.Pointer(&epclntab)) - uintptr(unsafe.Pointer(&pclntab)))
+ sp.cap = sp.len
+
+ // ftab is lookup table for function by program counter.
+ nftab := int(*(*uintptr)(add(unsafe.Pointer(pcln), 8)))
+ p := add(unsafe.Pointer(pcln), 8+ptrSize)
+ sp = (*sliceStruct)(unsafe.Pointer(&ftab))
+ sp.array = p
+ sp.len = nftab + 1
+ sp.cap = sp.len
+ for i := 0; i < nftab; i++ {
+ // NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
+ if ftab[i].entry > ftab[i+1].entry {
+ f1 := (*_func)(unsafe.Pointer(&pclntable[ftab[i].funcoff]))
+ f2 := (*_func)(unsafe.Pointer(&pclntable[ftab[i+1].funcoff]))
+ f2name := "end"
+ if i+1 < nftab {
+ f2name = gofuncname(f2)
+ }
+ println("function symbol table not sorted by program counter:", hex(ftab[i].entry), gofuncname(f1), ">", hex(ftab[i+1].entry), f2name)
+ for j := 0; j <= i; j++ {
+ print("\t", hex(ftab[j].entry), " ", gofuncname((*_func)(unsafe.Pointer(&pclntable[ftab[j].funcoff]))))
+ }
+ gothrow("invalid runtime symbol table")
+ }
+ }
+
+ // The ftab ends with a half functab consisting only of
+ // 'entry', followed by a uint32 giving the pcln-relative
+ // offset of the file table.
+ sp = (*sliceStruct)(unsafe.Pointer(&filetab))
+ end := unsafe.Pointer(&ftab[nftab].funcoff) // just beyond ftab
+ fileoffset := *(*uint32)(end)
+ sp.array = unsafe.Pointer(&pclntable[fileoffset])
+ // length is in first element of array.
+ // set len to 1 so we can get first element.
+ sp.len = 1
+ sp.cap = 1
+ sp.len = int(filetab[0])
+ sp.cap = sp.len
+}
+
+// FuncForPC returns a *Func describing the function that contains the
+// given program counter address, or else nil.
+func FuncForPC(pc uintptr) *Func {
+ return (*Func)(unsafe.Pointer(findfunc(pc)))
+}
+
+// Name returns the name of the function.
+func (f *Func) Name() string {
+ return gofuncname(f.raw())
+}
+
+// Entry returns the entry address of the function.
+func (f *Func) Entry() uintptr {
+ return f.raw().entry
+}
+
+// FileLine returns the file name and line number of the
+// source code corresponding to the program counter pc.
+// The result will not be accurate if pc is not a program
+// counter within f.
+func (f *Func) FileLine(pc uintptr) (file string, line int) {
+ // Pass strict=false here, because anyone can call this function,
+ // and they might just be wrong about targetpc belonging to f.
+ line = int(funcline1(f.raw(), pc, &file, false))
+ return file, line
+}
+
+func findfunc(pc uintptr) *_func {
+ if len(ftab) == 0 {
+ return nil
+ }
+
+ if pc < ftab[0].entry || pc >= ftab[len(ftab)-1].entry {
+ return nil
+ }
+
+ // binary search to find func with entry <= pc.
+ lo := 0
+ nf := len(ftab) - 1 // last entry is sentinel
+ for nf > 0 {
+ n := nf / 2
+ f := &ftab[lo+n]
+ if f.entry <= pc && pc < ftab[lo+n+1].entry {
+ return (*_func)(unsafe.Pointer(&pclntable[f.funcoff]))
+ } else if pc < f.entry {
+ nf = n
+ } else {
+ lo += n + 1
+ nf -= n + 1
+ }
+ }
+
+ gothrow("findfunc: binary search failed")
+ return nil
+}
+
+func pcvalue(f *_func, off int32, targetpc uintptr, strict bool) int32 {
+ if off == 0 {
+ return -1
+ }
+ p := pclntable[off:]
+ pc := f.entry
+ val := int32(-1)
+ for {
+ var ok bool
+ p, ok = step(p, &pc, &val, pc == f.entry)
+ if !ok {
+ break
+ }
+ if targetpc < pc {
+ return val
+ }
+ }
+
+ // If there was a table, it should have covered all program counters.
+ // If not, something is wrong.
+ if panicking != 0 || !strict {
+ return -1
+ }
+
+ print("runtime: invalid pc-encoded table f=", gofuncname(f), " pc=", hex(pc), " targetpc=", hex(targetpc), " tab=", p, "\n")
+
+ p = pclntable[off:]
+ pc = f.entry
+ val = -1
+ for {
+ var ok bool
+ p, ok = step(p, &pc, &val, pc == f.entry)
+ if !ok {
+ break
+ }
+ print("\tvalue=", val, " until pc=", hex(pc), "\n")
+ }
+
+ gothrow("invalid runtime symbol table")
+ return -1
+}
+
+func funcname(f *_func) *byte {
+ if f == nil || f.nameoff == 0 {
+ return nil
+ }
+ return (*byte)(unsafe.Pointer(&pclntable[f.nameoff]))
+}
+
+func gofuncname(f *_func) string {
+ return gostringnocopy(funcname(f))
+}
+
+func funcline1(f *_func, targetpc uintptr, file *string, strict bool) int32 {
+ *file = "?"
+ fileno := int(pcvalue(f, f.pcfile, targetpc, strict))
+ line := pcvalue(f, f.pcln, targetpc, strict)
+ if fileno == -1 || line == -1 || fileno >= len(filetab) {
+ // print("looking for ", hex(targetpc), " in ", gofuncname(f), " got file=", fileno, " line=", lineno, "\n")
+ return 0
+ }
+ *file = gostringnocopy(&pclntable[filetab[fileno]])
+ return line
+}
+
+func funcline(f *_func, targetpc uintptr, file *string) int32 {
+ return funcline1(f, targetpc, file, true)
+}
+
+func funcspdelta(f *_func, targetpc uintptr) int32 {
+ x := pcvalue(f, f.pcsp, targetpc, true)
+ if x&(ptrSize-1) != 0 {
+ print("invalid spdelta ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n")
+ }
+ return x
+}
+
+func pcdatavalue(f *_func, table int32, targetpc uintptr) 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)
+}
+
+func funcdata(f *_func, i int32) unsafe.Pointer {
+ if i < 0 || i >= f.nfuncdata {
+ return nil
+ }
+ p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4)
+ if 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))
+}
+
+// step advances to the next pc, value pair in the encoded table.
+func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) {
+ p, uvdelta := readvarint(p)
+ if uvdelta == 0 && !first {
+ return nil, false
+ }
+ if uvdelta&1 != 0 {
+ uvdelta = ^(uvdelta >> 1)
+ } else {
+ uvdelta >>= 1
+ }
+ vdelta := int32(uvdelta)
+ p, pcdelta := readvarint(p)
+ *pc += uintptr(pcdelta * _PCQuantum)
+ *val += vdelta
+ return p, true
+}
+
+// readvarint reads a varint from p.
+func readvarint(p []byte) (newp []byte, val uint32) {
+ var v, shift uint32
+ for {
+ b := p[0]
+ p = p[1:]
+ v |= (uint32(b) & 0x7F) << shift
+ if b&0x80 == 0 {
+ break
+ }
+ shift += 7
+ }
+ return p, v
+}
diff --git a/src/pkg/runtime/symtab_test.go b/src/runtime/symtab_test.go
index bd9fe18c4..bd9fe18c4 100644
--- a/src/pkg/runtime/symtab_test.go
+++ b/src/runtime/symtab_test.go
diff --git a/src/pkg/runtime/sys_arm.c b/src/runtime/sys_arm.c
index a65560e5b..a65560e5b 100644
--- a/src/pkg/runtime/sys_arm.c
+++ b/src/runtime/sys_arm.c
diff --git a/src/pkg/runtime/sys_darwin_386.s b/src/runtime/sys_darwin_386.s
index bfaaa00a7..a961c71a8 100644
--- a/src/pkg/runtime/sys_darwin_386.s
+++ b/src/runtime/sys_darwin_386.s
@@ -7,7 +7,7 @@
// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT,$0
@@ -28,21 +28,25 @@ TEXT runtime·exit1(SB),NOSPLIT,$0
TEXT runtime·open(SB),NOSPLIT,$0
MOVL $5, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$0
MOVL $6, AX
INT $0x80
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$0
MOVL $3, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$0
MOVL $4, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$16
@@ -59,6 +63,7 @@ TEXT runtime·raise(SB),NOSPLIT,$16
TEXT runtime·mmap(SB),NOSPLIT,$0
MOVL $197, AX
INT $0x80
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·madvise(SB),NOSPLIT,$0
@@ -206,9 +211,8 @@ TEXT time·now(SB),NOSPLIT,$0
// void nanotime(int64 *nsec)
TEXT runtime·nanotime(SB),NOSPLIT,$0
CALL runtime·now(SB)
- MOVL ret+0(FP), DI
- MOVL AX, 0(DI)
- MOVL DX, 4(DI)
+ MOVL AX, ret_lo+0(FP)
+ MOVL DX, ret_hi+4(FP)
RET
TEXT runtime·sigprocmask(SB),NOSPLIT,$0
@@ -236,9 +240,9 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0
TEXT runtime·sigtramp(SB),NOSPLIT,$40
get_tls(CX)
- // check that m exists
- MOVL m(CX), BP
- CMPL BP, $0
+ // check that g exists
+ MOVL g(CX), DI
+ CMPL DI, $0
JNE 6(PC)
MOVL sig+8(FP), BX
MOVL BX, 0(SP)
@@ -247,10 +251,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$40
JMP sigtramp_ret
// save g
- MOVL g(CX), DI
MOVL DI, 20(SP)
// g = m->gsignal
+ MOVL g_m(DI), BP
MOVL m_gsignal(BP), BP
MOVL BP, g(CX)
@@ -315,7 +319,7 @@ TEXT runtime·usleep(SB),NOSPLIT,$32
TEXT runtime·bsdthread_create(SB),NOSPLIT,$32
MOVL $360, AX
// 0(SP) is where the caller PC would be; kernel skips it
- MOVL func+12(FP), BX
+ MOVL fn+12(FP), BX
MOVL BX, 4(SP) // func
MOVL mm+4(FP), BX
MOVL BX, 8(SP) // arg
@@ -325,10 +329,12 @@ TEXT runtime·bsdthread_create(SB),NOSPLIT,$32
MOVL BX, 16(SP) // pthread
MOVL $0x1000000, 20(SP) // flags = PTHREAD_START_CUSTOM
INT $0x80
- JAE 3(PC)
+ JAE 4(PC)
NEGL AX
+ MOVL AX, ret+16(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+16(FP)
RET
// The thread that bsdthread_create creates starts executing here,
@@ -362,7 +368,7 @@ TEXT runtime·bsdthread_start(SB),NOSPLIT,$0
// Now segment is established. Initialize m, g.
get_tls(BP)
MOVL AX, g(BP)
- MOVL DX, m(BP)
+ MOVL DX, g_m(AX)
MOVL BX, m_procid(DX) // m->procid = thread port (for debuggers)
CALL runtime·stackcheck(SB) // smashes AX
CALL CX // fn()
@@ -382,10 +388,12 @@ TEXT runtime·bsdthread_register(SB),NOSPLIT,$40
MOVL $0, 20(SP) // targetconc_ptr
MOVL $0, 24(SP) // dispatchqueue_offset
INT $0x80
- JAE 3(PC)
+ JAE 4(PC)
NEGL AX
+ MOVL AX, ret+0(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+0(FP)
RET
// Invoke Mach system call.
@@ -408,16 +416,19 @@ TEXT runtime·sysenter(SB),NOSPLIT,$0
TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0
MOVL $-31, AX
CALL runtime·sysenter(SB)
+ MOVL AX, ret+28(FP)
RET
TEXT runtime·mach_reply_port(SB),NOSPLIT,$0
MOVL $-26, AX
CALL runtime·sysenter(SB)
+ MOVL AX, ret+0(FP)
RET
TEXT runtime·mach_task_self(SB),NOSPLIT,$0
MOVL $-28, AX
CALL runtime·sysenter(SB)
+ MOVL AX, ret+0(FP)
RET
// Mach provides trap versions of the semaphore ops,
@@ -427,24 +438,28 @@ TEXT runtime·mach_task_self(SB),NOSPLIT,$0
TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0
MOVL $-36, AX
CALL runtime·sysenter(SB)
+ MOVL AX, ret+4(FP)
RET
// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0
MOVL $-38, AX
CALL runtime·sysenter(SB)
+ MOVL AX, ret+12(FP)
RET
// uint32 mach_semaphore_signal(uint32)
TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0
MOVL $-33, AX
CALL runtime·sysenter(SB)
+ MOVL AX, ret+4(FP)
RET
// uint32 mach_semaphore_signal_all(uint32)
TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0
MOVL $-34, AX
CALL runtime·sysenter(SB)
+ MOVL AX, ret+4(FP)
RET
// setldt(int entry, int address, int limit)
@@ -486,10 +501,12 @@ TEXT runtime·setldt(SB),NOSPLIT,$32
TEXT runtime·sysctl(SB),NOSPLIT,$0
MOVL $202, AX
INT $0x80
- JAE 3(PC)
+ JAE 4(PC)
NEGL AX
+ MOVL AX, ret+24(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+24(FP)
RET
// int32 runtime·kqueue(void);
@@ -498,6 +515,7 @@ TEXT runtime·kqueue(SB),NOSPLIT,$0
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
@@ -506,6 +524,7 @@ TEXT runtime·kevent(SB),NOSPLIT,$0
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+24(FP)
RET
// int32 runtime·closeonexec(int32 fd);
diff --git a/src/pkg/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s
index a0c81b5d2..bd397d72a 100644
--- a/src/pkg/runtime/sys_darwin_amd64.s
+++ b/src/runtime/sys_darwin_amd64.s
@@ -12,11 +12,11 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT,$0
- MOVL 8(SP), DI // arg 1 exit status
+ MOVL code+0(FP), DI // arg 1 exit status
MOVL $(0x2000000+1), AX // syscall entry
SYSCALL
MOVL $0xf1, 0xf1 // crash
@@ -25,40 +25,44 @@ TEXT runtime·exit(SB),NOSPLIT,$0
// Exit this OS thread (like pthread_exit, which eventually
// calls __bsdthread_terminate).
TEXT runtime·exit1(SB),NOSPLIT,$0
- MOVL 8(SP), DI // arg 1 exit status
+ MOVL code+0(FP), DI // arg 1 exit status
MOVL $(0x2000000+361), AX // syscall entry
SYSCALL
MOVL $0xf1, 0xf1 // crash
RET
TEXT runtime·open(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 pathname
- MOVL 16(SP), SI // arg 2 flags
- MOVL 20(SP), DX // arg 3 mode
+ MOVQ name+0(FP), DI // arg 1 pathname
+ MOVL mode+8(FP), SI // arg 2 flags
+ MOVL perm+12(FP), DX // arg 3 mode
MOVL $(0x2000000+5), AX // syscall entry
SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$0
- MOVL 8(SP), DI // arg 1 fd
+ MOVL fd+0(FP), DI // arg 1 fd
MOVL $(0x2000000+6), AX // syscall entry
SYSCALL
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$0
- MOVL 8(SP), DI // arg 1 fd
- MOVQ 16(SP), SI // arg 2 buf
- MOVL 24(SP), DX // arg 3 count
+ MOVL fd+0(FP), DI // arg 1 fd
+ MOVQ p+8(FP), SI // arg 2 buf
+ MOVL n+16(FP), DX // arg 3 count
MOVL $(0x2000000+3), AX // syscall entry
SYSCALL
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$0
- MOVL 8(SP), DI // arg 1 fd
- MOVQ 16(SP), SI // arg 2 buf
- MOVL 24(SP), DX // arg 3 count
+ MOVQ fd+0(FP), DI // arg 1 fd
+ MOVQ p+8(FP), SI // arg 2 buf
+ MOVL n+16(FP), DX // arg 3 count
MOVL $(0x2000000+4), AX // syscall entry
SYSCALL
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$24
@@ -72,17 +76,17 @@ TEXT runtime·raise(SB),NOSPLIT,$24
RET
TEXT runtime·setitimer(SB), NOSPLIT, $0
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
+ MOVL mode+0(FP), DI
+ MOVQ new+8(FP), SI
+ MOVQ old+16(FP), DX
MOVL $(0x2000000+83), AX // syscall entry
SYSCALL
RET
TEXT runtime·madvise(SB), NOSPLIT, $0
- MOVQ 8(SP), DI // arg 1 addr
- MOVQ 16(SP), SI // arg 2 len
- MOVL 24(SP), DX // arg 3 advice
+ MOVQ addr+0(FP), DI // arg 1 addr
+ MOVQ n+8(FP), SI // arg 2 len
+ MOVL flags+16(FP), DX // arg 3 advice
MOVL $(0x2000000+75), AX // syscall entry madvise
SYSCALL
// ignore failure - maybe pages are locked
@@ -99,8 +103,7 @@ TEXT runtime·madvise(SB), NOSPLIT, $0
#define gtod_ns_base 0x70
#define gtod_sec_base 0x78
-// int64 nanotime(void)
-TEXT runtime·nanotime(SB), NOSPLIT, $32
+TEXT nanotime<>(SB), NOSPLIT, $32
MOVQ $0x7fffffe00000, BP /* comm page base */
// Loop trying to take a consistent snapshot
// of the time parameters.
@@ -149,9 +152,14 @@ systime:
ADDQ DX, AX
RET
+TEXT runtime·nanotime(SB),NOSPLIT,$0-8
+ CALL nanotime<>(SB)
+ MOVQ AX, ret+0(FP)
+ RET
+
// func now() (sec int64, nsec int32)
-TEXT time·now(SB),NOSPLIT,$0
- CALL runtime·nanotime(SB)
+TEXT time·now(SB),NOSPLIT,$0-12
+ CALL nanotime<>(SB)
// generated code for
// func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
@@ -169,9 +177,9 @@ TEXT time·now(SB),NOSPLIT,$0
RET
TEXT runtime·sigprocmask(SB),NOSPLIT,$0
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
+ MOVL sig+0(FP), DI
+ MOVQ new+8(FP), SI
+ MOVQ old+16(FP), DX
MOVL $(0x2000000+329), AX // pthread_sigmask (on OS X, sigprocmask==entire process)
SYSCALL
JCC 2(PC)
@@ -179,11 +187,11 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0
RET
TEXT runtime·sigaction(SB),NOSPLIT,$0
- MOVL 8(SP), DI // arg 1 sig
- MOVQ 16(SP), SI // arg 2 act
- MOVQ 24(SP), DX // arg 3 oact
- MOVQ 24(SP), CX // arg 3 oact
- MOVQ 24(SP), R10 // arg 3 oact
+ MOVL mode+0(FP), DI // arg 1 sig
+ MOVQ new+8(FP), SI // arg 2 act
+ MOVQ old+16(FP), DX // arg 3 oact
+ MOVQ old+16(FP), CX // arg 3 oact
+ MOVQ old+16(FP), R10 // arg 3 oact
MOVL $(0x2000000+46), AX // syscall entry
SYSCALL
JCC 2(PC)
@@ -196,9 +204,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
MOVQ R8, 32(SP) // save ucontext
MOVQ SI, 40(SP) // save infostyle
- // check that m exists
- MOVQ m(BX), BP
- CMPQ BP, $0
+ // check that g exists
+ MOVQ g(BX), R10
+ CMPQ R10, $0
JNE 5(PC)
MOVL DX, 0(SP)
MOVQ $runtime·badsignal(SB), AX
@@ -206,10 +214,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
JMP sigtramp_ret
// save g
- MOVQ g(BX), R10
MOVQ R10, 48(SP)
// g = m->gsignal
+ MOVQ g_m(R10), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
@@ -234,19 +242,20 @@ sigtramp_ret:
INT $3 // not reached
TEXT runtime·mmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 addr
- MOVQ 16(SP), SI // arg 2 len
- MOVL 24(SP), DX // arg 3 prot
- MOVL 28(SP), R10 // arg 4 flags
- MOVL 32(SP), R8 // arg 5 fid
- MOVL 36(SP), R9 // arg 6 offset
+ MOVQ addr+0(FP), DI // arg 1 addr
+ MOVQ n+8(FP), SI // arg 2 len
+ MOVL prot+16(FP), DX // arg 3 prot
+ MOVL flags+20(FP), R10 // arg 4 flags
+ MOVL fd+24(FP), R8 // arg 5 fid
+ MOVL off+28(FP), R9 // arg 6 offset
MOVL $(0x2000000+197), AX // syscall entry
SYSCALL
+ MOVQ AX, ret+32(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 addr
- MOVQ 16(SP), SI // arg 2 len
+ MOVQ addr+0(FP), DI // arg 1 addr
+ MOVQ n+8(FP), SI // arg 2 len
MOVL $(0x2000000+73), AX // syscall entry
SYSCALL
JCC 2(PC)
@@ -293,10 +302,12 @@ TEXT runtime·bsdthread_create(SB),NOSPLIT,$0
MOVQ $0, R9 // paranoia
MOVQ $(0x2000000+360), AX // bsdthread_create
SYSCALL
- JCC 3(PC)
+ JCC 4(PC)
NEGQ AX
+ MOVL AX, ret+32(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+32(FP)
RET
// The thread that bsdthread_create creates starts executing here,
@@ -325,10 +336,10 @@ TEXT runtime·bsdthread_start(SB),NOSPLIT,$0
POPQ DX
get_tls(BX)
- MOVQ CX, m(BX)
MOVQ SI, m_procid(CX) // thread port is m->procid
MOVQ m_g0(CX), AX
MOVQ AX, g(BX)
+ MOVQ CX, g_m(AX)
CALL runtime·stackcheck(SB) // smashes AX, CX
CALL DX // fn
CALL runtime·exit1(SB)
@@ -346,42 +357,48 @@ TEXT runtime·bsdthread_register(SB),NOSPLIT,$0
MOVQ $0, R9 // dispatchqueue_offset
MOVQ $(0x2000000+366), AX // bsdthread_register
SYSCALL
- JCC 3(PC)
+ JCC 4(PC)
NEGQ AX
+ MOVL AX, ret+0(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+0(FP)
RET
// Mach system calls use 0x1000000 instead of the BSD's 0x2000000.
// uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32)
TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI
- MOVL 16(SP), SI
- MOVL 20(SP), DX
- MOVL 24(SP), R10
- MOVL 28(SP), R8
- MOVL 32(SP), R9
- MOVL 36(SP), R11
+ MOVQ h+0(FP), DI
+ MOVL op+8(FP), SI
+ MOVL send_size+12(FP), DX
+ MOVL rcv_size+16(FP), R10
+ MOVL rcv_name+20(FP), R8
+ MOVL timeout+24(FP), R9
+ MOVL notify+28(FP), R11
PUSHQ R11 // seventh arg, on stack
MOVL $(0x1000000+31), AX // mach_msg_trap
SYSCALL
POPQ R11
+ MOVL AX, ret+32(FP)
RET
TEXT runtime·mach_task_self(SB),NOSPLIT,$0
MOVL $(0x1000000+28), AX // task_self_trap
SYSCALL
+ MOVL AX, ret+0(FP)
RET
TEXT runtime·mach_thread_self(SB),NOSPLIT,$0
MOVL $(0x1000000+27), AX // thread_self_trap
SYSCALL
+ MOVL AX, ret+0(FP)
RET
TEXT runtime·mach_reply_port(SB),NOSPLIT,$0
MOVL $(0x1000000+26), AX // mach_reply_port
SYSCALL
+ MOVL AX, ret+0(FP)
RET
// Mach provides trap versions of the semaphore ops,
@@ -389,32 +406,36 @@ TEXT runtime·mach_reply_port(SB),NOSPLIT,$0
// uint32 mach_semaphore_wait(uint32)
TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0
- MOVL 8(SP), DI
+ MOVL sema+0(FP), DI
MOVL $(0x1000000+36), AX // semaphore_wait_trap
SYSCALL
+ MOVL AX, ret+8(FP)
RET
// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0
- MOVL 8(SP), DI
- MOVL 12(SP), SI
- MOVL 16(SP), DX
+ MOVL sema+0(FP), DI
+ MOVL sec+4(FP), SI
+ MOVL nsec+8(FP), DX
MOVL $(0x1000000+38), AX // semaphore_timedwait_trap
SYSCALL
+ MOVL AX, ret+16(FP)
RET
// uint32 mach_semaphore_signal(uint32)
TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0
- MOVL 8(SP), DI
+ MOVL sema+0(FP), DI
MOVL $(0x1000000+33), AX // semaphore_signal_trap
SYSCALL
+ MOVL AX, ret+8(FP)
RET
// uint32 mach_semaphore_signal_all(uint32)
TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0
- MOVL 8(SP), DI
+ MOVL sema+0(FP), DI
MOVL $(0x1000000+34), AX // semaphore_signal_all_trap
SYSCALL
+ MOVL AX, ret+8(FP)
RET
// set tls base to DI
@@ -431,18 +452,20 @@ TEXT runtime·settls(SB),NOSPLIT,$32
RET
TEXT runtime·sysctl(SB),NOSPLIT,$0
- MOVQ 8(SP), DI
- MOVL 16(SP), SI
- MOVQ 24(SP), DX
- MOVQ 32(SP), R10
- MOVQ 40(SP), R8
- MOVQ 48(SP), R9
+ MOVQ mib+0(FP), DI
+ MOVL miblen+8(FP), SI
+ MOVQ out+16(FP), DX
+ MOVQ size+24(FP), R10
+ MOVQ dst+32(FP), R8
+ MOVQ ndst+40(FP), R9
MOVL $(0x2000000+202), AX // syscall entry
SYSCALL
- JCC 3(PC)
+ JCC 4(PC)
NEGQ AX
+ MOVL AX, ret+48(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+48(FP)
RET
// int32 runtime·kqueue(void);
@@ -454,25 +477,27 @@ TEXT runtime·kqueue(SB),NOSPLIT,$0
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
TEXT runtime·kevent(SB),NOSPLIT,$0
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVQ 32(SP), R10
- MOVL 40(SP), R8
- MOVQ 48(SP), R9
+ MOVL fd+0(FP), DI
+ MOVQ ev1+8(FP), SI
+ MOVL nev1+16(FP), DX
+ MOVQ ev2+24(FP), R10
+ MOVL nev2+32(FP), R8
+ MOVQ ts+40(FP), R9
MOVL $(0x2000000+363), AX
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+48(FP)
RET
// void runtime·closeonexec(int32 fd);
TEXT runtime·closeonexec(SB),NOSPLIT,$0
- MOVL 8(SP), DI // fd
+ MOVL fd+0(FP), DI // fd
MOVQ $2, SI // F_SETFD
MOVQ $1, DX // FD_CLOEXEC
MOVL $(0x2000000+92), AX // fcntl
diff --git a/src/pkg/runtime/sys_dragonfly_386.s b/src/runtime/sys_dragonfly_386.s
index 20e699966..161eaec19 100644
--- a/src/pkg/runtime/sys_dragonfly_386.s
+++ b/src/runtime/sys_dragonfly_386.s
@@ -7,13 +7,14 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT runtime·sys_umtx_sleep(SB),NOSPLIT,$-4
MOVL $469, AX // umtx_sleep
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·sys_umtx_wakeup(SB),NOSPLIT,$-4
@@ -21,11 +22,13 @@ TEXT runtime·sys_umtx_wakeup(SB),NOSPLIT,$-4
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·lwp_create(SB),NOSPLIT,$-4
MOVL $495, AX // lwp_create
INT $0x80
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·lwp_start(SB),NOSPLIT,$0
@@ -42,7 +45,7 @@ TEXT runtime·lwp_start(SB),NOSPLIT,$0
// Now segment is established. Initialize m, g.
get_tls(CX)
- MOVL BX, m(CX)
+ MOVL BX, g_m(DX)
MOVL DX, g(CX)
CALL runtime·stackcheck(SB) // smashes AX, CX
@@ -81,26 +84,31 @@ TEXT runtime·exit1(SB),NOSPLIT,$16
TEXT runtime·open(SB),NOSPLIT,$-4
MOVL $5, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$-4
MOVL $6, AX
INT $0x80
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$-4
MOVL $3, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$-4
MOVL $4, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·getrlimit(SB),NOSPLIT,$-4
MOVL $194, AX
INT $0x80
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$16
@@ -116,7 +124,7 @@ TEXT runtime·raise(SB),NOSPLIT,$16
RET
TEXT runtime·mmap(SB),NOSPLIT,$36
- LEAL arg0+0(FP), SI
+ LEAL addr+0(FP), SI
LEAL 4(SP), DI
CLD
MOVSL // arg 1 - addr
@@ -131,6 +139,7 @@ TEXT runtime·mmap(SB),NOSPLIT,$36
STOSL
MOVL $197, AX // sys_mmap
INT $0x80
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$-4
@@ -185,9 +194,8 @@ TEXT runtime·nanotime(SB), NOSPLIT, $32
ADDL BX, AX
ADCL $0, DX
- MOVL ret+0(FP), DI
- MOVL AX, 0(DI)
- MOVL DX, 4(DI)
+ MOVL AX, ret_lo+0(FP)
+ MOVL DX, ret_hi+4(FP)
RET
@@ -201,9 +209,9 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-4
TEXT runtime·sigtramp(SB),NOSPLIT,$44
get_tls(CX)
- // check that m exists
- MOVL m(CX), BX
- CMPL BX, $0
+ // check that g exists
+ MOVL g(CX), DI
+ CMPL DI, $0
JNE 6(PC)
MOVL signo+0(FP), BX
MOVL BX, 0(SP)
@@ -212,10 +220,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
JMP sigtramp_ret
// save g
- MOVL g(CX), DI
MOVL DI, 20(SP)
// g = m->gsignal
+ MOVL g_m(DI), BX
MOVL m_gsignal(BX), BX
MOVL BX, g(CX)
@@ -302,7 +310,7 @@ TEXT runtime·settls(SB),NOSPLIT,$24
RET
TEXT runtime·sysctl(SB),NOSPLIT,$28
- LEAL arg0+0(FP), SI
+ LEAL mib+0(FP), SI
LEAL 4(SP), DI
CLD
MOVSL // arg 1 - name
@@ -313,10 +321,12 @@ TEXT runtime·sysctl(SB),NOSPLIT,$28
MOVSL // arg 6 - newlen
MOVL $202, AX // sys___sysctl
INT $0x80
- JCC 3(PC)
+ JCC 4(PC)
NEGL AX
+ MOVL AX, ret+24(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·osyield(SB),NOSPLIT,$-4
@@ -327,9 +337,9 @@ TEXT runtime·osyield(SB),NOSPLIT,$-4
TEXT runtime·sigprocmask(SB),NOSPLIT,$16
MOVL $0, 0(SP) // syscall gap
MOVL $3, 4(SP) // arg 1 - how (SIG_SETMASK)
- MOVL args+0(FP), AX
+ MOVL new+0(FP), AX
MOVL AX, 8(SP) // arg 2 - set
- MOVL args+4(FP), AX
+ MOVL old+4(FP), AX
MOVL AX, 12(SP) // arg 3 - oset
MOVL $340, AX // sys_sigprocmask
INT $0x80
@@ -343,6 +353,7 @@ TEXT runtime·kqueue(SB),NOSPLIT,$0
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
@@ -351,6 +362,7 @@ TEXT runtime·kevent(SB),NOSPLIT,$0
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+24(FP)
RET
// int32 runtime·closeonexec(int32 fd);
@@ -366,4 +378,4 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$32
NEGL AX
RET
-GLOBL runtime·tlsoffset(SB),$4
+GLOBL runtime·tlsoffset(SB),NOPTR,$4
diff --git a/src/pkg/runtime/sys_dragonfly_amd64.s b/src/runtime/sys_dragonfly_amd64.s
index d70d2e80c..2c756018c 100644
--- a/src/pkg/runtime/sys_dragonfly_amd64.s
+++ b/src/runtime/sys_dragonfly_amd64.s
@@ -7,31 +7,34 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT runtime·sys_umtx_sleep(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - ptr
- MOVL 16(SP), SI // arg 2 - value
- MOVL 20(SP), DX // arg 3 - timeout
+ MOVQ addr+0(FP), DI // arg 1 - ptr
+ MOVL val+8(FP), SI // arg 2 - value
+ MOVL timeout+12(FP), DX // arg 3 - timeout
MOVL $469, AX // umtx_sleep
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·sys_umtx_wakeup(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - ptr
- MOVL 16(SP), SI // arg 2 - count
+ MOVQ addr+0(FP), DI // arg 1 - ptr
+ MOVL val+8(FP), SI // arg 2 - count
MOVL $470, AX // umtx_wakeup
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·lwp_create(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - params
+ MOVQ param+0(FP), DI // arg 1 - params
MOVL $495, AX // lwp_create
SYSCALL
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·lwp_start(SB),NOSPLIT,$0
@@ -43,8 +46,8 @@ TEXT runtime·lwp_start(SB),NOSPLIT,$0
// set up m, g
get_tls(CX)
- MOVQ R13, m(CX)
MOVQ m_g0(R13), DI
+ MOVQ R13, g_m(DI)
MOVQ DI, g(CX)
CALL runtime·stackcheck(SB)
@@ -54,54 +57,59 @@ TEXT runtime·lwp_start(SB),NOSPLIT,$0
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 exit status
+ MOVL code+0(FP), DI // arg 1 exit status
MOVL $1, AX
SYSCALL
MOVL $0xf1, 0xf1 // crash
RET
TEXT runtime·exit1(SB),NOSPLIT,$-8
- MOVQ 8(SP), DI // arg 1 exit status
+ MOVL code+0(FP), DI // arg 1 exit status
MOVL $431, AX
SYSCALL
MOVL $0xf1, 0xf1 // crash
RET
TEXT runtime·open(SB),NOSPLIT,$-8
- MOVQ 8(SP), DI // arg 1 pathname
- MOVL 16(SP), SI // arg 2 flags
- MOVL 20(SP), DX // arg 3 mode
+ MOVQ name+0(FP), DI // arg 1 pathname
+ MOVL mode+8(FP), SI // arg 2 flags
+ MOVL perm+12(FP), DX // arg 3 mode
MOVL $5, AX
SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 fd
+ MOVL fd+0(FP), DI // arg 1 fd
MOVL $6, AX
SYSCALL
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 fd
- MOVQ 16(SP), SI // arg 2 buf
- MOVL 24(SP), DX // arg 3 count
+ MOVL fd+0(FP), DI // arg 1 fd
+ MOVQ p+8(FP), SI // arg 2 buf
+ MOVL n+16(FP), DX // arg 3 count
MOVL $3, AX
SYSCALL
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 fd
- MOVQ 16(SP), SI // arg 2 buf
- MOVL 24(SP), DX // arg 3 count
+ MOVQ fd+0(FP), DI // arg 1 fd
+ MOVQ p+8(FP), SI // arg 2 buf
+ MOVL n+16(FP), DX // arg 3 count
MOVL $4, AX
SYSCALL
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·getrlimit(SB),NOSPLIT,$-8
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
+ MOVL kind+0(FP), DI
+ MOVQ limit+8(FP), SI
MOVL $194, AX
SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$16
@@ -115,9 +123,9 @@ TEXT runtime·raise(SB),NOSPLIT,$16
RET
TEXT runtime·setitimer(SB), NOSPLIT, $-8
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
+ MOVL mode+0(FP), DI
+ MOVQ new+8(FP), SI
+ MOVQ old+16(FP), DX
MOVL $83, AX
SYSCALL
RET
@@ -148,12 +156,13 @@ TEXT runtime·nanotime(SB), NOSPLIT, $32
// return nsec in AX
IMULQ $1000000000, AX
ADDQ DX, AX
+ MOVQ AX, ret+0(FP)
RET
TEXT runtime·sigaction(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 sig
- MOVQ 16(SP), SI // arg 2 act
- MOVQ 24(SP), DX // arg 3 oact
+ MOVL sig+0(FP), DI // arg 1 sig
+ MOVQ new+8(FP), SI // arg 2 act
+ MOVQ old+16(FP), DX // arg 3 oact
MOVL $342, AX
SYSCALL
JCC 2(PC)
@@ -163,9 +172,9 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
TEXT runtime·sigtramp(SB),NOSPLIT,$64
get_tls(BX)
- // check that m exists
- MOVQ m(BX), BP
- CMPQ BP, $0
+ // check that g exists
+ MOVQ g(BX), R10
+ CMPQ R10, $0
JNE 5(PC)
MOVQ DI, 0(SP)
MOVQ $runtime·badsignal(SB), AX
@@ -173,10 +182,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
RET
// save g
- MOVQ g(BX), R10
MOVQ R10, 40(SP)
// g = m->signal
+ MOVQ g_m(R10), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
@@ -194,23 +203,24 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
RET
TEXT runtime·mmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - addr
- MOVQ 16(SP), SI // arg 2 - len
- MOVL 24(SP), DX // arg 3 - prot
- MOVL 28(SP), R10 // arg 4 - flags
- MOVL 32(SP), R8 // arg 5 - fd
- MOVL 36(SP), R9
+ MOVQ addr+0(FP), DI // arg 1 - addr
+ MOVQ n+8(FP), SI // arg 2 - len
+ MOVL prot+16(FP), DX // arg 3 - prot
+ MOVL flags+20(FP), R10 // arg 4 - flags
+ MOVL fd+24(FP), R8 // arg 5 - fd
+ MOVL off+28(FP), R9
SUBQ $16, SP
MOVQ R9, 8(SP) // arg 7 - offset (passed on stack)
MOVQ $0, R9 // arg 6 - pad
MOVL $197, AX
SYSCALL
ADDQ $16, SP
+ MOVQ AX, ret+32(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 addr
- MOVQ 16(SP), SI // arg 2 len
+ MOVQ addr+0(FP), DI // arg 1 addr
+ MOVQ n+8(FP), SI // arg 2 len
MOVL $73, AX
SYSCALL
JCC 2(PC)
@@ -218,9 +228,9 @@ TEXT runtime·munmap(SB),NOSPLIT,$0
RET
TEXT runtime·madvise(SB),NOSPLIT,$0
- MOVQ 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
+ MOVQ addr+0(FP), DI
+ MOVQ n+8(FP), SI
+ MOVL flags+16(FP), DX
MOVQ $75, AX // madvise
SYSCALL
// ignore failure - maybe pages are locked
@@ -266,18 +276,20 @@ TEXT runtime·settls(SB),NOSPLIT,$16
RET
TEXT runtime·sysctl(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - name
- MOVL 16(SP), SI // arg 2 - namelen
- MOVQ 24(SP), DX // arg 3 - oldp
- MOVQ 32(SP), R10 // arg 4 - oldlenp
- MOVQ 40(SP), R8 // arg 5 - newp
- MOVQ 48(SP), R9 // arg 6 - newlen
+ MOVQ mib+0(FP), DI // arg 1 - name
+ MOVL miblen+8(FP), SI // arg 2 - namelen
+ MOVQ out+16(FP), DX // arg 3 - oldp
+ MOVQ size+24(FP), R10 // arg 4 - oldlenp
+ MOVQ dst+32(FP), R8 // arg 5 - newp
+ MOVQ ndst+40(FP), R9 // arg 6 - newlen
MOVQ $202, AX // sys___sysctl
SYSCALL
- JCC 3(PC)
+ JCC 4(PC)
NEGQ AX
+ MOVL AX, ret+48(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+48(FP)
RET
TEXT runtime·osyield(SB),NOSPLIT,$-4
@@ -287,8 +299,8 @@ TEXT runtime·osyield(SB),NOSPLIT,$-4
TEXT runtime·sigprocmask(SB),NOSPLIT,$0
MOVL $3, DI // arg 1 - how (SIG_SETMASK)
- MOVQ 8(SP), SI // arg 2 - set
- MOVQ 16(SP), DX // arg 3 - oset
+ MOVQ new+0(FP), SI // arg 2 - set
+ MOVQ old+8(FP), DX // arg 3 - oset
MOVL $340, AX // sys_sigprocmask
SYSCALL
JAE 2(PC)
@@ -304,25 +316,27 @@ TEXT runtime·kqueue(SB),NOSPLIT,$0
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
TEXT runtime·kevent(SB),NOSPLIT,$0
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVQ 32(SP), R10
- MOVL 40(SP), R8
- MOVQ 48(SP), R9
+ MOVL fd+0(FP), DI
+ MOVQ ev1+8(FP), SI
+ MOVL nev1+16(FP), DX
+ MOVQ ev2+24(FP), R10
+ MOVL nev2+32(FP), R8
+ MOVQ ts+40(FP), R9
MOVL $363, AX
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+48(FP)
RET
// void runtime·closeonexec(int32 fd);
TEXT runtime·closeonexec(SB),NOSPLIT,$0
- MOVL 8(SP), DI // fd
+ MOVL fd+0(FP), DI // fd
MOVQ $2, SI // F_SETFD
MOVQ $1, DX // FD_CLOEXEC
MOVL $92, AX // fcntl
diff --git a/src/pkg/runtime/sys_freebsd_386.s b/src/runtime/sys_freebsd_386.s
index 4c97eec7b..2c40fc433 100644
--- a/src/pkg/runtime/sys_freebsd_386.s
+++ b/src/runtime/sys_freebsd_386.s
@@ -7,11 +7,12 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT runtime·sys_umtx_op(SB),NOSPLIT,$-4
MOVL $454, AX
INT $0x80
+ MOVL AX, ret+20(FP)
RET
TEXT runtime·thr_new(SB),NOSPLIT,$-4
@@ -37,7 +38,7 @@ TEXT runtime·thr_start(SB),NOSPLIT,$0
get_tls(CX)
MOVL BX, g(CX)
- MOVL AX, m(CX)
+ MOVL AX, g_m(BX)
CALL runtime·stackcheck(SB) // smashes AX
CALL runtime·mstart(SB)
@@ -60,26 +61,31 @@ TEXT runtime·exit1(SB),NOSPLIT,$-4
TEXT runtime·open(SB),NOSPLIT,$-4
MOVL $5, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$-4
MOVL $6, AX
INT $0x80
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$-4
MOVL $3, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$-4
MOVL $4, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·getrlimit(SB),NOSPLIT,$-4
MOVL $194, AX
INT $0x80
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$16
@@ -98,7 +104,7 @@ TEXT runtime·raise(SB),NOSPLIT,$16
RET
TEXT runtime·mmap(SB),NOSPLIT,$32
- LEAL arg0+0(FP), SI
+ LEAL addr+0(FP), SI
LEAL 4(SP), DI
CLD
MOVSL
@@ -111,6 +117,7 @@ TEXT runtime·mmap(SB),NOSPLIT,$32
STOSL
MOVL $477, AX
INT $0x80
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$-4
@@ -167,9 +174,8 @@ TEXT runtime·nanotime(SB), NOSPLIT, $32
ADDL BX, AX
ADCL $0, DX
- MOVL ret+0(FP), DI
- MOVL AX, 0(DI)
- MOVL DX, 4(DI)
+ MOVL AX, ret_lo+0(FP)
+ MOVL DX, ret_hi+4(FP)
RET
@@ -183,9 +189,9 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-4
TEXT runtime·sigtramp(SB),NOSPLIT,$44
get_tls(CX)
- // check that m exists
- MOVL m(CX), BX
- CMPL BX, $0
+ // check that g exists
+ MOVL g(CX), DI
+ CMPL DI, $0
JNE 6(PC)
MOVL signo+0(FP), BX
MOVL BX, 0(SP)
@@ -194,10 +200,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
JMP sigtramp_ret
// save g
- MOVL g(CX), DI
MOVL DI, 20(SP)
// g = m->gsignal
+ MOVL g_m(DI), BX
MOVL m_gsignal(BX), BX
MOVL BX, g(CX)
@@ -314,7 +320,7 @@ TEXT runtime·i386_set_ldt(SB),NOSPLIT,$16
RET
TEXT runtime·sysctl(SB),NOSPLIT,$28
- LEAL arg0+0(FP), SI
+ LEAL mib+0(FP), SI
LEAL 4(SP), DI
CLD
MOVSL // arg 1 - name
@@ -325,10 +331,12 @@ TEXT runtime·sysctl(SB),NOSPLIT,$28
MOVSL // arg 6 - newlen
MOVL $202, AX // sys___sysctl
INT $0x80
- JAE 3(PC)
+ JAE 4(PC)
NEGL AX
+ MOVL AX, ret+24(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·osyield(SB),NOSPLIT,$-4
@@ -339,9 +347,9 @@ TEXT runtime·osyield(SB),NOSPLIT,$-4
TEXT runtime·sigprocmask(SB),NOSPLIT,$16
MOVL $0, 0(SP) // syscall gap
MOVL $3, 4(SP) // arg 1 - how (SIG_SETMASK)
- MOVL args+0(FP), AX
+ MOVL new+0(FP), AX
MOVL AX, 8(SP) // arg 2 - set
- MOVL args+4(FP), AX
+ MOVL old+4(FP), AX
MOVL AX, 12(SP) // arg 3 - oset
MOVL $340, AX // sys_sigprocmask
INT $0x80
@@ -355,6 +363,7 @@ TEXT runtime·kqueue(SB),NOSPLIT,$0
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
@@ -363,6 +372,7 @@ TEXT runtime·kevent(SB),NOSPLIT,$0
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+24(FP)
RET
// int32 runtime·closeonexec(int32 fd);
@@ -378,4 +388,4 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$32
NEGL AX
RET
-GLOBL runtime·tlsoffset(SB),$4
+GLOBL runtime·tlsoffset(SB),NOPTR,$4
diff --git a/src/pkg/runtime/sys_freebsd_amd64.s b/src/runtime/sys_freebsd_amd64.s
index 4c5b32504..65f8c1a6e 100644
--- a/src/pkg/runtime/sys_freebsd_amd64.s
+++ b/src/runtime/sys_freebsd_amd64.s
@@ -7,7 +7,7 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// FreeBSD 8, FreeBSD 9, and older versions that I have checked
// do not restore R10 on exit from a "restarted" system call
@@ -35,18 +35,19 @@
#define SYSCALL MOVQ R10, CX; INT $0x80
TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0
- MOVQ 8(SP), DI
- MOVL 16(SP), SI
- MOVL 20(SP), DX
- MOVQ 24(SP), R10
- MOVQ 32(SP), R8
+ MOVQ addr+0(FP), DI
+ MOVL mode+8(FP), SI
+ MOVL val+12(FP), DX
+ MOVQ ptr2+16(FP), R10
+ MOVQ ts+24(FP), R8
MOVL $454, AX
SYSCALL
+ MOVL AX, ret+32(FP)
RET
TEXT runtime·thr_new(SB),NOSPLIT,$0
- MOVQ 8(SP), DI
- MOVQ 16(SP), SI
+ MOVQ param+0(FP), DI
+ MOVL size+8(FP), SI
MOVL $455, AX
SYSCALL
RET
@@ -60,8 +61,8 @@ TEXT runtime·thr_start(SB),NOSPLIT,$0
// set up m, g
get_tls(CX)
- MOVQ R13, m(CX)
MOVQ m_g0(R13), DI
+ MOVQ R13, g_m(DI)
MOVQ DI, g(CX)
CALL runtime·stackcheck(SB)
@@ -71,54 +72,59 @@ TEXT runtime·thr_start(SB),NOSPLIT,$0
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 exit status
+ MOVL code+0(FP), DI // arg 1 exit status
MOVL $1, AX
SYSCALL
MOVL $0xf1, 0xf1 // crash
RET
TEXT runtime·exit1(SB),NOSPLIT,$-8
- MOVQ 8(SP), DI // arg 1 exit status
+ MOVL code+0(FP), DI // arg 1 exit status
MOVL $431, AX
SYSCALL
MOVL $0xf1, 0xf1 // crash
RET
TEXT runtime·open(SB),NOSPLIT,$-8
- MOVQ 8(SP), DI // arg 1 pathname
- MOVL 16(SP), SI // arg 2 flags
- MOVL 20(SP), DX // arg 3 mode
+ MOVQ name+0(FP), DI // arg 1 pathname
+ MOVL mode+8(FP), SI // arg 2 flags
+ MOVL perm+12(FP), DX // arg 3 mode
MOVL $5, AX
SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 fd
+ MOVL fd+0(FP), DI // arg 1 fd
MOVL $6, AX
SYSCALL
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 fd
- MOVQ 16(SP), SI // arg 2 buf
- MOVL 24(SP), DX // arg 3 count
+ MOVL fd+0(FP), DI // arg 1 fd
+ MOVQ p+8(FP), SI // arg 2 buf
+ MOVL n+16(FP), DX // arg 3 count
MOVL $3, AX
SYSCALL
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 fd
- MOVQ 16(SP), SI // arg 2 buf
- MOVL 24(SP), DX // arg 3 count
+ MOVQ fd+0(FP), DI // arg 1 fd
+ MOVQ p+8(FP), SI // arg 2 buf
+ MOVL n+16(FP), DX // arg 3 count
MOVL $4, AX
SYSCALL
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·getrlimit(SB),NOSPLIT,$-8
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
+ MOVL kind+0(FP), DI
+ MOVQ limit+8(FP), SI
MOVL $194, AX
SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$16
@@ -134,9 +140,9 @@ TEXT runtime·raise(SB),NOSPLIT,$16
RET
TEXT runtime·setitimer(SB), NOSPLIT, $-8
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
+ MOVL mode+0(FP), DI
+ MOVQ new+8(FP), SI
+ MOVQ old+16(FP), DX
MOVL $83, AX
SYSCALL
RET
@@ -169,12 +175,13 @@ TEXT runtime·nanotime(SB), NOSPLIT, $32
// return nsec in AX
IMULQ $1000000000, AX
ADDQ DX, AX
+ MOVQ AX, ret+0(FP)
RET
TEXT runtime·sigaction(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 sig
- MOVQ 16(SP), SI // arg 2 act
- MOVQ 24(SP), DX // arg 3 oact
+ MOVL sig+0(FP), DI // arg 1 sig
+ MOVQ new+8(FP), SI // arg 2 act
+ MOVQ old+16(FP), DX // arg 3 oact
MOVL $416, AX
SYSCALL
JCC 2(PC)
@@ -184,9 +191,9 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
TEXT runtime·sigtramp(SB),NOSPLIT,$64
get_tls(BX)
- // check that m exists
- MOVQ m(BX), BP
- CMPQ BP, $0
+ // check that g exists
+ MOVQ g(BX), R10
+ CMPQ R10, $0
JNE 5(PC)
MOVQ DI, 0(SP)
MOVQ $runtime·badsignal(SB), AX
@@ -194,10 +201,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
RET
// save g
- MOVQ g(BX), R10
MOVQ R10, 40(SP)
// g = m->signal
+ MOVQ g_m(R10), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
@@ -215,19 +222,20 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
RET
TEXT runtime·mmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 addr
- MOVQ 16(SP), SI // arg 2 len
- MOVL 24(SP), DX // arg 3 prot
- MOVL 28(SP), R10 // arg 4 flags
- MOVL 32(SP), R8 // arg 5 fid
- MOVL 36(SP), R9 // arg 6 offset
+ MOVQ addr+0(FP), DI // arg 1 addr
+ MOVQ n+8(FP), SI // arg 2 len
+ MOVL prot+16(FP), DX // arg 3 prot
+ MOVL flags+20(FP), R10 // arg 4 flags
+ MOVL fd+24(FP), R8 // arg 5 fid
+ MOVL off+28(FP), R9 // arg 6 offset
MOVL $477, AX
SYSCALL
+ MOVQ AX, ret+32(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 addr
- MOVQ 16(SP), SI // arg 2 len
+ MOVQ addr+0(FP), DI // arg 1 addr
+ MOVQ n+8(FP), SI // arg 2 len
MOVL $73, AX
SYSCALL
JCC 2(PC)
@@ -235,9 +243,9 @@ TEXT runtime·munmap(SB),NOSPLIT,$0
RET
TEXT runtime·madvise(SB),NOSPLIT,$0
- MOVQ 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
+ MOVQ addr+0(FP), DI
+ MOVQ n+8(FP), SI
+ MOVL flags+16(FP), DX
MOVQ $75, AX // madvise
SYSCALL
// ignore failure - maybe pages are locked
@@ -281,18 +289,20 @@ TEXT runtime·settls(SB),NOSPLIT,$8
RET
TEXT runtime·sysctl(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - name
- MOVL 16(SP), SI // arg 2 - namelen
- MOVQ 24(SP), DX // arg 3 - oldp
- MOVQ 32(SP), R10 // arg 4 - oldlenp
- MOVQ 40(SP), R8 // arg 5 - newp
- MOVQ 48(SP), R9 // arg 6 - newlen
+ MOVQ mib+0(FP), DI // arg 1 - name
+ MOVL miblen+8(FP), SI // arg 2 - namelen
+ MOVQ out+16(FP), DX // arg 3 - oldp
+ MOVQ size+24(FP), R10 // arg 4 - oldlenp
+ MOVQ dst+32(FP), R8 // arg 5 - newp
+ MOVQ ndst+40(FP), R9 // arg 6 - newlen
MOVQ $202, AX // sys___sysctl
SYSCALL
- JCC 3(PC)
+ JCC 4(PC)
NEGQ AX
+ MOVL AX, ret+48(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+48(FP)
RET
TEXT runtime·osyield(SB),NOSPLIT,$-4
@@ -302,8 +312,8 @@ TEXT runtime·osyield(SB),NOSPLIT,$-4
TEXT runtime·sigprocmask(SB),NOSPLIT,$0
MOVL $3, DI // arg 1 - how (SIG_SETMASK)
- MOVQ 8(SP), SI // arg 2 - set
- MOVQ 16(SP), DX // arg 3 - oset
+ MOVQ new+0(FP), SI // arg 2 - set
+ MOVQ old+8(FP), DX // arg 3 - oset
MOVL $340, AX // sys_sigprocmask
SYSCALL
JAE 2(PC)
@@ -319,25 +329,27 @@ TEXT runtime·kqueue(SB),NOSPLIT,$0
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
TEXT runtime·kevent(SB),NOSPLIT,$0
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVQ 32(SP), R10
- MOVL 40(SP), R8
- MOVQ 48(SP), R9
+ MOVL fd+0(FP), DI
+ MOVQ ev1+8(FP), SI
+ MOVL nev1+16(FP), DX
+ MOVQ ev2+24(FP), R10
+ MOVL nev2+32(FP), R8
+ MOVQ ts+40(FP), R9
MOVL $363, AX
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+48(FP)
RET
// void runtime·closeonexec(int32 fd);
TEXT runtime·closeonexec(SB),NOSPLIT,$0
- MOVL 8(SP), DI // fd
+ MOVL fd+0(FP), DI // fd
MOVQ $2, SI // F_SETFD
MOVQ $1, DX // FD_CLOEXEC
MOVL $92, AX // fcntl
diff --git a/src/pkg/runtime/sys_freebsd_arm.s b/src/runtime/sys_freebsd_arm.s
index 3ec95a651..d875138b6 100644
--- a/src/pkg/runtime/sys_freebsd_arm.s
+++ b/src/runtime/sys_freebsd_arm.s
@@ -7,7 +7,7 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// for EABI, as we don't support OABI
#define SYS_BASE 0x0
@@ -48,6 +48,7 @@ TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0
SWI $0
SUB $20, R13
// BCS error
+ MOVW R0, ret+20(FP)
RET
TEXT runtime·thr_new(SB),NOSPLIT,$0
@@ -58,10 +59,9 @@ TEXT runtime·thr_new(SB),NOSPLIT,$0
RET
TEXT runtime·thr_start(SB),NOSPLIT,$0
- MOVW R0, m
-
// set up g
- MOVW m_g0(m), g
+ MOVW m_g0(R0), g
+ MOVW R0, g_m(g)
BL runtime·emptyfunc(SB) // fault if stack check is wrong
BL runtime·mstart(SB)
@@ -92,6 +92,7 @@ TEXT runtime·open(SB),NOSPLIT,$-8
MOVW 8(FP), R2 // arg 3 perm
MOVW $SYS_open, R7
SWI $0
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$-8
@@ -100,6 +101,7 @@ TEXT runtime·read(SB),NOSPLIT,$-8
MOVW 8(FP), R2 // arg 3 count
MOVW $SYS_read, R7
SWI $0
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$-8
@@ -108,12 +110,14 @@ TEXT runtime·write(SB),NOSPLIT,$-8
MOVW 8(FP), R2 // arg 3 count
MOVW $SYS_write, R7
SWI $0
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$-8
MOVW 0(FP), R0 // arg 1 fd
MOVW $SYS_close, R7
SWI $0
+ MOVW R0, ret+4(FP)
RET
TEXT runtime·getrlimit(SB),NOSPLIT,$-8
@@ -121,6 +125,7 @@ TEXT runtime·getrlimit(SB),NOSPLIT,$-8
MOVW 4(FP), R1
MOVW $SYS_getrlimit, R7
SWI $0
+ MOVW R0, ret+8(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$8
@@ -179,9 +184,8 @@ TEXT runtime·nanotime(SB), NOSPLIT, $32
ADD.S R2, R0
ADC R4, R1
- MOVW 0(FP), R3
- MOVW R0, 0(R3)
- MOVW R1, 4(R3)
+ MOVW R0, ret_lo+0(FP)
+ MOVW R1, ret_hi+4(FP)
RET
TEXT runtime·sigaction(SB),NOSPLIT,$-8
@@ -196,14 +200,14 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
TEXT runtime·sigtramp(SB),NOSPLIT,$24
// this might be called in external code context,
- // where g and m are not set.
- // first save R0, because runtime·load_gm will clobber it
+ // where g is not set.
+ // first save R0, because runtime·load_g will clobber it
MOVW R0, 4(R13) // signum
MOVB runtime·iscgo(SB), R0
CMP $0, R0
- BL.NE runtime·load_gm(SB)
+ BL.NE runtime·load_g(SB)
- CMP $0, m
+ CMP $0, g
BNE 4(PC)
// signal number is already prepared in 4(R13)
MOVW $runtime·badsignal(SB), R11
@@ -215,7 +219,8 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
MOVW g, 20(R13)
// g = m->signal
- MOVW m_gsignal(m), g
+ MOVW g_m(g), R8
+ MOVW m_gsignal(R8), g
// R0 is already saved
MOVW R1, 8(R13) // info
@@ -247,6 +252,7 @@ TEXT runtime·mmap(SB),NOSPLIT,$16
SWI $0
SUB $4, R13
// TODO(dfc) error checking ?
+ MOVW R0, ret+24(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
@@ -307,6 +313,7 @@ TEXT runtime·sysctl(SB),NOSPLIT,$0
SWI $0
SUB.CS $0, R0, R0
SUB $20, R13
+ MOVW R0, ret+24(FP)
RET
TEXT runtime·osyield(SB),NOSPLIT,$-4
@@ -329,6 +336,7 @@ TEXT runtime·kqueue(SB),NOSPLIT,$0
MOVW $SYS_kqueue, R7
SWI $0
RSB.CS $0, R0
+ MOVW R0, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout)
@@ -342,6 +350,7 @@ TEXT runtime·kevent(SB),NOSPLIT,$0
SWI $0
RSB.CS $0, R0
SUB $20, R13
+ MOVW R0, ret+24(FP)
RET
// void runtime·closeonexec(int32 fd)
diff --git a/src/pkg/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s
index b7896f178..0f6d4bbb5 100644
--- a/src/pkg/runtime/sys_linux_386.s
+++ b/src/runtime/sys_linux_386.s
@@ -7,57 +7,62 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT runtime·exit(SB),NOSPLIT,$0
MOVL $252, AX // syscall number
- MOVL 4(SP), BX
+ MOVL code+0(FP), BX
CALL *runtime·_vdso(SB)
INT $3 // not reached
RET
TEXT runtime·exit1(SB),NOSPLIT,$0
MOVL $1, AX // exit - exit the current os thread
- MOVL 4(SP), BX
+ MOVL code+0(FP), BX
CALL *runtime·_vdso(SB)
INT $3 // not reached
RET
TEXT runtime·open(SB),NOSPLIT,$0
MOVL $5, AX // syscall - open
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
+ MOVL name+0(FP), BX
+ MOVL mode+4(FP), CX
+ MOVL perm+8(FP), DX
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$0
MOVL $6, AX // syscall - close
- MOVL 4(SP), BX
+ MOVL fd+0(FP), BX
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$0
MOVL $4, AX // syscall - write
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
+ MOVL fd+0(FP), BX
+ MOVL p+4(FP), CX
+ MOVL n+8(FP), DX
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$0
MOVL $3, AX // syscall - read
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
+ MOVL fd+0(FP), BX
+ MOVL p+4(FP), CX
+ MOVL n+8(FP), DX
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·getrlimit(SB),NOSPLIT,$0
MOVL $191, AX // syscall - ugetrlimit
- MOVL 4(SP), BX
- MOVL 8(SP), CX
+ MOVL kind+0(FP), BX
+ MOVL limit+4(FP), CX
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·usleep(SB),NOSPLIT,$8
@@ -87,20 +92,21 @@ TEXT runtime·raise(SB),NOSPLIT,$12
CALL *runtime·_vdso(SB)
RET
-TEXT runtime·setitimer(SB),NOSPLIT,$0-24
+TEXT runtime·setitimer(SB),NOSPLIT,$0-12
MOVL $104, AX // syscall - setitimer
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
+ MOVL mode+0(FP), BX
+ MOVL new+4(FP), CX
+ MOVL old+8(FP), DX
CALL *runtime·_vdso(SB)
RET
-TEXT runtime·mincore(SB),NOSPLIT,$0-24
+TEXT runtime·mincore(SB),NOSPLIT,$0-16
MOVL $218, AX // syscall - mincore
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
+ MOVL addr+0(FP), BX
+ MOVL n+4(FP), CX
+ MOVL dst+8(FP), DX
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+12(FP)
RET
// func now() (sec int64, nsec int32)
@@ -137,17 +143,16 @@ TEXT runtime·nanotime(SB), NOSPLIT, $32
ADDL BX, AX
ADCL $0, DX
- MOVL ret+0(FP), DI
- MOVL AX, 0(DI)
- MOVL DX, 4(DI)
+ MOVL AX, ret_lo+0(FP)
+ MOVL DX, ret_hi+4(FP)
RET
TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0
MOVL $175, AX // syscall entry
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
- MOVL 16(SP), SI
+ MOVL sig+0(FP), BX
+ MOVL new+4(FP), CX
+ MOVL old+8(FP), DX
+ MOVL size+12(FP), SI
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS 2(PC)
@@ -156,19 +161,20 @@ TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0
TEXT runtime·rt_sigaction(SB),NOSPLIT,$0
MOVL $174, AX // syscall - rt_sigaction
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
- MOVL 16(SP), SI
+ MOVL sig+0(FP), BX
+ MOVL new+4(FP), CX
+ MOVL old+8(FP), DX
+ MOVL size+12(FP), SI
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·sigtramp(SB),NOSPLIT,$44
get_tls(CX)
- // check that m exists
- MOVL m(CX), BX
- CMPL BX, $0
+ // check that g exists
+ MOVL g(CX), DI
+ CMPL DI, $0
JNE 6(PC)
MOVL sig+0(FP), BX
MOVL BX, 0(SP)
@@ -177,11 +183,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
RET
// save g
- MOVL g(CX), DI
MOVL DI, 20(SP)
// g = m->gsignal
- MOVL m(CX), BX
+ MOVL g_m(DI), BX
MOVL m_gsignal(BX), BX
MOVL BX, g(CX)
@@ -213,24 +218,25 @@ TEXT runtime·sigreturn(SB),NOSPLIT,$0
TEXT runtime·mmap(SB),NOSPLIT,$0
MOVL $192, AX // mmap2
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
- MOVL 16(SP), SI
- MOVL 20(SP), DI
- MOVL 24(SP), BP
+ MOVL addr+0(FP), BX
+ MOVL n+4(FP), CX
+ MOVL prot+8(FP), DX
+ MOVL flags+12(FP), SI
+ MOVL fd+16(FP), DI
+ MOVL off+20(FP), BP
SHRL $12, BP
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS 3(PC)
NOTL AX
INCL AX
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
MOVL $91, AX // munmap
- MOVL 4(SP), BX
- MOVL 8(SP), CX
+ MOVL addr+0(FP), BX
+ MOVL n+4(FP), CX
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS 2(PC)
@@ -239,9 +245,9 @@ TEXT runtime·munmap(SB),NOSPLIT,$0
TEXT runtime·madvise(SB),NOSPLIT,$0
MOVL $219, AX // madvise
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
+ MOVL addr+0(FP), BX
+ MOVL n+4(FP), CX
+ MOVL flags+8(FP), DX
CALL *runtime·_vdso(SB)
// ignore failure - maybe pages are locked
RET
@@ -250,13 +256,14 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
// struct timespec *timeout, int32 *uaddr2, int32 val2);
TEXT runtime·futex(SB),NOSPLIT,$0
MOVL $240, AX // futex
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
- MOVL 16(SP), SI
- MOVL 20(SP), DI
- MOVL 24(SP), BP
+ MOVL addr+0(FP), BX
+ MOVL op+4(FP), CX
+ MOVL val+8(FP), DX
+ MOVL ts+12(FP), SI
+ MOVL addr2+16(FP), DI
+ MOVL val3+20(FP), BP
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+24(FP)
RET
// int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
@@ -285,11 +292,12 @@ TEXT runtime·clone(SB),NOSPLIT,$0
// In parent, return.
CMPL AX, $0
- JEQ 2(PC)
+ JEQ 3(PC)
+ MOVL AX, ret+20(FP)
RET
// Paranoia: check that SP is as we expect.
- MOVL 12(SP), BP
+ MOVL mm+8(FP), BP
CMPL BP, $1234
JEQ 2(PC)
INT $3
@@ -300,8 +308,8 @@ TEXT runtime·clone(SB),NOSPLIT,$0
// In child on new stack. Reload registers (paranoia).
MOVL 0(SP), BX // m
- MOVL 4(SP), DX // g
- MOVL 8(SP), SI // fn
+ MOVL flags+0(FP), DX // g
+ MOVL stk+4(FP), SI // fn
MOVL AX, m_procid(BX) // save tid as m->procid
@@ -324,7 +332,7 @@ TEXT runtime·clone(SB),NOSPLIT,$0
// Now segment is established. Initialize m, g.
get_tls(AX)
MOVL DX, g(AX)
- MOVL BX, m(AX)
+ MOVL BX, g_m(DX)
CALL runtime·stackcheck(SB) // smashes AX, CX
MOVL 0(DX), DX // paranoia; check they are not nil
@@ -338,7 +346,6 @@ TEXT runtime·clone(SB),NOSPLIT,$0
CALL SI // fn()
CALL runtime·exit1(SB)
MOVL $0x1234, 0x1005
- RET
TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
MOVL $186, AX // sigaltstack
@@ -427,50 +434,55 @@ TEXT runtime·osyield(SB),NOSPLIT,$0
TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0
MOVL $242, AX // syscall - sched_getaffinity
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
+ MOVL pid+0(FP), BX
+ MOVL len+4(FP), CX
+ MOVL buf+8(FP), DX
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+12(FP)
RET
// int32 runtime·epollcreate(int32 size);
TEXT runtime·epollcreate(SB),NOSPLIT,$0
MOVL $254, AX
- MOVL 4(SP), BX
+ MOVL size+0(FP), BX
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+4(FP)
RET
// int32 runtime·epollcreate1(int32 flags);
TEXT runtime·epollcreate1(SB),NOSPLIT,$0
MOVL $329, AX
- MOVL 4(SP), BX
+ MOVL flags+0(FP), BX
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+4(FP)
RET
-// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev);
+// func epollctl(epfd, op, fd int32, ev *epollEvent) int
TEXT runtime·epollctl(SB),NOSPLIT,$0
MOVL $255, AX
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
- MOVL 16(SP), SI
+ MOVL epfd+0(FP), BX
+ MOVL op+4(FP), CX
+ MOVL fd+8(FP), DX
+ MOVL ev+12(FP), SI
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+16(FP)
RET
// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
TEXT runtime·epollwait(SB),NOSPLIT,$0
MOVL $256, AX
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
- MOVL 16(SP), SI
+ MOVL epfd+0(FP), BX
+ MOVL ev+4(FP), CX
+ MOVL nev+8(FP), DX
+ MOVL timeout+12(FP), SI
CALL *runtime·_vdso(SB)
+ MOVL AX, ret+16(FP)
RET
// void runtime·closeonexec(int32 fd);
TEXT runtime·closeonexec(SB),NOSPLIT,$0
MOVL $55, AX // fcntl
- MOVL 4(SP), BX // fd
+ MOVL fd+0(FP), BX // fd
MOVL $2, CX // F_SETFD
MOVL $1, DX // FD_CLOEXEC
CALL *runtime·_vdso(SB)
diff --git a/src/pkg/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
index b340c4f2c..33b91e872 100644
--- a/src/pkg/runtime/sys_linux_amd64.s
+++ b/src/runtime/sys_linux_amd64.s
@@ -7,55 +7,60 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
-TEXT runtime·exit(SB),NOSPLIT,$0-8
- MOVL 8(SP), DI
+TEXT runtime·exit(SB),NOSPLIT,$0-4
+ MOVL code+0(FP), DI
MOVL $231, AX // exitgroup - force all os threads to exit
SYSCALL
RET
-TEXT runtime·exit1(SB),NOSPLIT,$0-8
- MOVL 8(SP), DI
+TEXT runtime·exit1(SB),NOSPLIT,$0-4
+ MOVL code+0(FP), DI
MOVL $60, AX // exit - exit the current os thread
SYSCALL
RET
-TEXT runtime·open(SB),NOSPLIT,$0-16
- MOVQ 8(SP), DI
- MOVL 16(SP), SI
- MOVL 20(SP), DX
+TEXT runtime·open(SB),NOSPLIT,$0-20
+ MOVQ name+0(FP), DI
+ MOVL mode+8(FP), SI
+ MOVL perm+12(FP), DX
MOVL $2, AX // syscall entry
SYSCALL
+ MOVL AX, ret+16(FP)
RET
-TEXT runtime·close(SB),NOSPLIT,$0-16
- MOVL 8(SP), DI
+TEXT runtime·close(SB),NOSPLIT,$0-12
+ MOVL fd+0(FP), DI
MOVL $3, AX // syscall entry
SYSCALL
+ MOVL AX, ret+8(FP)
RET
-TEXT runtime·write(SB),NOSPLIT,$0-24
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
+TEXT runtime·write(SB),NOSPLIT,$0-28
+ MOVQ fd+0(FP), DI
+ MOVQ p+8(FP), SI
+ MOVL n+16(FP), DX
MOVL $1, AX // syscall entry
SYSCALL
+ MOVL AX, ret+24(FP)
RET
-TEXT runtime·read(SB),NOSPLIT,$0-24
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
+TEXT runtime·read(SB),NOSPLIT,$0-28
+ MOVL fd+0(FP), DI
+ MOVQ p+8(FP), SI
+ MOVL n+16(FP), DX
MOVL $0, AX // syscall entry
SYSCALL
+ MOVL AX, ret+24(FP)
RET
-TEXT runtime·getrlimit(SB),NOSPLIT,$0-24
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
+TEXT runtime·getrlimit(SB),NOSPLIT,$0-20
+ MOVL kind+0(FP), DI
+ MOVQ limit+8(FP), SI
MOVL $97, AX // syscall entry
SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·usleep(SB),NOSPLIT,$16
@@ -86,19 +91,20 @@ TEXT runtime·raise(SB),NOSPLIT,$0
RET
TEXT runtime·setitimer(SB),NOSPLIT,$0-24
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
+ MOVL mode+0(FP), DI
+ MOVQ new+8(FP), SI
+ MOVQ old+16(FP), DX
MOVL $38, AX // syscall entry
SYSCALL
RET
-TEXT runtime·mincore(SB),NOSPLIT,$0-24
- MOVQ 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
+TEXT runtime·mincore(SB),NOSPLIT,$0-28
+ MOVQ addr+0(FP), DI
+ MOVQ n+8(FP), SI
+ MOVQ dst+16(FP), DX
MOVL $27, AX // syscall entry
SYSCALL
+ MOVL AX, ret+24(FP)
RET
// func now() (sec int64, nsec int32)
@@ -145,6 +151,7 @@ TEXT runtime·nanotime(SB),NOSPLIT,$16
// return nsec in AX
IMULQ $1000000000, AX
ADDQ DX, AX
+ MOVQ AX, ret+0(FP)
RET
fallback_gtod_nt:
LEAQ 0(SP), DI
@@ -158,13 +165,14 @@ fallback_gtod_nt:
// return nsec in AX
IMULQ $1000000000, AX
ADDQ DX, AX
+ MOVQ AX, ret+0(FP)
RET
-TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0-32
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
- MOVL 32(SP), R10
+TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0-28
+ MOVL sig+0(FP), DI
+ MOVQ new+8(FP), SI
+ MOVQ old+16(FP), DX
+ MOVL size+24(FP), R10
MOVL $14, AX // syscall entry
SYSCALL
CMPQ AX, $0xfffffffffffff001
@@ -172,21 +180,22 @@ TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0-32
MOVL $0xf1, 0xf1 // crash
RET
-TEXT runtime·rt_sigaction(SB),NOSPLIT,$0-32
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
- MOVQ 32(SP), R10
+TEXT runtime·rt_sigaction(SB),NOSPLIT,$0-36
+ MOVQ sig+0(FP), DI
+ MOVQ new+8(FP), SI
+ MOVQ old+16(FP), DX
+ MOVQ size+24(FP), R10
MOVL $13, AX // syscall entry
SYSCALL
+ MOVL AX, ret+32(FP)
RET
TEXT runtime·sigtramp(SB),NOSPLIT,$64
get_tls(BX)
- // check that m exists
- MOVQ m(BX), BP
- CMPQ BP, $0
+ // check that g exists
+ MOVQ g(BX), R10
+ CMPQ R10, $0
JNE 5(PC)
MOVQ DI, 0(SP)
MOVQ $runtime·badsignal(SB), AX
@@ -194,10 +203,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
RET
// save g
- MOVQ g(BX), R10
MOVQ R10, 40(SP)
// g = m->gsignal
+ MOVQ g_m(R10), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
@@ -220,13 +229,12 @@ TEXT runtime·sigreturn(SB),NOSPLIT,$0
INT $3 // not reached
TEXT runtime·mmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI
- MOVQ $0, SI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVL 28(SP), R10
- MOVL 32(SP), R8
- MOVL 36(SP), R9
+ MOVQ addr+0(FP), DI
+ MOVQ n+8(FP), SI
+ MOVL prot+16(FP), DX
+ MOVL flags+20(FP), R10
+ MOVL fd+24(FP), R8
+ MOVL off+28(FP), R9
MOVL $9, AX // mmap
SYSCALL
@@ -234,11 +242,12 @@ TEXT runtime·mmap(SB),NOSPLIT,$0
JLS 3(PC)
NOTQ AX
INCQ AX
+ MOVQ AX, ret+32(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI
- MOVQ 16(SP), SI
+ MOVQ addr+0(FP), DI
+ MOVQ n+8(FP), SI
MOVQ $11, AX // munmap
SYSCALL
CMPQ AX, $0xfffffffffffff001
@@ -247,9 +256,9 @@ TEXT runtime·munmap(SB),NOSPLIT,$0
RET
TEXT runtime·madvise(SB),NOSPLIT,$0
- MOVQ 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
+ MOVQ addr+0(FP), DI
+ MOVQ n+8(FP), SI
+ MOVL flags+16(FP), DX
MOVQ $28, AX // madvise
SYSCALL
// ignore failure - maybe pages are locked
@@ -258,17 +267,18 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
// int64 futex(int32 *uaddr, int32 op, int32 val,
// struct timespec *timeout, int32 *uaddr2, int32 val2);
TEXT runtime·futex(SB),NOSPLIT,$0
- MOVQ 8(SP), DI
- MOVL 16(SP), SI
- MOVL 20(SP), DX
- MOVQ 24(SP), R10
- MOVQ 32(SP), R8
- MOVL 40(SP), R9
+ MOVQ addr+0(FP), DI
+ MOVL op+8(FP), SI
+ MOVL val+12(FP), DX
+ MOVQ ts+16(FP), R10
+ MOVQ addr2+24(FP), R8
+ MOVL val3+32(FP), R9
MOVL $202, AX
SYSCALL
+ MOVL AX, ret+40(FP)
RET
-// int64 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
+// int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL flags+8(SP), DI
MOVQ stack+16(SP), SI
@@ -284,7 +294,8 @@ TEXT runtime·clone(SB),NOSPLIT,$0
// In parent, return.
CMPQ AX, $0
- JEQ 2(PC)
+ JEQ 3(PC)
+ MOVL AX, ret+40(FP)
RET
// In child, on new stack.
@@ -301,7 +312,7 @@ TEXT runtime·clone(SB),NOSPLIT,$0
// In child, set up new stack
get_tls(CX)
- MOVQ R8, m(CX)
+ MOVQ R8, g_m(R9)
MOVQ R9, g(CX)
CALL runtime·stackcheck(SB)
@@ -343,50 +354,55 @@ TEXT runtime·osyield(SB),NOSPLIT,$0
RET
TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0
- MOVQ 8(SP), DI
- MOVL 16(SP), SI
- MOVQ 24(SP), DX
+ MOVQ pid+0(FP), DI
+ MOVQ len+8(FP), SI
+ MOVQ buf+16(FP), DX
MOVL $204, AX // syscall entry
SYSCALL
+ MOVL AX, ret+24(FP)
RET
// int32 runtime·epollcreate(int32 size);
TEXT runtime·epollcreate(SB),NOSPLIT,$0
- MOVL 8(SP), DI
+ MOVL size+0(FP), DI
MOVL $213, AX // syscall entry
SYSCALL
+ MOVL AX, ret+8(FP)
RET
// int32 runtime·epollcreate1(int32 flags);
TEXT runtime·epollcreate1(SB),NOSPLIT,$0
- MOVL 8(SP), DI
+ MOVL flags+0(FP), DI
MOVL $291, AX // syscall entry
SYSCALL
+ MOVL AX, ret+8(FP)
RET
-// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev);
+// func epollctl(epfd, op, fd int32, ev *epollEvent) int
TEXT runtime·epollctl(SB),NOSPLIT,$0
- MOVL 8(SP), DI
- MOVL 12(SP), SI
- MOVL 16(SP), DX
- MOVQ 24(SP), R10
+ MOVL epfd+0(FP), DI
+ MOVL op+4(FP), SI
+ MOVL fd+8(FP), DX
+ MOVQ ev+16(FP), R10
MOVL $233, AX // syscall entry
SYSCALL
+ MOVL AX, ret+24(FP)
RET
// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
TEXT runtime·epollwait(SB),NOSPLIT,$0
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVL 28(SP), R10
+ MOVL epfd+0(FP), DI
+ MOVQ ev+8(FP), SI
+ MOVL nev+16(FP), DX
+ MOVL timeout+20(FP), R10
MOVL $232, AX // syscall entry
SYSCALL
+ MOVL AX, ret+24(FP)
RET
// void runtime·closeonexec(int32 fd);
TEXT runtime·closeonexec(SB),NOSPLIT,$0
- MOVL 8(SP), DI // fd
+ MOVL fd+0(FP), DI // fd
MOVQ $2, SI // F_SETFD
MOVQ $1, DX // FD_CLOEXEC
MOVL $72, AX // fcntl
diff --git a/src/pkg/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s
index c537a8722..bd285f399 100644
--- a/src/pkg/runtime/sys_linux_arm.s
+++ b/src/runtime/sys_linux_arm.s
@@ -7,7 +7,7 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// for EABI, as we don't support OABI
#define SYS_BASE 0x0
@@ -51,12 +51,14 @@ TEXT runtime·open(SB),NOSPLIT,$0
MOVW 8(FP), R2
MOVW $SYS_open, R7
SWI $0
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$0
MOVW 0(FP), R0
MOVW $SYS_close, R7
SWI $0
+ MOVW R0, ret+4(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$0
@@ -65,6 +67,7 @@ TEXT runtime·write(SB),NOSPLIT,$0
MOVW 8(FP), R2
MOVW $SYS_write, R7
SWI $0
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$0
@@ -73,6 +76,7 @@ TEXT runtime·read(SB),NOSPLIT,$0
MOVW 8(FP), R2
MOVW $SYS_read, R7
SWI $0
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·getrlimit(SB),NOSPLIT,$0
@@ -80,6 +84,7 @@ TEXT runtime·getrlimit(SB),NOSPLIT,$0
MOVW 4(FP), R1
MOVW $SYS_ugetrlimit, R7
SWI $0
+ MOVW R0, ret+8(FP)
RET
TEXT runtime·exit(SB),NOSPLIT,$-4
@@ -119,6 +124,7 @@ TEXT runtime·mmap(SB),NOSPLIT,$0
MOVW $0xfffff001, R6
CMP R6, R0
RSB.HI $0, R0
+ MOVW R0, ret+24(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
@@ -155,6 +161,7 @@ TEXT runtime·mincore(SB),NOSPLIT,$0
MOVW 8(FP), R2
MOVW $SYS_mincore, R7
SWI $0
+ MOVW R0, ret+12(FP)
RET
TEXT time·now(SB), NOSPLIT, $32
@@ -172,8 +179,7 @@ TEXT time·now(SB), NOSPLIT, $32
MOVW R2, 8(FP)
RET
-// int64 nanotime(void) so really
-// void nanotime(int64 *nsec)
+// int64 nanotime(void)
TEXT runtime·nanotime(SB),NOSPLIT,$32
MOVW $1, R0 // CLOCK_MONOTONIC
MOVW $8(R13), R1 // timespec
@@ -189,9 +195,8 @@ TEXT runtime·nanotime(SB),NOSPLIT,$32
ADD.S R2, R0
ADC R4, R1
- MOVW 0(FP), R3
- MOVW R0, 0(R3)
- MOVW R1, 4(R3)
+ MOVW R0, ret_lo+0(FP)
+ MOVW R1, ret_hi+4(FP)
RET
// int32 futex(int32 *uaddr, int32 op, int32 val,
@@ -205,13 +210,14 @@ TEXT runtime·futex(SB),NOSPLIT,$0
MOVW 24(SP), R5
MOVW $SYS_futex, R7
SWI $0
+ MOVW R0, ret+24(FP)
RET
// int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVW flags+0(FP), R0
- MOVW stack+4(FP), R1
+ MOVW stk+4(FP), R1
MOVW $0, R2 // parent tid ptr
MOVW $0, R3 // tls_val
MOVW $0, R4 // child tid ptr
@@ -234,7 +240,8 @@ TEXT runtime·clone(SB),NOSPLIT,$0
// In parent, return.
CMP $0, R0
- BEQ 2(PC)
+ BEQ 3(PC)
+ MOVW R0, ret+20(FP)
RET
// Paranoia: check that SP is as we expect. Use R13 to avoid linker 'fixup'
@@ -244,11 +251,12 @@ TEXT runtime·clone(SB),NOSPLIT,$0
BEQ 2(PC)
BL runtime·abort(SB)
- MOVW 0(R13), m
MOVW 4(R13), g
+ MOVW 0(R13), R8
+ MOVW R8, g_m(g)
// paranoia; check they are not nil
- MOVW 0(m), R0
+ MOVW 0(R8), R0
MOVW 0(g), R0
BL runtime·emptyfunc(SB) // fault if stack check is wrong
@@ -256,7 +264,8 @@ TEXT runtime·clone(SB),NOSPLIT,$0
// Initialize m->procid to Linux tid
MOVW $SYS_gettid, R7
SWI $0
- MOVW R0, m_procid(m)
+ MOVW g_m(g), R8
+ MOVW R0, m_procid(R8)
// Call fn
MOVW 8(R13), R0
@@ -285,14 +294,14 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$0
TEXT runtime·sigtramp(SB),NOSPLIT,$24
// this might be called in external code context,
- // where g and m are not set.
- // first save R0, because runtime·load_gm will clobber it
+ // where g is not set.
+ // first save R0, because runtime·load_g will clobber it
MOVW R0, 4(R13)
MOVB runtime·iscgo(SB), R0
CMP $0, R0
- BL.NE runtime·load_gm(SB)
+ BL.NE runtime·load_g(SB)
- CMP $0, m
+ CMP $0, g
BNE 4(PC)
// signal number is already prepared in 4(R13)
MOVW $runtime·badsignal(SB), R11
@@ -304,7 +313,8 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
MOVW g, 20(R13)
// g = m->gsignal
- MOVW m_gsignal(m), g
+ MOVW g_m(g), R8
+ MOVW m_gsignal(R8), g
// copy arguments for call to sighandler
// R0 is already saved above
@@ -335,11 +345,7 @@ TEXT runtime·rt_sigaction(SB),NOSPLIT,$0
MOVW 12(FP), R3
MOVW $SYS_rt_sigaction, R7
SWI $0
- RET
-
-TEXT runtime·sigreturn(SB),NOSPLIT,$0
- MOVW $SYS_rt_sigreturn, R7
- SWI $0
+ MOVW R0, ret+16(FP)
RET
TEXT runtime·usleep(SB),NOSPLIT,$12
@@ -365,22 +371,24 @@ TEXT cas<>(SB),NOSPLIT,$0
MOVW $0xffff0fc0, PC
TEXT runtime·cas(SB),NOSPLIT,$0
- MOVW valptr+0(FP), R2
+ MOVW ptr+0(FP), R2
MOVW old+4(FP), R0
casagain:
MOVW new+8(FP), R1
BL cas<>(SB)
BCC cascheck
MOVW $1, R0
+ MOVB R0, ret+12(FP)
RET
cascheck:
// Kernel lies; double-check.
- MOVW valptr+0(FP), R2
+ MOVW ptr+0(FP), R2
MOVW old+4(FP), R0
MOVW 0(R2), R3
CMP R0, R3
BEQ casagain
MOVW $0, R0
+ MOVB R0, ret+12(FP)
RET
TEXT runtime·casp(SB),NOSPLIT,$0
@@ -397,6 +405,7 @@ TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0
MOVW 8(FP), R2
MOVW $SYS_sched_getaffinity, R7
SWI $0
+ MOVW R0, ret+12(FP)
RET
// int32 runtime·epollcreate(int32 size)
@@ -404,6 +413,7 @@ TEXT runtime·epollcreate(SB),NOSPLIT,$0
MOVW 0(FP), R0
MOVW $SYS_epoll_create, R7
SWI $0
+ MOVW R0, ret+4(FP)
RET
// int32 runtime·epollcreate1(int32 flags)
@@ -411,16 +421,18 @@ TEXT runtime·epollcreate1(SB),NOSPLIT,$0
MOVW 0(FP), R0
MOVW $SYS_epoll_create1, R7
SWI $0
+ MOVW R0, ret+4(FP)
RET
-// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev)
+// func epollctl(epfd, op, fd int32, ev *epollEvent) int
TEXT runtime·epollctl(SB),NOSPLIT,$0
- MOVW 0(FP), R0
- MOVW 4(FP), R1
- MOVW 8(FP), R2
- MOVW 12(FP), R3
+ MOVW epfd+0(FP), R0
+ MOVW op+4(FP), R1
+ MOVW fd+8(FP), R2
+ MOVW ev+12(FP), R3
MOVW $SYS_epoll_ctl, R7
SWI $0
+ MOVW R0, ret+16(FP)
RET
// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout)
@@ -431,6 +443,7 @@ TEXT runtime·epollwait(SB),NOSPLIT,$0
MOVW 12(FP), R3
MOVW $SYS_epoll_wait, R7
SWI $0
+ MOVW R0, ret+16(FP)
RET
// void runtime·closeonexec(int32 fd)
diff --git a/src/pkg/runtime/sys_nacl_386.s b/src/runtime/sys_nacl_386.s
index 42ba0e0ed..47985f31f 100644
--- a/src/pkg/runtime/sys_nacl_386.s
+++ b/src/runtime/sys_nacl_386.s
@@ -3,31 +3,54 @@
// license that can be found in the LICENSE file.
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#include "syscall_nacl.h"
#define NACL_SYSCALL(code) \
MOVL $(0x10000 + ((code)<<5)), AX; CALL AX
-#define NACL_SYSJMP(code) \
- MOVL $(0x10000 + ((code)<<5)), AX; JMP AX
+TEXT runtime·exit(SB),NOSPLIT,$4
+ MOVL code+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_exit)
+ JMP 0(PC)
-TEXT runtime·exit(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_exit)
-
-TEXT runtime·exit1(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_thread_exit)
+TEXT runtime·exit1(SB),NOSPLIT,$4
+ MOVL code+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_thread_exit)
+ RET
-TEXT runtime·open(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_open)
+TEXT runtime·open(SB),NOSPLIT,$12
+ MOVL name+0(FP), AX
+ MOVL AX, 0(SP)
+ MOVL mode+4(FP), AX
+ MOVL AX, 4(SP)
+ MOVL perm+8(FP), AX
+ MOVL AX, 8(SP)
+ NACL_SYSCALL(SYS_open)
+ MOVL AX, ret+12(FP)
+ RET
-TEXT runtime·close(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_close)
+TEXT runtime·close(SB),NOSPLIT,$4
+ MOVL fd+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_close)
+ MOVL AX, ret+4(FP)
+ RET
-TEXT runtime·read(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_read)
+TEXT runtime·read(SB),NOSPLIT,$12
+ MOVL fd+0(FP), AX
+ MOVL AX, 0(SP)
+ MOVL p+4(FP), AX
+ MOVL AX, 4(SP)
+ MOVL n+8(FP), AX
+ MOVL AX, 8(SP)
+ NACL_SYSCALL(SYS_read)
+ MOVL AX, ret+12(FP)
+ RET
-TEXT syscall·naclWrite(SB), NOSPLIT, $12-16
+TEXT syscall·naclWrite(SB), NOSPLIT, $16-16
MOVL arg1+0(FP), DI
MOVL arg2+4(FP), SI
MOVL arg3+8(FP), DX
@@ -38,80 +61,172 @@ TEXT syscall·naclWrite(SB), NOSPLIT, $12-16
MOVL AX, ret+16(FP)
RET
-TEXT runtime·write(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_write)
+TEXT runtime·write(SB),NOSPLIT,$12
+ MOVL fd+0(FP), AX
+ MOVL AX, 0(SP)
+ MOVL p+4(FP), AX
+ MOVL AX, 4(SP)
+ MOVL n+8(FP), AX
+ MOVL AX, 8(SP)
+ NACL_SYSCALL(SYS_write)
+ MOVL AX, ret+12(FP)
+ RET
-TEXT runtime·nacl_exception_stack(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_exception_stack)
+TEXT runtime·nacl_exception_stack(SB),NOSPLIT,$8
+ MOVL p+0(FP), AX
+ MOVL AX, 0(SP)
+ MOVL size+4(FP), AX
+ MOVL AX, 4(SP)
+ NACL_SYSCALL(SYS_exception_stack)
+ MOVL AX, ret+8(FP)
+ RET
-TEXT runtime·nacl_exception_handler(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_exception_handler)
+TEXT runtime·nacl_exception_handler(SB),NOSPLIT,$8
+ MOVL fn+0(FP), AX
+ MOVL AX, 0(SP)
+ MOVL arg+4(FP), AX
+ MOVL AX, 4(SP)
+ NACL_SYSCALL(SYS_exception_handler)
+ MOVL AX, ret+8(FP)
+ RET
-TEXT runtime·nacl_sem_create(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_sem_create)
+TEXT runtime·nacl_sem_create(SB),NOSPLIT,$4
+ MOVL flag+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_sem_create)
+ MOVL AX, ret+4(FP)
+ RET
-TEXT runtime·nacl_sem_wait(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_sem_wait)
+TEXT runtime·nacl_sem_wait(SB),NOSPLIT,$4
+ MOVL sem+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_sem_wait)
+ MOVL AX, ret+4(FP)
+ RET
-TEXT runtime·nacl_sem_post(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_sem_post)
+TEXT runtime·nacl_sem_post(SB),NOSPLIT,$4
+ MOVL sem+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_sem_post)
+ MOVL AX, ret+4(FP)
+ RET
-TEXT runtime·nacl_mutex_create(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_mutex_create)
+TEXT runtime·nacl_mutex_create(SB),NOSPLIT,$4
+ MOVL flag+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_mutex_create)
+ MOVL AX, ret+4(FP)
+ RET
-TEXT runtime·nacl_mutex_lock(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_mutex_lock)
+TEXT runtime·nacl_mutex_lock(SB),NOSPLIT,$4
+ MOVL mutex+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_mutex_lock)
+ MOVL AX, ret+4(FP)
+ RET
-TEXT runtime·nacl_mutex_trylock(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_mutex_trylock)
+TEXT runtime·nacl_mutex_trylock(SB),NOSPLIT,$4
+ MOVL mutex+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_mutex_trylock)
+ MOVL AX, ret+4(FP)
+ RET
-TEXT runtime·nacl_mutex_unlock(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_mutex_unlock)
+TEXT runtime·nacl_mutex_unlock(SB),NOSPLIT,$4
+ MOVL mutex+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_mutex_unlock)
+ MOVL AX, ret+4(FP)
+ RET
-TEXT runtime·nacl_cond_create(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_cond_create)
+TEXT runtime·nacl_cond_create(SB),NOSPLIT,$4
+ MOVL flag+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_cond_create)
+ MOVL AX, ret+4(FP)
+ RET
-TEXT runtime·nacl_cond_wait(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_cond_wait)
+TEXT runtime·nacl_cond_wait(SB),NOSPLIT,$8
+ MOVL cond+0(FP), AX
+ MOVL AX, 0(SP)
+ MOVL n+4(FP), AX
+ MOVL AX, 4(SP)
+ NACL_SYSCALL(SYS_cond_wait)
+ MOVL AX, ret+8(FP)
+ RET
-TEXT runtime·nacl_cond_signal(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_cond_signal)
+TEXT runtime·nacl_cond_signal(SB),NOSPLIT,$4
+ MOVL cond+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_cond_signal)
+ MOVL AX, ret+4(FP)
+ RET
-TEXT runtime·nacl_cond_broadcast(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_cond_broadcast)
+TEXT runtime·nacl_cond_broadcast(SB),NOSPLIT,$4
+ MOVL cond+0(FP), AX
+ MOVL AX, 0(SP)
+ NACL_SYSCALL(SYS_cond_broadcast)
+ MOVL AX, ret+4(FP)
+ RET
-TEXT runtime·nacl_cond_timed_wait_abs(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_cond_timed_wait_abs)
+TEXT runtime·nacl_cond_timed_wait_abs(SB),NOSPLIT,$12
+ MOVL cond+0(FP), AX
+ MOVL AX, 0(SP)
+ MOVL lock+4(FP), AX
+ MOVL AX, 4(SP)
+ MOVL ts+8(FP), AX
+ MOVL AX, 8(SP)
+ NACL_SYSCALL(SYS_cond_timed_wait_abs)
+ MOVL AX, ret+12(FP)
+ RET
-TEXT runtime·nacl_thread_create(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_thread_create)
+TEXT runtime·nacl_thread_create(SB),NOSPLIT,$16
+ MOVL fn+0(FP), AX
+ MOVL AX, 0(SP)
+ MOVL stk+4(FP), AX
+ MOVL AX, 4(SP)
+ MOVL tls+8(FP), AX
+ MOVL AX, 8(SP)
+ MOVL xx+12(FP), AX
+ MOVL AX, 12(SP)
+ NACL_SYSCALL(SYS_thread_create)
+ MOVL AX, ret+16(FP)
+ RET
TEXT runtime·mstart_nacl(SB),NOSPLIT,$0
JMP runtime·mstart(SB)
-TEXT runtime·nacl_nanosleep(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_nanosleep)
+TEXT runtime·nacl_nanosleep(SB),NOSPLIT,$8
+ MOVL ts+0(FP), AX
+ MOVL AX, 0(SP)
+ MOVL extra+4(FP), AX
+ MOVL AX, 4(SP)
+ NACL_SYSCALL(SYS_nanosleep)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·osyield(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_sched_yield)
+ NACL_SYSCALL(SYS_sched_yield)
+ RET
TEXT runtime·mmap(SB),NOSPLIT,$32
- MOVL arg1+0(FP), AX
+ MOVL addr+0(FP), AX
MOVL AX, 0(SP)
- MOVL arg2+4(FP), AX
+ MOVL n+4(FP), AX
MOVL AX, 4(SP)
- MOVL arg3+8(FP), AX
+ MOVL prot+8(FP), AX
MOVL AX, 8(SP)
- MOVL arg4+12(FP), AX
+ MOVL flags+12(FP), AX
MOVL AX, 12(SP)
- MOVL arg5+16(FP), AX
+ MOVL fd+16(FP), AX
MOVL AX, 16(SP)
- MOVL arg6+20(FP), AX
+ MOVL off+20(FP), AX
MOVL AX, 24(SP)
MOVL $0, 28(SP)
LEAL 24(SP), AX
MOVL AX, 20(SP)
NACL_SYSCALL(SYS_mmap)
+ MOVL AX, ret+24(FP)
RET
TEXT time·now(SB),NOSPLIT,$20
@@ -132,8 +247,14 @@ TEXT time·now(SB),NOSPLIT,$20
TEXT syscall·now(SB),NOSPLIT,$0
JMP time·now(SB)
-TEXT runtime·nacl_clock_gettime(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_clock_gettime)
+TEXT runtime·nacl_clock_gettime(SB),NOSPLIT,$8
+ MOVL arg1+0(FP), AX
+ MOVL AX, 0(SP)
+ MOVL arg2+4(FP), AX
+ MOVL AX, 4(SP)
+ NACL_SYSCALL(SYS_clock_gettime)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nanotime(SB),NOSPLIT,$20
MOVL $0, 0(SP) // real time clock
@@ -150,9 +271,8 @@ TEXT runtime·nanotime(SB),NOSPLIT,$20
ADDL BX, AX
ADCL $0, DX
- MOVL ret+0(FP), DI
- MOVL AX, 0(DI)
- MOVL DX, 4(DI)
+ MOVL AX, ret_lo+0(FP)
+ MOVL DX, ret_hi+4(FP)
RET
TEXT runtime·setldt(SB),NOSPLIT,$8
@@ -165,21 +285,21 @@ TEXT runtime·setldt(SB),NOSPLIT,$8
TEXT runtime·sigtramp(SB),NOSPLIT,$0
get_tls(CX)
- // check that m exists
- MOVL m(CX), BX
- CMPL BX, $0
+ // check that g exists
+ MOVL g(CX), DI
+ CMPL DI, $0
JNE 6(PC)
MOVL $11, BX
- MOVL BX, 0(SP)
+ MOVL $0, 0(SP)
MOVL $runtime·badsignal(SB), AX
CALL AX
JMP sigtramp_ret
// save g
- MOVL g(CX), DI
MOVL DI, 20(SP)
// g = m->gsignal
+ MOVL g_m(DI), BX
MOVL m_gsignal(BX), BX
MOVL BX, g(CX)
diff --git a/src/pkg/runtime/sys_nacl_amd64p32.s b/src/runtime/sys_nacl_amd64p32.s
index 43c172372..4eb4aacdd 100644
--- a/src/pkg/runtime/sys_nacl_amd64p32.s
+++ b/src/runtime/sys_nacl_amd64p32.s
@@ -3,44 +3,49 @@
// license that can be found in the LICENSE file.
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#include "syscall_nacl.h"
#define NACL_SYSCALL(code) \
MOVL $(0x10000 + ((code)<<5)), AX; CALL AX
-#define NACL_SYSJMP(code) \
- MOVL $(0x10000 + ((code)<<5)), AX; JMP AX
-
TEXT runtime·settls(SB),NOSPLIT,$0
MOVL DI, TLS // really BP
RET
TEXT runtime·exit(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_exit)
+ MOVL code+0(FP), DI
+ NACL_SYSCALL(SYS_exit)
+ RET
TEXT runtime·exit1(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_thread_exit)
+ MOVL code+0(FP), DI
+ NACL_SYSCALL(SYS_thread_exit)
+ RET
TEXT runtime·open(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- MOVL arg2+4(FP), SI
- MOVL arg3+8(FP), DX
- NACL_SYSJMP(SYS_open)
+ MOVL name+0(FP), DI
+ MOVL mode+4(FP), SI
+ MOVL perm+8(FP), DX
+ NACL_SYSCALL(SYS_open)
+ MOVL AX, ret+16(FP)
+ RET
TEXT runtime·close(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_close)
+ MOVL fd+0(FP), DI
+ NACL_SYSCALL(SYS_close)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·read(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- MOVL arg2+4(FP), SI
- MOVL arg3+8(FP), DX
- NACL_SYSJMP(SYS_read)
+ MOVL fd+0(FP), DI
+ MOVL p+4(FP), SI
+ MOVL n+8(FP), DX
+ NACL_SYSCALL(SYS_read)
+ MOVL AX, ret+16(FP)
+ RET
-TEXT syscall·naclWrite(SB), NOSPLIT, $16-20
+TEXT syscall·naclWrite(SB), NOSPLIT, $24-20
MOVL arg1+0(FP), DI
MOVL arg2+4(FP), SI
MOVL arg3+8(FP), DX
@@ -48,16 +53,17 @@ TEXT syscall·naclWrite(SB), NOSPLIT, $16-20
MOVL SI, 4(SP)
MOVL DX, 8(SP)
CALL runtime·write(SB)
+ MOVL 16(SP), AX
MOVL AX, ret+16(FP)
RET
-TEXT runtime·write(SB),NOSPLIT,$16-12
+TEXT runtime·write(SB),NOSPLIT,$16-20
// If using fake time and writing to stdout or stderr,
// emit playback header before actual data.
- MOVQ runtime·timens(SB), AX
+ MOVQ runtime·faketime(SB), AX
CMPQ AX, $0
JEQ write
- MOVL arg1+0(FP), DI
+ MOVL fd+0(FP), DI
CMPL DI, $1
JEQ playback
CMPL DI, $2
@@ -65,10 +71,11 @@ TEXT runtime·write(SB),NOSPLIT,$16-12
write:
// Ordinary write.
- MOVL arg1+0(FP), DI
- MOVL arg2+4(FP), SI
- MOVL arg3+8(FP), DX
+ MOVL fd+0(FP), DI
+ MOVL p+4(FP), SI
+ MOVL n+8(FP), DX
NACL_SYSCALL(SYS_write)
+ MOVL AX, ret+16(FP)
RET
// Write with playback header.
@@ -83,7 +90,7 @@ playback:
MOVL $(('B'<<24) | ('P'<<16)), 0(SP)
BSWAPQ AX
MOVQ AX, 4(SP)
- MOVL arg3+8(FP), DX
+ MOVL n+8(FP), DX
BSWAPL DX
MOVL DX, 12(SP)
MOVL $1, DI // standard output
@@ -93,82 +100,113 @@ playback:
// Write actual data.
MOVL $1, DI // standard output
- MOVL arg2+4(FP), SI
- MOVL arg3+8(FP), DX
+ MOVL p+4(FP), SI
+ MOVL n+8(FP), DX
NACL_SYSCALL(SYS_write)
// Unlock.
MOVL $0, runtime·writelock(SB)
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·nacl_exception_stack(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- MOVL arg2+4(FP), SI
- NACL_SYSJMP(SYS_exception_stack)
+ MOVL p+0(FP), DI
+ MOVL size+4(FP), SI
+ NACL_SYSCALL(SYS_exception_stack)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_exception_handler(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- MOVL arg2+4(FP), SI
- NACL_SYSJMP(SYS_exception_handler)
+ MOVL fn+0(FP), DI
+ MOVL arg+4(FP), SI
+ NACL_SYSCALL(SYS_exception_handler)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_sem_create(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_sem_create)
+ MOVL flag+0(FP), DI
+ NACL_SYSCALL(SYS_sem_create)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_sem_wait(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_sem_wait)
+ MOVL sem+0(FP), DI
+ NACL_SYSCALL(SYS_sem_wait)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_sem_post(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_sem_post)
+ MOVL sem+0(FP), DI
+ NACL_SYSCALL(SYS_sem_post)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_mutex_create(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_mutex_create)
+ MOVL flag+0(FP), DI
+ NACL_SYSCALL(SYS_mutex_create)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_mutex_lock(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_mutex_lock)
+ MOVL mutex+0(FP), DI
+ NACL_SYSCALL(SYS_mutex_lock)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_mutex_trylock(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_mutex_trylock)
+ MOVL mutex+0(FP), DI
+ NACL_SYSCALL(SYS_mutex_trylock)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_mutex_unlock(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_mutex_unlock)
+ MOVL mutex+0(FP), DI
+ NACL_SYSCALL(SYS_mutex_unlock)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_cond_create(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_cond_create)
+ MOVL flag+0(FP), DI
+ NACL_SYSCALL(SYS_cond_create)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_cond_wait(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- MOVL arg2+4(FP), SI
- NACL_SYSJMP(SYS_cond_wait)
+ MOVL cond+0(FP), DI
+ MOVL n+4(FP), SI
+ NACL_SYSCALL(SYS_cond_wait)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_cond_signal(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_cond_signal)
+ MOVL cond+0(FP), DI
+ NACL_SYSCALL(SYS_cond_signal)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_cond_broadcast(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- NACL_SYSJMP(SYS_cond_broadcast)
+ MOVL cond+0(FP), DI
+ NACL_SYSCALL(SYS_cond_broadcast)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nacl_cond_timed_wait_abs(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- MOVL arg2+4(FP), SI
- MOVL arg3+8(FP), DX
- NACL_SYSJMP(SYS_cond_timed_wait_abs)
+ MOVL cond+0(FP), DI
+ MOVL lock+4(FP), SI
+ MOVL ts+8(FP), DX
+ NACL_SYSCALL(SYS_cond_timed_wait_abs)
+ MOVL AX, ret+16(FP)
+ RET
TEXT runtime·nacl_thread_create(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- MOVL arg2+4(FP), SI
- MOVL arg3+8(FP), DX
- MOVL arg4+12(FP), CX
- NACL_SYSJMP(SYS_thread_create)
+ MOVL fn+0(FP), DI
+ MOVL stk+4(FP), SI
+ MOVL tls+8(FP), DX
+ MOVL xx+12(FP), CX
+ NACL_SYSCALL(SYS_thread_create)
+ MOVL AX, ret+16(FP)
+ RET
TEXT runtime·mstart_nacl(SB),NOSPLIT,$0
NACL_SYSCALL(SYS_tls_get)
@@ -177,30 +215,34 @@ TEXT runtime·mstart_nacl(SB),NOSPLIT,$0
JMP runtime·mstart(SB)
TEXT runtime·nacl_nanosleep(SB),NOSPLIT,$0
- MOVL arg1+0(FP), DI
- MOVL arg2+4(FP), SI
- NACL_SYSJMP(SYS_nanosleep)
+ MOVL ts+0(FP), DI
+ MOVL extra+4(FP), SI
+ NACL_SYSCALL(SYS_nanosleep)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·osyield(SB),NOSPLIT,$0
- NACL_SYSJMP(SYS_sched_yield)
+ NACL_SYSCALL(SYS_sched_yield)
+ RET
TEXT runtime·mmap(SB),NOSPLIT,$8
- MOVL arg1+0(FP), DI
- MOVL arg2+4(FP), SI
- MOVL arg3+8(FP), DX
- MOVL arg4+12(FP), CX
- MOVL arg5+16(FP), R8
- MOVL arg6+20(FP), AX
+ MOVL addr+0(FP), DI
+ MOVL n+4(FP), SI
+ MOVL prot+8(FP), DX
+ MOVL flags+12(FP), CX
+ MOVL fd+16(FP), R8
+ MOVL off+20(FP), AX
MOVQ AX, 0(SP)
MOVL SP, R9
NACL_SYSCALL(SYS_mmap)
CMPL AX, $-4095
JNA 2(PC)
NEGL AX
+ MOVL AX, ret+24(FP)
RET
TEXT time·now(SB),NOSPLIT,$16
- MOVQ runtime·timens(SB), AX
+ MOVQ runtime·faketime(SB), AX
CMPQ AX, $0
JEQ realtime
MOVQ $0, DX
@@ -230,12 +272,15 @@ TEXT syscall·now(SB),NOSPLIT,$0
TEXT runtime·nacl_clock_gettime(SB),NOSPLIT,$0
MOVL arg1+0(FP), DI
MOVL arg2+4(FP), SI
- NACL_SYSJMP(SYS_clock_gettime)
+ NACL_SYSCALL(SYS_clock_gettime)
+ MOVL AX, ret+8(FP)
+ RET
TEXT runtime·nanotime(SB),NOSPLIT,$16
- MOVQ runtime·timens(SB), AX
+ MOVQ runtime·faketime(SB), AX
CMPQ AX, $0
- JEQ 2(PC)
+ JEQ 3(PC)
+ MOVQ AX, ret+0(FP)
RET
MOVL $0, DI // real time clock
LEAL 0(SP), AX
@@ -248,6 +293,7 @@ TEXT runtime·nanotime(SB),NOSPLIT,$16
// return nsec in AX
IMULQ $1000000000, AX
ADDQ DX, AX
+ MOVQ AX, ret+0(FP)
RET
TEXT runtime·sigtramp(SB),NOSPLIT,$80
@@ -261,18 +307,18 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$80
MOVL (16*4+5*8)(AX), AX
MOVL AX, TLS
- // check that m exists
+ // check that g exists
get_tls(CX)
- MOVL m(CX), BX
+ MOVL g(CX), DI
- CMPL BX, $0
- JEQ nom
+ CMPL DI, $0
+ JEQ nog
// save g
- MOVL g(CX), DI
MOVL DI, 20(SP)
// g = m->gsignal
+ MOVL g_m(DI), BX
MOVL m_gsignal(BX), BX
MOVL BX, g(CX)
@@ -359,7 +405,7 @@ notls:
MOVL 0, AX
RET
-nom:
+nog:
MOVL 0, AX
RET
diff --git a/src/runtime/sys_nacl_arm.s b/src/runtime/sys_nacl_arm.s
new file mode 100644
index 000000000..d354ab483
--- /dev/null
+++ b/src/runtime/sys_nacl_arm.s
@@ -0,0 +1,320 @@
+// 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 "zasm_GOOS_GOARCH.h"
+#include "textflag.h"
+#include "syscall_nacl.h"
+
+#define NACL_SYSCALL(code) \
+ MOVW $(0x10000 + ((code)<<5)), R8; BL (R8)
+
+TEXT runtime·exit(SB),NOSPLIT,$0
+ MOVW code+0(FP), R0
+ NACL_SYSCALL(SYS_exit)
+ RET
+
+TEXT runtime·exit1(SB),NOSPLIT,$0
+ MOVW code+0(FP), R0
+ NACL_SYSCALL(SYS_thread_exit)
+ RET
+
+TEXT runtime·open(SB),NOSPLIT,$0
+ MOVW name+0(FP), R0
+ MOVW name+0(FP), R1
+ MOVW name+0(FP), R2
+ NACL_SYSCALL(SYS_open)
+ MOVW R0, ret+12(FP)
+ RET
+
+TEXT runtime·close(SB),NOSPLIT,$0
+ MOVW fd+0(FP), R0
+ NACL_SYSCALL(SYS_close)
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·read(SB),NOSPLIT,$0
+ MOVW fd+0(FP), R0
+ MOVW p+4(FP), R1
+ MOVW n+8(FP), R2
+ NACL_SYSCALL(SYS_read)
+ MOVW R0, ret+12(FP)
+ RET
+
+// func naclWrite(fd int, b []byte) int
+TEXT syscall·naclWrite(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ MOVW arg3+8(FP), R2
+ NACL_SYSCALL(SYS_write)
+ MOVW R0, ret+16(FP)
+ RET
+
+TEXT runtime·write(SB),NOSPLIT,$0
+ MOVW fd+0(FP), R0
+ MOVW p+4(FP), R1
+ MOVW n+8(FP), R2
+ NACL_SYSCALL(SYS_write)
+ MOVW R0, ret+12(FP)
+ RET
+
+TEXT runtime·nacl_exception_stack(SB),NOSPLIT,$0
+ MOVW p+0(FP), R0
+ MOVW size+4(FP), R1
+ NACL_SYSCALL(SYS_exception_stack)
+ MOVW R0, ret+8(FP)
+ RET
+
+TEXT runtime·nacl_exception_handler(SB),NOSPLIT,$0
+ MOVW fn+0(FP), R0
+ MOVW arg+4(FP), R1
+ NACL_SYSCALL(SYS_exception_handler)
+ MOVW R0, ret+8(FP)
+ RET
+
+TEXT runtime·nacl_sem_create(SB),NOSPLIT,$0
+ MOVW flag+0(FP), R0
+ NACL_SYSCALL(SYS_sem_create)
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·nacl_sem_wait(SB),NOSPLIT,$0
+ MOVW sem+0(FP), R0
+ NACL_SYSCALL(SYS_sem_wait)
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·nacl_sem_post(SB),NOSPLIT,$0
+ MOVW sem+0(FP), R0
+ NACL_SYSCALL(SYS_sem_post)
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·nacl_mutex_create(SB),NOSPLIT,$0
+ MOVW flag+0(FP), R0
+ NACL_SYSCALL(SYS_mutex_create)
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·nacl_mutex_lock(SB),NOSPLIT,$0
+ MOVW mutex+0(FP), R0
+ NACL_SYSCALL(SYS_mutex_lock)
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·nacl_mutex_trylock(SB),NOSPLIT,$0
+ MOVW mutex+0(FP), R0
+ NACL_SYSCALL(SYS_mutex_trylock)
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·nacl_mutex_unlock(SB),NOSPLIT,$0
+ MOVW mutex+0(FP), R0
+ NACL_SYSCALL(SYS_mutex_unlock)
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·nacl_cond_create(SB),NOSPLIT,$0
+ MOVW flag+0(FP), R0
+ NACL_SYSCALL(SYS_cond_create)
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·nacl_cond_wait(SB),NOSPLIT,$0
+ MOVW cond+0(FP), R0
+ MOVW n+4(FP), R1
+ NACL_SYSCALL(SYS_cond_wait)
+ MOVW R0, ret+8(FP)
+ RET
+
+TEXT runtime·nacl_cond_signal(SB),NOSPLIT,$0
+ MOVW cond+0(FP), R0
+ NACL_SYSCALL(SYS_cond_signal)
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·nacl_cond_broadcast(SB),NOSPLIT,$0
+ MOVW cond+0(FP), R0
+ NACL_SYSCALL(SYS_cond_broadcast)
+ MOVW R0, ret+4(FP)
+ RET
+
+TEXT runtime·nacl_cond_timed_wait_abs(SB),NOSPLIT,$0
+ MOVW cond+0(FP), R0
+ MOVW lock+4(FP), R1
+ MOVW ts+8(FP), R2
+ NACL_SYSCALL(SYS_cond_timed_wait_abs)
+ MOVW R0, ret+12(FP)
+ RET
+
+TEXT runtime·nacl_thread_create(SB),NOSPLIT,$0
+ MOVW fn+0(FP), R0
+ MOVW stk+4(FP), R1
+ MOVW tls+8(FP), R2
+ MOVW xx+12(FP), R3
+ NACL_SYSCALL(SYS_thread_create)
+ MOVW R0, ret+16(FP)
+ RET
+
+TEXT runtime·mstart_nacl(SB),NOSPLIT,$0
+ MOVW 0(R9), R0 // TLS
+ MOVW -8(R0), R1 // g
+ MOVW -4(R0), R2 // m
+ MOVW R2, g_m(R1)
+ MOVW R1, g
+ B runtime·mstart(SB)
+
+TEXT runtime·nacl_nanosleep(SB),NOSPLIT,$0
+ MOVW ts+0(FP), R0
+ MOVW extra+4(FP), R1
+ NACL_SYSCALL(SYS_nanosleep)
+ MOVW R0, ret+8(FP)
+ RET
+
+TEXT runtime·osyield(SB),NOSPLIT,$0
+ NACL_SYSCALL(SYS_sched_yield)
+ RET
+
+TEXT runtime·mmap(SB),NOSPLIT,$8
+ MOVW addr+0(FP), R0
+ MOVW n+4(FP), R1
+ MOVW prot+8(FP), R2
+ MOVW flags+12(FP), R3
+ MOVW fd+16(FP), R4
+ // arg6:offset should be passed as a pointer (to int64)
+ MOVW off+20(FP), R5
+ MOVW R5, 4(R13)
+ MOVW $0, R6
+ MOVW R6, 8(R13)
+ MOVW $4(R13), R5
+ MOVM.DB.W [R4,R5], (R13) // arg5 and arg6 are passed on stack
+ NACL_SYSCALL(SYS_mmap)
+ MOVM.IA.W (R13), [R4, R5]
+ CMP $-4095, R0
+ RSB.HI $0, R0
+ MOVW R0, ret+24(FP)
+ RET
+
+TEXT time·now(SB),NOSPLIT,$16
+ MOVW $0, R0 // real time clock
+ MOVW $4(R13), R1
+ NACL_SYSCALL(SYS_clock_gettime)
+ MOVW 4(R13), R0 // low 32-bit sec
+ MOVW 8(R13), R1 // high 32-bit sec
+ MOVW 12(R13), R2 // nsec
+ MOVW R0, sec+0(FP)
+ MOVW R1, sec+4(FP)
+ MOVW R2, sec+8(FP)
+ RET
+
+TEXT syscall·now(SB),NOSPLIT,$0
+ B time·now(SB)
+
+TEXT runtime·nacl_clock_gettime(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ NACL_SYSCALL(SYS_clock_gettime)
+ MOVW R0, ret+8(FP)
+ RET
+
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB),NOSPLIT,$16
+ MOVW $0, R0 // real time clock
+ MOVW $4(R13), R1
+ NACL_SYSCALL(SYS_clock_gettime)
+ MOVW 4(R13), R0 // low 32-bit sec
+ MOVW 8(R13), R1 // high 32-bit sec (ignored for now)
+ MOVW 12(R13), R2 // nsec
+ MOVW $1000000000, R3
+ MULLU R0, R3, (R1, R0)
+ MOVW $0, R4
+ ADD.S R2, R0
+ ADC R4, R1
+ MOVW R0, ret_lo+0(FP)
+ MOVW R1, ret_hi+4(FP)
+ RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT,$80
+ // load g from thread context
+ MOVW $ctxt+-4(FP), R0
+ MOVW (16*4+10*4)(R0), g
+
+ // check that g exists
+ CMP $0, g
+ BNE 4(PC)
+ MOVW $runtime·badsignal2(SB), R11
+ BL (R11)
+ RET
+
+ // save g
+ MOVW g, R3
+ MOVW g, 20(R13)
+
+ // g = m->gsignal
+ MOVW g_m(g), R8
+ MOVW m_gsignal(R8), g
+
+ // copy arguments for call to sighandler
+ MOVW $11, R0
+ MOVW R0, 4(R13) // signal
+ MOVW $0, R0
+ MOVW R0, 8(R13) // siginfo
+ MOVW $ctxt+-4(FP), R0
+ MOVW R0, 12(R13) // context
+ MOVW R3, 16(R13) // g
+
+ BL runtime·sighandler(SB)
+
+ // restore g
+ MOVW 20(R13), g
+
+sigtramp_ret:
+ // Enable exceptions again.
+ NACL_SYSCALL(SYS_exception_clear_flag)
+
+ // Restore registers as best we can. Impossible to do perfectly.
+ // See comment in sys_nacl_386.s for extended rationale.
+ MOVW $ctxt+-4(FP), R1
+ ADD $64, R1
+ MOVW (0*4)(R1), R0
+ MOVW (2*4)(R1), R2
+ MOVW (3*4)(R1), R3
+ MOVW (4*4)(R1), R4
+ MOVW (5*4)(R1), R5
+ MOVW (6*4)(R1), R6
+ MOVW (7*4)(R1), R7
+ MOVW (8*4)(R1), R8
+ // cannot write to R9
+ MOVW (10*4)(R1), g
+ MOVW (11*4)(R1), R11
+ MOVW (12*4)(R1), R12
+ MOVW (13*4)(R1), R13
+ MOVW (14*4)(R1), R14
+ MOVW (15*4)(R1), R1
+ B (R1)
+
+nog:
+ MOVW $0, R0
+ RET
+
+TEXT runtime·nacl_sysinfo(SB),NOSPLIT,$16
+ RET
+
+TEXT runtime·casp(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)
+
+TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4
+ WORD $0xe7fedef0 // NACL_INSTR_ARM_ABORT_NOW (UDF #0xEDE0)
diff --git a/src/pkg/runtime/sys_netbsd_386.s b/src/runtime/sys_netbsd_386.s
index 05de55e93..23f2f6bd1 100644
--- a/src/pkg/runtime/sys_netbsd_386.s
+++ b/src/runtime/sys_netbsd_386.s
@@ -7,7 +7,7 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT,$-4
@@ -26,21 +26,25 @@ TEXT runtime·exit1(SB),NOSPLIT,$-4
TEXT runtime·open(SB),NOSPLIT,$-4
MOVL $5, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$-4
MOVL $6, AX
INT $0x80
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$-4
MOVL $3, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$-4
MOVL $4, AX // sys_write
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·usleep(SB),NOSPLIT,$24
@@ -74,7 +78,7 @@ TEXT runtime·raise(SB),NOSPLIT,$12
RET
TEXT runtime·mmap(SB),NOSPLIT,$36
- LEAL arg0+0(FP), SI
+ LEAL addr+0(FP), SI
LEAL 4(SP), DI
CLD
MOVSL // arg 1 - addr
@@ -89,6 +93,7 @@ TEXT runtime·mmap(SB),NOSPLIT,$36
STOSL
MOVL $197, AX // sys_mmap
INT $0x80
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$-4
@@ -146,9 +151,8 @@ TEXT runtime·nanotime(SB),NOSPLIT,$32
ADDL BX, AX
ADCL CX, DX // add high bits with carry
- MOVL ret+0(FP), DI
- MOVL AX, 0(DI)
- MOVL DX, 4(DI)
+ MOVL AX, ret_lo+0(FP)
+ MOVL DX, ret_hi+4(FP)
RET
TEXT runtime·getcontext(SB),NOSPLIT,$-4
@@ -175,7 +179,7 @@ TEXT runtime·sigreturn_tramp(SB),NOSPLIT,$0
INT $0x80
TEXT runtime·sigaction(SB),NOSPLIT,$24
- LEAL arg0+0(FP), SI
+ LEAL sig+0(FP), SI
LEAL 4(SP), DI
CLD
MOVSL // arg 1 - sig
@@ -194,9 +198,9 @@ TEXT runtime·sigaction(SB),NOSPLIT,$24
TEXT runtime·sigtramp(SB),NOSPLIT,$44
get_tls(CX)
- // check that m exists
- MOVL m(CX), BX
- CMPL BX, $0
+ // check that g exists
+ MOVL g(CX), DI
+ CMPL DI, $0
JNE 6(PC)
MOVL signo+0(FP), BX
MOVL BX, 0(SP)
@@ -205,10 +209,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
RET
// save g
- MOVL g(CX), DI
MOVL DI, 20(SP)
// g = m->gsignal
+ MOVL g_m(DI), BX
MOVL m_gsignal(BX), BX
MOVL BX, g(CX)
@@ -232,7 +236,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
// int32 lwp_create(void *context, uintptr flags, void *lwpid);
TEXT runtime·lwp_create(SB),NOSPLIT,$16
MOVL $0, 0(SP)
- MOVL context+0(FP), AX
+ MOVL ctxt+0(FP), AX
MOVL AX, 4(SP) // arg 1 - context
MOVL flags+4(FP), AX
MOVL AX, 8(SP) // arg 2 - flags
@@ -242,6 +246,7 @@ TEXT runtime·lwp_create(SB),NOSPLIT,$16
INT $0x80
JCC 2(PC)
NEGL AX
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
@@ -257,7 +262,7 @@ TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
// Now segment is established. Initialize m, g.
get_tls(AX)
MOVL DX, g(AX)
- MOVL BX, m(AX)
+ MOVL BX, g_m(DX)
CALL runtime·stackcheck(SB) // smashes AX, CX
MOVL 0(DX), DX // paranoia; check they are not nil
@@ -312,20 +317,23 @@ TEXT runtime·osyield(SB),NOSPLIT,$-4
TEXT runtime·lwp_park(SB),NOSPLIT,$-4
MOVL $434, AX // sys__lwp_park
INT $0x80
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·lwp_unpark(SB),NOSPLIT,$-4
MOVL $321, AX // sys__lwp_unpark
INT $0x80
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·lwp_self(SB),NOSPLIT,$-4
MOVL $311, AX // sys__lwp_self
INT $0x80
+ MOVL AX, ret+0(FP)
RET
TEXT runtime·sysctl(SB),NOSPLIT,$28
- LEAL arg0+0(FP), SI
+ LEAL mib+0(FP), SI
LEAL 4(SP), DI
CLD
MOVSL // arg 1 - name
@@ -342,7 +350,7 @@ TEXT runtime·sysctl(SB),NOSPLIT,$28
MOVL $0, AX
RET
-GLOBL runtime·tlsoffset(SB),$4
+GLOBL runtime·tlsoffset(SB),NOPTR,$4
// int32 runtime·kqueue(void)
TEXT runtime·kqueue(SB),NOSPLIT,$0
@@ -350,6 +358,7 @@ TEXT runtime·kqueue(SB),NOSPLIT,$0
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout)
@@ -358,6 +367,7 @@ TEXT runtime·kevent(SB),NOSPLIT,$0
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+24(FP)
RET
// int32 runtime·closeonexec(int32 fd)
diff --git a/src/pkg/runtime/sys_netbsd_amd64.s b/src/runtime/sys_netbsd_amd64.s
index fcbced548..eb9766d3f 100644
--- a/src/pkg/runtime/sys_netbsd_amd64.s
+++ b/src/runtime/sys_netbsd_amd64.s
@@ -7,17 +7,18 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// int32 lwp_create(void *context, uintptr flags, void *lwpid)
TEXT runtime·lwp_create(SB),NOSPLIT,$0
- MOVQ context+0(FP), DI
+ MOVQ ctxt+0(FP), DI
MOVQ flags+8(FP), SI
MOVQ lwpid+16(FP), DX
MOVL $309, AX // sys__lwp_create
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
@@ -28,7 +29,7 @@ TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
// Set up new stack.
get_tls(CX)
- MOVQ R8, m(CX)
+ MOVQ R8, g_m(R9)
MOVQ R9, g(CX)
CALL runtime·stackcheck(SB)
@@ -46,29 +47,32 @@ TEXT runtime·osyield(SB),NOSPLIT,$0
RET
TEXT runtime·lwp_park(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - abstime
- MOVL 16(SP), SI // arg 2 - unpark
- MOVQ 24(SP), DX // arg 3 - hint
- MOVQ 32(SP), R10 // arg 4 - unparkhint
+ MOVQ abstime+0(FP), DI // arg 1 - abstime
+ MOVL unpark+8(FP), SI // arg 2 - unpark
+ MOVQ hint+16(FP), DX // arg 3 - hint
+ MOVQ unparkhint+24(FP), R10 // arg 4 - unparkhint
MOVL $434, AX // sys__lwp_park
SYSCALL
+ MOVL AX, ret+32(FP)
RET
TEXT runtime·lwp_unpark(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - lwp
- MOVL 16(SP), SI // arg 2 - hint
+ MOVL lwp+0(FP), DI // arg 1 - lwp
+ MOVQ hint+8(FP), SI // arg 2 - hint
MOVL $321, AX // sys__lwp_unpark
SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·lwp_self(SB),NOSPLIT,$0
MOVL $311, AX // sys__lwp_self
SYSCALL
+ MOVL AX, ret+0(FP)
RET
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 - exit status
+ MOVL code+0(FP), DI // arg 1 - exit status
MOVL $1, AX // sys_exit
SYSCALL
MOVL $0xf1, 0xf1 // crash
@@ -81,33 +85,37 @@ TEXT runtime·exit1(SB),NOSPLIT,$-8
RET
TEXT runtime·open(SB),NOSPLIT,$-8
- MOVQ 8(SP), DI // arg 1 pathname
- MOVL 16(SP), SI // arg 2 flags
- MOVL 20(SP), DX // arg 3 mode
+ MOVQ name+0(FP), DI // arg 1 pathname
+ MOVL mode+8(FP), SI // arg 2 flags
+ MOVL perm+12(FP), DX // arg 3 mode
MOVL $5, AX
SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 fd
+ MOVL fd+0(FP), DI // arg 1 fd
MOVL $6, AX
SYSCALL
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 fd
- MOVQ 16(SP), SI // arg 2 buf
- MOVL 24(SP), DX // arg 3 count
+ MOVL fd+0(FP), DI // arg 1 fd
+ MOVQ p+8(FP), SI // arg 2 buf
+ MOVL n+16(FP), DX // arg 3 count
MOVL $3, AX
SYSCALL
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 - fd
- MOVQ 16(SP), SI // arg 2 - buf
- MOVL 24(SP), DX // arg 3 - nbyte
+ MOVQ fd+0(FP), DI // arg 1 - fd
+ MOVQ p+8(FP), SI // arg 2 - buf
+ MOVL n+16(FP), DX // arg 3 - nbyte
MOVL $4, AX // sys_write
SYSCALL
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·usleep(SB),NOSPLIT,$16
@@ -136,9 +144,9 @@ TEXT runtime·raise(SB),NOSPLIT,$16
RET
TEXT runtime·setitimer(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 - which
- MOVQ 16(SP), SI // arg 2 - itv
- MOVQ 24(SP), DX // arg 3 - oitv
+ MOVL mode+0(FP), DI // arg 1 - which
+ MOVQ new+8(FP), SI // arg 2 - itv
+ MOVQ old+16(FP), DX // arg 3 - oitv
MOVL $425, AX // sys_setitimer
SYSCALL
RET
@@ -169,10 +177,11 @@ TEXT runtime·nanotime(SB),NOSPLIT,$32
// return nsec in AX
IMULQ $1000000000, AX
ADDQ DX, AX
+ MOVQ AX, ret+0(FP)
RET
TEXT runtime·getcontext(SB),NOSPLIT,$-8
- MOVQ 8(SP), DI // arg 1 - context
+ MOVQ ctxt+0(FP), DI // arg 1 - context
MOVL $307, AX // sys_getcontext
SYSCALL
JCC 2(PC)
@@ -180,9 +189,9 @@ TEXT runtime·getcontext(SB),NOSPLIT,$-8
RET
TEXT runtime·sigprocmask(SB),NOSPLIT,$0
- MOVL 8(SP), DI // arg 1 - how
- MOVQ 16(SP), SI // arg 2 - set
- MOVQ 24(SP), DX // arg 3 - oset
+ MOVL mode+0(FP), DI // arg 1 - how
+ MOVQ new+8(FP), SI // arg 2 - set
+ MOVQ old+16(FP), DX // arg 3 - oset
MOVL $293, AX // sys_sigprocmask
SYSCALL
JCC 2(PC)
@@ -198,9 +207,9 @@ TEXT runtime·sigreturn_tramp(SB),NOSPLIT,$-8
SYSCALL
TEXT runtime·sigaction(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 - signum
- MOVQ 16(SP), SI // arg 2 - nsa
- MOVQ 24(SP), DX // arg 3 - osa
+ MOVL sig+0(FP), DI // arg 1 - signum
+ MOVQ new+8(FP), SI // arg 2 - nsa
+ MOVQ old+16(FP), DX // arg 3 - osa
// arg 4 - tramp
LEAQ runtime·sigreturn_tramp(SB), R10
MOVQ $2, R8 // arg 5 - vers
@@ -213,9 +222,9 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
TEXT runtime·sigtramp(SB),NOSPLIT,$64
get_tls(BX)
- // check that m exists
- MOVQ m(BX), BP
- CMPQ BP, $0
+ // check that g exists
+ MOVQ g(BX), R10
+ CMPQ R10, $0
JNE 5(PC)
MOVQ DI, 0(SP)
MOVQ $runtime·badsignal(SB), AX
@@ -223,10 +232,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
RET
// save g
- MOVQ g(BX), R10
MOVQ R10, 40(SP)
// g = m->signal
+ MOVQ g_m(R10), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
@@ -244,23 +253,24 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
RET
TEXT runtime·mmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - addr
- MOVQ 16(SP), SI // arg 2 - len
- MOVL 24(SP), DX // arg 3 - prot
- MOVL 28(SP), R10 // arg 4 - flags
- MOVL 32(SP), R8 // arg 5 - fd
- MOVQ 36(SP), R9
+ MOVQ addr+0(FP), DI // arg 1 - addr
+ MOVQ n+8(FP), SI // arg 2 - len
+ MOVL prot+16(FP), DX // arg 3 - prot
+ MOVL flags+20(FP), R10 // arg 4 - flags
+ MOVL fd+24(FP), R8 // arg 5 - fd
+ MOVL off+28(FP), R9
SUBQ $16, SP
MOVQ R9, 8(SP) // arg 7 - offset (passed on stack)
MOVQ $0, R9 // arg 6 - pad
MOVL $197, AX // sys_mmap
SYSCALL
ADDQ $16, SP
+ MOVQ AX, ret+32(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - addr
- MOVQ 16(SP), SI // arg 2 - len
+ MOVQ addr+0(FP), DI // arg 1 - addr
+ MOVQ n+8(FP), SI // arg 2 - len
MOVL $73, AX // sys_munmap
SYSCALL
JCC 2(PC)
@@ -270,8 +280,8 @@ TEXT runtime·munmap(SB),NOSPLIT,$0
TEXT runtime·madvise(SB),NOSPLIT,$0
MOVQ addr+0(FP), DI // arg 1 - addr
- MOVQ len+8(FP), SI // arg 2 - len
- MOVQ behav+16(FP), DX // arg 3 - behav
+ MOVQ n+8(FP), SI // arg 2 - len
+ MOVL flags+16(FP), DX // arg 3 - behav
MOVQ $75, AX // sys_madvise
SYSCALL
// ignore failure - maybe pages are locked
@@ -297,18 +307,20 @@ TEXT runtime·settls(SB),NOSPLIT,$8
RET
TEXT runtime·sysctl(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - name
- MOVL 16(SP), SI // arg 2 - namelen
- MOVQ 24(SP), DX // arg 3 - oldp
- MOVQ 32(SP), R10 // arg 4 - oldlenp
- MOVQ 40(SP), R8 // arg 5 - newp
- MOVQ 48(SP), R9 // arg 6 - newlen
+ MOVQ mib+0(FP), DI // arg 1 - name
+ MOVL miblen+8(FP), SI // arg 2 - namelen
+ MOVQ out+16(FP), DX // arg 3 - oldp
+ MOVQ size+24(FP), R10 // arg 4 - oldlenp
+ MOVQ dst+32(FP), R8 // arg 5 - newp
+ MOVQ ndst+40(FP), R9 // arg 6 - newlen
MOVQ $202, AX // sys___sysctl
SYSCALL
- JCC 3(PC)
+ JCC 4(PC)
NEGQ AX
+ MOVL AX, ret+48(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+48(FP)
RET
// int32 runtime·kqueue(void)
@@ -318,25 +330,27 @@ TEXT runtime·kqueue(SB),NOSPLIT,$0
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout)
TEXT runtime·kevent(SB),NOSPLIT,$0
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVQ 32(SP), R10
- MOVL 40(SP), R8
- MOVQ 48(SP), R9
+ MOVL fd+0(FP), DI
+ MOVQ ev1+8(FP), SI
+ MOVL nev1+16(FP), DX
+ MOVQ ev2+24(FP), R10
+ MOVL nev2+32(FP), R8
+ MOVQ ts+40(FP), R9
MOVL $435, AX
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+48(FP)
RET
// void runtime·closeonexec(int32 fd)
TEXT runtime·closeonexec(SB),NOSPLIT,$0
- MOVL 8(SP), DI // fd
+ MOVL fd+0(FP), DI // fd
MOVQ $2, SI // F_SETFD
MOVQ $1, DX // FD_CLOEXEC
MOVL $92, AX // fcntl
diff --git a/src/pkg/runtime/sys_netbsd_arm.s b/src/runtime/sys_netbsd_arm.s
index b2eb74ee3..039a0832e 100644
--- a/src/pkg/runtime/sys_netbsd_arm.s
+++ b/src/runtime/sys_netbsd_arm.s
@@ -7,7 +7,7 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT,$-4
@@ -28,11 +28,13 @@ TEXT runtime·open(SB),NOSPLIT,$-8
MOVW 4(FP), R1
MOVW 8(FP), R2
SWI $0xa00005
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$-8
MOVW 0(FP), R0
SWI $0xa00006
+ MOVW R0, ret+4(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$-8
@@ -40,6 +42,7 @@ TEXT runtime·read(SB),NOSPLIT,$-8
MOVW 4(FP), R1
MOVW 8(FP), R2
SWI $0xa00003
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$-4
@@ -47,14 +50,16 @@ TEXT runtime·write(SB),NOSPLIT,$-4
MOVW 4(FP), R1 // arg 2 - buf
MOVW 8(FP), R2 // arg 3 - nbyte
SWI $0xa00004 // sys_write
+ MOVW R0, ret+12(FP)
RET
// int32 lwp_create(void *context, uintptr flags, void *lwpid)
TEXT runtime·lwp_create(SB),NOSPLIT,$0
- MOVW context+0(FP), R0
+ MOVW ctxt+0(FP), R0
MOVW flags+4(FP), R1
MOVW lwpid+8(FP), R2
SWI $0xa00135 // sys__lwp_create
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·osyield(SB),NOSPLIT,$0
@@ -67,20 +72,23 @@ TEXT runtime·lwp_park(SB),NOSPLIT,$0
MOVW 8(FP), R2 // arg 3 - hint
MOVW 12(FP), R3 // arg 4 - unparkhint
SWI $0xa001b2 // sys__lwp_park
+ MOVW R0, ret+16(FP)
RET
TEXT runtime·lwp_unpark(SB),NOSPLIT,$0
MOVW 0(FP), R0 // arg 1 - lwp
MOVW 4(FP), R1 // arg 2 - hint
SWI $0xa00141 // sys__lwp_unpark
+ MOVW R0, ret+8(FP)
RET
TEXT runtime·lwp_self(SB),NOSPLIT,$0
SWI $0xa00137 // sys__lwp_self
+ MOVW R0, ret+0(FP)
RET
TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
- MOVW R0, m
+ MOVW R0, g_m(R1)
MOVW R1, g
BL runtime·emptyfunc(SB) // fault if stack check is wrong
@@ -153,9 +161,8 @@ TEXT runtime·nanotime(SB), NOSPLIT, $32
ADD.S R2, R0
ADC R4, R1
- MOVW 0(FP), R3
- MOVW R0, 0(R3)
- MOVW R1, 4(R3)
+ MOVW R0, ret_lo+0(FP)
+ MOVW R1, ret_hi+4(FP)
RET
TEXT runtime·getcontext(SB),NOSPLIT,$-4
@@ -200,14 +207,14 @@ TEXT runtime·sigaction(SB),NOSPLIT,$4
TEXT runtime·sigtramp(SB),NOSPLIT,$24
// this might be called in external code context,
- // where g and m are not set.
- // first save R0, because runtime·load_gm will clobber it
+ // where g is not set.
+ // first save R0, because runtime·load_g will clobber it
MOVW R0, 4(R13) // signum
MOVB runtime·iscgo(SB), R0
CMP $0, R0
- BL.NE runtime·load_gm(SB)
+ BL.NE runtime·load_g(SB)
- CMP $0, m
+ CMP $0, g
BNE 4(PC)
// signal number is already prepared in 4(R13)
MOVW $runtime·badsignal(SB), R11
@@ -219,7 +226,8 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
MOVW g, 20(R13)
// g = m->signal
- MOVW m_gsignal(m), g
+ MOVW g_m(g), R8
+ MOVW m_gsignal(R8), g
// R0 is already saved
MOVW R1, 8(R13) // info
@@ -248,6 +256,7 @@ TEXT runtime·mmap(SB),NOSPLIT,$12
ADD $4, R13 // pass arg 5 and arg 6 on stack
SWI $0xa000c5 // sys_mmap
SUB $4, R13
+ MOVW R0, ret+24(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
@@ -286,12 +295,14 @@ TEXT runtime·sysctl(SB),NOSPLIT,$8
ADD $4, R13 // pass arg 5 and 6 on stack
SWI $0xa000ca // sys___sysctl
SUB $4, R13
+ MOVW R0, ret+24(FP)
RET
// int32 runtime·kqueue(void)
TEXT runtime·kqueue(SB),NOSPLIT,$0
SWI $0xa00158 // sys_kqueue
RSB.CS $0, R0
+ MOVW R0, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout)
@@ -308,6 +319,7 @@ TEXT runtime·kevent(SB),NOSPLIT,$8
SWI $0xa001b3 // sys___kevent50
RSB.CS $0, R0
SUB $4, R13
+ MOVW R0, ret+24(FP)
RET
// void runtime·closeonexec(int32 fd)
diff --git a/src/pkg/runtime/sys_openbsd_386.s b/src/runtime/sys_openbsd_386.s
index 8f0da5c0e..5cda7768a 100644
--- a/src/pkg/runtime/sys_openbsd_386.s
+++ b/src/runtime/sys_openbsd_386.s
@@ -7,7 +7,7 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#define CLOCK_MONOTONIC $3
@@ -30,21 +30,25 @@ TEXT runtime·exit1(SB),NOSPLIT,$8
TEXT runtime·open(SB),NOSPLIT,$-4
MOVL $5, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$-4
MOVL $6, AX
INT $0x80
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$-4
MOVL $3, AX
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$-4
MOVL $4, AX // sys_write
INT $0x80
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·usleep(SB),NOSPLIT,$24
@@ -78,7 +82,7 @@ TEXT runtime·raise(SB),NOSPLIT,$12
RET
TEXT runtime·mmap(SB),NOSPLIT,$36
- LEAL arg0+0(FP), SI
+ LEAL addr+0(FP), SI
LEAL 4(SP), DI
CLD
MOVSL // arg 1 - addr
@@ -93,6 +97,7 @@ TEXT runtime·mmap(SB),NOSPLIT,$36
STOSL
MOVL $197, AX // sys_mmap
INT $0x80
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$-4
@@ -151,9 +156,8 @@ TEXT runtime·nanotime(SB),NOSPLIT,$32
ADDL BX, AX
ADCL CX, DX // add high bits with carry
- MOVL ret+0(FP), DI
- MOVL AX, 0(DI)
- MOVL DX, 4(DI)
+ MOVL AX, ret_lo+0(FP)
+ MOVL DX, ret_hi+4(FP)
RET
TEXT runtime·sigaction(SB),NOSPLIT,$-4
@@ -168,15 +172,15 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$-4
INT $0x80
JAE 2(PC)
MOVL $0xf1, 0xf1 // crash
- MOVL AX, oset+0(FP)
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·sigtramp(SB),NOSPLIT,$44
get_tls(CX)
- // check that m exists
- MOVL m(CX), BX
- CMPL BX, $0
+ // check that g exists
+ MOVL g(CX), DI
+ CMPL DI, $0
JNE 6(PC)
MOVL signo+0(FP), BX
MOVL BX, 0(SP)
@@ -185,10 +189,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
JMP sigtramp_ret
// save g
- MOVL g(CX), DI
MOVL DI, 20(SP)
// g = m->gsignal
+ MOVL g_m(DI), BX
MOVL m_gsignal(BX), BX
MOVL BX, g(CX)
@@ -222,38 +226,36 @@ sigtramp_ret:
TEXT runtime·tfork(SB),NOSPLIT,$12
// Copy mp, gp and fn from the parent stack onto the child stack.
- MOVL params+4(FP), AX
+ MOVL param+0(FP), AX
MOVL 8(AX), CX // tf_stack
SUBL $16, CX
MOVL CX, 8(AX)
- MOVL mm+12(FP), SI
+ MOVL mm+8(FP), SI
MOVL SI, 0(CX)
- MOVL gg+16(FP), SI
+ MOVL gg+12(FP), SI
MOVL SI, 4(CX)
- MOVL fn+20(FP), SI
+ MOVL fn+16(FP), SI
MOVL SI, 8(CX)
MOVL $1234, 12(CX)
MOVL $0, 0(SP) // syscall gap
- MOVL params+4(FP), AX
+ MOVL param+0(FP), AX
MOVL AX, 4(SP) // arg 1 - param
- MOVL psize+8(FP), AX
+ MOVL psize+4(FP), AX
MOVL AX, 8(SP) // arg 2 - psize
MOVL $8, AX // sys___tfork
INT $0x80
// Return if tfork syscall failed.
- JCC 5(PC)
+ JCC 4(PC)
NEGL AX
- MOVL ret+0(FP), DX
- MOVL AX, 0(DX)
+ MOVL AX, ret+20(FP)
RET
// In parent, return.
CMPL AX, $0
- JEQ 4(PC)
- MOVL ret+0(FP), DX
- MOVL AX, 0(DX)
+ JEQ 3(PC)
+ MOVL AX, ret+20(FP)
RET
// Paranoia: check that SP is as we expect.
@@ -278,7 +280,7 @@ TEXT runtime·tfork(SB),NOSPLIT,$12
// Now segment is established. Initialize m, g.
get_tls(AX)
MOVL DX, g(AX)
- MOVL BX, m(AX)
+ MOVL BX, g_m(DX)
CALL runtime·stackcheck(SB) // smashes AX, CX
MOVL 0(DX), DX // paranoia; check they are not nil
@@ -333,15 +335,17 @@ TEXT runtime·osyield(SB),NOSPLIT,$-4
TEXT runtime·thrsleep(SB),NOSPLIT,$-4
MOVL $94, AX // sys___thrsleep
INT $0x80
+ MOVL AX, ret+20(FP)
RET
TEXT runtime·thrwakeup(SB),NOSPLIT,$-4
MOVL $301, AX // sys___thrwakeup
INT $0x80
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·sysctl(SB),NOSPLIT,$28
- LEAL arg0+0(FP), SI
+ LEAL mib+0(FP), SI
LEAL 4(SP), DI
CLD
MOVSL // arg 1 - name
@@ -352,10 +356,12 @@ TEXT runtime·sysctl(SB),NOSPLIT,$28
MOVSL // arg 6 - newlen
MOVL $202, AX // sys___sysctl
INT $0x80
- JCC 3(PC)
+ JCC 4(PC)
NEGL AX
+ MOVL AX, ret+24(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+24(FP)
RET
// int32 runtime·kqueue(void);
@@ -364,6 +370,7 @@ TEXT runtime·kqueue(SB),NOSPLIT,$0
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
@@ -372,6 +379,7 @@ TEXT runtime·kevent(SB),NOSPLIT,$0
INT $0x80
JAE 2(PC)
NEGL AX
+ MOVL AX, ret+24(FP)
RET
// int32 runtime·closeonexec(int32 fd);
@@ -387,4 +395,4 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$32
NEGL AX
RET
-GLOBL runtime·tlsoffset(SB),$4
+GLOBL runtime·tlsoffset(SB),NOPTR,$4
diff --git a/src/pkg/runtime/sys_openbsd_amd64.s b/src/runtime/sys_openbsd_amd64.s
index b2a61820a..4e9db2390 100644
--- a/src/pkg/runtime/sys_openbsd_amd64.s
+++ b/src/runtime/sys_openbsd_amd64.s
@@ -7,11 +7,11 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
#define CLOCK_MONOTONIC $3
-// int64 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
+// int32 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
TEXT runtime·tfork(SB),NOSPLIT,$32
// Copy mp, gp and fn off parent stack for use by child.
@@ -25,13 +25,15 @@ TEXT runtime·tfork(SB),NOSPLIT,$32
SYSCALL
// Return if tfork syscall failed.
- JCC 3(PC)
+ JCC 4(PC)
NEGQ AX
+ MOVL AX, ret+40(FP)
RET
// In parent, return.
CMPL AX, $0
- JEQ 2(PC)
+ JEQ 3(PC)
+ MOVL AX, ret+40(FP)
RET
// Set FS to point at m->tls.
@@ -40,7 +42,7 @@ TEXT runtime·tfork(SB),NOSPLIT,$32
// In child, set up new stack.
get_tls(CX)
- MOVQ R8, m(CX)
+ MOVQ R8, g_m(R9)
MOVQ R9, g(CX)
CALL runtime·stackcheck(SB)
@@ -59,25 +61,27 @@ TEXT runtime·osyield(SB),NOSPLIT,$0
RET
TEXT runtime·thrsleep(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - ident
- MOVL 16(SP), SI // arg 2 - clock_id
- MOVQ 24(SP), DX // arg 3 - tp
- MOVQ 32(SP), R10 // arg 4 - lock
- MOVQ 40(SP), R8 // arg 5 - abort
+ MOVQ ident+0(FP), DI // arg 1 - ident
+ MOVL clock_id+8(FP), SI // arg 2 - clock_id
+ MOVQ tsp+16(FP), DX // arg 3 - tp
+ MOVQ lock+24(FP), R10 // arg 4 - lock
+ MOVQ abort+32(FP), R8 // arg 5 - abort
MOVL $94, AX // sys___thrsleep
SYSCALL
+ MOVL AX, ret+40(FP)
RET
TEXT runtime·thrwakeup(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - ident
- MOVL 16(SP), SI // arg 2 - n
+ MOVQ ident+0(FP), DI // arg 1 - ident
+ MOVL n+8(FP), SI // arg 2 - n
MOVL $301, AX // sys___thrwakeup
SYSCALL
+ MOVL AX, ret+16(FP)
RET
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 - exit status
+ MOVL code+0(FP), DI // arg 1 - exit status
MOVL $1, AX // sys_exit
SYSCALL
MOVL $0xf1, 0xf1 // crash
@@ -91,33 +95,37 @@ TEXT runtime·exit1(SB),NOSPLIT,$-8
RET
TEXT runtime·open(SB),NOSPLIT,$-8
- MOVQ 8(SP), DI // arg 1 pathname
- MOVL 16(SP), SI // arg 2 flags
- MOVL 20(SP), DX // arg 3 mode
+ MOVQ name+0(FP), DI // arg 1 pathname
+ MOVL mode+8(FP), SI // arg 2 flags
+ MOVL perm+12(FP), DX // arg 3 mode
MOVL $5, AX
SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 fd
+ MOVL fd+0(FP), DI // arg 1 fd
MOVL $6, AX
SYSCALL
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 fd
- MOVQ 16(SP), SI // arg 2 buf
- MOVL 24(SP), DX // arg 3 count
+ MOVL fd+0(FP), DI // arg 1 fd
+ MOVQ p+8(FP), SI // arg 2 buf
+ MOVL n+16(FP), DX // arg 3 count
MOVL $3, AX
SYSCALL
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 - fd
- MOVQ 16(SP), SI // arg 2 - buf
- MOVL 24(SP), DX // arg 3 - nbyte
+ MOVQ fd+0(FP), DI // arg 1 - fd
+ MOVQ p+8(FP), SI // arg 2 - buf
+ MOVL n+16(FP), DX // arg 3 - nbyte
MOVL $4, AX // sys_write
SYSCALL
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·usleep(SB),NOSPLIT,$16
@@ -146,9 +154,9 @@ TEXT runtime·raise(SB),NOSPLIT,$16
RET
TEXT runtime·setitimer(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 - which
- MOVQ 16(SP), SI // arg 2 - itv
- MOVQ 24(SP), DX // arg 3 - oitv
+ MOVL mode+0(FP), DI // arg 1 - which
+ MOVQ new+8(FP), SI // arg 2 - itv
+ MOVQ old+16(FP), DX // arg 3 - oitv
MOVL $69, AX // sys_setitimer
SYSCALL
RET
@@ -179,12 +187,13 @@ TEXT runtime·nanotime(SB),NOSPLIT,$24
// return nsec in AX
IMULQ $1000000000, AX
ADDQ DX, AX
+ MOVQ AX, ret+0(FP)
RET
TEXT runtime·sigaction(SB),NOSPLIT,$-8
- MOVL 8(SP), DI // arg 1 - signum
- MOVQ 16(SP), SI // arg 2 - nsa
- MOVQ 24(SP), DX // arg 3 - osa
+ MOVL sig+0(FP), DI // arg 1 - signum
+ MOVQ new+8(FP), SI // arg 2 - nsa
+ MOVQ old+16(FP), DX // arg 3 - osa
MOVL $46, AX
SYSCALL
JCC 2(PC)
@@ -192,21 +201,21 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
RET
TEXT runtime·sigprocmask(SB),NOSPLIT,$0
- MOVL 8(SP), DI // arg 1 - how
- MOVL 12(SP), SI // arg 2 - set
+ MOVL mode+0(FP), DI // arg 1 - how
+ MOVL new+4(FP), SI // arg 2 - set
MOVL $48, AX // sys_sigprocmask
SYSCALL
JCC 2(PC)
MOVL $0xf1, 0xf1 // crash
- MOVL AX, oset+0(FP) // Return oset
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·sigtramp(SB),NOSPLIT,$64
get_tls(BX)
- // check that m exists
- MOVQ m(BX), BP
- CMPQ BP, $0
+ // check that g exists
+ MOVQ g(BX), R10
+ CMPQ R10, $0
JNE 5(PC)
MOVQ DI, 0(SP)
MOVQ $runtime·badsignal(SB), AX
@@ -214,10 +223,10 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
RET
// save g
- MOVQ g(BX), R10
MOVQ R10, 40(SP)
// g = m->signal
+ MOVQ g_m(R10), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
@@ -235,23 +244,24 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
RET
TEXT runtime·mmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - addr
- MOVQ 16(SP), SI // arg 2 - len
- MOVL 24(SP), DX // arg 3 - prot
- MOVL 28(SP), R10 // arg 4 - flags
- MOVL 32(SP), R8 // arg 5 - fd
- MOVQ 36(SP), R9
+ MOVQ addr+0(FP), DI // arg 1 - addr
+ MOVQ n+8(FP), SI // arg 2 - len
+ MOVL prot+16(FP), DX // arg 3 - prot
+ MOVL flags+20(FP), R10 // arg 4 - flags
+ MOVL fd+24(FP), R8 // arg 5 - fd
+ MOVL off+28(FP), R9
SUBQ $16, SP
MOVQ R9, 8(SP) // arg 7 - offset (passed on stack)
MOVQ $0, R9 // arg 6 - pad
MOVL $197, AX
SYSCALL
ADDQ $16, SP
+ MOVQ AX, ret+32(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - addr
- MOVQ 16(SP), SI // arg 2 - len
+ MOVQ addr+0(FP), DI // arg 1 - addr
+ MOVQ n+8(FP), SI // arg 2 - len
MOVL $73, AX // sys_munmap
SYSCALL
JCC 2(PC)
@@ -260,8 +270,8 @@ TEXT runtime·munmap(SB),NOSPLIT,$0
TEXT runtime·madvise(SB),NOSPLIT,$0
MOVQ addr+0(FP), DI // arg 1 - addr
- MOVQ len+8(FP), SI // arg 2 - len
- MOVQ behav+16(FP), DX // arg 3 - behav
+ MOVQ n+8(FP), SI // arg 2 - len
+ MOVL flags+16(FP), DX // arg 3 - behav
MOVQ $75, AX // sys_madvise
SYSCALL
// ignore failure - maybe pages are locked
@@ -287,18 +297,20 @@ TEXT runtime·settls(SB),NOSPLIT,$0
RET
TEXT runtime·sysctl(SB),NOSPLIT,$0
- MOVQ 8(SP), DI // arg 1 - name
- MOVL 16(SP), SI // arg 2 - namelen
- MOVQ 24(SP), DX // arg 3 - oldp
- MOVQ 32(SP), R10 // arg 4 - oldlenp
- MOVQ 40(SP), R8 // arg 5 - newp
- MOVQ 48(SP), R9 // arg 6 - newlen
+ MOVQ mib+0(FP), DI // arg 1 - name
+ MOVL miblen+8(FP), SI // arg 2 - namelen
+ MOVQ out+16(FP), DX // arg 3 - oldp
+ MOVQ size+24(FP), R10 // arg 4 - oldlenp
+ MOVQ dst+32(FP), R8 // arg 5 - newp
+ MOVQ ndst+40(FP), R9 // arg 6 - newlen
MOVQ $202, AX // sys___sysctl
SYSCALL
- JCC 3(PC)
+ JCC 4(PC)
NEGQ AX
+ MOVL AX, ret+48(FP)
RET
MOVL $0, AX
+ MOVL AX, ret+48(FP)
RET
// int32 runtime·kqueue(void);
@@ -310,25 +322,27 @@ TEXT runtime·kqueue(SB),NOSPLIT,$0
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
TEXT runtime·kevent(SB),NOSPLIT,$0
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVQ 32(SP), R10
- MOVL 40(SP), R8
- MOVQ 48(SP), R9
+ MOVL fd+0(FP), DI
+ MOVQ ev1+8(FP), SI
+ MOVL nev1+16(FP), DX
+ MOVQ ev2+24(FP), R10
+ MOVL nev2+32(FP), R8
+ MOVQ ts+40(FP), R9
MOVL $72, AX
SYSCALL
JCC 2(PC)
NEGQ AX
+ MOVL AX, ret+48(FP)
RET
// void runtime·closeonexec(int32 fd);
TEXT runtime·closeonexec(SB),NOSPLIT,$0
- MOVL 8(SP), DI // fd
+ MOVL fd+0(FP), DI // fd
MOVQ $2, SI // F_SETFD
MOVQ $1, DX // FD_CLOEXEC
MOVL $92, AX // fcntl
diff --git a/src/pkg/runtime/sys_plan9_386.s b/src/runtime/sys_plan9_386.s
index 143cd2e49..a41b56258 100644
--- a/src/pkg/runtime/sys_plan9_386.s
+++ b/src/runtime/sys_plan9_386.s
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// setldt(int entry, int address, int limit)
TEXT runtime·setldt(SB),NOSPLIT,$0
@@ -12,31 +12,49 @@ TEXT runtime·setldt(SB),NOSPLIT,$0
TEXT runtime·open(SB),NOSPLIT,$0
MOVL $14, AX
INT $64
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·pread(SB),NOSPLIT,$0
MOVL $50, AX
INT $64
+ MOVL AX, ret+20(FP)
RET
TEXT runtime·pwrite(SB),NOSPLIT,$0
MOVL $51, AX
INT $64
+ MOVL AX, ret+20(FP)
RET
-TEXT runtime·seek(SB),NOSPLIT,$0
+// int32 _seek(int64*, int32, int64, int32)
+TEXT _seek<>(SB),NOSPLIT,$0
MOVL $39, AX
INT $64
- CMPL AX, $-1
- JNE 4(PC)
- MOVL a+0(FP), CX
- MOVL AX, 0(CX)
- MOVL AX, 4(CX)
+ RET
+
+TEXT runtime·seek(SB),NOSPLIT,$24
+ LEAL ret+16(FP), AX
+ MOVL fd+0(FP), BX
+ MOVL offset_lo+4(FP), CX
+ MOVL offset_hi+8(FP), DX
+ MOVL whence+12(FP), SI
+ MOVL AX, 0(SP)
+ MOVL BX, 4(SP)
+ MOVL CX, 8(SP)
+ MOVL DX, 12(SP)
+ MOVL SI, 16(SP)
+ CALL _seek<>(SB)
+ CMPL AX, $0
+ JGE 3(PC)
+ MOVL $-1, ret_lo+16(FP)
+ MOVL $-1, ret_hi+20(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$0
MOVL $4, AX
INT $64
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·exits(SB),NOSPLIT,$0
@@ -47,84 +65,112 @@ TEXT runtime·exits(SB),NOSPLIT,$0
TEXT runtime·brk_(SB),NOSPLIT,$0
MOVL $24, AX
INT $64
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·sleep(SB),NOSPLIT,$0
MOVL $17, AX
INT $64
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·plan9_semacquire(SB),NOSPLIT,$0
MOVL $37, AX
INT $64
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0
MOVL $52, AX
INT $64
+ MOVL AX, ret+8(FP)
+ RET
+
+TEXT nsec<>(SB),NOSPLIT,$0
+ MOVL $53, AX
+ INT $64
+ RET
+
+TEXT runtime·nsec(SB),NOSPLIT,$8
+ LEAL ret+4(FP), AX
+ MOVL AX, 0(SP)
+ CALL nsec<>(SB)
+ CMPL AX, $0
+ JGE 3(PC)
+ MOVL $-1, ret_lo+4(FP)
+ MOVL $-1, ret_hi+8(FP)
+ RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),NOSPLIT,$8-12
+ CALL runtime·nanotime(SB)
+ MOVL 0(SP), AX
+ MOVL 4(SP), DX
+
+ MOVL $1000000000, CX
+ DIVL CX
+ MOVL AX, sec+0(FP)
+ MOVL $0, sec+4(FP)
+ MOVL DX, nsec+8(FP)
RET
TEXT runtime·notify(SB),NOSPLIT,$0
MOVL $28, AX
INT $64
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·noted(SB),NOSPLIT,$0
MOVL $29, AX
INT $64
+ MOVL AX, ret+4(FP)
RET
TEXT runtime·plan9_semrelease(SB),NOSPLIT,$0
MOVL $38, AX
INT $64
+ MOVL AX, ret+8(FP)
RET
-
-TEXT runtime·rfork(SB),NOSPLIT,$0
- MOVL $19, AX // rfork
- MOVL stack+8(SP), CX
- MOVL mm+12(SP), BX // m
- MOVL gg+16(SP), DX // g
- MOVL fn+20(SP), SI // fn
- INT $64
- // In parent, return.
- CMPL AX, $0
- JEQ 2(PC)
+TEXT runtime·rfork(SB),NOSPLIT,$0
+ MOVL $19, AX
+ INT $64
+ MOVL AX, ret+4(FP)
RET
- // set SP to be on the new child stack
- MOVL CX, SP
+TEXT runtime·tstart_plan9(SB),NOSPLIT,$0
+ MOVL newm+0(FP), CX
+ MOVL m_g0(CX), DX
- // Initialize m, g.
- get_tls(AX)
- MOVL DX, g(AX)
- MOVL BX, m(AX)
+ // Layout new m scheduler stack on os stack.
+ MOVL SP, AX
+ MOVL AX, (g_stack+stack_hi)(DX)
+ SUBL $(64*1024), AX // stack size
+ MOVL AX, (g_stack+stack_lo)(DX)
+ MOVL AX, g_stackguard0(DX)
+ MOVL AX, g_stackguard1(DX)
// Initialize procid from TOS struct.
- // TODO: Be explicit and insert a new MOVL _tos(SB), AX here.
- MOVL 48(AX), AX // procid
- MOVL AX, m_procid(BX) // save pid as m->procid
-
+ MOVL _tos(SB), AX
+ MOVL 48(AX), AX
+ MOVL AX, m_procid(CX) // save pid as m->procid
+
+ // Finally, initialize g.
+ get_tls(BX)
+ MOVL DX, g(BX)
+
CALL runtime·stackcheck(SB) // smashes AX, CX
-
- MOVL 0(DX), DX // paranoia; check they are not nil
- MOVL 0(BX), BX
-
- // more paranoia; check that stack splitting code works
- PUSHL SI
- CALL runtime·emptyfunc(SB)
- POPL SI
-
- CALL SI // fn()
- CALL runtime·exit(SB)
+ CALL runtime·mstart(SB)
+
+ MOVL $0x1234, 0x1234 // not reached
RET
// void sigtramp(void *ureg, int8 *note)
TEXT runtime·sigtramp(SB),NOSPLIT,$0
get_tls(AX)
- // check that m exists
- MOVL m(AX), BX
+ // check that g exists
+ MOVL g(AX), BX
CMPL BX, $0
JNE 3(PC)
CALL runtime·badsignal2(SB) // will exit
@@ -135,16 +181,17 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0
MOVL note+8(SP), DX
// change stack
+ MOVL g_m(BX), BX
MOVL m_gsignal(BX), BP
- MOVL g_stackbase(BP), BP
+ MOVL (g_stack+stack_hi)(BP), BP
MOVL BP, SP
// make room for args and g
- SUBL $16, SP
+ SUBL $24, SP
// save g
MOVL g(AX), BP
- MOVL BP, 12(SP)
+ MOVL BP, 20(SP)
// g = m->gsignal
MOVL m_gsignal(BX), DI
@@ -156,10 +203,11 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0
MOVL BP, 8(SP)
CALL runtime·sighandler(SB)
+ MOVL 12(SP), AX
// restore g
get_tls(BX)
- MOVL 12(SP), BP
+ MOVL 20(SP), BP
MOVL BP, g(BX)
// call noted(AX)
@@ -173,27 +221,29 @@ TEXT runtime·setfpmasks(SB),NOSPLIT,$0
#define ERRMAX 128 /* from os_plan9.h */
-// func errstr() String
+// void errstr(int8 *buf, int32 len)
+TEXT errstr<>(SB),NOSPLIT,$0
+ MOVL $41, AX
+ INT $64
+ RET
+
+// func errstr() string
// Only used by package syscall.
// Grab error string due to a syscall made
// in entersyscall mode, without going
// through the allocator (issue 4994).
// See ../syscall/asm_plan9_386.s:/·Syscall/
-TEXT runtime·errstr(SB),NOSPLIT,$0
+TEXT runtime·errstr(SB),NOSPLIT,$8-8
get_tls(AX)
- MOVL m(AX), BX
+ MOVL g(AX), BX
+ MOVL g_m(BX), BX
MOVL m_errstr(BX), CX
- MOVL CX, 4(SP)
- MOVL $ERRMAX, 8(SP)
- MOVL $41, AX
- INT $64
-
- // syscall requires caller-save
- MOVL 4(SP), CX
-
- // push the argument
- PUSHL CX
+ MOVL CX, 0(SP)
+ MOVL $ERRMAX, 4(SP)
+ CALL errstr<>(SB)
CALL runtime·findnull(SB)
- POPL CX
- MOVL AX, 8(SP)
+ MOVL 4(SP), AX
+ MOVL AX, ret_len+4(FP)
+ MOVL 0(SP), AX
+ MOVL AX, ret_base+0(FP)
RET
diff --git a/src/pkg/runtime/sys_plan9_amd64.s b/src/runtime/sys_plan9_amd64.s
index e60459cb8..3a96c2bf9 100644
--- a/src/pkg/runtime/sys_plan9_amd64.s
+++ b/src/runtime/sys_plan9_amd64.s
@@ -3,149 +3,163 @@
// license that can be found in the LICENSE file.
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// setldt(int entry, int address, int limit)
TEXT runtime·setldt(SB),NOSPLIT,$0
RET
TEXT runtime·open(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $14, BP
SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·pread(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $50, BP
SYSCALL
+ MOVL AX, ret+32(FP)
RET
TEXT runtime·pwrite(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $51, BP
SYSCALL
+ MOVL AX, ret+32(FP)
RET
// int32 _seek(int64*, int32, int64, int32)
TEXT _seek<>(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $39, BP
SYSCALL
RET
// int64 seek(int32, int64, int32)
-TEXT runtime·seek(SB),NOSPLIT,$56
- LEAQ new+48(SP), CX
- MOVQ CX, 0(SP)
- MOVQ fd+0(FP), CX
- MOVQ CX, 8(SP)
- MOVQ off+8(FP), CX
+// Convenience wrapper around _seek, the actual system call.
+TEXT runtime·seek(SB),NOSPLIT,$32
+ LEAQ ret+24(FP), AX
+ MOVL fd+0(FP), BX
+ MOVQ offset+8(FP), CX
+ MOVL whence+16(FP), DX
+ MOVQ AX, 0(SP)
+ MOVL BX, 8(SP)
MOVQ CX, 16(SP)
- MOVQ whence+16(FP), CX
- MOVQ CX, 24(SP)
+ MOVL DX, 24(SP)
CALL _seek<>(SB)
CMPL AX, $0
JGE 2(PC)
- MOVQ $-1, new+48(SP)
- MOVQ new+48(SP), AX
+ MOVQ $-1, ret+24(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $4, BP
SYSCALL
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·exits(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $8, BP
SYSCALL
RET
TEXT runtime·brk_(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $24, BP
SYSCALL
+ MOVQ AX, ret+8(FP)
RET
TEXT runtime·sleep(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $17, BP
SYSCALL
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·plan9_semacquire(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $37, BP
SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $52, BP
SYSCALL
+ MOVL AX, ret+16(FP)
+ RET
+
+TEXT runtime·nsec(SB),NOSPLIT,$0
+ MOVQ $53, BP
+ SYSCALL
+ MOVQ AX, ret+8(FP)
+ RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),NOSPLIT,$8-12
+ CALL runtime·nanotime(SB)
+ MOVQ 0(SP), AX
+
+ // generated code for
+ // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
+ // adapted to reduce duplication
+ MOVQ AX, CX
+ MOVQ $1360296554856532783, AX
+ MULQ CX
+ ADDQ CX, DX
+ RCRQ $1, DX
+ SHRQ $29, DX
+ MOVQ DX, sec+0(FP)
+ IMULQ $1000000000, DX
+ SUBQ DX, CX
+ MOVL CX, nsec+8(FP)
RET
TEXT runtime·notify(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $28, BP
SYSCALL
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·noted(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $29, BP
SYSCALL
+ MOVL AX, ret+8(FP)
RET
TEXT runtime·plan9_semrelease(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
MOVQ $38, BP
SYSCALL
- RET
-
-TEXT runtime·nanotime(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
- MOVQ $60, BP
- SYSCALL
+ MOVL AX, ret+16(FP)
RET
TEXT runtime·rfork(SB),NOSPLIT,$0
- MOVQ $0x8000, AX
- MOVQ $19, BP // rfork
+ MOVQ $19, BP
SYSCALL
-
- // In parent, return.
- CMPQ AX, $0
- JEQ 2(PC)
+ MOVL AX, ret+8(FP)
RET
- // In child on forked stack.
- MOVQ mm+24(SP), BX // m
- MOVQ gg+32(SP), DX // g
- MOVQ fn+40(SP), SI // fn
+TEXT runtime·tstart_plan9(SB),NOSPLIT,$0
+ MOVQ newm+0(FP), CX
+ MOVQ m_g0(CX), DX
- // set SP to be on the new child stack
- MOVQ stack+16(SP), CX
- MOVQ CX, SP
+ // Layout new m scheduler stack on os stack.
+ MOVQ SP, AX
+ MOVQ AX, (g_stack+stack_hi)(DX)
+ SUBQ $(64*1024), AX // stack size
+ MOVQ AX, (g_stack+stack_lo)(DX)
+ MOVQ AX, g_stackguard0(DX)
+ MOVQ AX, g_stackguard1(DX)
- // Initialize m, g.
- get_tls(AX)
- MOVQ DX, g(AX)
- MOVQ BX, m(AX)
+ // Initialize procid from TOS struct.
+ MOVQ _tos(SB), AX
+ MOVL 64(AX), AX
+ MOVQ AX, m_procid(CX) // save pid as m->procid
+
+ // Finally, initialize g.
+ get_tls(BX)
+ MOVQ DX, g(BX)
- // Initialize AX from pid in TLS.
- MOVQ 0(FS), AX
- MOVQ AX, m_procid(BX) // save pid as m->procid
-
CALL runtime·stackcheck(SB) // smashes AX, CX
-
- MOVQ 0(DX), DX // paranoia; check they are not nil
- MOVQ 0(BX), BX
-
- CALL SI // fn()
- CALL runtime·exit(SB)
+ CALL runtime·mstart(SB)
+
+ MOVQ $0x1234, 0x1234 // not reached
RET
// This is needed by asm_amd64.s
@@ -156,8 +170,8 @@ TEXT runtime·settls(SB),NOSPLIT,$0
TEXT runtime·sigtramp(SB),NOSPLIT,$0
get_tls(AX)
- // check that m exists
- MOVQ m(AX), BX
+ // check that g exists
+ MOVQ g(AX), BX
CMPQ BX, $0
JNE 3(PC)
CALL runtime·badsignal2(SB) // will exit
@@ -168,16 +182,17 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0
MOVQ note+16(SP), DX
// change stack
+ MOVQ g_m(BX), BX
MOVQ m_gsignal(BX), R10
- MOVQ g_stackbase(R10), BP
+ MOVQ (g_stack+stack_hi)(R10), BP
MOVQ BP, SP
// make room for args and g
- SUBQ $32, SP
+ SUBQ $128, SP
// save g
MOVQ g(AX), BP
- MOVQ BP, 24(SP)
+ MOVQ BP, 32(SP)
// g = m->gsignal
MOVQ R10, g(AX)
@@ -188,10 +203,11 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0
MOVQ BP, 16(SP)
CALL runtime·sighandler(SB)
+ MOVL 24(SP), AX
// restore g
get_tls(BX)
- MOVQ 24(SP), R10
+ MOVQ 32(SP), R10
MOVQ R10, g(BX)
// call noted(AX)
@@ -210,28 +226,29 @@ TEXT runtime·setfpmasks(SB),NOSPLIT,$8
#define ERRMAX 128 /* from os_plan9.h */
-// func errstr() String
+// void errstr(int8 *buf, int32 len)
+TEXT errstr<>(SB),NOSPLIT,$0
+ MOVQ $41, BP
+ SYSCALL
+ RET
+
+// func errstr() string
// Only used by package syscall.
// Grab error string due to a syscall made
// in entersyscall mode, without going
// through the allocator (issue 4994).
-// See ../syscall/asm_plan9_386.s:/·Syscall/
-TEXT runtime·errstr(SB),NOSPLIT,$0
+// See ../syscall/asm_plan9_amd64.s:/·Syscall/
+TEXT runtime·errstr(SB),NOSPLIT,$16-16
get_tls(AX)
- MOVQ m(AX), BX
+ MOVQ g(AX), BX
+ MOVQ g_m(BX), BX
MOVQ m_errstr(BX), CX
- MOVQ CX, 8(SP)
- MOVQ $ERRMAX, 16(SP)
- MOVQ $0x8000, AX
- MOVQ $41, BP
- SYSCALL
-
- // syscall requires caller-save
- MOVQ 8(SP), CX
-
- // push the argument
- PUSHQ CX
+ MOVQ CX, 0(SP)
+ MOVQ $ERRMAX, 8(SP)
+ CALL errstr<>(SB)
CALL runtime·findnull(SB)
- POPQ CX
- MOVQ AX, 16(SP)
+ MOVQ 8(SP), AX
+ MOVQ AX, ret_len+8(FP)
+ MOVQ 0(SP), AX
+ MOVQ AX, ret_base+0(FP)
RET
diff --git a/src/pkg/runtime/sys_solaris_amd64.s b/src/runtime/sys_solaris_amd64.s
index 21517693b..0ebdab6ee 100644
--- a/src/pkg/runtime/sys_solaris_amd64.s
+++ b/src/runtime/sys_solaris_amd64.s
@@ -7,7 +7,7 @@
//
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// This is needed by asm_amd64.s
TEXT runtime·settls(SB),NOSPLIT,$8
@@ -18,11 +18,13 @@ TEXT runtime·settls(SB),NOSPLIT,$8
// Set the TLS errno pointer in M.
//
// Called using runtime·asmcgocall from os_solaris.c:/minit.
+// NOT USING GO CALLING CONVENTION.
TEXT runtime·miniterrno(SB),NOSPLIT,$0
// asmcgocall will put first argument into DI.
CALL DI // SysV ABI so returns in AX
get_tls(CX)
- MOVQ m(CX), BX
+ MOVQ g(CX), BX
+ MOVQ g_m(BX), BX
MOVQ AX, m_perrno(BX)
RET
@@ -32,6 +34,7 @@ TEXT runtime·miniterrno(SB),NOSPLIT,$0
// runtime·nanotime stack.
//
// Called using runtime·sysvicall6 from os_solaris.c:/nanotime.
+// NOT USING GO CALLING CONVENTION.
TEXT runtime·nanotime1(SB),NOSPLIT,$0
// need space for the timespec argument.
SUBQ $64, SP // 16 bytes will do, but who knows in the future?
@@ -46,6 +49,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$0
RET
// pipe(3c) wrapper that returns fds in AX, DX.
+// NOT USING GO CALLING CONVENTION.
TEXT runtime·pipe1(SB),NOSPLIT,$0
SUBQ $16, SP // 8 bytes will do, but stack has to be 16-byte alligned
MOVQ SP, DI
@@ -65,6 +69,7 @@ TEXT runtime·pipe1(SB),NOSPLIT,$0
// section 3.2.3.
//
// Called by runtime·asmcgocall or runtime·cgocall.
+// NOT USING GO CALLING CONVENTION.
TEXT runtime·asmsysvicall6(SB),NOSPLIT,$0
// asmcgocall will put first argument into DI.
PUSHQ DI // save for later
@@ -73,7 +78,8 @@ TEXT runtime·asmsysvicall6(SB),NOSPLIT,$0
MOVQ libcall_n(DI), R10
get_tls(CX)
- MOVQ m(CX), BX
+ MOVQ g(CX), BX
+ MOVQ g_m(BX), BX
MOVQ m_perrno(BX), DX
CMPQ DX, $0
JEQ skiperrno1
@@ -100,7 +106,8 @@ skipargs:
MOVQ DX, libcall_r2(DI)
get_tls(CX)
- MOVQ m(CX), BX
+ MOVQ g(CX), BX
+ MOVQ g_m(BX), BX
MOVQ m_perrno(BX), AX
CMPQ AX, $0
JEQ skiperrno2
@@ -118,14 +125,16 @@ TEXT runtime·tstart_sysvicall(SB),NOSPLIT,$0
// Make TLS entries point at g and m.
get_tls(BX)
MOVQ DX, g(BX)
- MOVQ DI, m(BX)
+ MOVQ DI, g_m(DX)
// Layout new m scheduler stack on os stack.
MOVQ SP, AX
- MOVQ AX, g_stackbase(DX)
+ MOVQ AX, (g_stack+stack_hi)(DX)
SUBQ $(0x100000), AX // stack size
- MOVQ AX, g_stackguard(DX)
+ MOVQ AX, (g_stack+stack_lo)(DX)
+ ADDQ $const_StackGuard, AX
MOVQ AX, g_stackguard0(DX)
+ MOVQ AX, g_stackguard1(DX)
// Someday the convention will be D is always cleared.
CLD
@@ -134,6 +143,7 @@ TEXT runtime·tstart_sysvicall(SB),NOSPLIT,$0
CALL runtime·mstart(SB)
XORL AX, AX // return 0 == success
+ MOVL AX, ret+8(FP)
RET
// Careful, this is called by __sighndlr, a libc function. We must preserve
@@ -154,24 +164,24 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0
MOVQ R15, 72(SP)
get_tls(BX)
- // check that m exists
- MOVQ m(BX), BP
- CMPQ BP, $0
+ // check that g exists
+ MOVQ g(BX), R10
+ CMPQ R10, $0
JNE allgood
MOVQ DI, 0(SP)
MOVQ $runtime·badsignal(SB), AX
CALL AX
- RET
+ JMP exit
allgood:
// save g
- MOVQ g(BX), R10
MOVQ R10, 80(SP)
// Save m->libcall and m->scratch. We need to do this because we
// might get interrupted by a signal in runtime·asmcgocall.
// save m->libcall
+ MOVQ g_m(R10), BP
LEAQ m_libcall(BP), R11
MOVQ libcall_fn(R11), R10
MOVQ R10, 88(SP)
@@ -217,7 +227,8 @@ allgood:
CALL runtime·sighandler(SB)
get_tls(BX)
- MOVQ m(BX), BP
+ MOVQ g(BX), BP
+ MOVQ g_m(BP), BP
// restore libcall
LEAQ m_libcall(BP), R11
MOVQ 88(SP), R10
@@ -255,6 +266,7 @@ allgood:
MOVQ 80(SP), R10
MOVQ R10, g(BX)
+exit:
// restore registers
MOVQ 32(SP), BX
MOVQ 40(SP), BP
@@ -265,3 +277,75 @@ allgood:
ADDQ $184, SP
RET
+
+// Called from runtime·usleep (Go). Can be called on Go stack, on OS stack,
+// can also be called in cgo callback path without a g->m.
+TEXT runtime·usleep1(SB),NOSPLIT,$0
+ MOVL usec+0(FP), DI
+ MOVQ $runtime·usleep2(SB), AX // to hide from 6l
+
+ // Execute call on m->g0.
+ get_tls(R15)
+ CMPQ R15, $0
+ JE usleep1_noswitch
+
+ MOVQ g(R15), R13
+ CMPQ R13, $0
+ JE usleep1_noswitch
+ MOVQ g_m(R13), R13
+ CMPQ R13, $0
+ JE usleep1_noswitch
+ // TODO(aram): do something about the cpu profiler here.
+
+ MOVQ m_g0(R13), R14
+ CMPQ g(R15), R14
+ JNE usleep1_switch
+ // executing on m->g0 already
+ CALL AX
+ RET
+
+usleep1_switch:
+ // Switch to m->g0 stack and back.
+ MOVQ (g_sched+gobuf_sp)(R14), R14
+ MOVQ SP, -8(R14)
+ LEAQ -8(R14), SP
+ CALL AX
+ MOVQ 0(SP), SP
+ RET
+
+usleep1_noswitch:
+ // Not a Go-managed thread. Do not switch stack.
+ CALL AX
+ RET
+
+// Runs on OS stack. duration (in µs units) is in DI.
+TEXT runtime·usleep2(SB),NOSPLIT,$0
+ MOVQ libc·usleep(SB), AX
+ CALL AX
+ RET
+
+// Runs on OS stack, called from runtime·osyield.
+TEXT runtime·osyield1(SB),NOSPLIT,$0
+ MOVQ libc·sched_yield(SB), AX
+ CALL AX
+ RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),NOSPLIT,$8-12
+ CALL runtime·nanotime(SB)
+ MOVQ 0(SP), AX
+
+ // generated code for
+ // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
+ // adapted to reduce duplication
+ MOVQ AX, CX
+ MOVQ $1360296554856532783, AX
+ MULQ CX
+ ADDQ CX, DX
+ RCRQ $1, DX
+ SHRQ $29, DX
+ MOVQ DX, sec+0(FP)
+ IMULQ $1000000000, DX
+ SUBQ DX, CX
+ MOVL CX, nsec+8(FP)
+ RET
diff --git a/src/pkg/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s
index 576831d2c..932fe9dd2 100644
--- a/src/pkg/runtime/sys_windows_386.s
+++ b/src/runtime/sys_windows_386.s
@@ -3,11 +3,11 @@
// license that can be found in the LICENSE file.
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// void runtime·asmstdcall(void *c);
TEXT runtime·asmstdcall(SB),NOSPLIT,$0
- MOVL c+0(FP), BX
+ MOVL fn+0(FP), BX
// SetLastError(0).
MOVL $0, 0x34(FS)
@@ -29,7 +29,7 @@ TEXT runtime·asmstdcall(SB),NOSPLIT,$0
MOVL BP, SP
// Return result.
- MOVL c+0(FP), BX
+ MOVL fn+0(FP), BX
MOVL AX, libcall_r1(BX)
MOVL DX, libcall_r2(BX)
@@ -62,6 +62,7 @@ TEXT runtime·badsignal2(SB),NOSPLIT,$24
// faster get/set last error
TEXT runtime·getlasterror(SB),NOSPLIT,$0
MOVL 0x34(FS), AX
+ MOVL AX, ret+0(FP)
RET
TEXT runtime·setlasterror(SB),NOSPLIT,$0
@@ -72,49 +73,96 @@ TEXT runtime·setlasterror(SB),NOSPLIT,$0
// Called by Windows as a Vectored Exception Handler (VEH).
// First argument is pointer to struct containing
// exception record and context pointers.
+// Handler function is stored in AX.
// Return 0 for 'not handled', -1 for handled.
TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
MOVL ptrs+0(FP), CX
- SUBL $28, SP
+ SUBL $40, SP
// save callee-saved registers
- MOVL BX, 12(SP)
+ MOVL BX, 28(SP)
MOVL BP, 16(SP)
MOVL SI, 20(SP)
MOVL DI, 24(SP)
- MOVL 0(CX), BX // ExceptionRecord*
- MOVL 4(CX), CX // Context*
+ MOVL AX, SI // save handler address
- // fetch g
+ // find g
get_tls(DX)
- CMPL DX, $0
- JNE 3(PC)
- MOVL $0, AX // continue
- JMP done
- MOVL m(DX), AX
- CMPL AX, $0
+ CMPL DX, $0
+ JNE 3(PC)
+ MOVL $0, AX // continue
+ JMP done
+ MOVL g(DX), DX
+ CMPL DX, $0
JNE 2(PC)
CALL runtime·badsignal2(SB)
- MOVL g(DX), DX
- // call sighandler(ExceptionRecord*, Context*, G*)
+
+ // save g and SP in case of stack switch
+ MOVL DX, 32(SP) // g
+ MOVL SP, 36(SP)
+
+ // do we need to switch to the g0 stack?
+ MOVL g_m(DX), BX
+ MOVL m_g0(BX), BX
+ CMPL DX, BX
+ JEQ sigtramp_g0
+
+ // switch to the g0 stack
+ get_tls(BP)
+ MOVL BX, g(BP)
+ MOVL (g_sched+gobuf_sp)(BX), DI
+ // make it look like mstart called us on g0, to stop traceback
+ SUBL $4, DI
+ MOVL $runtime·mstart(SB), 0(DI)
+ // traceback will think that we've done SUBL
+ // on this stack, so subtract them here to match.
+ // (we need room for sighandler arguments anyway).
+ // and re-save old SP for restoring later.
+ SUBL $40, DI
+ MOVL SP, 36(DI)
+ MOVL DI, SP
+
+sigtramp_g0:
+ MOVL 0(CX), BX // ExceptionRecord*
+ MOVL 4(CX), CX // Context*
MOVL BX, 0(SP)
MOVL CX, 4(SP)
MOVL DX, 8(SP)
- CALL runtime·sighandler(SB)
+ CALL SI // call handler
// AX is set to report result back to Windows
+ MOVL 12(SP), AX
+
+ // switch back to original stack and g
+ // no-op if we never left.
+ MOVL 36(SP), SP
+ MOVL 32(SP), DX
+ get_tls(BP)
+ MOVL DX, g(BP)
done:
// restore callee-saved registers
MOVL 24(SP), DI
MOVL 20(SP), SI
MOVL 16(SP), BP
- MOVL 12(SP), BX
+ MOVL 28(SP), BX
- ADDL $28, SP
+ ADDL $40, SP
// RET 4 (return and pop 4 bytes parameters)
BYTE $0xC2; WORD $4
RET // unreached; make assembler happy
+
+TEXT runtime·exceptiontramp(SB),NOSPLIT,$0
+ MOVL $runtime·exceptionhandler(SB), AX
+ JMP runtime·sigtramp(SB)
+
+TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0
+ // is never called
+ INT $3
+
+TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0
+ MOVL $runtime·lastcontinuehandler(SB), AX
+ JMP runtime·sigtramp(SB)
TEXT runtime·ctrlhandler(SB),NOSPLIT,$0
PUSHL $runtime·ctrlhandler1(SB)
@@ -147,7 +195,6 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
LEAL m_tls(SP), CX
MOVL CX, 0x14(FS)
- MOVL SP, m(CX)
MOVL SP, BX
SUBL $g_end, SP // space for G
MOVL SP, g(CX)
@@ -156,9 +203,14 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
MOVL SP, 0(SP)
MOVL $g_end, 4(SP)
CALL runtime·memclr(SB) // smashes AX,BX,CX
- LEAL -4096(SP), CX
- MOVL CX, g_stackguard(SP)
- MOVL DX, g_stackbase(SP)
+ LEAL g_end(SP), BX
+ MOVL BX, g_m(SP)
+ LEAL -8192(SP), CX
+ MOVL CX, (g_stack+stack_lo)(SP)
+ ADDL $const_StackGuard, CX
+ MOVL CX, g_stackguard0(SP)
+ MOVL CX, g_stackguard1(SP)
+ MOVL DX, (g_stack+stack_hi)(SP)
PUSHL 16(BP) // arg for handler
CALL 8(BP)
@@ -166,7 +218,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
get_tls(CX)
MOVL g(CX), CX
- MOVL g_stackbase(CX), SP
+ MOVL (g_stack+stack_hi)(CX), SP
POPL 0x14(FS)
POPL DI
POPL SI
@@ -174,7 +226,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
POPL BP
RET
-GLOBL runtime·cbctxts(SB), $4
+GLOBL runtime·cbctxts(SB), NOPTR, $4
TEXT runtime·callbackasm1+0(SB),NOSPLIT,$0
MOVL 0(SP), AX // will use to find our callback context
@@ -258,14 +310,17 @@ TEXT runtime·tstart(SB),NOSPLIT,$0
// Layout new m scheduler stack on os stack.
MOVL SP, AX
- MOVL AX, g_stackbase(DX)
+ MOVL AX, (g_stack+stack_hi)(DX)
SUBL $(64*1024), AX // stack size
- MOVL AX, g_stackguard(DX)
+ MOVL AX, (g_stack+stack_lo)(DX)
+ ADDL $const_StackGuard, AX
+ MOVL AX, g_stackguard0(DX)
+ MOVL AX, g_stackguard1(DX)
// Set up tls.
LEAL m_tls(CX), SI
MOVL SI, 0x14(FS)
- MOVL CX, m(SI)
+ MOVL CX, g_m(DX)
MOVL DX, g(SI)
// Someday the convention will be D is always cleared.
@@ -301,7 +356,7 @@ TEXT runtime·setldt(SB),NOSPLIT,$0
// Sleep duration is in 100ns units.
TEXT runtime·usleep1(SB),NOSPLIT,$0
- MOVL duration+0(FP), BX
+ MOVL usec+0(FP), BX
MOVL $runtime·usleep2(SB), AX // to hide from 8l
// Execute call on m->g0 stack, in case we are not actually
@@ -313,7 +368,8 @@ TEXT runtime·usleep1(SB),NOSPLIT,$0
CALL AX
RET
- MOVL m(CX), BP
+ MOVL g(CX), BP
+ MOVL g_m(BP), BP
// leave pc/sp for cpu profiler
MOVL (SP), SI
@@ -322,7 +378,7 @@ TEXT runtime·usleep1(SB),NOSPLIT,$0
MOVL SI, m_libcallg(BP)
// sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them
- LEAL 4(SP), SI
+ LEAL usec+0(FP), SI
MOVL SI, m_libcallsp(BP)
MOVL m_g0(BP), SI
@@ -342,7 +398,8 @@ usleep1_switch:
usleep1_ret:
get_tls(CX)
- MOVL m(CX), BP
+ MOVL g(CX), BP
+ MOVL g_m(BP), BP
MOVL $0, m_libcallsp(BP)
RET
@@ -361,3 +418,16 @@ TEXT runtime·usleep2(SB),NOSPLIT,$20
CALL AX
MOVL BP, SP
RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),NOSPLIT,$8-12
+ CALL runtime·unixnano(SB)
+ MOVL 0(SP), AX
+ MOVL 4(SP), DX
+
+ MOVL $1000000000, CX
+ DIVL CX
+ MOVL AX, sec+0(FP)
+ MOVL $0, sec+4(FP)
+ MOVL DX, nsec+8(FP)
+ RET
diff --git a/src/pkg/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s
index d161be6a5..e6190ce68 100644
--- a/src/pkg/runtime/sys_windows_amd64.s
+++ b/src/runtime/sys_windows_amd64.s
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
// maxargs should be divisible by 2, as Windows stack
// must be kept 16-byte aligned on syscall entry.
@@ -87,6 +87,7 @@ TEXT runtime·badsignal2(SB),NOSPLIT,$48
TEXT runtime·getlasterror(SB),NOSPLIT,$0
MOVQ 0x30(GS), AX
MOVL 0x68(AX), AX
+ MOVL AX, ret+0(FP)
RET
TEXT runtime·setlasterror(SB),NOSPLIT,$0
@@ -98,6 +99,7 @@ TEXT runtime·setlasterror(SB),NOSPLIT,$0
// Called by Windows as a Vectored Exception Handler (VEH).
// First argument is pointer to struct containing
// exception record and context pointers.
+// Handler function is stored in AX.
// Return 0 for 'not handled', -1 for handled.
TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
// CX: PEXCEPTION_POINTERS ExceptionInfo
@@ -105,7 +107,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
// DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
// as required by windows callback convention.
PUSHFQ
- SUBQ $88, SP
+ SUBQ $112, SP
MOVQ DI, 80(SP)
MOVQ SI, 72(SP)
MOVQ BP, 64(SP)
@@ -113,32 +115,68 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
MOVQ R12, 48(SP)
MOVQ R13, 40(SP)
MOVQ R14, 32(SP)
- MOVQ R15, 24(SP)
+ MOVQ R15, 88(SP)
- MOVQ 0(CX), BX // ExceptionRecord*
- MOVQ 8(CX), CX // Context*
+ MOVQ AX, R15 // save handler address
- // fetch g
+ // find g
get_tls(DX)
- CMPQ DX, $0
- JNE 3(PC)
- MOVQ $0, AX // continue
- JMP done
- MOVQ m(DX), AX
- CMPQ AX, $0
+ CMPQ DX, $0
+ JNE 3(PC)
+ MOVQ $0, AX // continue
+ JMP done
+ MOVQ g(DX), DX
+ CMPQ DX, $0
JNE 2(PC)
CALL runtime·badsignal2(SB)
- MOVQ g(DX), DX
- // call sighandler(ExceptionRecord*, Context*, G*)
+
+ // save g and SP in case of stack switch
+ MOVQ DX, 96(SP) // g
+ MOVQ SP, 104(SP)
+
+ // do we need to switch to the g0 stack?
+ MOVQ g_m(DX), BX
+ MOVQ m_g0(BX), BX
+ CMPQ DX, BX
+ JEQ sigtramp_g0
+
+ // switch to g0 stack
+ get_tls(BP)
+ MOVQ BX, g(BP)
+ MOVQ (g_sched+gobuf_sp)(BX), DI
+ // make it look like mstart called us on g0, to stop traceback
+ SUBQ $8, DI
+ MOVQ $runtime·mstart(SB), SI
+ MOVQ SI, 0(DI)
+ // traceback will think that we've done PUSHFQ and SUBQ
+ // on this stack, so subtract them here to match.
+ // (we need room for sighandler arguments anyway).
+ // and re-save old SP for restoring later.
+ SUBQ $(112+8), DI
+ // save g, save old stack pointer.
+ MOVQ SP, 104(DI)
+ MOVQ DI, SP
+
+sigtramp_g0:
+ MOVQ 0(CX), BX // ExceptionRecord*
+ MOVQ 8(CX), CX // Context*
MOVQ BX, 0(SP)
MOVQ CX, 8(SP)
MOVQ DX, 16(SP)
- CALL runtime·sighandler(SB)
+ CALL R15 // call handler
// AX is set to report result back to Windows
+ MOVL 24(SP), AX
+
+ // switch back to original stack and g
+ // no-op if we never left.
+ MOVQ 104(SP), SP
+ MOVQ 96(SP), DX
+ get_tls(BP)
+ MOVQ DX, g(BP)
done:
// restore registers as required for windows callback
- MOVQ 24(SP), R15
+ MOVQ 88(SP), R15
MOVQ 32(SP), R14
MOVQ 40(SP), R13
MOVQ 48(SP), R12
@@ -146,11 +184,23 @@ done:
MOVQ 64(SP), BP
MOVQ 72(SP), SI
MOVQ 80(SP), DI
- ADDQ $88, SP
+ ADDQ $112, SP
POPFQ
RET
+TEXT runtime·exceptiontramp(SB),NOSPLIT,$0
+ MOVQ $runtime·exceptionhandler(SB), AX
+ JMP runtime·sigtramp(SB)
+
+TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0
+ MOVQ $runtime·firstcontinuehandler(SB), AX
+ JMP runtime·sigtramp(SB)
+
+TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0
+ MOVQ $runtime·lastcontinuehandler(SB), AX
+ JMP runtime·sigtramp(SB)
+
TEXT runtime·ctrlhandler(SB),NOSPLIT,$8
MOVQ CX, 16(SP) // spill
MOVQ $runtime·ctrlhandler1(SB), CX
@@ -181,7 +231,6 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
LEAQ m_tls(SP), CX
MOVQ CX, 0x28(GS)
- MOVQ SP, m(CX)
MOVQ SP, BX
SUBQ $g_end, SP // space for G
MOVQ SP, g(CX)
@@ -190,9 +239,15 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
MOVQ SP, 0(SP)
MOVQ $g_end, 8(SP)
CALL runtime·memclr(SB) // smashes AX,BX,CX
+ LEAQ g_end(SP), BX
+ MOVQ BX, g_m(SP)
+
LEAQ -8192(SP), CX
- MOVQ CX, g_stackguard(SP)
- MOVQ DX, g_stackbase(SP)
+ MOVQ CX, (g_stack+stack_lo)(SP)
+ ADDQ $const_StackGuard, CX
+ MOVQ CX, g_stackguard0(SP)
+ MOVQ CX, g_stackguard1(SP)
+ MOVQ DX, (g_stack+stack_hi)(SP)
PUSHQ 32(BP) // arg for handler
CALL 16(BP)
@@ -200,7 +255,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
get_tls(CX)
MOVQ g(CX), CX
- MOVQ g_stackbase(CX), SP
+ MOVQ (g_stack+stack_hi)(CX), SP
POPQ 0x28(GS)
POPQ DI
POPQ SI
@@ -208,7 +263,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
POPQ BP
RET
-GLOBL runtime·cbctxts(SB), $8
+GLOBL runtime·cbctxts(SB), NOPTR, $8
TEXT runtime·callbackasm1(SB),NOSPLIT,$0
// Construct args vector for cgocallback().
@@ -227,7 +282,8 @@ TEXT runtime·callbackasm1(SB),NOSPLIT,$0
ADDQ $8, SP
// determine index into runtime·cbctxts table
- SUBQ $runtime·callbackasm(SB), AX
+ MOVQ $runtime·callbackasm(SB), DX
+ SUBQ DX, AX
MOVQ $0, DX
MOVQ $5, CX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
DIVL CX,
@@ -295,14 +351,17 @@ TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
// Layout new m scheduler stack on os stack.
MOVQ SP, AX
- MOVQ AX, g_stackbase(DX)
+ MOVQ AX, (g_stack+stack_hi)(DX)
SUBQ $(64*1024), AX // stack size
- MOVQ AX, g_stackguard(DX)
+ MOVQ AX, (g_stack+stack_lo)(DX)
+ ADDQ $const_StackGuard, AX
+ MOVQ AX, g_stackguard0(DX)
+ MOVQ AX, g_stackguard1(DX)
// Set up tls.
LEAQ m_tls(CX), SI
MOVQ SI, 0x28(GS)
- MOVQ CX, m(SI)
+ MOVQ CX, g_m(DX)
MOVQ DX, g(SI)
// Someday the convention will be D is always cleared.
@@ -321,7 +380,7 @@ TEXT runtime·settls(SB),NOSPLIT,$0
// Sleep duration is in 100ns units.
TEXT runtime·usleep1(SB),NOSPLIT,$0
- MOVL duration+0(FP), BX
+ MOVL usec+0(FP), BX
MOVQ $runtime·usleep2(SB), AX // to hide from 6l
// Execute call on m->g0 stack, in case we are not actually
@@ -333,7 +392,8 @@ TEXT runtime·usleep1(SB),NOSPLIT,$0
CALL AX
RET
- MOVQ m(R15), R13
+ MOVQ g(R15), R13
+ MOVQ g_m(R13), R13
// leave pc/sp for cpu profiler
MOVQ (SP), R12
@@ -342,7 +402,7 @@ TEXT runtime·usleep1(SB),NOSPLIT,$0
MOVQ R12, m_libcallg(R13)
// sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them
- LEAQ 8(SP), R12
+ LEAQ usec+0(FP), R12
MOVQ R12, m_libcallsp(R13)
MOVQ m_g0(R13), R14
@@ -365,7 +425,10 @@ usleep1_ret:
RET
// Runs on OS stack. duration (in 100ns units) is in BX.
-TEXT runtime·usleep2(SB),NOSPLIT,$8
+TEXT runtime·usleep2(SB),NOSPLIT,$16
+ MOVQ SP, AX
+ ANDQ $~15, SP // alignment as per Windows requirement
+ MOVQ AX, 8(SP)
// Want negative 100ns units.
NEGQ BX
MOVQ SP, R8 // ptime
@@ -374,4 +437,26 @@ TEXT runtime·usleep2(SB),NOSPLIT,$8
MOVQ $0, DX // alertable
MOVQ runtime·NtWaitForSingleObject(SB), AX
CALL AX
+ MOVQ 8(SP), SP
RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),NOSPLIT,$8-12
+ CALL runtime·unixnano(SB)
+ MOVQ 0(SP), AX
+
+ // generated code for
+ // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
+ // adapted to reduce duplication
+ MOVQ AX, CX
+ MOVQ $1360296554856532783, AX
+ MULQ CX
+ ADDQ CX, DX
+ RCRQ $1, DX
+ SHRQ $29, DX
+ MOVQ DX, sec+0(FP)
+ IMULQ $1000000000, DX
+ SUBQ DX, CX
+ MOVL CX, nsec+8(FP)
+ RET
+
diff --git a/src/pkg/runtime/sys_x86.c b/src/runtime/sys_x86.c
index a450b3e58..a450b3e58 100644
--- a/src/pkg/runtime/sys_x86.c
+++ b/src/runtime/sys_x86.c
diff --git a/src/pkg/runtime/syscall_nacl.h b/src/runtime/syscall_nacl.h
index b33852ec8..b33852ec8 100644
--- a/src/pkg/runtime/syscall_nacl.h
+++ b/src/runtime/syscall_nacl.h
diff --git a/src/runtime/syscall_solaris.c b/src/runtime/syscall_solaris.c
new file mode 100644
index 000000000..13ac31bde
--- /dev/null
+++ b/src/runtime/syscall_solaris.c
@@ -0,0 +1,23 @@
+// 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.
+
+#pragma dynimport libc·chdir chdir "libc.so"
+#pragma dynimport libc·chroot chroot "libc.so"
+#pragma dynimport libc·close close "libc.so"
+#pragma dynimport libc·dlclose dlclose "libc.so"
+#pragma dynimport libc·dlopen dlopen "libc.so"
+#pragma dynimport libc·dlsym dlsym "libc.so"
+#pragma dynimport libc·execve execve "libc.so"
+#pragma dynimport libc·fcntl fcntl "libc.so"
+#pragma dynimport libc·gethostname gethostname "libc.so"
+#pragma dynimport libc·ioctl ioctl "libc.so"
+#pragma dynimport libc·pipe pipe "libc.so"
+#pragma dynimport libc·setgid setgid "libc.so"
+#pragma dynimport libc·setgroups setgroups "libc.so"
+#pragma dynimport libc·setsid setsid "libc.so"
+#pragma dynimport libc·setuid setuid "libc.so"
+#pragma dynimport libc·setpgid setsid "libc.so"
+#pragma dynimport libc·syscall syscall "libc.so"
+#pragma dynimport libc·forkx forkx "libc.so"
+#pragma dynimport libc·wait4 wait4 "libc.so"
diff --git a/src/runtime/syscall_solaris.go b/src/runtime/syscall_solaris.go
new file mode 100644
index 000000000..50d3a1d36
--- /dev/null
+++ b/src/runtime/syscall_solaris.go
@@ -0,0 +1,322 @@
+// 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 (
+ libc_chdir,
+ libc_chroot,
+ libc_close,
+ libc_dlopen,
+ libc_dlclose,
+ libc_dlsym,
+ libc_execve,
+ libc_exit,
+ libc_fcntl,
+ libc_forkx,
+ libc_gethostname,
+ libc_ioctl,
+ libc_pipe,
+ libc_setgid,
+ libc_setgroups,
+ libc_setsid,
+ libc_setuid,
+ libc_setpgid,
+ libc_syscall,
+ libc_wait4,
+ libc_write,
+ pipe1 libcFunc
+)
+
+//go:nosplit
+func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ call := libcall{
+ fn: fn,
+ n: nargs,
+ args: uintptr(unsafe.Pointer(&a1)),
+ }
+ entersyscallblock()
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ exitsyscall()
+ return call.r1, call.r2, call.err
+}
+
+//go:nosplit
+func syscall_rawsysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ call := libcall{
+ fn: fn,
+ n: nargs,
+ args: uintptr(unsafe.Pointer(&a1)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.r1, call.r2, call.err
+}
+
+// TODO(aram): Once we remove all instances of C calling sysvicallN, make
+// sysvicallN return errors and replace the body of the following functions
+// with calls to sysvicallN.
+
+//go:nosplit
+func syscall_chdir(path uintptr) (err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_chdir)),
+ n: 1,
+ args: uintptr(unsafe.Pointer(&path)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.err
+}
+
+//go:nosplit
+func syscall_chroot(path uintptr) (err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_chroot)),
+ n: 1,
+ args: uintptr(unsafe.Pointer(&path)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.err
+}
+
+// like close, but must not split stack, for forkx.
+//go:nosplit
+func syscall_close(fd int32) int32 {
+ return int32(sysvicall1(&libc_close, uintptr(fd)))
+}
+
+func syscall_dlopen(name *byte, mode uintptr) (handle uintptr, err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_dlopen)),
+ n: 2,
+ args: uintptr(unsafe.Pointer(&name)),
+ }
+ entersyscallblock()
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ exitsyscall()
+ if call.r1 == 0 {
+ return call.r1, call.err
+ }
+ return call.r1, 0
+}
+
+func syscall_dlclose(handle uintptr) (err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_dlclose)),
+ n: 1,
+ args: uintptr(unsafe.Pointer(&handle)),
+ }
+ entersyscallblock()
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ exitsyscall()
+ return call.r1
+}
+
+func syscall_dlsym(handle uintptr, name *byte) (proc uintptr, err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_dlsym)),
+ n: 2,
+ args: uintptr(unsafe.Pointer(&handle)),
+ }
+ entersyscallblock()
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ exitsyscall()
+ if call.r1 == 0 {
+ return call.r1, call.err
+ }
+ return call.r1, 0
+}
+
+//go:nosplit
+func syscall_execve(path, argv, envp uintptr) (err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_execve)),
+ n: 3,
+ args: uintptr(unsafe.Pointer(&path)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.err
+}
+
+// like exit, but must not split stack, for forkx.
+//go:nosplit
+func syscall_exit(code uintptr) {
+ sysvicall1(&libc_exit, code)
+}
+
+//go:nosplit
+func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_fcntl)),
+ n: 3,
+ args: uintptr(unsafe.Pointer(&fd)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.r1, call.err
+}
+
+//go:nosplit
+func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_forkx)),
+ n: 1,
+ args: uintptr(unsafe.Pointer(&flags)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.r1, call.err
+}
+
+func syscall_gethostname() (name string, err uintptr) {
+ cname := new([_MAXHOSTNAMELEN]byte)
+ var args = [2]uintptr{uintptr(unsafe.Pointer(&cname[0])), _MAXHOSTNAMELEN}
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_gethostname)),
+ n: 2,
+ args: uintptr(unsafe.Pointer(&args[0])),
+ }
+ entersyscallblock()
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ exitsyscall()
+ if call.r1 != 0 {
+ return "", call.err
+ }
+ cname[_MAXHOSTNAMELEN-1] = 0
+ return gostringnocopy(&cname[0]), 0
+}
+
+//go:nosplit
+func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_ioctl)),
+ n: 3,
+ args: uintptr(unsafe.Pointer(&fd)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.err
+}
+
+func syscall_pipe() (r, w, err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&pipe1)),
+ n: 0,
+ args: uintptr(unsafe.Pointer(&pipe1)), // it's unused but must be non-nil, otherwise crashes
+ }
+ entersyscallblock()
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ exitsyscall()
+ return call.r1, call.r2, call.err
+}
+
+// This is syscall.RawSyscall, it exists to satisfy some build dependency,
+// but it doesn't work correctly.
+//
+// DO NOT USE!
+//
+// TODO(aram): make this panic once we stop calling fcntl(2) in net using it.
+func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_syscall)),
+ n: 4,
+ args: uintptr(unsafe.Pointer(&trap)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.r1, call.r2, call.err
+}
+
+//go:nosplit
+func syscall_setgid(gid uintptr) (err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_setgid)),
+ n: 1,
+ args: uintptr(unsafe.Pointer(&gid)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.err
+}
+
+//go:nosplit
+func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_setgroups)),
+ n: 2,
+ args: uintptr(unsafe.Pointer(&ngid)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.err
+}
+
+//go:nosplit
+func syscall_setsid() (pid, err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_setsid)),
+ n: 0,
+ args: uintptr(unsafe.Pointer(&libc_setsid)), // it's unused but must be non-nil, otherwise crashes
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.r1, call.err
+}
+
+//go:nosplit
+func syscall_setuid(uid uintptr) (err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_setuid)),
+ n: 1,
+ args: uintptr(unsafe.Pointer(&uid)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.err
+}
+
+//go:nosplit
+func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_setpgid)),
+ n: 2,
+ args: uintptr(unsafe.Pointer(&pid)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.err
+}
+
+// This is syscall.Syscall, it exists to satisfy some build dependency,
+// but it doesn't work correctly.
+//
+// DO NOT USE!
+//
+// TODO(aram): make this panic once we stop calling fcntl(2) in net using it.
+func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_syscall)),
+ n: 4,
+ args: uintptr(unsafe.Pointer(&trap)),
+ }
+ entersyscallblock()
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ exitsyscall()
+ return call.r1, call.r2, call.err
+}
+
+func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_wait4)),
+ n: 4,
+ args: uintptr(unsafe.Pointer(&pid)),
+ }
+ entersyscallblock()
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ exitsyscall()
+ return int(call.r1), call.err
+}
+
+//go:nosplit
+func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) {
+ call := libcall{
+ fn: uintptr(unsafe.Pointer(&libc_write)),
+ n: 3,
+ args: uintptr(unsafe.Pointer(&fd)),
+ }
+ asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+ return call.r1, call.err
+}
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
new file mode 100644
index 000000000..efbcab510
--- /dev/null
+++ b/src/runtime/syscall_windows.go
@@ -0,0 +1,170 @@
+// 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"
+)
+
+type callbacks struct {
+ lock mutex
+ ctxt [cb_max]*wincallbackcontext
+ n int
+}
+
+func (c *wincallbackcontext) isCleanstack() bool {
+ return c.cleanstack
+}
+
+func (c *wincallbackcontext) setCleanstack(cleanstack bool) {
+ c.cleanstack = cleanstack
+}
+
+var (
+ cbs callbacks
+ cbctxts **wincallbackcontext = &cbs.ctxt[0] // to simplify access to cbs.ctxt in sys_windows_*.s
+
+ callbackasm byte // type isn't really byte, it's code in runtime
+)
+
+// callbackasmAddr returns address of runtime.callbackasm
+// function adjusted by i.
+// runtime.callbackasm is just a series of CALL instructions
+// (each is 5 bytes long), and we want callback to arrive at
+// correspondent call instruction instead of start of
+// runtime.callbackasm.
+func callbackasmAddr(i int) uintptr {
+ return uintptr(add(unsafe.Pointer(&callbackasm), uintptr(i*5)))
+}
+
+func compileCallback(fn eface, cleanstack bool) (code uintptr) {
+ if fn._type == nil || (fn._type.kind&kindMask) != kindFunc {
+ panic("compilecallback: not a function")
+ }
+ ft := (*functype)(unsafe.Pointer(fn._type))
+ 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[0])); (*t).size != uintptrSize {
+ panic("compilecallback: output parameter size is wrong")
+ }
+ argsize := uintptr(0)
+ for _, t := range (*[1024](*_type))(unsafe.Pointer(&ft.in[0]))[:len(ft.in)] {
+ if (*t).size > uintptrSize {
+ panic("compilecallback: input parameter size is wrong")
+ }
+ argsize += uintptrSize
+ }
+
+ lock(&cbs.lock)
+ defer unlock(&cbs.lock)
+
+ n := cbs.n
+ for i := 0; i < n; i++ {
+ if cbs.ctxt[i].gobody == fn.data && cbs.ctxt[i].isCleanstack() == cleanstack {
+ return callbackasmAddr(i)
+ }
+ }
+ if n >= cb_max {
+ gothrow("too many callback functions")
+ }
+
+ c := new(wincallbackcontext)
+ c.gobody = fn.data
+ c.argsize = argsize
+ c.setCleanstack(cleanstack)
+ if cleanstack && argsize != 0 {
+ c.restorestack = argsize
+ } else {
+ c.restorestack = 0
+ }
+ cbs.ctxt[n] = c
+ cbs.n++
+
+ return callbackasmAddr(n)
+}
+
+func getLoadLibrary() uintptr
+
+//go:nosplit
+func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
+ var c libcall
+ c.fn = getLoadLibrary()
+ c.n = 1
+ c.args = uintptr(unsafe.Pointer(&filename))
+ cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
+ handle = c.r1
+ if handle == 0 {
+ err = c.err
+ }
+ return
+}
+
+func getGetProcAddress() uintptr
+
+//go:nosplit
+func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {
+ var c libcall
+ c.fn = getGetProcAddress()
+ c.n = 2
+ c.args = uintptr(unsafe.Pointer(&handle))
+ cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
+ outhandle = c.r1
+ if outhandle == 0 {
+ err = c.err
+ }
+ return
+}
+
+//go:nosplit
+func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ var c libcall
+ c.fn = fn
+ c.n = nargs
+ c.args = uintptr(unsafe.Pointer(&a1))
+ cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
+ return c.r1, c.r2, c.err
+}
+
+//go:nosplit
+func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ var c libcall
+ c.fn = fn
+ c.n = nargs
+ c.args = uintptr(unsafe.Pointer(&a1))
+ cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
+ return c.r1, c.r2, c.err
+}
+
+//go:nosplit
+func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
+ var c libcall
+ c.fn = fn
+ c.n = nargs
+ c.args = uintptr(unsafe.Pointer(&a1))
+ cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
+ return c.r1, c.r2, c.err
+}
+
+//go:nosplit
+func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) {
+ var c libcall
+ c.fn = fn
+ c.n = nargs
+ c.args = uintptr(unsafe.Pointer(&a1))
+ cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
+ return c.r1, c.r2, c.err
+}
+
+//go:nosplit
+func syscall_Syscall15(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
+ var c libcall
+ c.fn = fn
+ c.n = nargs
+ c.args = uintptr(unsafe.Pointer(&a1))
+ cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
+ return c.r1, c.r2, c.err
+}
diff --git a/src/pkg/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go
index fabf935d8..ce8a9ec1b 100644
--- a/src/pkg/runtime/syscall_windows_test.go
+++ b/src/runtime/syscall_windows_test.go
@@ -449,3 +449,87 @@ func TestStdcallAndCDeclCallbacks(t *testing.T) {
}
}
}
+
+func TestRegisterClass(t *testing.T) {
+ kernel32 := GetDLL(t, "kernel32.dll")
+ user32 := GetDLL(t, "user32.dll")
+ mh, _, _ := kernel32.Proc("GetModuleHandleW").Call(0)
+ cb := syscall.NewCallback(func(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintptr) {
+ t.Fatal("callback should never get called")
+ return 0
+ })
+ type Wndclassex struct {
+ Size uint32
+ Style uint32
+ WndProc uintptr
+ ClsExtra int32
+ WndExtra int32
+ Instance syscall.Handle
+ Icon syscall.Handle
+ Cursor syscall.Handle
+ Background syscall.Handle
+ MenuName *uint16
+ ClassName *uint16
+ IconSm syscall.Handle
+ }
+ name := syscall.StringToUTF16Ptr("test_window")
+ wc := Wndclassex{
+ WndProc: cb,
+ Instance: syscall.Handle(mh),
+ ClassName: name,
+ }
+ wc.Size = uint32(unsafe.Sizeof(wc))
+ a, _, err := user32.Proc("RegisterClassExW").Call(uintptr(unsafe.Pointer(&wc)))
+ if a == 0 {
+ t.Fatalf("RegisterClassEx failed: %v", err)
+ }
+ r, _, err := user32.Proc("UnregisterClassW").Call(uintptr(unsafe.Pointer(name)), 0)
+ if r == 0 {
+ t.Fatalf("UnregisterClass failed: %v", err)
+ }
+}
+
+func TestOutputDebugString(t *testing.T) {
+ d := GetDLL(t, "kernel32.dll")
+ p := syscall.StringToUTF16Ptr("testing OutputDebugString")
+ d.Proc("OutputDebugStringW").Call(uintptr(unsafe.Pointer(p)))
+}
+
+func TestRaiseException(t *testing.T) {
+ o := executeTest(t, raiseExceptionSource, nil)
+ if strings.Contains(o, "RaiseException should not return") {
+ t.Fatalf("RaiseException did not crash program: %v", o)
+ }
+ if !strings.Contains(o, "Exception 0xbad") {
+ t.Fatalf("No stack trace: %v", o)
+ }
+}
+
+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)
+ 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)
+}
+`
diff --git a/src/runtime/thunk.s b/src/runtime/thunk.s
new file mode 100644
index 000000000..0a0f147c4
--- /dev/null
+++ b/src/runtime/thunk.s
@@ -0,0 +1,183 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file exposes various internal runtime functions to other packages in std lib.
+
+#include "zasm_GOOS_GOARCH.h"
+#include "textflag.h"
+
+#ifdef GOARCH_arm
+#define JMP B
+#endif
+
+TEXT net·runtimeNano(SB),NOSPLIT,$0-0
+ JMP runtime·nanotime(SB)
+
+TEXT time·runtimeNano(SB),NOSPLIT,$0-0
+ JMP runtime·nanotime(SB)
+
+TEXT time·Sleep(SB),NOSPLIT,$0-0
+ JMP runtime·timeSleep(SB)
+
+TEXT time·startTimer(SB),NOSPLIT,$0-0
+ JMP runtime·startTimer(SB)
+
+TEXT time·stopTimer(SB),NOSPLIT,$0-0
+ JMP runtime·stopTimer(SB)
+
+TEXT sync·runtime_Syncsemacquire(SB),NOSPLIT,$0-0
+ JMP runtime·syncsemacquire(SB)
+
+TEXT sync·runtime_Syncsemrelease(SB),NOSPLIT,$0-0
+ JMP runtime·syncsemrelease(SB)
+
+TEXT sync·runtime_Syncsemcheck(SB),NOSPLIT,$0-0
+ JMP runtime·syncsemcheck(SB)
+
+TEXT sync·runtime_Semacquire(SB),NOSPLIT,$0-0
+ JMP runtime·asyncsemacquire(SB)
+
+TEXT sync·runtime_Semrelease(SB),NOSPLIT,$0-0
+ JMP runtime·asyncsemrelease(SB)
+
+TEXT sync·runtime_registerPoolCleanup(SB),NOSPLIT,$0-0
+ JMP runtime·registerPoolCleanup(SB)
+
+TEXT net·runtime_Semacquire(SB),NOSPLIT,$0-0
+ JMP runtime·asyncsemacquire(SB)
+
+TEXT net·runtime_Semrelease(SB),NOSPLIT,$0-0
+ JMP runtime·asyncsemrelease(SB)
+
+TEXT runtime∕pprof·runtime_cyclesPerSecond(SB),NOSPLIT,$0-0
+ JMP runtime·tickspersecond(SB)
+
+TEXT bytes·Compare(SB),NOSPLIT,$0-0
+ JMP runtime·cmpbytes(SB)
+
+TEXT reflect·call(SB), NOSPLIT, $0-0
+ JMP runtime·reflectcall(SB)
+
+TEXT reflect·chanclose(SB), NOSPLIT, $0-0
+ JMP runtime·closechan(SB)
+
+TEXT reflect·chanlen(SB), NOSPLIT, $0-0
+ JMP runtime·reflect_chanlen(SB)
+
+TEXT reflect·chancap(SB), NOSPLIT, $0-0
+ JMP runtime·reflect_chancap(SB)
+
+TEXT reflect·chansend(SB), NOSPLIT, $0-0
+ JMP runtime·reflect_chansend(SB)
+
+TEXT reflect·chanrecv(SB), NOSPLIT, $0-0
+ JMP runtime·reflect_chanrecv(SB)
+
+TEXT reflect·memmove(SB), NOSPLIT, $0-0
+ JMP runtime·memmove(SB)
+
+TEXT runtime∕debug·freeOSMemory(SB), NOSPLIT, $0-0
+ JMP runtime·freeOSMemory(SB)
+
+TEXT runtime∕debug·WriteHeapDump(SB), NOSPLIT, $0-0
+ JMP runtime·writeHeapDump(SB)
+
+TEXT net·runtime_pollServerInit(SB),NOSPLIT,$0-0
+ JMP runtime·netpollServerInit(SB)
+
+TEXT net·runtime_pollOpen(SB),NOSPLIT,$0-0
+ JMP runtime·netpollOpen(SB)
+
+TEXT net·runtime_pollClose(SB),NOSPLIT,$0-0
+ JMP runtime·netpollClose(SB)
+
+TEXT net·runtime_pollReset(SB),NOSPLIT,$0-0
+ JMP runtime·netpollReset(SB)
+
+TEXT net·runtime_pollWait(SB),NOSPLIT,$0-0
+ JMP runtime·netpollWait(SB)
+
+TEXT net·runtime_pollWaitCanceled(SB),NOSPLIT,$0-0
+ JMP runtime·netpollWaitCanceled(SB)
+
+TEXT net·runtime_pollSetDeadline(SB),NOSPLIT,$0-0
+ JMP runtime·netpollSetDeadline(SB)
+
+TEXT net·runtime_pollUnblock(SB),NOSPLIT,$0-0
+ JMP runtime·netpollUnblock(SB)
+
+TEXT syscall·setenv_c(SB), NOSPLIT, $0-0
+ JMP runtime·syscall_setenv_c(SB)
+
+TEXT syscall·unsetenv_c(SB), NOSPLIT, $0-0
+ JMP runtime·syscall_unsetenv_c(SB)
+
+TEXT reflect·makemap(SB),NOSPLIT,$0-0
+ JMP runtime·reflect_makemap(SB)
+
+TEXT reflect·mapaccess(SB),NOSPLIT,$0-0
+ JMP runtime·reflect_mapaccess(SB)
+
+TEXT reflect·mapassign(SB),NOSPLIT,$0-0
+ JMP runtime·reflect_mapassign(SB)
+
+TEXT reflect·mapdelete(SB),NOSPLIT,$0-0
+ JMP runtime·reflect_mapdelete(SB)
+
+TEXT reflect·mapiterinit(SB),NOSPLIT,$0-0
+ JMP runtime·reflect_mapiterinit(SB)
+
+TEXT reflect·mapiterkey(SB),NOSPLIT,$0-0
+ JMP runtime·reflect_mapiterkey(SB)
+
+TEXT reflect·mapiternext(SB),NOSPLIT,$0-0
+ JMP runtime·reflect_mapiternext(SB)
+
+TEXT reflect·maplen(SB),NOSPLIT,$0-0
+ JMP runtime·reflect_maplen(SB)
+
+TEXT reflect·ismapkey(SB),NOSPLIT,$0-0
+ JMP runtime·reflect_ismapkey(SB)
+
+TEXT reflect·ifaceE2I(SB),NOSPLIT,$0-0
+ JMP runtime·reflect_ifaceE2I(SB)
+
+TEXT reflect·unsafe_New(SB),NOSPLIT,$0-0
+ JMP runtime·newobject(SB)
+
+TEXT reflect·unsafe_NewArray(SB),NOSPLIT,$0-0
+ JMP runtime·newarray(SB)
+
+TEXT reflect·makechan(SB),NOSPLIT,$0-0
+ JMP runtime·makechan(SB)
+
+TEXT reflect·rselect(SB),NOSPLIT,$0-0
+ JMP runtime·reflect_rselect(SB)
+
+TEXT os·sigpipe(SB),NOSPLIT,$0-0
+ JMP runtime·os_sigpipe(SB)
+
+TEXT runtime·runtime_init(SB),NOSPLIT,$0-0
+ JMP runtime·init(SB)
+
+TEXT runtime·main_init(SB),NOSPLIT,$0-0
+ JMP main·init(SB)
+
+TEXT runtime·main_main(SB),NOSPLIT,$0-0
+ JMP main·main(SB)
+
+TEXT runtime·timenow(SB),NOSPLIT,$0-0
+ JMP time·now(SB)
+
+TEXT sync∕atomic·runtime_procPin(SB),NOSPLIT,$0-0
+ JMP sync·runtime_procPin(SB)
+
+TEXT sync∕atomic·runtime_procUnpin(SB),NOSPLIT,$0-0
+ JMP sync·runtime_procUnpin(SB)
+
+TEXT syscall·runtime_envs(SB),NOSPLIT,$0-0
+ JMP runtime·runtime_envs(SB)
+
+TEXT os·runtime_args(SB),NOSPLIT,$0-0
+ JMP runtime·runtime_args(SB)
diff --git a/src/runtime/thunk_solaris_amd64.s b/src/runtime/thunk_solaris_amd64.s
new file mode 100644
index 000000000..f61188c14
--- /dev/null
+++ b/src/runtime/thunk_solaris_amd64.s
@@ -0,0 +1,88 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file exposes various external library functions to Go code in the runtime.
+
+#include "zasm_GOOS_GOARCH.h"
+#include "textflag.h"
+
+TEXT runtime·libc_chdir(SB),NOSPLIT,$0
+ MOVQ libc·chdir(SB), AX
+ JMP AX
+
+TEXT runtime·libc_chroot(SB),NOSPLIT,$0
+ MOVQ libc·chroot(SB), AX
+ JMP AX
+
+TEXT runtime·libc_close(SB),NOSPLIT,$0
+ MOVQ libc·close(SB), AX
+ JMP AX
+
+TEXT runtime·libc_dlopen(SB),NOSPLIT,$0
+ MOVQ libc·dlopen(SB), AX
+ JMP AX
+
+TEXT runtime·libc_dlclose(SB),NOSPLIT,$0
+ MOVQ libc·dlclose(SB), AX
+ JMP AX
+
+TEXT runtime·libc_dlsym(SB),NOSPLIT,$0
+ MOVQ libc·dlsym(SB), AX
+ JMP AX
+
+TEXT runtime·libc_execve(SB),NOSPLIT,$0
+ MOVQ libc·execve(SB), AX
+ JMP AX
+
+TEXT runtime·libc_exit(SB),NOSPLIT,$0
+ MOVQ libc·exit(SB), AX
+ JMP AX
+
+TEXT runtime·libc_fcntl(SB),NOSPLIT,$0
+ MOVQ libc·fcntl(SB), AX
+ JMP AX
+
+TEXT runtime·libc_forkx(SB),NOSPLIT,$0
+ MOVQ libc·forkx(SB), AX
+ JMP AX
+
+TEXT runtime·libc_gethostname(SB),NOSPLIT,$0
+ MOVQ libc·gethostname(SB), AX
+ JMP AX
+
+TEXT runtime·libc_ioctl(SB),NOSPLIT,$0
+ MOVQ libc·ioctl(SB), AX
+ JMP AX
+
+TEXT runtime·libc_setgid(SB),NOSPLIT,$0
+ MOVQ libc·setgid(SB), AX
+ JMP AX
+
+TEXT runtime·libc_setgroups(SB),NOSPLIT,$0
+ MOVQ libc·setgroups(SB), AX
+ JMP AX
+
+TEXT runtime·libc_setsid(SB),NOSPLIT,$0
+ MOVQ libc·setsid(SB), AX
+ JMP AX
+
+TEXT runtime·libc_setuid(SB),NOSPLIT,$0
+ MOVQ libc·setuid(SB), AX
+ JMP AX
+
+TEXT runtime·libc_setpgid(SB),NOSPLIT,$0
+ MOVQ libc·setpgid(SB), AX
+ JMP AX
+
+TEXT runtime·libc_syscall(SB),NOSPLIT,$0
+ MOVQ libc·syscall(SB), AX
+ JMP AX
+
+TEXT runtime·libc_wait4(SB),NOSPLIT,$0
+ MOVQ libc·wait4(SB), AX
+ JMP AX
+
+TEXT runtime·libc_write(SB),NOSPLIT,$0
+ MOVQ libc·write(SB), AX
+ JMP AX
diff --git a/src/runtime/thunk_windows.s b/src/runtime/thunk_windows.s
new file mode 100644
index 000000000..7ccb98fd4
--- /dev/null
+++ b/src/runtime/thunk_windows.s
@@ -0,0 +1,30 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "zasm_GOOS_GOARCH.h"
+#include "textflag.h"
+
+TEXT syscall·Syscall(SB),NOSPLIT,$0-0
+ JMP runtime·syscall_Syscall(SB)
+
+TEXT syscall·Syscall6(SB),NOSPLIT,$0-0
+ JMP runtime·syscall_Syscall6(SB)
+
+TEXT syscall·Syscall9(SB),NOSPLIT,$0-0
+ JMP runtime·syscall_Syscall9(SB)
+
+TEXT syscall·Syscall12(SB),NOSPLIT,$0-0
+ JMP runtime·syscall_Syscall12(SB)
+
+TEXT syscall·Syscall15(SB),NOSPLIT,$0-0
+ JMP runtime·syscall_Syscall15(SB)
+
+TEXT syscall·loadlibrary(SB),NOSPLIT,$0-0
+ JMP runtime·syscall_loadlibrary(SB)
+
+TEXT syscall·getprocaddress(SB),NOSPLIT,$0-0
+ JMP runtime·syscall_getprocaddress(SB)
+
+TEXT syscall·compileCallback(SB),NOSPLIT,$0
+ JMP runtime·compileCallback(SB)
diff --git a/src/runtime/time.go b/src/runtime/time.go
new file mode 100644
index 000000000..11862c7e2
--- /dev/null
+++ b/src/runtime/time.go
@@ -0,0 +1,289 @@
+// 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.
+
+// Time-related runtime and pieces of package time.
+
+package runtime
+
+import "unsafe"
+
+// Package time knows the layout of this structure.
+// If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
+// For GOOS=nacl, package syscall knows the layout of this structure.
+// If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
+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
+ // a well-behaved function and not block.
+ when int64
+ period int64
+ f func(interface{}, uintptr)
+ arg interface{}
+ seq uintptr
+}
+
+var timers struct {
+ lock mutex
+ gp *g
+ created bool
+ sleeping bool
+ rescheduling bool
+ waitnote note
+ t []*timer
+}
+
+// nacl fake time support - time in nanoseconds since 1970
+var faketime int64
+
+// Package time APIs.
+// Godoc uses the comments in package time, not these.
+
+// time.now is implemented in assembly.
+
+// Sleep puts the current goroutine to sleep for at least ns nanoseconds.
+func timeSleep(ns int64) {
+ if ns <= 0 {
+ return
+ }
+
+ t := new(timer)
+ t.when = nanotime() + ns
+ t.f = goroutineReady
+ t.arg = getg()
+ lock(&timers.lock)
+ addtimerLocked(t)
+ goparkunlock(&timers.lock, "sleep")
+}
+
+// startTimer adds t to the timer heap.
+func startTimer(t *timer) {
+ if raceenabled {
+ racerelease(unsafe.Pointer(t))
+ }
+ addtimer(t)
+}
+
+// stopTimer removes t from the timer heap if it is there.
+// It returns true if t was removed, false if t wasn't even there.
+func stopTimer(t *timer) bool {
+ return deltimer(t)
+}
+
+// Go runtime.
+
+// Ready the goroutine arg.
+func goroutineReady(arg interface{}, seq uintptr) {
+ goready(arg.(*g))
+}
+
+func addtimer(t *timer) {
+ lock(&timers.lock)
+ addtimerLocked(t)
+ unlock(&timers.lock)
+}
+
+// Add a timer to the heap and start or kick the timer proc.
+// If the new timer is earlier than any of the others.
+// Timers are locked.
+func addtimerLocked(t *timer) {
+ // when must never be negative; otherwise timerproc will overflow
+ // during its delta calculation and never expire other runtime·timers.
+ if t.when < 0 {
+ t.when = 1<<63 - 1
+ }
+ t.i = len(timers.t)
+ timers.t = append(timers.t, t)
+ siftupTimer(t.i)
+ if t.i == 0 {
+ // siftup moved to top: new earliest deadline.
+ if timers.sleeping {
+ timers.sleeping = false
+ notewakeup(&timers.waitnote)
+ }
+ if timers.rescheduling {
+ timers.rescheduling = false
+ goready(timers.gp)
+ }
+ }
+ if !timers.created {
+ timers.created = true
+ go timerproc()
+ }
+}
+
+// Delete timer t from the heap.
+// Do not need to update the timerproc: if it wakes up early, no big deal.
+func deltimer(t *timer) bool {
+ // Dereference t so that any panic happens before the lock is held.
+ // Discard result, because t might be moving in the heap.
+ _ = t.i
+
+ lock(&timers.lock)
+ // t may not be registered anymore and may have
+ // a bogus i (typically 0, if generated by Go).
+ // Verify it before proceeding.
+ i := t.i
+ last := len(timers.t) - 1
+ if i < 0 || i > last || timers.t[i] != t {
+ unlock(&timers.lock)
+ return false
+ }
+ if i != last {
+ timers.t[i] = timers.t[last]
+ timers.t[i].i = i
+ }
+ timers.t[last] = nil
+ timers.t = timers.t[:last]
+ if i != last {
+ siftupTimer(i)
+ siftdownTimer(i)
+ }
+ unlock(&timers.lock)
+ return true
+}
+
+// Timerproc runs the time-driven events.
+// It sleeps until the next event in the timers heap.
+// If addtimer inserts a new earlier event, addtimer1 wakes timerproc early.
+func timerproc() {
+ timers.gp = getg()
+ timers.gp.issystem = true
+ for {
+ lock(&timers.lock)
+ timers.sleeping = false
+ now := nanotime()
+ delta := int64(-1)
+ for {
+ if len(timers.t) == 0 {
+ delta = -1
+ break
+ }
+ t := timers.t[0]
+ delta = t.when - now
+ if delta > 0 {
+ break
+ }
+ if t.period > 0 {
+ // leave in heap but adjust next time to fire
+ t.when += t.period * (1 + -delta/t.period)
+ siftdownTimer(0)
+ } else {
+ // remove from heap
+ last := len(timers.t) - 1
+ if last > 0 {
+ timers.t[0] = timers.t[last]
+ timers.t[0].i = 0
+ }
+ timers.t[last] = nil
+ timers.t = timers.t[:last]
+ if last > 0 {
+ siftdownTimer(0)
+ }
+ t.i = -1 // mark as removed
+ }
+ f := t.f
+ arg := t.arg
+ seq := t.seq
+ unlock(&timers.lock)
+ if raceenabled {
+ raceacquire(unsafe.Pointer(t))
+ }
+ f(arg, seq)
+ lock(&timers.lock)
+ }
+ if delta < 0 || faketime > 0 {
+ // No timers left - put goroutine to sleep.
+ timers.rescheduling = true
+ goparkunlock(&timers.lock, "timer goroutine (idle)")
+ continue
+ }
+ // At least one timer pending. Sleep until then.
+ timers.sleeping = true
+ noteclear(&timers.waitnote)
+ unlock(&timers.lock)
+ notetsleepg(&timers.waitnote, delta)
+ }
+}
+
+func timejump() *g {
+ if faketime == 0 {
+ return nil
+ }
+
+ lock(&timers.lock)
+ if !timers.created || len(timers.t) == 0 {
+ unlock(&timers.lock)
+ return nil
+ }
+
+ var gp *g
+ if faketime < timers.t[0].when {
+ faketime = timers.t[0].when
+ if timers.rescheduling {
+ timers.rescheduling = false
+ gp = timers.gp
+ }
+ }
+ unlock(&timers.lock)
+ return gp
+}
+
+// Heap maintenance algorithms.
+
+func siftupTimer(i int) {
+ t := timers.t
+ when := t[i].when
+ tmp := t[i]
+ for i > 0 {
+ p := (i - 1) / 4 // parent
+ if when >= t[p].when {
+ break
+ }
+ t[i] = t[p]
+ t[i].i = i
+ t[p] = tmp
+ t[p].i = p
+ i = p
+ }
+}
+
+func siftdownTimer(i int) {
+ t := timers.t
+ n := len(t)
+ when := t[i].when
+ tmp := t[i]
+ for {
+ c := i*4 + 1 // left child
+ c3 := c + 2 // mid child
+ if c >= n {
+ break
+ }
+ w := t[c].when
+ if c+1 < n && t[c+1].when < w {
+ w = t[c+1].when
+ c++
+ }
+ if c3 < n {
+ w3 := t[c3].when
+ if c3+1 < n && t[c3+1].when < w3 {
+ w3 = t[c3+1].when
+ c3++
+ }
+ if w3 < w {
+ w = w3
+ c = c3
+ }
+ }
+ if w >= when {
+ break
+ }
+ t[i] = t[c]
+ t[i].i = i
+ t[c] = tmp
+ t[c].i = c
+ i = c
+ }
+}
diff --git a/src/runtime/tls_arm.s b/src/runtime/tls_arm.s
new file mode 100644
index 000000000..85c3940bf
--- /dev/null
+++ b/src/runtime/tls_arm.s
@@ -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.
+
+#include "zasm_GOOS_GOARCH.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+// We have to resort to TLS variable to save g(R10).
+// One reason is that external code might trigger
+// SIGSEGV, and our runtime.sigtramp don't even know we
+// are in external code, and will continue to use R10,
+// this might as well result in another SIGSEGV.
+// Note: both functions will clobber R0 and R11 and
+// can be called from 5c ABI code.
+
+// On android, runtime.tlsg is a normal variable.
+// TLS offset is computed in x_cgo_inittls.
+
+// save_g saves the g register into pthread-provided
+// thread-local memory, so that we can call externally compiled
+// ARM code that will overwrite those registers.
+// NOTE: runtime.gogo assumes that R1 is preserved by this function.
+// runtime.mcall assumes this function only clobbers R0 and R11.
+// Returns with g in R0.
+TEXT runtime·save_g(SB),NOSPLIT,$-4
+#ifdef GOOS_nacl
+ // nothing to do as nacl/arm does not use TLS at all.
+ MOVW g, R0 // preserve R0 across call to setg<>
+ RET
+#endif
+ // If the host does not support MRC the linker will replace it with
+ // a call to runtime.read_tls_fallback which jumps to __kuser_get_tls.
+ // 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
+ // $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 GOOS_android
+ MOVW runtime·tlsg(SB), R11
+#else
+ MOVW $runtime·tlsg(SB), R11
+#endif
+ ADD R11, R0
+ MOVW g, 0(R0)
+ MOVW g, R0 // preserve R0 across call to setg<>
+ RET
+
+// load_g loads the g register from pthread-provided
+// thread-local memory, for use after calling externally compiled
+// ARM code that overwrote those registers.
+TEXT runtime·load_g(SB),NOSPLIT,$0
+#ifdef GOOS_nacl
+ // nothing to do as nacl/arm does not use TLS at all.
+ RET
+#endif
+ // See save_g
+ MRC 15, 0, R0, C13, C0, 3 // fetch TLS base 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 GOOS_android
+ MOVW runtime·tlsg(SB), R11
+#else
+ MOVW $runtime·tlsg(SB), R11
+#endif
+ ADD R11, R0
+ MOVW 0(R0), g
+ RET
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
new file mode 100644
index 000000000..1c6ce6e64
--- /dev/null
+++ b/src/runtime/traceback.go
@@ -0,0 +1,659 @@
+// 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 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.
+// On systems with link registers, the prologue for a non-leaf function stores the
+// incoming value of LR at the bottom of the newly allocated stack frame.
+// On systems without link registers, the architecture pushes a return PC during
+// the call instruction, so the return PC ends up above the stack frame.
+// In this file, the return PC is always called LR, no matter how it was found.
+//
+// To date, the opposite of a link register architecture is an x86 architecture.
+// This code may need to change if some other kind of non-link-register
+// architecture comes along.
+//
+// The other important fact is the size of a pointer: on 32-bit systems the LR
+// takes up only 4 bytes on the stack, while on 64-bit systems it takes up 8 bytes.
+// Typically this is ptrSize.
+//
+// As an exception, amd64p32 has ptrSize == 4 but the CALL instruction still
+// 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.
+
+const usesLR = GOARCH != "amd64" && GOARCH != "amd64p32" && GOARCH != "386"
+
+var (
+ // initialized in tracebackinit
+ deferprocPC uintptr
+ goexitPC uintptr
+ jmpdeferPC uintptr
+ mcallPC uintptr
+ morestackPC uintptr
+ mstartPC uintptr
+ newprocPC uintptr
+ rt0_goPC uintptr
+ sigpanicPC uintptr
+
+ externalthreadhandlerp uintptr // initialized elsewhere
+)
+
+func tracebackinit() {
+ // Go variable initialization happens late during runtime startup.
+ // Instead of initializing the variables above in the declarations,
+ // schedinit calls this function so that the variables are
+ // initialized and available earlier in the startup sequence.
+ deferprocPC = funcPC(deferproc)
+ goexitPC = funcPC(goexit)
+ jmpdeferPC = funcPC(jmpdefer)
+ mcallPC = funcPC(mcall)
+ morestackPC = funcPC(morestack)
+ mstartPC = funcPC(mstart)
+ newprocPC = funcPC(newproc)
+ rt0_goPC = funcPC(rt0_go)
+ sigpanicPC = funcPC(sigpanic)
+}
+
+// Traceback over the deferred function calls.
+// Report them like calls that have been invoked but not started executing yet.
+func tracebackdefers(gp *g, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer) {
+ var frame stkframe
+ for d := gp._defer; d != nil; d = d.link {
+ fn := d.fn
+ if fn == nil {
+ // Defer of nil function. Args don't matter.
+ frame.pc = 0
+ frame.fn = nil
+ frame.argp = 0
+ frame.arglen = 0
+ frame.argmap = nil
+ } else {
+ frame.pc = uintptr(fn.fn)
+ f := findfunc(frame.pc)
+ if f == nil {
+ print("runtime: unknown pc in defer ", hex(frame.pc), "\n")
+ gothrow("unknown pc")
+ }
+ frame.fn = f
+ frame.argp = uintptr(deferArgs(d))
+ setArgInfo(&frame, f, true)
+ }
+ frame.continpc = frame.pc
+ if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) {
+ return
+ }
+ }
+}
+
+// Generic traceback. Handles runtime stack prints (pcbuf == nil),
+// the runtime.Callers function (pcbuf != nil), as well as the garbage
+// collector (callback != nil). A little clunky to merge these, but avoids
+// duplicating the code and all its subtlety.
+func gentraceback(pc0 uintptr, sp0 uintptr, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max int, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer, flags uint) int {
+ if goexitPC == 0 {
+ gothrow("gentraceback before goexitPC initialization")
+ }
+ g := getg()
+ if g == gp && g == g.m.curg {
+ // The starting sp has been passed in as a uintptr, and the caller may
+ // have other uintptr-typed stack references as well.
+ // If during one of the calls that got us here or during one of the
+ // callbacks below the stack must be grown, all these uintptr references
+ // to the stack will not be updated, and gentraceback will continue
+ // to inspect the old stack memory, which may no longer be valid.
+ // Even if all the variables were updated correctly, it is not clear that
+ // we want to expose a traceback that begins on one stack and ends
+ // on another stack. That could confuse callers quite a bit.
+ // Instead, we require that gentraceback and any other function that
+ // accepts an sp for the current goroutine (typically obtained by
+ // calling getcallersp) must not run on that goroutine's stack but
+ // instead on the g0 stack.
+ gothrow("gentraceback cannot trace user goroutine on its own stack")
+ }
+ gotraceback := gotraceback(nil)
+ if pc0 == ^uintptr(0) && sp0 == ^uintptr(0) { // Signal to fetch saved values from gp.
+ if gp.syscallsp != 0 {
+ pc0 = gp.syscallpc
+ sp0 = gp.syscallsp
+ if usesLR {
+ lr0 = 0
+ }
+ } else {
+ pc0 = gp.sched.pc
+ sp0 = gp.sched.sp
+ if usesLR {
+ lr0 = gp.sched.lr
+ }
+ }
+ }
+
+ nprint := 0
+ var frame stkframe
+ frame.pc = pc0
+ frame.sp = sp0
+ if usesLR {
+ frame.lr = lr0
+ }
+ waspanic := false
+ wasnewproc := false
+ printing := pcbuf == nil && callback == nil
+ _defer := gp._defer
+
+ for _defer != nil && uintptr(_defer.argp) == _NoArgs {
+ _defer = _defer.link
+ }
+
+ // If the PC is zero, it's likely a nil function call.
+ // Start in the caller's frame.
+ if frame.pc == 0 {
+ if usesLR {
+ frame.pc = *(*uintptr)(unsafe.Pointer(frame.sp))
+ frame.lr = 0
+ } else {
+ frame.pc = uintptr(*(*uintreg)(unsafe.Pointer(frame.sp)))
+ frame.sp += regSize
+ }
+ }
+
+ f := findfunc(frame.pc)
+ if f == nil {
+ if callback != nil {
+ print("runtime: unknown pc ", hex(frame.pc), "\n")
+ gothrow("unknown pc")
+ }
+ return 0
+ }
+ frame.fn = f
+
+ n := 0
+ for n < max {
+ // Typically:
+ // pc is the PC of the running function.
+ // sp is the stack pointer at that program counter.
+ // fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown.
+ // stk is the stack containing sp.
+ // The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp.
+ f = frame.fn
+
+ // Found an actual function.
+ // Derive frame pointer and link register.
+ if frame.fp == 0 {
+ frame.fp = frame.sp + uintptr(funcspdelta(f, frame.pc))
+ if !usesLR {
+ // On x86, call instruction pushes return PC before entering new function.
+ frame.fp += regSize
+ }
+ }
+ var flr *_func
+ if topofstack(f) {
+ frame.lr = 0
+ flr = nil
+ } else if usesLR && f.entry == jmpdeferPC {
+ // jmpdefer modifies SP/LR/PC non-atomically.
+ // If a profiling interrupt arrives during jmpdefer,
+ // the stack unwind may see a mismatched register set
+ // and get confused. Stop if we see PC within jmpdefer
+ // to avoid that confusion.
+ // See golang.org/issue/8153.
+ if callback != nil {
+ gothrow("traceback_arm: found jmpdefer when tracing with callback")
+ }
+ frame.lr = 0
+ } else {
+ if usesLR {
+ if n == 0 && frame.sp < frame.fp || frame.lr == 0 {
+ frame.lr = *(*uintptr)(unsafe.Pointer(frame.sp))
+ }
+ } else {
+ if frame.lr == 0 {
+ frame.lr = uintptr(*(*uintreg)(unsafe.Pointer(frame.fp - regSize)))
+ }
+ }
+ flr = findfunc(frame.lr)
+ if flr == nil {
+ // This happens if you get a profiling interrupt at just the wrong time.
+ // In that context it is okay to stop early.
+ // But if callback is set, we're doing a garbage collection and must
+ // get everything, so crash loudly.
+ if callback != nil {
+ print("runtime: unexpected return pc for ", gofuncname(f), " called from ", hex(frame.lr), "\n")
+ gothrow("unknown caller pc")
+ }
+ }
+ }
+
+ frame.varp = frame.fp
+ if !usesLR {
+ // On x86, call instruction pushes return PC before entering new function.
+ frame.varp -= regSize
+ }
+
+ // Derive size of arguments.
+ // Most functions have a fixed-size argument block,
+ // so we can use metadata about the function f.
+ // Not all, though: there are some variadic functions
+ // 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)
+ }
+
+ // Determine function SP where deferproc would find its arguments.
+ var sparg uintptr
+ if usesLR {
+ // On link register architectures, that's the standard bottom-of-stack plus 1 word
+ // for the saved LR. If the previous frame was a direct call to newproc/deferproc,
+ // however, the SP is three words lower than normal.
+ // If the function has no frame at all - perhaps it just started, or perhaps
+ // it is a leaf with no local variables - then we cannot possibly find its
+ // SP in a defer, and we might confuse its SP for its caller's SP, so
+ // leave sparg=0 in that case.
+ if frame.fp != frame.sp {
+ sparg = frame.sp + regSize
+ if wasnewproc {
+ sparg += 3 * regSize
+ }
+ }
+ } else {
+ // On x86 that's the standard bottom-of-stack, so SP exactly.
+ // If the previous frame was a direct call to newproc/deferproc, however,
+ // the SP is two words lower than normal.
+ sparg = frame.sp
+ if wasnewproc {
+ sparg += 2 * ptrSize
+ }
+ }
+
+ // Determine frame's 'continuation PC', where it can continue.
+ // Normally this is the return address on the stack, but if sigpanic
+ // is immediately below this function on the stack, then the frame
+ // stopped executing due to a trap, and frame.pc is probably not
+ // a safe point for looking up liveness information. In this panicking case,
+ // the function either doesn't return at all (if it has no defers or if the
+ // defers do not recover) or it returns from one of the calls to
+ // deferproc a second time (if the corresponding deferred func recovers).
+ // It suffices to assume that the most recent deferproc is the one that
+ // returns; everything live at earlier deferprocs is still live at that one.
+ frame.continpc = frame.pc
+ if waspanic {
+ if _defer != nil && _defer.argp == sparg {
+ frame.continpc = _defer.pc
+ } else {
+ frame.continpc = 0
+ }
+ }
+
+ // Unwind our local defer stack past this frame.
+ for _defer != nil && (_defer.argp == sparg || _defer.argp == _NoArgs) {
+ _defer = _defer.link
+ }
+
+ if skip > 0 {
+ skip--
+ goto skipped
+ }
+
+ if pcbuf != nil {
+ (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = frame.pc
+ }
+ if callback != nil {
+ if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) {
+ return n
+ }
+ }
+ if printing {
+ if (flags&_TraceRuntimeFrames) != 0 || showframe(f, gp) {
+ // Print during crash.
+ // main(0x1, 0x2, 0x3)
+ // /home/rsc/go/src/runtime/x.go:23 +0xf
+ //
+ tracepc := frame.pc // back up to CALL instruction for funcline.
+ if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic {
+ tracepc--
+ }
+ print(gofuncname(f), "(")
+ argp := (*[100]uintptr)(unsafe.Pointer(frame.argp))
+ for i := uintptr(0); i < frame.arglen/ptrSize; i++ {
+ if i >= 10 {
+ print(", ...")
+ break
+ }
+ if i != 0 {
+ print(", ")
+ }
+ print(hex(argp[i]))
+ }
+ print(")\n")
+ var file string
+ line := funcline(f, tracepc, &file)
+ print("\t", file, ":", line)
+ if frame.pc > f.entry {
+ print(" +", hex(frame.pc-f.entry))
+ }
+ if g.m.throwing > 0 && gp == g.m.curg || gotraceback >= 2 {
+ print(" fp=", hex(frame.fp), " sp=", hex(frame.sp))
+ }
+ print("\n")
+ nprint++
+ }
+ }
+ n++
+
+ skipped:
+ waspanic = f.entry == sigpanicPC
+ wasnewproc = f.entry == newprocPC || f.entry == deferprocPC
+
+ // Do not unwind past the bottom of the stack.
+ if flr == nil {
+ break
+ }
+
+ // Unwind to next frame.
+ frame.fn = flr
+ frame.pc = frame.lr
+ frame.lr = 0
+ frame.sp = frame.fp
+ frame.fp = 0
+ frame.argmap = nil
+
+ // On link register architectures, sighandler saves the LR on stack
+ // before faking a call to sigpanic.
+ if usesLR && waspanic {
+ x := *(*uintptr)(unsafe.Pointer(frame.sp))
+ frame.sp += ptrSize
+ f = findfunc(frame.pc)
+ frame.fn = f
+ if f == nil {
+ frame.pc = x
+ } else if f.frame == 0 {
+ frame.lr = x
+ }
+ }
+ }
+
+ if pcbuf == nil && callback == nil {
+ n = nprint
+ }
+
+ // If callback != nil, we're being called to gather stack information during
+ // garbage collection or stack growth. In that context, require that we used
+ // up the entire defer stack. If not, then there is a bug somewhere and the
+ // garbage collection or stack growth may not have seen the correct picture
+ // of the stack. Crash now instead of silently executing the garbage collection
+ // or stack copy incorrectly and setting up for a mysterious crash later.
+ //
+ // Note that panic != nil is okay here: there can be leftover panics,
+ // because the defers on the panic stack do not nest in frame order as
+ // they do on the defer stack. If you have:
+ //
+ // frame 1 defers d1
+ // frame 2 defers d2
+ // frame 3 defers d3
+ // frame 4 panics
+ // frame 4's panic starts running defers
+ // frame 5, running d3, defers d4
+ // frame 5 panics
+ // frame 5's panic starts running defers
+ // frame 6, running d4, garbage collects
+ // frame 6, running d2, garbage collects
+ //
+ // During the execution of d4, the panic stack is d4 -> d3, which
+ // is nested properly, and we'll treat frame 3 as resumable, because we
+ // can find d3. (And in fact frame 3 is resumable. If d4 recovers
+ // and frame 5 continues running, d3, d3 can recover and we'll
+ // resume execution in (returning from) frame 3.)
+ //
+ // During the execution of d2, however, the panic stack is d2 -> d3,
+ // which is inverted. The scan will match d2 to frame 2 but having
+ // d2 on the stack until then means it will not match d3 to frame 3.
+ // This is okay: if we're running d2, then all the defers after d2 have
+ // completed and their corresponding frames are dead. Not finding d3
+ // for frame 3 means we'll set frame 3's continpc == 0, which is correct
+ // (frame 3 is dead). At the end of the walk the panic stack can thus
+ // contain defers (d3 in this case) for dead frames. The inversion here
+ // always indicates a dead frame, and the effect of the inversion on the
+ // scan is to hide those dead frames, so the scan is still okay:
+ // what's left on the panic stack are exactly (and only) the dead frames.
+ //
+ // We require callback != nil here because only when callback != nil
+ // do we know that gentraceback is being called in a "must be correct"
+ // context as opposed to a "best effort" context. The tracebacks with
+ // callbacks only happen when everything is stopped nicely.
+ // At other times, such as when gathering a stack for a profiling signal
+ // or when printing a traceback during a crash, everything may not be
+ // stopped nicely, and the stack walk may not be able to complete.
+ // It's okay in those situations not to use up the entire defer stack:
+ // incomplete information then is still better than nothing.
+ if callback != nil && n < max && _defer != nil {
+ if _defer != nil {
+ print("runtime: g", gp.goid, ": leftover defer argp=", hex(_defer.argp), " pc=", hex(_defer.pc), "\n")
+ }
+ for _defer = gp._defer; _defer != nil; _defer = _defer.link {
+ print("\tdefer ", _defer, " argp=", hex(_defer.argp), " pc=", hex(_defer.pc), "\n")
+ }
+ gothrow("traceback has leftover defers")
+ }
+
+ return n
+}
+
+func setArgInfo(frame *stkframe, f *_func, needArgMap bool) {
+ frame.arglen = uintptr(f.args)
+ if needArgMap && f.args == _ArgsSizeUnknown {
+ // Extract argument bitmaps for reflect stubs from the calls they made to reflect.
+ switch gofuncname(f) {
+ case "reflect.makeFuncStub", "reflect.methodValueCall":
+ arg0 := frame.sp
+ if usesLR {
+ arg0 += ptrSize
+ }
+ fn := *(**[2]uintptr)(unsafe.Pointer(arg0))
+ if fn[0] != f.entry {
+ print("runtime: confused by ", gofuncname(f), "\n")
+ gothrow("reflect mismatch")
+ }
+ bv := (*bitvector)(unsafe.Pointer(fn[1]))
+ frame.arglen = uintptr(bv.n / 2 * ptrSize)
+ frame.argmap = bv
+ }
+ }
+}
+
+func printcreatedby(gp *g) {
+ // Show what created goroutine, except main goroutine (goid 1).
+ pc := gp.gopc
+ f := findfunc(pc)
+ if f != nil && showframe(f, gp) && gp.goid != 1 {
+ print("created by ", gofuncname(f), "\n")
+ tracepc := pc // back up to CALL instruction for funcline.
+ if pc > f.entry {
+ tracepc -= _PCQuantum
+ }
+ var file string
+ line := funcline(f, tracepc, &file)
+ print("\t", file, ":", line)
+ if pc > f.entry {
+ print(" +", hex(pc-f.entry))
+ }
+ print("\n")
+ }
+}
+
+func traceback(pc uintptr, sp uintptr, lr uintptr, gp *g) {
+ traceback1(pc, sp, lr, gp, 0)
+}
+
+// tracebacktrap is like traceback but expects that the PC and SP were obtained
+// from a trap, not from gp->sched or gp->syscallpc/gp->syscallsp or getcallerpc/getcallersp.
+// Because they are from a trap instead of from a saved pair,
+// the initial PC must not be rewound to the previous instruction.
+// (All the saved pairs record a PC that is a return address, so we
+// rewind it into the CALL instruction.)
+func tracebacktrap(pc uintptr, sp uintptr, lr uintptr, gp *g) {
+ traceback1(pc, sp, lr, gp, _TraceTrap)
+}
+
+func traceback1(pc uintptr, sp uintptr, lr uintptr, gp *g, flags uint) {
+ var n int
+ if readgstatus(gp)&^_Gscan == _Gsyscall {
+ // Override registers if blocked in system call.
+ pc = gp.syscallpc
+ sp = gp.syscallsp
+ flags &^= _TraceTrap
+ }
+ // Print traceback. By default, omits runtime frames.
+ // If that means we print nothing at all, repeat forcing all frames printed.
+ n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags)
+ if n == 0 && (flags&_TraceRuntimeFrames) == 0 {
+ n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags|_TraceRuntimeFrames)
+ }
+ if n == _TracebackMaxFrames {
+ print("...additional frames elided...\n")
+ }
+ printcreatedby(gp)
+}
+
+func callers(skip int, pcbuf *uintptr, m int) int {
+ sp := getcallersp(unsafe.Pointer(&skip))
+ pc := uintptr(getcallerpc(unsafe.Pointer(&skip)))
+ var n int
+ onM(func() {
+ n = gentraceback(pc, sp, 0, getg(), skip, pcbuf, m, nil, nil, 0)
+ })
+ return n
+}
+
+func gcallers(gp *g, skip int, pcbuf *uintptr, m int) int {
+ return gentraceback(^uintptr(0), ^uintptr(0), 0, gp, skip, pcbuf, m, nil, nil, 0)
+}
+
+func showframe(f *_func, gp *g) bool {
+ g := getg()
+ if g.m.throwing > 0 && gp != nil && (gp == g.m.curg || gp == g.m.caughtsig) {
+ return true
+ }
+ traceback := gotraceback(nil)
+ name := gostringnocopy(funcname(f))
+
+ // Special case: always show runtime.panic 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" {
+ return true
+ }
+
+ return traceback > 1 || f != nil && contains(name, ".") && (!hasprefix(name, "runtime.") || isExportedRuntime(name))
+}
+
+// isExportedRuntime reports whether name is an exported runtime function.
+// It is only for runtime functions, so ASCII A-Z is fine.
+func isExportedRuntime(name string) bool {
+ const n = len("runtime.")
+ return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z'
+}
+
+var gStatusStrings = [...]string{
+ _Gidle: "idle",
+ _Grunnable: "runnable",
+ _Grunning: "running",
+ _Gsyscall: "syscall",
+ _Gwaiting: "waiting",
+ _Gdead: "dead",
+ _Genqueue: "enqueue",
+ _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)
+
+ // 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 != "" {
+ 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 waitfor >= 1 {
+ print(", ", waitfor, " minutes")
+ }
+ if gp.lockedm != nil {
+ print(", locked to thread")
+ }
+ print("]:\n")
+}
+
+func tracebackothers(me *g) {
+ level := gotraceback(nil)
+
+ // Show the current goroutine first, if we haven't already.
+ g := getg()
+ gp := g.m.curg
+ if gp != nil && gp != me {
+ print("\n")
+ goroutineheader(gp)
+ traceback(^uintptr(0), ^uintptr(0), 0, gp)
+ }
+
+ lock(&allglock)
+ for _, gp := range allgs {
+ if gp == me || gp == g.m.curg || readgstatus(gp) == _Gdead || gp.issystem && level < 2 {
+ continue
+ }
+ print("\n")
+ goroutineheader(gp)
+ if readgstatus(gp)&^_Gscan == _Grunning {
+ print("\tgoroutine running on other thread; stack unavailable\n")
+ printcreatedby(gp)
+ } else {
+ traceback(^uintptr(0), ^uintptr(0), 0, gp)
+ }
+ }
+ unlock(&allglock)
+}
+
+// Does f mark the top of a goroutine stack?
+func topofstack(f *_func) bool {
+ pc := f.entry
+ return pc == goexitPC ||
+ pc == mstartPC ||
+ pc == mcallPC ||
+ pc == morestackPC ||
+ pc == rt0_goPC ||
+ externalthreadhandlerp != 0 && pc == externalthreadhandlerp
+}
diff --git a/src/pkg/runtime/type.h b/src/runtime/type.h
index 1598acc18..f5b4f9d13 100644
--- a/src/pkg/runtime/type.h
+++ b/src/runtime/type.h
@@ -2,11 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-/*
- * Runtime type representation; master is type.go
- *
- * The Type*s here correspond 1-1 to type.go's *rtype.
- */
+// Runtime type representation.
typedef struct Type Type;
typedef struct UncommonType UncommonType;
@@ -16,7 +12,7 @@ typedef struct IMethod IMethod;
typedef struct SliceType SliceType;
typedef struct FuncType FuncType;
-// Needs to be in sync with ../../cmd/ld/decodesym.c:/^commonsize
+// Needs to be in sync with ../../cmd/ld/decodesym.c:/^commonsize and pkg/reflect/type.go:/type.
struct Type
{
uintptr size;
@@ -25,8 +21,18 @@ struct Type
uint8 align;
uint8 fieldAlign;
uint8 kind;
- Alg *alg;
- void *gc;
+ void* alg;
+ // gc stores type info required for garbage collector.
+ // If (kind&KindGCProg)==0, then gc[0] points at sparse GC bitmap
+ // (no indirection), 4 bits per word.
+ // If (kind&KindGCProg)!=0, then gc[1] points to a compiler-generated
+ // read-only GC program; and gc[0] points to BSS space for sparse GC bitmap.
+ // For huge types (>MaxGCMask), runtime unrolls the program directly into
+ // GC bitmap and gc[0] is not used. For moderately-sized types, runtime
+ // unrolls the program into gc[0] space on first use. The first byte of gc[0]
+ // (gc[0][0]) contains 'unroll' flag saying whether the program is already
+ // unrolled into gc[0] or not.
+ uintptr gc[2];
String *string;
UncommonType *x;
Type *ptrto;
@@ -60,36 +66,41 @@ struct IMethod
struct InterfaceType
{
- Type;
+ Type typ;
Slice mhdr;
IMethod m[];
};
struct MapType
{
- Type;
+ Type typ;
Type *key;
Type *elem;
- Type *bucket; // internal type representing a hash bucket
- Type *hmap; // internal type representing a Hmap
+ Type *bucket; // internal type representing a hash bucket
+ Type *hmap; // internal type representing a Hmap
+ uint8 keysize; // size of key slot
+ bool indirectkey; // store ptr to key instead of key itself
+ uint8 valuesize; // size of value slot
+ bool indirectvalue; // store ptr to value instead of value itself
+ uint16 bucketsize; // size of bucket
};
struct ChanType
{
- Type;
+ Type typ;
Type *elem;
uintptr dir;
};
struct SliceType
{
- Type;
+ Type typ;
Type *elem;
};
struct FuncType
{
- Type;
+ Type typ;
bool dotdotdot;
Slice in;
Slice out;
@@ -97,6 +108,6 @@ struct FuncType
struct PtrType
{
- Type;
+ Type typ;
Type *elem;
};
diff --git a/src/runtime/typekind.go b/src/runtime/typekind.go
new file mode 100644
index 000000000..b64ec44f9
--- /dev/null
+++ b/src/runtime/typekind.go
@@ -0,0 +1,44 @@
+// 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 (
+ 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
+
+ kindDirectIface = _KindDirectIface
+ kindGCProg = _KindGCProg
+ kindNoPointers = _KindNoPointers
+ kindMask = _KindMask
+)
+
+// isDirectIface reports whether t is stored directly in an interface value.
+func isDirectIface(t *_type) bool {
+ return t.kind&kindDirectIface != 0
+}
diff --git a/src/pkg/runtime/typekind.h b/src/runtime/typekind.h
index 3f0ba9acb..e0fe177bb 100644
--- a/src/pkg/runtime/typekind.h
+++ b/src/runtime/typekind.h
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// PtrSize vs sizeof(void*): This file is also included from src/cmd/ld/...
-// which defines PtrSize to be different from sizeof(void*) when crosscompiling.
-
enum {
KindBool = 1,
KindInt,
@@ -33,6 +30,9 @@ enum {
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/pkg/runtime/vdso_linux_amd64.c b/src/runtime/vdso_linux_amd64.c
index f55d312a0..681340c5b 100644
--- a/src/pkg/runtime/vdso_linux_amd64.c
+++ b/src/runtime/vdso_linux_amd64.c
@@ -3,6 +3,18 @@
// license that can be found in the LICENSE file.
#include "runtime.h"
+#include "textflag.h"
+
+// Look up symbols in the Linux vDSO.
+
+// This code was originally based on the sample Linux vDSO parser at
+// https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/vDSO/parse_vdso.c
+
+// This implements the ELF dynamic linking spec at
+// http://sco.com/developers/gabi/latest/ch5.dynamic.html
+
+// The version section is documented at
+// http://refspecs.linuxfoundation.org/LSB_3.2.0/LSB-Core-generic/LSB-Core-generic/symversion.html
#define AT_RANDOM 25
#define AT_SYSINFO_EHDR 33
@@ -10,6 +22,7 @@
#define PT_LOAD 1 /* Loadable program segment */
#define PT_DYNAMIC 2 /* Dynamic linking information */
#define DT_NULL 0 /* Marks end of dynamic section */
+#define DT_HASH 4 /* Dynamic symbol hash table */
#define DT_STRTAB 5 /* Address of string table */
#define DT_SYMTAB 6 /* Address of symbol table */
#define DT_VERSYM 0x6ffffff0
@@ -39,7 +52,7 @@ typedef uint16 Elf64_Section;
typedef Elf64_Half Elf64_Versym;
-typedef struct
+typedef struct Elf64_Sym
{
Elf64_Word st_name;
byte st_info;
@@ -49,7 +62,7 @@ typedef struct
Elf64_Xword st_size;
} Elf64_Sym;
-typedef struct
+typedef struct Elf64_Verdef
{
Elf64_Half vd_version; /* Version revision */
Elf64_Half vd_flags; /* Version information */
@@ -60,7 +73,7 @@ typedef struct
Elf64_Word vd_next; /* Offset in bytes to next verdef entry */
} Elf64_Verdef;
-typedef struct
+typedef struct Elf64_Ehdr
{
byte e_ident[EI_NIDENT]; /* Magic number and other info */
Elf64_Half e_type; /* Object file type */
@@ -78,7 +91,7 @@ typedef struct
Elf64_Half e_shstrndx; /* Section header string table index */
} Elf64_Ehdr;
-typedef struct
+typedef struct Elf64_Phdr
{
Elf64_Word p_type; /* Segment type */
Elf64_Word p_flags; /* Segment flags */
@@ -90,7 +103,7 @@ typedef struct
Elf64_Xword p_align; /* Segment alignment */
} Elf64_Phdr;
-typedef struct
+typedef struct Elf64_Shdr
{
Elf64_Word sh_name; /* Section name (string tbl index) */
Elf64_Word sh_type; /* Section type */
@@ -104,7 +117,7 @@ typedef struct
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
-typedef struct
+typedef struct Elf64_Dyn
{
Elf64_Sxword d_tag; /* Dynamic entry type */
union
@@ -114,13 +127,13 @@ typedef struct
} d_un;
} Elf64_Dyn;
-typedef struct
+typedef struct Elf64_Verdaux
{
Elf64_Word vda_name; /* Version or dependency names */
Elf64_Word vda_next; /* Offset in bytes to next verdaux entry */
} Elf64_Verdaux;
-typedef struct
+typedef struct Elf64_auxv_t
{
uint64 a_type; /* Entry type */
union
@@ -130,12 +143,13 @@ typedef struct
} Elf64_auxv_t;
-typedef struct {
+typedef struct symbol_key {
byte* name;
+ int32 sym_hash;
void** var_ptr;
} symbol_key;
-typedef struct {
+typedef struct version_key {
byte* version;
int32 ver_hash;
} version_key;
@@ -148,27 +162,32 @@ struct vdso_info {
uintptr load_offset; /* load_addr - recorded vaddr */
/* Symbol table */
- int32 num_sym;
Elf64_Sym *symtab;
const byte *symstrings;
+ Elf64_Word *bucket, *chain;
+ Elf64_Word nbucket, nchain;
/* Version table */
Elf64_Versym *versym;
Elf64_Verdef *verdef;
};
+#pragma dataflag NOPTR
static version_key linux26 = { (byte*)"LINUX_2.6", 0x3ae75f6 };
// initialize with vsyscall fallbacks
+#pragma dataflag NOPTR
void* runtime·__vdso_time_sym = (void*)0xffffffffff600400ULL;
+#pragma dataflag NOPTR
void* runtime·__vdso_gettimeofday_sym = (void*)0xffffffffff600000ULL;
+#pragma dataflag NOPTR
void* runtime·__vdso_clock_gettime_sym = (void*)0;
-#define SYM_KEYS_COUNT 3
+#pragma dataflag NOPTR
static symbol_key sym_keys[] = {
- { (byte*)"__vdso_time", &runtime·__vdso_time_sym },
- { (byte*)"__vdso_gettimeofday", &runtime·__vdso_gettimeofday_sym },
- { (byte*)"__vdso_clock_gettime", &runtime·__vdso_clock_gettime_sym },
+ { (byte*)"__vdso_time", 0xa33c485, &runtime·__vdso_time_sym },
+ { (byte*)"__vdso_gettimeofday", 0x315ca59, &runtime·__vdso_gettimeofday_sym },
+ { (byte*)"__vdso_clock_gettime", 0xd35ec75, &runtime·__vdso_clock_gettime_sym },
};
static void
@@ -176,18 +195,15 @@ vdso_init_from_sysinfo_ehdr(struct vdso_info *vdso_info, Elf64_Ehdr* hdr)
{
uint64 i;
bool found_vaddr = false;
+ Elf64_Phdr *pt;
+ Elf64_Dyn *dyn;
+ Elf64_Word *hash;
+ vdso_info->valid = false;
vdso_info->load_addr = (uintptr) hdr;
- Elf64_Phdr *pt = (Elf64_Phdr*)(vdso_info->load_addr + hdr->e_phoff);
- Elf64_Shdr *sh = (Elf64_Shdr*)(vdso_info->load_addr + hdr->e_shoff);
- Elf64_Dyn *dyn = 0;
-
- for(i=0; i<hdr->e_shnum; i++) {
- if(sh[i].sh_type == SHT_DYNSYM) {
- vdso_info->num_sym = sh[i].sh_size / sizeof(Elf64_Sym);
- }
- }
+ pt = (Elf64_Phdr*)(vdso_info->load_addr + hdr->e_phoff);
+ dyn = nil;
// We need two things from the segment table: the load offset
// and the dynamic table.
@@ -206,6 +222,11 @@ vdso_init_from_sysinfo_ehdr(struct vdso_info *vdso_info, Elf64_Ehdr* hdr)
return; // Failed
// Fish out the useful bits of the dynamic table.
+ hash = nil;
+ vdso_info->symstrings = nil;
+ vdso_info->symtab = nil;
+ vdso_info->versym = nil;
+ vdso_info->verdef = nil;
for(i=0; dyn[i].d_tag!=DT_NULL; i++) {
switch(dyn[i].d_tag) {
case DT_STRTAB:
@@ -218,6 +239,11 @@ vdso_init_from_sysinfo_ehdr(struct vdso_info *vdso_info, Elf64_Ehdr* hdr)
((uintptr)dyn[i].d_un.d_ptr
+ vdso_info->load_offset);
break;
+ case DT_HASH:
+ hash = (Elf64_Word *)
+ ((uintptr)dyn[i].d_un.d_ptr
+ + vdso_info->load_offset);
+ break;
case DT_VERSYM:
vdso_info->versym = (Elf64_Versym *)
((uintptr)dyn[i].d_un.d_ptr
@@ -230,12 +256,18 @@ vdso_init_from_sysinfo_ehdr(struct vdso_info *vdso_info, Elf64_Ehdr* hdr)
break;
}
}
- if(vdso_info->symstrings == nil || vdso_info->symtab == nil)
+ if(vdso_info->symstrings == nil || vdso_info->symtab == nil || hash == nil)
return; // Failed
if(vdso_info->verdef == nil)
vdso_info->versym = 0;
+ // Parse the hash table header.
+ vdso_info->nbucket = hash[0];
+ vdso_info->nchain = hash[1];
+ vdso_info->bucket = &hash[2];
+ vdso_info->chain = &hash[vdso_info->nbucket + 2];
+
// That's all we need.
vdso_info->valid = true;
}
@@ -261,39 +293,41 @@ vdso_find_version(struct vdso_info *vdso_info, version_key* ver)
}
def = (Elf64_Verdef *)((byte *)def + def->vd_next);
}
- return 0;
+ return -1; // can not match any version
}
static void
vdso_parse_symbols(struct vdso_info *vdso_info, int32 version)
{
- int32 i, j;
+ int32 i;
+ Elf64_Word chain;
+ Elf64_Sym *sym;
if(vdso_info->valid == false)
return;
- for(i=0; i<vdso_info->num_sym; i++) {
- Elf64_Sym *sym = &vdso_info->symtab[i];
+ for(i=0; i<nelem(sym_keys); i++) {
+ for(chain = vdso_info->bucket[sym_keys[i].sym_hash % vdso_info->nbucket];
+ chain != 0; chain = vdso_info->chain[chain]) {
- // Check for a defined global or weak function w/ right name.
- if(ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
- continue;
- if(ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
- ELF64_ST_BIND(sym->st_info) != STB_WEAK)
- continue;
- if(sym->st_shndx == SHN_UNDEF)
- continue;
-
- for(j=0; j<SYM_KEYS_COUNT; j++) {
- if(runtime·strcmp(sym_keys[j].name, vdso_info->symstrings + sym->st_name) != 0)
+ sym = &vdso_info->symtab[chain];
+ if(ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
+ continue;
+ if(ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
+ ELF64_ST_BIND(sym->st_info) != STB_WEAK)
+ continue;
+ if(sym->st_shndx == SHN_UNDEF)
+ continue;
+ if(runtime·strcmp(sym_keys[i].name, vdso_info->symstrings + sym->st_name) != 0)
continue;
// Check symbol version.
if(vdso_info->versym != nil && version != 0
- && vdso_info->versym[i] & 0x7fff != version)
+ && vdso_info->versym[chain] & 0x7fff != version)
continue;
- *sym_keys[j].var_ptr = (void *)(vdso_info->load_offset + sym->st_value);
+ *sym_keys[i].var_ptr = (void *)(vdso_info->load_offset + sym->st_value);
+ break;
}
}
}
diff --git a/src/pkg/runtime/vlop_386.s b/src/runtime/vlop_386.s
index 9783fdc93..ce8e7d064 100644
--- a/src/pkg/runtime/vlop_386.s
+++ b/src/runtime/vlop_386.s
@@ -23,15 +23,15 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
/*
* C runtime for 64-bit divide.
*/
-// _mul64x32(r *uint64, a uint64, b uint32)
+// runtime·_mul64x32(r *uint64, a uint64, b uint32) uint32
// sets *r = low 64 bits of 96-bit product a*b; returns high 32 bits.
-TEXT _mul64by32(SB), NOSPLIT, $0
+TEXT runtime·_mul64by32(SB), NOSPLIT, $0
MOVL r+0(FP), CX
MOVL a+4(FP), AX
MULL b+12(FP)
@@ -43,12 +43,14 @@ TEXT _mul64by32(SB), NOSPLIT, $0
ADCL $0, DX
MOVL BX, 4(CX)
MOVL DX, AX
+ MOVL AX, ret+16(FP)
RET
-TEXT _div64by32(SB), NOSPLIT, $0
+TEXT runtime·_div64by32(SB), NOSPLIT, $0
MOVL r+12(FP), CX
MOVL a+0(FP), AX
MOVL a+4(FP), DX
DIVL b+8(FP)
MOVL DX, 0(CX)
+ MOVL AX, ret+16(FP)
RET
diff --git a/src/pkg/runtime/vlop_arm.s b/src/runtime/vlop_arm.s
index 80f516ec4..b4b905bb7 100644
--- a/src/pkg/runtime/vlop_arm.s
+++ b/src/runtime/vlop_arm.s
@@ -24,36 +24,35 @@
// THE SOFTWARE.
#include "zasm_GOOS_GOARCH.h"
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
arg=0
/* replaced use of R10 by R11 because the former can be the data segment base register */
TEXT _mulv(SB), NOSPLIT, $0
- MOVW 0(FP), R0
- MOVW 4(FP), R2 /* l0 */
- MOVW 8(FP), R11 /* h0 */
- MOVW 12(FP), R4 /* l1 */
- MOVW 16(FP), R5 /* h1 */
+ MOVW l0+0(FP), R2 /* l0 */
+ MOVW h0+4(FP), R11 /* h0 */
+ MOVW l1+8(FP), R4 /* l1 */
+ MOVW h1+12(FP), R5 /* h1 */
MULLU R4, R2, (R7,R6)
MUL R11, R4, R8
ADD R8, R7
MUL R2, R5, R8
ADD R8, R7
- MOVW R6, 0(R(arg))
- MOVW R7, 4(R(arg))
+ MOVW R6, ret_lo+16(FP)
+ MOVW R7, ret_hi+20(FP)
RET
// trampoline for _sfloat2. passes LR as arg0 and
// saves registers R0-R13 and CPSR on the stack. R0-R12 and CPSR flags can
// be changed by _sfloat2.
-TEXT _sfloat(SB), NOSPLIT, $64-0 // 4 arg + 14*4 saved regs + cpsr
+TEXT _sfloat(SB), NOSPLIT, $68-0 // 4 arg + 14*4 saved regs + cpsr + return value
MOVW R14, 4(R13)
MOVW R0, 8(R13)
MOVW $12(R13), R0
MOVM.IA.W [R1-R12], (R0)
- MOVW $68(R13), R1 // correct for frame size
+ MOVW $72(R13), R1 // correct for frame size
MOVW R1, 60(R13)
WORD $0xe10f1000 // mrs r1, cpsr
MOVW R1, 64(R13)
@@ -72,33 +71,41 @@ TEXT _sfloat(SB), NOSPLIT, $64-0 // 4 arg + 14*4 saved regs + cpsr
// registers into G, but they do not need to be kept at the
// usual places a goroutine reschedules (at function calls),
// so it would be a waste of 132 bytes per G.
- MOVW m_locks(m), R1
+ MOVW g_m(g), R8
+ MOVW m_locks(R8), R1
ADD $1, R1
- MOVW R1, m_locks(m)
+ MOVW R1, m_locks(R8)
MOVW $1, R1
- MOVW R1, m_softfloat(m)
+ MOVW R1, m_softfloat(R8)
BL runtime·_sfloat2(SB)
- MOVW m_locks(m), R1
+ MOVW 68(R13), R0
+ MOVW g_m(g), R8
+ MOVW m_locks(R8), R1
SUB $1, R1
- MOVW R1, m_locks(m)
+ MOVW R1, m_locks(R8)
MOVW $0, R1
- MOVW R1, m_softfloat(m)
+ MOVW R1, m_softfloat(R8)
MOVW R0, 0(R13)
MOVW 64(R13), R1
WORD $0xe128f001 // msr cpsr_f, r1
MOVW $12(R13), R0
- // Restore R1-R8 and R11-R12, but ignore the saved R9 (m) and R10 (g).
- // Both are maintained by the runtime and always have correct values,
- // so there is no need to restore old values here.
- // The g should not have changed, but m may have, if we were preempted
- // and restarted on a different thread, in which case restoring the old
- // value is incorrect and will cause serious confusion in the runtime.
- MOVM.IA.W (R0), [R1-R8]
- MOVW $52(R13), R0
- MOVM.IA.W (R0), [R11-R12]
+ // Restore R1-R12, R0.
+ MOVM.IA.W (R0), [R1-R12]
MOVW 8(R13), R0
RET
+// trampoline for _sfloat2 panic.
+// _sfloat2 instructs _sfloat to return here.
+// We need to push a fake saved LR onto the stack,
+// load the signal fault address into LR, and jump
+// to the real sigpanic.
+// This simulates what sighandler does for a memory fault.
+TEXT _sfloatpanic(SB),NOSPLIT,$-4
+ MOVW $0, R0
+ MOVW.W R0, -4(R13)
+ MOVW g_sigpc(g), LR
+ B runtime·sigpanic(SB)
+
// func udiv(n, d uint32) (q, r uint32)
// Reference:
// Sloss, Andrew et. al; ARM System Developer's Guide: Designing and Optimizing System Software
@@ -113,7 +120,8 @@ TEXT udiv<>(SB),NOSPLIT,$-4
CLZ R(q), R(s) // find normalizing shift
MOVW.S R(q)<<R(s), R(a)
MOVW $fast_udiv_tab<>-64(SB), R(M)
- MOVBU.NE R(a)>>25(R(M)), R(a) // index by most significant 7 bits of divisor
+ ADD.NE R(a)>>25, R(M), R(a) // index by most significant 7 bits of divisor
+ MOVBU.NE (R(a)), R(a)
SUB.S $7, R(s)
RSB $0, R(q), R(M) // M = -q
@@ -186,26 +194,26 @@ udiv_by_0:
MOVW R1, 0(R13) // expected here for traceback
B runtime·panicdivide(SB)
-TEXT fast_udiv_tab<>(SB),NOSPLIT,$-4
- // var tab [64]byte
- // tab[0] = 255; for i := 1; i <= 63; i++ { tab[i] = (1<<14)/(64+i) }
- // laid out here as little-endian uint32s
- WORD $0xf4f8fcff
- WORD $0xe6eaedf0
- WORD $0xdadde0e3
- WORD $0xcfd2d4d7
- WORD $0xc5c7cacc
- WORD $0xbcbec0c3
- WORD $0xb4b6b8ba
- WORD $0xacaeb0b2
- WORD $0xa5a7a8aa
- WORD $0x9fa0a2a3
- WORD $0x999a9c9d
- WORD $0x93949697
- WORD $0x8e8f9092
- WORD $0x898a8c8d
- WORD $0x85868788
- WORD $0x81828384
+// var tab [64]byte
+// tab[0] = 255; for i := 1; i <= 63; i++ { tab[i] = (1<<14)/(64+i) }
+// laid out here as little-endian uint32s
+DATA fast_udiv_tab<>+0x00(SB)/4, $0xf4f8fcff
+DATA fast_udiv_tab<>+0x04(SB)/4, $0xe6eaedf0
+DATA fast_udiv_tab<>+0x08(SB)/4, $0xdadde0e3
+DATA fast_udiv_tab<>+0x0c(SB)/4, $0xcfd2d4d7
+DATA fast_udiv_tab<>+0x10(SB)/4, $0xc5c7cacc
+DATA fast_udiv_tab<>+0x14(SB)/4, $0xbcbec0c3
+DATA fast_udiv_tab<>+0x18(SB)/4, $0xb4b6b8ba
+DATA fast_udiv_tab<>+0x1c(SB)/4, $0xacaeb0b2
+DATA fast_udiv_tab<>+0x20(SB)/4, $0xa5a7a8aa
+DATA fast_udiv_tab<>+0x24(SB)/4, $0x9fa0a2a3
+DATA fast_udiv_tab<>+0x28(SB)/4, $0x999a9c9d
+DATA fast_udiv_tab<>+0x2c(SB)/4, $0x93949697
+DATA fast_udiv_tab<>+0x30(SB)/4, $0x8e8f9092
+DATA fast_udiv_tab<>+0x34(SB)/4, $0x898a8c8d
+DATA fast_udiv_tab<>+0x38(SB)/4, $0x85868788
+DATA fast_udiv_tab<>+0x3c(SB)/4, $0x81828384
+GLOBL fast_udiv_tab<>(SB), RODATA, $64
// The linker will pass numerator in R(TMP), and it also
// expects the result in R(TMP)
@@ -298,3 +306,12 @@ out:
MOVW 12(R13), R(s)
MOVW 16(R13), R(M)
RET
+
+// _mul64by32 and _div64by32 not implemented on arm
+TEXT runtime·_mul64by32(SB), NOSPLIT, $0
+ MOVW $0, R0
+ MOVW (R0), R1 // crash
+
+TEXT runtime·_div64by32(SB), NOSPLIT, $0
+ MOVW $0, R0
+ MOVW (R0), R1 // crash
diff --git a/src/pkg/runtime/vlop_arm_test.go b/src/runtime/vlop_arm_test.go
index cd28419ad..cd28419ad 100644
--- a/src/pkg/runtime/vlop_arm_test.go
+++ b/src/runtime/vlop_arm_test.go
diff --git a/src/pkg/runtime/vlrt_386.c b/src/runtime/vlrt.c
index ace1beb4c..cb0d14796 100644
--- a/src/pkg/runtime/vlrt_386.c
+++ b/src/runtime/vlrt.c
@@ -23,7 +23,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../../cmd/ld/textflag.h"
+// +build arm 386
+
+#include "textflag.h"
/*
* C runtime for 64-bit divide, others.
@@ -32,7 +34,7 @@
* to generate the code directly now. Find and remove.
*/
-extern void runtime·panicdivide(void);
+void runtime·panicdivide(void);
typedef unsigned long ulong;
typedef unsigned int uint;
@@ -45,38 +47,58 @@ typedef signed char schar;
typedef struct Vlong Vlong;
struct Vlong
{
- union
- {
- long long v;
- struct
- {
- ulong lo;
- ulong hi;
- };
- struct
- {
- ushort lols;
- ushort loms;
- ushort hils;
- ushort hims;
- };
- };
+ ulong lo;
+ ulong hi;
+};
+
+typedef union Vlong64 Vlong64;
+union Vlong64
+{
+ long long v;
+ Vlong v2;
};
void runtime·abort(void);
-void
-_d2v(Vlong *y, double d)
+#pragma textflag NOSPLIT
+Vlong
+_addv(Vlong a, Vlong b)
+{
+ Vlong r;
+
+ r.lo = a.lo + b.lo;
+ r.hi = a.hi + b.hi;
+ if(r.lo < a.lo)
+ r.hi++;
+ return r;
+}
+
+#pragma textflag NOSPLIT
+Vlong
+_subv(Vlong a, Vlong b)
+{
+ Vlong r;
+
+ r.lo = a.lo - b.lo;
+ r.hi = a.hi - b.hi;
+ if(r.lo > a.lo)
+ r.hi--;
+ return r;
+}
+
+Vlong
+_d2v(double d)
{
- union { double d; struct Vlong; } x;
+ union { double d; Vlong vl; } x;
ulong xhi, xlo, ylo, yhi;
int sh;
+ Vlong y;
x.d = d;
- xhi = (x.hi & 0xfffff) | 0x100000;
- xlo = x.lo;
- sh = 1075 - ((x.hi >> 20) & 0x7ff);
+ xhi = (x.vl.hi & 0xfffff) | 0x100000;
+ xlo = x.vl.lo;
+ sh = 1075 - ((x.vl.hi >> 20) & 0x7ff);
ylo = 0;
yhi = 0;
@@ -101,7 +123,7 @@ _d2v(Vlong *y, double d)
} else {
/* v = (hi||lo) << -sh */
sh = -sh;
- if(sh <= 10) {
+ if(sh <= 10) { /* NOTE: sh <= 11 on ARM??? */
ylo = xlo << sh;
yhi = (xhi << sh) | (xlo >> (32-sh));
} else {
@@ -109,7 +131,7 @@ _d2v(Vlong *y, double d)
yhi = d; /* causes something awful */
}
}
- if(x.hi & SIGN(32)) {
+ if(x.vl.hi & SIGN(32)) {
if(ylo != 0) {
ylo = -ylo;
yhi = ~yhi;
@@ -117,15 +139,26 @@ _d2v(Vlong *y, double d)
yhi = -yhi;
}
- y->hi = yhi;
- y->lo = ylo;
+ y.hi = yhi;
+ y.lo = ylo;
+ return y;
}
-void
-_f2v(Vlong *y, float f)
+Vlong
+_f2v(float f)
{
+ return _d2v(f);
+}
- _d2v(y, f);
+double
+_ul2d(ulong u)
+{
+ // compensate for bug in c
+ if(u & SIGN(32)) {
+ u ^= SIGN(32);
+ return 2147483648. + u;
+ }
+ return u;
}
double
@@ -137,7 +170,7 @@ _v2d(Vlong x)
x.hi = ~x.hi;
} else
x.hi = -x.hi;
- return -((long)x.hi*4294967296. + x.lo);
+ return -(_ul2d(x.hi)*4294967296. + _ul2d(x.lo));
}
return (long)x.hi*4294967296. + x.lo;
}
@@ -148,8 +181,8 @@ _v2f(Vlong x)
return _v2d(x);
}
-ulong _div64by32(Vlong, ulong, ulong*);
-int _mul64by32(Vlong*, Vlong, ulong);
+ulong runtime·_div64by32(Vlong, ulong, ulong*);
+int runtime·_mul64by32(Vlong*, Vlong, ulong);
static void
slowdodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
@@ -166,7 +199,7 @@ slowdodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
* get a divide by zero
*/
if(denlo==0 && denhi==0) {
- numlo = numlo / denlo;
+ runtime·panicdivide();
}
/*
@@ -213,12 +246,21 @@ slowdodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
}
}
+#ifdef GOARCH_arm
+static void
+dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
+{
+ slowdodiv(num, den, qp, rp);
+}
+#endif
+
+#ifdef GOARCH_386
static void
dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
{
ulong n;
Vlong x, q, r;
-
+
if(den.hi > num.hi || (den.hi == num.hi && den.lo > num.lo)){
if(qp) {
qp->hi = 0;
@@ -234,11 +276,11 @@ dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
if(den.hi != 0){
q.hi = 0;
n = num.hi/den.hi;
- if(_mul64by32(&x, den, n) || x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo))
+ if(runtime·_mul64by32(&x, den, n) || x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo))
slowdodiv(num, den, &q, &r);
else {
q.lo = n;
- r.v = num.v - x.v;
+ *(long long*)&r = *(long long*)&num - *(long long*)&x;
}
} else {
if(num.hi >= den.lo){
@@ -249,7 +291,7 @@ dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
} else {
q.hi = 0;
}
- q.lo = _div64by32(num, den.lo, &r.lo);
+ q.lo = runtime·_div64by32(num, den.lo, &r.lo);
r.hi = 0;
}
if(qp) {
@@ -261,45 +303,38 @@ dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
rp->hi = r.hi;
}
}
+#endif
-void
-_divvu(Vlong *q, Vlong n, Vlong d)
+Vlong
+_divvu(Vlong n, Vlong d)
{
+ Vlong q;
if(n.hi == 0 && d.hi == 0) {
if(d.lo == 0)
runtime·panicdivide();
- q->hi = 0;
- q->lo = n.lo / d.lo;
- return;
+ q.hi = 0;
+ q.lo = n.lo / d.lo;
+ return q;
}
- dodiv(n, d, q, 0);
-}
-
-void
-runtime·uint64div(Vlong n, Vlong d, Vlong q)
-{
- _divvu(&q, n, d);
+ dodiv(n, d, &q, 0);
+ return q;
}
-void
-_modvu(Vlong *r, Vlong n, Vlong d)
+Vlong
+_modvu(Vlong n, Vlong d)
{
+ Vlong r;
if(n.hi == 0 && d.hi == 0) {
if(d.lo == 0)
runtime·panicdivide();
- r->hi = 0;
- r->lo = n.lo % d.lo;
- return;
+ r.hi = 0;
+ r.lo = n.lo % d.lo;
+ return r;
}
- dodiv(n, d, 0, r);
-}
-
-void
-runtime·uint64mod(Vlong n, Vlong d, Vlong q)
-{
- _modvu(&q, n, d);
+ dodiv(n, d, 0, &r);
+ return r;
}
static void
@@ -314,24 +349,25 @@ vneg(Vlong *v)
v->hi = ~v->hi;
}
-void
-_divv(Vlong *q, Vlong n, Vlong d)
+Vlong
+_divv(Vlong n, Vlong d)
{
long nneg, dneg;
+ Vlong q;
if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
if((long)n.lo == -0x80000000 && (long)d.lo == -1) {
// special case: 32-bit -0x80000000 / -1 causes divide error,
// but it's okay in this 64-bit context.
- q->lo = 0x80000000;
- q->hi = 0;
- return;
+ q.lo = 0x80000000;
+ q.hi = 0;
+ return q;
}
if(d.lo == 0)
runtime·panicdivide();
- q->lo = (long)n.lo / (long)d.lo;
- q->hi = ((long)q->lo) >> 31;
- return;
+ q.lo = (long)n.lo / (long)d.lo;
+ q.hi = ((long)q.lo) >> 31;
+ return q;
}
nneg = n.hi >> 31;
if(nneg)
@@ -339,35 +375,31 @@ _divv(Vlong *q, Vlong n, Vlong d)
dneg = d.hi >> 31;
if(dneg)
vneg(&d);
- dodiv(n, d, q, 0);
+ dodiv(n, d, &q, 0);
if(nneg != dneg)
- vneg(q);
-}
-
-void
-runtime·int64div(Vlong n, Vlong d, Vlong q)
-{
- _divv(&q, n, d);
+ vneg(&q);
+ return q;
}
-void
-_modv(Vlong *r, Vlong n, Vlong d)
+Vlong
+_modv(Vlong n, Vlong d)
{
long nneg, dneg;
+ Vlong r;
if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
if((long)n.lo == -0x80000000 && (long)d.lo == -1) {
// special case: 32-bit -0x80000000 % -1 causes divide error,
// but it's okay in this 64-bit context.
- r->lo = 0;
- r->hi = 0;
- return;
+ r.lo = 0;
+ r.hi = 0;
+ return r;
}
if(d.lo == 0)
runtime·panicdivide();
- r->lo = (long)n.lo % (long)d.lo;
- r->hi = ((long)r->lo) >> 31;
- return;
+ r.lo = (long)n.lo % (long)d.lo;
+ r.hi = ((long)r.lo) >> 31;
+ return r;
}
nneg = n.hi >> 31;
if(nneg)
@@ -375,160 +407,171 @@ _modv(Vlong *r, Vlong n, Vlong d)
dneg = d.hi >> 31;
if(dneg)
vneg(&d);
- dodiv(n, d, 0, r);
+ dodiv(n, d, 0, &r);
if(nneg)
- vneg(r);
+ vneg(&r);
+ return r;
}
-void
-runtime·int64mod(Vlong n, Vlong d, Vlong q)
-{
- _modv(&q, n, d);
-}
-
-void
-_rshav(Vlong *r, Vlong a, int b)
+#pragma textflag NOSPLIT
+Vlong
+_rshav(Vlong a, int b)
{
long t;
+ Vlong r;
t = a.hi;
if(b >= 32) {
- r->hi = t>>31;
+ r.hi = t>>31;
if(b >= 64) {
/* this is illegal re C standard */
- r->lo = t>>31;
- return;
+ r.lo = t>>31;
+ return r;
}
- r->lo = t >> (b-32);
- return;
+ r.lo = t >> (b-32);
+ return r;
}
if(b <= 0) {
- r->hi = t;
- r->lo = a.lo;
- return;
+ r.hi = t;
+ r.lo = a.lo;
+ return r;
}
- r->hi = t >> b;
- r->lo = (t << (32-b)) | (a.lo >> b);
+ r.hi = t >> b;
+ r.lo = (t << (32-b)) | (a.lo >> b);
+ return r;
}
-void
-_rshlv(Vlong *r, Vlong a, int b)
+#pragma textflag NOSPLIT
+Vlong
+_rshlv(Vlong a, int b)
{
ulong t;
+ Vlong r;
t = a.hi;
if(b >= 32) {
- r->hi = 0;
+ r.hi = 0;
if(b >= 64) {
/* this is illegal re C standard */
- r->lo = 0;
- return;
+ r.lo = 0;
+ return r;
}
- r->lo = t >> (b-32);
- return;
+ r.lo = t >> (b-32);
+ return r;
}
if(b <= 0) {
- r->hi = t;
- r->lo = a.lo;
- return;
+ r.hi = t;
+ r.lo = a.lo;
+ return r;
}
- r->hi = t >> b;
- r->lo = (t << (32-b)) | (a.lo >> b);
+ r.hi = t >> b;
+ r.lo = (t << (32-b)) | (a.lo >> b);
+ return r;
}
#pragma textflag NOSPLIT
-void
-_lshv(Vlong *r, Vlong a, int b)
+Vlong
+_lshv(Vlong a, int b)
{
ulong t;
t = a.lo;
if(b >= 32) {
- r->lo = 0;
if(b >= 64) {
/* this is illegal re C standard */
- r->hi = 0;
- return;
+ return (Vlong){0, 0};
}
- r->hi = t << (b-32);
- return;
+ return (Vlong){0, t<<(b-32)};
}
if(b <= 0) {
- r->lo = t;
- r->hi = a.hi;
- return;
+ return (Vlong){t, a.hi};
}
- r->lo = t << b;
- r->hi = (t >> (32-b)) | (a.hi << b);
+ return (Vlong){t<<b, (t >> (32-b)) | (a.hi << b)};
}
-void
-_andv(Vlong *r, Vlong a, Vlong b)
+#pragma textflag NOSPLIT
+Vlong
+_andv(Vlong a, Vlong b)
{
- r->hi = a.hi & b.hi;
- r->lo = a.lo & b.lo;
+ Vlong r;
+
+ r.hi = a.hi & b.hi;
+ r.lo = a.lo & b.lo;
+ return r;
}
-void
-_orv(Vlong *r, Vlong a, Vlong b)
+#pragma textflag NOSPLIT
+Vlong
+_orv(Vlong a, Vlong b)
{
- r->hi = a.hi | b.hi;
- r->lo = a.lo | b.lo;
+ Vlong r;
+
+ r.hi = a.hi | b.hi;
+ r.lo = a.lo | b.lo;
+ return r;
}
-void
-_xorv(Vlong *r, Vlong a, Vlong b)
+#pragma textflag NOSPLIT
+Vlong
+_xorv(Vlong a, Vlong b)
{
- r->hi = a.hi ^ b.hi;
- r->lo = a.lo ^ b.lo;
+ Vlong r;
+
+ r.hi = a.hi ^ b.hi;
+ r.lo = a.lo ^ b.lo;
+ return r;
}
-void
-_vpp(Vlong *l, Vlong *r)
+Vlong
+_vpp(Vlong *r)
{
+ Vlong l;
- l->hi = r->hi;
- l->lo = r->lo;
+ l = *r;
r->lo++;
if(r->lo == 0)
r->hi++;
+ return l;
}
-void
-_vmm(Vlong *l, Vlong *r)
+#pragma textflag NOSPLIT
+Vlong
+_vmm(Vlong *r)
{
+ Vlong l;
- l->hi = r->hi;
- l->lo = r->lo;
+ l = *r;
if(r->lo == 0)
r->hi--;
r->lo--;
+ return l;
}
-void
-_ppv(Vlong *l, Vlong *r)
+#pragma textflag NOSPLIT
+Vlong
+_ppv(Vlong *r)
{
r->lo++;
if(r->lo == 0)
r->hi++;
- l->hi = r->hi;
- l->lo = r->lo;
+ return *r;
}
-void
-_mmv(Vlong *l, Vlong *r)
+#pragma textflag NOSPLIT
+Vlong
+_mmv(Vlong *r)
{
if(r->lo == 0)
r->hi--;
r->lo--;
- l->hi = r->hi;
- l->lo = r->lo;
+ return *r;
}
-void
-_vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
+#pragma textflag NOSPLIT
+Vlong
+_vasop(void *lv, Vlong fn(Vlong, Vlong), int type, Vlong rv)
{
Vlong t, u;
@@ -542,158 +585,183 @@ _vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
case 1: /* schar */
t.lo = *(schar*)lv;
t.hi = t.lo >> 31;
- fn(&u, t, rv);
+ u = fn(t, rv);
*(schar*)lv = u.lo;
break;
case 2: /* uchar */
t.lo = *(uchar*)lv;
t.hi = 0;
- fn(&u, t, rv);
+ u = fn(t, rv);
*(uchar*)lv = u.lo;
break;
case 3: /* short */
t.lo = *(short*)lv;
t.hi = t.lo >> 31;
- fn(&u, t, rv);
+ u = fn(t, rv);
*(short*)lv = u.lo;
break;
case 4: /* ushort */
t.lo = *(ushort*)lv;
t.hi = 0;
- fn(&u, t, rv);
+ u = fn(t, rv);
*(ushort*)lv = u.lo;
break;
case 9: /* int */
t.lo = *(int*)lv;
t.hi = t.lo >> 31;
- fn(&u, t, rv);
+ u = fn(t, rv);
*(int*)lv = u.lo;
break;
case 10: /* uint */
t.lo = *(uint*)lv;
t.hi = 0;
- fn(&u, t, rv);
+ u = fn(t, rv);
*(uint*)lv = u.lo;
break;
case 5: /* long */
t.lo = *(long*)lv;
t.hi = t.lo >> 31;
- fn(&u, t, rv);
+ u = fn(t, rv);
*(long*)lv = u.lo;
break;
case 6: /* ulong */
t.lo = *(ulong*)lv;
t.hi = 0;
- fn(&u, t, rv);
+ u = fn(t, rv);
*(ulong*)lv = u.lo;
break;
case 7: /* vlong */
case 8: /* uvlong */
- fn(&u, *(Vlong*)lv, rv);
+ if((void*)fn == _lshv || (void*)fn == _rshav || (void*)fn == _rshlv)
+ u = ((Vlong(*)(Vlong,int))fn)(*(Vlong*)lv, *(int*)&rv);
+ else
+ u = fn(*(Vlong*)lv, rv);
*(Vlong*)lv = u;
break;
}
- *ret = u;
+ return u;
}
-void
-_p2v(Vlong *ret, void *p)
+#pragma textflag NOSPLIT
+Vlong
+_p2v(void *p)
{
long t;
+ Vlong ret;
t = (ulong)p;
- ret->lo = t;
- ret->hi = 0;
+ ret.lo = t;
+ ret.hi = 0;
+ return ret;
}
-void
-_sl2v(Vlong *ret, long sl)
+#pragma textflag NOSPLIT
+Vlong
+_sl2v(long sl)
{
long t;
+ Vlong ret;
t = sl;
- ret->lo = t;
- ret->hi = t >> 31;
+ ret.lo = t;
+ ret.hi = t >> 31;
+ return ret;
}
-void
-_ul2v(Vlong *ret, ulong ul)
+#pragma textflag NOSPLIT
+Vlong
+_ul2v(ulong ul)
{
long t;
+ Vlong ret;
t = ul;
- ret->lo = t;
- ret->hi = 0;
+ ret.lo = t;
+ ret.hi = 0;
+ return ret;
}
-void
-_si2v(Vlong *ret, int si)
+#pragma textflag NOSPLIT
+Vlong
+_si2v(int si)
{
- long t;
-
- t = si;
- ret->lo = t;
- ret->hi = t >> 31;
+ return (Vlong){si, si>>31};
}
-void
-_ui2v(Vlong *ret, uint ui)
+#pragma textflag NOSPLIT
+Vlong
+_ui2v(uint ui)
{
long t;
+ Vlong ret;
t = ui;
- ret->lo = t;
- ret->hi = 0;
+ ret.lo = t;
+ ret.hi = 0;
+ return ret;
}
-void
-_sh2v(Vlong *ret, long sh)
+#pragma textflag NOSPLIT
+Vlong
+_sh2v(long sh)
{
long t;
+ Vlong ret;
t = (sh << 16) >> 16;
- ret->lo = t;
- ret->hi = t >> 31;
+ ret.lo = t;
+ ret.hi = t >> 31;
+ return ret;
}
-void
-_uh2v(Vlong *ret, ulong ul)
+#pragma textflag NOSPLIT
+Vlong
+_uh2v(ulong ul)
{
long t;
+ Vlong ret;
t = ul & 0xffff;
- ret->lo = t;
- ret->hi = 0;
+ ret.lo = t;
+ ret.hi = 0;
+ return ret;
}
-void
-_sc2v(Vlong *ret, long uc)
+#pragma textflag NOSPLIT
+Vlong
+_sc2v(long uc)
{
long t;
+ Vlong ret;
t = (uc << 24) >> 24;
- ret->lo = t;
- ret->hi = t >> 31;
+ ret.lo = t;
+ ret.hi = t >> 31;
+ return ret;
}
-void
-_uc2v(Vlong *ret, ulong ul)
+#pragma textflag NOSPLIT
+Vlong
+_uc2v(ulong ul)
{
long t;
+ Vlong ret;
t = ul & 0xff;
- ret->lo = t;
- ret->hi = 0;
+ ret.lo = t;
+ ret.hi = 0;
+ return ret;
}
+#pragma textflag NOSPLIT
long
_v2sc(Vlong rv)
{
@@ -703,6 +771,7 @@ _v2sc(Vlong rv)
return (t << 24) >> 24;
}
+#pragma textflag NOSPLIT
long
_v2uc(Vlong rv)
{
@@ -710,6 +779,7 @@ _v2uc(Vlong rv)
return rv.lo & 0xff;
}
+#pragma textflag NOSPLIT
long
_v2sh(Vlong rv)
{
@@ -719,6 +789,7 @@ _v2sh(Vlong rv)
return (t << 16) >> 16;
}
+#pragma textflag NOSPLIT
long
_v2uh(Vlong rv)
{
@@ -726,6 +797,7 @@ _v2uh(Vlong rv)
return rv.lo & 0xffff;
}
+#pragma textflag NOSPLIT
long
_v2sl(Vlong rv)
{
@@ -733,6 +805,7 @@ _v2sl(Vlong rv)
return rv.lo;
}
+#pragma textflag NOSPLIT
long
_v2ul(Vlong rv)
{
@@ -740,13 +813,14 @@ _v2ul(Vlong rv)
return rv.lo;
}
+#pragma textflag NOSPLIT
long
_v2si(Vlong rv)
{
-
return rv.lo;
}
+#pragma textflag NOSPLIT
long
_v2ui(Vlong rv)
{
@@ -754,24 +828,28 @@ _v2ui(Vlong rv)
return rv.lo;
}
+#pragma textflag NOSPLIT
int
_testv(Vlong rv)
{
return rv.lo || rv.hi;
}
+#pragma textflag NOSPLIT
int
_eqv(Vlong lv, Vlong rv)
{
return lv.lo == rv.lo && lv.hi == rv.hi;
}
+#pragma textflag NOSPLIT
int
_nev(Vlong lv, Vlong rv)
{
return lv.lo != rv.lo || lv.hi != rv.hi;
}
+#pragma textflag NOSPLIT
int
_ltv(Vlong lv, Vlong rv)
{
@@ -779,6 +857,7 @@ _ltv(Vlong lv, Vlong rv)
(lv.hi == rv.hi && lv.lo < rv.lo);
}
+#pragma textflag NOSPLIT
int
_lev(Vlong lv, Vlong rv)
{
@@ -786,6 +865,7 @@ _lev(Vlong lv, Vlong rv)
(lv.hi == rv.hi && lv.lo <= rv.lo);
}
+#pragma textflag NOSPLIT
int
_gtv(Vlong lv, Vlong rv)
{
@@ -793,6 +873,7 @@ _gtv(Vlong lv, Vlong rv)
(lv.hi == rv.hi && lv.lo > rv.lo);
}
+#pragma textflag NOSPLIT
int
_gev(Vlong lv, Vlong rv)
{
@@ -800,6 +881,7 @@ _gev(Vlong lv, Vlong rv)
(lv.hi == rv.hi && lv.lo >= rv.lo);
}
+#pragma textflag NOSPLIT
int
_lov(Vlong lv, Vlong rv)
{
@@ -807,6 +889,7 @@ _lov(Vlong lv, Vlong rv)
(lv.hi == rv.hi && lv.lo < rv.lo);
}
+#pragma textflag NOSPLIT
int
_lsv(Vlong lv, Vlong rv)
{
@@ -814,6 +897,7 @@ _lsv(Vlong lv, Vlong rv)
(lv.hi == rv.hi && lv.lo <= rv.lo);
}
+#pragma textflag NOSPLIT
int
_hiv(Vlong lv, Vlong rv)
{
@@ -821,6 +905,7 @@ _hiv(Vlong lv, Vlong rv)
(lv.hi == rv.hi && lv.lo > rv.lo);
}
+#pragma textflag NOSPLIT
int
_hsv(Vlong lv, Vlong rv)
{
diff --git a/src/runtime/vlrt.go b/src/runtime/vlrt.go
new file mode 100644
index 000000000..6370732ca
--- /dev/null
+++ b/src/runtime/vlrt.go
@@ -0,0 +1,258 @@
+// Inferno's libkern/vlrt-arm.c
+// http://code.google.com/p/inferno-os/source/browse/libkern/vlrt-arm.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
+// 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.
+
+// +build arm 386
+
+package runtime
+
+import "unsafe"
+
+const (
+ sign32 = 1 << (32 - 1)
+ sign64 = 1 << (64 - 1)
+)
+
+func float64toint64(d float64) (y uint64) {
+ _d2v(&y, d)
+ return
+}
+
+func float64touint64(d float64) (y uint64) {
+ _d2v(&y, d)
+ return
+}
+
+func int64tofloat64(y int64) float64 {
+ if y < 0 {
+ return -uint64tofloat64(-uint64(y))
+ }
+ return uint64tofloat64(uint64(y))
+}
+
+func uint64tofloat64(y uint64) float64 {
+ hi := float64(uint32(y >> 32))
+ lo := float64(uint32(y))
+ d := hi*(1<<32) + lo
+ return d
+}
+
+func _d2v(y *uint64, d float64) {
+ x := *(*uint64)(unsafe.Pointer(&d))
+
+ xhi := uint32(x>>32)&0xfffff | 0x100000
+ xlo := uint32(x)
+ sh := 1075 - int32(uint32(x>>52)&0x7ff)
+
+ var ylo, yhi uint32
+ if sh >= 0 {
+ sh := uint32(sh)
+ /* v = (hi||lo) >> sh */
+ if sh < 32 {
+ if sh == 0 {
+ ylo = xlo
+ yhi = xhi
+ } else {
+ ylo = xlo>>sh | xhi<<(32-sh)
+ yhi = xhi >> sh
+ }
+ } else {
+ if sh == 32 {
+ ylo = xhi
+ } else if sh < 64 {
+ ylo = xhi >> (sh - 32)
+ }
+ }
+ } else {
+ /* v = (hi||lo) << -sh */
+ sh := uint32(-sh)
+ if sh <= 11 {
+ ylo = xlo << sh
+ yhi = xhi<<sh | xlo>>(32-sh)
+ } else {
+ /* overflow */
+ yhi = uint32(d) /* causes something awful */
+ }
+ }
+ if x&sign64 != 0 {
+ if ylo != 0 {
+ ylo = -ylo
+ yhi = ^yhi
+ } else {
+ yhi = -yhi
+ }
+ }
+
+ *y = uint64(yhi)<<32 | uint64(ylo)
+}
+
+func uint64div(n, d uint64) uint64 {
+ // Check for 32 bit operands
+ if uint32(n>>32) == 0 && uint32(d>>32) == 0 {
+ if uint32(d) == 0 {
+ panicdivide()
+ }
+ return uint64(uint32(n) / uint32(d))
+ }
+ q, _ := dodiv(n, d)
+ return q
+}
+
+func uint64mod(n, d uint64) uint64 {
+ // Check for 32 bit operands
+ if uint32(n>>32) == 0 && uint32(d>>32) == 0 {
+ if uint32(d) == 0 {
+ panicdivide()
+ }
+ return uint64(uint32(n) % uint32(d))
+ }
+ _, r := dodiv(n, d)
+ return r
+}
+
+func int64div(n, d int64) int64 {
+ // Check for 32 bit operands
+ if int64(int32(n)) == n && int64(int32(d)) == d {
+ if int32(n) == -0x80000000 && int32(d) == -1 {
+ // special case: 32-bit -0x80000000 / -1 = -0x80000000,
+ // but 64-bit -0x80000000 / -1 = 0x80000000.
+ return 0x80000000
+ }
+ if int32(d) == 0 {
+ panicdivide()
+ }
+ return int64(int32(n) / int32(d))
+ }
+
+ nneg := n < 0
+ dneg := d < 0
+ if nneg {
+ n = -n
+ }
+ if dneg {
+ d = -d
+ }
+ uq, _ := dodiv(uint64(n), uint64(d))
+ q := int64(uq)
+ if nneg != dneg {
+ q = -q
+ }
+ return q
+}
+
+func int64mod(n, d int64) int64 {
+ // Check for 32 bit operands
+ if int64(int32(n)) == n && int64(int32(d)) == d {
+ if int32(d) == 0 {
+ panicdivide()
+ }
+ return int64(int32(n) % int32(d))
+ }
+
+ nneg := n < 0
+ if nneg {
+ n = -n
+ }
+ if d < 0 {
+ d = -d
+ }
+ _, ur := dodiv(uint64(n), uint64(d))
+ r := int64(ur)
+ if nneg {
+ r = -r
+ }
+ return r
+}
+
+//go:noescape
+func _mul64by32(lo64 *uint64, a uint64, b uint32) (hi32 uint32)
+
+//go:noescape
+func _div64by32(a uint64, b uint32, r *uint32) (q uint32)
+
+func dodiv(n, d uint64) (q, r uint64) {
+ if GOARCH == "arm" {
+ // arm doesn't have a division instruction, so
+ // slowdodiv is the best that we can do.
+ // TODO: revisit for arm64.
+ return slowdodiv(n, d)
+ }
+
+ if d > n {
+ return 0, n
+ }
+
+ if uint32(d>>32) != 0 {
+ t := uint32(n>>32) / uint32(d>>32)
+ var lo64 uint64
+ hi32 := _mul64by32(&lo64, d, t)
+ if hi32 != 0 || lo64 > n {
+ return slowdodiv(n, d)
+ }
+ return uint64(t), n - lo64
+ }
+
+ // d is 32 bit
+ var qhi uint32
+ if uint32(n>>32) >= uint32(d) {
+ if uint32(d) == 0 {
+ panicdivide()
+ }
+ qhi = uint32(n>>32) / uint32(d)
+ n -= uint64(uint32(d)*qhi) << 32
+ } else {
+ qhi = 0
+ }
+
+ var rlo uint32
+ qlo := _div64by32(n, uint32(d), &rlo)
+ return uint64(qhi)<<32 + uint64(qlo), uint64(rlo)
+}
+
+func slowdodiv(n, d uint64) (q, r uint64) {
+ if d == 0 {
+ panicdivide()
+ }
+
+ // Set up the divisor and find the number of iterations needed.
+ capn := n
+ if n >= sign64 {
+ capn = sign64
+ }
+ i := 0
+ for d < capn {
+ d <<= 1
+ i++
+ }
+
+ for ; i >= 0; i-- {
+ q <<= 1
+ if n >= d {
+ n -= d
+ q |= 1
+ }
+ d >>= 1
+ }
+ return q, n
+}
diff --git a/src/pkg/sort/example_interface_test.go b/src/sort/example_interface_test.go
index 442204ea9..442204ea9 100644
--- a/src/pkg/sort/example_interface_test.go
+++ b/src/sort/example_interface_test.go
diff --git a/src/pkg/sort/example_keys_test.go b/src/sort/example_keys_test.go
index a8e47e492..a8e47e492 100644
--- a/src/pkg/sort/example_keys_test.go
+++ b/src/sort/example_keys_test.go
diff --git a/src/pkg/sort/example_multi_test.go b/src/sort/example_multi_test.go
index ac316540f..ac316540f 100644
--- a/src/pkg/sort/example_multi_test.go
+++ b/src/sort/example_multi_test.go
diff --git a/src/pkg/sort/example_test.go b/src/sort/example_test.go
index f7372bec3..f7372bec3 100644
--- a/src/pkg/sort/example_test.go
+++ b/src/sort/example_test.go
diff --git a/src/pkg/sort/example_wrapper_test.go b/src/sort/example_wrapper_test.go
index cf6d74cf7..cf6d74cf7 100644
--- a/src/pkg/sort/example_wrapper_test.go
+++ b/src/sort/example_wrapper_test.go
diff --git a/src/pkg/sort/export_test.go b/src/sort/export_test.go
index b6e30ceb5..b6e30ceb5 100644
--- a/src/pkg/sort/export_test.go
+++ b/src/sort/export_test.go
diff --git a/src/pkg/sort/search.go b/src/sort/search.go
index 8a2c1c33b..8a2c1c33b 100644
--- a/src/pkg/sort/search.go
+++ b/src/sort/search.go
diff --git a/src/pkg/sort/search_test.go b/src/sort/search_test.go
index 29b8d62df..29b8d62df 100644
--- a/src/pkg/sort/search_test.go
+++ b/src/sort/search_test.go
diff --git a/src/pkg/sort/sort.go b/src/sort/sort.go
index e980c295c..e980c295c 100644
--- a/src/pkg/sort/sort.go
+++ b/src/sort/sort.go
diff --git a/src/pkg/sort/sort_test.go b/src/sort/sort_test.go
index 6c36f30e0..6c36f30e0 100644
--- a/src/pkg/sort/sort_test.go
+++ b/src/sort/sort_test.go
diff --git a/src/pkg/strconv/atob.go b/src/strconv/atob.go
index d0cb09721..d0cb09721 100644
--- a/src/pkg/strconv/atob.go
+++ b/src/strconv/atob.go
diff --git a/src/pkg/strconv/atob_test.go b/src/strconv/atob_test.go
index 28f469f58..28f469f58 100644
--- a/src/pkg/strconv/atob_test.go
+++ b/src/strconv/atob_test.go
diff --git a/src/pkg/strconv/atof.go b/src/strconv/atof.go
index 286206481..286206481 100644
--- a/src/pkg/strconv/atof.go
+++ b/src/strconv/atof.go
diff --git a/src/pkg/strconv/atof_test.go b/src/strconv/atof_test.go
index ba4933218..ba4933218 100644
--- a/src/pkg/strconv/atof_test.go
+++ b/src/strconv/atof_test.go
diff --git a/src/pkg/strconv/atoi.go b/src/strconv/atoi.go
index cbf0380ec..9ecec5a58 100644
--- a/src/pkg/strconv/atoi.go
+++ b/src/strconv/atoi.go
@@ -31,7 +31,7 @@ func rangeError(fn, str string) *NumError {
return &NumError{fn, str, ErrRange}
}
-const intSize = 32 << uint(^uint(0)>>63)
+const intSize = 32 << (^uint(0) >> 63)
// IntSize is the size in bits of an int or uint value.
const IntSize = intSize
diff --git a/src/pkg/strconv/atoi_test.go b/src/strconv/atoi_test.go
index 940757307..940757307 100644
--- a/src/pkg/strconv/atoi_test.go
+++ b/src/strconv/atoi_test.go
diff --git a/src/pkg/strconv/decimal.go b/src/strconv/decimal.go
index 42601283d..42601283d 100644
--- a/src/pkg/strconv/decimal.go
+++ b/src/strconv/decimal.go
diff --git a/src/pkg/strconv/decimal_test.go b/src/strconv/decimal_test.go
index 13a127f5b..13a127f5b 100644
--- a/src/pkg/strconv/decimal_test.go
+++ b/src/strconv/decimal_test.go
diff --git a/src/pkg/strconv/extfloat.go b/src/strconv/extfloat.go
index bed8b16bd..bed8b16bd 100644
--- a/src/pkg/strconv/extfloat.go
+++ b/src/strconv/extfloat.go
diff --git a/src/pkg/strconv/fp_test.go b/src/strconv/fp_test.go
index 6de2f8bc6..6de2f8bc6 100644
--- a/src/pkg/strconv/fp_test.go
+++ b/src/strconv/fp_test.go
diff --git a/src/pkg/strconv/ftoa.go b/src/strconv/ftoa.go
index 1a9c41b85..1a9c41b85 100644
--- a/src/pkg/strconv/ftoa.go
+++ b/src/strconv/ftoa.go
diff --git a/src/pkg/strconv/ftoa_test.go b/src/strconv/ftoa_test.go
index 39b861547..39b861547 100644
--- a/src/pkg/strconv/ftoa_test.go
+++ b/src/strconv/ftoa_test.go
diff --git a/src/pkg/strconv/internal_test.go b/src/strconv/internal_test.go
index d0fa80edf..d0fa80edf 100644
--- a/src/pkg/strconv/internal_test.go
+++ b/src/strconv/internal_test.go
diff --git a/src/pkg/strconv/isprint.go b/src/strconv/isprint.go
index 91f179535..80738ed71 100644
--- a/src/pkg/strconv/isprint.go
+++ b/src/strconv/isprint.go
@@ -3,20 +3,19 @@
// license that can be found in the LICENSE file.
// DO NOT EDIT. GENERATED BY
-// go run makeisprint.go >x && mv x isprint.go
+// go run makeisprint.go -output isprint.go
package strconv
-// (470+136+60)*2 + (218)*4 = 2204 bytes
+// (468+138+67)*2 + (326)*4 = 2650 bytes
var isPrint16 = []uint16{
0x0020, 0x007e,
0x00a1, 0x0377,
- 0x037a, 0x037e,
- 0x0384, 0x0527,
- 0x0531, 0x0556,
+ 0x037a, 0x037f,
+ 0x0384, 0x0556,
0x0559, 0x058a,
- 0x058f, 0x05c7,
+ 0x058d, 0x05c7,
0x05d0, 0x05ea,
0x05f0, 0x05f4,
0x0606, 0x061b,
@@ -27,7 +26,7 @@ var isPrint16 = []uint16{
0x0800, 0x082d,
0x0830, 0x085b,
0x085e, 0x085e,
- 0x08a0, 0x08ac,
+ 0x08a0, 0x08b2,
0x08e4, 0x098c,
0x098f, 0x0990,
0x0993, 0x09b2,
@@ -72,18 +71,17 @@ var isPrint16 = []uint16{
0x0bd0, 0x0bd0,
0x0bd7, 0x0bd7,
0x0be6, 0x0bfa,
- 0x0c01, 0x0c39,
+ 0x0c00, 0x0c39,
0x0c3d, 0x0c4d,
0x0c55, 0x0c59,
0x0c60, 0x0c63,
0x0c66, 0x0c6f,
- 0x0c78, 0x0c7f,
- 0x0c82, 0x0cb9,
+ 0x0c78, 0x0cb9,
0x0cbc, 0x0ccd,
0x0cd5, 0x0cd6,
0x0cde, 0x0ce3,
0x0ce6, 0x0cf2,
- 0x0d02, 0x0d3a,
+ 0x0d01, 0x0d3a,
0x0d3d, 0x0d4e,
0x0d57, 0x0d57,
0x0d60, 0x0d63,
@@ -94,6 +92,7 @@ var isPrint16 = []uint16{
0x0dc0, 0x0dc6,
0x0dca, 0x0dca,
0x0dcf, 0x0ddf,
+ 0x0de6, 0x0def,
0x0df2, 0x0df4,
0x0e01, 0x0e3a,
0x0e3f, 0x0e5b,
@@ -120,7 +119,7 @@ var isPrint16 = []uint16{
0x1380, 0x1399,
0x13a0, 0x13f4,
0x1400, 0x169c,
- 0x16a0, 0x16f0,
+ 0x16a0, 0x16f8,
0x1700, 0x1714,
0x1720, 0x1736,
0x1740, 0x1753,
@@ -133,8 +132,7 @@ var isPrint16 = []uint16{
0x1820, 0x1877,
0x1880, 0x18aa,
0x18b0, 0x18f5,
- 0x1900, 0x191c,
- 0x1920, 0x192b,
+ 0x1900, 0x192b,
0x1930, 0x193b,
0x1940, 0x1940,
0x1944, 0x196d,
@@ -147,6 +145,7 @@ var isPrint16 = []uint16{
0x1a7f, 0x1a89,
0x1a90, 0x1a99,
0x1aa0, 0x1aad,
+ 0x1ab0, 0x1abe,
0x1b00, 0x1b4b,
0x1b50, 0x1b7c,
0x1b80, 0x1bf3,
@@ -154,8 +153,8 @@ var isPrint16 = []uint16{
0x1c3b, 0x1c49,
0x1c4d, 0x1c7f,
0x1cc0, 0x1cc7,
- 0x1cd0, 0x1cf6,
- 0x1d00, 0x1de6,
+ 0x1cd0, 0x1cf9,
+ 0x1d00, 0x1df5,
0x1dfc, 0x1f15,
0x1f18, 0x1f1d,
0x1f20, 0x1f45,
@@ -168,21 +167,23 @@ var isPrint16 = []uint16{
0x2030, 0x205e,
0x2070, 0x2071,
0x2074, 0x209c,
- 0x20a0, 0x20ba,
+ 0x20a0, 0x20bd,
0x20d0, 0x20f0,
0x2100, 0x2189,
- 0x2190, 0x23f3,
+ 0x2190, 0x23fa,
0x2400, 0x2426,
0x2440, 0x244a,
- 0x2460, 0x2b4c,
- 0x2b50, 0x2b59,
+ 0x2460, 0x2b73,
+ 0x2b76, 0x2b95,
+ 0x2b98, 0x2bb9,
+ 0x2bbd, 0x2bd1,
0x2c00, 0x2cf3,
0x2cf9, 0x2d27,
0x2d2d, 0x2d2d,
0x2d30, 0x2d67,
0x2d6f, 0x2d70,
0x2d7f, 0x2d96,
- 0x2da0, 0x2e3b,
+ 0x2da0, 0x2e42,
0x2e80, 0x2ef3,
0x2f00, 0x2fd5,
0x2ff0, 0x2ffb,
@@ -196,11 +197,10 @@ var isPrint16 = []uint16{
0xa000, 0xa48c,
0xa490, 0xa4c6,
0xa4d0, 0xa62b,
- 0xa640, 0xa697,
- 0xa69f, 0xa6f7,
- 0xa700, 0xa793,
- 0xa7a0, 0xa7aa,
- 0xa7f8, 0xa82b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7ad,
+ 0xa7b0, 0xa7b1,
+ 0xa7f7, 0xa82b,
0xa830, 0xa839,
0xa840, 0xa877,
0xa880, 0xa8c4,
@@ -209,17 +209,16 @@ var isPrint16 = []uint16{
0xa900, 0xa953,
0xa95f, 0xa97c,
0xa980, 0xa9d9,
- 0xa9de, 0xa9df,
- 0xaa00, 0xaa36,
+ 0xa9de, 0xaa36,
0xaa40, 0xaa4d,
0xaa50, 0xaa59,
- 0xaa5c, 0xaa7b,
- 0xaa80, 0xaac2,
+ 0xaa5c, 0xaac2,
0xaadb, 0xaaf6,
0xab01, 0xab06,
0xab09, 0xab0e,
0xab11, 0xab16,
- 0xab20, 0xab2e,
+ 0xab20, 0xab5f,
+ 0xab64, 0xab65,
0xabc0, 0xabed,
0xabf0, 0xabf9,
0xac00, 0xd7a3,
@@ -235,7 +234,7 @@ var isPrint16 = []uint16{
0xfd92, 0xfdc7,
0xfdf0, 0xfdfd,
0xfe00, 0xfe19,
- 0xfe20, 0xfe26,
+ 0xfe20, 0xfe2d,
0xfe30, 0xfe6b,
0xfe70, 0xfefc,
0xff01, 0xffbe,
@@ -252,15 +251,12 @@ var isNotPrint16 = []uint16{
0x038b,
0x038d,
0x03a2,
+ 0x0530,
0x0560,
0x0588,
0x0590,
0x06dd,
0x083f,
- 0x08a1,
- 0x08ff,
- 0x0978,
- 0x0980,
0x0984,
0x09a9,
0x09b1,
@@ -294,10 +290,10 @@ var isNotPrint16 = []uint16{
0x0c0d,
0x0c11,
0x0c29,
- 0x0c34,
0x0c45,
0x0c49,
0x0c57,
+ 0x0c80,
0x0c84,
0x0c8d,
0x0c91,
@@ -345,7 +341,9 @@ var isNotPrint16 = []uint16{
0x170d,
0x176d,
0x1771,
+ 0x191f,
0x1a5f,
+ 0x1cf7,
0x1f58,
0x1f5a,
0x1f5c,
@@ -355,7 +353,7 @@ var isNotPrint16 = []uint16{
0x1fdc,
0x1ff5,
0x208f,
- 0x2700,
+ 0x2bc9,
0x2c2f,
0x2c5f,
0x2d26,
@@ -372,9 +370,12 @@ var isNotPrint16 = []uint16{
0x318f,
0x321f,
0x32ff,
+ 0xa69e,
0xa78f,
0xa9ce,
+ 0xa9ff,
0xab27,
+ 0xab2f,
0xfb37,
0xfb3d,
0xfb3f,
@@ -392,21 +393,31 @@ var isPrint32 = []uint32{
0x010080, 0x0100fa,
0x010100, 0x010102,
0x010107, 0x010133,
- 0x010137, 0x01018a,
+ 0x010137, 0x01018c,
0x010190, 0x01019b,
+ 0x0101a0, 0x0101a0,
0x0101d0, 0x0101fd,
0x010280, 0x01029c,
0x0102a0, 0x0102d0,
+ 0x0102e0, 0x0102fb,
0x010300, 0x010323,
0x010330, 0x01034a,
+ 0x010350, 0x01037a,
0x010380, 0x0103c3,
0x0103c8, 0x0103d5,
0x010400, 0x01049d,
0x0104a0, 0x0104a9,
+ 0x010500, 0x010527,
+ 0x010530, 0x010563,
+ 0x01056f, 0x01056f,
+ 0x010600, 0x010736,
+ 0x010740, 0x010755,
+ 0x010760, 0x010767,
0x010800, 0x010805,
0x010808, 0x010838,
0x01083c, 0x01083c,
- 0x01083f, 0x01085f,
+ 0x01083f, 0x01089e,
+ 0x0108a7, 0x0108af,
0x010900, 0x01091b,
0x01091f, 0x010939,
0x01093f, 0x01093f,
@@ -417,32 +428,72 @@ var isPrint32 = []uint32{
0x010a38, 0x010a3a,
0x010a3f, 0x010a47,
0x010a50, 0x010a58,
- 0x010a60, 0x010a7f,
+ 0x010a60, 0x010a9f,
+ 0x010ac0, 0x010ae6,
+ 0x010aeb, 0x010af6,
0x010b00, 0x010b35,
0x010b39, 0x010b55,
0x010b58, 0x010b72,
- 0x010b78, 0x010b7f,
+ 0x010b78, 0x010b91,
+ 0x010b99, 0x010b9c,
+ 0x010ba9, 0x010baf,
0x010c00, 0x010c48,
0x010e60, 0x010e7e,
0x011000, 0x01104d,
0x011052, 0x01106f,
- 0x011080, 0x0110c1,
+ 0x01107f, 0x0110c1,
0x0110d0, 0x0110e8,
0x0110f0, 0x0110f9,
0x011100, 0x011143,
+ 0x011150, 0x011176,
0x011180, 0x0111c8,
- 0x0111d0, 0x0111d9,
+ 0x0111cd, 0x0111cd,
+ 0x0111d0, 0x0111da,
+ 0x0111e1, 0x0111f4,
+ 0x011200, 0x01123d,
+ 0x0112b0, 0x0112ea,
+ 0x0112f0, 0x0112f9,
+ 0x011301, 0x01130c,
+ 0x01130f, 0x011310,
+ 0x011313, 0x011339,
+ 0x01133c, 0x011344,
+ 0x011347, 0x011348,
+ 0x01134b, 0x01134d,
+ 0x011357, 0x011357,
+ 0x01135d, 0x011363,
+ 0x011366, 0x01136c,
+ 0x011370, 0x011374,
+ 0x011480, 0x0114c7,
+ 0x0114d0, 0x0114d9,
+ 0x011580, 0x0115b5,
+ 0x0115b8, 0x0115c9,
+ 0x011600, 0x011644,
+ 0x011650, 0x011659,
0x011680, 0x0116b7,
0x0116c0, 0x0116c9,
- 0x012000, 0x01236e,
- 0x012400, 0x012462,
- 0x012470, 0x012473,
+ 0x0118a0, 0x0118f2,
+ 0x0118ff, 0x0118ff,
+ 0x011ac0, 0x011af8,
+ 0x012000, 0x012398,
+ 0x012400, 0x012474,
0x013000, 0x01342e,
0x016800, 0x016a38,
+ 0x016a40, 0x016a69,
+ 0x016a6e, 0x016a6f,
+ 0x016ad0, 0x016aed,
+ 0x016af0, 0x016af5,
+ 0x016b00, 0x016b45,
+ 0x016b50, 0x016b77,
+ 0x016b7d, 0x016b8f,
0x016f00, 0x016f44,
0x016f50, 0x016f7e,
0x016f8f, 0x016f9f,
0x01b000, 0x01b001,
+ 0x01bc00, 0x01bc6a,
+ 0x01bc70, 0x01bc7c,
+ 0x01bc80, 0x01bc88,
+ 0x01bc90, 0x01bc99,
+ 0x01bc9c, 0x01bc9f,
0x01d000, 0x01d0f5,
0x01d100, 0x01d126,
0x01d129, 0x01d172,
@@ -458,6 +509,8 @@ var isPrint32 = []uint32{
0x01d54a, 0x01d6a5,
0x01d6a8, 0x01d7cb,
0x01d7ce, 0x01d7ff,
+ 0x01e800, 0x01e8c4,
+ 0x01e8c7, 0x01e8d6,
0x01ee00, 0x01ee24,
0x01ee27, 0x01ee3b,
0x01ee42, 0x01ee42,
@@ -469,28 +522,30 @@ var isPrint32 = []uint32{
0x01f000, 0x01f02b,
0x01f030, 0x01f093,
0x01f0a0, 0x01f0ae,
- 0x01f0b1, 0x01f0be,
- 0x01f0c1, 0x01f0df,
- 0x01f100, 0x01f10a,
+ 0x01f0b1, 0x01f0f5,
+ 0x01f100, 0x01f10c,
0x01f110, 0x01f16b,
0x01f170, 0x01f19a,
0x01f1e6, 0x01f202,
0x01f210, 0x01f23a,
0x01f240, 0x01f248,
0x01f250, 0x01f251,
- 0x01f300, 0x01f320,
- 0x01f330, 0x01f37c,
- 0x01f380, 0x01f393,
- 0x01f3a0, 0x01f3ca,
- 0x01f3e0, 0x01f3f0,
- 0x01f400, 0x01f4fc,
- 0x01f500, 0x01f53d,
- 0x01f540, 0x01f543,
- 0x01f550, 0x01f567,
- 0x01f5fb, 0x01f640,
- 0x01f645, 0x01f64f,
- 0x01f680, 0x01f6c5,
+ 0x01f300, 0x01f32c,
+ 0x01f330, 0x01f37d,
+ 0x01f380, 0x01f3ce,
+ 0x01f3d4, 0x01f3f7,
+ 0x01f400, 0x01f54a,
+ 0x01f550, 0x01f642,
+ 0x01f645, 0x01f6cf,
+ 0x01f6e0, 0x01f6ec,
+ 0x01f6f0, 0x01f6f3,
0x01f700, 0x01f773,
+ 0x01f780, 0x01f7d4,
+ 0x01f800, 0x01f80b,
+ 0x01f810, 0x01f847,
+ 0x01f850, 0x01f859,
+ 0x01f860, 0x01f887,
+ 0x01f890, 0x01f8ad,
0x020000, 0x02a6d6,
0x02a700, 0x02b734,
0x02b740, 0x02b81d,
@@ -503,7 +558,6 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry
0x0027,
0x003b,
0x003e,
- 0x031f,
0x039e,
0x0809,
0x0836,
@@ -513,6 +567,15 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry
0x0a18,
0x10bd,
0x1135,
+ 0x1212,
+ 0x1304,
+ 0x1329,
+ 0x1331,
+ 0x1334,
+ 0x246f,
+ 0x6a5f,
+ 0x6b5a,
+ 0x6b62,
0xd455,
0xd49d,
0xd4ad,
@@ -552,11 +615,10 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry
0xee8a,
0xeea4,
0xeeaa,
+ 0xf0c0,
0xf0d0,
0xf12f,
- 0xf336,
- 0xf3c5,
- 0xf43f,
- 0xf441,
- 0xf4f8,
+ 0xf4ff,
+ 0xf57a,
+ 0xf5a4,
}
diff --git a/src/pkg/strconv/itoa.go b/src/strconv/itoa.go
index 67f17d866..67f17d866 100644
--- a/src/pkg/strconv/itoa.go
+++ b/src/strconv/itoa.go
diff --git a/src/pkg/strconv/itoa_test.go b/src/strconv/itoa_test.go
index e0213ae9a..e0213ae9a 100644
--- a/src/pkg/strconv/itoa_test.go
+++ b/src/strconv/itoa_test.go
diff --git a/src/pkg/strconv/makeisprint.go b/src/strconv/makeisprint.go
index 216159cc0..588d0a00b 100644
--- a/src/pkg/strconv/makeisprint.go
+++ b/src/strconv/makeisprint.go
@@ -4,15 +4,26 @@
// +build ignore
-// makeisprint generates the tables for strconv's compact isPrint.
+//
+// usage:
+//
+// go run makeisprint.go -output isprint.go
+//
+
package main
import (
+ "bytes"
+ "flag"
"fmt"
- "os"
+ "go/format"
+ "io/ioutil"
+ "log"
"unicode"
)
+var filename = flag.String("output", "isprint.go", "output file name")
+
var (
range16 []uint16
except16 []uint16
@@ -110,6 +121,8 @@ func to16(x []uint32) []uint16 {
}
func main() {
+ flag.Parse()
+
rang, except := scan(0, 0xFFFF)
range16 = to16(rang)
except16 = to16(except)
@@ -117,49 +130,58 @@ func main() {
for i := rune(0); i <= unicode.MaxRune; i++ {
if isPrint(i) != unicode.IsPrint(i) {
- fmt.Fprintf(os.Stderr, "%U: isPrint=%v, want %v\n", i, isPrint(i), unicode.IsPrint(i))
- return
+ log.Fatalf("%U: isPrint=%v, want %v\n", i, isPrint(i), unicode.IsPrint(i))
}
}
- fmt.Printf(`// Copyright 2013 The Go Authors. All rights reserved.
+ 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.Printf("// DO NOT EDIT. GENERATED BY\n")
- fmt.Printf("// go run makeisprint.go >x && mv x isprint.go\n\n")
- fmt.Printf("package strconv\n\n")
+// license that can be found in the LICENSE file.`+"\n\n")
+ fmt.Fprintf(&buf, "// DO NOT EDIT. GENERATED BY\n")
+ fmt.Fprintf(&buf, "// go run makeisprint.go -output isprint.go\n\n")
+ fmt.Fprintf(&buf, "package strconv\n\n")
- fmt.Printf("// (%d+%d+%d)*2 + (%d)*4 = %d bytes\n\n",
+ fmt.Fprintf(&buf, "// (%d+%d+%d)*2 + (%d)*4 = %d bytes\n\n",
len(range16), len(except16), len(except32),
len(range32),
(len(range16)+len(except16)+len(except32))*2+
(len(range32))*4)
- fmt.Printf("var isPrint16 = []uint16{\n")
+ fmt.Fprintf(&buf, "var isPrint16 = []uint16{\n")
for i := 0; i < len(range16); i += 2 {
- fmt.Printf("\t%#04x, %#04x,\n", range16[i], range16[i+1])
+ fmt.Fprintf(&buf, "\t%#04x, %#04x,\n", range16[i], range16[i+1])
}
- fmt.Printf("}\n\n")
+ fmt.Fprintf(&buf, "}\n\n")
- fmt.Printf("var isNotPrint16 = []uint16{\n")
+ fmt.Fprintf(&buf, "var isNotPrint16 = []uint16{\n")
for _, r := range except16 {
- fmt.Printf("\t%#04x,\n", r)
+ fmt.Fprintf(&buf, "\t%#04x,\n", r)
}
- fmt.Printf("}\n\n")
+ fmt.Fprintf(&buf, "}\n\n")
- fmt.Printf("var isPrint32 = []uint32{\n")
+ fmt.Fprintf(&buf, "var isPrint32 = []uint32{\n")
for i := 0; i < len(range32); i += 2 {
- fmt.Printf("\t%#06x, %#06x,\n", range32[i], range32[i+1])
+ fmt.Fprintf(&buf, "\t%#06x, %#06x,\n", range32[i], range32[i+1])
}
- fmt.Printf("}\n\n")
+ fmt.Fprintf(&buf, "}\n\n")
- fmt.Printf("var isNotPrint32 = []uint16{ // add 0x10000 to each entry\n")
+ fmt.Fprintf(&buf, "var isNotPrint32 = []uint16{ // add 0x10000 to each entry\n")
for _, r := range except32 {
if r >= 0x20000 {
- fmt.Fprintf(os.Stderr, "%U too big for isNotPrint32\n", r)
- return
+ log.Fatalf("%U too big for isNotPrint32\n", r)
}
- fmt.Printf("\t%#04x,\n", r-0x10000)
+ fmt.Fprintf(&buf, "\t%#04x,\n", r-0x10000)
+ }
+ fmt.Fprintf(&buf, "}\n")
+
+ data, err := format.Source(buf.Bytes())
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = ioutil.WriteFile(*filename, data, 0644)
+ if err != nil {
+ log.Fatal(err)
}
- fmt.Printf("}\n")
}
diff --git a/src/pkg/strconv/quote.go b/src/strconv/quote.go
index aded7e593..53d51b5a4 100644
--- a/src/pkg/strconv/quote.go
+++ b/src/strconv/quote.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.
+//go:generate go run makeisprint.go -output isprint.go
+
package strconv
import (
@@ -141,11 +143,21 @@ func AppendQuoteRuneToASCII(dst []byte, r rune) []byte {
// CanBackquote reports whether the string s can be represented
// unchanged as a single-line backquoted string without control
-// characters other than space and tab.
+// characters other than tab.
func CanBackquote(s string) bool {
- for i := 0; i < len(s); i++ {
- c := s[i]
- if (c < ' ' && c != '\t') || c == '`' || c == '\u007F' {
+ for len(s) > 0 {
+ r, wid := utf8.DecodeRuneInString(s)
+ s = s[wid:]
+ if wid > 1 {
+ if r == '\ufeff' {
+ return false // BOMs are invisible and should not be quoted.
+ }
+ continue // All other multibyte runes are correctly encoded and assumed printable.
+ }
+ if r == utf8.RuneError {
+ return false
+ }
+ if (r < ' ' && r != '\t') || r == '`' || r == '\u007F' {
return false
}
}
diff --git a/src/pkg/strconv/quote_example_test.go b/src/strconv/quote_example_test.go
index 405a57eb5..405a57eb5 100644
--- a/src/pkg/strconv/quote_example_test.go
+++ b/src/strconv/quote_example_test.go
diff --git a/src/pkg/strconv/quote_test.go b/src/strconv/quote_test.go
index e4b5b6b9f..3bf162f98 100644
--- a/src/pkg/strconv/quote_test.go
+++ b/src/strconv/quote_test.go
@@ -146,6 +146,10 @@ var canbackquotetests = []canBackquoteTest{
{`ABCDEFGHIJKLMNOPQRSTUVWXYZ`, true},
{`abcdefghijklmnopqrstuvwxyz`, true},
{`☺`, true},
+ {"\x80", false},
+ {"a\xe0\xa0z", false},
+ {"\ufeffabc", false},
+ {"a\ufeffz", false},
}
func TestCanBackquote(t *testing.T) {
diff --git a/src/pkg/strconv/strconv_test.go b/src/strconv/strconv_test.go
index 9a007dde4..9a007dde4 100644
--- a/src/pkg/strconv/strconv_test.go
+++ b/src/strconv/strconv_test.go
diff --git a/src/pkg/strconv/testdata/testfp.txt b/src/strconv/testdata/testfp.txt
index 08d3c4ef0..08d3c4ef0 100644
--- a/src/pkg/strconv/testdata/testfp.txt
+++ b/src/strconv/testdata/testfp.txt
diff --git a/src/pkg/strings/example_test.go b/src/strings/example_test.go
index 7243e16b1..7243e16b1 100644
--- a/src/pkg/strings/example_test.go
+++ b/src/strings/example_test.go
diff --git a/src/pkg/strings/export_test.go b/src/strings/export_test.go
index 17c806aa5..17c806aa5 100644
--- a/src/pkg/strings/export_test.go
+++ b/src/strings/export_test.go
diff --git a/src/pkg/strings/reader.go b/src/strings/reader.go
index 82df97439..82df97439 100644
--- a/src/pkg/strings/reader.go
+++ b/src/strings/reader.go
diff --git a/src/pkg/strings/reader_test.go b/src/strings/reader_test.go
index bee90eb25..bee90eb25 100644
--- a/src/pkg/strings/reader_test.go
+++ b/src/strings/reader_test.go
diff --git a/src/pkg/strings/replace.go b/src/strings/replace.go
index 3e05d2057..4752641be 100644
--- a/src/pkg/strings/replace.go
+++ b/src/strings/replace.go
@@ -6,7 +6,8 @@ package strings
import "io"
-// A Replacer replaces a list of strings with replacements.
+// Replacer replaces a list of strings with replacements.
+// It is safe for concurrent use by multiple goroutines.
type Replacer struct {
r replacer
}
@@ -17,15 +18,6 @@ type replacer interface {
WriteString(w io.Writer, s string) (n int, err error)
}
-// byteBitmap represents bytes which are sought for replacement.
-// byteBitmap is 256 bits wide, with a bit set for each old byte to be
-// replaced.
-type byteBitmap [256 / 32]uint32
-
-func (m *byteBitmap) set(b byte) {
- m[b>>5] |= uint32(1 << (b & 31))
-}
-
// NewReplacer returns a new Replacer from a list of old, new string pairs.
// Replacements are performed in order, without overlapping matches.
func NewReplacer(oldnew ...string) *Replacer {
@@ -48,30 +40,29 @@ func NewReplacer(oldnew ...string) *Replacer {
}
if allNewBytes {
- bb := &byteReplacer{}
- for i := 0; i < len(oldnew); i += 2 {
- o, n := oldnew[i][0], oldnew[i+1][0]
- if bb.old[o>>5]&uint32(1<<(o&31)) != 0 {
- // Later old->new maps do not override previous ones with the same old string.
- continue
- }
- bb.old.set(o)
- bb.new[o] = n
+ r := byteReplacer{}
+ for i := range r {
+ r[i] = byte(i)
}
- return &Replacer{r: bb}
+ // The first occurrence of old->new map takes precedence
+ // over the others with the same old string.
+ for i := len(oldnew) - 2; i >= 0; i -= 2 {
+ o := oldnew[i][0]
+ n := oldnew[i+1][0]
+ r[o] = n
+ }
+ return &Replacer{r: &r}
}
- bs := &byteStringReplacer{}
- for i := 0; i < len(oldnew); i += 2 {
- o, new := oldnew[i][0], oldnew[i+1]
- if bs.old[o>>5]&uint32(1<<(o&31)) != 0 {
- // Later old->new maps do not override previous ones with the same old string.
- continue
- }
- bs.old.set(o)
- bs.new[o] = []byte(new)
+ r := byteStringReplacer{}
+ // The first occurrence of old->new map takes precedence
+ // over the others with the same old string.
+ for i := len(oldnew) - 2; i >= 0; i -= 2 {
+ o := oldnew[i][0]
+ n := oldnew[i+1]
+ r[o] = []byte(n)
}
- return &Replacer{r: bs}
+ return &Replacer{r: &r}
}
// Replace returns a copy of s with all replacements performed.
@@ -323,6 +314,15 @@ func (r *genericReplacer) WriteString(w io.Writer, s string) (n int, err error)
var last, wn int
var prevMatchEmpty bool
for i := 0; i <= len(s); {
+ // Fast path: s[i] is not a prefix of any pattern.
+ if i != len(s) && r.root.priority == 0 {
+ index := int(r.mapping[s[i]])
+ if index == r.tableSize || r.root.table[index] == nil {
+ i++
+ continue
+ }
+ }
+
// Ignore the empty match iff the previous loop found the empty match.
val, keylen, match := r.lookup(s[i:], prevMatchEmpty)
prevMatchEmpty = match && keylen == 0
@@ -409,24 +409,18 @@ func (r *singleStringReplacer) WriteString(w io.Writer, s string) (n int, err er
// byteReplacer is the implementation that's used when all the "old"
// and "new" values are single ASCII bytes.
-type byteReplacer struct {
- // old has a bit set for each old byte that should be replaced.
- old byteBitmap
-
- // replacement byte, indexed by old byte. only valid if
- // corresponding old bit is set.
- new [256]byte
-}
+// The array contains replacement bytes indexed by old byte.
+type byteReplacer [256]byte
func (r *byteReplacer) Replace(s string) string {
var buf []byte // lazily allocated
for i := 0; i < len(s); i++ {
b := s[i]
- if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+ if r[b] != b {
if buf == nil {
buf = []byte(s)
}
- buf[i] = r.new[b]
+ buf[i] = r[b]
}
}
if buf == nil {
@@ -447,9 +441,7 @@ func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) {
ncopy := copy(buf, s[:])
s = s[ncopy:]
for i, b := range buf[:ncopy] {
- if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
- buf[i] = r.new[b]
- }
+ buf[i] = r[b]
}
wn, err := w.Write(buf[:ncopy])
n += wn
@@ -461,27 +453,20 @@ func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) {
}
// byteStringReplacer is the implementation that's used when all the
-// "old" values are single ASCII bytes but the "new" values vary in
-// size.
-type byteStringReplacer struct {
- // old has a bit set for each old byte that should be replaced.
- old byteBitmap
-
- // replacement string, indexed by old byte. only valid if
- // corresponding old bit is set.
- new [256][]byte
-}
+// "old" values are single ASCII bytes but the "new" values vary in size.
+// The array contains replacement byte slices indexed by old byte.
+// A nil []byte means that the old byte should not be replaced.
+type byteStringReplacer [256][]byte
func (r *byteStringReplacer) Replace(s string) string {
- newSize := 0
+ newSize := len(s)
anyChanges := false
for i := 0; i < len(s); i++ {
b := s[i]
- if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+ if r[b] != nil {
anyChanges = true
- newSize += len(r.new[b])
- } else {
- newSize++
+ // The -1 is because we are replacing 1 byte with len(r[b]) bytes.
+ newSize += len(r[b]) - 1
}
}
if !anyChanges {
@@ -491,8 +476,8 @@ func (r *byteStringReplacer) Replace(s string) string {
bi := buf
for i := 0; i < len(s); i++ {
b := s[i]
- if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
- n := copy(bi, r.new[b])
+ if r[b] != nil {
+ n := copy(bi, r[b])
bi = bi[n:]
} else {
bi[0] = b
@@ -502,48 +487,32 @@ func (r *byteStringReplacer) Replace(s string) string {
return string(buf)
}
-// WriteString maintains one buffer that's at most 32KB. The bytes in
-// s are enumerated and the buffer is filled. If it reaches its
-// capacity or a byte has a replacement, the buffer is flushed to w.
func (r *byteStringReplacer) WriteString(w io.Writer, s string) (n int, err error) {
- // TODO(bradfitz): use io.WriteString with slices of s instead.
- bufsize := 32 << 10
- if len(s) < bufsize {
- bufsize = len(s)
- }
- buf := make([]byte, bufsize)
- bi := buf[:0]
-
+ sw := getStringWriter(w)
+ last := 0
for i := 0; i < len(s); i++ {
b := s[i]
- var new []byte
- if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
- new = r.new[b]
- } else {
- bi = append(bi, b)
- }
- if len(bi) == cap(bi) || (len(bi) > 0 && len(new) > 0) {
- nw, err := w.Write(bi)
- n += nw
- if err != nil {
- return n, err
- }
- bi = buf[:0]
+ if r[b] == nil {
+ continue
}
- if len(new) > 0 {
- nw, err := w.Write(new)
+ if last != i {
+ nw, err := sw.WriteString(s[last:i])
n += nw
if err != nil {
return n, err
}
}
- }
- if len(bi) > 0 {
- nw, err := w.Write(bi)
+ last = i + 1
+ nw, err := w.Write(r[b])
n += nw
if err != nil {
return n, err
}
}
- return n, nil
+ if last != len(s) {
+ var nw int
+ nw, err = sw.WriteString(s[last:])
+ n += nw
+ }
+ return
}
diff --git a/src/pkg/strings/replace_test.go b/src/strings/replace_test.go
index 82e4b6ef0..77e48b988 100644
--- a/src/pkg/strings/replace_test.go
+++ b/src/strings/replace_test.go
@@ -308,20 +308,21 @@ func TestReplacer(t *testing.T) {
}
}
+var algorithmTestCases = []struct {
+ r *Replacer
+ want string
+}{
+ {capitalLetters, "*strings.byteReplacer"},
+ {htmlEscaper, "*strings.byteStringReplacer"},
+ {NewReplacer("12", "123"), "*strings.singleStringReplacer"},
+ {NewReplacer("1", "12"), "*strings.byteStringReplacer"},
+ {NewReplacer("", "X"), "*strings.genericReplacer"},
+ {NewReplacer("a", "1", "b", "12", "cde", "123"), "*strings.genericReplacer"},
+}
+
// TestPickAlgorithm tests that NewReplacer picks the correct algorithm.
func TestPickAlgorithm(t *testing.T) {
- testCases := []struct {
- r *Replacer
- want string
- }{
- {capitalLetters, "*strings.byteReplacer"},
- {htmlEscaper, "*strings.byteStringReplacer"},
- {NewReplacer("12", "123"), "*strings.singleStringReplacer"},
- {NewReplacer("1", "12"), "*strings.byteStringReplacer"},
- {NewReplacer("", "X"), "*strings.genericReplacer"},
- {NewReplacer("a", "1", "b", "12", "cde", "123"), "*strings.genericReplacer"},
- }
- for i, tc := range testCases {
+ for i, tc := range algorithmTestCases {
got := fmt.Sprintf("%T", tc.r.Replacer())
if got != tc.want {
t.Errorf("%d. algorithm = %s, want %s", i, got, tc.want)
@@ -329,6 +330,23 @@ func TestPickAlgorithm(t *testing.T) {
}
}
+type errWriter struct{}
+
+func (errWriter) Write(p []byte) (n int, err error) {
+ return 0, fmt.Errorf("unwritable")
+}
+
+// TestWriteStringError tests that WriteString returns an error
+// received from the underlying io.Writer.
+func TestWriteStringError(t *testing.T) {
+ for i, tc := range algorithmTestCases {
+ n, err := tc.r.WriteString(errWriter{}, "abc")
+ if n != 0 || err == nil || err.Error() != "unwritable" {
+ t.Errorf("%d. WriteStringError = %d, %v, want 0, unwritable", i, n, err)
+ }
+ }
+}
+
// TestGenericTrieBuilding verifies the structure of the generated trie. There
// is one node per line, and the key ending with the current line is in the
// trie if it ends with a "+".
@@ -480,6 +498,24 @@ func BenchmarkHTMLEscapeOld(b *testing.B) {
}
}
+func BenchmarkByteStringReplacerWriteString(b *testing.B) {
+ str := Repeat("I <3 to escape HTML & other text too.", 100)
+ buf := new(bytes.Buffer)
+ for i := 0; i < b.N; i++ {
+ htmlEscaper.WriteString(buf, str)
+ buf.Reset()
+ }
+}
+
+func BenchmarkByteReplacerWriteString(b *testing.B) {
+ str := Repeat("abcdefghijklmnopqrstuvwxyz", 100)
+ buf := new(bytes.Buffer)
+ for i := 0; i < b.N; i++ {
+ capitalLetters.WriteString(buf, str)
+ buf.Reset()
+ }
+}
+
// BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces.
func BenchmarkByteByteReplaces(b *testing.B) {
str := Repeat("a", 100) + Repeat("b", 100)
diff --git a/src/pkg/strings/search.go b/src/strings/search.go
index f77c879c5..f77c879c5 100644
--- a/src/pkg/strings/search.go
+++ b/src/strings/search.go
diff --git a/src/pkg/strings/search_test.go b/src/strings/search_test.go
index 966c05e65..966c05e65 100644
--- a/src/pkg/strings/search_test.go
+++ b/src/strings/search_test.go
diff --git a/src/pkg/strings/strings.go b/src/strings/strings.go
index 5d46211d8..27d384983 100644
--- a/src/pkg/strings/strings.go
+++ b/src/strings/strings.go
@@ -43,13 +43,29 @@ func explode(s string, n int) []string {
// primeRK is the prime base used in Rabin-Karp algorithm.
const primeRK = 16777619
-// hashstr returns the hash and the appropriate multiplicative
+// hashStr returns the hash and the appropriate multiplicative
// factor for use in Rabin-Karp algorithm.
-func hashstr(sep string) (uint32, uint32) {
+func hashStr(sep string) (uint32, uint32) {
hash := uint32(0)
for i := 0; i < len(sep); i++ {
hash = hash*primeRK + uint32(sep[i])
+ }
+ var pow, sq uint32 = 1, primeRK
+ for i := len(sep); i > 0; i >>= 1 {
+ if i&1 != 0 {
+ pow *= sq
+ }
+ sq *= sq
+ }
+ return hash, pow
+}
+// hashStrRev returns the hash of the reverse of sep and the
+// appropriate multiplicative factor for use in Rabin-Karp algorithm.
+func hashStrRev(sep string) (uint32, uint32) {
+ hash := uint32(0)
+ for i := len(sep) - 1; i >= 0; i-- {
+ hash = hash*primeRK + uint32(sep[i])
}
var pow, sq uint32 = 1, primeRK
for i := len(sep); i > 0; i >>= 1 {
@@ -85,7 +101,8 @@ func Count(s, sep string) int {
}
return 0
}
- hashsep, pow := hashstr(sep)
+ // Rabin-Karp search
+ hashsep, pow := hashStr(sep)
h := uint32(0)
for i := 0; i < len(sep); i++ {
h = h*primeRK + uint32(s[i])
@@ -139,8 +156,8 @@ func Index(s, sep string) int {
case n > len(s):
return -1
}
- // Hash sep.
- hashsep, pow := hashstr(sep)
+ // Rabin-Karp search
+ hashsep, pow := hashStr(sep)
var h uint32
for i := 0; i < n; i++ {
h = h*primeRK + uint32(s[i])
@@ -163,22 +180,41 @@ func Index(s, sep string) int {
// 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)
- if n == 0 {
+ switch {
+ case n == 0:
return len(s)
- }
- c := sep[0]
- if n == 1 {
+ case n == 1:
// special case worth making fast
+ c := sep[0]
for i := len(s) - 1; i >= 0; i-- {
if s[i] == c {
return i
}
}
return -1
+ case n == len(s):
+ if sep == s {
+ return 0
+ }
+ return -1
+ case n > len(s):
+ return -1
+ }
+ // Rabin-Karp search from the end of the string
+ hashsep, pow := hashStrRev(sep)
+ last := len(s) - n
+ var h uint32
+ for i := len(s) - 1; i >= last; i-- {
+ h = h*primeRK + uint32(s[i])
+ }
+ if h == hashsep && s[last:] == sep {
+ return last
}
- // n > 1
- for i := len(s) - n; i >= 0; i-- {
- if s[i] == c && s[i:i+n] == sep {
+ for i := last - 1; i >= 0; i-- {
+ h *= primeRK
+ h += uint32(s[i])
+ h -= pow * uint32(s[i+n])
+ if h == hashsep && s[i:i+n] == sep {
return i
}
}
@@ -189,13 +225,8 @@ func LastIndex(s, sep string) int {
// r, or -1 if rune is not present in s.
func IndexRune(s string, r rune) int {
switch {
- case r < 0x80:
- b := byte(r)
- for i := 0; i < len(s); i++ {
- if s[i] == b {
- return i
- }
- }
+ case r < utf8.RuneSelf:
+ return IndexByte(s, byte(r))
default:
for i, c := range s {
if c == r {
@@ -311,6 +342,8 @@ func Fields(s string) []string {
// FieldsFunc splits the string s at each run of Unicode code points c satisfying f(c)
// and returns an array of slices of s. If all code points in s satisfy f(c) or the
// string is empty, an empty slice is returned.
+// FieldsFunc makes no guarantees about the order in which it calls f(c).
+// If f does not return consistent results for a given c, FieldsFunc may crash.
func FieldsFunc(s string, f func(rune) bool) []string {
// First count the fields.
n := 0
@@ -423,9 +456,10 @@ func Map(mapping func(rune) rune, s string) string {
// Repeat returns a new string consisting of count copies of the string s.
func Repeat(s string, count int) string {
b := make([]byte, len(s)*count)
- bp := 0
- for i := 0; i < count; i++ {
- bp += copy(b[bp:], s)
+ bp := copy(b, s)
+ for bp < len(b) {
+ copy(b[bp:], b[:bp])
+ bp *= 2
}
return string(b)
}
@@ -634,6 +668,9 @@ func TrimSuffix(s, suffix string) string {
// Replace returns a copy of the string s with the first n
// non-overlapping instances of old replaced by new.
+// If old is empty, it matches at the beginning of the string
+// and after each UTF-8 sequence, yielding up to k+1 replacements
+// for a k-rune string.
// If n < 0, there is no limit on the number of replacements.
func Replace(s, old, new string, n int) string {
if old == new || n == 0 {
diff --git a/src/pkg/strings/strings.s b/src/strings/strings.s
index 55103bae0..55103bae0 100644
--- a/src/pkg/strings/strings.s
+++ b/src/strings/strings.s
diff --git a/src/pkg/strings/strings_decl.go b/src/strings/strings_decl.go
index 810a696af..810a696af 100644
--- a/src/pkg/strings/strings_decl.go
+++ b/src/strings/strings_decl.go
diff --git a/src/pkg/strings/strings_test.go b/src/strings/strings_test.go
index e40a18015..7bb81ef3c 100644
--- a/src/pkg/strings/strings_test.go
+++ b/src/strings/strings_test.go
@@ -168,6 +168,15 @@ func BenchmarkIndex(b *testing.B) {
}
}
+func BenchmarkLastIndex(b *testing.B) {
+ if got := Index(benchmarkString, "v"); got != 17 {
+ b.Fatalf("wrong index: expected 17, got=%d", got)
+ }
+ for i := 0; i < b.N; i++ {
+ LastIndex(benchmarkString, "v")
+ }
+}
+
func BenchmarkIndexByte(b *testing.B) {
if got := IndexByte(benchmarkString, 'v'); got != 17 {
b.Fatalf("wrong index: expected 17, got=%d", got)
@@ -1069,8 +1078,11 @@ func makeBenchInputHard() string {
"hello", "world",
}
x := make([]byte, 0, 1<<20)
- for len(x) < 1<<20 {
+ for {
i := rand.Intn(len(tokens))
+ if len(x)+len(tokens[i]) >= 1<<20 {
+ break
+ }
x = append(x, tokens[i]...)
}
return string(x)
@@ -1084,6 +1096,12 @@ func benchmarkIndexHard(b *testing.B, sep string) {
}
}
+func benchmarkLastIndexHard(b *testing.B, sep string) {
+ for i := 0; i < b.N; i++ {
+ LastIndex(benchInputHard, sep)
+ }
+}
+
func benchmarkCountHard(b *testing.B, sep string) {
for i := 0; i < b.N; i++ {
Count(benchInputHard, sep)
@@ -1094,6 +1112,10 @@ func BenchmarkIndexHard1(b *testing.B) { benchmarkIndexHard(b, "<>") }
func BenchmarkIndexHard2(b *testing.B) { benchmarkIndexHard(b, "</pre>") }
func BenchmarkIndexHard3(b *testing.B) { benchmarkIndexHard(b, "<b>hello world</b>") }
+func BenchmarkLastIndexHard1(b *testing.B) { benchmarkLastIndexHard(b, "<>") }
+func BenchmarkLastIndexHard2(b *testing.B) { benchmarkLastIndexHard(b, "</pre>") }
+func BenchmarkLastIndexHard3(b *testing.B) { benchmarkLastIndexHard(b, "<b>hello world</b>") }
+
func BenchmarkCountHard1(b *testing.B) { benchmarkCountHard(b, "<>") }
func BenchmarkCountHard2(b *testing.B) { benchmarkCountHard(b, "</pre>") }
func BenchmarkCountHard3(b *testing.B) { benchmarkCountHard(b, "<b>hello world</b>") }
@@ -1174,3 +1196,9 @@ func BenchmarkSplit3(b *testing.B) {
Split(benchInputHard, "hello")
}
}
+
+func BenchmarkRepeat(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Repeat("-", 80)
+ }
+}
diff --git a/src/pkg/sync/atomic/64bit_arm.go b/src/sync/atomic/64bit_arm.go
index c08f214c7..b98e60827 100644
--- a/src/pkg/sync/atomic/64bit_arm.go
+++ b/src/sync/atomic/64bit_arm.go
@@ -44,3 +44,15 @@ func swapUint64(addr *uint64, new uint64) (old uint64) {
}
return
}
+
+// Additional ARM-specific assembly routines.
+// Declaration here to give assembly routines correct stack maps for arguments.
+func armCompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)
+func armCompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool)
+func generalCAS64(addr *uint64, old, new uint64) (swapped bool)
+func armAddUint32(addr *uint32, delta uint32) (new uint32)
+func armAddUint64(addr *uint64, delta uint64) (new uint64)
+func armSwapUint32(addr *uint32, new uint32) (old uint32)
+func armSwapUint64(addr *uint64, new uint64) (old uint64)
+func armLoadUint64(addr *uint64) (val uint64)
+func armStoreUint64(addr *uint64, val uint64)
diff --git a/src/pkg/sync/atomic/asm_386.s b/src/sync/atomic/asm_386.s
index 807c2f873..740dfe76b 100644
--- a/src/pkg/sync/atomic/asm_386.s
+++ b/src/sync/atomic/asm_386.s
@@ -4,7 +4,7 @@
// +build !race
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·SwapInt32(SB),NOSPLIT,$0-12
JMP ·SwapUint32(SB)
diff --git a/src/pkg/sync/atomic/asm_amd64.s b/src/sync/atomic/asm_amd64.s
index 77afa129e..6e53ebedd 100644
--- a/src/pkg/sync/atomic/asm_amd64.s
+++ b/src/sync/atomic/asm_amd64.s
@@ -4,7 +4,7 @@
// +build !race
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·SwapInt32(SB),NOSPLIT,$0-20
JMP ·SwapUint32(SB)
diff --git a/src/pkg/sync/atomic/asm_amd64p32.s b/src/sync/atomic/asm_amd64p32.s
index b24ae7a59..d77cc2c08 100644
--- a/src/pkg/sync/atomic/asm_amd64p32.s
+++ b/src/sync/atomic/asm_amd64p32.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·SwapInt32(SB),NOSPLIT,$0-12
JMP ·SwapUint32(SB)
diff --git a/src/pkg/sync/atomic/asm_arm.s b/src/sync/atomic/asm_arm.s
index 7c8620a51..8a85273da 100644
--- a/src/pkg/sync/atomic/asm_arm.s
+++ b/src/sync/atomic/asm_arm.s
@@ -4,7 +4,7 @@
// +build !race
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// ARM atomic operations, for use by asm_$(GOOS)_arm.s.
@@ -194,4 +194,4 @@ TEXT slowCheck64<>(SB),NOSPLIT,$0-0
MOVW R0, ok64<>(SB)
RET
-GLOBL ok64<>(SB), $4
+GLOBL ok64<>(SB), NOPTR, $4
diff --git a/src/pkg/sync/atomic/asm_freebsd_arm.s b/src/sync/atomic/asm_freebsd_arm.s
index db37f73bc..06b975e89 100644
--- a/src/pkg/sync/atomic/asm_freebsd_arm.s
+++ b/src/sync/atomic/asm_freebsd_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// FreeBSD/ARM atomic operations.
// TODO(minux): this only supports ARMv6K or higher.
diff --git a/src/pkg/sync/atomic/asm_linux_arm.s b/src/sync/atomic/asm_linux_arm.s
index 27be57aa1..944758441 100644
--- a/src/pkg/sync/atomic/asm_linux_arm.s
+++ b/src/sync/atomic/asm_linux_arm.s
@@ -4,7 +4,7 @@
// +build !race
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// Linux/ARM atomic operations.
@@ -121,30 +121,10 @@ TEXT kernelCAS64<>(SB),NOSPLIT,$0-21
MOVW R0, 20(FP)
RET
-TEXT ·generalCAS64(SB),NOSPLIT,$20-21
- // bool runtime·cas64(uint64 volatile *addr, uint64 old, uint64 new)
- MOVW addr+0(FP), R0
- // trigger potential paging fault here,
- // because a fault in runtime.cas64 will hang.
- MOVW (R0), R2
- // make unaligned atomic access panic
- AND.S $7, R0, R1
- BEQ 2(PC)
- MOVW R1, (R1)
- MOVW R0, 4(R13)
- MOVW old_lo+4(FP), R1
- MOVW R1, 8(R13)
- MOVW old_hi+8(FP), R1
- MOVW R1, 12(R13)
- MOVW new_lo+12(FP), R2
- MOVW R2, 16(R13)
- MOVW new_hi+16(FP), R3
- MOVW R3, 20(R13)
- BL runtime·cas64(SB)
- MOVB R0, ret+20(FP)
- RET
+TEXT ·generalCAS64(SB),NOSPLIT,$0-21
+ B runtime·cas64(SB)
-GLOBL armCAS64(SB), $4
+GLOBL armCAS64(SB), NOPTR, $4
TEXT setupAndCallCAS64<>(SB),NOSPLIT,$-4-21
MOVW $0xffff0ffc, R0 // __kuser_helper_version
diff --git a/src/sync/atomic/asm_nacl_arm.s b/src/sync/atomic/asm_nacl_arm.s
new file mode 100644
index 000000000..76f623336
--- /dev/null
+++ b/src/sync/atomic/asm_nacl_arm.s
@@ -0,0 +1,109 @@
+// 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"
+
+// NaCl/ARM atomic operations.
+// NaCl/ARM explicitly targets ARMv7A.
+
+TEXT ·CompareAndSwapInt32(SB),NOSPLIT,$0
+ B ·CompareAndSwapUint32(SB)
+
+TEXT ·CompareAndSwapUint32(SB),NOSPLIT,$0
+ B ·armCompareAndSwapUint32(SB)
+
+TEXT ·CompareAndSwapUintptr(SB),NOSPLIT,$0
+ B ·CompareAndSwapUint32(SB)
+
+TEXT ·CompareAndSwapPointer(SB),NOSPLIT,$0
+ B ·CompareAndSwapUint32(SB)
+
+TEXT ·AddInt32(SB),NOSPLIT,$0
+ B ·AddUint32(SB)
+
+TEXT ·AddUint32(SB),NOSPLIT,$0
+ B ·armAddUint32(SB)
+
+TEXT ·AddUintptr(SB),NOSPLIT,$0
+ B ·AddUint32(SB)
+
+TEXT ·SwapInt32(SB),NOSPLIT,$0
+ B ·SwapUint32(SB)
+
+TEXT ·SwapUint32(SB),NOSPLIT,$0
+ B ·armSwapUint32(SB)
+
+TEXT ·SwapUintptr(SB),NOSPLIT,$0
+ B ·SwapUint32(SB)
+
+TEXT ·SwapPointer(SB),NOSPLIT,$0
+ B ·SwapUint32(SB)
+
+TEXT ·CompareAndSwapInt64(SB),NOSPLIT,$0
+ B ·CompareAndSwapUint64(SB)
+
+TEXT ·CompareAndSwapUint64(SB),NOSPLIT,$-4
+ B ·armCompareAndSwapUint64(SB)
+
+TEXT ·AddInt64(SB),NOSPLIT,$0
+ B ·addUint64(SB)
+
+TEXT ·AddUint64(SB),NOSPLIT,$0
+ B ·addUint64(SB)
+
+TEXT ·SwapInt64(SB),NOSPLIT,$0
+ B ·swapUint64(SB)
+
+TEXT ·SwapUint64(SB),NOSPLIT,$0
+ B ·swapUint64(SB)
+
+TEXT ·LoadInt32(SB),NOSPLIT,$0
+ B ·LoadUint32(SB)
+
+TEXT ·LoadUint32(SB),NOSPLIT,$0-8
+ MOVW addr+0(FP), R1
+load32loop:
+ LDREX (R1), R2 // loads R2
+ STREX R2, (R1), R0 // stores R2
+ CMP $0, R0
+ BNE load32loop
+ MOVW R2, val+4(FP)
+ RET
+
+TEXT ·LoadInt64(SB),NOSPLIT,$0
+ B ·loadUint64(SB)
+
+TEXT ·LoadUint64(SB),NOSPLIT,$0
+ B ·loadUint64(SB)
+
+TEXT ·LoadUintptr(SB),NOSPLIT,$0
+ B ·LoadUint32(SB)
+
+TEXT ·LoadPointer(SB),NOSPLIT,$0
+ B ·LoadUint32(SB)
+
+TEXT ·StoreInt32(SB),NOSPLIT,$0
+ B ·StoreUint32(SB)
+
+TEXT ·StoreUint32(SB),NOSPLIT,$0-8
+ MOVW addr+0(FP), R1
+ MOVW val+4(FP), R2
+storeloop:
+ LDREX (R1), R4 // loads R4
+ STREX R2, (R1), R0 // stores R2
+ CMP $0, R0
+ BNE storeloop
+ RET
+
+TEXT ·StoreInt64(SB),NOSPLIT,$0
+ B ·storeUint64(SB)
+
+TEXT ·StoreUint64(SB),NOSPLIT,$0
+ B ·storeUint64(SB)
+
+TEXT ·StoreUintptr(SB),NOSPLIT,$0
+ B ·StoreUint32(SB)
+
+TEXT ·StorePointer(SB),NOSPLIT,$0
+ B ·StoreUint32(SB)
diff --git a/src/pkg/sync/atomic/asm_netbsd_arm.s b/src/sync/atomic/asm_netbsd_arm.s
index 64f4dbe71..dbe80898f 100644
--- a/src/pkg/sync/atomic/asm_netbsd_arm.s
+++ b/src/sync/atomic/asm_netbsd_arm.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../../cmd/ld/textflag.h"
+#include "textflag.h"
// NetBSD/ARM atomic operations.
// TODO(minux): this only supports ARMv6K or higher.
diff --git a/src/pkg/sync/atomic/atomic_linux_arm_test.go b/src/sync/atomic/atomic_linux_arm_test.go
index b6965b99b..b6965b99b 100644
--- a/src/pkg/sync/atomic/atomic_linux_arm_test.go
+++ b/src/sync/atomic/atomic_linux_arm_test.go
diff --git a/src/pkg/sync/atomic/atomic_test.go b/src/sync/atomic/atomic_test.go
index a5f44f70d..9f13af48b 100644
--- a/src/pkg/sync/atomic/atomic_test.go
+++ b/src/sync/atomic/atomic_test.go
@@ -858,7 +858,7 @@ func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
addr := (*int32)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *addr
+ v := LoadInt32(addr)
if CompareAndSwapInt32(addr, v, v+1) {
break
}
@@ -869,7 +869,7 @@ func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
func hammerCompareAndSwapUint32(addr *uint32, count int) {
for i := 0; i < count; i++ {
for {
- v := *addr
+ v := LoadUint32(addr)
if CompareAndSwapUint32(addr, v, v+1) {
break
}
@@ -883,7 +883,7 @@ func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
addr := (*uintptr)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *addr
+ v := LoadUintptr(addr)
if CompareAndSwapUintptr(addr, v, v+1) {
break
}
@@ -897,7 +897,7 @@ func hammerCompareAndSwapPointer32(uaddr *uint32, count int) {
addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *addr
+ v := LoadPointer(addr)
if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
break
}
@@ -1039,7 +1039,7 @@ func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
addr := (*int64)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *addr
+ v := LoadInt64(addr)
if CompareAndSwapInt64(addr, v, v+1) {
break
}
@@ -1050,7 +1050,7 @@ func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
func hammerCompareAndSwapUint64(addr *uint64, count int) {
for i := 0; i < count; i++ {
for {
- v := *addr
+ v := LoadUint64(addr)
if CompareAndSwapUint64(addr, v, v+1) {
break
}
@@ -1064,7 +1064,7 @@ func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
addr := (*uintptr)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *addr
+ v := LoadUintptr(addr)
if CompareAndSwapUintptr(addr, v, v+1) {
break
}
@@ -1078,7 +1078,7 @@ func hammerCompareAndSwapPointer64(uaddr *uint64, count int) {
addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
for i := 0; i < count; i++ {
for {
- v := *addr
+ v := LoadPointer(addr)
if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
break
}
diff --git a/src/pkg/sync/atomic/doc.go b/src/sync/atomic/doc.go
index 17ba72fa1..10fb8c917 100644
--- a/src/pkg/sync/atomic/doc.go
+++ b/src/sync/atomic/doc.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.
-// +build !race
-
// Package atomic provides low-level atomic memory primitives
// useful for implementing synchronization algorithms.
//
diff --git a/src/pkg/sync/atomic/export_linux_arm_test.go b/src/sync/atomic/export_linux_arm_test.go
index 5cd43353e..9f0c856a7 100644
--- a/src/pkg/sync/atomic/export_linux_arm_test.go
+++ b/src/sync/atomic/export_linux_arm_test.go
@@ -4,6 +4,4 @@
package atomic
-func generalCAS64(addr *uint64, old uint64, new uint64) bool
-
var GeneralCAS64 = generalCAS64
diff --git a/src/sync/atomic/race.s b/src/sync/atomic/race.s
new file mode 100644
index 000000000..bdce7668b
--- /dev/null
+++ b/src/sync/atomic/race.s
@@ -0,0 +1,8 @@
+// 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 race
+
+// This file is here only to allow external functions.
+// The operations are implemented in src/runtime/race_amd64.s
diff --git a/src/sync/atomic/value.go b/src/sync/atomic/value.go
new file mode 100644
index 000000000..ab3aa1128
--- /dev/null
+++ b/src/sync/atomic/value.go
@@ -0,0 +1,85 @@
+// 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 atomic
+
+import (
+ "unsafe"
+)
+
+// A Value provides an atomic load and store of a consistently typed value.
+// Values can be created as part of other data structures.
+// The zero value for a Value returns nil from Load.
+// Once Store has been called, a Value must not be copied.
+type Value struct {
+ v interface{}
+}
+
+// ifaceWords is interface{} internal representation.
+type ifaceWords struct {
+ typ unsafe.Pointer
+ data unsafe.Pointer
+}
+
+// Load returns the value set by the most recent Store.
+// It returns nil if there has been no call to Store for this Value.
+func (v *Value) Load() (x interface{}) {
+ vp := (*ifaceWords)(unsafe.Pointer(v))
+ typ := LoadPointer(&vp.typ)
+ if typ == nil || uintptr(typ) == ^uintptr(0) {
+ // First store not yet completed.
+ return nil
+ }
+ data := LoadPointer(&vp.data)
+ xp := (*ifaceWords)(unsafe.Pointer(&x))
+ xp.typ = typ
+ xp.data = data
+ return
+}
+
+// Store sets the value of the Value to x.
+// All calls to Store for a given Value must use values of the same concrete type.
+// Store of an inconsistent type panics, as does Store(nil).
+func (v *Value) Store(x interface{}) {
+ if x == nil {
+ panic("sync/atomic: store of nil value into Value")
+ }
+ vp := (*ifaceWords)(unsafe.Pointer(v))
+ xp := (*ifaceWords)(unsafe.Pointer(&x))
+ for {
+ typ := LoadPointer(&vp.typ)
+ if typ == nil {
+ // Attempt to start first store.
+ // Disable preemption so that other goroutines can use
+ // active spin wait to wait for completion; and so that
+ // GC does not see the fake type accidentally.
+ runtime_procPin()
+ if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
+ runtime_procUnpin()
+ continue
+ }
+ // Complete first store.
+ StorePointer(&vp.data, xp.data)
+ StorePointer(&vp.typ, xp.typ)
+ runtime_procUnpin()
+ return
+ }
+ if uintptr(typ) == ^uintptr(0) {
+ // First store in progress. Wait.
+ // Since we disable preemption around the first store,
+ // we can wait with active spinning.
+ continue
+ }
+ // First store completed. Check type and overwrite data.
+ if typ != xp.typ {
+ panic("sync/atomic: store of inconsistently typed value into Value")
+ }
+ StorePointer(&vp.data, xp.data)
+ return
+ }
+}
+
+// Disable/enable preemption, implemented in runtime.
+func runtime_procPin()
+func runtime_procUnpin()
diff --git a/src/sync/atomic/value_test.go b/src/sync/atomic/value_test.go
new file mode 100644
index 000000000..382dc6854
--- /dev/null
+++ b/src/sync/atomic/value_test.go
@@ -0,0 +1,195 @@
+// 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 atomic_test
+
+import (
+ "math/rand"
+ "runtime"
+ "sync"
+ . "sync/atomic"
+ "testing"
+ "time"
+)
+
+func TestValue(t *testing.T) {
+ var v Value
+ if v.Load() != nil {
+ t.Fatal("initial Value is not nil")
+ }
+ v.Store(42)
+ x := v.Load()
+ if xx, ok := x.(int); !ok || xx != 42 {
+ t.Fatalf("wrong value: got %+v, want 42", x)
+ }
+ v.Store(84)
+ x = v.Load()
+ if xx, ok := x.(int); !ok || xx != 84 {
+ t.Fatalf("wrong value: got %+v, want 84", x)
+ }
+}
+
+func TestValueLarge(t *testing.T) {
+ var v Value
+ v.Store("foo")
+ x := v.Load()
+ if xx, ok := x.(string); !ok || xx != "foo" {
+ t.Fatalf("wrong value: got %+v, want foo", x)
+ }
+ v.Store("barbaz")
+ x = v.Load()
+ if xx, ok := x.(string); !ok || xx != "barbaz" {
+ t.Fatalf("wrong value: got %+v, want barbaz", x)
+ }
+}
+
+func TestValuePanic(t *testing.T) {
+ const nilErr = "sync/atomic: store of nil value into Value"
+ const badErr = "sync/atomic: store of inconsistently typed value into Value"
+ var v Value
+ func() {
+ defer func() {
+ err := recover()
+ if err != nilErr {
+ t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, nilErr)
+ }
+ }()
+ v.Store(nil)
+ }()
+ v.Store(42)
+ func() {
+ defer func() {
+ err := recover()
+ if err != badErr {
+ t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, badErr)
+ }
+ }()
+ v.Store("foo")
+ }()
+ func() {
+ defer func() {
+ err := recover()
+ if err != nilErr {
+ t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, nilErr)
+ }
+ }()
+ v.Store(nil)
+ }()
+}
+
+func TestValueConcurrent(t *testing.T) {
+ tests := [][]interface{}{
+ {uint16(0), ^uint16(0), uint16(1 + 2<<8), uint16(3 + 4<<8)},
+ {uint32(0), ^uint32(0), uint32(1 + 2<<16), uint32(3 + 4<<16)},
+ {uint64(0), ^uint64(0), uint64(1 + 2<<32), uint64(3 + 4<<32)},
+ {complex(0, 0), complex(1, 2), complex(3, 4), complex(5, 6)},
+ }
+ p := 4 * runtime.GOMAXPROCS(0)
+ for _, test := range tests {
+ var v Value
+ done := make(chan bool)
+ for i := 0; i < p; i++ {
+ go func() {
+ r := rand.New(rand.NewSource(rand.Int63()))
+ loop:
+ for j := 0; j < 1e5; j++ {
+ x := test[r.Intn(len(test))]
+ v.Store(x)
+ x = v.Load()
+ for _, x1 := range test {
+ if x == x1 {
+ continue loop
+ }
+ }
+ t.Logf("loaded unexpected value %+v, want %+v", x, test)
+ done <- false
+ }
+ done <- true
+ }()
+ }
+ for i := 0; i < p; i++ {
+ if !<-done {
+ t.FailNow()
+ }
+ }
+ }
+}
+
+func BenchmarkValueRead(b *testing.B) {
+ var v Value
+ v.Store(new(int))
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ x := v.Load().(*int)
+ if *x != 0 {
+ b.Fatalf("wrong value: got %v, want 0", *x)
+ }
+ }
+ })
+}
+
+// The following example shows how to use Value for periodic program config updates
+// and propagation of the changes to worker goroutines.
+func ExampleValue_config() {
+ var config Value // holds current server configuration
+ // Create initial config value and store into config.
+ config.Store(loadConfig())
+ go func() {
+ // Reload config every 10 seconds
+ // and update config value with the new version.
+ for {
+ time.Sleep(10 * time.Second)
+ config.Store(loadConfig())
+ }
+ }()
+ // Create worker goroutines that handle incoming requests
+ // using the latest config value.
+ for i := 0; i < 10; i++ {
+ go func() {
+ for r := range requests() {
+ c := config.Load()
+ // Handle request r using config c.
+ _, _ = r, c
+ }
+ }()
+ }
+}
+
+func loadConfig() map[string]string {
+ return make(map[string]string)
+}
+
+func requests() chan int {
+ return make(chan int)
+}
+
+// The following example shows how to maintain a scalable frequently read,
+// but infrequently updated data structure using copy-on-write idiom.
+func ExampleValue_readMostly() {
+ type Map map[string]string
+ var m Value
+ m.Store(make(Map))
+ var mu sync.Mutex // used only by writers
+ // read function can be used to read the data without further synchronization
+ read := func(key string) (val string) {
+ m1 := m.Load().(Map)
+ return m1[key]
+ }
+ // insert function can be used to update the data without further synchronization
+ insert := func(key, val string) {
+ mu.Lock() // synchronize with other potential writers
+ defer mu.Unlock()
+ m1 := m.Load().(Map) // load current value of the data structure
+ m2 := make(Map) // create a new value
+ for k, v := range m1 {
+ m2[k] = v // copy all data from the current object to the new one
+ }
+ m2[key] = val // do the update that we need
+ m.Store(m2) // atomically replace the current object with the new one
+ // At this point all new readers start working with the new version.
+ // The old version will be garbage collected once the existing readers
+ // (if any) are done with it.
+ }
+ _, _ = read, insert
+}
diff --git a/src/pkg/sync/cond.go b/src/sync/cond.go
index 9e6bc170f..9e6bc170f 100644
--- a/src/pkg/sync/cond.go
+++ b/src/sync/cond.go
diff --git a/src/pkg/sync/cond_test.go b/src/sync/cond_test.go
index 467c80621..467c80621 100644
--- a/src/pkg/sync/cond_test.go
+++ b/src/sync/cond_test.go
diff --git a/src/pkg/sync/example_test.go b/src/sync/example_test.go
index bdd3af6fe..bdd3af6fe 100644
--- a/src/pkg/sync/example_test.go
+++ b/src/sync/example_test.go
diff --git a/src/pkg/sync/export_test.go b/src/sync/export_test.go
index fa5983a2d..fa5983a2d 100644
--- a/src/pkg/sync/export_test.go
+++ b/src/sync/export_test.go
diff --git a/src/pkg/sync/mutex.go b/src/sync/mutex.go
index 73b337702..73b337702 100644
--- a/src/pkg/sync/mutex.go
+++ b/src/sync/mutex.go
diff --git a/src/pkg/sync/mutex_test.go b/src/sync/mutex_test.go
index 151b25c10..151b25c10 100644
--- a/src/pkg/sync/mutex_test.go
+++ b/src/sync/mutex_test.go
diff --git a/src/pkg/sync/once.go b/src/sync/once.go
index 161ae3b3e..10b42fddc 100644
--- a/src/pkg/sync/once.go
+++ b/src/sync/once.go
@@ -15,7 +15,7 @@ type Once struct {
}
// Do calls the function f if and only if Do is being called for the
-// first time for this instance of Once. In other words, given
+// first time for this instance of Once. In other words, given
// var once Once
// if once.Do(f) is called multiple times, only the first call will invoke f,
// even if f has a different value in each invocation. A new instance of
@@ -29,6 +29,9 @@ type Once struct {
// Because no call to Do returns until the one call to f returns, if f causes
// Do to be called, it will deadlock.
//
+// If f panics, Do considers it to have returned; future calls of Do return
+// without calling f.
+//
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 1 {
return
@@ -37,7 +40,7 @@ func (o *Once) Do(f func()) {
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
+ defer atomic.StoreUint32(&o.done, 1)
f()
- atomic.StoreUint32(&o.done, 1)
}
}
diff --git a/src/pkg/sync/once_test.go b/src/sync/once_test.go
index 8afda82f3..1eec8d18e 100644
--- a/src/pkg/sync/once_test.go
+++ b/src/sync/once_test.go
@@ -40,22 +40,20 @@ func TestOnce(t *testing.T) {
}
func TestOncePanic(t *testing.T) {
- once := new(Once)
- for i := 0; i < 2; i++ {
- func() {
- defer func() {
- if recover() == nil {
- t.Fatalf("Once.Do() has not panic'ed")
- }
- }()
- once.Do(func() {
- panic("failed")
- })
+ var once Once
+ func() {
+ defer func() {
+ if r := recover(); r == nil {
+ t.Fatalf("Once.Do did not panic")
+ }
}()
- }
- once.Do(func() {})
+ once.Do(func() {
+ panic("failed")
+ })
+ }()
+
once.Do(func() {
- t.Fatalf("Once called twice")
+ t.Fatalf("Once.Do called twice")
})
}
diff --git a/src/pkg/sync/pool.go b/src/sync/pool.go
index 1f08707cd..0cf063702 100644
--- a/src/pkg/sync/pool.go
+++ b/src/sync/pool.go
@@ -200,6 +200,8 @@ func poolCleanup() {
}
l.shared = nil
}
+ p.local = nil
+ p.localSize = 0
}
allPools = []*Pool{}
}
diff --git a/src/pkg/sync/pool_test.go b/src/sync/pool_test.go
index 509448b62..fa1a27bea 100644
--- a/src/pkg/sync/pool_test.go
+++ b/src/sync/pool_test.go
@@ -69,32 +69,44 @@ func TestPoolNew(t *testing.T) {
}
}
-// Test that Pool does not hold pointers to previously cached
-// resources
+// Test that Pool does not hold pointers to previously cached resources.
func TestPoolGC(t *testing.T) {
+ testPool(t, true)
+}
+
+// Test that Pool releases resources on GC.
+func TestPoolRelease(t *testing.T) {
+ testPool(t, false)
+}
+
+func testPool(t *testing.T, drain bool) {
var p Pool
- var fin uint32
const N = 100
- for i := 0; i < N; i++ {
- v := new(string)
- runtime.SetFinalizer(v, func(vv *string) {
- atomic.AddUint32(&fin, 1)
- })
- p.Put(v)
- }
- for i := 0; i < N; i++ {
- p.Get()
- }
- for i := 0; i < 5; i++ {
- runtime.GC()
- time.Sleep(time.Duration(i*100+10) * time.Millisecond)
- // 1 pointer can remain on stack or elsewhere
- if atomic.LoadUint32(&fin) >= N-1 {
- return
+loop:
+ for try := 0; try < 3; try++ {
+ var fin, fin1 uint32
+ for i := 0; i < N; i++ {
+ v := new(string)
+ runtime.SetFinalizer(v, func(vv *string) {
+ atomic.AddUint32(&fin, 1)
+ })
+ p.Put(v)
+ }
+ if drain {
+ for i := 0; i < N; i++ {
+ p.Get()
+ }
+ }
+ for i := 0; i < 5; i++ {
+ runtime.GC()
+ time.Sleep(time.Duration(i*100+10) * time.Millisecond)
+ // 1 pointer can remain on stack or elsewhere
+ if fin1 = atomic.LoadUint32(&fin); fin1 >= N-1 {
+ continue loop
+ }
}
+ t.Fatalf("only %v out of %v resources are finalized on try %v", fin1, N, try)
}
- t.Fatalf("only %v out of %v resources are finalized",
- atomic.LoadUint32(&fin), N)
}
func TestPoolStress(t *testing.T) {
@@ -136,7 +148,7 @@ func BenchmarkPool(b *testing.B) {
})
}
-func BenchmarkPoolOverlflow(b *testing.B) {
+func BenchmarkPoolOverflow(b *testing.B) {
var p Pool
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
diff --git a/src/pkg/sync/race.go b/src/sync/race.go
index fd0277dcc..fd0277dcc 100644
--- a/src/pkg/sync/race.go
+++ b/src/sync/race.go
diff --git a/src/pkg/sync/race0.go b/src/sync/race0.go
index 65ada1c5d..65ada1c5d 100644
--- a/src/pkg/sync/race0.go
+++ b/src/sync/race0.go
diff --git a/src/pkg/sync/runtime.go b/src/sync/runtime.go
index 3bf47ea52..3b866303a 100644
--- a/src/pkg/sync/runtime.go
+++ b/src/sync/runtime.go
@@ -19,8 +19,12 @@ func runtime_Semacquire(s *uint32)
// library and should not be used directly.
func runtime_Semrelease(s *uint32)
-// Opaque representation of SyncSema in runtime/sema.goc.
-type syncSema [3]uintptr
+// Approximation of syncSema in runtime/sema.go.
+type syncSema struct {
+ lock uintptr
+ head unsafe.Pointer
+ tail unsafe.Pointer
+}
// Syncsemacquire waits for a pairing Syncsemrelease on the same semaphore s.
func runtime_Syncsemacquire(s *syncSema)
diff --git a/src/pkg/sync/runtime_sema_test.go b/src/sync/runtime_sema_test.go
index 5b7dd3df3..5b7dd3df3 100644
--- a/src/pkg/sync/runtime_sema_test.go
+++ b/src/sync/runtime_sema_test.go
diff --git a/src/pkg/sync/rwmutex.go b/src/sync/rwmutex.go
index 3db541995..0e8a58e5f 100644
--- a/src/pkg/sync/rwmutex.go
+++ b/src/sync/rwmutex.go
@@ -51,7 +51,11 @@ func (rw *RWMutex) RUnlock() {
raceReleaseMerge(unsafe.Pointer(&rw.writerSem))
raceDisable()
}
- if atomic.AddInt32(&rw.readerCount, -1) < 0 {
+ if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {
+ if r+1 == 0 || r+1 == -rwmutexMaxReaders {
+ raceEnable()
+ panic("sync: RUnlock of unlocked RWMutex")
+ }
// A writer is pending.
if atomic.AddInt32(&rw.readerWait, -1) == 0 {
// The last reader unblocks the writer.
@@ -105,6 +109,10 @@ func (rw *RWMutex) Unlock() {
// Announce to readers there is no active writer.
r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
+ if r >= rwmutexMaxReaders {
+ raceEnable()
+ panic("sync: Unlock of unlocked RWMutex")
+ }
// Unblock blocked readers, if any.
for i := 0; i < int(r); i++ {
runtime_Semrelease(&rw.readerSem)
diff --git a/src/pkg/sync/rwmutex_test.go b/src/sync/rwmutex_test.go
index 0436f9723..f625bc3a5 100644
--- a/src/pkg/sync/rwmutex_test.go
+++ b/src/sync/rwmutex_test.go
@@ -155,6 +155,48 @@ func TestRLocker(t *testing.T) {
}
}
+func TestUnlockPanic(t *testing.T) {
+ defer func() {
+ if recover() == nil {
+ t.Fatalf("unlock of unlocked RWMutex did not panic")
+ }
+ }()
+ var mu RWMutex
+ mu.Unlock()
+}
+
+func TestUnlockPanic2(t *testing.T) {
+ defer func() {
+ if recover() == nil {
+ t.Fatalf("unlock of unlocked RWMutex did not panic")
+ }
+ }()
+ var mu RWMutex
+ mu.RLock()
+ mu.Unlock()
+}
+
+func TestRUnlockPanic(t *testing.T) {
+ defer func() {
+ if recover() == nil {
+ t.Fatalf("read unlock of unlocked RWMutex did not panic")
+ }
+ }()
+ var mu RWMutex
+ mu.RUnlock()
+}
+
+func TestRUnlockPanic2(t *testing.T) {
+ defer func() {
+ if recover() == nil {
+ t.Fatalf("read unlock of unlocked RWMutex did not panic")
+ }
+ }()
+ var mu RWMutex
+ mu.Lock()
+ mu.RUnlock()
+}
+
func BenchmarkRWMutexUncontended(b *testing.B) {
type PaddedRWMutex struct {
RWMutex
diff --git a/src/pkg/sync/waitgroup.go b/src/sync/waitgroup.go
index 4c64dca39..92cc57d2c 100644
--- a/src/pkg/sync/waitgroup.go
+++ b/src/sync/waitgroup.go
@@ -37,10 +37,13 @@ type WaitGroup struct {
// If the counter becomes zero, all goroutines blocked on Wait are released.
// If the counter goes negative, Add panics.
//
-// Note that calls with positive delta must happen before the call to Wait,
-// or else Wait may wait for too small a group. Typically this means the calls
-// to Add should execute before the statement creating the goroutine or
-// other event to be waited for. See the WaitGroup example.
+// Note that calls with a positive delta that occur when the counter is zero
+// must happen before a Wait. Calls with a negative delta, or calls with a
+// positive delta that start when the counter is greater than zero, may happen
+// at any time.
+// Typically this means the calls to Add should execute before the statement
+// creating the goroutine or other event to be waited for.
+// See the WaitGroup example.
func (wg *WaitGroup) Add(delta int) {
if raceenabled {
_ = wg.m.state // trigger nil deref early
diff --git a/src/pkg/sync/waitgroup_test.go b/src/sync/waitgroup_test.go
index 4c0a043c0..4c0a043c0 100644
--- a/src/pkg/sync/waitgroup_test.go
+++ b/src/sync/waitgroup_test.go
diff --git a/src/syscall/asm.s b/src/syscall/asm.s
new file mode 100644
index 000000000..d4ca868f1
--- /dev/null
+++ b/src/syscall/asm.s
@@ -0,0 +1,8 @@
+// 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"
+
+TEXT ·use(SB),NOSPLIT,$0
+ RET
diff --git a/src/pkg/syscall/asm_darwin_386.s b/src/syscall/asm_darwin_386.s
index 9b4dfa81d..7205deb12 100644
--- a/src/pkg/syscall/asm_darwin_386.s
+++ b/src/syscall/asm_darwin_386.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for 386, Darwin
diff --git a/src/pkg/syscall/asm_darwin_amd64.s b/src/syscall/asm_darwin_amd64.s
index 19ea05be7..e57199d2b 100644
--- a/src/pkg/syscall/asm_darwin_amd64.s
+++ b/src/syscall/asm_darwin_amd64.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for AMD64, Darwin
diff --git a/src/pkg/syscall/asm_dragonfly_386.s b/src/syscall/asm_dragonfly_386.s
index d24216fdd..7012d23c2 100644
--- a/src/pkg/syscall/asm_dragonfly_386.s
+++ b/src/syscall/asm_dragonfly_386.s
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for 386, FreeBSD
diff --git a/src/pkg/syscall/asm_dragonfly_amd64.s b/src/syscall/asm_dragonfly_amd64.s
index 31d107490..004d36089 100644
--- a/src/pkg/syscall/asm_dragonfly_amd64.s
+++ b/src/syscall/asm_dragonfly_amd64.s
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for AMD64, DragonFly
diff --git a/src/pkg/syscall/asm_freebsd_386.s b/src/syscall/asm_freebsd_386.s
index 91a46b106..1400d5fea 100644
--- a/src/pkg/syscall/asm_freebsd_386.s
+++ b/src/syscall/asm_freebsd_386.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for 386, FreeBSD
diff --git a/src/pkg/syscall/asm_freebsd_amd64.s b/src/syscall/asm_freebsd_amd64.s
index 7abb36828..c52519098 100644
--- a/src/pkg/syscall/asm_freebsd_amd64.s
+++ b/src/syscall/asm_freebsd_amd64.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for AMD64, FreeBSD
diff --git a/src/pkg/syscall/asm_freebsd_arm.s b/src/syscall/asm_freebsd_arm.s
index c01ce6feb..6b0c182a7 100644
--- a/src/pkg/syscall/asm_freebsd_arm.s
+++ b/src/syscall/asm_freebsd_arm.s
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for ARM, FreeBSD
diff --git a/src/pkg/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s
index 30b22073d..fa1b37120 100644
--- a/src/pkg/syscall/asm_linux_386.s
+++ b/src/syscall/asm_linux_386.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System calls for 386, Linux
diff --git a/src/pkg/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s
index 995b60ecd..b3ce2165d 100644
--- a/src/pkg/syscall/asm_linux_amd64.s
+++ b/src/syscall/asm_linux_amd64.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System calls for AMD64, Linux
diff --git a/src/pkg/syscall/asm_linux_arm.s b/src/syscall/asm_linux_arm.s
index a28bc6cfc..352653301 100644
--- a/src/pkg/syscall/asm_linux_arm.s
+++ b/src/syscall/asm_linux_arm.s
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System calls for arm, Linux
@@ -18,6 +19,9 @@ TEXT ·Syscall(SB),NOSPLIT,$0-28
MOVW 8(SP), R0
MOVW 12(SP), R1
MOVW 16(SP), R2
+ MOVW $0, R3
+ MOVW $0, R4
+ MOVW $0, R5
SWI $0
MOVW $0xfffff001, R1
CMP R1, R0
diff --git a/src/pkg/syscall/asm_nacl_386.s b/src/syscall/asm_nacl_386.s
index de7c3cc5d..cb6fb4416 100644
--- a/src/pkg/syscall/asm_nacl_386.s
+++ b/src/syscall/asm_nacl_386.s
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
#include "../runtime/syscall_nacl.h"
//
diff --git a/src/pkg/syscall/asm_nacl_amd64p32.s b/src/syscall/asm_nacl_amd64p32.s
index de030ec80..72391c431 100644
--- a/src/pkg/syscall/asm_nacl_amd64p32.s
+++ b/src/syscall/asm_nacl_amd64p32.s
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
#include "../runtime/syscall_nacl.h"
//
diff --git a/src/syscall/asm_nacl_arm.s b/src/syscall/asm_nacl_arm.s
new file mode 100644
index 000000000..78e10bf7a
--- /dev/null
+++ b/src/syscall/asm_nacl_arm.s
@@ -0,0 +1,44 @@
+// 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"
+#include "funcdata.h"
+#include "../runtime/syscall_nacl.h"
+
+//
+// System call support for ARM, Native Client
+//
+
+#define NACL_SYSCALL(code) \
+ MOVW $(0x10000 + ((code)<<5)), R8; BL (R8)
+
+#define NACL_SYSJMP(code) \
+ MOVW $(0x10000 + ((code)<<5)), R8; B (R8)
+
+TEXT syscall·Syscall(SB),NOSPLIT,$0-28
+ BL runtime·entersyscall(SB)
+ MOVW trap+0(FP), R8
+ MOVW a1+4(FP), R0
+ MOVW a2+8(FP), R1
+ MOVW a3+12(FP), R2
+ // more args would use R3, and then stack.
+ MOVW $0x10000, R7
+ ADD R8<<5, R7
+ BL (R7)
+ CMP $0, R0
+ BGE ok
+ MOVW $-1, R1
+ MOVW R1, r1+16(FP)
+ MOVW R1, r2+20(FP)
+ RSB $0, R0
+ MOVW R0, err+24(FP)
+ BL runtime·exitsyscall(SB)
+ RET
+ok:
+ MOVW R0, r1+16(FP)
+ MOVW R1, r2+20(FP)
+ MOVW $0, R2
+ MOVW R2, err+24(FP)
+ BL runtime·exitsyscall(SB)
+ RET
diff --git a/src/pkg/syscall/asm_netbsd_386.s b/src/syscall/asm_netbsd_386.s
index 40b30b405..a8c4849f2 100644
--- a/src/pkg/syscall/asm_netbsd_386.s
+++ b/src/syscall/asm_netbsd_386.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for 386, NetBSD
diff --git a/src/pkg/syscall/asm_netbsd_amd64.s b/src/syscall/asm_netbsd_amd64.s
index 94ad0284a..b300148f4 100644
--- a/src/pkg/syscall/asm_netbsd_amd64.s
+++ b/src/syscall/asm_netbsd_amd64.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for AMD64, NetBSD
diff --git a/src/pkg/syscall/asm_netbsd_arm.s b/src/syscall/asm_netbsd_arm.s
index 2c0d65401..290bb5806 100644
--- a/src/pkg/syscall/asm_netbsd_arm.s
+++ b/src/syscall/asm_netbsd_arm.s
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for ARM, NetBSD
diff --git a/src/pkg/syscall/asm_openbsd_386.s b/src/syscall/asm_openbsd_386.s
index 7dd2e373f..6458bdf02 100644
--- a/src/pkg/syscall/asm_openbsd_386.s
+++ b/src/syscall/asm_openbsd_386.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for 386, OpenBSD
diff --git a/src/pkg/syscall/asm_openbsd_amd64.s b/src/syscall/asm_openbsd_amd64.s
index e127bf220..1e981fc01 100644
--- a/src/pkg/syscall/asm_openbsd_amd64.s
+++ b/src/syscall/asm_openbsd_amd64.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for AMD64, OpenBSD
diff --git a/src/pkg/syscall/asm_plan9_386.s b/src/syscall/asm_plan9_386.s
index f8c07c407..fc13640b9 100644
--- a/src/pkg/syscall/asm_plan9_386.s
+++ b/src/syscall/asm_plan9_386.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for 386, Plan 9
@@ -158,6 +159,7 @@ copyresult6:
//func exit(code int)
// Import runtime·exit for cleanly exiting.
TEXT ·exit(SB),NOSPLIT,$4-4
+ NO_LOCAL_POINTERS
MOVL code+0(FP), AX
MOVL AX, 0(SP)
CALL runtime·exit(SB)
diff --git a/src/pkg/syscall/asm_plan9_amd64.s b/src/syscall/asm_plan9_amd64.s
index 2154a87d5..92419b717 100644
--- a/src/pkg/syscall/asm_plan9_amd64.s
+++ b/src/syscall/asm_plan9_amd64.s
@@ -5,7 +5,8 @@
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
// so that go vet can check that they are correct.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
+#include "funcdata.h"
//
// System call support for Plan 9
@@ -16,12 +17,8 @@
//func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
//func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
-// Trap # in BP, args on stack above caller pc.
-// NxM requires that Plan 9 system calls be
-// marked with $0x8000 in AX.
TEXT ·Syscall(SB),NOSPLIT,$0-64
CALL runtime·entersyscall(SB)
- MOVQ $0x8000, AX // for NxM
MOVQ 8(SP), BP // syscall entry
// slide args down on top of system call number
LEAQ 16(SP), SI
@@ -57,7 +54,6 @@ copyresult3:
TEXT ·Syscall6(SB),NOSPLIT,$0-88
CALL runtime·entersyscall(SB)
- MOVQ $0x8000, AX // for NxM
MOVQ 8(SP), BP // syscall entry
// slide args down on top of system call number
LEAQ 16(SP), SI
@@ -95,7 +91,6 @@ copyresult4:
RET
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
- MOVQ $0x8000, AX // for NxM
MOVQ 8(SP), BP // syscall entry
// slide args down on top of system call number
LEAQ 16(SP), SI
@@ -111,7 +106,6 @@ TEXT ·RawSyscall(SB),NOSPLIT,$0-56
RET
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
- MOVQ $0x8000, AX // for NxM
MOVQ 8(SP), BP // syscall entry
// slide args down on top of system call number
LEAQ 16(SP), SI
@@ -136,7 +130,6 @@ TEXT ·seek(SB),NOSPLIT,$0-56
LEAQ newoffset+40(SP), AX
MOVQ AX, placeholder+8(SP)
- MOVQ $0x8000, AX // for NxM
MOVQ $SYS_SEEK, BP // syscall entry
SYSCALL
@@ -164,6 +157,7 @@ copyresult6:
//func exit(code int)
// Import runtime·exit for cleanly exiting.
TEXT ·exit(SB),NOSPLIT,$8-8
+ NO_LOCAL_POINTERS
MOVQ code+0(FP), AX
MOVQ AX, 0(SP)
CALL runtime·exit(SB)
diff --git a/src/syscall/asm_solaris_amd64.s b/src/syscall/asm_solaris_amd64.s
new file mode 100644
index 000000000..d0d271c76
--- /dev/null
+++ b/src/syscall/asm_solaris_amd64.s
@@ -0,0 +1,81 @@
+// 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"
+
+//
+// System calls for solaris/amd64 are implemented in ../runtime/syscall_solaris.go
+//
+
+TEXT ·sysvicall6(SB),NOSPLIT,$0
+ JMP runtime·syscall_sysvicall6(SB)
+
+TEXT ·rawSysvicall6(SB),NOSPLIT,$0
+ JMP runtime·syscall_rawsysvicall6(SB)
+
+TEXT ·chdir(SB),NOSPLIT,$0
+ JMP runtime·syscall_chdir(SB)
+
+TEXT ·chroot1(SB),NOSPLIT,$0
+ JMP runtime·syscall_chroot(SB)
+
+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)
+
+TEXT ·exit(SB),NOSPLIT,$0
+ JMP runtime·syscall_exit(SB)
+
+TEXT ·fcntl1(SB),NOSPLIT,$0
+ JMP runtime·syscall_fcntl(SB)
+
+TEXT ·forkx(SB),NOSPLIT,$0
+ JMP runtime·syscall_forkx(SB)
+
+TEXT ·gethostname(SB),NOSPLIT,$0
+ JMP runtime·syscall_gethostname(SB)
+
+TEXT ·ioctl(SB),NOSPLIT,$0
+ JMP runtime·syscall_ioctl(SB)
+
+TEXT ·pipe(SB),NOSPLIT,$0
+ JMP runtime·syscall_pipe(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0
+ JMP runtime·syscall_rawsyscall(SB)
+
+TEXT ·setgid(SB),NOSPLIT,$0
+ JMP runtime·syscall_setgid(SB)
+
+TEXT ·setgroups1(SB),NOSPLIT,$0
+ JMP runtime·syscall_setgroups(SB)
+
+TEXT ·setsid(SB),NOSPLIT,$0
+ JMP runtime·syscall_setsid(SB)
+
+TEXT ·setuid(SB),NOSPLIT,$0
+ JMP runtime·syscall_setuid(SB)
+
+TEXT ·setpgid(SB),NOSPLIT,$0
+ JMP runtime·syscall_setpgid(SB)
+
+TEXT ·Syscall(SB),NOSPLIT,$0
+ JMP runtime·syscall_syscall(SB)
+
+TEXT ·wait4(SB),NOSPLIT,$0
+ JMP runtime·syscall_wait4(SB)
+
+TEXT ·write1(SB),NOSPLIT,$0
+ JMP runtime·syscall_write(SB)
diff --git a/src/pkg/syscall/bpf_bsd.go b/src/syscall/bpf_bsd.go
index cc6c1e77c..cc6c1e77c 100644
--- a/src/pkg/syscall/bpf_bsd.go
+++ b/src/syscall/bpf_bsd.go
diff --git a/src/pkg/syscall/creds_test.go b/src/syscall/creds_test.go
index b1894c66b..b1894c66b 100644
--- a/src/pkg/syscall/creds_test.go
+++ b/src/syscall/creds_test.go
diff --git a/src/pkg/syscall/dir_plan9.go b/src/syscall/dir_plan9.go
index 697bf5499..697bf5499 100644
--- a/src/pkg/syscall/dir_plan9.go
+++ b/src/syscall/dir_plan9.go
diff --git a/src/pkg/syscall/dll_windows.go b/src/syscall/dll_windows.go
index d29e9921c..18663b486 100644
--- a/src/pkg/syscall/dll_windows.go
+++ b/src/syscall/dll_windows.go
@@ -19,7 +19,7 @@ type DLLError struct {
func (e *DLLError) Error() string { return e.Msg }
-// Implemented in ../runtime/syscall_windows.goc.
+// Implemented in ../runtime/syscall_windows.go.
func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
func Syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func Syscall9(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
@@ -72,6 +72,7 @@ func (d *DLL) FindProc(name string) (proc *Proc, err error) {
return nil, err
}
a, e := getprocaddress(uintptr(d.Handle), namep)
+ use(unsafe.Pointer(namep))
if e != 0 {
return nil, &DLLError{
Err: e,
diff --git a/src/pkg/syscall/env_plan9.go b/src/syscall/env_plan9.go
index 9587ab5af..9ea36c886 100644
--- a/src/pkg/syscall/env_plan9.go
+++ b/src/syscall/env_plan9.go
@@ -8,22 +8,9 @@ package syscall
import (
"errors"
- "sync"
)
var (
- // envOnce guards copyenv, which populates env.
- envOnce sync.Once
-
- // envLock guards env and envs.
- envLock sync.RWMutex
-
- // env maps from an environment variable to its value.
- env = make(map[string]string)
-
- // envs contains elements of env in the form "key=value".
- envs []string
-
errZeroLengthKey = errors.New("zero length key")
errShortWrite = errors.New("i/o count too small")
)
@@ -64,46 +51,14 @@ func writeenv(key, value string) error {
return nil
}
-func copyenv() {
- fd, err := Open("/env", O_RDONLY)
- if err != nil {
- return
- }
- defer Close(fd)
- files, err := readdirnames(fd)
- if err != nil {
- return
- }
- envs = make([]string, len(files))
- i := 0
- for _, key := range files {
- v, err := readenv(key)
- if err != nil {
- continue
- }
- env[key] = v
- envs[i] = key + "=" + v
- i++
- }
-}
-
func Getenv(key string) (value string, found bool) {
if len(key) == 0 {
return "", false
}
-
- envLock.RLock()
- defer envLock.RUnlock()
-
- if v, ok := env[key]; ok {
- return v, true
- }
v, err := readenv(key)
if err != nil {
return "", false
}
- env[key] = v
- envs = append(envs, key+"="+v)
return v, true
}
@@ -111,32 +66,43 @@ func Setenv(key, value string) error {
if len(key) == 0 {
return errZeroLengthKey
}
-
- envLock.Lock()
- defer envLock.Unlock()
-
err := writeenv(key, value)
if err != nil {
return err
}
- env[key] = value
- envs = append(envs, key+"="+value)
return nil
}
func Clearenv() {
- envLock.Lock()
- defer envLock.Unlock()
-
- env = make(map[string]string)
- envs = []string{}
RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
}
+func Unsetenv(key string) error {
+ if len(key) == 0 {
+ return errZeroLengthKey
+ }
+ Remove("/env/" + key)
+ return nil
+}
+
func Environ() []string {
- envLock.RLock()
- defer envLock.RUnlock()
+ fd, err := Open("/env", O_RDONLY)
+ if err != nil {
+ return nil
+ }
+ defer Close(fd)
+ files, err := readdirnames(fd)
+ if err != nil {
+ return nil
+ }
+ ret := make([]string, 0, len(files))
- envOnce.Do(copyenv)
- return append([]string(nil), envs...)
+ for _, key := range files {
+ v, err := readenv(key)
+ if err != nil {
+ continue
+ }
+ ret = append(ret, key+"="+v)
+ }
+ return ret
}
diff --git a/src/pkg/syscall/env_unix.go b/src/syscall/env_unix.go
index ad354ed05..b5ded9c76 100644
--- a/src/pkg/syscall/env_unix.go
+++ b/src/syscall/env_unix.go
@@ -20,14 +20,18 @@ var (
// env maps from an environment variable to its first occurrence in envs.
env map[string]int
- // envs is provided by the runtime. elements are expected to be
- // of the form "key=value".
- envs []string
+ // envs is provided by the runtime. elements are expected to
+ // be of the form "key=value". An empty string means deleted
+ // (or a duplicate to be ignored).
+ envs []string = runtime_envs()
)
-// setenv_c is provided by the runtime, but is a no-op if cgo isn't
-// loaded.
+func runtime_envs() []string // in package runtime
+
+// setenv_c and unsetenv_c are provided by the runtime but are no-ops
+// if cgo isn't loaded.
func setenv_c(k, v string)
+func unsetenv_c(k string)
func copyenv() {
env = make(map[string]int)
@@ -36,7 +40,13 @@ func copyenv() {
if s[j] == '=' {
key := s[:j]
if _, ok := env[key]; !ok {
- env[key] = i
+ env[key] = i // first mention of key
+ } else {
+ // Clear duplicate keys. This permits Unsetenv to
+ // safely delete only the first item without
+ // worrying about unshadowing a later one,
+ // which might be a security problem.
+ envs[i] = ""
}
break
}
@@ -44,6 +54,20 @@ func copyenv() {
}
}
+func Unsetenv(key string) error {
+ envOnce.Do(copyenv)
+
+ envLock.Lock()
+ defer envLock.Unlock()
+
+ if i, ok := env[key]; ok {
+ envs[i] = ""
+ delete(env, key)
+ }
+ unsetenv_c(key)
+ return nil
+}
+
func Getenv(key string) (value string, found bool) {
envOnce.Do(copyenv)
if len(key) == 0 {
@@ -104,16 +128,22 @@ func Clearenv() {
envLock.Lock()
defer envLock.Unlock()
+ for k := range env {
+ unsetenv_c(k)
+ }
env = make(map[string]int)
envs = []string{}
- // TODO(bradfitz): pass through to C
}
func Environ() []string {
envOnce.Do(copyenv)
envLock.RLock()
defer envLock.RUnlock()
- a := make([]string, len(envs))
- copy(a, envs)
+ a := make([]string, 0, len(envs))
+ for _, env := range envs {
+ if env != "" {
+ a = append(a, env)
+ }
+ }
return a
}
diff --git a/src/pkg/syscall/env_windows.go b/src/syscall/env_windows.go
index 420b38724..bc21690d9 100644
--- a/src/pkg/syscall/env_windows.go
+++ b/src/syscall/env_windows.go
@@ -47,6 +47,14 @@ func Setenv(key, value string) error {
return nil
}
+func Unsetenv(key string) error {
+ keyp, err := UTF16PtrFromString(key)
+ if err != nil {
+ return err
+ }
+ return SetEnvironmentVariable(keyp, nil)
+}
+
func Clearenv() {
for _, s := range Environ() {
// Environment variables can begin with =
diff --git a/src/pkg/syscall/exec_bsd.go b/src/syscall/exec_bsd.go
index ff78f197f..ff78f197f 100644
--- a/src/pkg/syscall/exec_bsd.go
+++ b/src/syscall/exec_bsd.go
diff --git a/src/pkg/syscall/exec_linux.go b/src/syscall/exec_linux.go
index f27950f73..042c20a46 100644
--- a/src/pkg/syscall/exec_linux.go
+++ b/src/syscall/exec_linux.go
@@ -10,17 +10,27 @@ import (
"unsafe"
)
+// SysProcIDMap holds Container ID to Host ID mappings used for User Namespaces in Linux.
+// See user_namespaces(7).
+type SysProcIDMap struct {
+ ContainerID int // Container ID.
+ HostID int // Host ID.
+ Size int // Size.
+}
+
type SysProcAttr struct {
- Chroot string // Chroot.
- Credential *Credential // Credential.
- Ptrace bool // Enable tracing.
- Setsid bool // Create session.
- Setpgid bool // Set process group ID to new pid (SYSV setpgrp)
- Setctty bool // Set controlling terminal to fd Ctty (only meaningful if Setsid is set)
- Noctty bool // Detach fd 0 from controlling terminal
- Ctty int // Controlling TTY fd (Linux only)
- Pdeathsig Signal // Signal that the process will get when its parent dies (Linux only)
- Cloneflags uintptr // Flags for clone calls (Linux only)
+ Chroot string // Chroot.
+ Credential *Credential // Credential.
+ Ptrace bool // Enable tracing.
+ Setsid bool // Create session.
+ Setpgid bool // Set process group ID to new pid (SYSV setpgrp)
+ Setctty bool // Set controlling terminal to fd Ctty (only meaningful if Setsid is set)
+ Noctty bool // Detach fd 0 from controlling terminal
+ Ctty int // Controlling TTY fd (Linux only)
+ Pdeathsig Signal // Signal that the process will get when its parent dies (Linux only)
+ Cloneflags uintptr // Flags for clone calls (Linux only)
+ UidMappings []SysProcIDMap // User ID mappings for user namespaces.
+ GidMappings []SysProcIDMap // Group ID mappings for user namespaces.
}
// Implemented in runtime package.
@@ -42,8 +52,10 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
var (
r1 uintptr
err1 Errno
+ err2 Errno
nextfd int
i int
+ p [2]int
)
// Guard against side effects of shuffling fds below.
@@ -59,6 +71,14 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
}
nextfd++
+ // Allocate another pipe for parent to child communication for
+ // synchronizing writing of User ID/Group ID mappings.
+ if sys.UidMappings != nil || sys.GidMappings != nil {
+ if err := forkExecPipe(p[:]); err != nil {
+ return 0, err.(Errno)
+ }
+ }
+
// About to call fork.
// No more allocation or calls of non-assembly functions.
runtime_BeforeFork()
@@ -71,11 +91,42 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
if r1 != 0 {
// parent; return PID
runtime_AfterFork()
- return int(r1), 0
+ pid = int(r1)
+
+ if sys.UidMappings != nil || sys.GidMappings != nil {
+ Close(p[0])
+ err := writeUidGidMappings(pid, sys)
+ if err != nil {
+ err2 = err.(Errno)
+ }
+ RawSyscall(SYS_WRITE, uintptr(p[1]), uintptr(unsafe.Pointer(&err2)), unsafe.Sizeof(err2))
+ Close(p[1])
+ }
+
+ return pid, 0
}
// Fork succeeded, now in child.
+ // Wait for User ID/Group ID mappings to be written.
+ if sys.UidMappings != nil || sys.GidMappings != nil {
+ if _, _, err1 = RawSyscall(SYS_CLOSE, uintptr(p[1]), 0, 0); err1 != 0 {
+ goto childerror
+ }
+ r1, _, err1 = RawSyscall(SYS_READ, uintptr(p[0]), uintptr(unsafe.Pointer(&err2)), unsafe.Sizeof(err2))
+ if err1 != 0 {
+ goto childerror
+ }
+ if r1 != unsafe.Sizeof(err2) {
+ err1 = EINVAL
+ goto childerror
+ }
+ if err2 != 0 {
+ err1 = err2
+ goto childerror
+ }
+ }
+
// Parent death signal
if sys.Pdeathsig != 0 {
_, _, err1 = RawSyscall6(SYS_PRCTL, PR_SET_PDEATHSIG, uintptr(sys.Pdeathsig), 0, 0, 0, 0)
@@ -260,3 +311,53 @@ func forkExecPipe(p []int) (err error) {
}
return
}
+
+// writeIDMappings writes the user namespace User ID or Group ID mappings to the specified path.
+func writeIDMappings(path string, idMap []SysProcIDMap) error {
+ fd, err := Open(path, O_RDWR, 0)
+ if err != nil {
+ return err
+ }
+
+ data := ""
+ for _, im := range idMap {
+ data = data + itoa(im.ContainerID) + " " + itoa(im.HostID) + " " + itoa(im.Size) + "\n"
+ }
+
+ bytes, err := ByteSliceFromString(data)
+ if err != nil {
+ Close(fd)
+ return err
+ }
+
+ if _, err := Write(fd, bytes); err != nil {
+ Close(fd)
+ return err
+ }
+
+ if err := Close(fd); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// writeUidGidMappings writes User ID and Group ID mappings for user namespaces
+// for a process and it is called from the parent process.
+func writeUidGidMappings(pid int, sys *SysProcAttr) error {
+ if sys.UidMappings != nil {
+ uidf := "/proc/" + itoa(pid) + "/uid_map"
+ if err := writeIDMappings(uidf, sys.UidMappings); err != nil {
+ return err
+ }
+ }
+
+ if sys.GidMappings != nil {
+ gidf := "/proc/" + itoa(pid) + "/gid_map"
+ if err := writeIDMappings(gidf, sys.GidMappings); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/src/pkg/syscall/exec_plan9.go b/src/syscall/exec_plan9.go
index 45ee542bb..45ee542bb 100644
--- a/src/pkg/syscall/exec_plan9.go
+++ b/src/syscall/exec_plan9.go
diff --git a/src/pkg/syscall/exec_solaris.go b/src/syscall/exec_solaris.go
index 97de6ca00..97de6ca00 100644
--- a/src/pkg/syscall/exec_solaris.go
+++ b/src/syscall/exec_solaris.go
diff --git a/src/pkg/syscall/exec_unix.go b/src/syscall/exec_unix.go
index 890bfdc22..890bfdc22 100644
--- a/src/pkg/syscall/exec_unix.go
+++ b/src/syscall/exec_unix.go
diff --git a/src/pkg/syscall/exec_windows.go b/src/syscall/exec_windows.go
index 82abc0715..936aeb577 100644
--- a/src/pkg/syscall/exec_windows.go
+++ b/src/syscall/exec_windows.go
@@ -129,9 +129,8 @@ func SetNonblock(fd Handle, nonblocking bool) (err error) {
return nil
}
-// getFullPath retrieves the full path of the specified file.
-// Just a wrapper for Windows GetFullPathName api.
-func getFullPath(name string) (path string, err error) {
+// FullPath retrieves the full path of the specified file.
+func FullPath(name string) (path string, err error) {
p, err := UTF16PtrFromString(name)
if err != nil {
return "", err
@@ -160,7 +159,7 @@ func isSlash(c uint8) bool {
}
func normalizeDir(dir string) (name string, err error) {
- ndir, err := getFullPath(dir)
+ ndir, err := FullPath(dir)
if err != nil {
return "", err
}
@@ -199,9 +198,9 @@ func joinExeDirAndFName(dir, p string) (name string, err error) {
return "", err
}
if volToUpper(int(p[0])) == volToUpper(int(d[0])) {
- return getFullPath(d + "\\" + p[2:])
+ return FullPath(d + "\\" + p[2:])
} else {
- return getFullPath(p)
+ return FullPath(p)
}
}
} else {
@@ -211,9 +210,9 @@ func joinExeDirAndFName(dir, p string) (name string, err error) {
return "", err
}
if isSlash(p[0]) {
- return getFullPath(d[:2] + p)
+ return FullPath(d[:2] + p)
} else {
- return getFullPath(d + "\\" + p)
+ return FullPath(d + "\\" + p)
}
}
// we shouldn't be here
diff --git a/src/syscall/export_test.go b/src/syscall/export_test.go
new file mode 100644
index 000000000..c9774622c
--- /dev/null
+++ b/src/syscall/export_test.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 syscall
+
+var Itoa = itoa
diff --git a/src/pkg/syscall/fd_nacl.go b/src/syscall/fd_nacl.go
index 74324142a..74324142a 100644
--- a/src/pkg/syscall/fd_nacl.go
+++ b/src/syscall/fd_nacl.go
diff --git a/src/pkg/syscall/flock.go b/src/syscall/flock.go
index 62736ae9d..62736ae9d 100644
--- a/src/pkg/syscall/flock.go
+++ b/src/syscall/flock.go
diff --git a/src/pkg/syscall/flock_linux_32bit.go b/src/syscall/flock_linux_32bit.go
index 500a97344..500a97344 100644
--- a/src/pkg/syscall/flock_linux_32bit.go
+++ b/src/syscall/flock_linux_32bit.go
diff --git a/src/pkg/syscall/fs_nacl.go b/src/syscall/fs_nacl.go
index ac9239483..6e6ce2ab7 100644
--- a/src/pkg/syscall/fs_nacl.go
+++ b/src/syscall/fs_nacl.go
@@ -79,8 +79,13 @@ func newFsys() *fsys {
}
var fs = newFsys()
+var fsinit = func() {}
func init() {
+ // do not trigger loading of zipped file system here
+ oldFsinit := fsinit
+ defer func() { fsinit = oldFsinit }()
+ fsinit = func() {}
Mkdir("/dev", 0555)
Mkdir("/tmp", 0777)
mkdev("/dev/null", 0666, openNull)
@@ -93,7 +98,7 @@ func init() {
func chdirEnv() {
pwd, ok := Getenv("NACLPWD")
if ok {
- Chdir(pwd)
+ chdir(pwd)
}
}
@@ -181,7 +186,7 @@ func skipelem(path string) (elem, rest string) {
// namei translates a file system path name into an inode.
// If parent is false, the returned ip corresponds to the given name, and elem is the empty string.
-// If parent is false, the walk stops at the next-to-last element in the name,
+// If parent is true, the walk stops at the next-to-last element in the name,
// so that ip is the parent directory and elem is the final element in the path.
func (fs *fsys) namei(path string, parent bool) (ip *inode, elem string, err error) {
// Reject NUL in name.
@@ -465,6 +470,7 @@ func (f *fsysFile) pwriteLocked(b []byte, offset int64) (int, error) {
// Standard Unix system calls.
func Open(path string, openmode int, perm uint32) (fd int, err error) {
+ fsinit()
fs.mu.Lock()
defer fs.mu.Unlock()
f, err := fs.open(path, openmode, perm&0777|S_IFREG)
@@ -487,6 +493,7 @@ func Getcwd(buf []byte) (n int, err error) {
}
func Stat(path string, st *Stat_t) error {
+ fsinit()
fs.mu.Lock()
defer fs.mu.Unlock()
ip, _, err := fs.namei(path, false)
@@ -502,6 +509,7 @@ func Lstat(path string, st *Stat_t) error {
}
func unlink(path string, isdir bool) error {
+ fsinit()
fs.mu.Lock()
defer fs.mu.Unlock()
dp, elem, err := fs.namei(path, true)
@@ -543,6 +551,7 @@ func Rmdir(path string) error {
}
func Chmod(path string, mode uint32) error {
+ fsinit()
fs.mu.Lock()
defer fs.mu.Unlock()
ip, _, err := fs.namei(path, false)
@@ -565,6 +574,7 @@ func Fchmod(fd int, mode uint32) error {
}
func Chown(path string, uid, gid int) error {
+ fsinit()
fs.mu.Lock()
defer fs.mu.Unlock()
ip, _, err := fs.namei(path, false)
@@ -598,6 +608,7 @@ func UtimesNano(path string, ts []Timespec) error {
if len(ts) != 2 {
return EINVAL
}
+ fsinit()
fs.mu.Lock()
defer fs.mu.Unlock()
ip, _, err := fs.namei(path, false)
@@ -612,6 +623,7 @@ func UtimesNano(path string, ts []Timespec) error {
}
func Link(path, link string) error {
+ fsinit()
ip, _, err := fs.namei(path, false)
if err != nil {
return err
@@ -628,6 +640,7 @@ func Link(path, link string) error {
}
func Rename(from, to string) error {
+ fsinit()
fdp, felem, err := fs.namei(from, true)
if err != nil {
return err
@@ -664,6 +677,7 @@ func (fs *fsys) truncate(ip *inode, length int64) error {
}
func Truncate(path string, length int64) error {
+ fsinit()
fs.mu.Lock()
defer fs.mu.Unlock()
ip, _, err := fs.namei(path, false)
@@ -684,6 +698,11 @@ func Ftruncate(fd int, length int64) error {
}
func Chdir(path string) error {
+ fsinit()
+ return chdir(path)
+}
+
+func chdir(path string) error {
fs.mu.Lock()
defer fs.mu.Unlock()
ip, _, err := fs.namei(path, false)
@@ -723,8 +742,6 @@ func Fsync(fd int) error {
// Special devices.
func mkdev(path string, mode uint32, open func() (devFile, error)) error {
- fs.mu.Lock()
- fs.mu.Unlock()
f, err := fs.open(path, O_CREATE|O_RDONLY|O_EXCL, S_IFCHR|mode)
if err != nil {
return err
@@ -801,6 +818,12 @@ func create(name string, mode uint32, sec int64, data []byte) error {
fs.mu.Unlock()
f, err := fs.open(name, O_CREATE|O_EXCL, mode)
if err != nil {
+ if mode&S_IFMT == S_IFDIR {
+ ip, _, err := fs.namei(name, false)
+ if err == nil && (ip.Mode&S_IFMT) == S_IFDIR {
+ return nil // directory already exists
+ }
+ }
return err
}
ip := f.(*fsysFile).inode
diff --git a/src/pkg/syscall/lsf_linux.go b/src/syscall/lsf_linux.go
index ee07fea3f..ee07fea3f 100644
--- a/src/pkg/syscall/lsf_linux.go
+++ b/src/syscall/lsf_linux.go
diff --git a/src/pkg/syscall/mkall.sh b/src/syscall/mkall.sh
index 886db133c..9cb82a608 100755
--- a/src/pkg/syscall/mkall.sh
+++ b/src/syscall/mkall.sh
@@ -244,7 +244,7 @@ esac
case "$GOOS" in
windows)
echo "GOOS= GOARCH= go build mksyscall_windows.go"
- echo "./mksyscall_windows syscall_windows.go security_windows.go syscall_$GOOSARCH.go |gofmt >zsyscall_$GOOSARCH.go"
+ echo "./mksyscall_windows syscall_windows.go security_windows.go |gofmt >zsyscall_windows.go"
echo "rm -f ./mksyscall_windows"
;;
*)
diff --git a/src/syscall/mkall_windows.bat b/src/syscall/mkall_windows.bat
new file mode 100644
index 000000000..0f3a98b72
--- /dev/null
+++ b/src/syscall/mkall_windows.bat
@@ -0,0 +1,15 @@
+:: 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.
+@echo off
+
+if exist mkall.sh goto dirok
+echo mkall_windows.bat must be run from src\syscall directory
+goto :end
+:dirok
+
+go build mksyscall_windows.go
+.\mksyscall_windows syscall_windows.go security_windows.go |gofmt >zsyscall_windows.go
+del mksyscall_windows.exe
+
+:end
diff --git a/src/pkg/syscall/mkerrors.sh b/src/syscall/mkerrors.sh
index cf0afe0bd..cf0afe0bd 100755
--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/syscall/mkerrors.sh
diff --git a/src/pkg/syscall/mksyscall.pl b/src/syscall/mksyscall.pl
index 6d35fa689..dff913838 100755
--- a/src/pkg/syscall/mksyscall.pl
+++ b/src/syscall/mksyscall.pl
@@ -132,6 +132,7 @@ while(<>) {
# Prepare arguments to Syscall.
my @args = ();
+ my @uses = ();
my $n = 0;
foreach my $p (@in) {
my ($name, $type) = parseparam($p);
@@ -142,12 +143,14 @@ while(<>) {
$text .= "\t_p$n, $errvar = BytePtrFromString($name)\n";
$text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
push @args, "uintptr(unsafe.Pointer(_p$n))";
+ push @uses, "use(unsafe.Pointer(_p$n))";
$n++;
} elsif($type eq "string") {
print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
$text .= "\tvar _p$n *byte\n";
$text .= "\t_p$n, _ = BytePtrFromString($name)\n";
push @args, "uintptr(unsafe.Pointer(_p$n))";
+ push @uses, "use(unsafe.Pointer(_p$n))";
$n++;
} elsif($type =~ /^\[\](.*)/) {
# Convert slice into pointer, length.
@@ -278,6 +281,9 @@ while(<>) {
} else {
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
}
+ foreach my $use (@uses) {
+ $text .= "\t$use\n";
+ }
$text .= $body;
if ($plan9 && $ret[2] eq "e1") {
diff --git a/src/pkg/syscall/mksyscall_solaris.pl b/src/syscall/mksyscall_solaris.pl
index 130d043d9..e72a4d11a 100755
--- a/src/pkg/syscall/mksyscall_solaris.pl
+++ b/src/syscall/mksyscall_solaris.pl
@@ -136,8 +136,8 @@ while(<>) {
# Prepare arguments to Syscall.
my @args = ();
+ my @uses = ();
my $n = 0;
- my @pin= ();
foreach my $p (@in) {
my ($name, $type) = parseparam($p);
if($type =~ /^\*/) {
@@ -147,12 +147,14 @@ while(<>) {
$text .= "\t_p$n, $errvar = $strconvfunc($name)\n";
$text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
push @args, "uintptr(unsafe.Pointer(_p$n))";
+ push @uses, "use(unsafe.Pointer(_p$n))";
$n++;
} elsif($type eq "string") {
print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
$text .= "\tvar _p$n $strconvtype\n";
$text .= "\t_p$n, _ = $strconvfunc($name)\n";
push @args, "uintptr(unsafe.Pointer(_p$n))";
+ push @uses, "use(unsafe.Pointer(_p$n))";
$n++;
} elsif($type =~ /^\[\](.*)/) {
# Convert slice into pointer, length.
@@ -176,7 +178,6 @@ while(<>) {
} else {
push @args, "uintptr($name)";
}
- push @pin, sprintf "\"%s=\", %s, ", $name, $name;
}
my $nargs = @args;
@@ -240,6 +241,9 @@ while(<>) {
} else {
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
}
+ foreach my $use (@uses) {
+ $text .= "\t$use\n";
+ }
$text .= $body;
if ($do_errno) {
diff --git a/src/pkg/syscall/mksyscall_windows.go b/src/syscall/mksyscall_windows.go
index 4225588de..316e88d7e 100644
--- a/src/pkg/syscall/mksyscall_windows.go
+++ b/src/syscall/mksyscall_windows.go
@@ -47,6 +47,8 @@ import (
"errors"
"flag"
"fmt"
+ "go/parser"
+ "go/token"
"io"
"log"
"os"
@@ -61,6 +63,19 @@ func trim(s string) string {
return strings.Trim(s, " \t")
}
+var packageName string
+
+func packagename() string {
+ return packageName
+}
+
+func syscalldot() string {
+ if packageName == "syscall" {
+ return ""
+ }
+ return "syscall."
+}
+
// Param is function parameter
type Param struct {
Name string
@@ -123,8 +138,6 @@ func (p *Param) StringTmpVarCode() string {
// TmpVarCode returns source code for temp variable.
func (p *Param) TmpVarCode() string {
switch {
- case p.Type == "string":
- return p.StringTmpVarCode()
case p.Type == "bool":
return p.BoolTmpVarCode()
case strings.HasPrefix(p.Type, "[]"):
@@ -134,19 +147,26 @@ func (p *Param) TmpVarCode() string {
}
}
+// TmpVarHelperCode returns source code for helper's temp variable.
+func (p *Param) TmpVarHelperCode() string {
+ if p.Type != "string" {
+ return ""
+ }
+ return p.StringTmpVarCode()
+}
+
// SyscallArgList returns source code fragments representing p parameter
// in syscall. Slices are translated into 2 syscall parameters: pointer to
// the first element and length.
func (p *Param) SyscallArgList() []string {
+ t := p.HelperType()
var s string
switch {
- case p.Type[0] == '*':
+ case t[0] == '*':
s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name)
- case p.Type == "string":
- s = fmt.Sprintf("unsafe.Pointer(%s)", p.tmpVar())
- case p.Type == "bool":
+ case t == "bool":
s = p.tmpVar()
- case strings.HasPrefix(p.Type, "[]"):
+ case strings.HasPrefix(t, "[]"):
return []string{
fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()),
fmt.Sprintf("uintptr(len(%s))", p.Name),
@@ -162,6 +182,14 @@ func (p *Param) IsError() bool {
return p.Name == "err" && p.Type == "error"
}
+// HelperType returns type of parameter p used in helper function.
+func (p *Param) HelperType() string {
+ if p.Type == "string" {
+ return p.fn.StrconvType()
+ }
+ return p.Type
+}
+
// join concatenates parameters ps into a string with sep separator.
// Each parameter is converted into string by applying fn to it
// before conversion.
@@ -243,20 +271,20 @@ func (r *Rets) useLongHandleErrorCode(retvar string) string {
if e1 != 0 {
err = error(e1)
} else {
- err = EINVAL
+ err = %sEINVAL
}
}`
cond := retvar + " == 0"
if r.FailCond != "" {
cond = strings.Replace(r.FailCond, "failretval", retvar, 1)
}
- return fmt.Sprintf(code, cond)
+ return fmt.Sprintf(code, cond, syscalldot())
}
// SetErrorCode returns source code that sets return parameters.
func (r *Rets) SetErrorCode() string {
const code = `if r0 != 0 {
- %s = Errno(r0)
+ %s = %sErrno(r0)
}`
if r.Name == "" && !r.ReturnsError {
return ""
@@ -265,12 +293,15 @@ func (r *Rets) SetErrorCode() string {
return r.useLongHandleErrorCode("r1")
}
if r.Type == "error" {
- return fmt.Sprintf(code, r.Name)
+ return fmt.Sprintf(code, r.Name, syscalldot())
}
s := ""
- if r.Type[0] == '*' {
+ switch {
+ case r.Type[0] == '*':
s = fmt.Sprintf("%s = (%s)(unsafe.Pointer(r0))", r.Name, r.Type)
- } else {
+ case r.Type == "bool":
+ s = fmt.Sprintf("%s = r0 != 0", r.Name)
+ default:
s = fmt.Sprintf("%s = %s(r0)", r.Name, r.Type)
}
if !r.ReturnsError {
@@ -436,6 +467,11 @@ func (f *Fn) ParamList() string {
return join(f.Params, func(p *Param) string { return p.Name + " " + p.Type }, ", ")
}
+// HelperParamList returns source code for helper function f parameters.
+func (f *Fn) HelperParamList() string {
+ return join(f.Params, func(p *Param) string { return p.Name + " " + p.HelperType() }, ", ")
+}
+
// ParamPrintList returns source code of trace printing part correspondent
// to syscall input parameters.
func (f *Fn) ParamPrintList() string {
@@ -475,9 +511,9 @@ func (f *Fn) SyscallParamCount() int {
func (f *Fn) Syscall() string {
c := f.SyscallParamCount()
if c == 3 {
- return "Syscall"
+ return syscalldot() + "Syscall"
}
- return "Syscall" + strconv.Itoa(c)
+ return syscalldot() + "Syscall" + strconv.Itoa(c)
}
// SyscallParamList returns source code for SyscallX parameters for function f.
@@ -492,6 +528,19 @@ func (f *Fn) SyscallParamList() string {
return strings.Join(a, ", ")
}
+// HelperCallParamList returns source code of call into function f helper.
+func (f *Fn) HelperCallParamList() string {
+ a := make([]string, 0, len(f.Params))
+ for _, p := range f.Params {
+ s := p.Name
+ if p.Type == "string" {
+ s = p.tmpVar()
+ }
+ a = append(a, s)
+ }
+ return strings.Join(a, ", ")
+}
+
// IsUTF16 is true, if f is W (utf16) function. It is false
// for all A (ascii) functions.
func (f *Fn) IsUTF16() bool {
@@ -502,9 +551,9 @@ func (f *Fn) IsUTF16() bool {
// StrconvFunc returns name of Go string to OS string function for f.
func (f *Fn) StrconvFunc() string {
if f.IsUTF16() {
- return "UTF16PtrFromString"
+ return syscalldot() + "UTF16PtrFromString"
}
- return "BytePtrFromString"
+ return syscalldot() + "BytePtrFromString"
}
// StrconvType returns Go type name used for OS string for f.
@@ -515,6 +564,25 @@ func (f *Fn) StrconvType() string {
return "*byte"
}
+// HasStringParam is true, if f has at least one string parameter.
+// Otherwise it is false.
+func (f *Fn) HasStringParam() bool {
+ for _, p := range f.Params {
+ if p.Type == "string" {
+ return true
+ }
+ }
+ return false
+}
+
+// HelperName returns name of function f helper.
+func (f *Fn) HelperName() string {
+ if !f.HasStringParam() {
+ return f.Name
+ }
+ return "_" + f.Name
+}
+
// Source files and functions.
type Source struct {
Funcs []*Fn
@@ -582,12 +650,29 @@ func (src *Source) ParseFile(path string) error {
return err
}
src.Files = append(src.Files, path)
+
+ // get package name
+ fset := token.NewFileSet()
+ _, err = file.Seek(0, 0)
+ if err != nil {
+ return err
+ }
+ pkg, err := parser.ParseFile(fset, "", file, parser.PackageClauseOnly)
+ if err != nil {
+ return err
+ }
+ packageName = pkg.Name.Name
+
return nil
}
// Generate output source file from a source set src.
func (src *Source) Generate(w io.Writer) error {
- t := template.Must(template.New("main").Parse(srcTemplate))
+ funcMap := template.FuncMap{
+ "syscalldot": syscalldot,
+ "packagename": packagename,
+ }
+ t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate))
err := t.Execute(w, src)
if err != nil {
return errors.New("Failed to execute template: " + err.Error())
@@ -623,34 +708,46 @@ const srcTemplate = `
{{define "main"}}// go build mksyscall_windows.go && ./mksyscall_windows{{range .Files}} {{.}}{{end}}
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
-package syscall
+package {{packagename}}
-import "unsafe"
+import "unsafe"{{if syscalldot}}
+import "syscall"{{end}}
var (
{{template "dlls" .}}
{{template "funcnames" .}})
-{{range .Funcs}}{{template "funcbody" .}}{{end}}
+{{range .Funcs}}{{if .HasStringParam}}{{template "helperbody" .}}{{end}}{{template "funcbody" .}}{{end}}
{{end}}
{{/* help functions */}}
-{{define "dlls"}}{{range .DLLs}} mod{{.}} = NewLazyDLL("{{.}}.dll")
+{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{syscalldot}}NewLazyDLL("{{.}}.dll")
{{end}}{{end}}
{{define "funcnames"}}{{range .Funcs}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}")
{{end}}{{end}}
+{{define "helperbody"}}
+func {{.Name}}({{.ParamList}}) {{template "results" .}}{
+{{template "helpertmpvars" .}} return {{.HelperName}}({{.HelperCallParamList}})
+}
+{{end}}
+
{{define "funcbody"}}
-func {{.Name}}({{.ParamList}}) {{if .Rets.List}}{{.Rets.List}} {{end}}{
+func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{
{{template "tmpvars" .}} {{template "syscall" .}}
{{template "seterror" .}}{{template "printtrace" .}} return
}
{{end}}
+{{define "helpertmpvars"}}{{range .Params}}{{if .TmpVarHelperCode}} {{.TmpVarHelperCode}}
+{{end}}{{end}}{{end}}
+
{{define "tmpvars"}}{{range .Params}}{{if .TmpVarCode}} {{.TmpVarCode}}
{{end}}{{end}}{{end}}
+{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}}
+
{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}}
{{define "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}}
diff --git a/src/pkg/syscall/mksysctl_openbsd.pl b/src/syscall/mksysctl_openbsd.pl
index c2e2ea925..c2e2ea925 100755
--- a/src/pkg/syscall/mksysctl_openbsd.pl
+++ b/src/syscall/mksysctl_openbsd.pl
diff --git a/src/pkg/syscall/mksysnum_darwin.pl b/src/syscall/mksysnum_darwin.pl
index e3470435d..e3470435d 100755
--- a/src/pkg/syscall/mksysnum_darwin.pl
+++ b/src/syscall/mksysnum_darwin.pl
diff --git a/src/pkg/syscall/mksysnum_dragonfly.pl b/src/syscall/mksysnum_dragonfly.pl
index 3eba3ab3d..3eba3ab3d 100755
--- a/src/pkg/syscall/mksysnum_dragonfly.pl
+++ b/src/syscall/mksysnum_dragonfly.pl
diff --git a/src/pkg/syscall/mksysnum_freebsd.pl b/src/syscall/mksysnum_freebsd.pl
index cd675780b..cd675780b 100755
--- a/src/pkg/syscall/mksysnum_freebsd.pl
+++ b/src/syscall/mksysnum_freebsd.pl
diff --git a/src/pkg/syscall/mksysnum_linux.pl b/src/syscall/mksysnum_linux.pl
index c7e5cf73a..c7e5cf73a 100755
--- a/src/pkg/syscall/mksysnum_linux.pl
+++ b/src/syscall/mksysnum_linux.pl
diff --git a/src/pkg/syscall/mksysnum_netbsd.pl b/src/syscall/mksysnum_netbsd.pl
index f1534ed58..f1534ed58 100755
--- a/src/pkg/syscall/mksysnum_netbsd.pl
+++ b/src/syscall/mksysnum_netbsd.pl
diff --git a/src/pkg/syscall/mksysnum_openbsd.pl b/src/syscall/mksysnum_openbsd.pl
index ad1ccc12a..ad1ccc12a 100755
--- a/src/pkg/syscall/mksysnum_openbsd.pl
+++ b/src/syscall/mksysnum_openbsd.pl
diff --git a/src/pkg/syscall/mksysnum_plan9.sh b/src/syscall/mksysnum_plan9.sh
index fc619f090..fc619f090 100755
--- a/src/pkg/syscall/mksysnum_plan9.sh
+++ b/src/syscall/mksysnum_plan9.sh
diff --git a/src/pkg/syscall/mmap_unix_test.go b/src/syscall/mmap_unix_test.go
index 01f778302..01f778302 100644
--- a/src/pkg/syscall/mmap_unix_test.go
+++ b/src/syscall/mmap_unix_test.go
diff --git a/src/pkg/syscall/net_nacl.go b/src/syscall/net_nacl.go
index b9488f48d..b5cb53030 100644
--- a/src/pkg/syscall/net_nacl.go
+++ b/src/syscall/net_nacl.go
@@ -18,11 +18,12 @@ import (
// Really for use by package time, but we cannot import time here.
type runtimeTimer struct {
- i int32
+ i int
when int64
period int64
- f func(int64, interface{}) // NOTE: must not be closure
+ f func(interface{}, uintptr) // NOTE: must not be closure
arg interface{}
+ seq uintptr
}
func startTimer(*runtimeTimer)
@@ -49,7 +50,7 @@ func (t *timer) stop() {
stopTimer(&t.r)
}
-func timerExpired(now int64, i interface{}) {
+func timerExpired(i interface{}, seq uintptr) {
t := i.(*timer)
go func() {
t.q.Lock()
diff --git a/src/pkg/syscall/netlink_linux.go b/src/syscall/netlink_linux.go
index 49550ea2f..1b73dce82 100644
--- a/src/pkg/syscall/netlink_linux.go
+++ b/src/syscall/netlink_linux.go
@@ -64,9 +64,10 @@ func NetlinkRIB(proto, family int) ([]byte, error) {
return nil, err
}
var tab []byte
+ rbNew := make([]byte, Getpagesize())
done:
for {
- rb := make([]byte, Getpagesize())
+ rb := rbNew
nr, _, err := Recvfrom(s, rb, 0)
if err != nil {
return nil, err
diff --git a/src/pkg/syscall/race.go b/src/syscall/race.go
index e69c1119a..e69c1119a 100644
--- a/src/pkg/syscall/race.go
+++ b/src/syscall/race.go
diff --git a/src/pkg/syscall/race0.go b/src/syscall/race0.go
index b02f882fd..b02f882fd 100644
--- a/src/pkg/syscall/race0.go
+++ b/src/syscall/race0.go
diff --git a/src/pkg/syscall/route_bsd.go b/src/syscall/route_bsd.go
index 48af58745..1dabe4253 100644
--- a/src/pkg/syscall/route_bsd.go
+++ b/src/syscall/route_bsd.go
@@ -153,7 +153,7 @@ func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
// RTAX_NETMASK socket address on the FreeBSD kernel.
preferredFamily := uint8(AF_UNSPEC)
for i := uint(0); i < RTAX_MAX; i++ {
- if m.Header.Addrs&rtaIfaMask&(1<<i) == 0 {
+ if m.Header.Addrs&(1<<i) == 0 {
continue
}
rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
diff --git a/src/pkg/syscall/route_darwin.go b/src/syscall/route_darwin.go
index ad2790723..ad2790723 100644
--- a/src/pkg/syscall/route_darwin.go
+++ b/src/syscall/route_darwin.go
diff --git a/src/pkg/syscall/route_dragonfly.go b/src/syscall/route_dragonfly.go
index 79190d2b0..79190d2b0 100644
--- a/src/pkg/syscall/route_dragonfly.go
+++ b/src/syscall/route_dragonfly.go
diff --git a/src/pkg/syscall/route_freebsd.go b/src/syscall/route_freebsd.go
index 15897b1ac..15897b1ac 100644
--- a/src/pkg/syscall/route_freebsd.go
+++ b/src/syscall/route_freebsd.go
diff --git a/src/pkg/syscall/route_freebsd_32bit.go b/src/syscall/route_freebsd_32bit.go
index 93efdddb3..93efdddb3 100644
--- a/src/pkg/syscall/route_freebsd_32bit.go
+++ b/src/syscall/route_freebsd_32bit.go
diff --git a/src/pkg/syscall/route_freebsd_64bit.go b/src/syscall/route_freebsd_64bit.go
index 9377f2fed..9377f2fed 100644
--- a/src/pkg/syscall/route_freebsd_64bit.go
+++ b/src/syscall/route_freebsd_64bit.go
diff --git a/src/pkg/syscall/route_netbsd.go b/src/syscall/route_netbsd.go
index 9883aebaf..9883aebaf 100644
--- a/src/pkg/syscall/route_netbsd.go
+++ b/src/syscall/route_netbsd.go
diff --git a/src/pkg/syscall/route_openbsd.go b/src/syscall/route_openbsd.go
index 19f902db7..19f902db7 100644
--- a/src/pkg/syscall/route_openbsd.go
+++ b/src/syscall/route_openbsd.go
diff --git a/src/pkg/syscall/security_windows.go b/src/syscall/security_windows.go
index b22ecf578..b22ecf578 100644
--- a/src/pkg/syscall/security_windows.go
+++ b/src/syscall/security_windows.go
diff --git a/src/pkg/syscall/so_solaris.go b/src/syscall/so_solaris.go
index 659cd67c1..8b1980fb4 100644
--- a/src/pkg/syscall/so_solaris.go
+++ b/src/syscall/so_solaris.go
@@ -19,7 +19,7 @@ type soError struct {
func (e *soError) Error() string { return e.Msg }
-// Implemented in ../runtime/syscall_solaris.goc.
+// Implemented in asm_solaris_amd64.s.
func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func dlclose(handle uintptr) (err Errno)
@@ -39,6 +39,7 @@ func loadSO(name string) (*so, error) {
return nil, err
}
h, e := dlopen(namep, 1) // RTLD_LAZY
+ use(unsafe.Pointer(namep))
if e != 0 {
return nil, &soError{
Err: e,
@@ -70,6 +71,7 @@ func (d *so) FindProc(name string) (*proc, error) {
return nil, err
}
a, _ := dlsym(uintptr(d.Handle), namep)
+ use(unsafe.Pointer(namep))
if a == 0 {
return nil, &soError{
Err: ENOSYS,
diff --git a/src/pkg/syscall/sockcmsg_linux.go b/src/syscall/sockcmsg_linux.go
index a2e26a1f4..a2e26a1f4 100644
--- a/src/pkg/syscall/sockcmsg_linux.go
+++ b/src/syscall/sockcmsg_linux.go
diff --git a/src/pkg/syscall/sockcmsg_unix.go b/src/syscall/sockcmsg_unix.go
index 045a012c0..045a012c0 100644
--- a/src/pkg/syscall/sockcmsg_unix.go
+++ b/src/syscall/sockcmsg_unix.go
diff --git a/src/pkg/syscall/srpc_nacl.go b/src/syscall/srpc_nacl.go
index dd07373d1..dd07373d1 100644
--- a/src/pkg/syscall/srpc_nacl.go
+++ b/src/syscall/srpc_nacl.go
diff --git a/src/pkg/syscall/str.go b/src/syscall/str.go
index 0fce842e8..2ddf04b22 100644
--- a/src/pkg/syscall/str.go
+++ b/src/syscall/str.go
@@ -6,8 +6,12 @@ package syscall
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
if val < 0 {
- return "-" + itoa(-val)
+ return "-" + uitoa(uint(-val))
}
+ return uitoa(uint(val))
+}
+
+func uitoa(val uint) string {
var buf [32]byte // big enough for int64
i := len(buf) - 1
for val >= 10 {
diff --git a/src/pkg/syscall/syscall.go b/src/syscall/syscall.go
index f7473fd5a..1f209ecd5 100644
--- a/src/pkg/syscall/syscall.go
+++ b/src/syscall/syscall.go
@@ -17,8 +17,17 @@
// These calls return err == nil to indicate success; otherwise
// err is an operating system error describing the failure.
// On most systems, that error has type syscall.Errno.
+//
+// NOTE: This package is locked down. Code outside the standard
+// Go repository should be migrated to use the corresponding
+// package in the go.sys subrepository. That is also where updates
+// required by new systems or versions should be applied.
+// See https://golang.org/s/go1.4-syscall for more information.
+//
package syscall
+import "unsafe"
+
// StringByteSlice is deprecated. Use ByteSliceFromString instead.
// If s contains a NUL byte this function panics instead of
// returning an error.
@@ -79,3 +88,8 @@ func (ts *Timespec) Nano() int64 {
func (tv *Timeval) Nano() int64 {
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
}
+
+// 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.
+//go:noescape
+func use(p unsafe.Pointer)
diff --git a/src/pkg/syscall/syscall_bsd.go b/src/syscall/syscall_bsd.go
index b042841a5..2556fa874 100644
--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/syscall/syscall_bsd.go
@@ -68,7 +68,40 @@ func ReadDirent(fd int, buf []byte) (n int, err error) {
// actual system call is getdirentries64, 64 is a good guess.
// TODO(rsc): Can we use a single global basep for all calls?
var base = (*uintptr)(unsafe.Pointer(new(uint64)))
- return Getdirentries(fd, buf, base)
+ n, err = Getdirentries(fd, buf, base)
+
+ // On OS X 10.10 Yosemite, if you have a directory that can be returned
+ // in a single getdirentries64 call (for example, a directory with one file),
+ // and you read from the directory at EOF twice, you get EOF both times:
+ // fd = open("dir")
+ // getdirentries64(fd) // returns data
+ // getdirentries64(fd) // returns 0 (EOF)
+ // getdirentries64(fd) // returns 0 (EOF)
+ //
+ // But if you remove the file in the middle between the two calls, the
+ // second call returns an error instead.
+ // fd = open("dir")
+ // getdirentries64(fd) // returns data
+ // getdirentries64(fd) // returns 0 (EOF)
+ // remove("dir/file")
+ // getdirentries64(fd) // returns ENOENT/EINVAL
+ //
+ // Whether you get ENOENT or EINVAL depends on exactly what was
+ // in the directory. It is deterministic, just data-dependent.
+ //
+ // This only happens in small directories. A directory containing more data
+ // than fits in a 4k getdirentries64 call will return EOF correctly.
+ // (It's not clear if the criteria is that the directory be split across multiple
+ // getdirentries64 calls or that it be split across multiple file system blocks.)
+ //
+ // We could change package os to avoid the second read at EOF,
+ // and maybe we should, but that's a bit involved.
+ // For now, treat the EINVAL/ENOENT as EOF.
+ if runtime.GOOS == "darwin" && (err == EINVAL || err == ENOENT) {
+ err = nil
+ }
+
+ return
}
// Wait status is 7 bits at bottom, either 0 (exited),
@@ -498,6 +531,7 @@ func SysctlUint32(name string) (value uint32, err error) {
}
//sys utimes(path string, timeval *[2]Timeval) (err error)
+
func Utimes(path string, tv []Timeval) (err error) {
if len(tv) != 2 {
return EINVAL
@@ -521,6 +555,7 @@ func UtimesNano(path string, ts []Timespec) error {
}
//sys futimes(fd int, timeval *[2]Timeval) (err error)
+
func Futimes(fd int, tv []Timeval) (err error) {
if len(tv) != 2 {
return EINVAL
diff --git a/src/pkg/syscall/syscall_bsd_test.go b/src/syscall/syscall_bsd_test.go
index c2ea089d5..c2ea089d5 100644
--- a/src/pkg/syscall/syscall_bsd_test.go
+++ b/src/syscall/syscall_bsd_test.go
diff --git a/src/pkg/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go
index 97414dcda..f026a56d8 100644
--- a/src/pkg/syscall/syscall_darwin.go
+++ b/src/syscall/syscall_darwin.go
@@ -143,6 +143,7 @@ func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (
uintptr(options),
0,
)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
return nil, e1
}
diff --git a/src/pkg/syscall/syscall_darwin_386.go b/src/syscall/syscall_darwin_386.go
index 2074e7ac2..2074e7ac2 100644
--- a/src/pkg/syscall/syscall_darwin_386.go
+++ b/src/syscall/syscall_darwin_386.go
diff --git a/src/pkg/syscall/syscall_darwin_amd64.go b/src/syscall/syscall_darwin_amd64.go
index 81b1fd3d2..81b1fd3d2 100644
--- a/src/pkg/syscall/syscall_darwin_amd64.go
+++ b/src/syscall/syscall_darwin_amd64.go
diff --git a/src/pkg/syscall/syscall_dragonfly.go b/src/syscall/syscall_dragonfly.go
index 39c51df7e..39c51df7e 100644
--- a/src/pkg/syscall/syscall_dragonfly.go
+++ b/src/syscall/syscall_dragonfly.go
diff --git a/src/pkg/syscall/syscall_dragonfly_386.go b/src/syscall/syscall_dragonfly_386.go
index ebd3d4c9c..ebd3d4c9c 100644
--- a/src/pkg/syscall/syscall_dragonfly_386.go
+++ b/src/syscall/syscall_dragonfly_386.go
diff --git a/src/pkg/syscall/syscall_dragonfly_amd64.go b/src/syscall/syscall_dragonfly_amd64.go
index 70c2ffb03..70c2ffb03 100644
--- a/src/pkg/syscall/syscall_dragonfly_amd64.go
+++ b/src/syscall/syscall_dragonfly_amd64.go
diff --git a/src/pkg/syscall/syscall_freebsd.go b/src/syscall/syscall_freebsd.go
index 3d834f52b..3d834f52b 100644
--- a/src/pkg/syscall/syscall_freebsd.go
+++ b/src/syscall/syscall_freebsd.go
diff --git a/src/pkg/syscall/syscall_freebsd_386.go b/src/syscall/syscall_freebsd_386.go
index ebd3d4c9c..ebd3d4c9c 100644
--- a/src/pkg/syscall/syscall_freebsd_386.go
+++ b/src/syscall/syscall_freebsd_386.go
diff --git a/src/pkg/syscall/syscall_freebsd_amd64.go b/src/syscall/syscall_freebsd_amd64.go
index 70c2ffb03..70c2ffb03 100644
--- a/src/pkg/syscall/syscall_freebsd_amd64.go
+++ b/src/syscall/syscall_freebsd_amd64.go
diff --git a/src/pkg/syscall/syscall_freebsd_arm.go b/src/syscall/syscall_freebsd_arm.go
index ab72871dd..ab72871dd 100644
--- a/src/pkg/syscall/syscall_freebsd_arm.go
+++ b/src/syscall/syscall_freebsd_arm.go
diff --git a/src/pkg/syscall/syscall_linux.go b/src/syscall/syscall_linux.go
index fa0d7ea3c..c40c71890 100644
--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/syscall/syscall_linux.go
@@ -94,7 +94,9 @@ func Futimesat(dirfd int, path string, tv []Timeval) (err error) {
if err != nil {
return err
}
- return futimesat(dirfd, pathp, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+ err = futimesat(dirfd, pathp, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+ use(unsafe.Pointer(pathp))
+ return err
}
func Futimes(fd int, tv []Timeval) (err error) {
@@ -769,7 +771,9 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
if err != nil {
return err
}
- return mount(source, target, fstype, flags, datap)
+ err = mount(source, target, fstype, flags, datap)
+ use(unsafe.Pointer(datap))
+ return err
}
// Sendto
@@ -841,7 +845,20 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
//sysnb Setpgid(pid int, pgid int) (err error)
//sysnb Setsid() (pid int, err error)
//sysnb Settimeofday(tv *Timeval) (err error)
-//sysnb Setuid(uid int) (err error)
+
+// issue 1435.
+// On linux Setuid and Setgid only affects the current thread, not the process.
+// This does not match what most callers expect so we must return an error
+// here rather than letting the caller think that the call succeeded.
+
+func Setuid(uid int) (err error) {
+ return EOPNOTSUPP
+}
+
+func Setgid(uid int) (err error) {
+ return EOPNOTSUPP
+}
+
//sys Setpriority(which int, who int, prio int) (err error)
//sys Setxattr(path string, attr string, data []byte, flags int) (err error)
//sys Symlink(oldpath string, newpath string) (err error)
diff --git a/src/pkg/syscall/syscall_linux_386.go b/src/syscall/syscall_linux_386.go
index c491a286c..827875053 100644
--- a/src/pkg/syscall/syscall_linux_386.go
+++ b/src/syscall/syscall_linux_386.go
@@ -47,7 +47,6 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32
//sys Setfsuid(uid int) (err error) = SYS_SETFSUID32
-//sysnb Setgid(gid int) (err error) = SYS_SETGID32
//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32
//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32
@@ -333,6 +332,7 @@ func Statfs(path string, buf *Statfs_t) (err error) {
return err
}
_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(pathp)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
+ use(unsafe.Pointer(pathp))
if e != 0 {
err = e
}
diff --git a/src/pkg/syscall/syscall_linux_amd64.go b/src/syscall/syscall_linux_amd64.go
index 8915ed83b..74a89fb67 100644
--- a/src/pkg/syscall/syscall_linux_amd64.go
+++ b/src/syscall/syscall_linux_amd64.go
@@ -26,7 +26,6 @@ package syscall
//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 Setgid(gid 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)
diff --git a/src/pkg/syscall/syscall_linux_arm.go b/src/syscall/syscall_linux_arm.go
index 9fe80232a..b127345d3 100644
--- a/src/pkg/syscall/syscall_linux_arm.go
+++ b/src/syscall/syscall_linux_arm.go
@@ -68,7 +68,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32
//sys Setfsuid(uid int) (err error) = SYS_SETFSUID32
-//sysnb Setgid(gid int) (err error) = SYS_SETGID32
//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32
//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32
@@ -102,6 +101,7 @@ func Statfs(path string, buf *Statfs_t) (err error) {
return err
}
_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(pathp)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
+ use(unsafe.Pointer(pathp))
if e != 0 {
err = e
}
diff --git a/src/pkg/syscall/syscall_nacl.go b/src/syscall/syscall_nacl.go
index c2788b20a..c2788b20a 100644
--- a/src/pkg/syscall/syscall_nacl.go
+++ b/src/syscall/syscall_nacl.go
diff --git a/src/pkg/syscall/syscall_nacl_386.go b/src/syscall/syscall_nacl_386.go
index d12f8e2d6..d12f8e2d6 100644
--- a/src/pkg/syscall/syscall_nacl_386.go
+++ b/src/syscall/syscall_nacl_386.go
diff --git a/src/pkg/syscall/syscall_nacl_amd64p32.go b/src/syscall/syscall_nacl_amd64p32.go
index d12f8e2d6..d12f8e2d6 100644
--- a/src/pkg/syscall/syscall_nacl_amd64p32.go
+++ b/src/syscall/syscall_nacl_amd64p32.go
diff --git a/src/syscall/syscall_nacl_arm.go b/src/syscall/syscall_nacl_arm.go
new file mode 100644
index 000000000..fc0cdda5d
--- /dev/null
+++ b/src/syscall/syscall_nacl_arm.go
@@ -0,0 +1,32 @@
+// 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 syscall
+
+type Timespec struct {
+ Sec int64
+ Nsec int32
+}
+
+type Timeval struct {
+ Sec int64
+ Usec int32
+}
+
+func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+ ts.Sec = int64(nsec / 1e9)
+ ts.Nsec = int32(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.Usec = int32(nsec % 1e9 / 1e3)
+ tv.Sec = int64(nsec / 1e9)
+ return
+}
diff --git a/src/pkg/syscall/syscall_netbsd.go b/src/syscall/syscall_netbsd.go
index 97812717f..97812717f 100644
--- a/src/pkg/syscall/syscall_netbsd.go
+++ b/src/syscall/syscall_netbsd.go
diff --git a/src/pkg/syscall/syscall_netbsd_386.go b/src/syscall/syscall_netbsd_386.go
index 2dbff07f1..2dbff07f1 100644
--- a/src/pkg/syscall/syscall_netbsd_386.go
+++ b/src/syscall/syscall_netbsd_386.go
diff --git a/src/pkg/syscall/syscall_netbsd_amd64.go b/src/syscall/syscall_netbsd_amd64.go
index 5784db99a..5784db99a 100644
--- a/src/pkg/syscall/syscall_netbsd_amd64.go
+++ b/src/syscall/syscall_netbsd_amd64.go
diff --git a/src/pkg/syscall/syscall_netbsd_arm.go b/src/syscall/syscall_netbsd_arm.go
index 659698aac..659698aac 100644
--- a/src/pkg/syscall/syscall_netbsd_arm.go
+++ b/src/syscall/syscall_netbsd_arm.go
diff --git a/src/pkg/syscall/syscall_no_getwd.go b/src/syscall/syscall_no_getwd.go
index 0080c5ca0..0080c5ca0 100644
--- a/src/pkg/syscall/syscall_no_getwd.go
+++ b/src/syscall/syscall_no_getwd.go
diff --git a/src/pkg/syscall/syscall_openbsd.go b/src/syscall/syscall_openbsd.go
index 8d3f825f8..8d3f825f8 100644
--- a/src/pkg/syscall/syscall_openbsd.go
+++ b/src/syscall/syscall_openbsd.go
diff --git a/src/pkg/syscall/syscall_openbsd_386.go b/src/syscall/syscall_openbsd_386.go
index ad5ae14bf..ad5ae14bf 100644
--- a/src/pkg/syscall/syscall_openbsd_386.go
+++ b/src/syscall/syscall_openbsd_386.go
diff --git a/src/pkg/syscall/syscall_openbsd_amd64.go b/src/syscall/syscall_openbsd_amd64.go
index 6181344cd..6181344cd 100644
--- a/src/pkg/syscall/syscall_openbsd_amd64.go
+++ b/src/syscall/syscall_openbsd_amd64.go
diff --git a/src/pkg/syscall/syscall_plan9.go b/src/syscall/syscall_plan9.go
index a8c340541..618e02cec 100644
--- a/src/pkg/syscall/syscall_plan9.go
+++ b/src/syscall/syscall_plan9.go
@@ -260,7 +260,9 @@ func Unmount(name, old string) (err error) {
return err
}
r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
+ use(unsafe.Pointer(namep))
}
+ use(unsafe.Pointer(oldp))
if int32(r0) == -1 {
err = e
@@ -295,30 +297,25 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
return
}
-func DecodeBintime(b []byte) (nsec int64, err error) {
- if len(b) != 8 {
- return -1, NewError("bad /dev/bintime format")
+func nsec() int64 {
+ var scratch int64
+
+ r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
+ // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
+ if r0 == 0 {
+ return scratch
}
- nsec = int64(b[0])<<56 |
- int64(b[1])<<48 |
- int64(b[2])<<40 |
- int64(b[3])<<32 |
- int64(b[4])<<24 |
- int64(b[5])<<16 |
- int64(b[6])<<8 |
- int64(b[7])
- return
+ return int64(r0)
}
func Gettimeofday(tv *Timeval) error {
- nsec, e := nanotime()
- if e != nil {
- return e
- }
+ nsec := nsec()
*tv = NsecToTimeval(nsec)
- return e
+ return nil
}
+func Getpagesize() int { return 0x1000 }
+
func Getegid() (egid int) { return -1 }
func Geteuid() (euid int) { return -1 }
func Getgid() (gid int) { return -1 }
diff --git a/src/pkg/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go
index adc52b1f7..adc52b1f7 100644
--- a/src/pkg/syscall/syscall_solaris.go
+++ b/src/syscall/syscall_solaris.go
diff --git a/src/pkg/syscall/syscall_solaris_amd64.go b/src/syscall/syscall_solaris_amd64.go
index 37cf06d70..37cf06d70 100644
--- a/src/pkg/syscall/syscall_solaris_amd64.go
+++ b/src/syscall/syscall_solaris_amd64.go
diff --git a/src/pkg/syscall/syscall_test.go b/src/syscall/syscall_test.go
index 2a39b54f1..846c4873d 100644
--- a/src/pkg/syscall/syscall_test.go
+++ b/src/syscall/syscall_test.go
@@ -5,6 +5,7 @@
package syscall_test
import (
+ "fmt"
"syscall"
"testing"
)
@@ -28,3 +29,19 @@ func TestEnv(t *testing.T) {
// make sure TESTENV gets set to "", not deleted
testSetGetenv(t, "TESTENV", "")
}
+
+func TestItoa(t *testing.T) {
+ // Make most negative integer: 0x8000...
+ i := 1
+ for i<<1 != 0 {
+ i <<= 1
+ }
+ if i >= 0 {
+ t.Fatal("bad math")
+ }
+ s := syscall.Itoa(i)
+ f := fmt.Sprint(i)
+ if s != f {
+ t.Fatalf("itoa(%d) = %s, want %s", i, s, f)
+ }
+}
diff --git a/src/pkg/syscall/syscall_unix.go b/src/syscall/syscall_unix.go
index b28891568..a06bd7dd0 100644
--- a/src/pkg/syscall/syscall_unix.go
+++ b/src/syscall/syscall_unix.go
@@ -56,7 +56,7 @@ func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (d
cap int
}{addr, length, length}
- // Use unsafeto turn sl into a []byte.
+ // Use unsafe to turn sl into a []byte.
b := *(*[]byte)(unsafe.Pointer(&sl))
// Register mapping in m and return it.
@@ -109,7 +109,7 @@ func (e Errno) Error() string {
}
func (e Errno) Temporary() bool {
- return e == EINTR || e == EMFILE || e.Timeout()
+ return e == EINTR || e == EMFILE || e == ECONNRESET || e == ECONNABORTED || e.Timeout()
}
func (e Errno) Timeout() bool {
diff --git a/src/pkg/syscall/syscall_unix_test.go b/src/syscall/syscall_unix_test.go
index a0afb91fc..a0afb91fc 100644
--- a/src/pkg/syscall/syscall_unix_test.go
+++ b/src/syscall/syscall_unix_test.go
diff --git a/src/pkg/syscall/syscall_windows.go b/src/syscall/syscall_windows.go
index f9733f6ce..e89fd096a 100644
--- a/src/pkg/syscall/syscall_windows.go
+++ b/src/syscall/syscall_windows.go
@@ -105,12 +105,22 @@ func (e Errno) Timeout() bool {
return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
}
+// Implemented in asm_windows.s
+func compileCallback(fn interface{}, cleanstack bool) uintptr
+
// Converts a Go function to a function pointer conforming
-// to the stdcall or cdecl calling convention. This is useful when
+// to the stdcall calling convention. This is useful when
// interoperating with Windows code requiring callbacks.
-// Implemented in ../runtime/syscall_windows.goc
-func NewCallback(fn interface{}) uintptr
-func NewCallbackCDecl(fn interface{}) uintptr
+func NewCallback(fn interface{}) uintptr {
+ return compileCallback(fn, true)
+}
+
+// Converts a Go function to a function pointer conforming
+// to the cdecl calling convention. This is useful when
+// interoperating with Windows code requiring callbacks.
+func NewCallbackCDecl(fn interface{}) uintptr {
+ return compileCallback(fn, false)
+}
// windows api calls
@@ -204,6 +214,13 @@ func NewCallbackCDecl(fn interface{}) uintptr
//sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode
//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
+//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
+//sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW
+//sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW
+//sys DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error)
+// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
+//sys CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) [failretval&0xff==0] = CreateSymbolicLinkW
+//sys CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardLinkW
// syscall interface implementation for other packages
@@ -451,7 +468,7 @@ func Utimes(path string, tv []Timeval) (err error) {
}
h, e := CreateFile(pathp,
FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
if e != nil {
return e
}
@@ -471,7 +488,7 @@ func UtimesNano(path string, ts []Timespec) (err error) {
}
h, e := CreateFile(pathp,
FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
if e != nil {
return e
}
@@ -542,6 +559,7 @@ const socket_error = uintptr(^uint32(0))
//sys GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname
//sys DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W
//sys DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree
+//sys DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) = dnsapi.DnsNameCompare_W
//sys GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) = ws2_32.GetAddrInfoW
//sys FreeAddrInfoW(addrinfo *AddrinfoW) = ws2_32.FreeAddrInfoW
//sys GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry
@@ -902,13 +920,40 @@ func FindNextFile(handle Handle, data *Win32finddata) (err error) {
return
}
-// TODO(brainman): fix all needed for os
-func Getppid() (ppid int) { return -1 }
+func getProcessEntry(pid int) (*ProcessEntry32, error) {
+ snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
+ if err != nil {
+ return nil, err
+ }
+ defer CloseHandle(snapshot)
+ var procEntry ProcessEntry32
+ procEntry.Size = uint32(unsafe.Sizeof(procEntry))
+ if err = Process32First(snapshot, &procEntry); err != nil {
+ return nil, err
+ }
+ for {
+ if procEntry.ProcessID == uint32(pid) {
+ return &procEntry, nil
+ }
+ err = Process32Next(snapshot, &procEntry)
+ if err != nil {
+ return nil, err
+ }
+ }
+}
-func Fchdir(fd Handle) (err error) { return EWINDOWS }
-func Link(oldpath, newpath string) (err error) { return EWINDOWS }
-func Symlink(path, link string) (err error) { return EWINDOWS }
-func Readlink(path string, buf []byte) (n int, err error) { return 0, EWINDOWS }
+func Getppid() (ppid int) {
+ pe, err := getProcessEntry(Getpid())
+ if err != nil {
+ return -1
+ }
+ return int(pe.ParentProcessID)
+}
+
+// TODO(brainman): fix all needed for os
+func Fchdir(fd Handle) (err error) { return EWINDOWS }
+func Link(oldpath, newpath string) (err error) { return EWINDOWS }
+func Symlink(path, link string) (err error) { return EWINDOWS }
func Fchmod(fd Handle, mode uint32) (err error) { return EWINDOWS }
func Chown(path string, uid int, gid int) (err error) { return EWINDOWS }
@@ -934,3 +979,35 @@ func (s Signal) String() string {
}
return "signal " + itoa(int(s))
}
+
+func LoadCreateSymbolicLink() error {
+ return procCreateSymbolicLinkW.Find()
+}
+
+// Readlink returns the destination of the named symbolic link.
+func Readlink(path string, buf []byte) (n int, err error) {
+ fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0)
+ if err != nil {
+ return -1, err
+ }
+ defer CloseHandle(fd)
+
+ rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
+ var bytesReturned uint32
+ err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
+ if err != nil {
+ return -1, err
+ }
+
+ rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
+ if uintptr(bytesReturned) < unsafe.Sizeof(*rdb) ||
+ rdb.ReparseTag != IO_REPARSE_TAG_SYMLINK {
+ // the path is not a symlink but another type of reparse point
+ return -1, ENOENT
+ }
+
+ s := UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(&rdb.PathBuffer[0]))[:rdb.PrintNameLength/2])
+ n = copy(buf, []byte(s))
+ return n, nil
+}
diff --git a/src/pkg/syscall/syscall_windows_386.go b/src/syscall/syscall_windows_386.go
index 61d2d8cb6..61d2d8cb6 100644
--- a/src/pkg/syscall/syscall_windows_386.go
+++ b/src/syscall/syscall_windows_386.go
diff --git a/src/pkg/syscall/syscall_windows_amd64.go b/src/syscall/syscall_windows_amd64.go
index 61d2d8cb6..61d2d8cb6 100644
--- a/src/pkg/syscall/syscall_windows_amd64.go
+++ b/src/syscall/syscall_windows_amd64.go
diff --git a/src/pkg/syscall/syscall_windows_test.go b/src/syscall/syscall_windows_test.go
index 86842f2ad..86842f2ad 100644
--- a/src/pkg/syscall/syscall_windows_test.go
+++ b/src/syscall/syscall_windows_test.go
diff --git a/src/pkg/syscall/tables_nacl.go b/src/syscall/tables_nacl.go
index 08f4ced53..08f4ced53 100644
--- a/src/pkg/syscall/tables_nacl.go
+++ b/src/syscall/tables_nacl.go
diff --git a/src/pkg/syscall/time_nacl_386.s b/src/syscall/time_nacl_386.s
index b5a22d31b..c0c89dccc 100644
--- a/src/pkg/syscall/time_nacl_386.s
+++ b/src/syscall/time_nacl_386.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·startTimer(SB),NOSPLIT,$0
JMP time·startTimer(SB)
diff --git a/src/pkg/syscall/time_nacl_amd64p32.s b/src/syscall/time_nacl_amd64p32.s
index b5a22d31b..c0c89dccc 100644
--- a/src/pkg/syscall/time_nacl_amd64p32.s
+++ b/src/syscall/time_nacl_amd64p32.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "../../cmd/ld/textflag.h"
+#include "textflag.h"
TEXT ·startTimer(SB),NOSPLIT,$0
JMP time·startTimer(SB)
diff --git a/src/syscall/time_nacl_arm.s b/src/syscall/time_nacl_arm.s
new file mode 100644
index 000000000..4f4b4d89a
--- /dev/null
+++ b/src/syscall/time_nacl_arm.s
@@ -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.
+
+#include "textflag.h"
+
+TEXT ·startTimer(SB),NOSPLIT,$0
+ B time·startTimer(SB)
+
+TEXT ·stopTimer(SB),NOSPLIT,$0
+ B time·stopTimer(SB)
diff --git a/src/pkg/syscall/types_darwin.go b/src/syscall/types_darwin.go
index a043071f2..a043071f2 100644
--- a/src/pkg/syscall/types_darwin.go
+++ b/src/syscall/types_darwin.go
diff --git a/src/pkg/syscall/types_dragonfly.go b/src/syscall/types_dragonfly.go
index fb7fd1bb4..fb7fd1bb4 100644
--- a/src/pkg/syscall/types_dragonfly.go
+++ b/src/syscall/types_dragonfly.go
diff --git a/src/pkg/syscall/types_freebsd.go b/src/syscall/types_freebsd.go
index 68a69312b..68a69312b 100644
--- a/src/pkg/syscall/types_freebsd.go
+++ b/src/syscall/types_freebsd.go
diff --git a/src/pkg/syscall/types_linux.go b/src/syscall/types_linux.go
index e8396a41f..e8396a41f 100644
--- a/src/pkg/syscall/types_linux.go
+++ b/src/syscall/types_linux.go
diff --git a/src/pkg/syscall/types_netbsd.go b/src/syscall/types_netbsd.go
index 04354a32a..04354a32a 100644
--- a/src/pkg/syscall/types_netbsd.go
+++ b/src/syscall/types_netbsd.go
diff --git a/src/pkg/syscall/types_openbsd.go b/src/syscall/types_openbsd.go
index e6d1ea704..e6d1ea704 100644
--- a/src/pkg/syscall/types_openbsd.go
+++ b/src/syscall/types_openbsd.go
diff --git a/src/pkg/syscall/types_plan9.c b/src/syscall/types_plan9.c
index cd9e15fa8..cd9e15fa8 100644
--- a/src/pkg/syscall/types_plan9.c
+++ b/src/syscall/types_plan9.c
diff --git a/src/pkg/syscall/types_solaris.go b/src/syscall/types_solaris.go
index 53fa35068..53fa35068 100644
--- a/src/pkg/syscall/types_solaris.go
+++ b/src/syscall/types_solaris.go
diff --git a/src/pkg/syscall/unzip_nacl.go b/src/syscall/unzip_nacl.go
index 5845e44f0..5845e44f0 100644
--- a/src/pkg/syscall/unzip_nacl.go
+++ b/src/syscall/unzip_nacl.go
diff --git a/src/pkg/syscall/zerrors_darwin_386.go b/src/syscall/zerrors_darwin_386.go
index bb3a1610c..bb3a1610c 100644
--- a/src/pkg/syscall/zerrors_darwin_386.go
+++ b/src/syscall/zerrors_darwin_386.go
diff --git a/src/pkg/syscall/zerrors_darwin_amd64.go b/src/syscall/zerrors_darwin_amd64.go
index 05ab48ee3..05ab48ee3 100644
--- a/src/pkg/syscall/zerrors_darwin_amd64.go
+++ b/src/syscall/zerrors_darwin_amd64.go
diff --git a/src/pkg/syscall/zerrors_dragonfly_386.go b/src/syscall/zerrors_dragonfly_386.go
index 701a1c381..701a1c381 100644
--- a/src/pkg/syscall/zerrors_dragonfly_386.go
+++ b/src/syscall/zerrors_dragonfly_386.go
diff --git a/src/pkg/syscall/zerrors_dragonfly_amd64.go b/src/syscall/zerrors_dragonfly_amd64.go
index 59bff751c..59bff751c 100644
--- a/src/pkg/syscall/zerrors_dragonfly_amd64.go
+++ b/src/syscall/zerrors_dragonfly_amd64.go
diff --git a/src/pkg/syscall/zerrors_freebsd_386.go b/src/syscall/zerrors_freebsd_386.go
index cd3aa80a9..cd3aa80a9 100644
--- a/src/pkg/syscall/zerrors_freebsd_386.go
+++ b/src/syscall/zerrors_freebsd_386.go
diff --git a/src/pkg/syscall/zerrors_freebsd_amd64.go b/src/syscall/zerrors_freebsd_amd64.go
index 9edce6e2f..9edce6e2f 100644
--- a/src/pkg/syscall/zerrors_freebsd_amd64.go
+++ b/src/syscall/zerrors_freebsd_amd64.go
diff --git a/src/pkg/syscall/zerrors_freebsd_arm.go b/src/syscall/zerrors_freebsd_arm.go
index f29dd057b..f29dd057b 100644
--- a/src/pkg/syscall/zerrors_freebsd_arm.go
+++ b/src/syscall/zerrors_freebsd_arm.go
diff --git a/src/pkg/syscall/zerrors_linux_386.go b/src/syscall/zerrors_linux_386.go
index 7aa8ff07a..7aa8ff07a 100644
--- a/src/pkg/syscall/zerrors_linux_386.go
+++ b/src/syscall/zerrors_linux_386.go
diff --git a/src/pkg/syscall/zerrors_linux_amd64.go b/src/syscall/zerrors_linux_amd64.go
index 94d051d8a..94d051d8a 100644
--- a/src/pkg/syscall/zerrors_linux_amd64.go
+++ b/src/syscall/zerrors_linux_amd64.go
diff --git a/src/pkg/syscall/zerrors_linux_arm.go b/src/syscall/zerrors_linux_arm.go
index dcaaef742..dcaaef742 100644
--- a/src/pkg/syscall/zerrors_linux_arm.go
+++ b/src/syscall/zerrors_linux_arm.go
diff --git a/src/pkg/syscall/zerrors_netbsd_386.go b/src/syscall/zerrors_netbsd_386.go
index 1e3dff7fa..1e3dff7fa 100644
--- a/src/pkg/syscall/zerrors_netbsd_386.go
+++ b/src/syscall/zerrors_netbsd_386.go
diff --git a/src/pkg/syscall/zerrors_netbsd_amd64.go b/src/syscall/zerrors_netbsd_amd64.go
index 1469d00b7..1469d00b7 100644
--- a/src/pkg/syscall/zerrors_netbsd_amd64.go
+++ b/src/syscall/zerrors_netbsd_amd64.go
diff --git a/src/pkg/syscall/zerrors_netbsd_arm.go b/src/syscall/zerrors_netbsd_arm.go
index 1a88c0d22..1a88c0d22 100644
--- a/src/pkg/syscall/zerrors_netbsd_arm.go
+++ b/src/syscall/zerrors_netbsd_arm.go
diff --git a/src/pkg/syscall/zerrors_openbsd_386.go b/src/syscall/zerrors_openbsd_386.go
index 082983494..082983494 100644
--- a/src/pkg/syscall/zerrors_openbsd_386.go
+++ b/src/syscall/zerrors_openbsd_386.go
diff --git a/src/pkg/syscall/zerrors_openbsd_amd64.go b/src/syscall/zerrors_openbsd_amd64.go
index e9fa37cde..e9fa37cde 100644
--- a/src/pkg/syscall/zerrors_openbsd_amd64.go
+++ b/src/syscall/zerrors_openbsd_amd64.go
diff --git a/src/pkg/syscall/zerrors_plan9_386.go b/src/syscall/zerrors_plan9_386.go
index ede3d6a32..ede3d6a32 100644
--- a/src/pkg/syscall/zerrors_plan9_386.go
+++ b/src/syscall/zerrors_plan9_386.go
diff --git a/src/pkg/syscall/zerrors_plan9_amd64.go b/src/syscall/zerrors_plan9_amd64.go
index ede3d6a32..ede3d6a32 100644
--- a/src/pkg/syscall/zerrors_plan9_amd64.go
+++ b/src/syscall/zerrors_plan9_amd64.go
diff --git a/src/pkg/syscall/zerrors_solaris_amd64.go b/src/syscall/zerrors_solaris_amd64.go
index 3f4cbfd98..3f4cbfd98 100644
--- a/src/pkg/syscall/zerrors_solaris_amd64.go
+++ b/src/syscall/zerrors_solaris_amd64.go
diff --git a/src/pkg/syscall/zerrors_windows.go b/src/syscall/zerrors_windows.go
index afdeae2bc..afdeae2bc 100644
--- a/src/pkg/syscall/zerrors_windows.go
+++ b/src/syscall/zerrors_windows.go
diff --git a/src/pkg/syscall/zerrors_windows_386.go b/src/syscall/zerrors_windows_386.go
index d1008bd03..d1008bd03 100644
--- a/src/pkg/syscall/zerrors_windows_386.go
+++ b/src/syscall/zerrors_windows_386.go
diff --git a/src/pkg/syscall/zerrors_windows_amd64.go b/src/syscall/zerrors_windows_amd64.go
index d1008bd03..d1008bd03 100644
--- a/src/pkg/syscall/zerrors_windows_amd64.go
+++ b/src/syscall/zerrors_windows_amd64.go
diff --git a/src/pkg/syscall/zsyscall_darwin_386.go b/src/syscall/zsyscall_darwin_386.go
index a6a176b60..934565fc3 100644
--- a/src/pkg/syscall/zsyscall_darwin_386.go
+++ b/src/syscall/zsyscall_darwin_386.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -298,6 +299,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -323,6 +325,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -338,6 +341,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -353,6 +357,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -368,6 +373,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -383,6 +389,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -434,6 +441,8 @@ func Exchangedata(path1 string, path2 string, options int) (err error) {
return
}
_, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options))
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -710,6 +719,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -730,6 +740,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -755,6 +767,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -770,6 +783,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -785,6 +799,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -800,6 +815,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -883,6 +899,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -899,6 +916,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -972,6 +990,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -993,6 +1012,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1008,6 +1029,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1023,6 +1045,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1089,6 +1112,7 @@ func Setlogin(name string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1195,6 +1219,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1210,6 +1235,7 @@ func Statfs(path string, stat *Statfs_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1230,6 +1256,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1255,6 +1283,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1278,6 +1307,7 @@ func Undelete(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1293,6 +1323,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1308,6 +1339,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_darwin_amd64.go b/src/syscall/zsyscall_darwin_amd64.go
index f5867c45d..75cf2513b 100644
--- a/src/pkg/syscall/zsyscall_darwin_amd64.go
+++ b/src/syscall/zsyscall_darwin_amd64.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -298,6 +299,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -323,6 +325,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -338,6 +341,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -353,6 +357,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -368,6 +373,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -383,6 +389,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -434,6 +441,8 @@ func Exchangedata(path1 string, path2 string, options int) (err error) {
return
}
_, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options))
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -710,6 +719,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -730,6 +740,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -755,6 +767,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -770,6 +783,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -785,6 +799,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -800,6 +815,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -883,6 +899,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -899,6 +916,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -972,6 +990,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -993,6 +1012,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1008,6 +1029,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1023,6 +1045,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1089,6 +1112,7 @@ func Setlogin(name string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1195,6 +1219,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1210,6 +1235,7 @@ func Statfs(path string, stat *Statfs_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1230,6 +1256,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1255,6 +1283,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1278,6 +1307,7 @@ func Undelete(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1293,6 +1323,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1308,6 +1339,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_dragonfly_386.go b/src/syscall/zsyscall_dragonfly_386.go
index 0ec813232..01b081977 100644
--- a/src/pkg/syscall/zsyscall_dragonfly_386.go
+++ b/src/syscall/zsyscall_dragonfly_386.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -312,6 +313,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -337,6 +339,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -352,6 +355,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -367,6 +371,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -382,6 +387,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -397,6 +403,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -724,6 +731,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -744,6 +752,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -769,6 +779,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -784,6 +795,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -799,6 +811,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -814,6 +827,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -839,6 +853,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -855,6 +870,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -894,6 +910,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -915,6 +932,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -930,6 +949,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -945,6 +965,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1011,6 +1032,7 @@ func Setlogin(name string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1107,6 +1129,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1122,6 +1145,7 @@ func Statfs(path string, stat *Statfs_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1142,6 +1166,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1167,6 +1193,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1190,6 +1217,7 @@ func Undelete(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1205,6 +1233,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1220,6 +1249,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_dragonfly_amd64.go b/src/syscall/zsyscall_dragonfly_amd64.go
index 8c7cce54e..012137469 100644
--- a/src/pkg/syscall/zsyscall_dragonfly_amd64.go
+++ b/src/syscall/zsyscall_dragonfly_amd64.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -312,6 +313,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -337,6 +339,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -352,6 +355,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -367,6 +371,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -382,6 +387,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -397,6 +403,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -724,6 +731,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -744,6 +752,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -769,6 +779,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -784,6 +795,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -799,6 +811,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -814,6 +827,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -839,6 +853,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -855,6 +870,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -894,6 +910,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -915,6 +932,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -930,6 +949,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -945,6 +965,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1011,6 +1032,7 @@ func Setlogin(name string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1107,6 +1129,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1122,6 +1145,7 @@ func Statfs(path string, stat *Statfs_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1142,6 +1166,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1167,6 +1193,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1190,6 +1217,7 @@ func Undelete(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1205,6 +1233,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1220,6 +1249,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_freebsd_386.go b/src/syscall/zsyscall_freebsd_386.go
index 5befe83c6..c8c636fa1 100644
--- a/src/pkg/syscall/zsyscall_freebsd_386.go
+++ b/src/syscall/zsyscall_freebsd_386.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -278,6 +279,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -303,6 +305,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -318,6 +321,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -333,6 +337,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -348,6 +353,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -363,6 +369,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -690,6 +697,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -710,6 +718,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -735,6 +745,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -750,6 +761,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -765,6 +777,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -780,6 +793,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -805,6 +819,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -821,6 +836,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -894,6 +910,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -915,6 +932,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -930,6 +949,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -945,6 +965,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1011,6 +1032,7 @@ func Setlogin(name string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1107,6 +1129,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1122,6 +1145,7 @@ func Statfs(path string, stat *Statfs_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1142,6 +1166,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1167,6 +1193,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1190,6 +1217,7 @@ func Undelete(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1205,6 +1233,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1220,6 +1249,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_freebsd_amd64.go b/src/syscall/zsyscall_freebsd_amd64.go
index ab2eb80c6..026b560ca 100644
--- a/src/pkg/syscall/zsyscall_freebsd_amd64.go
+++ b/src/syscall/zsyscall_freebsd_amd64.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -278,6 +279,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -303,6 +305,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -318,6 +321,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -333,6 +337,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -348,6 +353,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -363,6 +369,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -690,6 +697,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -710,6 +718,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -735,6 +745,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -750,6 +761,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -765,6 +777,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -780,6 +793,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -805,6 +819,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -821,6 +836,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -894,6 +910,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -915,6 +932,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -930,6 +949,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -945,6 +965,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1011,6 +1032,7 @@ func Setlogin(name string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1107,6 +1129,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1122,6 +1145,7 @@ func Statfs(path string, stat *Statfs_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1142,6 +1166,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1167,6 +1193,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1190,6 +1217,7 @@ func Undelete(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1205,6 +1233,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1220,6 +1249,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_freebsd_arm.go b/src/syscall/zsyscall_freebsd_arm.go
index c1f0f907c..0c349cb61 100644
--- a/src/pkg/syscall/zsyscall_freebsd_arm.go
+++ b/src/syscall/zsyscall_freebsd_arm.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -278,6 +279,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -303,6 +305,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -318,6 +321,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -333,6 +337,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -348,6 +353,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -363,6 +369,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -690,6 +697,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -710,6 +718,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -735,6 +745,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -750,6 +761,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -765,6 +777,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -780,6 +793,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -805,6 +819,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -821,6 +836,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -894,6 +910,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -915,6 +932,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -930,6 +949,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -945,6 +965,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1011,6 +1032,7 @@ func Setlogin(name string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1107,6 +1129,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1122,6 +1145,7 @@ func Statfs(path string, stat *Statfs_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1142,6 +1166,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1167,6 +1193,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1190,6 +1217,7 @@ func Undelete(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1205,6 +1233,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1220,6 +1249,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_linux_386.go b/src/syscall/zsyscall_linux_386.go
index 6eeb11828..dee834313 100644
--- a/src/pkg/syscall/zsyscall_linux_386.go
+++ b/src/syscall/zsyscall_linux_386.go
@@ -14,6 +14,7 @@ func open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -30,6 +31,7 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
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 = e1
@@ -66,6 +68,7 @@ func utimes(path string, times *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -81,6 +84,7 @@ func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -144,6 +148,7 @@ func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
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 = e1
}
@@ -169,6 +174,9 @@ func mount(source string, target string, fstype string, flags uintptr, data *byt
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 = e1
}
@@ -184,6 +192,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -199,6 +208,7 @@ func Acct(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -225,6 +235,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -240,6 +251,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -255,6 +267,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -280,6 +293,7 @@ func Creat(path string, mode uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -383,6 +397,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
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 = e1
}
@@ -428,6 +443,7 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
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 = e1
}
@@ -443,6 +459,7 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
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 = e1
}
@@ -591,6 +608,8 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
_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 = e1
@@ -607,6 +626,7 @@ func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err e
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 = e1
@@ -688,6 +708,8 @@ func Link(oldpath string, newpath string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -709,6 +731,7 @@ func Listxattr(path string, dest []byte) (sz int, err error) {
_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 = e1
@@ -725,6 +748,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -740,6 +764,7 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -755,6 +780,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -770,6 +796,7 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
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 = e1
}
@@ -810,6 +837,8 @@ func PivotRoot(newroot string, putold string) (err error) {
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 = e1
}
@@ -858,6 +887,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -879,6 +909,8 @@ func Removexattr(path string, attr string) (err error) {
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 = e1
}
@@ -899,6 +931,8 @@ func Rename(oldpath string, newpath string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -919,6 +953,8 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e
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 = e1
}
@@ -934,6 +970,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1005,16 +1042,6 @@ func Settimeofday(tv *Timeval) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Setuid(uid int) (err error) {
- _, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
- if e1 != 0 {
- err = 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 {
@@ -1043,6 +1070,8 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
_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 = e1
}
@@ -1063,6 +1092,8 @@ func Symlink(oldpath string, newpath string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1145,6 +1176,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1160,6 +1192,7 @@ func Unlinkat(dirfd int, path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1175,6 +1208,7 @@ func Unmount(target string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1210,6 +1244,7 @@ func Utime(path string, buf *Utimbuf) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1368,6 +1403,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN32, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1465,6 +1501,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN32, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1480,6 +1517,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1553,16 +1591,6 @@ func Setfsuid(uid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Setgid(gid int) (err error) {
- _, _, e1 := RawSyscall(SYS_SETGID32, uintptr(gid), 0, 0)
- if e1 != 0 {
- err = 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_SETREGID32, uintptr(rgid), uintptr(egid), 0)
if e1 != 0 {
@@ -1621,6 +1649,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1646,6 +1675,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall(SYS_TRUNCATE64, uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_linux_amd64.go b/src/syscall/zsyscall_linux_amd64.go
index c65448e21..ed3afd4e0 100644
--- a/src/pkg/syscall/zsyscall_linux_amd64.go
+++ b/src/syscall/zsyscall_linux_amd64.go
@@ -14,6 +14,7 @@ func open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -30,6 +31,7 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
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 = e1
@@ -66,6 +68,7 @@ func utimes(path string, times *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -81,6 +84,7 @@ func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -144,6 +148,7 @@ func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
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 = e1
}
@@ -169,6 +174,9 @@ func mount(source string, target string, fstype string, flags uintptr, data *byt
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 = e1
}
@@ -184,6 +192,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -199,6 +208,7 @@ func Acct(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -225,6 +235,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -240,6 +251,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -255,6 +267,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -280,6 +293,7 @@ func Creat(path string, mode uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -383,6 +397,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
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 = e1
}
@@ -428,6 +443,7 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
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 = e1
}
@@ -443,6 +459,7 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
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 = e1
}
@@ -591,6 +608,8 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
_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 = e1
@@ -607,6 +626,7 @@ func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err e
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 = e1
@@ -688,6 +708,8 @@ func Link(oldpath string, newpath string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -709,6 +731,7 @@ func Listxattr(path string, dest []byte) (sz int, err error) {
_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 = e1
@@ -725,6 +748,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -740,6 +764,7 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -755,6 +780,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -770,6 +796,7 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
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 = e1
}
@@ -810,6 +837,8 @@ func PivotRoot(newroot string, putold string) (err error) {
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 = e1
}
@@ -858,6 +887,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -879,6 +909,8 @@ func Removexattr(path string, attr string) (err error) {
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 = e1
}
@@ -899,6 +931,8 @@ func Rename(oldpath string, newpath string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -919,6 +953,8 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e
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 = e1
}
@@ -934,6 +970,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1005,16 +1042,6 @@ func Settimeofday(tv *Timeval) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Setuid(uid int) (err error) {
- _, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
- if e1 != 0 {
- err = 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 {
@@ -1043,6 +1070,8 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
_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 = e1
}
@@ -1063,6 +1092,8 @@ func Symlink(oldpath string, newpath string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1145,6 +1176,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1160,6 +1192,7 @@ func Unlinkat(dirfd int, path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1175,6 +1208,7 @@ func Unmount(target string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1210,6 +1244,7 @@ func Utime(path string, buf *Utimbuf) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1368,6 +1403,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1485,6 +1521,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1510,6 +1547,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1605,16 +1643,6 @@ func Setfsuid(uid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Setgid(gid int) (err error) {
- _, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)
- if e1 != 0 {
- err = 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 {
@@ -1693,6 +1721,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1708,6 +1737,7 @@ func Statfs(path string, buf *Statfs_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1733,6 +1763,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_linux_arm.go b/src/syscall/zsyscall_linux_arm.go
index a970ce6dc..fbf69350d 100644
--- a/src/pkg/syscall/zsyscall_linux_arm.go
+++ b/src/syscall/zsyscall_linux_arm.go
@@ -14,6 +14,7 @@ func open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -30,6 +31,7 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
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 = e1
@@ -66,6 +68,7 @@ func utimes(path string, times *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -81,6 +84,7 @@ func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -144,6 +148,7 @@ func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
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 = e1
}
@@ -169,6 +174,9 @@ func mount(source string, target string, fstype string, flags uintptr, data *byt
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 = e1
}
@@ -184,6 +192,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -199,6 +208,7 @@ func Acct(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -225,6 +235,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -240,6 +251,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -255,6 +267,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -280,6 +293,7 @@ func Creat(path string, mode uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -383,6 +397,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
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 = e1
}
@@ -428,6 +443,7 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
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 = e1
}
@@ -443,6 +459,7 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
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 = e1
}
@@ -591,6 +608,8 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
_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 = e1
@@ -607,6 +626,7 @@ func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err e
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 = e1
@@ -688,6 +708,8 @@ func Link(oldpath string, newpath string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -709,6 +731,7 @@ func Listxattr(path string, dest []byte) (sz int, err error) {
_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 = e1
@@ -725,6 +748,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -740,6 +764,7 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -755,6 +780,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -770,6 +796,7 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
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 = e1
}
@@ -810,6 +837,8 @@ func PivotRoot(newroot string, putold string) (err error) {
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 = e1
}
@@ -858,6 +887,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -879,6 +909,8 @@ func Removexattr(path string, attr string) (err error) {
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 = e1
}
@@ -899,6 +931,8 @@ func Rename(oldpath string, newpath string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -919,6 +953,8 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e
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 = e1
}
@@ -934,6 +970,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1005,16 +1042,6 @@ func Settimeofday(tv *Timeval) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Setuid(uid int) (err error) {
- _, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
- if e1 != 0 {
- err = 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 {
@@ -1043,6 +1070,8 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
_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 = e1
}
@@ -1063,6 +1092,8 @@ func Symlink(oldpath string, newpath string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1145,6 +1176,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1160,6 +1192,7 @@ func Unlinkat(dirfd int, path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1175,6 +1208,7 @@ func Unmount(target string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1210,6 +1244,7 @@ func Utime(path string, buf *Utimbuf) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1547,6 +1582,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN32, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1614,6 +1650,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN32, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1639,6 +1676,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1689,16 +1727,6 @@ func Setfsuid(uid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Setgid(gid int) (err error) {
- _, _, e1 := RawSyscall(SYS_SETGID32, uintptr(gid), 0, 0)
- if e1 != 0 {
- err = 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_SETREGID32, uintptr(rgid), uintptr(egid), 0)
if e1 != 0 {
@@ -1767,6 +1795,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1837,6 +1866,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall6(SYS_TRUNCATE64, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_nacl_386.go b/src/syscall/zsyscall_nacl_386.go
index 32eed339a..32eed339a 100644
--- a/src/pkg/syscall/zsyscall_nacl_386.go
+++ b/src/syscall/zsyscall_nacl_386.go
diff --git a/src/pkg/syscall/zsyscall_nacl_amd64p32.go b/src/syscall/zsyscall_nacl_amd64p32.go
index 8bc81fac9..8bc81fac9 100644
--- a/src/pkg/syscall/zsyscall_nacl_amd64p32.go
+++ b/src/syscall/zsyscall_nacl_amd64p32.go
diff --git a/src/syscall/zsyscall_nacl_arm.go b/src/syscall/zsyscall_nacl_arm.go
new file mode 100644
index 000000000..adbaed0e7
--- /dev/null
+++ b/src/syscall/zsyscall_nacl_arm.go
@@ -0,0 +1,63 @@
+// mksyscall.pl -l32 -nacl -arm syscall_nacl.go syscall_nacl_arm.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 naclClose(fd int) (err error) {
+ _, _, e1 := Syscall(sys_close, uintptr(fd), 0, 0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Exit(code int) (err error) {
+ _, _, e1 := Syscall(sys_exit, uintptr(code), 0, 0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func naclFstat(fd int, stat *Stat_t) (err error) {
+ _, _, e1 := Syscall(sys_fstat, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func naclRead(fd int, b []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(b) > 0 {
+ _p0 = unsafe.Pointer(&b[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(sys_read, uintptr(fd), uintptr(_p0), uintptr(len(b)))
+ n = int(r0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func naclSeek(fd int, off *int64, whence int) (err error) {
+ _, _, e1 := Syscall(sys_lseek, uintptr(fd), uintptr(unsafe.Pointer(off)), uintptr(whence))
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
diff --git a/src/pkg/syscall/zsyscall_netbsd_386.go b/src/syscall/zsyscall_netbsd_386.go
index 281208f41..e9bd3d0f6 100644
--- a/src/pkg/syscall/zsyscall_netbsd_386.go
+++ b/src/syscall/zsyscall_netbsd_386.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -295,6 +296,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -320,6 +322,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -335,6 +338,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -350,6 +354,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -365,6 +370,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -380,6 +386,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -672,6 +679,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -692,6 +700,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -717,6 +727,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -732,6 +743,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -747,6 +759,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -762,6 +775,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -787,6 +801,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -803,6 +818,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -876,6 +892,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -897,6 +914,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -912,6 +931,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -927,6 +947,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1074,6 +1095,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1094,6 +1116,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1119,6 +1143,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1142,6 +1167,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1157,6 +1183,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_netbsd_amd64.go b/src/syscall/zsyscall_netbsd_amd64.go
index ed9a87df6..1acd7c273 100644
--- a/src/pkg/syscall/zsyscall_netbsd_amd64.go
+++ b/src/syscall/zsyscall_netbsd_amd64.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -295,6 +296,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -320,6 +322,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -335,6 +338,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -350,6 +354,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -365,6 +370,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -380,6 +386,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -672,6 +679,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -692,6 +700,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -717,6 +727,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -732,6 +743,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -747,6 +759,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -762,6 +775,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -787,6 +801,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -803,6 +818,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -876,6 +892,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -897,6 +914,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -912,6 +931,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -927,6 +947,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1074,6 +1095,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1094,6 +1116,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1119,6 +1143,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1142,6 +1167,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1157,6 +1183,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_netbsd_arm.go b/src/syscall/zsyscall_netbsd_arm.go
index c5c9a9f2c..898e0ce80 100644
--- a/src/pkg/syscall/zsyscall_netbsd_arm.go
+++ b/src/syscall/zsyscall_netbsd_arm.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -295,6 +296,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -320,6 +322,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -335,6 +338,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -350,6 +354,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -365,6 +370,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -380,6 +386,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -672,6 +679,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -692,6 +700,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -717,6 +727,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -732,6 +743,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -747,6 +759,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -762,6 +775,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -787,6 +801,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -803,6 +818,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -876,6 +892,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -897,6 +914,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -912,6 +931,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -927,6 +947,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1074,6 +1095,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1094,6 +1116,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1119,6 +1143,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1142,6 +1167,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1157,6 +1183,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_openbsd_386.go b/src/syscall/zsyscall_openbsd_386.go
index 785e7c3b8..5b005d2dc 100644
--- a/src/pkg/syscall/zsyscall_openbsd_386.go
+++ b/src/syscall/zsyscall_openbsd_386.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -293,6 +294,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -318,6 +320,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -333,6 +336,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -348,6 +352,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -363,6 +368,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -378,6 +384,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -680,6 +687,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -700,6 +708,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -725,6 +735,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -740,6 +751,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -755,6 +767,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -770,6 +783,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -795,6 +809,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -811,6 +826,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -884,6 +900,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -905,6 +922,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -920,6 +939,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -935,6 +955,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1001,6 +1022,7 @@ func Setlogin(name string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1097,6 +1119,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1112,6 +1135,7 @@ func Statfs(path string, stat *Statfs_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1132,6 +1156,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1157,6 +1183,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1180,6 +1207,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1195,6 +1223,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_openbsd_amd64.go b/src/syscall/zsyscall_openbsd_amd64.go
index 7a8d9b6f1..ce9397bca 100644
--- a/src/pkg/syscall/zsyscall_openbsd_amd64.go
+++ b/src/syscall/zsyscall_openbsd_amd64.go
@@ -230,6 +230,7 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
return
}
_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -293,6 +294,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -318,6 +320,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -333,6 +336,7 @@ func Chflags(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -348,6 +352,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -363,6 +368,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -378,6 +384,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -680,6 +687,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -700,6 +708,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -725,6 +735,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -740,6 +751,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -755,6 +767,7 @@ func Mkfifo(path string, mode uint32) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -770,6 +783,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -795,6 +809,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -811,6 +826,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -884,6 +900,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -905,6 +922,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -920,6 +939,7 @@ func Revoke(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -935,6 +955,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1001,6 +1022,7 @@ func Setlogin(name string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1097,6 +1119,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1112,6 +1135,7 @@ func Statfs(path string, stat *Statfs_t) (err error) {
return
}
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1132,6 +1156,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -1157,6 +1183,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length))
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1180,6 +1207,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -1195,6 +1223,7 @@ func Unmount(path string, flags int) (err error) {
return
}
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_plan9_386.go b/src/syscall/zsyscall_plan9_386.go
index 5ffa0e439..44b74d71c 100644
--- a/src/pkg/syscall/zsyscall_plan9_386.go
+++ b/src/syscall/zsyscall_plan9_386.go
@@ -1,4 +1,4 @@
-// mksyscall.pl -l32 -plan9 syscall_plan9.go syscall_plan9_386.go
+// mksyscall.pl -l32 -plan9 syscall_plan9.go
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package syscall
@@ -15,7 +15,7 @@ func fd2path(fd int, buf []byte) (err error) {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
@@ -25,7 +25,7 @@ func fd2path(fd int, buf []byte) (err error) {
func pipe(p *[2]_C_int) (err error) {
r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
@@ -42,7 +42,7 @@ func await(s []byte) (n int, err error) {
}
r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
n = int(r0)
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
@@ -53,7 +53,7 @@ func await(s []byte) (n int, err error) {
func Dup(oldfd int, newfd int) (fd int, err error) {
r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
fd = int(r0)
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
@@ -68,8 +68,9 @@ func Open(path string, mode int) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
fd = int(r0)
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
@@ -84,8 +85,9 @@ func Create(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
@@ -100,7 +102,8 @@ func Remove(path string) (err error) {
return
}
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
- if int(r0) == -1 {
+ use(unsafe.Pointer(_p0))
+ if int32(r0) == -1 {
err = e1
}
return
@@ -117,7 +120,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
}
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
@@ -134,7 +137,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
}
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
@@ -144,7 +147,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
func Close(fd int) (err error) {
r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
@@ -159,7 +162,8 @@ func Chdir(path string) (err error) {
return
}
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
- if int(r0) == -1 {
+ use(unsafe.Pointer(_p0))
+ if int32(r0) == -1 {
err = e1
}
return
@@ -179,7 +183,9 @@ func Bind(name string, old string, flag int) (err error) {
return
}
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
- if int(r0) == -1 {
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if int32(r0) == -1 {
err = e1
}
return
@@ -199,7 +205,9 @@ func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
return
}
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
- if int(r0) == -1 {
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if int32(r0) == -1 {
err = e1
}
return
@@ -220,8 +228,9 @@ func Stat(path string, edir []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
@@ -238,7 +247,7 @@ func Fstat(fd int, edir []byte) (n int, err error) {
}
r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
n = int(r0)
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
@@ -259,7 +268,8 @@ func Wstat(path string, edir []byte) (err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
- if int(r0) == -1 {
+ use(unsafe.Pointer(_p0))
+ if int32(r0) == -1 {
err = e1
}
return
@@ -275,7 +285,7 @@ func Fwstat(fd int, edir []byte) (err error) {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
- if int(r0) == -1 {
+ if int32(r0) == -1 {
err = e1
}
return
diff --git a/src/pkg/syscall/zsyscall_plan9_amd64.go b/src/syscall/zsyscall_plan9_amd64.go
index c64533f49..44b74d71c 100644
--- a/src/pkg/syscall/zsyscall_plan9_amd64.go
+++ b/src/syscall/zsyscall_plan9_amd64.go
@@ -1,4 +1,4 @@
-// mksyscall.pl -l32 -plan9 syscall_plan9.go syscall_plan9_amd64.go
+// mksyscall.pl -l32 -plan9 syscall_plan9.go
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package syscall
@@ -68,6 +68,7 @@ func Open(path string, mode int) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if int32(r0) == -1 {
err = e1
@@ -84,6 +85,7 @@ func Create(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if int32(r0) == -1 {
err = e1
@@ -100,6 +102,7 @@ func Remove(path string) (err error) {
return
}
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if int32(r0) == -1 {
err = e1
}
@@ -159,6 +162,7 @@ func Chdir(path string) (err error) {
return
}
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
if int32(r0) == -1 {
err = e1
}
@@ -179,6 +183,8 @@ func Bind(name string, old string, flag int) (err error) {
return
}
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if int32(r0) == -1 {
err = e1
}
@@ -199,6 +205,8 @@ func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
return
}
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if int32(r0) == -1 {
err = e1
}
@@ -220,6 +228,7 @@ func Stat(path string, edir []byte) (n int, err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+ use(unsafe.Pointer(_p0))
n = int(r0)
if int32(r0) == -1 {
err = e1
@@ -259,6 +268,7 @@ func Wstat(path string, edir []byte) (err error) {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+ use(unsafe.Pointer(_p0))
if int32(r0) == -1 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_solaris_amd64.go b/src/syscall/zsyscall_solaris_amd64.go
index 8847cad01..43b224a7b 100644
--- a/src/pkg/syscall/zsyscall_solaris_amd64.go
+++ b/src/syscall/zsyscall_solaris_amd64.go
@@ -142,6 +142,7 @@ func Access(path string, mode uint32) (err error) {
return
}
_, _, e1 := sysvicall6(procAccess.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -163,6 +164,7 @@ func Chdir(path string) (err error) {
return
}
_, _, e1 := sysvicall6(procChdir.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -176,6 +178,7 @@ func Chmod(path string, mode uint32) (err error) {
return
}
_, _, e1 := sysvicall6(procChmod.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -189,6 +192,7 @@ func Chown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := sysvicall6(procChown.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -202,6 +206,7 @@ func Chroot(path string) (err error) {
return
}
_, _, e1 := sysvicall6(procChroot.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -360,6 +365,7 @@ func Lchown(path string, uid int, gid int) (err error) {
return
}
_, _, e1 := sysvicall6(procLchown.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -378,6 +384,8 @@ func Link(path string, link string) (err error) {
return
}
_, _, e1 := sysvicall6(procLink.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -399,6 +407,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := sysvicall6(procLstat.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -412,6 +421,7 @@ func Mkdir(path string, mode uint32) (err error) {
return
}
_, _, e1 := sysvicall6(procMkdir.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -425,6 +435,7 @@ func Mknod(path string, mode uint32, dev int) (err error) {
return
}
_, _, e1 := sysvicall6(procMknod.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -446,6 +457,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return
}
r0, _, e1 := sysvicall6(procOpen.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0, 0)
+ use(unsafe.Pointer(_p0))
fd = int(r0)
if e1 != 0 {
err = e1
@@ -460,6 +472,7 @@ func Pathconf(path string, name int) (val int, err error) {
return
}
r0, _, e1 := sysvicall6(procPathconf.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
val = int(r0)
if e1 != 0 {
err = e1
@@ -517,6 +530,7 @@ func Readlink(path string, buf []byte) (n int, err error) {
_p1 = &buf[0]
}
r0, _, e1 := sysvicall6(procReadlink.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(len(buf)), 0, 0, 0)
+ use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1
@@ -536,6 +550,8 @@ func Rename(from string, to string) (err error) {
return
}
_, _, e1 := sysvicall6(procRename.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -549,6 +565,7 @@ func Rmdir(path string) (err error) {
return
}
_, _, e1 := sysvicall6(procRmdir.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -660,6 +677,7 @@ func Stat(path string, stat *Stat_t) (err error) {
return
}
_, _, e1 := sysvicall6(procStat.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -678,6 +696,8 @@ func Symlink(path string, link string) (err error) {
return
}
_, _, e1 := sysvicall6(procSymlink.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
if e1 != 0 {
err = e1
}
@@ -699,6 +719,7 @@ func Truncate(path string, length int64) (err error) {
return
}
_, _, e1 := sysvicall6(procTruncate.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -734,6 +755,7 @@ func Unlink(path string) (err error) {
return
}
_, _, e1 := sysvicall6(procUnlink.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
@@ -747,6 +769,7 @@ func Utimes(path string, times *[2]Timeval) (err error) {
return
}
_, _, e1 := sysvicall6(procUtimes.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0, 0, 0, 0)
+ use(unsafe.Pointer(_p0))
if e1 != 0 {
err = e1
}
diff --git a/src/pkg/syscall/zsyscall_windows_amd64.go b/src/syscall/zsyscall_windows.go
index 353a6fd98..afc28f993 100644
--- a/src/pkg/syscall/zsyscall_windows_amd64.go
+++ b/src/syscall/zsyscall_windows.go
@@ -1,4 +1,4 @@
-// go build mksyscall_windows.go && ./mksyscall_windows syscall_windows.go security_windows.go syscall_windows_amd64.go
+// go build mksyscall_windows.go && ./mksyscall_windows syscall_windows.go security_windows.go
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package syscall
@@ -108,6 +108,12 @@ var (
procGetConsoleMode = modkernel32.NewProc("GetConsoleMode")
procWriteConsoleW = modkernel32.NewProc("WriteConsoleW")
procReadConsoleW = modkernel32.NewProc("ReadConsoleW")
+ procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot")
+ procProcess32FirstW = modkernel32.NewProc("Process32FirstW")
+ procProcess32NextW = modkernel32.NewProc("Process32NextW")
+ procDeviceIoControl = modkernel32.NewProc("DeviceIoControl")
+ procCreateSymbolicLinkW = modkernel32.NewProc("CreateSymbolicLinkW")
+ procCreateHardLinkW = modkernel32.NewProc("CreateHardLinkW")
procWSAStartup = modws2_32.NewProc("WSAStartup")
procWSACleanup = modws2_32.NewProc("WSACleanup")
procWSAIoctl = modws2_32.NewProc("WSAIoctl")
@@ -133,6 +139,7 @@ var (
procgetprotobyname = modws2_32.NewProc("getprotobyname")
procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W")
procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree")
+ procDnsNameCompare_W = moddnsapi.NewProc("DnsNameCompare_W")
procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW")
procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW")
procGetIfEntry = modiphlpapi.NewProc("GetIfEntry")
@@ -169,7 +176,11 @@ func LoadLibrary(libname string) (handle Handle, err error) {
if err != nil {
return
}
- r0, _, e1 := Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ return _LoadLibrary(_p0)
+}
+
+func _LoadLibrary(libname *uint16) (handle Handle, err error) {
+ r0, _, e1 := Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(libname)), 0, 0)
handle = Handle(r0)
if handle == 0 {
if e1 != 0 {
@@ -199,7 +210,11 @@ func GetProcAddress(module Handle, procname string) (proc uintptr, err error) {
if err != nil {
return
}
- r0, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(_p0)), 0)
+ return _GetProcAddress(module, _p0)
+}
+
+func _GetProcAddress(module Handle, procname *byte) (proc uintptr, err error) {
+ r0, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(procname)), 0)
proc = uintptr(r0)
if proc == 0 {
if e1 != 0 {
@@ -1254,6 +1269,79 @@ func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, input
return
}
+func CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) {
+ r0, _, e1 := Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processId), 0)
+ handle = Handle(r0)
+ if handle == InvalidHandle {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = EINVAL
+ }
+ }
+ return
+}
+
+func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) {
+ r1, _, e1 := Syscall(procProcess32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = EINVAL
+ }
+ }
+ return
+}
+
+func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) {
+ r1, _, e1 := Syscall(procProcess32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = EINVAL
+ }
+ }
+ return
+}
+
+func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) {
+ r1, _, e1 := Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), uintptr(ioControlCode), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferSize), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferSize), uintptr(unsafe.Pointer(bytesReturned)), uintptr(unsafe.Pointer(overlapped)), 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = EINVAL
+ }
+ }
+ return
+}
+
+func CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) {
+ r1, _, e1 := Syscall(procCreateSymbolicLinkW.Addr(), 3, uintptr(unsafe.Pointer(symlinkfilename)), uintptr(unsafe.Pointer(targetfilename)), uintptr(flags))
+ if r1&0xff == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = EINVAL
+ }
+ }
+ return
+}
+
+func CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) {
+ r1, _, e1 := Syscall(procCreateHardLinkW.Addr(), 3, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(existingfilename)), uintptr(reserved))
+ if r1&0xff == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = EINVAL
+ }
+ }
+ return
+}
+
func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
r0, _, _ := Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
if r0 != 0 {
@@ -1478,7 +1566,11 @@ func GetHostByName(name string) (h *Hostent, err error) {
if err != nil {
return
}
- r0, _, e1 := Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ return _GetHostByName(_p0)
+}
+
+func _GetHostByName(name *byte) (h *Hostent, err error) {
+ r0, _, e1 := Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0)
h = (*Hostent)(unsafe.Pointer(r0))
if h == nil {
if e1 != 0 {
@@ -1501,7 +1593,11 @@ func GetServByName(name string, proto string) (s *Servent, err error) {
if err != nil {
return
}
- r0, _, e1 := Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ return _GetServByName(_p0, _p1)
+}
+
+func _GetServByName(name *byte, proto *byte) (s *Servent, err error) {
+ r0, _, e1 := Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(proto)), 0)
s = (*Servent)(unsafe.Pointer(r0))
if s == nil {
if e1 != 0 {
@@ -1525,7 +1621,11 @@ func GetProtoByName(name string) (p *Protoent, err error) {
if err != nil {
return
}
- r0, _, e1 := Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ return _GetProtoByName(_p0)
+}
+
+func _GetProtoByName(name *byte) (p *Protoent, err error) {
+ r0, _, e1 := Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0)
p = (*Protoent)(unsafe.Pointer(r0))
if p == nil {
if e1 != 0 {
@@ -1543,7 +1643,11 @@ func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSR
if status != nil {
return
}
- r0, _, _ := Syscall6(procDnsQuery_W.Addr(), 6, uintptr(unsafe.Pointer(_p0)), uintptr(qtype), uintptr(options), uintptr(unsafe.Pointer(extra)), uintptr(unsafe.Pointer(qrs)), uintptr(unsafe.Pointer(pr)))
+ return _DnsQuery(_p0, qtype, options, extra, qrs, pr)
+}
+
+func _DnsQuery(name *uint16, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) {
+ r0, _, _ := Syscall6(procDnsQuery_W.Addr(), 6, uintptr(unsafe.Pointer(name)), uintptr(qtype), uintptr(options), uintptr(unsafe.Pointer(extra)), uintptr(unsafe.Pointer(qrs)), uintptr(unsafe.Pointer(pr)))
if r0 != 0 {
status = Errno(r0)
}
@@ -1555,6 +1659,12 @@ func DnsRecordListFree(rl *DNSRecord, freetype uint32) {
return
}
+func DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) {
+ r0, _, _ := Syscall(procDnsNameCompare_W.Addr(), 2, uintptr(unsafe.Pointer(name1)), uintptr(unsafe.Pointer(name2)), 0)
+ same = r0 != 0
+ return
+}
+
func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) {
r0, _, _ := Syscall6(procGetAddrInfoW.Addr(), 4, uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result)), 0, 0)
if r0 != 0 {
diff --git a/src/pkg/syscall/zsysctl_openbsd.go b/src/syscall/zsysctl_openbsd.go
index 923b2c29f..923b2c29f 100644
--- a/src/pkg/syscall/zsysctl_openbsd.go
+++ b/src/syscall/zsysctl_openbsd.go
diff --git a/src/pkg/syscall/zsysnum_darwin_386.go b/src/syscall/zsysnum_darwin_386.go
index abdef7743..abdef7743 100644
--- a/src/pkg/syscall/zsysnum_darwin_386.go
+++ b/src/syscall/zsysnum_darwin_386.go
diff --git a/src/pkg/syscall/zsysnum_darwin_amd64.go b/src/syscall/zsysnum_darwin_amd64.go
index abdef7743..abdef7743 100644
--- a/src/pkg/syscall/zsysnum_darwin_amd64.go
+++ b/src/syscall/zsysnum_darwin_amd64.go
diff --git a/src/pkg/syscall/zsysnum_dragonfly_386.go b/src/syscall/zsysnum_dragonfly_386.go
index 4b086b921..4b086b921 100644
--- a/src/pkg/syscall/zsysnum_dragonfly_386.go
+++ b/src/syscall/zsysnum_dragonfly_386.go
diff --git a/src/pkg/syscall/zsysnum_dragonfly_amd64.go b/src/syscall/zsysnum_dragonfly_amd64.go
index 4b086b921..4b086b921 100644
--- a/src/pkg/syscall/zsysnum_dragonfly_amd64.go
+++ b/src/syscall/zsysnum_dragonfly_amd64.go
diff --git a/src/pkg/syscall/zsysnum_freebsd_386.go b/src/syscall/zsysnum_freebsd_386.go
index dfca558bb..dfca558bb 100644
--- a/src/pkg/syscall/zsysnum_freebsd_386.go
+++ b/src/syscall/zsysnum_freebsd_386.go
diff --git a/src/pkg/syscall/zsysnum_freebsd_amd64.go b/src/syscall/zsysnum_freebsd_amd64.go
index dfca558bb..dfca558bb 100644
--- a/src/pkg/syscall/zsysnum_freebsd_amd64.go
+++ b/src/syscall/zsysnum_freebsd_amd64.go
diff --git a/src/pkg/syscall/zsysnum_freebsd_arm.go b/src/syscall/zsysnum_freebsd_arm.go
index dfca558bb..dfca558bb 100644
--- a/src/pkg/syscall/zsysnum_freebsd_arm.go
+++ b/src/syscall/zsysnum_freebsd_arm.go
diff --git a/src/pkg/syscall/zsysnum_linux_386.go b/src/syscall/zsysnum_linux_386.go
index c40b5f1ac..c40b5f1ac 100644
--- a/src/pkg/syscall/zsysnum_linux_386.go
+++ b/src/syscall/zsysnum_linux_386.go
diff --git a/src/pkg/syscall/zsysnum_linux_amd64.go b/src/syscall/zsysnum_linux_amd64.go
index 7cf70a4d8..7cf70a4d8 100644
--- a/src/pkg/syscall/zsysnum_linux_amd64.go
+++ b/src/syscall/zsysnum_linux_amd64.go
diff --git a/src/pkg/syscall/zsysnum_linux_arm.go b/src/syscall/zsysnum_linux_arm.go
index 7068e4e21..7068e4e21 100644
--- a/src/pkg/syscall/zsysnum_linux_arm.go
+++ b/src/syscall/zsysnum_linux_arm.go
diff --git a/src/pkg/syscall/zsysnum_netbsd_386.go b/src/syscall/zsysnum_netbsd_386.go
index c57096523..c57096523 100644
--- a/src/pkg/syscall/zsysnum_netbsd_386.go
+++ b/src/syscall/zsysnum_netbsd_386.go
diff --git a/src/pkg/syscall/zsysnum_netbsd_amd64.go b/src/syscall/zsysnum_netbsd_amd64.go
index c57096523..c57096523 100644
--- a/src/pkg/syscall/zsysnum_netbsd_amd64.go
+++ b/src/syscall/zsysnum_netbsd_amd64.go
diff --git a/src/pkg/syscall/zsysnum_netbsd_arm.go b/src/syscall/zsysnum_netbsd_arm.go
index c57096523..c57096523 100644
--- a/src/pkg/syscall/zsysnum_netbsd_arm.go
+++ b/src/syscall/zsysnum_netbsd_arm.go
diff --git a/src/pkg/syscall/zsysnum_openbsd_386.go b/src/syscall/zsysnum_openbsd_386.go
index 3b9ac4c94..3b9ac4c94 100644
--- a/src/pkg/syscall/zsysnum_openbsd_386.go
+++ b/src/syscall/zsysnum_openbsd_386.go
diff --git a/src/pkg/syscall/zsysnum_openbsd_amd64.go b/src/syscall/zsysnum_openbsd_amd64.go
index 3b9ac4c94..3b9ac4c94 100644
--- a/src/pkg/syscall/zsysnum_openbsd_amd64.go
+++ b/src/syscall/zsysnum_openbsd_amd64.go
diff --git a/src/syscall/zsysnum_plan9_386.go b/src/syscall/zsysnum_plan9_386.go
new file mode 100644
index 000000000..07498c489
--- /dev/null
+++ b/src/syscall/zsysnum_plan9_386.go
@@ -0,0 +1,49 @@
+// mksysnum_plan9.sh /media/sys/src/libc/9syscall/sys.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+ SYS_SYSR1 = 0
+ SYS_BIND = 2
+ SYS_CHDIR = 3
+ SYS_CLOSE = 4
+ SYS_DUP = 5
+ SYS_ALARM = 6
+ SYS_EXEC = 7
+ SYS_EXITS = 8
+ SYS_FAUTH = 10
+ SYS_SEGBRK = 12
+ SYS_OPEN = 14
+ SYS_OSEEK = 16
+ SYS_SLEEP = 17
+ SYS_RFORK = 19
+ SYS_PIPE = 21
+ SYS_CREATE = 22
+ SYS_FD2PATH = 23
+ SYS_BRK_ = 24
+ SYS_REMOVE = 25
+ SYS_NOTIFY = 28
+ SYS_NOTED = 29
+ SYS_SEGATTACH = 30
+ SYS_SEGDETACH = 31
+ SYS_SEGFREE = 32
+ SYS_SEGFLUSH = 33
+ SYS_RENDEZVOUS = 34
+ SYS_UNMOUNT = 35
+ SYS_SEMACQUIRE = 37
+ SYS_SEMRELEASE = 38
+ SYS_SEEK = 39
+ SYS_FVERSION = 40
+ SYS_ERRSTR = 41
+ SYS_STAT = 42
+ SYS_FSTAT = 43
+ SYS_WSTAT = 44
+ SYS_FWSTAT = 45
+ SYS_MOUNT = 46
+ SYS_AWAIT = 47
+ SYS_PREAD = 50
+ SYS_PWRITE = 51
+ SYS_TSEMACQUIRE = 52
+ SYS_NSEC = 53
+)
diff --git a/src/syscall/zsysnum_plan9_amd64.go b/src/syscall/zsysnum_plan9_amd64.go
new file mode 100644
index 000000000..07498c489
--- /dev/null
+++ b/src/syscall/zsysnum_plan9_amd64.go
@@ -0,0 +1,49 @@
+// mksysnum_plan9.sh /media/sys/src/libc/9syscall/sys.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+ SYS_SYSR1 = 0
+ SYS_BIND = 2
+ SYS_CHDIR = 3
+ SYS_CLOSE = 4
+ SYS_DUP = 5
+ SYS_ALARM = 6
+ SYS_EXEC = 7
+ SYS_EXITS = 8
+ SYS_FAUTH = 10
+ SYS_SEGBRK = 12
+ SYS_OPEN = 14
+ SYS_OSEEK = 16
+ SYS_SLEEP = 17
+ SYS_RFORK = 19
+ SYS_PIPE = 21
+ SYS_CREATE = 22
+ SYS_FD2PATH = 23
+ SYS_BRK_ = 24
+ SYS_REMOVE = 25
+ SYS_NOTIFY = 28
+ SYS_NOTED = 29
+ SYS_SEGATTACH = 30
+ SYS_SEGDETACH = 31
+ SYS_SEGFREE = 32
+ SYS_SEGFLUSH = 33
+ SYS_RENDEZVOUS = 34
+ SYS_UNMOUNT = 35
+ SYS_SEMACQUIRE = 37
+ SYS_SEMRELEASE = 38
+ SYS_SEEK = 39
+ SYS_FVERSION = 40
+ SYS_ERRSTR = 41
+ SYS_STAT = 42
+ SYS_FSTAT = 43
+ SYS_WSTAT = 44
+ SYS_FWSTAT = 45
+ SYS_MOUNT = 46
+ SYS_AWAIT = 47
+ SYS_PREAD = 50
+ SYS_PWRITE = 51
+ SYS_TSEMACQUIRE = 52
+ SYS_NSEC = 53
+)
diff --git a/src/pkg/syscall/zsysnum_solaris_amd64.go b/src/syscall/zsysnum_solaris_amd64.go
index 43b3d8b40..43b3d8b40 100644
--- a/src/pkg/syscall/zsysnum_solaris_amd64.go
+++ b/src/syscall/zsysnum_solaris_amd64.go
diff --git a/src/pkg/syscall/zsysnum_windows_386.go b/src/syscall/zsysnum_windows_386.go
index 36bf065d1..36bf065d1 100644
--- a/src/pkg/syscall/zsysnum_windows_386.go
+++ b/src/syscall/zsysnum_windows_386.go
diff --git a/src/pkg/syscall/zsysnum_windows_amd64.go b/src/syscall/zsysnum_windows_amd64.go
index 36bf065d1..36bf065d1 100644
--- a/src/pkg/syscall/zsysnum_windows_amd64.go
+++ b/src/syscall/zsysnum_windows_amd64.go
diff --git a/src/pkg/syscall/ztypes_darwin_386.go b/src/syscall/ztypes_darwin_386.go
index 13724c3cc..13724c3cc 100644
--- a/src/pkg/syscall/ztypes_darwin_386.go
+++ b/src/syscall/ztypes_darwin_386.go
diff --git a/src/pkg/syscall/ztypes_darwin_amd64.go b/src/syscall/ztypes_darwin_amd64.go
index 65b02ae4f..65b02ae4f 100644
--- a/src/pkg/syscall/ztypes_darwin_amd64.go
+++ b/src/syscall/ztypes_darwin_amd64.go
diff --git a/src/pkg/syscall/ztypes_dragonfly_386.go b/src/syscall/ztypes_dragonfly_386.go
index 6b6ec1525..6b6ec1525 100644
--- a/src/pkg/syscall/ztypes_dragonfly_386.go
+++ b/src/syscall/ztypes_dragonfly_386.go
diff --git a/src/pkg/syscall/ztypes_dragonfly_amd64.go b/src/syscall/ztypes_dragonfly_amd64.go
index 954ffd7ab..954ffd7ab 100644
--- a/src/pkg/syscall/ztypes_dragonfly_amd64.go
+++ b/src/syscall/ztypes_dragonfly_amd64.go
diff --git a/src/pkg/syscall/ztypes_freebsd_386.go b/src/syscall/ztypes_freebsd_386.go
index b809eea37..b809eea37 100644
--- a/src/pkg/syscall/ztypes_freebsd_386.go
+++ b/src/syscall/ztypes_freebsd_386.go
diff --git a/src/pkg/syscall/ztypes_freebsd_amd64.go b/src/syscall/ztypes_freebsd_amd64.go
index a05908aed..a05908aed 100644
--- a/src/pkg/syscall/ztypes_freebsd_amd64.go
+++ b/src/syscall/ztypes_freebsd_amd64.go
diff --git a/src/pkg/syscall/ztypes_freebsd_arm.go b/src/syscall/ztypes_freebsd_arm.go
index 9303816f9..9303816f9 100644
--- a/src/pkg/syscall/ztypes_freebsd_arm.go
+++ b/src/syscall/ztypes_freebsd_arm.go
diff --git a/src/pkg/syscall/ztypes_linux_386.go b/src/syscall/ztypes_linux_386.go
index daecb1ded..daecb1ded 100644
--- a/src/pkg/syscall/ztypes_linux_386.go
+++ b/src/syscall/ztypes_linux_386.go
diff --git a/src/pkg/syscall/ztypes_linux_amd64.go b/src/syscall/ztypes_linux_amd64.go
index 694fe1eac..694fe1eac 100644
--- a/src/pkg/syscall/ztypes_linux_amd64.go
+++ b/src/syscall/ztypes_linux_amd64.go
diff --git a/src/pkg/syscall/ztypes_linux_arm.go b/src/syscall/ztypes_linux_arm.go
index 5f21a948d..5f21a948d 100644
--- a/src/pkg/syscall/ztypes_linux_arm.go
+++ b/src/syscall/ztypes_linux_arm.go
diff --git a/src/pkg/syscall/ztypes_netbsd_386.go b/src/syscall/ztypes_netbsd_386.go
index 6add325a3..6add325a3 100644
--- a/src/pkg/syscall/ztypes_netbsd_386.go
+++ b/src/syscall/ztypes_netbsd_386.go
diff --git a/src/pkg/syscall/ztypes_netbsd_amd64.go b/src/syscall/ztypes_netbsd_amd64.go
index 4451fc1f0..4451fc1f0 100644
--- a/src/pkg/syscall/ztypes_netbsd_amd64.go
+++ b/src/syscall/ztypes_netbsd_amd64.go
diff --git a/src/pkg/syscall/ztypes_netbsd_arm.go b/src/syscall/ztypes_netbsd_arm.go
index 4e853eaa2..4e853eaa2 100644
--- a/src/pkg/syscall/ztypes_netbsd_arm.go
+++ b/src/syscall/ztypes_netbsd_arm.go
diff --git a/src/pkg/syscall/ztypes_openbsd_386.go b/src/syscall/ztypes_openbsd_386.go
index 2e4d9dd17..2e4d9dd17 100644
--- a/src/pkg/syscall/ztypes_openbsd_386.go
+++ b/src/syscall/ztypes_openbsd_386.go
diff --git a/src/pkg/syscall/ztypes_openbsd_amd64.go b/src/syscall/ztypes_openbsd_amd64.go
index f07bc714e..f07bc714e 100644
--- a/src/pkg/syscall/ztypes_openbsd_amd64.go
+++ b/src/syscall/ztypes_openbsd_amd64.go
diff --git a/src/pkg/syscall/ztypes_plan9_386.go b/src/syscall/ztypes_plan9_386.go
index 3e3a8d1f3..3e3a8d1f3 100644
--- a/src/pkg/syscall/ztypes_plan9_386.go
+++ b/src/syscall/ztypes_plan9_386.go
diff --git a/src/pkg/syscall/ztypes_plan9_amd64.go b/src/syscall/ztypes_plan9_amd64.go
index 3e3a8d1f3..3e3a8d1f3 100644
--- a/src/pkg/syscall/ztypes_plan9_amd64.go
+++ b/src/syscall/ztypes_plan9_amd64.go
diff --git a/src/pkg/syscall/ztypes_solaris_amd64.go b/src/syscall/ztypes_solaris_amd64.go
index 77275a54e..77275a54e 100644
--- a/src/pkg/syscall/ztypes_solaris_amd64.go
+++ b/src/syscall/ztypes_solaris_amd64.go
diff --git a/src/pkg/syscall/ztypes_windows.go b/src/syscall/ztypes_windows.go
index a1d77e0b5..4c8a99ab9 100644
--- a/src/pkg/syscall/ztypes_windows.go
+++ b/src/syscall/ztypes_windows.go
@@ -24,6 +24,7 @@ const (
ERROR_OPERATION_ABORTED Errno = 995
ERROR_IO_PENDING Errno = 997
ERROR_NOT_FOUND Errno = 1168
+ ERROR_PRIVILEGE_NOT_HELD Errno = 1314
WSAEACCES Errno = 10013
WSAECONNRESET Errno = 10054
)
@@ -89,15 +90,16 @@ const (
FILE_APPEND_DATA = 0x00000004
FILE_WRITE_ATTRIBUTES = 0x00000100
- FILE_SHARE_READ = 0x00000001
- FILE_SHARE_WRITE = 0x00000002
- FILE_SHARE_DELETE = 0x00000004
- FILE_ATTRIBUTE_READONLY = 0x00000001
- FILE_ATTRIBUTE_HIDDEN = 0x00000002
- FILE_ATTRIBUTE_SYSTEM = 0x00000004
- FILE_ATTRIBUTE_DIRECTORY = 0x00000010
- FILE_ATTRIBUTE_ARCHIVE = 0x00000020
- FILE_ATTRIBUTE_NORMAL = 0x00000080
+ FILE_SHARE_READ = 0x00000001
+ FILE_SHARE_WRITE = 0x00000002
+ FILE_SHARE_DELETE = 0x00000004
+ FILE_ATTRIBUTE_READONLY = 0x00000001
+ FILE_ATTRIBUTE_HIDDEN = 0x00000002
+ FILE_ATTRIBUTE_SYSTEM = 0x00000004
+ FILE_ATTRIBUTE_DIRECTORY = 0x00000010
+ FILE_ATTRIBUTE_ARCHIVE = 0x00000020
+ FILE_ATTRIBUTE_NORMAL = 0x00000080
+ FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400
INVALID_FILE_ATTRIBUTES = 0xffffffff
@@ -107,8 +109,9 @@ const (
OPEN_ALWAYS = 4
TRUNCATE_EXISTING = 5
- FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
- FILE_FLAG_OVERLAPPED = 0x40000000
+ FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
+ FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
+ FILE_FLAG_OVERLAPPED = 0x40000000
HANDLE_FLAG_INHERIT = 0x00000001
STARTF_USESTDHANDLES = 0x00000100
@@ -176,6 +179,17 @@ const (
)
const (
+ // flags for CreateToolhelp32Snapshot
+ TH32CS_SNAPHEAPLIST = 0x01
+ TH32CS_SNAPPROCESS = 0x02
+ TH32CS_SNAPTHREAD = 0x04
+ TH32CS_SNAPMODULE = 0x08
+ TH32CS_SNAPMODULE32 = 0x10
+ TH32CS_SNAPALL = TH32CS_SNAPHEAPLIST | TH32CS_SNAPMODULE | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD
+ TH32CS_INHERIT = 0x80000000
+)
+
+const (
// do not reorder
FILE_NOTIFY_CHANGE_FILE_NAME = 1 << iota
FILE_NOTIFY_CHANGE_DIR_NAME
@@ -462,6 +476,19 @@ type ProcessInformation struct {
ThreadId uint32
}
+type ProcessEntry32 struct {
+ Size uint32
+ Usage uint32
+ ProcessID uint32
+ DefaultHeapID uintptr
+ ModuleID uint32
+ Threads uint32
+ ParentProcessID uint32
+ PriClassBase int32
+ Flags uint32
+ ExeFile [MAX_PATH]uint16
+}
+
type Systemtime struct {
Year uint16
Month uint16
@@ -520,6 +547,7 @@ const (
IOC_WS2 = 0x08000000
SIO_GET_EXTENSION_FUNCTION_POINTER = IOC_INOUT | IOC_WS2 | 6
SIO_KEEPALIVE_VALS = IOC_IN | IOC_VENDOR | 4
+ SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12
// cf. http://support.microsoft.com/default.aspx?scid=kb;en-us;257460
@@ -662,6 +690,18 @@ const (
DNS_TYPE_NBSTAT = 0xff01
)
+const (
+ DNS_INFO_NO_RECORDS = 0x251D
+)
+
+const (
+ // flags inside DNSRecord.Dw
+ DnsSectionQuestion = 0x0000
+ DnsSectionAnswer = 0x0001
+ DnsSectionAuthority = 0x0002
+ DnsSectionAdditional = 0x0003
+)
+
type DNSSRVData struct {
Target *uint16
Priority uint16
@@ -1042,3 +1082,24 @@ type TCPKeepalive struct {
Time uint32
Interval uint32
}
+
+type reparseDataBuffer struct {
+ ReparseTag uint32
+ ReparseDataLength uint16
+ Reserved uint16
+
+ // SymbolicLinkReparseBuffer
+ SubstituteNameOffset uint16
+ SubstituteNameLength uint16
+ PrintNameOffset uint16
+ PrintNameLength uint16
+ Flags uint32
+ PathBuffer [1]uint16
+}
+
+const (
+ FSCTL_GET_REPARSE_POINT = 0x900A8
+ MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024
+ IO_REPARSE_TAG_SYMLINK = 0xA000000C
+ SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1
+)
diff --git a/src/pkg/syscall/ztypes_windows_386.go b/src/syscall/ztypes_windows_386.go
index 734ee6e0f..734ee6e0f 100644
--- a/src/pkg/syscall/ztypes_windows_386.go
+++ b/src/syscall/ztypes_windows_386.go
diff --git a/src/pkg/syscall/ztypes_windows_amd64.go b/src/syscall/ztypes_windows_amd64.go
index 78aa55b2e..78aa55b2e 100644
--- a/src/pkg/syscall/ztypes_windows_amd64.go
+++ b/src/syscall/ztypes_windows_amd64.go
diff --git a/src/pkg/testing/allocs.go b/src/testing/allocs.go
index 9ec47bd46..9ec47bd46 100644
--- a/src/pkg/testing/allocs.go
+++ b/src/testing/allocs.go
diff --git a/src/testing/allocs_test.go b/src/testing/allocs_test.go
new file mode 100644
index 000000000..ec17daa2b
--- /dev/null
+++ b/src/testing/allocs_test.go
@@ -0,0 +1,29 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testing_test
+
+import "testing"
+
+var global interface{}
+
+var allocsPerRunTests = []struct {
+ name string
+ fn func()
+ allocs float64
+}{
+ {"alloc *byte", func() { global = new(*byte) }, 1},
+ {"alloc complex128", func() { global = new(complex128) }, 1},
+ {"alloc float64", func() { global = new(float64) }, 1},
+ {"alloc int32", func() { global = new(int32) }, 1},
+ {"alloc byte", func() { global = new(byte) }, 1},
+}
+
+func TestAllocsPerRun(t *testing.T) {
+ for _, tt := range allocsPerRunTests {
+ if allocs := testing.AllocsPerRun(100, tt.fn); allocs != tt.allocs {
+ t.Errorf("AllocsPerRun(100, %s) = %v, want %v", tt.name, allocs, tt.allocs)
+ }
+ }
+}
diff --git a/src/pkg/testing/benchmark.go b/src/testing/benchmark.go
index 1fbf5c861..ffd537684 100644
--- a/src/pkg/testing/benchmark.go
+++ b/src/testing/benchmark.go
@@ -157,7 +157,7 @@ func roundDown10(n int) int {
return result
}
-// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
+// roundUp rounds x up to a number of the form [1eX, 2eX, 3eX, 5eX].
func roundUp(n int) int {
base := roundDown10(n)
switch {
@@ -165,6 +165,8 @@ func roundUp(n int) int {
return base
case n <= (2 * base):
return 2 * base
+ case n <= (3 * base):
+ return 3 * base
case n <= (5 * base):
return 5 * base
default:
@@ -180,10 +182,10 @@ func (b *B) run() BenchmarkResult {
}
// launch launches the benchmark function. It gradually increases the number
-// of benchmark iterations until the benchmark runs for a second in order
-// to get a reasonable measurement. It prints timing information in this form
+// of benchmark iterations until the benchmark runs for the requested benchtime.
+// It prints timing information in this form
// testing.BenchmarkHello 100000 19 ns/op
-// launch is run by the fun function as a separate goroutine.
+// launch is run by the run function as a separate goroutine.
func (b *B) launch() {
// Run the benchmark for a single iteration in case it's expensive.
n := 1
@@ -199,16 +201,16 @@ func (b *B) launch() {
d := *benchTime
for !b.failed && b.duration < d && n < 1e9 {
last := n
- // Predict iterations/sec.
+ // Predict required iterations.
if b.nsPerOp() == 0 {
n = 1e9
} else {
n = int(d.Nanoseconds() / b.nsPerOp())
}
- // Run more iterations than we think we'll need for a second (1.5x).
+ // Run more iterations than we think we'll need (1.2x).
// Don't grow too fast in case we had timing errors previously.
// Be sure to run at least one more than last time.
- n = max(min(n+n/2, 100*last), last+1)
+ n = max(min(n+n/5, 100*last), last+1)
// Round up to something easy to read.
n = roundUp(n)
b.runN(n)
diff --git a/src/pkg/testing/benchmark_test.go b/src/testing/benchmark_test.go
index f7ea64e7f..431bb537b 100644
--- a/src/pkg/testing/benchmark_test.go
+++ b/src/testing/benchmark_test.go
@@ -41,12 +41,14 @@ var roundUpTests = []struct {
{0, 1},
{1, 1},
{2, 2},
+ {3, 3},
{5, 5},
{9, 10},
{999, 1000},
{1000, 1000},
{1400, 2000},
{1700, 2000},
+ {2700, 3000},
{4999, 5000},
{5000, 5000},
{5001, 10000},
diff --git a/src/pkg/testing/cover.go b/src/testing/cover.go
index dd29364d8..a4ce37f7c 100644
--- a/src/pkg/testing/cover.go
+++ b/src/testing/cover.go
@@ -9,6 +9,7 @@ package testing
import (
"fmt"
"os"
+ "sync/atomic"
)
// CoverBlock records the coverage data for a single basic block.
@@ -34,6 +35,29 @@ type Cover struct {
CoveredPackages string
}
+// Coverage reports the current code coverage as a fraction in the range [0, 1].
+// If coverage is not enabled, Coverage returns 0.
+//
+// When running a large set of sequential test cases, checking Coverage after each one
+// can be useful for identifying which test cases exercise new code paths.
+// It is not a replacement for the reports generated by 'go test -cover' and
+// 'go tool cover'.
+func Coverage() float64 {
+ var n, d int64
+ for _, counters := range cover.Counters {
+ for i := range counters {
+ if atomic.LoadUint32(&counters[i]) > 0 {
+ n++
+ }
+ d++
+ }
+ }
+ if d == 0 {
+ return 0
+ }
+ return float64(n) / float64(d)
+}
+
// RegisterCover records the coverage data accumulators for the tests.
// NOTE: This function is internal to the testing infrastructure and may change.
// It is not covered (yet) by the Go 1 compatibility guidelines.
@@ -61,11 +85,13 @@ func coverReport() {
}
var active, total int64
+ var count uint32
for name, counts := range cover.Counters {
blocks := cover.Blocks[name]
- for i, count := range counts {
+ for i := range counts {
stmts := int64(blocks[i].Stmts)
total += stmts
+ count = atomic.LoadUint32(&counts[i]) // For -mode=atomic.
if count > 0 {
active += stmts
}
diff --git a/src/pkg/testing/example.go b/src/testing/example.go
index 828c2d3ed..f5762e4db 100644
--- a/src/pkg/testing/example.go
+++ b/src/testing/example.go
@@ -71,7 +71,7 @@ func runExample(eg InternalExample) (ok bool) {
// Clean up in a deferred call so we can recover if the example panics.
defer func() {
- d := time.Now().Sub(start)
+ dstr := fmtDuration(time.Now().Sub(start))
// Close pipe, restore stdout, get output.
w.Close()
@@ -84,10 +84,10 @@ func runExample(eg InternalExample) (ok bool) {
fail = fmt.Sprintf("got:\n%s\nwant:\n%s\n", g, e)
}
if fail != "" || err != nil {
- fmt.Printf("--- FAIL: %s (%v)\n%s", eg.Name, d, fail)
+ fmt.Printf("--- FAIL: %s (%s)\n%s", eg.Name, dstr, fail)
ok = false
} else if *chatty {
- fmt.Printf("--- PASS: %s (%v)\n", eg.Name, d)
+ fmt.Printf("--- PASS: %s (%s)\n", eg.Name, dstr)
}
if err != nil {
panic(err)
diff --git a/src/pkg/testing/export_test.go b/src/testing/export_test.go
index 89781b439..89781b439 100644
--- a/src/pkg/testing/export_test.go
+++ b/src/testing/export_test.go
diff --git a/src/pkg/testing/iotest/logger.go b/src/testing/iotest/logger.go
index 1475d9b0c..1475d9b0c 100644
--- a/src/pkg/testing/iotest/logger.go
+++ b/src/testing/iotest/logger.go
diff --git a/src/pkg/testing/iotest/reader.go b/src/testing/iotest/reader.go
index a5bccca90..a5bccca90 100644
--- a/src/pkg/testing/iotest/reader.go
+++ b/src/testing/iotest/reader.go
diff --git a/src/pkg/testing/iotest/writer.go b/src/testing/iotest/writer.go
index af61ab858..af61ab858 100644
--- a/src/pkg/testing/iotest/writer.go
+++ b/src/testing/iotest/writer.go
diff --git a/src/pkg/testing/quick/quick.go b/src/testing/quick/quick.go
index bc79cc329..909c65f78 100644
--- a/src/pkg/testing/quick/quick.go
+++ b/src/testing/quick/quick.go
@@ -225,12 +225,12 @@ func (s *CheckEqualError) Error() string {
// t.Error(err)
// }
// }
-func Check(function interface{}, config *Config) (err error) {
+func Check(f interface{}, config *Config) (err error) {
if config == nil {
config = &defaultConfig
}
- f, fType, ok := functionAndType(function)
+ fVal, fType, ok := functionAndType(f)
if !ok {
err = SetupError("argument is not a function")
return
@@ -255,7 +255,7 @@ func Check(function interface{}, config *Config) (err error) {
return
}
- if !f.Call(arguments)[0].Bool() {
+ if !fVal.Call(arguments)[0].Bool() {
err = &CheckError{i + 1, toInterfaces(arguments)}
return
}
diff --git a/src/pkg/testing/quick/quick_test.go b/src/testing/quick/quick_test.go
index e925ba675..e925ba675 100644
--- a/src/pkg/testing/quick/quick_test.go
+++ b/src/testing/quick/quick_test.go
diff --git a/src/pkg/testing/testing.go b/src/testing/testing.go
index 8078ba7cc..e54a3b8ce 100644
--- a/src/pkg/testing/testing.go
+++ b/src/testing/testing.go
@@ -44,7 +44,7 @@
// }
//
// The benchmark function must run the target code b.N times.
-// The benchmark package will vary b.N until the benchmark function lasts
+// During benchark execution, b.N is adjusted until the benchmark function lasts
// long enough to be timed reliably. The output
// BenchmarkHello 10000000 282 ns/op
// means that the loop ran 10000000 times at a speed of 282 ns per loop.
@@ -117,6 +117,26 @@
// The entire test file is presented as the example when it contains a single
// example function, at least one other function, type, variable, or constant
// declaration, and no test or benchmark functions.
+//
+// Main
+//
+// It is sometimes necessary for a test program to do extra setup or teardown
+// before or after testing. It is also sometimes necessary for a test to control
+// which code runs on the main thread. To support these and other cases,
+// if a test file contains a function:
+//
+// func TestMain(m *testing.M)
+//
+// then the generated test will call TestMain(m) instead of running the tests
+// directly. TestMain runs in the main goroutine and can do whatever setup
+// and teardown is necessary around a call to m.Run. It should then call
+// os.Exit with the result of m.Run.
+//
+// The minimal implementation of TestMain is:
+//
+// func TestMain(m *testing.M) { os.Exit(m.Run()) }
+//
+// In effect, that is the implementation used when no TestMain is explicitly defined.
package testing
import (
@@ -223,6 +243,11 @@ func decorate(s string) string {
return buf.String()
}
+// fmtDuration returns a string representing d in the form "87.00s".
+func fmtDuration(d time.Duration) string {
+ return fmt.Sprintf("%.2fs", d.Seconds())
+}
+
// TB is the interface common to T and B.
type TB interface {
Error(args ...interface{})
@@ -426,35 +451,61 @@ func tRunner(t *T, test *InternalTest) {
// An internal function but exported because it is cross-package; part of the implementation
// of the "go test" command.
func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
+ os.Exit(MainStart(matchString, tests, benchmarks, examples).Run())
+}
+
+// M is a type passed to a TestMain function to run the actual tests.
+type M struct {
+ matchString func(pat, str string) (bool, error)
+ tests []InternalTest
+ benchmarks []InternalBenchmark
+ examples []InternalExample
+}
+
+// MainStart is meant for use by tests generated by 'go test'.
+// It is not meant to be called directly and is not subject to the Go 1 compatibility document.
+// It may change signature from release to release.
+func MainStart(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
+ return &M{
+ matchString: matchString,
+ tests: tests,
+ benchmarks: benchmarks,
+ examples: examples,
+ }
+}
+
+// Run runs the tests. It returns an exit code to pass to os.Exit.
+func (m *M) Run() int {
flag.Parse()
parseCpuList()
before()
startAlarm()
- haveExamples = len(examples) > 0
- testOk := RunTests(matchString, tests)
- exampleOk := RunExamples(matchString, examples)
+ haveExamples = len(m.examples) > 0
+ testOk := RunTests(m.matchString, m.tests)
+ exampleOk := RunExamples(m.matchString, m.examples)
stopAlarm()
if !testOk || !exampleOk {
fmt.Println("FAIL")
after()
- os.Exit(1)
+ return 1
}
fmt.Println("PASS")
- RunBenchmarks(matchString, benchmarks)
+ RunBenchmarks(m.matchString, m.benchmarks)
after()
+ return 0
}
func (t *T) report() {
- tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds())
- format := "--- %s: %s %s\n%s"
+ dstr := fmtDuration(t.duration)
+ format := "--- %s: %s (%s)\n%s"
if t.Failed() {
- fmt.Printf(format, "FAIL", t.name, tstr, t.output)
+ fmt.Printf(format, "FAIL", t.name, dstr, t.output)
} else if *chatty {
if t.Skipped() {
- fmt.Printf(format, "SKIP", t.name, tstr, t.output)
+ fmt.Printf(format, "SKIP", t.name, dstr, t.output)
} else {
- fmt.Printf(format, "PASS", t.name, tstr, t.output)
+ fmt.Printf(format, "PASS", t.name, dstr, t.output)
}
}
}
@@ -569,6 +620,7 @@ func after() {
fmt.Fprintf(os.Stderr, "testing: %s\n", err)
os.Exit(2)
}
+ runtime.GC() // materialize all statistics
if err = pprof.WriteHeapProfile(f); err != nil {
fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *memProfile, err)
os.Exit(2)
diff --git a/src/testing/testing_test.go b/src/testing/testing_test.go
new file mode 100644
index 000000000..87a5c16d6
--- /dev/null
+++ b/src/testing/testing_test.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 testing_test
+
+import (
+ "os"
+ "testing"
+)
+
+// This is exactly what a test would do without a TestMain.
+// It's here only so that there is at least one package in the
+// standard library with a TestMain, so that code is executed.
+
+func TestMain(m *testing.M) {
+ os.Exit(m.Run())
+}
diff --git a/src/pkg/text/scanner/scanner.go b/src/text/scanner/scanner.go
index db7ca73c6..5199ee4fc 100644
--- a/src/pkg/text/scanner/scanner.go
+++ b/src/text/scanner/scanner.go
@@ -11,7 +11,7 @@
// By default, a Scanner skips white space and Go comments and recognizes all
// literals as defined by the Go language specification. It may be
// customized to recognize only a subset of those literals and to recognize
-// different white space characters.
+// different identifier and white space characters.
//
// Basic usage pattern:
//
@@ -34,8 +34,6 @@ import (
"unicode/utf8"
)
-// TODO(gri): Consider changing this to use the new (token) Position package.
-
// A source position is represented by a Position value.
// A position is valid if Line > 0.
type Position struct {
@@ -68,6 +66,12 @@ func (pos Position) String() string {
//
// ScanIdents | ScanInts | SkipComments
//
+// With the exceptions of comments, which are skipped if SkipComments is
+// set, unrecognized tokens are not ignored. Instead, the scanner simply
+// returns the respective individual characters (or possibly sub-tokens).
+// For instance, if the mode is ScanIdents (not ScanStrings), the string
+// "foo" is scanned as the token sequence '"' Ident '"'.
+//
const (
ScanIdents = 1 << -Ident
ScanInts = 1 << -Int
@@ -164,6 +168,13 @@ type Scanner struct {
// for values ch > ' '). The field may be changed at any time.
Whitespace uint64
+ // IsIdentRune is a predicate controlling the characters accepted
+ // as the ith rune in an identifier. The set of valid characters
+ // must not intersect with the set of white space characters.
+ // If no IsIdentRune function is set, regular Go identifiers are
+ // accepted instead. The field may be changed at any time.
+ IsIdentRune func(ch rune, i int) bool
+
// Start position of most recently scanned token; set by Scan.
// Calling Init or Next invalidates the position (Line == 0).
// The Filename field is always left untouched by the Scanner.
@@ -334,9 +345,17 @@ func (s *Scanner) error(msg string) {
fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
}
+func (s *Scanner) isIdentRune(ch rune, i int) bool {
+ if s.IsIdentRune != nil {
+ return s.IsIdentRune(ch, i)
+ }
+ return ch == '_' || unicode.IsLetter(ch) || unicode.IsDigit(ch) && i > 0
+}
+
func (s *Scanner) scanIdentifier() rune {
- ch := s.next() // read character after first '_' or letter
- for ch == '_' || unicode.IsLetter(ch) || unicode.IsDigit(ch) {
+ // we know the zero'th rune is OK; start scanning at the next one
+ ch := s.next()
+ for i := 1; s.isIdentRune(ch, i); i++ {
ch = s.next()
}
return ch
@@ -563,7 +582,7 @@ redo:
// determine token value
tok := ch
switch {
- case unicode.IsLetter(ch) || ch == '_':
+ case s.isIdentRune(ch, 0):
if s.Mode&ScanIdents != 0 {
tok = Ident
ch = s.scanIdentifier()
diff --git a/src/pkg/text/scanner/scanner_test.go b/src/text/scanner/scanner_test.go
index 7d3f597eb..702fac2b1 100644
--- a/src/pkg/text/scanner/scanner_test.go
+++ b/src/text/scanner/scanner_test.go
@@ -357,6 +357,28 @@ func TestScanSelectedMask(t *testing.T) {
testScanSelectedMode(t, ScanComments, Comment)
}
+func TestScanCustomIdent(t *testing.T) {
+ const src = "faab12345 a12b123 a12 3b"
+ s := new(Scanner).Init(strings.NewReader(src))
+ // ident = ( 'a' | 'b' ) { digit } .
+ // digit = '0' .. '3' .
+ // with a maximum length of 4
+ s.IsIdentRune = func(ch rune, i int) bool {
+ return i == 0 && (ch == 'a' || ch == 'b') || 0 < i && i < 4 && '0' <= ch && ch <= '3'
+ }
+ checkTok(t, s, 1, s.Scan(), 'f', "f")
+ checkTok(t, s, 1, s.Scan(), Ident, "a")
+ checkTok(t, s, 1, s.Scan(), Ident, "a")
+ checkTok(t, s, 1, s.Scan(), Ident, "b123")
+ checkTok(t, s, 1, s.Scan(), Int, "45")
+ checkTok(t, s, 1, s.Scan(), Ident, "a12")
+ checkTok(t, s, 1, s.Scan(), Ident, "b123")
+ checkTok(t, s, 1, s.Scan(), Ident, "a12")
+ checkTok(t, s, 1, s.Scan(), Int, "3")
+ checkTok(t, s, 1, s.Scan(), Ident, "b")
+ checkTok(t, s, 1, s.Scan(), EOF, "")
+}
+
func TestScanNext(t *testing.T) {
const BOM = '\uFEFF'
BOMs := string(BOM)
diff --git a/src/pkg/text/tabwriter/example_test.go b/src/text/tabwriter/example_test.go
index 20443cb1f..20443cb1f 100644
--- a/src/pkg/text/tabwriter/example_test.go
+++ b/src/text/tabwriter/example_test.go
diff --git a/src/pkg/text/tabwriter/tabwriter.go b/src/text/tabwriter/tabwriter.go
index c0c32d5de..c0c32d5de 100644
--- a/src/pkg/text/tabwriter/tabwriter.go
+++ b/src/text/tabwriter/tabwriter.go
diff --git a/src/pkg/text/tabwriter/tabwriter_test.go b/src/text/tabwriter/tabwriter_test.go
index 9d3111e2c..9d3111e2c 100644
--- a/src/pkg/text/tabwriter/tabwriter_test.go
+++ b/src/text/tabwriter/tabwriter_test.go
diff --git a/src/pkg/text/template/doc.go b/src/text/template/doc.go
index 7c6efd59c..223c595c2 100644
--- a/src/pkg/text/template/doc.go
+++ b/src/text/template/doc.go
@@ -338,10 +338,11 @@ arguments will be evaluated.)
The comparison functions work on basic types only (or named basic
types, such as "type Celsius float32"). They implement the Go rules
for comparison of values, except that size and exact type are
-ignored, so any integer value may be compared with any other integer
-value, any unsigned integer value may be compared with any other
-unsigned integer value, and so on. However, as usual, one may not
-compare an int with a float32 and so on.
+ignored, so any integer value, signed or unsigned, may be compared
+with any other integer value. (The arithmetic value is compared,
+not the bit pattern, so all negative integers are less than all
+unsigned integers.) However, as usual, one may not compare an int
+with a float32 and so on.
Associated templates
diff --git a/src/pkg/text/template/example_test.go b/src/text/template/example_test.go
index de1d51851..de1d51851 100644
--- a/src/pkg/text/template/example_test.go
+++ b/src/text/template/example_test.go
diff --git a/src/pkg/text/template/examplefiles_test.go b/src/text/template/examplefiles_test.go
index a15c7a62a..a15c7a62a 100644
--- a/src/pkg/text/template/examplefiles_test.go
+++ b/src/text/template/examplefiles_test.go
diff --git a/src/pkg/text/template/examplefunc_test.go b/src/text/template/examplefunc_test.go
index 080b5e3a0..080b5e3a0 100644
--- a/src/pkg/text/template/examplefunc_test.go
+++ b/src/text/template/examplefunc_test.go
diff --git a/src/pkg/text/template/exec.go b/src/text/template/exec.go
index 2f3231264..b00e10c7e 100644
--- a/src/pkg/text/template/exec.go
+++ b/src/text/template/exec.go
@@ -393,7 +393,7 @@ func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
switch {
case constant.IsComplex:
return reflect.ValueOf(constant.Complex128) // incontrovertible.
- case constant.IsFloat && strings.IndexAny(constant.Text, ".eE") >= 0:
+ case constant.IsFloat && !isHexConstant(constant.Text) && strings.IndexAny(constant.Text, ".eE") >= 0:
return reflect.ValueOf(constant.Float64)
case constant.IsInt:
n := int(constant.Int64)
@@ -407,6 +407,10 @@ func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
return zero
}
+func isHexConstant(s string) bool {
+ return len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')
+}
+
func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value {
s.at(field)
return s.evalFieldChain(dot, dot, field, field.Ident, args, final)
@@ -542,7 +546,7 @@ func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, a
argv := make([]reflect.Value, numIn)
// Args must be evaluated. Fixed args first.
i := 0
- for ; i < numFixed; i++ {
+ for ; i < numFixed && i < len(args); i++ {
argv[i] = s.evalArg(dot, typ.In(i), args[i])
}
// Now the ... args.
@@ -632,6 +636,8 @@ func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) refle
return s.validateType(s.evalPipeline(dot, arg), typ)
case *parse.IdentifierNode:
return s.evalFunction(dot, arg, arg, nil, zero)
+ case *parse.ChainNode:
+ return s.validateType(s.evalChainNode(dot, arg, nil, zero), typ)
}
switch typ.Kind() {
case reflect.Bool:
diff --git a/src/pkg/text/template/exec_test.go b/src/text/template/exec_test.go
index 868f2cb94..69c213ed2 100644
--- a/src/pkg/text/template/exec_test.go
+++ b/src/text/template/exec_test.go
@@ -176,6 +176,12 @@ func (t *T) Method3(v interface{}) string {
return fmt.Sprintf("Method3: %v", v)
}
+func (t *T) Copy() *T {
+ n := new(T)
+ *n = *t
+ return n
+}
+
func (t *T) MAdd(a int, b []int) []int {
v := make([]int, len(b))
for i, x := range b {
@@ -514,6 +520,13 @@ var execTests = []execTest{
{"bug10", "{{mapOfThree.three}}-{{(mapOfThree).three}}", "3-3", 0, true},
// Dereferencing nil pointer while evaluating function arguments should not panic. Issue 7333.
{"bug11", "{{valueString .PS}}", "", T{}, false},
+ // 0xef gave constant type float64. Issue 8622.
+ {"bug12xe", "{{printf `%T` 0xef}}", "int", T{}, true},
+ {"bug12xE", "{{printf `%T` 0xEE}}", "int", T{}, true},
+ {"bug12Xe", "{{printf `%T` 0Xef}}", "int", T{}, true},
+ {"bug12XE", "{{printf `%T` 0XEE}}", "int", T{}, true},
+ // Chained nodes did not work as arguments. Issue 8473.
+ {"bug13", "{{print (.Copy).I}}", "17", tVal, true},
}
func zeroArgs() string {
@@ -880,6 +893,18 @@ func TestMessageForExecuteEmpty(t *testing.T) {
}
}
+func TestFinalForPrintf(t *testing.T) {
+ tmpl, err := New("").Parse(`{{"x" | printf}}`)
+ if err != nil {
+ t.Fatal(err)
+ }
+ var b bytes.Buffer
+ err = tmpl.Execute(&b, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
type cmpTest struct {
expr string
truth string
@@ -897,8 +922,8 @@ var cmpTests = []cmpTest{
{"eq 1 2", "false", true},
{"eq `xy` `xy`", "true", true},
{"eq `xy` `xyz`", "false", true},
- {"eq .Xuint .Xuint", "true", true},
- {"eq .Xuint .Yuint", "false", true},
+ {"eq .Uthree .Uthree", "true", true},
+ {"eq .Uthree .Ufour", "false", true},
{"eq 3 4 5 6 3", "true", true},
{"eq 3 4 5 6 7", "false", true},
{"ne true true", "false", true},
@@ -911,16 +936,16 @@ var cmpTests = []cmpTest{
{"ne 1 2", "true", true},
{"ne `xy` `xy`", "false", true},
{"ne `xy` `xyz`", "true", true},
- {"ne .Xuint .Xuint", "false", true},
- {"ne .Xuint .Yuint", "true", true},
+ {"ne .Uthree .Uthree", "false", true},
+ {"ne .Uthree .Ufour", "true", true},
{"lt 1.5 1.5", "false", true},
{"lt 1.5 2.5", "true", true},
{"lt 1 1", "false", true},
{"lt 1 2", "true", true},
{"lt `xy` `xy`", "false", true},
{"lt `xy` `xyz`", "true", true},
- {"lt .Xuint .Xuint", "false", true},
- {"lt .Xuint .Yuint", "true", true},
+ {"lt .Uthree .Uthree", "false", true},
+ {"lt .Uthree .Ufour", "true", true},
{"le 1.5 1.5", "true", true},
{"le 1.5 2.5", "true", true},
{"le 2.5 1.5", "false", true},
@@ -930,9 +955,9 @@ var cmpTests = []cmpTest{
{"le `xy` `xy`", "true", true},
{"le `xy` `xyz`", "true", true},
{"le `xyz` `xy`", "false", true},
- {"le .Xuint .Xuint", "true", true},
- {"le .Xuint .Yuint", "true", true},
- {"le .Yuint .Xuint", "false", true},
+ {"le .Uthree .Uthree", "true", true},
+ {"le .Uthree .Ufour", "true", true},
+ {"le .Ufour .Uthree", "false", true},
{"gt 1.5 1.5", "false", true},
{"gt 1.5 2.5", "false", true},
{"gt 1 1", "false", true},
@@ -940,9 +965,9 @@ var cmpTests = []cmpTest{
{"gt 1 2", "false", true},
{"gt `xy` `xy`", "false", true},
{"gt `xy` `xyz`", "false", true},
- {"gt .Xuint .Xuint", "false", true},
- {"gt .Xuint .Yuint", "false", true},
- {"gt .Yuint .Xuint", "true", true},
+ {"gt .Uthree .Uthree", "false", true},
+ {"gt .Uthree .Ufour", "false", true},
+ {"gt .Ufour .Uthree", "true", true},
{"ge 1.5 1.5", "true", true},
{"ge 1.5 2.5", "false", true},
{"ge 2.5 1.5", "true", true},
@@ -952,11 +977,40 @@ var cmpTests = []cmpTest{
{"ge `xy` `xy`", "true", true},
{"ge `xy` `xyz`", "false", true},
{"ge `xyz` `xy`", "true", true},
- {"ge .Xuint .Xuint", "true", true},
- {"ge .Xuint .Yuint", "false", true},
- {"ge .Yuint .Xuint", "true", true},
+ {"ge .Uthree .Uthree", "true", true},
+ {"ge .Uthree .Ufour", "false", true},
+ {"ge .Ufour .Uthree", "true", true},
+ // Mixing signed and unsigned integers.
+ {"eq .Uthree .Three", "true", true},
+ {"eq .Three .Uthree", "true", true},
+ {"le .Uthree .Three", "true", true},
+ {"le .Three .Uthree", "true", true},
+ {"ge .Uthree .Three", "true", true},
+ {"ge .Three .Uthree", "true", true},
+ {"lt .Uthree .Three", "false", true},
+ {"lt .Three .Uthree", "false", true},
+ {"gt .Uthree .Three", "false", true},
+ {"gt .Three .Uthree", "false", true},
+ {"eq .Ufour .Three", "false", true},
+ {"lt .Ufour .Three", "false", true},
+ {"gt .Ufour .Three", "true", true},
+ {"eq .NegOne .Uthree", "false", true},
+ {"eq .Uthree .NegOne", "false", true},
+ {"ne .NegOne .Uthree", "true", true},
+ {"ne .Uthree .NegOne", "true", true},
+ {"lt .NegOne .Uthree", "true", true},
+ {"lt .Uthree .NegOne", "false", true},
+ {"le .NegOne .Uthree", "true", true},
+ {"le .Uthree .NegOne", "false", true},
+ {"gt .NegOne .Uthree", "false", true},
+ {"gt .Uthree .NegOne", "true", true},
+ {"ge .NegOne .Uthree", "false", true},
+ {"ge .Uthree .NegOne", "true", true},
+ {"eq (index `x` 0) 'x'", "true", true}, // The example that triggered this rule.
+ {"eq (index `x` 0) 'y'", "false", true},
// Errors
{"eq `xy` 1", "", false}, // Different types.
+ {"eq 2 2.0", "", false}, // Different types.
{"lt true true", "", false}, // Unordered types.
{"lt 1+0i 1+0i", "", false}, // Unordered types.
}
@@ -964,13 +1018,14 @@ var cmpTests = []cmpTest{
func TestComparison(t *testing.T) {
b := new(bytes.Buffer)
var cmpStruct = struct {
- Xuint, Yuint uint
- }{3, 4}
+ Uthree, Ufour uint
+ NegOne, Three int
+ }{3, 4, -1, 3}
for _, test := range cmpTests {
text := fmt.Sprintf("{{if %s}}true{{else}}false{{end}}", test.expr)
tmpl, err := New("empty").Parse(text)
if err != nil {
- t.Fatal(err)
+ t.Fatalf("%q: %s", test.expr, err)
}
b.Reset()
err = tmpl.Execute(b, &cmpStruct)
diff --git a/src/pkg/text/template/funcs.go b/src/text/template/funcs.go
index e85412262..39ee5ed68 100644
--- a/src/pkg/text/template/funcs.go
+++ b/src/text/template/funcs.go
@@ -314,25 +314,34 @@ func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
if err != nil {
return false, err
}
- if k1 != k2 {
- return false, errBadComparison
- }
truth := false
- switch k1 {
- case boolKind:
- truth = v1.Bool() == v2.Bool()
- case complexKind:
- truth = v1.Complex() == v2.Complex()
- case floatKind:
- truth = v1.Float() == v2.Float()
- case intKind:
- truth = v1.Int() == v2.Int()
- case stringKind:
- truth = v1.String() == v2.String()
- case uintKind:
- truth = v1.Uint() == v2.Uint()
- default:
- panic("invalid kind")
+ if k1 != k2 {
+ // Special case: Can compare integer values regardless of type's sign.
+ switch {
+ case k1 == intKind && k2 == uintKind:
+ truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint()
+ case k1 == uintKind && k2 == intKind:
+ truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int())
+ default:
+ return false, errBadComparison
+ }
+ } else {
+ switch k1 {
+ case boolKind:
+ truth = v1.Bool() == v2.Bool()
+ case complexKind:
+ truth = v1.Complex() == v2.Complex()
+ case floatKind:
+ truth = v1.Float() == v2.Float()
+ case intKind:
+ truth = v1.Int() == v2.Int()
+ case stringKind:
+ truth = v1.String() == v2.String()
+ case uintKind:
+ truth = v1.Uint() == v2.Uint()
+ default:
+ panic("invalid kind")
+ }
}
if truth {
return true, nil
@@ -360,23 +369,32 @@ func lt(arg1, arg2 interface{}) (bool, error) {
if err != nil {
return false, err
}
- if k1 != k2 {
- return false, errBadComparison
- }
truth := false
- switch k1 {
- case boolKind, complexKind:
- return false, errBadComparisonType
- case floatKind:
- truth = v1.Float() < v2.Float()
- case intKind:
- truth = v1.Int() < v2.Int()
- case stringKind:
- truth = v1.String() < v2.String()
- case uintKind:
- truth = v1.Uint() < v2.Uint()
- default:
- panic("invalid kind")
+ if k1 != k2 {
+ // Special case: Can compare integer values regardless of type's sign.
+ switch {
+ case k1 == intKind && k2 == uintKind:
+ truth = v1.Int() < 0 || uint64(v1.Int()) < v2.Uint()
+ case k1 == uintKind && k2 == intKind:
+ truth = v2.Int() >= 0 && v1.Uint() < uint64(v2.Int())
+ default:
+ return false, errBadComparison
+ }
+ } else {
+ switch k1 {
+ case boolKind, complexKind:
+ return false, errBadComparisonType
+ case floatKind:
+ truth = v1.Float() < v2.Float()
+ case intKind:
+ truth = v1.Int() < v2.Int()
+ case stringKind:
+ truth = v1.String() < v2.String()
+ case uintKind:
+ truth = v1.Uint() < v2.Uint()
+ default:
+ panic("invalid kind")
+ }
}
return truth, nil
}
diff --git a/src/pkg/text/template/helper.go b/src/text/template/helper.go
index 3636fb54d..3636fb54d 100644
--- a/src/pkg/text/template/helper.go
+++ b/src/text/template/helper.go
diff --git a/src/pkg/text/template/multi_test.go b/src/text/template/multi_test.go
index e4e804880..e4e804880 100644
--- a/src/pkg/text/template/multi_test.go
+++ b/src/text/template/multi_test.go
diff --git a/src/pkg/text/template/parse/lex.go b/src/text/template/parse/lex.go
index 1674aaf9c..1674aaf9c 100644
--- a/src/pkg/text/template/parse/lex.go
+++ b/src/text/template/parse/lex.go
diff --git a/src/pkg/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go
index d251ccffb..d251ccffb 100644
--- a/src/pkg/text/template/parse/lex_test.go
+++ b/src/text/template/parse/lex_test.go
diff --git a/src/pkg/text/template/parse/node.go b/src/text/template/parse/node.go
index dc6a3bb92..55c37f6db 100644
--- a/src/pkg/text/template/parse/node.go
+++ b/src/text/template/parse/node.go
@@ -26,8 +26,9 @@ type Node interface {
// CopyXxx methods that return *XxxNode.
Copy() Node
Position() Pos // byte position of start of node in full original input string
- // Make sure only functions in this package can create Nodes.
- unexported()
+ // tree returns the containing *Tree.
+ // It is unexported so all implementations of Node are in this package.
+ tree() *Tree
}
// NodeType identifies the type of a parse tree node.
@@ -41,11 +42,6 @@ func (p Pos) Position() Pos {
return p
}
-// unexported keeps Node implementations local to the package.
-// All implementations embed Pos, so this takes care of it.
-func (Pos) unexported() {
-}
-
// Type returns itself and provides an easy default implementation
// for embedding in a Node. Embedded in all non-trivial Nodes.
func (t NodeType) Type() NodeType {
@@ -81,17 +77,22 @@ const (
type ListNode struct {
NodeType
Pos
+ tr *Tree
Nodes []Node // The element nodes in lexical order.
}
-func newList(pos Pos) *ListNode {
- return &ListNode{NodeType: NodeList, Pos: pos}
+func (t *Tree) newList(pos Pos) *ListNode {
+ return &ListNode{tr: t, NodeType: NodeList, Pos: pos}
}
func (l *ListNode) append(n Node) {
l.Nodes = append(l.Nodes, n)
}
+func (l *ListNode) tree() *Tree {
+ return l.tr
+}
+
func (l *ListNode) String() string {
b := new(bytes.Buffer)
for _, n := range l.Nodes {
@@ -104,7 +105,7 @@ func (l *ListNode) CopyList() *ListNode {
if l == nil {
return l
}
- n := newList(l.Pos)
+ n := l.tr.newList(l.Pos)
for _, elem := range l.Nodes {
n.append(elem.Copy())
}
@@ -119,32 +120,38 @@ func (l *ListNode) Copy() Node {
type TextNode struct {
NodeType
Pos
+ tr *Tree
Text []byte // The text; may span newlines.
}
-func newText(pos Pos, text string) *TextNode {
- return &TextNode{NodeType: NodeText, Pos: pos, Text: []byte(text)}
+func (t *Tree) newText(pos Pos, text string) *TextNode {
+ return &TextNode{tr: t, NodeType: NodeText, Pos: pos, Text: []byte(text)}
}
func (t *TextNode) String() string {
return fmt.Sprintf(textFormat, t.Text)
}
+func (t *TextNode) tree() *Tree {
+ return t.tr
+}
+
func (t *TextNode) Copy() Node {
- return &TextNode{NodeType: NodeText, Text: append([]byte{}, t.Text...)}
+ return &TextNode{tr: t.tr, NodeType: NodeText, Pos: t.Pos, Text: append([]byte{}, t.Text...)}
}
// PipeNode holds a pipeline with optional declaration
type PipeNode struct {
NodeType
Pos
+ tr *Tree
Line int // The line number in the input (deprecated; kept for compatibility)
Decl []*VariableNode // Variable declarations in lexical order.
Cmds []*CommandNode // The commands in lexical order.
}
-func newPipeline(pos Pos, line int, decl []*VariableNode) *PipeNode {
- return &PipeNode{NodeType: NodePipe, Pos: pos, Line: line, Decl: decl}
+func (t *Tree) newPipeline(pos Pos, line int, decl []*VariableNode) *PipeNode {
+ return &PipeNode{tr: t, NodeType: NodePipe, Pos: pos, Line: line, Decl: decl}
}
func (p *PipeNode) append(command *CommandNode) {
@@ -171,6 +178,10 @@ func (p *PipeNode) String() string {
return s
}
+func (p *PipeNode) tree() *Tree {
+ return p.tr
+}
+
func (p *PipeNode) CopyPipe() *PipeNode {
if p == nil {
return p
@@ -179,7 +190,7 @@ func (p *PipeNode) CopyPipe() *PipeNode {
for _, d := range p.Decl {
decl = append(decl, d.Copy().(*VariableNode))
}
- n := newPipeline(p.Pos, p.Line, decl)
+ n := p.tr.newPipeline(p.Pos, p.Line, decl)
for _, c := range p.Cmds {
n.append(c.Copy().(*CommandNode))
}
@@ -196,12 +207,13 @@ func (p *PipeNode) Copy() Node {
type ActionNode struct {
NodeType
Pos
+ tr *Tree
Line int // The line number in the input (deprecated; kept for compatibility)
Pipe *PipeNode // The pipeline in the action.
}
-func newAction(pos Pos, line int, pipe *PipeNode) *ActionNode {
- return &ActionNode{NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe}
+func (t *Tree) newAction(pos Pos, line int, pipe *PipeNode) *ActionNode {
+ return &ActionNode{tr: t, NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe}
}
func (a *ActionNode) String() string {
@@ -209,8 +221,12 @@ func (a *ActionNode) String() string {
}
+func (a *ActionNode) tree() *Tree {
+ return a.tr
+}
+
func (a *ActionNode) Copy() Node {
- return newAction(a.Pos, a.Line, a.Pipe.CopyPipe())
+ return a.tr.newAction(a.Pos, a.Line, a.Pipe.CopyPipe())
}
@@ -218,11 +234,12 @@ func (a *ActionNode) Copy() Node {
type CommandNode struct {
NodeType
Pos
+ tr *Tree
Args []Node // Arguments in lexical order: Identifier, field, or constant.
}
-func newCommand(pos Pos) *CommandNode {
- return &CommandNode{NodeType: NodeCommand, Pos: pos}
+func (t *Tree) newCommand(pos Pos) *CommandNode {
+ return &CommandNode{tr: t, NodeType: NodeCommand, Pos: pos}
}
func (c *CommandNode) append(arg Node) {
@@ -244,11 +261,15 @@ func (c *CommandNode) String() string {
return s
}
+func (c *CommandNode) tree() *Tree {
+ return c.tr
+}
+
func (c *CommandNode) Copy() Node {
if c == nil {
return c
}
- n := newCommand(c.Pos)
+ n := c.tr.newCommand(c.Pos)
for _, c := range c.Args {
n.append(c.Copy())
}
@@ -259,6 +280,7 @@ func (c *CommandNode) Copy() Node {
type IdentifierNode struct {
NodeType
Pos
+ tr *Tree
Ident string // The identifier's name.
}
@@ -275,12 +297,24 @@ func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode {
return i
}
+// SetTree sets the parent tree for the node. NewIdentifier is a public method so we can't modify its signature.
+// Chained for convenience.
+// TODO: fix one day?
+func (i *IdentifierNode) SetTree(t *Tree) *IdentifierNode {
+ i.tr = t
+ return i
+}
+
func (i *IdentifierNode) String() string {
return i.Ident
}
+func (i *IdentifierNode) tree() *Tree {
+ return i.tr
+}
+
func (i *IdentifierNode) Copy() Node {
- return NewIdentifier(i.Ident).SetPos(i.Pos)
+ return NewIdentifier(i.Ident).SetTree(i.tr).SetPos(i.Pos)
}
// VariableNode holds a list of variable names, possibly with chained field
@@ -288,11 +322,12 @@ func (i *IdentifierNode) Copy() Node {
type VariableNode struct {
NodeType
Pos
+ tr *Tree
Ident []string // Variable name and fields in lexical order.
}
-func newVariable(pos Pos, ident string) *VariableNode {
- return &VariableNode{NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")}
+func (t *Tree) newVariable(pos Pos, ident string) *VariableNode {
+ return &VariableNode{tr: t, NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")}
}
func (v *VariableNode) String() string {
@@ -306,20 +341,29 @@ func (v *VariableNode) String() string {
return s
}
+func (v *VariableNode) tree() *Tree {
+ return v.tr
+}
+
func (v *VariableNode) Copy() Node {
- return &VariableNode{NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)}
+ return &VariableNode{tr: v.tr, NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)}
}
// DotNode holds the special identifier '.'.
type DotNode struct {
+ NodeType
Pos
+ tr *Tree
}
-func newDot(pos Pos) *DotNode {
- return &DotNode{Pos: pos}
+func (t *Tree) newDot(pos Pos) *DotNode {
+ return &DotNode{tr: t, NodeType: NodeDot, Pos: pos}
}
func (d *DotNode) Type() NodeType {
+ // Override method on embedded NodeType for API compatibility.
+ // TODO: Not really a problem; could change API without effect but
+ // api tool complains.
return NodeDot
}
@@ -327,20 +371,29 @@ func (d *DotNode) String() string {
return "."
}
+func (d *DotNode) tree() *Tree {
+ return d.tr
+}
+
func (d *DotNode) Copy() Node {
- return newDot(d.Pos)
+ return d.tr.newDot(d.Pos)
}
// NilNode holds the special identifier 'nil' representing an untyped nil constant.
type NilNode struct {
+ NodeType
Pos
+ tr *Tree
}
-func newNil(pos Pos) *NilNode {
- return &NilNode{Pos: pos}
+func (t *Tree) newNil(pos Pos) *NilNode {
+ return &NilNode{tr: t, NodeType: NodeNil, Pos: pos}
}
func (n *NilNode) Type() NodeType {
+ // Override method on embedded NodeType for API compatibility.
+ // TODO: Not really a problem; could change API without effect but
+ // api tool complains.
return NodeNil
}
@@ -348,8 +401,12 @@ func (n *NilNode) String() string {
return "nil"
}
+func (n *NilNode) tree() *Tree {
+ return n.tr
+}
+
func (n *NilNode) Copy() Node {
- return newNil(n.Pos)
+ return n.tr.newNil(n.Pos)
}
// FieldNode holds a field (identifier starting with '.').
@@ -358,11 +415,12 @@ func (n *NilNode) Copy() Node {
type FieldNode struct {
NodeType
Pos
+ tr *Tree
Ident []string // The identifiers in lexical order.
}
-func newField(pos Pos, ident string) *FieldNode {
- return &FieldNode{NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
+func (t *Tree) newField(pos Pos, ident string) *FieldNode {
+ return &FieldNode{tr: t, NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
}
func (f *FieldNode) String() string {
@@ -373,8 +431,12 @@ func (f *FieldNode) String() string {
return s
}
+func (f *FieldNode) tree() *Tree {
+ return f.tr
+}
+
func (f *FieldNode) Copy() Node {
- return &FieldNode{NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)}
+ return &FieldNode{tr: f.tr, NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)}
}
// ChainNode holds a term followed by a chain of field accesses (identifier starting with '.').
@@ -383,12 +445,13 @@ func (f *FieldNode) Copy() Node {
type ChainNode struct {
NodeType
Pos
+ tr *Tree
Node Node
Field []string // The identifiers in lexical order.
}
-func newChain(pos Pos, node Node) *ChainNode {
- return &ChainNode{NodeType: NodeChain, Pos: pos, Node: node}
+func (t *Tree) newChain(pos Pos, node Node) *ChainNode {
+ return &ChainNode{tr: t, NodeType: NodeChain, Pos: pos, Node: node}
}
// Add adds the named field (which should start with a period) to the end of the chain.
@@ -414,19 +477,24 @@ func (c *ChainNode) String() string {
return s
}
+func (c *ChainNode) tree() *Tree {
+ return c.tr
+}
+
func (c *ChainNode) Copy() Node {
- return &ChainNode{NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)}
+ return &ChainNode{tr: c.tr, NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)}
}
// BoolNode holds a boolean constant.
type BoolNode struct {
NodeType
Pos
+ tr *Tree
True bool // The value of the boolean constant.
}
-func newBool(pos Pos, true bool) *BoolNode {
- return &BoolNode{NodeType: NodeBool, Pos: pos, True: true}
+func (t *Tree) newBool(pos Pos, true bool) *BoolNode {
+ return &BoolNode{tr: t, NodeType: NodeBool, Pos: pos, True: true}
}
func (b *BoolNode) String() string {
@@ -436,8 +504,12 @@ func (b *BoolNode) String() string {
return "false"
}
+func (b *BoolNode) tree() *Tree {
+ return b.tr
+}
+
func (b *BoolNode) Copy() Node {
- return newBool(b.Pos, b.True)
+ return b.tr.newBool(b.Pos, b.True)
}
// NumberNode holds a number: signed or unsigned integer, float, or complex.
@@ -446,6 +518,7 @@ func (b *BoolNode) Copy() Node {
type NumberNode struct {
NodeType
Pos
+ tr *Tree
IsInt bool // Number has an integral value.
IsUint bool // Number has an unsigned integral value.
IsFloat bool // Number has a floating-point value.
@@ -457,8 +530,8 @@ type NumberNode struct {
Text string // The original textual representation from the input.
}
-func newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) {
- n := &NumberNode{NodeType: NodeNumber, Pos: pos, Text: text}
+func (t *Tree) newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) {
+ n := &NumberNode{tr: t, NodeType: NodeNumber, Pos: pos, Text: text}
switch typ {
case itemCharConstant:
rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0])
@@ -559,6 +632,10 @@ func (n *NumberNode) String() string {
return n.Text
}
+func (n *NumberNode) tree() *Tree {
+ return n.tr
+}
+
func (n *NumberNode) Copy() Node {
nn := new(NumberNode)
*nn = *n // Easy, fast, correct.
@@ -569,53 +646,61 @@ func (n *NumberNode) Copy() Node {
type StringNode struct {
NodeType
Pos
+ tr *Tree
Quoted string // The original text of the string, with quotes.
Text string // The string, after quote processing.
}
-func newString(pos Pos, orig, text string) *StringNode {
- return &StringNode{NodeType: NodeString, Pos: pos, Quoted: orig, Text: text}
+func (t *Tree) newString(pos Pos, orig, text string) *StringNode {
+ return &StringNode{tr: t, NodeType: NodeString, Pos: pos, Quoted: orig, Text: text}
}
func (s *StringNode) String() string {
return s.Quoted
}
+func (s *StringNode) tree() *Tree {
+ return s.tr
+}
+
func (s *StringNode) Copy() Node {
- return newString(s.Pos, s.Quoted, s.Text)
+ return s.tr.newString(s.Pos, s.Quoted, s.Text)
}
// endNode represents an {{end}} action.
// It does not appear in the final parse tree.
type endNode struct {
+ NodeType
Pos
+ tr *Tree
}
-func newEnd(pos Pos) *endNode {
- return &endNode{Pos: pos}
-}
-
-func (e *endNode) Type() NodeType {
- return nodeEnd
+func (t *Tree) newEnd(pos Pos) *endNode {
+ return &endNode{tr: t, NodeType: nodeEnd, Pos: pos}
}
func (e *endNode) String() string {
return "{{end}}"
}
+func (e *endNode) tree() *Tree {
+ return e.tr
+}
+
func (e *endNode) Copy() Node {
- return newEnd(e.Pos)
+ return e.tr.newEnd(e.Pos)
}
// elseNode represents an {{else}} action. Does not appear in the final tree.
type elseNode struct {
NodeType
Pos
+ tr *Tree
Line int // The line number in the input (deprecated; kept for compatibility)
}
-func newElse(pos Pos, line int) *elseNode {
- return &elseNode{NodeType: nodeElse, Pos: pos, Line: line}
+func (t *Tree) newElse(pos Pos, line int) *elseNode {
+ return &elseNode{tr: t, NodeType: nodeElse, Pos: pos, Line: line}
}
func (e *elseNode) Type() NodeType {
@@ -626,14 +711,19 @@ func (e *elseNode) String() string {
return "{{else}}"
}
+func (e *elseNode) tree() *Tree {
+ return e.tr
+}
+
func (e *elseNode) Copy() Node {
- return newElse(e.Pos, e.Line)
+ return e.tr.newElse(e.Pos, e.Line)
}
// BranchNode is the common representation of if, range, and with.
type BranchNode struct {
NodeType
Pos
+ tr *Tree
Line int // The line number in the input (deprecated; kept for compatibility)
Pipe *PipeNode // The pipeline to be evaluated.
List *ListNode // What to execute if the value is non-empty.
@@ -658,17 +748,34 @@ func (b *BranchNode) String() string {
return fmt.Sprintf("{{%s %s}}%s{{end}}", name, b.Pipe, b.List)
}
+func (b *BranchNode) tree() *Tree {
+ return b.tr
+}
+
+func (b *BranchNode) Copy() Node {
+ switch b.NodeType {
+ case NodeIf:
+ return b.tr.newIf(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
+ case NodeRange:
+ return b.tr.newRange(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
+ case NodeWith:
+ return b.tr.newWith(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
+ default:
+ panic("unknown branch type")
+ }
+}
+
// IfNode represents an {{if}} action and its commands.
type IfNode struct {
BranchNode
}
-func newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
- return &IfNode{BranchNode{NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+func (t *Tree) newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
+ return &IfNode{BranchNode{tr: t, NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
func (i *IfNode) Copy() Node {
- return newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
+ return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
}
// RangeNode represents a {{range}} action and its commands.
@@ -676,12 +783,12 @@ type RangeNode struct {
BranchNode
}
-func newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
- return &RangeNode{BranchNode{NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+func (t *Tree) newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
+ return &RangeNode{BranchNode{tr: t, NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
func (r *RangeNode) Copy() Node {
- return newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
+ return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
}
// WithNode represents a {{with}} action and its commands.
@@ -689,25 +796,26 @@ type WithNode struct {
BranchNode
}
-func newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
- return &WithNode{BranchNode{NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+func (t *Tree) newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
+ return &WithNode{BranchNode{tr: t, NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
func (w *WithNode) Copy() Node {
- return newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
+ return w.tr.newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
}
// TemplateNode represents a {{template}} action.
type TemplateNode struct {
NodeType
Pos
+ tr *Tree
Line int // The line number in the input (deprecated; kept for compatibility)
Name string // The name of the template (unquoted).
Pipe *PipeNode // The command to evaluate as dot for the template.
}
-func newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode {
- return &TemplateNode{NodeType: NodeTemplate, Line: line, Pos: pos, Name: name, Pipe: pipe}
+func (t *Tree) newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode {
+ return &TemplateNode{tr: t, NodeType: NodeTemplate, Pos: pos, Line: line, Name: name, Pipe: pipe}
}
func (t *TemplateNode) String() string {
@@ -717,6 +825,10 @@ func (t *TemplateNode) String() string {
return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe)
}
+func (t *TemplateNode) tree() *Tree {
+ return t.tr
+}
+
func (t *TemplateNode) Copy() Node {
- return newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe())
+ return t.tr.newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe())
}
diff --git a/src/pkg/text/template/parse/parse.go b/src/text/template/parse/parse.go
index 34112fb7b..af33880c1 100644
--- a/src/pkg/text/template/parse/parse.go
+++ b/src/text/template/parse/parse.go
@@ -129,9 +129,15 @@ func New(name string, funcs ...map[string]interface{}) *Tree {
}
// ErrorContext returns a textual representation of the location of the node in the input text.
+// The receiver is only used when the node does not have a pointer to the tree inside,
+// which can occur in old code.
func (t *Tree) ErrorContext(n Node) (location, context string) {
pos := int(n.Position())
- text := t.text[:pos]
+ tree := n.tree()
+ if tree == nil {
+ tree = t
+ }
+ text := tree.text[:pos]
byteNum := strings.LastIndex(text, "\n")
if byteNum == -1 {
byteNum = pos // On first line.
@@ -144,7 +150,7 @@ func (t *Tree) ErrorContext(n Node) (location, context string) {
if len(context) > 20 {
context = fmt.Sprintf("%.20s...", context)
}
- return fmt.Sprintf("%s:%d:%d", t.ParseName, lineNum, byteNum), context
+ return fmt.Sprintf("%s:%d:%d", tree.ParseName, lineNum, byteNum), context
}
// errorf formats the error and terminates processing.
@@ -268,7 +274,7 @@ func IsEmptyTree(n Node) bool {
// as itemList except it also parses {{define}} actions.
// It runs to EOF.
func (t *Tree) parse(treeSet map[string]*Tree) (next Node) {
- t.Root = newList(t.peek().pos)
+ t.Root = t.newList(t.peek().pos)
for t.peek().typ != itemEOF {
if t.peek().typ == itemLeftDelim {
delim := t.next()
@@ -316,7 +322,7 @@ func (t *Tree) parseDefinition(treeSet map[string]*Tree) {
// textOrAction*
// Terminates at {{end}} or {{else}}, returned separately.
func (t *Tree) itemList() (list *ListNode, next Node) {
- list = newList(t.peekNonSpace().pos)
+ list = t.newList(t.peekNonSpace().pos)
for t.peekNonSpace().typ != itemEOF {
n := t.textOrAction()
switch n.Type() {
@@ -334,7 +340,7 @@ func (t *Tree) itemList() (list *ListNode, next Node) {
func (t *Tree) textOrAction() Node {
switch token := t.nextNonSpace(); token.typ {
case itemText:
- return newText(token.pos, token.val)
+ return t.newText(token.pos, token.val)
case itemLeftDelim:
return t.action()
default:
@@ -365,7 +371,7 @@ func (t *Tree) action() (n Node) {
}
t.backup()
// Do not pop variables; they persist until "end".
- return newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command"))
+ return t.newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command"))
}
// Pipeline:
@@ -384,7 +390,7 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
tokenAfterVariable := t.peek()
if next := t.peekNonSpace(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
t.nextNonSpace()
- variable := newVariable(v.pos, v.val)
+ variable := t.newVariable(v.pos, v.val)
decl = append(decl, variable)
t.vars = append(t.vars, v.val)
if next.typ == itemChar && next.val == "," {
@@ -401,7 +407,7 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
}
break
}
- pipe = newPipeline(pos, t.lex.lineNumber(), decl)
+ pipe = t.newPipeline(pos, t.lex.lineNumber(), decl)
for {
switch token := t.nextNonSpace(); token.typ {
case itemRightDelim, itemRightParen:
@@ -442,7 +448,7 @@ func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int
// TODO: Should we allow else-if in with and range?
if t.peek().typ == itemIf {
t.next() // Consume the "if" token.
- elseList = newList(next.Position())
+ elseList = t.newList(next.Position())
elseList.append(t.ifControl())
// Do not consume the next item - only one {{end}} required.
break
@@ -461,7 +467,7 @@ func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int
// {{if pipeline}} itemList {{else}} itemList {{end}}
// If keyword is past.
func (t *Tree) ifControl() Node {
- return newIf(t.parseControl(true, "if"))
+ return t.newIf(t.parseControl(true, "if"))
}
// Range:
@@ -469,7 +475,7 @@ func (t *Tree) ifControl() Node {
// {{range pipeline}} itemList {{else}} itemList {{end}}
// Range keyword is past.
func (t *Tree) rangeControl() Node {
- return newRange(t.parseControl(false, "range"))
+ return t.newRange(t.parseControl(false, "range"))
}
// With:
@@ -477,14 +483,14 @@ func (t *Tree) rangeControl() Node {
// {{with pipeline}} itemList {{else}} itemList {{end}}
// If keyword is past.
func (t *Tree) withControl() Node {
- return newWith(t.parseControl(false, "with"))
+ return t.newWith(t.parseControl(false, "with"))
}
// End:
// {{end}}
// End keyword is past.
func (t *Tree) endControl() Node {
- return newEnd(t.expect(itemRightDelim, "end").pos)
+ return t.newEnd(t.expect(itemRightDelim, "end").pos)
}
// Else:
@@ -495,9 +501,9 @@ func (t *Tree) elseControl() Node {
peek := t.peekNonSpace()
if peek.typ == itemIf {
// We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ".
- return newElse(peek.pos, t.lex.lineNumber())
+ return t.newElse(peek.pos, t.lex.lineNumber())
}
- return newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber())
+ return t.newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber())
}
// Template:
@@ -523,7 +529,7 @@ func (t *Tree) templateControl() Node {
// Do not pop variables; they persist until "end".
pipe = t.pipeline("template")
}
- return newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
+ return t.newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
}
// command:
@@ -531,7 +537,7 @@ func (t *Tree) templateControl() Node {
// space-separated arguments up to a pipeline character or right delimiter.
// we consume the pipe character but leave the right delim to terminate the action.
func (t *Tree) command() *CommandNode {
- cmd := newCommand(t.peekNonSpace().pos)
+ cmd := t.newCommand(t.peekNonSpace().pos)
for {
t.peekNonSpace() // skip leading spaces.
operand := t.operand()
@@ -568,7 +574,7 @@ func (t *Tree) operand() Node {
return nil
}
if t.peek().typ == itemField {
- chain := newChain(t.peek().pos, node)
+ chain := t.newChain(t.peek().pos, node)
for t.peek().typ == itemField {
chain.Add(t.next().val)
}
@@ -578,9 +584,9 @@ func (t *Tree) operand() Node {
// TODO: Switch to Chains always when we can.
switch node.Type() {
case NodeField:
- node = newField(chain.Position(), chain.String())
+ node = t.newField(chain.Position(), chain.String())
case NodeVariable:
- node = newVariable(chain.Position(), chain.String())
+ node = t.newVariable(chain.Position(), chain.String())
default:
node = chain
}
@@ -605,19 +611,19 @@ func (t *Tree) term() Node {
if !t.hasFunction(token.val) {
t.errorf("function %q not defined", token.val)
}
- return NewIdentifier(token.val).SetPos(token.pos)
+ return NewIdentifier(token.val).SetTree(t).SetPos(token.pos)
case itemDot:
- return newDot(token.pos)
+ return t.newDot(token.pos)
case itemNil:
- return newNil(token.pos)
+ return t.newNil(token.pos)
case itemVariable:
return t.useVar(token.pos, token.val)
case itemField:
- return newField(token.pos, token.val)
+ return t.newField(token.pos, token.val)
case itemBool:
- return newBool(token.pos, token.val == "true")
+ return t.newBool(token.pos, token.val == "true")
case itemCharConstant, itemComplex, itemNumber:
- number, err := newNumber(token.pos, token.val, token.typ)
+ number, err := t.newNumber(token.pos, token.val, token.typ)
if err != nil {
t.error(err)
}
@@ -633,7 +639,7 @@ func (t *Tree) term() Node {
if err != nil {
t.error(err)
}
- return newString(token.pos, token.val, s)
+ return t.newString(token.pos, token.val, s)
}
t.backup()
return nil
@@ -660,7 +666,7 @@ func (t *Tree) popVars(n int) {
// useVar returns a node for a variable reference. It errors if the
// variable is not defined.
func (t *Tree) useVar(pos Pos, name string) Node {
- v := newVariable(pos, name)
+ v := t.newVariable(pos, name)
for _, varName := range t.vars {
if varName == v.Ident[0] {
return v
diff --git a/src/pkg/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go
index ba1a18ec5..4a504fa7c 100644
--- a/src/pkg/text/template/parse/parse_test.go
+++ b/src/text/template/parse/parse_test.go
@@ -69,6 +69,8 @@ var numberTests = []numberTest{
{text: "1+2."},
{text: "'x"},
{text: "'xx'"},
+ // Issue 8622 - 0xe parsed as floating point. Very embarrassing.
+ {"0xef", true, true, true, false, 0xef, 0xef, 0xef, 0},
}
func TestNumberParse(t *testing.T) {
@@ -77,6 +79,7 @@ func TestNumberParse(t *testing.T) {
// because imaginary comes out as a number.
var c complex128
typ := itemNumber
+ var tree *Tree
if test.text[0] == '\'' {
typ = itemCharConstant
} else {
@@ -85,7 +88,7 @@ func TestNumberParse(t *testing.T) {
typ = itemComplex
}
}
- n, err := newNumber(0, test.text, typ)
+ n, err := tree.newNumber(0, test.text, typ)
ok := test.isInt || test.isUint || test.isFloat || test.isComplex
if ok && err != nil {
t.Errorf("unexpected error for %q: %s", test.text, err)
diff --git a/src/pkg/text/template/template.go b/src/text/template/template.go
index 249d0cbfb..249d0cbfb 100644
--- a/src/pkg/text/template/template.go
+++ b/src/text/template/template.go
diff --git a/src/pkg/text/template/testdata/file1.tmpl b/src/text/template/testdata/file1.tmpl
index febf9d9f8..febf9d9f8 100644
--- a/src/pkg/text/template/testdata/file1.tmpl
+++ b/src/text/template/testdata/file1.tmpl
diff --git a/src/pkg/text/template/testdata/file2.tmpl b/src/text/template/testdata/file2.tmpl
index 39bf6fb9e..39bf6fb9e 100644
--- a/src/pkg/text/template/testdata/file2.tmpl
+++ b/src/text/template/testdata/file2.tmpl
diff --git a/src/pkg/text/template/testdata/tmpl1.tmpl b/src/text/template/testdata/tmpl1.tmpl
index b72b3a340..b72b3a340 100644
--- a/src/pkg/text/template/testdata/tmpl1.tmpl
+++ b/src/text/template/testdata/tmpl1.tmpl
diff --git a/src/pkg/text/template/testdata/tmpl2.tmpl b/src/text/template/testdata/tmpl2.tmpl
index 16beba6e7..16beba6e7 100644
--- a/src/pkg/text/template/testdata/tmpl2.tmpl
+++ b/src/text/template/testdata/tmpl2.tmpl
diff --git a/src/pkg/time/example_test.go b/src/time/example_test.go
index cfa5b38c5..a37e8b86d 100644
--- a/src/pkg/time/example_test.go
+++ b/src/time/example_test.go
@@ -122,7 +122,7 @@ func ExampleTime_Round() {
}
// Output:
// t.Round( 1ns) = 12:15:30.918273645
- // t.Round( 1us) = 12:15:30.918274
+ // t.Round( 1µs) = 12:15:30.918274
// t.Round( 1ms) = 12:15:30.918
// t.Round( 1s) = 12:15:31
// t.Round( 2s) = 12:15:30
@@ -150,7 +150,7 @@ func ExampleTime_Truncate() {
// Output:
// t.Truncate( 1ns) = 12:15:30.918273645
- // t.Truncate( 1us) = 12:15:30.918273
+ // t.Truncate( 1µs) = 12:15:30.918273
// t.Truncate( 1ms) = 12:15:30.918
// t.Truncate( 1s) = 12:15:30
// t.Truncate( 2s) = 12:15:30
diff --git a/src/pkg/time/export_test.go b/src/time/export_test.go
index 6cd535f6b..6cd535f6b 100644
--- a/src/pkg/time/export_test.go
+++ b/src/time/export_test.go
diff --git a/src/pkg/time/export_windows_test.go b/src/time/export_windows_test.go
index 7e689b829..7e689b829 100644
--- a/src/pkg/time/export_windows_test.go
+++ b/src/time/export_windows_test.go
diff --git a/src/pkg/time/format.go b/src/time/format.go
index 9f210ea27..04e79f32d 100644
--- a/src/pkg/time/format.go
+++ b/src/time/format.go
@@ -7,7 +7,7 @@ package time
import "errors"
// These are predefined layouts for use in Time.Format and Time.Parse.
-// The reference time used in the layouts is:
+// The reference time used in the layouts is the specific time:
// Mon Jan 2 15:04:05 MST 2006
// which is Unix time 1136239445. Since MST is GMT-0700,
// the reference time can be thought of as
@@ -402,7 +402,7 @@ func (t Time) String() string {
// Format returns a textual representation of the time value formatted
// according to layout, which defines the format by showing how the reference
-// time,
+// time, defined to be
// Mon Jan 2 15:04:05 -0700 MST 2006
// would be displayed if it were the value; it serves as an example of the
// desired output. The same display rules will then be applied to the time
@@ -556,7 +556,7 @@ func (t Time) Format(layout string) string {
b = append(b, '+')
}
b = appendUint(b, uint(zone/60), '0')
- if std == stdISO8601ColonTZ || std == stdNumColonTZ {
+ if std == stdISO8601ColonTZ || std == stdNumColonTZ || std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
b = append(b, ':')
}
b = appendUint(b, uint(zone%60), '0')
@@ -676,6 +676,7 @@ func skip(value, prefix string) (string, error) {
// Parse parses a formatted string and returns the time value it represents.
// The layout defines the format by showing how the reference time,
+// defined to be
// Mon Jan 2 15:04:05 -0700 MST 2006
// would be interpreted if it were the value; it serves as an example of
// the input format. The same interpretation will then be made to the
@@ -704,7 +705,7 @@ func skip(value, prefix string) (string, error) {
// The zone abbreviation "UTC" is recognized as UTC regardless of location.
// If the zone abbreviation is unknown, Parse records the time as being
// in a fabricated location with the given zone abbreviation and a zero offset.
-// This choice means that such a time can be parse and reformatted with the
+// This choice means that such a time can be parsed and reformatted with the
// same layout losslessly, but the exact instant used in the representation will
// differ by the actual zone offset. To avoid such problems, prefer time layouts
// that use a numeric zone offset, or use ParseInLocation.
diff --git a/src/pkg/time/format_test.go b/src/time/format_test.go
index 46a598155..ecc5c8f28 100644
--- a/src/pkg/time/format_test.go
+++ b/src/time/format_test.go
@@ -508,10 +508,11 @@ func TestParseSecondsInTimeZone(t *testing.T) {
}
func TestFormatSecondsInTimeZone(t *testing.T) {
- d := Date(1871, 9, 17, 20, 4, 26, 0, FixedZone("LMT", -(34*60+8)))
- timestr := d.Format("2006-01-02T15:04:05Z070000")
- expected := "1871-09-17T20:04:26-003408"
- if timestr != expected {
- t.Errorf("Got %s, want %s", timestr, expected)
+ for _, test := range secondsTimeZoneOffsetTests {
+ d := Date(1871, 1, 1, 5, 33, 2, 0, FixedZone("LMT", test.expectedoffset))
+ timestr := d.Format(test.format)
+ if timestr != test.value {
+ t.Errorf("Format = %s, want %s", timestr, test.value)
+ }
}
}
diff --git a/src/pkg/time/genzabbrs.go b/src/time/genzabbrs.go
index 7c637cb43..9eb0728a4 100644
--- a/src/pkg/time/genzabbrs.go
+++ b/src/time/genzabbrs.go
@@ -7,22 +7,26 @@
//
// usage:
//
-// go run genzabbrs.go | gofmt > $GOROOT/src/pkg/time/zoneinfo_abbrs_windows.go
+// go run genzabbrs.go -output zoneinfo_abbrs_windows.go
//
package main
import (
+ "bytes"
"encoding/xml"
+ "flag"
+ "go/format"
"io/ioutil"
"log"
"net/http"
- "os"
"sort"
"text/template"
"time"
)
+var filename = flag.String("output", "zoneinfo_abbrs_windows.go", "output file name")
+
// getAbbrs finds timezone abbreviations (standard and daylight saving time)
// for location l.
func getAbbrs(l *time.Location) (st, dt string) {
@@ -105,6 +109,7 @@ func readWindowsZones() (zones, error) {
}
func main() {
+ flag.Parse()
zs, err := readWindowsZones()
if err != nil {
log.Fatal(err)
@@ -117,7 +122,16 @@ func main() {
wzURL,
zs,
}
- err = template.Must(template.New("prog").Parse(prog)).Execute(os.Stdout, v)
+ var buf bytes.Buffer
+ err = template.Must(template.New("prog").Parse(prog)).Execute(&buf, v)
+ if err != nil {
+ log.Fatal(err)
+ }
+ data, err := format.Source(buf.Bytes())
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = ioutil.WriteFile(*filename, data, 0644)
if err != nil {
log.Fatal(err)
}
diff --git a/src/time/internal_test.go b/src/time/internal_test.go
new file mode 100644
index 000000000..edd523bc8
--- /dev/null
+++ b/src/time/internal_test.go
@@ -0,0 +1,59 @@
+// 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 time
+
+func init() {
+ // force US/Pacific for time zone tests
+ ForceUSPacificForTesting()
+}
+
+var Interrupt = interrupt
+var DaysIn = daysIn
+
+func empty(arg interface{}, seq uintptr) {}
+
+// Test that a runtimeTimer with a duration so large it overflows
+// does not cause other timers to hang.
+//
+// This test has to be in internal_test.go since it fiddles with
+// unexported data structures.
+func CheckRuntimeTimerOverflow() {
+ // We manually create a runtimeTimer to bypass the overflow
+ // detection logic in NewTimer: we're testing the underlying
+ // runtime.addtimer function.
+ r := &runtimeTimer{
+ when: runtimeNano() + (1<<63 - 1),
+ f: empty,
+ arg: nil,
+ }
+ startTimer(r)
+
+ // Start a goroutine that should send on t.C right away.
+ t := NewTimer(1)
+
+ defer func() {
+ // Subsequent tests won't work correctly if we don't stop the
+ // overflow timer and kick the timer proc back into service.
+ //
+ // The timer proc is now sleeping and can only be awoken by
+ // adding a timer to the *beginning* of the heap. We can't
+ // wake it up by calling NewTimer since other tests may have
+ // left timers running that should have expired before ours.
+ // Instead we zero the overflow timer duration and start it
+ // once more.
+ stopTimer(r)
+ t.Stop()
+ r.when = 0
+ startTimer(r)
+ }()
+
+ // If the test fails, we will hang here until the timeout in the testing package
+ // fires, which is 10 minutes. It would be nice to catch the problem sooner,
+ // but there is no reliable way to guarantee that timerproc schedules without
+ // doing something involving timerproc itself. Previous failed attempts have
+ // tried calling runtime.Gosched and runtime.GC, but neither is reliable.
+ // So we fall back to hope: We hope we don't hang here.
+ <-t.C
+}
diff --git a/src/pkg/time/sleep.go b/src/time/sleep.go
index 6a03f417b..e7a2ee205 100644
--- a/src/pkg/time/sleep.go
+++ b/src/time/sleep.go
@@ -14,11 +14,12 @@ func runtimeNano() int64
// Interface to timers implemented in package runtime.
// Must be in sync with ../runtime/runtime.h:/^struct.Timer$
type runtimeTimer struct {
- i int32
+ i int
when int64
period int64
- f func(int64, interface{}) // NOTE: must not be closure
+ f func(interface{}, uintptr) // NOTE: must not be closure
arg interface{}
+ seq uintptr
}
// when is a helper function for setting the 'when' field of a runtimeTimer.
@@ -42,6 +43,7 @@ func stopTimer(*runtimeTimer) bool
// The Timer type represents a single event.
// When the Timer expires, the current time will be sent on C,
// unless the Timer was created by AfterFunc.
+// A Timer must be created with NewTimer or AfterFunc.
type Timer struct {
C <-chan Time
r runtimeTimer
@@ -53,6 +55,9 @@ type Timer struct {
// Stop does not close the channel, to prevent a read from the channel succeeding
// incorrectly.
func (t *Timer) Stop() bool {
+ if t.r.f == nil {
+ panic("time: Stop called on uninitialized Timer")
+ }
return stopTimer(&t.r)
}
@@ -76,6 +81,9 @@ func NewTimer(d Duration) *Timer {
// It returns true if the timer had been active, false if the timer had
// expired or been stopped.
func (t *Timer) Reset(d Duration) bool {
+ if t.r.f == nil {
+ panic("time: Reset called on uninitialized Timer")
+ }
w := when(d)
active := stopTimer(&t.r)
t.r.when = w
@@ -83,7 +91,7 @@ func (t *Timer) Reset(d Duration) bool {
return active
}
-func sendTime(now int64, c interface{}) {
+func sendTime(c interface{}, seq uintptr) {
// Non-blocking send of time on c.
// Used in NewTimer, it cannot block anyway (buffer).
// Used in NewTicker, dropping sends on the floor is
@@ -117,6 +125,6 @@ func AfterFunc(d Duration, f func()) *Timer {
return t
}
-func goFunc(now int64, arg interface{}) {
+func goFunc(arg interface{}, seq uintptr) {
go arg.(func())()
}
diff --git a/src/pkg/time/sleep_test.go b/src/time/sleep_test.go
index 03f8e732c..c9b2956b7 100644
--- a/src/pkg/time/sleep_test.go
+++ b/src/time/sleep_test.go
@@ -9,12 +9,21 @@ import (
"fmt"
"runtime"
"sort"
+ "strings"
"sync"
"sync/atomic"
"testing"
. "time"
)
+// Go runtime uses different Windows timers for time.Now and sleeping.
+// These can tick at different frequencies and can arrive out of sync.
+// The effect can be seen, for example, as time.Sleep(100ms) is actually
+// shorter then 100ms when measured as difference between time.Now before and
+// after time.Sleep call. This was observed on Windows XP SP3 (windows/386).
+// windowsInaccuracy is to ignore such errors.
+const windowsInaccuracy = 17 * Millisecond
+
func TestSleep(t *testing.T) {
const delay = 100 * Millisecond
go func() {
@@ -23,8 +32,12 @@ func TestSleep(t *testing.T) {
}()
start := Now()
Sleep(delay)
+ delayadj := delay
+ if runtime.GOOS == "windows" {
+ delayadj -= windowsInaccuracy
+ }
duration := Now().Sub(start)
- if duration < delay {
+ if duration < delayadj {
t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
}
}
@@ -150,10 +163,14 @@ func TestAfter(t *testing.T) {
const delay = 100 * Millisecond
start := Now()
end := <-After(delay)
- if duration := Now().Sub(start); duration < delay {
+ delayadj := delay
+ if runtime.GOOS == "windows" {
+ delayadj -= windowsInaccuracy
+ }
+ if duration := Now().Sub(start); duration < delayadj {
t.Fatalf("After(%s) slept for only %d ns", delay, duration)
}
- if min := start.Add(delay); end.Before(min) {
+ if min := start.Add(delayadj); end.Before(min) {
t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
}
}
@@ -387,7 +404,27 @@ func TestOverflowRuntimeTimer(t *testing.T) {
if testing.Short() {
t.Skip("skipping in short mode, see issue 6874")
}
- if err := CheckRuntimeTimerOverflow(); err != nil {
- t.Fatalf(err.Error())
+ // This may hang forever if timers are broken. See comment near
+ // the end of CheckRuntimeTimerOverflow in internal_test.go.
+ CheckRuntimeTimerOverflow()
+}
+
+func checkZeroPanicString(t *testing.T) {
+ e := recover()
+ s, _ := e.(string)
+ if want := "called on uninitialized Timer"; !strings.Contains(s, want) {
+ t.Errorf("panic = %v; want substring %q", e, want)
}
}
+
+func TestZeroTimerResetPanics(t *testing.T) {
+ defer checkZeroPanicString(t)
+ var tr Timer
+ tr.Reset(1)
+}
+
+func TestZeroTimerStopPanics(t *testing.T) {
+ defer checkZeroPanicString(t)
+ var tr Timer
+ tr.Stop()
+}
diff --git a/src/pkg/time/sys_plan9.go b/src/time/sys_plan9.go
index 848472944..848472944 100644
--- a/src/pkg/time/sys_plan9.go
+++ b/src/time/sys_plan9.go
diff --git a/src/pkg/time/sys_unix.go b/src/time/sys_unix.go
index 379e13d6a..379e13d6a 100644
--- a/src/pkg/time/sys_unix.go
+++ b/src/time/sys_unix.go
diff --git a/src/pkg/time/sys_windows.go b/src/time/sys_windows.go
index de63b4bf4..de63b4bf4 100644
--- a/src/pkg/time/sys_windows.go
+++ b/src/time/sys_windows.go
diff --git a/src/pkg/time/tick.go b/src/time/tick.go
index 19007841e..19007841e 100644
--- a/src/pkg/time/tick.go
+++ b/src/time/tick.go
diff --git a/src/pkg/time/tick_test.go b/src/time/tick_test.go
index 32f4740ad..32f4740ad 100644
--- a/src/pkg/time/tick_test.go
+++ b/src/time/tick_test.go
diff --git a/src/pkg/time/time.go b/src/time/time.go
index 0a2b09142..0300e846a 100644
--- a/src/pkg/time/time.go
+++ b/src/time/time.go
@@ -31,6 +31,11 @@ import "errors"
// change the instant in time being denoted and therefore does not affect the
// computations described in earlier paragraphs.
//
+// Note that the Go == operator compares not just the time instant but also the
+// Location. Therefore, Time values should not be used as map or database keys
+// without first guaranteeing that the identical Location has been set for all
+// values, which can be achieved through use of the UTC or Local method.
+//
type Time struct {
// sec gives the number of seconds elapsed since
// January 1, year 1 00:00:00 UTC.
@@ -39,14 +44,7 @@ type Time struct {
// nsec specifies a non-negative nanosecond
// offset within the second named by Seconds.
// It must be in the range [0, 999999999].
- //
- // It is declared as uintptr instead of int32 or uint32
- // to avoid garbage collector aliasing in the case where
- // on a 64-bit system the int32 or uint32 field is written
- // over the low half of a pointer, creating another pointer.
- // TODO(rsc): When the garbage collector is completely
- // precise, change back to int32.
- nsec uintptr
+ nsec int32
// loc specifies the Location that should be used to
// determine the minute, hour, month, day, and year
@@ -475,29 +473,28 @@ func (d Duration) String() string {
if u < uint64(Second) {
// Special case: if duration is smaller than a second,
// use smaller units, like 1.2ms
- var (
- prec int
- unit byte
- )
+ var prec int
+ w--
+ buf[w] = 's'
+ w--
switch {
case u == 0:
return "0"
case u < uint64(Microsecond):
// print nanoseconds
prec = 0
- unit = 'n'
+ buf[w] = 'n'
case u < uint64(Millisecond):
// print microseconds
prec = 3
- unit = 'u'
+ // U+00B5 'µ' micro sign == 0xC2 0xB5
+ w-- // Need room for two bytes.
+ copy(buf[w:], "µ")
default:
// print milliseconds
prec = 6
- unit = 'm'
+ buf[w] = 'm'
}
- w -= 2
- buf[w] = unit
- buf[w+1] = 's'
w, u = fmtFrac(buf[:w], u, prec)
w = fmtInt(buf[:w], u)
} else {
@@ -620,7 +617,7 @@ func (t Time) Add(d Duration) Time {
t.sec--
nsec += 1e9
}
- t.nsec = uintptr(nsec)
+ t.nsec = nsec
return t
}
@@ -783,7 +780,7 @@ func now() (sec int64, nsec int32)
// Now returns the current local time.
func Now() Time {
sec, nsec := now()
- return Time{sec + unixToInternal, uintptr(nsec), Local}
+ return Time{sec + unixToInternal, nsec, Local}
}
// UTC returns t with the location set to UTC.
@@ -900,7 +897,7 @@ func (t *Time) UnmarshalBinary(data []byte) error {
int64(buf[3])<<32 | int64(buf[2])<<40 | int64(buf[1])<<48 | int64(buf[0])<<56
buf = buf[8:]
- t.nsec = uintptr(int32(buf[3]) | int32(buf[2])<<8 | int32(buf[1])<<16 | int32(buf[0])<<24)
+ t.nsec = int32(buf[3]) | int32(buf[2])<<8 | int32(buf[1])<<16 | int32(buf[0])<<24
buf = buf[4:]
offset := int(int16(buf[1])|int16(buf[0])<<8) * 60
@@ -979,7 +976,7 @@ func Unix(sec int64, nsec int64) Time {
sec--
}
}
- return Time{sec + unixToInternal, uintptr(nsec), Local}
+ return Time{sec + unixToInternal, int32(nsec), Local}
}
func isLeap(year int) bool {
@@ -1088,7 +1085,7 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T
unix -= int64(offset)
}
- return Time{unix + unixToInternal, uintptr(nsec), loc}
+ return Time{unix + unixToInternal, int32(nsec), loc}
}
// Truncate returns the result of rounding t down to a multiple of d (since the zero time).
diff --git a/src/pkg/time/time_test.go b/src/time/time_test.go
index 4ae7da5a4..7e31dd78a 100644
--- a/src/pkg/time/time_test.go
+++ b/src/time/time_test.go
@@ -535,7 +535,7 @@ var durationTests = []struct {
}{
{"0", 0},
{"1ns", 1 * Nanosecond},
- {"1.1us", 1100 * Nanosecond},
+ {"1.1µs", 1100 * Nanosecond},
{"2.2ms", 2200 * Microsecond},
{"3.3s", 3300 * Millisecond},
{"4m5s", 4*Minute + 5*Second},
diff --git a/src/pkg/time/zoneinfo.go b/src/time/zoneinfo.go
index c8e53a27c..c8e53a27c 100644
--- a/src/pkg/time/zoneinfo.go
+++ b/src/time/zoneinfo.go
diff --git a/src/pkg/time/zoneinfo_abbrs_windows.go b/src/time/zoneinfo_abbrs_windows.go
index 80334371f..51a1a2f66 100644
--- a/src/pkg/time/zoneinfo_abbrs_windows.go
+++ b/src/time/zoneinfo_abbrs_windows.go
@@ -18,6 +18,7 @@ var abbrs = map[string]abbr{
"South Africa Standard Time": {"SAST", "SAST"}, // Africa/Johannesburg
"W. Central Africa Standard Time": {"WAT", "WAT"}, // Africa/Lagos
"E. Africa Standard Time": {"EAT", "EAT"}, // Africa/Nairobi
+ "Libya Standard Time": {"EET", "EET"}, // Africa/Tripoli
"Namibia Standard Time": {"WAT", "WAST"}, // Africa/Windhoek
"Alaskan Standard Time": {"AKST", "AKDT"}, // America/Anchorage
"Paraguay Standard Time": {"PYT", "PYST"}, // America/Asuncion
@@ -63,7 +64,6 @@ var abbrs = map[string]abbr{
"Nepal Standard Time": {"NPT", "NPT"}, // Asia/Katmandu
"North Asia Standard Time": {"KRAT", "KRAT"}, // Asia/Krasnoyarsk
"Magadan Standard Time": {"MAGT", "MAGT"}, // Asia/Magadan
- "E. Europe Standard Time": {"EET", "EEST"}, // Asia/Nicosia
"N. Central Asia Standard Time": {"NOVT", "NOVT"}, // Asia/Novosibirsk
"Myanmar Standard Time": {"MMT", "MMT"}, // Asia/Rangoon
"Arab Standard Time": {"AST", "AST"}, // Asia/Riyadh
@@ -110,6 +110,7 @@ var abbrs = map[string]abbr{
"Fiji Standard Time": {"FJT", "FJT"}, // Pacific/Fiji
"Central Pacific Standard Time": {"SBT", "SBT"}, // Pacific/Guadalcanal
"Hawaiian Standard Time": {"HST", "HST"}, // Pacific/Honolulu
+ "Line Islands Standard Time": {"LINT", "LINT"}, // Pacific/Kiritimati
"West Pacific Standard Time": {"PGT", "PGT"}, // Pacific/Port_Moresby
"Tonga Standard Time": {"TOT", "TOT"}, // Pacific/Tongatapu
}
diff --git a/src/pkg/time/zoneinfo_plan9.go b/src/time/zoneinfo_plan9.go
index 4bb0cb390..4bb0cb390 100644
--- a/src/pkg/time/zoneinfo_plan9.go
+++ b/src/time/zoneinfo_plan9.go
diff --git a/src/pkg/time/zoneinfo_read.go b/src/time/zoneinfo_read.go
index de9ebb41c..de9ebb41c 100644
--- a/src/pkg/time/zoneinfo_read.go
+++ b/src/time/zoneinfo_read.go
diff --git a/src/pkg/time/zoneinfo_test.go b/src/time/zoneinfo_test.go
index 4ca7fad93..4ca7fad93 100644
--- a/src/pkg/time/zoneinfo_test.go
+++ b/src/time/zoneinfo_test.go
diff --git a/src/pkg/time/zoneinfo_unix.go b/src/time/zoneinfo_unix.go
index ab7e4612e..ab7e4612e 100644
--- a/src/pkg/time/zoneinfo_unix.go
+++ b/src/time/zoneinfo_unix.go
diff --git a/src/pkg/time/zoneinfo_windows.go b/src/time/zoneinfo_windows.go
index 6046743e6..02d8e0edc 100644
--- a/src/pkg/time/zoneinfo_windows.go
+++ b/src/time/zoneinfo_windows.go
@@ -11,6 +11,8 @@ import (
"unsafe"
)
+//go:generate go run genzabbrs.go -output zoneinfo_abbrs_windows.go
+
// TODO(rsc): Fall back to copy of zoneinfo files.
// BUG(brainman,rsc): On Windows, the operating system does not provide complete
diff --git a/src/pkg/time/zoneinfo_windows_test.go b/src/time/zoneinfo_windows_test.go
index 9db81b7cf..9db81b7cf 100644
--- a/src/pkg/time/zoneinfo_windows_test.go
+++ b/src/time/zoneinfo_windows_test.go
diff --git a/src/pkg/unicode/casetables.go b/src/unicode/casetables.go
index 29bf167e5..29bf167e5 100644
--- a/src/pkg/unicode/casetables.go
+++ b/src/unicode/casetables.go
diff --git a/src/pkg/unicode/digit.go b/src/unicode/digit.go
index 53171b396..53171b396 100644
--- a/src/pkg/unicode/digit.go
+++ b/src/unicode/digit.go
diff --git a/src/pkg/unicode/digit_test.go b/src/unicode/digit_test.go
index 551c42a24..551c42a24 100644
--- a/src/pkg/unicode/digit_test.go
+++ b/src/unicode/digit_test.go
diff --git a/src/pkg/unicode/graphic.go b/src/unicode/graphic.go
index ba90b4e51..ba90b4e51 100644
--- a/src/pkg/unicode/graphic.go
+++ b/src/unicode/graphic.go
diff --git a/src/pkg/unicode/graphic_test.go b/src/unicode/graphic_test.go
index c9f289c7f..c9f289c7f 100644
--- a/src/pkg/unicode/graphic_test.go
+++ b/src/unicode/graphic_test.go
diff --git a/src/pkg/unicode/letter.go b/src/unicode/letter.go
index 977bd2b3b..7fe4241ed 100644
--- a/src/pkg/unicode/letter.go
+++ b/src/unicode/letter.go
@@ -6,6 +6,9 @@
// Unicode code points.
package unicode
+// Tables are regenerated each time we update the Unicode version.
+//go:generate go run maketables.go -tables=all -output tables.go
+
const (
MaxRune = '\U0010FFFF' // Maximum valid Unicode code point.
ReplacementChar = '\uFFFD' // Represents invalid code points.
diff --git a/src/pkg/unicode/letter_test.go b/src/unicode/letter_test.go
index 4ee11fb36..4ee11fb36 100644
--- a/src/pkg/unicode/letter_test.go
+++ b/src/unicode/letter_test.go
diff --git a/src/pkg/unicode/maketables.go b/src/unicode/maketables.go
index 8116ab8a4..d1c9aa04a 100644
--- a/src/pkg/unicode/maketables.go
+++ b/src/unicode/maketables.go
@@ -13,9 +13,11 @@ import (
"bufio"
"flag"
"fmt"
+ "io"
"log"
"net/http"
"os"
+ "os/exec"
"path/filepath"
"regexp"
"sort"
@@ -26,6 +28,7 @@ import (
func main() {
flag.Parse()
+ setupOutput()
loadChars() // always needed
loadCasefold()
printCategories()
@@ -35,12 +38,13 @@ func main() {
printLatinProperties()
printCasefold()
printSizes()
+ flushOutput()
}
var dataURL = flag.String("data", "", "full URL for UnicodeData.txt; defaults to --url/UnicodeData.txt")
var casefoldingURL = flag.String("casefolding", "", "full URL for CaseFolding.txt; defaults to --url/CaseFolding.txt")
var url = flag.String("url",
- "http://www.unicode.org/Public/6.3.0/ucd/",
+ "http://www.unicode.org/Public/7.0.0/ucd/",
"URL of Unicode database directory")
var tablelist = flag.String("tables",
"all",
@@ -60,10 +64,62 @@ var test = flag.Bool("test",
var localFiles = flag.Bool("local",
false,
"data files have been copied to current directory; for debugging only")
+var outputFile = flag.String("output",
+ "",
+ "output file for generated tables; default stdout")
var scriptRe = regexp.MustCompile(`^([0-9A-F]+)(\.\.[0-9A-F]+)? *; ([A-Za-z_]+)$`)
var logger = log.New(os.Stderr, "", log.Lshortfile)
+var output *bufio.Writer // points to os.Stdout or to "gofmt > outputFile"
+
+func setupOutput() {
+ output = bufio.NewWriter(startGofmt())
+}
+
+// startGofmt connects output to a gofmt process if -output is set.
+func startGofmt() io.Writer {
+ if *outputFile == "" {
+ return os.Stdout
+ }
+ stdout, err := os.Create(*outputFile)
+ if err != nil {
+ logger.Fatal(err)
+ }
+ // Pipe output to gofmt.
+ gofmt := exec.Command("gofmt")
+ fd, err := gofmt.StdinPipe()
+ if err != nil {
+ logger.Fatal(err)
+ }
+ gofmt.Stdout = stdout
+ gofmt.Stderr = os.Stderr
+ err = gofmt.Start()
+ if err != nil {
+ logger.Fatal(err)
+ }
+ return fd
+}
+
+func flushOutput() {
+ err := output.Flush()
+ if err != nil {
+ logger.Fatal(err)
+ }
+}
+
+func printf(format string, args ...interface{}) {
+ fmt.Fprintf(output, format, args...)
+}
+
+func print(args ...interface{}) {
+ fmt.Fprint(output, args...)
+}
+
+func println(args ...interface{}) {
+ fmt.Fprintln(output, args...)
+}
+
type reader struct {
*bufio.Reader
fd *os.File
@@ -245,11 +301,11 @@ func parseCategory(line string) (state State) {
}
func (char *Char) dump(s string) {
- fmt.Print(s, " ")
+ print(s, " ")
for i := 0; i < len(char.field); i++ {
- fmt.Printf("%s:%q ", fieldName[i], char.field[i])
+ printf("%s:%q ", fieldName[i], char.field[i])
}
- fmt.Print("\n")
+ print("\n")
}
func (char *Char) letter(u, l, t string) {
@@ -411,18 +467,18 @@ func printCategories() {
fullCategoryTest(list)
return
}
- fmt.Printf(progHeader, *tablelist, *dataURL, *casefoldingURL)
+ printf(progHeader, *tablelist, *dataURL, *casefoldingURL)
- fmt.Println("// Version is the Unicode edition from which the tables are derived.")
- fmt.Printf("const Version = %q\n\n", version())
+ println("// Version is the Unicode edition from which the tables are derived.")
+ printf("const Version = %q\n\n", version())
if *tablelist == "all" {
- fmt.Println("// Categories is the set of Unicode category tables.")
- fmt.Println("var Categories = map[string] *RangeTable {")
+ println("// Categories is the set of Unicode category tables.")
+ println("var Categories = map[string] *RangeTable {")
for _, k := range allCategories() {
- fmt.Printf("\t%q: %s,\n", k, k)
+ printf("\t%q: %s,\n", k, k)
}
- fmt.Print("}\n\n")
+ print("}\n\n")
}
decl := make(sort.StringSlice, len(list))
@@ -486,12 +542,12 @@ func printCategories() {
func(code rune) bool { return chars[code].category == name })
}
decl.Sort()
- fmt.Println("// These variables have type *RangeTable.")
- fmt.Println("var (")
+ println("// These variables have type *RangeTable.")
+ println("var (")
for _, d := range decl {
- fmt.Print(d)
+ print(d)
}
- fmt.Print(")\n\n")
+ print(")\n\n")
}
type Op func(code rune) bool
@@ -499,10 +555,10 @@ type Op func(code rune) bool
const format = "\t\t{0x%04x, 0x%04x, %d},\n"
func dumpRange(header string, inCategory Op) {
- fmt.Print(header)
+ print(header)
next := rune(0)
latinOffset := 0
- fmt.Print("\tR16: []Range16{\n")
+ print("\tR16: []Range16{\n")
// one Range for each iteration
count := &range16Count
size := 16
@@ -528,7 +584,7 @@ func dumpRange(header string, inCategory Op) {
}
if next >= rune(len(chars)) {
// no more characters
- fmt.Printf(format, lo, hi, stride)
+ printf(format, lo, hi, stride)
break
}
// set stride
@@ -552,11 +608,11 @@ func dumpRange(header string, inCategory Op) {
// next range: start looking where this range ends
next = hi + 1
}
- fmt.Print("\t},\n")
+ print("\t},\n")
if latinOffset > 0 {
- fmt.Printf("\tLatinOffset: %d,\n", latinOffset)
+ printf("\tLatinOffset: %d,\n", latinOffset)
}
- fmt.Print("}\n\n")
+ print("}\n\n")
}
func printRange(lo, hi, stride uint32, size int, count *int) (int, *int) {
@@ -568,17 +624,17 @@ func printRange(lo, hi, stride uint32, size int, count *int) (int, *int) {
// No range contains U+FFFF as an instance, so split
// the range into two entries. That way we can maintain
// the invariant that R32 contains only >= 1<<16.
- fmt.Printf(format, lo, lo, 1)
+ printf(format, lo, lo, 1)
lo = hi
stride = 1
*count++
}
- fmt.Print("\t},\n")
- fmt.Print("\tR32: []Range32{\n")
+ print("\t},\n")
+ print("\tR32: []Range32{\n")
size = 32
count = &range32Count
}
- fmt.Printf(format, lo, hi, stride)
+ printf(format, lo, hi, stride)
*count++
return size, count
}
@@ -727,7 +783,7 @@ func printScriptOrProperty(doProps bool) {
return
}
- fmt.Printf(
+ printf(
"// Generated by running\n"+
"// maketables --%s=%s --url=%s\n"+
"// DO NOT EDIT\n\n",
@@ -736,16 +792,16 @@ func printScriptOrProperty(doProps bool) {
*url)
if flaglist == "all" {
if doProps {
- fmt.Println("// Properties is the set of Unicode property tables.")
- fmt.Println("var Properties = map[string] *RangeTable{")
+ println("// Properties is the set of Unicode property tables.")
+ println("var Properties = map[string] *RangeTable{")
} else {
- fmt.Println("// Scripts is the set of Unicode script tables.")
- fmt.Println("var Scripts = map[string] *RangeTable{")
+ println("// Scripts is the set of Unicode script tables.")
+ println("var Scripts = map[string] *RangeTable{")
}
for _, k := range all(table) {
- fmt.Printf("\t%q: %s,\n", k, k)
+ printf("\t%q: %s,\n", k, k)
}
- fmt.Print("}\n\n")
+ print("}\n\n")
}
decl := make(sort.StringSlice, len(list))
@@ -761,27 +817,27 @@ func printScriptOrProperty(doProps bool) {
name, name, name, name)
}
ndecl++
- fmt.Printf("var _%s = &RangeTable {\n", name)
+ printf("var _%s = &RangeTable {\n", name)
ranges := foldAdjacent(table[name])
- fmt.Print("\tR16: []Range16{\n")
+ print("\tR16: []Range16{\n")
size := 16
count := &range16Count
for _, s := range ranges {
size, count = printRange(s.Lo, s.Hi, s.Stride, size, count)
}
- fmt.Print("\t},\n")
+ print("\t},\n")
if off := findLatinOffset(ranges); off > 0 {
- fmt.Printf("\tLatinOffset: %d,\n", off)
+ printf("\tLatinOffset: %d,\n", off)
}
- fmt.Print("}\n\n")
+ print("}\n\n")
}
decl.Sort()
- fmt.Println("// These variables have type *RangeTable.")
- fmt.Println("var (")
+ println("// These variables have type *RangeTable.")
+ println("var (")
for _, d := range decl {
- fmt.Print(d)
+ print(d)
}
- fmt.Print(")\n\n")
+ print(")\n\n")
}
func findLatinOffset(ranges []unicode.Range32) int {
@@ -940,7 +996,7 @@ func printCases() {
fullCaseTest()
return
}
- fmt.Printf(
+ printf(
"// Generated by running\n"+
"// maketables --data=%s --casefolding=%s\n"+
"// DO NOT EDIT\n\n"+
@@ -966,7 +1022,7 @@ func printCases() {
}
prevState = state
}
- fmt.Print("}\n")
+ print("}\n")
}
func printCaseRange(lo, hi *caseState) {
@@ -979,14 +1035,14 @@ func printCaseRange(lo, hi *caseState) {
}
switch {
case hi.point > lo.point && lo.isUpperLower():
- fmt.Printf("\t{0x%04X, 0x%04X, d{UpperLower, UpperLower, UpperLower}},\n",
+ printf("\t{0x%04X, 0x%04X, d{UpperLower, UpperLower, UpperLower}},\n",
lo.point, hi.point)
case hi.point > lo.point && lo.isLowerUpper():
logger.Fatalf("LowerUpper sequence: should not happen: %U. If it's real, need to fix To()", lo.point)
- fmt.Printf("\t{0x%04X, 0x%04X, d{LowerUpper, LowerUpper, LowerUpper}},\n",
+ printf("\t{0x%04X, 0x%04X, d{LowerUpper, LowerUpper, LowerUpper}},\n",
lo.point, hi.point)
default:
- fmt.Printf("\t{0x%04X, 0x%04X, d{%d, %d, %d}},\n",
+ printf("\t{0x%04X, 0x%04X, d{%d, %d, %d}},\n",
lo.point, hi.point,
lo.deltaToUpper, lo.deltaToLower, lo.deltaToTitle)
}
@@ -1025,7 +1081,7 @@ func printLatinProperties() {
if *test {
return
}
- fmt.Println("var properties = [MaxLatin1+1]uint8{")
+ println("var properties = [MaxLatin1+1]uint8{")
for code := 0; code <= unicode.MaxLatin1; code++ {
var property string
switch chars[code].category {
@@ -1054,9 +1110,9 @@ func printLatinProperties() {
if code == ' ' {
property = "pZ | pp"
}
- fmt.Printf("\t0x%02X: %s, // %q\n", code, property, code)
+ printf("\t0x%02X: %s, // %q\n", code, property, code)
}
- fmt.Printf("}\n\n")
+ printf("}\n\n")
}
type runeSlice []rune
@@ -1235,15 +1291,15 @@ func printCaseOrbit() {
return
}
- fmt.Printf("var caseOrbit = []foldPair{\n")
+ printf("var caseOrbit = []foldPair{\n")
for i := range chars {
c := &chars[i]
if c.caseOrbit != 0 {
- fmt.Printf("\t{0x%04X, 0x%04X},\n", i, c.caseOrbit)
+ printf("\t{0x%04X, 0x%04X},\n", i, c.caseOrbit)
foldPairCount++
}
}
- fmt.Printf("}\n\n")
+ printf("}\n\n")
}
func printCatFold(name string, m map[string]map[rune]bool) {
@@ -1288,12 +1344,12 @@ func printCatFold(name string, m map[string]map[rune]bool) {
return
}
- fmt.Print(comment[name])
- fmt.Printf("var %s = map[string]*RangeTable{\n", name)
+ print(comment[name])
+ printf("var %s = map[string]*RangeTable{\n", name)
for _, name := range allCatFold(m) {
- fmt.Printf("\t%q: fold%s,\n", name, name)
+ printf("\t%q: fold%s,\n", name, name)
}
- fmt.Printf("}\n\n")
+ printf("}\n\n")
for _, name := range allCatFold(m) {
class := m[name]
dumpRange(
@@ -1310,11 +1366,11 @@ func printSizes() {
if *test {
return
}
- fmt.Println()
- fmt.Printf("// Range entries: %d 16-bit, %d 32-bit, %d total.\n", range16Count, range32Count, range16Count+range32Count)
+ println()
+ printf("// Range entries: %d 16-bit, %d 32-bit, %d total.\n", range16Count, range32Count, range16Count+range32Count)
range16Bytes := range16Count * 3 * 2
range32Bytes := range32Count * 3 * 4
- fmt.Printf("// Range bytes: %d 16-bit, %d 32-bit, %d total.\n", range16Bytes, range32Bytes, range16Bytes+range32Bytes)
- fmt.Println()
- fmt.Printf("// Fold orbit bytes: %d pairs, %d bytes\n", foldPairCount, foldPairCount*2*2)
+ printf("// Range bytes: %d 16-bit, %d 32-bit, %d total.\n", range16Bytes, range32Bytes, range16Bytes+range32Bytes)
+ println()
+ printf("// Fold orbit bytes: %d pairs, %d bytes\n", foldPairCount, foldPairCount*2*2)
}
diff --git a/src/pkg/unicode/script_test.go b/src/unicode/script_test.go
index e2ba0011a..795cb4e17 100644
--- a/src/pkg/unicode/script_test.go
+++ b/src/unicode/script_test.go
@@ -14,14 +14,15 @@ type T struct {
script string
}
-// Hand-chosen tests from Unicode 5.1.0, 6.0.0 and 6.2.0 mostly to discover when new
-// scripts and categories arise.
+// Hand-chosen tests from Unicode 5.1.0, 6.0.0, 6.2.0, 6.3.0 and 7.0.0 mostly to
+// discover when new scripts and categories arise.
var inTest = []T{
{0x06e2, "Arabic"},
{0x0567, "Armenian"},
{0x10b20, "Avestan"},
{0x1b37, "Balinese"},
{0xa6af, "Bamum"},
+ {0x16ada, "Bassa_Vah"},
{0x1be1, "Batak"},
{0x09c2, "Bengali"},
{0x3115, "Bopomofo"},
@@ -31,6 +32,7 @@ var inTest = []T{
{0x11011, "Brahmi"},
{0x156d, "Canadian_Aboriginal"},
{0x102a9, "Carian"},
+ {0x10563, "Caucasian_Albanian"},
{0x11111, "Chakma"},
{0xaa4d, "Cham"},
{0x13c2, "Cherokee"},
@@ -42,11 +44,14 @@ var inTest = []T{
{0xa663, "Cyrillic"},
{0x10430, "Deseret"},
{0x094a, "Devanagari"},
+ {0x1BC00, "Duployan"},
{0x13001, "Egyptian_Hieroglyphs"},
+ {0x10500, "Elbasan"},
{0x1271, "Ethiopic"},
{0x10fc, "Georgian"},
{0x2c40, "Glagolitic"},
{0x10347, "Gothic"},
+ {0x11303, "Grantha"},
{0x03ae, "Greek"},
{0x0abf, "Gujarati"},
{0x0a24, "Gurmukhi"},
@@ -66,40 +71,56 @@ var inTest = []T{
{0xa928, "Kayah_Li"},
{0x10a11, "Kharoshthi"},
{0x17c6, "Khmer"},
+ {0x11211, "Khojki"},
+ {0x112df, "Khudawadi"},
{0x0eaa, "Lao"},
{0x1d79, "Latin"},
{0x1c10, "Lepcha"},
{0x1930, "Limbu"},
+ {0x10755, "Linear_A"},
{0x1003c, "Linear_B"},
{0xa4e1, "Lisu"},
{0x10290, "Lycian"},
{0x10930, "Lydian"},
+ {0x11173, "Mahajani"},
{0x0d42, "Malayalam"},
{0x0843, "Mandaic"},
+ {0x10ac8, "Manichaean"},
{0xabd0, "Meetei_Mayek"},
+ {0x1e800, "Mende_Kikakui"},
{0x1099f, "Meroitic_Hieroglyphs"},
{0x109a0, "Meroitic_Cursive"},
{0x16f00, "Miao"},
+ {0x11611, "Modi"},
{0x1822, "Mongolian"},
+ {0x16a60, "Mro"},
{0x104c, "Myanmar"},
+ {0x10880, "Nabataean"},
{0x19c3, "New_Tai_Lue"},
{0x07f8, "Nko"},
{0x169b, "Ogham"},
{0x1c6a, "Ol_Chiki"},
{0x10310, "Old_Italic"},
+ {0x10a80, "Old_North_Arabian"},
+ {0x10350, "Old_Permic"},
{0x103c9, "Old_Persian"},
{0x10a6f, "Old_South_Arabian"},
{0x10c20, "Old_Turkic"},
{0x0b3e, "Oriya"},
{0x10491, "Osmanya"},
+ {0x16b2b, "Pahawh_Hmong"},
+ {0x10876, "Palmyrene"},
+ {0x11ACE, "Pau_Cin_Hau"},
{0xa860, "Phags_Pa"},
{0x10918, "Phoenician"},
+ {0x10baf, "Psalter_Pahlavi"},
{0xa949, "Rejang"},
{0x16c0, "Runic"},
{0x081d, "Samaritan"},
{0xa892, "Saurashtra"},
{0x111a0, "Sharada"},
{0x10463, "Shavian"},
+ {0x115c1, "Siddham"},
{0x0dbd, "Sinhala"},
{0x110d0, "Sora_Sompeng"},
{0x1ba3, "Sundanese"},
@@ -117,8 +138,10 @@ var inTest = []T{
{0x0e46, "Thai"},
{0x0f36, "Tibetan"},
{0x2d55, "Tifinagh"},
+ {0x114d9, "Tirhuta"},
{0x10388, "Ugaritic"},
{0xa60e, "Vai"},
+ {0x118ff, "Warang_Citi"},
{0xa216, "Yi"},
}
diff --git a/src/pkg/unicode/tables.go b/src/unicode/tables.go
index 5670d1c5b..8b77dd603 100644
--- a/src/pkg/unicode/tables.go
+++ b/src/unicode/tables.go
@@ -3,13 +3,13 @@
// license that can be found in the LICENSE file.
// Generated by running
-// maketables --tables=all --data=http://www.unicode.org/Public/6.3.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/6.3.0/ucd/CaseFolding.txt
+// maketables --tables=all --data=http://www.unicode.org/Public/7.0.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/7.0.0/ucd/CaseFolding.txt
// DO NOT EDIT
package unicode
// Version is the Unicode edition from which the tables are derived.
-const Version = "6.3.0"
+const Version = "7.0.0"
// Categories is the set of Unicode category tables.
var Categories = map[string]*RangeTable{
@@ -56,7 +56,7 @@ var _C = &RangeTable{
{0x0001, 0x001f, 1},
{0x007f, 0x009f, 1},
{0x00ad, 0x0600, 1363},
- {0x0601, 0x0604, 1},
+ {0x0601, 0x0605, 1},
{0x061c, 0x06dd, 193},
{0x070f, 0x180e, 4351},
{0x200b, 0x200f, 1},
@@ -68,8 +68,9 @@ var _C = &RangeTable{
{0xfffa, 0xfffb, 1},
},
R32: []Range32{
- {0x110bd, 0x1d173, 49334},
- {0x1d174, 0x1d17a, 1},
+ {0x110bd, 0x1bca0, 44003},
+ {0x1bca1, 0x1bca3, 1},
+ {0x1d173, 0x1d17a, 1},
{0xe0001, 0xe0020, 31},
{0xe0021, 0xe007f, 1},
{0xf0000, 0xffffd, 1},
@@ -89,7 +90,7 @@ var _Cc = &RangeTable{
var _Cf = &RangeTable{
R16: []Range16{
{0x00ad, 0x0600, 1363},
- {0x0601, 0x0604, 1},
+ {0x0601, 0x0605, 1},
{0x061c, 0x06dd, 193},
{0x070f, 0x180e, 4351},
{0x200b, 0x200f, 1},
@@ -100,8 +101,9 @@ var _Cf = &RangeTable{
{0xfffa, 0xfffb, 1},
},
R32: []Range32{
- {0x110bd, 0x1d173, 49334},
- {0x1d174, 0x1d17a, 1},
+ {0x110bd, 0x1bca0, 44003},
+ {0x1bca1, 0x1bca3, 1},
+ {0x1d173, 0x1d17a, 1},
{0xe0001, 0xe0020, 31},
{0xe0021, 0xe007f, 1},
},
@@ -138,13 +140,13 @@ var _L = &RangeTable{
{0x0370, 0x0374, 1},
{0x0376, 0x0377, 1},
{0x037a, 0x037d, 1},
- {0x0386, 0x0388, 2},
- {0x0389, 0x038a, 1},
+ {0x037f, 0x0386, 7},
+ {0x0388, 0x038a, 1},
{0x038c, 0x038e, 2},
{0x038f, 0x03a1, 1},
{0x03a3, 0x03f5, 1},
{0x03f7, 0x0481, 1},
- {0x048a, 0x0527, 1},
+ {0x048a, 0x052f, 1},
{0x0531, 0x0556, 1},
{0x0559, 0x0561, 8},
{0x0562, 0x0587, 1},
@@ -168,13 +170,11 @@ var _L = &RangeTable{
{0x081a, 0x0824, 10},
{0x0828, 0x0840, 24},
{0x0841, 0x0858, 1},
- {0x08a0, 0x08a2, 2},
- {0x08a3, 0x08ac, 1},
+ {0x08a0, 0x08b2, 1},
{0x0904, 0x0939, 1},
{0x093d, 0x0950, 19},
{0x0958, 0x0961, 1},
- {0x0971, 0x0977, 1},
- {0x0979, 0x097f, 1},
+ {0x0971, 0x0980, 1},
{0x0985, 0x098c, 1},
{0x098f, 0x0990, 1},
{0x0993, 0x09a8, 1},
@@ -226,8 +226,7 @@ var _L = &RangeTable{
{0x0c06, 0x0c0c, 1},
{0x0c0e, 0x0c10, 1},
{0x0c12, 0x0c28, 1},
- {0x0c2a, 0x0c33, 1},
- {0x0c35, 0x0c39, 1},
+ {0x0c2a, 0x0c39, 1},
{0x0c3d, 0x0c58, 27},
{0x0c59, 0x0c60, 7},
{0x0c61, 0x0c85, 36},
@@ -306,6 +305,7 @@ var _L = &RangeTable{
{0x166f, 0x167f, 1},
{0x1681, 0x169a, 1},
{0x16a0, 0x16ea, 1},
+ {0x16f1, 0x16f8, 1},
{0x1700, 0x170c, 1},
{0x170e, 0x1711, 1},
{0x1720, 0x1731, 1},
@@ -318,7 +318,7 @@ var _L = &RangeTable{
{0x1880, 0x18a8, 1},
{0x18aa, 0x18b0, 6},
{0x18b1, 0x18f5, 1},
- {0x1900, 0x191c, 1},
+ {0x1900, 0x191e, 1},
{0x1950, 0x196d, 1},
{0x1970, 0x1974, 1},
{0x1980, 0x19ab, 1},
@@ -406,14 +406,14 @@ var _L = &RangeTable{
{0xa610, 0xa61f, 1},
{0xa62a, 0xa62b, 1},
{0xa640, 0xa66e, 1},
- {0xa67f, 0xa697, 1},
+ {0xa67f, 0xa69d, 1},
{0xa6a0, 0xa6e5, 1},
{0xa717, 0xa71f, 1},
{0xa722, 0xa788, 1},
{0xa78b, 0xa78e, 1},
- {0xa790, 0xa793, 1},
- {0xa7a0, 0xa7aa, 1},
- {0xa7f8, 0xa801, 1},
+ {0xa790, 0xa7ad, 1},
+ {0xa7b0, 0xa7b1, 1},
+ {0xa7f7, 0xa801, 1},
{0xa803, 0xa805, 1},
{0xa807, 0xa80a, 1},
{0xa80c, 0xa822, 1},
@@ -425,13 +425,16 @@ var _L = &RangeTable{
{0xa930, 0xa946, 1},
{0xa960, 0xa97c, 1},
{0xa984, 0xa9b2, 1},
- {0xa9cf, 0xaa00, 49},
- {0xaa01, 0xaa28, 1},
+ {0xa9cf, 0xa9e0, 17},
+ {0xa9e1, 0xa9e4, 1},
+ {0xa9e6, 0xa9ef, 1},
+ {0xa9fa, 0xa9fe, 1},
+ {0xaa00, 0xaa28, 1},
{0xaa40, 0xaa42, 1},
{0xaa44, 0xaa4b, 1},
{0xaa60, 0xaa76, 1},
- {0xaa7a, 0xaa80, 6},
- {0xaa81, 0xaaaf, 1},
+ {0xaa7a, 0xaa7e, 4},
+ {0xaa7f, 0xaaaf, 1},
{0xaab1, 0xaab5, 4},
{0xaab6, 0xaab9, 3},
{0xaaba, 0xaabd, 1},
@@ -444,6 +447,9 @@ var _L = &RangeTable{
{0xab11, 0xab16, 1},
{0xab20, 0xab26, 1},
{0xab28, 0xab2e, 1},
+ {0xab30, 0xab5a, 1},
+ {0xab5c, 0xab5f, 1},
+ {0xab64, 0xab65, 1},
{0xabc0, 0xabe2, 1},
{0xac00, 0xd7a3, 1},
{0xd7b0, 0xd7c6, 1},
@@ -484,19 +490,27 @@ var _L = &RangeTable{
{0x10080, 0x100fa, 1},
{0x10280, 0x1029c, 1},
{0x102a0, 0x102d0, 1},
- {0x10300, 0x1031e, 1},
+ {0x10300, 0x1031f, 1},
{0x10330, 0x10340, 1},
{0x10342, 0x10349, 1},
+ {0x10350, 0x10375, 1},
{0x10380, 0x1039d, 1},
{0x103a0, 0x103c3, 1},
{0x103c8, 0x103cf, 1},
{0x10400, 0x1049d, 1},
+ {0x10500, 0x10527, 1},
+ {0x10530, 0x10563, 1},
+ {0x10600, 0x10736, 1},
+ {0x10740, 0x10755, 1},
+ {0x10760, 0x10767, 1},
{0x10800, 0x10805, 1},
{0x10808, 0x1080a, 2},
{0x1080b, 0x10835, 1},
{0x10837, 0x10838, 1},
{0x1083c, 0x1083f, 3},
{0x10840, 0x10855, 1},
+ {0x10860, 0x10876, 1},
+ {0x10880, 0x1089e, 1},
{0x10900, 0x10915, 1},
{0x10920, 0x10939, 1},
{0x10980, 0x109b7, 1},
@@ -506,24 +520,61 @@ var _L = &RangeTable{
{0x10a15, 0x10a17, 1},
{0x10a19, 0x10a33, 1},
{0x10a60, 0x10a7c, 1},
+ {0x10a80, 0x10a9c, 1},
+ {0x10ac0, 0x10ac7, 1},
+ {0x10ac9, 0x10ae4, 1},
{0x10b00, 0x10b35, 1},
{0x10b40, 0x10b55, 1},
{0x10b60, 0x10b72, 1},
+ {0x10b80, 0x10b91, 1},
{0x10c00, 0x10c48, 1},
{0x11003, 0x11037, 1},
{0x11083, 0x110af, 1},
{0x110d0, 0x110e8, 1},
{0x11103, 0x11126, 1},
- {0x11183, 0x111b2, 1},
+ {0x11150, 0x11172, 1},
+ {0x11176, 0x11183, 13},
+ {0x11184, 0x111b2, 1},
{0x111c1, 0x111c4, 1},
- {0x11680, 0x116aa, 1},
- {0x12000, 0x1236e, 1},
+ {0x111da, 0x11200, 38},
+ {0x11201, 0x11211, 1},
+ {0x11213, 0x1122b, 1},
+ {0x112b0, 0x112de, 1},
+ {0x11305, 0x1130c, 1},
+ {0x1130f, 0x11310, 1},
+ {0x11313, 0x11328, 1},
+ {0x1132a, 0x11330, 1},
+ {0x11332, 0x11333, 1},
+ {0x11335, 0x11339, 1},
+ {0x1133d, 0x1135d, 32},
+ {0x1135e, 0x11361, 1},
+ {0x11480, 0x114af, 1},
+ {0x114c4, 0x114c5, 1},
+ {0x114c7, 0x11580, 185},
+ {0x11581, 0x115ae, 1},
+ {0x11600, 0x1162f, 1},
+ {0x11644, 0x11680, 60},
+ {0x11681, 0x116aa, 1},
+ {0x118a0, 0x118df, 1},
+ {0x118ff, 0x11ac0, 449},
+ {0x11ac1, 0x11af8, 1},
+ {0x12000, 0x12398, 1},
{0x13000, 0x1342e, 1},
{0x16800, 0x16a38, 1},
+ {0x16a40, 0x16a5e, 1},
+ {0x16ad0, 0x16aed, 1},
+ {0x16b00, 0x16b2f, 1},
+ {0x16b40, 0x16b43, 1},
+ {0x16b63, 0x16b77, 1},
+ {0x16b7d, 0x16b8f, 1},
{0x16f00, 0x16f44, 1},
{0x16f50, 0x16f93, 67},
{0x16f94, 0x16f9f, 1},
{0x1b000, 0x1b001, 1},
+ {0x1bc00, 0x1bc6a, 1},
+ {0x1bc70, 0x1bc7c, 1},
+ {0x1bc80, 0x1bc88, 1},
+ {0x1bc90, 0x1bc99, 1},
{0x1d400, 0x1d454, 1},
{0x1d456, 0x1d49c, 1},
{0x1d49e, 0x1d49f, 1},
@@ -554,6 +605,7 @@ var _L = &RangeTable{
{0x1d78a, 0x1d7a8, 1},
{0x1d7aa, 0x1d7c2, 1},
{0x1d7c4, 0x1d7cb, 1},
+ {0x1e800, 0x1e8c4, 1},
{0x1ee00, 0x1ee03, 1},
{0x1ee05, 0x1ee1f, 1},
{0x1ee21, 0x1ee22, 1},
@@ -637,7 +689,7 @@ var _Ll = &RangeTable{
{0x0461, 0x0481, 2},
{0x048b, 0x04bf, 2},
{0x04c2, 0x04ce, 2},
- {0x04cf, 0x0527, 2},
+ {0x04cf, 0x052f, 2},
{0x0561, 0x0587, 1},
{0x1d00, 0x1d2b, 1},
{0x1d6b, 0x1d77, 1},
@@ -684,7 +736,7 @@ var _Ll = &RangeTable{
{0x2d00, 0x2d25, 1},
{0x2d27, 0x2d2d, 6},
{0xa641, 0xa66d, 2},
- {0xa681, 0xa697, 2},
+ {0xa681, 0xa69b, 2},
{0xa723, 0xa72f, 2},
{0xa730, 0xa731, 1},
{0xa733, 0xa771, 2},
@@ -693,14 +745,18 @@ var _Ll = &RangeTable{
{0xa77f, 0xa787, 2},
{0xa78c, 0xa78e, 2},
{0xa791, 0xa793, 2},
- {0xa7a1, 0xa7a9, 2},
- {0xa7fa, 0xfb00, 21254},
- {0xfb01, 0xfb06, 1},
+ {0xa794, 0xa795, 1},
+ {0xa797, 0xa7a9, 2},
+ {0xa7fa, 0xab30, 822},
+ {0xab31, 0xab5a, 1},
+ {0xab64, 0xab65, 1},
+ {0xfb00, 0xfb06, 1},
{0xfb13, 0xfb17, 1},
{0xff41, 0xff5a, 1},
},
R32: []Range32{
{0x10428, 0x1044f, 1},
+ {0x118c0, 0x118df, 1},
{0x1d41a, 0x1d433, 1},
{0x1d44e, 0x1d454, 1},
{0x1d456, 0x1d467, 1},
@@ -765,15 +821,20 @@ var _Lm = &RangeTable{
{0xa015, 0xa4f8, 1251},
{0xa4f9, 0xa4fd, 1},
{0xa60c, 0xa67f, 115},
+ {0xa69c, 0xa69d, 1},
{0xa717, 0xa71f, 1},
{0xa770, 0xa788, 24},
{0xa7f8, 0xa7f9, 1},
- {0xa9cf, 0xaa70, 161},
- {0xaadd, 0xaaf3, 22},
- {0xaaf4, 0xff70, 21628},
- {0xff9e, 0xff9f, 1},
+ {0xa9cf, 0xa9e6, 23},
+ {0xaa70, 0xaadd, 109},
+ {0xaaf3, 0xaaf4, 1},
+ {0xab5c, 0xab5f, 1},
+ {0xff70, 0xff9e, 46},
+ {0xff9f, 0xff9f, 1},
},
R32: []Range32{
+ {0x16b40, 0x16b40, 1},
+ {0x16b41, 0x16b43, 1},
{0x16f93, 0x16f9f, 1},
},
}
@@ -800,13 +861,11 @@ var _Lo = &RangeTable{
{0x07cb, 0x07ea, 1},
{0x0800, 0x0815, 1},
{0x0840, 0x0858, 1},
- {0x08a0, 0x08a2, 2},
- {0x08a3, 0x08ac, 1},
+ {0x08a0, 0x08b2, 1},
{0x0904, 0x0939, 1},
{0x093d, 0x0950, 19},
{0x0958, 0x0961, 1},
- {0x0972, 0x0977, 1},
- {0x0979, 0x097f, 1},
+ {0x0972, 0x0980, 1},
{0x0985, 0x098c, 1},
{0x098f, 0x0990, 1},
{0x0993, 0x09a8, 1},
@@ -858,8 +917,7 @@ var _Lo = &RangeTable{
{0x0c06, 0x0c0c, 1},
{0x0c0e, 0x0c10, 1},
{0x0c12, 0x0c28, 1},
- {0x0c2a, 0x0c33, 1},
- {0x0c35, 0x0c39, 1},
+ {0x0c2a, 0x0c39, 1},
{0x0c3d, 0x0c58, 27},
{0x0c59, 0x0c60, 7},
{0x0c61, 0x0c85, 36},
@@ -935,6 +993,7 @@ var _Lo = &RangeTable{
{0x166f, 0x167f, 1},
{0x1681, 0x169a, 1},
{0x16a0, 0x16ea, 1},
+ {0x16f1, 0x16f8, 1},
{0x1700, 0x170c, 1},
{0x170e, 0x1711, 1},
{0x1720, 0x1731, 1},
@@ -948,7 +1007,7 @@ var _Lo = &RangeTable{
{0x1880, 0x18a8, 1},
{0x18aa, 0x18b0, 6},
{0x18b1, 0x18f5, 1},
- {0x1900, 0x191c, 1},
+ {0x1900, 0x191e, 1},
{0x1950, 0x196d, 1},
{0x1970, 0x1974, 1},
{0x1980, 0x19ab, 1},
@@ -996,7 +1055,8 @@ var _Lo = &RangeTable{
{0xa62a, 0xa62b, 1},
{0xa66e, 0xa6a0, 50},
{0xa6a1, 0xa6e5, 1},
- {0xa7fb, 0xa801, 1},
+ {0xa7f7, 0xa7fb, 4},
+ {0xa7fc, 0xa801, 1},
{0xa803, 0xa805, 1},
{0xa807, 0xa80a, 1},
{0xa80c, 0xa822, 1},
@@ -1008,13 +1068,16 @@ var _Lo = &RangeTable{
{0xa930, 0xa946, 1},
{0xa960, 0xa97c, 1},
{0xa984, 0xa9b2, 1},
+ {0xa9e0, 0xa9e4, 1},
+ {0xa9e7, 0xa9ef, 1},
+ {0xa9fa, 0xa9fe, 1},
{0xaa00, 0xaa28, 1},
{0xaa40, 0xaa42, 1},
{0xaa44, 0xaa4b, 1},
{0xaa60, 0xaa6f, 1},
{0xaa71, 0xaa76, 1},
- {0xaa7a, 0xaa80, 6},
- {0xaa81, 0xaaaf, 1},
+ {0xaa7a, 0xaa7e, 4},
+ {0xaa7f, 0xaaaf, 1},
{0xaab1, 0xaab5, 4},
{0xaab6, 0xaab9, 3},
{0xaaba, 0xaabd, 1},
@@ -1065,19 +1128,27 @@ var _Lo = &RangeTable{
{0x10080, 0x100fa, 1},
{0x10280, 0x1029c, 1},
{0x102a0, 0x102d0, 1},
- {0x10300, 0x1031e, 1},
+ {0x10300, 0x1031f, 1},
{0x10330, 0x10340, 1},
{0x10342, 0x10349, 1},
+ {0x10350, 0x10375, 1},
{0x10380, 0x1039d, 1},
{0x103a0, 0x103c3, 1},
{0x103c8, 0x103cf, 1},
{0x10450, 0x1049d, 1},
+ {0x10500, 0x10527, 1},
+ {0x10530, 0x10563, 1},
+ {0x10600, 0x10736, 1},
+ {0x10740, 0x10755, 1},
+ {0x10760, 0x10767, 1},
{0x10800, 0x10805, 1},
{0x10808, 0x1080a, 2},
{0x1080b, 0x10835, 1},
{0x10837, 0x10838, 1},
{0x1083c, 0x1083f, 3},
{0x10840, 0x10855, 1},
+ {0x10860, 0x10876, 1},
+ {0x10880, 0x1089e, 1},
{0x10900, 0x10915, 1},
{0x10920, 0x10939, 1},
{0x10980, 0x109b7, 1},
@@ -1087,24 +1158,60 @@ var _Lo = &RangeTable{
{0x10a15, 0x10a17, 1},
{0x10a19, 0x10a33, 1},
{0x10a60, 0x10a7c, 1},
+ {0x10a80, 0x10a9c, 1},
+ {0x10ac0, 0x10ac7, 1},
+ {0x10ac9, 0x10ae4, 1},
{0x10b00, 0x10b35, 1},
{0x10b40, 0x10b55, 1},
{0x10b60, 0x10b72, 1},
+ {0x10b80, 0x10b91, 1},
{0x10c00, 0x10c48, 1},
{0x11003, 0x11037, 1},
{0x11083, 0x110af, 1},
{0x110d0, 0x110e8, 1},
{0x11103, 0x11126, 1},
- {0x11183, 0x111b2, 1},
+ {0x11150, 0x11172, 1},
+ {0x11176, 0x11183, 13},
+ {0x11184, 0x111b2, 1},
{0x111c1, 0x111c4, 1},
- {0x11680, 0x116aa, 1},
- {0x12000, 0x1236e, 1},
+ {0x111da, 0x11200, 38},
+ {0x11201, 0x11211, 1},
+ {0x11213, 0x1122b, 1},
+ {0x112b0, 0x112de, 1},
+ {0x11305, 0x1130c, 1},
+ {0x1130f, 0x11310, 1},
+ {0x11313, 0x11328, 1},
+ {0x1132a, 0x11330, 1},
+ {0x11332, 0x11333, 1},
+ {0x11335, 0x11339, 1},
+ {0x1133d, 0x1135d, 32},
+ {0x1135e, 0x11361, 1},
+ {0x11480, 0x114af, 1},
+ {0x114c4, 0x114c5, 1},
+ {0x114c7, 0x11580, 185},
+ {0x11581, 0x115ae, 1},
+ {0x11600, 0x1162f, 1},
+ {0x11644, 0x11680, 60},
+ {0x11681, 0x116aa, 1},
+ {0x118ff, 0x11ac0, 449},
+ {0x11ac1, 0x11af8, 1},
+ {0x12000, 0x12398, 1},
{0x13000, 0x1342e, 1},
{0x16800, 0x16a38, 1},
+ {0x16a40, 0x16a5e, 1},
+ {0x16ad0, 0x16aed, 1},
+ {0x16b00, 0x16b2f, 1},
+ {0x16b63, 0x16b77, 1},
+ {0x16b7d, 0x16b8f, 1},
{0x16f00, 0x16f44, 1},
{0x16f50, 0x1b000, 16560},
- {0x1b001, 0x1ee00, 15871},
- {0x1ee01, 0x1ee03, 1},
+ {0x1b001, 0x1bc00, 3071},
+ {0x1bc01, 0x1bc6a, 1},
+ {0x1bc70, 0x1bc7c, 1},
+ {0x1bc80, 0x1bc88, 1},
+ {0x1bc90, 0x1bc99, 1},
+ {0x1e800, 0x1e8c4, 1},
+ {0x1ee00, 0x1ee03, 1},
{0x1ee05, 0x1ee1f, 1},
{0x1ee21, 0x1ee22, 1},
{0x1ee24, 0x1ee27, 3},
@@ -1185,8 +1292,9 @@ var _Lu = &RangeTable{
{0x0244, 0x0246, 1},
{0x0248, 0x024e, 2},
{0x0370, 0x0372, 2},
- {0x0376, 0x0386, 16},
- {0x0388, 0x038a, 1},
+ {0x0376, 0x037f, 9},
+ {0x0386, 0x0388, 2},
+ {0x0389, 0x038a, 1},
{0x038c, 0x038e, 2},
{0x038f, 0x0391, 2},
{0x0392, 0x03a1, 1},
@@ -1200,7 +1308,7 @@ var _Lu = &RangeTable{
{0x0460, 0x0480, 2},
{0x048a, 0x04c0, 2},
{0x04c1, 0x04cd, 2},
- {0x04d0, 0x0526, 2},
+ {0x04d0, 0x052e, 2},
{0x0531, 0x0556, 1},
{0x10a0, 0x10c5, 1},
{0x10c7, 0x10cd, 6},
@@ -1239,18 +1347,21 @@ var _Lu = &RangeTable{
{0x2ceb, 0x2ced, 2},
{0x2cf2, 0xa640, 31054},
{0xa642, 0xa66c, 2},
- {0xa680, 0xa696, 2},
+ {0xa680, 0xa69a, 2},
{0xa722, 0xa72e, 2},
{0xa732, 0xa76e, 2},
{0xa779, 0xa77d, 2},
{0xa77e, 0xa786, 2},
{0xa78b, 0xa78d, 2},
{0xa790, 0xa792, 2},
- {0xa7a0, 0xa7aa, 2},
+ {0xa796, 0xa7aa, 2},
+ {0xa7ab, 0xa7ad, 1},
+ {0xa7b0, 0xa7b1, 1},
{0xff21, 0xff3a, 1},
},
R32: []Range32{
{0x10400, 0x10427, 1},
+ {0x118a0, 0x118bf, 1},
{0x1d400, 0x1d419, 1},
{0x1d434, 0x1d44d, 1},
{0x1d468, 0x1d481, 1},
@@ -1309,8 +1420,7 @@ var _M = &RangeTable{
{0x0825, 0x0827, 1},
{0x0829, 0x082d, 1},
{0x0859, 0x085b, 1},
- {0x08e4, 0x08fe, 1},
- {0x0900, 0x0903, 1},
+ {0x08e4, 0x0903, 1},
{0x093a, 0x093c, 1},
{0x093e, 0x094f, 1},
{0x0951, 0x0957, 1},
@@ -1346,21 +1456,21 @@ var _M = &RangeTable{
{0x0bbf, 0x0bc2, 1},
{0x0bc6, 0x0bc8, 1},
{0x0bca, 0x0bcd, 1},
- {0x0bd7, 0x0c01, 42},
- {0x0c02, 0x0c03, 1},
+ {0x0bd7, 0x0c00, 41},
+ {0x0c01, 0x0c03, 1},
{0x0c3e, 0x0c44, 1},
{0x0c46, 0x0c48, 1},
{0x0c4a, 0x0c4d, 1},
{0x0c55, 0x0c56, 1},
{0x0c62, 0x0c63, 1},
- {0x0c82, 0x0c83, 1},
+ {0x0c81, 0x0c83, 1},
{0x0cbc, 0x0cbe, 2},
{0x0cbf, 0x0cc4, 1},
{0x0cc6, 0x0cc8, 1},
{0x0cca, 0x0ccd, 1},
{0x0cd5, 0x0cd6, 1},
{0x0ce2, 0x0ce3, 1},
- {0x0d02, 0x0d03, 1},
+ {0x0d01, 0x0d03, 1},
{0x0d3e, 0x0d44, 1},
{0x0d46, 0x0d48, 1},
{0x0d4a, 0x0d4d, 1},
@@ -1411,8 +1521,9 @@ var _M = &RangeTable{
{0x1a17, 0x1a1b, 1},
{0x1a55, 0x1a5e, 1},
{0x1a60, 0x1a7c, 1},
- {0x1a7f, 0x1b00, 129},
- {0x1b01, 0x1b04, 1},
+ {0x1a7f, 0x1ab0, 49},
+ {0x1ab1, 0x1abe, 1},
+ {0x1b00, 0x1b04, 1},
{0x1b34, 0x1b44, 1},
{0x1b6b, 0x1b73, 1},
{0x1b80, 0x1b82, 1},
@@ -1423,7 +1534,8 @@ var _M = &RangeTable{
{0x1cd4, 0x1ce8, 1},
{0x1ced, 0x1cf2, 5},
{0x1cf3, 0x1cf4, 1},
- {0x1dc0, 0x1de6, 1},
+ {0x1cf8, 0x1cf9, 1},
+ {0x1dc0, 0x1df5, 1},
{0x1dfc, 0x1dff, 1},
{0x20d0, 0x20f0, 1},
{0x2cef, 0x2cf1, 1},
@@ -1444,9 +1556,11 @@ var _M = &RangeTable{
{0xa947, 0xa953, 1},
{0xa980, 0xa983, 1},
{0xa9b3, 0xa9c0, 1},
- {0xaa29, 0xaa36, 1},
+ {0xa9e5, 0xaa29, 68},
+ {0xaa2a, 0xaa36, 1},
{0xaa43, 0xaa4c, 9},
{0xaa4d, 0xaa7b, 46},
+ {0xaa7c, 0xaa7d, 1},
{0xaab0, 0xaab2, 2},
{0xaab3, 0xaab4, 1},
{0xaab7, 0xaab8, 1},
@@ -1458,32 +1572,54 @@ var _M = &RangeTable{
{0xabec, 0xabed, 1},
{0xfb1e, 0xfe00, 738},
{0xfe01, 0xfe0f, 1},
- {0xfe20, 0xfe26, 1},
+ {0xfe20, 0xfe2d, 1},
},
R32: []Range32{
- {0x101fd, 0x10a01, 2052},
- {0x10a02, 0x10a03, 1},
+ {0x101fd, 0x102e0, 227},
+ {0x10376, 0x1037a, 1},
+ {0x10a01, 0x10a03, 1},
{0x10a05, 0x10a06, 1},
{0x10a0c, 0x10a0f, 1},
{0x10a38, 0x10a3a, 1},
- {0x10a3f, 0x11000, 1473},
+ {0x10a3f, 0x10ae5, 166},
+ {0x10ae6, 0x11000, 1306},
{0x11001, 0x11002, 1},
{0x11038, 0x11046, 1},
- {0x11080, 0x11082, 1},
+ {0x1107f, 0x11082, 1},
{0x110b0, 0x110ba, 1},
{0x11100, 0x11102, 1},
{0x11127, 0x11134, 1},
- {0x11180, 0x11182, 1},
+ {0x11173, 0x11180, 13},
+ {0x11181, 0x11182, 1},
{0x111b3, 0x111c0, 1},
+ {0x1122c, 0x11237, 1},
+ {0x112df, 0x112ea, 1},
+ {0x11301, 0x11303, 1},
+ {0x1133c, 0x1133e, 2},
+ {0x1133f, 0x11344, 1},
+ {0x11347, 0x11348, 1},
+ {0x1134b, 0x1134d, 1},
+ {0x11357, 0x11362, 11},
+ {0x11363, 0x11366, 3},
+ {0x11367, 0x1136c, 1},
+ {0x11370, 0x11374, 1},
+ {0x114b0, 0x114c3, 1},
+ {0x115af, 0x115b5, 1},
+ {0x115b8, 0x115c0, 1},
+ {0x11630, 0x11640, 1},
{0x116ab, 0x116b7, 1},
+ {0x16af0, 0x16af4, 1},
+ {0x16b30, 0x16b36, 1},
{0x16f51, 0x16f7e, 1},
{0x16f8f, 0x16f92, 1},
+ {0x1bc9d, 0x1bc9e, 1},
{0x1d165, 0x1d169, 1},
{0x1d16d, 0x1d172, 1},
{0x1d17b, 0x1d182, 1},
{0x1d185, 0x1d18b, 1},
{0x1d1aa, 0x1d1ad, 1},
{0x1d242, 0x1d244, 1},
+ {0x1e8d0, 0x1e8d6, 1},
{0xe0100, 0xe01ef, 1},
},
}
@@ -1562,8 +1698,7 @@ var _Mc = &RangeTable{
{0x1b43, 0x1b44, 1},
{0x1b82, 0x1ba1, 31},
{0x1ba6, 0x1ba7, 1},
- {0x1baa, 0x1bac, 2},
- {0x1bad, 0x1be7, 58},
+ {0x1baa, 0x1be7, 61},
{0x1bea, 0x1bec, 1},
{0x1bee, 0x1bf2, 4},
{0x1bf3, 0x1c24, 49},
@@ -1583,24 +1718,45 @@ var _Mc = &RangeTable{
{0xaa2f, 0xaa30, 1},
{0xaa33, 0xaa34, 1},
{0xaa4d, 0xaa7b, 46},
- {0xaaeb, 0xaaee, 3},
- {0xaaef, 0xaaf5, 6},
- {0xabe3, 0xabe4, 1},
- {0xabe6, 0xabe7, 1},
- {0xabe9, 0xabea, 1},
- {0xabec, 0xabec, 1},
+ {0xaa7d, 0xaaeb, 110},
+ {0xaaee, 0xaaef, 1},
+ {0xaaf5, 0xabe3, 238},
+ {0xabe4, 0xabe6, 2},
+ {0xabe7, 0xabe9, 2},
+ {0xabea, 0xabec, 2},
},
R32: []Range32{
- {0x11000, 0x11000, 1},
- {0x11002, 0x11082, 128},
- {0x110b0, 0x110b2, 1},
+ {0x11000, 0x11002, 2},
+ {0x11082, 0x110b0, 46},
+ {0x110b1, 0x110b2, 1},
{0x110b7, 0x110b8, 1},
{0x1112c, 0x11182, 86},
{0x111b3, 0x111b5, 1},
{0x111bf, 0x111c0, 1},
- {0x116ac, 0x116ae, 2},
- {0x116af, 0x116b6, 7},
- {0x16f51, 0x16f7e, 1},
+ {0x1122c, 0x1122e, 1},
+ {0x11232, 0x11233, 1},
+ {0x11235, 0x112e0, 171},
+ {0x112e1, 0x112e2, 1},
+ {0x11302, 0x11303, 1},
+ {0x1133e, 0x1133f, 1},
+ {0x11341, 0x11344, 1},
+ {0x11347, 0x11348, 1},
+ {0x1134b, 0x1134d, 1},
+ {0x11357, 0x11362, 11},
+ {0x11363, 0x114b0, 333},
+ {0x114b1, 0x114b2, 1},
+ {0x114b9, 0x114bb, 2},
+ {0x114bc, 0x114be, 1},
+ {0x114c1, 0x115af, 238},
+ {0x115b0, 0x115b1, 1},
+ {0x115b8, 0x115bb, 1},
+ {0x115be, 0x11630, 114},
+ {0x11631, 0x11632, 1},
+ {0x1163b, 0x1163c, 1},
+ {0x1163e, 0x116ac, 110},
+ {0x116ae, 0x116af, 1},
+ {0x116b6, 0x16f51, 22683},
+ {0x16f52, 0x16f7e, 1},
{0x1d165, 0x1d166, 1},
{0x1d16d, 0x1d172, 1},
},
@@ -1609,7 +1765,8 @@ var _Mc = &RangeTable{
var _Me = &RangeTable{
R16: []Range16{
{0x0488, 0x0489, 1},
- {0x20dd, 0x20e0, 1},
+ {0x1abe, 0x20dd, 1567},
+ {0x20de, 0x20e0, 1},
{0x20e2, 0x20e4, 1},
{0xa670, 0xa672, 1},
},
@@ -1639,8 +1796,7 @@ var _Mn = &RangeTable{
{0x0825, 0x0827, 1},
{0x0829, 0x082d, 1},
{0x0859, 0x085b, 1},
- {0x08e4, 0x08fe, 1},
- {0x0900, 0x0902, 1},
+ {0x08e4, 0x0902, 1},
{0x093a, 0x093c, 2},
{0x0941, 0x0948, 1},
{0x094d, 0x0951, 4},
@@ -1667,16 +1823,17 @@ var _Mn = &RangeTable{
{0x0b4d, 0x0b56, 9},
{0x0b62, 0x0b63, 1},
{0x0b82, 0x0bc0, 62},
- {0x0bcd, 0x0c3e, 113},
- {0x0c3f, 0x0c40, 1},
+ {0x0bcd, 0x0c00, 51},
+ {0x0c3e, 0x0c40, 1},
{0x0c46, 0x0c48, 1},
{0x0c4a, 0x0c4d, 1},
{0x0c55, 0x0c56, 1},
{0x0c62, 0x0c63, 1},
- {0x0cbc, 0x0cbf, 3},
- {0x0cc6, 0x0ccc, 6},
- {0x0ccd, 0x0ce2, 21},
- {0x0ce3, 0x0d41, 94},
+ {0x0c81, 0x0cbc, 59},
+ {0x0cbf, 0x0cc6, 7},
+ {0x0ccc, 0x0ccd, 1},
+ {0x0ce2, 0x0ce3, 1},
+ {0x0d01, 0x0d41, 64},
{0x0d42, 0x0d44, 1},
{0x0d4d, 0x0d62, 21},
{0x0d63, 0x0dca, 103},
@@ -1728,8 +1885,9 @@ var _Mn = &RangeTable{
{0x1a60, 0x1a62, 2},
{0x1a65, 0x1a6c, 1},
{0x1a73, 0x1a7c, 1},
- {0x1a7f, 0x1b00, 129},
- {0x1b01, 0x1b03, 1},
+ {0x1a7f, 0x1ab0, 49},
+ {0x1ab1, 0x1abd, 1},
+ {0x1b00, 0x1b03, 1},
{0x1b34, 0x1b36, 2},
{0x1b37, 0x1b3a, 1},
{0x1b3c, 0x1b42, 6},
@@ -1737,17 +1895,18 @@ var _Mn = &RangeTable{
{0x1b80, 0x1b81, 1},
{0x1ba2, 0x1ba5, 1},
{0x1ba8, 0x1ba9, 1},
- {0x1bab, 0x1be6, 59},
- {0x1be8, 0x1be9, 1},
- {0x1bed, 0x1bef, 2},
- {0x1bf0, 0x1bf1, 1},
+ {0x1bab, 0x1bad, 1},
+ {0x1be6, 0x1be8, 2},
+ {0x1be9, 0x1bed, 4},
+ {0x1bef, 0x1bf1, 1},
{0x1c2c, 0x1c33, 1},
{0x1c36, 0x1c37, 1},
{0x1cd0, 0x1cd2, 1},
{0x1cd4, 0x1ce0, 1},
{0x1ce2, 0x1ce8, 1},
{0x1ced, 0x1cf4, 7},
- {0x1dc0, 0x1de6, 1},
+ {0x1cf8, 0x1cf9, 1},
+ {0x1dc0, 0x1df5, 1},
{0x1dfc, 0x1dff, 1},
{0x20d0, 0x20dc, 1},
{0x20e1, 0x20e5, 4},
@@ -1770,13 +1929,13 @@ var _Mn = &RangeTable{
{0xa980, 0xa982, 1},
{0xa9b3, 0xa9b6, 3},
{0xa9b7, 0xa9b9, 1},
- {0xa9bc, 0xaa29, 109},
- {0xaa2a, 0xaa2e, 1},
+ {0xa9bc, 0xa9e5, 41},
+ {0xaa29, 0xaa2e, 1},
{0xaa31, 0xaa32, 1},
{0xaa35, 0xaa36, 1},
{0xaa43, 0xaa4c, 9},
- {0xaab0, 0xaab2, 2},
- {0xaab3, 0xaab4, 1},
+ {0xaa7c, 0xaab0, 52},
+ {0xaab2, 0xaab4, 1},
{0xaab7, 0xaab8, 1},
{0xaabe, 0xaabf, 1},
{0xaac1, 0xaaec, 43},
@@ -1784,33 +1943,58 @@ var _Mn = &RangeTable{
{0xabe5, 0xabe8, 3},
{0xabed, 0xfb1e, 20273},
{0xfe00, 0xfe0f, 1},
- {0xfe20, 0xfe26, 1},
+ {0xfe20, 0xfe2d, 1},
},
R32: []Range32{
- {0x101fd, 0x10a01, 2052},
- {0x10a02, 0x10a03, 1},
+ {0x101fd, 0x102e0, 227},
+ {0x10376, 0x1037a, 1},
+ {0x10a01, 0x10a03, 1},
{0x10a05, 0x10a06, 1},
{0x10a0c, 0x10a0f, 1},
{0x10a38, 0x10a3a, 1},
- {0x10a3f, 0x11001, 1474},
+ {0x10a3f, 0x10ae5, 166},
+ {0x10ae6, 0x11001, 1307},
{0x11038, 0x11046, 1},
- {0x11080, 0x11081, 1},
+ {0x1107f, 0x11081, 1},
{0x110b3, 0x110b6, 1},
{0x110b9, 0x110ba, 1},
{0x11100, 0x11102, 1},
{0x11127, 0x1112b, 1},
{0x1112d, 0x11134, 1},
- {0x11180, 0x11181, 1},
- {0x111b6, 0x111be, 1},
- {0x116ab, 0x116ad, 2},
- {0x116b0, 0x116b5, 1},
- {0x116b7, 0x16f8f, 22744},
- {0x16f90, 0x16f92, 1},
+ {0x11173, 0x11180, 13},
+ {0x11181, 0x111b6, 53},
+ {0x111b7, 0x111be, 1},
+ {0x1122f, 0x11231, 1},
+ {0x11234, 0x11236, 2},
+ {0x11237, 0x112df, 168},
+ {0x112e3, 0x112ea, 1},
+ {0x11301, 0x1133c, 59},
+ {0x11340, 0x11366, 38},
+ {0x11367, 0x1136c, 1},
+ {0x11370, 0x11374, 1},
+ {0x114b3, 0x114b8, 1},
+ {0x114ba, 0x114bf, 5},
+ {0x114c0, 0x114c2, 2},
+ {0x114c3, 0x115b2, 239},
+ {0x115b3, 0x115b5, 1},
+ {0x115bc, 0x115bd, 1},
+ {0x115bf, 0x115c0, 1},
+ {0x11633, 0x1163a, 1},
+ {0x1163d, 0x1163f, 2},
+ {0x11640, 0x116ab, 107},
+ {0x116ad, 0x116b0, 3},
+ {0x116b1, 0x116b5, 1},
+ {0x116b7, 0x16af0, 21561},
+ {0x16af1, 0x16af4, 1},
+ {0x16b30, 0x16b36, 1},
+ {0x16f8f, 0x16f92, 1},
+ {0x1bc9d, 0x1bc9e, 1},
{0x1d167, 0x1d169, 1},
{0x1d17b, 0x1d182, 1},
{0x1d185, 0x1d18b, 1},
{0x1d1aa, 0x1d1ad, 1},
{0x1d242, 0x1d244, 1},
+ {0x1e8d0, 0x1e8d6, 1},
{0xe0100, 0xe01ef, 1},
},
}
@@ -1836,6 +2020,7 @@ var _N = &RangeTable{
{0x0c78, 0x0c7e, 1},
{0x0ce6, 0x0cef, 1},
{0x0d66, 0x0d75, 1},
+ {0x0de6, 0x0def, 1},
{0x0e50, 0x0e59, 1},
{0x0ed0, 0x0ed9, 1},
{0x0f20, 0x0f33, 1},
@@ -1877,6 +2062,7 @@ var _N = &RangeTable{
{0xa8d0, 0xa8d9, 1},
{0xa900, 0xa909, 1},
{0xa9d0, 0xa9d9, 1},
+ {0xa9f0, 0xa9f9, 1},
{0xaa50, 0xaa59, 1},
{0xabf0, 0xabf9, 1},
{0xff10, 0xff19, 1},
@@ -1884,27 +2070,42 @@ var _N = &RangeTable{
R32: []Range32{
{0x10107, 0x10133, 1},
{0x10140, 0x10178, 1},
- {0x1018a, 0x10320, 406},
- {0x10321, 0x10323, 1},
+ {0x1018a, 0x1018b, 1},
+ {0x102e1, 0x102fb, 1},
+ {0x10320, 0x10323, 1},
{0x10341, 0x1034a, 9},
{0x103d1, 0x103d5, 1},
{0x104a0, 0x104a9, 1},
{0x10858, 0x1085f, 1},
+ {0x10879, 0x1087f, 1},
+ {0x108a7, 0x108af, 1},
{0x10916, 0x1091b, 1},
{0x10a40, 0x10a47, 1},
{0x10a7d, 0x10a7e, 1},
+ {0x10a9d, 0x10a9f, 1},
+ {0x10aeb, 0x10aef, 1},
{0x10b58, 0x10b5f, 1},
{0x10b78, 0x10b7f, 1},
+ {0x10ba9, 0x10baf, 1},
{0x10e60, 0x10e7e, 1},
{0x11052, 0x1106f, 1},
{0x110f0, 0x110f9, 1},
{0x11136, 0x1113f, 1},
{0x111d0, 0x111d9, 1},
+ {0x111e1, 0x111f4, 1},
+ {0x112f0, 0x112f9, 1},
+ {0x114d0, 0x114d9, 1},
+ {0x11650, 0x11659, 1},
{0x116c0, 0x116c9, 1},
- {0x12400, 0x12462, 1},
+ {0x118e0, 0x118f2, 1},
+ {0x12400, 0x1246e, 1},
+ {0x16a60, 0x16a69, 1},
+ {0x16b50, 0x16b59, 1},
+ {0x16b5b, 0x16b61, 1},
{0x1d360, 0x1d371, 1},
{0x1d7ce, 0x1d7ff, 1},
- {0x1f100, 0x1f10a, 1},
+ {0x1e8c7, 0x1e8cf, 1},
+ {0x1f100, 0x1f10c, 1},
},
LatinOffset: 4,
}
@@ -1924,6 +2125,7 @@ var _Nd = &RangeTable{
{0x0c66, 0x0c6f, 1},
{0x0ce6, 0x0cef, 1},
{0x0d66, 0x0d6f, 1},
+ {0x0de6, 0x0def, 1},
{0x0e50, 0x0e59, 1},
{0x0ed0, 0x0ed9, 1},
{0x0f20, 0x0f29, 1},
@@ -1943,6 +2145,7 @@ var _Nd = &RangeTable{
{0xa8d0, 0xa8d9, 1},
{0xa900, 0xa909, 1},
{0xa9d0, 0xa9d9, 1},
+ {0xa9f0, 0xa9f9, 1},
{0xaa50, 0xaa59, 1},
{0xabf0, 0xabf9, 1},
{0xff10, 0xff19, 1},
@@ -1953,7 +2156,13 @@ var _Nd = &RangeTable{
{0x110f0, 0x110f9, 1},
{0x11136, 0x1113f, 1},
{0x111d0, 0x111d9, 1},
+ {0x112f0, 0x112f9, 1},
+ {0x114d0, 0x114d9, 1},
+ {0x11650, 0x11659, 1},
{0x116c0, 0x116c9, 1},
+ {0x118e0, 0x118e9, 1},
+ {0x16a60, 0x16a69, 1},
+ {0x16b50, 0x16b59, 1},
{0x1d7ce, 0x1d7ff, 1},
},
LatinOffset: 1,
@@ -1973,7 +2182,7 @@ var _Nl = &RangeTable{
{0x10140, 0x10174, 1},
{0x10341, 0x1034a, 9},
{0x103d1, 0x103d5, 1},
- {0x12400, 0x12462, 1},
+ {0x12400, 0x1246e, 1},
},
}
@@ -2010,18 +2219,28 @@ var _No = &RangeTable{
R32: []Range32{
{0x10107, 0x10133, 1},
{0x10175, 0x10178, 1},
- {0x1018a, 0x10320, 406},
- {0x10321, 0x10323, 1},
+ {0x1018a, 0x1018b, 1},
+ {0x102e1, 0x102fb, 1},
+ {0x10320, 0x10323, 1},
{0x10858, 0x1085f, 1},
+ {0x10879, 0x1087f, 1},
+ {0x108a7, 0x108af, 1},
{0x10916, 0x1091b, 1},
{0x10a40, 0x10a47, 1},
{0x10a7d, 0x10a7e, 1},
+ {0x10a9d, 0x10a9f, 1},
+ {0x10aeb, 0x10aef, 1},
{0x10b58, 0x10b5f, 1},
{0x10b78, 0x10b7f, 1},
+ {0x10ba9, 0x10baf, 1},
{0x10e60, 0x10e7e, 1},
{0x11052, 0x11065, 1},
+ {0x111e1, 0x111f4, 1},
+ {0x118ea, 0x118f2, 1},
+ {0x16b5b, 0x16b61, 1},
{0x1d360, 0x1d371, 1},
- {0x1f100, 0x1f10a, 1},
+ {0x1e8c7, 0x1e8cf, 1},
+ {0x1f100, 0x1f10c, 1},
},
LatinOffset: 3,
}
@@ -2104,7 +2323,7 @@ var _P = &RangeTable{
{0x2cfe, 0x2cff, 1},
{0x2d70, 0x2e00, 144},
{0x2e01, 0x2e2e, 1},
- {0x2e30, 0x2e3b, 1},
+ {0x2e30, 0x2e42, 1},
{0x3001, 0x3003, 1},
{0x3008, 0x3011, 1},
{0x3014, 0x301f, 1},
@@ -2144,17 +2363,29 @@ var _P = &RangeTable{
R32: []Range32{
{0x10100, 0x10102, 1},
{0x1039f, 0x103d0, 49},
- {0x10857, 0x1091f, 200},
- {0x1093f, 0x10a50, 273},
- {0x10a51, 0x10a58, 1},
- {0x10a7f, 0x10b39, 186},
- {0x10b3a, 0x10b3f, 1},
+ {0x1056f, 0x10857, 744},
+ {0x1091f, 0x1093f, 32},
+ {0x10a50, 0x10a58, 1},
+ {0x10a7f, 0x10af0, 113},
+ {0x10af1, 0x10af6, 1},
+ {0x10b39, 0x10b3f, 1},
+ {0x10b99, 0x10b9c, 1},
{0x11047, 0x1104d, 1},
{0x110bb, 0x110bc, 1},
{0x110be, 0x110c1, 1},
{0x11140, 0x11143, 1},
+ {0x11174, 0x11175, 1},
{0x111c5, 0x111c8, 1},
- {0x12470, 0x12473, 1},
+ {0x111cd, 0x11238, 107},
+ {0x11239, 0x1123d, 1},
+ {0x114c6, 0x115c1, 251},
+ {0x115c2, 0x115c9, 1},
+ {0x11641, 0x11643, 1},
+ {0x12470, 0x12474, 1},
+ {0x16a6e, 0x16a6f, 1},
+ {0x16af5, 0x16b37, 66},
+ {0x16b38, 0x16b3b, 1},
+ {0x16b44, 0x1bc9f, 20827},
},
LatinOffset: 11,
}
@@ -2177,10 +2408,11 @@ var _Pd = &RangeTable{
{0x2011, 0x2015, 1},
{0x2e17, 0x2e1a, 3},
{0x2e3a, 0x2e3b, 1},
- {0x301c, 0x3030, 20},
- {0x30a0, 0xfe31, 52625},
- {0xfe32, 0xfe58, 38},
- {0xfe63, 0xff0d, 170},
+ {0x2e40, 0x301c, 476},
+ {0x3030, 0x30a0, 112},
+ {0xfe31, 0xfe32, 1},
+ {0xfe58, 0xfe63, 11},
+ {0xff0d, 0xff0d, 1},
},
}
@@ -2202,7 +2434,7 @@ var _Pe = &RangeTable{
{0x3009, 0x3011, 2},
{0x3015, 0x301b, 2},
{0x301e, 0x301f, 1},
- {0xfd3f, 0xfe18, 217},
+ {0xfd3e, 0xfe18, 218},
{0xfe36, 0xfe44, 2},
{0xfe48, 0xfe5a, 18},
{0xfe5c, 0xfe5e, 2},
@@ -2307,7 +2539,9 @@ var _Po = &RangeTable{
{0x2e1f, 0x2e2a, 11},
{0x2e2b, 0x2e2e, 1},
{0x2e30, 0x2e39, 1},
- {0x3001, 0x3003, 1},
+ {0x2e3c, 0x2e3f, 1},
+ {0x2e41, 0x3001, 448},
+ {0x3002, 0x3003, 1},
{0x303d, 0x30fb, 190},
{0xa4fe, 0xa4ff, 1},
{0xa60d, 0xa60f, 1},
@@ -2346,17 +2580,29 @@ var _Po = &RangeTable{
{0x10100, 0x10100, 1},
{0x10101, 0x10102, 1},
{0x1039f, 0x103d0, 49},
- {0x10857, 0x1091f, 200},
- {0x1093f, 0x10a50, 273},
- {0x10a51, 0x10a58, 1},
- {0x10a7f, 0x10b39, 186},
- {0x10b3a, 0x10b3f, 1},
+ {0x1056f, 0x10857, 744},
+ {0x1091f, 0x1093f, 32},
+ {0x10a50, 0x10a58, 1},
+ {0x10a7f, 0x10af0, 113},
+ {0x10af1, 0x10af6, 1},
+ {0x10b39, 0x10b3f, 1},
+ {0x10b99, 0x10b9c, 1},
{0x11047, 0x1104d, 1},
{0x110bb, 0x110bc, 1},
{0x110be, 0x110c1, 1},
{0x11140, 0x11143, 1},
+ {0x11174, 0x11175, 1},
{0x111c5, 0x111c8, 1},
- {0x12470, 0x12473, 1},
+ {0x111cd, 0x11238, 107},
+ {0x11239, 0x1123d, 1},
+ {0x114c6, 0x115c1, 251},
+ {0x115c2, 0x115c9, 1},
+ {0x11641, 0x11643, 1},
+ {0x12470, 0x12474, 1},
+ {0x16a6e, 0x16a6f, 1},
+ {0x16af5, 0x16b37, 66},
+ {0x16b38, 0x16b3b, 1},
+ {0x16b44, 0x1bc9f, 20827},
},
LatinOffset: 8,
}
@@ -2377,9 +2623,10 @@ var _Ps = &RangeTable{
{0x29d8, 0x29da, 2},
{0x29fc, 0x2e22, 1062},
{0x2e24, 0x2e28, 2},
- {0x3008, 0x3010, 2},
+ {0x2e42, 0x3008, 454},
+ {0x300a, 0x3010, 2},
{0x3014, 0x301a, 2},
- {0x301d, 0xfd3e, 52513},
+ {0x301d, 0xfd3f, 52514},
{0xfe17, 0xfe35, 30},
{0xfe37, 0xfe43, 2},
{0xfe47, 0xfe59, 18},
@@ -2410,7 +2657,8 @@ var _S = &RangeTable{
{0x02f0, 0x02ff, 1},
{0x0375, 0x0384, 15},
{0x0385, 0x03f6, 113},
- {0x0482, 0x058f, 269},
+ {0x0482, 0x058d, 267},
+ {0x058e, 0x058f, 1},
{0x0606, 0x0608, 1},
{0x060b, 0x060e, 3},
{0x060f, 0x06de, 207},
@@ -2446,7 +2694,7 @@ var _S = &RangeTable{
{0x2044, 0x2052, 14},
{0x207a, 0x207c, 1},
{0x208a, 0x208c, 1},
- {0x20a0, 0x20ba, 1},
+ {0x20a0, 0x20bd, 1},
{0x2100, 0x2101, 1},
{0x2103, 0x2106, 1},
{0x2108, 0x2109, 1},
@@ -2461,19 +2709,21 @@ var _S = &RangeTable{
{0x214f, 0x2190, 65},
{0x2191, 0x2307, 1},
{0x230c, 0x2328, 1},
- {0x232b, 0x23f3, 1},
+ {0x232b, 0x23fa, 1},
{0x2400, 0x2426, 1},
{0x2440, 0x244a, 1},
{0x249c, 0x24e9, 1},
- {0x2500, 0x26ff, 1},
- {0x2701, 0x2767, 1},
+ {0x2500, 0x2767, 1},
{0x2794, 0x27c4, 1},
{0x27c7, 0x27e5, 1},
{0x27f0, 0x2982, 1},
{0x2999, 0x29d7, 1},
{0x29dc, 0x29fb, 1},
- {0x29fe, 0x2b4c, 1},
- {0x2b50, 0x2b59, 1},
+ {0x29fe, 0x2b73, 1},
+ {0x2b76, 0x2b95, 1},
+ {0x2b98, 0x2bb9, 1},
+ {0x2bbd, 0x2bc8, 1},
+ {0x2bca, 0x2bd1, 1},
{0x2ce5, 0x2cea, 1},
{0x2e80, 0x2e99, 1},
{0x2e9b, 0x2ef3, 1},
@@ -2502,8 +2752,8 @@ var _S = &RangeTable{
{0xa828, 0xa82b, 1},
{0xa836, 0xa839, 1},
{0xaa77, 0xaa79, 1},
- {0xfb29, 0xfbb2, 137},
- {0xfbb3, 0xfbc1, 1},
+ {0xab5b, 0xfb29, 20430},
+ {0xfbb2, 0xfbc1, 1},
{0xfdfc, 0xfdfd, 1},
{0xfe62, 0xfe64, 2},
{0xfe65, 0xfe66, 1},
@@ -2519,8 +2769,14 @@ var _S = &RangeTable{
R32: []Range32{
{0x10137, 0x1013f, 1},
{0x10179, 0x10189, 1},
- {0x10190, 0x1019b, 1},
- {0x101d0, 0x101fc, 1},
+ {0x1018c, 0x10190, 4},
+ {0x10191, 0x1019b, 1},
+ {0x101a0, 0x101d0, 48},
+ {0x101d1, 0x101fc, 1},
+ {0x10877, 0x10878, 1},
+ {0x10ac8, 0x16b3c, 24692},
+ {0x16b3d, 0x16b3f, 1},
+ {0x16b45, 0x1bc9c, 20823},
{0x1d000, 0x1d0f5, 1},
{0x1d100, 0x1d126, 1},
{0x1d129, 0x1d164, 1},
@@ -2540,9 +2796,9 @@ var _S = &RangeTable{
{0x1f000, 0x1f02b, 1},
{0x1f030, 0x1f093, 1},
{0x1f0a0, 0x1f0ae, 1},
- {0x1f0b1, 0x1f0be, 1},
+ {0x1f0b1, 0x1f0bf, 1},
{0x1f0c1, 0x1f0cf, 1},
- {0x1f0d1, 0x1f0df, 1},
+ {0x1f0d1, 0x1f0f5, 1},
{0x1f110, 0x1f12e, 1},
{0x1f130, 0x1f16b, 1},
{0x1f170, 0x1f19a, 1},
@@ -2550,24 +2806,25 @@ var _S = &RangeTable{
{0x1f210, 0x1f23a, 1},
{0x1f240, 0x1f248, 1},
{0x1f250, 0x1f251, 1},
- {0x1f300, 0x1f320, 1},
- {0x1f330, 0x1f335, 1},
- {0x1f337, 0x1f37c, 1},
- {0x1f380, 0x1f393, 1},
- {0x1f3a0, 0x1f3c4, 1},
- {0x1f3c6, 0x1f3ca, 1},
- {0x1f3e0, 0x1f3f0, 1},
- {0x1f400, 0x1f43e, 1},
- {0x1f440, 0x1f442, 2},
- {0x1f443, 0x1f4f7, 1},
- {0x1f4f9, 0x1f4fc, 1},
- {0x1f500, 0x1f53d, 1},
- {0x1f540, 0x1f543, 1},
- {0x1f550, 0x1f567, 1},
- {0x1f5fb, 0x1f640, 1},
- {0x1f645, 0x1f64f, 1},
- {0x1f680, 0x1f6c5, 1},
+ {0x1f300, 0x1f32c, 1},
+ {0x1f330, 0x1f37d, 1},
+ {0x1f380, 0x1f3ce, 1},
+ {0x1f3d4, 0x1f3f7, 1},
+ {0x1f400, 0x1f4fe, 1},
+ {0x1f500, 0x1f54a, 1},
+ {0x1f550, 0x1f579, 1},
+ {0x1f57b, 0x1f5a3, 1},
+ {0x1f5a5, 0x1f642, 1},
+ {0x1f645, 0x1f6cf, 1},
+ {0x1f6e0, 0x1f6ec, 1},
+ {0x1f6f0, 0x1f6f3, 1},
{0x1f700, 0x1f773, 1},
+ {0x1f780, 0x1f7d4, 1},
+ {0x1f800, 0x1f80b, 1},
+ {0x1f810, 0x1f847, 1},
+ {0x1f850, 0x1f859, 1},
+ {0x1f860, 0x1f887, 1},
+ {0x1f890, 0x1f8ad, 1},
},
LatinOffset: 10,
}
@@ -2581,7 +2838,7 @@ var _Sc = &RangeTable{
{0x09fb, 0x0af1, 246},
{0x0bf9, 0x0e3f, 582},
{0x17db, 0x20a0, 2245},
- {0x20a1, 0x20ba, 1},
+ {0x20a1, 0x20bd, 1},
{0xa838, 0xfdfc, 21956},
{0xfe69, 0xff04, 155},
{0xffe0, 0xffe1, 1},
@@ -2611,7 +2868,8 @@ var _Sk = &RangeTable{
{0xa700, 0xa716, 1},
{0xa720, 0xa721, 1},
{0xa789, 0xa78a, 1},
- {0xfbb2, 0xfbc1, 1},
+ {0xab5b, 0xfbb2, 20567},
+ {0xfbb3, 0xfbc1, 1},
{0xff3e, 0xff40, 2},
{0xffe3, 0xffe3, 1},
},
@@ -2679,7 +2937,8 @@ var _So = &RangeTable{
R16: []Range16{
{0x00a6, 0x00a9, 3},
{0x00ae, 0x00b0, 2},
- {0x0482, 0x060e, 396},
+ {0x0482, 0x058d, 267},
+ {0x058e, 0x060e, 128},
{0x060f, 0x06de, 207},
{0x06e9, 0x06fd, 20},
{0x06fe, 0x07f6, 248},
@@ -2728,7 +2987,7 @@ var _So = &RangeTable{
{0x232b, 0x237b, 1},
{0x237d, 0x239a, 1},
{0x23b4, 0x23db, 1},
- {0x23e2, 0x23f3, 1},
+ {0x23e2, 0x23fa, 1},
{0x2400, 0x2426, 1},
{0x2440, 0x244a, 1},
{0x249c, 0x24e9, 1},
@@ -2736,13 +2995,16 @@ var _So = &RangeTable{
{0x25b8, 0x25c0, 1},
{0x25c2, 0x25f7, 1},
{0x2600, 0x266e, 1},
- {0x2670, 0x26ff, 1},
- {0x2701, 0x2767, 1},
+ {0x2670, 0x2767, 1},
{0x2794, 0x27bf, 1},
{0x2800, 0x28ff, 1},
{0x2b00, 0x2b2f, 1},
{0x2b45, 0x2b46, 1},
- {0x2b50, 0x2b59, 1},
+ {0x2b4d, 0x2b73, 1},
+ {0x2b76, 0x2b95, 1},
+ {0x2b98, 0x2bb9, 1},
+ {0x2bbd, 0x2bc8, 1},
+ {0x2bca, 0x2bd1, 1},
{0x2ce5, 0x2cea, 1},
{0x2e80, 0x2e99, 1},
{0x2e9b, 0x2ef3, 1},
@@ -2777,8 +3039,14 @@ var _So = &RangeTable{
{0x10137, 0x10137, 1},
{0x10138, 0x1013f, 1},
{0x10179, 0x10189, 1},
- {0x10190, 0x1019b, 1},
- {0x101d0, 0x101fc, 1},
+ {0x1018c, 0x10190, 4},
+ {0x10191, 0x1019b, 1},
+ {0x101a0, 0x101d0, 48},
+ {0x101d1, 0x101fc, 1},
+ {0x10877, 0x10878, 1},
+ {0x10ac8, 0x16b3c, 24692},
+ {0x16b3d, 0x16b3f, 1},
+ {0x16b45, 0x1bc9c, 20823},
{0x1d000, 0x1d0f5, 1},
{0x1d100, 0x1d126, 1},
{0x1d129, 0x1d164, 1},
@@ -2792,9 +3060,9 @@ var _So = &RangeTable{
{0x1f000, 0x1f02b, 1},
{0x1f030, 0x1f093, 1},
{0x1f0a0, 0x1f0ae, 1},
- {0x1f0b1, 0x1f0be, 1},
+ {0x1f0b1, 0x1f0bf, 1},
{0x1f0c1, 0x1f0cf, 1},
- {0x1f0d1, 0x1f0df, 1},
+ {0x1f0d1, 0x1f0f5, 1},
{0x1f110, 0x1f12e, 1},
{0x1f130, 0x1f16b, 1},
{0x1f170, 0x1f19a, 1},
@@ -2802,24 +3070,25 @@ var _So = &RangeTable{
{0x1f210, 0x1f23a, 1},
{0x1f240, 0x1f248, 1},
{0x1f250, 0x1f251, 1},
- {0x1f300, 0x1f320, 1},
- {0x1f330, 0x1f335, 1},
- {0x1f337, 0x1f37c, 1},
- {0x1f380, 0x1f393, 1},
- {0x1f3a0, 0x1f3c4, 1},
- {0x1f3c6, 0x1f3ca, 1},
- {0x1f3e0, 0x1f3f0, 1},
- {0x1f400, 0x1f43e, 1},
- {0x1f440, 0x1f442, 2},
- {0x1f443, 0x1f4f7, 1},
- {0x1f4f9, 0x1f4fc, 1},
- {0x1f500, 0x1f53d, 1},
- {0x1f540, 0x1f543, 1},
- {0x1f550, 0x1f567, 1},
- {0x1f5fb, 0x1f640, 1},
- {0x1f645, 0x1f64f, 1},
- {0x1f680, 0x1f6c5, 1},
+ {0x1f300, 0x1f32c, 1},
+ {0x1f330, 0x1f37d, 1},
+ {0x1f380, 0x1f3ce, 1},
+ {0x1f3d4, 0x1f3f7, 1},
+ {0x1f400, 0x1f4fe, 1},
+ {0x1f500, 0x1f54a, 1},
+ {0x1f550, 0x1f579, 1},
+ {0x1f57b, 0x1f5a3, 1},
+ {0x1f5a5, 0x1f642, 1},
+ {0x1f645, 0x1f6cf, 1},
+ {0x1f6e0, 0x1f6ec, 1},
+ {0x1f6f0, 0x1f6f3, 1},
{0x1f700, 0x1f773, 1},
+ {0x1f780, 0x1f7d4, 1},
+ {0x1f800, 0x1f80b, 1},
+ {0x1f810, 0x1f847, 1},
+ {0x1f850, 0x1f859, 1},
+ {0x1f860, 0x1f887, 1},
+ {0x1f890, 0x1f8ad, 1},
},
LatinOffset: 2,
}
@@ -2911,7 +3180,7 @@ var (
)
// Generated by running
-// maketables --scripts=all --url=http://www.unicode.org/Public/6.3.0/ucd/
+// maketables --scripts=all --url=http://www.unicode.org/Public/7.0.0/ucd/
// DO NOT EDIT
// Scripts is the set of Unicode script tables.
@@ -2921,6 +3190,7 @@ var Scripts = map[string]*RangeTable{
"Avestan": Avestan,
"Balinese": Balinese,
"Bamum": Bamum,
+ "Bassa_Vah": Bassa_Vah,
"Batak": Batak,
"Bengali": Bengali,
"Bopomofo": Bopomofo,
@@ -2930,6 +3200,7 @@ var Scripts = map[string]*RangeTable{
"Buhid": Buhid,
"Canadian_Aboriginal": Canadian_Aboriginal,
"Carian": Carian,
+ "Caucasian_Albanian": Caucasian_Albanian,
"Chakma": Chakma,
"Cham": Cham,
"Cherokee": Cherokee,
@@ -2940,11 +3211,14 @@ var Scripts = map[string]*RangeTable{
"Cyrillic": Cyrillic,
"Deseret": Deseret,
"Devanagari": Devanagari,
+ "Duployan": Duployan,
"Egyptian_Hieroglyphs": Egyptian_Hieroglyphs,
+ "Elbasan": Elbasan,
"Ethiopic": Ethiopic,
"Georgian": Georgian,
"Glagolitic": Glagolitic,
"Gothic": Gothic,
+ "Grantha": Grantha,
"Greek": Greek,
"Gujarati": Gujarati,
"Gurmukhi": Gurmukhi,
@@ -2964,40 +3238,56 @@ var Scripts = map[string]*RangeTable{
"Kayah_Li": Kayah_Li,
"Kharoshthi": Kharoshthi,
"Khmer": Khmer,
+ "Khojki": Khojki,
+ "Khudawadi": Khudawadi,
"Lao": Lao,
"Latin": Latin,
"Lepcha": Lepcha,
"Limbu": Limbu,
+ "Linear_A": Linear_A,
"Linear_B": Linear_B,
"Lisu": Lisu,
"Lycian": Lycian,
"Lydian": Lydian,
+ "Mahajani": Mahajani,
"Malayalam": Malayalam,
"Mandaic": Mandaic,
+ "Manichaean": Manichaean,
"Meetei_Mayek": Meetei_Mayek,
+ "Mende_Kikakui": Mende_Kikakui,
"Meroitic_Cursive": Meroitic_Cursive,
"Meroitic_Hieroglyphs": Meroitic_Hieroglyphs,
"Miao": Miao,
+ "Modi": Modi,
"Mongolian": Mongolian,
+ "Mro": Mro,
"Myanmar": Myanmar,
+ "Nabataean": Nabataean,
"New_Tai_Lue": New_Tai_Lue,
"Nko": Nko,
"Ogham": Ogham,
"Ol_Chiki": Ol_Chiki,
"Old_Italic": Old_Italic,
+ "Old_North_Arabian": Old_North_Arabian,
+ "Old_Permic": Old_Permic,
"Old_Persian": Old_Persian,
"Old_South_Arabian": Old_South_Arabian,
"Old_Turkic": Old_Turkic,
"Oriya": Oriya,
"Osmanya": Osmanya,
+ "Pahawh_Hmong": Pahawh_Hmong,
+ "Palmyrene": Palmyrene,
+ "Pau_Cin_Hau": Pau_Cin_Hau,
"Phags_Pa": Phags_Pa,
"Phoenician": Phoenician,
+ "Psalter_Pahlavi": Psalter_Pahlavi,
"Rejang": Rejang,
"Runic": Runic,
"Samaritan": Samaritan,
"Saurashtra": Saurashtra,
"Sharada": Sharada,
"Shavian": Shavian,
+ "Siddham": Siddham,
"Sinhala": Sinhala,
"Sora_Sompeng": Sora_Sompeng,
"Sundanese": Sundanese,
@@ -3015,8 +3305,10 @@ var Scripts = map[string]*RangeTable{
"Thai": Thai,
"Tibetan": Tibetan,
"Tifinagh": Tifinagh,
+ "Tirhuta": Tirhuta,
"Ugaritic": Ugaritic,
"Vai": Vai,
+ "Warang_Citi": Warang_Citi,
"Yi": Yi,
}
@@ -3025,7 +3317,6 @@ var _Arabic = &RangeTable{
{0x0600, 0x0604, 1},
{0x0606, 0x060b, 1},
{0x060d, 0x061a, 1},
- {0x061c, 0x061c, 1},
{0x061e, 0x061e, 1},
{0x0620, 0x063f, 1},
{0x0641, 0x064a, 1},
@@ -3034,14 +3325,13 @@ var _Arabic = &RangeTable{
{0x0671, 0x06dc, 1},
{0x06de, 0x06ff, 1},
{0x0750, 0x077f, 1},
- {0x08a0, 0x08a0, 1},
- {0x08a2, 0x08ac, 1},
- {0x08e4, 0x08fe, 1},
+ {0x08a0, 0x08b2, 1},
+ {0x08e4, 0x08ff, 1},
{0xfb50, 0xfbc1, 1},
{0xfbd3, 0xfd3d, 1},
{0xfd50, 0xfd8f, 1},
{0xfd92, 0xfdc7, 1},
- {0xfdf0, 0xfdfc, 1},
+ {0xfdf0, 0xfdfd, 1},
{0xfe70, 0xfe74, 1},
{0xfe76, 0xfefc, 1},
},
@@ -3090,7 +3380,7 @@ var _Armenian = &RangeTable{
{0x0559, 0x055f, 1},
{0x0561, 0x0587, 1},
{0x058a, 0x058a, 1},
- {0x058f, 0x058f, 1},
+ {0x058d, 0x058f, 1},
{0xfb13, 0xfb17, 1},
},
}
@@ -3119,6 +3409,14 @@ var _Bamum = &RangeTable{
},
}
+var _Bassa_Vah = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x16ad0, 0x16aed, 1},
+ {0x16af0, 0x16af5, 1},
+ },
+}
+
var _Batak = &RangeTable{
R16: []Range16{
{0x1bc0, 0x1bf3, 1},
@@ -3128,7 +3426,7 @@ var _Batak = &RangeTable{
var _Bengali = &RangeTable{
R16: []Range16{
- {0x0981, 0x0983, 1},
+ {0x0980, 0x0983, 1},
{0x0985, 0x098c, 1},
{0x098f, 0x0990, 1},
{0x0993, 0x09a8, 1},
@@ -3158,6 +3456,7 @@ var _Brahmi = &RangeTable{
R32: []Range32{
{0x11000, 0x1104d, 1},
{0x11052, 0x1106f, 1},
+ {0x1107f, 0x1107f, 1},
},
}
@@ -3194,6 +3493,14 @@ var _Carian = &RangeTable{
},
}
+var _Caucasian_Albanian = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x10530, 0x10563, 1},
+ {0x1056f, 0x1056f, 1},
+ },
+}
+
var _Chakma = &RangeTable{
R16: []Range16{},
R32: []Range32{
@@ -3234,8 +3541,9 @@ var _Common = &RangeTable{
{0x0385, 0x0385, 1},
{0x0387, 0x0387, 1},
{0x0589, 0x0589, 1},
+ {0x0605, 0x0605, 1},
{0x060c, 0x060c, 1},
- {0x061b, 0x061b, 1},
+ {0x061b, 0x061c, 1},
{0x061f, 0x061f, 1},
{0x0640, 0x0640, 1},
{0x0660, 0x0669, 1},
@@ -3258,21 +3566,23 @@ var _Common = &RangeTable{
{0x2066, 0x2070, 1},
{0x2074, 0x207e, 1},
{0x2080, 0x208e, 1},
- {0x20a0, 0x20ba, 1},
+ {0x20a0, 0x20bd, 1},
{0x2100, 0x2125, 1},
{0x2127, 0x2129, 1},
{0x212c, 0x2131, 1},
{0x2133, 0x214d, 1},
{0x214f, 0x215f, 1},
{0x2189, 0x2189, 1},
- {0x2190, 0x23f3, 1},
+ {0x2190, 0x23fa, 1},
{0x2400, 0x2426, 1},
{0x2440, 0x244a, 1},
- {0x2460, 0x26ff, 1},
- {0x2701, 0x27ff, 1},
- {0x2900, 0x2b4c, 1},
- {0x2b50, 0x2b59, 1},
- {0x2e00, 0x2e3b, 1},
+ {0x2460, 0x27ff, 1},
+ {0x2900, 0x2b73, 1},
+ {0x2b76, 0x2b95, 1},
+ {0x2b98, 0x2bb9, 1},
+ {0x2bbd, 0x2bc8, 1},
+ {0x2bca, 0x2bd1, 1},
+ {0x2e00, 0x2e42, 1},
{0x2ff0, 0x2ffb, 1},
{0x3000, 0x3004, 1},
{0x3006, 0x3006, 1},
@@ -3291,9 +3601,10 @@ var _Common = &RangeTable{
{0xa700, 0xa721, 1},
{0xa788, 0xa78a, 1},
{0xa830, 0xa839, 1},
+ {0xa92e, 0xa92e, 1},
{0xa9cf, 0xa9cf, 1},
+ {0xab5b, 0xab5b, 1},
{0xfd3e, 0xfd3f, 1},
- {0xfdfd, 0xfdfd, 1},
{0xfe10, 0xfe19, 1},
{0xfe30, 0xfe52, 1},
{0xfe54, 0xfe66, 1},
@@ -3314,6 +3625,8 @@ var _Common = &RangeTable{
{0x10137, 0x1013f, 1},
{0x10190, 0x1019b, 1},
{0x101d0, 0x101fc, 1},
+ {0x102e1, 0x102fb, 1},
+ {0x1bca0, 0x1bca3, 1},
{0x1d000, 0x1d0f5, 1},
{0x1d100, 0x1d126, 1},
{0x1d129, 0x1d166, 1},
@@ -3347,10 +3660,10 @@ var _Common = &RangeTable{
{0x1f000, 0x1f02b, 1},
{0x1f030, 0x1f093, 1},
{0x1f0a0, 0x1f0ae, 1},
- {0x1f0b1, 0x1f0be, 1},
+ {0x1f0b1, 0x1f0bf, 1},
{0x1f0c1, 0x1f0cf, 1},
- {0x1f0d1, 0x1f0df, 1},
- {0x1f100, 0x1f10a, 1},
+ {0x1f0d1, 0x1f0f5, 1},
+ {0x1f100, 0x1f10c, 1},
{0x1f110, 0x1f12e, 1},
{0x1f130, 0x1f16b, 1},
{0x1f170, 0x1f19a, 1},
@@ -3359,24 +3672,25 @@ var _Common = &RangeTable{
{0x1f210, 0x1f23a, 1},
{0x1f240, 0x1f248, 1},
{0x1f250, 0x1f251, 1},
- {0x1f300, 0x1f320, 1},
- {0x1f330, 0x1f335, 1},
- {0x1f337, 0x1f37c, 1},
- {0x1f380, 0x1f393, 1},
- {0x1f3a0, 0x1f3c4, 1},
- {0x1f3c6, 0x1f3ca, 1},
- {0x1f3e0, 0x1f3f0, 1},
- {0x1f400, 0x1f43e, 1},
- {0x1f440, 0x1f440, 1},
- {0x1f442, 0x1f4f7, 1},
- {0x1f4f9, 0x1f4fc, 1},
- {0x1f500, 0x1f53d, 1},
- {0x1f540, 0x1f543, 1},
- {0x1f550, 0x1f567, 1},
- {0x1f5fb, 0x1f640, 1},
- {0x1f645, 0x1f64f, 1},
- {0x1f680, 0x1f6c5, 1},
+ {0x1f300, 0x1f32c, 1},
+ {0x1f330, 0x1f37d, 1},
+ {0x1f380, 0x1f3ce, 1},
+ {0x1f3d4, 0x1f3f7, 1},
+ {0x1f400, 0x1f4fe, 1},
+ {0x1f500, 0x1f54a, 1},
+ {0x1f550, 0x1f579, 1},
+ {0x1f57b, 0x1f5a3, 1},
+ {0x1f5a5, 0x1f642, 1},
+ {0x1f645, 0x1f6cf, 1},
+ {0x1f6e0, 0x1f6ec, 1},
+ {0x1f6f0, 0x1f6f3, 1},
{0x1f700, 0x1f773, 1},
+ {0x1f780, 0x1f7d4, 1},
+ {0x1f800, 0x1f80b, 1},
+ {0x1f810, 0x1f847, 1},
+ {0x1f850, 0x1f859, 1},
+ {0x1f860, 0x1f887, 1},
+ {0x1f890, 0x1f8ad, 1},
{0xe0001, 0xe0001, 1},
{0xe0020, 0xe007f, 1},
},
@@ -3394,9 +3708,9 @@ var _Coptic = &RangeTable{
var _Cuneiform = &RangeTable{
R16: []Range16{},
R32: []Range32{
- {0x12000, 0x1236e, 1},
- {0x12400, 0x12462, 1},
- {0x12470, 0x12473, 1},
+ {0x12000, 0x12398, 1},
+ {0x12400, 0x1246e, 1},
+ {0x12470, 0x12474, 1},
},
}
@@ -3415,11 +3729,11 @@ var _Cypriot = &RangeTable{
var _Cyrillic = &RangeTable{
R16: []Range16{
{0x0400, 0x0484, 1},
- {0x0487, 0x0527, 1},
+ {0x0487, 0x052f, 1},
{0x1d2b, 0x1d2b, 1},
{0x1d78, 0x1d78, 1},
{0x2de0, 0x2dff, 1},
- {0xa640, 0xa697, 1},
+ {0xa640, 0xa69d, 1},
{0xa69f, 0xa69f, 1},
},
}
@@ -3435,12 +3749,22 @@ var _Devanagari = &RangeTable{
R16: []Range16{
{0x0900, 0x0950, 1},
{0x0953, 0x0963, 1},
- {0x0966, 0x0977, 1},
- {0x0979, 0x097f, 1},
+ {0x0966, 0x097f, 1},
{0xa8e0, 0xa8fb, 1},
},
}
+var _Duployan = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x1bc00, 0x1bc6a, 1},
+ {0x1bc70, 0x1bc7c, 1},
+ {0x1bc80, 0x1bc88, 1},
+ {0x1bc90, 0x1bc99, 1},
+ {0x1bc9c, 0x1bc9f, 1},
+ },
+}
+
var _Egyptian_Hieroglyphs = &RangeTable{
R16: []Range16{},
R32: []Range32{
@@ -3448,6 +3772,13 @@ var _Egyptian_Hieroglyphs = &RangeTable{
},
}
+var _Elbasan = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x10500, 0x10527, 1},
+ },
+}
+
var _Ethiopic = &RangeTable{
R16: []Range16{
{0x1200, 0x1248, 1},
@@ -3512,11 +3843,32 @@ var _Gothic = &RangeTable{
},
}
+var _Grantha = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x11301, 0x11303, 1},
+ {0x11305, 0x1130c, 1},
+ {0x1130f, 0x11310, 1},
+ {0x11313, 0x11328, 1},
+ {0x1132a, 0x11330, 1},
+ {0x11332, 0x11333, 1},
+ {0x11335, 0x11339, 1},
+ {0x1133c, 0x11344, 1},
+ {0x11347, 0x11348, 1},
+ {0x1134b, 0x1134d, 1},
+ {0x11357, 0x11357, 1},
+ {0x1135d, 0x11363, 1},
+ {0x11366, 0x1136c, 1},
+ {0x11370, 0x11374, 1},
+ },
+}
+
var _Greek = &RangeTable{
R16: []Range16{
{0x0370, 0x0373, 1},
{0x0375, 0x0377, 1},
{0x037a, 0x037d, 1},
+ {0x037f, 0x037f, 1},
{0x0384, 0x0384, 1},
{0x0386, 0x0386, 1},
{0x0388, 0x038a, 1},
@@ -3545,9 +3897,11 @@ var _Greek = &RangeTable{
{0x1ff2, 0x1ff4, 1},
{0x1ff6, 0x1ffe, 1},
{0x2126, 0x2126, 1},
+ {0xab65, 0xab65, 1},
},
R32: []Range32{
- {0x10140, 0x1018a, 1},
+ {0x10140, 0x1018c, 1},
+ {0x101a0, 0x101a0, 1},
{0x1d200, 0x1d245, 1},
},
}
@@ -3678,22 +4032,25 @@ var _Inherited = &RangeTable{
{0x064b, 0x0655, 1},
{0x0670, 0x0670, 1},
{0x0951, 0x0952, 1},
+ {0x1ab0, 0x1abe, 1},
{0x1cd0, 0x1cd2, 1},
{0x1cd4, 0x1ce0, 1},
{0x1ce2, 0x1ce8, 1},
{0x1ced, 0x1ced, 1},
{0x1cf4, 0x1cf4, 1},
- {0x1dc0, 0x1de6, 1},
+ {0x1cf8, 0x1cf9, 1},
+ {0x1dc0, 0x1df5, 1},
{0x1dfc, 0x1dff, 1},
{0x200c, 0x200d, 1},
{0x20d0, 0x20f0, 1},
{0x302a, 0x302d, 1},
{0x3099, 0x309a, 1},
{0xfe00, 0xfe0f, 1},
- {0xfe20, 0xfe26, 1},
+ {0xfe20, 0xfe2d, 1},
},
R32: []Range32{
{0x101fd, 0x101fd, 1},
+ {0x102e0, 0x102e0, 1},
{0x1d167, 0x1d169, 1},
{0x1d17b, 0x1d182, 1},
{0x1d185, 0x1d18b, 1},
@@ -3735,7 +4092,7 @@ var _Kaithi = &RangeTable{
var _Kannada = &RangeTable{
R16: []Range16{
- {0x0c82, 0x0c83, 1},
+ {0x0c81, 0x0c83, 1},
{0x0c85, 0x0c8c, 1},
{0x0c8e, 0x0c90, 1},
{0x0c92, 0x0ca8, 1},
@@ -3769,7 +4126,8 @@ var _Katakana = &RangeTable{
var _Kayah_Li = &RangeTable{
R16: []Range16{
- {0xa900, 0xa92f, 1},
+ {0xa900, 0xa92d, 1},
+ {0xa92f, 0xa92f, 1},
},
}
@@ -3796,6 +4154,22 @@ var _Khmer = &RangeTable{
},
}
+var _Khojki = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x11200, 0x11211, 1},
+ {0x11213, 0x1123d, 1},
+ },
+}
+
+var _Khudawadi = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x112b0, 0x112ea, 1},
+ {0x112f0, 0x112f9, 1},
+ },
+}
+
var _Lao = &RangeTable{
R16: []Range16{
{0x0e81, 0x0e82, 1},
@@ -3845,9 +4219,12 @@ var _Latin = &RangeTable{
{0x2c60, 0x2c7f, 1},
{0xa722, 0xa787, 1},
{0xa78b, 0xa78e, 1},
- {0xa790, 0xa793, 1},
- {0xa7a0, 0xa7aa, 1},
- {0xa7f8, 0xa7ff, 1},
+ {0xa790, 0xa7ad, 1},
+ {0xa7b0, 0xa7b1, 1},
+ {0xa7f7, 0xa7ff, 1},
+ {0xab30, 0xab5a, 1},
+ {0xab5c, 0xab5f, 1},
+ {0xab64, 0xab64, 1},
{0xfb00, 0xfb06, 1},
{0xff21, 0xff3a, 1},
{0xff41, 0xff5a, 1},
@@ -3865,7 +4242,7 @@ var _Lepcha = &RangeTable{
var _Limbu = &RangeTable{
R16: []Range16{
- {0x1900, 0x191c, 1},
+ {0x1900, 0x191e, 1},
{0x1920, 0x192b, 1},
{0x1930, 0x193b, 1},
{0x1940, 0x1940, 1},
@@ -3873,6 +4250,15 @@ var _Limbu = &RangeTable{
},
}
+var _Linear_A = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x10600, 0x10736, 1},
+ {0x10740, 0x10755, 1},
+ {0x10760, 0x10767, 1},
+ },
+}
+
var _Linear_B = &RangeTable{
R16: []Range16{},
R32: []Range32{
@@ -3907,9 +4293,16 @@ var _Lydian = &RangeTable{
},
}
+var _Mahajani = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x11150, 0x11176, 1},
+ },
+}
+
var _Malayalam = &RangeTable{
R16: []Range16{
- {0x0d02, 0x0d03, 1},
+ {0x0d01, 0x0d03, 1},
{0x0d05, 0x0d0c, 1},
{0x0d0e, 0x0d10, 1},
{0x0d12, 0x0d3a, 1},
@@ -3930,6 +4323,14 @@ var _Mandaic = &RangeTable{
},
}
+var _Manichaean = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x10ac0, 0x10ae6, 1},
+ {0x10aeb, 0x10af6, 1},
+ },
+}
+
var _Meetei_Mayek = &RangeTable{
R16: []Range16{
{0xaae0, 0xaaf6, 1},
@@ -3938,6 +4339,14 @@ var _Meetei_Mayek = &RangeTable{
},
}
+var _Mende_Kikakui = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x1e800, 0x1e8c4, 1},
+ {0x1e8c7, 0x1e8d6, 1},
+ },
+}
+
var _Meroitic_Cursive = &RangeTable{
R16: []Range16{},
R32: []Range32{
@@ -3962,6 +4371,14 @@ var _Miao = &RangeTable{
},
}
+var _Modi = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x11600, 0x11644, 1},
+ {0x11650, 0x11659, 1},
+ },
+}
+
var _Mongolian = &RangeTable{
R16: []Range16{
{0x1800, 0x1801, 1},
@@ -3973,10 +4390,28 @@ var _Mongolian = &RangeTable{
},
}
+var _Mro = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x16a40, 0x16a5e, 1},
+ {0x16a60, 0x16a69, 1},
+ {0x16a6e, 0x16a6f, 1},
+ },
+}
+
var _Myanmar = &RangeTable{
R16: []Range16{
{0x1000, 0x109f, 1},
- {0xaa60, 0xaa7b, 1},
+ {0xa9e0, 0xa9fe, 1},
+ {0xaa60, 0xaa7f, 1},
+ },
+}
+
+var _Nabataean = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x10880, 0x1089e, 1},
+ {0x108a7, 0x108af, 1},
},
}
@@ -4010,8 +4445,21 @@ var _Ol_Chiki = &RangeTable{
var _Old_Italic = &RangeTable{
R16: []Range16{},
R32: []Range32{
- {0x10300, 0x1031e, 1},
- {0x10320, 0x10323, 1},
+ {0x10300, 0x10323, 1},
+ },
+}
+
+var _Old_North_Arabian = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x10a80, 0x10a9f, 1},
+ },
+}
+
+var _Old_Permic = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x10350, 0x1037a, 1},
},
}
@@ -4064,6 +4512,31 @@ var _Osmanya = &RangeTable{
},
}
+var _Pahawh_Hmong = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x16b00, 0x16b45, 1},
+ {0x16b50, 0x16b59, 1},
+ {0x16b5b, 0x16b61, 1},
+ {0x16b63, 0x16b77, 1},
+ {0x16b7d, 0x16b8f, 1},
+ },
+}
+
+var _Palmyrene = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x10860, 0x1087f, 1},
+ },
+}
+
+var _Pau_Cin_Hau = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x11ac0, 0x11af8, 1},
+ },
+}
+
var _Phags_Pa = &RangeTable{
R16: []Range16{
{0xa840, 0xa877, 1},
@@ -4078,6 +4551,15 @@ var _Phoenician = &RangeTable{
},
}
+var _Psalter_Pahlavi = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x10b80, 0x10b91, 1},
+ {0x10b99, 0x10b9c, 1},
+ {0x10ba9, 0x10baf, 1},
+ },
+}
+
var _Rejang = &RangeTable{
R16: []Range16{
{0xa930, 0xa953, 1},
@@ -4088,7 +4570,7 @@ var _Rejang = &RangeTable{
var _Runic = &RangeTable{
R16: []Range16{
{0x16a0, 0x16ea, 1},
- {0x16ee, 0x16f0, 1},
+ {0x16ee, 0x16f8, 1},
},
}
@@ -4110,7 +4592,8 @@ var _Sharada = &RangeTable{
R16: []Range16{},
R32: []Range32{
{0x11180, 0x111c8, 1},
- {0x111d0, 0x111d9, 1},
+ {0x111cd, 0x111cd, 1},
+ {0x111d0, 0x111da, 1},
},
}
@@ -4121,6 +4604,14 @@ var _Shavian = &RangeTable{
},
}
+var _Siddham = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x11580, 0x115b5, 1},
+ {0x115b8, 0x115c9, 1},
+ },
+}
+
var _Sinhala = &RangeTable{
R16: []Range16{
{0x0d82, 0x0d83, 1},
@@ -4133,8 +4624,12 @@ var _Sinhala = &RangeTable{
{0x0dcf, 0x0dd4, 1},
{0x0dd6, 0x0dd6, 1},
{0x0dd8, 0x0ddf, 1},
+ {0x0de6, 0x0def, 1},
{0x0df2, 0x0df4, 1},
},
+ R32: []Range32{
+ {0x111e1, 0x111f4, 1},
+ },
}
var _Sora_Sompeng = &RangeTable{
@@ -4236,12 +4731,11 @@ var _Tamil = &RangeTable{
var _Telugu = &RangeTable{
R16: []Range16{
- {0x0c01, 0x0c03, 1},
+ {0x0c00, 0x0c03, 1},
{0x0c05, 0x0c0c, 1},
{0x0c0e, 0x0c10, 1},
{0x0c12, 0x0c28, 1},
- {0x0c2a, 0x0c33, 1},
- {0x0c35, 0x0c39, 1},
+ {0x0c2a, 0x0c39, 1},
{0x0c3d, 0x0c44, 1},
{0x0c46, 0x0c48, 1},
{0x0c4a, 0x0c4d, 1},
@@ -4286,6 +4780,14 @@ var _Tifinagh = &RangeTable{
},
}
+var _Tirhuta = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x11480, 0x114c7, 1},
+ {0x114d0, 0x114d9, 1},
+ },
+}
+
var _Ugaritic = &RangeTable{
R16: []Range16{},
R32: []Range32{
@@ -4300,6 +4802,14 @@ var _Vai = &RangeTable{
},
}
+var _Warang_Citi = &RangeTable{
+ R16: []Range16{},
+ R32: []Range32{
+ {0x118a0, 0x118f2, 1},
+ {0x118ff, 0x118ff, 1},
+ },
+}
+
var _Yi = &RangeTable{
R16: []Range16{
{0xa000, 0xa48c, 1},
@@ -4314,6 +4824,7 @@ var (
Avestan = _Avestan // Avestan is the set of Unicode characters in script Avestan.
Balinese = _Balinese // Balinese is the set of Unicode characters in script Balinese.
Bamum = _Bamum // Bamum is the set of Unicode characters in script Bamum.
+ Bassa_Vah = _Bassa_Vah // Bassa_Vah is the set of Unicode characters in script Bassa_Vah.
Batak = _Batak // Batak is the set of Unicode characters in script Batak.
Bengali = _Bengali // Bengali is the set of Unicode characters in script Bengali.
Bopomofo = _Bopomofo // Bopomofo is the set of Unicode characters in script Bopomofo.
@@ -4323,6 +4834,7 @@ var (
Buhid = _Buhid // Buhid is the set of Unicode characters in script Buhid.
Canadian_Aboriginal = _Canadian_Aboriginal // Canadian_Aboriginal is the set of Unicode characters in script Canadian_Aboriginal.
Carian = _Carian // Carian is the set of Unicode characters in script Carian.
+ Caucasian_Albanian = _Caucasian_Albanian // Caucasian_Albanian is the set of Unicode characters in script Caucasian_Albanian.
Chakma = _Chakma // Chakma is the set of Unicode characters in script Chakma.
Cham = _Cham // Cham is the set of Unicode characters in script Cham.
Cherokee = _Cherokee // Cherokee is the set of Unicode characters in script Cherokee.
@@ -4333,11 +4845,14 @@ var (
Cyrillic = _Cyrillic // Cyrillic is the set of Unicode characters in script Cyrillic.
Deseret = _Deseret // Deseret is the set of Unicode characters in script Deseret.
Devanagari = _Devanagari // Devanagari is the set of Unicode characters in script Devanagari.
+ Duployan = _Duployan // Duployan is the set of Unicode characters in script Duployan.
Egyptian_Hieroglyphs = _Egyptian_Hieroglyphs // Egyptian_Hieroglyphs is the set of Unicode characters in script Egyptian_Hieroglyphs.
+ Elbasan = _Elbasan // Elbasan is the set of Unicode characters in script Elbasan.
Ethiopic = _Ethiopic // Ethiopic is the set of Unicode characters in script Ethiopic.
Georgian = _Georgian // Georgian is the set of Unicode characters in script Georgian.
Glagolitic = _Glagolitic // Glagolitic is the set of Unicode characters in script Glagolitic.
Gothic = _Gothic // Gothic is the set of Unicode characters in script Gothic.
+ Grantha = _Grantha // Grantha is the set of Unicode characters in script Grantha.
Greek = _Greek // Greek is the set of Unicode characters in script Greek.
Gujarati = _Gujarati // Gujarati is the set of Unicode characters in script Gujarati.
Gurmukhi = _Gurmukhi // Gurmukhi is the set of Unicode characters in script Gurmukhi.
@@ -4357,40 +4872,56 @@ var (
Kayah_Li = _Kayah_Li // Kayah_Li is the set of Unicode characters in script Kayah_Li.
Kharoshthi = _Kharoshthi // Kharoshthi is the set of Unicode characters in script Kharoshthi.
Khmer = _Khmer // Khmer is the set of Unicode characters in script Khmer.
+ Khojki = _Khojki // Khojki is the set of Unicode characters in script Khojki.
+ Khudawadi = _Khudawadi // Khudawadi is the set of Unicode characters in script Khudawadi.
Lao = _Lao // Lao is the set of Unicode characters in script Lao.
Latin = _Latin // Latin is the set of Unicode characters in script Latin.
Lepcha = _Lepcha // Lepcha is the set of Unicode characters in script Lepcha.
Limbu = _Limbu // Limbu is the set of Unicode characters in script Limbu.
+ Linear_A = _Linear_A // Linear_A is the set of Unicode characters in script Linear_A.
Linear_B = _Linear_B // Linear_B is the set of Unicode characters in script Linear_B.
Lisu = _Lisu // Lisu is the set of Unicode characters in script Lisu.
Lycian = _Lycian // Lycian is the set of Unicode characters in script Lycian.
Lydian = _Lydian // Lydian is the set of Unicode characters in script Lydian.
+ Mahajani = _Mahajani // Mahajani is the set of Unicode characters in script Mahajani.
Malayalam = _Malayalam // Malayalam is the set of Unicode characters in script Malayalam.
Mandaic = _Mandaic // Mandaic is the set of Unicode characters in script Mandaic.
+ Manichaean = _Manichaean // Manichaean is the set of Unicode characters in script Manichaean.
Meetei_Mayek = _Meetei_Mayek // Meetei_Mayek is the set of Unicode characters in script Meetei_Mayek.
+ Mende_Kikakui = _Mende_Kikakui // Mende_Kikakui is the set of Unicode characters in script Mende_Kikakui.
Meroitic_Cursive = _Meroitic_Cursive // Meroitic_Cursive is the set of Unicode characters in script Meroitic_Cursive.
Meroitic_Hieroglyphs = _Meroitic_Hieroglyphs // Meroitic_Hieroglyphs is the set of Unicode characters in script Meroitic_Hieroglyphs.
Miao = _Miao // Miao is the set of Unicode characters in script Miao.
+ Modi = _Modi // Modi is the set of Unicode characters in script Modi.
Mongolian = _Mongolian // Mongolian is the set of Unicode characters in script Mongolian.
+ Mro = _Mro // Mro is the set of Unicode characters in script Mro.
Myanmar = _Myanmar // Myanmar is the set of Unicode characters in script Myanmar.
+ Nabataean = _Nabataean // Nabataean is the set of Unicode characters in script Nabataean.
New_Tai_Lue = _New_Tai_Lue // New_Tai_Lue is the set of Unicode characters in script New_Tai_Lue.
Nko = _Nko // Nko is the set of Unicode characters in script Nko.
Ogham = _Ogham // Ogham is the set of Unicode characters in script Ogham.
Ol_Chiki = _Ol_Chiki // Ol_Chiki is the set of Unicode characters in script Ol_Chiki.
Old_Italic = _Old_Italic // Old_Italic is the set of Unicode characters in script Old_Italic.
+ Old_North_Arabian = _Old_North_Arabian // Old_North_Arabian is the set of Unicode characters in script Old_North_Arabian.
+ Old_Permic = _Old_Permic // Old_Permic is the set of Unicode characters in script Old_Permic.
Old_Persian = _Old_Persian // Old_Persian is the set of Unicode characters in script Old_Persian.
Old_South_Arabian = _Old_South_Arabian // Old_South_Arabian is the set of Unicode characters in script Old_South_Arabian.
Old_Turkic = _Old_Turkic // Old_Turkic is the set of Unicode characters in script Old_Turkic.
Oriya = _Oriya // Oriya is the set of Unicode characters in script Oriya.
Osmanya = _Osmanya // Osmanya is the set of Unicode characters in script Osmanya.
+ Pahawh_Hmong = _Pahawh_Hmong // Pahawh_Hmong is the set of Unicode characters in script Pahawh_Hmong.
+ Palmyrene = _Palmyrene // Palmyrene is the set of Unicode characters in script Palmyrene.
+ Pau_Cin_Hau = _Pau_Cin_Hau // Pau_Cin_Hau is the set of Unicode characters in script Pau_Cin_Hau.
Phags_Pa = _Phags_Pa // Phags_Pa is the set of Unicode characters in script Phags_Pa.
Phoenician = _Phoenician // Phoenician is the set of Unicode characters in script Phoenician.
+ Psalter_Pahlavi = _Psalter_Pahlavi // Psalter_Pahlavi is the set of Unicode characters in script Psalter_Pahlavi.
Rejang = _Rejang // Rejang is the set of Unicode characters in script Rejang.
Runic = _Runic // Runic is the set of Unicode characters in script Runic.
Samaritan = _Samaritan // Samaritan is the set of Unicode characters in script Samaritan.
Saurashtra = _Saurashtra // Saurashtra is the set of Unicode characters in script Saurashtra.
Sharada = _Sharada // Sharada is the set of Unicode characters in script Sharada.
Shavian = _Shavian // Shavian is the set of Unicode characters in script Shavian.
+ Siddham = _Siddham // Siddham is the set of Unicode characters in script Siddham.
Sinhala = _Sinhala // Sinhala is the set of Unicode characters in script Sinhala.
Sora_Sompeng = _Sora_Sompeng // Sora_Sompeng is the set of Unicode characters in script Sora_Sompeng.
Sundanese = _Sundanese // Sundanese is the set of Unicode characters in script Sundanese.
@@ -4408,13 +4939,15 @@ var (
Thai = _Thai // Thai is the set of Unicode characters in script Thai.
Tibetan = _Tibetan // Tibetan is the set of Unicode characters in script Tibetan.
Tifinagh = _Tifinagh // Tifinagh is the set of Unicode characters in script Tifinagh.
+ Tirhuta = _Tirhuta // Tirhuta is the set of Unicode characters in script Tirhuta.
Ugaritic = _Ugaritic // Ugaritic is the set of Unicode characters in script Ugaritic.
Vai = _Vai // Vai is the set of Unicode characters in script Vai.
+ Warang_Citi = _Warang_Citi // Warang_Citi is the set of Unicode characters in script Warang_Citi.
Yi = _Yi // Yi is the set of Unicode characters in script Yi.
)
// Generated by running
-// maketables --props=all --url=http://www.unicode.org/Public/6.3.0/ucd/
+// maketables --props=all --url=http://www.unicode.org/Public/7.0.0/ucd/
// DO NOT EDIT
// Properties is the set of Unicode property tables.
@@ -4486,6 +5019,7 @@ var _Dash = &RangeTable{
{0x2e17, 0x2e17, 1},
{0x2e1a, 0x2e1a, 1},
{0x2e3a, 0x2e3b, 1},
+ {0x2e40, 0x2e40, 1},
{0x301c, 0x301c, 1},
{0x3030, 0x3030, 1},
{0x30a0, 0x30a0, 1},
@@ -4583,6 +5117,7 @@ var _Diacritic = &RangeTable{
{0x1939, 0x193b, 1},
{0x1a75, 0x1a7c, 1},
{0x1a7f, 0x1a7f, 1},
+ {0x1ab0, 0x1abd, 1},
{0x1b34, 0x1b34, 1},
{0x1b44, 0x1b44, 1},
{0x1b6b, 0x1b73, 1},
@@ -4592,8 +5127,10 @@ var _Diacritic = &RangeTable{
{0x1cd0, 0x1ce8, 1},
{0x1ced, 0x1ced, 1},
{0x1cf4, 0x1cf4, 1},
+ {0x1cf8, 0x1cf9, 1},
{0x1d2c, 0x1d6a, 1},
{0x1dc4, 0x1dcf, 1},
+ {0x1df5, 0x1df5, 1},
{0x1dfd, 0x1dff, 1},
{0x1fbd, 0x1fbd, 1},
{0x1fbf, 0x1fc1, 1},
@@ -4609,6 +5146,7 @@ var _Diacritic = &RangeTable{
{0xa66f, 0xa66f, 1},
{0xa67c, 0xa67d, 1},
{0xa67f, 0xa67f, 1},
+ {0xa69c, 0xa69d, 1},
{0xa6f0, 0xa6f1, 1},
{0xa717, 0xa721, 1},
{0xa788, 0xa788, 1},
@@ -4619,12 +5157,14 @@ var _Diacritic = &RangeTable{
{0xa953, 0xa953, 1},
{0xa9b3, 0xa9b3, 1},
{0xa9c0, 0xa9c0, 1},
- {0xaa7b, 0xaa7b, 1},
+ {0xa9e5, 0xa9e5, 1},
+ {0xaa7b, 0xaa7d, 1},
{0xaabf, 0xaac2, 1},
{0xaaf6, 0xaaf6, 1},
+ {0xab5b, 0xab5f, 1},
{0xabec, 0xabed, 1},
{0xfb1e, 0xfb1e, 1},
- {0xfe20, 0xfe26, 1},
+ {0xfe20, 0xfe2d, 1},
{0xff3e, 0xff3e, 1},
{0xff40, 0xff40, 1},
{0xff70, 0xff70, 1},
@@ -4632,16 +5172,30 @@ var _Diacritic = &RangeTable{
{0xffe3, 0xffe3, 1},
},
R32: []Range32{
+ {0x102e0, 0x102e0, 1},
+ {0x10ae5, 0x10ae6, 1},
{0x110b9, 0x110ba, 1},
{0x11133, 0x11134, 1},
+ {0x11173, 0x11173, 1},
{0x111c0, 0x111c0, 1},
+ {0x11235, 0x11236, 1},
+ {0x112e9, 0x112ea, 1},
+ {0x1133c, 0x1133c, 1},
+ {0x1134d, 0x1134d, 1},
+ {0x11366, 0x1136c, 1},
+ {0x11370, 0x11374, 1},
+ {0x114c2, 0x114c3, 1},
+ {0x115bf, 0x115c0, 1},
+ {0x1163f, 0x1163f, 1},
{0x116b6, 0x116b7, 1},
+ {0x16af0, 0x16af4, 1},
{0x16f8f, 0x16f9f, 1},
{0x1d167, 0x1d169, 1},
{0x1d16d, 0x1d172, 1},
{0x1d17b, 0x1d182, 1},
{0x1d185, 0x1d18b, 1},
{0x1d1aa, 0x1d1ad, 1},
+ {0x1e8d0, 0x1e8d6, 1},
},
LatinOffset: 6,
}
@@ -4666,11 +5220,17 @@ var _Extender = &RangeTable{
{0xa015, 0xa015, 1},
{0xa60c, 0xa60c, 1},
{0xa9cf, 0xa9cf, 1},
+ {0xa9e6, 0xa9e6, 1},
{0xaa70, 0xaa70, 1},
{0xaadd, 0xaadd, 1},
{0xaaf3, 0xaaf4, 1},
{0xff70, 0xff70, 1},
},
+ R32: []Range32{
+ {0x1135d, 0x1135d, 1},
+ {0x115c6, 0x115c8, 1},
+ {0x16b42, 0x16b43, 1},
+ },
LatinOffset: 1,
}
@@ -4798,8 +5358,7 @@ var _Other_Alphabetic = &RangeTable{
{0x0825, 0x0827, 1},
{0x0829, 0x082c, 1},
{0x08e4, 0x08e9, 1},
- {0x08f0, 0x08fe, 1},
- {0x0900, 0x0903, 1},
+ {0x08f0, 0x0903, 1},
{0x093a, 0x093b, 1},
{0x093e, 0x094c, 1},
{0x094e, 0x094f, 1},
@@ -4834,19 +5393,19 @@ var _Other_Alphabetic = &RangeTable{
{0x0bc6, 0x0bc8, 1},
{0x0bca, 0x0bcc, 1},
{0x0bd7, 0x0bd7, 1},
- {0x0c01, 0x0c03, 1},
+ {0x0c00, 0x0c03, 1},
{0x0c3e, 0x0c44, 1},
{0x0c46, 0x0c48, 1},
{0x0c4a, 0x0c4c, 1},
{0x0c55, 0x0c56, 1},
{0x0c62, 0x0c63, 1},
- {0x0c82, 0x0c83, 1},
+ {0x0c81, 0x0c83, 1},
{0x0cbe, 0x0cc4, 1},
{0x0cc6, 0x0cc8, 1},
{0x0cca, 0x0ccc, 1},
{0x0cd5, 0x0cd6, 1},
{0x0ce2, 0x0ce3, 1},
- {0x0d02, 0x0d03, 1},
+ {0x0d01, 0x0d03, 1},
{0x0d3e, 0x0d44, 1},
{0x0d46, 0x0d48, 1},
{0x0d4a, 0x0d4c, 1},
@@ -4899,6 +5458,7 @@ var _Other_Alphabetic = &RangeTable{
{0x1be7, 0x1bf1, 1},
{0x1c24, 0x1c35, 1},
{0x1cf2, 0x1cf3, 1},
+ {0x1de7, 0x1df4, 1},
{0x24b6, 0x24e9, 1},
{0x2de0, 0x2dff, 1},
{0xa674, 0xa67b, 1},
@@ -4923,6 +5483,7 @@ var _Other_Alphabetic = &RangeTable{
{0xfb1e, 0xfb1e, 1},
},
R32: []Range32{
+ {0x10376, 0x1037a, 1},
{0x10a01, 0x10a03, 1},
{0x10a05, 0x10a06, 1},
{0x10a0c, 0x10a0f, 1},
@@ -4934,8 +5495,27 @@ var _Other_Alphabetic = &RangeTable{
{0x11127, 0x11132, 1},
{0x11180, 0x11182, 1},
{0x111b3, 0x111bf, 1},
+ {0x1122c, 0x11234, 1},
+ {0x11237, 0x11237, 1},
+ {0x112df, 0x112e8, 1},
+ {0x11301, 0x11303, 1},
+ {0x1133e, 0x11344, 1},
+ {0x11347, 0x11348, 1},
+ {0x1134b, 0x1134c, 1},
+ {0x11357, 0x11357, 1},
+ {0x11362, 0x11363, 1},
+ {0x114b0, 0x114c1, 1},
+ {0x115af, 0x115b5, 1},
+ {0x115b8, 0x115be, 1},
+ {0x11630, 0x1163e, 1},
+ {0x11640, 0x11640, 1},
{0x116ab, 0x116b5, 1},
+ {0x16b30, 0x16b36, 1},
{0x16f51, 0x16f7e, 1},
+ {0x1bc9e, 0x1bc9e, 1},
+ {0x1f130, 0x1f149, 1},
+ {0x1f150, 0x1f169, 1},
+ {0x1f170, 0x1f189, 1},
},
}
@@ -4976,6 +5556,11 @@ var _Other_Grapheme_Extend = &RangeTable{
{0xff9e, 0xff9f, 1},
},
R32: []Range32{
+ {0x1133e, 0x1133e, 1},
+ {0x11357, 0x11357, 1},
+ {0x114b0, 0x114b0, 1},
+ {0x114bd, 0x114bd, 1},
+ {0x115af, 0x115af, 1},
{0x1d165, 0x1d165, 1},
{0x1d16e, 0x1d172, 1},
},
@@ -5017,8 +5602,10 @@ var _Other_Lowercase = &RangeTable{
{0x2170, 0x217f, 1},
{0x24d0, 0x24e9, 1},
{0x2c7c, 0x2c7d, 1},
+ {0xa69c, 0xa69d, 1},
{0xa770, 0xa770, 1},
{0xa7f8, 0xa7f9, 1},
+ {0xab5c, 0xab5f, 1},
},
LatinOffset: 2,
}
@@ -5170,6 +5757,11 @@ var _Other_Uppercase = &RangeTable{
{0x2160, 0x216f, 1},
{0x24b6, 0x24cf, 1},
},
+ R32: []Range32{
+ {0x1f130, 0x1f149, 1},
+ {0x1f150, 0x1f169, 1},
+ {0x1f170, 0x1f189, 1},
+ },
}
var _Pattern_Syntax = &RangeTable{
@@ -5225,6 +5817,7 @@ var _Quotation_Mark = &RangeTable{
{0x00bb, 0x00bb, 1},
{0x2018, 0x201f, 1},
{0x2039, 0x203a, 1},
+ {0x2e42, 0x2e42, 1},
{0x300c, 0x300f, 1},
{0x301d, 0x301f, 1},
{0xfe41, 0xfe44, 1},
@@ -5248,8 +5841,6 @@ var _STerm = &RangeTable{
{0x0021, 0x0021, 1},
{0x002e, 0x002e, 1},
{0x003f, 0x003f, 1},
- {0x055c, 0x055c, 1},
- {0x055e, 0x055e, 1},
{0x0589, 0x0589, 1},
{0x061f, 0x061f, 1},
{0x06d4, 0x06d4, 1},
@@ -5272,6 +5863,7 @@ var _STerm = &RangeTable{
{0x203c, 0x203d, 1},
{0x2047, 0x2049, 1},
{0x2e2e, 0x2e2e, 1},
+ {0x2e3c, 0x2e3c, 1},
{0x3002, 0x3002, 1},
{0xa4ff, 0xa4ff, 1},
{0xa60e, 0xa60f, 1},
@@ -5297,6 +5889,17 @@ var _STerm = &RangeTable{
{0x110be, 0x110c1, 1},
{0x11141, 0x11143, 1},
{0x111c5, 0x111c6, 1},
+ {0x111cd, 0x111cd, 1},
+ {0x11238, 0x11239, 1},
+ {0x1123b, 0x1123c, 1},
+ {0x115c2, 0x115c3, 1},
+ {0x115c9, 0x115c9, 1},
+ {0x11641, 0x11642, 1},
+ {0x16a6e, 0x16a6f, 1},
+ {0x16af5, 0x16af5, 1},
+ {0x16b37, 0x16b38, 1},
+ {0x16b44, 0x16b44, 1},
+ {0x1bc9f, 0x1bc9f, 1},
},
LatinOffset: 3,
}
@@ -5368,6 +5971,7 @@ var _Terminal_Punctuation = &RangeTable{
{0x1361, 0x1368, 1},
{0x166d, 0x166e, 1},
{0x16eb, 0x16ed, 1},
+ {0x1735, 0x1736, 1},
{0x17d4, 0x17d6, 1},
{0x17da, 0x17da, 1},
{0x1802, 0x1805, 1},
@@ -5381,6 +5985,8 @@ var _Terminal_Punctuation = &RangeTable{
{0x203c, 0x203d, 1},
{0x2047, 0x2049, 1},
{0x2e2e, 0x2e2e, 1},
+ {0x2e3c, 0x2e3c, 1},
+ {0x2e41, 0x2e41, 1},
{0x3001, 0x3002, 1},
{0xa4fe, 0xa4ff, 1},
{0xa60d, 0xa60f, 1},
@@ -5408,12 +6014,25 @@ var _Terminal_Punctuation = &RangeTable{
{0x103d0, 0x103d0, 1},
{0x10857, 0x10857, 1},
{0x1091f, 0x1091f, 1},
+ {0x10a56, 0x10a57, 1},
+ {0x10af0, 0x10af5, 1},
{0x10b3a, 0x10b3f, 1},
+ {0x10b99, 0x10b9c, 1},
{0x11047, 0x1104d, 1},
{0x110be, 0x110c1, 1},
{0x11141, 0x11143, 1},
{0x111c5, 0x111c6, 1},
- {0x12470, 0x12473, 1},
+ {0x111cd, 0x111cd, 1},
+ {0x11238, 0x1123c, 1},
+ {0x115c2, 0x115c5, 1},
+ {0x115c9, 0x115c9, 1},
+ {0x11641, 0x11642, 1},
+ {0x12470, 0x12474, 1},
+ {0x16a6e, 0x16a6f, 1},
+ {0x16af5, 0x16af5, 1},
+ {0x16b37, 0x16b39, 1},
+ {0x16b44, 0x16b44, 1},
+ {0x1bc9f, 0x1bc9f, 1},
},
LatinOffset: 5,
}
@@ -5500,7 +6119,7 @@ var (
)
// Generated by running
-// maketables --data=http://www.unicode.org/Public/6.3.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/6.3.0/ucd/CaseFolding.txt
+// maketables --data=http://www.unicode.org/Public/7.0.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/7.0.0/ucd/CaseFolding.txt
// DO NOT EDIT
// CaseRanges is the table describing case mappings for all letters with
@@ -5598,13 +6217,16 @@ var _CaseRanges = []CaseRange{
{0x0256, 0x0257, d{-205, 0, -205}},
{0x0259, 0x0259, d{-202, 0, -202}},
{0x025B, 0x025B, d{-203, 0, -203}},
+ {0x025C, 0x025C, d{42319, 0, 42319}},
{0x0260, 0x0260, d{-205, 0, -205}},
+ {0x0261, 0x0261, d{42315, 0, 42315}},
{0x0263, 0x0263, d{-207, 0, -207}},
{0x0265, 0x0265, d{42280, 0, 42280}},
{0x0266, 0x0266, d{42308, 0, 42308}},
{0x0268, 0x0268, d{-209, 0, -209}},
{0x0269, 0x0269, d{-211, 0, -211}},
{0x026B, 0x026B, d{10743, 0, 10743}},
+ {0x026C, 0x026C, d{42305, 0, 42305}},
{0x026F, 0x026F, d{-211, 0, -211}},
{0x0271, 0x0271, d{10749, 0, 10749}},
{0x0272, 0x0272, d{-213, 0, -213}},
@@ -5612,15 +6234,18 @@ var _CaseRanges = []CaseRange{
{0x027D, 0x027D, d{10727, 0, 10727}},
{0x0280, 0x0280, d{-218, 0, -218}},
{0x0283, 0x0283, d{-218, 0, -218}},
+ {0x0287, 0x0287, d{42282, 0, 42282}},
{0x0288, 0x0288, d{-218, 0, -218}},
{0x0289, 0x0289, d{-69, 0, -69}},
{0x028A, 0x028B, d{-217, 0, -217}},
{0x028C, 0x028C, d{-71, 0, -71}},
{0x0292, 0x0292, d{-219, 0, -219}},
+ {0x029E, 0x029E, d{42258, 0, 42258}},
{0x0345, 0x0345, d{84, 0, 84}},
{0x0370, 0x0373, d{UpperLower, UpperLower, UpperLower}},
{0x0376, 0x0377, d{UpperLower, UpperLower, UpperLower}},
{0x037B, 0x037D, d{130, 0, 130}},
+ {0x037F, 0x037F, d{0, 116, 0}},
{0x0386, 0x0386, d{0, 38, 0}},
{0x0388, 0x038A, d{0, 37, 0}},
{0x038C, 0x038C, d{0, 64, 0}},
@@ -5644,6 +6269,7 @@ var _CaseRanges = []CaseRange{
{0x03F0, 0x03F0, d{-86, 0, -86}},
{0x03F1, 0x03F1, d{-80, 0, -80}},
{0x03F2, 0x03F2, d{7, 0, 7}},
+ {0x03F3, 0x03F3, d{-116, 0, -116}},
{0x03F4, 0x03F4, d{0, -60, 0}},
{0x03F5, 0x03F5, d{-96, 0, -96}},
{0x03F7, 0x03F8, d{UpperLower, UpperLower, UpperLower}},
@@ -5659,7 +6285,7 @@ var _CaseRanges = []CaseRange{
{0x04C0, 0x04C0, d{0, 15, 0}},
{0x04C1, 0x04CE, d{UpperLower, UpperLower, UpperLower}},
{0x04CF, 0x04CF, d{-15, 0, -15}},
- {0x04D0, 0x0527, d{UpperLower, UpperLower, UpperLower}},
+ {0x04D0, 0x052F, d{UpperLower, UpperLower, UpperLower}},
{0x0531, 0x0556, d{0, 48, 0}},
{0x0561, 0x0586, d{-48, 0, -48}},
{0x10A0, 0x10C5, d{0, 7264, 0}},
@@ -5757,7 +6383,7 @@ var _CaseRanges = []CaseRange{
{0x2D27, 0x2D27, d{-7264, 0, -7264}},
{0x2D2D, 0x2D2D, d{-7264, 0, -7264}},
{0xA640, 0xA66D, d{UpperLower, UpperLower, UpperLower}},
- {0xA680, 0xA697, d{UpperLower, UpperLower, UpperLower}},
+ {0xA680, 0xA69B, d{UpperLower, UpperLower, UpperLower}},
{0xA722, 0xA72F, d{UpperLower, UpperLower, UpperLower}},
{0xA732, 0xA76F, d{UpperLower, UpperLower, UpperLower}},
{0xA779, 0xA77C, d{UpperLower, UpperLower, UpperLower}},
@@ -5766,12 +6392,19 @@ var _CaseRanges = []CaseRange{
{0xA78B, 0xA78C, d{UpperLower, UpperLower, UpperLower}},
{0xA78D, 0xA78D, d{0, -42280, 0}},
{0xA790, 0xA793, d{UpperLower, UpperLower, UpperLower}},
- {0xA7A0, 0xA7A9, d{UpperLower, UpperLower, UpperLower}},
+ {0xA796, 0xA7A9, d{UpperLower, UpperLower, UpperLower}},
{0xA7AA, 0xA7AA, d{0, -42308, 0}},
+ {0xA7AB, 0xA7AB, d{0, -42319, 0}},
+ {0xA7AC, 0xA7AC, d{0, -42315, 0}},
+ {0xA7AD, 0xA7AD, d{0, -42305, 0}},
+ {0xA7B0, 0xA7B0, d{0, -42258, 0}},
+ {0xA7B1, 0xA7B1, d{0, -42282, 0}},
{0xFF21, 0xFF3A, d{0, 32, 0}},
{0xFF41, 0xFF5A, d{-32, 0, -32}},
{0x10400, 0x10427, d{0, 40, 0}},
{0x10428, 0x1044F, d{-40, 0, -40}},
+ {0x118A0, 0x118BF, d{0, 32, 0}},
+ {0x118C0, 0x118DF, d{-32, 0, -32}},
}
var properties = [MaxLatin1 + 1]uint8{
0x00: pC, // '\x00'
@@ -6181,8 +6814,8 @@ var foldLl = &RangeTable{
{0x0248, 0x024e, 2},
{0x0345, 0x0370, 43},
{0x0372, 0x0376, 4},
- {0x0386, 0x0388, 2},
- {0x0389, 0x038a, 1},
+ {0x037f, 0x0386, 7},
+ {0x0388, 0x038a, 1},
{0x038c, 0x038e, 2},
{0x038f, 0x0391, 2},
{0x0392, 0x03a1, 1},
@@ -6195,7 +6828,7 @@ var foldLl = &RangeTable{
{0x0460, 0x0480, 2},
{0x048a, 0x04c0, 2},
{0x04c1, 0x04cd, 2},
- {0x04d0, 0x0526, 2},
+ {0x04d0, 0x052e, 2},
{0x0531, 0x0556, 1},
{0x10a0, 0x10c5, 1},
{0x10c7, 0x10cd, 6},
@@ -6230,18 +6863,21 @@ var foldLl = &RangeTable{
{0x2ceb, 0x2ced, 2},
{0x2cf2, 0xa640, 31054},
{0xa642, 0xa66c, 2},
- {0xa680, 0xa696, 2},
+ {0xa680, 0xa69a, 2},
{0xa722, 0xa72e, 2},
{0xa732, 0xa76e, 2},
{0xa779, 0xa77d, 2},
{0xa77e, 0xa786, 2},
{0xa78b, 0xa78d, 2},
{0xa790, 0xa792, 2},
- {0xa7a0, 0xa7aa, 2},
+ {0xa796, 0xa7aa, 2},
+ {0xa7ab, 0xa7ad, 1},
+ {0xa7b0, 0xa7b1, 1},
{0xff21, 0xff3a, 1},
},
R32: []Range32{
{0x10400, 0x10427, 1},
+ {0x118a0, 0x118bf, 1},
},
LatinOffset: 3,
}
@@ -6297,30 +6933,31 @@ var foldLu = &RangeTable{
{0x0250, 0x0254, 1},
{0x0256, 0x0257, 1},
{0x0259, 0x025b, 2},
- {0x0260, 0x0263, 3},
- {0x0265, 0x0266, 1},
- {0x0268, 0x0269, 1},
- {0x026b, 0x026f, 4},
+ {0x025c, 0x0260, 4},
+ {0x0261, 0x0265, 2},
+ {0x0266, 0x0268, 2},
+ {0x0269, 0x026b, 2},
+ {0x026c, 0x026f, 3},
{0x0271, 0x0272, 1},
{0x0275, 0x027d, 8},
{0x0280, 0x0283, 3},
- {0x0288, 0x028c, 1},
- {0x0292, 0x0345, 179},
- {0x0371, 0x0373, 2},
- {0x0377, 0x037b, 4},
+ {0x0287, 0x028c, 1},
+ {0x0292, 0x029e, 12},
+ {0x0345, 0x0371, 44},
+ {0x0373, 0x037b, 4},
{0x037c, 0x037d, 1},
{0x03ac, 0x03af, 1},
{0x03b1, 0x03ce, 1},
{0x03d0, 0x03d1, 1},
{0x03d5, 0x03d7, 1},
{0x03d9, 0x03ef, 2},
- {0x03f0, 0x03f2, 1},
+ {0x03f0, 0x03f3, 1},
{0x03f5, 0x03fb, 3},
{0x0430, 0x045f, 1},
{0x0461, 0x0481, 2},
{0x048b, 0x04bf, 2},
{0x04c2, 0x04ce, 2},
- {0x04cf, 0x0527, 2},
+ {0x04cf, 0x052f, 2},
{0x0561, 0x0586, 1},
{0x1d79, 0x1d7d, 4},
{0x1e01, 0x1e95, 2},
@@ -6349,18 +6986,19 @@ var foldLu = &RangeTable{
{0x2d01, 0x2d25, 1},
{0x2d27, 0x2d2d, 6},
{0xa641, 0xa66d, 2},
- {0xa681, 0xa697, 2},
+ {0xa681, 0xa69b, 2},
{0xa723, 0xa72f, 2},
{0xa733, 0xa76f, 2},
{0xa77a, 0xa77c, 2},
{0xa77f, 0xa787, 2},
{0xa78c, 0xa791, 5},
- {0xa793, 0xa7a1, 14},
- {0xa7a3, 0xa7a9, 2},
+ {0xa793, 0xa797, 4},
+ {0xa799, 0xa7a9, 2},
{0xff41, 0xff5a, 1},
},
R32: []Range32{
{0x10428, 0x1044f, 1},
+ {0x118c0, 0x118df, 1},
},
LatinOffset: 4,
}
@@ -6385,7 +7023,7 @@ var foldMn = &RangeTable{
// If there is no entry for a script name, there are no such points.
var FoldScript = map[string]*RangeTable{}
-// Range entries: 3471 16-bit, 832 32-bit, 4303 total.
-// Range bytes: 20826 16-bit, 9984 32-bit, 30810 total.
+// Range entries: 3532 16-bit, 1204 32-bit, 4736 total.
+// Range bytes: 21192 16-bit, 14448 32-bit, 35640 total.
// Fold orbit bytes: 63 pairs, 252 bytes
diff --git a/src/pkg/unicode/utf16/export_test.go b/src/unicode/utf16/export_test.go
index 306247e48..306247e48 100644
--- a/src/pkg/unicode/utf16/export_test.go
+++ b/src/unicode/utf16/export_test.go
diff --git a/src/pkg/unicode/utf16/utf16.go b/src/unicode/utf16/utf16.go
index c0e47c535..c0e47c535 100644
--- a/src/pkg/unicode/utf16/utf16.go
+++ b/src/unicode/utf16/utf16.go
diff --git a/src/pkg/unicode/utf16/utf16_test.go b/src/unicode/utf16/utf16_test.go
index 3dca472bb..3dca472bb 100644
--- a/src/pkg/unicode/utf16/utf16_test.go
+++ b/src/unicode/utf16/utf16_test.go
diff --git a/src/pkg/unicode/utf8/example_test.go b/src/unicode/utf8/example_test.go
index 7b3e7ac74..7b3e7ac74 100644
--- a/src/pkg/unicode/utf8/example_test.go
+++ b/src/unicode/utf8/example_test.go
diff --git a/src/pkg/unicode/utf8/utf8.go b/src/unicode/utf8/utf8.go
index 0dc859a04..9ac37184d 100644
--- a/src/pkg/unicode/utf8/utf8.go
+++ b/src/unicode/utf8/utf8.go
@@ -211,8 +211,11 @@ func FullRuneInString(s string) bool {
return !short
}
-// DecodeRune unpacks the first UTF-8 encoding in p and returns the rune and its width in bytes.
-// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// 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.
+//
// 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.
@@ -221,8 +224,10 @@ func DecodeRune(p []byte) (r rune, size int) {
return
}
-// DecodeRuneInString is like DecodeRune but its input is a string.
-// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// 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.
+//
// 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.
@@ -231,8 +236,11 @@ func DecodeRuneInString(s string) (r rune, size int) {
return
}
-// DecodeLastRune unpacks the last UTF-8 encoding in p and returns the rune and its width in bytes.
-// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// 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.
+//
// 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.
@@ -268,8 +276,10 @@ func DecodeLastRune(p []byte) (r rune, size int) {
return r, size
}
-// DecodeLastRuneInString is like DecodeLastRune but its input is a string.
-// If the encoding is invalid, it returns (RuneError, 1), an impossible result for correct UTF-8.
+// 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.
+//
// 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.
@@ -372,7 +382,7 @@ func RuneCount(p []byte) int {
// RuneCountInString is like RuneCount but its input is a string.
func RuneCountInString(s string) (n int) {
- for _ = range s {
+ for range s {
n++
}
return
diff --git a/src/pkg/unicode/utf8/utf8_test.go b/src/unicode/utf8/utf8_test.go
index 758d7a0f8..758d7a0f8 100644
--- a/src/pkg/unicode/utf8/utf8_test.go
+++ b/src/unicode/utf8/utf8_test.go
diff --git a/src/pkg/unsafe/unsafe.go b/src/unsafe/unsafe.go
index 83b2e1405..79499b295 100644
--- a/src/pkg/unsafe/unsafe.go
+++ b/src/unsafe/unsafe.go
@@ -4,6 +4,9 @@
/*
Package unsafe contains operations that step around the type safety of Go programs.
+
+ Packages that import unsafe may be non-portable and are not protected by the
+ Go 1 compatibility guidelines.
*/
package unsafe
diff --git a/test/assign.go b/test/assign.go
index da0192f83..6611f8ce3 100644
--- a/test/assign.go
+++ b/test/assign.go
@@ -53,4 +53,16 @@ func main() {
_ = x
_ = y
}
+ {
+ var x = 1
+ {
+ x, x := 2, 3 // ERROR "x repeated on left side of :="
+ _ = x
+ }
+ _ = x
+ }
+ {
+ a, a := 1, 2 // ERROR "a repeated on left side of :="
+ _ = a
+ }
}
diff --git a/test/bench/garbage/parser.go b/test/bench/garbage/parser.go
index d85110b63..a685507c5 100644
--- a/test/bench/garbage/parser.go
+++ b/test/bench/garbage/parser.go
@@ -85,7 +85,7 @@ func main() {
var t0 time.Time
var numGC uint32
var pauseTotalNs uint64
- pkgroot := runtime.GOROOT() + "/src/pkg/"
+ pkgroot := runtime.GOROOT() + "/src/"
for pass := 0; pass < 2; pass++ {
// Once the heap is grown to full size, reset counters.
// This hides the start-up pauses, which are much smaller
diff --git a/test/bench/shootout/chameneosredux.go b/test/bench/shootout/chameneosredux.go
index 339579862..72ce7dd13 100644
--- a/test/bench/shootout/chameneosredux.go
+++ b/test/bench/shootout/chameneosredux.go
@@ -123,7 +123,7 @@ func pallmall(cols []int) {
fmt.Println(msg)
tot := 0
// wait for all results
- for _ = range cols {
+ for range cols {
result := <-ended
tot += result.met
fmt.Printf("%v%v\n", result.met, spell(result.same, true))
diff --git a/test/chan/perm.go b/test/chan/perm.go
index 7e152c5eb..919fa30fb 100644
--- a/test/chan/perm.go
+++ b/test/chan/perm.go
@@ -56,6 +56,9 @@ func main() {
for _ = range cs {// ERROR "receive"
}
+ for range cs {// ERROR "receive"
+ }
+
close(c)
close(cs)
close(cr) // ERROR "receive"
diff --git a/test/chan/select5.go b/test/chan/select5.go
index f72cfe4b4..1081cb296 100644
--- a/test/chan/select5.go
+++ b/test/chan/select5.go
@@ -27,16 +27,16 @@ func main() {
fmt.Fprintln(out, header)
a := new(arg)
- // Generate each kind of test as a separate function to avoid
+ // Generate each test as a separate function to avoid
// hitting the 6g optimizer with one enormous function.
// If we name all the functions init we don't have to
// maintain a list of which ones to run.
do := func(t *template.Template) {
- fmt.Fprintln(out, `func init() {`)
for ; next(); a.reset() {
+ fmt.Fprintln(out, `func init() {`)
run(t, a, out)
+ fmt.Fprintln(out, `}`)
}
- fmt.Fprintln(out, `}`)
}
do(recv)
diff --git a/test/escape2.go b/test/escape2.go
index 28251aa98..6a46ce86a 100644
--- a/test/escape2.go
+++ b/test/escape2.go
@@ -7,6 +7,8 @@
// Test, using compiler diagnostic flags, that the escape analysis is working.
// Compiles but does not run. Inlining is disabled.
+// escape2n.go contains all the same tests but compiles with -N.
+
package foo
import (
diff --git a/test/escape2n.go b/test/escape2n.go
new file mode 100644
index 000000000..002a78ea5
--- /dev/null
+++ b/test/escape2n.go
@@ -0,0 +1,1494 @@
+// errorcheck -0 -N -m -l
+
+// 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.
+
+// 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 foo
+
+import (
+ "fmt"
+ "unsafe"
+)
+
+var gxx *int
+
+func foo1(x int) { // ERROR "moved to heap: x"
+ gxx = &x // ERROR "&x escapes to heap"
+}
+
+func foo2(yy *int) { // ERROR "leaking param: yy"
+ gxx = yy
+}
+
+func foo3(x int) *int { // ERROR "moved to heap: x"
+ return &x // ERROR "&x escapes to heap"
+}
+
+type T *T
+
+func foo3b(t T) { // ERROR "leaking param: t"
+ *t = t
+}
+
+// xx isn't going anywhere, so use of yy is ok
+func foo4(xx, yy *int) { // ERROR "xx does not escape" "yy does not escape"
+ xx = yy
+}
+
+// xx isn't going anywhere, so taking address of yy is ok
+func foo5(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape"
+ xx = &yy // ERROR "&yy does not escape"
+}
+
+func foo6(xx **int, yy *int) { // ERROR "xx does not escape" "leaking param: yy"
+ *xx = yy
+}
+
+func foo7(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape"
+ **xx = *yy
+}
+
+func foo8(xx, yy *int) int { // ERROR "xx does not escape" "yy does not escape"
+ xx = yy
+ return *xx
+}
+
+func foo9(xx, yy *int) *int { // ERROR "leaking param: xx" "leaking param: yy"
+ xx = yy
+ return xx
+}
+
+func foo10(xx, yy *int) { // ERROR "xx does not escape" "yy does not escape"
+ *xx = *yy
+}
+
+func foo11() int {
+ x, y := 0, 42
+ xx := &x // ERROR "&x does not escape"
+ yy := &y // ERROR "&y does not escape"
+ *xx = *yy
+ return x
+}
+
+var xxx **int
+
+func foo12(yyy **int) { // ERROR "leaking param: yyy"
+ xxx = yyy
+}
+
+// Must treat yyy as leaking because *yyy leaks, and the escape analysis
+// summaries in exported metadata do not distinguish these two cases.
+func foo13(yyy **int) { // ERROR "leaking param: yyy"
+ *xxx = *yyy
+}
+
+func foo14(yyy **int) { // ERROR "yyy does not escape"
+ **xxx = **yyy
+}
+
+func foo15(yy *int) { // ERROR "moved to heap: yy"
+ xxx = &yy // ERROR "&yy escapes to heap"
+}
+
+func foo16(yy *int) { // ERROR "leaking param: yy"
+ *xxx = yy
+}
+
+func foo17(yy *int) { // ERROR "yy does not escape"
+ **xxx = *yy
+}
+
+func foo18(y int) { // ERROR "moved to heap: "y"
+ *xxx = &y // ERROR "&y escapes to heap"
+}
+
+func foo19(y int) {
+ **xxx = y
+}
+
+type Bar struct {
+ i int
+ ii *int
+}
+
+func NewBar() *Bar {
+ return &Bar{42, nil} // ERROR "&Bar literal escapes to heap"
+}
+
+func NewBarp(x *int) *Bar { // ERROR "leaking param: x"
+ return &Bar{42, x} // ERROR "&Bar literal escapes to heap"
+}
+
+func NewBarp2(x *int) *Bar { // ERROR "x does not escape"
+ return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap"
+}
+
+func (b *Bar) NoLeak() int { // ERROR "b does not escape"
+ return *(b.ii)
+}
+
+func (b *Bar) Leak() *int { // ERROR "leaking param: b"
+ return &b.i // ERROR "&b.i escapes to heap"
+}
+
+func (b *Bar) AlsoNoLeak() *int { // ERROR "leaking param b content to result ~r0"
+ return b.ii
+}
+
+func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b"
+ return b.ii
+}
+
+func (b Bar) LeaksToo() *int { // ERROR "leaking param: b"
+ v := 0 // ERROR "moved to heap: v"
+ b.ii = &v // ERROR "&v escapes"
+ return b.ii
+}
+
+func (b *Bar) LeaksABit() *int { // ERROR "leaking param b content to result ~r0"
+ v := 0 // ERROR "moved to heap: v"
+ b.ii = &v // ERROR "&v escapes"
+ return b.ii
+}
+
+func (b Bar) StillNoLeak() int { // ERROR "b does not escape"
+ v := 0
+ b.ii = &v // ERROR "&v does not escape"
+ return b.i
+}
+
+func goLeak(b *Bar) { // ERROR "leaking param: b"
+ go b.NoLeak()
+}
+
+type Bar2 struct {
+ i [12]int
+ ii []int
+}
+
+func NewBar2() *Bar2 {
+ return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap"
+}
+
+func (b *Bar2) NoLeak() int { // ERROR "b does not escape"
+ return b.i[0]
+}
+
+func (b *Bar2) Leak() []int { // ERROR "leaking param: b"
+ return b.i[:] // ERROR "b.i escapes to heap"
+}
+
+func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param b content to result ~r0"
+ return b.ii[0:1]
+}
+
+func (b Bar2) AgainNoLeak() [12]int { // ERROR "b does not escape"
+ return b.i
+}
+
+func (b *Bar2) LeakSelf() { // ERROR "leaking param: b"
+ b.ii = b.i[0:4] // ERROR "b.i escapes to heap"
+}
+
+func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b"
+ var buf []int
+ buf = b.i[0:] // ERROR "b.i escapes to heap"
+ b.ii = buf
+}
+
+func foo21() func() int {
+ x := 42 // ERROR "moved to heap: x"
+ return func() int { // ERROR "func literal escapes to heap"
+ return x // ERROR "&x escapes to heap"
+ }
+}
+
+func foo22() int {
+ x := 42
+ return func() int { // ERROR "func literal does not escape"
+ return x
+ }()
+}
+
+func foo23(x int) func() int { // ERROR "moved to heap: x"
+ return func() int { // ERROR "func literal escapes to heap"
+ return x // ERROR "&x escapes to heap"
+ }
+}
+
+func foo23a(x int) func() int { // ERROR "moved to heap: x"
+ f := func() int { // ERROR "func literal escapes to heap"
+ return x // ERROR "&x escapes to heap"
+ }
+ return f
+}
+
+func foo23b(x int) *(func() int) { // ERROR "moved to heap: x"
+ f := func() int { return x } // ERROR "moved to heap: f" "func literal escapes to heap" "&x escapes to heap"
+ return &f // ERROR "&f escapes to heap"
+}
+
+func foo24(x int) int {
+ return func() int { // ERROR "func literal does not escape"
+ return x
+ }()
+}
+
+var x *int
+
+func fooleak(xx *int) int { // ERROR "leaking param: xx"
+ x = xx
+ return *x
+}
+
+func foonoleak(xx *int) int { // ERROR "xx does not escape"
+ return *x + *xx
+}
+
+func foo31(x int) int { // ERROR "moved to heap: x"
+ return fooleak(&x) // ERROR "&x escapes to heap"
+}
+
+func foo32(x int) int {
+ return foonoleak(&x) // ERROR "&x does not escape"
+}
+
+type Foo struct {
+ xx *int
+ x int
+}
+
+var F Foo
+var pf *Foo
+
+func (f *Foo) fooleak() { // ERROR "leaking param: f"
+ pf = f
+}
+
+func (f *Foo) foonoleak() { // ERROR "f does not escape"
+ F.x = f.x
+}
+
+func (f *Foo) Leak() { // ERROR "leaking param: f"
+ f.fooleak()
+}
+
+func (f *Foo) NoLeak() { // ERROR "f does not escape"
+ f.foonoleak()
+}
+
+func foo41(x int) { // ERROR "moved to heap: x"
+ F.xx = &x // ERROR "&x escapes to heap"
+}
+
+func (f *Foo) foo42(x int) { // ERROR "f does not escape" "moved to heap: x"
+ f.xx = &x // ERROR "&x escapes to heap"
+}
+
+func foo43(f *Foo, x int) { // ERROR "f does not escape" "moved to heap: x"
+ f.xx = &x // ERROR "&x escapes to heap"
+}
+
+func foo44(yy *int) { // ERROR "leaking param: yy"
+ F.xx = yy
+}
+
+func (f *Foo) foo45() { // ERROR "f does not escape"
+ F.x = f.x
+}
+
+// See foo13 above for explanation of why f leaks.
+func (f *Foo) foo46() { // ERROR "leaking param: f"
+ F.xx = f.xx
+}
+
+func (f *Foo) foo47() { // ERROR "leaking param: f"
+ f.xx = &f.x // ERROR "&f.x escapes to heap"
+}
+
+var ptrSlice []*int
+
+func foo50(i *int) { // ERROR "leaking param: i"
+ ptrSlice[0] = i
+}
+
+var ptrMap map[*int]*int
+
+func foo51(i *int) { // ERROR "leaking param: i"
+ ptrMap[i] = i
+}
+
+func indaddr1(x int) *int { // ERROR "moved to heap: x"
+ return &x // ERROR "&x escapes to heap"
+}
+
+func indaddr2(x *int) *int { // ERROR "leaking param: x"
+ return *&x // ERROR "&x does not escape"
+}
+
+func indaddr3(x *int32) *int { // ERROR "leaking param: x"
+ return *(**int)(unsafe.Pointer(&x)) // ERROR "&x does not escape"
+}
+
+// From package math:
+
+func Float32bits(f float32) uint32 {
+ return *(*uint32)(unsafe.Pointer(&f)) // ERROR "&f does not escape"
+}
+
+func Float32frombits(b uint32) float32 {
+ return *(*float32)(unsafe.Pointer(&b)) // ERROR "&b does not escape"
+}
+
+func Float64bits(f float64) uint64 {
+ return *(*uint64)(unsafe.Pointer(&f)) // ERROR "&f does not escape"
+}
+
+func Float64frombits(b uint64) float64 {
+ return *(*float64)(unsafe.Pointer(&b)) // ERROR "&b does not escape"
+}
+
+// contrast with
+func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f"
+ return (*uint64)(unsafe.Pointer(&f)) // ERROR "&f escapes to heap"
+}
+
+func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f"
+ return (*uint64)(unsafe.Pointer(f))
+}
+
+func typesw(i interface{}) *int { // ERROR "leaking param: i"
+ switch val := i.(type) {
+ case *int:
+ return val
+ case *int8:
+ v := int(*val) // ERROR "moved to heap: v"
+ return &v // ERROR "&v escapes to heap"
+ }
+ return nil
+}
+
+func exprsw(i *int) *int { // ERROR "leaking param: i"
+ switch j := i; *j + 110 {
+ case 12:
+ return j
+ case 42:
+ return nil
+ }
+ return nil
+
+}
+
+// assigning to an array element is like assigning to the array
+func foo60(i *int) *int { // ERROR "leaking param: i"
+ var a [12]*int
+ a[0] = i
+ return a[1]
+}
+
+func foo60a(i *int) *int { // ERROR "i does not escape"
+ var a [12]*int
+ a[0] = i
+ return nil
+}
+
+// assigning to a struct field is like assigning to the struct
+func foo61(i *int) *int { // ERROR "leaking param: i"
+ type S struct {
+ a, b *int
+ }
+ var s S
+ s.a = i
+ return s.b
+}
+
+func foo61a(i *int) *int { // ERROR "i does not escape"
+ type S struct {
+ a, b *int
+ }
+ var s S
+ s.a = i
+ return nil
+}
+
+// assigning to a struct field is like assigning to the struct but
+// here this subtlety is lost, since s.a counts as an assignment to a
+// track-losing dereference.
+func foo62(i *int) *int { // ERROR "leaking param: i"
+ type S struct {
+ a, b *int
+ }
+ s := new(S) // ERROR "new[(]S[)] does not escape"
+ s.a = i
+ return nil // s.b
+}
+
+type M interface {
+ M()
+}
+
+func foo63(m M) { // ERROR "m does not escape"
+}
+
+func foo64(m M) { // ERROR "leaking param: m"
+ m.M()
+}
+
+func foo64b(m M) { // ERROR "leaking param: m"
+ defer m.M()
+}
+
+type MV int
+
+func (MV) M() {}
+
+func foo65() {
+ var mv MV
+ foo63(&mv) // ERROR "&mv does not escape"
+}
+
+func foo66() {
+ var mv MV // ERROR "moved to heap: mv"
+ foo64(&mv) // ERROR "&mv escapes to heap"
+}
+
+func foo67() {
+ var mv MV
+ foo63(mv)
+}
+
+func foo68() {
+ var mv MV
+ foo64(mv) // escapes but it's an int so irrelevant
+}
+
+func foo69(m M) { // ERROR "leaking param: m"
+ foo64(m)
+}
+
+func foo70(mv1 *MV, m M) { // ERROR "leaking param: mv1" "leaking param: m"
+ m = mv1
+ foo64(m)
+}
+
+func foo71(x *int) []*int { // ERROR "leaking param: x"
+ var y []*int
+ y = append(y, x)
+ return y
+}
+
+func foo71a(x int) []*int { // ERROR "moved to heap: x"
+ var y []*int
+ y = append(y, &x) // ERROR "&x escapes to heap"
+ return y
+}
+
+func foo72() {
+ var x int
+ var y [1]*int
+ y[0] = &x // ERROR "&x does not escape"
+}
+
+func foo72aa() [10]*int {
+ var x int // ERROR "moved to heap: x"
+ var y [10]*int
+ y[0] = &x // ERROR "&x escapes to heap"
+ return y
+}
+
+func foo72a() {
+ var y [10]*int
+ for i := 0; i < 10; i++ {
+ // escapes its scope
+ x := i // ERROR "moved to heap: x"
+ y[i] = &x // ERROR "&x escapes to heap"
+ }
+ return
+}
+
+func foo72b() [10]*int {
+ var y [10]*int
+ for i := 0; i < 10; i++ {
+ x := i // ERROR "moved to heap: x"
+ y[i] = &x // ERROR "&x escapes to heap"
+ }
+ return y
+}
+
+// issue 2145
+func foo73() {
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ for _, v := range s {
+ vv := v // ERROR "moved to heap: vv"
+ // actually just escapes its scope
+ defer func() { // ERROR "func literal escapes to heap"
+ println(vv) // ERROR "&vv escapes to heap"
+ }()
+ }
+}
+
+func foo74() {
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ for _, v := range s {
+ vv := v // ERROR "moved to heap: vv"
+ // actually just escapes its scope
+ fn := func() { // ERROR "func literal escapes to heap"
+ println(vv) // ERROR "&vv escapes to heap"
+ }
+ defer fn()
+ }
+}
+
+// issue 3975
+func foo74b() {
+ var array [3]func()
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ for i, v := range s {
+ vv := v // ERROR "moved to heap: vv"
+ // actually just escapes its scope
+ array[i] = func() { // ERROR "func literal escapes to heap"
+ println(vv) // ERROR "&vv escapes to heap"
+ }
+ }
+}
+
+func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: y"
+ return y
+}
+
+func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not escape" "leaking param: x"
+ return &x[0] // ERROR "&x.0. escapes to heap"
+}
+
+func foo75(z *int) { // ERROR "z does not escape"
+ myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+}
+
+func foo75a(z *int) { // ERROR "z does not escape"
+ myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+}
+
+func foo75esc(z *int) { // ERROR "leaking param: z"
+ gxx = myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+}
+
+func foo75aesc(z *int) { // ERROR "z does not escape"
+ var ppi **interface{} // assignments to pointer dereferences lose track
+ *ppi = myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+}
+
+func foo76(z *int) { // ERROR "leaking param: z"
+ myprint(nil, z) // ERROR "[.][.][.] argument does not escape"
+}
+
+func foo76a(z *int) { // ERROR "leaking param: z"
+ myprint1(nil, z) // ERROR "[.][.][.] argument does not escape"
+}
+
+func foo76b() {
+ myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+}
+
+func foo76c() {
+ myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+}
+
+func foo76d() {
+ defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+}
+
+func foo76e() {
+ defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+}
+
+func foo76f() {
+ for {
+ // TODO: This one really only escapes its scope, but we don't distinguish yet.
+ defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+ }
+}
+
+func foo76g() {
+ for {
+ defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+ }
+}
+
+func foo77(z []interface{}) { // ERROR "z does not escape"
+ myprint(nil, z...) // z does not escape
+}
+
+func foo77a(z []interface{}) { // ERROR "z does not escape"
+ myprint1(nil, z...)
+}
+
+func foo77b(z []interface{}) { // ERROR "leaking param: z"
+ var ppi **interface{}
+ *ppi = myprint1(nil, z...)
+}
+
+func foo78(z int) *int { // ERROR "moved to heap: z"
+ return &z // ERROR "&z escapes to heap"
+}
+
+func foo78a(z int) *int { // ERROR "moved to heap: z"
+ y := &z // ERROR "&z escapes to heap"
+ x := &y // ERROR "&y does not escape"
+ return *x // really return y
+}
+
+func foo79() *int {
+ return new(int) // ERROR "new[(]int[)] escapes to heap"
+}
+
+func foo80() *int {
+ var z *int
+ for {
+ // Really just escapes its scope but we don't distinguish
+ z = new(int) // ERROR "new[(]int[)] escapes to heap"
+ }
+ _ = z
+ return nil
+}
+
+func foo81() *int {
+ for {
+ z := new(int) // ERROR "new[(]int[)] does not escape"
+ _ = z
+ }
+ return nil
+}
+
+func tee(p *int) (x, y *int) { return p, p } // ERROR "leaking param"
+
+func noop(x, y *int) {} // ERROR "does not escape"
+
+func foo82() {
+ var x, y, z int // ERROR "moved to heap"
+ go noop(tee(&z)) // ERROR "&z escapes to heap"
+ go noop(&x, &y) // ERROR "escapes to heap"
+ for {
+ var u, v, w int // ERROR "moved to heap"
+ defer noop(tee(&u)) // ERROR "&u escapes to heap"
+ defer noop(&v, &w) // ERROR "escapes to heap"
+ }
+}
+
+type Fooer interface {
+ Foo()
+}
+
+type LimitedFooer struct {
+ Fooer
+ N int64
+}
+
+func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r"
+ return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap"
+}
+
+func foo90(x *int) map[*int]*int { // ERROR "leaking param: x"
+ return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap"
+}
+
+func foo91(x *int) map[*int]*int { // ERROR "leaking param: x"
+ return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap"
+}
+
+func foo92(x *int) [2]*int { // ERROR "leaking param: x"
+ return [2]*int{x, nil}
+}
+
+// does not leak c
+func foo93(c chan *int) *int { // ERROR "c does not escape"
+ for v := range c {
+ return v
+ }
+ return nil
+}
+
+// does not leak m
+func foo94(m map[*int]*int, b bool) *int { // ERROR "m does not escape"
+ for k, v := range m {
+ if b {
+ return k
+ }
+ return v
+ }
+ return nil
+}
+
+// does leak x
+func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape" "leaking param: x"
+ m[x] = x
+}
+
+// does not leak m
+func foo96(m []*int) *int { // ERROR "m does not escape"
+ return m[0]
+}
+
+// does leak m
+func foo97(m [1]*int) *int { // ERROR "leaking param: m"
+ return m[0]
+}
+
+// does not leak m
+func foo98(m map[int]*int) *int { // ERROR "m does not escape"
+ return m[0]
+}
+
+// does leak m
+func foo99(m *[1]*int) []*int { // ERROR "leaking param: m"
+ return m[:]
+}
+
+// does not leak m
+func foo100(m []*int) *int { // ERROR "m does not escape"
+ for _, v := range m {
+ return v
+ }
+ return nil
+}
+
+// does leak m
+func foo101(m [1]*int) *int { // ERROR "leaking param: m"
+ for _, v := range m {
+ return v
+ }
+ return nil
+}
+
+// does not leak m
+func foo101a(m [1]*int) *int { // ERROR "m does not escape"
+ for i := range m { // ERROR "moved to heap: i"
+ return &i // ERROR "&i escapes to heap"
+ }
+ return nil
+}
+
+// does leak x
+func foo102(m []*int, x *int) { // ERROR "m does not escape" "leaking param: x"
+ m[0] = x
+}
+
+// does not leak x
+func foo103(m [1]*int, x *int) { // ERROR "m does not escape" "x does not escape"
+ m[0] = x
+}
+
+var y []*int
+
+// does not leak x
+func foo104(x []*int) { // ERROR "x does not escape"
+ copy(y, x)
+}
+
+// does not leak x
+func foo105(x []*int) { // ERROR "x does not escape"
+ _ = append(y, x...)
+}
+
+// does leak x
+func foo106(x *int) { // ERROR "leaking param: x"
+ _ = append(y, x)
+}
+
+func foo107(x *int) map[*int]*int { // ERROR "leaking param: x"
+ return map[*int]*int{x: nil} // ERROR "map.* literal escapes to heap"
+}
+
+func foo108(x *int) map[*int]*int { // ERROR "leaking param: x"
+ return map[*int]*int{nil: x} // ERROR "map.* literal escapes to heap"
+}
+
+func foo109(x *int) *int { // ERROR "leaking param: x"
+ m := map[*int]*int{x: nil} // ERROR "map.* literal does not escape"
+ for k, _ := range m {
+ return k
+ }
+ return nil
+}
+
+func foo110(x *int) *int { // ERROR "leaking param: x"
+ m := map[*int]*int{nil: x} // ERROR "map.* literal does not escape"
+ return m[nil]
+}
+
+func foo111(x *int) *int { // ERROR "leaking param: x"
+ m := []*int{x} // ERROR "\[\]\*int literal does not escape"
+ return m[0]
+}
+
+func foo112(x *int) *int { // ERROR "leaking param: x"
+ m := [1]*int{x}
+ return m[0]
+}
+
+func foo113(x *int) *int { // ERROR "leaking param: x"
+ m := Bar{ii: x}
+ return m.ii
+}
+
+func foo114(x *int) *int { // ERROR "leaking param: x"
+ m := &Bar{ii: x} // ERROR "&Bar literal does not escape"
+ return m.ii
+}
+
+func foo115(x *int) *int { // ERROR "leaking param: x"
+ return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1))
+}
+
+func foo116(b bool) *int {
+ if b {
+ x := 1 // ERROR "moved to heap: x"
+ return &x // ERROR "&x escapes to heap"
+ } else {
+ y := 1 // ERROR "moved to heap: y"
+ return &y // ERROR "&y escapes to heap"
+ }
+ return nil
+}
+
+func foo117(unknown func(interface{})) { // ERROR "unknown does not escape"
+ x := 1 // ERROR "moved to heap: x"
+ unknown(&x) // ERROR "&x escapes to heap"
+}
+
+func foo118(unknown func(*int)) { // ERROR "unknown does not escape"
+ x := 1 // ERROR "moved to heap: x"
+ unknown(&x) // ERROR "&x escapes to heap"
+}
+
+func external(*int)
+
+func foo119(x *int) { // ERROR "leaking param: x"
+ external(x)
+}
+
+func foo120() {
+ // formerly exponential time analysis
+L1:
+L2:
+L3:
+L4:
+L5:
+L6:
+L7:
+L8:
+L9:
+L10:
+L11:
+L12:
+L13:
+L14:
+L15:
+L16:
+L17:
+L18:
+L19:
+L20:
+L21:
+L22:
+L23:
+L24:
+L25:
+L26:
+L27:
+L28:
+L29:
+L30:
+L31:
+L32:
+L33:
+L34:
+L35:
+L36:
+L37:
+L38:
+L39:
+L40:
+L41:
+L42:
+L43:
+L44:
+L45:
+L46:
+L47:
+L48:
+L49:
+L50:
+L51:
+L52:
+L53:
+L54:
+L55:
+L56:
+L57:
+L58:
+L59:
+L60:
+L61:
+L62:
+L63:
+L64:
+L65:
+L66:
+L67:
+L68:
+L69:
+L70:
+L71:
+L72:
+L73:
+L74:
+L75:
+L76:
+L77:
+L78:
+L79:
+L80:
+L81:
+L82:
+L83:
+L84:
+L85:
+L86:
+L87:
+L88:
+L89:
+L90:
+L91:
+L92:
+L93:
+L94:
+L95:
+L96:
+L97:
+L98:
+L99:
+L100:
+ // use the labels to silence compiler errors
+ goto L1
+ goto L2
+ goto L3
+ goto L4
+ goto L5
+ goto L6
+ goto L7
+ goto L8
+ goto L9
+ goto L10
+ goto L11
+ goto L12
+ goto L13
+ goto L14
+ goto L15
+ goto L16
+ goto L17
+ goto L18
+ goto L19
+ goto L20
+ goto L21
+ goto L22
+ goto L23
+ goto L24
+ goto L25
+ goto L26
+ goto L27
+ goto L28
+ goto L29
+ goto L30
+ goto L31
+ goto L32
+ goto L33
+ goto L34
+ goto L35
+ goto L36
+ goto L37
+ goto L38
+ goto L39
+ goto L40
+ goto L41
+ goto L42
+ goto L43
+ goto L44
+ goto L45
+ goto L46
+ goto L47
+ goto L48
+ goto L49
+ goto L50
+ goto L51
+ goto L52
+ goto L53
+ goto L54
+ goto L55
+ goto L56
+ goto L57
+ goto L58
+ goto L59
+ goto L60
+ goto L61
+ goto L62
+ goto L63
+ goto L64
+ goto L65
+ goto L66
+ goto L67
+ goto L68
+ goto L69
+ goto L70
+ goto L71
+ goto L72
+ goto L73
+ goto L74
+ goto L75
+ goto L76
+ goto L77
+ goto L78
+ goto L79
+ goto L80
+ goto L81
+ goto L82
+ goto L83
+ goto L84
+ goto L85
+ goto L86
+ goto L87
+ goto L88
+ goto L89
+ goto L90
+ goto L91
+ goto L92
+ goto L93
+ goto L94
+ goto L95
+ goto L96
+ goto L97
+ goto L98
+ goto L99
+ goto L100
+}
+
+func foo121() {
+ for i := 0; i < 10; i++ {
+ defer myprint(nil, i) // ERROR "[.][.][.] argument escapes to heap"
+ go myprint(nil, i) // ERROR "[.][.][.] argument escapes to heap"
+ }
+}
+
+// same as foo121 but check across import
+func foo121b() {
+ for i := 0; i < 10; i++ {
+ defer fmt.Printf("%d", i) // ERROR "[.][.][.] argument escapes to heap"
+ go fmt.Printf("%d", i) // ERROR "[.][.][.] argument escapes to heap"
+ }
+}
+
+// a harmless forward jump
+func foo122() {
+ var i *int
+
+ goto L1
+L1:
+ i = new(int) // ERROR "new.int. does not escape"
+ _ = i
+}
+
+// a backward jump, increases loopdepth
+func foo123() {
+ var i *int
+
+L1:
+ i = new(int) // ERROR "new.int. escapes to heap"
+
+ goto L1
+ _ = i
+}
+
+func foo124(x **int) { // ERROR "x does not escape"
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes"
+ func() { // ERROR "func literal does not escape"
+ *x = p // ERROR "leaking closure reference p"
+ }()
+}
+
+func foo125(ch chan *int) { // ERROR "does not escape"
+ var i int // ERROR "moved to heap"
+ p := &i // ERROR "&i escapes to heap"
+ func() { // ERROR "func literal does not escape"
+ ch <- p // ERROR "leaking closure reference p"
+ }()
+}
+
+func foo126() {
+ var px *int // loopdepth 0
+ for {
+ // loopdepth 1
+ var i int // ERROR "moved to heap"
+ func() { // ERROR "func literal does not escape"
+ px = &i // ERROR "&i escapes"
+ }()
+ }
+ _ = px
+}
+
+var px *int
+
+func foo127() {
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap"
+ q := p
+ px = q
+}
+
+func foo128() {
+ var i int
+ p := &i // ERROR "&i does not escape"
+ q := p
+ _ = q
+}
+
+func foo129() {
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap"
+ func() { // ERROR "func literal does not escape"
+ q := p // ERROR "leaking closure reference p"
+ func() { // ERROR "func literal does not escape"
+ r := q // ERROR "leaking closure reference q"
+ px = r
+ }()
+ }()
+}
+
+func foo130() {
+ for {
+ var i int // ERROR "moved to heap"
+ func() { // ERROR "func literal does not escape"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
+ }()
+ }
+}
+
+func foo131() {
+ var i int // ERROR "moved to heap"
+ func() { // ERROR "func literal does not escape"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
+ }()
+}
+
+func foo132() {
+ var i int // ERROR "moved to heap"
+ go func() { // ERROR "func literal escapes to heap"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
+ }()
+}
+
+func foo133() {
+ var i int // ERROR "moved to heap"
+ defer func() { // ERROR "func literal does not escape"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
+ }()
+}
+
+func foo134() {
+ var i int
+ p := &i // ERROR "&i does not escape"
+ func() { // ERROR "func literal does not escape"
+ q := p
+ func() { // ERROR "func literal does not escape"
+ r := q
+ _ = r
+ }()
+ }()
+}
+
+func foo135() {
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap" "moved to heap: p"
+ go func() { // ERROR "func literal escapes to heap"
+ q := p // ERROR "&p escapes to heap"
+ func() { // ERROR "func literal does not escape"
+ r := q
+ _ = r
+ }()
+ }()
+}
+
+func foo136() {
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap" "moved to heap: p"
+ go func() { // ERROR "func literal escapes to heap"
+ q := p // ERROR "&p escapes to heap" "leaking closure reference p"
+ func() { // ERROR "func literal does not escape"
+ r := q // ERROR "leaking closure reference q"
+ px = r
+ }()
+ }()
+}
+
+func foo137() {
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap"
+ func() { // ERROR "func literal does not escape"
+ q := p // ERROR "leaking closure reference p" "moved to heap: q"
+ go func() { // ERROR "func literal escapes to heap"
+ r := q // ERROR "&q escapes to heap"
+ _ = r
+ }()
+ }()
+}
+
+func foo138() *byte {
+ type T struct {
+ x [1]byte
+ }
+ t := new(T) // ERROR "new.T. escapes to heap"
+ return &t.x[0] // ERROR "&t.x.0. escapes to heap"
+}
+
+func foo139() *byte {
+ type T struct {
+ x struct {
+ y byte
+ }
+ }
+ t := new(T) // ERROR "new.T. escapes to heap"
+ return &t.x.y // ERROR "&t.x.y escapes to heap"
+}
+
+// issue 4751
+func foo140() interface{} {
+ type T struct {
+ X string
+ }
+ type U struct {
+ X string
+ T *T
+ }
+ t := &T{} // ERROR "&T literal escapes to heap"
+ return U{
+ X: t.X,
+ T: t,
+ }
+}
+
+//go:noescape
+
+func F1([]byte)
+
+func F2([]byte)
+
+//go:noescape
+
+func F3(x []byte) // ERROR "F3 x does not escape"
+
+func F4(x []byte)
+
+func G() {
+ var buf1 [10]byte
+ F1(buf1[:]) // ERROR "buf1 does not escape"
+
+ var buf2 [10]byte // ERROR "moved to heap: buf2"
+ F2(buf2[:]) // ERROR "buf2 escapes to heap"
+
+ var buf3 [10]byte
+ F3(buf3[:]) // ERROR "buf3 does not escape"
+
+ var buf4 [10]byte // ERROR "moved to heap: buf4"
+ F4(buf4[:]) // ERROR "buf4 escapes to heap"
+}
+
+type Tm struct {
+ x int
+}
+
+func (t *Tm) M() { // ERROR "t does not escape"
+}
+
+func foo141() {
+ var f func()
+
+ t := new(Tm) // ERROR "escapes to heap"
+ f = t.M // ERROR "t.M does not escape"
+ _ = f
+}
+
+var gf func()
+
+func foo142() {
+ t := new(Tm) // ERROR "escapes to heap"
+ gf = t.M // ERROR "t.M escapes to heap"
+}
+
+// issue 3888.
+func foo143() {
+ for i := 0; i < 1000; i++ {
+ func() { // ERROR "func literal does not escape"
+ for i := 0; i < 1; i++ {
+ var t Tm
+ t.M() // ERROR "t does not escape"
+ }
+ }()
+ }
+}
+
+// issue 5773
+// Check that annotations take effect regardless of whether they
+// are before or after the use in the source code.
+
+//go:noescape
+
+func foo144a(*int)
+
+func foo144() {
+ var x int
+ foo144a(&x) // ERROR "&x does not escape"
+ var y int
+ foo144b(&y) // ERROR "&y does not escape"
+}
+
+//go:noescape
+
+func foo144b(*int)
+
+// issue 7313: for loop init should not be treated as "in loop"
+
+type List struct {
+ Next *List
+}
+
+func foo145(l List) { // ERROR "l does not escape"
+ var p *List
+ for p = &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape"
+ }
+}
+
+func foo146(l List) { // ERROR "l does not escape"
+ var p *List
+ p = &l // ERROR "&l does not escape"
+ for ; p.Next != nil; p = p.Next {
+ }
+}
+
+func foo147(l List) { // ERROR "l does not escape"
+ var p *List
+ p = &l // ERROR "&l does not escape"
+ for p.Next != nil {
+ p = p.Next
+ }
+}
+
+func foo148(l List) { // ERROR " l does not escape"
+ for p := &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape"
+ }
+}
+
+// related: address of variable should have depth of variable, not of loop
+
+func foo149(l List) { // ERROR " l does not escape"
+ var p *List
+ for {
+ for p = &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape"
+ }
+ }
+}
+
+// issue 7934: missed ... if element type had no pointers
+
+var save150 []byte
+
+func foo150(x ...byte) { // ERROR "leaking param: x"
+ save150 = x
+}
+
+func bar150() {
+ foo150(1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+}
+
+// issue 7931: bad handling of slice of array
+
+var save151 *int
+
+func foo151(x *int) { // ERROR "leaking param: x"
+ save151 = x
+}
+
+func bar151() {
+ var a [64]int // ERROR "moved to heap: a"
+ a[4] = 101
+ foo151(&(&a)[4:8][0]) // ERROR "&\(&a\)\[4:8\]\[0\] escapes to heap" "&a escapes to heap"
+}
+
+func bar151b() {
+ var a [10]int // ERROR "moved to heap: a"
+ b := a[:] // ERROR "a escapes to heap"
+ foo151(&b[4:8][0]) // ERROR "&b\[4:8\]\[0\] escapes to heap"
+}
+
+func bar151c() {
+ var a [64]int // ERROR "moved to heap: a"
+ a[4] = 101
+ foo151(&(&a)[4:8:8][0]) // ERROR "&\(&a\)\[4:8:8\]\[0\] escapes to heap" "&a escapes to heap"
+}
+
+func bar151d() {
+ var a [10]int // ERROR "moved to heap: a"
+ b := a[:] // ERROR "a escapes to heap"
+ foo151(&b[4:8:8][0]) // ERROR "&b\[4:8:8\]\[0\] escapes to heap"
+}
+
+// issue 8120
+
+type U struct {
+ s *string
+}
+
+func (u *U) String() *string { // ERROR "leaking param u content to result ~r0"
+ return u.s
+}
+
+type V struct {
+ s *string
+}
+
+func NewV(u U) *V { // ERROR "leaking param: u"
+ return &V{u.String()} // ERROR "&V literal escapes to heap" "u does not escape"
+}
+
+func foo152() {
+ a := "a" // ERROR "moved to heap: a"
+ u := U{&a} // ERROR "&a escapes to heap"
+ v := NewV(u)
+ println(v)
+}
+
+// issue 8176 - &x in type switch body not marked as escaping
+
+func foo153(v interface{}) *int { // ERROR "leaking param: v"
+ switch x := v.(type) {
+ case int: // ERROR "moved to heap: x"
+ return &x // ERROR "&x escapes to heap"
+ }
+ panic(0)
+}
+
+// issue 8185 - &result escaping into result
+
+func f() (x int, y *int) { // ERROR "moved to heap: x"
+ y = &x // ERROR "&x escapes to heap"
+ return
+}
+
+func g() (x interface{}) { // ERROR "moved to heap: x"
+ x = &x // ERROR "&x escapes to heap"
+ return
+}
diff --git a/test/fixedbugs/bug173.go b/test/fixedbugs/bug173.go
index 6479bb253..3515c649b 100644
--- a/test/fixedbugs/bug173.go
+++ b/test/fixedbugs/bug173.go
@@ -18,4 +18,6 @@ func main() {
}
for _ = range t {
}
+ for range t {
+ }
}
diff --git a/test/fixedbugs/bug255.go b/test/fixedbugs/bug255.go
index acf4f2391..65ed1b8f6 100644
--- a/test/fixedbugs/bug255.go
+++ b/test/fixedbugs/bug255.go
@@ -6,10 +6,15 @@
package main
-var a [10]int // ok
-var b [1e1]int // ok
-var c [1.5]int // ERROR "truncated"
-var d ["abc"]int // ERROR "invalid array bound|not numeric"
-var e [nil]int // ERROR "invalid array bound|not numeric"
-var f [e]int // ERROR "invalid array bound|not constant"
-var g [1<<65]int // ERROR "array bound is too large|overflows"
+var a [10]int // ok
+var b [1e1]int // ok
+var c [1.5]int // ERROR "truncated"
+var d ["abc"]int // ERROR "invalid array bound|not numeric"
+var e [nil]int // ERROR "invalid array bound|not numeric"
+var f [e]int // ERROR "invalid array bound|not constant"
+var g [1 << 65]int // ERROR "array bound is too large|overflows"
+var h [len(a)]int // ok
+
+func ff() string
+
+var i [len([1]string{ff()})]int // ERROR "non-constant array bound|not constant"
diff --git a/test/fixedbugs/bug299.go b/test/fixedbugs/bug299.go
index 9646723bf..1067fd147 100644
--- a/test/fixedbugs/bug299.go
+++ b/test/fixedbugs/bug299.go
@@ -21,7 +21,9 @@ type T struct {
// legal according to spec
func (p T) m() {}
-// not legal according to spec
-func (p (T)) f() {} // ERROR "parenthesize|expected"
-func (p *(T)) g() {} // ERROR "parenthesize|expected"
-func (p (*T)) h() {} // ERROR "parenthesize|expected"
+// now legal according to spec
+func (p (T)) f() {}
+func (p *(T)) g() {}
+func (p (*T)) h() {}
+func (p (*(T))) i() {}
+func ((T),) j() {}
diff --git a/test/fixedbugs/bug371.go b/test/fixedbugs/bug371.go
index 6329e9635..86c73bf4a 100644
--- a/test/fixedbugs/bug371.go
+++ b/test/fixedbugs/bug371.go
@@ -8,10 +8,10 @@
package main
-type T struct {}
+type T struct{}
func (t *T) pm() {}
-func (t T) m() {}
+func (t T) m() {}
func main() {
p := &T{}
@@ -20,5 +20,5 @@ func main() {
q := &p
q.m() // ERROR "requires explicit dereference"
- q.pm()
+ q.pm() // ERROR "requires explicit dereference"
}
diff --git a/test/fixedbugs/bug406.go b/test/fixedbugs/bug406.go
index c6f8534c9..6df3c5cae 100644
--- a/test/fixedbugs/bug406.go
+++ b/test/fixedbugs/bug406.go
@@ -14,6 +14,8 @@ type matrix struct {
func (a matrix) equal() bool {
for _ = range a.e {
}
+ for range a.e {
+ }
return true
}
diff --git a/test/fixedbugs/bug486.go b/test/fixedbugs/bug486.go
new file mode 100644
index 000000000..c1a4723f9
--- /dev/null
+++ b/test/fixedbugs/bug486.go
@@ -0,0 +1,14 @@
+// compile
+
+// 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.
+
+// The gccgo lexer had a bug handling nested comments.
+// http://gcc.gnu.org/PR61746
+// http://code.google.com/p/gofrontend/issues/detail?id=35
+
+package main
+
+/*// comment
+*/
diff --git a/test/fixedbugs/bug487.go b/test/fixedbugs/bug487.go
new file mode 100644
index 000000000..eb1ad5e57
--- /dev/null
+++ b/test/fixedbugs/bug487.go
@@ -0,0 +1,24 @@
+// errorcheck
+
+// 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.
+
+// The gccgo compiler did not reliably report mismatches between the
+// number of function results and the number of expected results.
+
+package p
+
+func G() (int, int, int) {
+ return 0, 0, 0
+}
+
+func F() {
+ a, b := G() // ERROR "mismatch"
+ a, b = G() // ERROR "mismatch"
+ _, _ = a, b
+}
+
+func H() (int, int) {
+ return G() // ERROR "too many|mismatch"
+}
diff --git a/test/fixedbugs/bug488.dir/a.go b/test/fixedbugs/bug488.dir/a.go
new file mode 100644
index 000000000..94eaf7f1e
--- /dev/null
+++ b/test/fixedbugs/bug488.dir/a.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 a
+
+var p2 = Printf // ERROR "undefined"
diff --git a/test/fixedbugs/bug488.dir/b.go b/test/fixedbugs/bug488.dir/b.go
new file mode 100644
index 000000000..21b4c5b54
--- /dev/null
+++ b/test/fixedbugs/bug488.dir/b.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.
+
+package a
+
+import . "fmt"
+
+var p1 = Print
diff --git a/test/fixedbugs/bug488.go b/test/fixedbugs/bug488.go
new file mode 100644
index 000000000..63a601ed9
--- /dev/null
+++ b/test/fixedbugs/bug488.go
@@ -0,0 +1,12 @@
+// errorcheckdir
+
+// 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.
+
+// The gccgo compiler had a bug: if one file in a package did a dot
+// import, then an earlier file in the package would incorrectly
+// resolve to the imported names rather than reporting undefined
+// errors.
+
+package ignored
diff --git a/test/fixedbugs/bug489.go b/test/fixedbugs/bug489.go
new file mode 100644
index 000000000..4cf19e059
--- /dev/null
+++ b/test/fixedbugs/bug489.go
@@ -0,0 +1,22 @@
+// compile
+
+// 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.
+
+// The gccgo compiler had a bug: mentioning a function type in an
+// expression in a function literal messed up the list of variables
+// referenced in enclosing functions.
+
+package main
+
+func main() {
+ v1, v2 := 0, 0
+ f := func() {
+ a := v1
+ g := (func())(nil)
+ b := v2
+ _, _, _ = a, g, b
+ }
+ _, _, _ = v1, v2, f
+}
diff --git a/test/fixedbugs/bug490.go b/test/fixedbugs/bug490.go
new file mode 100644
index 000000000..7d05f3945
--- /dev/null
+++ b/test/fixedbugs/bug490.go
@@ -0,0 +1,16 @@
+// compile
+
+// 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.
+
+// The gccgo compiler used to crash building a comparison between an
+// interface and an empty struct literal.
+
+package p
+
+type S struct{}
+
+func F(v interface{}) bool {
+ return v == S{}
+}
diff --git a/test/fixedbugs/bug491.go b/test/fixedbugs/bug491.go
new file mode 100644
index 000000000..f4b58af1e
--- /dev/null
+++ b/test/fixedbugs/bug491.go
@@ -0,0 +1,110 @@
+// 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.
+
+// Test order of calls to builtin functions.
+// Discovered during CL 144530045 review.
+
+package main
+
+func main() {
+ // append
+ {
+ x := make([]int, 0)
+ f := func() int { x = make([]int, 2); return 2 }
+ a, b, c := append(x, 1), f(), append(x, 1)
+ if len(a) != 1 || len(c) != 3 {
+ bug()
+ println("append call not ordered:", len(a), b, len(c))
+ }
+ }
+
+ // cap
+ {
+ x := make([]int, 1)
+ f := func() int { x = make([]int, 3); return 2 }
+ a, b, c := cap(x), f(), cap(x)
+ if a != 1 || c != 3 {
+ bug()
+ println("cap call not ordered:", a, b, c)
+ }
+ }
+
+ // complex
+ {
+ x := 1.0
+ f := func() int { x = 3; return 2 }
+ a, b, c := complex(x, 0), f(), complex(x, 0)
+ if real(a) != 1 || real(c) != 3 {
+ bug()
+ println("complex call not ordered:", a, b, c)
+ }
+ }
+
+ // copy
+ {
+ tmp := make([]int, 100)
+ x := make([]int, 1)
+ f := func() int { x = make([]int, 3); return 2 }
+ a, b, c := copy(tmp, x), f(), copy(tmp, x)
+ if a != 1 || c != 3 {
+ bug()
+ println("copy call not ordered:", a, b, c)
+ }
+ }
+
+ // imag
+ {
+ x := 1i
+ f := func() int { x = 3i; return 2 }
+ a, b, c := imag(x), f(), imag(x)
+ if a != 1 || c != 3 {
+ bug()
+ println("imag call not ordered:", a, b, c)
+ }
+ }
+
+ // len
+ {
+ x := make([]int, 1)
+ f := func() int { x = make([]int, 3); return 2 }
+ a, b, c := len(x), f(), len(x)
+ if a != 1 || c != 3 {
+ bug()
+ println("len call not ordered:", a, b, c)
+ }
+ }
+
+ // make
+ {
+ x := 1
+ f := func() int { x = 3; return 2 }
+ a, b, c := make([]int, x), f(), make([]int, x)
+ if len(a) != 1 || len(c) != 3 {
+ bug()
+ println("make call not ordered:", len(a), b, len(c))
+ }
+ }
+
+ // real
+ {
+ x := 1 + 0i
+ f := func() int { x = 3; return 2 }
+ a, b, c := real(x), f(), real(x)
+ if a != 1 || c != 3 {
+ bug()
+ println("real call not ordered:", a, b, c)
+ }
+ }
+}
+
+var bugged = false
+
+func bug() {
+ if !bugged {
+ println("BUG")
+ bugged = true
+ }
+} \ No newline at end of file
diff --git a/test/fixedbugs/issue4232.go b/test/fixedbugs/issue4232.go
index e5daa6562..755b1b1de 100644
--- a/test/fixedbugs/issue4232.go
+++ b/test/fixedbugs/issue4232.go
@@ -4,6 +4,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// issue 4232
+// issue 7200
+
package p
func f() {
@@ -12,22 +15,42 @@ func f() {
_ = a[-1:] // ERROR "invalid slice index -1|index out of bounds"
_ = a[:-1] // ERROR "invalid slice index -1|index out of bounds"
_ = a[10] // ERROR "invalid array index 10|index out of bounds"
+ _ = a[9:10]
+ _ = a[10:10]
+ _ = a[9:12] // ERROR "invalid slice index 12|index out of bounds"
+ _ = a[11:12] // ERROR "invalid slice index 11|index out of bounds"
+ _ = a[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds"
var s []int
_ = s[-1] // ERROR "invalid slice index -1|index out of bounds"
_ = s[-1:] // ERROR "invalid slice index -1|index out of bounds"
_ = s[:-1] // ERROR "invalid slice index -1|index out of bounds"
_ = s[10]
+ _ = s[9:10]
+ _ = s[10:10]
+ _ = s[9:12]
+ _ = s[11:12]
+ _ = s[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds"
- const c = "foo"
+ const c = "foofoofoof"
_ = c[-1] // ERROR "invalid string index -1|index out of bounds"
_ = c[-1:] // ERROR "invalid slice index -1|index out of bounds"
_ = c[:-1] // ERROR "invalid slice index -1|index out of bounds"
- _ = c[3] // ERROR "invalid string index 3|index out of bounds"
+ _ = c[10] // ERROR "invalid string index 10|index out of bounds"
+ _ = c[9:10]
+ _ = c[10:10]
+ _ = c[9:12] // ERROR "invalid slice index 12|index out of bounds"
+ _ = c[11:12] // ERROR "invalid slice index 11|index out of bounds"
+ _ = c[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds"
var t string
_ = t[-1] // ERROR "invalid string index -1|index out of bounds"
_ = t[-1:] // ERROR "invalid slice index -1|index out of bounds"
_ = t[:-1] // ERROR "invalid slice index -1|index out of bounds"
- _ = t[3]
+ _ = t[10]
+ _ = t[9:10]
+ _ = t[10:10]
+ _ = t[9:12]
+ _ = t[11:12]
+ _ = t[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds"
}
diff --git a/test/fixedbugs/issue4388.go b/test/fixedbugs/issue4388.go
index 2e052e138..b18c98bac 100644
--- a/test/fixedbugs/issue4388.go
+++ b/test/fixedbugs/issue4388.go
@@ -17,18 +17,18 @@ type T struct {
}
func f1() {
- // The 4 here and below depends on the number of internal runtime frames
+ // The 5 here and below depends on the number of internal runtime frames
// that sit between a deferred function called during panic and
// the original frame. If that changes, this test will start failing and
// the number here will need to be updated.
- defer checkLine(4)
+ defer checkLine(5)
var t *T
var c io.Closer = t
c.Close()
}
func f2() {
- defer checkLine(4)
+ defer checkLine(5)
var t T
var c io.Closer = t
c.Close()
diff --git a/test/fixedbugs/issue5856.go b/test/fixedbugs/issue5856.go
index 35cadf8c9..78ca3b9f6 100644
--- a/test/fixedbugs/issue5856.go
+++ b/test/fixedbugs/issue5856.go
@@ -29,7 +29,7 @@ func f() {
}
func g() {
- _, file, line, _ := runtime.Caller(2)
+ _, file, line, _ := runtime.Caller(3)
if !strings.HasSuffix(file, "issue5856.go") || line != 28 {
fmt.Printf("BUG: defer called from %s:%d, want issue5856.go:28\n", file, line)
os.Exit(1)
diff --git a/test/fixedbugs/issue6703a.go b/test/fixedbugs/issue6703a.go
new file mode 100644
index 000000000..d4c008f83
--- /dev/null
+++ b/test/fixedbugs/issue6703a.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in a function value.
+
+package funcvalue
+
+func fx() int {
+ _ = x
+ return 0
+}
+
+var x = fx // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703b.go b/test/fixedbugs/issue6703b.go
new file mode 100644
index 000000000..326b5839a
--- /dev/null
+++ b/test/fixedbugs/issue6703b.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in a function call.
+
+package funccall
+
+func fx() int {
+ _ = x
+ return 0
+}
+
+var x = fx() // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703c.go b/test/fixedbugs/issue6703c.go
new file mode 100644
index 000000000..473576475
--- /dev/null
+++ b/test/fixedbugs/issue6703c.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in a method expression.
+
+package methexpr
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var x = T.m // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703d.go b/test/fixedbugs/issue6703d.go
new file mode 100644
index 000000000..0a1952f78
--- /dev/null
+++ b/test/fixedbugs/issue6703d.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in a method expression call.
+
+package methexprcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var x = T.m(0) // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703e.go b/test/fixedbugs/issue6703e.go
new file mode 100644
index 000000000..416066e85
--- /dev/null
+++ b/test/fixedbugs/issue6703e.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in the method value of a value literal.
+
+package litmethvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var x = T(0).m // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703f.go b/test/fixedbugs/issue6703f.go
new file mode 100644
index 000000000..30238297b
--- /dev/null
+++ b/test/fixedbugs/issue6703f.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in the method call of a value literal.
+
+package litmethcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var x = T(0).m() // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703g.go b/test/fixedbugs/issue6703g.go
new file mode 100644
index 000000000..002b5a636
--- /dev/null
+++ b/test/fixedbugs/issue6703g.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in an embedded method expression.
+
+package embedmethexpr
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var x = E.m // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703h.go b/test/fixedbugs/issue6703h.go
new file mode 100644
index 000000000..234ccb365
--- /dev/null
+++ b/test/fixedbugs/issue6703h.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles when calling an embedded method expression.
+
+package embedmethexprcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var x = E.m(E{0}) // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703i.go b/test/fixedbugs/issue6703i.go
new file mode 100644
index 000000000..78b4d4980
--- /dev/null
+++ b/test/fixedbugs/issue6703i.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in an embedded struct literal's method value.
+
+package embedlitmethvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var x = E{}.m // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703j.go b/test/fixedbugs/issue6703j.go
new file mode 100644
index 000000000..a7f63f748
--- /dev/null
+++ b/test/fixedbugs/issue6703j.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in an embedded struct literal's method call.
+
+package embedlitmethcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var x = E{}.m() // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703k.go b/test/fixedbugs/issue6703k.go
new file mode 100644
index 000000000..19c61078c
--- /dev/null
+++ b/test/fixedbugs/issue6703k.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in a method value.
+
+package methvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var (
+ t T
+ x = t.m // ERROR "initialization loop|depends upon itself"
+)
diff --git a/test/fixedbugs/issue6703l.go b/test/fixedbugs/issue6703l.go
new file mode 100644
index 000000000..3f4ca3147
--- /dev/null
+++ b/test/fixedbugs/issue6703l.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in a method call.
+
+package methcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var (
+ t T
+ x = t.m() // ERROR "initialization loop|depends upon itself"
+)
diff --git a/test/fixedbugs/issue6703m.go b/test/fixedbugs/issue6703m.go
new file mode 100644
index 000000000..d80959cdc
--- /dev/null
+++ b/test/fixedbugs/issue6703m.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in the method value of a value returned from a function call.
+
+package funcmethvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+func f() T {
+ return T(0)
+}
+
+var (
+ t T
+ x = f().m // ERROR "initialization loop|depends upon itself"
+)
diff --git a/test/fixedbugs/issue6703n.go b/test/fixedbugs/issue6703n.go
new file mode 100644
index 000000000..2c623f219
--- /dev/null
+++ b/test/fixedbugs/issue6703n.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in the method call of a value returned from a function call.
+
+package funcmethcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+func f() T {
+ return T(0)
+}
+
+var (
+ t T
+ x = f().m() // ERROR "initialization loop|depends upon itself"
+)
diff --git a/test/fixedbugs/issue6703o.go b/test/fixedbugs/issue6703o.go
new file mode 100644
index 000000000..efc894737
--- /dev/null
+++ b/test/fixedbugs/issue6703o.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in an embedded struct's method value.
+
+package embedmethvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var (
+ e E
+ x = e.m // ERROR "initialization loop|depends upon itself"
+)
diff --git a/test/fixedbugs/issue6703p.go b/test/fixedbugs/issue6703p.go
new file mode 100644
index 000000000..dad88f634
--- /dev/null
+++ b/test/fixedbugs/issue6703p.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in an embedded struct's method call.
+
+package embedmethcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var (
+ e E
+ x = e.m() // ERROR "initialization loop|depends upon itself"
+)
diff --git a/test/fixedbugs/issue6703q.go b/test/fixedbugs/issue6703q.go
new file mode 100644
index 000000000..7bd748aaa
--- /dev/null
+++ b/test/fixedbugs/issue6703q.go
@@ -0,0 +1,28 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in the method value of an embedded struct returned
+// from a function call.
+
+package funcembedmethvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+func g() E {
+ return E{0}
+}
+
+type E struct{ T }
+
+var (
+ e E
+ x = g().m // ERROR "initialization loop|depends upon itself"
+)
diff --git a/test/fixedbugs/issue6703r.go b/test/fixedbugs/issue6703r.go
new file mode 100644
index 000000000..669846241
--- /dev/null
+++ b/test/fixedbugs/issue6703r.go
@@ -0,0 +1,28 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in the method call of an embedded struct returned
+// from a function call.
+
+package funcembedmethcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+func g() E {
+ return E{0}
+}
+
+type E struct{ T }
+
+var (
+ e E
+ x = g().m() // ERROR "initialization loop|depends upon itself"
+)
diff --git a/test/fixedbugs/issue6703s.go b/test/fixedbugs/issue6703s.go
new file mode 100644
index 000000000..6aa28483a
--- /dev/null
+++ b/test/fixedbugs/issue6703s.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in a pointer method expression.
+
+package ptrmethexpr
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var x = (*T).pm // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703t.go b/test/fixedbugs/issue6703t.go
new file mode 100644
index 000000000..bad65ad16
--- /dev/null
+++ b/test/fixedbugs/issue6703t.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in the call of a pointer method expression.
+
+package ptrmethexprcall
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var x = (*T).pm(nil) // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703u.go b/test/fixedbugs/issue6703u.go
new file mode 100644
index 000000000..b6813b771
--- /dev/null
+++ b/test/fixedbugs/issue6703u.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in a pointer literal's method value.
+
+package ptrlitmethvalue
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var x = (*T)(nil).pm // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703v.go b/test/fixedbugs/issue6703v.go
new file mode 100644
index 000000000..a1b3711bb
--- /dev/null
+++ b/test/fixedbugs/issue6703v.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in a pointer literal's method call.
+
+package ptrlitmethcall
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var x = (*T)(nil).pm() // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703w.go b/test/fixedbugs/issue6703w.go
new file mode 100644
index 000000000..d4733deba
--- /dev/null
+++ b/test/fixedbugs/issue6703w.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in a pointer value's method value.
+
+package ptrmethvalue
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var (
+ p *T
+ x = p.pm // ERROR "initialization loop|depends upon itself"
+)
diff --git a/test/fixedbugs/issue6703x.go b/test/fixedbugs/issue6703x.go
new file mode 100644
index 000000000..8008b8c37
--- /dev/null
+++ b/test/fixedbugs/issue6703x.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in a pointer value's method call.
+
+package ptrmethcall
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var (
+ p *T
+ x = p.pm() // ERROR "initialization loop|depends upon itself"
+)
diff --git a/test/fixedbugs/issue6703y.go b/test/fixedbugs/issue6703y.go
new file mode 100644
index 000000000..ac4526dda
--- /dev/null
+++ b/test/fixedbugs/issue6703y.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in the method value of a pointer value returned
+// from a function call.
+
+package funcptrmethvalue
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+func pf() *T {
+ return nil
+}
+
+var x = pf().pm // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue6703z.go b/test/fixedbugs/issue6703z.go
new file mode 100644
index 000000000..d4c17e13a
--- /dev/null
+++ b/test/fixedbugs/issue6703z.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// 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.
+
+// Check for cycles in the method call of a pointer value returned
+// from a function call.
+
+package funcptrmethcall
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+func pf() *T {
+ return nil
+}
+
+var x = pf().pm() // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/issue7690.go b/test/fixedbugs/issue7690.go
new file mode 100644
index 000000000..4ad9e8622
--- /dev/null
+++ b/test/fixedbugs/issue7690.go
@@ -0,0 +1,49 @@
+// 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.
+
+// issue 7690 - Stack and other routines did not back up initial PC
+// into CALL instruction, instead reporting line number of next instruction,
+// which might be on a different line.
+
+package main
+
+import (
+ "bytes"
+ "regexp"
+ "runtime"
+ "strconv"
+)
+
+func main() {
+ buf1 := make([]byte, 1000)
+ buf2 := make([]byte, 1000)
+
+ runtime.Stack(buf1, false) // CALL is last instruction on this line
+ n := runtime.Stack(buf2, false) // CALL is followed by load of result from stack
+
+ buf1 = buf1[:bytes.IndexByte(buf1, 0)]
+ buf2 = buf2[:n]
+
+ re := regexp.MustCompile(`(?m)^main\.main\(\)\n.*/issue7690.go:([0-9]+)`)
+ m1 := re.FindStringSubmatch(string(buf1))
+ if m1 == nil {
+ println("BUG: cannot find main.main in first trace")
+ return
+ }
+ m2 := re.FindStringSubmatch(string(buf2))
+ if m2 == nil {
+ println("BUG: cannot find main.main in second trace")
+ return
+ }
+
+ n1, _ := strconv.Atoi(m1[1])
+ n2, _ := strconv.Atoi(m2[1])
+ if n1+1 != n2 {
+ println("BUG: expect runtime.Stack on back to back lines, have", n1, n2)
+ println(string(buf1))
+ println(string(buf2))
+ }
+}
diff --git a/test/fixedbugs/issue7760.go b/test/fixedbugs/issue7760.go
new file mode 100644
index 000000000..cccae4891
--- /dev/null
+++ b/test/fixedbugs/issue7760.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// 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.
+
+// Verify that pointers can't be used as constants.
+
+package main
+
+import "unsafe"
+
+type myPointer unsafe.Pointer
+
+const _ = unsafe.Pointer(uintptr(1)) // ERROR "is not (a )?constant"
+const _ = myPointer(uintptr(1)) // ERROR "is not (a )?constant"
+
+const _ = (*int)(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant"
+const _ = (*int)(myPointer(uintptr(1))) // ERROR "is not (a )?constant"
+
+const _ = uintptr(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant"
+const _ = uintptr(myPointer(uintptr(1))) // ERROR "is not (a )?constant"
+
+const _ = []byte("") // ERROR "is not (a )?constant"
+const _ = []rune("") // ERROR "is not (a )?constant"
diff --git a/test/fixedbugs/issue8017.go b/test/fixedbugs/issue8017.go
new file mode 100644
index 000000000..22056e08c
--- /dev/null
+++ b/test/fixedbugs/issue8017.go
@@ -0,0 +1,26 @@
+// compile
+
+// 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.
+
+// Issues 8017 and 8058: walk modifies nodes generated
+// by slicelit and causes an internal error afterwards
+// when gen_as_init parses it back.
+
+package main
+
+func F() {
+ var ch chan int
+ select {
+ case <-ch:
+ case <-make(chan int, len([2][]int{([][]int{})[len(ch)], []int{}})):
+ }
+}
+
+func G() {
+ select {
+ case <-([1][]chan int{[]chan int{}})[0][0]:
+ default:
+ }
+}
diff --git a/test/fixedbugs/issue8060.dir/a.go b/test/fixedbugs/issue8060.dir/a.go
new file mode 100644
index 000000000..22ba69ee1
--- /dev/null
+++ b/test/fixedbugs/issue8060.dir/a.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 a
+
+var A = []*[2][1]float64{}
diff --git a/test/fixedbugs/issue8060.dir/b.go b/test/fixedbugs/issue8060.dir/b.go
new file mode 100644
index 000000000..85fb6ec7d
--- /dev/null
+++ b/test/fixedbugs/issue8060.dir/b.go
@@ -0,0 +1,13 @@
+// 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 b
+
+import "a"
+
+var X = a.A
+
+func b() {
+ _ = [3][1]float64{}
+}
diff --git a/test/fixedbugs/issue8060.go b/test/fixedbugs/issue8060.go
new file mode 100644
index 000000000..ec52659e6
--- /dev/null
+++ b/test/fixedbugs/issue8060.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// 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.
+
+// Issue 8060: internal compiler error.
+
+package ignored
diff --git a/test/fixedbugs/issue8074.go b/test/fixedbugs/issue8074.go
new file mode 100644
index 000000000..aedab240e
--- /dev/null
+++ b/test/fixedbugs/issue8074.go
@@ -0,0 +1,16 @@
+// compile
+
+// 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.
+
+// issue 8074.
+// was "cannot take the address of 1"
+
+package main
+
+func main() {
+ a := make([]byte, 10)
+ m := make(map[float64][]byte)
+ go copy(a, m[1.0])
+}
diff --git a/test/fixedbugs/issue8079.go b/test/fixedbugs/issue8079.go
new file mode 100644
index 000000000..994999bf6
--- /dev/null
+++ b/test/fixedbugs/issue8079.go
@@ -0,0 +1,11 @@
+// compile
+
+// 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.
+
+// Issue 8079: gccgo crashes when compiling interface with blank type name.
+
+package p
+
+type _ interface{}
diff --git a/test/fixedbugs/issue8280.dir/a.go b/test/fixedbugs/issue8280.dir/a.go
new file mode 100644
index 000000000..588536e79
--- /dev/null
+++ b/test/fixedbugs/issue8280.dir/a.go
@@ -0,0 +1,3 @@
+package a
+
+var Bar = func() (_ int) { return 0 }
diff --git a/test/fixedbugs/issue8280.dir/b.go b/test/fixedbugs/issue8280.dir/b.go
new file mode 100644
index 000000000..c46c55458
--- /dev/null
+++ b/test/fixedbugs/issue8280.dir/b.go
@@ -0,0 +1,5 @@
+package b
+
+import "./a"
+
+var foo = a.Bar
diff --git a/test/fixedbugs/issue8280.go b/test/fixedbugs/issue8280.go
new file mode 100644
index 000000000..91256c852
--- /dev/null
+++ b/test/fixedbugs/issue8280.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// 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.
+
+// Issue 8280: cannot import package exporting a func var returning a result named _
+
+package ignored
diff --git a/test/fixedbugs/issue8311.go b/test/fixedbugs/issue8311.go
new file mode 100644
index 000000000..dd928566d
--- /dev/null
+++ b/test/fixedbugs/issue8311.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// 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.
+
+// issue 8311.
+// error for x++ should say x++ not x += 1
+
+package p
+
+func f() {
+ var x []byte
+ x++ // ERROR "invalid operation: x[+][+]"
+
+}
diff --git a/test/fixedbugs/issue8336.go b/test/fixedbugs/issue8336.go
new file mode 100644
index 000000000..26bdeabb2
--- /dev/null
+++ b/test/fixedbugs/issue8336.go
@@ -0,0 +1,29 @@
+// 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.
+
+// Issue 8336. Order of evaluation of receive channels in select.
+
+package main
+
+type X struct {
+ c chan int
+}
+
+func main() {
+ defer func() {
+ recover()
+ }()
+ var x *X
+ select {
+ case <-x.c: // should fault and panic before foo is called
+ case <-foo():
+ }
+}
+
+func foo() chan int {
+ println("BUG: foo must not be called")
+ return make(chan int)
+}
diff --git a/test/fixedbugs/issue8347.go b/test/fixedbugs/issue8347.go
new file mode 100644
index 000000000..0828ccf06
--- /dev/null
+++ b/test/fixedbugs/issue8347.go
@@ -0,0 +1,27 @@
+// 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.
+
+package main
+
+func main() {
+ c := make(chan bool, 1)
+ ok := true
+ for i := 0; i < 12; i++ {
+ select {
+ case _, ok = <-c:
+ if i < 10 && !ok {
+ panic("BUG")
+ }
+ default:
+ }
+ if i < 10 && !ok {
+ panic("BUG")
+ }
+ if i >= 10 && ok {
+ close(c)
+ }
+ }
+}
diff --git a/test/fixedbugs/issue8475.go b/test/fixedbugs/issue8475.go
new file mode 100644
index 000000000..e69794534
--- /dev/null
+++ b/test/fixedbugs/issue8475.go
@@ -0,0 +1,25 @@
+// build
+
+// 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.
+
+// Issue 8745: comma-ok assignments should produce untyped bool as 2nd result.
+
+package main
+
+type mybool bool
+
+func main() {
+ var ok mybool
+ _ = ok
+
+ var i interface{}
+ _, ok = i.(int)
+
+ var m map[int]int
+ _, ok = m[0]
+
+ var c chan int
+ _, ok = <-c
+}
diff --git a/test/fixedbugs/issue8507.go b/test/fixedbugs/issue8507.go
new file mode 100644
index 000000000..00a14aa88
--- /dev/null
+++ b/test/fixedbugs/issue8507.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// 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.
+
+// issue 8507
+// used to call algtype on invalid recursive type and get into infinite recursion
+
+package p
+
+type T struct{ T } // ERROR "invalid recursive type T"
+
+func f() {
+ println(T{} == T{})
+}
diff --git a/test/fixedbugs/issue8612.go b/test/fixedbugs/issue8612.go
new file mode 100644
index 000000000..93370cf66
--- /dev/null
+++ b/test/fixedbugs/issue8612.go
@@ -0,0 +1,34 @@
+//compile
+
+// 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.
+
+// Gccgo had a bug comparing a struct or array value with an interface
+// values, when the struct or array was not addressable.
+
+package p
+
+type A [10]int
+
+type S struct {
+ i int
+}
+
+func F1() S {
+ return S{0}
+}
+
+func F2() A {
+ return A{}
+}
+
+func Cmp(v interface{}) bool {
+ if F1() == v {
+ return true
+ }
+ if F2() == v {
+ return true
+ }
+ return false
+}
diff --git a/test/fixedbugs/issue8761.go b/test/fixedbugs/issue8761.go
new file mode 100644
index 000000000..badf639fc
--- /dev/null
+++ b/test/fixedbugs/issue8761.go
@@ -0,0 +1,26 @@
+// compile
+
+// 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.
+
+// issue 8761
+// used to confuse code generator into using temporary before initialization.
+// caused 'variable live at entry' error in liveness analysis.
+
+package p
+
+func _() {
+ type C chan int
+ _ = [1][]C{[]C{make(chan int)}}
+}
+
+func _() {
+ type C interface{}
+ _ = [1][]C{[]C{recover()}}
+}
+
+func _() {
+ type C *int
+ _ = [1][]C{[]C{new(int)}}
+}
diff --git a/test/fixedbugs/issue8947.go b/test/fixedbugs/issue8947.go
new file mode 100644
index 000000000..f40c02e99
--- /dev/null
+++ b/test/fixedbugs/issue8947.go
@@ -0,0 +1,53 @@
+// 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.
+
+// Some uses of zeroed constants in non-assignment
+// expressions broke with our more aggressive zeroing
+// of assignments (internal compiler errors).
+
+package main
+
+func f1() {
+ type T [2]int
+ p := T{0, 1}
+ switch p {
+ case T{0, 0}:
+ panic("wrong1")
+ case T{0, 1}:
+ // ok
+ default:
+ panic("wrong2")
+ }
+
+ if p == (T{0, 0}) {
+ panic("wrong3")
+ } else if p == (T{0, 1}) {
+ // ok
+ } else {
+ panic("wrong4")
+ }
+}
+
+type T struct {
+ V int
+}
+
+var X = T{}.V
+
+func f2() {
+ var x = T{}.V
+ if x != 0 {
+ panic("wrongx")
+ }
+ if X != 0 {
+ panic("wrongX")
+ }
+}
+
+func main() {
+ f1()
+ f2()
+}
diff --git a/test/fixedbugs/issue8961.go b/test/fixedbugs/issue8961.go
new file mode 100644
index 000000000..fbfb7e67f
--- /dev/null
+++ b/test/fixedbugs/issue8961.go
@@ -0,0 +1,20 @@
+// 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.
+
+// Issue 8961. Empty composite literals to small globals were not filled in
+package main
+
+type small struct { a int }
+var foo small
+
+func main() {
+ foo.a = 1
+ foo = small{}
+ if foo.a != 0 {
+ println("expected foo.a to be 0, was", foo.a)
+ panic("composite literal not filled in")
+ }
+}
diff --git a/test/fixedbugs/issue9006.go b/test/fixedbugs/issue9006.go
new file mode 100644
index 000000000..c559f58f1
--- /dev/null
+++ b/test/fixedbugs/issue9006.go
@@ -0,0 +1,37 @@
+// 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.
+
+package main
+
+type T1 struct {
+ X int
+}
+
+func NewT1(x int) T1 { return T1{x} }
+
+type T2 int
+
+func NewT2(x int) T2 { return T2(x) }
+
+func main() {
+ switch (T1{}) {
+ case NewT1(1):
+ panic("bad1")
+ case NewT1(0):
+ // ok
+ default:
+ panic("bad2")
+ }
+
+ switch T2(0) {
+ case NewT2(2):
+ panic("bad3")
+ case NewT2(0):
+ // ok
+ default:
+ panic("bad4")
+ }
+}
diff --git a/test/fixedbugs/issue9110.go b/test/fixedbugs/issue9110.go
new file mode 100644
index 000000000..729463305
--- /dev/null
+++ b/test/fixedbugs/issue9110.go
@@ -0,0 +1,90 @@
+// 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.
+
+// Scenario that used to leak arbitrarily many SudoG structs.
+// See golang.org/issue/9110.
+
+package main
+
+import (
+ "runtime"
+ "runtime/debug"
+ "sync"
+ "time"
+)
+
+func main() {
+ debug.SetGCPercent(1000000) // only GC when we ask for GC
+
+ var stats, stats1, stats2 runtime.MemStats
+
+ release := func() {}
+ for i := 0; i < 20; i++ {
+ if i == 10 {
+ // Should be warmed up by now.
+ runtime.ReadMemStats(&stats1)
+ }
+
+ c := make(chan int)
+ for i := 0; i < 10; i++ {
+ go func() {
+ select {
+ case <-c:
+ case <-c:
+ case <-c:
+ }
+ }()
+ }
+ time.Sleep(1 * time.Millisecond)
+ release()
+
+ close(c) // let select put its sudog's into the cache
+ time.Sleep(1 * time.Millisecond)
+
+ // pick up top sudog
+ var cond1 sync.Cond
+ var mu1 sync.Mutex
+ cond1.L = &mu1
+ go func() {
+ mu1.Lock()
+ cond1.Wait()
+ mu1.Unlock()
+ }()
+ time.Sleep(1 * time.Millisecond)
+
+ // pick up next sudog
+ var cond2 sync.Cond
+ var mu2 sync.Mutex
+ cond2.L = &mu2
+ go func() {
+ mu2.Lock()
+ cond2.Wait()
+ mu2.Unlock()
+ }()
+ time.Sleep(1 * time.Millisecond)
+
+ // put top sudog back
+ cond1.Broadcast()
+ time.Sleep(1 * time.Millisecond)
+
+ // drop cache on floor
+ runtime.GC()
+
+ // release cond2 after select has gotten to run
+ release = func() {
+ cond2.Broadcast()
+ time.Sleep(1 * time.Millisecond)
+ }
+ }
+
+ runtime.GC()
+
+ runtime.ReadMemStats(&stats2)
+
+ if int(stats2.HeapObjects)-int(stats1.HeapObjects) > 20 { // normally at most 1 or 2; was 300 with leak
+ print("BUG: object leak: ", stats.HeapObjects, " -> ", stats1.HeapObjects, " -> ", stats2.HeapObjects, "\n")
+ }
+}
diff --git a/test/interface/explicit.go b/test/interface/explicit.go
index 36fa1a422..b10d02f24 100644
--- a/test/interface/explicit.go
+++ b/test/interface/explicit.go
@@ -83,12 +83,12 @@ var m4 = M(jj) // ERROR "invalid|wrong type for M method"
type B1 interface {
- _()
+ _() // ERROR "methods must have a unique non-blank name"
}
type B2 interface {
M()
- _()
+ _() // ERROR "methods must have a unique non-blank name"
}
type T2 struct{}
diff --git a/test/interface/fail.go b/test/interface/fail.go
index 81eb6cb3c..d40a15138 100644
--- a/test/interface/fail.go
+++ b/test/interface/fail.go
@@ -14,7 +14,6 @@ type I interface {
func main() {
shouldPanic(p1)
- shouldPanic(p2)
}
func p1() {
@@ -30,19 +29,6 @@ type S struct{}
func (s *S) _() {}
-type B interface {
- _()
-}
-
-func p2() {
- var s *S
- var b B
- var e interface{}
- e = s
- b = e.(B)
- _ = b
-}
-
func shouldPanic(f func()) {
defer func() {
if recover() == nil {
diff --git a/test/linkx.go b/test/linkx.go
index 12d446ffc..151b6db1e 100644
--- a/test/linkx.go
+++ b/test/linkx.go
@@ -1,20 +1,18 @@
-// $G $D/$F.go && $L -X main.tbd hello $F.$A && ./$A.out
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// skip
// 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.
// Test the -X facility of the gc linker (6l etc.).
+// This test is run by linkx_run.go.
package main
var tbd string
+var overwrite string = "dibs"
func main() {
- if tbd != "hello" {
- println("BUG: test/linkx", len(tbd), tbd)
- }
+ println(tbd)
+ println(overwrite)
}
diff --git a/test/linkx_run.go b/test/linkx_run.go
new file mode 100644
index 000000000..5b67ce7d3
--- /dev/null
+++ b/test/linkx_run.go
@@ -0,0 +1,33 @@
+// +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 linkx test.
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+)
+
+func main() {
+ cmd := exec.Command("go", "run", "-ldflags=-X main.tbd hello -X main.overwrite trumped", "linkx.go")
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ fmt.Println(string(out))
+ fmt.Println(err)
+ os.Exit(1)
+ }
+
+ want := "hello\ntrumped\n"
+ got := string(out)
+ if got != want {
+ fmt.Printf("got %q want %q\n", got, want)
+ os.Exit(1)
+ }
+}
diff --git a/test/live.go b/test/live.go
index b4cced47e..f15bb74ba 100644
--- a/test/live.go
+++ b/test/live.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -l -live
+// errorcheck -0 -l -live -wb=0
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -118,7 +118,10 @@ var i9 interface{}
func f9() bool {
g8()
x := i9
- return x != 99
+ // using complex number in comparison so that
+ // there is always a convT2E, no matter what the
+ // interface rules are.
+ return x != 99.0i // ERROR "live at call to convT2E: x"
}
// liveness formerly confused by UNDEF followed by RET,
@@ -138,7 +141,7 @@ var b bool
// this used to have a spurious "live at entry to f11a: ~r0"
func f11a() *int {
- select { // ERROR "live at call to selectgo: autotmp"
+ select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp"
case <-c: // ERROR "live at call to selectrecv: autotmp"
return nil
case <-c: // ERROR "live at call to selectrecv: autotmp"
@@ -153,7 +156,7 @@ func f11b() *int {
// get to the bottom of the function.
// This used to have a spurious "live at call to printint: p".
print(1) // nothing live here!
- select { // ERROR "live at call to selectgo: autotmp"
+ select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp"
case <-c: // ERROR "live at call to selectrecv: autotmp"
return nil
case <-c: // ERROR "live at call to selectrecv: autotmp"
@@ -170,7 +173,7 @@ func f11c() *int {
// Unlike previous, the cases in this select fall through,
// so we can get to the println, so p is not dead.
print(1) // ERROR "live at call to printint: p"
- select { // ERROR "live at call to newselect: p" "live at call to selectgo: autotmp.* p"
+ select { // ERROR "live at call to newselect: autotmp.* p" "live at call to selectgo: autotmp.* p"
case <-c: // ERROR "live at call to selectrecv: autotmp.* p"
case <-c: // ERROR "live at call to selectrecv: autotmp.* p"
}
@@ -184,7 +187,7 @@ func f11c() *int {
func f12() *int {
if b {
- select{}
+ select {}
} else {
return nil
}
@@ -215,7 +218,7 @@ func f15() {
var x string
_ = &x
x = g15() // ERROR "live at call to g15: x"
- print(x) // ERROR "live at call to printstring: x"
+ print(x) // ERROR "live at call to printstring: x"
}
func g15() string
@@ -287,7 +290,7 @@ var ch chan *byte
func f19() {
// dest temporary for channel receive.
var z *byte
-
+
if b {
z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
}
@@ -348,21 +351,21 @@ func f25(b bool) {
var x string
_ = &x
x = g15() // ERROR "live at call to g15: x"
- print(x) // ERROR "live at call to printstring: x"
+ print(x) // ERROR "live at call to printstring: x"
} // ERROR "live at call to deferreturn: x"
func g25()
-
+
// non-escaping ... slices passed to function call should die on return,
// so that the temporaries do not stack and do not cause ambiguously
// live variables.
func f26(b bool) {
if b {
- print26(1,2,3) // ERROR "live at call to print26: autotmp_[0-9]+$"
+ print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
}
- print26(4,5,6) // ERROR "live at call to print26: autotmp_[0-9]+$"
- print26(7,8,9) // ERROR "live at call to print26: autotmp_[0-9]+$"
+ print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
+ print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
println()
}
@@ -374,10 +377,10 @@ func print26(...interface{})
func f27(b bool) {
x := 0
if b {
- call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$"
+ call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
}
- call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$"
- call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$"
+ call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
+ call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
println()
}
@@ -386,10 +389,10 @@ func f27(b bool) {
func f27defer(b bool) {
x := 0
if b {
- defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$"
+ defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$"
}
- defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live"
- println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$"
+ defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live"
+ println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$"
} // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$"
// and newproc (go) escapes to the heap
@@ -397,9 +400,9 @@ func f27defer(b bool) {
func f27go(b bool) {
x := 0
if b {
- go call27(func() {x++}) // ERROR "live at call to new: &x" "live at call to newproc: &x$"
+ go call27(func() { x++ }) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$"
}
- go call27(func() {x++}) // ERROR "live at call to new: &x"
+ go call27(func() { x++ }) // ERROR "live at call to newobject: &x"
println()
}
@@ -412,11 +415,11 @@ var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string
func f28(b bool) {
if b {
- print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+ print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
}
- print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
- print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
-}
+ print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+ print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+}
// map iterator should die on end of range loop
@@ -461,10 +464,10 @@ func f31(b1, b2, b3 bool) {
g31("a") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to g31: autotmp_[0-9]+$"
}
if b2 {
- h31("b") // ERROR "live at call to new: autotmp_[0-9]+$" "live at call to convT2E: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to h31: autotmp_[0-9]+$"
+ h31("b") // ERROR "live at call to newobject: autotmp_[0-9]+$" "live at call to convT2E: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to h31: autotmp_[0-9]+$"
}
if b3 {
- panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to panic: autotmp_[0-9]+$"
+ panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to gopanic: autotmp_[0-9]+$"
}
print(b3)
}
@@ -583,14 +586,16 @@ func f39a() (x []int) {
}
func f39b() (x [10]*int) {
- x = [10]*int{new(int)} // ERROR "live at call to new: x"
- println() // ERROR "live at call to printnl: x"
+ x = [10]*int{}
+ x[0] = new(int) // ERROR "live at call to newobject: x"
+ println() // ERROR "live at call to printnl: x"
return x
}
func f39c() (x [10]*int) {
- x = [10]*int{new(int)} // ERROR "live at call to new: x"
- println() // ERROR "live at call to printnl: x"
+ x = [10]*int{}
+ x[0] = new(int) // ERROR "live at call to newobject: x"
+ println() // ERROR "live at call to printnl: x"
return
}
@@ -602,9 +607,8 @@ type T40 struct {
}
func newT40() *T40 {
- ret := T40{ // ERROR "live at call to makemap: &ret"
- make(map[int]int),
- }
+ ret := T40{}
+ ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret"
return &ret
}
@@ -615,9 +619,8 @@ func bad40() {
}
func good40() {
- ret := T40{ // ERROR "live at call to makemap: ret"
- make(map[int]int),
- }
+ ret := T40{}
+ ret.m = make(map[int]int) // ERROR "live at call to makemap: ret"
t := &ret
println() // ERROR "live at call to printnl: ret"
_ = t
diff --git a/test/live2.go b/test/live2.go
index 1e3279402..ef6ad994c 100644
--- a/test/live2.go
+++ b/test/live2.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -live
+// errorcheck -0 -live -wb=0
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -17,9 +17,8 @@ type T40 struct {
}
func newT40() *T40 {
- ret := T40{ // ERROR "live at call to makemap: &ret"
- make(map[int]int),
- }
+ ret := T40{}
+ ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret"
return &ret
}
@@ -30,9 +29,8 @@ func bad40() {
}
func good40() {
- ret := T40{ // ERROR "live at call to makemap: ret"
- make(map[int]int),
- }
+ ret := T40{}
+ ret.m = make(map[int]int) // ERROR "live at call to makemap: ret"
t := &ret
println() // ERROR "live at call to printnl: ret"
_ = t
diff --git a/test/map.go b/test/map.go
index 485e743fe..2c1cf8a14 100644
--- a/test/map.go
+++ b/test/map.go
@@ -5,7 +5,7 @@
// license that can be found in the LICENSE file.
// Test maps, almost exhaustively.
-// NaN complexity test is in mapnan.go.
+// Complexity (linearity) test is in maplinear.go.
package main
diff --git a/test/maplinear.go b/test/maplinear.go
new file mode 100644
index 000000000..34d091491
--- /dev/null
+++ b/test/maplinear.go
@@ -0,0 +1,172 @@
+// +build darwin linux
+// run
+
+// 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.
+
+// Test that maps don't go quadratic for NaNs and other values.
+
+package main
+
+import (
+ "fmt"
+ "math"
+ "time"
+)
+
+// checkLinear asserts that the running time of f(n) is in O(n).
+// tries is the initial number of iterations.
+func checkLinear(typ string, tries int, f func(n int)) {
+ // Depending on the machine and OS, this test might be too fast
+ // to measure with accurate enough granularity. On failure,
+ // make it run longer, hoping that the timing granularity
+ // is eventually sufficient.
+
+ timeF := func(n int) time.Duration {
+ t1 := time.Now()
+ f(n)
+ return time.Since(t1)
+ }
+
+ t0 := time.Now()
+
+ n := tries
+ fails := 0
+ for {
+ t1 := timeF(n)
+ t2 := timeF(2 * n)
+
+ // should be 2x (linear); allow up to 3x
+ if t2 < 3*t1 {
+ if false {
+ fmt.Println(typ, "\t", time.Since(t0))
+ }
+ return
+ }
+ // If n ops run in under a second and the ratio
+ // doesn't work out, make n bigger, trying to reduce
+ // the effect that a constant amount of overhead has
+ // on the computed ratio.
+ if t1 < 1*time.Second {
+ n *= 2
+ continue
+ }
+ // Once the test runs long enough for n ops,
+ // try to get the right ratio at least once.
+ // If five in a row all fail, give up.
+ if fails++; fails >= 5 {
+ panic(fmt.Sprintf("%s: too slow: %d inserts: %v; %d inserts: %v\n",
+ typ, n, t1, 2*n, t2))
+ }
+ }
+}
+
+type I interface {
+ f()
+}
+
+type C int
+
+func (C) f() {}
+
+func main() {
+ // NaNs. ~31ms on a 1.6GHz Zeon.
+ checkLinear("NaN", 30000, func(n int) {
+ m := map[float64]int{}
+ nan := math.NaN()
+ for i := 0; i < n; i++ {
+ m[nan] = 1
+ }
+ if len(m) != n {
+ panic("wrong size map after nan insertion")
+ }
+ })
+
+ // ~6ms on a 1.6GHz Zeon.
+ checkLinear("eface", 10000, func(n int) {
+ m := map[interface{}]int{}
+ for i := 0; i < n; i++ {
+ m[i] = 1
+ }
+ })
+
+ // ~7ms on a 1.6GHz Zeon.
+ // Regression test for CL 119360043.
+ checkLinear("iface", 10000, func(n int) {
+ m := map[I]int{}
+ for i := 0; i < n; i++ {
+ m[C(i)] = 1
+ }
+ })
+
+ // ~6ms on a 1.6GHz Zeon.
+ checkLinear("int", 10000, func(n int) {
+ m := map[int]int{}
+ for i := 0; i < n; i++ {
+ m[i] = 1
+ }
+ })
+
+ // ~18ms on a 1.6GHz Zeon.
+ checkLinear("string", 10000, func(n int) {
+ m := map[string]int{}
+ for i := 0; i < n; i++ {
+ m[fmt.Sprint(i)] = 1
+ }
+ })
+
+ // ~6ms on a 1.6GHz Zeon.
+ checkLinear("float32", 10000, func(n int) {
+ m := map[float32]int{}
+ for i := 0; i < n; i++ {
+ m[float32(i)] = 1
+ }
+ })
+
+ // ~6ms on a 1.6GHz Zeon.
+ checkLinear("float64", 10000, func(n int) {
+ m := map[float64]int{}
+ for i := 0; i < n; i++ {
+ m[float64(i)] = 1
+ }
+ })
+
+ // ~22ms on a 1.6GHz Zeon.
+ checkLinear("complex64", 10000, func(n int) {
+ m := map[complex64]int{}
+ for i := 0; i < n; i++ {
+ m[complex(float32(i), float32(i))] = 1
+ }
+ })
+
+ // ~32ms on a 1.6GHz Zeon.
+ checkLinear("complex128", 10000, func(n int) {
+ m := map[complex128]int{}
+ for i := 0; i < n; i++ {
+ m[complex(float64(i), float64(i))] = 1
+ }
+ })
+
+ // ~70ms on a 1.6GHz Zeon.
+ // The iterate/delete idiom currently takes expected
+ // O(n lg n) time. Fortunately, the checkLinear test
+ // leaves enough wiggle room to include n lg n time
+ // (it actually tests for O(n^log_2(3)).
+ // To prevent false positives, average away variation
+ // by doing multiple rounds within a single run.
+ checkLinear("iterdelete", 2500, func(n int) {
+ for round := 0; round < 4; round++ {
+ m := map[int]int{}
+ for i := 0; i < n; i++ {
+ m[i] = i
+ }
+ for i := 0; i < n; i++ {
+ for k := range m {
+ delete(m, k)
+ break
+ }
+ }
+ }
+ })
+}
diff --git a/test/mapnan.go b/test/mapnan.go
deleted file mode 100644
index f081cab01..000000000
--- a/test/mapnan.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// +build darwin linux
-// run
-
-// 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.
-
-// Test that NaNs in maps don't go quadratic.
-
-package main
-
-import (
- "fmt"
- "math"
- "time"
-)
-
-func main() {
-
- // Test that NaNs in maps don't go quadratic.
- t := func(n int) time.Duration {
- t1 := time.Now()
- m := map[float64]int{}
- nan := math.NaN()
- for i := 0; i < n; i++ {
- m[nan] = 1
- }
- if len(m) != n {
- panic("wrong size map after nan insertion")
- }
- return time.Since(t1)
- }
-
- // Depending on the machine and OS, this test might be too fast
- // to measure with accurate enough granularity. On failure,
- // make it run longer, hoping that the timing granularity
- // is eventually sufficient.
-
- n := 30000 // ~8ms user time on a Mid 2011 MacBook Air (1.8 GHz Core i7)
- fails := 0
- for {
- t1 := t(n)
- t2 := t(2 * n)
- // should be 2x (linear); allow up to 3x
- if t2 < 3*t1 {
- return
- }
- fails++
- if fails == 6 {
- panic(fmt.Sprintf("too slow: %d inserts: %v; %d inserts: %v\n", n, t1, 2*n, t2))
- }
- if fails < 4 {
- n *= 2
- }
- }
-}
diff --git a/test/named1.go b/test/named1.go
index 62b874c5c..febad64ec 100644
--- a/test/named1.go
+++ b/test/named1.go
@@ -41,21 +41,21 @@ func main() {
asBool(1 != 2) // ok now
asBool(i < j) // ok now
- _, b = m[2] // ERROR "cannot .* bool.*type Bool"
+ _, b = m[2] // ok now
var inter interface{}
- _, b = inter.(Map) // ERROR "cannot .* bool.*type Bool"
+ _, b = inter.(Map) // ok now
_ = b
var minter interface {
M()
}
- _, b = minter.(Map) // ERROR "cannot .* bool.*type Bool"
+ _, b = minter.(Map) // ok now
_ = b
_, bb := <-c
asBool(bb) // ERROR "cannot use.*type bool.*as type Bool"
- _, b = <-c // ERROR "cannot .* bool.*type Bool"
+ _, b = <-c // ok now
_ = b
asString(String(slice)) // ok
diff --git a/test/nosplit.go b/test/nosplit.go
index 35aa51017..953a5bf0a 100644
--- a/test/nosplit.go
+++ b/test/nosplit.go
@@ -12,6 +12,7 @@ import (
"bytes"
"fmt"
"io/ioutil"
+ "log"
"os"
"os/exec"
"path/filepath"
@@ -190,7 +191,6 @@ func main() {
return
}
defer os.RemoveAll(dir)
- ioutil.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\nfunc main()\n"), 0666)
tests = strings.Replace(tests, "\t", " ", -1)
tests = commentRE.ReplaceAllString(tests, "")
@@ -230,6 +230,9 @@ TestCases:
continue
}
+ var gobuf bytes.Buffer
+ fmt.Fprintf(&gobuf, "package main\n")
+
var buf bytes.Buffer
if goarch == "arm" {
fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n")
@@ -242,7 +245,7 @@ TestCases:
if line == "" {
continue
}
- for _, subline := range strings.Split(line, ";") {
+ for i, subline := range strings.Split(line, ";") {
subline = strings.TrimSpace(subline)
if subline == "" {
continue
@@ -255,6 +258,14 @@ TestCases:
}
name := m[1]
size, _ := strconv.Atoi(m[2])
+
+ // The limit was originally 128 but is now 384.
+ // Instead of rewriting the test cases above, adjust
+ // the first stack frame to use up the extra 32 bytes.
+ if i == 0 {
+ size += 384 - 128
+ }
+
if goarch == "amd64" && size%8 == 4 {
continue TestCases
}
@@ -269,11 +280,17 @@ TestCases:
body = callRE.ReplaceAllString(body, "CALL ·$1(SB);")
body = callindRE.ReplaceAllString(body, "CALL REGISTER;")
+ fmt.Fprintf(&gobuf, "func %s()\n", name)
fmt.Fprintf(&buf, "TEXT ·%s(SB)%s,$%d-0\n\t%s\n\tRET\n\n", name, nosplit, size, body)
}
}
- ioutil.WriteFile(filepath.Join(dir, "asm.s"), buf.Bytes(), 0666)
+ if err := ioutil.WriteFile(filepath.Join(dir, "asm.s"), buf.Bytes(), 0666); err != nil {
+ log.Fatal(err)
+ }
+ if err := ioutil.WriteFile(filepath.Join(dir, "main.go"), gobuf.Bytes(), 0666); err != nil {
+ log.Fatal(err)
+ }
cmd := exec.Command("go", "build")
cmd.Dir = dir
diff --git a/test/print.go b/test/print.go
new file mode 100644
index 000000000..466e19f1b
--- /dev/null
+++ b/test/print.go
@@ -0,0 +1,42 @@
+// cmpout
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test internal print routines that are generated
+// by the print builtin. This test is not exhaustive,
+// we're just checking that the formatting is correct.
+
+package main
+
+func main() {
+ println((interface{})(nil)) // printeface
+ println((interface { // printiface
+ f()
+ })(nil))
+ println((map[int]int)(nil)) // printpointer
+ println(([]int)(nil)) // printslice
+ println(int64(-7)) // printint
+ println(uint64(7)) // printuint
+ println(8.0) // printfloat
+ println(complex(9.0, 10.0)) // printcomplex
+ println(true) // printbool
+ println(false) // printbool
+ println("hello") // printstring
+ println("one", "two") // printsp
+
+ // test goprintf
+ defer println((interface{})(nil))
+ defer println((interface{f()})(nil))
+ defer println((map[int]int)(nil))
+ defer println(([]int)(nil))
+ defer println(int64(-11))
+ defer println(uint64(12))
+ defer println(13.0)
+ defer println(complex(14.0, 15.0))
+ defer println(true)
+ defer println(false)
+ defer println("hello")
+ defer println("one", "two")
+}
diff --git a/test/print.out b/test/print.out
new file mode 100644
index 000000000..266fe5d6b
--- /dev/null
+++ b/test/print.out
@@ -0,0 +1,24 @@
+(0x0,0x0)
+(0x0,0x0)
+0x0
+[0/0]0x0
+-7
+7
++8.000000e+000
+(+9.000000e+000+1.000000e+001i)
+true
+false
+hello
+one two
+one two
+hello
+false
+true
+(+1.400000e+001+1.500000e+001i)
++1.300000e+001
+12
+-11
+[0/0]0x0
+0x0
+(0x0,0x0)
+(0x0,0x0)
diff --git a/test/range.go b/test/range.go
index 8effbe9c5..af89edac5 100644
--- a/test/range.go
+++ b/test/range.go
@@ -32,6 +32,13 @@ func testchan() {
println("Wanted lowercase alphabet; got", s)
panic("fail")
}
+ n := 0
+ for range seq('a', 'z') {
+ n++
+ }
+ if n != 26 {
+ println("testchan wrong count", n, "want 26")
+ }
}
// test that range over slice only evaluates
@@ -87,6 +94,22 @@ func testslice1() {
}
}
+func testslice2() {
+ n := 0
+ nmake = 0
+ for range makeslice() {
+ n++
+ }
+ if nmake != 1 {
+ println("range called makeslice", nmake, "times")
+ panic("fail")
+ }
+ if n != 5 {
+ println("wrong count ranging over makeslice", n)
+ panic("fail")
+ }
+}
+
// test that range over array only evaluates
// the expression after "range" once.
@@ -127,6 +150,22 @@ func testarray1() {
}
}
+func testarray2() {
+ n := 0
+ nmake = 0
+ for range makearray() {
+ n++
+ }
+ if nmake != 1 {
+ println("range called makearray", nmake, "times")
+ panic("fail")
+ }
+ if n != 5 {
+ println("wrong count ranging over makearray", n)
+ panic("fail")
+ }
+}
+
func makearrayptr() *[5]int {
nmake++
return &[5]int{1, 2, 3, 4, 5}
@@ -176,6 +215,22 @@ func testarrayptr1() {
}
}
+func testarrayptr2() {
+ n := 0
+ nmake = 0
+ for range makearrayptr() {
+ n++
+ }
+ if nmake != 1 {
+ println("range called makearrayptr", nmake, "times")
+ panic("fail")
+ }
+ if n != 5 {
+ println("wrong count ranging over makearrayptr", n)
+ panic("fail")
+ }
+}
+
// test that range over string only evaluates
// the expression after "range" once.
@@ -216,6 +271,22 @@ func teststring1() {
}
}
+func teststring2() {
+ n := 0
+ nmake = 0
+ for range makestring() {
+ n++
+ }
+ if nmake != 1 {
+ println("range called makestring", nmake, "times")
+ panic("fail")
+ }
+ if n != 5 {
+ println("wrong count ranging over makestring", n)
+ panic("fail")
+ }
+}
+
// test that range over map only evaluates
// the expression after "range" once.
@@ -256,6 +327,22 @@ func testmap1() {
}
}
+func testmap2() {
+ n := 0
+ nmake = 0
+ for range makemap() {
+ n++
+ }
+ if nmake != 1 {
+ println("range called makemap", nmake, "times")
+ panic("fail")
+ }
+ if n != 5 {
+ println("wrong count ranging over makemap", n)
+ panic("fail")
+ }
+}
+
// test that range evaluates the index and value expressions
// exactly once per iteration.
@@ -298,13 +385,18 @@ func main() {
testchan()
testarray()
testarray1()
+ testarray2()
testarrayptr()
testarrayptr1()
+ testarrayptr2()
testslice()
testslice1()
+ testslice2()
teststring()
teststring1()
+ teststring2()
testmap()
testmap1()
+ testmap2()
testcalls()
}
diff --git a/test/recover.go b/test/recover.go
index 071be6667..f92c15c1d 100644
--- a/test/recover.go
+++ b/test/recover.go
@@ -47,6 +47,7 @@ func main() {
test11reflect1()
test11reflect2()
}
+ test111()
test12()
if !interp {
test12reflect1()
@@ -62,6 +63,7 @@ func main() {
test14reflect1()
test14reflect2()
test15()
+ test16()
}
}
@@ -77,7 +79,7 @@ func mustRecoverBody(v1, v2, v3, x interface{}) {
}
v = v2
if v == nil {
- println("missing recover")
+ println("missing recover", x.(int))
die() // panic is useless here
}
if v != x {
@@ -113,10 +115,23 @@ func withoutRecover() {
mustNotRecover() // because it's a sub-call
}
+func withoutRecoverRecursive(n int) {
+ if n == 0 {
+ withoutRecoverRecursive(1)
+ } else {
+ v := recover()
+ if v != nil {
+ println("spurious recover (recursive)", v)
+ die()
+ }
+ }
+}
+
func test1() {
- defer mustNotRecover() // because mustRecover will squelch it
- defer mustRecover(1) // because of panic below
- defer withoutRecover() // should be no-op, leaving for mustRecover to find
+ defer mustNotRecover() // because mustRecover will squelch it
+ defer mustRecover(1) // because of panic below
+ defer withoutRecover() // should be no-op, leaving for mustRecover to find
+ defer withoutRecoverRecursive(0) // ditto
panic(1)
}
@@ -137,7 +152,7 @@ func test1WithClosures() {
mustNotRecover()
v := recover()
if v == nil {
- println("missing recover")
+ println("missing recover", x.(int))
die()
}
if v != x {
@@ -406,6 +421,49 @@ func test11reflect2() {
panic(11)
}
+// tiny receiver, so basic wrapper in i.M()
+type T3deeper struct{}
+
+func (T3deeper) M() {
+ badstate() // difference from T3
+ mustRecoverBody(doubleRecover(), recover(), recover(), 111)
+}
+
+func test111() {
+ var i I = T3deeper{}
+ defer i.M()
+ panic(111)
+}
+
+type Tiny struct{}
+
+func (Tiny) M() {
+ panic(112)
+}
+
+// i.M is a wrapper, and i.M panics.
+//
+// This is a torture test for an old implementation of recover that
+// tried to deal with wrapper functions by doing some argument
+// positioning math on both entry and exit. Doing anything on exit
+// is a problem because sometimes functions exit via panic instead
+// of an ordinary return, so panic would have to know to do the
+// same math when unwinding the stack. It gets complicated fast.
+// This particular test never worked with the old scheme, because
+// panic never did the right unwinding math.
+//
+// The new scheme adjusts Panic.argp on entry to a wrapper.
+// It has no exit work, so if a wrapper is interrupted by a panic,
+// there's no cleanup that panic itself must do.
+// This test just works now.
+func badstate() {
+ defer func() {
+ recover()
+ }()
+ var i I = Tiny{}
+ i.M()
+}
+
// large receiver, so basic wrapper in i.M()
type T4 [2]string
@@ -503,3 +561,27 @@ func test15() {
defer f()
panic(15)
}
+
+func reflectFunc2(args []reflect.Value) (results []reflect.Value) {
+ // This will call reflectFunc3
+ args[0].Interface().(func())()
+ return nil
+}
+
+func reflectFunc3(args []reflect.Value) (results []reflect.Value) {
+ if v := recover(); v != nil {
+ println("spurious recover", v)
+ die()
+ }
+ return nil
+}
+
+func test16() {
+ defer mustRecover(16)
+
+ f2 := reflect.MakeFunc(reflect.TypeOf((func(func()))(nil)), reflectFunc2).Interface().(func(func()))
+ f3 := reflect.MakeFunc(reflect.TypeOf((func())(nil)), reflectFunc3).Interface().(func())
+ defer f2(f3)
+
+ panic(16)
+}
diff --git a/test/run.go b/test/run.go
index a8d4baa3a..e8ec2df9c 100644
--- a/test/run.go
+++ b/test/run.go
@@ -45,7 +45,7 @@ var (
// letter is the build.ArchChar
letter string
-
+
goos, goarch string
// dirs are the directories to look for *.go files in.
@@ -71,8 +71,9 @@ const maxTests = 5000
func main() {
flag.Parse()
- goos = os.Getenv("GOOS")
- goarch = os.Getenv("GOARCH")
+ goos = getenv("GOOS", runtime.GOOS)
+ goarch = getenv("GOARCH", runtime.GOARCH)
+
findExecCmd()
// Disable parallelism if printing or if using a simulator.
@@ -121,7 +122,7 @@ func main() {
failed := false
resCount := map[string]int{}
for _, test := range tests {
- <-test.donec
+ <-test.donec
status := "ok "
errStr := ""
if _, isSkip := test.err.(skipError); isSkip {
@@ -225,8 +226,8 @@ func check(err error) {
type test struct {
dir, gofile string
donec chan bool // closed when done
- dt time.Duration
-
+ dt time.Duration
+
src string
action string // "compile", "build", etc.
@@ -625,6 +626,7 @@ func (t *test) run() {
out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
if err != nil {
t.err = err
+ return
}
if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
t.err = fmt.Errorf("incorrect output\n%s", out)
@@ -639,6 +641,7 @@ func (t *test) run() {
out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
if err != nil {
t.err = err
+ return
}
tfile := filepath.Join(t.tempDir, "tmp__.go")
if err := ioutil.WriteFile(tfile, out, 0666); err != nil {
@@ -648,6 +651,7 @@ func (t *test) run() {
out, err = runcmd("go", "run", tfile)
if err != nil {
t.err = err
+ return
}
if string(out) != t.expectedOutput() {
t.err = fmt.Errorf("incorrect output\n%s", out)
@@ -658,6 +662,7 @@ func (t *test) run() {
out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
if err != nil {
t.err = err
+ return
}
tfile := filepath.Join(t.tempDir, "tmp__.go")
err = ioutil.WriteFile(tfile, out, 0666)
@@ -700,7 +705,7 @@ func findExecCmd() []string {
execCmd = []string{path}
}
return execCmd
-}
+}
func (t *test) String() string {
return filepath.Join(t.dir, t.gofile)
@@ -834,11 +839,11 @@ func partitionStrings(prefix string, strs []string) (matched, unmatched []string
}
type wantedError struct {
- reStr string
- re *regexp.Regexp
- lineNum int
- file string
- prefix string
+ reStr string
+ re *regexp.Regexp
+ lineNum int
+ file string
+ prefix string
}
var (
@@ -889,11 +894,11 @@ func (t *test) wantedErrors(file, short string) (errs []wantedError) {
}
prefix := fmt.Sprintf("%s:%d", short, lineNum)
errs = append(errs, wantedError{
- reStr: rx,
- re: re,
- prefix: prefix,
- lineNum: lineNum,
- file: short,
+ reStr: rx,
+ re: re,
+ prefix: prefix,
+ lineNum: lineNum,
+ file: short,
})
}
}
@@ -902,8 +907,6 @@ func (t *test) wantedErrors(file, short string) (errs []wantedError) {
}
var skipOkay = map[string]bool{
- "linkx.go": true, // like "run" but wants linker flags
- "sinit.go": true,
"fixedbugs/bug248.go": true, // combines errorcheckdir and rundir in the same dir.
"fixedbugs/bug302.go": true, // tests both .$O and .a imports.
"fixedbugs/bug345.go": true, // needs the appropriate flags in gc invocation.
@@ -972,3 +975,11 @@ func envForDir(dir string) []string {
env = append(env, "PWD="+dir)
return env
}
+
+func getenv(key, def string) string {
+ value := os.Getenv(key)
+ if value != "" {
+ return value
+ }
+ return def
+}
diff --git a/test/shift1.go b/test/shift1.go
index 44a3792c4..04f5321b7 100644
--- a/test/shift1.go
+++ b/test/shift1.go
@@ -238,4 +238,6 @@ func _() {
z = (1. << s) << (1 << s) // ERROR "non-integer|type complex128"
z = (1. << s) << (1. << s) // ERROR "non-integer|type complex128"
z = (1.1 << s) << (1.1 << s) // ERROR "invalid|truncated|complex128"
+
+ _, _, _ = x, y, z
}
diff --git a/test/sinit.go b/test/sinit.go
index 5e50e1100..df1a4cc93 100644
--- a/test/sinit.go
+++ b/test/sinit.go
@@ -1,7 +1,4 @@
-// $G -S $D/$F.go | egrep initdone >/dev/null && echo BUG sinit || true
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// skip
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -9,6 +6,7 @@
// Test that many initializations can be done at link time and
// generate no executable init functions.
+// This test is run by sinit_run.go.
package p
@@ -106,20 +104,27 @@ var answers = [...]int{
}
var (
- copy_zero = zero
- copy_one = one
- copy_pi = pi
- copy_slice = slice
+ copy_zero = zero
+ copy_one = one
+ copy_pi = pi
+ copy_slice = slice
copy_sliceInt = sliceInt
- copy_hello = hello
- copy_bytes = bytes
+ copy_hello = hello
+
+ // Could be handled without an initialization function, but
+ // requires special handling for "a = []byte("..."); b = a"
+ // which is not a likely case.
+ // copy_bytes = bytes
+ // https://codereview.appspot.com/171840043 is one approach to
+ // make this special case work.
+
copy_four, copy_five = four, five
- copy_x, copy_y = x, y
- copy_nilslice = nilslice
- copy_nilmap = nilmap
- copy_nilfunc = nilfunc
- copy_nilchan = nilchan
- copy_nilptr = nilptr
+ copy_x, copy_y = x, y
+ copy_nilslice = nilslice
+ copy_nilmap = nilmap
+ copy_nilfunc = nilfunc
+ copy_nilchan = nilchan
+ copy_nilptr = nilptr
)
var copy_a = a
@@ -172,7 +177,7 @@ var sx []int
var s0 = []int{0, 0, 0}
var s1 = []int{1, 2, 3}
-func fi() int
+func fi() int { return 1 }
var ax [10]int
var a0 = [10]int{0, 0, 0}
@@ -202,58 +207,66 @@ var pt0b = &T{X: 0}
var pt1 = &T{X: 1, Y: 2}
var pt1a = &T{3, 4}
-var copy_bx = bx
+// The checks similar to
+// var copy_bx = bx
+// are commented out. The compiler no longer statically initializes them.
+// See issue 7665 and https://codereview.appspot.com/93200044.
+// If https://codereview.appspot.com/169040043 is submitted, and this
+// test is changed to pass -complete to the compiler, then we can
+// uncomment the copy lines again.
+
+// var copy_bx = bx
var copy_b0 = b0
var copy_b1 = b1
-var copy_fx = fx
+// var copy_fx = fx
var copy_f0 = f0
var copy_f1 = f1
-var copy_gx = gx
+// var copy_gx = gx
var copy_g0 = g0
var copy_g1 = g1
-var copy_ix = ix
+// var copy_ix = ix
var copy_i0 = i0
var copy_i1 = i1
-var copy_jx = jx
+// var copy_jx = jx
var copy_j0 = j0
var copy_j1 = j1
-var copy_cx = cx
+// var copy_cx = cx
var copy_c0 = c0
var copy_c1 = c1
-var copy_dx = dx
+// var copy_dx = dx
var copy_d0 = d0
var copy_d1 = d1
-var copy_sx = sx
+// var copy_sx = sx
var copy_s0 = s0
var copy_s1 = s1
-var copy_ax = ax
+// var copy_ax = ax
var copy_a0 = a0
var copy_a1 = a1
-var copy_tx = tx
+// var copy_tx = tx
var copy_t0 = t0
var copy_t0a = t0a
var copy_t0b = t0b
var copy_t1 = t1
var copy_t1a = t1a
-var copy_psx = psx
+// var copy_psx = psx
var copy_ps0 = ps0
var copy_ps1 = ps1
-var copy_pax = pax
+// var copy_pax = pax
var copy_pa0 = pa0
var copy_pa1 = pa1
-var copy_ptx = ptx
+// var copy_ptx = ptx
var copy_pt0 = pt0
var copy_pt0a = pt0a
var copy_pt0b = pt0b
@@ -266,6 +279,8 @@ type T1 int
func (t *T1) M() {}
-type Mer interface { M() }
+type Mer interface {
+ M()
+}
var _ Mer = (*T1)(nil)
diff --git a/test/sinit_run.go b/test/sinit_run.go
new file mode 100644
index 000000000..b0a91ce5b
--- /dev/null
+++ b/test/sinit_run.go
@@ -0,0 +1,40 @@
+// +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 (
+ "bytes"
+ "fmt"
+ "go/build"
+ "os"
+ "os/exec"
+)
+
+func main() {
+ letter, err := build.ArchChar(build.Default.GOARCH)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+
+ cmd := exec.Command("go", "tool", letter+"g", "-S", "sinit.go")
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ fmt.Println(string(out))
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ os.Remove("sinit." + letter)
+
+ if bytes.Contains(out, []byte("initdone")) {
+ fmt.Println("sinit generated an init function")
+ os.Exit(1)
+ }
+}
diff --git a/test/slice3.go b/test/slice3.go
index 3cf34b57e..857eaf3a0 100644
--- a/test/slice3.go
+++ b/test/slice3.go
@@ -19,10 +19,10 @@ var bout *bufio.Writer
func main() {
bout = bufio.NewWriter(os.Stdout)
-
+
fmt.Fprintf(bout, "%s", programTop)
fmt.Fprintf(bout, "func main() {\n")
-
+
index := []string{
"0",
"1",
@@ -38,7 +38,7 @@ func main() {
"v10",
"v20",
}
-
+
parse := func(s string) (n int, isconst bool) {
if s == "vminus1" {
return -1, false
@@ -69,7 +69,7 @@ func main() {
iconst && kconst && iv > kv,
iconst && base == "array" && iv > Cap,
jconst && base == "array" && jv > Cap,
- kconst && base == "array" && kv > Cap:
+ kconst && base == "array" && kv > Cap:
continue
}
@@ -82,7 +82,7 @@ func main() {
xlen = jv - iv
xcap = kv - iv
}
- fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap)
+ fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap)
}
}
}
@@ -147,9 +147,13 @@ func checkSlice(desc string, f func() []byte, xbase, xlen, xcap int) {
println(desc, "=", base, len, cap, "want panic")
return
}
- if base != uintptr(xbase) || len != uintptr(xlen) || cap != uintptr(xcap) {
+ if cap != 0 && base != uintptr(xbase) || base >= 10 || len != uintptr(xlen) || cap != uintptr(xcap) {
notOK()
- println(desc, "=", base, len, cap, "want", xbase, xlen, xcap)
+ if cap == 0 {
+ println(desc, "=", base, len, cap, "want", "0-9", xlen, xcap)
+ } else {
+ println(desc, "=", base, len, cap, "want", xbase, xlen, xcap)
+ }
}
}
diff --git a/test/slicecap.go b/test/slicecap.go
new file mode 100644
index 000000000..dceb7e2cc
--- /dev/null
+++ b/test/slicecap.go
@@ -0,0 +1,90 @@
+// 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.
+
+package main
+
+import "unsafe"
+
+var (
+ hello = "hello"
+ bytes = []byte{1, 2, 3, 4, 5}
+ ints = []int32{1, 2, 3, 4, 5}
+
+ five = 5
+
+ ok = true
+)
+
+func notOK() {
+ if ok {
+ println("BUG:")
+ ok = false
+ }
+}
+
+func checkString(desc, s string) {
+ p1 := *(*uintptr)(unsafe.Pointer(&s))
+ p2 := *(*uintptr)(unsafe.Pointer(&hello))
+ if p1-p2 >= 5 {
+ notOK()
+ println("string", desc, "has invalid base")
+ }
+}
+
+func checkBytes(desc string, s []byte) {
+ p1 := *(*uintptr)(unsafe.Pointer(&s))
+ p2 := *(*uintptr)(unsafe.Pointer(&bytes))
+ if p1-p2 >= 5 {
+ println("byte slice", desc, "has invalid base")
+ }
+}
+
+func checkInts(desc string, s []int32) {
+ p1 := *(*uintptr)(unsafe.Pointer(&s))
+ p2 := *(*uintptr)(unsafe.Pointer(&ints))
+ if p1-p2 >= 5*4 {
+ println("int slice", desc, "has invalid base")
+ }
+}
+
+func main() {
+ {
+ x := hello
+ checkString("x", x)
+ checkString("x[5:]", x[5:])
+ checkString("x[five:]", x[five:])
+ checkString("x[5:five]", x[5:five])
+ checkString("x[five:5]", x[five:5])
+ checkString("x[five:five]", x[five:five])
+ checkString("x[1:][2:][2:]", x[1:][2:][2:])
+ y := x[4:]
+ checkString("y[1:]", y[1:])
+ }
+ {
+ x := bytes
+ checkBytes("x", x)
+ checkBytes("x[5:]", x[5:])
+ checkBytes("x[five:]", x[five:])
+ checkBytes("x[5:five]", x[5:five])
+ checkBytes("x[five:5]", x[five:5])
+ checkBytes("x[five:five]", x[five:five])
+ checkBytes("x[1:][2:][2:]", x[1:][2:][2:])
+ y := x[4:]
+ checkBytes("y[1:]", y[1:])
+ }
+ {
+ x := ints
+ checkInts("x", x)
+ checkInts("x[5:]", x[5:])
+ checkInts("x[five:]", x[five:])
+ checkInts("x[5:five]", x[5:five])
+ checkInts("x[five:5]", x[five:5])
+ checkInts("x[five:five]", x[five:five])
+ checkInts("x[1:][2:][2:]", x[1:][2:][2:])
+ y := x[4:]
+ checkInts("y[1:]", y[1:])
+ }
+}
diff --git a/test/stress/maps.go b/test/stress/maps.go
index d022e19ad..fc5ab05a2 100644
--- a/test/stress/maps.go
+++ b/test/stress/maps.go
@@ -97,6 +97,8 @@ func (m intMap) Len() int { return len(m) }
func (m intMap) RangeAll() {
for _ = range m {
}
+ for range m {
+ }
}
func stressMaps() {
diff --git a/test/stress/parsego.go b/test/stress/parsego.go
index a781f1993..a5856dd80 100644
--- a/test/stress/parsego.go
+++ b/test/stress/parsego.go
@@ -64,7 +64,7 @@ func parseDir(dirpath string) map[string]*ast.Package {
}
func stressParseGo() {
- pkgroot := runtime.GOROOT() + "/src/pkg/"
+ pkgroot := runtime.GOROOT() + "/src/"
for {
m := make(map[string]map[string]*ast.Package)
for _, pkg := range packages {
diff --git a/test/torture.go b/test/torture.go
index bbf6d347d..197b481e6 100644
--- a/test/torture.go
+++ b/test/torture.go
@@ -337,3 +337,10 @@ func ChainDivConst(a int) int {
func ChainMulBytes(a, b, c byte) byte {
return a*(a*(a*(a*(a*(a*(a*(a*(a*b+c)+c)+c)+c)+c)+c)+c)+c) + c
}
+
+func ChainCap() {
+ select {
+ case <-make(chan int, cap(make(chan int, cap(make(chan int, cap(make(chan int, cap(make(chan int))))))))):
+ default:
+ }
+}